| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510245112451224513245142451524516245172451824519245202452124522245232452424525245262452724528245292453024531245322453324534245352453624537245382453924540245412454224543245442454524546245472454824549245502455124552245532455424555245562455724558245592456024561245622456324564245652456624567245682456924570245712457224573245742457524576245772457824579245802458124582245832458424585245862458724588245892459024591245922459324594245952459624597245982459924600246012460224603246042460524606246072460824609246102461124612246132461424615246162461724618246192462024621246222462324624246252462624627246282462924630246312463224633246342463524636246372463824639246402464124642246432464424645246462464724648246492465024651246522465324654246552465624657246582465924660246612466224663246642466524666246672466824669246702467124672246732467424675246762467724678246792468024681246822468324684246852468624687246882468924690246912469224693246942469524696246972469824699247002470124702247032470424705247062470724708247092471024711247122471324714247152471624717247182471924720247212472224723247242472524726247272472824729247302473124732247332473424735247362473724738247392474024741247422474324744247452474624747247482474924750247512475224753247542475524756247572475824759247602476124762247632476424765247662476724768247692477024771247722477324774247752477624777247782477924780247812478224783247842478524786247872478824789247902479124792247932479424795247962479724798247992480024801248022480324804248052480624807248082480924810248112481224813248142481524816248172481824819248202482124822248232482424825248262482724828248292483024831248322483324834248352483624837248382483924840248412484224843248442484524846248472484824849248502485124852248532485424855248562485724858248592486024861248622486324864248652486624867248682486924870248712487224873248742487524876248772487824879248802488124882248832488424885248862488724888248892489024891248922489324894248952489624897248982489924900249012490224903249042490524906249072490824909249102491124912249132491424915249162491724918249192492024921249222492324924249252492624927249282492924930249312493224933249342493524936249372493824939249402494124942249432494424945249462494724948249492495024951249522495324954249552495624957249582495924960249612496224963249642496524966249672496824969249702497124972249732497424975249762497724978249792498024981249822498324984249852498624987249882498924990249912499224993249942499524996249972499824999250002500125002250032500425005250062500725008250092501025011250122501325014250152501625017250182501925020250212502225023250242502525026250272502825029250302503125032250332503425035250362503725038250392504025041250422504325044250452504625047250482504925050250512505225053250542505525056250572505825059250602506125062250632506425065250662506725068250692507025071250722507325074250752507625077250782507925080250812508225083250842508525086250872508825089250902509125092250932509425095250962509725098250992510025101251022510325104251052510625107251082510925110251112511225113251142511525116251172511825119251202512125122251232512425125251262512725128251292513025131251322513325134251352513625137251382513925140251412514225143251442514525146251472514825149251502515125152251532515425155251562515725158251592516025161251622516325164251652516625167251682516925170251712517225173251742517525176251772517825179251802518125182251832518425185251862518725188251892519025191251922519325194251952519625197251982519925200252012520225203252042520525206252072520825209252102521125212252132521425215252162521725218252192522025221252222522325224252252522625227252282522925230252312523225233252342523525236252372523825239252402524125242252432524425245252462524725248252492525025251252522525325254252552525625257252582525925260252612526225263252642526525266252672526825269252702527125272252732527425275252762527725278252792528025281252822528325284252852528625287252882528925290252912529225293252942529525296252972529825299253002530125302253032530425305253062530725308253092531025311253122531325314253152531625317253182531925320253212532225323253242532525326253272532825329253302533125332253332533425335253362533725338253392534025341253422534325344253452534625347253482534925350253512535225353253542535525356253572535825359253602536125362253632536425365253662536725368253692537025371253722537325374253752537625377253782537925380253812538225383253842538525386253872538825389253902539125392253932539425395253962539725398253992540025401254022540325404254052540625407254082540925410254112541225413254142541525416254172541825419254202542125422254232542425425254262542725428254292543025431254322543325434254352543625437254382543925440254412544225443254442544525446254472544825449254502545125452254532545425455254562545725458254592546025461254622546325464254652546625467254682546925470254712547225473254742547525476254772547825479254802548125482254832548425485254862548725488254892549025491254922549325494254952549625497254982549925500255012550225503255042550525506255072550825509255102551125512255132551425515255162551725518255192552025521255222552325524255252552625527255282552925530255312553225533255342553525536255372553825539255402554125542255432554425545255462554725548255492555025551255522555325554255552555625557255582555925560255612556225563255642556525566255672556825569255702557125572255732557425575255762557725578255792558025581255822558325584255852558625587255882558925590255912559225593255942559525596255972559825599256002560125602256032560425605256062560725608256092561025611256122561325614256152561625617256182561925620256212562225623256242562525626256272562825629256302563125632256332563425635256362563725638256392564025641256422564325644256452564625647256482564925650256512565225653256542565525656256572565825659256602566125662256632566425665256662566725668256692567025671256722567325674256752567625677256782567925680256812568225683256842568525686256872568825689256902569125692256932569425695256962569725698256992570025701257022570325704257052570625707257082570925710257112571225713257142571525716257172571825719257202572125722257232572425725257262572725728257292573025731257322573325734257352573625737257382573925740257412574225743257442574525746257472574825749257502575125752257532575425755257562575725758257592576025761257622576325764257652576625767257682576925770257712577225773257742577525776257772577825779257802578125782257832578425785257862578725788257892579025791257922579325794257952579625797257982579925800258012580225803258042580525806258072580825809258102581125812258132581425815258162581725818258192582025821258222582325824258252582625827258282582925830258312583225833258342583525836258372583825839258402584125842258432584425845258462584725848258492585025851258522585325854258552585625857258582585925860258612586225863258642586525866258672586825869258702587125872258732587425875258762587725878258792588025881258822588325884258852588625887258882588925890258912589225893258942589525896258972589825899259002590125902259032590425905259062590725908259092591025911259122591325914259152591625917259182591925920259212592225923259242592525926259272592825929259302593125932259332593425935259362593725938259392594025941259422594325944259452594625947259482594925950259512595225953259542595525956259572595825959259602596125962259632596425965259662596725968259692597025971259722597325974259752597625977259782597925980259812598225983259842598525986259872598825989259902599125992259932599425995259962599725998259992600026001260022600326004260052600626007260082600926010260112601226013260142601526016260172601826019260202602126022260232602426025260262602726028260292603026031260322603326034260352603626037260382603926040260412604226043260442604526046260472604826049260502605126052260532605426055260562605726058260592606026061260622606326064260652606626067260682606926070260712607226073260742607526076260772607826079260802608126082260832608426085260862608726088260892609026091260922609326094260952609626097260982609926100261012610226103261042610526106261072610826109261102611126112261132611426115261162611726118261192612026121261222612326124261252612626127261282612926130261312613226133261342613526136261372613826139261402614126142261432614426145261462614726148261492615026151261522615326154261552615626157261582615926160261612616226163261642616526166261672616826169261702617126172261732617426175261762617726178261792618026181261822618326184261852618626187261882618926190261912619226193261942619526196261972619826199262002620126202262032620426205262062620726208262092621026211262122621326214262152621626217262182621926220262212622226223262242622526226262272622826229262302623126232262332623426235262362623726238262392624026241262422624326244262452624626247262482624926250262512625226253262542625526256262572625826259262602626126262262632626426265262662626726268262692627026271262722627326274262752627626277262782627926280262812628226283262842628526286262872628826289262902629126292262932629426295262962629726298262992630026301263022630326304263052630626307263082630926310263112631226313263142631526316263172631826319263202632126322263232632426325263262632726328263292633026331263322633326334263352633626337263382633926340263412634226343263442634526346263472634826349263502635126352263532635426355263562635726358263592636026361263622636326364263652636626367263682636926370263712637226373263742637526376263772637826379263802638126382263832638426385263862638726388263892639026391263922639326394263952639626397263982639926400264012640226403264042640526406264072640826409264102641126412264132641426415264162641726418264192642026421264222642326424264252642626427264282642926430264312643226433264342643526436264372643826439264402644126442264432644426445264462644726448264492645026451264522645326454264552645626457264582645926460264612646226463264642646526466264672646826469264702647126472264732647426475264762647726478264792648026481264822648326484264852648626487264882648926490264912649226493264942649526496264972649826499265002650126502265032650426505265062650726508265092651026511265122651326514265152651626517265182651926520265212652226523265242652526526265272652826529265302653126532265332653426535265362653726538265392654026541265422654326544265452654626547265482654926550265512655226553265542655526556265572655826559265602656126562265632656426565265662656726568265692657026571265722657326574265752657626577265782657926580265812658226583265842658526586265872658826589265902659126592265932659426595265962659726598265992660026601266022660326604266052660626607266082660926610266112661226613266142661526616266172661826619266202662126622266232662426625266262662726628266292663026631266322663326634266352663626637266382663926640266412664226643266442664526646266472664826649266502665126652266532665426655266562665726658266592666026661266622666326664266652666626667266682666926670266712667226673266742667526676266772667826679266802668126682266832668426685266862668726688266892669026691266922669326694266952669626697266982669926700267012670226703267042670526706267072670826709267102671126712267132671426715267162671726718267192672026721267222672326724267252672626727267282672926730267312673226733267342673526736267372673826739267402674126742267432674426745267462674726748267492675026751267522675326754267552675626757267582675926760267612676226763267642676526766267672676826769267702677126772267732677426775267762677726778267792678026781267822678326784267852678626787267882678926790267912679226793267942679526796267972679826799268002680126802268032680426805268062680726808268092681026811268122681326814268152681626817268182681926820268212682226823268242682526826268272682826829268302683126832268332683426835268362683726838268392684026841268422684326844268452684626847268482684926850268512685226853268542685526856268572685826859268602686126862268632686426865268662686726868268692687026871268722687326874268752687626877268782687926880268812688226883268842688526886268872688826889268902689126892268932689426895268962689726898268992690026901269022690326904269052690626907269082690926910269112691226913269142691526916269172691826919269202692126922269232692426925269262692726928269292693026931269322693326934269352693626937269382693926940269412694226943269442694526946269472694826949269502695126952269532695426955269562695726958269592696026961269622696326964269652696626967269682696926970269712697226973269742697526976269772697826979269802698126982269832698426985269862698726988269892699026991269922699326994269952699626997269982699927000270012700227003270042700527006270072700827009270102701127012270132701427015270162701727018270192702027021270222702327024270252702627027270282702927030270312703227033270342703527036270372703827039270402704127042270432704427045270462704727048270492705027051270522705327054270552705627057270582705927060270612706227063270642706527066270672706827069270702707127072270732707427075270762707727078270792708027081270822708327084270852708627087270882708927090270912709227093270942709527096270972709827099271002710127102271032710427105271062710727108271092711027111271122711327114271152711627117271182711927120271212712227123271242712527126271272712827129271302713127132271332713427135271362713727138271392714027141271422714327144271452714627147271482714927150271512715227153271542715527156271572715827159271602716127162271632716427165271662716727168271692717027171271722717327174271752717627177271782717927180271812718227183271842718527186271872718827189271902719127192271932719427195271962719727198271992720027201272022720327204272052720627207272082720927210272112721227213272142721527216272172721827219272202722127222272232722427225272262722727228272292723027231272322723327234272352723627237272382723927240272412724227243272442724527246272472724827249272502725127252272532725427255272562725727258272592726027261272622726327264272652726627267272682726927270272712727227273272742727527276272772727827279272802728127282272832728427285272862728727288272892729027291272922729327294272952729627297272982729927300273012730227303273042730527306273072730827309273102731127312273132731427315273162731727318273192732027321273222732327324273252732627327273282732927330273312733227333273342733527336273372733827339273402734127342273432734427345273462734727348273492735027351273522735327354273552735627357273582735927360273612736227363273642736527366273672736827369273702737127372273732737427375273762737727378273792738027381273822738327384273852738627387273882738927390273912739227393273942739527396273972739827399274002740127402274032740427405274062740727408274092741027411274122741327414274152741627417274182741927420274212742227423274242742527426274272742827429274302743127432274332743427435274362743727438274392744027441274422744327444274452744627447274482744927450274512745227453274542745527456274572745827459274602746127462274632746427465274662746727468274692747027471274722747327474274752747627477274782747927480274812748227483274842748527486274872748827489274902749127492274932749427495274962749727498274992750027501275022750327504275052750627507275082750927510275112751227513275142751527516275172751827519275202752127522275232752427525275262752727528275292753027531275322753327534275352753627537275382753927540275412754227543275442754527546275472754827549275502755127552275532755427555275562755727558275592756027561275622756327564275652756627567275682756927570275712757227573275742757527576275772757827579275802758127582275832758427585275862758727588275892759027591275922759327594275952759627597275982759927600276012760227603276042760527606276072760827609276102761127612276132761427615276162761727618276192762027621276222762327624276252762627627276282762927630276312763227633276342763527636276372763827639276402764127642276432764427645276462764727648276492765027651276522765327654276552765627657276582765927660276612766227663276642766527666276672766827669276702767127672276732767427675276762767727678276792768027681276822768327684276852768627687276882768927690276912769227693276942769527696276972769827699277002770127702277032770427705277062770727708277092771027711277122771327714277152771627717277182771927720277212772227723277242772527726277272772827729277302773127732277332773427735277362773727738277392774027741277422774327744277452774627747277482774927750277512775227753277542775527756277572775827759277602776127762277632776427765277662776727768277692777027771277722777327774277752777627777277782777927780277812778227783277842778527786277872778827789277902779127792277932779427795277962779727798277992780027801278022780327804278052780627807278082780927810278112781227813278142781527816278172781827819278202782127822278232782427825278262782727828278292783027831278322783327834278352783627837278382783927840278412784227843278442784527846278472784827849278502785127852278532785427855278562785727858278592786027861278622786327864278652786627867278682786927870278712787227873278742787527876278772787827879278802788127882278832788427885278862788727888278892789027891278922789327894278952789627897278982789927900279012790227903279042790527906279072790827909279102791127912279132791427915279162791727918279192792027921279222792327924279252792627927279282792927930279312793227933279342793527936279372793827939279402794127942279432794427945279462794727948279492795027951279522795327954279552795627957279582795927960279612796227963279642796527966279672796827969279702797127972279732797427975279762797727978279792798027981279822798327984279852798627987279882798927990279912799227993279942799527996279972799827999280002800128002280032800428005280062800728008280092801028011280122801328014280152801628017280182801928020280212802228023280242802528026280272802828029280302803128032280332803428035280362803728038280392804028041280422804328044280452804628047280482804928050280512805228053280542805528056280572805828059280602806128062280632806428065280662806728068280692807028071280722807328074280752807628077280782807928080280812808228083280842808528086280872808828089280902809128092280932809428095280962809728098280992810028101281022810328104281052810628107281082810928110281112811228113281142811528116281172811828119281202812128122281232812428125281262812728128281292813028131281322813328134281352813628137281382813928140281412814228143281442814528146281472814828149281502815128152281532815428155281562815728158281592816028161281622816328164281652816628167281682816928170281712817228173281742817528176281772817828179281802818128182281832818428185281862818728188281892819028191281922819328194281952819628197281982819928200282012820228203282042820528206282072820828209282102821128212282132821428215282162821728218282192822028221282222822328224282252822628227282282822928230282312823228233282342823528236282372823828239282402824128242282432824428245282462824728248282492825028251282522825328254282552825628257282582825928260282612826228263282642826528266282672826828269282702827128272282732827428275282762827728278282792828028281282822828328284282852828628287282882828928290282912829228293282942829528296282972829828299283002830128302283032830428305283062830728308283092831028311283122831328314283152831628317283182831928320283212832228323283242832528326283272832828329283302833128332283332833428335283362833728338283392834028341283422834328344283452834628347283482834928350283512835228353283542835528356283572835828359283602836128362283632836428365283662836728368283692837028371283722837328374283752837628377283782837928380283812838228383283842838528386283872838828389283902839128392283932839428395283962839728398283992840028401284022840328404284052840628407284082840928410284112841228413284142841528416284172841828419284202842128422284232842428425284262842728428284292843028431284322843328434284352843628437284382843928440284412844228443284442844528446284472844828449284502845128452284532845428455284562845728458284592846028461284622846328464284652846628467284682846928470284712847228473284742847528476284772847828479284802848128482284832848428485284862848728488284892849028491284922849328494284952849628497284982849928500285012850228503285042850528506285072850828509285102851128512285132851428515285162851728518285192852028521285222852328524285252852628527285282852928530285312853228533285342853528536285372853828539285402854128542285432854428545285462854728548285492855028551285522855328554285552855628557285582855928560285612856228563285642856528566285672856828569285702857128572285732857428575285762857728578285792858028581285822858328584285852858628587285882858928590285912859228593285942859528596285972859828599286002860128602286032860428605286062860728608286092861028611286122861328614286152861628617286182861928620286212862228623286242862528626286272862828629286302863128632286332863428635286362863728638286392864028641286422864328644286452864628647286482864928650286512865228653286542865528656286572865828659286602866128662286632866428665286662866728668286692867028671286722867328674286752867628677286782867928680286812868228683286842868528686286872868828689286902869128692286932869428695286962869728698286992870028701287022870328704287052870628707287082870928710287112871228713287142871528716287172871828719287202872128722287232872428725287262872728728287292873028731287322873328734287352873628737287382873928740287412874228743287442874528746287472874828749287502875128752287532875428755287562875728758287592876028761287622876328764287652876628767287682876928770287712877228773287742877528776287772877828779287802878128782287832878428785287862878728788287892879028791287922879328794287952879628797287982879928800288012880228803288042880528806288072880828809288102881128812288132881428815288162881728818288192882028821288222882328824288252882628827288282882928830288312883228833288342883528836288372883828839288402884128842288432884428845288462884728848288492885028851288522885328854288552885628857288582885928860288612886228863288642886528866288672886828869288702887128872288732887428875288762887728878288792888028881288822888328884288852888628887288882888928890288912889228893288942889528896288972889828899289002890128902289032890428905289062890728908289092891028911289122891328914289152891628917289182891928920289212892228923289242892528926289272892828929289302893128932289332893428935289362893728938289392894028941289422894328944289452894628947289482894928950289512895228953289542895528956289572895828959289602896128962289632896428965289662896728968289692897028971289722897328974289752897628977289782897928980289812898228983289842898528986289872898828989289902899128992289932899428995289962899728998289992900029001290022900329004290052900629007290082900929010290112901229013290142901529016290172901829019290202902129022290232902429025290262902729028290292903029031290322903329034290352903629037290382903929040290412904229043290442904529046290472904829049290502905129052290532905429055290562905729058290592906029061290622906329064290652906629067290682906929070290712907229073290742907529076290772907829079290802908129082290832908429085290862908729088290892909029091290922909329094290952909629097290982909929100291012910229103291042910529106291072910829109291102911129112291132911429115291162911729118291192912029121291222912329124291252912629127291282912929130291312913229133291342913529136291372913829139291402914129142291432914429145291462914729148291492915029151291522915329154291552915629157291582915929160291612916229163291642916529166291672916829169291702917129172291732917429175291762917729178291792918029181291822918329184291852918629187291882918929190291912919229193291942919529196291972919829199292002920129202292032920429205292062920729208292092921029211292122921329214292152921629217292182921929220292212922229223292242922529226292272922829229292302923129232292332923429235292362923729238292392924029241292422924329244292452924629247292482924929250292512925229253292542925529256292572925829259292602926129262292632926429265292662926729268292692927029271292722927329274292752927629277292782927929280292812928229283292842928529286292872928829289292902929129292292932929429295292962929729298292992930029301293022930329304293052930629307293082930929310293112931229313293142931529316293172931829319293202932129322293232932429325293262932729328293292933029331293322933329334293352933629337293382933929340293412934229343293442934529346293472934829349293502935129352293532935429355293562935729358293592936029361293622936329364293652936629367293682936929370293712937229373293742937529376293772937829379293802938129382293832938429385293862938729388293892939029391293922939329394293952939629397293982939929400294012940229403294042940529406294072940829409294102941129412294132941429415294162941729418294192942029421294222942329424294252942629427294282942929430294312943229433294342943529436294372943829439294402944129442294432944429445294462944729448294492945029451294522945329454294552945629457294582945929460294612946229463294642946529466294672946829469294702947129472294732947429475294762947729478294792948029481294822948329484294852948629487294882948929490294912949229493294942949529496294972949829499295002950129502295032950429505295062950729508295092951029511295122951329514295152951629517295182951929520295212952229523295242952529526295272952829529295302953129532295332953429535295362953729538295392954029541295422954329544295452954629547295482954929550295512955229553295542955529556295572955829559295602956129562295632956429565295662956729568295692957029571295722957329574295752957629577295782957929580295812958229583295842958529586295872958829589295902959129592295932959429595295962959729598295992960029601296022960329604296052960629607296082960929610296112961229613296142961529616296172961829619296202962129622296232962429625296262962729628296292963029631296322963329634296352963629637296382963929640296412964229643296442964529646296472964829649296502965129652296532965429655296562965729658296592966029661296622966329664296652966629667296682966929670296712967229673296742967529676296772967829679296802968129682296832968429685296862968729688296892969029691296922969329694296952969629697296982969929700297012970229703297042970529706297072970829709297102971129712297132971429715297162971729718297192972029721297222972329724297252972629727297282972929730297312973229733297342973529736297372973829739297402974129742297432974429745297462974729748297492975029751297522975329754297552975629757297582975929760297612976229763297642976529766297672976829769297702977129772297732977429775297762977729778297792978029781297822978329784297852978629787297882978929790297912979229793297942979529796297972979829799298002980129802298032980429805298062980729808298092981029811298122981329814298152981629817298182981929820298212982229823298242982529826298272982829829298302983129832298332983429835298362983729838298392984029841298422984329844298452984629847298482984929850298512985229853298542985529856298572985829859298602986129862298632986429865298662986729868298692987029871298722987329874298752987629877298782987929880298812988229883298842988529886298872988829889298902989129892298932989429895298962989729898298992990029901299022990329904299052990629907299082990929910299112991229913299142991529916299172991829919299202992129922299232992429925299262992729928299292993029931299322993329934299352993629937299382993929940299412994229943299442994529946299472994829949299502995129952299532995429955299562995729958299592996029961299622996329964299652996629967299682996929970299712997229973299742997529976299772997829979299802998129982299832998429985299862998729988299892999029991299922999329994299952999629997299982999930000300013000230003300043000530006300073000830009300103001130012300133001430015300163001730018300193002030021300223002330024300253002630027300283002930030300313003230033300343003530036300373003830039300403004130042300433004430045300463004730048300493005030051300523005330054300553005630057300583005930060300613006230063300643006530066300673006830069300703007130072300733007430075300763007730078300793008030081300823008330084300853008630087300883008930090300913009230093300943009530096300973009830099301003010130102301033010430105301063010730108301093011030111301123011330114301153011630117301183011930120301213012230123301243012530126301273012830129301303013130132301333013430135301363013730138301393014030141301423014330144301453014630147301483014930150301513015230153301543015530156301573015830159301603016130162301633016430165301663016730168301693017030171301723017330174301753017630177301783017930180301813018230183301843018530186301873018830189301903019130192301933019430195301963019730198301993020030201302023020330204302053020630207302083020930210302113021230213302143021530216302173021830219302203022130222302233022430225302263022730228302293023030231302323023330234302353023630237302383023930240302413024230243302443024530246302473024830249302503025130252302533025430255302563025730258302593026030261302623026330264302653026630267302683026930270302713027230273302743027530276302773027830279302803028130282302833028430285302863028730288302893029030291302923029330294302953029630297302983029930300303013030230303303043030530306303073030830309303103031130312303133031430315303163031730318303193032030321303223032330324303253032630327303283032930330303313033230333303343033530336303373033830339303403034130342303433034430345303463034730348303493035030351303523035330354303553035630357303583035930360303613036230363303643036530366303673036830369303703037130372303733037430375303763037730378303793038030381303823038330384303853038630387303883038930390303913039230393303943039530396303973039830399304003040130402304033040430405304063040730408304093041030411304123041330414304153041630417304183041930420304213042230423304243042530426304273042830429304303043130432304333043430435304363043730438304393044030441304423044330444304453044630447304483044930450304513045230453304543045530456304573045830459304603046130462304633046430465304663046730468304693047030471304723047330474304753047630477304783047930480304813048230483304843048530486304873048830489304903049130492304933049430495304963049730498304993050030501305023050330504305053050630507305083050930510305113051230513305143051530516305173051830519305203052130522305233052430525305263052730528305293053030531305323053330534305353053630537305383053930540305413054230543305443054530546305473054830549305503055130552305533055430555305563055730558305593056030561305623056330564305653056630567305683056930570305713057230573305743057530576305773057830579305803058130582305833058430585305863058730588305893059030591305923059330594305953059630597305983059930600306013060230603306043060530606306073060830609306103061130612306133061430615306163061730618306193062030621306223062330624306253062630627306283062930630306313063230633306343063530636306373063830639306403064130642306433064430645306463064730648306493065030651306523065330654306553065630657306583065930660306613066230663306643066530666306673066830669306703067130672306733067430675306763067730678306793068030681306823068330684306853068630687306883068930690306913069230693306943069530696306973069830699307003070130702307033070430705307063070730708307093071030711307123071330714307153071630717307183071930720307213072230723307243072530726307273072830729307303073130732307333073430735307363073730738307393074030741307423074330744307453074630747307483074930750307513075230753307543075530756307573075830759307603076130762307633076430765307663076730768307693077030771307723077330774307753077630777307783077930780307813078230783307843078530786307873078830789307903079130792307933079430795307963079730798307993080030801308023080330804308053080630807308083080930810308113081230813308143081530816308173081830819308203082130822308233082430825308263082730828308293083030831308323083330834308353083630837308383083930840308413084230843308443084530846308473084830849308503085130852308533085430855308563085730858308593086030861308623086330864308653086630867308683086930870308713087230873308743087530876308773087830879308803088130882308833088430885308863088730888308893089030891308923089330894308953089630897308983089930900309013090230903309043090530906309073090830909309103091130912309133091430915309163091730918309193092030921309223092330924309253092630927309283092930930309313093230933309343093530936309373093830939309403094130942309433094430945309463094730948309493095030951309523095330954309553095630957309583095930960309613096230963309643096530966309673096830969309703097130972309733097430975309763097730978309793098030981309823098330984309853098630987309883098930990309913099230993309943099530996309973099830999310003100131002310033100431005310063100731008310093101031011310123101331014310153101631017310183101931020310213102231023310243102531026310273102831029310303103131032310333103431035310363103731038310393104031041310423104331044310453104631047310483104931050310513105231053310543105531056310573105831059310603106131062310633106431065310663106731068310693107031071310723107331074310753107631077310783107931080310813108231083310843108531086310873108831089310903109131092310933109431095310963109731098310993110031101311023110331104311053110631107311083110931110311113111231113311143111531116311173111831119311203112131122311233112431125311263112731128311293113031131311323113331134311353113631137311383113931140311413114231143311443114531146311473114831149311503115131152311533115431155311563115731158311593116031161311623116331164311653116631167311683116931170311713117231173311743117531176311773117831179311803118131182311833118431185311863118731188311893119031191311923119331194311953119631197311983119931200312013120231203312043120531206312073120831209312103121131212312133121431215312163121731218312193122031221312223122331224312253122631227312283122931230312313123231233312343123531236312373123831239312403124131242312433124431245312463124731248312493125031251312523125331254312553125631257312583125931260312613126231263312643126531266312673126831269312703127131272312733127431275312763127731278312793128031281312823128331284312853128631287312883128931290312913129231293312943129531296312973129831299313003130131302313033130431305313063130731308313093131031311313123131331314313153131631317313183131931320313213132231323313243132531326313273132831329313303133131332313333133431335313363133731338313393134031341313423134331344313453134631347313483134931350313513135231353313543135531356313573135831359313603136131362313633136431365313663136731368313693137031371313723137331374313753137631377313783137931380313813138231383313843138531386313873138831389313903139131392313933139431395313963139731398313993140031401314023140331404314053140631407314083140931410314113141231413314143141531416314173141831419314203142131422314233142431425314263142731428314293143031431314323143331434314353143631437314383143931440314413144231443314443144531446314473144831449314503145131452314533145431455314563145731458314593146031461314623146331464314653146631467314683146931470314713147231473314743147531476314773147831479314803148131482314833148431485314863148731488314893149031491314923149331494314953149631497314983149931500315013150231503315043150531506315073150831509315103151131512315133151431515315163151731518315193152031521315223152331524315253152631527315283152931530315313153231533315343153531536315373153831539315403154131542315433154431545315463154731548315493155031551315523155331554315553155631557315583155931560315613156231563315643156531566315673156831569315703157131572315733157431575315763157731578315793158031581315823158331584315853158631587315883158931590315913159231593315943159531596315973159831599316003160131602316033160431605316063160731608316093161031611316123161331614316153161631617316183161931620316213162231623316243162531626316273162831629316303163131632316333163431635316363163731638316393164031641316423164331644316453164631647316483164931650316513165231653316543165531656316573165831659316603166131662316633166431665316663166731668316693167031671316723167331674316753167631677316783167931680316813168231683316843168531686316873168831689316903169131692316933169431695316963169731698316993170031701317023170331704317053170631707317083170931710317113171231713317143171531716317173171831719317203172131722317233172431725317263172731728317293173031731317323173331734317353173631737317383173931740317413174231743317443174531746317473174831749317503175131752317533175431755317563175731758317593176031761317623176331764317653176631767317683176931770317713177231773317743177531776317773177831779317803178131782317833178431785317863178731788317893179031791317923179331794317953179631797317983179931800318013180231803318043180531806318073180831809318103181131812318133181431815318163181731818318193182031821318223182331824318253182631827318283182931830318313183231833318343183531836318373183831839318403184131842318433184431845318463184731848318493185031851318523185331854318553185631857318583185931860318613186231863318643186531866318673186831869318703187131872318733187431875318763187731878318793188031881318823188331884318853188631887318883188931890318913189231893318943189531896318973189831899319003190131902319033190431905319063190731908319093191031911319123191331914319153191631917319183191931920319213192231923319243192531926319273192831929319303193131932319333193431935319363193731938319393194031941319423194331944319453194631947319483194931950319513195231953319543195531956319573195831959319603196131962319633196431965319663196731968319693197031971319723197331974319753197631977319783197931980319813198231983319843198531986319873198831989319903199131992319933199431995319963199731998319993200032001320023200332004320053200632007320083200932010320113201232013320143201532016320173201832019320203202132022320233202432025320263202732028320293203032031320323203332034320353203632037320383203932040320413204232043320443204532046320473204832049320503205132052320533205432055320563205732058320593206032061320623206332064320653206632067320683206932070320713207232073320743207532076320773207832079320803208132082320833208432085320863208732088320893209032091320923209332094320953209632097320983209932100321013210232103321043210532106321073210832109321103211132112321133211432115321163211732118321193212032121321223212332124321253212632127321283212932130321313213232133321343213532136321373213832139321403214132142321433214432145321463214732148321493215032151321523215332154321553215632157321583215932160321613216232163321643216532166321673216832169321703217132172321733217432175321763217732178321793218032181321823218332184321853218632187321883218932190321913219232193321943219532196321973219832199322003220132202322033220432205322063220732208322093221032211322123221332214322153221632217322183221932220322213222232223322243222532226322273222832229322303223132232322333223432235322363223732238322393224032241322423224332244322453224632247322483224932250322513225232253322543225532256322573225832259322603226132262322633226432265322663226732268322693227032271322723227332274322753227632277322783227932280322813228232283322843228532286322873228832289322903229132292322933229432295322963229732298322993230032301323023230332304323053230632307323083230932310323113231232313323143231532316323173231832319323203232132322323233232432325323263232732328323293233032331323323233332334323353233632337323383233932340323413234232343323443234532346323473234832349323503235132352323533235432355323563235732358323593236032361323623236332364323653236632367323683236932370323713237232373323743237532376323773237832379323803238132382323833238432385323863238732388323893239032391323923239332394323953239632397323983239932400324013240232403324043240532406324073240832409324103241132412324133241432415324163241732418324193242032421324223242332424324253242632427324283242932430324313243232433324343243532436324373243832439324403244132442324433244432445324463244732448324493245032451324523245332454324553245632457324583245932460324613246232463324643246532466324673246832469324703247132472324733247432475324763247732478324793248032481324823248332484324853248632487324883248932490324913249232493324943249532496324973249832499325003250132502325033250432505325063250732508325093251032511325123251332514325153251632517325183251932520325213252232523325243252532526325273252832529325303253132532325333253432535325363253732538325393254032541325423254332544325453254632547325483254932550325513255232553325543255532556325573255832559325603256132562325633256432565325663256732568325693257032571325723257332574325753257632577325783257932580325813258232583325843258532586325873258832589325903259132592325933259432595325963259732598325993260032601326023260332604326053260632607326083260932610326113261232613326143261532616326173261832619326203262132622326233262432625326263262732628326293263032631326323263332634326353263632637326383263932640326413264232643326443264532646326473264832649326503265132652326533265432655326563265732658326593266032661326623266332664326653266632667326683266932670326713267232673326743267532676326773267832679326803268132682326833268432685326863268732688326893269032691326923269332694326953269632697326983269932700327013270232703327043270532706327073270832709327103271132712327133271432715327163271732718327193272032721327223272332724327253272632727327283272932730327313273232733327343273532736327373273832739327403274132742327433274432745327463274732748327493275032751327523275332754327553275632757327583275932760327613276232763327643276532766327673276832769327703277132772327733277432775327763277732778327793278032781327823278332784327853278632787327883278932790327913279232793327943279532796327973279832799328003280132802328033280432805328063280732808328093281032811328123281332814328153281632817328183281932820328213282232823328243282532826328273282832829328303283132832328333283432835328363283732838328393284032841328423284332844328453284632847328483284932850328513285232853328543285532856328573285832859328603286132862328633286432865328663286732868328693287032871328723287332874328753287632877328783287932880328813288232883328843288532886328873288832889328903289132892328933289432895328963289732898328993290032901329023290332904329053290632907329083290932910329113291232913329143291532916329173291832919329203292132922329233292432925329263292732928329293293032931329323293332934329353293632937329383293932940329413294232943329443294532946329473294832949329503295132952329533295432955329563295732958329593296032961329623296332964329653296632967329683296932970329713297232973329743297532976329773297832979329803298132982329833298432985329863298732988329893299032991329923299332994329953299632997329983299933000330013300233003330043300533006330073300833009330103301133012330133301433015330163301733018330193302033021330223302333024330253302633027330283302933030330313303233033330343303533036330373303833039330403304133042330433304433045330463304733048330493305033051330523305333054330553305633057330583305933060330613306233063330643306533066330673306833069330703307133072330733307433075330763307733078330793308033081330823308333084330853308633087330883308933090330913309233093330943309533096330973309833099331003310133102331033310433105331063310733108331093311033111331123311333114331153311633117331183311933120331213312233123331243312533126331273312833129331303313133132331333313433135331363313733138331393314033141331423314333144331453314633147331483314933150331513315233153331543315533156331573315833159331603316133162331633316433165331663316733168331693317033171331723317333174331753317633177331783317933180331813318233183331843318533186331873318833189331903319133192331933319433195331963319733198331993320033201332023320333204332053320633207332083320933210332113321233213332143321533216332173321833219332203322133222332233322433225332263322733228332293323033231332323323333234332353323633237332383323933240332413324233243332443324533246332473324833249332503325133252332533325433255332563325733258332593326033261332623326333264332653326633267332683326933270332713327233273332743327533276332773327833279332803328133282332833328433285332863328733288332893329033291332923329333294332953329633297332983329933300333013330233303333043330533306333073330833309333103331133312333133331433315333163331733318333193332033321333223332333324333253332633327333283332933330333313333233333333343333533336333373333833339333403334133342333433334433345333463334733348333493335033351333523335333354333553335633357333583335933360333613336233363333643336533366333673336833369333703337133372333733337433375333763337733378333793338033381333823338333384333853338633387333883338933390333913339233393333943339533396333973339833399334003340133402334033340433405334063340733408334093341033411334123341333414334153341633417334183341933420334213342233423334243342533426334273342833429334303343133432334333343433435334363343733438334393344033441334423344333444334453344633447334483344933450334513345233453334543345533456334573345833459334603346133462334633346433465334663346733468334693347033471334723347333474334753347633477334783347933480334813348233483334843348533486334873348833489334903349133492334933349433495334963349733498334993350033501335023350333504335053350633507335083350933510335113351233513335143351533516335173351833519335203352133522335233352433525335263352733528335293353033531335323353333534335353353633537335383353933540335413354233543335443354533546335473354833549335503355133552335533355433555335563355733558335593356033561335623356333564335653356633567335683356933570335713357233573335743357533576335773357833579335803358133582335833358433585335863358733588335893359033591335923359333594335953359633597335983359933600336013360233603336043360533606336073360833609336103361133612336133361433615336163361733618336193362033621336223362333624336253362633627336283362933630336313363233633336343363533636336373363833639336403364133642336433364433645336463364733648336493365033651336523365333654336553365633657336583365933660336613366233663336643366533666336673366833669336703367133672336733367433675336763367733678336793368033681336823368333684336853368633687336883368933690336913369233693336943369533696336973369833699337003370133702337033370433705337063370733708337093371033711337123371333714337153371633717337183371933720337213372233723337243372533726337273372833729337303373133732337333373433735337363373733738337393374033741337423374333744337453374633747337483374933750337513375233753337543375533756337573375833759337603376133762337633376433765337663376733768337693377033771337723377333774337753377633777337783377933780337813378233783337843378533786337873378833789337903379133792337933379433795337963379733798337993380033801338023380333804338053380633807338083380933810338113381233813338143381533816338173381833819338203382133822338233382433825338263382733828338293383033831338323383333834338353383633837338383383933840338413384233843338443384533846338473384833849338503385133852338533385433855338563385733858338593386033861338623386333864338653386633867338683386933870338713387233873338743387533876338773387833879338803388133882338833388433885338863388733888338893389033891338923389333894338953389633897338983389933900339013390233903339043390533906339073390833909339103391133912339133391433915339163391733918339193392033921339223392333924339253392633927339283392933930339313393233933339343393533936339373393833939339403394133942339433394433945339463394733948339493395033951339523395333954339553395633957339583395933960339613396233963339643396533966339673396833969339703397133972339733397433975339763397733978339793398033981339823398333984339853398633987339883398933990339913399233993339943399533996339973399833999340003400134002340033400434005340063400734008340093401034011340123401334014340153401634017340183401934020340213402234023340243402534026340273402834029340303403134032340333403434035340363403734038340393404034041340423404334044340453404634047340483404934050340513405234053340543405534056340573405834059340603406134062340633406434065340663406734068340693407034071340723407334074340753407634077340783407934080340813408234083340843408534086340873408834089340903409134092340933409434095340963409734098340993410034101341023410334104341053410634107341083410934110341113411234113341143411534116341173411834119341203412134122341233412434125341263412734128341293413034131341323413334134341353413634137341383413934140341413414234143341443414534146341473414834149341503415134152341533415434155341563415734158341593416034161341623416334164341653416634167341683416934170341713417234173341743417534176341773417834179341803418134182341833418434185341863418734188341893419034191341923419334194341953419634197341983419934200342013420234203342043420534206342073420834209342103421134212342133421434215342163421734218342193422034221342223422334224342253422634227342283422934230342313423234233342343423534236342373423834239342403424134242342433424434245342463424734248342493425034251342523425334254342553425634257342583425934260342613426234263342643426534266342673426834269342703427134272342733427434275342763427734278342793428034281342823428334284342853428634287342883428934290342913429234293342943429534296342973429834299343003430134302343033430434305343063430734308343093431034311343123431334314343153431634317343183431934320343213432234323343243432534326343273432834329343303433134332343333433434335343363433734338343393434034341343423434334344343453434634347343483434934350343513435234353343543435534356343573435834359343603436134362343633436434365343663436734368343693437034371343723437334374343753437634377343783437934380343813438234383343843438534386343873438834389343903439134392343933439434395343963439734398343993440034401344023440334404344053440634407344083440934410344113441234413344143441534416344173441834419344203442134422344233442434425344263442734428344293443034431344323443334434344353443634437344383443934440344413444234443344443444534446344473444834449344503445134452344533445434455344563445734458344593446034461344623446334464344653446634467344683446934470344713447234473344743447534476344773447834479344803448134482344833448434485344863448734488344893449034491344923449334494344953449634497344983449934500345013450234503345043450534506345073450834509345103451134512345133451434515345163451734518345193452034521345223452334524345253452634527345283452934530345313453234533345343453534536345373453834539345403454134542345433454434545345463454734548345493455034551345523455334554345553455634557345583455934560345613456234563345643456534566345673456834569345703457134572345733457434575345763457734578345793458034581345823458334584345853458634587345883458934590345913459234593345943459534596345973459834599346003460134602346033460434605346063460734608346093461034611346123461334614346153461634617346183461934620346213462234623346243462534626346273462834629346303463134632346333463434635346363463734638346393464034641346423464334644346453464634647346483464934650346513465234653346543465534656346573465834659346603466134662346633466434665346663466734668346693467034671346723467334674346753467634677346783467934680346813468234683346843468534686346873468834689346903469134692346933469434695346963469734698346993470034701347023470334704347053470634707347083470934710347113471234713347143471534716347173471834719347203472134722347233472434725347263472734728347293473034731347323473334734347353473634737347383473934740347413474234743347443474534746347473474834749347503475134752347533475434755347563475734758347593476034761347623476334764347653476634767347683476934770347713477234773347743477534776347773477834779347803478134782347833478434785347863478734788347893479034791347923479334794347953479634797347983479934800348013480234803348043480534806348073480834809348103481134812348133481434815348163481734818348193482034821348223482334824348253482634827348283482934830348313483234833348343483534836348373483834839348403484134842348433484434845348463484734848348493485034851348523485334854348553485634857348583485934860348613486234863348643486534866348673486834869348703487134872348733487434875348763487734878348793488034881348823488334884348853488634887348883488934890348913489234893348943489534896348973489834899349003490134902349033490434905349063490734908349093491034911349123491334914349153491634917349183491934920349213492234923349243492534926349273492834929349303493134932349333493434935349363493734938349393494034941349423494334944349453494634947349483494934950349513495234953349543495534956349573495834959349603496134962349633496434965349663496734968349693497034971349723497334974349753497634977349783497934980349813498234983349843498534986349873498834989349903499134992349933499434995349963499734998349993500035001350023500335004350053500635007350083500935010350113501235013350143501535016350173501835019350203502135022350233502435025350263502735028350293503035031350323503335034350353503635037350383503935040350413504235043350443504535046350473504835049350503505135052350533505435055350563505735058350593506035061350623506335064350653506635067350683506935070350713507235073350743507535076350773507835079350803508135082350833508435085350863508735088350893509035091350923509335094350953509635097350983509935100351013510235103351043510535106351073510835109351103511135112351133511435115351163511735118351193512035121351223512335124351253512635127351283512935130351313513235133351343513535136351373513835139351403514135142351433514435145351463514735148351493515035151351523515335154351553515635157351583515935160351613516235163351643516535166351673516835169351703517135172351733517435175351763517735178351793518035181351823518335184351853518635187351883518935190351913519235193351943519535196351973519835199352003520135202352033520435205352063520735208352093521035211352123521335214352153521635217352183521935220352213522235223352243522535226352273522835229352303523135232352333523435235352363523735238352393524035241352423524335244352453524635247352483524935250352513525235253352543525535256352573525835259352603526135262352633526435265352663526735268352693527035271352723527335274352753527635277352783527935280352813528235283352843528535286352873528835289352903529135292352933529435295352963529735298352993530035301353023530335304353053530635307353083530935310353113531235313353143531535316353173531835319353203532135322353233532435325353263532735328353293533035331353323533335334353353533635337353383533935340353413534235343353443534535346353473534835349353503535135352353533535435355353563535735358353593536035361353623536335364353653536635367353683536935370353713537235373353743537535376353773537835379353803538135382353833538435385353863538735388353893539035391353923539335394353953539635397353983539935400354013540235403354043540535406354073540835409354103541135412354133541435415354163541735418354193542035421354223542335424354253542635427354283542935430354313543235433354343543535436354373543835439354403544135442354433544435445354463544735448354493545035451354523545335454354553545635457354583545935460354613546235463354643546535466354673546835469354703547135472354733547435475354763547735478354793548035481354823548335484354853548635487354883548935490354913549235493354943549535496354973549835499355003550135502355033550435505355063550735508355093551035511355123551335514355153551635517355183551935520355213552235523355243552535526355273552835529355303553135532355333553435535355363553735538355393554035541355423554335544355453554635547355483554935550355513555235553355543555535556355573555835559355603556135562355633556435565355663556735568355693557035571355723557335574355753557635577355783557935580355813558235583355843558535586355873558835589355903559135592355933559435595355963559735598355993560035601356023560335604356053560635607356083560935610356113561235613356143561535616356173561835619356203562135622356233562435625356263562735628356293563035631356323563335634356353563635637356383563935640356413564235643356443564535646356473564835649356503565135652356533565435655356563565735658356593566035661356623566335664356653566635667356683566935670356713567235673356743567535676356773567835679356803568135682356833568435685356863568735688356893569035691356923569335694356953569635697356983569935700357013570235703357043570535706357073570835709357103571135712357133571435715357163571735718357193572035721357223572335724357253572635727357283572935730357313573235733357343573535736357373573835739357403574135742357433574435745357463574735748357493575035751357523575335754357553575635757357583575935760357613576235763357643576535766357673576835769357703577135772357733577435775357763577735778357793578035781357823578335784357853578635787357883578935790357913579235793357943579535796357973579835799358003580135802358033580435805358063580735808358093581035811358123581335814358153581635817358183581935820358213582235823358243582535826358273582835829358303583135832358333583435835358363583735838358393584035841358423584335844358453584635847358483584935850358513585235853358543585535856358573585835859358603586135862358633586435865358663586735868358693587035871358723587335874358753587635877358783587935880358813588235883358843588535886358873588835889358903589135892358933589435895358963589735898358993590035901359023590335904359053590635907359083590935910359113591235913359143591535916359173591835919359203592135922359233592435925359263592735928359293593035931359323593335934359353593635937359383593935940359413594235943359443594535946359473594835949359503595135952359533595435955359563595735958359593596035961359623596335964359653596635967359683596935970359713597235973359743597535976359773597835979359803598135982359833598435985359863598735988359893599035991359923599335994359953599635997359983599936000360013600236003360043600536006360073600836009360103601136012360133601436015360163601736018360193602036021360223602336024360253602636027360283602936030360313603236033360343603536036360373603836039360403604136042360433604436045360463604736048360493605036051360523605336054360553605636057360583605936060360613606236063360643606536066360673606836069360703607136072360733607436075360763607736078360793608036081360823608336084360853608636087360883608936090360913609236093360943609536096360973609836099361003610136102361033610436105361063610736108361093611036111361123611336114361153611636117361183611936120361213612236123361243612536126361273612836129361303613136132361333613436135361363613736138361393614036141361423614336144361453614636147361483614936150361513615236153361543615536156361573615836159361603616136162361633616436165361663616736168361693617036171361723617336174361753617636177361783617936180361813618236183361843618536186361873618836189361903619136192361933619436195361963619736198361993620036201362023620336204362053620636207362083620936210362113621236213362143621536216362173621836219362203622136222362233622436225362263622736228362293623036231362323623336234362353623636237362383623936240362413624236243362443624536246362473624836249362503625136252362533625436255362563625736258362593626036261362623626336264362653626636267362683626936270362713627236273362743627536276362773627836279362803628136282362833628436285362863628736288362893629036291362923629336294362953629636297362983629936300363013630236303363043630536306363073630836309363103631136312363133631436315363163631736318363193632036321363223632336324363253632636327363283632936330363313633236333363343633536336363373633836339363403634136342363433634436345363463634736348363493635036351363523635336354363553635636357363583635936360363613636236363363643636536366363673636836369363703637136372363733637436375363763637736378363793638036381363823638336384363853638636387363883638936390363913639236393363943639536396363973639836399364003640136402364033640436405364063640736408364093641036411364123641336414364153641636417364183641936420364213642236423364243642536426364273642836429364303643136432364333643436435364363643736438364393644036441364423644336444364453644636447364483644936450364513645236453364543645536456364573645836459364603646136462364633646436465364663646736468364693647036471364723647336474364753647636477364783647936480364813648236483364843648536486364873648836489364903649136492364933649436495364963649736498364993650036501365023650336504365053650636507365083650936510365113651236513365143651536516365173651836519365203652136522365233652436525365263652736528365293653036531365323653336534365353653636537365383653936540365413654236543365443654536546365473654836549365503655136552365533655436555365563655736558365593656036561365623656336564365653656636567365683656936570365713657236573365743657536576365773657836579365803658136582365833658436585365863658736588365893659036591365923659336594365953659636597365983659936600366013660236603366043660536606366073660836609366103661136612366133661436615366163661736618366193662036621366223662336624366253662636627366283662936630366313663236633366343663536636366373663836639366403664136642366433664436645366463664736648366493665036651366523665336654366553665636657366583665936660366613666236663366643666536666366673666836669366703667136672366733667436675366763667736678366793668036681366823668336684366853668636687366883668936690366913669236693366943669536696366973669836699367003670136702367033670436705367063670736708367093671036711367123671336714367153671636717367183671936720367213672236723367243672536726367273672836729367303673136732367333673436735367363673736738367393674036741367423674336744367453674636747367483674936750367513675236753367543675536756367573675836759367603676136762367633676436765367663676736768367693677036771367723677336774367753677636777367783677936780367813678236783367843678536786367873678836789367903679136792367933679436795367963679736798367993680036801368023680336804368053680636807368083680936810368113681236813368143681536816368173681836819368203682136822368233682436825368263682736828368293683036831368323683336834368353683636837368383683936840368413684236843368443684536846368473684836849368503685136852368533685436855368563685736858368593686036861368623686336864368653686636867368683686936870368713687236873368743687536876368773687836879368803688136882368833688436885368863688736888368893689036891368923689336894368953689636897368983689936900369013690236903369043690536906369073690836909369103691136912369133691436915369163691736918369193692036921369223692336924369253692636927369283692936930369313693236933369343693536936369373693836939369403694136942369433694436945369463694736948369493695036951369523695336954369553695636957369583695936960369613696236963369643696536966369673696836969369703697136972369733697436975369763697736978369793698036981369823698336984369853698636987369883698936990369913699236993369943699536996369973699836999370003700137002370033700437005370063700737008370093701037011370123701337014370153701637017370183701937020370213702237023370243702537026370273702837029370303703137032370333703437035370363703737038370393704037041370423704337044370453704637047370483704937050370513705237053370543705537056370573705837059370603706137062370633706437065370663706737068370693707037071370723707337074370753707637077370783707937080370813708237083370843708537086370873708837089370903709137092370933709437095370963709737098370993710037101371023710337104371053710637107371083710937110371113711237113371143711537116371173711837119371203712137122371233712437125371263712737128371293713037131371323713337134371353713637137371383713937140371413714237143371443714537146371473714837149371503715137152371533715437155371563715737158371593716037161371623716337164371653716637167371683716937170371713717237173371743717537176371773717837179371803718137182371833718437185371863718737188371893719037191371923719337194371953719637197371983719937200372013720237203372043720537206372073720837209372103721137212372133721437215372163721737218372193722037221372223722337224372253722637227372283722937230372313723237233372343723537236372373723837239372403724137242372433724437245372463724737248372493725037251372523725337254372553725637257372583725937260372613726237263372643726537266372673726837269372703727137272372733727437275372763727737278372793728037281372823728337284372853728637287372883728937290372913729237293372943729537296372973729837299373003730137302373033730437305373063730737308373093731037311373123731337314373153731637317373183731937320373213732237323373243732537326373273732837329373303733137332373333733437335373363733737338373393734037341373423734337344373453734637347373483734937350373513735237353373543735537356373573735837359373603736137362373633736437365373663736737368373693737037371373723737337374373753737637377373783737937380373813738237383373843738537386373873738837389373903739137392373933739437395373963739737398373993740037401374023740337404374053740637407374083740937410374113741237413374143741537416374173741837419374203742137422374233742437425374263742737428374293743037431374323743337434374353743637437374383743937440374413744237443374443744537446374473744837449374503745137452374533745437455374563745737458374593746037461374623746337464374653746637467374683746937470374713747237473374743747537476374773747837479374803748137482374833748437485374863748737488374893749037491374923749337494374953749637497374983749937500375013750237503375043750537506375073750837509375103751137512375133751437515375163751737518375193752037521375223752337524375253752637527375283752937530375313753237533375343753537536375373753837539375403754137542375433754437545375463754737548375493755037551375523755337554375553755637557375583755937560375613756237563375643756537566375673756837569375703757137572375733757437575375763757737578375793758037581375823758337584375853758637587375883758937590375913759237593375943759537596375973759837599376003760137602376033760437605376063760737608376093761037611376123761337614376153761637617376183761937620376213762237623376243762537626376273762837629376303763137632376333763437635376363763737638376393764037641376423764337644376453764637647376483764937650376513765237653376543765537656376573765837659376603766137662376633766437665376663766737668376693767037671376723767337674376753767637677376783767937680376813768237683376843768537686376873768837689376903769137692376933769437695376963769737698376993770037701377023770337704377053770637707377083770937710377113771237713377143771537716377173771837719377203772137722377233772437725377263772737728377293773037731377323773337734377353773637737377383773937740377413774237743377443774537746377473774837749377503775137752377533775437755377563775737758377593776037761377623776337764377653776637767377683776937770377713777237773377743777537776377773777837779377803778137782377833778437785377863778737788377893779037791377923779337794377953779637797377983779937800378013780237803378043780537806378073780837809378103781137812378133781437815378163781737818378193782037821378223782337824378253782637827378283782937830378313783237833378343783537836378373783837839378403784137842378433784437845378463784737848378493785037851378523785337854378553785637857378583785937860378613786237863378643786537866378673786837869378703787137872378733787437875378763787737878378793788037881378823788337884378853788637887378883788937890378913789237893378943789537896378973789837899379003790137902379033790437905379063790737908379093791037911379123791337914379153791637917379183791937920379213792237923379243792537926379273792837929379303793137932379333793437935379363793737938379393794037941379423794337944379453794637947379483794937950379513795237953379543795537956379573795837959379603796137962379633796437965379663796737968379693797037971379723797337974379753797637977379783797937980379813798237983379843798537986379873798837989379903799137992379933799437995379963799737998379993800038001380023800338004380053800638007380083800938010380113801238013380143801538016380173801838019380203802138022380233802438025380263802738028380293803038031380323803338034380353803638037380383803938040380413804238043380443804538046380473804838049380503805138052380533805438055380563805738058380593806038061380623806338064380653806638067380683806938070380713807238073380743807538076380773807838079380803808138082380833808438085380863808738088380893809038091380923809338094380953809638097380983809938100381013810238103381043810538106381073810838109381103811138112381133811438115381163811738118381193812038121381223812338124381253812638127381283812938130381313813238133381343813538136381373813838139381403814138142381433814438145381463814738148381493815038151381523815338154381553815638157381583815938160381613816238163381643816538166381673816838169381703817138172381733817438175381763817738178381793818038181381823818338184381853818638187381883818938190381913819238193381943819538196381973819838199382003820138202382033820438205382063820738208382093821038211382123821338214382153821638217382183821938220382213822238223382243822538226382273822838229382303823138232382333823438235382363823738238382393824038241382423824338244382453824638247382483824938250382513825238253382543825538256382573825838259382603826138262382633826438265382663826738268382693827038271382723827338274382753827638277382783827938280382813828238283382843828538286382873828838289382903829138292382933829438295382963829738298382993830038301383023830338304383053830638307383083830938310383113831238313383143831538316383173831838319383203832138322383233832438325383263832738328383293833038331383323833338334383353833638337383383833938340383413834238343383443834538346383473834838349383503835138352383533835438355383563835738358383593836038361383623836338364383653836638367383683836938370383713837238373383743837538376383773837838379383803838138382383833838438385383863838738388383893839038391383923839338394383953839638397383983839938400384013840238403384043840538406384073840838409384103841138412384133841438415384163841738418384193842038421384223842338424384253842638427384283842938430384313843238433384343843538436384373843838439384403844138442384433844438445384463844738448384493845038451384523845338454384553845638457384583845938460384613846238463384643846538466384673846838469384703847138472384733847438475384763847738478384793848038481384823848338484384853848638487384883848938490384913849238493384943849538496384973849838499385003850138502385033850438505385063850738508385093851038511385123851338514385153851638517385183851938520385213852238523385243852538526385273852838529385303853138532385333853438535385363853738538385393854038541385423854338544385453854638547385483854938550385513855238553385543855538556385573855838559385603856138562385633856438565385663856738568385693857038571385723857338574385753857638577385783857938580385813858238583385843858538586385873858838589385903859138592385933859438595385963859738598385993860038601386023860338604386053860638607386083860938610386113861238613386143861538616386173861838619386203862138622386233862438625386263862738628386293863038631386323863338634386353863638637386383863938640386413864238643386443864538646386473864838649386503865138652386533865438655386563865738658386593866038661386623866338664386653866638667386683866938670386713867238673386743867538676386773867838679386803868138682386833868438685386863868738688386893869038691386923869338694386953869638697386983869938700387013870238703387043870538706387073870838709387103871138712387133871438715387163871738718387193872038721387223872338724387253872638727387283872938730387313873238733387343873538736387373873838739387403874138742387433874438745387463874738748387493875038751387523875338754387553875638757387583875938760387613876238763387643876538766387673876838769387703877138772387733877438775387763877738778387793878038781387823878338784387853878638787387883878938790387913879238793387943879538796387973879838799388003880138802388033880438805388063880738808388093881038811388123881338814388153881638817388183881938820388213882238823388243882538826388273882838829388303883138832388333883438835388363883738838388393884038841388423884338844388453884638847388483884938850388513885238853388543885538856388573885838859388603886138862388633886438865388663886738868388693887038871388723887338874388753887638877388783887938880388813888238883388843888538886388873888838889388903889138892388933889438895388963889738898388993890038901389023890338904389053890638907389083890938910389113891238913389143891538916389173891838919389203892138922389233892438925389263892738928389293893038931389323893338934389353893638937389383893938940389413894238943389443894538946389473894838949389503895138952389533895438955389563895738958389593896038961389623896338964389653896638967389683896938970389713897238973389743897538976389773897838979389803898138982389833898438985389863898738988389893899038991389923899338994389953899638997389983899939000390013900239003390043900539006390073900839009390103901139012390133901439015390163901739018390193902039021390223902339024390253902639027390283902939030390313903239033390343903539036390373903839039390403904139042390433904439045390463904739048390493905039051390523905339054390553905639057390583905939060390613906239063390643906539066390673906839069390703907139072390733907439075390763907739078390793908039081390823908339084390853908639087390883908939090390913909239093390943909539096390973909839099391003910139102391033910439105391063910739108391093911039111391123911339114391153911639117391183911939120391213912239123391243912539126391273912839129391303913139132391333913439135391363913739138391393914039141391423914339144391453914639147391483914939150391513915239153391543915539156391573915839159391603916139162391633916439165391663916739168391693917039171391723917339174391753917639177391783917939180391813918239183391843918539186391873918839189391903919139192391933919439195391963919739198391993920039201392023920339204392053920639207392083920939210392113921239213392143921539216392173921839219392203922139222392233922439225392263922739228392293923039231392323923339234392353923639237392383923939240392413924239243392443924539246392473924839249392503925139252392533925439255392563925739258392593926039261392623926339264392653926639267392683926939270392713927239273392743927539276392773927839279392803928139282392833928439285392863928739288392893929039291392923929339294392953929639297392983929939300393013930239303393043930539306393073930839309393103931139312393133931439315393163931739318393193932039321393223932339324393253932639327393283932939330393313933239333393343933539336393373933839339393403934139342393433934439345393463934739348393493935039351393523935339354393553935639357393583935939360393613936239363393643936539366393673936839369393703937139372393733937439375393763937739378393793938039381393823938339384393853938639387393883938939390393913939239393393943939539396393973939839399394003940139402394033940439405394063940739408394093941039411394123941339414394153941639417394183941939420394213942239423394243942539426394273942839429394303943139432394333943439435394363943739438394393944039441394423944339444394453944639447394483944939450394513945239453394543945539456394573945839459394603946139462394633946439465394663946739468394693947039471394723947339474394753947639477394783947939480394813948239483394843948539486394873948839489394903949139492394933949439495394963949739498394993950039501395023950339504395053950639507395083950939510395113951239513395143951539516395173951839519395203952139522395233952439525395263952739528395293953039531395323953339534395353953639537395383953939540395413954239543395443954539546395473954839549395503955139552395533955439555395563955739558395593956039561395623956339564395653956639567395683956939570395713957239573395743957539576395773957839579395803958139582395833958439585395863958739588395893959039591395923959339594395953959639597395983959939600396013960239603396043960539606396073960839609396103961139612396133961439615396163961739618396193962039621396223962339624396253962639627396283962939630396313963239633396343963539636396373963839639396403964139642396433964439645396463964739648396493965039651396523965339654396553965639657396583965939660396613966239663396643966539666396673966839669396703967139672396733967439675396763967739678396793968039681396823968339684396853968639687396883968939690396913969239693396943969539696396973969839699397003970139702397033970439705397063970739708397093971039711397123971339714397153971639717397183971939720397213972239723397243972539726397273972839729397303973139732397333973439735397363973739738397393974039741397423974339744397453974639747397483974939750397513975239753397543975539756397573975839759397603976139762397633976439765397663976739768397693977039771397723977339774397753977639777397783977939780397813978239783397843978539786397873978839789397903979139792397933979439795397963979739798397993980039801398023980339804398053980639807398083980939810398113981239813398143981539816398173981839819398203982139822398233982439825398263982739828398293983039831398323983339834398353983639837398383983939840398413984239843398443984539846398473984839849398503985139852398533985439855398563985739858398593986039861398623986339864398653986639867398683986939870398713987239873398743987539876398773987839879398803988139882398833988439885398863988739888398893989039891398923989339894398953989639897398983989939900399013990239903399043990539906399073990839909399103991139912399133991439915399163991739918399193992039921399223992339924399253992639927399283992939930399313993239933399343993539936399373993839939399403994139942399433994439945399463994739948399493995039951399523995339954399553995639957399583995939960399613996239963399643996539966399673996839969399703997139972399733997439975399763997739978399793998039981399823998339984399853998639987399883998939990399913999239993399943999539996399973999839999400004000140002400034000440005400064000740008400094001040011400124001340014400154001640017400184001940020400214002240023400244002540026400274002840029400304003140032400334003440035400364003740038400394004040041400424004340044400454004640047400484004940050400514005240053400544005540056400574005840059400604006140062400634006440065400664006740068400694007040071400724007340074400754007640077400784007940080400814008240083400844008540086400874008840089400904009140092400934009440095400964009740098400994010040101401024010340104401054010640107401084010940110401114011240113401144011540116401174011840119401204012140122401234012440125401264012740128401294013040131401324013340134401354013640137401384013940140401414014240143401444014540146401474014840149401504015140152401534015440155401564015740158401594016040161401624016340164401654016640167401684016940170401714017240173401744017540176401774017840179401804018140182401834018440185401864018740188401894019040191401924019340194401954019640197401984019940200402014020240203402044020540206402074020840209402104021140212402134021440215402164021740218402194022040221402224022340224402254022640227402284022940230402314023240233402344023540236402374023840239402404024140242402434024440245402464024740248402494025040251402524025340254402554025640257402584025940260402614026240263402644026540266402674026840269402704027140272402734027440275402764027740278402794028040281402824028340284402854028640287402884028940290402914029240293402944029540296402974029840299403004030140302403034030440305403064030740308403094031040311403124031340314403154031640317403184031940320403214032240323403244032540326403274032840329403304033140332403334033440335403364033740338403394034040341403424034340344403454034640347403484034940350403514035240353403544035540356403574035840359403604036140362403634036440365403664036740368403694037040371403724037340374403754037640377403784037940380403814038240383403844038540386403874038840389403904039140392403934039440395403964039740398403994040040401404024040340404404054040640407404084040940410404114041240413404144041540416404174041840419404204042140422404234042440425404264042740428404294043040431404324043340434404354043640437404384043940440404414044240443404444044540446404474044840449404504045140452404534045440455404564045740458404594046040461404624046340464404654046640467404684046940470404714047240473404744047540476404774047840479404804048140482404834048440485404864048740488404894049040491404924049340494404954049640497404984049940500405014050240503405044050540506405074050840509405104051140512405134051440515405164051740518405194052040521405224052340524405254052640527405284052940530405314053240533405344053540536405374053840539405404054140542405434054440545405464054740548405494055040551405524055340554405554055640557405584055940560405614056240563405644056540566405674056840569405704057140572405734057440575405764057740578405794058040581405824058340584405854058640587405884058940590405914059240593405944059540596405974059840599406004060140602406034060440605406064060740608406094061040611406124061340614406154061640617406184061940620406214062240623406244062540626406274062840629406304063140632406334063440635406364063740638406394064040641406424064340644406454064640647406484064940650406514065240653406544065540656406574065840659406604066140662406634066440665406664066740668406694067040671406724067340674406754067640677406784067940680406814068240683406844068540686406874068840689406904069140692406934069440695406964069740698406994070040701407024070340704407054070640707407084070940710407114071240713407144071540716407174071840719407204072140722407234072440725407264072740728407294073040731407324073340734407354073640737407384073940740407414074240743407444074540746407474074840749407504075140752407534075440755407564075740758407594076040761407624076340764407654076640767407684076940770407714077240773407744077540776407774077840779407804078140782407834078440785407864078740788407894079040791407924079340794407954079640797407984079940800408014080240803408044080540806408074080840809408104081140812408134081440815408164081740818408194082040821408224082340824408254082640827408284082940830408314083240833408344083540836408374083840839408404084140842408434084440845408464084740848408494085040851408524085340854408554085640857408584085940860408614086240863408644086540866408674086840869408704087140872408734087440875408764087740878408794088040881408824088340884408854088640887408884088940890408914089240893408944089540896408974089840899409004090140902409034090440905409064090740908409094091040911409124091340914409154091640917409184091940920409214092240923409244092540926409274092840929409304093140932409334093440935409364093740938409394094040941409424094340944409454094640947409484094940950409514095240953409544095540956409574095840959409604096140962409634096440965409664096740968409694097040971409724097340974409754097640977409784097940980409814098240983409844098540986409874098840989409904099140992409934099440995409964099740998409994100041001410024100341004410054100641007410084100941010410114101241013410144101541016410174101841019410204102141022410234102441025410264102741028410294103041031410324103341034410354103641037410384103941040410414104241043410444104541046410474104841049410504105141052410534105441055410564105741058410594106041061410624106341064410654106641067410684106941070410714107241073410744107541076410774107841079410804108141082410834108441085410864108741088410894109041091410924109341094410954109641097410984109941100411014110241103411044110541106411074110841109411104111141112411134111441115411164111741118411194112041121411224112341124411254112641127411284112941130411314113241133411344113541136411374113841139411404114141142411434114441145411464114741148411494115041151411524115341154411554115641157411584115941160411614116241163411644116541166411674116841169411704117141172411734117441175411764117741178411794118041181411824118341184411854118641187411884118941190411914119241193411944119541196411974119841199412004120141202412034120441205412064120741208412094121041211412124121341214412154121641217412184121941220412214122241223412244122541226412274122841229412304123141232412334123441235412364123741238412394124041241412424124341244412454124641247412484124941250412514125241253412544125541256412574125841259412604126141262412634126441265412664126741268412694127041271412724127341274412754127641277412784127941280412814128241283412844128541286412874128841289412904129141292412934129441295412964129741298412994130041301413024130341304413054130641307413084130941310413114131241313413144131541316413174131841319413204132141322413234132441325413264132741328413294133041331413324133341334413354133641337413384133941340413414134241343413444134541346413474134841349413504135141352413534135441355413564135741358413594136041361413624136341364413654136641367413684136941370413714137241373413744137541376413774137841379413804138141382413834138441385413864138741388413894139041391413924139341394413954139641397413984139941400414014140241403414044140541406414074140841409414104141141412414134141441415414164141741418414194142041421414224142341424414254142641427414284142941430414314143241433414344143541436414374143841439414404144141442414434144441445414464144741448414494145041451414524145341454414554145641457414584145941460414614146241463414644146541466414674146841469414704147141472414734147441475414764147741478414794148041481414824148341484414854148641487414884148941490414914149241493414944149541496414974149841499415004150141502415034150441505415064150741508415094151041511415124151341514415154151641517415184151941520415214152241523415244152541526415274152841529415304153141532415334153441535415364153741538415394154041541415424154341544415454154641547415484154941550415514155241553415544155541556415574155841559415604156141562415634156441565415664156741568415694157041571415724157341574415754157641577415784157941580415814158241583415844158541586415874158841589415904159141592415934159441595415964159741598415994160041601416024160341604416054160641607416084160941610416114161241613416144161541616416174161841619416204162141622416234162441625416264162741628416294163041631416324163341634416354163641637416384163941640416414164241643416444164541646416474164841649416504165141652416534165441655416564165741658416594166041661416624166341664416654166641667416684166941670416714167241673416744167541676416774167841679416804168141682416834168441685416864168741688416894169041691416924169341694416954169641697416984169941700417014170241703417044170541706417074170841709417104171141712417134171441715417164171741718417194172041721417224172341724417254172641727417284172941730417314173241733417344173541736417374173841739417404174141742417434174441745417464174741748417494175041751417524175341754417554175641757417584175941760417614176241763417644176541766417674176841769417704177141772417734177441775417764177741778417794178041781417824178341784417854178641787417884178941790417914179241793417944179541796417974179841799418004180141802418034180441805418064180741808418094181041811418124181341814418154181641817418184181941820418214182241823418244182541826418274182841829418304183141832418334183441835418364183741838418394184041841418424184341844418454184641847418484184941850418514185241853418544185541856418574185841859418604186141862418634186441865418664186741868418694187041871418724187341874418754187641877418784187941880418814188241883418844188541886418874188841889418904189141892418934189441895418964189741898418994190041901419024190341904419054190641907419084190941910419114191241913419144191541916419174191841919419204192141922419234192441925419264192741928419294193041931419324193341934419354193641937419384193941940419414194241943419444194541946419474194841949419504195141952419534195441955419564195741958419594196041961419624196341964419654196641967419684196941970419714197241973419744197541976419774197841979419804198141982419834198441985419864198741988419894199041991419924199341994419954199641997419984199942000420014200242003420044200542006420074200842009420104201142012420134201442015420164201742018420194202042021420224202342024420254202642027420284202942030420314203242033420344203542036420374203842039420404204142042420434204442045420464204742048420494205042051420524205342054420554205642057420584205942060420614206242063420644206542066420674206842069420704207142072420734207442075420764207742078420794208042081420824208342084420854208642087420884208942090420914209242093420944209542096420974209842099421004210142102421034210442105421064210742108421094211042111421124211342114421154211642117421184211942120421214212242123421244212542126421274212842129421304213142132421334213442135421364213742138421394214042141421424214342144421454214642147421484214942150421514215242153421544215542156421574215842159421604216142162421634216442165421664216742168421694217042171421724217342174421754217642177421784217942180421814218242183421844218542186421874218842189421904219142192421934219442195421964219742198421994220042201422024220342204422054220642207422084220942210422114221242213422144221542216422174221842219422204222142222422234222442225422264222742228422294223042231422324223342234422354223642237422384223942240422414224242243422444224542246422474224842249422504225142252422534225442255422564225742258422594226042261422624226342264422654226642267422684226942270422714227242273422744227542276422774227842279422804228142282422834228442285422864228742288422894229042291422924229342294422954229642297422984229942300423014230242303423044230542306423074230842309423104231142312423134231442315423164231742318423194232042321423224232342324423254232642327423284232942330423314233242333423344233542336423374233842339423404234142342423434234442345423464234742348423494235042351423524235342354423554235642357423584235942360423614236242363423644236542366423674236842369423704237142372423734237442375423764237742378423794238042381423824238342384423854238642387423884238942390423914239242393423944239542396423974239842399424004240142402424034240442405424064240742408424094241042411424124241342414424154241642417424184241942420424214242242423424244242542426424274242842429424304243142432424334243442435424364243742438424394244042441424424244342444424454244642447424484244942450424514245242453424544245542456424574245842459424604246142462424634246442465424664246742468424694247042471424724247342474424754247642477424784247942480424814248242483424844248542486424874248842489424904249142492424934249442495424964249742498424994250042501425024250342504425054250642507425084250942510425114251242513425144251542516425174251842519425204252142522425234252442525425264252742528425294253042531425324253342534425354253642537425384253942540425414254242543425444254542546425474254842549425504255142552425534255442555425564255742558425594256042561425624256342564425654256642567425684256942570425714257242573425744257542576425774257842579425804258142582425834258442585425864258742588425894259042591425924259342594425954259642597425984259942600426014260242603426044260542606426074260842609426104261142612426134261442615426164261742618426194262042621426224262342624426254262642627426284262942630426314263242633426344263542636426374263842639426404264142642426434264442645426464264742648426494265042651426524265342654426554265642657426584265942660426614266242663426644266542666426674266842669426704267142672426734267442675426764267742678426794268042681426824268342684426854268642687426884268942690426914269242693426944269542696426974269842699427004270142702427034270442705427064270742708427094271042711427124271342714427154271642717427184271942720427214272242723427244272542726427274272842729427304273142732427334273442735427364273742738427394274042741427424274342744427454274642747427484274942750427514275242753427544275542756427574275842759427604276142762427634276442765427664276742768427694277042771427724277342774427754277642777427784277942780427814278242783427844278542786427874278842789427904279142792427934279442795427964279742798427994280042801428024280342804428054280642807428084280942810428114281242813428144281542816428174281842819428204282142822428234282442825428264282742828428294283042831428324283342834428354283642837428384283942840428414284242843428444284542846428474284842849428504285142852428534285442855428564285742858428594286042861428624286342864428654286642867428684286942870428714287242873428744287542876428774287842879428804288142882428834288442885428864288742888428894289042891428924289342894428954289642897428984289942900429014290242903429044290542906429074290842909429104291142912429134291442915429164291742918429194292042921429224292342924429254292642927429284292942930429314293242933429344293542936429374293842939429404294142942429434294442945429464294742948429494295042951429524295342954429554295642957429584295942960429614296242963429644296542966429674296842969429704297142972429734297442975429764297742978429794298042981429824298342984429854298642987429884298942990429914299242993429944299542996429974299842999430004300143002430034300443005430064300743008430094301043011430124301343014430154301643017430184301943020430214302243023430244302543026430274302843029430304303143032430334303443035430364303743038430394304043041430424304343044430454304643047430484304943050430514305243053430544305543056430574305843059430604306143062430634306443065430664306743068430694307043071430724307343074430754307643077430784307943080430814308243083430844308543086430874308843089430904309143092430934309443095430964309743098430994310043101431024310343104431054310643107431084310943110431114311243113431144311543116431174311843119431204312143122431234312443125431264312743128431294313043131431324313343134431354313643137431384313943140431414314243143431444314543146431474314843149431504315143152431534315443155431564315743158431594316043161431624316343164431654316643167431684316943170431714317243173431744317543176431774317843179431804318143182431834318443185431864318743188431894319043191431924319343194431954319643197431984319943200432014320243203432044320543206432074320843209432104321143212432134321443215432164321743218432194322043221432224322343224432254322643227432284322943230432314323243233432344323543236432374323843239432404324143242432434324443245432464324743248432494325043251432524325343254432554325643257432584325943260432614326243263432644326543266432674326843269432704327143272432734327443275432764327743278432794328043281432824328343284432854328643287432884328943290432914329243293432944329543296432974329843299433004330143302433034330443305433064330743308433094331043311433124331343314433154331643317433184331943320433214332243323433244332543326433274332843329433304333143332433334333443335433364333743338433394334043341433424334343344433454334643347433484334943350433514335243353433544335543356433574335843359433604336143362433634336443365433664336743368433694337043371433724337343374433754337643377433784337943380433814338243383433844338543386433874338843389433904339143392433934339443395433964339743398433994340043401434024340343404434054340643407434084340943410434114341243413434144341543416434174341843419434204342143422434234342443425434264342743428434294343043431434324343343434434354343643437434384343943440434414344243443434444344543446434474344843449434504345143452434534345443455434564345743458434594346043461434624346343464434654346643467434684346943470434714347243473434744347543476434774347843479434804348143482434834348443485434864348743488434894349043491434924349343494434954349643497434984349943500435014350243503435044350543506435074350843509435104351143512435134351443515435164351743518435194352043521435224352343524435254352643527435284352943530435314353243533435344353543536435374353843539435404354143542435434354443545435464354743548435494355043551435524355343554435554355643557435584355943560435614356243563435644356543566435674356843569435704357143572435734357443575435764357743578435794358043581435824358343584435854358643587435884358943590435914359243593435944359543596435974359843599436004360143602436034360443605436064360743608436094361043611436124361343614436154361643617436184361943620436214362243623436244362543626436274362843629436304363143632436334363443635436364363743638436394364043641436424364343644436454364643647436484364943650436514365243653436544365543656436574365843659436604366143662436634366443665436664366743668436694367043671436724367343674436754367643677436784367943680436814368243683436844368543686436874368843689436904369143692436934369443695436964369743698436994370043701437024370343704437054370643707437084370943710437114371243713437144371543716437174371843719437204372143722437234372443725437264372743728437294373043731437324373343734437354373643737437384373943740437414374243743437444374543746437474374843749437504375143752437534375443755437564375743758437594376043761437624376343764437654376643767437684376943770437714377243773437744377543776437774377843779437804378143782437834378443785437864378743788437894379043791437924379343794437954379643797437984379943800438014380243803438044380543806438074380843809438104381143812438134381443815438164381743818438194382043821438224382343824438254382643827438284382943830438314383243833438344383543836438374383843839438404384143842438434384443845438464384743848438494385043851438524385343854438554385643857438584385943860438614386243863438644386543866438674386843869438704387143872438734387443875438764387743878438794388043881438824388343884438854388643887438884388943890438914389243893438944389543896438974389843899439004390143902439034390443905439064390743908439094391043911439124391343914439154391643917439184391943920439214392243923439244392543926439274392843929439304393143932439334393443935439364393743938439394394043941439424394343944439454394643947439484394943950439514395243953439544395543956439574395843959439604396143962439634396443965439664396743968439694397043971439724397343974439754397643977439784397943980439814398243983439844398543986439874398843989439904399143992439934399443995439964399743998439994400044001440024400344004440054400644007440084400944010440114401244013440144401544016440174401844019440204402144022440234402444025440264402744028440294403044031440324403344034440354403644037440384403944040440414404244043440444404544046440474404844049440504405144052440534405444055440564405744058440594406044061440624406344064440654406644067440684406944070440714407244073440744407544076440774407844079440804408144082440834408444085440864408744088440894409044091440924409344094440954409644097440984409944100441014410244103441044410544106441074410844109441104411144112441134411444115441164411744118441194412044121441224412344124441254412644127441284412944130441314413244133441344413544136441374413844139441404414144142441434414444145441464414744148441494415044151441524415344154441554415644157441584415944160441614416244163441644416544166441674416844169441704417144172441734417444175441764417744178441794418044181441824418344184441854418644187441884418944190441914419244193441944419544196441974419844199442004420144202442034420444205442064420744208442094421044211442124421344214442154421644217442184421944220442214422244223442244422544226442274422844229442304423144232442334423444235442364423744238442394424044241442424424344244442454424644247442484424944250442514425244253442544425544256442574425844259442604426144262442634426444265442664426744268442694427044271442724427344274442754427644277442784427944280442814428244283442844428544286442874428844289442904429144292442934429444295442964429744298442994430044301443024430344304443054430644307443084430944310443114431244313443144431544316443174431844319443204432144322443234432444325443264432744328443294433044331443324433344334443354433644337443384433944340443414434244343443444434544346443474434844349443504435144352443534435444355443564435744358443594436044361443624436344364443654436644367443684436944370443714437244373443744437544376443774437844379443804438144382443834438444385443864438744388443894439044391443924439344394443954439644397443984439944400444014440244403444044440544406444074440844409444104441144412444134441444415444164441744418444194442044421444224442344424444254442644427444284442944430444314443244433444344443544436444374443844439444404444144442444434444444445444464444744448444494445044451444524445344454444554445644457444584445944460444614446244463444644446544466444674446844469444704447144472444734447444475444764447744478444794448044481444824448344484444854448644487444884448944490444914449244493444944449544496444974449844499445004450144502445034450444505445064450744508445094451044511445124451344514445154451644517445184451944520445214452244523445244452544526445274452844529445304453144532445334453444535445364453744538445394454044541445424454344544445454454644547445484454944550445514455244553445544455544556445574455844559445604456144562445634456444565445664456744568445694457044571445724457344574445754457644577445784457944580445814458244583445844458544586445874458844589445904459144592445934459444595445964459744598445994460044601446024460344604446054460644607446084460944610446114461244613446144461544616446174461844619446204462144622446234462444625446264462744628446294463044631446324463344634446354463644637446384463944640446414464244643446444464544646446474464844649446504465144652446534465444655446564465744658446594466044661446624466344664446654466644667446684466944670446714467244673446744467544676446774467844679446804468144682446834468444685446864468744688446894469044691446924469344694446954469644697446984469944700447014470244703447044470544706447074470844709447104471144712447134471444715447164471744718447194472044721447224472344724447254472644727447284472944730447314473244733447344473544736447374473844739447404474144742447434474444745447464474744748447494475044751447524475344754447554475644757447584475944760447614476244763447644476544766447674476844769447704477144772447734477444775447764477744778447794478044781447824478344784447854478644787447884478944790447914479244793447944479544796447974479844799448004480144802448034480444805448064480744808448094481044811448124481344814448154481644817448184481944820448214482244823448244482544826448274482844829448304483144832448334483444835448364483744838448394484044841448424484344844448454484644847448484484944850448514485244853448544485544856448574485844859448604486144862448634486444865448664486744868448694487044871448724487344874448754487644877448784487944880448814488244883448844488544886448874488844889448904489144892448934489444895448964489744898448994490044901449024490344904449054490644907449084490944910449114491244913449144491544916449174491844919449204492144922449234492444925449264492744928449294493044931449324493344934449354493644937449384493944940449414494244943449444494544946449474494844949449504495144952449534495444955449564495744958449594496044961449624496344964449654496644967449684496944970449714497244973449744497544976449774497844979449804498144982449834498444985449864498744988449894499044991449924499344994449954499644997449984499945000450014500245003450044500545006450074500845009450104501145012450134501445015450164501745018450194502045021450224502345024450254502645027450284502945030450314503245033450344503545036450374503845039450404504145042450434504445045450464504745048450494505045051450524505345054450554505645057450584505945060450614506245063450644506545066450674506845069450704507145072450734507445075450764507745078450794508045081450824508345084450854508645087450884508945090450914509245093450944509545096450974509845099451004510145102451034510445105451064510745108451094511045111451124511345114451154511645117451184511945120451214512245123451244512545126451274512845129451304513145132451334513445135451364513745138451394514045141451424514345144451454514645147451484514945150451514515245153451544515545156451574515845159451604516145162451634516445165451664516745168451694517045171451724517345174451754517645177451784517945180451814518245183451844518545186451874518845189451904519145192451934519445195451964519745198451994520045201452024520345204452054520645207452084520945210452114521245213452144521545216452174521845219452204522145222452234522445225452264522745228452294523045231452324523345234452354523645237452384523945240452414524245243452444524545246452474524845249452504525145252452534525445255452564525745258452594526045261452624526345264452654526645267452684526945270452714527245273452744527545276452774527845279452804528145282452834528445285452864528745288452894529045291452924529345294452954529645297452984529945300453014530245303453044530545306453074530845309453104531145312453134531445315453164531745318453194532045321453224532345324453254532645327453284532945330453314533245333453344533545336453374533845339453404534145342453434534445345453464534745348453494535045351453524535345354453554535645357453584535945360453614536245363453644536545366453674536845369453704537145372453734537445375453764537745378453794538045381453824538345384453854538645387453884538945390453914539245393453944539545396453974539845399454004540145402454034540445405454064540745408454094541045411454124541345414454154541645417454184541945420454214542245423454244542545426454274542845429454304543145432454334543445435454364543745438454394544045441454424544345444454454544645447454484544945450454514545245453454544545545456454574545845459454604546145462454634546445465454664546745468454694547045471454724547345474454754547645477454784547945480454814548245483454844548545486454874548845489454904549145492454934549445495454964549745498454994550045501455024550345504455054550645507455084550945510455114551245513455144551545516455174551845519455204552145522455234552445525455264552745528455294553045531455324553345534455354553645537455384553945540455414554245543455444554545546455474554845549455504555145552455534555445555455564555745558455594556045561455624556345564455654556645567455684556945570455714557245573455744557545576455774557845579455804558145582455834558445585455864558745588455894559045591455924559345594455954559645597455984559945600456014560245603456044560545606456074560845609456104561145612456134561445615456164561745618456194562045621456224562345624456254562645627456284562945630456314563245633456344563545636456374563845639456404564145642456434564445645456464564745648456494565045651456524565345654456554565645657456584565945660456614566245663456644566545666456674566845669456704567145672456734567445675456764567745678456794568045681456824568345684456854568645687456884568945690456914569245693456944569545696456974569845699457004570145702457034570445705457064570745708457094571045711457124571345714457154571645717457184571945720457214572245723457244572545726457274572845729457304573145732457334573445735457364573745738457394574045741457424574345744457454574645747457484574945750457514575245753457544575545756457574575845759457604576145762457634576445765457664576745768457694577045771457724577345774457754577645777457784577945780457814578245783457844578545786457874578845789457904579145792457934579445795457964579745798457994580045801458024580345804458054580645807458084580945810458114581245813458144581545816458174581845819458204582145822458234582445825458264582745828458294583045831458324583345834458354583645837458384583945840458414584245843458444584545846458474584845849458504585145852458534585445855458564585745858458594586045861458624586345864458654586645867458684586945870458714587245873458744587545876458774587845879458804588145882458834588445885458864588745888458894589045891458924589345894458954589645897458984589945900459014590245903459044590545906459074590845909459104591145912459134591445915459164591745918459194592045921459224592345924459254592645927459284592945930459314593245933459344593545936459374593845939459404594145942459434594445945459464594745948459494595045951459524595345954459554595645957459584595945960459614596245963459644596545966459674596845969459704597145972459734597445975459764597745978459794598045981459824598345984459854598645987459884598945990459914599245993459944599545996459974599845999460004600146002460034600446005460064600746008460094601046011460124601346014460154601646017460184601946020460214602246023460244602546026460274602846029460304603146032460334603446035460364603746038460394604046041460424604346044460454604646047460484604946050460514605246053460544605546056460574605846059460604606146062460634606446065460664606746068460694607046071460724607346074460754607646077460784607946080460814608246083460844608546086460874608846089460904609146092460934609446095460964609746098460994610046101461024610346104461054610646107461084610946110461114611246113461144611546116461174611846119461204612146122461234612446125461264612746128461294613046131461324613346134461354613646137461384613946140461414614246143461444614546146461474614846149461504615146152461534615446155461564615746158461594616046161461624616346164461654616646167461684616946170461714617246173461744617546176461774617846179461804618146182461834618446185461864618746188461894619046191461924619346194461954619646197461984619946200462014620246203462044620546206462074620846209462104621146212462134621446215462164621746218462194622046221462224622346224462254622646227462284622946230462314623246233462344623546236462374623846239462404624146242462434624446245462464624746248462494625046251462524625346254462554625646257462584625946260462614626246263462644626546266462674626846269462704627146272462734627446275462764627746278462794628046281462824628346284462854628646287462884628946290462914629246293462944629546296462974629846299463004630146302463034630446305463064630746308463094631046311463124631346314463154631646317463184631946320463214632246323463244632546326463274632846329463304633146332463334633446335463364633746338463394634046341463424634346344463454634646347463484634946350463514635246353463544635546356463574635846359463604636146362463634636446365463664636746368463694637046371463724637346374463754637646377463784637946380463814638246383463844638546386463874638846389463904639146392463934639446395463964639746398463994640046401464024640346404464054640646407464084640946410464114641246413464144641546416464174641846419464204642146422464234642446425464264642746428464294643046431464324643346434464354643646437464384643946440464414644246443464444644546446464474644846449464504645146452464534645446455464564645746458464594646046461464624646346464464654646646467464684646946470464714647246473464744647546476464774647846479464804648146482464834648446485464864648746488464894649046491464924649346494464954649646497464984649946500465014650246503465044650546506465074650846509465104651146512465134651446515465164651746518465194652046521465224652346524465254652646527465284652946530465314653246533465344653546536465374653846539465404654146542465434654446545465464654746548465494655046551465524655346554465554655646557465584655946560465614656246563465644656546566465674656846569465704657146572465734657446575465764657746578465794658046581465824658346584465854658646587465884658946590465914659246593465944659546596465974659846599466004660146602466034660446605466064660746608466094661046611466124661346614466154661646617466184661946620466214662246623466244662546626466274662846629466304663146632466334663446635466364663746638466394664046641466424664346644466454664646647466484664946650466514665246653466544665546656466574665846659466604666146662466634666446665466664666746668466694667046671466724667346674466754667646677466784667946680466814668246683466844668546686466874668846689466904669146692466934669446695466964669746698466994670046701467024670346704467054670646707467084670946710467114671246713467144671546716467174671846719467204672146722467234672446725467264672746728467294673046731467324673346734467354673646737467384673946740467414674246743467444674546746467474674846749467504675146752467534675446755467564675746758467594676046761467624676346764467654676646767467684676946770467714677246773467744677546776467774677846779467804678146782467834678446785467864678746788467894679046791467924679346794467954679646797467984679946800468014680246803468044680546806468074680846809468104681146812468134681446815468164681746818468194682046821468224682346824468254682646827468284682946830468314683246833468344683546836468374683846839468404684146842468434684446845468464684746848468494685046851468524685346854468554685646857468584685946860468614686246863468644686546866468674686846869468704687146872468734687446875468764687746878468794688046881468824688346884468854688646887468884688946890468914689246893468944689546896468974689846899469004690146902469034690446905469064690746908469094691046911469124691346914469154691646917469184691946920469214692246923469244692546926469274692846929469304693146932469334693446935469364693746938469394694046941469424694346944469454694646947469484694946950469514695246953469544695546956469574695846959469604696146962469634696446965469664696746968469694697046971469724697346974469754697646977469784697946980469814698246983469844698546986469874698846989469904699146992469934699446995469964699746998469994700047001470024700347004470054700647007470084700947010470114701247013470144701547016470174701847019470204702147022470234702447025470264702747028470294703047031470324703347034470354703647037470384703947040470414704247043470444704547046470474704847049470504705147052470534705447055470564705747058470594706047061470624706347064470654706647067470684706947070470714707247073470744707547076470774707847079470804708147082470834708447085470864708747088470894709047091470924709347094470954709647097470984709947100471014710247103471044710547106471074710847109471104711147112471134711447115471164711747118471194712047121471224712347124471254712647127471284712947130471314713247133471344713547136471374713847139471404714147142471434714447145471464714747148471494715047151471524715347154471554715647157471584715947160471614716247163471644716547166471674716847169471704717147172471734717447175471764717747178471794718047181471824718347184471854718647187471884718947190471914719247193471944719547196471974719847199472004720147202472034720447205472064720747208472094721047211472124721347214472154721647217472184721947220472214722247223472244722547226472274722847229472304723147232472334723447235472364723747238472394724047241472424724347244472454724647247472484724947250472514725247253472544725547256472574725847259472604726147262472634726447265472664726747268472694727047271472724727347274472754727647277472784727947280472814728247283472844728547286472874728847289472904729147292472934729447295472964729747298472994730047301473024730347304473054730647307473084730947310473114731247313473144731547316473174731847319473204732147322473234732447325473264732747328473294733047331473324733347334473354733647337473384733947340473414734247343473444734547346473474734847349473504735147352473534735447355473564735747358473594736047361473624736347364473654736647367473684736947370473714737247373473744737547376473774737847379473804738147382473834738447385473864738747388473894739047391473924739347394473954739647397473984739947400474014740247403474044740547406474074740847409474104741147412474134741447415474164741747418474194742047421474224742347424474254742647427474284742947430474314743247433474344743547436474374743847439474404744147442474434744447445474464744747448474494745047451474524745347454474554745647457474584745947460474614746247463474644746547466474674746847469474704747147472474734747447475474764747747478474794748047481474824748347484474854748647487474884748947490474914749247493474944749547496474974749847499475004750147502475034750447505475064750747508475094751047511475124751347514475154751647517475184751947520475214752247523475244752547526475274752847529475304753147532475334753447535475364753747538475394754047541475424754347544475454754647547475484754947550475514755247553475544755547556475574755847559475604756147562475634756447565475664756747568475694757047571475724757347574475754757647577475784757947580475814758247583475844758547586475874758847589475904759147592475934759447595475964759747598475994760047601476024760347604476054760647607476084760947610476114761247613476144761547616476174761847619476204762147622476234762447625476264762747628476294763047631476324763347634476354763647637476384763947640476414764247643476444764547646476474764847649476504765147652476534765447655476564765747658476594766047661476624766347664476654766647667476684766947670476714767247673476744767547676476774767847679476804768147682476834768447685476864768747688476894769047691476924769347694476954769647697476984769947700477014770247703477044770547706477074770847709477104771147712477134771447715477164771747718477194772047721477224772347724477254772647727477284772947730477314773247733477344773547736477374773847739477404774147742477434774447745477464774747748477494775047751477524775347754477554775647757477584775947760477614776247763477644776547766477674776847769477704777147772477734777447775477764777747778477794778047781477824778347784477854778647787477884778947790477914779247793477944779547796477974779847799478004780147802478034780447805478064780747808478094781047811478124781347814478154781647817478184781947820478214782247823478244782547826478274782847829478304783147832478334783447835478364783747838478394784047841478424784347844478454784647847478484784947850478514785247853478544785547856478574785847859478604786147862478634786447865478664786747868478694787047871478724787347874478754787647877478784787947880478814788247883478844788547886478874788847889478904789147892478934789447895478964789747898478994790047901479024790347904479054790647907479084790947910479114791247913479144791547916479174791847919479204792147922479234792447925479264792747928479294793047931479324793347934479354793647937479384793947940479414794247943479444794547946479474794847949479504795147952479534795447955479564795747958479594796047961479624796347964479654796647967479684796947970479714797247973479744797547976479774797847979479804798147982479834798447985479864798747988479894799047991479924799347994479954799647997479984799948000480014800248003480044800548006480074800848009480104801148012480134801448015480164801748018480194802048021480224802348024480254802648027480284802948030480314803248033480344803548036480374803848039480404804148042480434804448045480464804748048480494805048051480524805348054480554805648057480584805948060480614806248063480644806548066480674806848069480704807148072480734807448075480764807748078480794808048081480824808348084480854808648087480884808948090480914809248093480944809548096480974809848099481004810148102481034810448105481064810748108481094811048111481124811348114481154811648117481184811948120481214812248123481244812548126481274812848129481304813148132481334813448135481364813748138481394814048141481424814348144481454814648147481484814948150481514815248153481544815548156481574815848159481604816148162481634816448165481664816748168481694817048171481724817348174481754817648177481784817948180481814818248183481844818548186481874818848189481904819148192481934819448195481964819748198481994820048201482024820348204482054820648207482084820948210482114821248213482144821548216482174821848219482204822148222482234822448225482264822748228482294823048231482324823348234482354823648237482384823948240482414824248243482444824548246482474824848249482504825148252482534825448255482564825748258482594826048261482624826348264482654826648267482684826948270482714827248273482744827548276482774827848279482804828148282482834828448285482864828748288482894829048291482924829348294482954829648297482984829948300483014830248303483044830548306483074830848309483104831148312483134831448315483164831748318483194832048321483224832348324483254832648327483284832948330483314833248333483344833548336483374833848339483404834148342483434834448345483464834748348483494835048351483524835348354483554835648357483584835948360483614836248363483644836548366483674836848369483704837148372483734837448375483764837748378483794838048381483824838348384483854838648387483884838948390483914839248393483944839548396483974839848399484004840148402484034840448405484064840748408484094841048411484124841348414484154841648417484184841948420484214842248423484244842548426484274842848429484304843148432484334843448435484364843748438484394844048441484424844348444484454844648447484484844948450484514845248453484544845548456484574845848459484604846148462484634846448465484664846748468484694847048471484724847348474484754847648477484784847948480484814848248483484844848548486484874848848489484904849148492484934849448495484964849748498484994850048501485024850348504485054850648507485084850948510485114851248513485144851548516485174851848519485204852148522485234852448525485264852748528485294853048531485324853348534485354853648537485384853948540485414854248543485444854548546485474854848549485504855148552485534855448555485564855748558485594856048561485624856348564485654856648567485684856948570485714857248573485744857548576485774857848579485804858148582485834858448585485864858748588485894859048591485924859348594485954859648597485984859948600486014860248603486044860548606486074860848609486104861148612486134861448615486164861748618486194862048621486224862348624486254862648627486284862948630486314863248633486344863548636486374863848639486404864148642486434864448645486464864748648486494865048651486524865348654486554865648657486584865948660486614866248663486644866548666486674866848669486704867148672486734867448675486764867748678486794868048681486824868348684486854868648687486884868948690486914869248693486944869548696486974869848699487004870148702487034870448705487064870748708487094871048711487124871348714487154871648717487184871948720487214872248723487244872548726487274872848729487304873148732487334873448735487364873748738487394874048741487424874348744487454874648747487484874948750487514875248753487544875548756487574875848759487604876148762487634876448765487664876748768487694877048771487724877348774487754877648777487784877948780487814878248783487844878548786487874878848789487904879148792487934879448795487964879748798487994880048801488024880348804488054880648807488084880948810488114881248813488144881548816488174881848819488204882148822488234882448825488264882748828488294883048831488324883348834488354883648837488384883948840488414884248843488444884548846488474884848849488504885148852488534885448855488564885748858488594886048861488624886348864488654886648867488684886948870488714887248873488744887548876488774887848879488804888148882488834888448885488864888748888488894889048891488924889348894488954889648897488984889948900489014890248903489044890548906489074890848909489104891148912489134891448915489164891748918489194892048921489224892348924489254892648927489284892948930489314893248933489344893548936489374893848939489404894148942489434894448945489464894748948489494895048951489524895348954489554895648957489584895948960489614896248963489644896548966489674896848969489704897148972489734897448975489764897748978489794898048981489824898348984489854898648987489884898948990489914899248993489944899548996489974899848999490004900149002490034900449005490064900749008490094901049011490124901349014490154901649017490184901949020490214902249023490244902549026490274902849029490304903149032490334903449035490364903749038490394904049041490424904349044490454904649047490484904949050490514905249053490544905549056490574905849059490604906149062490634906449065490664906749068490694907049071490724907349074490754907649077490784907949080490814908249083490844908549086490874908849089490904909149092490934909449095490964909749098490994910049101491024910349104491054910649107491084910949110491114911249113491144911549116491174911849119491204912149122491234912449125491264912749128491294913049131491324913349134491354913649137491384913949140491414914249143491444914549146491474914849149491504915149152491534915449155491564915749158491594916049161491624916349164491654916649167491684916949170491714917249173491744917549176491774917849179491804918149182491834918449185491864918749188491894919049191491924919349194491954919649197491984919949200492014920249203492044920549206492074920849209492104921149212492134921449215492164921749218492194922049221492224922349224492254922649227492284922949230492314923249233492344923549236492374923849239492404924149242492434924449245492464924749248492494925049251492524925349254492554925649257492584925949260492614926249263492644926549266492674926849269492704927149272492734927449275492764927749278492794928049281492824928349284492854928649287492884928949290492914929249293492944929549296492974929849299493004930149302493034930449305493064930749308493094931049311493124931349314493154931649317493184931949320493214932249323493244932549326493274932849329493304933149332493334933449335493364933749338493394934049341493424934349344493454934649347493484934949350493514935249353493544935549356493574935849359493604936149362493634936449365493664936749368493694937049371493724937349374493754937649377493784937949380493814938249383493844938549386493874938849389493904939149392493934939449395493964939749398493994940049401494024940349404494054940649407494084940949410494114941249413494144941549416494174941849419494204942149422494234942449425494264942749428494294943049431494324943349434494354943649437494384943949440494414944249443494444944549446494474944849449494504945149452494534945449455494564945749458494594946049461494624946349464494654946649467494684946949470494714947249473494744947549476494774947849479494804948149482494834948449485494864948749488494894949049491494924949349494494954949649497494984949949500495014950249503495044950549506495074950849509495104951149512495134951449515495164951749518495194952049521495224952349524495254952649527495284952949530495314953249533495344953549536495374953849539495404954149542495434954449545495464954749548495494955049551495524955349554495554955649557495584955949560495614956249563495644956549566495674956849569495704957149572495734957449575495764957749578495794958049581495824958349584495854958649587495884958949590495914959249593495944959549596495974959849599496004960149602496034960449605496064960749608496094961049611496124961349614496154961649617496184961949620496214962249623496244962549626496274962849629496304963149632496334963449635496364963749638496394964049641496424964349644496454964649647496484964949650496514965249653496544965549656496574965849659496604966149662496634966449665496664966749668496694967049671496724967349674496754967649677496784967949680496814968249683496844968549686496874968849689496904969149692496934969449695496964969749698496994970049701497024970349704497054970649707497084970949710497114971249713497144971549716497174971849719497204972149722497234972449725497264972749728497294973049731497324973349734497354973649737497384973949740497414974249743497444974549746497474974849749497504975149752497534975449755497564975749758497594976049761497624976349764497654976649767497684976949770497714977249773497744977549776497774977849779497804978149782497834978449785497864978749788497894979049791497924979349794497954979649797497984979949800498014980249803498044980549806498074980849809498104981149812498134981449815498164981749818498194982049821498224982349824498254982649827498284982949830498314983249833498344983549836498374983849839498404984149842498434984449845498464984749848498494985049851498524985349854498554985649857498584985949860498614986249863498644986549866498674986849869498704987149872498734987449875498764987749878498794988049881498824988349884498854988649887498884988949890498914989249893498944989549896498974989849899499004990149902499034990449905499064990749908499094991049911499124991349914499154991649917499184991949920499214992249923499244992549926499274992849929499304993149932499334993449935499364993749938499394994049941499424994349944499454994649947499484994949950499514995249953499544995549956499574995849959499604996149962499634996449965499664996749968499694997049971499724997349974499754997649977499784997949980499814998249983499844998549986499874998849989499904999149992499934999449995499964999749998499995000050001500025000350004500055000650007500085000950010500115001250013500145001550016500175001850019500205002150022500235002450025500265002750028500295003050031500325003350034500355003650037500385003950040500415004250043500445004550046500475004850049500505005150052500535005450055500565005750058500595006050061500625006350064500655006650067500685006950070500715007250073500745007550076500775007850079500805008150082500835008450085500865008750088500895009050091500925009350094500955009650097500985009950100501015010250103501045010550106501075010850109501105011150112501135011450115501165011750118501195012050121501225012350124501255012650127501285012950130501315013250133501345013550136501375013850139501405014150142501435014450145501465014750148501495015050151501525015350154501555015650157501585015950160501615016250163501645016550166501675016850169501705017150172501735017450175501765017750178501795018050181501825018350184501855018650187501885018950190501915019250193501945019550196501975019850199502005020150202502035020450205502065020750208502095021050211502125021350214502155021650217502185021950220502215022250223502245022550226502275022850229502305023150232502335023450235502365023750238502395024050241502425024350244502455024650247502485024950250502515025250253502545025550256502575025850259502605026150262502635026450265502665026750268502695027050271502725027350274502755027650277502785027950280502815028250283502845028550286502875028850289502905029150292502935029450295502965029750298502995030050301503025030350304503055030650307503085030950310503115031250313503145031550316503175031850319503205032150322503235032450325503265032750328503295033050331503325033350334503355033650337503385033950340503415034250343503445034550346503475034850349503505035150352503535035450355503565035750358503595036050361503625036350364503655036650367503685036950370503715037250373503745037550376503775037850379503805038150382503835038450385503865038750388503895039050391503925039350394503955039650397503985039950400504015040250403504045040550406504075040850409504105041150412504135041450415504165041750418504195042050421504225042350424504255042650427504285042950430504315043250433504345043550436504375043850439504405044150442504435044450445504465044750448504495045050451504525045350454504555045650457504585045950460504615046250463504645046550466504675046850469504705047150472504735047450475504765047750478504795048050481504825048350484504855048650487504885048950490504915049250493504945049550496504975049850499505005050150502505035050450505505065050750508505095051050511505125051350514505155051650517505185051950520505215052250523505245052550526505275052850529505305053150532505335053450535505365053750538505395054050541505425054350544505455054650547505485054950550505515055250553505545055550556505575055850559505605056150562505635056450565505665056750568505695057050571505725057350574505755057650577505785057950580505815058250583505845058550586505875058850589505905059150592505935059450595505965059750598505995060050601506025060350604506055060650607506085060950610506115061250613506145061550616506175061850619506205062150622506235062450625506265062750628506295063050631506325063350634506355063650637506385063950640506415064250643506445064550646506475064850649506505065150652506535065450655506565065750658506595066050661506625066350664506655066650667506685066950670506715067250673506745067550676506775067850679506805068150682506835068450685506865068750688506895069050691506925069350694506955069650697506985069950700507015070250703507045070550706507075070850709507105071150712507135071450715507165071750718507195072050721507225072350724507255072650727507285072950730507315073250733507345073550736507375073850739507405074150742507435074450745507465074750748507495075050751507525075350754507555075650757507585075950760507615076250763507645076550766507675076850769507705077150772507735077450775507765077750778507795078050781507825078350784507855078650787507885078950790507915079250793507945079550796507975079850799508005080150802508035080450805508065080750808508095081050811508125081350814508155081650817508185081950820508215082250823508245082550826508275082850829508305083150832508335083450835508365083750838508395084050841508425084350844508455084650847508485084950850508515085250853508545085550856508575085850859508605086150862508635086450865508665086750868508695087050871508725087350874508755087650877508785087950880508815088250883508845088550886508875088850889508905089150892508935089450895508965089750898508995090050901509025090350904509055090650907509085090950910509115091250913509145091550916509175091850919509205092150922509235092450925509265092750928509295093050931509325093350934509355093650937509385093950940509415094250943509445094550946509475094850949509505095150952509535095450955509565095750958509595096050961509625096350964509655096650967509685096950970509715097250973509745097550976509775097850979509805098150982509835098450985509865098750988509895099050991509925099350994509955099650997509985099951000510015100251003510045100551006510075100851009510105101151012510135101451015510165101751018510195102051021510225102351024510255102651027510285102951030510315103251033510345103551036510375103851039510405104151042510435104451045510465104751048510495105051051510525105351054510555105651057510585105951060510615106251063510645106551066510675106851069510705107151072510735107451075510765107751078510795108051081510825108351084510855108651087510885108951090510915109251093510945109551096510975109851099511005110151102511035110451105511065110751108511095111051111511125111351114511155111651117511185111951120511215112251123511245112551126511275112851129511305113151132511335113451135511365113751138511395114051141511425114351144511455114651147511485114951150511515115251153511545115551156511575115851159511605116151162511635116451165511665116751168511695117051171511725117351174511755117651177511785117951180511815118251183511845118551186511875118851189511905119151192511935119451195511965119751198511995120051201512025120351204512055120651207512085120951210512115121251213512145121551216512175121851219512205122151222512235122451225512265122751228512295123051231512325123351234512355123651237512385123951240512415124251243512445124551246512475124851249512505125151252512535125451255512565125751258512595126051261512625126351264512655126651267512685126951270512715127251273512745127551276512775127851279512805128151282512835128451285512865128751288512895129051291512925129351294512955129651297512985129951300513015130251303513045130551306513075130851309513105131151312513135131451315513165131751318513195132051321513225132351324513255132651327513285132951330513315133251333513345133551336513375133851339513405134151342513435134451345513465134751348513495135051351513525135351354513555135651357513585135951360513615136251363513645136551366513675136851369513705137151372513735137451375513765137751378513795138051381513825138351384513855138651387513885138951390513915139251393513945139551396513975139851399514005140151402514035140451405514065140751408514095141051411514125141351414514155141651417514185141951420514215142251423514245142551426514275142851429514305143151432514335143451435514365143751438514395144051441514425144351444514455144651447514485144951450514515145251453514545145551456514575145851459514605146151462514635146451465514665146751468514695147051471514725147351474514755147651477514785147951480514815148251483514845148551486514875148851489514905149151492514935149451495514965149751498514995150051501515025150351504515055150651507515085150951510515115151251513515145151551516515175151851519515205152151522515235152451525515265152751528515295153051531515325153351534515355153651537515385153951540515415154251543515445154551546515475154851549515505155151552515535155451555515565155751558515595156051561515625156351564515655156651567515685156951570515715157251573515745157551576515775157851579515805158151582515835158451585515865158751588515895159051591515925159351594515955159651597515985159951600516015160251603516045160551606516075160851609516105161151612516135161451615516165161751618516195162051621516225162351624516255162651627516285162951630516315163251633516345163551636516375163851639516405164151642516435164451645516465164751648516495165051651516525165351654516555165651657516585165951660516615166251663516645166551666516675166851669516705167151672516735167451675516765167751678516795168051681516825168351684516855168651687516885168951690516915169251693516945169551696516975169851699517005170151702517035170451705517065170751708517095171051711517125171351714517155171651717517185171951720517215172251723517245172551726517275172851729517305173151732517335173451735517365173751738517395174051741517425174351744517455174651747517485174951750517515175251753517545175551756517575175851759517605176151762517635176451765517665176751768517695177051771517725177351774517755177651777517785177951780517815178251783517845178551786517875178851789517905179151792517935179451795517965179751798517995180051801518025180351804518055180651807518085180951810518115181251813518145181551816518175181851819518205182151822518235182451825518265182751828518295183051831518325183351834518355183651837518385183951840518415184251843518445184551846518475184851849518505185151852518535185451855518565185751858518595186051861518625186351864518655186651867518685186951870518715187251873518745187551876518775187851879518805188151882518835188451885518865188751888518895189051891518925189351894518955189651897518985189951900519015190251903519045190551906519075190851909519105191151912519135191451915519165191751918519195192051921519225192351924519255192651927519285192951930519315193251933519345193551936519375193851939519405194151942519435194451945519465194751948519495195051951519525195351954519555195651957519585195951960519615196251963519645196551966519675196851969519705197151972519735197451975519765197751978519795198051981519825198351984519855198651987519885198951990519915199251993519945199551996519975199851999520005200152002520035200452005520065200752008520095201052011520125201352014520155201652017520185201952020520215202252023520245202552026520275202852029520305203152032520335203452035520365203752038520395204052041520425204352044520455204652047520485204952050520515205252053520545205552056520575205852059520605206152062520635206452065520665206752068520695207052071520725207352074520755207652077520785207952080520815208252083520845208552086520875208852089520905209152092520935209452095520965209752098520995210052101521025210352104521055210652107521085210952110521115211252113521145211552116521175211852119521205212152122521235212452125521265212752128521295213052131521325213352134521355213652137521385213952140521415214252143521445214552146521475214852149521505215152152521535215452155521565215752158521595216052161521625216352164521655216652167521685216952170521715217252173521745217552176521775217852179521805218152182521835218452185521865218752188521895219052191521925219352194521955219652197521985219952200522015220252203522045220552206522075220852209522105221152212522135221452215522165221752218522195222052221522225222352224522255222652227522285222952230522315223252233522345223552236522375223852239522405224152242522435224452245522465224752248522495225052251522525225352254522555225652257522585225952260522615226252263522645226552266522675226852269522705227152272522735227452275522765227752278522795228052281522825228352284522855228652287522885228952290522915229252293522945229552296522975229852299523005230152302523035230452305523065230752308523095231052311523125231352314523155231652317523185231952320523215232252323523245232552326523275232852329523305233152332523335233452335523365233752338523395234052341523425234352344523455234652347523485234952350523515235252353523545235552356523575235852359523605236152362523635236452365523665236752368523695237052371523725237352374523755237652377523785237952380523815238252383523845238552386523875238852389523905239152392523935239452395523965239752398523995240052401524025240352404524055240652407524085240952410524115241252413524145241552416524175241852419524205242152422524235242452425524265242752428524295243052431524325243352434524355243652437524385243952440524415244252443524445244552446524475244852449524505245152452524535245452455524565245752458524595246052461524625246352464524655246652467524685246952470524715247252473524745247552476524775247852479524805248152482524835248452485524865248752488524895249052491524925249352494524955249652497524985249952500525015250252503525045250552506525075250852509525105251152512525135251452515525165251752518525195252052521525225252352524525255252652527525285252952530525315253252533525345253552536525375253852539525405254152542525435254452545525465254752548525495255052551525525255352554525555255652557525585255952560525615256252563525645256552566525675256852569525705257152572525735257452575525765257752578525795258052581525825258352584525855258652587525885258952590525915259252593525945259552596525975259852599526005260152602526035260452605526065260752608526095261052611526125261352614526155261652617526185261952620526215262252623526245262552626526275262852629526305263152632526335263452635526365263752638526395264052641526425264352644526455264652647526485264952650526515265252653526545265552656526575265852659526605266152662526635266452665526665266752668526695267052671526725267352674526755267652677526785267952680526815268252683526845268552686526875268852689526905269152692526935269452695526965269752698526995270052701527025270352704527055270652707527085270952710527115271252713527145271552716527175271852719527205272152722527235272452725527265272752728527295273052731527325273352734527355273652737527385273952740527415274252743527445274552746527475274852749527505275152752527535275452755527565275752758527595276052761527625276352764527655276652767527685276952770527715277252773527745277552776527775277852779527805278152782527835278452785527865278752788527895279052791527925279352794527955279652797527985279952800528015280252803528045280552806528075280852809528105281152812528135281452815528165281752818528195282052821528225282352824528255282652827528285282952830528315283252833528345283552836528375283852839528405284152842528435284452845528465284752848528495285052851528525285352854528555285652857528585285952860528615286252863528645286552866528675286852869528705287152872528735287452875528765287752878528795288052881528825288352884528855288652887528885288952890528915289252893528945289552896528975289852899529005290152902529035290452905529065290752908529095291052911529125291352914529155291652917529185291952920529215292252923529245292552926529275292852929529305293152932529335293452935529365293752938529395294052941529425294352944529455294652947529485294952950529515295252953529545295552956529575295852959529605296152962529635296452965529665296752968529695297052971529725297352974529755297652977529785297952980529815298252983529845298552986529875298852989529905299152992529935299452995529965299752998529995300053001530025300353004530055300653007530085300953010530115301253013530145301553016530175301853019530205302153022530235302453025530265302753028530295303053031530325303353034530355303653037530385303953040530415304253043530445304553046530475304853049530505305153052530535305453055530565305753058530595306053061530625306353064530655306653067530685306953070530715307253073530745307553076530775307853079530805308153082530835308453085530865308753088530895309053091530925309353094530955309653097530985309953100531015310253103531045310553106531075310853109531105311153112531135311453115531165311753118531195312053121531225312353124531255312653127531285312953130531315313253133531345313553136531375313853139531405314153142531435314453145531465314753148531495315053151531525315353154531555315653157531585315953160531615316253163531645316553166531675316853169531705317153172531735317453175531765317753178531795318053181531825318353184531855318653187531885318953190531915319253193531945319553196531975319853199532005320153202532035320453205532065320753208532095321053211532125321353214532155321653217532185321953220532215322253223532245322553226532275322853229532305323153232532335323453235532365323753238532395324053241532425324353244532455324653247532485324953250532515325253253532545325553256532575325853259532605326153262532635326453265532665326753268532695327053271532725327353274532755327653277532785327953280532815328253283532845328553286532875328853289532905329153292532935329453295532965329753298532995330053301533025330353304533055330653307533085330953310533115331253313533145331553316533175331853319533205332153322533235332453325533265332753328533295333053331533325333353334533355333653337533385333953340533415334253343533445334553346533475334853349533505335153352533535335453355533565335753358533595336053361533625336353364533655336653367533685336953370533715337253373533745337553376533775337853379533805338153382533835338453385533865338753388533895339053391533925339353394533955339653397533985339953400534015340253403534045340553406534075340853409534105341153412534135341453415534165341753418534195342053421534225342353424534255342653427534285342953430534315343253433534345343553436534375343853439534405344153442534435344453445534465344753448534495345053451534525345353454534555345653457534585345953460534615346253463534645346553466534675346853469534705347153472534735347453475534765347753478534795348053481534825348353484534855348653487534885348953490534915349253493534945349553496534975349853499535005350153502535035350453505535065350753508535095351053511535125351353514535155351653517535185351953520535215352253523535245352553526535275352853529535305353153532535335353453535535365353753538535395354053541535425354353544535455354653547535485354953550535515355253553535545355553556535575355853559535605356153562535635356453565535665356753568535695357053571535725357353574535755357653577535785357953580535815358253583535845358553586535875358853589535905359153592535935359453595535965359753598535995360053601536025360353604536055360653607536085360953610536115361253613536145361553616536175361853619536205362153622536235362453625536265362753628536295363053631536325363353634536355363653637536385363953640536415364253643536445364553646536475364853649536505365153652536535365453655536565365753658536595366053661536625366353664536655366653667536685366953670536715367253673536745367553676536775367853679536805368153682536835368453685536865368753688536895369053691536925369353694536955369653697536985369953700537015370253703537045370553706537075370853709537105371153712537135371453715537165371753718537195372053721537225372353724537255372653727537285372953730537315373253733537345373553736537375373853739537405374153742537435374453745537465374753748537495375053751537525375353754537555375653757537585375953760537615376253763537645376553766537675376853769537705377153772537735377453775537765377753778537795378053781537825378353784537855378653787537885378953790537915379253793537945379553796537975379853799538005380153802538035380453805538065380753808538095381053811538125381353814538155381653817538185381953820538215382253823538245382553826538275382853829538305383153832538335383453835538365383753838538395384053841538425384353844538455384653847538485384953850538515385253853538545385553856538575385853859538605386153862538635386453865538665386753868538695387053871538725387353874538755387653877538785387953880538815388253883538845388553886538875388853889538905389153892538935389453895538965389753898538995390053901539025390353904539055390653907539085390953910539115391253913539145391553916539175391853919539205392153922539235392453925539265392753928539295393053931539325393353934539355393653937539385393953940539415394253943539445394553946539475394853949539505395153952539535395453955539565395753958539595396053961539625396353964539655396653967539685396953970539715397253973539745397553976539775397853979539805398153982539835398453985539865398753988539895399053991539925399353994539955399653997539985399954000540015400254003540045400554006540075400854009540105401154012540135401454015540165401754018540195402054021540225402354024540255402654027540285402954030540315403254033540345403554036540375403854039540405404154042540435404454045540465404754048540495405054051540525405354054540555405654057540585405954060540615406254063540645406554066540675406854069540705407154072540735407454075540765407754078540795408054081540825408354084540855408654087540885408954090540915409254093540945409554096540975409854099541005410154102541035410454105541065410754108541095411054111541125411354114541155411654117541185411954120541215412254123541245412554126541275412854129541305413154132541335413454135541365413754138541395414054141541425414354144541455414654147541485414954150541515415254153541545415554156541575415854159541605416154162541635416454165541665416754168541695417054171541725417354174541755417654177541785417954180541815418254183541845418554186541875418854189541905419154192541935419454195541965419754198541995420054201542025420354204542055420654207542085420954210542115421254213542145421554216542175421854219542205422154222542235422454225542265422754228542295423054231542325423354234542355423654237542385423954240542415424254243542445424554246542475424854249542505425154252542535425454255542565425754258542595426054261542625426354264542655426654267542685426954270542715427254273542745427554276542775427854279542805428154282542835428454285542865428754288542895429054291542925429354294542955429654297542985429954300543015430254303543045430554306543075430854309543105431154312543135431454315543165431754318543195432054321543225432354324543255432654327543285432954330543315433254333543345433554336543375433854339543405434154342543435434454345543465434754348543495435054351543525435354354543555435654357543585435954360543615436254363543645436554366543675436854369543705437154372543735437454375543765437754378543795438054381543825438354384543855438654387543885438954390543915439254393543945439554396543975439854399544005440154402544035440454405544065440754408544095441054411544125441354414544155441654417544185441954420544215442254423544245442554426544275442854429544305443154432544335443454435544365443754438544395444054441544425444354444544455444654447544485444954450544515445254453544545445554456544575445854459544605446154462544635446454465544665446754468544695447054471544725447354474544755447654477544785447954480544815448254483544845448554486544875448854489544905449154492544935449454495544965449754498544995450054501545025450354504545055450654507545085450954510545115451254513545145451554516545175451854519545205452154522545235452454525545265452754528545295453054531545325453354534545355453654537545385453954540545415454254543545445454554546545475454854549545505455154552545535455454555545565455754558545595456054561545625456354564545655456654567545685456954570545715457254573545745457554576545775457854579545805458154582545835458454585545865458754588545895459054591545925459354594545955459654597545985459954600546015460254603546045460554606546075460854609546105461154612546135461454615546165461754618546195462054621546225462354624546255462654627546285462954630546315463254633546345463554636546375463854639546405464154642546435464454645546465464754648546495465054651546525465354654546555465654657546585465954660546615466254663546645466554666546675466854669546705467154672546735467454675546765467754678546795468054681546825468354684546855468654687546885468954690546915469254693546945469554696546975469854699547005470154702547035470454705547065470754708547095471054711547125471354714547155471654717547185471954720547215472254723547245472554726547275472854729547305473154732547335473454735547365473754738547395474054741547425474354744547455474654747547485474954750547515475254753547545475554756547575475854759547605476154762547635476454765547665476754768547695477054771547725477354774547755477654777547785477954780547815478254783547845478554786547875478854789547905479154792547935479454795547965479754798547995480054801548025480354804548055480654807548085480954810548115481254813548145481554816548175481854819548205482154822548235482454825548265482754828548295483054831548325483354834548355483654837548385483954840548415484254843548445484554846548475484854849548505485154852548535485454855548565485754858548595486054861548625486354864548655486654867548685486954870548715487254873548745487554876548775487854879548805488154882548835488454885548865488754888548895489054891548925489354894548955489654897548985489954900549015490254903549045490554906549075490854909549105491154912549135491454915549165491754918549195492054921549225492354924549255492654927549285492954930549315493254933549345493554936549375493854939549405494154942549435494454945549465494754948549495495054951549525495354954549555495654957549585495954960549615496254963549645496554966549675496854969549705497154972549735497454975549765497754978549795498054981549825498354984549855498654987549885498954990549915499254993549945499554996549975499854999550005500155002550035500455005550065500755008550095501055011550125501355014550155501655017550185501955020550215502255023550245502555026550275502855029550305503155032550335503455035550365503755038550395504055041550425504355044550455504655047550485504955050550515505255053550545505555056550575505855059550605506155062550635506455065550665506755068550695507055071550725507355074550755507655077550785507955080550815508255083550845508555086550875508855089550905509155092550935509455095550965509755098550995510055101551025510355104551055510655107551085510955110551115511255113551145511555116551175511855119551205512155122551235512455125551265512755128551295513055131551325513355134551355513655137551385513955140551415514255143551445514555146551475514855149551505515155152551535515455155551565515755158551595516055161551625516355164551655516655167551685516955170551715517255173551745517555176551775517855179551805518155182551835518455185551865518755188551895519055191551925519355194551955519655197551985519955200552015520255203552045520555206552075520855209552105521155212552135521455215552165521755218552195522055221552225522355224552255522655227552285522955230552315523255233552345523555236552375523855239552405524155242552435524455245552465524755248552495525055251552525525355254552555525655257552585525955260552615526255263552645526555266552675526855269552705527155272552735527455275552765527755278552795528055281552825528355284552855528655287552885528955290552915529255293552945529555296552975529855299553005530155302553035530455305553065530755308553095531055311553125531355314553155531655317553185531955320553215532255323553245532555326553275532855329553305533155332553335533455335553365533755338553395534055341553425534355344553455534655347553485534955350553515535255353553545535555356553575535855359553605536155362553635536455365553665536755368553695537055371553725537355374553755537655377553785537955380553815538255383553845538555386553875538855389553905539155392553935539455395553965539755398553995540055401554025540355404554055540655407554085540955410554115541255413554145541555416554175541855419554205542155422554235542455425554265542755428554295543055431554325543355434554355543655437554385543955440554415544255443554445544555446554475544855449554505545155452554535545455455554565545755458554595546055461554625546355464554655546655467554685546955470554715547255473554745547555476554775547855479554805548155482554835548455485554865548755488554895549055491554925549355494554955549655497554985549955500555015550255503555045550555506555075550855509555105551155512555135551455515555165551755518555195552055521555225552355524555255552655527555285552955530555315553255533555345553555536555375553855539555405554155542555435554455545555465554755548555495555055551555525555355554555555555655557555585555955560555615556255563555645556555566555675556855569555705557155572555735557455575555765557755578555795558055581555825558355584555855558655587555885558955590555915559255593555945559555596555975559855599556005560155602556035560455605556065560755608556095561055611556125561355614556155561655617556185561955620556215562255623556245562555626556275562855629556305563155632556335563455635556365563755638556395564055641556425564355644556455564655647556485564955650556515565255653556545565555656556575565855659556605566155662556635566455665556665566755668556695567055671556725567355674556755567655677556785567955680556815568255683556845568555686556875568855689556905569155692556935569455695556965569755698556995570055701557025570355704557055570655707557085570955710557115571255713557145571555716557175571855719557205572155722557235572455725557265572755728557295573055731557325573355734557355573655737557385573955740557415574255743557445574555746557475574855749557505575155752557535575455755557565575755758557595576055761557625576355764557655576655767557685576955770557715577255773557745577555776557775577855779557805578155782557835578455785557865578755788557895579055791557925579355794557955579655797557985579955800558015580255803558045580555806558075580855809558105581155812558135581455815558165581755818558195582055821558225582355824558255582655827558285582955830558315583255833558345583555836558375583855839558405584155842558435584455845558465584755848558495585055851558525585355854558555585655857558585585955860558615586255863558645586555866558675586855869558705587155872558735587455875558765587755878558795588055881558825588355884558855588655887558885588955890558915589255893558945589555896558975589855899559005590155902559035590455905559065590755908559095591055911559125591355914559155591655917559185591955920559215592255923559245592555926559275592855929559305593155932559335593455935559365593755938559395594055941559425594355944559455594655947559485594955950559515595255953559545595555956559575595855959559605596155962559635596455965559665596755968559695597055971559725597355974559755597655977559785597955980559815598255983559845598555986559875598855989559905599155992559935599455995559965599755998559995600056001560025600356004560055600656007560085600956010560115601256013560145601556016560175601856019560205602156022560235602456025560265602756028560295603056031560325603356034560355603656037560385603956040560415604256043560445604556046560475604856049560505605156052560535605456055560565605756058560595606056061560625606356064560655606656067560685606956070560715607256073560745607556076560775607856079560805608156082560835608456085560865608756088560895609056091560925609356094560955609656097560985609956100561015610256103561045610556106561075610856109561105611156112561135611456115561165611756118561195612056121561225612356124561255612656127561285612956130561315613256133561345613556136561375613856139561405614156142561435614456145561465614756148561495615056151561525615356154561555615656157561585615956160561615616256163561645616556166561675616856169561705617156172561735617456175561765617756178561795618056181561825618356184561855618656187561885618956190561915619256193561945619556196561975619856199562005620156202562035620456205562065620756208562095621056211562125621356214562155621656217562185621956220562215622256223562245622556226562275622856229562305623156232562335623456235562365623756238562395624056241562425624356244562455624656247562485624956250562515625256253562545625556256562575625856259562605626156262562635626456265562665626756268562695627056271562725627356274562755627656277562785627956280562815628256283562845628556286562875628856289562905629156292562935629456295562965629756298562995630056301563025630356304563055630656307563085630956310563115631256313563145631556316563175631856319563205632156322563235632456325563265632756328563295633056331563325633356334563355633656337563385633956340563415634256343563445634556346563475634856349563505635156352563535635456355563565635756358563595636056361563625636356364563655636656367563685636956370563715637256373563745637556376563775637856379563805638156382563835638456385563865638756388563895639056391563925639356394563955639656397563985639956400564015640256403564045640556406564075640856409564105641156412564135641456415564165641756418564195642056421564225642356424564255642656427564285642956430564315643256433564345643556436564375643856439564405644156442564435644456445564465644756448564495645056451564525645356454564555645656457564585645956460564615646256463564645646556466564675646856469564705647156472564735647456475564765647756478564795648056481564825648356484564855648656487564885648956490564915649256493564945649556496564975649856499565005650156502565035650456505565065650756508565095651056511565125651356514565155651656517565185651956520565215652256523565245652556526565275652856529565305653156532565335653456535565365653756538565395654056541565425654356544565455654656547565485654956550565515655256553565545655556556565575655856559565605656156562565635656456565565665656756568565695657056571565725657356574565755657656577565785657956580565815658256583565845658556586565875658856589565905659156592565935659456595565965659756598565995660056601566025660356604566055660656607566085660956610566115661256613566145661556616566175661856619566205662156622566235662456625566265662756628566295663056631566325663356634566355663656637566385663956640566415664256643566445664556646566475664856649566505665156652566535665456655566565665756658566595666056661566625666356664566655666656667566685666956670566715667256673566745667556676566775667856679566805668156682566835668456685566865668756688566895669056691566925669356694566955669656697566985669956700567015670256703567045670556706567075670856709567105671156712567135671456715567165671756718567195672056721567225672356724567255672656727567285672956730567315673256733567345673556736567375673856739567405674156742567435674456745567465674756748567495675056751567525675356754567555675656757567585675956760567615676256763567645676556766567675676856769567705677156772567735677456775567765677756778567795678056781567825678356784567855678656787567885678956790567915679256793567945679556796567975679856799568005680156802568035680456805568065680756808568095681056811568125681356814568155681656817568185681956820568215682256823568245682556826568275682856829568305683156832568335683456835568365683756838568395684056841568425684356844568455684656847568485684956850568515685256853568545685556856568575685856859568605686156862568635686456865568665686756868568695687056871568725687356874568755687656877568785687956880568815688256883568845688556886568875688856889568905689156892568935689456895568965689756898568995690056901569025690356904569055690656907569085690956910569115691256913569145691556916569175691856919569205692156922569235692456925569265692756928569295693056931569325693356934569355693656937569385693956940569415694256943569445694556946569475694856949569505695156952569535695456955569565695756958569595696056961569625696356964569655696656967569685696956970569715697256973569745697556976569775697856979569805698156982569835698456985569865698756988569895699056991569925699356994569955699656997569985699957000570015700257003570045700557006570075700857009570105701157012570135701457015570165701757018570195702057021570225702357024570255702657027570285702957030570315703257033570345703557036570375703857039570405704157042570435704457045570465704757048570495705057051570525705357054570555705657057570585705957060570615706257063570645706557066570675706857069570705707157072570735707457075570765707757078570795708057081570825708357084570855708657087570885708957090570915709257093570945709557096570975709857099571005710157102571035710457105571065710757108571095711057111571125711357114571155711657117571185711957120571215712257123571245712557126571275712857129571305713157132571335713457135571365713757138571395714057141571425714357144571455714657147571485714957150571515715257153571545715557156571575715857159571605716157162571635716457165571665716757168571695717057171571725717357174571755717657177571785717957180571815718257183571845718557186571875718857189571905719157192571935719457195571965719757198571995720057201572025720357204572055720657207572085720957210572115721257213572145721557216572175721857219572205722157222572235722457225572265722757228572295723057231572325723357234572355723657237572385723957240572415724257243572445724557246572475724857249572505725157252572535725457255572565725757258572595726057261572625726357264572655726657267572685726957270572715727257273572745727557276572775727857279572805728157282572835728457285572865728757288572895729057291572925729357294572955729657297572985729957300573015730257303573045730557306573075730857309573105731157312573135731457315573165731757318573195732057321573225732357324573255732657327573285732957330573315733257333573345733557336573375733857339573405734157342573435734457345573465734757348573495735057351573525735357354573555735657357573585735957360573615736257363573645736557366573675736857369573705737157372573735737457375573765737757378573795738057381573825738357384573855738657387573885738957390573915739257393573945739557396573975739857399574005740157402574035740457405574065740757408574095741057411574125741357414574155741657417574185741957420574215742257423574245742557426574275742857429574305743157432574335743457435574365743757438574395744057441574425744357444574455744657447574485744957450574515745257453574545745557456574575745857459574605746157462574635746457465574665746757468574695747057471574725747357474574755747657477574785747957480574815748257483574845748557486574875748857489574905749157492574935749457495574965749757498574995750057501575025750357504575055750657507575085750957510575115751257513575145751557516575175751857519575205752157522575235752457525575265752757528575295753057531575325753357534575355753657537575385753957540575415754257543575445754557546575475754857549575505755157552575535755457555575565755757558575595756057561575625756357564575655756657567575685756957570575715757257573575745757557576575775757857579575805758157582575835758457585575865758757588575895759057591575925759357594575955759657597575985759957600576015760257603576045760557606576075760857609576105761157612576135761457615576165761757618576195762057621576225762357624576255762657627576285762957630576315763257633576345763557636576375763857639576405764157642576435764457645576465764757648576495765057651576525765357654576555765657657576585765957660576615766257663576645766557666576675766857669576705767157672576735767457675576765767757678576795768057681576825768357684576855768657687576885768957690576915769257693576945769557696576975769857699577005770157702577035770457705577065770757708577095771057711577125771357714577155771657717577185771957720577215772257723577245772557726577275772857729577305773157732577335773457735577365773757738577395774057741577425774357744577455774657747577485774957750577515775257753577545775557756577575775857759577605776157762577635776457765577665776757768577695777057771577725777357774577755777657777577785777957780577815778257783577845778557786577875778857789577905779157792577935779457795577965779757798577995780057801578025780357804578055780657807578085780957810578115781257813578145781557816578175781857819578205782157822578235782457825578265782757828578295783057831578325783357834578355783657837578385783957840578415784257843578445784557846578475784857849578505785157852578535785457855578565785757858578595786057861578625786357864578655786657867578685786957870578715787257873578745787557876578775787857879578805788157882578835788457885578865788757888578895789057891578925789357894578955789657897578985789957900579015790257903579045790557906579075790857909579105791157912579135791457915579165791757918579195792057921579225792357924579255792657927579285792957930579315793257933579345793557936579375793857939579405794157942579435794457945579465794757948579495795057951579525795357954579555795657957579585795957960579615796257963579645796557966579675796857969579705797157972579735797457975579765797757978579795798057981579825798357984579855798657987579885798957990579915799257993579945799557996579975799857999580005800158002580035800458005580065800758008580095801058011580125801358014580155801658017580185801958020580215802258023580245802558026580275802858029580305803158032580335803458035580365803758038580395804058041580425804358044580455804658047580485804958050580515805258053580545805558056580575805858059580605806158062580635806458065580665806758068580695807058071580725807358074580755807658077580785807958080580815808258083580845808558086580875808858089580905809158092580935809458095580965809758098580995810058101581025810358104581055810658107581085810958110581115811258113581145811558116581175811858119581205812158122581235812458125581265812758128581295813058131581325813358134581355813658137581385813958140581415814258143581445814558146581475814858149581505815158152581535815458155581565815758158581595816058161581625816358164581655816658167581685816958170581715817258173581745817558176581775817858179581805818158182581835818458185581865818758188581895819058191581925819358194581955819658197581985819958200582015820258203582045820558206582075820858209582105821158212582135821458215582165821758218582195822058221582225822358224582255822658227582285822958230582315823258233582345823558236582375823858239582405824158242582435824458245582465824758248582495825058251582525825358254582555825658257582585825958260582615826258263582645826558266582675826858269582705827158272582735827458275582765827758278582795828058281582825828358284582855828658287582885828958290582915829258293582945829558296582975829858299583005830158302583035830458305583065830758308583095831058311583125831358314583155831658317583185831958320583215832258323583245832558326583275832858329583305833158332583335833458335583365833758338583395834058341583425834358344583455834658347583485834958350583515835258353583545835558356583575835858359583605836158362583635836458365583665836758368583695837058371583725837358374583755837658377583785837958380583815838258383583845838558386583875838858389583905839158392583935839458395583965839758398583995840058401584025840358404584055840658407584085840958410584115841258413584145841558416584175841858419584205842158422584235842458425584265842758428584295843058431584325843358434584355843658437584385843958440584415844258443584445844558446584475844858449584505845158452584535845458455584565845758458584595846058461584625846358464584655846658467584685846958470584715847258473584745847558476584775847858479584805848158482584835848458485584865848758488584895849058491584925849358494584955849658497584985849958500585015850258503585045850558506585075850858509585105851158512585135851458515585165851758518585195852058521585225852358524585255852658527585285852958530585315853258533585345853558536585375853858539585405854158542585435854458545585465854758548585495855058551585525855358554585555855658557585585855958560585615856258563585645856558566585675856858569585705857158572585735857458575585765857758578585795858058581585825858358584585855858658587585885858958590585915859258593585945859558596585975859858599586005860158602586035860458605586065860758608586095861058611586125861358614586155861658617586185861958620586215862258623586245862558626586275862858629586305863158632586335863458635586365863758638586395864058641586425864358644586455864658647586485864958650586515865258653586545865558656586575865858659586605866158662586635866458665586665866758668586695867058671586725867358674586755867658677586785867958680586815868258683586845868558686586875868858689586905869158692586935869458695586965869758698586995870058701587025870358704587055870658707587085870958710587115871258713587145871558716587175871858719587205872158722587235872458725587265872758728587295873058731587325873358734587355873658737587385873958740587415874258743587445874558746587475874858749587505875158752587535875458755587565875758758587595876058761587625876358764587655876658767587685876958770587715877258773587745877558776587775877858779587805878158782587835878458785587865878758788587895879058791587925879358794587955879658797587985879958800588015880258803588045880558806588075880858809588105881158812588135881458815588165881758818588195882058821588225882358824588255882658827588285882958830588315883258833588345883558836588375883858839588405884158842588435884458845588465884758848588495885058851588525885358854588555885658857588585885958860588615886258863588645886558866588675886858869588705887158872588735887458875588765887758878588795888058881588825888358884588855888658887588885888958890588915889258893588945889558896588975889858899589005890158902589035890458905589065890758908589095891058911589125891358914589155891658917589185891958920589215892258923589245892558926589275892858929589305893158932589335893458935589365893758938589395894058941589425894358944589455894658947589485894958950589515895258953589545895558956589575895858959589605896158962589635896458965589665896758968589695897058971589725897358974589755897658977589785897958980589815898258983589845898558986589875898858989589905899158992589935899458995589965899758998589995900059001590025900359004590055900659007590085900959010590115901259013590145901559016590175901859019590205902159022590235902459025590265902759028590295903059031590325903359034590355903659037590385903959040590415904259043590445904559046590475904859049590505905159052590535905459055590565905759058590595906059061590625906359064590655906659067590685906959070590715907259073590745907559076590775907859079590805908159082590835908459085590865908759088590895909059091590925909359094590955909659097590985909959100591015910259103591045910559106591075910859109591105911159112591135911459115591165911759118591195912059121591225912359124591255912659127591285912959130591315913259133591345913559136591375913859139591405914159142591435914459145591465914759148591495915059151591525915359154591555915659157591585915959160591615916259163591645916559166591675916859169591705917159172591735917459175591765917759178591795918059181591825918359184591855918659187591885918959190591915919259193591945919559196591975919859199592005920159202592035920459205592065920759208592095921059211592125921359214592155921659217592185921959220592215922259223592245922559226592275922859229592305923159232592335923459235592365923759238592395924059241592425924359244592455924659247592485924959250592515925259253592545925559256592575925859259592605926159262592635926459265592665926759268592695927059271592725927359274592755927659277592785927959280592815928259283592845928559286592875928859289592905929159292592935929459295592965929759298592995930059301593025930359304593055930659307593085930959310593115931259313593145931559316593175931859319593205932159322593235932459325593265932759328593295933059331593325933359334593355933659337593385933959340593415934259343593445934559346593475934859349593505935159352593535935459355593565935759358593595936059361593625936359364593655936659367593685936959370593715937259373593745937559376593775937859379593805938159382593835938459385593865938759388593895939059391593925939359394593955939659397593985939959400594015940259403594045940559406594075940859409594105941159412594135941459415594165941759418594195942059421594225942359424594255942659427594285942959430594315943259433594345943559436594375943859439594405944159442594435944459445594465944759448594495945059451594525945359454594555945659457594585945959460594615946259463594645946559466594675946859469594705947159472594735947459475594765947759478594795948059481594825948359484594855948659487594885948959490594915949259493594945949559496594975949859499595005950159502595035950459505595065950759508595095951059511595125951359514595155951659517595185951959520595215952259523595245952559526595275952859529595305953159532595335953459535595365953759538595395954059541595425954359544595455954659547595485954959550595515955259553595545955559556595575955859559595605956159562595635956459565595665956759568595695957059571595725957359574595755957659577595785957959580595815958259583595845958559586595875958859589595905959159592595935959459595595965959759598595995960059601596025960359604596055960659607596085960959610596115961259613596145961559616596175961859619596205962159622596235962459625596265962759628596295963059631596325963359634596355963659637596385963959640596415964259643596445964559646596475964859649596505965159652596535965459655596565965759658596595966059661596625966359664596655966659667596685966959670596715967259673596745967559676596775967859679596805968159682596835968459685596865968759688596895969059691596925969359694596955969659697596985969959700597015970259703597045970559706597075970859709597105971159712597135971459715597165971759718597195972059721597225972359724597255972659727597285972959730597315973259733597345973559736597375973859739597405974159742597435974459745597465974759748597495975059751597525975359754597555975659757597585975959760597615976259763597645976559766597675976859769597705977159772597735977459775597765977759778597795978059781597825978359784597855978659787597885978959790597915979259793597945979559796597975979859799598005980159802598035980459805598065980759808598095981059811598125981359814598155981659817598185981959820598215982259823598245982559826598275982859829598305983159832598335983459835598365983759838598395984059841598425984359844598455984659847598485984959850598515985259853598545985559856598575985859859598605986159862598635986459865598665986759868598695987059871598725987359874598755987659877598785987959880598815988259883598845988559886598875988859889598905989159892598935989459895598965989759898598995990059901599025990359904599055990659907599085990959910599115991259913599145991559916599175991859919599205992159922599235992459925599265992759928599295993059931599325993359934599355993659937599385993959940599415994259943599445994559946599475994859949599505995159952599535995459955599565995759958599595996059961599625996359964599655996659967599685996959970599715997259973599745997559976599775997859979599805998159982599835998459985599865998759988599895999059991599925999359994599955999659997599985999960000600016000260003600046000560006600076000860009600106001160012600136001460015600166001760018600196002060021600226002360024600256002660027600286002960030600316003260033600346003560036600376003860039600406004160042600436004460045600466004760048600496005060051600526005360054600556005660057600586005960060600616006260063600646006560066600676006860069600706007160072600736007460075600766007760078600796008060081600826008360084600856008660087600886008960090600916009260093600946009560096600976009860099601006010160102601036010460105601066010760108601096011060111601126011360114601156011660117601186011960120601216012260123601246012560126601276012860129601306013160132601336013460135601366013760138601396014060141601426014360144601456014660147601486014960150601516015260153601546015560156601576015860159601606016160162601636016460165601666016760168601696017060171601726017360174601756017660177601786017960180601816018260183601846018560186601876018860189601906019160192601936019460195601966019760198601996020060201602026020360204602056020660207602086020960210602116021260213602146021560216602176021860219602206022160222602236022460225602266022760228602296023060231602326023360234602356023660237602386023960240602416024260243602446024560246602476024860249602506025160252602536025460255602566025760258602596026060261602626026360264602656026660267602686026960270602716027260273602746027560276602776027860279602806028160282602836028460285602866028760288602896029060291602926029360294602956029660297602986029960300603016030260303603046030560306603076030860309603106031160312603136031460315603166031760318603196032060321603226032360324603256032660327603286032960330603316033260333603346033560336603376033860339603406034160342603436034460345603466034760348603496035060351603526035360354603556035660357603586035960360603616036260363603646036560366603676036860369603706037160372603736037460375603766037760378603796038060381603826038360384603856038660387603886038960390603916039260393603946039560396603976039860399604006040160402604036040460405604066040760408604096041060411604126041360414604156041660417604186041960420604216042260423604246042560426604276042860429604306043160432604336043460435604366043760438604396044060441604426044360444604456044660447604486044960450604516045260453604546045560456604576045860459604606046160462604636046460465604666046760468604696047060471604726047360474604756047660477604786047960480604816048260483604846048560486604876048860489604906049160492604936049460495604966049760498604996050060501605026050360504605056050660507605086050960510605116051260513605146051560516605176051860519605206052160522605236052460525605266052760528605296053060531605326053360534605356053660537605386053960540605416054260543605446054560546605476054860549605506055160552605536055460555605566055760558605596056060561605626056360564605656056660567605686056960570605716057260573605746057560576605776057860579605806058160582605836058460585605866058760588605896059060591605926059360594605956059660597605986059960600606016060260603606046060560606606076060860609606106061160612606136061460615606166061760618606196062060621606226062360624606256062660627606286062960630606316063260633606346063560636606376063860639606406064160642606436064460645606466064760648606496065060651606526065360654606556065660657606586065960660606616066260663606646066560666606676066860669606706067160672606736067460675606766067760678606796068060681606826068360684606856068660687606886068960690606916069260693606946069560696606976069860699607006070160702607036070460705607066070760708607096071060711607126071360714607156071660717607186071960720607216072260723607246072560726607276072860729607306073160732607336073460735607366073760738607396074060741607426074360744607456074660747607486074960750607516075260753607546075560756607576075860759607606076160762607636076460765607666076760768607696077060771607726077360774607756077660777607786077960780607816078260783607846078560786607876078860789607906079160792607936079460795607966079760798607996080060801608026080360804608056080660807608086080960810608116081260813608146081560816608176081860819608206082160822608236082460825608266082760828608296083060831608326083360834608356083660837608386083960840608416084260843608446084560846608476084860849608506085160852608536085460855608566085760858608596086060861608626086360864608656086660867608686086960870608716087260873608746087560876608776087860879608806088160882608836088460885608866088760888608896089060891608926089360894608956089660897608986089960900609016090260903609046090560906609076090860909609106091160912609136091460915609166091760918609196092060921609226092360924609256092660927609286092960930609316093260933609346093560936609376093860939609406094160942609436094460945609466094760948609496095060951609526095360954609556095660957609586095960960609616096260963609646096560966609676096860969609706097160972609736097460975609766097760978609796098060981609826098360984609856098660987609886098960990609916099260993609946099560996609976099860999610006100161002610036100461005610066100761008610096101061011610126101361014610156101661017610186101961020610216102261023610246102561026610276102861029610306103161032610336103461035610366103761038610396104061041610426104361044610456104661047610486104961050610516105261053610546105561056610576105861059610606106161062610636106461065610666106761068610696107061071610726107361074610756107661077610786107961080610816108261083610846108561086610876108861089610906109161092610936109461095610966109761098610996110061101611026110361104611056110661107611086110961110611116111261113611146111561116611176111861119611206112161122611236112461125611266112761128611296113061131611326113361134611356113661137611386113961140611416114261143611446114561146611476114861149611506115161152611536115461155611566115761158611596116061161611626116361164611656116661167611686116961170611716117261173611746117561176611776117861179611806118161182611836118461185611866118761188611896119061191611926119361194611956119661197611986119961200612016120261203612046120561206612076120861209612106121161212612136121461215612166121761218612196122061221612226122361224612256122661227612286122961230612316123261233612346123561236612376123861239612406124161242612436124461245612466124761248612496125061251612526125361254612556125661257612586125961260612616126261263612646126561266612676126861269612706127161272612736127461275612766127761278612796128061281612826128361284612856128661287612886128961290612916129261293612946129561296612976129861299613006130161302613036130461305613066130761308613096131061311613126131361314613156131661317613186131961320613216132261323613246132561326613276132861329613306133161332613336133461335613366133761338613396134061341613426134361344613456134661347613486134961350613516135261353613546135561356613576135861359613606136161362613636136461365613666136761368613696137061371613726137361374613756137661377613786137961380613816138261383613846138561386613876138861389613906139161392613936139461395613966139761398613996140061401614026140361404614056140661407614086140961410614116141261413614146141561416614176141861419614206142161422614236142461425614266142761428614296143061431614326143361434614356143661437614386143961440614416144261443614446144561446614476144861449614506145161452614536145461455614566145761458614596146061461614626146361464614656146661467614686146961470614716147261473614746147561476614776147861479614806148161482614836148461485614866148761488614896149061491614926149361494614956149661497614986149961500615016150261503615046150561506615076150861509615106151161512615136151461515615166151761518615196152061521615226152361524615256152661527615286152961530615316153261533615346153561536615376153861539615406154161542615436154461545615466154761548615496155061551615526155361554615556155661557615586155961560615616156261563615646156561566615676156861569615706157161572615736157461575615766157761578615796158061581615826158361584615856158661587615886158961590615916159261593615946159561596615976159861599616006160161602616036160461605616066160761608616096161061611616126161361614616156161661617616186161961620616216162261623616246162561626616276162861629616306163161632616336163461635616366163761638616396164061641616426164361644616456164661647616486164961650616516165261653616546165561656616576165861659616606166161662616636166461665616666166761668616696167061671616726167361674616756167661677616786167961680616816168261683616846168561686616876168861689616906169161692616936169461695616966169761698616996170061701617026170361704617056170661707617086170961710617116171261713617146171561716617176171861719617206172161722617236172461725617266172761728617296173061731617326173361734617356173661737617386173961740617416174261743617446174561746617476174861749617506175161752617536175461755617566175761758617596176061761617626176361764617656176661767617686176961770617716177261773617746177561776617776177861779617806178161782617836178461785617866178761788617896179061791617926179361794617956179661797617986179961800618016180261803618046180561806618076180861809618106181161812618136181461815618166181761818618196182061821618226182361824618256182661827618286182961830618316183261833618346183561836618376183861839618406184161842618436184461845618466184761848618496185061851618526185361854618556185661857618586185961860618616186261863618646186561866618676186861869618706187161872618736187461875618766187761878618796188061881618826188361884618856188661887618886188961890618916189261893618946189561896618976189861899619006190161902619036190461905619066190761908619096191061911619126191361914619156191661917619186191961920619216192261923619246192561926619276192861929619306193161932619336193461935619366193761938619396194061941619426194361944619456194661947619486194961950619516195261953619546195561956619576195861959619606196161962619636196461965619666196761968619696197061971619726197361974619756197661977619786197961980619816198261983619846198561986619876198861989619906199161992619936199461995619966199761998619996200062001620026200362004620056200662007620086200962010620116201262013620146201562016620176201862019620206202162022620236202462025620266202762028620296203062031620326203362034620356203662037620386203962040620416204262043620446204562046620476204862049620506205162052620536205462055620566205762058620596206062061620626206362064620656206662067620686206962070620716207262073620746207562076620776207862079620806208162082620836208462085620866208762088620896209062091620926209362094620956209662097620986209962100621016210262103621046210562106621076210862109621106211162112621136211462115621166211762118621196212062121621226212362124621256212662127621286212962130621316213262133621346213562136621376213862139621406214162142621436214462145621466214762148621496215062151621526215362154621556215662157621586215962160621616216262163621646216562166621676216862169621706217162172621736217462175621766217762178621796218062181621826218362184621856218662187621886218962190621916219262193621946219562196621976219862199622006220162202622036220462205622066220762208622096221062211622126221362214622156221662217622186221962220622216222262223622246222562226622276222862229622306223162232622336223462235622366223762238622396224062241622426224362244622456224662247622486224962250622516225262253622546225562256622576225862259622606226162262622636226462265622666226762268622696227062271622726227362274622756227662277622786227962280622816228262283622846228562286622876228862289622906229162292622936229462295622966229762298622996230062301623026230362304623056230662307623086230962310623116231262313623146231562316623176231862319623206232162322623236232462325623266232762328623296233062331623326233362334623356233662337623386233962340623416234262343623446234562346623476234862349623506235162352623536235462355623566235762358623596236062361623626236362364623656236662367623686236962370623716237262373623746237562376623776237862379623806238162382623836238462385623866238762388623896239062391623926239362394623956239662397623986239962400624016240262403624046240562406624076240862409624106241162412624136241462415624166241762418624196242062421624226242362424624256242662427624286242962430624316243262433624346243562436624376243862439624406244162442624436244462445624466244762448624496245062451624526245362454624556245662457624586245962460624616246262463624646246562466624676246862469624706247162472624736247462475624766247762478624796248062481624826248362484624856248662487624886248962490624916249262493624946249562496624976249862499625006250162502625036250462505625066250762508625096251062511625126251362514625156251662517625186251962520625216252262523625246252562526625276252862529625306253162532625336253462535625366253762538625396254062541625426254362544625456254662547625486254962550625516255262553625546255562556625576255862559625606256162562625636256462565625666256762568625696257062571625726257362574625756257662577625786257962580625816258262583625846258562586625876258862589625906259162592625936259462595625966259762598625996260062601626026260362604626056260662607626086260962610626116261262613626146261562616626176261862619626206262162622626236262462625626266262762628626296263062631626326263362634626356263662637626386263962640626416264262643626446264562646626476264862649626506265162652626536265462655626566265762658626596266062661626626266362664626656266662667626686266962670626716267262673626746267562676626776267862679626806268162682626836268462685626866268762688626896269062691626926269362694626956269662697626986269962700627016270262703627046270562706627076270862709627106271162712627136271462715627166271762718627196272062721627226272362724627256272662727627286272962730627316273262733627346273562736627376273862739627406274162742627436274462745627466274762748627496275062751627526275362754627556275662757627586275962760627616276262763627646276562766627676276862769627706277162772627736277462775627766277762778627796278062781627826278362784627856278662787627886278962790627916279262793627946279562796627976279862799628006280162802628036280462805628066280762808628096281062811628126281362814628156281662817628186281962820628216282262823628246282562826628276282862829628306283162832628336283462835628366283762838628396284062841628426284362844628456284662847628486284962850628516285262853628546285562856628576285862859628606286162862628636286462865628666286762868628696287062871628726287362874628756287662877628786287962880628816288262883628846288562886628876288862889628906289162892628936289462895628966289762898628996290062901629026290362904629056290662907629086290962910629116291262913629146291562916629176291862919629206292162922629236292462925629266292762928629296293062931629326293362934629356293662937629386293962940629416294262943629446294562946629476294862949629506295162952629536295462955629566295762958629596296062961629626296362964629656296662967629686296962970629716297262973629746297562976629776297862979629806298162982629836298462985629866298762988629896299062991629926299362994629956299662997629986299963000630016300263003630046300563006630076300863009630106301163012630136301463015630166301763018630196302063021630226302363024630256302663027630286302963030630316303263033630346303563036630376303863039630406304163042630436304463045630466304763048630496305063051630526305363054630556305663057630586305963060630616306263063630646306563066630676306863069630706307163072630736307463075630766307763078630796308063081630826308363084630856308663087630886308963090630916309263093630946309563096630976309863099631006310163102631036310463105631066310763108631096311063111631126311363114631156311663117631186311963120631216312263123631246312563126631276312863129631306313163132631336313463135631366313763138631396314063141631426314363144631456314663147631486314963150631516315263153631546315563156631576315863159631606316163162631636316463165631666316763168631696317063171631726317363174631756317663177631786317963180631816318263183631846318563186631876318863189631906319163192631936319463195631966319763198631996320063201632026320363204632056320663207632086320963210632116321263213632146321563216632176321863219632206322163222632236322463225632266322763228632296323063231632326323363234632356323663237632386323963240632416324263243632446324563246632476324863249632506325163252632536325463255632566325763258632596326063261632626326363264632656326663267632686326963270632716327263273632746327563276632776327863279632806328163282632836328463285632866328763288632896329063291632926329363294632956329663297632986329963300633016330263303633046330563306633076330863309633106331163312633136331463315633166331763318633196332063321633226332363324633256332663327633286332963330633316333263333633346333563336633376333863339633406334163342633436334463345633466334763348633496335063351633526335363354633556335663357633586335963360633616336263363633646336563366633676336863369633706337163372633736337463375633766337763378633796338063381633826338363384633856338663387633886338963390633916339263393633946339563396633976339863399634006340163402634036340463405634066340763408634096341063411634126341363414634156341663417634186341963420634216342263423634246342563426634276342863429634306343163432634336343463435634366343763438634396344063441634426344363444634456344663447634486344963450634516345263453634546345563456634576345863459634606346163462634636346463465634666346763468634696347063471634726347363474634756347663477634786347963480634816348263483634846348563486634876348863489634906349163492634936349463495634966349763498634996350063501635026350363504635056350663507635086350963510635116351263513635146351563516635176351863519635206352163522635236352463525635266352763528635296353063531635326353363534635356353663537635386353963540635416354263543635446354563546635476354863549635506355163552635536355463555635566355763558635596356063561635626356363564635656356663567635686356963570635716357263573635746357563576635776357863579635806358163582635836358463585635866358763588635896359063591635926359363594635956359663597635986359963600636016360263603636046360563606636076360863609636106361163612636136361463615636166361763618636196362063621636226362363624636256362663627636286362963630636316363263633636346363563636636376363863639636406364163642636436364463645636466364763648636496365063651636526365363654636556365663657636586365963660636616366263663636646366563666636676366863669636706367163672636736367463675636766367763678636796368063681636826368363684636856368663687636886368963690636916369263693636946369563696636976369863699637006370163702637036370463705637066370763708637096371063711637126371363714637156371663717637186371963720637216372263723637246372563726637276372863729637306373163732637336373463735637366373763738637396374063741637426374363744637456374663747637486374963750637516375263753637546375563756637576375863759637606376163762637636376463765637666376763768637696377063771637726377363774637756377663777637786377963780637816378263783637846378563786637876378863789637906379163792637936379463795637966379763798637996380063801638026380363804638056380663807638086380963810638116381263813638146381563816638176381863819638206382163822638236382463825638266382763828638296383063831638326383363834638356383663837638386383963840638416384263843638446384563846638476384863849638506385163852638536385463855638566385763858638596386063861638626386363864638656386663867638686386963870638716387263873638746387563876638776387863879638806388163882638836388463885638866388763888638896389063891638926389363894638956389663897638986389963900639016390263903639046390563906639076390863909639106391163912639136391463915639166391763918639196392063921639226392363924639256392663927639286392963930639316393263933639346393563936639376393863939639406394163942639436394463945639466394763948639496395063951639526395363954639556395663957639586395963960639616396263963639646396563966639676396863969639706397163972639736397463975639766397763978639796398063981639826398363984639856398663987639886398963990639916399263993639946399563996639976399863999640006400164002640036400464005640066400764008640096401064011640126401364014640156401664017640186401964020640216402264023640246402564026640276402864029640306403164032640336403464035640366403764038640396404064041640426404364044640456404664047640486404964050640516405264053640546405564056640576405864059640606406164062640636406464065640666406764068640696407064071640726407364074640756407664077640786407964080640816408264083640846408564086640876408864089640906409164092640936409464095640966409764098640996410064101641026410364104641056410664107641086410964110641116411264113641146411564116641176411864119641206412164122641236412464125641266412764128641296413064131641326413364134641356413664137641386413964140641416414264143641446414564146641476414864149641506415164152641536415464155641566415764158641596416064161641626416364164641656416664167641686416964170641716417264173641746417564176641776417864179641806418164182641836418464185641866418764188641896419064191641926419364194641956419664197641986419964200642016420264203642046420564206642076420864209642106421164212642136421464215642166421764218642196422064221642226422364224642256422664227642286422964230642316423264233642346423564236642376423864239642406424164242642436424464245642466424764248642496425064251642526425364254642556425664257642586425964260642616426264263642646426564266642676426864269642706427164272642736427464275642766427764278642796428064281642826428364284642856428664287642886428964290642916429264293642946429564296642976429864299643006430164302643036430464305643066430764308643096431064311643126431364314643156431664317643186431964320643216432264323643246432564326643276432864329643306433164332643336433464335643366433764338643396434064341643426434364344643456434664347643486434964350643516435264353643546435564356643576435864359643606436164362643636436464365643666436764368643696437064371643726437364374643756437664377643786437964380643816438264383643846438564386643876438864389643906439164392643936439464395643966439764398643996440064401644026440364404644056440664407644086440964410644116441264413644146441564416644176441864419644206442164422644236442464425644266442764428644296443064431644326443364434644356443664437644386443964440644416444264443644446444564446644476444864449644506445164452644536445464455644566445764458644596446064461644626446364464644656446664467644686446964470644716447264473644746447564476644776447864479644806448164482644836448464485644866448764488644896449064491644926449364494644956449664497644986449964500645016450264503645046450564506645076450864509645106451164512645136451464515645166451764518645196452064521645226452364524645256452664527645286452964530645316453264533645346453564536645376453864539645406454164542645436454464545645466454764548645496455064551645526455364554645556455664557645586455964560645616456264563645646456564566645676456864569645706457164572645736457464575645766457764578645796458064581645826458364584645856458664587645886458964590645916459264593645946459564596645976459864599646006460164602646036460464605646066460764608646096461064611646126461364614646156461664617646186461964620646216462264623646246462564626646276462864629646306463164632646336463464635646366463764638646396464064641646426464364644646456464664647646486464964650646516465264653646546465564656646576465864659646606466164662646636466464665646666466764668646696467064671646726467364674646756467664677646786467964680646816468264683646846468564686646876468864689646906469164692646936469464695646966469764698646996470064701647026470364704647056470664707647086470964710647116471264713647146471564716647176471864719647206472164722647236472464725647266472764728647296473064731647326473364734647356473664737647386473964740647416474264743647446474564746647476474864749647506475164752647536475464755647566475764758647596476064761647626476364764647656476664767647686476964770647716477264773647746477564776647776477864779647806478164782647836478464785647866478764788647896479064791647926479364794647956479664797647986479964800648016480264803648046480564806648076480864809648106481164812648136481464815648166481764818648196482064821648226482364824648256482664827648286482964830648316483264833648346483564836648376483864839648406484164842648436484464845648466484764848648496485064851648526485364854648556485664857648586485964860648616486264863648646486564866648676486864869648706487164872648736487464875648766487764878648796488064881648826488364884648856488664887648886488964890648916489264893648946489564896648976489864899649006490164902649036490464905649066490764908649096491064911649126491364914649156491664917649186491964920649216492264923649246492564926649276492864929649306493164932649336493464935649366493764938649396494064941649426494364944649456494664947649486494964950649516495264953649546495564956649576495864959649606496164962649636496464965649666496764968649696497064971649726497364974649756497664977649786497964980649816498264983649846498564986649876498864989649906499164992649936499464995649966499764998649996500065001650026500365004650056500665007650086500965010650116501265013650146501565016650176501865019650206502165022650236502465025650266502765028650296503065031650326503365034650356503665037650386503965040650416504265043650446504565046650476504865049650506505165052650536505465055650566505765058650596506065061650626506365064650656506665067650686506965070650716507265073650746507565076650776507865079650806508165082650836508465085650866508765088650896509065091650926509365094650956509665097650986509965100651016510265103651046510565106651076510865109651106511165112651136511465115651166511765118651196512065121651226512365124651256512665127651286512965130651316513265133651346513565136651376513865139651406514165142651436514465145651466514765148651496515065151651526515365154651556515665157651586515965160651616516265163651646516565166651676516865169651706517165172651736517465175651766517765178651796518065181651826518365184651856518665187651886518965190651916519265193651946519565196651976519865199652006520165202652036520465205652066520765208652096521065211652126521365214652156521665217652186521965220652216522265223652246522565226652276522865229652306523165232652336523465235652366523765238652396524065241652426524365244652456524665247652486524965250652516525265253652546525565256652576525865259652606526165262652636526465265652666526765268652696527065271652726527365274652756527665277652786527965280652816528265283652846528565286652876528865289652906529165292652936529465295652966529765298652996530065301653026530365304653056530665307653086530965310653116531265313653146531565316653176531865319653206532165322653236532465325653266532765328653296533065331653326533365334653356533665337653386533965340653416534265343653446534565346653476534865349653506535165352653536535465355653566535765358653596536065361653626536365364653656536665367653686536965370653716537265373653746537565376653776537865379653806538165382653836538465385653866538765388653896539065391653926539365394653956539665397653986539965400654016540265403654046540565406654076540865409654106541165412654136541465415654166541765418654196542065421654226542365424654256542665427654286542965430654316543265433654346543565436654376543865439654406544165442654436544465445654466544765448654496545065451654526545365454654556545665457654586545965460654616546265463654646546565466654676546865469654706547165472654736547465475654766547765478654796548065481654826548365484654856548665487654886548965490654916549265493654946549565496654976549865499655006550165502655036550465505655066550765508655096551065511655126551365514655156551665517655186551965520655216552265523655246552565526655276552865529655306553165532655336553465535655366553765538655396554065541655426554365544655456554665547655486554965550655516555265553655546555565556655576555865559655606556165562655636556465565655666556765568655696557065571655726557365574655756557665577655786557965580655816558265583655846558565586655876558865589655906559165592655936559465595655966559765598655996560065601656026560365604656056560665607656086560965610656116561265613656146561565616656176561865619656206562165622656236562465625656266562765628656296563065631656326563365634656356563665637656386563965640656416564265643656446564565646656476564865649656506565165652656536565465655656566565765658656596566065661656626566365664656656566665667656686566965670656716567265673656746567565676656776567865679656806568165682656836568465685656866568765688656896569065691656926569365694656956569665697656986569965700657016570265703657046570565706657076570865709657106571165712657136571465715657166571765718657196572065721657226572365724657256572665727657286572965730657316573265733657346573565736657376573865739657406574165742657436574465745657466574765748657496575065751657526575365754657556575665757657586575965760657616576265763657646576565766657676576865769657706577165772657736577465775657766577765778657796578065781657826578365784657856578665787657886578965790657916579265793657946579565796657976579865799658006580165802658036580465805658066580765808658096581065811658126581365814658156581665817658186581965820658216582265823658246582565826658276582865829658306583165832658336583465835658366583765838658396584065841658426584365844658456584665847658486584965850658516585265853658546585565856658576585865859658606586165862658636586465865658666586765868658696587065871658726587365874658756587665877658786587965880658816588265883658846588565886658876588865889658906589165892658936589465895658966589765898658996590065901659026590365904659056590665907659086590965910659116591265913659146591565916659176591865919659206592165922659236592465925659266592765928659296593065931659326593365934659356593665937659386593965940659416594265943659446594565946659476594865949659506595165952659536595465955659566595765958659596596065961659626596365964659656596665967659686596965970659716597265973659746597565976659776597865979659806598165982659836598465985659866598765988659896599065991659926599365994659956599665997659986599966000660016600266003660046600566006660076600866009660106601166012660136601466015660166601766018660196602066021660226602366024660256602666027660286602966030660316603266033660346603566036660376603866039660406604166042660436604466045660466604766048660496605066051660526605366054660556605666057660586605966060660616606266063660646606566066660676606866069660706607166072660736607466075660766607766078660796608066081660826608366084660856608666087660886608966090660916609266093660946609566096660976609866099661006610166102661036610466105661066610766108661096611066111661126611366114661156611666117661186611966120661216612266123661246612566126661276612866129661306613166132661336613466135661366613766138661396614066141661426614366144661456614666147661486614966150661516615266153661546615566156661576615866159661606616166162661636616466165661666616766168661696617066171661726617366174661756617666177661786617966180661816618266183661846618566186661876618866189661906619166192661936619466195661966619766198661996620066201662026620366204662056620666207662086620966210662116621266213662146621566216662176621866219662206622166222662236622466225662266622766228662296623066231662326623366234662356623666237662386623966240662416624266243662446624566246662476624866249662506625166252662536625466255662566625766258662596626066261662626626366264662656626666267662686626966270662716627266273662746627566276662776627866279662806628166282662836628466285662866628766288662896629066291662926629366294662956629666297662986629966300663016630266303663046630566306663076630866309663106631166312663136631466315663166631766318663196632066321663226632366324663256632666327663286632966330663316633266333663346633566336663376633866339663406634166342663436634466345663466634766348663496635066351663526635366354663556635666357663586635966360663616636266363663646636566366663676636866369663706637166372663736637466375663766637766378663796638066381663826638366384663856638666387663886638966390663916639266393663946639566396663976639866399664006640166402664036640466405664066640766408664096641066411664126641366414664156641666417664186641966420664216642266423664246642566426664276642866429664306643166432664336643466435664366643766438664396644066441664426644366444664456644666447664486644966450664516645266453664546645566456664576645866459664606646166462664636646466465664666646766468664696647066471664726647366474664756647666477664786647966480664816648266483664846648566486664876648866489664906649166492664936649466495664966649766498664996650066501665026650366504665056650666507665086650966510665116651266513665146651566516665176651866519665206652166522665236652466525665266652766528665296653066531665326653366534665356653666537665386653966540665416654266543665446654566546665476654866549665506655166552665536655466555665566655766558665596656066561665626656366564665656656666567665686656966570665716657266573665746657566576665776657866579665806658166582665836658466585665866658766588665896659066591665926659366594665956659666597665986659966600666016660266603666046660566606666076660866609666106661166612666136661466615666166661766618666196662066621666226662366624666256662666627666286662966630666316663266633666346663566636666376663866639666406664166642666436664466645666466664766648666496665066651666526665366654666556665666657666586665966660666616666266663666646666566666666676666866669666706667166672666736667466675666766667766678666796668066681666826668366684666856668666687666886668966690666916669266693666946669566696666976669866699667006670166702667036670466705667066670766708667096671066711667126671366714667156671666717667186671966720667216672266723667246672566726667276672866729667306673166732667336673466735667366673766738667396674066741667426674366744667456674666747667486674966750667516675266753667546675566756667576675866759667606676166762667636676466765667666676766768667696677066771667726677366774667756677666777667786677966780667816678266783667846678566786667876678866789667906679166792667936679466795667966679766798667996680066801668026680366804668056680666807668086680966810668116681266813668146681566816668176681866819668206682166822668236682466825668266682766828668296683066831668326683366834668356683666837668386683966840668416684266843668446684566846668476684866849668506685166852668536685466855668566685766858668596686066861668626686366864668656686666867668686686966870668716687266873668746687566876668776687866879668806688166882668836688466885668866688766888668896689066891668926689366894668956689666897668986689966900669016690266903669046690566906669076690866909669106691166912669136691466915669166691766918669196692066921669226692366924669256692666927669286692966930669316693266933669346693566936669376693866939669406694166942669436694466945669466694766948669496695066951669526695366954669556695666957669586695966960669616696266963669646696566966669676696866969669706697166972669736697466975669766697766978669796698066981669826698366984669856698666987669886698966990669916699266993669946699566996669976699866999670006700167002670036700467005670066700767008670096701067011670126701367014670156701667017670186701967020670216702267023670246702567026670276702867029670306703167032670336703467035670366703767038670396704067041670426704367044670456704667047670486704967050670516705267053670546705567056670576705867059670606706167062670636706467065670666706767068670696707067071670726707367074670756707667077670786707967080670816708267083670846708567086670876708867089670906709167092670936709467095670966709767098670996710067101671026710367104671056710667107671086710967110671116711267113671146711567116671176711867119671206712167122671236712467125671266712767128671296713067131671326713367134671356713667137671386713967140671416714267143671446714567146671476714867149671506715167152671536715467155671566715767158671596716067161671626716367164671656716667167671686716967170671716717267173671746717567176671776717867179671806718167182671836718467185671866718767188671896719067191671926719367194671956719667197671986719967200672016720267203672046720567206672076720867209672106721167212672136721467215672166721767218672196722067221672226722367224672256722667227672286722967230672316723267233672346723567236672376723867239672406724167242672436724467245672466724767248672496725067251672526725367254672556725667257672586725967260672616726267263672646726567266672676726867269672706727167272672736727467275672766727767278672796728067281672826728367284672856728667287672886728967290672916729267293672946729567296672976729867299673006730167302673036730467305673066730767308673096731067311673126731367314673156731667317673186731967320673216732267323673246732567326673276732867329673306733167332673336733467335673366733767338673396734067341673426734367344673456734667347673486734967350673516735267353673546735567356673576735867359673606736167362673636736467365673666736767368673696737067371673726737367374673756737667377673786737967380673816738267383673846738567386673876738867389673906739167392673936739467395673966739767398673996740067401674026740367404674056740667407674086740967410674116741267413674146741567416674176741867419674206742167422674236742467425674266742767428674296743067431674326743367434674356743667437674386743967440674416744267443674446744567446674476744867449674506745167452674536745467455674566745767458674596746067461674626746367464674656746667467674686746967470674716747267473674746747567476674776747867479674806748167482674836748467485674866748767488674896749067491674926749367494674956749667497674986749967500675016750267503675046750567506675076750867509675106751167512675136751467515675166751767518675196752067521675226752367524675256752667527675286752967530675316753267533675346753567536675376753867539675406754167542675436754467545675466754767548675496755067551675526755367554675556755667557675586755967560675616756267563675646756567566675676756867569675706757167572675736757467575675766757767578675796758067581675826758367584675856758667587675886758967590675916759267593675946759567596675976759867599676006760167602676036760467605676066760767608676096761067611676126761367614676156761667617676186761967620676216762267623676246762567626676276762867629676306763167632676336763467635676366763767638676396764067641676426764367644676456764667647676486764967650676516765267653676546765567656676576765867659676606766167662676636766467665676666766767668676696767067671676726767367674676756767667677676786767967680676816768267683676846768567686676876768867689676906769167692676936769467695676966769767698676996770067701677026770367704677056770667707677086770967710677116771267713677146771567716677176771867719677206772167722677236772467725677266772767728677296773067731677326773367734677356773667737677386773967740677416774267743677446774567746677476774867749677506775167752677536775467755677566775767758677596776067761677626776367764677656776667767677686776967770677716777267773677746777567776677776777867779677806778167782677836778467785677866778767788677896779067791677926779367794677956779667797677986779967800678016780267803678046780567806678076780867809678106781167812678136781467815678166781767818678196782067821678226782367824678256782667827678286782967830678316783267833678346783567836678376783867839678406784167842678436784467845678466784767848678496785067851678526785367854678556785667857678586785967860678616786267863678646786567866678676786867869678706787167872678736787467875678766787767878678796788067881678826788367884678856788667887678886788967890678916789267893678946789567896678976789867899679006790167902679036790467905679066790767908679096791067911679126791367914679156791667917679186791967920679216792267923679246792567926679276792867929679306793167932679336793467935679366793767938679396794067941679426794367944679456794667947679486794967950679516795267953679546795567956679576795867959679606796167962679636796467965679666796767968679696797067971679726797367974679756797667977679786797967980679816798267983679846798567986679876798867989679906799167992679936799467995679966799767998679996800068001680026800368004680056800668007680086800968010680116801268013680146801568016680176801868019680206802168022680236802468025680266802768028680296803068031680326803368034680356803668037680386803968040680416804268043680446804568046680476804868049680506805168052680536805468055680566805768058680596806068061680626806368064680656806668067680686806968070680716807268073680746807568076680776807868079680806808168082680836808468085680866808768088680896809068091680926809368094680956809668097680986809968100681016810268103681046810568106681076810868109681106811168112681136811468115681166811768118681196812068121681226812368124681256812668127681286812968130681316813268133681346813568136681376813868139681406814168142681436814468145681466814768148681496815068151681526815368154681556815668157681586815968160681616816268163681646816568166681676816868169681706817168172681736817468175681766817768178681796818068181681826818368184681856818668187681886818968190681916819268193681946819568196681976819868199682006820168202682036820468205682066820768208682096821068211682126821368214682156821668217682186821968220682216822268223682246822568226682276822868229682306823168232682336823468235682366823768238682396824068241682426824368244682456824668247682486824968250682516825268253682546825568256682576825868259682606826168262682636826468265682666826768268682696827068271682726827368274682756827668277682786827968280682816828268283682846828568286682876828868289682906829168292682936829468295682966829768298682996830068301683026830368304683056830668307683086830968310683116831268313683146831568316683176831868319683206832168322683236832468325683266832768328683296833068331683326833368334683356833668337683386833968340683416834268343683446834568346683476834868349683506835168352683536835468355683566835768358683596836068361683626836368364683656836668367683686836968370683716837268373683746837568376683776837868379683806838168382683836838468385683866838768388683896839068391683926839368394683956839668397683986839968400684016840268403684046840568406684076840868409684106841168412684136841468415684166841768418684196842068421684226842368424684256842668427684286842968430684316843268433684346843568436684376843868439684406844168442684436844468445684466844768448684496845068451684526845368454684556845668457684586845968460684616846268463684646846568466684676846868469684706847168472684736847468475684766847768478684796848068481684826848368484684856848668487684886848968490684916849268493684946849568496684976849868499685006850168502685036850468505685066850768508685096851068511685126851368514685156851668517685186851968520685216852268523685246852568526685276852868529685306853168532685336853468535685366853768538685396854068541685426854368544685456854668547685486854968550685516855268553685546855568556685576855868559685606856168562685636856468565685666856768568685696857068571685726857368574685756857668577685786857968580685816858268583685846858568586685876858868589685906859168592685936859468595685966859768598685996860068601686026860368604686056860668607686086860968610686116861268613686146861568616686176861868619686206862168622686236862468625686266862768628686296863068631686326863368634686356863668637686386863968640686416864268643686446864568646686476864868649686506865168652686536865468655686566865768658686596866068661686626866368664686656866668667686686866968670686716867268673686746867568676686776867868679686806868168682686836868468685686866868768688686896869068691686926869368694686956869668697686986869968700687016870268703687046870568706687076870868709687106871168712687136871468715687166871768718687196872068721687226872368724687256872668727687286872968730687316873268733687346873568736687376873868739687406874168742687436874468745687466874768748687496875068751687526875368754687556875668757687586875968760687616876268763687646876568766687676876868769687706877168772687736877468775687766877768778687796878068781687826878368784687856878668787687886878968790687916879268793687946879568796687976879868799688006880168802688036880468805688066880768808688096881068811688126881368814688156881668817688186881968820688216882268823688246882568826688276882868829688306883168832688336883468835688366883768838688396884068841688426884368844688456884668847688486884968850688516885268853688546885568856688576885868859688606886168862688636886468865688666886768868688696887068871688726887368874688756887668877688786887968880688816888268883688846888568886688876888868889688906889168892688936889468895688966889768898688996890068901689026890368904689056890668907689086890968910689116891268913689146891568916689176891868919689206892168922689236892468925689266892768928689296893068931689326893368934689356893668937689386893968940689416894268943689446894568946689476894868949689506895168952689536895468955689566895768958689596896068961689626896368964689656896668967689686896968970689716897268973689746897568976689776897868979689806898168982689836898468985689866898768988689896899068991689926899368994689956899668997689986899969000690016900269003690046900569006690076900869009690106901169012690136901469015690166901769018690196902069021690226902369024690256902669027690286902969030690316903269033690346903569036690376903869039690406904169042690436904469045690466904769048690496905069051690526905369054690556905669057690586905969060690616906269063690646906569066690676906869069690706907169072690736907469075690766907769078690796908069081690826908369084690856908669087690886908969090690916909269093690946909569096690976909869099691006910169102691036910469105691066910769108691096911069111691126911369114691156911669117691186911969120691216912269123691246912569126691276912869129691306913169132691336913469135691366913769138691396914069141691426914369144691456914669147691486914969150691516915269153691546915569156691576915869159691606916169162691636916469165691666916769168691696917069171691726917369174691756917669177691786917969180691816918269183691846918569186691876918869189691906919169192691936919469195691966919769198691996920069201692026920369204692056920669207692086920969210692116921269213692146921569216692176921869219692206922169222692236922469225692266922769228692296923069231692326923369234692356923669237692386923969240692416924269243692446924569246692476924869249692506925169252692536925469255692566925769258692596926069261692626926369264692656926669267692686926969270692716927269273692746927569276692776927869279692806928169282692836928469285692866928769288692896929069291692926929369294692956929669297692986929969300693016930269303693046930569306693076930869309693106931169312693136931469315693166931769318693196932069321693226932369324693256932669327693286932969330693316933269333693346933569336693376933869339693406934169342693436934469345693466934769348693496935069351693526935369354693556935669357693586935969360693616936269363693646936569366693676936869369693706937169372693736937469375693766937769378693796938069381693826938369384693856938669387693886938969390693916939269393693946939569396693976939869399694006940169402694036940469405694066940769408694096941069411694126941369414694156941669417694186941969420694216942269423694246942569426694276942869429694306943169432694336943469435694366943769438694396944069441694426944369444694456944669447694486944969450694516945269453694546945569456694576945869459694606946169462694636946469465694666946769468694696947069471694726947369474694756947669477694786947969480694816948269483694846948569486694876948869489694906949169492694936949469495694966949769498694996950069501695026950369504695056950669507695086950969510695116951269513695146951569516695176951869519695206952169522695236952469525695266952769528695296953069531695326953369534695356953669537695386953969540695416954269543695446954569546695476954869549695506955169552695536955469555695566955769558695596956069561695626956369564695656956669567695686956969570695716957269573695746957569576695776957869579695806958169582695836958469585695866958769588695896959069591695926959369594695956959669597695986959969600696016960269603696046960569606696076960869609696106961169612696136961469615696166961769618696196962069621696226962369624696256962669627696286962969630696316963269633696346963569636696376963869639696406964169642696436964469645696466964769648696496965069651696526965369654696556965669657696586965969660696616966269663696646966569666696676966869669696706967169672696736967469675696766967769678696796968069681696826968369684696856968669687696886968969690696916969269693696946969569696696976969869699697006970169702697036970469705697066970769708697096971069711697126971369714697156971669717697186971969720697216972269723697246972569726697276972869729697306973169732697336973469735697366973769738697396974069741697426974369744697456974669747697486974969750697516975269753697546975569756697576975869759697606976169762697636976469765697666976769768697696977069771697726977369774697756977669777697786977969780697816978269783697846978569786697876978869789697906979169792697936979469795697966979769798697996980069801698026980369804698056980669807698086980969810698116981269813698146981569816698176981869819698206982169822698236982469825698266982769828698296983069831698326983369834698356983669837698386983969840698416984269843698446984569846698476984869849698506985169852698536985469855698566985769858698596986069861698626986369864698656986669867698686986969870698716987269873698746987569876698776987869879698806988169882698836988469885698866988769888698896989069891698926989369894698956989669897698986989969900699016990269903699046990569906699076990869909699106991169912699136991469915699166991769918699196992069921699226992369924699256992669927699286992969930699316993269933699346993569936699376993869939699406994169942699436994469945699466994769948699496995069951699526995369954699556995669957699586995969960699616996269963699646996569966699676996869969699706997169972699736997469975699766997769978699796998069981699826998369984699856998669987699886998969990699916999269993699946999569996699976999869999700007000170002700037000470005700067000770008700097001070011700127001370014700157001670017700187001970020700217002270023700247002570026700277002870029700307003170032700337003470035700367003770038700397004070041700427004370044700457004670047700487004970050700517005270053700547005570056700577005870059700607006170062700637006470065700667006770068700697007070071700727007370074700757007670077700787007970080700817008270083700847008570086700877008870089700907009170092700937009470095700967009770098700997010070101701027010370104701057010670107701087010970110701117011270113701147011570116701177011870119701207012170122701237012470125701267012770128701297013070131701327013370134701357013670137701387013970140701417014270143701447014570146701477014870149701507015170152701537015470155701567015770158701597016070161701627016370164701657016670167701687016970170701717017270173701747017570176701777017870179701807018170182701837018470185701867018770188701897019070191701927019370194701957019670197701987019970200702017020270203702047020570206702077020870209702107021170212702137021470215702167021770218702197022070221702227022370224702257022670227702287022970230702317023270233702347023570236702377023870239702407024170242702437024470245702467024770248702497025070251702527025370254702557025670257702587025970260702617026270263702647026570266702677026870269702707027170272702737027470275702767027770278702797028070281702827028370284702857028670287702887028970290702917029270293702947029570296702977029870299703007030170302703037030470305703067030770308703097031070311703127031370314703157031670317703187031970320703217032270323703247032570326703277032870329703307033170332703337033470335703367033770338703397034070341703427034370344703457034670347703487034970350703517035270353703547035570356703577035870359703607036170362703637036470365703667036770368703697037070371703727037370374703757037670377703787037970380703817038270383703847038570386703877038870389703907039170392703937039470395703967039770398703997040070401704027040370404704057040670407704087040970410704117041270413704147041570416704177041870419704207042170422704237042470425704267042770428704297043070431704327043370434704357043670437704387043970440704417044270443704447044570446704477044870449704507045170452704537045470455704567045770458704597046070461704627046370464704657046670467704687046970470704717047270473704747047570476704777047870479704807048170482704837048470485704867048770488704897049070491704927049370494704957049670497704987049970500705017050270503705047050570506705077050870509705107051170512705137051470515705167051770518705197052070521705227052370524705257052670527705287052970530705317053270533705347053570536705377053870539705407054170542705437054470545705467054770548705497055070551705527055370554705557055670557705587055970560705617056270563705647056570566705677056870569705707057170572705737057470575705767057770578705797058070581705827058370584705857058670587705887058970590705917059270593705947059570596705977059870599706007060170602706037060470605706067060770608706097061070611706127061370614706157061670617706187061970620706217062270623706247062570626706277062870629706307063170632706337063470635706367063770638706397064070641706427064370644706457064670647706487064970650706517065270653706547065570656706577065870659706607066170662706637066470665706667066770668706697067070671706727067370674706757067670677706787067970680706817068270683706847068570686706877068870689706907069170692706937069470695706967069770698706997070070701707027070370704707057070670707707087070970710707117071270713707147071570716707177071870719707207072170722707237072470725707267072770728707297073070731707327073370734707357073670737707387073970740707417074270743707447074570746707477074870749707507075170752707537075470755707567075770758707597076070761707627076370764707657076670767707687076970770707717077270773707747077570776707777077870779707807078170782707837078470785707867078770788707897079070791707927079370794707957079670797707987079970800708017080270803708047080570806708077080870809708107081170812708137081470815708167081770818708197082070821708227082370824708257082670827708287082970830708317083270833708347083570836708377083870839708407084170842708437084470845708467084770848708497085070851708527085370854708557085670857708587085970860708617086270863708647086570866708677086870869708707087170872708737087470875708767087770878708797088070881708827088370884708857088670887708887088970890708917089270893708947089570896708977089870899709007090170902709037090470905709067090770908709097091070911709127091370914709157091670917709187091970920709217092270923709247092570926709277092870929709307093170932709337093470935709367093770938709397094070941709427094370944709457094670947709487094970950709517095270953709547095570956709577095870959709607096170962709637096470965709667096770968709697097070971709727097370974709757097670977709787097970980709817098270983709847098570986709877098870989709907099170992709937099470995709967099770998709997100071001710027100371004710057100671007710087100971010710117101271013710147101571016710177101871019710207102171022710237102471025710267102771028710297103071031710327103371034710357103671037710387103971040710417104271043710447104571046710477104871049710507105171052710537105471055710567105771058710597106071061710627106371064710657106671067710687106971070710717107271073710747107571076710777107871079710807108171082710837108471085710867108771088710897109071091710927109371094710957109671097710987109971100711017110271103711047110571106711077110871109711107111171112711137111471115711167111771118711197112071121711227112371124711257112671127711287112971130711317113271133711347113571136711377113871139711407114171142711437114471145711467114771148711497115071151711527115371154711557115671157711587115971160711617116271163711647116571166711677116871169711707117171172711737117471175711767117771178711797118071181711827118371184711857118671187711887118971190711917119271193711947119571196711977119871199712007120171202712037120471205712067120771208712097121071211712127121371214712157121671217712187121971220712217122271223712247122571226712277122871229712307123171232712337123471235712367123771238712397124071241712427124371244712457124671247712487124971250712517125271253712547125571256712577125871259712607126171262712637126471265712667126771268712697127071271712727127371274712757127671277712787127971280712817128271283712847128571286712877128871289712907129171292712937129471295712967129771298712997130071301713027130371304713057130671307713087130971310713117131271313713147131571316713177131871319713207132171322713237132471325713267132771328713297133071331713327133371334713357133671337713387133971340713417134271343713447134571346713477134871349713507135171352713537135471355713567135771358713597136071361713627136371364713657136671367713687136971370713717137271373713747137571376713777137871379713807138171382713837138471385713867138771388713897139071391713927139371394713957139671397713987139971400714017140271403714047140571406714077140871409714107141171412714137141471415714167141771418714197142071421714227142371424714257142671427714287142971430714317143271433714347143571436714377143871439714407144171442714437144471445714467144771448714497145071451714527145371454714557145671457714587145971460714617146271463714647146571466714677146871469714707147171472714737147471475714767147771478714797148071481714827148371484714857148671487714887148971490714917149271493714947149571496714977149871499715007150171502715037150471505715067150771508715097151071511715127151371514715157151671517715187151971520715217152271523715247152571526715277152871529715307153171532715337153471535715367153771538715397154071541715427154371544715457154671547715487154971550715517155271553715547155571556715577155871559715607156171562715637156471565715667156771568715697157071571715727157371574715757157671577715787157971580715817158271583715847158571586715877158871589715907159171592715937159471595715967159771598715997160071601716027160371604716057160671607716087160971610716117161271613716147161571616716177161871619716207162171622716237162471625716267162771628716297163071631716327163371634716357163671637716387163971640716417164271643716447164571646716477164871649716507165171652716537165471655716567165771658716597166071661716627166371664716657166671667716687166971670716717167271673716747167571676716777167871679716807168171682716837168471685716867168771688716897169071691716927169371694716957169671697716987169971700717017170271703717047170571706717077170871709717107171171712717137171471715717167171771718717197172071721717227172371724717257172671727717287172971730717317173271733717347173571736717377173871739717407174171742717437174471745717467174771748717497175071751717527175371754717557175671757717587175971760717617176271763717647176571766717677176871769717707177171772717737177471775717767177771778717797178071781717827178371784717857178671787717887178971790717917179271793717947179571796717977179871799718007180171802718037180471805718067180771808718097181071811718127181371814718157181671817718187181971820718217182271823718247182571826718277182871829718307183171832718337183471835718367183771838718397184071841718427184371844718457184671847718487184971850718517185271853718547185571856718577185871859718607186171862718637186471865718667186771868718697187071871718727187371874718757187671877718787187971880718817188271883718847188571886718877188871889718907189171892718937189471895718967189771898718997190071901719027190371904719057190671907719087190971910719117191271913719147191571916719177191871919719207192171922719237192471925719267192771928719297193071931719327193371934719357193671937719387193971940719417194271943719447194571946719477194871949719507195171952719537195471955719567195771958719597196071961719627196371964719657196671967719687196971970719717197271973719747197571976719777197871979719807198171982719837198471985719867198771988719897199071991719927199371994719957199671997719987199972000720017200272003720047200572006720077200872009720107201172012720137201472015720167201772018720197202072021720227202372024720257202672027720287202972030720317203272033720347203572036720377203872039720407204172042720437204472045720467204772048720497205072051720527205372054720557205672057720587205972060720617206272063720647206572066720677206872069720707207172072720737207472075720767207772078720797208072081720827208372084720857208672087720887208972090720917209272093720947209572096720977209872099721007210172102721037210472105721067210772108721097211072111721127211372114721157211672117721187211972120721217212272123721247212572126721277212872129721307213172132721337213472135721367213772138721397214072141721427214372144721457214672147721487214972150721517215272153721547215572156721577215872159721607216172162721637216472165721667216772168721697217072171721727217372174721757217672177721787217972180721817218272183721847218572186721877218872189721907219172192721937219472195721967219772198721997220072201722027220372204722057220672207722087220972210722117221272213722147221572216722177221872219722207222172222722237222472225722267222772228722297223072231722327223372234722357223672237722387223972240722417224272243722447224572246722477224872249722507225172252722537225472255722567225772258722597226072261722627226372264722657226672267722687226972270722717227272273722747227572276722777227872279722807228172282722837228472285722867228772288722897229072291722927229372294722957229672297722987229972300723017230272303723047230572306723077230872309723107231172312723137231472315723167231772318723197232072321723227232372324723257232672327723287232972330723317233272333723347233572336723377233872339723407234172342723437234472345723467234772348723497235072351723527235372354723557235672357723587235972360723617236272363723647236572366723677236872369723707237172372723737237472375723767237772378723797238072381723827238372384723857238672387723887238972390723917239272393723947239572396723977239872399724007240172402724037240472405724067240772408724097241072411724127241372414724157241672417724187241972420724217242272423724247242572426724277242872429724307243172432724337243472435724367243772438724397244072441724427244372444724457244672447724487244972450724517245272453724547245572456724577245872459724607246172462724637246472465724667246772468724697247072471724727247372474724757247672477724787247972480724817248272483724847248572486724877248872489724907249172492724937249472495724967249772498724997250072501725027250372504725057250672507725087250972510725117251272513725147251572516725177251872519725207252172522725237252472525725267252772528725297253072531725327253372534725357253672537725387253972540725417254272543725447254572546725477254872549725507255172552725537255472555725567255772558725597256072561725627256372564725657256672567725687256972570725717257272573725747257572576725777257872579725807258172582725837258472585725867258772588725897259072591725927259372594725957259672597725987259972600726017260272603726047260572606726077260872609726107261172612726137261472615726167261772618726197262072621726227262372624726257262672627726287262972630726317263272633726347263572636726377263872639726407264172642726437264472645726467264772648726497265072651726527265372654726557265672657726587265972660726617266272663726647266572666726677266872669726707267172672726737267472675726767267772678726797268072681726827268372684726857268672687726887268972690726917269272693726947269572696726977269872699727007270172702727037270472705727067270772708727097271072711727127271372714727157271672717727187271972720727217272272723727247272572726727277272872729727307273172732727337273472735727367273772738727397274072741727427274372744727457274672747727487274972750727517275272753727547275572756727577275872759727607276172762727637276472765727667276772768727697277072771727727277372774727757277672777727787277972780727817278272783727847278572786727877278872789727907279172792727937279472795727967279772798727997280072801728027280372804728057280672807728087280972810728117281272813728147281572816728177281872819728207282172822728237282472825728267282772828728297283072831728327283372834728357283672837728387283972840728417284272843728447284572846728477284872849728507285172852728537285472855728567285772858728597286072861728627286372864728657286672867728687286972870728717287272873728747287572876728777287872879728807288172882728837288472885728867288772888728897289072891728927289372894728957289672897728987289972900729017290272903729047290572906729077290872909729107291172912729137291472915729167291772918729197292072921729227292372924729257292672927729287292972930729317293272933729347293572936729377293872939729407294172942729437294472945729467294772948729497295072951729527295372954729557295672957729587295972960729617296272963729647296572966729677296872969729707297172972729737297472975729767297772978729797298072981729827298372984729857298672987729887298972990729917299272993729947299572996729977299872999730007300173002730037300473005730067300773008730097301073011730127301373014730157301673017730187301973020730217302273023730247302573026730277302873029730307303173032730337303473035730367303773038730397304073041730427304373044730457304673047730487304973050730517305273053730547305573056730577305873059730607306173062730637306473065730667306773068730697307073071730727307373074730757307673077730787307973080730817308273083730847308573086730877308873089730907309173092730937309473095730967309773098730997310073101731027310373104731057310673107731087310973110731117311273113731147311573116731177311873119731207312173122731237312473125731267312773128731297313073131731327313373134731357313673137731387313973140731417314273143731447314573146731477314873149731507315173152731537315473155731567315773158731597316073161731627316373164731657316673167731687316973170731717317273173731747317573176731777317873179731807318173182731837318473185731867318773188731897319073191731927319373194731957319673197731987319973200732017320273203732047320573206732077320873209732107321173212732137321473215732167321773218732197322073221732227322373224732257322673227732287322973230732317323273233732347323573236732377323873239732407324173242732437324473245732467324773248732497325073251732527325373254732557325673257732587325973260732617326273263732647326573266732677326873269732707327173272732737327473275732767327773278732797328073281732827328373284732857328673287732887328973290732917329273293732947329573296732977329873299733007330173302733037330473305733067330773308733097331073311733127331373314733157331673317733187331973320733217332273323733247332573326733277332873329733307333173332733337333473335733367333773338733397334073341733427334373344733457334673347733487334973350733517335273353733547335573356733577335873359733607336173362733637336473365733667336773368733697337073371733727337373374733757337673377733787337973380733817338273383733847338573386733877338873389733907339173392733937339473395733967339773398733997340073401734027340373404734057340673407734087340973410734117341273413734147341573416734177341873419734207342173422734237342473425734267342773428734297343073431734327343373434734357343673437734387343973440734417344273443734447344573446734477344873449734507345173452734537345473455734567345773458734597346073461734627346373464734657346673467734687346973470734717347273473734747347573476734777347873479734807348173482734837348473485734867348773488734897349073491734927349373494734957349673497734987349973500735017350273503735047350573506735077350873509735107351173512735137351473515735167351773518735197352073521735227352373524735257352673527735287352973530735317353273533735347353573536735377353873539735407354173542735437354473545735467354773548735497355073551735527355373554735557355673557735587355973560735617356273563735647356573566735677356873569735707357173572735737357473575735767357773578735797358073581735827358373584735857358673587735887358973590735917359273593735947359573596735977359873599736007360173602736037360473605736067360773608736097361073611736127361373614736157361673617736187361973620736217362273623736247362573626736277362873629736307363173632736337363473635736367363773638736397364073641736427364373644736457364673647736487364973650736517365273653736547365573656736577365873659736607366173662736637366473665736667366773668736697367073671736727367373674736757367673677736787367973680736817368273683736847368573686736877368873689736907369173692736937369473695736967369773698736997370073701737027370373704737057370673707737087370973710737117371273713737147371573716737177371873719737207372173722737237372473725737267372773728737297373073731737327373373734737357373673737737387373973740737417374273743737447374573746737477374873749737507375173752737537375473755737567375773758737597376073761737627376373764737657376673767737687376973770737717377273773737747377573776737777377873779737807378173782737837378473785737867378773788737897379073791737927379373794737957379673797737987379973800738017380273803738047380573806738077380873809738107381173812738137381473815738167381773818738197382073821738227382373824738257382673827738287382973830738317383273833738347383573836738377383873839738407384173842738437384473845738467384773848738497385073851738527385373854738557385673857738587385973860738617386273863738647386573866738677386873869738707387173872738737387473875738767387773878738797388073881738827388373884738857388673887738887388973890738917389273893738947389573896738977389873899739007390173902739037390473905739067390773908739097391073911739127391373914739157391673917739187391973920739217392273923739247392573926739277392873929739307393173932739337393473935739367393773938739397394073941739427394373944739457394673947739487394973950739517395273953739547395573956739577395873959739607396173962739637396473965739667396773968739697397073971739727397373974739757397673977739787397973980739817398273983739847398573986739877398873989739907399173992739937399473995739967399773998739997400074001740027400374004740057400674007740087400974010740117401274013740147401574016740177401874019740207402174022740237402474025740267402774028740297403074031740327403374034740357403674037740387403974040740417404274043740447404574046740477404874049740507405174052740537405474055740567405774058740597406074061740627406374064740657406674067740687406974070740717407274073740747407574076740777407874079740807408174082740837408474085740867408774088740897409074091740927409374094740957409674097740987409974100741017410274103741047410574106741077410874109741107411174112741137411474115741167411774118741197412074121741227412374124741257412674127741287412974130741317413274133741347413574136741377413874139741407414174142741437414474145741467414774148741497415074151741527415374154741557415674157741587415974160741617416274163741647416574166741677416874169741707417174172741737417474175741767417774178741797418074181741827418374184741857418674187741887418974190741917419274193741947419574196741977419874199742007420174202742037420474205742067420774208742097421074211742127421374214742157421674217742187421974220742217422274223742247422574226742277422874229742307423174232742337423474235742367423774238742397424074241742427424374244742457424674247742487424974250742517425274253742547425574256742577425874259742607426174262742637426474265742667426774268742697427074271742727427374274742757427674277742787427974280742817428274283742847428574286742877428874289742907429174292742937429474295742967429774298742997430074301743027430374304743057430674307743087430974310743117431274313743147431574316743177431874319743207432174322743237432474325743267432774328743297433074331743327433374334743357433674337743387433974340743417434274343743447434574346743477434874349743507435174352743537435474355743567435774358743597436074361743627436374364743657436674367743687436974370743717437274373743747437574376743777437874379743807438174382743837438474385743867438774388743897439074391743927439374394743957439674397743987439974400744017440274403744047440574406744077440874409744107441174412744137441474415744167441774418744197442074421744227442374424744257442674427744287442974430744317443274433744347443574436744377443874439744407444174442744437444474445744467444774448744497445074451744527445374454744557445674457744587445974460744617446274463744647446574466744677446874469744707447174472744737447474475744767447774478744797448074481744827448374484744857448674487744887448974490744917449274493744947449574496744977449874499745007450174502745037450474505745067450774508745097451074511745127451374514745157451674517745187451974520745217452274523745247452574526745277452874529745307453174532745337453474535745367453774538745397454074541745427454374544745457454674547745487454974550745517455274553745547455574556745577455874559745607456174562745637456474565745667456774568745697457074571745727457374574745757457674577745787457974580745817458274583745847458574586745877458874589745907459174592745937459474595745967459774598745997460074601746027460374604746057460674607746087460974610746117461274613746147461574616746177461874619746207462174622746237462474625746267462774628746297463074631746327463374634746357463674637746387463974640746417464274643746447464574646746477464874649746507465174652746537465474655746567465774658746597466074661746627466374664746657466674667746687466974670746717467274673746747467574676746777467874679746807468174682746837468474685746867468774688746897469074691746927469374694746957469674697746987469974700747017470274703747047470574706747077470874709747107471174712747137471474715747167471774718747197472074721747227472374724747257472674727747287472974730747317473274733747347473574736747377473874739747407474174742747437474474745747467474774748747497475074751747527475374754747557475674757747587475974760747617476274763747647476574766747677476874769747707477174772747737477474775747767477774778747797478074781747827478374784747857478674787747887478974790747917479274793747947479574796747977479874799748007480174802748037480474805748067480774808748097481074811748127481374814748157481674817748187481974820748217482274823748247482574826748277482874829748307483174832748337483474835748367483774838748397484074841748427484374844748457484674847748487484974850748517485274853748547485574856748577485874859748607486174862748637486474865748667486774868748697487074871748727487374874748757487674877748787487974880748817488274883748847488574886748877488874889748907489174892748937489474895748967489774898748997490074901749027490374904749057490674907749087490974910749117491274913749147491574916749177491874919749207492174922749237492474925749267492774928749297493074931749327493374934749357493674937749387493974940749417494274943749447494574946749477494874949749507495174952749537495474955749567495774958749597496074961749627496374964749657496674967749687496974970749717497274973749747497574976749777497874979749807498174982749837498474985749867498774988749897499074991749927499374994749957499674997749987499975000750017500275003750047500575006750077500875009750107501175012750137501475015750167501775018750197502075021750227502375024750257502675027750287502975030750317503275033750347503575036750377503875039750407504175042750437504475045750467504775048750497505075051750527505375054750557505675057750587505975060750617506275063750647506575066750677506875069750707507175072750737507475075750767507775078750797508075081750827508375084750857508675087750887508975090750917509275093750947509575096750977509875099751007510175102751037510475105751067510775108751097511075111751127511375114751157511675117751187511975120751217512275123751247512575126751277512875129751307513175132751337513475135751367513775138751397514075141751427514375144751457514675147751487514975150751517515275153751547515575156751577515875159751607516175162751637516475165751667516775168751697517075171751727517375174751757517675177751787517975180751817518275183751847518575186751877518875189751907519175192751937519475195751967519775198751997520075201752027520375204752057520675207752087520975210752117521275213752147521575216752177521875219752207522175222752237522475225752267522775228752297523075231752327523375234752357523675237752387523975240752417524275243752447524575246752477524875249752507525175252752537525475255752567525775258752597526075261752627526375264752657526675267752687526975270752717527275273752747527575276752777527875279752807528175282752837528475285752867528775288752897529075291752927529375294752957529675297752987529975300753017530275303753047530575306753077530875309753107531175312753137531475315753167531775318753197532075321753227532375324753257532675327753287532975330753317533275333753347533575336753377533875339753407534175342753437534475345753467534775348753497535075351753527535375354753557535675357753587535975360753617536275363753647536575366753677536875369753707537175372753737537475375753767537775378753797538075381753827538375384753857538675387753887538975390753917539275393753947539575396753977539875399754007540175402754037540475405754067540775408754097541075411754127541375414754157541675417754187541975420754217542275423754247542575426754277542875429754307543175432754337543475435754367543775438754397544075441754427544375444754457544675447754487544975450754517545275453754547545575456754577545875459754607546175462754637546475465754667546775468754697547075471754727547375474754757547675477754787547975480754817548275483754847548575486754877548875489754907549175492754937549475495754967549775498754997550075501755027550375504755057550675507755087550975510755117551275513755147551575516755177551875519755207552175522755237552475525755267552775528755297553075531755327553375534755357553675537755387553975540755417554275543755447554575546755477554875549755507555175552755537555475555755567555775558755597556075561755627556375564755657556675567755687556975570755717557275573755747557575576755777557875579755807558175582755837558475585755867558775588755897559075591755927559375594755957559675597755987559975600756017560275603756047560575606756077560875609756107561175612756137561475615756167561775618756197562075621756227562375624756257562675627756287562975630756317563275633756347563575636756377563875639756407564175642756437564475645756467564775648756497565075651756527565375654756557565675657756587565975660756617566275663756647566575666756677566875669756707567175672756737567475675756767567775678756797568075681756827568375684756857568675687756887568975690756917569275693756947569575696756977569875699757007570175702757037570475705757067570775708757097571075711757127571375714757157571675717757187571975720757217572275723757247572575726757277572875729757307573175732757337573475735757367573775738757397574075741757427574375744757457574675747757487574975750757517575275753757547575575756757577575875759757607576175762757637576475765757667576775768757697577075771757727577375774757757577675777757787577975780757817578275783757847578575786757877578875789757907579175792757937579475795757967579775798757997580075801758027580375804758057580675807758087580975810758117581275813758147581575816758177581875819758207582175822758237582475825758267582775828758297583075831758327583375834758357583675837758387583975840758417584275843758447584575846758477584875849758507585175852758537585475855758567585775858758597586075861758627586375864758657586675867758687586975870758717587275873758747587575876758777587875879758807588175882758837588475885758867588775888758897589075891758927589375894758957589675897758987589975900759017590275903759047590575906759077590875909759107591175912759137591475915759167591775918759197592075921759227592375924759257592675927759287592975930759317593275933759347593575936759377593875939759407594175942759437594475945759467594775948759497595075951759527595375954759557595675957759587595975960759617596275963759647596575966759677596875969759707597175972759737597475975759767597775978759797598075981759827598375984759857598675987759887598975990759917599275993759947599575996759977599875999760007600176002760037600476005760067600776008760097601076011760127601376014760157601676017760187601976020760217602276023760247602576026760277602876029760307603176032760337603476035760367603776038760397604076041760427604376044760457604676047760487604976050760517605276053760547605576056760577605876059760607606176062760637606476065760667606776068760697607076071760727607376074760757607676077760787607976080760817608276083760847608576086760877608876089760907609176092760937609476095760967609776098760997610076101761027610376104761057610676107761087610976110761117611276113761147611576116761177611876119761207612176122761237612476125761267612776128761297613076131761327613376134761357613676137761387613976140761417614276143761447614576146761477614876149761507615176152761537615476155761567615776158761597616076161761627616376164761657616676167761687616976170761717617276173761747617576176761777617876179761807618176182761837618476185761867618776188761897619076191761927619376194761957619676197761987619976200762017620276203762047620576206762077620876209762107621176212762137621476215762167621776218762197622076221762227622376224762257622676227762287622976230762317623276233762347623576236762377623876239762407624176242762437624476245762467624776248762497625076251762527625376254762557625676257762587625976260762617626276263762647626576266762677626876269762707627176272762737627476275762767627776278762797628076281762827628376284762857628676287762887628976290762917629276293762947629576296762977629876299763007630176302763037630476305763067630776308763097631076311763127631376314763157631676317763187631976320763217632276323763247632576326763277632876329763307633176332763337633476335763367633776338763397634076341763427634376344763457634676347763487634976350763517635276353763547635576356763577635876359763607636176362763637636476365763667636776368763697637076371763727637376374763757637676377763787637976380763817638276383763847638576386763877638876389763907639176392763937639476395763967639776398763997640076401764027640376404764057640676407764087640976410764117641276413764147641576416764177641876419764207642176422764237642476425764267642776428764297643076431764327643376434764357643676437764387643976440764417644276443764447644576446764477644876449764507645176452764537645476455764567645776458764597646076461764627646376464764657646676467764687646976470764717647276473764747647576476764777647876479764807648176482764837648476485764867648776488764897649076491764927649376494764957649676497764987649976500765017650276503765047650576506765077650876509765107651176512765137651476515765167651776518765197652076521765227652376524765257652676527765287652976530765317653276533765347653576536765377653876539765407654176542765437654476545765467654776548765497655076551765527655376554765557655676557765587655976560765617656276563765647656576566765677656876569765707657176572765737657476575765767657776578765797658076581765827658376584765857658676587765887658976590765917659276593765947659576596765977659876599766007660176602766037660476605766067660776608766097661076611766127661376614766157661676617766187661976620766217662276623766247662576626766277662876629766307663176632766337663476635766367663776638766397664076641766427664376644766457664676647766487664976650766517665276653766547665576656766577665876659766607666176662766637666476665766667666776668766697667076671766727667376674766757667676677766787667976680766817668276683766847668576686766877668876689766907669176692766937669476695766967669776698766997670076701767027670376704767057670676707767087670976710767117671276713767147671576716767177671876719767207672176722767237672476725767267672776728767297673076731767327673376734767357673676737767387673976740767417674276743767447674576746767477674876749767507675176752767537675476755767567675776758767597676076761767627676376764767657676676767767687676976770767717677276773767747677576776767777677876779767807678176782767837678476785767867678776788767897679076791767927679376794767957679676797767987679976800768017680276803768047680576806768077680876809768107681176812768137681476815768167681776818768197682076821768227682376824768257682676827768287682976830768317683276833768347683576836768377683876839768407684176842768437684476845768467684776848768497685076851768527685376854768557685676857768587685976860768617686276863768647686576866768677686876869768707687176872768737687476875768767687776878768797688076881768827688376884768857688676887768887688976890768917689276893768947689576896768977689876899769007690176902769037690476905769067690776908769097691076911769127691376914769157691676917769187691976920769217692276923769247692576926769277692876929769307693176932769337693476935769367693776938769397694076941769427694376944769457694676947769487694976950769517695276953769547695576956769577695876959769607696176962769637696476965769667696776968769697697076971769727697376974769757697676977769787697976980769817698276983769847698576986769877698876989769907699176992769937699476995769967699776998769997700077001770027700377004770057700677007770087700977010770117701277013770147701577016770177701877019770207702177022770237702477025770267702777028770297703077031770327703377034770357703677037770387703977040770417704277043770447704577046770477704877049770507705177052770537705477055770567705777058770597706077061770627706377064770657706677067770687706977070770717707277073770747707577076770777707877079770807708177082770837708477085770867708777088770897709077091770927709377094770957709677097770987709977100771017710277103771047710577106771077710877109771107711177112771137711477115771167711777118771197712077121771227712377124771257712677127771287712977130771317713277133771347713577136771377713877139771407714177142771437714477145771467714777148771497715077151771527715377154771557715677157771587715977160771617716277163771647716577166771677716877169771707717177172771737717477175771767717777178771797718077181771827718377184771857718677187771887718977190771917719277193771947719577196771977719877199772007720177202772037720477205772067720777208772097721077211772127721377214772157721677217772187721977220772217722277223772247722577226772277722877229772307723177232772337723477235772367723777238772397724077241772427724377244772457724677247772487724977250772517725277253772547725577256772577725877259772607726177262772637726477265772667726777268772697727077271772727727377274772757727677277772787727977280772817728277283772847728577286772877728877289772907729177292772937729477295772967729777298772997730077301773027730377304773057730677307773087730977310773117731277313773147731577316773177731877319773207732177322773237732477325773267732777328773297733077331773327733377334773357733677337773387733977340773417734277343773447734577346773477734877349773507735177352773537735477355773567735777358773597736077361773627736377364773657736677367773687736977370773717737277373773747737577376773777737877379773807738177382773837738477385773867738777388773897739077391773927739377394773957739677397773987739977400774017740277403774047740577406774077740877409774107741177412774137741477415774167741777418774197742077421774227742377424774257742677427774287742977430774317743277433774347743577436774377743877439774407744177442774437744477445774467744777448774497745077451774527745377454774557745677457774587745977460774617746277463774647746577466774677746877469774707747177472774737747477475774767747777478774797748077481774827748377484774857748677487774887748977490774917749277493774947749577496774977749877499775007750177502775037750477505775067750777508775097751077511775127751377514775157751677517775187751977520775217752277523775247752577526775277752877529775307753177532775337753477535775367753777538775397754077541775427754377544775457754677547775487754977550775517755277553775547755577556775577755877559775607756177562775637756477565775667756777568775697757077571775727757377574775757757677577775787757977580775817758277583775847758577586775877758877589775907759177592775937759477595775967759777598775997760077601776027760377604776057760677607776087760977610776117761277613776147761577616776177761877619776207762177622776237762477625776267762777628776297763077631776327763377634776357763677637776387763977640776417764277643776447764577646776477764877649776507765177652776537765477655776567765777658776597766077661776627766377664776657766677667776687766977670776717767277673776747767577676776777767877679776807768177682776837768477685776867768777688776897769077691776927769377694776957769677697776987769977700777017770277703777047770577706777077770877709777107771177712777137771477715777167771777718777197772077721777227772377724777257772677727777287772977730777317773277733777347773577736777377773877739777407774177742777437774477745777467774777748777497775077751777527775377754777557775677757777587775977760777617776277763777647776577766777677776877769777707777177772777737777477775777767777777778777797778077781777827778377784777857778677787777887778977790777917779277793777947779577796777977779877799778007780177802778037780477805778067780777808778097781077811778127781377814778157781677817778187781977820778217782277823778247782577826778277782877829778307783177832778337783477835778367783777838778397784077841778427784377844778457784677847778487784977850778517785277853778547785577856778577785877859778607786177862778637786477865778667786777868778697787077871778727787377874778757787677877778787787977880778817788277883778847788577886778877788877889778907789177892778937789477895778967789777898778997790077901779027790377904779057790677907779087790977910779117791277913779147791577916779177791877919779207792177922779237792477925779267792777928779297793077931779327793377934779357793677937779387793977940779417794277943779447794577946779477794877949779507795177952779537795477955779567795777958779597796077961779627796377964779657796677967779687796977970779717797277973779747797577976779777797877979779807798177982779837798477985779867798777988779897799077991779927799377994779957799677997779987799978000780017800278003780047800578006780077800878009780107801178012780137801478015780167801778018780197802078021780227802378024780257802678027780287802978030780317803278033780347803578036780377803878039780407804178042780437804478045780467804778048780497805078051780527805378054780557805678057780587805978060780617806278063780647806578066780677806878069780707807178072780737807478075780767807778078780797808078081780827808378084780857808678087780887808978090780917809278093780947809578096780977809878099781007810178102781037810478105781067810778108781097811078111781127811378114781157811678117781187811978120781217812278123781247812578126781277812878129781307813178132781337813478135781367813778138781397814078141781427814378144781457814678147781487814978150781517815278153781547815578156781577815878159781607816178162781637816478165781667816778168781697817078171781727817378174781757817678177781787817978180781817818278183781847818578186781877818878189781907819178192781937819478195781967819778198781997820078201782027820378204782057820678207782087820978210782117821278213782147821578216782177821878219782207822178222782237822478225782267822778228782297823078231782327823378234782357823678237782387823978240782417824278243782447824578246782477824878249782507825178252782537825478255782567825778258782597826078261782627826378264782657826678267782687826978270782717827278273782747827578276782777827878279782807828178282782837828478285782867828778288782897829078291782927829378294782957829678297782987829978300783017830278303783047830578306783077830878309783107831178312783137831478315783167831778318783197832078321783227832378324783257832678327783287832978330783317833278333783347833578336783377833878339783407834178342783437834478345783467834778348783497835078351783527835378354783557835678357783587835978360783617836278363783647836578366783677836878369783707837178372783737837478375783767837778378783797838078381783827838378384783857838678387783887838978390783917839278393783947839578396783977839878399784007840178402784037840478405784067840778408784097841078411784127841378414784157841678417784187841978420784217842278423784247842578426784277842878429784307843178432784337843478435784367843778438784397844078441784427844378444784457844678447784487844978450784517845278453784547845578456784577845878459784607846178462784637846478465784667846778468784697847078471784727847378474784757847678477784787847978480784817848278483784847848578486784877848878489784907849178492784937849478495784967849778498784997850078501785027850378504785057850678507785087850978510785117851278513785147851578516785177851878519785207852178522785237852478525785267852778528785297853078531785327853378534785357853678537785387853978540785417854278543785447854578546785477854878549785507855178552785537855478555785567855778558785597856078561785627856378564785657856678567785687856978570785717857278573785747857578576785777857878579785807858178582785837858478585785867858778588785897859078591785927859378594785957859678597785987859978600786017860278603786047860578606786077860878609786107861178612786137861478615786167861778618786197862078621786227862378624786257862678627786287862978630786317863278633786347863578636786377863878639786407864178642786437864478645786467864778648786497865078651786527865378654786557865678657786587865978660786617866278663786647866578666786677866878669786707867178672786737867478675786767867778678786797868078681786827868378684786857868678687786887868978690786917869278693786947869578696786977869878699787007870178702787037870478705787067870778708787097871078711787127871378714787157871678717787187871978720787217872278723787247872578726787277872878729787307873178732787337873478735787367873778738787397874078741787427874378744787457874678747787487874978750787517875278753787547875578756787577875878759787607876178762787637876478765787667876778768787697877078771787727877378774787757877678777787787877978780787817878278783787847878578786787877878878789787907879178792787937879478795787967879778798787997880078801788027880378804788057880678807788087880978810788117881278813788147881578816788177881878819788207882178822788237882478825788267882778828788297883078831788327883378834788357883678837788387883978840788417884278843788447884578846788477884878849788507885178852788537885478855788567885778858788597886078861788627886378864788657886678867788687886978870788717887278873788747887578876788777887878879788807888178882788837888478885788867888778888788897889078891788927889378894788957889678897788987889978900789017890278903789047890578906789077890878909789107891178912789137891478915789167891778918789197892078921789227892378924789257892678927789287892978930789317893278933789347893578936789377893878939789407894178942789437894478945789467894778948789497895078951789527895378954789557895678957789587895978960789617896278963789647896578966789677896878969789707897178972789737897478975789767897778978789797898078981789827898378984789857898678987789887898978990789917899278993789947899578996789977899878999790007900179002790037900479005790067900779008790097901079011790127901379014790157901679017790187901979020790217902279023790247902579026790277902879029790307903179032790337903479035790367903779038790397904079041790427904379044790457904679047790487904979050790517905279053790547905579056790577905879059790607906179062790637906479065790667906779068790697907079071790727907379074790757907679077790787907979080790817908279083790847908579086790877908879089790907909179092790937909479095790967909779098790997910079101791027910379104791057910679107791087910979110791117911279113791147911579116791177911879119791207912179122791237912479125791267912779128791297913079131791327913379134791357913679137791387913979140791417914279143791447914579146791477914879149791507915179152791537915479155791567915779158791597916079161791627916379164791657916679167791687916979170791717917279173791747917579176791777917879179791807918179182791837918479185791867918779188791897919079191791927919379194791957919679197791987919979200792017920279203792047920579206792077920879209792107921179212792137921479215792167921779218792197922079221792227922379224792257922679227792287922979230792317923279233792347923579236792377923879239792407924179242792437924479245792467924779248792497925079251792527925379254792557925679257792587925979260792617926279263792647926579266792677926879269792707927179272792737927479275792767927779278792797928079281792827928379284792857928679287792887928979290792917929279293792947929579296792977929879299793007930179302793037930479305793067930779308793097931079311793127931379314793157931679317793187931979320793217932279323793247932579326793277932879329793307933179332793337933479335793367933779338793397934079341793427934379344793457934679347793487934979350793517935279353793547935579356793577935879359793607936179362793637936479365793667936779368793697937079371793727937379374793757937679377793787937979380793817938279383793847938579386793877938879389793907939179392793937939479395793967939779398793997940079401794027940379404794057940679407794087940979410794117941279413794147941579416794177941879419794207942179422794237942479425794267942779428794297943079431794327943379434794357943679437794387943979440794417944279443794447944579446794477944879449794507945179452794537945479455794567945779458794597946079461794627946379464794657946679467794687946979470794717947279473794747947579476794777947879479794807948179482794837948479485794867948779488794897949079491794927949379494794957949679497794987949979500795017950279503795047950579506795077950879509795107951179512795137951479515795167951779518795197952079521795227952379524795257952679527795287952979530795317953279533795347953579536795377953879539795407954179542795437954479545795467954779548795497955079551795527955379554795557955679557795587955979560795617956279563795647956579566795677956879569795707957179572795737957479575795767957779578795797958079581795827958379584795857958679587795887958979590795917959279593795947959579596795977959879599796007960179602796037960479605796067960779608796097961079611796127961379614796157961679617796187961979620796217962279623796247962579626796277962879629796307963179632796337963479635796367963779638796397964079641796427964379644796457964679647796487964979650796517965279653796547965579656796577965879659796607966179662796637966479665796667966779668796697967079671796727967379674796757967679677796787967979680796817968279683796847968579686796877968879689796907969179692796937969479695796967969779698796997970079701797027970379704797057970679707797087970979710797117971279713797147971579716797177971879719797207972179722797237972479725797267972779728797297973079731797327973379734797357973679737797387973979740797417974279743797447974579746797477974879749797507975179752797537975479755797567975779758797597976079761797627976379764797657976679767797687976979770797717977279773797747977579776797777977879779797807978179782797837978479785797867978779788797897979079791797927979379794797957979679797797987979979800798017980279803798047980579806798077980879809798107981179812798137981479815798167981779818798197982079821798227982379824798257982679827798287982979830798317983279833798347983579836798377983879839798407984179842798437984479845798467984779848798497985079851798527985379854798557985679857798587985979860798617986279863798647986579866798677986879869798707987179872798737987479875798767987779878798797988079881798827988379884798857988679887798887988979890798917989279893798947989579896798977989879899799007990179902799037990479905799067990779908799097991079911799127991379914799157991679917799187991979920799217992279923799247992579926799277992879929799307993179932799337993479935799367993779938799397994079941799427994379944799457994679947799487994979950799517995279953799547995579956799577995879959799607996179962799637996479965799667996779968799697997079971799727997379974799757997679977799787997979980799817998279983799847998579986799877998879989799907999179992799937999479995799967999779998799998000080001800028000380004800058000680007800088000980010800118001280013800148001580016800178001880019800208002180022800238002480025800268002780028800298003080031800328003380034800358003680037800388003980040800418004280043800448004580046800478004880049800508005180052800538005480055800568005780058800598006080061800628006380064800658006680067800688006980070800718007280073800748007580076800778007880079800808008180082800838008480085800868008780088800898009080091800928009380094800958009680097800988009980100801018010280103801048010580106801078010880109801108011180112801138011480115801168011780118801198012080121801228012380124801258012680127801288012980130801318013280133801348013580136801378013880139801408014180142801438014480145801468014780148801498015080151801528015380154801558015680157801588015980160801618016280163801648016580166801678016880169801708017180172801738017480175801768017780178801798018080181801828018380184801858018680187801888018980190801918019280193801948019580196801978019880199802008020180202802038020480205802068020780208802098021080211802128021380214802158021680217802188021980220802218022280223802248022580226802278022880229802308023180232802338023480235802368023780238802398024080241802428024380244802458024680247802488024980250802518025280253802548025580256802578025880259802608026180262802638026480265802668026780268802698027080271802728027380274802758027680277802788027980280802818028280283802848028580286802878028880289802908029180292802938029480295802968029780298802998030080301803028030380304803058030680307803088030980310803118031280313803148031580316803178031880319803208032180322803238032480325803268032780328803298033080331803328033380334803358033680337803388033980340803418034280343803448034580346803478034880349803508035180352803538035480355803568035780358803598036080361803628036380364803658036680367803688036980370803718037280373803748037580376803778037880379803808038180382803838038480385803868038780388803898039080391803928039380394803958039680397803988039980400804018040280403804048040580406804078040880409804108041180412804138041480415804168041780418804198042080421804228042380424804258042680427804288042980430804318043280433804348043580436804378043880439804408044180442804438044480445804468044780448804498045080451804528045380454804558045680457804588045980460804618046280463804648046580466804678046880469804708047180472804738047480475804768047780478804798048080481804828048380484804858048680487804888048980490804918049280493804948049580496804978049880499805008050180502805038050480505805068050780508805098051080511805128051380514805158051680517805188051980520805218052280523805248052580526805278052880529805308053180532805338053480535805368053780538805398054080541805428054380544805458054680547805488054980550805518055280553805548055580556805578055880559805608056180562805638056480565805668056780568805698057080571805728057380574805758057680577805788057980580805818058280583805848058580586805878058880589805908059180592805938059480595805968059780598805998060080601806028060380604806058060680607806088060980610806118061280613806148061580616806178061880619806208062180622806238062480625806268062780628806298063080631806328063380634806358063680637806388063980640806418064280643806448064580646806478064880649806508065180652806538065480655806568065780658806598066080661806628066380664806658066680667806688066980670806718067280673806748067580676806778067880679806808068180682806838068480685806868068780688806898069080691806928069380694806958069680697806988069980700807018070280703807048070580706807078070880709807108071180712807138071480715807168071780718807198072080721807228072380724807258072680727807288072980730807318073280733807348073580736807378073880739807408074180742807438074480745807468074780748807498075080751807528075380754807558075680757807588075980760807618076280763807648076580766807678076880769807708077180772807738077480775807768077780778807798078080781807828078380784807858078680787807888078980790807918079280793807948079580796807978079880799808008080180802808038080480805808068080780808808098081080811808128081380814808158081680817808188081980820808218082280823808248082580826808278082880829808308083180832808338083480835808368083780838808398084080841808428084380844808458084680847808488084980850808518085280853808548085580856808578085880859808608086180862808638086480865808668086780868808698087080871808728087380874808758087680877808788087980880808818088280883808848088580886808878088880889808908089180892808938089480895808968089780898808998090080901809028090380904809058090680907809088090980910809118091280913809148091580916809178091880919809208092180922809238092480925809268092780928809298093080931809328093380934809358093680937809388093980940809418094280943809448094580946809478094880949809508095180952809538095480955809568095780958809598096080961809628096380964809658096680967809688096980970809718097280973809748097580976809778097880979809808098180982809838098480985809868098780988809898099080991809928099380994809958099680997809988099981000810018100281003810048100581006810078100881009810108101181012810138101481015810168101781018810198102081021810228102381024810258102681027810288102981030810318103281033810348103581036810378103881039810408104181042810438104481045810468104781048810498105081051810528105381054810558105681057810588105981060810618106281063810648106581066810678106881069810708107181072810738107481075810768107781078810798108081081810828108381084810858108681087810888108981090810918109281093810948109581096810978109881099811008110181102811038110481105811068110781108811098111081111811128111381114811158111681117811188111981120811218112281123811248112581126811278112881129811308113181132811338113481135811368113781138811398114081141811428114381144811458114681147811488114981150811518115281153811548115581156811578115881159811608116181162811638116481165811668116781168811698117081171811728117381174811758117681177811788117981180811818118281183811848118581186811878118881189811908119181192811938119481195811968119781198811998120081201812028120381204812058120681207812088120981210812118121281213812148121581216812178121881219812208122181222812238122481225812268122781228812298123081231812328123381234812358123681237812388123981240812418124281243812448124581246812478124881249812508125181252812538125481255812568125781258812598126081261812628126381264812658126681267812688126981270812718127281273812748127581276812778127881279812808128181282812838128481285812868128781288812898129081291812928129381294812958129681297812988129981300813018130281303813048130581306813078130881309813108131181312813138131481315813168131781318813198132081321813228132381324813258132681327813288132981330813318133281333813348133581336813378133881339813408134181342813438134481345813468134781348813498135081351813528135381354813558135681357813588135981360813618136281363813648136581366813678136881369813708137181372813738137481375813768137781378813798138081381813828138381384813858138681387813888138981390813918139281393813948139581396813978139881399814008140181402814038140481405814068140781408814098141081411814128141381414814158141681417814188141981420814218142281423814248142581426814278142881429814308143181432814338143481435814368143781438814398144081441814428144381444814458144681447814488144981450814518145281453814548145581456814578145881459814608146181462814638146481465814668146781468814698147081471814728147381474814758147681477814788147981480814818148281483814848148581486814878148881489814908149181492814938149481495814968149781498814998150081501815028150381504815058150681507815088150981510815118151281513815148151581516815178151881519815208152181522815238152481525815268152781528815298153081531815328153381534815358153681537815388153981540815418154281543815448154581546815478154881549815508155181552815538155481555815568155781558815598156081561815628156381564815658156681567815688156981570815718157281573815748157581576815778157881579815808158181582815838158481585815868158781588815898159081591815928159381594815958159681597815988159981600816018160281603816048160581606816078160881609816108161181612816138161481615816168161781618816198162081621816228162381624816258162681627816288162981630816318163281633816348163581636816378163881639816408164181642816438164481645816468164781648816498165081651816528165381654816558165681657816588165981660816618166281663816648166581666816678166881669816708167181672816738167481675816768167781678816798168081681816828168381684816858168681687816888168981690816918169281693816948169581696816978169881699817008170181702817038170481705817068170781708817098171081711817128171381714817158171681717817188171981720817218172281723817248172581726817278172881729817308173181732817338173481735817368173781738817398174081741817428174381744817458174681747817488174981750817518175281753817548175581756817578175881759817608176181762817638176481765817668176781768817698177081771817728177381774817758177681777817788177981780817818178281783817848178581786817878178881789817908179181792817938179481795817968179781798817998180081801818028180381804818058180681807818088180981810818118181281813818148181581816818178181881819818208182181822818238182481825818268182781828818298183081831818328183381834818358183681837818388183981840818418184281843818448184581846818478184881849818508185181852818538185481855818568185781858818598186081861818628186381864818658186681867818688186981870818718187281873818748187581876818778187881879818808188181882818838188481885818868188781888818898189081891818928189381894818958189681897818988189981900819018190281903819048190581906819078190881909819108191181912819138191481915819168191781918819198192081921819228192381924819258192681927819288192981930819318193281933819348193581936819378193881939819408194181942819438194481945819468194781948819498195081951819528195381954819558195681957819588195981960819618196281963819648196581966819678196881969819708197181972819738197481975819768197781978819798198081981819828198381984819858198681987819888198981990819918199281993819948199581996819978199881999820008200182002820038200482005820068200782008820098201082011820128201382014820158201682017820188201982020820218202282023820248202582026820278202882029820308203182032820338203482035820368203782038820398204082041820428204382044820458204682047820488204982050820518205282053820548205582056820578205882059820608206182062820638206482065820668206782068820698207082071820728207382074820758207682077820788207982080820818208282083820848208582086820878208882089820908209182092820938209482095820968209782098820998210082101821028210382104821058210682107821088210982110821118211282113821148211582116821178211882119821208212182122821238212482125821268212782128821298213082131821328213382134821358213682137821388213982140821418214282143821448214582146821478214882149821508215182152821538215482155821568215782158821598216082161821628216382164821658216682167821688216982170821718217282173821748217582176821778217882179821808218182182821838218482185821868218782188821898219082191821928219382194821958219682197821988219982200822018220282203822048220582206822078220882209822108221182212822138221482215822168221782218822198222082221822228222382224822258222682227822288222982230822318223282233822348223582236822378223882239822408224182242822438224482245822468224782248822498225082251822528225382254822558225682257822588225982260822618226282263822648226582266822678226882269822708227182272822738227482275822768227782278822798228082281822828228382284822858228682287822888228982290822918229282293822948229582296822978229882299823008230182302823038230482305823068230782308823098231082311823128231382314823158231682317823188231982320823218232282323823248232582326823278232882329823308233182332823338233482335823368233782338823398234082341823428234382344823458234682347823488234982350823518235282353823548235582356823578235882359823608236182362823638236482365823668236782368823698237082371823728237382374823758237682377823788237982380823818238282383823848238582386823878238882389823908239182392823938239482395823968239782398823998240082401824028240382404824058240682407824088240982410824118241282413824148241582416824178241882419824208242182422824238242482425824268242782428824298243082431824328243382434824358243682437824388243982440824418244282443824448244582446824478244882449824508245182452824538245482455824568245782458824598246082461824628246382464824658246682467824688246982470824718247282473824748247582476824778247882479824808248182482824838248482485824868248782488824898249082491824928249382494824958249682497824988249982500825018250282503825048250582506825078250882509825108251182512825138251482515825168251782518825198252082521825228252382524825258252682527825288252982530825318253282533825348253582536825378253882539825408254182542825438254482545825468254782548825498255082551825528255382554825558255682557825588255982560825618256282563825648256582566825678256882569825708257182572825738257482575825768257782578825798258082581825828258382584825858258682587825888258982590825918259282593825948259582596825978259882599826008260182602826038260482605826068260782608826098261082611826128261382614826158261682617826188261982620826218262282623826248262582626826278262882629826308263182632826338263482635826368263782638826398264082641826428264382644826458264682647826488264982650826518265282653826548265582656826578265882659826608266182662826638266482665826668266782668826698267082671826728267382674826758267682677826788267982680826818268282683826848268582686826878268882689826908269182692826938269482695826968269782698826998270082701827028270382704827058270682707827088270982710827118271282713827148271582716827178271882719827208272182722827238272482725827268272782728827298273082731827328273382734827358273682737827388273982740827418274282743827448274582746827478274882749827508275182752827538275482755827568275782758827598276082761827628276382764827658276682767827688276982770827718277282773827748277582776827778277882779827808278182782827838278482785827868278782788827898279082791827928279382794827958279682797827988279982800828018280282803828048280582806828078280882809828108281182812828138281482815828168281782818828198282082821828228282382824828258282682827828288282982830828318283282833828348283582836828378283882839828408284182842828438284482845828468284782848828498285082851828528285382854828558285682857828588285982860828618286282863828648286582866828678286882869828708287182872828738287482875828768287782878828798288082881828828288382884828858288682887828888288982890828918289282893828948289582896828978289882899829008290182902829038290482905829068290782908829098291082911829128291382914829158291682917829188291982920829218292282923829248292582926829278292882929829308293182932829338293482935829368293782938829398294082941829428294382944829458294682947829488294982950829518295282953829548295582956829578295882959829608296182962829638296482965829668296782968829698297082971829728297382974829758297682977829788297982980829818298282983829848298582986829878298882989829908299182992829938299482995829968299782998829998300083001830028300383004830058300683007830088300983010830118301283013830148301583016830178301883019830208302183022830238302483025830268302783028830298303083031830328303383034830358303683037830388303983040830418304283043830448304583046830478304883049830508305183052830538305483055830568305783058830598306083061830628306383064830658306683067830688306983070830718307283073830748307583076830778307883079830808308183082830838308483085830868308783088830898309083091830928309383094830958309683097830988309983100831018310283103831048310583106831078310883109831108311183112831138311483115831168311783118831198312083121831228312383124831258312683127831288312983130831318313283133831348313583136831378313883139831408314183142831438314483145831468314783148831498315083151831528315383154831558315683157831588315983160831618316283163831648316583166831678316883169831708317183172831738317483175831768317783178831798318083181831828318383184831858318683187831888318983190831918319283193831948319583196831978319883199832008320183202832038320483205832068320783208832098321083211832128321383214832158321683217832188321983220832218322283223832248322583226832278322883229832308323183232832338323483235832368323783238832398324083241832428324383244832458324683247832488324983250832518325283253832548325583256832578325883259832608326183262832638326483265832668326783268832698327083271832728327383274832758327683277832788327983280832818328283283832848328583286832878328883289832908329183292832938329483295832968329783298832998330083301833028330383304833058330683307833088330983310833118331283313833148331583316833178331883319833208332183322833238332483325833268332783328833298333083331833328333383334833358333683337833388333983340833418334283343833448334583346833478334883349833508335183352833538335483355833568335783358833598336083361833628336383364833658336683367833688336983370833718337283373833748337583376833778337883379833808338183382833838338483385833868338783388833898339083391833928339383394833958339683397833988339983400834018340283403834048340583406834078340883409834108341183412834138341483415834168341783418834198342083421834228342383424834258342683427834288342983430834318343283433834348343583436834378343883439834408344183442834438344483445834468344783448834498345083451834528345383454834558345683457834588345983460834618346283463834648346583466834678346883469834708347183472834738347483475834768347783478834798348083481834828348383484834858348683487834888348983490834918349283493834948349583496834978349883499835008350183502835038350483505835068350783508835098351083511835128351383514835158351683517835188351983520835218352283523835248352583526835278352883529835308353183532835338353483535835368353783538835398354083541835428354383544835458354683547835488354983550835518355283553835548355583556835578355883559835608356183562835638356483565835668356783568835698357083571835728357383574835758357683577835788357983580835818358283583835848358583586835878358883589835908359183592835938359483595835968359783598835998360083601836028360383604836058360683607836088360983610836118361283613836148361583616836178361883619836208362183622836238362483625836268362783628836298363083631836328363383634836358363683637836388363983640836418364283643836448364583646836478364883649836508365183652836538365483655836568365783658836598366083661836628366383664836658366683667836688366983670836718367283673836748367583676836778367883679836808368183682836838368483685836868368783688836898369083691836928369383694836958369683697836988369983700837018370283703837048370583706837078370883709837108371183712837138371483715837168371783718837198372083721837228372383724837258372683727837288372983730837318373283733837348373583736837378373883739837408374183742837438374483745837468374783748837498375083751837528375383754837558375683757837588375983760837618376283763837648376583766837678376883769837708377183772837738377483775837768377783778837798378083781837828378383784837858378683787837888378983790837918379283793837948379583796837978379883799838008380183802838038380483805838068380783808838098381083811838128381383814838158381683817838188381983820838218382283823838248382583826838278382883829838308383183832838338383483835838368383783838838398384083841838428384383844838458384683847838488384983850838518385283853838548385583856838578385883859838608386183862838638386483865838668386783868838698387083871838728387383874838758387683877838788387983880838818388283883838848388583886838878388883889838908389183892838938389483895838968389783898838998390083901839028390383904839058390683907839088390983910839118391283913839148391583916839178391883919839208392183922839238392483925839268392783928839298393083931839328393383934839358393683937839388393983940839418394283943839448394583946839478394883949839508395183952839538395483955839568395783958839598396083961839628396383964839658396683967839688396983970839718397283973839748397583976839778397883979839808398183982839838398483985839868398783988839898399083991839928399383994839958399683997839988399984000840018400284003840048400584006840078400884009840108401184012840138401484015840168401784018840198402084021840228402384024840258402684027840288402984030840318403284033840348403584036840378403884039840408404184042840438404484045840468404784048840498405084051840528405384054840558405684057840588405984060840618406284063840648406584066840678406884069840708407184072840738407484075840768407784078840798408084081840828408384084840858408684087840888408984090840918409284093840948409584096840978409884099841008410184102841038410484105841068410784108841098411084111841128411384114841158411684117841188411984120841218412284123841248412584126841278412884129841308413184132841338413484135841368413784138841398414084141841428414384144841458414684147841488414984150841518415284153841548415584156841578415884159841608416184162841638416484165841668416784168841698417084171841728417384174841758417684177841788417984180841818418284183841848418584186841878418884189841908419184192841938419484195841968419784198841998420084201842028420384204842058420684207842088420984210842118421284213842148421584216842178421884219842208422184222842238422484225842268422784228842298423084231842328423384234842358423684237842388423984240842418424284243842448424584246842478424884249842508425184252842538425484255842568425784258842598426084261842628426384264842658426684267842688426984270842718427284273842748427584276842778427884279842808428184282842838428484285842868428784288842898429084291842928429384294842958429684297842988429984300843018430284303843048430584306843078430884309843108431184312843138431484315843168431784318843198432084321843228432384324843258432684327843288432984330843318433284333843348433584336843378433884339843408434184342843438434484345843468434784348843498435084351843528435384354843558435684357843588435984360843618436284363843648436584366843678436884369843708437184372843738437484375843768437784378843798438084381843828438384384843858438684387843888438984390843918439284393843948439584396843978439884399844008440184402844038440484405844068440784408844098441084411844128441384414844158441684417844188441984420844218442284423844248442584426844278442884429844308443184432844338443484435844368443784438844398444084441844428444384444844458444684447844488444984450844518445284453844548445584456844578445884459844608446184462844638446484465844668446784468844698447084471844728447384474844758447684477844788447984480844818448284483844848448584486844878448884489844908449184492844938449484495844968449784498844998450084501845028450384504845058450684507845088450984510845118451284513845148451584516845178451884519845208452184522845238452484525845268452784528845298453084531845328453384534845358453684537845388453984540845418454284543845448454584546845478454884549845508455184552845538455484555845568455784558845598456084561845628456384564845658456684567845688456984570845718457284573845748457584576845778457884579845808458184582845838458484585845868458784588845898459084591845928459384594845958459684597845988459984600846018460284603846048460584606846078460884609846108461184612846138461484615846168461784618846198462084621846228462384624846258462684627846288462984630846318463284633846348463584636846378463884639846408464184642846438464484645846468464784648846498465084651846528465384654846558465684657846588465984660846618466284663846648466584666846678466884669846708467184672846738467484675846768467784678846798468084681846828468384684846858468684687846888468984690846918469284693846948469584696846978469884699847008470184702847038470484705847068470784708847098471084711847128471384714847158471684717847188471984720847218472284723847248472584726847278472884729847308473184732847338473484735847368473784738847398474084741847428474384744847458474684747847488474984750847518475284753847548475584756847578475884759847608476184762847638476484765847668476784768847698477084771847728477384774847758477684777847788477984780847818478284783847848478584786847878478884789847908479184792847938479484795847968479784798847998480084801848028480384804848058480684807848088480984810848118481284813848148481584816848178481884819848208482184822848238482484825848268482784828848298483084831848328483384834848358483684837848388483984840848418484284843848448484584846848478484884849848508485184852848538485484855848568485784858848598486084861848628486384864848658486684867848688486984870848718487284873848748487584876848778487884879848808488184882848838488484885848868488784888848898489084891848928489384894848958489684897848988489984900849018490284903849048490584906849078490884909849108491184912849138491484915849168491784918849198492084921849228492384924849258492684927849288492984930849318493284933849348493584936849378493884939849408494184942849438494484945849468494784948849498495084951849528495384954849558495684957849588495984960849618496284963849648496584966849678496884969849708497184972849738497484975849768497784978849798498084981849828498384984849858498684987849888498984990849918499284993849948499584996849978499884999850008500185002850038500485005850068500785008850098501085011850128501385014850158501685017850188501985020850218502285023850248502585026850278502885029850308503185032850338503485035850368503785038850398504085041850428504385044850458504685047850488504985050850518505285053850548505585056850578505885059850608506185062850638506485065850668506785068850698507085071850728507385074850758507685077850788507985080850818508285083850848508585086850878508885089850908509185092850938509485095850968509785098850998510085101851028510385104851058510685107851088510985110851118511285113851148511585116851178511885119851208512185122851238512485125851268512785128851298513085131851328513385134851358513685137851388513985140851418514285143851448514585146851478514885149851508515185152851538515485155851568515785158851598516085161851628516385164851658516685167851688516985170851718517285173851748517585176851778517885179851808518185182851838518485185851868518785188851898519085191851928519385194851958519685197851988519985200852018520285203852048520585206852078520885209852108521185212852138521485215852168521785218852198522085221852228522385224852258522685227852288522985230852318523285233852348523585236852378523885239852408524185242852438524485245852468524785248852498525085251852528525385254852558525685257852588525985260852618526285263852648526585266852678526885269852708527185272852738527485275852768527785278852798528085281852828528385284852858528685287852888528985290852918529285293852948529585296852978529885299853008530185302853038530485305853068530785308853098531085311853128531385314853158531685317853188531985320853218532285323853248532585326853278532885329853308533185332853338533485335853368533785338853398534085341853428534385344853458534685347853488534985350853518535285353853548535585356853578535885359853608536185362853638536485365853668536785368853698537085371853728537385374853758537685377853788537985380853818538285383853848538585386853878538885389853908539185392853938539485395853968539785398853998540085401854028540385404854058540685407854088540985410854118541285413854148541585416854178541885419854208542185422854238542485425854268542785428854298543085431854328543385434854358543685437854388543985440854418544285443854448544585446854478544885449854508545185452854538545485455854568545785458854598546085461854628546385464854658546685467854688546985470854718547285473854748547585476854778547885479854808548185482854838548485485854868548785488854898549085491854928549385494854958549685497854988549985500855018550285503855048550585506855078550885509855108551185512855138551485515855168551785518855198552085521855228552385524855258552685527855288552985530855318553285533855348553585536855378553885539855408554185542855438554485545855468554785548855498555085551855528555385554855558555685557855588555985560855618556285563855648556585566855678556885569855708557185572855738557485575855768557785578855798558085581855828558385584855858558685587855888558985590855918559285593855948559585596855978559885599856008560185602856038560485605856068560785608856098561085611856128561385614856158561685617856188561985620856218562285623856248562585626856278562885629856308563185632856338563485635856368563785638856398564085641856428564385644856458564685647856488564985650856518565285653856548565585656856578565885659856608566185662856638566485665856668566785668856698567085671856728567385674856758567685677856788567985680856818568285683856848568585686856878568885689856908569185692856938569485695856968569785698856998570085701857028570385704857058570685707857088570985710857118571285713857148571585716857178571885719857208572185722857238572485725857268572785728857298573085731857328573385734857358573685737857388573985740857418574285743857448574585746857478574885749857508575185752857538575485755857568575785758857598576085761857628576385764857658576685767857688576985770857718577285773857748577585776857778577885779857808578185782857838578485785857868578785788857898579085791857928579385794857958579685797857988579985800858018580285803858048580585806858078580885809858108581185812858138581485815858168581785818858198582085821858228582385824858258582685827858288582985830858318583285833858348583585836858378583885839858408584185842858438584485845858468584785848858498585085851858528585385854858558585685857858588585985860858618586285863858648586585866858678586885869858708587185872858738587485875858768587785878858798588085881858828588385884858858588685887858888588985890858918589285893858948589585896858978589885899859008590185902859038590485905859068590785908859098591085911859128591385914859158591685917859188591985920859218592285923859248592585926859278592885929859308593185932859338593485935859368593785938859398594085941859428594385944859458594685947859488594985950859518595285953859548595585956859578595885959859608596185962859638596485965859668596785968859698597085971859728597385974859758597685977859788597985980859818598285983859848598585986859878598885989859908599185992859938599485995859968599785998859998600086001860028600386004860058600686007860088600986010860118601286013860148601586016860178601886019860208602186022860238602486025860268602786028860298603086031860328603386034860358603686037860388603986040860418604286043860448604586046860478604886049860508605186052860538605486055860568605786058860598606086061860628606386064860658606686067860688606986070860718607286073860748607586076860778607886079860808608186082860838608486085860868608786088860898609086091860928609386094860958609686097860988609986100861018610286103861048610586106861078610886109861108611186112861138611486115861168611786118861198612086121861228612386124861258612686127861288612986130861318613286133861348613586136861378613886139861408614186142861438614486145861468614786148861498615086151861528615386154861558615686157861588615986160861618616286163861648616586166861678616886169861708617186172861738617486175861768617786178861798618086181861828618386184861858618686187861888618986190861918619286193861948619586196861978619886199862008620186202862038620486205862068620786208862098621086211862128621386214862158621686217862188621986220862218622286223862248622586226862278622886229862308623186232862338623486235862368623786238862398624086241862428624386244862458624686247862488624986250862518625286253862548625586256862578625886259862608626186262862638626486265862668626786268862698627086271862728627386274862758627686277862788627986280862818628286283862848628586286862878628886289862908629186292862938629486295862968629786298862998630086301863028630386304863058630686307863088630986310863118631286313863148631586316863178631886319863208632186322863238632486325863268632786328863298633086331863328633386334863358633686337863388633986340863418634286343863448634586346863478634886349863508635186352863538635486355863568635786358863598636086361863628636386364863658636686367863688636986370863718637286373863748637586376863778637886379863808638186382863838638486385863868638786388863898639086391863928639386394863958639686397863988639986400864018640286403864048640586406864078640886409864108641186412864138641486415864168641786418864198642086421864228642386424864258642686427864288642986430864318643286433864348643586436864378643886439864408644186442864438644486445864468644786448864498645086451864528645386454864558645686457864588645986460864618646286463864648646586466864678646886469864708647186472864738647486475864768647786478864798648086481864828648386484864858648686487864888648986490864918649286493864948649586496864978649886499865008650186502865038650486505865068650786508865098651086511865128651386514865158651686517865188651986520865218652286523865248652586526865278652886529865308653186532865338653486535865368653786538865398654086541865428654386544865458654686547865488654986550865518655286553865548655586556865578655886559865608656186562865638656486565865668656786568865698657086571865728657386574865758657686577865788657986580865818658286583865848658586586865878658886589865908659186592865938659486595865968659786598865998660086601866028660386604866058660686607866088660986610866118661286613866148661586616866178661886619866208662186622866238662486625866268662786628866298663086631866328663386634866358663686637866388663986640866418664286643866448664586646866478664886649866508665186652866538665486655866568665786658866598666086661866628666386664866658666686667866688666986670866718667286673866748667586676866778667886679866808668186682866838668486685866868668786688866898669086691866928669386694866958669686697866988669986700867018670286703867048670586706867078670886709867108671186712867138671486715867168671786718867198672086721867228672386724867258672686727867288672986730867318673286733867348673586736867378673886739867408674186742867438674486745867468674786748867498675086751867528675386754867558675686757867588675986760867618676286763867648676586766867678676886769867708677186772867738677486775867768677786778867798678086781867828678386784867858678686787867888678986790867918679286793867948679586796867978679886799868008680186802868038680486805868068680786808868098681086811868128681386814868158681686817868188681986820868218682286823868248682586826868278682886829868308683186832868338683486835868368683786838868398684086841868428684386844868458684686847868488684986850868518685286853868548685586856868578685886859868608686186862868638686486865868668686786868868698687086871868728687386874868758687686877868788687986880868818688286883868848688586886868878688886889868908689186892868938689486895868968689786898868998690086901869028690386904869058690686907869088690986910869118691286913869148691586916869178691886919869208692186922869238692486925869268692786928869298693086931869328693386934869358693686937869388693986940869418694286943869448694586946869478694886949869508695186952869538695486955869568695786958869598696086961869628696386964869658696686967869688696986970869718697286973869748697586976869778697886979869808698186982869838698486985869868698786988869898699086991869928699386994869958699686997869988699987000870018700287003870048700587006870078700887009870108701187012870138701487015870168701787018870198702087021870228702387024870258702687027870288702987030870318703287033870348703587036870378703887039870408704187042870438704487045870468704787048870498705087051870528705387054870558705687057870588705987060870618706287063870648706587066870678706887069870708707187072870738707487075870768707787078870798708087081870828708387084870858708687087870888708987090870918709287093870948709587096870978709887099871008710187102871038710487105871068710787108871098711087111871128711387114871158711687117871188711987120871218712287123871248712587126871278712887129871308713187132871338713487135871368713787138871398714087141871428714387144871458714687147871488714987150871518715287153871548715587156871578715887159871608716187162871638716487165871668716787168871698717087171871728717387174871758717687177871788717987180871818718287183871848718587186871878718887189871908719187192871938719487195871968719787198871998720087201872028720387204872058720687207872088720987210872118721287213872148721587216872178721887219872208722187222872238722487225872268722787228872298723087231872328723387234872358723687237872388723987240872418724287243872448724587246872478724887249872508725187252872538725487255872568725787258872598726087261872628726387264872658726687267872688726987270872718727287273872748727587276872778727887279872808728187282872838728487285872868728787288872898729087291872928729387294872958729687297872988729987300873018730287303873048730587306873078730887309873108731187312873138731487315873168731787318873198732087321873228732387324873258732687327873288732987330873318733287333873348733587336873378733887339873408734187342873438734487345873468734787348873498735087351873528735387354873558735687357873588735987360873618736287363873648736587366873678736887369873708737187372873738737487375873768737787378873798738087381873828738387384873858738687387873888738987390873918739287393873948739587396873978739887399874008740187402874038740487405874068740787408874098741087411874128741387414874158741687417874188741987420874218742287423874248742587426874278742887429874308743187432874338743487435874368743787438874398744087441874428744387444874458744687447874488744987450874518745287453874548745587456874578745887459874608746187462874638746487465874668746787468874698747087471874728747387474874758747687477874788747987480874818748287483874848748587486874878748887489874908749187492874938749487495874968749787498874998750087501875028750387504875058750687507875088750987510875118751287513875148751587516875178751887519875208752187522875238752487525875268752787528875298753087531875328753387534875358753687537875388753987540875418754287543875448754587546875478754887549875508755187552875538755487555875568755787558875598756087561875628756387564875658756687567875688756987570875718757287573875748757587576875778757887579875808758187582875838758487585875868758787588875898759087591875928759387594875958759687597875988759987600876018760287603876048760587606876078760887609876108761187612876138761487615876168761787618876198762087621876228762387624876258762687627876288762987630876318763287633876348763587636876378763887639876408764187642876438764487645876468764787648876498765087651876528765387654876558765687657876588765987660876618766287663876648766587666876678766887669876708767187672876738767487675876768767787678876798768087681876828768387684876858768687687876888768987690876918769287693876948769587696876978769887699877008770187702877038770487705877068770787708877098771087711877128771387714877158771687717877188771987720877218772287723877248772587726877278772887729877308773187732877338773487735877368773787738877398774087741877428774387744877458774687747877488774987750877518775287753877548775587756877578775887759877608776187762877638776487765877668776787768877698777087771877728777387774877758777687777877788777987780877818778287783877848778587786877878778887789877908779187792877938779487795877968779787798877998780087801878028780387804878058780687807878088780987810878118781287813878148781587816878178781887819878208782187822878238782487825878268782787828878298783087831878328783387834878358783687837878388783987840878418784287843878448784587846878478784887849878508785187852878538785487855878568785787858878598786087861878628786387864878658786687867878688786987870878718787287873878748787587876878778787887879878808788187882878838788487885878868788787888878898789087891878928789387894878958789687897878988789987900879018790287903879048790587906879078790887909879108791187912879138791487915879168791787918879198792087921879228792387924879258792687927879288792987930879318793287933879348793587936879378793887939879408794187942879438794487945879468794787948879498795087951879528795387954879558795687957879588795987960879618796287963879648796587966879678796887969879708797187972879738797487975879768797787978879798798087981879828798387984879858798687987879888798987990879918799287993879948799587996879978799887999880008800188002880038800488005880068800788008880098801088011880128801388014880158801688017880188801988020880218802288023880248802588026880278802888029880308803188032880338803488035880368803788038880398804088041880428804388044880458804688047880488804988050880518805288053880548805588056880578805888059880608806188062880638806488065880668806788068880698807088071880728807388074880758807688077880788807988080880818808288083880848808588086880878808888089880908809188092880938809488095880968809788098880998810088101881028810388104881058810688107881088810988110881118811288113881148811588116881178811888119881208812188122881238812488125881268812788128881298813088131881328813388134881358813688137881388813988140881418814288143881448814588146881478814888149881508815188152881538815488155881568815788158881598816088161881628816388164881658816688167881688816988170881718817288173881748817588176881778817888179881808818188182881838818488185881868818788188881898819088191881928819388194881958819688197881988819988200882018820288203882048820588206882078820888209882108821188212882138821488215882168821788218882198822088221882228822388224882258822688227882288822988230882318823288233882348823588236882378823888239882408824188242882438824488245882468824788248882498825088251882528825388254882558825688257882588825988260882618826288263882648826588266882678826888269882708827188272882738827488275882768827788278882798828088281882828828388284882858828688287882888828988290882918829288293882948829588296882978829888299883008830188302883038830488305883068830788308883098831088311883128831388314883158831688317883188831988320883218832288323883248832588326883278832888329883308833188332883338833488335883368833788338883398834088341883428834388344883458834688347883488834988350883518835288353883548835588356883578835888359883608836188362883638836488365883668836788368883698837088371883728837388374883758837688377883788837988380883818838288383883848838588386883878838888389883908839188392883938839488395883968839788398883998840088401884028840388404884058840688407884088840988410884118841288413884148841588416884178841888419884208842188422884238842488425884268842788428884298843088431884328843388434884358843688437884388843988440884418844288443884448844588446884478844888449884508845188452884538845488455884568845788458884598846088461884628846388464884658846688467884688846988470884718847288473884748847588476884778847888479884808848188482884838848488485884868848788488884898849088491884928849388494884958849688497884988849988500885018850288503885048850588506885078850888509885108851188512885138851488515885168851788518885198852088521885228852388524885258852688527885288852988530885318853288533885348853588536885378853888539885408854188542885438854488545885468854788548885498855088551885528855388554885558855688557885588855988560885618856288563885648856588566885678856888569885708857188572885738857488575885768857788578885798858088581885828858388584885858858688587885888858988590885918859288593885948859588596885978859888599886008860188602886038860488605886068860788608886098861088611886128861388614886158861688617886188861988620886218862288623886248862588626886278862888629886308863188632886338863488635886368863788638886398864088641886428864388644886458864688647886488864988650886518865288653886548865588656886578865888659886608866188662886638866488665886668866788668886698867088671886728867388674886758867688677886788867988680886818868288683886848868588686886878868888689886908869188692886938869488695886968869788698886998870088701887028870388704887058870688707887088870988710887118871288713887148871588716887178871888719887208872188722887238872488725887268872788728887298873088731887328873388734887358873688737887388873988740887418874288743887448874588746887478874888749887508875188752887538875488755887568875788758887598876088761887628876388764887658876688767887688876988770887718877288773887748877588776887778877888779887808878188782887838878488785887868878788788887898879088791887928879388794887958879688797887988879988800888018880288803888048880588806888078880888809888108881188812888138881488815888168881788818888198882088821888228882388824888258882688827888288882988830888318883288833888348883588836888378883888839888408884188842888438884488845888468884788848888498885088851888528885388854888558885688857888588885988860888618886288863888648886588866888678886888869888708887188872888738887488875888768887788878888798888088881888828888388884888858888688887888888888988890888918889288893888948889588896888978889888899889008890188902889038890488905889068890788908889098891088911889128891388914889158891688917889188891988920889218892288923889248892588926889278892888929889308893188932889338893488935889368893788938889398894088941889428894388944889458894688947889488894988950889518895288953889548895588956889578895888959889608896188962889638896488965889668896788968889698897088971889728897388974889758897688977889788897988980889818898288983889848898588986889878898888989889908899188992889938899488995889968899788998889998900089001890028900389004890058900689007890088900989010890118901289013890148901589016890178901889019890208902189022890238902489025890268902789028890298903089031890328903389034890358903689037890388903989040890418904289043890448904589046890478904889049890508905189052890538905489055890568905789058890598906089061890628906389064890658906689067890688906989070890718907289073890748907589076890778907889079890808908189082890838908489085890868908789088890898909089091890928909389094890958909689097890988909989100891018910289103891048910589106891078910889109891108911189112891138911489115891168911789118891198912089121891228912389124891258912689127891288912989130891318913289133891348913589136891378913889139891408914189142891438914489145891468914789148891498915089151891528915389154891558915689157891588915989160891618916289163891648916589166891678916889169891708917189172891738917489175891768917789178891798918089181891828918389184891858918689187891888918989190891918919289193891948919589196891978919889199892008920189202892038920489205892068920789208892098921089211892128921389214892158921689217892188921989220892218922289223892248922589226892278922889229892308923189232892338923489235892368923789238892398924089241892428924389244892458924689247892488924989250892518925289253892548925589256892578925889259892608926189262892638926489265892668926789268892698927089271892728927389274892758927689277892788927989280892818928289283892848928589286892878928889289892908929189292892938929489295892968929789298892998930089301893028930389304893058930689307893088930989310893118931289313893148931589316893178931889319893208932189322893238932489325893268932789328893298933089331893328933389334893358933689337893388933989340893418934289343893448934589346893478934889349893508935189352893538935489355893568935789358893598936089361893628936389364893658936689367893688936989370893718937289373893748937589376893778937889379893808938189382893838938489385893868938789388893898939089391893928939389394893958939689397893988939989400894018940289403894048940589406894078940889409894108941189412894138941489415894168941789418894198942089421894228942389424894258942689427894288942989430894318943289433894348943589436894378943889439894408944189442894438944489445894468944789448894498945089451894528945389454894558945689457894588945989460894618946289463894648946589466894678946889469894708947189472894738947489475894768947789478894798948089481894828948389484894858948689487894888948989490894918949289493894948949589496894978949889499895008950189502895038950489505895068950789508895098951089511895128951389514895158951689517895188951989520895218952289523895248952589526895278952889529895308953189532895338953489535895368953789538895398954089541895428954389544895458954689547895488954989550895518955289553895548955589556895578955889559895608956189562895638956489565895668956789568895698957089571895728957389574895758957689577895788957989580895818958289583895848958589586895878958889589895908959189592895938959489595895968959789598895998960089601896028960389604896058960689607896088960989610896118961289613896148961589616896178961889619896208962189622896238962489625896268962789628896298963089631896328963389634896358963689637896388963989640896418964289643896448964589646896478964889649896508965189652896538965489655896568965789658896598966089661896628966389664896658966689667896688966989670896718967289673896748967589676896778967889679896808968189682896838968489685896868968789688896898969089691896928969389694896958969689697896988969989700897018970289703897048970589706897078970889709897108971189712897138971489715897168971789718897198972089721897228972389724897258972689727897288972989730897318973289733897348973589736897378973889739897408974189742897438974489745897468974789748897498975089751897528975389754897558975689757897588975989760897618976289763897648976589766897678976889769897708977189772897738977489775897768977789778897798978089781897828978389784897858978689787897888978989790897918979289793897948979589796897978979889799898008980189802898038980489805898068980789808898098981089811898128981389814898158981689817898188981989820898218982289823898248982589826898278982889829898308983189832898338983489835898368983789838898398984089841898428984389844898458984689847898488984989850898518985289853898548985589856898578985889859898608986189862898638986489865898668986789868898698987089871898728987389874898758987689877898788987989880898818988289883898848988589886898878988889889898908989189892898938989489895898968989789898898998990089901899028990389904899058990689907899088990989910899118991289913899148991589916899178991889919899208992189922899238992489925899268992789928899298993089931899328993389934899358993689937899388993989940899418994289943899448994589946899478994889949899508995189952899538995489955899568995789958899598996089961899628996389964899658996689967899688996989970899718997289973899748997589976899778997889979899808998189982899838998489985899868998789988899898999089991899928999389994899958999689997899988999990000900019000290003900049000590006900079000890009900109001190012900139001490015900169001790018900199002090021900229002390024900259002690027900289002990030900319003290033900349003590036900379003890039900409004190042900439004490045900469004790048900499005090051900529005390054900559005690057900589005990060900619006290063900649006590066900679006890069900709007190072900739007490075900769007790078900799008090081900829008390084900859008690087900889008990090900919009290093900949009590096900979009890099901009010190102901039010490105901069010790108901099011090111901129011390114901159011690117901189011990120901219012290123901249012590126901279012890129901309013190132901339013490135901369013790138901399014090141901429014390144901459014690147901489014990150901519015290153901549015590156901579015890159901609016190162901639016490165901669016790168901699017090171901729017390174901759017690177901789017990180901819018290183901849018590186901879018890189901909019190192901939019490195901969019790198901999020090201902029020390204902059020690207902089020990210902119021290213902149021590216902179021890219902209022190222902239022490225902269022790228902299023090231902329023390234902359023690237902389023990240902419024290243902449024590246902479024890249902509025190252902539025490255902569025790258902599026090261902629026390264902659026690267902689026990270902719027290273902749027590276902779027890279902809028190282902839028490285902869028790288902899029090291902929029390294902959029690297902989029990300903019030290303903049030590306903079030890309903109031190312903139031490315903169031790318903199032090321903229032390324903259032690327903289032990330903319033290333903349033590336903379033890339903409034190342903439034490345903469034790348903499035090351903529035390354903559035690357903589035990360903619036290363903649036590366903679036890369903709037190372903739037490375903769037790378903799038090381903829038390384903859038690387903889038990390903919039290393903949039590396903979039890399904009040190402904039040490405904069040790408904099041090411904129041390414904159041690417904189041990420904219042290423904249042590426904279042890429904309043190432904339043490435904369043790438904399044090441904429044390444904459044690447904489044990450904519045290453904549045590456904579045890459904609046190462904639046490465904669046790468904699047090471904729047390474904759047690477904789047990480904819048290483904849048590486904879048890489904909049190492904939049490495904969049790498904999050090501905029050390504905059050690507905089050990510905119051290513905149051590516905179051890519905209052190522905239052490525905269052790528905299053090531905329053390534905359053690537905389053990540905419054290543905449054590546905479054890549905509055190552905539055490555905569055790558905599056090561905629056390564905659056690567905689056990570905719057290573905749057590576905779057890579905809058190582905839058490585905869058790588905899059090591905929059390594905959059690597905989059990600906019060290603906049060590606906079060890609906109061190612906139061490615906169061790618906199062090621906229062390624906259062690627906289062990630906319063290633906349063590636906379063890639906409064190642906439064490645906469064790648906499065090651906529065390654906559065690657906589065990660906619066290663906649066590666906679066890669906709067190672906739067490675906769067790678906799068090681906829068390684906859068690687906889068990690906919069290693906949069590696906979069890699907009070190702907039070490705907069070790708907099071090711907129071390714907159071690717907189071990720907219072290723907249072590726907279072890729907309073190732907339073490735907369073790738907399074090741907429074390744907459074690747907489074990750907519075290753907549075590756907579075890759907609076190762907639076490765907669076790768907699077090771907729077390774907759077690777907789077990780907819078290783907849078590786907879078890789907909079190792907939079490795907969079790798907999080090801908029080390804908059080690807908089080990810908119081290813908149081590816908179081890819908209082190822908239082490825908269082790828908299083090831908329083390834908359083690837908389083990840908419084290843908449084590846908479084890849908509085190852908539085490855908569085790858908599086090861908629086390864908659086690867908689086990870908719087290873908749087590876908779087890879908809088190882908839088490885908869088790888908899089090891908929089390894908959089690897908989089990900909019090290903909049090590906909079090890909909109091190912909139091490915909169091790918909199092090921909229092390924909259092690927909289092990930909319093290933909349093590936909379093890939909409094190942909439094490945909469094790948909499095090951909529095390954909559095690957909589095990960909619096290963909649096590966909679096890969909709097190972909739097490975909769097790978909799098090981909829098390984909859098690987909889098990990909919099290993909949099590996909979099890999910009100191002910039100491005910069100791008910099101091011910129101391014910159101691017910189101991020910219102291023910249102591026910279102891029910309103191032910339103491035910369103791038910399104091041910429104391044910459104691047910489104991050910519105291053910549105591056910579105891059910609106191062910639106491065910669106791068910699107091071910729107391074910759107691077910789107991080910819108291083910849108591086910879108891089910909109191092910939109491095910969109791098910999110091101911029110391104911059110691107911089110991110911119111291113911149111591116911179111891119911209112191122911239112491125911269112791128911299113091131911329113391134911359113691137911389113991140911419114291143911449114591146911479114891149911509115191152911539115491155911569115791158911599116091161911629116391164911659116691167911689116991170911719117291173911749117591176911779117891179911809118191182911839118491185911869118791188911899119091191911929119391194911959119691197911989119991200912019120291203912049120591206912079120891209912109121191212912139121491215912169121791218912199122091221912229122391224912259122691227912289122991230912319123291233912349123591236912379123891239912409124191242912439124491245912469124791248912499125091251912529125391254912559125691257912589125991260912619126291263912649126591266912679126891269912709127191272912739127491275912769127791278912799128091281912829128391284912859128691287912889128991290912919129291293912949129591296912979129891299913009130191302913039130491305913069130791308913099131091311913129131391314913159131691317913189131991320913219132291323913249132591326913279132891329913309133191332913339133491335913369133791338913399134091341913429134391344913459134691347913489134991350913519135291353913549135591356913579135891359913609136191362913639136491365913669136791368913699137091371913729137391374913759137691377913789137991380913819138291383913849138591386913879138891389913909139191392913939139491395913969139791398913999140091401914029140391404914059140691407914089140991410914119141291413914149141591416914179141891419914209142191422914239142491425914269142791428914299143091431914329143391434914359143691437914389143991440914419144291443914449144591446914479144891449914509145191452914539145491455914569145791458914599146091461914629146391464914659146691467914689146991470914719147291473914749147591476914779147891479914809148191482914839148491485914869148791488914899149091491914929149391494914959149691497914989149991500915019150291503915049150591506915079150891509915109151191512915139151491515915169151791518915199152091521915229152391524915259152691527915289152991530915319153291533915349153591536915379153891539915409154191542915439154491545915469154791548915499155091551915529155391554915559155691557915589155991560915619156291563915649156591566915679156891569915709157191572915739157491575915769157791578915799158091581915829158391584915859158691587915889158991590915919159291593915949159591596915979159891599916009160191602916039160491605916069160791608916099161091611916129161391614916159161691617916189161991620916219162291623916249162591626916279162891629916309163191632916339163491635916369163791638916399164091641916429164391644916459164691647916489164991650916519165291653916549165591656916579165891659916609166191662916639166491665916669166791668916699167091671916729167391674916759167691677916789167991680916819168291683916849168591686916879168891689916909169191692916939169491695916969169791698916999170091701917029170391704917059170691707917089170991710917119171291713917149171591716917179171891719917209172191722917239172491725917269172791728917299173091731917329173391734917359173691737917389173991740917419174291743917449174591746917479174891749917509175191752917539175491755917569175791758917599176091761917629176391764917659176691767917689176991770917719177291773917749177591776917779177891779917809178191782917839178491785917869178791788917899179091791917929179391794917959179691797917989179991800918019180291803918049180591806918079180891809918109181191812918139181491815918169181791818918199182091821918229182391824918259182691827918289182991830918319183291833918349183591836918379183891839918409184191842918439184491845918469184791848918499185091851918529185391854918559185691857918589185991860918619186291863918649186591866918679186891869918709187191872918739187491875918769187791878918799188091881918829188391884918859188691887918889188991890918919189291893918949189591896918979189891899919009190191902919039190491905919069190791908919099191091911919129191391914919159191691917919189191991920919219192291923919249192591926919279192891929919309193191932919339193491935919369193791938919399194091941919429194391944919459194691947919489194991950919519195291953919549195591956919579195891959919609196191962919639196491965919669196791968919699197091971919729197391974919759197691977919789197991980919819198291983919849198591986919879198891989919909199191992919939199491995919969199791998919999200092001920029200392004920059200692007920089200992010920119201292013920149201592016920179201892019920209202192022920239202492025920269202792028920299203092031920329203392034920359203692037920389203992040920419204292043920449204592046920479204892049920509205192052920539205492055920569205792058920599206092061920629206392064920659206692067920689206992070920719207292073920749207592076920779207892079920809208192082920839208492085920869208792088920899209092091920929209392094920959209692097920989209992100921019210292103921049210592106921079210892109921109211192112921139211492115921169211792118921199212092121921229212392124921259212692127921289212992130921319213292133921349213592136921379213892139921409214192142921439214492145921469214792148921499215092151921529215392154921559215692157921589215992160921619216292163921649216592166921679216892169921709217192172921739217492175921769217792178921799218092181921829218392184921859218692187921889218992190921919219292193921949219592196921979219892199922009220192202922039220492205922069220792208922099221092211922129221392214922159221692217922189221992220922219222292223922249222592226922279222892229922309223192232922339223492235922369223792238922399224092241922429224392244922459224692247922489224992250922519225292253922549225592256922579225892259922609226192262922639226492265922669226792268922699227092271922729227392274922759227692277922789227992280922819228292283922849228592286922879228892289922909229192292922939229492295922969229792298922999230092301923029230392304923059230692307923089230992310923119231292313923149231592316923179231892319923209232192322923239232492325923269232792328923299233092331923329233392334923359233692337923389233992340923419234292343923449234592346923479234892349923509235192352923539235492355923569235792358923599236092361923629236392364923659236692367923689236992370923719237292373923749237592376923779237892379923809238192382923839238492385923869238792388923899239092391923929239392394923959239692397923989239992400924019240292403924049240592406924079240892409924109241192412924139241492415924169241792418924199242092421924229242392424924259242692427924289242992430924319243292433924349243592436924379243892439924409244192442924439244492445924469244792448924499245092451924529245392454924559245692457924589245992460924619246292463924649246592466924679246892469924709247192472924739247492475924769247792478924799248092481924829248392484924859248692487924889248992490924919249292493924949249592496924979249892499925009250192502925039250492505925069250792508925099251092511925129251392514925159251692517925189251992520925219252292523925249252592526925279252892529925309253192532925339253492535925369253792538925399254092541925429254392544925459254692547925489254992550925519255292553925549255592556925579255892559925609256192562925639256492565925669256792568925699257092571925729257392574925759257692577925789257992580925819258292583925849258592586925879258892589925909259192592925939259492595925969259792598925999260092601926029260392604926059260692607926089260992610926119261292613926149261592616926179261892619926209262192622926239262492625926269262792628926299263092631926329263392634926359263692637926389263992640926419264292643926449264592646926479264892649926509265192652926539265492655926569265792658926599266092661926629266392664926659266692667926689266992670926719267292673926749267592676926779267892679926809268192682926839268492685926869268792688926899269092691926929269392694926959269692697926989269992700927019270292703927049270592706927079270892709927109271192712927139271492715927169271792718927199272092721927229272392724927259272692727927289272992730927319273292733927349273592736927379273892739927409274192742927439274492745927469274792748927499275092751927529275392754927559275692757927589275992760927619276292763927649276592766927679276892769927709277192772927739277492775927769277792778927799278092781927829278392784927859278692787927889278992790927919279292793927949279592796927979279892799928009280192802928039280492805928069280792808928099281092811928129281392814928159281692817928189281992820928219282292823928249282592826928279282892829928309283192832928339283492835928369283792838928399284092841928429284392844928459284692847928489284992850928519285292853928549285592856928579285892859928609286192862928639286492865928669286792868928699287092871928729287392874928759287692877928789287992880928819288292883928849288592886928879288892889928909289192892928939289492895928969289792898928999290092901929029290392904929059290692907929089290992910929119291292913929149291592916929179291892919929209292192922929239292492925929269292792928929299293092931929329293392934929359293692937929389293992940929419294292943929449294592946929479294892949929509295192952929539295492955929569295792958929599296092961929629296392964929659296692967929689296992970929719297292973929749297592976929779297892979929809298192982929839298492985929869298792988929899299092991929929299392994929959299692997929989299993000930019300293003930049300593006930079300893009930109301193012930139301493015930169301793018930199302093021930229302393024930259302693027930289302993030930319303293033930349303593036930379303893039930409304193042930439304493045930469304793048930499305093051930529305393054930559305693057930589305993060930619306293063930649306593066930679306893069930709307193072930739307493075930769307793078930799308093081930829308393084930859308693087930889308993090930919309293093930949309593096930979309893099931009310193102931039310493105931069310793108931099311093111931129311393114931159311693117931189311993120931219312293123931249312593126931279312893129931309313193132931339313493135931369313793138931399314093141931429314393144931459314693147931489314993150931519315293153931549315593156931579315893159931609316193162931639316493165931669316793168931699317093171931729317393174931759317693177931789317993180931819318293183931849318593186931879318893189931909319193192931939319493195931969319793198931999320093201932029320393204932059320693207932089320993210932119321293213932149321593216932179321893219932209322193222932239322493225932269322793228932299323093231932329323393234932359323693237932389323993240932419324293243932449324593246932479324893249932509325193252932539325493255932569325793258932599326093261932629326393264932659326693267932689326993270932719327293273932749327593276932779327893279932809328193282932839328493285932869328793288932899329093291932929329393294932959329693297932989329993300933019330293303933049330593306933079330893309933109331193312933139331493315933169331793318933199332093321933229332393324933259332693327933289332993330933319333293333933349333593336933379333893339933409334193342933439334493345933469334793348933499335093351933529335393354933559335693357933589335993360933619336293363933649336593366933679336893369933709337193372933739337493375933769337793378933799338093381933829338393384933859338693387933889338993390933919339293393933949339593396933979339893399934009340193402934039340493405934069340793408934099341093411934129341393414934159341693417934189341993420934219342293423934249342593426934279342893429934309343193432934339343493435934369343793438934399344093441934429344393444934459344693447934489344993450934519345293453934549345593456934579345893459934609346193462934639346493465934669346793468934699347093471934729347393474934759347693477934789347993480934819348293483934849348593486934879348893489934909349193492934939349493495934969349793498934999350093501935029350393504935059350693507935089350993510935119351293513935149351593516935179351893519935209352193522935239352493525935269352793528935299353093531935329353393534935359353693537935389353993540935419354293543935449354593546935479354893549935509355193552935539355493555935569355793558935599356093561935629356393564935659356693567935689356993570935719357293573935749357593576935779357893579935809358193582935839358493585935869358793588935899359093591935929359393594935959359693597935989359993600936019360293603936049360593606936079360893609936109361193612936139361493615936169361793618936199362093621936229362393624936259362693627936289362993630936319363293633936349363593636936379363893639936409364193642936439364493645936469364793648936499365093651936529365393654936559365693657936589365993660936619366293663936649366593666936679366893669936709367193672936739367493675936769367793678936799368093681936829368393684936859368693687936889368993690936919369293693936949369593696936979369893699937009370193702937039370493705937069370793708937099371093711937129371393714937159371693717937189371993720937219372293723937249372593726937279372893729937309373193732937339373493735937369373793738937399374093741937429374393744937459374693747937489374993750937519375293753937549375593756937579375893759937609376193762937639376493765937669376793768937699377093771937729377393774937759377693777937789377993780937819378293783937849378593786937879378893789937909379193792937939379493795937969379793798937999380093801938029380393804938059380693807938089380993810938119381293813938149381593816938179381893819938209382193822938239382493825938269382793828938299383093831938329383393834938359383693837938389383993840938419384293843938449384593846938479384893849938509385193852938539385493855938569385793858938599386093861938629386393864938659386693867938689386993870938719387293873938749387593876938779387893879938809388193882938839388493885938869388793888938899389093891938929389393894938959389693897938989389993900939019390293903939049390593906939079390893909939109391193912939139391493915939169391793918939199392093921939229392393924939259392693927939289392993930939319393293933939349393593936939379393893939939409394193942939439394493945939469394793948939499395093951939529395393954939559395693957939589395993960939619396293963939649396593966939679396893969939709397193972939739397493975939769397793978939799398093981939829398393984939859398693987939889398993990939919399293993939949399593996939979399893999940009400194002940039400494005940069400794008940099401094011940129401394014940159401694017940189401994020940219402294023940249402594026940279402894029940309403194032940339403494035940369403794038940399404094041940429404394044940459404694047940489404994050940519405294053940549405594056940579405894059940609406194062940639406494065940669406794068940699407094071940729407394074940759407694077940789407994080940819408294083940849408594086940879408894089940909409194092940939409494095940969409794098940999410094101941029410394104941059410694107941089410994110941119411294113941149411594116941179411894119941209412194122941239412494125941269412794128941299413094131941329413394134941359413694137941389413994140941419414294143941449414594146941479414894149941509415194152941539415494155941569415794158941599416094161941629416394164941659416694167941689416994170941719417294173941749417594176941779417894179941809418194182941839418494185941869418794188941899419094191941929419394194941959419694197941989419994200942019420294203942049420594206942079420894209942109421194212942139421494215942169421794218942199422094221942229422394224942259422694227942289422994230942319423294233942349423594236942379423894239942409424194242942439424494245942469424794248942499425094251942529425394254942559425694257942589425994260942619426294263942649426594266942679426894269942709427194272942739427494275942769427794278942799428094281942829428394284942859428694287942889428994290942919429294293942949429594296942979429894299943009430194302943039430494305943069430794308943099431094311943129431394314943159431694317943189431994320943219432294323943249432594326943279432894329943309433194332943339433494335943369433794338943399434094341943429434394344943459434694347943489434994350943519435294353943549435594356943579435894359943609436194362943639436494365943669436794368943699437094371943729437394374943759437694377943789437994380943819438294383943849438594386943879438894389943909439194392943939439494395943969439794398943999440094401944029440394404944059440694407944089440994410944119441294413944149441594416944179441894419944209442194422944239442494425944269442794428944299443094431944329443394434944359443694437944389443994440944419444294443944449444594446944479444894449944509445194452944539445494455944569445794458944599446094461944629446394464944659446694467944689446994470944719447294473944749447594476944779447894479944809448194482944839448494485944869448794488944899449094491944929449394494944959449694497944989449994500945019450294503945049450594506945079450894509945109451194512945139451494515945169451794518945199452094521945229452394524945259452694527945289452994530945319453294533945349453594536945379453894539945409454194542945439454494545945469454794548945499455094551945529455394554945559455694557945589455994560945619456294563945649456594566945679456894569945709457194572945739457494575945769457794578945799458094581945829458394584945859458694587945889458994590945919459294593945949459594596945979459894599946009460194602946039460494605946069460794608946099461094611946129461394614946159461694617946189461994620946219462294623946249462594626946279462894629946309463194632946339463494635946369463794638946399464094641946429464394644946459464694647946489464994650946519465294653946549465594656946579465894659946609466194662946639466494665946669466794668946699467094671946729467394674946759467694677946789467994680946819468294683946849468594686946879468894689946909469194692946939469494695946969469794698946999470094701947029470394704947059470694707947089470994710947119471294713947149471594716947179471894719947209472194722947239472494725947269472794728947299473094731947329473394734947359473694737947389473994740947419474294743947449474594746947479474894749947509475194752947539475494755947569475794758947599476094761947629476394764947659476694767947689476994770947719477294773947749477594776947779477894779947809478194782947839478494785947869478794788947899479094791947929479394794947959479694797947989479994800948019480294803948049480594806948079480894809948109481194812948139481494815948169481794818948199482094821948229482394824948259482694827948289482994830948319483294833948349483594836948379483894839948409484194842948439484494845948469484794848948499485094851948529485394854948559485694857948589485994860948619486294863948649486594866948679486894869948709487194872948739487494875948769487794878948799488094881948829488394884948859488694887948889488994890948919489294893948949489594896948979489894899949009490194902949039490494905949069490794908949099491094911949129491394914949159491694917949189491994920949219492294923949249492594926949279492894929949309493194932949339493494935949369493794938949399494094941949429494394944949459494694947949489494994950949519495294953949549495594956949579495894959949609496194962949639496494965949669496794968949699497094971949729497394974949759497694977949789497994980949819498294983949849498594986949879498894989949909499194992949939499494995949969499794998949999500095001950029500395004950059500695007950089500995010950119501295013950149501595016950179501895019950209502195022950239502495025950269502795028950299503095031950329503395034950359503695037950389503995040950419504295043950449504595046950479504895049950509505195052950539505495055950569505795058950599506095061950629506395064950659506695067950689506995070950719507295073950749507595076950779507895079950809508195082950839508495085950869508795088950899509095091950929509395094950959509695097950989509995100951019510295103951049510595106951079510895109951109511195112951139511495115951169511795118951199512095121951229512395124951259512695127951289512995130951319513295133951349513595136951379513895139951409514195142951439514495145951469514795148951499515095151951529515395154951559515695157951589515995160951619516295163951649516595166951679516895169951709517195172951739517495175951769517795178951799518095181951829518395184951859518695187951889518995190951919519295193951949519595196951979519895199952009520195202952039520495205952069520795208952099521095211952129521395214952159521695217952189521995220952219522295223952249522595226952279522895229952309523195232952339523495235952369523795238952399524095241952429524395244952459524695247952489524995250952519525295253952549525595256952579525895259952609526195262952639526495265952669526795268952699527095271952729527395274952759527695277952789527995280952819528295283952849528595286952879528895289952909529195292952939529495295952969529795298952999530095301953029530395304953059530695307953089530995310953119531295313953149531595316953179531895319953209532195322953239532495325953269532795328953299533095331953329533395334953359533695337953389533995340953419534295343953449534595346953479534895349953509535195352953539535495355953569535795358953599536095361953629536395364953659536695367953689536995370953719537295373953749537595376953779537895379953809538195382953839538495385953869538795388953899539095391953929539395394953959539695397953989539995400954019540295403954049540595406954079540895409954109541195412954139541495415954169541795418954199542095421954229542395424954259542695427954289542995430954319543295433954349543595436954379543895439954409544195442954439544495445954469544795448954499545095451954529545395454954559545695457954589545995460954619546295463954649546595466954679546895469954709547195472954739547495475954769547795478954799548095481954829548395484954859548695487954889548995490954919549295493954949549595496954979549895499955009550195502955039550495505955069550795508955099551095511955129551395514955159551695517955189551995520955219552295523955249552595526955279552895529955309553195532955339553495535955369553795538955399554095541955429554395544955459554695547955489554995550955519555295553955549555595556955579555895559955609556195562955639556495565955669556795568955699557095571955729557395574955759557695577955789557995580955819558295583955849558595586955879558895589955909559195592955939559495595955969559795598955999560095601956029560395604956059560695607956089560995610956119561295613956149561595616956179561895619956209562195622956239562495625956269562795628956299563095631956329563395634956359563695637956389563995640956419564295643956449564595646956479564895649956509565195652956539565495655956569565795658956599566095661956629566395664956659566695667956689566995670956719567295673956749567595676956779567895679956809568195682956839568495685956869568795688956899569095691956929569395694956959569695697956989569995700957019570295703957049570595706957079570895709957109571195712957139571495715957169571795718957199572095721957229572395724957259572695727957289572995730957319573295733957349573595736957379573895739957409574195742957439574495745957469574795748957499575095751957529575395754957559575695757957589575995760957619576295763957649576595766957679576895769957709577195772957739577495775957769577795778957799578095781957829578395784957859578695787957889578995790957919579295793957949579595796957979579895799958009580195802958039580495805958069580795808958099581095811958129581395814958159581695817958189581995820958219582295823958249582595826958279582895829958309583195832958339583495835958369583795838958399584095841958429584395844958459584695847958489584995850958519585295853958549585595856958579585895859958609586195862958639586495865958669586795868958699587095871958729587395874958759587695877958789587995880958819588295883958849588595886958879588895889958909589195892958939589495895958969589795898958999590095901959029590395904959059590695907959089590995910959119591295913959149591595916959179591895919959209592195922959239592495925959269592795928959299593095931959329593395934959359593695937959389593995940959419594295943959449594595946959479594895949959509595195952959539595495955959569595795958959599596095961959629596395964959659596695967959689596995970959719597295973959749597595976959779597895979959809598195982959839598495985959869598795988959899599095991959929599395994959959599695997959989599996000960019600296003960049600596006960079600896009960109601196012960139601496015960169601796018960199602096021960229602396024960259602696027960289602996030960319603296033960349603596036960379603896039960409604196042960439604496045960469604796048960499605096051960529605396054960559605696057960589605996060960619606296063960649606596066960679606896069960709607196072960739607496075960769607796078960799608096081960829608396084960859608696087960889608996090960919609296093960949609596096960979609896099961009610196102961039610496105961069610796108961099611096111961129611396114961159611696117961189611996120961219612296123961249612596126961279612896129961309613196132961339613496135961369613796138961399614096141961429614396144961459614696147961489614996150961519615296153961549615596156961579615896159961609616196162961639616496165961669616796168961699617096171961729617396174961759617696177961789617996180961819618296183961849618596186961879618896189961909619196192961939619496195961969619796198961999620096201962029620396204962059620696207962089620996210962119621296213962149621596216962179621896219962209622196222962239622496225962269622796228962299623096231962329623396234962359623696237962389623996240962419624296243962449624596246962479624896249962509625196252962539625496255962569625796258962599626096261962629626396264962659626696267962689626996270962719627296273962749627596276962779627896279962809628196282962839628496285962869628796288962899629096291962929629396294962959629696297962989629996300963019630296303963049630596306963079630896309963109631196312963139631496315963169631796318963199632096321963229632396324963259632696327963289632996330963319633296333963349633596336963379633896339963409634196342963439634496345963469634796348963499635096351963529635396354963559635696357963589635996360963619636296363963649636596366963679636896369963709637196372963739637496375963769637796378963799638096381963829638396384963859638696387963889638996390963919639296393963949639596396963979639896399964009640196402964039640496405964069640796408964099641096411964129641396414964159641696417964189641996420964219642296423964249642596426964279642896429964309643196432964339643496435964369643796438964399644096441964429644396444964459644696447964489644996450964519645296453964549645596456964579645896459964609646196462964639646496465964669646796468964699647096471964729647396474964759647696477964789647996480964819648296483964849648596486964879648896489964909649196492964939649496495964969649796498964999650096501965029650396504965059650696507965089650996510965119651296513965149651596516965179651896519965209652196522965239652496525965269652796528965299653096531965329653396534965359653696537965389653996540965419654296543965449654596546965479654896549965509655196552965539655496555965569655796558965599656096561965629656396564965659656696567965689656996570965719657296573965749657596576965779657896579965809658196582965839658496585965869658796588965899659096591965929659396594965959659696597965989659996600966019660296603966049660596606966079660896609966109661196612966139661496615966169661796618966199662096621966229662396624966259662696627966289662996630966319663296633966349663596636966379663896639966409664196642966439664496645966469664796648966499665096651966529665396654966559665696657966589665996660966619666296663966649666596666966679666896669966709667196672966739667496675966769667796678966799668096681966829668396684966859668696687966889668996690966919669296693966949669596696966979669896699967009670196702967039670496705967069670796708967099671096711967129671396714967159671696717967189671996720967219672296723967249672596726967279672896729967309673196732967339673496735967369673796738967399674096741967429674396744967459674696747967489674996750967519675296753967549675596756967579675896759967609676196762967639676496765967669676796768967699677096771967729677396774967759677696777967789677996780967819678296783967849678596786967879678896789967909679196792967939679496795967969679796798967999680096801968029680396804968059680696807968089680996810968119681296813968149681596816968179681896819968209682196822968239682496825968269682796828968299683096831968329683396834968359683696837968389683996840968419684296843968449684596846968479684896849968509685196852968539685496855968569685796858968599686096861968629686396864968659686696867968689686996870968719687296873968749687596876968779687896879968809688196882968839688496885968869688796888968899689096891968929689396894968959689696897968989689996900969019690296903969049690596906969079690896909969109691196912969139691496915969169691796918969199692096921969229692396924969259692696927969289692996930969319693296933969349693596936969379693896939969409694196942969439694496945969469694796948969499695096951969529695396954969559695696957969589695996960969619696296963969649696596966969679696896969969709697196972969739697496975969769697796978969799698096981969829698396984969859698696987969889698996990969919699296993969949699596996969979699896999970009700197002970039700497005970069700797008970099701097011970129701397014970159701697017970189701997020970219702297023970249702597026970279702897029970309703197032970339703497035970369703797038970399704097041970429704397044970459704697047970489704997050970519705297053970549705597056970579705897059970609706197062970639706497065970669706797068970699707097071970729707397074970759707697077970789707997080970819708297083970849708597086970879708897089970909709197092970939709497095970969709797098970999710097101971029710397104971059710697107971089710997110971119711297113971149711597116971179711897119971209712197122971239712497125971269712797128971299713097131971329713397134971359713697137971389713997140971419714297143971449714597146971479714897149971509715197152971539715497155971569715797158971599716097161971629716397164971659716697167971689716997170971719717297173971749717597176971779717897179971809718197182971839718497185971869718797188971899719097191971929719397194971959719697197971989719997200972019720297203972049720597206972079720897209972109721197212972139721497215972169721797218972199722097221972229722397224972259722697227972289722997230972319723297233972349723597236972379723897239972409724197242972439724497245972469724797248972499725097251972529725397254972559725697257972589725997260972619726297263972649726597266972679726897269972709727197272972739727497275972769727797278972799728097281972829728397284972859728697287972889728997290972919729297293972949729597296972979729897299973009730197302973039730497305973069730797308973099731097311973129731397314973159731697317973189731997320973219732297323973249732597326973279732897329973309733197332973339733497335973369733797338973399734097341973429734397344973459734697347973489734997350973519735297353973549735597356973579735897359973609736197362973639736497365973669736797368973699737097371973729737397374973759737697377973789737997380973819738297383973849738597386973879738897389973909739197392973939739497395973969739797398973999740097401974029740397404974059740697407974089740997410974119741297413974149741597416974179741897419974209742197422974239742497425974269742797428974299743097431974329743397434974359743697437974389743997440974419744297443974449744597446974479744897449974509745197452974539745497455974569745797458974599746097461974629746397464974659746697467974689746997470974719747297473974749747597476974779747897479974809748197482974839748497485974869748797488974899749097491974929749397494974959749697497974989749997500975019750297503975049750597506975079750897509975109751197512975139751497515975169751797518975199752097521975229752397524975259752697527975289752997530975319753297533975349753597536975379753897539975409754197542975439754497545975469754797548975499755097551975529755397554975559755697557975589755997560975619756297563975649756597566975679756897569975709757197572975739757497575975769757797578975799758097581975829758397584975859758697587975889758997590975919759297593975949759597596975979759897599976009760197602976039760497605976069760797608976099761097611976129761397614976159761697617976189761997620976219762297623976249762597626976279762897629976309763197632976339763497635976369763797638976399764097641976429764397644976459764697647976489764997650976519765297653976549765597656976579765897659976609766197662976639766497665976669766797668976699767097671976729767397674976759767697677976789767997680976819768297683976849768597686976879768897689976909769197692976939769497695976969769797698976999770097701977029770397704977059770697707977089770997710977119771297713977149771597716977179771897719977209772197722977239772497725977269772797728977299773097731977329773397734977359773697737977389773997740977419774297743977449774597746977479774897749977509775197752977539775497755977569775797758977599776097761977629776397764977659776697767977689776997770977719777297773977749777597776977779777897779977809778197782977839778497785977869778797788977899779097791977929779397794977959779697797977989779997800978019780297803978049780597806978079780897809978109781197812978139781497815978169781797818978199782097821978229782397824978259782697827978289782997830978319783297833978349783597836978379783897839978409784197842978439784497845978469784797848978499785097851978529785397854978559785697857978589785997860978619786297863978649786597866978679786897869978709787197872978739787497875978769787797878978799788097881978829788397884978859788697887978889788997890978919789297893978949789597896978979789897899979009790197902979039790497905979069790797908979099791097911979129791397914979159791697917979189791997920979219792297923979249792597926979279792897929979309793197932979339793497935979369793797938979399794097941979429794397944979459794697947979489794997950979519795297953979549795597956979579795897959979609796197962979639796497965979669796797968979699797097971979729797397974979759797697977979789797997980979819798297983979849798597986979879798897989979909799197992979939799497995979969799797998979999800098001980029800398004980059800698007980089800998010980119801298013980149801598016980179801898019980209802198022980239802498025980269802798028980299803098031980329803398034980359803698037980389803998040980419804298043980449804598046980479804898049980509805198052980539805498055980569805798058980599806098061980629806398064980659806698067980689806998070980719807298073980749807598076980779807898079980809808198082980839808498085980869808798088980899809098091980929809398094980959809698097980989809998100981019810298103981049810598106981079810898109981109811198112981139811498115981169811798118981199812098121981229812398124981259812698127981289812998130981319813298133981349813598136981379813898139981409814198142981439814498145981469814798148981499815098151981529815398154981559815698157981589815998160981619816298163981649816598166981679816898169981709817198172981739817498175981769817798178981799818098181981829818398184981859818698187981889818998190981919819298193981949819598196981979819898199982009820198202982039820498205982069820798208982099821098211982129821398214982159821698217982189821998220982219822298223982249822598226982279822898229982309823198232982339823498235982369823798238982399824098241982429824398244982459824698247982489824998250982519825298253982549825598256982579825898259982609826198262982639826498265982669826798268982699827098271982729827398274982759827698277982789827998280982819828298283982849828598286982879828898289982909829198292982939829498295982969829798298982999830098301983029830398304983059830698307983089830998310983119831298313983149831598316983179831898319983209832198322983239832498325983269832798328983299833098331983329833398334983359833698337983389833998340983419834298343983449834598346983479834898349983509835198352983539835498355983569835798358983599836098361983629836398364983659836698367983689836998370983719837298373983749837598376983779837898379983809838198382983839838498385983869838798388983899839098391983929839398394983959839698397983989839998400984019840298403984049840598406984079840898409984109841198412984139841498415984169841798418984199842098421984229842398424984259842698427984289842998430984319843298433984349843598436984379843898439984409844198442984439844498445984469844798448984499845098451984529845398454984559845698457984589845998460984619846298463984649846598466984679846898469984709847198472984739847498475984769847798478984799848098481984829848398484984859848698487984889848998490984919849298493984949849598496984979849898499985009850198502985039850498505985069850798508985099851098511985129851398514985159851698517985189851998520985219852298523985249852598526985279852898529985309853198532985339853498535985369853798538985399854098541985429854398544985459854698547985489854998550985519855298553985549855598556985579855898559985609856198562985639856498565985669856798568985699857098571985729857398574985759857698577985789857998580985819858298583985849858598586985879858898589985909859198592985939859498595985969859798598985999860098601986029860398604986059860698607986089860998610986119861298613986149861598616986179861898619986209862198622986239862498625986269862798628986299863098631986329863398634986359863698637986389863998640986419864298643986449864598646986479864898649986509865198652986539865498655986569865798658986599866098661986629866398664986659866698667986689866998670986719867298673986749867598676986779867898679986809868198682986839868498685986869868798688986899869098691986929869398694986959869698697986989869998700987019870298703987049870598706987079870898709987109871198712987139871498715987169871798718987199872098721987229872398724987259872698727987289872998730987319873298733987349873598736987379873898739987409874198742987439874498745987469874798748987499875098751987529875398754987559875698757987589875998760987619876298763987649876598766987679876898769987709877198772987739877498775987769877798778987799878098781987829878398784987859878698787987889878998790987919879298793987949879598796987979879898799988009880198802988039880498805988069880798808988099881098811988129881398814988159881698817988189881998820988219882298823988249882598826988279882898829988309883198832988339883498835988369883798838988399884098841988429884398844988459884698847988489884998850988519885298853988549885598856988579885898859988609886198862988639886498865988669886798868988699887098871988729887398874988759887698877988789887998880988819888298883988849888598886988879888898889988909889198892988939889498895988969889798898988999890098901989029890398904989059890698907989089890998910989119891298913989149891598916989179891898919989209892198922989239892498925989269892798928989299893098931989329893398934989359893698937989389893998940989419894298943989449894598946989479894898949989509895198952989539895498955989569895798958989599896098961989629896398964989659896698967989689896998970989719897298973989749897598976989779897898979989809898198982989839898498985989869898798988989899899098991989929899398994989959899698997989989899999000990019900299003990049900599006990079900899009990109901199012990139901499015990169901799018990199902099021990229902399024990259902699027990289902999030990319903299033990349903599036990379903899039990409904199042990439904499045990469904799048990499905099051990529905399054990559905699057990589905999060990619906299063990649906599066990679906899069990709907199072990739907499075990769907799078990799908099081990829908399084990859908699087990889908999090990919909299093990949909599096990979909899099991009910199102991039910499105991069910799108991099911099111991129911399114991159911699117991189911999120991219912299123991249912599126991279912899129991309913199132991339913499135991369913799138991399914099141991429914399144991459914699147991489914999150991519915299153991549915599156991579915899159991609916199162991639916499165991669916799168991699917099171991729917399174991759917699177991789917999180991819918299183991849918599186991879918899189991909919199192991939919499195991969919799198991999920099201992029920399204992059920699207992089920999210992119921299213992149921599216992179921899219992209922199222992239922499225992269922799228992299923099231992329923399234992359923699237992389923999240992419924299243992449924599246992479924899249992509925199252992539925499255992569925799258992599926099261992629926399264992659926699267992689926999270992719927299273992749927599276992779927899279992809928199282992839928499285992869928799288992899929099291992929929399294992959929699297992989929999300993019930299303993049930599306993079930899309993109931199312993139931499315993169931799318993199932099321993229932399324993259932699327993289932999330993319933299333993349933599336993379933899339993409934199342993439934499345993469934799348993499935099351993529935399354993559935699357993589935999360993619936299363993649936599366993679936899369993709937199372993739937499375993769937799378993799938099381993829938399384993859938699387993889938999390993919939299393993949939599396993979939899399994009940199402994039940499405994069940799408994099941099411994129941399414994159941699417994189941999420994219942299423994249942599426994279942899429994309943199432994339943499435994369943799438994399944099441994429944399444994459944699447994489944999450994519945299453994549945599456994579945899459994609946199462994639946499465994669946799468994699947099471994729947399474994759947699477994789947999480994819948299483994849948599486994879948899489994909949199492994939949499495994969949799498994999950099501995029950399504995059950699507995089950999510995119951299513995149951599516995179951899519995209952199522995239952499525995269952799528995299953099531995329953399534995359953699537995389953999540995419954299543995449954599546995479954899549995509955199552995539955499555995569955799558995599956099561995629956399564995659956699567995689956999570995719957299573995749957599576995779957899579995809958199582995839958499585995869958799588995899959099591995929959399594995959959699597995989959999600996019960299603996049960599606996079960899609996109961199612996139961499615996169961799618996199962099621996229962399624996259962699627996289962999630996319963299633996349963599636996379963899639996409964199642996439964499645996469964799648996499965099651996529965399654996559965699657996589965999660996619966299663996649966599666996679966899669996709967199672996739967499675996769967799678996799968099681996829968399684996859968699687996889968999690996919969299693996949969599696996979969899699997009970199702997039970499705997069970799708997099971099711997129971399714997159971699717997189971999720997219972299723997249972599726997279972899729997309973199732997339973499735997369973799738997399974099741997429974399744997459974699747997489974999750997519975299753997549975599756997579975899759997609976199762997639976499765997669976799768997699977099771997729977399774997759977699777997789977999780997819978299783997849978599786997879978899789997909979199792997939979499795997969979799798997999980099801998029980399804998059980699807998089980999810998119981299813998149981599816998179981899819998209982199822998239982499825998269982799828998299983099831998329983399834998359983699837998389983999840998419984299843998449984599846998479984899849998509985199852998539985499855998569985799858998599986099861998629986399864998659986699867998689986999870998719987299873998749987599876998779987899879998809988199882998839988499885998869988799888998899989099891998929989399894998959989699897998989989999900999019990299903999049990599906999079990899909999109991199912999139991499915999169991799918999199992099921999229992399924999259992699927999289992999930999319993299933999349993599936999379993899939999409994199942999439994499945999469994799948999499995099951999529995399954999559995699957999589995999960999619996299963999649996599966999679996899969999709997199972999739997499975999769997799978999799998099981999829998399984999859998699987999889998999990999919999299993999949999599996999979999899999100000100001100002100003100004100005100006100007100008100009100010100011100012100013100014100015100016100017100018100019100020100021100022100023100024100025100026100027100028100029100030100031100032100033100034100035100036100037100038100039100040100041100042100043100044100045100046100047100048100049100050100051100052100053100054100055100056100057100058100059100060100061100062100063100064100065100066100067100068100069100070100071100072100073100074100075100076100077100078100079100080100081100082100083100084100085100086100087100088100089100090100091100092100093100094100095100096100097100098100099100100100101100102100103100104100105100106100107100108100109100110100111100112100113100114100115100116100117100118100119100120100121100122100123100124100125100126100127100128100129100130100131100132100133100134100135100136100137100138100139100140100141100142100143100144100145100146100147100148100149100150100151100152100153100154100155100156100157100158100159100160100161100162100163100164100165100166100167100168100169100170100171100172100173100174100175100176100177100178100179100180100181100182100183100184100185100186100187100188100189100190100191100192100193100194100195100196100197100198100199100200100201100202100203100204100205100206100207100208100209100210100211100212100213100214100215100216100217100218100219100220100221100222100223100224100225100226100227100228100229100230100231100232100233100234100235100236100237100238100239100240100241100242100243100244100245100246100247100248100249100250100251100252100253100254100255100256100257100258100259100260100261100262100263100264100265100266100267100268100269100270100271100272100273100274100275100276100277100278100279100280100281100282100283100284100285100286100287100288100289100290100291100292100293100294100295100296100297100298100299100300100301100302100303100304100305100306100307100308100309100310100311100312100313100314100315100316100317100318100319100320100321100322100323100324100325100326100327100328100329100330100331100332100333100334100335100336100337100338100339100340100341100342100343100344100345100346100347100348100349100350100351100352100353100354100355100356100357100358100359100360100361100362100363100364100365100366100367100368100369100370100371100372100373100374100375100376100377100378100379100380100381100382100383100384100385100386100387100388100389100390100391100392100393100394100395100396100397100398100399100400100401100402100403100404100405100406100407100408100409100410100411100412100413100414100415100416100417100418100419100420100421100422100423100424100425100426100427100428100429100430100431100432100433100434100435100436100437100438100439100440100441100442100443100444100445100446100447100448100449100450100451100452100453100454100455100456100457100458100459100460100461100462100463100464100465100466100467100468100469100470100471100472100473100474100475100476100477100478100479100480100481100482100483100484100485100486100487100488100489100490100491100492100493100494100495100496100497100498100499100500100501100502100503100504100505100506100507100508100509100510100511100512100513100514100515100516100517100518100519100520100521100522100523100524100525100526100527100528100529100530100531100532100533100534100535100536100537100538100539100540100541100542100543100544100545100546100547100548100549100550100551100552100553100554100555100556100557100558100559100560100561100562100563100564100565100566100567100568100569100570100571100572100573100574100575100576100577100578100579100580100581100582100583100584100585100586100587100588100589100590100591100592100593100594100595100596100597100598100599100600100601100602100603100604100605100606100607100608100609100610100611100612100613100614100615100616100617100618100619100620100621100622100623100624100625100626100627100628100629100630100631100632100633100634100635100636100637100638100639100640100641100642100643100644100645100646100647100648100649100650100651100652100653100654100655100656100657100658100659100660100661100662100663100664100665100666100667100668100669100670100671100672100673100674100675100676100677100678100679100680100681100682100683100684100685100686100687100688100689100690100691100692100693100694100695100696100697100698100699100700100701100702100703100704100705100706100707100708100709100710100711100712100713100714100715100716100717100718100719100720100721100722100723100724100725100726100727100728100729100730100731100732100733100734100735100736100737100738100739100740100741100742100743100744100745100746100747100748100749100750100751100752100753100754100755100756100757100758100759100760100761100762100763100764100765100766100767100768100769100770100771100772100773100774100775100776100777100778100779100780100781100782100783100784100785100786100787100788100789100790100791100792100793100794100795100796100797100798100799100800100801100802100803100804100805100806100807100808100809100810100811100812100813100814100815100816100817100818100819100820100821100822100823100824100825100826100827100828100829100830100831100832100833100834100835100836100837100838100839100840100841100842100843100844100845100846100847100848100849100850100851100852100853100854100855100856100857100858100859100860100861100862100863100864100865100866100867100868100869100870100871100872100873100874100875100876100877100878100879100880100881100882100883100884100885100886100887100888100889100890100891100892100893100894100895100896100897100898100899100900100901100902100903100904100905100906100907100908100909100910100911100912100913100914100915100916100917100918100919100920100921100922100923100924100925100926100927100928100929100930100931100932100933100934100935100936100937100938100939100940100941100942100943100944100945100946100947100948100949100950100951100952100953100954100955100956100957100958100959100960100961100962100963100964100965100966100967100968100969100970100971100972100973100974100975100976100977100978100979100980100981100982100983100984100985100986100987100988100989100990100991100992100993100994100995100996100997100998100999101000101001101002101003101004101005101006101007101008101009101010101011101012101013101014101015101016101017101018101019101020101021101022101023101024101025101026101027101028101029101030101031101032101033101034101035101036101037101038101039101040101041101042101043101044101045101046101047101048101049101050101051101052101053101054101055101056101057101058101059101060101061101062101063101064101065101066101067101068101069101070101071101072101073101074101075101076101077101078101079101080101081101082101083101084101085101086101087101088101089101090101091101092101093101094101095101096101097101098101099101100101101101102101103101104101105101106101107101108101109101110101111101112101113101114101115101116101117101118101119101120101121101122101123101124101125101126101127101128101129101130101131101132101133101134101135101136101137101138101139101140101141101142101143101144101145101146101147101148101149101150101151101152101153101154101155101156101157101158101159101160101161101162101163101164101165101166101167101168101169101170101171101172101173101174101175101176101177101178101179101180101181101182101183101184101185101186101187101188101189101190101191101192101193101194101195101196101197101198101199101200101201101202101203101204101205101206101207101208101209101210101211101212101213101214101215101216101217101218101219101220101221101222101223101224101225101226101227101228101229101230101231101232101233101234101235101236101237101238101239101240101241101242101243101244101245101246101247101248101249101250101251101252101253101254101255101256101257101258101259101260101261101262101263101264101265101266101267101268101269101270101271101272101273101274101275101276101277101278101279101280101281101282101283101284101285101286101287101288101289101290101291101292101293101294101295101296101297101298101299101300101301101302101303101304101305101306101307101308101309101310101311101312101313101314101315101316101317101318101319101320101321101322101323101324101325101326101327101328101329101330101331101332101333101334101335101336101337101338101339101340101341101342101343101344101345101346101347101348101349101350101351101352101353101354101355101356101357101358101359101360101361101362101363101364101365101366101367101368101369101370101371101372101373101374101375101376101377101378101379101380101381101382101383101384101385101386101387101388101389101390101391101392101393101394101395101396101397101398101399101400101401101402101403101404101405101406101407101408101409101410101411101412101413101414101415101416101417101418101419101420101421101422101423101424101425101426101427101428101429101430101431101432101433101434101435101436101437101438101439101440101441101442101443101444101445101446101447101448101449101450101451101452101453101454101455101456101457101458101459101460101461101462101463101464101465101466101467101468101469101470101471101472101473101474101475101476101477101478101479101480101481101482101483101484101485101486101487101488101489101490101491101492101493101494101495101496101497101498101499101500101501101502101503101504101505101506101507101508101509101510101511101512101513101514101515101516101517101518101519101520101521101522101523101524101525101526101527101528101529101530101531101532101533101534101535101536101537101538101539101540101541101542101543101544101545101546101547101548101549101550101551101552101553101554101555101556101557101558101559101560101561101562101563101564101565101566101567101568101569101570101571101572101573101574101575101576101577101578101579101580101581101582101583101584101585101586101587101588101589101590101591101592101593101594101595101596101597101598101599101600101601101602101603101604101605101606101607101608101609101610101611101612101613101614101615101616101617101618101619101620101621101622101623101624101625101626101627101628101629101630101631101632101633101634101635101636101637101638101639101640101641101642101643101644101645101646101647101648101649101650101651101652101653101654101655101656101657101658101659101660101661101662101663101664101665101666101667101668101669101670101671101672101673101674101675101676101677101678101679101680101681101682101683101684101685101686101687101688101689101690101691101692101693101694101695101696101697101698101699101700101701101702101703101704101705101706101707101708101709101710101711101712101713101714101715101716101717101718101719101720101721101722101723101724101725101726101727101728101729101730101731101732101733101734101735101736101737101738101739101740101741101742101743101744101745101746101747101748101749101750101751101752101753101754101755101756101757101758101759101760101761101762101763101764101765101766101767101768101769101770101771101772101773101774101775101776101777101778101779101780101781101782101783101784101785101786101787101788101789101790101791101792101793101794101795101796101797101798101799101800101801101802101803101804101805101806101807101808101809101810101811101812101813101814101815101816101817101818101819101820101821101822101823101824101825101826101827101828101829101830101831101832101833101834101835101836101837101838101839101840101841101842101843101844101845101846101847101848101849101850101851101852101853101854101855101856101857101858101859101860101861101862101863101864101865101866101867101868101869101870101871101872101873101874101875101876101877101878101879101880101881101882101883101884101885101886101887101888101889101890101891101892101893101894101895101896101897101898101899101900101901101902101903101904101905101906101907101908101909101910101911101912101913101914101915101916101917101918101919101920101921101922101923101924101925101926101927101928101929101930101931101932101933101934101935101936101937101938101939101940101941101942101943101944101945101946101947101948101949101950101951101952101953101954101955101956101957101958101959101960101961101962101963101964101965101966101967101968101969101970101971101972101973101974101975101976101977101978101979101980101981101982101983101984101985101986101987101988101989101990101991101992101993101994101995101996101997101998101999102000102001102002102003102004102005102006102007102008102009102010102011102012102013102014102015102016102017102018102019102020102021102022102023102024102025102026102027102028102029102030102031102032102033102034102035102036102037102038102039102040102041102042102043102044102045102046102047102048102049102050102051102052102053102054102055102056102057102058102059102060102061102062102063102064102065102066102067102068102069102070102071102072102073102074102075102076102077102078102079102080102081102082102083102084102085102086102087102088102089102090102091102092102093102094102095102096102097102098102099102100102101102102102103102104102105102106102107102108102109102110102111102112102113102114102115102116102117102118102119102120102121102122102123102124102125102126102127102128102129102130102131102132102133102134102135102136102137102138102139102140102141102142102143102144102145102146102147102148102149102150102151102152102153102154102155102156102157102158102159102160102161102162102163102164102165102166102167102168102169102170102171102172102173102174102175102176102177102178102179102180102181102182102183102184102185102186102187102188102189102190102191102192102193102194102195102196102197102198102199102200102201102202102203102204102205102206102207102208102209102210102211102212102213102214102215102216102217102218102219102220102221102222102223102224102225102226102227102228102229102230102231102232102233102234102235102236102237102238102239102240102241102242102243102244102245102246102247102248102249102250102251102252102253102254102255102256102257102258102259102260102261102262102263102264102265102266102267102268102269102270102271102272102273102274102275102276102277102278102279102280102281102282102283102284102285102286102287102288102289102290102291102292102293102294102295102296102297102298102299102300102301102302102303102304102305102306102307102308102309102310102311102312102313102314102315102316102317102318102319102320102321102322102323102324102325102326102327102328102329102330102331102332102333102334102335102336102337102338102339102340102341102342102343102344102345102346102347102348102349102350102351102352102353102354102355102356102357102358102359102360102361102362102363102364102365102366102367102368102369102370102371102372102373102374102375102376102377102378102379102380102381102382102383102384102385102386102387102388102389102390102391102392102393102394102395102396102397102398102399102400102401102402102403102404102405102406102407102408102409102410102411102412102413102414102415102416102417102418102419102420102421102422102423102424102425102426102427102428102429102430102431102432102433102434102435102436102437102438102439102440102441102442102443102444102445102446102447102448102449102450102451102452102453102454102455102456102457102458102459102460102461102462102463102464102465102466102467102468102469102470102471102472102473102474102475102476102477102478102479102480102481102482102483102484102485102486102487102488102489102490102491102492102493102494102495102496102497102498102499102500102501102502102503102504102505102506102507102508102509102510102511102512102513102514102515102516102517102518102519102520102521102522102523102524102525102526102527102528102529102530102531102532102533102534102535102536102537102538102539102540102541102542102543102544102545102546102547102548102549102550102551102552102553102554102555102556102557102558102559102560102561102562102563102564102565102566102567102568102569102570102571102572102573102574102575102576102577102578102579102580102581102582102583102584102585102586102587102588102589102590102591102592102593102594102595102596102597102598102599102600102601102602102603102604102605102606102607102608102609102610102611102612102613102614102615102616102617102618102619102620102621102622102623102624102625102626102627102628102629102630102631102632102633102634102635102636102637102638102639102640102641102642102643102644102645102646102647102648102649102650102651102652102653102654102655102656102657102658102659102660102661102662102663102664102665102666102667102668102669102670102671102672102673102674102675102676102677102678102679102680102681102682102683102684102685102686102687102688102689102690102691102692102693102694102695102696102697102698102699102700102701102702102703102704102705102706102707102708102709102710102711102712102713102714102715102716102717102718102719102720102721102722102723102724102725102726102727102728102729102730102731102732102733102734102735102736102737102738102739102740102741102742102743102744102745102746102747102748102749102750102751102752102753102754102755102756102757102758102759102760102761102762102763102764102765102766102767102768102769102770102771102772102773102774102775102776102777102778102779102780102781102782102783102784102785102786102787102788102789102790102791102792102793102794102795102796102797102798102799102800102801102802102803102804102805102806102807102808102809102810102811102812102813102814102815102816102817102818102819102820102821102822102823102824102825102826102827102828102829102830102831102832102833102834102835102836102837102838102839102840102841102842102843102844102845102846102847102848102849102850102851102852102853102854102855102856102857102858102859102860102861102862102863102864102865102866102867102868102869102870102871102872102873102874102875102876102877102878102879102880102881102882102883102884102885102886102887102888102889102890102891102892102893102894102895102896102897102898102899102900102901102902102903102904102905102906102907102908102909102910102911102912102913102914102915102916102917102918102919102920102921102922102923102924102925102926102927102928102929102930102931102932102933102934102935102936102937102938102939102940102941102942102943102944102945102946102947102948102949102950102951102952102953102954102955102956102957102958102959102960102961102962102963102964102965102966102967102968102969102970102971102972102973102974102975102976102977102978102979102980102981102982102983102984102985102986102987102988102989102990102991102992102993102994102995102996102997102998102999103000103001103002103003103004103005103006103007103008103009103010103011103012103013103014103015103016103017103018103019103020103021103022103023103024103025103026103027103028103029103030103031103032103033103034103035103036103037103038103039103040103041103042103043103044103045103046103047103048103049103050103051103052103053103054103055103056103057103058103059103060103061103062103063103064103065103066103067103068103069103070103071103072103073103074103075103076103077103078103079103080103081103082103083103084103085103086103087103088103089103090103091103092103093103094103095103096103097103098103099103100103101103102103103103104103105103106103107103108103109103110103111103112103113103114103115103116103117103118103119103120103121103122103123103124103125103126103127103128103129103130103131103132103133103134103135103136103137103138103139103140103141103142103143103144103145103146103147103148103149103150103151103152103153103154103155103156103157103158103159103160103161103162103163103164103165103166103167103168103169103170103171103172103173103174103175103176103177103178103179103180103181103182103183103184103185103186103187103188103189103190103191103192103193103194103195103196103197103198103199103200103201103202103203103204103205103206103207103208103209103210103211103212103213103214103215103216103217103218103219103220103221103222103223103224103225103226103227103228103229103230103231103232103233103234103235103236103237103238103239103240103241103242103243103244103245103246103247103248103249103250103251103252103253103254103255103256103257103258103259103260103261103262103263103264103265103266103267103268103269103270103271103272103273103274103275103276103277103278103279103280103281103282103283103284103285103286103287103288103289103290103291103292103293103294103295103296103297103298103299103300103301103302103303103304103305103306103307103308103309103310103311103312103313103314103315103316103317103318103319103320103321103322103323103324103325103326103327103328103329103330103331103332103333103334103335103336103337103338103339103340103341103342103343103344103345103346103347103348103349103350103351103352103353103354103355103356103357103358103359103360103361103362103363103364103365103366103367103368103369103370103371103372103373103374103375103376103377103378103379103380103381103382103383103384103385103386103387103388103389103390103391103392103393103394103395103396103397103398103399103400103401103402103403103404103405103406103407103408103409103410103411103412103413103414103415103416103417103418103419103420103421103422103423103424103425103426103427103428103429103430103431103432103433103434103435103436103437103438103439103440103441103442103443103444103445103446103447103448103449103450103451103452103453103454103455103456103457103458103459103460103461103462103463103464103465103466103467103468103469103470103471103472103473103474103475103476103477103478103479103480103481103482103483103484103485103486103487103488103489103490103491103492103493103494103495103496103497103498103499103500103501103502103503103504103505103506103507103508103509103510103511103512103513103514103515103516103517103518103519103520103521103522103523103524103525103526103527103528103529103530103531103532103533103534103535103536103537103538103539103540103541103542103543103544103545103546103547103548103549103550103551103552103553103554103555103556103557103558103559103560103561103562103563103564103565103566103567103568103569103570103571103572103573103574103575103576103577103578103579103580103581103582103583103584103585103586103587103588103589103590103591103592103593103594103595103596103597103598103599103600103601103602103603103604103605103606103607103608103609103610103611103612103613103614103615103616103617103618103619103620103621103622103623103624103625103626103627103628103629103630103631103632103633103634103635103636103637103638103639103640103641103642103643103644103645103646103647103648103649103650103651103652103653103654103655103656103657103658103659103660103661103662103663103664103665103666103667103668103669103670103671103672103673103674103675103676103677103678103679103680103681103682103683103684103685103686103687103688103689103690103691103692103693103694103695103696103697103698103699103700103701103702103703103704103705103706103707103708103709103710103711103712103713103714103715103716103717103718103719103720103721103722103723103724103725103726103727103728103729103730103731103732103733103734103735103736103737103738103739103740103741103742103743103744103745103746103747103748103749103750103751103752103753103754103755103756103757103758103759103760103761103762103763103764103765103766103767103768103769103770103771103772103773103774103775103776103777103778103779103780103781103782103783103784103785103786103787103788103789103790103791103792103793103794103795103796103797103798103799103800103801103802103803103804103805103806103807103808103809103810103811103812103813103814103815103816103817103818103819103820103821103822103823103824103825103826103827103828103829103830103831103832103833103834103835103836103837103838103839103840103841103842103843103844103845103846103847103848103849103850103851103852103853103854103855103856103857103858103859103860103861103862103863103864103865103866103867103868103869103870103871103872103873103874103875103876103877103878103879103880103881103882103883103884103885103886103887103888103889103890103891103892103893103894103895103896103897103898103899103900103901103902103903103904103905103906103907103908103909103910103911103912103913103914103915103916103917103918103919103920103921103922103923103924103925103926103927103928103929103930103931103932103933103934103935103936103937103938103939103940103941103942103943103944103945103946103947103948103949103950103951103952103953103954103955103956103957103958103959103960103961103962103963103964103965103966103967103968103969103970103971103972103973103974103975103976103977103978103979103980103981103982103983103984103985103986103987103988103989103990103991103992103993103994103995103996103997103998103999104000104001104002104003104004104005104006104007104008104009104010104011104012104013104014104015104016104017104018104019104020104021104022104023104024104025104026104027104028104029104030104031104032104033104034104035104036104037104038104039104040104041104042104043104044104045104046104047104048104049104050104051104052104053104054104055104056104057104058104059104060104061104062104063104064104065104066104067104068104069104070104071104072104073104074104075104076104077104078104079104080104081104082104083104084104085104086104087104088104089104090104091104092104093104094104095104096104097104098104099104100104101104102104103104104104105104106104107104108104109104110104111104112104113104114104115104116104117104118104119104120104121104122104123104124104125104126104127104128104129104130104131104132104133104134104135104136104137104138104139104140104141104142104143104144104145104146104147104148104149104150104151104152104153104154104155104156104157104158104159104160104161104162104163104164104165104166104167104168104169104170104171104172104173104174104175104176104177104178104179104180104181104182104183104184104185104186104187104188104189104190104191104192104193104194104195104196104197104198104199104200104201104202104203104204104205104206104207104208104209104210104211104212104213104214104215104216104217104218104219104220104221104222104223104224104225104226104227104228104229104230104231104232104233104234104235104236104237104238104239104240104241104242104243104244104245104246104247104248104249104250104251104252104253104254104255104256104257104258104259104260104261104262104263104264104265104266104267104268104269104270104271104272104273104274104275104276104277104278104279104280104281104282104283104284104285104286104287104288104289104290104291104292104293104294104295104296104297104298104299104300104301104302104303104304104305104306104307104308104309104310104311104312104313104314104315104316104317104318104319104320104321104322104323104324104325104326104327104328104329104330104331104332104333104334104335104336104337104338104339104340104341104342104343104344104345104346104347104348104349104350104351104352104353104354104355104356104357104358104359104360104361104362104363104364104365104366104367104368104369104370104371104372104373104374104375104376104377104378104379104380104381104382104383104384104385104386104387104388104389104390104391104392104393104394104395104396104397104398104399104400104401104402104403104404104405104406104407104408104409104410104411104412104413104414104415104416104417104418104419104420104421104422104423104424104425104426104427104428104429104430104431104432104433104434104435104436104437104438104439104440104441104442104443104444104445104446104447104448104449104450104451104452104453104454104455104456104457104458104459104460104461104462104463104464104465104466104467104468104469104470104471104472104473104474104475104476104477104478104479104480104481104482104483104484104485104486104487104488104489104490104491104492104493104494104495104496104497104498104499104500104501104502104503104504104505104506104507104508104509104510104511104512104513104514104515104516104517104518104519104520104521104522104523104524104525104526104527104528104529104530104531104532104533104534104535104536104537104538104539104540104541104542104543104544104545104546104547104548104549104550104551104552104553104554104555104556104557104558104559104560104561104562104563104564104565104566104567104568104569104570104571104572104573104574104575104576104577104578104579104580104581104582104583104584104585104586104587104588104589104590104591104592104593104594104595104596104597104598104599104600104601104602104603104604104605104606104607104608104609104610104611104612104613104614104615104616104617104618104619104620104621104622104623104624104625104626104627104628104629104630104631104632104633104634104635104636104637104638104639104640104641104642104643104644104645104646104647104648104649104650104651104652104653104654104655104656104657104658104659104660104661104662104663104664104665104666104667104668104669104670104671104672104673104674104675104676104677104678104679104680104681104682104683104684104685104686104687104688104689104690104691104692104693104694104695104696104697104698104699104700104701104702104703104704104705104706104707104708104709104710104711104712104713104714104715104716104717104718104719104720104721104722104723104724104725104726104727104728104729104730104731104732104733104734104735104736104737104738104739104740104741104742104743104744104745104746104747104748104749104750104751104752104753104754104755104756104757104758104759104760104761104762104763104764104765104766104767104768104769104770104771104772104773104774104775104776104777104778104779104780104781104782104783104784104785104786104787104788104789104790104791104792104793104794104795104796104797104798104799104800104801104802104803104804104805104806104807104808104809104810104811104812104813104814104815104816104817104818104819104820104821104822104823104824104825104826104827104828104829104830104831104832104833104834104835104836104837104838104839104840104841104842104843104844104845104846104847104848104849104850104851104852104853104854104855104856104857104858104859104860104861104862104863104864104865104866104867104868104869104870104871104872104873104874104875104876104877104878104879104880104881104882104883104884104885104886104887104888104889104890104891104892104893104894104895104896104897104898104899104900104901104902104903104904104905104906104907104908104909104910104911104912104913104914104915104916104917104918104919104920104921104922104923104924104925104926104927104928104929104930104931104932104933104934104935104936104937104938104939104940104941104942104943104944104945104946104947104948104949104950104951104952104953104954104955104956104957104958104959104960104961104962104963104964104965104966104967104968104969104970104971104972104973104974104975104976104977104978104979104980104981104982104983104984104985104986104987104988104989104990104991104992104993104994104995104996104997104998104999105000105001105002105003105004105005105006105007105008105009105010105011105012105013105014105015105016105017105018105019105020105021105022105023105024105025105026105027105028105029105030105031105032105033105034105035105036105037105038105039105040105041105042105043105044105045105046105047105048105049105050105051105052105053105054105055105056105057105058105059105060105061105062105063105064105065105066105067105068105069105070105071105072105073105074105075105076105077105078105079105080105081105082105083105084105085105086105087105088105089105090105091105092105093105094105095105096105097105098105099105100105101105102105103105104105105105106105107105108105109105110105111105112105113105114105115105116105117105118105119105120105121105122105123105124105125105126105127105128105129105130105131105132105133105134105135105136105137105138105139105140105141105142105143105144105145105146105147105148105149105150105151105152105153105154105155105156105157105158105159105160105161105162105163105164105165105166105167105168105169105170105171105172105173105174105175105176105177105178105179105180105181105182105183105184105185105186105187105188105189105190105191105192105193105194105195105196105197105198105199105200105201105202105203105204105205105206105207105208105209105210105211105212105213105214105215105216105217105218105219105220105221105222105223105224105225105226105227105228105229105230105231105232105233105234105235105236105237105238105239105240105241105242105243105244105245105246105247105248105249105250105251105252105253105254105255105256105257105258105259105260105261105262105263105264105265105266105267105268105269105270105271105272105273105274105275105276105277105278105279105280105281105282105283105284105285105286105287105288105289105290105291105292105293105294105295105296105297105298105299105300105301105302105303105304105305105306105307105308105309105310105311105312105313105314105315105316105317105318105319105320105321105322105323105324105325105326105327105328105329105330105331105332105333105334105335105336105337105338105339105340105341105342105343105344105345105346105347105348105349105350105351105352105353105354105355105356105357105358105359105360105361105362105363105364105365105366105367105368105369105370105371105372105373105374105375105376105377105378105379105380105381105382105383105384105385105386105387105388105389105390105391105392105393105394105395105396105397105398105399105400105401105402105403105404105405105406105407105408105409105410105411105412105413105414105415105416105417105418105419105420105421105422105423105424105425105426105427105428105429105430105431105432105433105434105435105436105437105438105439105440105441105442105443105444105445105446105447105448105449105450105451105452105453105454105455105456105457105458105459105460105461105462105463105464105465105466105467105468105469105470105471105472105473105474105475105476105477105478105479105480105481105482105483105484105485105486105487105488105489105490105491105492105493105494105495105496105497105498105499105500105501105502105503105504105505105506105507105508105509105510105511105512105513105514105515105516105517105518105519105520105521105522105523105524105525105526105527105528105529105530105531105532105533105534105535105536105537105538105539105540105541105542105543105544105545105546105547105548105549105550105551105552105553105554105555105556105557105558105559105560105561105562105563105564105565105566105567105568105569105570105571105572105573105574105575105576105577105578105579105580105581105582105583105584105585105586105587105588105589105590105591105592105593105594105595105596105597105598105599105600105601105602105603105604105605105606105607105608105609105610105611105612105613105614105615105616105617105618105619105620105621105622105623105624105625105626105627105628105629105630105631105632105633105634105635105636105637105638105639105640105641105642105643105644105645105646105647105648105649105650105651105652105653105654105655105656105657105658105659105660105661105662105663105664105665105666105667105668105669105670105671105672105673105674105675105676105677105678105679105680105681105682105683105684105685105686105687105688105689105690105691105692105693105694105695105696105697105698105699105700105701105702105703105704105705105706105707105708105709105710105711105712105713105714105715105716105717105718105719105720105721105722105723105724105725105726105727105728105729105730105731105732105733105734105735105736105737105738105739105740105741105742105743105744105745105746105747105748105749105750105751105752105753105754105755105756105757105758105759105760105761105762105763105764105765105766105767105768105769105770105771105772105773105774105775105776105777105778105779105780105781105782105783105784105785105786105787105788105789105790105791105792105793105794105795105796105797105798105799105800105801105802105803105804105805105806105807105808105809105810105811105812105813105814105815105816105817105818105819105820105821105822105823105824105825105826105827105828105829105830105831105832105833105834105835105836105837105838105839105840105841105842105843105844105845105846105847105848105849105850105851105852105853105854105855105856105857105858105859105860105861105862105863105864105865105866105867105868105869105870105871105872105873105874105875105876105877105878105879105880105881105882105883105884105885105886105887105888105889105890105891105892105893105894105895105896105897105898105899105900105901105902105903105904105905105906105907105908105909105910105911105912105913105914105915105916105917105918105919105920105921105922105923105924105925105926105927105928105929105930105931105932105933105934105935105936105937105938105939105940105941105942105943105944105945105946105947105948105949105950105951105952105953105954105955105956105957105958105959105960105961105962105963105964105965105966105967105968105969105970105971105972105973105974105975105976105977105978105979105980105981105982105983105984105985105986105987105988105989105990105991105992105993105994105995105996105997105998105999106000106001106002106003106004106005106006106007106008106009106010106011106012106013106014106015106016106017106018106019106020106021106022106023106024106025106026106027106028106029106030106031106032106033106034106035106036106037106038106039106040106041106042106043106044106045106046106047106048106049106050106051106052106053106054106055106056106057106058106059106060106061106062106063106064106065106066106067106068106069106070106071106072106073106074106075106076106077106078106079106080106081106082106083106084106085106086106087106088106089106090106091106092106093106094106095106096106097106098106099106100106101106102106103106104106105106106106107106108106109106110106111106112106113106114106115106116106117106118106119106120106121106122106123106124106125106126106127106128106129106130106131106132106133106134106135106136106137106138106139106140106141106142106143106144106145106146106147106148106149106150106151106152106153106154106155106156106157106158106159106160106161106162106163106164106165106166106167106168106169106170106171106172106173106174106175106176106177106178106179106180106181106182106183106184106185106186106187106188106189106190106191106192106193106194106195106196106197106198106199106200106201106202106203106204106205106206106207106208106209106210106211106212106213106214106215106216106217106218106219106220106221106222106223106224106225106226106227106228106229106230106231106232106233106234106235106236106237106238106239106240106241106242106243106244106245106246106247106248106249106250106251106252106253106254106255106256106257106258106259106260106261106262106263106264106265106266106267106268106269106270106271106272106273106274106275106276106277106278106279106280106281106282106283106284106285106286106287106288106289106290106291106292106293106294106295106296106297106298106299106300106301106302106303106304106305106306106307106308106309106310106311106312106313106314106315106316106317106318106319106320106321106322106323106324106325106326106327106328106329106330106331106332106333106334106335106336106337106338106339106340106341106342106343106344106345106346106347106348106349106350106351106352106353106354106355106356106357106358106359106360106361106362106363106364106365106366106367106368106369106370106371106372106373106374106375106376106377106378106379106380106381106382106383106384106385106386106387106388106389106390106391106392106393106394106395106396106397106398106399106400106401106402106403106404106405106406106407106408106409106410106411106412106413106414106415106416106417106418106419106420106421106422106423106424106425106426106427106428106429106430106431106432106433106434106435106436106437106438106439106440106441106442106443106444106445106446106447106448106449106450106451106452106453106454106455106456106457106458106459106460106461106462106463106464106465106466106467106468106469106470106471106472106473106474106475106476106477106478106479106480106481106482106483106484106485106486106487106488106489106490106491106492106493106494106495106496106497106498106499106500106501106502106503106504106505106506106507106508106509106510106511106512106513106514106515106516106517106518106519106520106521106522106523106524106525106526106527106528106529106530106531106532106533106534106535106536106537106538106539106540106541106542106543106544106545106546106547106548106549106550106551106552106553106554106555106556106557106558106559106560106561106562106563106564106565106566106567106568106569106570106571106572106573106574106575106576106577106578106579106580106581106582106583106584106585106586106587106588106589106590106591106592106593106594106595106596106597106598106599106600106601106602106603106604106605106606106607106608106609106610106611106612106613106614106615106616106617106618106619106620106621106622106623106624106625106626106627106628106629106630106631106632106633106634106635106636106637106638106639106640106641106642106643106644106645106646106647106648106649106650106651106652106653106654106655106656106657106658106659106660106661106662106663106664106665106666106667106668106669106670106671106672106673106674106675106676106677106678106679106680106681106682106683106684106685106686106687106688106689106690106691106692106693106694106695106696106697106698106699106700106701106702106703106704106705106706106707106708106709106710106711106712106713106714106715106716106717106718106719106720106721106722106723106724106725106726106727106728106729106730106731106732106733106734106735106736106737106738106739106740106741106742106743106744106745106746106747106748106749106750106751106752106753106754106755106756106757106758106759106760106761106762106763106764106765106766106767106768106769106770106771106772106773106774106775106776106777106778106779106780106781106782106783106784106785106786106787106788106789106790106791106792106793106794106795106796106797106798106799106800106801106802106803106804106805106806106807106808106809106810106811106812106813106814106815106816106817106818106819106820106821106822106823106824106825106826106827106828106829106830106831106832106833106834106835106836106837106838106839106840106841106842106843106844106845106846106847106848106849106850106851106852106853106854106855106856106857106858106859106860106861106862106863106864106865106866106867106868106869106870106871106872106873106874106875106876106877106878106879106880106881106882106883106884106885106886106887106888106889106890106891106892106893106894106895106896106897106898106899106900106901106902106903106904106905106906106907106908106909106910106911106912106913106914106915106916106917106918106919106920106921106922106923106924106925106926106927106928106929106930106931106932106933106934106935106936106937106938106939106940106941106942106943106944106945106946106947106948106949106950106951106952106953106954106955106956106957106958106959106960106961106962106963106964106965106966106967106968106969106970106971106972106973106974106975106976106977106978106979106980106981106982106983106984106985106986106987106988106989106990106991106992106993106994106995106996106997106998106999107000107001107002107003107004107005107006107007107008107009107010107011107012107013107014107015107016107017107018107019107020107021107022107023107024107025107026107027107028107029107030107031107032107033107034107035107036107037107038107039107040107041107042107043107044107045107046107047107048107049107050107051107052107053107054107055107056107057107058107059107060107061107062107063107064107065107066107067107068107069107070107071107072107073107074107075107076107077107078107079107080107081107082107083107084107085107086107087107088107089107090107091107092107093107094107095107096107097107098107099107100107101107102107103107104107105107106107107107108107109107110107111107112107113107114107115107116107117107118107119107120107121107122107123107124107125107126107127107128107129107130107131107132107133107134107135107136107137107138107139107140107141107142107143107144107145107146107147107148107149107150107151107152107153107154107155107156107157107158107159107160107161107162107163107164107165107166107167107168107169107170107171107172107173107174107175107176107177107178107179107180107181107182107183107184107185107186107187107188107189107190107191107192107193107194107195107196107197107198107199107200107201107202107203107204107205107206107207107208107209107210107211107212107213107214107215107216107217107218107219107220107221107222107223107224107225107226107227107228107229107230107231107232107233107234107235107236107237107238107239107240107241107242107243107244107245107246107247107248107249107250107251107252107253107254107255107256107257107258107259107260107261107262107263107264107265107266107267107268107269107270107271107272107273107274107275107276107277107278107279107280107281107282107283107284107285107286107287107288107289107290107291107292107293107294107295107296107297107298107299107300107301107302107303107304107305107306107307107308107309107310107311107312107313107314107315107316107317107318107319107320107321107322107323107324107325107326107327107328107329107330107331107332107333107334107335107336107337107338107339107340107341107342107343107344107345107346107347107348107349107350107351107352107353107354107355107356107357107358107359107360107361107362107363107364107365107366107367107368107369107370107371107372107373107374107375107376107377107378107379107380107381107382107383107384107385107386107387107388107389107390107391107392107393107394107395107396107397107398107399107400107401107402107403107404107405107406107407107408107409107410107411107412107413107414107415107416107417107418107419107420107421107422107423107424107425107426107427107428107429107430107431107432107433107434107435107436107437107438107439107440107441107442107443107444107445107446107447107448107449107450107451107452107453107454107455107456107457107458107459107460107461107462107463107464107465107466107467107468107469107470107471107472107473107474107475107476107477107478107479107480107481107482107483107484107485107486107487107488107489107490107491107492107493107494107495107496107497107498107499107500107501107502107503107504107505107506107507107508107509107510107511107512107513107514107515107516107517107518107519107520107521107522107523107524107525107526107527107528107529107530107531107532107533107534107535107536107537107538107539107540107541107542107543107544107545107546107547107548107549107550107551107552107553107554107555107556107557107558107559107560107561107562107563107564107565107566107567107568107569107570107571107572107573107574107575107576107577107578107579107580107581107582107583107584107585107586107587107588107589107590107591107592107593107594107595107596107597107598107599107600107601107602107603107604107605107606107607107608107609107610107611107612107613107614107615107616107617107618107619107620107621107622107623107624107625107626107627107628107629107630107631107632107633107634107635107636107637107638107639107640107641107642107643107644107645107646107647107648107649107650107651107652107653107654107655107656107657107658107659107660107661107662107663107664107665107666107667107668107669107670107671107672107673107674107675107676107677107678107679107680107681107682107683107684107685107686107687107688107689107690107691107692107693107694107695107696107697107698107699107700107701107702107703107704107705107706107707107708107709107710107711107712107713107714107715107716107717107718107719107720107721107722107723107724107725107726107727107728107729107730107731107732107733107734107735107736107737107738107739107740107741107742107743107744107745107746107747107748107749107750107751107752107753107754107755107756107757107758107759107760107761107762107763107764107765107766107767107768107769107770107771107772107773107774107775107776107777107778107779107780107781107782107783107784107785107786107787107788107789107790107791107792107793107794107795107796107797107798107799107800107801107802107803107804107805107806107807107808107809107810107811107812107813107814107815107816107817107818107819107820107821107822107823107824107825107826107827107828107829107830107831107832107833107834107835107836107837107838107839107840107841107842107843107844107845107846107847107848107849107850107851107852107853107854107855107856107857107858107859107860107861107862107863107864107865107866107867107868107869107870107871107872107873107874107875107876107877107878107879107880107881107882107883107884107885107886107887107888107889107890107891107892107893107894107895107896107897107898107899107900107901107902107903107904107905107906107907107908107909107910107911107912107913107914107915107916107917107918107919107920107921107922107923107924107925107926107927107928107929107930107931107932107933107934107935107936107937107938107939107940107941107942107943107944107945107946107947107948107949107950107951107952107953107954107955107956107957107958107959107960107961107962107963107964107965107966107967107968107969107970107971107972107973107974107975107976107977107978107979107980107981107982107983107984107985107986107987107988107989107990107991107992107993107994107995107996107997107998107999108000108001108002108003108004108005108006108007108008108009108010108011108012108013108014108015108016108017108018108019108020108021108022108023108024108025108026108027108028108029108030108031108032108033108034108035108036108037108038108039108040108041108042108043108044108045108046108047108048108049108050108051108052108053108054108055108056108057108058108059108060108061108062108063108064108065108066108067108068108069108070108071108072108073108074108075108076108077108078108079108080108081108082108083108084108085108086108087108088108089108090108091108092108093108094108095108096108097108098108099108100108101108102108103108104108105108106108107108108108109108110108111108112108113108114108115108116108117108118108119108120108121108122108123108124108125108126108127108128108129108130108131108132108133108134108135108136108137108138108139108140108141108142108143108144108145108146108147108148108149108150108151108152108153108154108155108156108157108158108159108160108161108162108163108164108165108166108167108168108169108170108171108172108173108174108175108176108177108178108179108180108181108182108183108184108185108186108187108188108189108190108191108192108193108194108195108196108197108198108199108200108201108202108203108204108205108206108207108208108209108210108211108212108213108214108215108216108217108218108219108220108221108222108223108224108225108226108227108228108229108230108231108232108233108234108235108236108237108238108239108240108241108242108243108244108245108246108247108248108249108250108251108252108253108254108255108256108257108258108259108260108261108262108263108264108265108266108267108268108269108270108271108272108273108274108275108276108277108278108279108280108281108282108283108284108285108286108287108288108289108290108291108292108293108294108295108296108297108298108299108300108301108302108303108304108305108306108307108308108309108310108311108312108313108314108315108316108317108318108319108320108321108322108323108324108325108326108327108328108329108330108331108332108333108334108335108336108337108338108339108340108341108342108343108344108345108346108347108348108349108350108351108352108353108354108355108356108357108358108359108360108361108362108363108364108365108366108367108368108369108370108371108372108373108374108375108376108377108378108379108380108381108382108383108384108385108386108387108388108389108390108391108392108393108394108395108396108397108398108399108400108401108402108403108404108405108406108407108408108409108410108411108412108413108414108415108416108417108418108419108420108421108422108423108424108425108426108427108428108429108430108431108432108433108434108435108436108437108438108439108440108441108442108443108444108445108446108447108448108449108450108451108452108453108454108455108456108457108458108459108460108461108462108463108464108465108466108467108468108469108470108471108472108473108474108475108476108477108478108479108480108481108482108483108484108485108486108487108488108489108490108491108492108493108494108495108496108497108498108499108500108501108502108503108504108505108506108507108508108509108510108511108512108513108514108515108516108517108518108519108520108521108522108523108524108525108526108527108528108529108530108531108532108533108534108535108536108537108538108539108540108541108542108543108544108545108546108547108548108549108550108551108552108553108554108555108556108557108558108559108560108561108562108563108564108565108566108567108568108569108570108571108572108573108574108575108576108577108578108579108580108581108582108583108584108585108586108587108588108589108590108591108592108593108594108595108596108597108598108599108600108601108602108603108604108605108606108607108608108609108610108611108612108613108614108615108616108617108618108619108620108621108622108623108624108625108626108627108628108629108630108631108632108633108634108635108636108637108638108639108640108641108642108643108644108645108646108647108648108649108650108651108652108653108654108655108656108657108658108659108660108661108662108663108664108665108666108667108668108669108670108671108672108673108674108675108676108677108678108679108680108681108682108683108684108685108686108687108688108689108690108691108692108693108694108695108696108697108698108699108700108701108702108703108704108705108706108707108708108709108710108711108712108713108714108715108716108717108718108719108720108721108722108723108724108725108726108727108728108729108730108731108732108733108734108735108736108737108738108739108740108741108742108743108744108745108746108747108748108749108750108751108752108753108754108755108756108757108758108759108760108761108762108763108764108765108766108767108768108769108770108771108772108773108774108775108776108777108778108779108780108781108782108783108784108785108786108787108788108789108790108791108792108793108794108795108796108797108798108799108800108801108802108803108804108805108806108807108808108809108810108811108812108813108814108815108816108817108818108819108820108821108822108823108824108825108826108827108828108829108830108831108832108833108834108835108836108837108838108839108840108841108842108843108844108845108846108847108848108849108850108851108852108853108854108855108856108857108858108859108860108861108862108863108864108865108866108867108868108869108870108871108872108873108874108875108876108877108878108879108880108881108882108883108884108885108886108887108888108889108890108891108892108893108894108895108896108897108898108899108900108901108902108903108904108905108906108907108908108909108910108911108912108913108914108915108916108917108918108919108920108921108922108923108924108925108926108927108928108929108930108931108932108933108934108935108936108937108938108939108940108941108942108943108944108945108946108947108948108949108950108951108952108953108954108955108956108957108958108959108960108961108962108963108964108965108966108967108968108969108970108971108972108973108974108975108976108977108978108979108980108981108982108983108984108985108986108987108988108989108990108991108992108993108994108995108996108997108998108999109000109001109002109003109004109005109006109007109008109009109010109011109012109013109014109015109016109017109018109019109020109021109022109023109024109025109026109027109028109029109030109031109032109033109034109035109036109037109038109039109040109041109042109043109044109045109046109047109048109049109050109051109052109053109054109055109056109057109058109059109060109061109062109063109064109065109066109067109068109069109070109071109072109073109074109075109076109077109078109079109080109081109082109083109084109085109086109087109088109089109090109091109092109093109094109095109096109097109098109099109100109101109102109103109104109105109106109107109108109109109110109111109112109113109114109115109116109117109118109119109120109121109122109123109124109125109126109127109128109129109130109131109132109133109134109135109136109137109138109139109140109141109142109143109144109145109146109147109148109149109150109151109152109153109154109155109156109157109158109159109160109161109162109163109164109165109166109167109168109169109170109171109172109173109174109175109176109177109178109179109180109181109182109183109184109185109186109187109188109189109190109191109192109193109194109195109196109197109198109199109200109201109202109203109204109205109206109207109208109209109210109211109212109213109214109215109216109217109218109219109220109221109222109223109224109225109226109227109228109229109230109231109232109233109234109235109236109237109238109239109240109241109242109243109244109245109246109247109248109249109250109251109252109253109254109255109256109257109258109259109260109261109262109263109264109265109266109267109268109269109270109271109272109273109274109275109276109277109278109279109280109281109282109283109284109285109286109287109288109289109290109291109292109293109294109295109296109297109298109299109300109301109302109303109304109305109306109307109308109309109310109311109312109313109314109315109316109317109318109319109320109321109322109323109324109325109326109327109328109329109330109331109332109333109334109335109336109337109338109339109340109341109342109343109344109345109346109347109348109349109350109351109352109353109354109355109356109357109358109359109360109361109362109363109364109365109366109367109368109369109370109371109372109373109374109375109376109377109378109379109380109381109382109383109384109385109386109387109388109389109390109391109392109393109394109395109396109397109398109399109400109401109402109403109404109405109406109407109408109409109410109411109412109413109414109415109416109417109418109419109420109421109422109423109424109425109426109427109428109429109430109431109432109433109434109435109436109437109438109439109440109441109442109443109444109445109446109447109448109449109450109451109452109453109454109455109456109457109458109459109460109461109462109463109464109465109466109467109468109469109470109471109472109473109474109475109476109477109478109479109480109481109482109483109484109485109486109487109488109489109490109491109492109493109494109495109496109497109498109499109500109501109502109503109504109505109506109507109508109509109510109511109512109513109514109515109516109517109518109519109520109521109522109523109524109525109526109527109528109529109530109531109532109533109534109535109536109537109538109539109540109541109542109543109544109545109546109547109548109549109550109551109552109553109554109555109556109557109558109559109560109561109562109563109564109565109566109567109568109569109570109571109572109573109574109575109576109577109578109579109580109581109582109583109584109585109586109587109588109589109590109591109592109593109594109595109596109597109598109599109600109601109602109603109604109605109606109607109608109609109610109611109612109613109614109615109616109617109618109619109620109621109622109623109624109625109626109627109628109629109630109631109632109633109634109635109636109637109638109639109640109641109642109643109644109645109646109647109648109649109650109651109652109653109654109655109656109657109658109659109660109661109662109663109664109665109666109667109668109669109670109671109672109673109674109675109676109677109678109679109680109681109682109683109684109685109686109687109688109689109690109691109692109693109694109695109696109697109698109699109700109701109702109703109704109705109706109707109708109709109710109711109712109713109714109715109716109717109718109719109720109721109722109723109724109725109726109727109728109729109730109731109732109733109734109735109736109737109738109739109740109741109742109743109744109745109746109747109748109749109750109751109752109753109754109755109756109757109758109759109760109761109762109763109764109765109766109767109768109769109770109771109772109773109774109775109776109777109778109779109780109781109782109783109784109785109786109787109788109789109790109791109792109793109794109795109796109797109798109799109800109801109802109803109804109805109806109807109808109809109810109811109812109813109814109815109816109817109818109819109820109821109822109823109824109825109826109827109828109829109830109831109832109833109834109835109836109837109838109839109840109841109842109843109844109845109846109847109848109849109850109851109852109853109854109855109856109857109858109859109860109861109862109863109864109865109866109867109868109869109870109871109872109873109874109875109876109877109878109879109880109881109882109883109884109885109886109887109888109889109890109891109892109893109894109895109896109897109898109899109900109901109902109903109904109905109906109907109908109909109910109911109912109913109914109915109916109917109918109919109920109921109922109923109924109925109926109927109928109929109930109931109932109933109934109935109936109937109938109939109940109941109942109943109944109945109946109947109948109949109950109951109952109953109954109955109956109957109958109959109960109961109962109963109964109965109966109967109968109969109970109971109972109973109974109975109976109977109978109979109980109981109982109983109984109985109986109987109988109989109990109991109992109993109994109995109996109997109998109999110000110001110002110003110004110005110006110007110008110009110010110011110012110013110014110015110016110017110018110019110020110021110022110023110024110025110026110027110028110029110030110031110032110033110034110035110036110037110038110039110040110041110042110043110044110045110046110047110048110049110050110051110052110053110054110055110056110057110058110059110060110061110062110063110064110065110066110067110068110069110070110071110072110073110074110075110076110077110078110079110080110081110082110083110084110085110086110087110088110089110090110091110092110093110094110095110096110097110098110099110100110101110102110103110104110105110106110107110108110109110110110111110112110113110114110115110116110117110118110119110120110121110122110123110124110125110126110127110128110129110130110131110132110133110134110135110136110137110138110139110140110141110142110143110144110145110146110147110148110149110150110151110152110153110154110155110156110157110158110159110160110161110162110163110164110165110166110167110168110169110170110171110172110173110174110175110176110177110178110179110180110181110182110183110184110185110186110187110188110189110190110191110192110193110194110195110196110197110198110199110200110201110202110203110204110205110206110207110208110209110210110211110212110213110214110215110216110217110218110219110220110221110222110223110224110225110226110227110228110229110230110231110232110233110234110235110236110237110238110239110240110241110242110243110244110245110246110247110248110249110250110251110252110253110254110255110256110257110258110259110260110261110262110263110264110265110266110267110268110269110270110271110272110273110274110275110276110277110278110279110280110281110282110283110284110285110286110287110288110289110290110291110292110293110294110295110296110297110298110299110300110301110302110303110304110305110306110307110308110309110310110311110312110313110314110315110316110317110318110319110320110321110322110323110324110325110326110327110328110329110330110331110332110333110334110335110336110337110338110339110340110341110342110343110344110345110346110347110348110349110350110351110352110353110354110355110356110357110358110359110360110361110362110363110364110365110366110367110368110369110370110371110372110373110374110375110376110377110378110379110380110381110382110383110384110385110386110387110388110389110390110391110392110393110394110395110396110397110398110399110400110401110402110403110404110405110406110407110408110409110410110411110412110413110414110415110416110417110418110419110420110421110422110423110424110425110426110427110428110429110430110431110432110433110434110435110436110437110438110439110440110441110442110443110444110445110446110447110448110449110450110451110452110453110454110455110456110457110458110459110460110461110462110463110464110465110466110467110468110469110470110471110472110473110474110475110476110477110478110479110480110481110482110483110484110485110486110487110488110489110490110491110492110493110494110495110496110497110498110499110500110501110502110503110504110505110506110507110508110509110510110511110512110513110514110515110516110517110518110519110520110521110522110523110524110525110526110527110528110529110530110531110532110533110534110535110536110537110538110539110540110541110542110543110544110545110546110547110548110549110550110551110552110553110554110555110556110557110558110559110560110561110562110563110564110565110566110567110568110569110570110571110572110573110574110575110576110577110578110579110580110581110582110583110584110585110586110587110588110589110590110591110592110593110594110595110596110597110598110599110600110601110602110603110604110605110606110607110608110609110610110611110612110613110614110615110616110617110618110619110620110621110622110623110624110625110626110627110628110629110630110631110632110633110634110635110636110637110638110639110640110641110642110643110644110645110646110647110648110649110650110651110652110653110654110655110656110657110658110659110660110661110662110663110664110665110666110667110668110669110670110671110672110673110674110675110676110677110678110679110680110681110682110683110684110685110686110687110688110689110690110691110692110693110694110695110696110697110698110699110700110701110702110703110704110705110706110707110708110709110710110711110712110713110714110715110716110717110718110719110720110721110722110723110724110725110726110727110728110729110730110731110732110733110734110735110736110737110738110739110740110741110742110743110744110745110746110747110748110749110750110751110752110753110754110755110756110757110758110759110760110761110762110763110764110765110766110767110768110769110770110771110772110773110774110775110776110777110778110779110780110781110782110783110784110785110786110787110788110789110790110791110792110793110794110795110796110797110798110799110800110801110802110803110804110805110806110807110808110809110810110811110812110813110814110815110816110817110818110819110820110821110822110823110824110825110826110827110828110829110830110831110832110833110834110835110836110837110838110839110840110841110842110843110844110845110846110847110848110849110850110851110852110853110854110855110856110857110858110859110860110861110862110863110864110865110866110867110868110869110870110871110872110873110874110875110876110877110878110879110880110881110882110883110884110885110886110887110888110889110890110891110892110893110894110895110896110897110898110899110900110901110902110903110904110905110906110907110908110909110910110911110912110913110914110915110916110917110918110919110920110921110922110923110924110925110926110927110928110929110930110931110932110933110934110935110936110937110938110939110940110941110942110943110944110945110946110947110948110949110950110951110952110953110954110955110956110957110958110959110960110961110962110963110964110965110966110967110968110969110970110971110972110973110974110975110976110977110978110979110980110981110982110983110984110985110986110987110988110989110990110991110992110993110994110995110996110997110998110999111000111001111002111003111004111005111006111007111008111009111010111011111012111013111014111015111016111017111018111019111020111021111022111023111024111025111026111027111028111029111030111031111032111033111034111035111036111037111038111039111040111041111042111043111044111045111046111047111048111049111050111051111052111053111054111055111056111057111058111059111060111061111062111063111064111065111066111067111068111069111070111071111072111073111074111075111076111077111078111079111080111081111082111083111084111085111086111087111088111089111090111091111092111093111094111095111096111097111098111099111100111101111102111103111104111105111106111107111108111109111110111111111112111113111114111115111116111117111118111119111120111121111122111123111124111125111126111127111128111129111130111131111132111133111134111135111136111137111138111139111140111141111142111143111144111145111146111147111148111149111150111151111152111153111154111155111156111157111158111159111160111161111162111163111164111165111166111167111168111169111170111171111172111173111174111175111176111177111178111179111180111181111182111183111184111185111186111187111188111189111190111191111192111193111194111195111196111197111198111199111200111201111202111203111204111205111206111207111208111209111210111211111212111213111214111215111216111217111218111219111220111221111222111223111224111225111226111227111228111229111230111231111232111233111234111235111236111237111238111239111240111241111242111243111244111245111246111247111248111249111250111251111252111253111254111255111256111257111258111259111260111261111262111263111264111265111266111267111268111269111270111271111272111273111274111275111276111277111278111279111280111281111282111283111284111285111286111287111288111289111290111291111292111293111294111295111296111297111298111299111300111301111302111303111304111305111306111307111308111309111310111311111312111313111314111315111316111317111318111319111320111321111322111323111324111325111326111327111328111329111330111331111332111333111334111335111336111337111338111339111340111341111342111343111344111345111346111347111348111349111350111351111352111353111354111355111356111357111358111359111360111361111362111363111364111365111366111367111368111369111370111371111372111373111374111375111376111377111378111379111380111381111382111383111384111385111386111387111388111389111390111391111392111393111394111395111396111397111398111399111400111401111402111403111404111405111406111407111408111409111410111411111412111413111414111415111416111417111418111419111420111421111422111423111424111425111426111427111428111429111430111431111432111433111434111435111436111437111438111439111440111441111442111443111444111445111446111447111448111449111450111451111452111453111454111455111456111457111458111459111460111461111462111463111464111465111466111467111468111469111470111471111472111473111474111475111476111477111478111479111480111481111482111483111484111485111486111487111488111489111490111491111492111493111494111495111496111497111498111499111500111501111502111503111504111505111506111507111508111509111510111511111512111513111514111515111516111517111518111519111520111521111522111523111524111525111526111527111528111529111530111531111532111533111534111535111536111537111538111539111540111541111542111543111544111545111546111547111548111549111550111551111552111553111554111555111556111557111558111559111560111561111562111563111564111565111566111567111568111569111570111571111572111573111574111575111576111577111578111579111580111581111582111583111584111585111586111587111588111589111590111591111592111593111594111595111596111597111598111599111600111601111602111603111604111605111606111607111608111609111610111611111612111613111614111615111616111617111618111619111620111621111622111623111624111625111626111627111628111629111630111631111632111633111634111635111636111637111638111639111640111641111642111643111644111645111646111647111648111649111650111651111652111653111654111655111656111657111658111659111660111661111662111663111664111665111666111667111668111669111670111671111672111673111674111675111676111677111678111679111680111681111682111683111684111685111686111687111688111689111690111691111692111693111694111695111696111697111698111699111700111701111702111703111704111705111706111707111708111709111710111711111712111713111714111715111716111717111718111719111720111721111722111723111724111725111726111727111728111729111730111731111732111733111734111735111736111737111738111739111740111741111742111743111744111745111746111747111748111749111750111751111752111753111754111755111756111757111758111759111760111761111762111763111764111765111766111767111768111769111770111771111772111773111774111775111776111777111778111779111780111781111782111783111784111785111786111787111788111789111790111791111792111793111794111795111796111797111798111799111800111801111802111803111804111805111806111807111808111809111810111811111812111813111814111815111816111817111818111819111820111821111822111823111824111825111826111827111828111829111830111831111832111833111834111835111836111837111838111839111840111841111842111843111844111845111846111847111848111849111850111851111852111853111854111855111856111857111858111859111860111861111862111863111864111865111866111867111868111869111870111871111872111873111874111875111876111877111878111879111880111881111882111883111884111885111886111887111888111889111890111891111892111893111894111895111896111897111898111899111900111901111902111903111904111905111906111907111908111909111910111911111912111913111914111915111916111917111918111919111920111921111922111923111924111925111926111927111928111929111930111931111932111933111934111935111936111937111938111939111940111941111942111943111944111945111946111947111948111949111950111951111952111953111954111955111956111957111958111959111960111961111962111963111964111965111966111967111968111969111970111971111972111973111974111975111976111977111978111979111980111981111982111983111984111985111986111987111988111989111990111991111992111993111994111995111996111997111998111999112000112001112002112003112004112005112006112007112008112009112010112011112012112013112014112015112016112017112018112019112020112021112022112023112024112025112026112027112028112029112030112031112032112033112034112035112036112037112038112039112040112041112042112043112044112045112046112047112048112049112050112051112052112053112054112055112056112057112058112059112060112061112062112063112064112065112066112067112068112069112070112071112072112073112074112075112076112077112078112079112080112081112082112083112084112085112086112087112088112089112090112091112092112093112094112095112096112097112098112099112100112101112102112103112104112105112106112107112108112109112110112111112112112113112114112115112116112117112118112119112120112121112122112123112124112125112126112127112128112129112130112131112132112133112134112135112136112137112138112139112140112141112142112143112144112145112146112147112148112149112150112151112152112153112154112155112156112157112158112159112160112161112162112163112164112165112166112167112168112169112170112171112172112173112174112175112176112177112178112179112180112181112182112183112184112185112186112187112188112189112190112191112192112193112194112195112196112197112198112199112200112201112202112203112204112205112206112207112208112209112210112211112212112213112214112215112216112217112218112219112220112221112222112223112224112225112226112227112228112229112230112231112232112233112234112235112236112237112238112239112240112241112242112243112244112245112246112247112248112249112250112251112252112253112254112255112256112257112258112259112260112261112262112263112264112265112266112267112268112269112270112271112272112273112274112275112276112277112278112279112280112281112282112283112284112285112286112287112288112289112290112291112292112293112294112295112296112297112298112299112300112301112302112303112304112305112306112307112308112309112310112311112312112313112314112315112316112317112318112319112320112321112322112323112324112325112326112327112328112329112330112331112332112333112334112335112336112337112338112339112340112341112342112343112344112345112346112347112348112349112350112351112352112353112354112355112356112357112358112359112360112361112362112363112364112365112366112367112368112369112370112371112372112373112374112375112376112377112378112379112380112381112382112383112384112385112386112387112388112389112390112391112392112393112394112395112396112397112398112399112400112401112402112403112404112405112406112407112408112409112410112411112412112413112414112415112416112417112418112419112420112421112422112423112424112425112426112427112428112429112430112431112432112433112434112435112436112437112438112439112440112441112442112443112444112445112446112447112448112449112450112451112452112453112454112455112456112457112458112459112460112461112462112463112464112465112466112467112468112469112470112471112472112473112474112475112476112477112478112479112480112481112482112483112484112485112486112487112488112489112490112491112492112493112494112495112496112497112498112499112500112501112502112503112504112505112506112507112508112509112510112511112512112513112514112515112516112517112518112519112520112521112522112523112524112525112526112527112528112529112530112531112532112533112534112535112536112537112538112539112540112541112542112543112544112545112546112547112548112549112550112551112552112553112554112555112556112557112558112559112560112561112562112563112564112565112566112567112568112569112570112571112572112573112574112575112576112577112578112579112580112581112582112583112584112585112586112587112588112589112590112591112592112593112594112595112596112597112598112599112600112601112602112603112604112605112606112607112608112609112610112611112612112613112614112615112616112617112618112619112620112621112622112623112624112625112626112627112628112629112630112631112632112633112634112635112636112637112638112639112640112641112642112643112644112645112646112647112648112649112650112651112652112653112654112655112656112657112658112659112660112661112662112663112664112665112666112667112668112669112670112671112672112673112674112675112676112677112678112679112680112681112682112683112684112685112686112687112688112689112690112691112692112693112694112695112696112697112698112699112700112701112702112703112704112705112706112707112708112709112710112711112712112713112714112715112716112717112718112719112720112721112722112723112724112725112726112727112728112729112730112731112732112733112734112735112736112737112738112739112740112741112742112743112744112745112746112747112748112749112750112751112752112753112754112755112756112757112758112759112760112761112762112763112764112765112766112767112768112769112770112771112772112773112774112775112776112777112778112779112780112781112782112783112784112785112786112787112788112789112790112791112792112793112794112795112796112797112798112799112800112801112802112803112804112805112806112807112808112809112810112811112812112813112814112815112816112817112818112819112820112821112822112823112824112825112826112827112828112829112830112831112832112833112834112835112836112837112838112839112840112841112842112843112844112845112846112847112848112849112850112851112852112853112854112855112856112857112858112859112860112861112862112863112864112865112866112867112868112869112870112871112872112873112874112875112876112877112878112879112880112881112882112883112884112885112886112887112888112889112890112891112892112893112894112895112896112897112898112899112900112901112902112903112904112905112906112907112908112909112910112911112912112913112914112915112916112917112918112919112920112921112922112923112924112925112926112927112928112929112930112931112932112933112934112935112936112937112938112939112940112941112942112943112944112945112946112947112948112949112950112951112952112953112954112955112956112957112958112959112960112961112962112963112964112965112966112967112968112969112970112971112972112973112974112975112976112977112978112979112980112981112982112983112984112985112986112987112988112989112990112991112992112993112994112995112996112997112998112999113000113001113002113003113004113005113006113007113008113009113010113011113012113013113014113015113016113017113018113019113020113021113022113023113024113025113026113027113028113029113030113031113032113033113034113035113036113037113038113039113040113041113042113043113044113045113046113047113048113049113050113051113052113053113054113055113056113057113058113059113060113061113062113063113064113065113066113067113068113069113070113071113072113073113074113075113076113077113078113079113080113081113082113083113084113085113086113087113088113089113090113091113092113093113094113095113096113097113098113099113100113101113102113103113104113105113106113107113108113109113110113111113112113113113114113115113116113117113118113119113120113121113122113123113124113125113126113127113128113129113130113131113132113133113134113135113136113137113138113139113140113141113142113143113144113145113146113147113148113149113150113151113152113153113154113155113156113157113158113159113160113161113162113163113164113165113166113167113168113169113170113171113172113173113174113175113176113177113178113179113180113181113182113183113184113185113186113187113188113189113190113191113192113193113194113195113196113197113198113199113200113201113202113203113204113205113206113207113208113209113210113211113212113213113214113215113216113217113218113219113220113221113222113223113224113225113226113227113228113229113230113231113232113233113234113235113236113237113238113239113240113241113242113243113244113245113246113247113248113249113250113251113252113253113254113255113256113257113258113259113260113261113262113263113264113265113266113267113268113269113270113271113272113273113274113275113276113277113278113279113280113281113282113283113284113285113286113287113288113289113290113291113292113293113294113295113296113297113298113299113300113301113302113303113304113305113306113307113308113309113310113311113312113313113314113315113316113317113318113319113320113321113322113323113324113325113326113327113328113329113330113331113332113333113334113335113336113337113338113339113340113341113342113343113344113345113346113347113348113349113350113351113352113353113354113355113356113357113358113359113360113361113362113363113364113365113366113367113368113369113370113371113372113373113374113375113376113377113378113379113380113381113382113383113384113385113386113387113388113389113390113391113392113393113394113395113396113397113398113399113400113401113402113403113404113405113406113407113408113409113410113411113412113413113414113415113416113417113418113419113420113421113422113423113424113425113426113427113428113429113430113431113432113433113434113435113436113437113438113439113440113441113442113443113444113445113446113447113448113449113450113451113452113453113454113455113456113457113458113459113460113461113462113463113464113465113466113467113468113469113470113471113472113473113474113475113476113477113478113479113480113481113482113483113484113485113486113487113488113489113490113491113492113493113494113495113496113497113498113499113500113501113502113503113504113505113506113507113508113509113510113511113512113513113514113515113516113517113518113519113520113521113522113523113524113525113526113527113528113529113530113531113532113533113534113535113536113537113538113539113540113541113542113543113544113545113546113547113548113549113550113551113552113553113554113555113556113557113558113559113560113561113562113563113564113565113566113567113568113569113570113571113572113573113574113575113576113577113578113579113580113581113582113583113584113585113586113587113588113589113590113591113592113593113594113595113596113597113598113599113600113601113602113603113604113605113606113607113608113609113610113611113612113613113614113615113616113617113618113619113620113621113622113623113624113625113626113627113628113629113630113631113632113633113634113635113636113637113638113639113640113641113642113643113644113645113646113647113648113649113650113651113652113653113654113655113656113657113658113659113660113661113662113663113664113665113666113667113668113669113670113671113672113673113674113675113676113677113678113679113680113681113682113683113684113685113686113687113688113689113690113691113692113693113694113695113696113697113698113699113700113701113702113703113704113705113706113707113708113709113710113711113712113713113714113715113716113717113718113719113720113721113722113723113724113725113726113727113728113729113730113731113732113733113734113735113736113737113738113739113740113741113742113743113744113745113746113747113748113749113750113751113752113753113754113755113756113757113758113759113760113761113762113763113764113765113766113767113768113769113770113771113772113773113774113775113776113777113778113779113780113781113782113783113784113785113786113787113788113789113790113791113792113793113794113795113796113797113798113799113800113801113802113803113804113805113806113807113808113809113810113811113812113813113814113815113816113817113818113819113820113821113822113823113824113825113826113827113828113829113830113831113832113833113834113835113836113837113838113839113840113841113842113843113844113845113846113847113848113849113850113851113852113853113854113855113856113857113858113859113860113861113862113863113864113865113866113867113868113869113870113871113872113873113874113875113876113877113878113879113880113881113882113883113884113885113886113887113888113889113890113891113892113893113894113895113896113897113898113899113900113901113902113903113904113905113906113907113908113909113910113911113912113913113914113915113916113917113918113919113920113921113922113923113924113925113926113927113928113929113930113931113932113933113934113935113936113937113938113939113940113941113942113943113944113945113946113947113948113949113950113951113952113953113954113955113956113957113958113959113960113961113962113963113964113965113966113967113968113969113970113971113972113973113974113975113976113977113978113979113980113981113982113983113984113985113986113987113988113989113990113991113992113993113994113995113996113997113998113999114000114001114002114003114004114005114006114007114008114009114010114011114012114013114014114015114016114017114018114019114020114021114022114023114024114025114026114027114028114029114030114031114032114033114034114035114036114037114038114039114040114041114042114043114044114045114046114047114048114049114050114051114052114053114054114055114056114057114058114059114060114061114062114063114064114065114066114067114068114069114070114071114072114073114074114075114076114077114078114079114080114081114082114083114084114085114086114087114088114089114090114091114092114093114094114095114096114097114098114099114100114101114102114103114104114105114106114107114108114109114110114111114112114113114114114115114116114117114118114119114120114121114122114123114124114125114126114127114128114129114130114131114132114133114134114135114136114137114138114139114140114141114142114143114144114145114146114147114148114149114150114151114152114153114154114155114156114157114158114159114160114161114162114163114164114165114166114167114168114169114170114171114172114173114174114175114176114177114178114179114180114181114182114183114184114185114186114187114188114189114190114191114192114193114194114195114196114197114198114199114200114201114202114203114204114205114206114207114208114209114210114211114212114213114214114215114216114217114218114219114220114221114222114223114224114225114226114227114228114229114230114231114232114233114234114235114236114237114238114239114240114241114242114243114244114245114246114247114248114249114250114251114252114253114254114255114256114257114258114259114260114261114262114263114264114265114266114267114268114269114270114271114272114273114274114275114276114277114278114279114280114281114282114283114284114285114286114287114288114289114290114291114292114293114294114295114296114297114298114299114300114301114302114303114304114305114306114307114308114309114310114311114312114313114314114315114316114317114318114319114320114321114322114323114324114325114326114327114328114329114330114331114332114333114334114335114336114337114338114339114340114341114342114343114344114345114346114347114348114349114350114351114352114353114354114355114356114357114358114359114360114361114362114363114364114365114366114367114368114369114370114371114372114373114374114375114376114377114378114379114380114381114382114383114384114385114386114387114388114389114390114391114392114393114394114395114396114397114398114399114400114401114402114403114404114405114406114407114408114409114410114411114412114413114414114415114416114417114418114419114420114421114422114423114424114425114426114427114428114429114430114431114432114433114434114435114436114437114438114439114440114441114442114443114444114445114446114447114448114449114450114451114452114453114454114455114456114457114458114459114460114461114462114463114464114465114466114467114468114469114470114471114472114473114474114475114476114477114478114479114480114481114482114483114484114485114486114487114488114489114490114491114492114493114494114495114496114497114498114499114500114501114502114503114504114505114506114507114508114509114510114511114512114513114514114515114516114517114518114519114520114521114522114523114524114525114526114527114528114529114530114531114532114533114534114535114536114537114538114539114540114541114542114543114544114545114546114547114548114549114550114551114552114553114554114555114556114557114558114559114560114561114562114563114564114565114566114567114568114569114570114571114572114573114574114575114576114577114578114579114580114581114582114583114584114585114586114587114588114589114590114591114592114593114594114595114596114597114598114599114600114601114602114603114604114605114606114607114608114609114610114611114612114613114614114615114616114617114618114619114620114621114622114623114624114625114626114627114628114629114630114631114632114633114634114635114636114637114638114639114640114641114642114643114644114645114646114647114648114649114650114651114652114653114654114655114656114657114658114659114660114661114662114663114664114665114666114667114668114669114670114671114672114673114674114675114676114677114678114679114680114681114682114683114684114685114686114687114688114689114690114691114692114693114694114695114696114697114698114699114700114701114702114703114704114705114706114707114708114709114710114711114712114713114714114715114716114717114718114719114720114721114722114723114724114725114726114727114728114729114730114731114732114733114734114735114736114737114738114739114740114741114742114743114744114745114746114747114748114749114750114751114752114753114754114755114756114757114758114759114760114761114762114763114764114765114766114767114768114769114770114771114772114773114774114775114776114777114778114779114780114781114782114783114784114785114786114787114788114789114790114791114792114793114794114795114796114797114798114799114800114801114802114803114804114805114806114807114808114809114810114811114812114813114814114815114816114817114818114819114820114821114822114823114824114825114826114827114828114829114830114831114832114833114834114835114836114837114838114839114840114841114842114843114844114845114846114847114848114849114850114851114852114853114854114855114856114857114858114859114860114861114862114863114864114865114866114867114868114869114870114871114872114873114874114875114876114877114878114879114880114881114882114883114884114885114886114887114888114889114890114891114892114893114894114895114896114897114898114899114900114901114902114903114904114905114906114907114908114909114910114911114912114913114914114915114916114917114918114919114920114921114922114923114924114925114926114927114928114929114930114931114932114933114934114935114936114937114938114939114940114941114942114943114944114945114946114947114948114949114950114951114952114953114954114955114956114957114958114959114960114961114962114963114964114965114966114967114968114969114970114971114972114973114974114975114976114977114978114979114980114981114982114983114984114985114986114987114988114989114990114991114992114993114994114995114996114997114998114999115000115001115002115003115004115005115006115007115008115009115010115011115012115013115014115015115016115017115018115019115020115021115022115023115024115025115026115027115028115029115030115031115032115033115034115035115036115037115038115039115040115041115042115043115044115045115046115047115048115049115050115051115052115053115054115055115056115057115058115059115060115061115062115063115064115065115066115067115068115069115070115071115072115073115074115075115076115077115078115079115080115081115082115083115084115085115086115087115088115089115090115091115092115093115094115095115096115097115098115099115100115101115102115103115104115105115106115107115108115109115110115111115112115113115114115115115116115117115118115119115120115121115122115123115124115125115126115127115128115129115130115131115132115133115134115135115136115137115138115139115140115141115142115143115144115145115146115147115148115149115150115151115152115153115154115155115156115157115158115159115160115161115162115163115164115165115166115167115168115169115170115171115172115173115174115175115176115177115178115179115180115181115182115183115184115185115186115187115188115189115190115191115192115193115194115195115196115197115198115199115200115201115202115203115204115205115206115207115208115209115210115211115212115213115214115215115216115217115218115219115220115221115222115223115224115225115226115227115228115229115230115231115232115233115234115235115236115237115238115239115240115241115242115243115244115245115246115247115248115249115250115251115252115253115254115255115256115257115258115259115260115261115262115263115264115265115266115267115268115269115270115271115272115273115274115275115276115277115278115279115280115281115282115283115284115285115286115287115288115289115290115291115292115293115294115295115296115297115298115299115300115301115302115303115304115305115306115307115308115309115310115311115312115313115314115315115316115317115318115319115320115321115322115323115324115325115326115327115328115329115330115331115332115333115334115335115336115337115338115339115340115341115342115343115344115345115346115347115348115349115350115351115352115353115354115355115356115357115358115359115360115361115362115363115364115365115366115367115368115369115370115371115372115373115374115375115376115377115378115379115380115381115382115383115384115385115386115387115388115389115390115391115392115393115394115395115396115397115398115399115400115401115402115403115404115405115406115407115408115409115410115411115412115413115414115415115416115417115418115419115420115421115422115423115424115425115426115427115428115429115430115431115432115433115434115435115436115437115438115439115440115441115442115443115444115445115446115447115448115449115450115451115452115453115454115455115456115457115458115459115460115461115462115463115464115465115466115467115468115469115470115471115472115473115474115475115476115477115478115479115480115481115482115483115484115485115486115487115488115489115490115491115492115493115494115495115496115497115498115499115500115501115502115503115504115505115506115507115508115509115510115511115512115513115514115515115516115517115518115519115520115521115522115523115524115525115526115527115528115529115530115531115532115533115534115535115536115537115538115539115540115541115542115543115544115545115546115547115548115549115550115551115552115553115554115555115556115557115558115559115560115561115562115563115564115565115566115567115568115569115570115571115572115573115574115575115576115577115578115579115580115581115582115583115584115585115586115587115588115589115590115591115592115593115594115595115596115597115598115599115600115601115602115603115604115605115606115607115608115609115610115611115612115613115614115615115616115617115618115619115620115621115622115623115624115625115626115627115628115629115630115631115632115633115634115635115636115637115638115639115640115641115642115643115644115645115646115647115648115649115650115651115652115653115654115655115656115657115658115659115660115661115662115663115664115665115666115667115668115669115670115671115672115673115674115675115676115677115678115679115680115681115682115683115684115685115686115687115688115689115690115691115692115693115694115695115696115697115698115699115700115701115702115703115704115705115706115707115708115709115710115711115712115713115714115715115716115717115718115719115720115721115722115723115724115725115726115727115728115729115730115731115732115733115734115735115736115737115738115739115740115741115742115743115744115745115746115747115748115749115750115751115752115753115754115755115756115757115758115759115760115761115762115763115764115765115766115767115768115769115770115771115772115773115774115775115776115777115778115779115780115781115782115783115784115785115786115787115788115789115790115791115792115793115794115795115796115797115798115799115800115801115802115803115804115805115806115807115808115809115810115811115812115813115814115815115816115817115818115819115820115821115822115823115824115825115826115827115828115829115830115831115832115833115834115835115836115837115838115839115840115841115842115843115844115845115846115847115848115849115850115851115852115853115854115855115856115857115858115859115860115861115862115863115864115865115866115867115868115869115870115871115872115873115874115875115876115877115878115879115880115881115882115883115884115885115886115887115888115889115890115891115892115893115894115895115896115897115898115899115900115901115902115903115904115905115906115907115908115909115910115911115912115913115914115915115916115917115918115919115920115921115922115923115924115925115926115927115928115929115930115931115932115933115934115935115936115937115938115939115940115941115942115943115944115945115946115947115948115949115950115951115952115953115954115955115956115957115958115959115960115961115962115963115964115965115966115967115968115969115970115971115972115973115974115975115976115977115978115979115980115981115982115983115984115985115986115987115988115989115990115991115992115993115994115995115996115997115998115999116000116001116002116003116004116005116006116007116008116009116010116011116012116013116014116015116016116017116018116019116020116021116022116023116024116025116026116027116028116029116030116031116032116033116034116035116036116037116038116039116040116041116042116043116044116045116046116047116048116049116050116051116052116053116054116055116056116057116058116059116060116061116062116063116064116065116066116067116068116069116070116071116072116073116074116075116076116077116078116079116080116081116082116083116084116085116086116087116088116089116090116091116092116093116094116095116096116097116098116099116100116101116102116103116104116105116106116107116108116109116110116111116112116113116114116115116116116117116118116119116120116121116122116123116124116125116126116127116128116129116130116131116132116133116134116135116136116137116138116139116140116141116142116143116144116145116146116147116148116149116150116151116152116153116154116155116156116157116158116159116160116161116162116163116164116165116166116167116168116169116170116171116172116173116174116175116176116177116178116179116180116181116182116183116184116185116186116187116188116189116190116191116192116193116194116195116196116197116198116199116200116201116202116203116204116205116206116207116208116209116210116211116212116213116214116215116216116217116218116219116220116221116222116223116224116225116226116227116228116229116230116231116232116233116234116235116236116237116238116239116240116241116242116243116244116245116246116247116248116249116250116251116252116253116254116255116256116257116258116259116260116261116262116263116264116265116266116267116268116269116270116271116272116273116274116275116276116277116278116279116280116281116282116283116284116285116286116287116288116289116290116291116292116293116294116295116296116297116298116299116300116301116302116303116304116305116306116307116308116309116310116311116312116313116314116315116316116317116318116319116320116321116322116323116324116325116326116327116328116329116330116331116332116333116334116335116336116337116338116339116340116341116342116343116344116345116346116347116348116349116350116351116352116353116354116355116356116357116358116359116360116361116362116363116364116365116366116367116368116369116370116371116372116373116374116375116376116377116378116379116380116381116382116383116384116385116386116387116388116389116390116391116392116393116394116395116396116397116398116399116400116401116402116403116404116405116406116407116408116409116410116411116412116413116414116415116416116417116418116419116420116421116422116423116424116425116426116427116428116429116430116431116432116433116434116435116436116437116438116439116440116441116442116443116444116445116446116447116448116449116450116451116452116453116454116455116456116457116458116459116460116461116462116463116464116465116466116467116468116469116470116471116472116473116474116475116476116477116478116479116480116481116482116483116484116485116486116487116488116489116490116491116492116493116494116495116496116497116498116499116500116501116502116503116504116505116506116507116508116509116510116511116512116513116514116515116516116517116518116519116520116521116522116523116524116525116526116527116528116529116530116531116532116533116534116535116536116537116538116539116540116541116542116543116544116545116546116547116548116549116550116551116552116553116554116555116556116557116558116559116560116561116562116563116564116565116566116567116568116569116570116571116572116573116574116575116576116577116578116579116580116581116582116583116584116585116586116587116588116589116590116591116592116593116594116595116596116597116598116599116600116601116602116603116604116605116606116607116608116609116610116611116612116613116614116615116616116617116618116619116620116621116622116623116624116625116626116627116628116629116630116631116632116633116634116635116636116637116638116639116640116641116642116643116644116645116646116647116648116649116650116651116652116653116654116655116656116657116658116659116660116661116662116663116664116665116666116667116668116669116670116671116672116673116674116675116676116677116678116679116680116681116682116683116684116685116686116687116688116689116690116691116692116693116694116695116696116697116698116699116700116701116702116703116704116705116706116707116708116709116710116711116712116713116714116715116716116717116718116719116720116721116722116723116724116725116726116727116728116729116730116731116732116733116734116735116736116737116738116739116740116741116742116743116744116745116746116747116748116749116750116751116752116753116754116755116756116757116758116759116760116761116762116763116764116765116766116767116768116769116770116771116772116773116774116775116776116777116778116779116780116781116782116783116784116785116786116787116788116789116790116791116792116793116794116795116796116797116798116799116800116801116802116803116804116805116806116807116808116809116810116811116812116813116814116815116816116817116818116819116820116821116822116823116824116825116826116827116828116829116830116831116832116833116834116835116836116837116838116839116840116841116842116843116844116845116846116847116848116849116850116851116852116853116854116855116856116857116858116859116860116861116862116863116864116865116866116867116868116869116870116871116872116873116874116875116876116877116878116879116880116881116882116883116884116885116886116887116888116889116890116891116892116893116894116895116896116897116898116899116900116901116902116903116904116905116906116907116908116909116910116911116912116913116914116915116916116917116918116919116920116921116922116923116924116925116926116927116928116929116930116931116932116933116934116935116936116937116938116939116940116941116942116943116944116945116946116947116948116949116950116951116952116953116954116955116956116957116958116959116960116961116962116963116964116965116966116967116968116969116970116971116972116973116974116975116976116977116978116979116980116981116982116983116984116985116986116987116988116989116990116991116992116993116994116995116996116997116998116999117000117001117002117003117004117005117006117007117008117009117010117011117012117013117014117015117016117017117018117019117020117021117022117023117024117025117026117027117028117029117030117031117032117033117034117035117036117037117038117039117040117041117042117043117044117045117046117047117048117049117050117051117052117053117054117055117056117057117058117059117060117061117062117063117064117065117066117067117068117069117070117071117072117073117074117075117076117077117078117079117080117081117082117083117084117085117086117087117088117089117090117091117092117093117094117095117096117097117098117099117100117101117102117103117104117105117106117107117108117109117110117111117112117113117114117115117116117117117118117119117120117121117122117123117124117125117126117127117128117129117130117131117132117133117134117135117136117137117138117139117140117141117142117143117144117145117146117147117148117149117150117151117152117153117154117155117156117157117158117159117160117161117162117163117164117165117166117167117168117169117170117171117172117173117174117175117176117177117178117179117180117181117182117183117184117185117186117187117188117189117190117191117192117193117194117195117196117197117198117199117200117201117202117203117204117205117206117207117208117209117210117211117212117213117214117215117216117217117218117219117220117221117222117223117224117225117226117227117228117229117230117231117232117233117234117235117236117237117238117239117240117241117242117243117244117245117246117247117248117249117250117251117252117253117254117255117256117257117258117259117260117261117262117263117264117265117266117267117268117269117270117271117272117273117274117275117276117277117278117279117280117281117282117283117284117285117286117287117288117289117290117291117292117293117294117295117296117297117298117299117300117301117302117303117304117305117306117307117308117309117310117311117312117313117314117315117316117317117318117319117320117321117322117323117324117325117326117327117328117329117330117331117332117333117334117335117336117337117338117339117340117341117342117343117344117345117346117347117348117349117350117351117352117353117354117355117356117357117358117359117360117361117362117363117364117365117366117367117368117369117370117371117372117373117374117375117376117377117378117379117380117381117382117383117384117385117386117387117388117389117390117391117392117393117394117395117396117397117398117399117400117401117402117403117404117405117406117407117408117409117410117411117412117413117414117415117416117417117418117419117420117421117422117423117424117425117426117427117428117429117430117431117432117433117434117435117436117437117438117439117440117441117442117443117444117445117446117447117448117449117450117451117452117453117454117455117456117457117458117459117460117461117462117463117464117465117466117467117468117469117470117471117472117473117474117475117476117477117478117479117480117481117482117483117484117485117486117487117488117489117490117491117492117493117494117495117496117497117498117499117500117501117502117503117504117505117506117507117508117509117510117511117512117513117514117515117516117517117518117519117520117521117522117523117524117525117526117527117528117529117530117531117532117533117534117535117536117537117538117539117540117541117542117543117544117545117546117547117548117549117550117551117552117553117554117555117556117557117558117559117560117561117562117563117564117565117566117567117568117569117570117571117572117573117574117575117576117577117578117579117580117581117582117583117584117585117586117587117588117589117590117591117592117593117594117595117596117597117598117599117600117601117602117603117604117605117606117607117608117609117610117611117612117613117614117615117616117617117618117619117620117621117622117623117624117625117626117627117628117629117630117631117632117633117634117635117636117637117638117639117640117641117642117643117644117645117646117647117648117649117650117651117652117653117654117655117656117657117658117659117660117661117662117663117664117665117666117667117668117669117670117671117672117673117674117675117676117677117678117679117680117681117682117683117684117685117686117687117688117689117690117691117692117693117694117695117696117697117698117699117700117701117702117703117704117705117706117707117708117709117710117711117712117713117714117715117716117717117718117719117720117721117722117723117724117725117726117727117728117729117730117731117732117733117734117735117736117737117738117739117740117741117742117743117744117745117746117747117748117749117750117751117752117753117754117755117756117757117758117759117760117761117762117763117764117765117766117767117768117769117770117771117772117773117774117775117776117777117778117779117780117781117782117783117784117785117786117787117788117789117790117791117792117793117794117795117796117797117798117799117800117801117802117803117804117805117806117807117808117809117810117811117812117813117814117815117816117817117818117819117820117821117822117823117824117825117826117827117828117829117830117831117832117833117834117835117836117837117838117839117840117841117842117843117844117845117846117847117848117849117850117851117852117853117854117855117856117857117858117859117860117861117862117863117864117865117866117867117868117869117870117871117872117873117874117875117876117877117878117879117880117881117882117883117884117885117886117887117888117889117890117891117892117893117894117895117896117897117898117899117900117901117902117903117904117905117906117907117908117909117910117911117912117913117914117915117916117917117918117919117920117921117922117923117924117925117926117927117928117929117930117931117932117933117934117935117936117937117938117939117940117941117942117943117944117945117946117947117948117949117950117951117952117953117954117955117956117957117958117959117960117961117962117963117964117965117966117967117968117969117970117971117972117973117974117975117976117977117978117979117980117981117982117983117984117985117986117987117988117989117990117991117992117993117994117995117996117997117998117999118000118001118002118003118004118005118006118007118008118009118010118011118012118013118014118015118016118017118018118019118020118021118022118023118024118025118026118027118028118029118030118031118032118033118034118035118036118037118038118039118040118041118042118043118044118045118046118047118048118049118050118051118052118053118054118055118056118057118058118059118060118061118062118063118064118065118066118067118068118069118070118071118072118073118074118075118076118077118078118079118080118081118082118083118084118085118086118087118088118089118090118091118092118093118094118095118096118097118098118099118100118101118102118103118104118105118106118107118108118109118110118111118112118113118114118115118116118117118118118119118120118121118122118123118124118125118126118127118128118129118130118131118132118133118134118135118136118137118138118139118140118141118142118143118144118145118146118147118148118149118150118151118152118153118154118155118156118157118158118159118160118161118162118163118164118165118166118167118168118169118170118171118172118173118174118175118176118177118178118179118180118181118182118183118184118185118186118187118188118189118190118191118192118193118194118195118196118197118198118199118200118201118202118203118204118205118206118207118208118209118210118211118212118213118214118215118216118217118218118219118220118221118222118223118224118225118226118227118228118229118230118231118232118233118234118235118236118237118238118239118240118241118242118243118244118245118246118247118248118249118250118251118252118253118254118255118256118257118258118259118260118261118262118263118264118265118266118267118268118269118270118271118272118273118274118275118276118277118278118279118280118281118282118283118284118285118286118287118288118289118290118291118292118293118294118295118296118297118298118299118300118301118302118303118304118305118306118307118308118309118310118311118312118313118314118315118316118317118318118319118320118321118322118323118324118325118326118327118328118329118330118331118332118333118334118335118336118337118338118339118340118341118342118343118344118345118346118347118348118349118350118351118352118353118354118355118356118357118358118359118360118361118362118363118364118365118366118367118368118369118370118371118372118373118374118375118376118377118378118379118380118381118382118383118384118385118386118387118388118389118390118391118392118393118394118395118396118397118398118399118400118401118402118403118404118405118406118407118408118409118410118411118412118413118414118415118416118417118418118419118420118421118422118423118424118425118426118427118428118429118430118431118432118433118434118435118436118437118438118439118440118441118442118443118444118445118446118447118448118449118450118451118452118453118454118455118456118457118458118459118460118461118462118463118464118465118466118467118468118469118470118471118472118473118474118475118476118477118478118479118480118481118482118483118484118485118486118487118488118489118490118491118492118493118494118495118496118497118498118499118500118501118502118503118504118505118506118507118508118509118510118511118512118513118514118515118516118517118518118519118520118521118522118523118524118525118526118527118528118529118530118531118532118533118534118535118536118537118538118539118540118541118542118543118544118545118546118547118548118549118550118551118552118553118554118555118556118557118558118559118560118561118562118563118564118565118566118567118568118569118570118571118572118573118574118575118576118577118578118579118580118581118582118583118584118585118586118587118588118589118590118591118592118593118594118595118596118597118598118599118600118601118602118603118604118605118606118607118608118609118610118611118612118613118614118615118616118617118618118619118620118621118622118623118624118625118626118627118628118629118630118631118632118633118634118635118636118637118638118639118640118641118642118643118644118645118646118647118648118649118650118651118652118653118654118655118656118657118658118659118660118661118662118663118664118665118666118667118668118669118670118671118672118673118674118675118676118677118678118679118680118681118682118683118684118685118686118687118688118689118690118691118692118693118694118695118696118697118698118699118700118701118702118703118704118705118706118707118708118709118710118711118712118713118714118715118716118717118718118719118720118721118722118723118724118725118726118727118728118729118730118731118732118733118734118735118736118737118738118739118740118741118742118743118744118745118746118747118748118749118750118751118752118753118754118755118756118757118758118759118760118761118762118763118764118765118766118767118768118769118770118771118772118773118774118775118776118777118778118779118780118781118782118783118784118785118786118787118788118789118790118791118792118793118794118795118796118797118798118799118800118801118802118803118804118805118806118807118808118809118810118811118812118813118814118815118816118817118818118819118820118821118822118823118824118825118826118827118828118829118830118831118832118833118834118835118836118837118838118839118840118841118842118843118844118845118846118847118848118849118850118851118852118853118854118855118856118857118858118859118860118861118862118863118864118865118866118867118868118869118870118871118872118873118874118875118876118877118878118879118880118881118882118883118884118885118886118887118888118889118890118891118892118893118894118895118896118897118898118899118900118901118902118903118904118905118906118907118908118909118910118911118912118913118914118915118916118917118918118919118920118921118922118923118924118925118926118927118928118929118930118931118932118933118934118935118936118937118938118939118940118941118942118943118944118945118946118947118948118949118950118951118952118953118954118955118956118957118958118959118960118961118962118963118964118965118966118967118968118969118970118971118972118973118974118975118976118977118978118979118980118981118982118983118984118985118986118987118988118989118990118991118992118993118994118995118996118997118998118999119000119001119002119003119004119005119006119007119008119009119010119011119012119013119014119015119016119017119018119019119020119021119022119023119024119025119026119027119028119029119030119031119032119033119034119035119036119037119038119039119040119041119042119043119044119045119046119047119048119049119050119051119052119053119054119055119056119057119058119059119060119061119062119063119064119065119066119067119068119069119070119071119072119073119074119075119076119077119078119079119080119081119082119083119084119085119086119087119088119089119090119091119092119093119094119095119096119097119098119099119100119101119102119103119104119105119106119107119108119109119110119111119112119113119114119115119116119117119118119119119120119121119122119123119124119125119126119127119128119129119130119131119132119133119134119135119136119137119138119139119140119141119142119143119144119145119146119147119148119149119150119151119152119153119154119155119156119157119158119159119160119161119162119163119164119165119166119167119168119169119170119171119172119173119174119175119176119177119178119179119180119181119182119183119184119185119186119187119188119189119190119191119192119193119194119195119196119197119198119199119200119201119202119203119204119205119206119207119208119209119210119211119212119213119214119215119216119217119218119219119220119221119222119223119224119225119226119227119228119229119230119231119232119233119234119235119236119237119238119239119240119241119242119243119244119245119246119247119248119249119250119251119252119253119254119255119256119257119258119259119260119261119262119263119264119265119266119267119268119269119270119271119272119273119274119275119276119277119278119279119280119281119282119283119284119285119286119287119288119289119290119291119292119293119294119295119296119297119298119299119300119301119302119303119304119305119306119307119308119309119310119311119312119313119314119315119316119317119318119319119320119321119322119323119324119325119326119327119328119329119330119331119332119333119334119335119336119337119338119339119340119341119342119343119344119345119346119347119348119349119350119351119352119353119354119355119356119357119358119359119360119361119362119363119364119365119366119367119368119369119370119371119372119373119374119375119376119377119378119379119380119381119382119383119384119385119386119387119388119389119390119391119392119393119394119395119396119397119398119399119400119401119402119403119404119405119406119407119408119409119410119411119412119413119414119415119416119417119418119419119420119421119422119423119424119425119426119427119428119429119430119431119432119433119434119435119436119437119438119439119440119441119442119443119444119445119446119447119448119449119450119451119452119453119454119455119456119457119458119459119460119461119462119463119464119465119466119467119468119469119470119471119472119473119474119475119476119477119478119479119480119481119482119483119484119485119486119487119488119489119490119491119492119493119494119495119496119497119498119499119500119501119502119503119504119505119506119507119508119509119510119511119512119513119514119515119516119517119518119519119520119521119522119523119524119525119526119527119528119529119530119531119532119533119534119535119536119537119538119539119540119541119542119543119544119545119546119547119548119549119550119551119552119553119554119555119556119557119558119559119560119561119562119563119564119565119566119567119568119569119570119571119572119573119574119575119576119577119578119579119580119581119582119583119584119585119586119587119588119589119590119591119592119593119594119595119596119597119598119599119600119601119602119603119604119605119606119607119608119609119610119611119612119613119614119615119616119617119618119619119620119621119622119623119624119625119626119627119628119629119630119631119632119633119634119635119636119637119638119639119640119641119642119643119644119645119646119647119648119649119650119651119652119653119654119655119656119657119658119659119660119661119662119663119664119665119666119667119668119669119670119671119672119673119674119675119676119677119678119679119680119681119682119683119684119685119686119687119688119689119690119691119692119693119694119695119696119697119698119699119700119701119702119703119704119705119706119707119708119709119710119711119712119713119714119715119716119717119718119719119720119721119722119723119724119725119726119727119728119729119730119731119732119733119734119735119736119737119738119739119740119741119742119743119744119745119746119747119748119749119750119751119752119753119754119755119756119757119758119759119760119761119762119763119764119765119766119767119768119769119770119771119772119773119774119775119776119777119778119779119780119781119782119783119784119785119786119787119788119789119790119791119792119793119794119795119796119797119798119799119800119801119802119803119804119805119806119807119808119809119810119811119812119813119814119815119816119817119818119819119820119821119822119823119824119825119826119827119828119829119830119831119832119833119834119835119836119837119838119839119840119841119842119843119844119845119846119847119848119849119850119851119852119853119854119855119856119857119858119859119860119861119862119863119864119865119866119867119868119869119870119871119872119873119874119875119876119877119878119879119880119881119882119883119884119885119886119887119888119889119890119891119892119893119894119895119896119897119898119899119900119901119902119903119904119905119906119907119908119909119910119911119912119913119914119915119916119917119918119919119920119921119922119923119924119925119926119927119928119929119930119931119932119933119934119935119936119937119938119939119940119941119942119943119944119945119946119947119948119949119950119951119952119953119954119955119956119957119958119959119960119961119962119963119964119965119966119967119968119969119970119971119972119973119974119975119976119977119978119979119980119981119982119983119984119985119986119987119988119989119990119991119992119993119994119995119996119997119998119999120000120001120002120003120004120005120006120007120008120009120010120011120012120013120014120015120016120017120018120019120020120021120022120023120024120025120026120027120028120029120030120031120032120033120034120035120036120037120038120039120040120041120042120043120044120045120046120047120048120049120050120051120052120053120054120055120056120057120058120059120060120061120062120063120064120065120066120067120068120069120070120071120072120073120074120075120076120077120078120079120080120081120082120083120084120085120086120087120088120089120090120091120092120093120094120095120096120097120098120099120100120101120102120103120104120105120106120107120108120109120110120111120112120113120114120115120116120117120118120119120120120121120122120123120124120125120126120127120128120129120130120131120132120133120134120135120136120137120138120139120140120141120142120143120144120145120146120147120148120149120150120151120152120153120154120155120156120157120158120159120160120161120162120163120164120165120166120167120168120169120170120171120172120173120174120175120176120177120178120179120180120181120182120183120184120185120186120187120188120189120190120191120192120193120194120195120196120197120198120199120200120201120202120203120204120205120206120207120208120209120210120211120212120213120214120215120216120217120218120219120220120221120222120223120224120225120226120227120228120229120230120231120232120233120234120235120236120237120238120239120240120241120242120243120244120245120246120247120248120249120250120251120252120253120254120255120256120257120258120259120260120261120262120263120264120265120266120267120268120269120270120271120272120273120274120275120276120277120278120279120280120281120282120283120284120285120286120287120288120289120290120291120292120293120294120295120296120297120298120299120300120301120302120303120304120305120306120307120308120309120310120311120312120313120314120315120316120317120318120319120320120321120322120323120324120325120326120327120328120329120330120331120332120333120334120335120336120337120338120339120340120341120342120343120344120345120346120347120348120349120350120351120352120353120354120355120356120357120358120359120360120361120362120363120364120365120366120367120368120369120370120371120372120373120374120375120376120377120378120379120380120381120382120383120384120385120386120387120388120389120390120391120392120393120394120395120396120397120398120399120400120401120402120403120404120405120406120407120408120409120410120411120412120413120414120415120416120417120418120419120420120421120422120423120424120425120426120427120428120429120430120431120432120433120434120435120436120437120438120439120440120441120442120443120444120445120446120447120448120449120450120451120452120453120454120455120456120457120458120459120460120461120462120463120464120465120466120467120468120469120470120471120472120473120474120475120476120477120478120479120480120481120482120483120484120485120486120487120488120489120490120491120492120493120494120495120496120497120498120499120500120501120502120503120504120505120506120507120508120509120510120511120512120513120514120515120516120517120518120519120520120521120522120523120524120525120526120527120528120529120530120531120532120533120534120535120536120537120538120539120540120541120542120543120544120545120546120547120548120549120550120551120552120553120554120555120556120557120558120559120560120561120562120563120564120565120566120567120568120569120570120571120572120573120574120575120576120577120578120579120580120581120582120583120584120585120586120587120588120589120590120591120592120593120594120595120596120597120598120599120600120601120602120603120604120605120606120607120608120609120610120611120612120613120614120615120616120617120618120619120620120621120622120623120624120625120626120627120628120629120630120631120632120633120634120635120636120637120638120639120640120641120642120643120644120645120646120647120648120649120650120651120652120653120654120655120656120657120658120659120660120661120662120663120664120665120666120667120668120669120670120671120672120673120674120675120676120677120678120679120680120681120682120683120684120685120686120687120688120689120690120691120692120693120694120695120696120697120698120699120700120701120702120703120704120705120706120707120708120709120710120711120712120713120714120715120716120717120718120719120720120721120722120723120724120725120726120727120728120729120730120731120732120733120734120735120736120737120738120739120740120741120742120743120744120745120746120747120748120749120750120751120752120753120754120755120756120757120758120759120760120761120762120763120764120765120766120767120768120769120770120771120772120773120774120775120776120777120778120779120780120781120782120783120784120785120786120787120788120789120790120791120792120793120794120795120796120797120798120799120800120801120802120803120804120805120806120807120808120809120810120811120812120813120814120815120816120817120818120819120820120821120822120823120824120825120826120827120828120829120830120831120832120833120834120835120836120837120838120839120840120841120842120843120844120845120846120847120848120849120850120851120852120853120854120855120856120857120858120859120860120861120862120863120864120865120866120867120868120869120870120871120872120873120874120875120876120877120878120879120880120881120882120883120884120885120886120887120888120889120890120891120892120893120894120895120896120897120898120899120900120901120902120903120904120905120906120907120908120909120910120911120912120913120914120915120916120917120918120919120920120921120922120923120924120925120926120927120928120929120930120931120932120933120934120935120936120937120938120939120940120941120942120943120944120945120946120947120948120949120950120951120952120953120954120955120956120957120958120959120960120961120962120963120964120965120966120967120968120969120970120971120972120973120974120975120976120977120978120979120980120981120982120983120984120985120986120987120988120989120990120991120992120993120994120995120996120997120998120999121000121001121002121003121004121005121006121007121008121009121010121011121012121013121014121015121016121017121018121019121020121021121022121023121024121025121026121027121028121029121030121031121032121033121034121035121036121037121038121039121040121041121042121043121044121045121046121047121048121049121050121051121052121053121054121055121056121057121058121059121060121061121062121063121064121065121066121067121068121069121070121071121072121073121074121075121076121077121078121079121080121081121082121083121084121085121086121087121088121089121090121091121092121093121094121095121096121097121098121099121100121101121102121103121104121105121106121107121108121109121110121111121112121113121114121115121116121117121118121119121120121121121122121123121124121125121126121127121128121129121130121131121132121133121134121135121136121137121138121139121140121141121142121143121144121145121146121147121148121149121150121151121152121153121154121155121156121157121158121159121160121161121162121163121164121165121166121167121168121169121170121171121172121173121174121175121176121177121178121179121180121181121182121183121184121185121186121187121188121189121190121191121192121193121194121195121196121197121198121199121200121201121202121203121204121205121206121207121208121209121210121211121212121213121214121215121216121217121218121219121220121221121222121223121224121225121226121227121228121229121230121231121232121233121234121235121236121237121238121239121240121241121242121243121244121245121246121247121248121249121250121251121252121253121254121255121256121257121258121259121260121261121262121263121264121265121266121267121268121269121270121271121272121273121274121275121276121277121278121279121280121281121282121283121284121285121286121287121288121289121290121291121292121293121294121295121296121297121298121299121300121301121302121303121304121305121306121307121308121309121310121311121312121313121314121315121316121317121318121319121320121321121322121323121324121325121326121327121328121329121330121331121332121333121334121335121336121337121338121339121340121341121342121343121344121345121346121347121348121349121350121351121352121353121354121355121356121357121358121359121360121361121362121363121364121365121366121367121368121369121370121371121372121373121374121375121376121377121378121379121380121381121382121383121384121385121386121387121388121389121390121391121392121393121394121395121396121397121398121399121400121401121402121403121404121405121406121407121408121409121410121411121412121413121414121415121416121417121418121419121420121421121422121423121424121425121426121427121428121429121430121431121432121433121434121435121436121437121438121439121440121441121442121443121444121445121446121447121448121449121450121451121452121453121454121455121456121457121458121459121460121461121462121463121464121465121466121467121468121469121470121471121472121473121474121475121476121477121478121479121480121481121482121483121484121485121486121487121488121489121490121491121492121493121494121495121496121497121498121499121500121501121502121503121504121505121506121507121508121509121510121511121512121513121514121515121516121517121518121519121520121521121522121523121524121525121526121527121528121529121530121531121532121533121534121535121536121537121538121539121540121541121542121543121544121545121546121547121548121549121550121551121552121553121554121555121556121557121558121559121560121561121562121563121564121565121566121567121568121569121570121571121572121573121574121575121576121577121578121579121580121581121582121583121584121585121586121587121588121589121590121591121592121593121594121595121596121597121598121599121600121601121602121603121604121605121606121607121608121609121610121611121612121613121614121615121616121617121618121619121620121621121622121623121624121625121626121627121628121629121630121631121632121633121634121635121636121637121638121639121640121641121642121643121644121645121646121647121648121649121650121651121652121653121654121655121656121657121658121659121660121661121662121663121664121665121666121667121668121669121670121671121672121673121674121675121676121677121678121679121680121681121682121683121684121685121686121687121688121689121690121691121692121693121694121695121696121697121698121699121700121701121702121703121704121705121706121707121708121709121710121711121712121713121714121715121716121717121718121719121720121721121722121723121724121725121726121727121728121729121730121731121732121733121734121735121736121737121738121739121740121741121742121743121744121745121746121747121748121749121750121751121752121753121754121755121756121757121758121759121760121761121762121763121764121765121766121767121768121769121770121771121772121773121774121775121776121777121778121779121780121781121782121783121784121785121786121787121788121789121790121791121792121793121794121795121796121797121798121799121800121801121802121803121804121805121806121807121808121809121810121811121812121813121814121815121816121817121818121819121820121821121822121823121824121825121826121827121828121829121830121831121832121833121834121835121836121837121838121839121840121841121842121843121844121845121846121847121848121849121850121851121852121853121854121855121856121857121858121859121860121861121862121863121864121865121866121867121868121869121870121871121872121873121874121875121876121877121878121879121880121881121882121883121884121885121886121887121888121889121890121891121892121893121894121895121896121897121898121899121900121901121902121903121904121905121906121907121908121909121910121911121912121913121914121915121916121917121918121919121920121921121922121923121924121925121926121927121928121929121930121931121932121933121934121935121936121937121938121939121940121941121942121943121944121945121946121947121948121949121950121951121952121953121954121955121956121957121958121959121960121961121962121963121964121965121966121967121968121969121970121971121972121973121974121975121976121977121978121979121980121981121982121983121984121985121986121987121988121989121990121991121992121993121994121995121996121997121998121999122000122001122002122003122004122005122006122007122008122009122010122011122012122013122014122015122016122017122018122019122020122021122022122023122024122025122026122027122028122029122030122031122032122033122034122035122036122037122038122039122040122041122042122043122044122045122046122047122048122049122050122051122052122053122054122055122056122057122058122059122060122061122062122063122064122065122066122067122068122069122070122071122072122073122074122075122076122077122078122079122080122081122082122083122084122085122086122087122088122089122090122091122092122093122094122095122096122097122098122099122100122101122102122103122104122105122106122107122108122109122110122111122112122113122114122115122116122117122118122119122120122121122122122123122124122125122126122127122128122129122130122131122132122133122134122135122136122137122138122139122140122141122142122143122144122145122146122147122148122149122150122151122152122153122154122155122156122157122158122159122160122161122162122163122164122165122166122167122168122169122170122171122172122173122174122175122176122177122178122179122180122181122182122183122184122185122186122187122188122189122190122191122192122193122194122195122196122197122198122199122200122201122202122203122204122205122206122207122208122209122210122211122212122213122214122215122216122217122218122219122220122221122222122223122224122225122226122227122228122229122230122231122232122233122234122235122236122237122238122239122240122241122242122243122244122245122246122247122248122249122250122251122252122253122254122255122256122257122258122259122260122261122262122263122264122265122266122267122268122269122270122271122272122273122274122275122276122277122278122279122280122281122282122283122284122285122286122287122288122289122290122291122292122293122294122295122296122297122298122299122300122301122302122303122304122305122306122307122308122309122310122311122312122313122314122315122316122317122318122319122320122321122322122323122324122325122326122327122328122329122330122331122332122333122334122335122336122337122338122339122340122341122342122343122344122345122346122347122348122349122350122351122352122353122354122355122356122357122358122359122360122361122362122363122364122365122366122367122368122369122370122371122372122373122374122375122376122377122378122379122380122381122382122383122384122385122386122387122388122389122390122391122392122393122394122395122396122397122398122399122400122401122402122403122404122405122406122407122408122409122410122411122412122413122414122415122416122417122418122419122420122421122422122423122424122425122426122427122428122429122430122431122432122433122434122435122436122437122438122439122440122441122442122443122444122445122446122447122448122449122450122451122452122453122454122455122456122457122458122459122460122461122462122463122464122465122466122467122468122469122470122471122472122473122474122475122476122477122478122479122480122481122482122483122484122485122486122487122488122489122490122491122492122493122494122495122496122497122498122499122500122501122502122503122504122505122506122507122508122509122510122511122512122513122514122515122516122517122518122519122520122521122522122523122524122525122526122527122528122529122530122531122532122533122534122535122536122537122538122539122540122541122542122543122544122545122546122547122548122549122550122551122552122553122554122555122556122557122558122559122560122561122562122563122564122565122566122567122568122569122570122571122572122573122574122575122576122577122578122579122580122581122582122583122584122585122586122587122588122589122590122591122592122593122594122595122596122597122598122599122600122601122602122603122604122605122606122607122608122609122610122611122612122613122614122615122616122617122618122619122620122621122622122623122624122625122626122627122628122629122630122631122632122633122634122635122636122637122638122639122640122641122642122643122644122645122646122647122648122649122650122651122652122653122654122655122656122657122658122659122660122661122662122663122664122665122666122667122668122669122670122671122672122673122674122675122676122677122678122679122680122681122682122683122684122685122686122687122688122689122690122691122692122693122694122695122696122697122698122699122700122701122702122703122704122705122706122707122708122709122710122711122712122713122714122715122716122717122718122719122720122721122722122723122724122725122726122727122728122729122730122731122732122733122734122735122736122737122738122739122740122741122742122743122744122745122746122747122748122749122750122751122752122753122754122755122756122757122758122759122760122761122762122763122764122765122766122767122768122769122770122771122772122773122774122775122776122777122778122779122780122781122782122783122784122785122786122787122788122789122790122791122792122793122794122795122796122797122798122799122800122801122802122803122804122805122806122807122808122809122810122811122812122813122814122815122816122817122818122819122820122821122822122823122824122825122826122827122828122829122830122831122832122833122834122835122836122837122838122839122840122841122842122843122844122845122846122847122848122849122850122851122852122853122854122855122856122857122858122859122860122861122862122863122864122865122866122867122868122869122870122871122872122873122874122875122876122877122878122879122880122881122882122883122884122885122886122887122888122889122890122891122892122893122894122895122896122897122898122899122900122901122902122903122904122905122906122907122908122909122910122911122912122913122914122915122916122917122918122919122920122921122922122923122924122925122926122927122928122929122930122931122932122933122934122935122936122937122938122939122940122941122942122943122944122945122946122947122948122949122950122951122952122953122954122955122956122957122958122959122960122961122962122963122964122965122966122967122968122969122970122971122972122973122974122975122976122977122978122979122980122981122982122983122984122985122986122987122988122989122990122991122992122993122994122995122996122997122998122999123000123001123002123003123004123005123006123007123008123009123010123011123012123013123014123015123016123017123018123019123020123021123022123023123024123025123026123027123028123029123030123031123032123033123034123035123036123037123038123039123040123041123042123043123044123045123046123047123048123049123050123051123052123053123054123055123056123057123058123059123060123061123062123063123064123065123066123067123068123069123070123071123072123073123074123075123076123077123078123079123080123081123082123083123084123085123086123087123088123089123090123091123092123093123094123095123096123097123098123099123100123101123102123103123104123105123106123107123108123109123110123111123112123113123114123115123116123117123118123119123120123121123122123123123124123125123126123127123128123129123130123131123132123133123134123135123136123137123138123139123140123141123142123143123144123145123146123147123148123149123150123151123152123153123154123155123156123157123158123159123160123161123162123163123164123165123166123167123168123169123170123171123172123173123174123175123176123177123178123179123180123181123182123183123184123185123186123187123188123189123190123191123192123193123194123195123196123197123198123199123200123201123202123203123204123205123206123207123208123209123210123211123212123213123214123215123216123217123218123219123220123221123222123223123224123225123226123227123228123229123230123231123232123233123234123235123236123237123238123239123240123241123242123243123244123245123246123247123248123249123250123251123252123253123254123255123256123257123258123259123260123261123262123263123264123265123266123267123268123269123270123271123272123273123274123275123276123277123278123279123280123281123282123283123284123285123286123287123288123289123290123291123292123293123294123295123296123297123298123299123300123301123302123303123304123305123306123307123308123309123310123311123312123313123314123315123316123317123318123319123320123321123322123323123324123325123326123327123328123329123330123331123332123333123334123335123336123337123338123339123340123341123342123343123344123345123346123347123348123349123350123351123352123353123354123355123356123357123358123359123360123361123362123363123364123365123366123367123368123369123370123371123372123373123374123375123376123377123378123379123380123381123382123383123384123385123386123387123388123389123390123391123392123393123394123395123396123397123398123399123400123401123402123403123404123405123406123407123408123409123410123411123412123413123414123415123416123417123418123419123420123421123422123423123424123425123426123427123428123429123430123431123432123433123434123435123436123437123438123439123440123441123442123443123444123445123446123447123448123449123450123451123452123453123454123455123456123457123458123459123460123461123462123463123464123465123466123467123468123469123470123471123472123473123474123475123476123477123478123479123480123481123482123483123484123485123486123487123488123489123490123491123492123493123494123495123496123497123498123499123500123501123502123503123504123505123506123507123508123509123510123511123512123513123514123515123516123517123518123519123520123521123522123523123524123525123526123527123528123529123530123531123532123533123534123535123536123537123538123539123540123541123542123543123544123545123546123547123548123549123550123551123552123553123554123555123556123557123558123559123560123561123562123563123564123565123566123567123568123569123570123571123572123573123574123575123576123577123578123579123580123581123582123583123584123585123586123587123588123589123590123591123592123593123594123595123596123597123598123599123600123601123602123603123604123605123606123607123608123609123610123611123612123613123614123615123616123617123618123619123620123621123622123623123624123625123626123627123628123629123630123631123632123633123634123635123636123637123638123639123640123641123642123643123644123645123646123647123648123649123650123651123652123653123654123655123656123657123658123659123660123661123662123663123664123665123666123667123668123669123670123671123672123673123674123675123676123677123678123679123680123681123682123683123684123685123686123687123688123689123690123691123692123693123694123695123696123697123698123699123700123701123702123703123704123705123706123707123708123709123710123711123712123713123714123715123716123717123718123719123720123721123722123723123724123725123726123727123728123729123730123731123732123733123734123735123736123737123738123739123740123741123742123743123744123745123746123747123748123749123750123751123752123753123754123755123756123757123758123759123760123761123762123763123764123765123766123767123768123769123770123771123772123773123774123775123776123777123778123779123780123781123782123783123784123785123786123787123788123789123790123791123792123793123794123795123796123797123798123799123800123801123802123803123804123805123806123807123808123809123810123811123812123813123814123815123816123817123818123819123820123821123822123823123824123825123826123827123828123829123830123831123832123833123834123835123836123837123838123839123840123841123842123843123844123845123846123847123848123849123850123851123852123853123854123855123856123857123858123859123860123861123862123863123864123865123866123867123868123869123870123871123872123873123874123875123876123877123878123879123880123881123882123883123884123885123886123887123888123889123890123891123892123893123894123895123896123897123898123899123900123901123902123903123904123905123906123907123908123909123910123911123912123913123914123915123916123917123918123919123920123921123922123923123924123925123926123927123928123929123930123931123932123933123934123935123936123937123938123939123940123941123942123943123944123945123946123947123948123949123950123951123952123953123954123955123956123957123958123959123960123961123962123963123964123965123966123967123968123969123970123971123972123973123974123975123976123977123978123979123980123981123982123983123984123985123986123987123988123989123990123991123992123993123994123995123996123997123998123999124000124001124002124003124004124005124006124007124008124009124010124011124012124013124014124015124016124017124018124019124020124021124022124023124024124025124026124027124028124029124030124031124032124033124034124035124036124037124038124039124040124041124042124043124044124045124046124047124048124049124050124051124052124053124054124055124056124057124058124059124060124061124062124063124064124065124066124067124068124069124070124071124072124073124074124075124076124077124078124079124080124081124082124083124084124085124086124087124088124089124090124091124092124093124094124095124096124097124098124099124100124101124102124103124104124105124106124107124108124109124110124111124112124113124114124115124116124117124118124119124120124121124122124123124124124125124126124127124128124129124130124131124132124133124134124135124136124137124138124139124140124141124142124143124144124145124146124147124148124149124150124151124152124153124154124155124156124157124158124159124160124161124162124163124164124165124166124167124168124169124170124171124172124173124174124175124176124177124178124179124180124181124182124183124184124185124186124187124188124189124190124191124192124193124194124195124196124197124198124199124200124201124202124203124204124205124206124207124208124209124210124211124212124213124214124215124216124217124218124219124220124221124222124223124224124225124226124227124228124229124230124231124232124233124234124235124236124237124238124239124240124241124242124243124244124245124246124247124248124249124250124251124252124253124254124255124256124257124258124259124260124261124262124263124264124265124266124267124268124269124270124271124272124273124274124275124276124277124278124279124280124281124282124283124284124285124286124287124288124289124290124291124292124293124294124295124296124297124298124299124300124301124302124303124304124305124306124307124308124309124310124311124312124313124314124315124316124317124318124319124320124321124322124323124324124325124326124327124328124329124330124331124332124333124334124335124336124337124338124339124340124341124342124343124344124345124346124347124348124349124350124351124352124353124354124355124356124357124358124359124360124361124362124363124364124365124366124367124368124369124370124371124372124373124374124375124376124377124378124379124380124381124382124383124384124385124386124387124388124389124390124391124392124393124394124395124396124397124398124399124400124401124402124403124404124405124406124407124408124409124410124411124412124413124414124415124416124417124418124419124420124421124422124423124424124425124426124427124428124429124430124431124432124433124434124435124436124437124438124439124440124441124442124443124444124445124446124447124448124449124450124451124452124453124454124455124456124457124458124459124460124461124462124463124464124465124466124467124468124469124470124471124472124473124474124475124476124477124478124479124480124481124482124483124484124485124486124487124488124489124490124491124492124493124494124495124496124497124498124499124500124501124502124503124504124505124506124507124508124509124510124511124512124513124514124515124516124517124518124519124520124521124522124523124524124525124526124527124528124529124530124531124532124533124534124535124536124537124538124539124540124541124542124543124544124545124546124547124548124549124550124551124552124553124554124555124556124557124558124559124560124561124562124563124564124565124566124567124568124569124570124571124572124573124574124575124576124577124578124579124580124581124582124583124584124585124586124587124588124589124590124591124592124593124594124595124596124597124598124599124600124601124602124603124604124605124606124607124608124609124610124611124612124613124614124615124616124617124618124619124620124621124622124623124624124625124626124627124628124629124630124631124632124633124634124635124636124637124638124639124640124641124642124643124644124645124646124647124648124649124650124651124652124653124654124655124656124657124658124659124660124661124662124663124664124665124666124667124668124669124670124671124672124673124674124675124676124677124678124679124680124681124682124683124684124685124686124687124688124689124690124691124692124693124694124695124696124697124698124699124700124701124702124703124704124705124706124707124708124709124710124711124712124713124714124715124716124717124718124719124720124721124722124723124724124725124726124727124728124729124730124731124732124733124734124735124736124737124738124739124740124741124742124743124744124745124746124747124748124749124750124751124752124753124754124755124756124757124758124759124760124761124762124763124764124765124766124767124768124769124770124771124772124773124774124775124776124777124778124779124780124781124782124783124784124785124786124787124788124789124790124791124792124793124794124795124796124797124798124799124800124801124802124803124804124805124806124807124808124809124810124811124812124813124814124815124816124817124818124819124820124821124822124823124824124825124826124827124828124829124830124831124832124833124834124835124836124837124838124839124840124841124842124843124844124845124846124847124848124849124850124851124852124853124854124855124856124857124858124859124860124861124862124863124864124865124866124867124868124869124870124871124872124873124874124875124876124877124878124879124880124881124882124883124884124885124886124887124888124889124890124891124892124893124894124895124896124897124898124899124900124901124902124903124904124905124906124907124908124909124910124911124912124913124914124915124916124917124918124919124920124921124922124923124924124925124926124927124928124929124930124931124932124933124934124935124936124937124938124939124940124941124942124943124944124945124946124947124948124949124950124951124952124953124954124955124956124957124958124959124960124961124962124963124964124965124966124967124968124969124970124971124972124973124974124975124976124977124978124979124980124981124982124983124984124985124986124987124988124989124990124991124992124993124994124995124996124997124998124999125000125001125002125003125004125005125006125007125008125009125010125011125012125013125014125015125016125017125018125019125020125021125022125023125024125025125026125027125028125029125030125031125032125033125034125035125036125037125038125039125040125041125042125043125044125045125046125047125048125049125050125051125052125053125054125055125056125057125058125059125060125061125062125063125064125065125066125067125068125069125070125071125072125073125074125075125076125077125078125079125080125081125082125083125084125085125086125087125088125089125090125091125092125093125094125095125096125097125098125099125100125101125102125103125104125105125106125107125108125109125110125111125112125113125114125115125116125117125118125119125120125121125122125123125124125125125126125127125128125129125130125131125132125133125134125135125136125137125138125139125140125141125142125143125144125145125146125147125148125149125150125151125152125153125154125155125156125157125158125159125160125161125162125163125164125165125166125167125168125169125170125171125172125173125174125175125176125177125178125179125180125181125182125183125184125185125186125187125188125189125190125191125192125193125194125195125196125197125198125199125200125201125202125203125204125205125206125207125208125209125210125211125212125213125214125215125216125217125218125219125220125221125222125223125224125225125226125227125228125229125230125231125232125233125234125235125236125237125238125239125240125241125242125243125244125245125246125247125248125249125250125251125252125253125254125255125256125257125258125259125260125261125262125263125264125265125266125267125268125269125270125271125272125273125274125275125276125277125278125279125280125281125282125283125284125285125286125287125288125289125290125291125292125293125294125295125296125297125298125299125300125301125302125303125304125305125306125307125308125309125310125311125312125313125314125315125316125317125318125319125320125321125322125323125324125325125326125327125328125329125330125331125332125333125334125335125336125337125338125339125340125341125342125343125344125345125346125347125348125349125350125351125352125353125354125355125356125357125358125359125360125361125362125363125364125365125366125367125368125369125370125371125372125373125374125375125376125377125378125379125380125381125382125383125384125385125386125387125388125389125390125391125392125393125394125395125396125397125398125399125400125401125402125403125404125405125406125407125408125409125410125411125412125413125414125415125416125417125418125419125420125421125422125423125424125425125426125427125428125429125430125431125432125433125434125435125436125437125438125439125440125441125442125443125444125445125446125447125448125449125450125451125452125453125454125455125456125457125458125459125460125461125462125463125464125465125466125467125468125469125470125471125472125473125474125475125476125477125478125479125480125481125482125483125484125485125486125487125488125489125490125491125492125493125494125495125496125497125498125499125500125501125502125503125504125505125506125507125508125509125510125511125512125513125514125515125516125517125518125519125520125521125522125523125524125525125526125527125528125529125530125531125532125533125534125535125536125537125538125539125540125541125542125543125544125545125546125547125548125549125550125551125552125553125554125555125556125557125558125559125560125561125562125563125564125565125566125567125568125569125570125571125572125573125574125575125576125577125578125579125580125581125582125583125584125585125586125587125588125589125590125591125592125593125594125595125596125597125598125599125600125601125602125603125604125605125606125607125608125609125610125611125612125613125614125615125616125617125618125619125620125621125622125623125624125625125626125627125628125629125630125631125632125633125634125635125636125637125638125639125640125641125642125643125644125645125646125647125648125649125650125651125652125653125654125655125656125657125658125659125660125661125662125663125664125665125666125667125668125669125670125671125672125673125674125675125676125677125678125679125680125681125682125683125684125685125686125687125688125689125690125691125692125693125694125695125696125697125698125699125700125701125702125703125704125705125706125707125708125709125710125711125712125713125714125715125716125717125718125719125720125721125722125723125724125725125726125727125728125729125730125731125732125733125734125735125736125737125738125739125740125741125742125743125744125745125746125747125748125749125750125751125752125753125754125755125756125757125758125759125760125761125762125763125764125765125766125767125768125769125770125771125772125773125774125775125776125777125778125779125780125781125782125783125784125785125786125787125788125789125790125791125792125793125794125795125796125797125798125799125800125801125802125803125804125805125806125807125808125809125810125811125812125813125814125815125816125817125818125819125820125821125822125823125824125825125826125827125828125829125830125831125832125833125834125835125836125837125838125839125840125841125842125843125844125845125846125847125848125849125850125851125852125853125854125855125856125857125858125859125860125861125862125863125864125865125866125867125868125869125870125871125872125873125874125875125876125877125878125879125880125881125882125883125884125885125886125887125888125889125890125891125892125893125894125895125896125897125898125899125900125901125902125903125904125905125906125907125908125909125910125911125912125913125914125915125916125917125918125919125920125921125922125923125924125925125926125927125928125929125930125931125932125933125934125935125936125937125938125939125940125941125942125943125944125945125946125947125948125949125950125951125952125953125954125955125956125957125958125959125960125961125962125963125964125965125966125967125968125969125970125971125972125973125974125975125976125977125978125979125980125981125982125983125984125985125986125987125988125989125990125991125992125993125994125995125996125997125998125999126000126001126002126003126004126005126006126007126008126009126010126011126012126013126014126015126016126017126018126019126020126021126022126023126024126025126026126027126028126029126030126031126032126033126034126035126036126037126038126039126040126041126042126043126044126045126046126047126048126049126050126051126052126053126054126055126056126057126058126059126060126061126062126063126064126065126066126067126068126069126070126071126072126073126074126075126076126077126078126079126080126081126082126083126084126085126086126087126088126089126090126091126092126093126094126095126096126097126098126099126100126101126102126103126104126105126106126107126108126109126110126111126112126113126114126115126116126117126118126119126120126121126122126123126124126125126126126127126128126129126130126131126132126133126134126135126136126137126138126139126140126141126142126143126144126145126146126147126148126149126150126151126152126153126154126155126156126157126158126159126160126161126162126163126164126165126166126167126168126169126170126171126172126173126174126175126176126177126178126179126180126181126182126183126184126185126186126187126188126189126190126191126192126193126194126195126196126197126198126199126200126201126202126203126204126205126206126207126208126209126210126211126212126213126214126215126216126217126218126219126220126221126222126223126224126225126226126227126228126229126230126231126232126233126234126235126236126237126238126239126240126241126242126243126244126245126246126247126248126249126250126251126252126253126254126255126256126257126258126259126260126261126262126263126264126265126266126267126268126269126270126271126272126273126274126275126276126277126278126279126280126281126282126283126284126285126286126287126288126289126290126291126292126293126294126295126296126297126298126299126300126301126302126303126304126305126306126307126308126309126310126311126312126313126314126315126316126317126318126319126320126321126322126323126324126325126326126327126328126329126330126331126332126333126334126335126336126337126338126339126340126341126342126343126344126345126346126347126348126349126350126351126352126353126354126355126356126357126358126359126360126361126362126363126364126365126366126367126368126369126370126371126372126373126374126375126376126377126378126379126380126381126382126383126384126385126386126387126388126389126390126391126392126393126394126395126396126397126398126399126400126401126402126403126404126405126406126407126408126409126410126411126412126413126414126415126416126417126418126419126420126421126422126423126424126425126426126427126428126429126430126431126432126433126434126435126436126437126438126439126440126441126442126443126444126445126446126447126448126449126450126451126452126453126454126455126456126457126458126459126460126461126462126463126464126465126466126467126468126469126470126471126472126473126474126475126476126477126478126479126480126481126482126483126484126485126486126487126488126489126490126491126492126493126494126495126496126497126498126499126500126501126502126503126504126505126506126507126508126509126510126511126512126513126514126515126516126517126518126519126520126521126522126523126524126525126526126527126528126529126530126531126532126533126534126535126536126537126538126539126540126541126542126543126544126545126546126547126548126549126550126551126552126553126554126555126556126557126558126559126560126561126562126563126564126565126566126567126568126569126570126571126572126573126574126575126576126577126578126579126580126581126582126583126584126585126586126587126588126589126590126591126592126593126594126595126596126597126598126599126600126601126602126603126604126605126606126607126608126609126610126611126612126613126614126615126616126617126618126619126620126621126622126623126624126625126626126627126628126629126630126631126632126633126634126635126636126637126638126639126640126641126642126643126644126645126646126647126648126649126650126651126652126653126654126655126656126657126658126659126660126661126662126663126664126665126666126667126668126669126670126671126672126673126674126675126676126677126678126679126680126681126682126683126684126685126686126687126688126689126690126691126692126693126694126695126696126697126698126699126700126701126702126703126704126705126706126707126708126709126710126711126712126713126714126715126716126717126718126719126720126721126722126723126724126725126726126727126728126729126730126731126732126733126734126735126736126737126738126739126740126741126742126743126744126745126746126747126748126749126750126751126752126753126754126755126756126757126758126759126760126761126762126763126764126765126766126767126768126769126770126771126772126773126774126775126776126777126778126779126780126781126782126783126784126785126786126787126788126789126790126791126792126793126794126795126796126797126798126799126800126801126802126803126804126805126806126807126808126809126810126811126812126813126814126815126816126817126818126819126820126821126822126823126824126825126826126827126828126829126830126831126832126833126834126835126836126837126838126839126840126841126842126843126844126845126846126847126848126849126850126851126852126853126854126855126856126857126858126859126860126861126862126863126864126865126866126867126868126869126870126871126872126873126874126875126876126877126878126879126880126881126882126883126884126885126886126887126888126889126890126891126892126893126894126895126896126897126898126899126900126901126902126903126904126905126906126907126908126909126910126911126912126913126914126915126916126917126918126919126920126921126922126923126924126925126926126927126928126929126930126931126932126933126934126935126936126937126938126939126940126941126942126943126944126945126946126947126948126949126950126951126952126953126954126955126956126957126958126959126960126961126962126963126964126965126966126967126968126969126970126971126972126973126974126975126976126977126978126979126980126981126982126983126984126985126986126987126988126989126990126991126992126993126994126995126996126997126998126999127000127001127002127003127004127005127006127007127008127009127010127011127012127013127014127015127016127017127018127019127020127021127022127023127024127025127026127027127028127029127030127031127032127033127034127035127036127037127038127039127040127041127042127043127044127045127046127047127048127049127050127051127052127053127054127055127056127057127058127059127060127061127062127063127064127065127066127067127068127069127070127071127072127073127074127075127076127077127078127079127080127081127082127083127084127085127086127087127088127089127090127091127092127093127094127095127096127097127098127099127100127101127102127103127104127105127106127107127108127109127110127111127112127113127114127115127116127117127118127119127120127121127122127123127124127125127126127127127128127129127130127131127132127133127134127135127136127137127138127139127140127141127142127143127144127145127146127147127148127149127150127151127152127153127154127155127156127157127158127159127160127161127162127163127164127165127166127167127168127169127170127171127172127173127174127175127176127177127178127179127180127181127182127183127184127185127186127187127188127189127190127191127192127193127194127195127196127197127198127199127200127201127202127203127204127205127206127207127208127209127210127211127212127213127214127215127216127217127218127219127220127221127222127223127224127225127226127227127228127229127230127231127232127233127234127235127236127237127238127239127240127241127242127243127244127245127246127247127248127249127250127251127252127253127254127255127256127257127258127259127260127261127262127263127264127265127266127267127268127269127270127271127272127273127274127275127276127277127278127279127280127281127282127283127284127285127286127287127288127289127290127291127292127293127294127295127296127297127298127299127300127301127302127303127304127305127306127307127308127309127310127311127312127313127314127315127316127317127318127319127320127321127322127323127324127325127326127327127328127329127330127331127332127333127334127335127336127337127338127339127340127341127342127343127344127345127346127347127348127349127350127351127352127353127354127355127356127357127358127359127360127361127362127363127364127365127366127367127368127369127370127371127372127373127374127375127376127377127378127379127380127381127382127383127384127385127386127387127388127389127390127391127392127393127394127395127396127397127398127399127400127401127402127403127404127405127406127407127408127409127410127411127412127413127414127415127416127417127418127419127420127421127422127423127424127425127426127427127428127429127430127431127432127433127434127435127436127437127438127439127440127441127442127443127444127445127446127447127448127449127450127451127452127453127454127455127456127457127458127459127460127461127462127463127464127465127466127467127468127469127470127471127472127473127474127475127476127477127478127479127480127481127482127483127484127485127486127487127488127489127490127491127492127493127494127495127496127497127498127499127500127501127502127503127504127505127506127507127508127509127510127511127512127513127514127515127516127517127518127519127520127521127522127523127524127525127526127527127528127529127530127531127532127533127534127535127536127537127538127539127540127541127542127543127544127545127546127547127548127549127550127551127552127553127554127555127556127557127558127559127560127561127562127563127564127565127566127567127568127569127570127571127572127573127574127575127576127577127578127579127580127581127582127583127584127585127586127587127588127589127590127591127592127593127594127595127596127597127598127599127600127601127602127603127604127605127606127607127608127609127610127611127612127613127614127615127616127617127618127619127620127621127622127623127624127625127626127627127628127629127630127631127632127633127634127635127636127637127638127639127640127641127642127643127644127645127646127647127648127649127650127651127652127653127654127655127656127657127658127659127660127661127662127663127664127665127666127667127668127669127670127671127672127673127674127675127676127677127678127679127680127681127682127683127684127685127686127687127688127689127690127691127692127693127694127695127696127697127698127699127700127701127702127703127704127705127706127707127708127709127710127711127712127713127714127715127716127717127718127719127720127721127722127723127724127725127726127727127728127729127730127731127732127733127734127735127736127737127738127739127740127741127742127743127744127745127746127747127748127749127750127751127752127753127754127755127756127757127758127759127760127761127762127763127764127765127766127767127768127769127770127771127772127773127774127775127776127777127778127779127780127781127782127783127784127785127786127787127788127789127790127791127792127793127794127795127796127797127798127799127800127801127802127803127804127805127806127807127808127809127810127811127812127813127814127815127816127817127818127819127820127821127822127823127824127825127826127827127828127829127830127831127832127833127834127835127836127837127838127839127840127841127842127843127844127845127846127847127848127849127850127851127852127853127854127855127856127857127858127859127860127861127862127863127864127865127866127867127868127869127870127871127872127873127874127875127876127877127878127879127880127881127882127883127884127885127886127887127888127889127890127891127892127893127894127895127896127897127898127899127900127901127902127903127904127905127906127907127908127909127910127911127912127913127914127915127916127917127918127919127920127921127922127923127924127925127926127927127928127929127930127931127932127933127934127935127936127937127938127939127940127941127942127943127944127945127946127947127948127949127950127951127952127953127954127955127956127957127958127959127960127961127962127963127964127965127966127967127968127969127970127971127972127973127974127975127976127977127978127979127980127981127982127983127984127985127986127987127988127989127990127991127992127993127994127995127996127997127998127999128000128001128002128003128004128005128006128007128008128009128010128011128012128013128014128015128016128017128018128019128020128021128022128023128024128025128026128027128028128029128030128031128032128033128034128035128036128037128038128039128040128041128042128043128044128045128046128047128048128049128050128051128052128053128054128055128056128057128058128059128060128061128062128063128064128065128066128067128068128069128070128071128072128073128074128075128076128077128078128079128080128081128082128083128084128085128086128087128088128089128090128091128092128093128094128095128096128097128098128099128100128101128102128103128104128105128106128107128108128109128110128111128112128113128114128115128116128117128118128119128120128121128122128123128124128125128126128127128128128129128130128131128132128133128134128135128136128137128138128139128140128141128142128143128144128145128146128147128148128149128150128151128152128153128154128155128156128157128158128159128160128161128162128163128164128165128166128167128168128169128170128171128172128173128174128175128176128177128178128179128180128181128182128183128184128185128186128187128188128189128190128191128192128193128194128195128196128197128198128199128200128201128202128203128204128205128206128207128208128209128210128211128212128213128214128215128216128217128218128219128220128221128222128223128224128225128226128227128228128229128230128231128232128233128234128235128236128237128238128239128240128241128242128243128244128245128246128247128248128249128250128251128252128253128254128255128256128257128258128259128260128261128262128263128264128265128266128267128268128269128270128271128272128273128274128275128276128277128278128279128280128281128282128283128284128285128286128287128288128289128290128291128292128293128294128295128296128297128298128299128300128301128302128303128304128305128306128307128308128309128310128311128312128313128314128315128316128317128318128319128320128321128322128323128324128325128326128327128328128329128330128331128332128333128334128335128336128337128338128339128340128341128342128343128344128345128346128347128348128349128350128351128352128353128354128355128356128357128358128359128360128361128362128363128364128365128366128367128368128369128370128371128372128373128374128375128376128377128378128379128380128381128382128383128384128385128386128387128388128389128390128391128392128393128394128395128396128397128398128399128400128401128402128403128404128405128406128407128408128409128410128411128412128413128414128415128416128417128418128419128420128421128422128423128424128425128426128427128428128429128430128431128432128433128434128435128436128437128438128439128440128441128442128443128444128445128446128447128448128449128450128451128452128453128454128455128456128457128458128459128460128461128462128463128464128465128466128467128468128469128470128471128472128473128474128475128476128477128478128479128480128481128482128483128484128485128486128487128488128489128490128491128492128493128494128495128496128497128498128499128500128501128502128503128504128505128506128507128508128509128510128511128512128513128514128515128516128517128518128519128520128521128522128523128524128525128526128527128528128529128530128531128532128533128534128535128536128537128538128539128540128541128542128543128544128545128546128547128548128549128550128551128552128553128554128555128556128557128558128559128560128561128562128563128564128565128566128567128568128569128570128571128572128573128574128575128576128577128578128579128580128581128582128583128584128585128586128587128588128589128590128591128592128593128594128595128596128597128598128599128600128601128602128603128604128605128606128607128608128609128610128611128612128613128614128615128616128617128618128619128620128621128622128623128624128625128626128627128628128629128630128631128632128633128634128635128636128637128638128639128640128641128642128643128644128645128646128647128648128649128650128651128652128653128654128655128656128657128658128659128660128661128662128663128664128665128666128667128668128669128670128671128672128673128674128675128676128677128678128679128680128681128682128683128684128685128686128687128688128689128690128691128692128693128694128695128696128697128698128699128700128701128702128703128704128705128706128707128708128709128710128711128712128713128714128715128716128717128718128719128720128721128722128723128724128725128726128727128728128729128730128731128732128733128734128735128736128737128738128739128740128741128742128743128744128745128746128747128748128749128750128751128752128753128754128755128756128757128758128759128760128761128762128763128764128765128766128767128768128769128770128771128772128773128774128775128776128777128778128779128780128781128782128783128784128785128786128787128788128789128790128791128792128793128794128795128796128797128798128799128800128801128802128803128804128805128806128807128808128809128810128811128812128813128814128815128816128817128818128819128820128821128822128823128824128825128826128827128828128829128830128831128832128833128834128835128836128837128838128839128840128841128842128843128844128845128846128847128848128849128850128851128852128853128854128855128856128857128858128859128860128861128862128863128864128865128866128867128868128869128870128871128872128873128874128875128876128877128878128879128880128881128882128883128884128885128886128887128888128889128890128891128892128893128894128895128896128897128898128899128900128901128902128903128904128905128906128907128908128909128910128911128912128913128914128915128916128917128918128919128920128921128922128923128924128925128926128927128928128929128930128931128932128933128934128935128936128937128938128939128940128941128942128943128944128945128946128947128948128949128950128951128952128953128954128955128956128957128958128959128960128961128962128963128964128965128966128967128968128969128970128971128972128973128974128975128976128977128978128979128980128981128982128983128984128985128986128987128988128989128990128991128992128993128994128995128996128997128998128999129000129001129002129003129004129005129006129007129008129009129010129011129012129013129014129015129016129017129018129019129020129021129022129023129024129025129026129027129028129029129030129031129032129033129034129035129036129037129038129039129040129041129042129043129044129045129046129047129048129049129050129051129052129053129054129055129056129057129058129059129060129061129062129063129064129065129066129067129068129069129070129071129072129073129074129075129076129077129078129079129080129081129082129083129084129085129086129087129088129089129090129091129092129093129094129095129096129097129098129099129100129101129102129103129104129105129106129107129108129109129110129111129112129113129114129115129116129117129118129119129120129121129122129123129124129125129126129127129128129129129130129131129132129133129134129135129136129137129138129139129140129141129142129143129144129145129146129147129148129149129150129151129152129153129154129155129156129157129158129159129160129161129162129163129164129165129166129167129168129169129170129171129172129173129174129175129176129177129178129179129180129181129182129183129184129185129186129187129188129189129190129191129192129193129194129195129196129197129198129199129200129201129202129203129204129205129206129207129208129209129210129211129212129213129214129215129216129217129218129219129220129221129222129223129224129225129226129227129228129229129230129231129232129233129234129235129236129237129238129239129240129241129242129243129244129245129246129247129248129249129250129251129252129253129254129255129256129257129258129259129260129261129262129263129264129265129266129267129268129269129270129271129272129273129274129275129276129277129278129279129280129281129282129283129284129285129286129287129288129289129290129291129292129293129294129295129296129297129298129299129300129301129302129303129304129305129306129307129308129309129310129311129312129313129314129315129316129317129318129319129320129321129322129323129324129325129326129327129328129329129330129331129332129333129334129335129336129337129338129339129340129341129342129343129344129345129346129347129348129349129350129351129352129353129354129355129356129357129358129359129360129361129362129363129364129365129366129367129368129369129370129371129372129373129374129375129376129377129378129379129380129381129382129383129384129385129386129387129388129389129390129391129392129393129394129395129396129397129398129399129400129401129402129403129404129405129406129407129408129409129410129411129412129413129414129415129416129417129418129419129420129421129422129423129424129425129426129427129428129429129430129431129432129433129434129435129436129437129438129439129440129441129442129443129444129445129446129447129448129449129450129451129452129453129454129455129456129457129458129459129460129461129462129463129464129465129466129467129468129469129470129471129472129473129474129475129476129477129478129479129480129481129482129483129484129485129486129487129488129489129490129491129492129493129494129495129496129497129498129499129500129501129502129503129504129505129506129507129508129509129510129511129512129513129514129515129516129517129518129519129520129521129522129523129524129525129526129527129528129529129530129531129532129533129534129535129536129537129538129539129540129541129542129543129544129545129546129547129548129549129550129551129552129553129554129555129556129557129558129559129560129561129562129563129564129565129566129567129568129569129570129571129572129573129574129575129576129577129578129579129580129581129582129583129584129585129586129587129588129589129590129591129592129593129594129595129596129597129598129599129600129601129602129603129604129605129606129607129608129609129610129611129612129613129614129615129616129617129618129619129620129621129622129623129624129625129626129627129628129629129630129631129632129633129634129635129636129637129638129639129640129641129642129643129644129645129646129647129648129649129650129651129652129653129654129655129656129657129658129659129660129661129662129663129664129665129666129667129668129669129670129671129672129673129674129675129676129677129678129679129680129681129682129683129684129685129686129687129688129689129690129691129692129693129694129695129696129697129698129699129700129701129702129703129704129705129706129707129708129709129710129711129712129713129714129715129716129717129718129719129720129721129722129723129724129725129726129727129728129729129730129731129732129733129734129735129736129737129738129739129740129741129742129743129744129745129746129747129748129749129750129751129752129753129754129755129756129757129758129759129760129761129762129763129764129765129766129767129768129769129770129771129772129773129774129775129776129777129778129779129780129781129782129783129784129785129786129787129788129789129790129791129792129793129794129795129796129797129798129799129800129801129802129803129804129805129806129807129808129809129810129811129812129813129814129815129816129817129818129819129820129821129822129823129824129825129826129827129828129829129830129831129832129833129834129835129836129837129838129839129840129841129842129843129844129845129846129847129848129849129850129851129852129853129854129855129856129857129858129859129860129861129862129863129864129865129866129867129868129869129870129871129872129873129874129875129876129877129878129879129880129881129882129883129884129885129886129887129888129889129890129891129892129893129894129895129896129897129898129899129900129901129902129903129904129905129906129907129908129909129910129911129912129913129914129915129916129917129918129919129920129921129922129923129924129925129926129927129928129929129930129931129932129933129934129935129936129937129938129939129940129941129942129943129944129945129946129947129948129949129950129951129952129953129954129955129956129957129958129959129960129961129962129963129964129965129966129967129968129969129970129971129972129973129974129975129976129977129978129979129980129981129982129983129984129985129986129987129988129989129990129991129992129993129994129995129996129997129998129999130000130001130002130003130004130005130006130007130008130009130010130011130012130013130014130015130016130017130018130019130020130021130022130023130024130025130026130027130028130029130030130031130032130033130034130035130036130037130038130039130040130041130042130043130044130045130046130047130048130049130050130051130052130053130054130055130056130057130058130059130060130061130062130063130064130065130066130067130068130069130070130071130072130073130074130075130076130077130078130079130080130081130082130083130084130085130086130087130088130089130090130091130092130093130094130095130096130097130098130099130100130101130102130103130104130105130106130107130108130109130110130111130112130113130114130115130116130117130118130119130120130121130122130123130124130125130126130127130128130129130130130131130132130133130134130135130136130137130138130139130140130141130142130143130144130145130146130147130148130149130150130151130152130153130154130155130156130157130158130159130160130161130162130163130164130165130166130167130168130169130170130171130172130173130174130175130176130177130178130179130180130181130182130183130184130185130186130187130188130189130190130191130192130193130194130195130196130197130198130199130200130201130202130203130204130205130206130207130208130209130210130211130212130213130214130215130216130217130218130219130220130221130222130223130224130225130226130227130228130229130230130231130232130233130234130235130236130237130238130239130240130241130242130243130244130245130246130247130248130249130250130251130252130253130254130255130256130257130258130259130260130261130262130263130264130265130266130267130268130269130270130271130272130273130274130275130276130277130278130279130280130281130282130283130284130285130286130287130288130289130290130291130292130293130294130295130296130297130298130299130300130301130302130303130304130305130306130307130308130309130310130311130312130313130314130315130316130317130318130319130320130321130322130323130324130325130326130327130328130329130330130331130332130333130334130335130336130337130338130339130340130341130342130343130344130345130346130347130348130349130350130351130352130353130354130355130356130357130358130359130360130361130362130363130364130365130366130367130368130369130370130371130372130373130374130375130376130377130378130379130380130381130382130383130384130385130386130387130388130389130390130391130392130393130394130395130396130397130398130399130400130401130402130403130404130405130406130407130408130409130410130411130412130413130414130415130416130417130418130419130420130421130422130423130424130425130426130427130428130429130430130431130432130433130434130435130436130437130438130439130440130441130442130443130444130445130446130447130448130449130450130451130452130453130454130455130456130457130458130459130460130461130462130463130464130465130466130467130468130469130470130471130472130473130474130475130476130477130478130479130480130481130482130483130484130485130486130487130488130489130490130491130492130493130494130495130496130497130498130499130500130501130502130503130504130505130506130507130508130509130510130511130512130513130514130515130516130517130518130519130520130521130522130523130524130525130526130527130528130529130530130531130532130533130534130535130536130537130538130539130540130541130542130543130544130545130546130547130548130549130550130551130552130553130554130555130556130557130558130559130560130561130562130563130564130565130566130567130568130569130570130571130572130573130574130575130576130577130578130579130580130581130582130583130584130585130586130587130588130589130590130591130592130593130594130595130596130597130598130599130600130601130602130603130604130605130606130607130608130609130610130611130612130613130614130615130616130617130618130619130620130621130622130623130624130625130626130627130628130629130630130631130632130633130634130635130636130637130638130639130640130641130642130643130644130645130646130647130648130649130650130651130652130653130654130655130656130657130658130659130660130661130662130663130664130665130666130667130668130669130670130671130672130673130674130675130676130677130678130679130680130681130682130683130684130685130686130687130688130689130690130691130692130693130694130695130696130697130698130699130700130701130702130703130704130705130706130707130708130709130710130711130712130713130714130715130716130717130718130719130720130721130722130723130724130725130726130727130728130729130730130731130732130733130734130735130736130737130738130739130740130741130742130743130744130745130746130747130748130749130750130751130752130753130754130755130756130757130758130759130760130761130762130763130764130765130766130767130768130769130770130771130772130773130774130775130776130777130778130779130780130781130782130783130784130785130786130787130788130789130790130791130792130793130794130795130796130797130798130799130800130801130802130803130804130805130806130807130808130809130810130811130812130813130814130815130816130817130818130819130820130821130822130823130824130825130826130827130828130829130830130831130832130833130834130835130836130837130838130839130840130841130842130843130844130845130846130847130848130849130850130851130852130853130854130855130856130857130858130859130860130861130862130863130864130865130866130867130868130869130870130871130872130873130874130875130876130877130878130879130880130881130882130883130884130885130886130887130888130889130890130891130892130893130894130895130896130897130898130899130900130901130902130903130904130905130906130907130908130909130910130911130912130913130914130915130916130917130918130919130920130921130922130923130924130925130926130927130928130929130930130931130932130933130934130935130936130937130938130939130940130941130942130943130944130945130946130947130948130949130950130951130952130953130954130955130956130957130958130959130960130961130962130963130964130965130966130967130968130969130970130971130972130973130974130975130976130977130978130979130980130981130982130983130984130985130986130987130988130989130990130991130992130993130994130995130996130997130998130999131000131001131002131003131004131005131006131007131008131009131010131011131012131013131014131015131016131017131018131019131020131021131022131023131024131025131026131027131028131029131030131031131032131033131034131035131036131037131038131039131040131041131042131043131044131045131046131047131048131049131050131051131052131053131054131055131056131057131058131059131060131061131062131063131064131065131066131067131068131069131070131071131072131073131074131075131076131077131078131079131080131081131082131083131084131085131086131087131088131089131090131091131092131093131094131095131096131097131098131099131100131101131102131103131104131105131106131107131108131109131110131111131112131113131114131115131116131117131118131119131120131121131122131123131124131125131126131127131128131129131130131131131132131133131134131135131136131137131138131139131140131141131142131143131144131145131146131147131148131149131150131151131152131153131154131155131156131157131158131159131160131161131162131163131164131165131166131167131168131169131170131171131172131173131174131175131176131177131178131179131180131181131182131183131184131185131186131187131188131189131190131191131192131193131194131195131196131197131198131199131200131201131202131203131204131205131206131207131208131209131210131211131212131213131214131215131216131217131218131219131220131221131222131223131224131225131226131227131228131229131230131231131232131233131234131235131236131237131238131239131240131241131242131243131244131245131246131247131248131249131250131251131252131253131254131255131256131257131258131259131260131261131262131263131264131265131266131267131268131269131270131271131272131273131274131275131276131277131278131279131280131281131282131283131284131285131286131287131288131289131290131291131292131293131294131295131296131297131298131299131300131301131302131303131304131305131306131307131308131309131310131311131312131313131314131315131316131317131318131319131320131321131322131323131324131325131326131327131328131329131330131331131332131333131334131335131336131337131338131339131340131341131342131343131344131345131346131347131348131349131350131351131352131353131354131355131356131357131358131359131360131361131362131363131364131365131366131367131368131369131370131371131372131373131374131375131376131377131378131379131380131381131382131383131384131385131386131387131388131389131390131391131392131393131394131395131396131397131398131399131400131401131402131403131404131405131406131407131408131409131410131411131412131413131414131415131416131417131418131419131420131421131422131423131424131425131426131427131428131429131430131431131432131433131434131435131436131437131438131439131440131441131442131443131444131445131446131447131448131449131450131451131452131453131454131455131456131457131458131459131460131461131462131463131464131465131466131467131468131469131470131471131472131473131474131475131476131477131478131479131480131481131482131483131484131485131486131487131488131489131490131491131492131493131494131495131496131497131498131499131500131501131502131503131504131505131506131507131508131509131510131511131512131513131514131515131516131517131518131519131520131521131522131523131524131525131526131527131528131529131530131531131532131533131534131535131536131537131538131539131540131541131542131543131544131545131546131547131548131549131550131551131552131553131554131555131556131557131558131559131560131561131562131563131564131565131566131567131568131569131570131571131572131573131574131575131576131577131578131579131580131581131582131583131584131585131586131587131588131589131590131591131592131593131594131595131596131597131598131599131600131601131602131603131604131605131606131607131608131609131610131611131612131613131614131615131616131617131618131619131620131621131622131623131624131625131626131627131628131629131630131631131632131633131634131635131636131637131638131639131640131641131642131643131644131645131646131647131648131649131650131651131652131653131654131655131656131657131658131659131660131661131662131663131664131665131666131667131668131669131670131671131672131673131674131675131676131677131678131679131680131681131682131683131684131685131686131687131688131689131690131691131692131693131694131695131696131697131698131699131700131701131702131703131704131705131706131707131708131709131710131711131712131713131714131715131716131717131718131719131720131721131722131723131724131725131726131727131728131729131730131731131732131733131734131735131736131737131738131739131740131741131742131743131744131745131746131747131748131749131750131751131752131753131754131755131756131757131758131759131760131761131762131763131764131765131766131767131768131769131770131771131772131773131774131775131776131777131778131779131780131781131782131783131784131785131786131787131788131789131790131791131792131793131794131795131796131797131798131799131800131801131802131803131804131805131806131807131808131809131810131811131812131813131814131815131816131817131818131819131820131821131822131823131824131825131826131827131828131829131830131831131832131833131834131835131836131837131838131839131840131841131842131843131844131845131846131847131848131849131850131851131852131853131854131855131856131857131858131859131860131861131862131863131864131865131866131867131868131869131870131871131872131873131874131875131876131877131878131879131880131881131882131883131884131885131886131887131888131889131890131891131892131893131894131895131896131897131898131899131900131901131902131903131904131905131906131907131908131909131910131911131912131913131914131915131916131917131918131919131920131921131922131923131924131925131926131927131928131929131930131931131932131933131934131935131936131937131938131939131940131941131942131943131944131945131946131947131948131949131950131951131952131953131954131955131956131957131958131959131960131961131962131963131964131965131966131967131968131969131970131971131972131973131974131975131976131977131978131979131980131981131982131983131984131985131986131987131988131989131990131991131992131993131994131995131996131997131998131999132000132001132002132003132004132005132006132007132008132009132010132011132012132013132014132015132016132017132018132019132020132021132022132023132024132025132026132027132028132029132030132031132032132033132034132035132036132037132038132039132040132041132042132043132044132045132046132047132048132049132050132051132052132053132054132055132056132057132058132059132060132061132062132063132064132065132066132067132068132069132070132071132072132073132074132075132076132077132078132079132080132081132082132083132084132085132086132087132088132089132090132091132092132093132094132095132096132097132098132099132100132101132102132103132104132105132106132107132108132109132110132111132112132113132114132115132116132117132118132119132120132121132122132123132124132125132126132127132128132129132130132131132132132133132134132135132136132137132138132139132140132141132142132143132144132145132146132147132148132149132150132151132152132153132154132155132156132157132158132159132160132161132162132163132164132165132166132167132168132169132170132171132172132173132174132175132176132177132178132179132180132181132182132183132184132185132186132187132188132189132190132191132192132193132194132195132196132197132198132199132200132201132202132203132204132205132206132207132208132209132210132211132212132213132214132215132216132217132218132219132220132221132222132223132224132225132226132227132228132229132230132231132232132233132234132235132236132237132238132239132240132241132242132243132244132245132246132247132248132249132250132251132252132253132254132255132256132257132258132259132260132261132262132263132264132265132266132267132268132269132270132271132272132273132274132275132276132277132278132279132280132281132282132283132284132285132286132287132288132289132290132291132292132293132294132295132296132297132298132299132300132301132302132303132304132305132306132307132308132309132310132311132312132313132314132315132316132317132318132319132320132321132322132323132324132325132326132327132328132329132330132331132332132333132334132335132336132337132338132339132340132341132342132343132344132345132346132347132348132349132350132351132352132353132354132355132356132357132358132359132360132361132362132363132364132365132366132367132368132369132370132371132372132373132374132375132376132377132378132379132380132381132382132383132384132385132386132387132388132389132390132391132392132393132394132395132396132397132398132399132400132401132402132403132404132405132406132407132408132409132410132411132412132413132414132415132416132417132418132419132420132421132422132423132424132425132426132427132428132429132430132431132432132433132434132435132436132437132438132439132440132441132442132443132444132445132446132447132448132449132450132451132452132453132454132455132456132457132458132459132460132461132462132463132464132465132466132467132468132469132470132471132472132473132474132475132476132477132478132479132480132481132482132483132484132485132486132487132488132489132490132491132492132493132494132495132496132497132498132499132500132501132502132503132504132505132506132507132508132509132510132511132512132513132514132515132516132517132518132519132520132521132522132523132524132525132526132527132528132529132530132531132532132533132534132535132536132537132538132539132540132541132542132543132544132545132546132547132548132549132550132551132552132553132554132555132556132557132558132559132560132561132562132563132564132565132566132567132568132569132570132571132572132573132574132575132576132577132578132579132580132581132582132583132584132585132586132587132588132589132590132591132592132593132594132595132596132597132598132599132600132601132602132603132604132605132606132607132608132609132610132611132612132613132614132615132616132617132618132619132620132621132622132623132624132625132626132627132628132629132630132631132632132633132634132635132636132637132638132639132640132641132642132643132644132645132646132647132648132649132650132651132652132653132654132655132656132657132658132659132660132661132662132663132664132665132666132667132668132669132670132671132672132673132674132675132676132677132678132679132680132681132682132683132684132685132686132687132688132689132690132691132692132693132694132695132696132697132698132699132700132701132702132703132704132705132706132707132708132709132710132711132712132713132714132715132716132717132718132719132720132721132722132723132724132725132726132727132728132729132730132731132732132733132734132735132736132737132738132739132740132741132742132743132744132745132746132747132748132749132750132751132752132753132754132755132756132757132758132759132760132761132762132763132764132765132766132767132768132769132770132771132772132773132774132775132776132777132778132779132780132781132782132783132784132785132786132787132788132789132790132791132792132793132794132795132796132797132798132799132800132801132802132803132804132805132806132807132808132809132810132811132812132813132814132815132816132817132818132819132820132821132822132823132824132825132826132827132828132829132830132831132832132833132834132835132836132837132838132839132840132841132842132843132844132845132846132847132848132849132850132851132852132853132854132855132856132857132858132859132860132861132862132863132864132865132866132867132868132869132870132871132872132873132874132875132876132877132878132879132880132881132882132883132884132885132886132887132888132889132890132891132892132893132894132895132896132897132898132899132900132901132902132903132904132905132906132907132908132909132910132911132912132913132914132915132916132917132918132919132920132921132922132923132924132925132926132927132928132929132930132931132932132933132934132935132936132937132938132939132940132941132942132943132944132945132946132947132948132949132950132951132952132953132954132955132956132957132958132959132960132961132962132963132964132965132966132967132968132969132970132971132972132973132974132975132976132977132978132979132980132981132982132983132984132985132986132987132988132989132990132991132992132993132994132995132996132997132998132999133000133001133002133003133004133005133006133007133008133009133010133011133012133013133014133015133016133017133018133019133020133021133022133023133024133025133026133027133028133029133030133031133032133033133034133035133036133037133038133039133040133041133042133043133044133045133046133047133048133049133050133051133052133053133054133055133056133057133058133059133060133061133062133063133064133065133066133067133068133069133070133071133072133073133074133075133076133077133078133079133080133081133082133083133084133085133086133087133088133089133090133091133092133093133094133095133096133097133098133099133100133101133102133103133104133105133106133107133108133109133110133111133112133113133114133115133116133117133118133119133120133121133122133123133124133125133126133127133128133129133130133131133132133133133134133135133136133137133138133139133140133141133142133143133144133145133146133147133148133149133150133151133152133153133154133155133156133157133158133159133160133161133162133163133164133165133166133167133168133169133170133171133172133173133174133175133176133177133178133179133180133181133182133183133184133185133186133187133188133189133190133191133192133193133194133195133196133197133198133199133200133201133202133203133204133205133206133207133208133209133210133211133212133213133214133215133216133217133218133219133220133221133222133223133224133225133226133227133228133229133230133231133232133233133234133235133236133237133238133239133240133241133242133243133244133245133246133247133248133249133250133251133252133253133254133255133256133257133258133259133260133261133262133263133264133265133266133267133268133269133270133271133272133273133274133275133276133277133278133279133280133281133282133283133284133285133286133287133288133289133290133291133292133293133294133295133296133297133298133299133300133301133302133303133304133305133306133307133308133309133310133311133312133313133314133315133316133317133318133319133320133321133322133323133324133325133326133327133328133329133330133331133332133333133334133335133336133337133338133339133340133341133342133343133344133345133346133347133348133349133350133351133352133353133354133355133356133357133358133359133360133361133362133363133364133365133366133367133368133369133370133371133372133373133374133375133376133377133378133379133380133381133382133383133384133385133386133387133388133389133390133391133392133393133394133395133396133397133398133399133400133401133402133403133404133405133406133407133408133409133410133411133412133413133414133415133416133417133418133419133420133421133422133423133424133425133426133427133428133429133430133431133432133433133434133435133436133437133438133439133440133441133442133443133444133445133446133447133448133449133450133451133452133453133454133455133456133457133458133459133460133461133462133463133464133465133466133467133468133469133470133471133472133473133474133475133476133477133478133479133480133481133482133483133484133485133486133487133488133489133490133491133492133493133494133495133496133497133498133499133500133501133502133503133504133505133506133507133508133509133510133511133512133513133514133515133516133517133518133519133520133521133522133523133524133525133526133527133528133529133530133531133532133533133534133535133536133537133538133539133540133541133542133543133544133545133546133547133548133549133550133551133552133553133554133555133556133557133558133559133560133561133562133563133564133565133566133567133568133569133570133571133572133573133574133575133576133577133578133579133580133581133582133583133584133585133586133587133588133589133590133591133592133593133594133595133596133597133598133599133600133601133602133603133604133605133606133607133608133609133610133611133612133613133614133615133616133617133618133619133620133621133622133623133624133625133626133627133628133629133630133631133632133633133634133635133636133637133638133639133640133641133642133643133644133645133646133647133648133649133650133651133652133653133654133655133656133657133658133659133660133661133662133663133664133665133666133667133668133669133670133671133672133673133674133675133676133677133678133679133680133681133682133683133684133685133686133687133688133689133690133691133692133693133694133695133696133697133698133699133700133701133702133703133704133705133706133707133708133709133710133711133712133713133714133715133716133717133718133719133720133721133722133723133724133725133726133727133728133729133730133731133732133733133734133735133736133737133738133739133740133741133742133743133744133745133746133747133748133749133750133751133752133753133754133755133756133757133758133759133760133761133762133763133764133765133766133767133768133769133770133771133772133773133774133775133776133777133778133779133780133781133782133783133784133785133786133787133788133789133790133791133792133793133794133795133796133797133798133799133800133801133802133803133804133805133806133807133808133809133810133811133812133813133814133815133816133817133818133819133820133821133822133823133824133825133826133827133828133829133830133831133832133833133834133835133836133837133838133839133840133841133842133843133844133845133846133847133848133849133850133851133852133853133854133855133856133857133858133859133860133861133862133863133864133865133866133867133868133869133870133871133872133873133874133875133876133877133878133879133880133881133882133883133884133885133886133887133888133889133890133891133892133893133894133895133896133897133898133899133900133901133902133903133904133905133906133907133908133909133910133911133912133913133914133915133916133917133918133919133920133921133922133923133924133925133926133927133928133929133930133931133932133933133934133935133936133937133938133939133940133941133942133943133944133945133946133947133948133949133950133951133952133953133954133955133956133957133958133959133960133961133962133963133964133965133966133967133968133969133970133971133972133973133974133975133976133977133978133979133980133981133982133983133984133985133986133987133988133989133990133991133992133993133994133995133996133997133998133999134000134001134002134003134004134005134006134007134008134009134010134011134012134013134014134015134016134017134018134019134020134021134022134023134024134025134026134027134028134029134030134031134032134033134034134035134036134037134038134039134040134041134042134043134044134045134046134047134048134049134050134051134052134053134054134055134056134057134058134059134060134061134062134063134064134065134066134067134068134069134070134071134072134073134074134075134076134077134078134079134080134081134082134083134084134085134086134087134088134089134090134091134092134093134094134095134096134097134098134099134100134101134102134103134104134105134106134107134108134109134110134111134112134113134114134115134116134117134118134119134120134121134122134123134124134125134126134127134128134129134130134131134132134133134134134135134136134137134138134139134140134141134142134143134144134145134146134147134148134149134150134151134152134153134154134155134156134157134158134159134160134161134162134163134164134165134166134167134168134169134170134171134172134173134174134175134176134177134178134179134180134181134182134183134184134185134186134187134188134189134190134191134192134193134194134195134196134197134198134199134200134201134202134203134204134205134206134207134208134209134210134211134212134213134214134215134216134217134218134219134220134221134222134223134224134225134226134227134228134229134230134231134232134233134234134235134236134237134238134239134240134241134242134243134244134245134246134247134248134249134250134251134252134253134254134255134256134257134258134259134260134261134262134263134264134265134266134267134268134269134270134271134272134273134274134275134276134277134278134279134280134281134282134283134284134285134286134287134288134289134290134291134292134293134294134295134296134297134298134299134300134301134302134303134304134305134306134307134308134309134310134311134312134313134314134315134316134317134318134319134320134321134322134323134324134325134326134327134328134329134330134331134332134333134334134335134336134337134338134339134340134341134342134343134344134345134346134347134348134349134350134351134352134353134354134355134356134357134358134359134360134361134362134363134364134365134366134367134368134369134370134371134372134373134374134375134376134377134378134379134380134381134382134383134384134385134386134387134388134389134390134391134392134393134394134395134396134397134398134399134400134401134402134403134404134405134406134407134408134409134410134411134412134413134414134415134416134417134418134419134420134421134422134423134424134425134426134427134428134429134430134431134432134433134434134435134436134437134438134439134440134441134442134443134444134445134446134447134448134449134450134451134452134453134454134455134456134457134458134459134460134461134462134463134464134465134466134467134468134469134470134471134472134473134474134475134476134477134478134479134480134481134482134483134484134485134486134487134488134489134490134491134492134493134494134495134496134497134498134499134500134501134502134503134504134505134506134507134508134509134510134511134512134513134514134515134516134517134518134519134520134521134522134523134524134525134526134527134528134529134530134531134532134533134534134535134536134537134538134539134540134541134542134543134544134545134546134547134548134549134550134551134552134553134554134555134556134557134558134559134560134561134562134563134564134565134566134567134568134569134570134571134572134573134574134575134576134577134578134579134580134581134582134583134584134585134586134587134588134589134590134591134592134593134594134595134596134597134598134599134600134601134602134603134604134605134606134607134608134609134610134611134612134613134614134615134616134617134618134619134620134621134622134623134624134625134626134627134628134629134630134631134632134633134634134635134636134637134638134639134640134641134642134643134644134645134646134647134648134649134650134651134652134653134654134655134656134657134658134659134660134661134662134663134664134665134666134667134668134669134670134671134672134673134674134675134676134677134678134679134680134681134682134683134684134685134686134687134688134689134690134691134692134693134694134695134696134697134698134699134700134701134702134703134704134705134706134707134708134709134710134711134712134713134714134715134716134717134718134719134720134721134722134723134724134725134726134727134728134729134730134731134732134733134734134735134736134737134738134739134740134741134742134743134744134745134746134747134748134749134750134751134752134753134754134755134756134757134758134759134760134761134762134763134764134765134766134767134768134769134770134771134772134773134774134775134776134777134778134779134780134781134782134783134784134785134786134787134788134789134790134791134792134793134794134795134796134797134798134799134800134801134802134803134804134805134806134807134808134809134810134811134812134813134814134815134816134817134818134819134820134821134822134823134824134825134826134827134828134829134830134831134832134833134834134835134836134837134838134839134840134841134842134843134844134845134846134847134848134849134850134851134852134853134854134855134856134857134858134859134860134861134862134863134864134865134866134867134868134869134870134871134872134873134874134875134876134877134878134879134880134881134882134883134884134885134886134887134888134889134890134891134892134893134894134895134896134897134898134899134900134901134902134903134904134905134906134907134908134909134910134911134912134913134914134915134916134917134918134919134920134921134922134923134924134925134926134927134928134929134930134931134932134933134934134935134936134937134938134939134940134941134942134943134944134945134946134947134948134949134950134951134952134953134954134955134956134957134958134959134960134961134962134963134964134965134966134967134968134969134970134971134972134973134974134975134976134977134978134979134980134981134982134983134984134985134986134987134988134989134990134991134992134993134994134995134996134997134998134999135000135001135002135003135004135005135006135007135008135009135010135011135012135013135014135015135016135017135018135019135020135021135022135023135024135025135026135027135028135029135030135031135032135033135034135035135036135037135038135039135040135041135042135043135044135045135046135047135048135049135050135051135052135053135054135055135056135057135058135059135060135061135062135063135064135065135066135067135068135069135070135071135072135073135074135075135076135077135078135079135080135081135082135083135084135085135086135087135088135089135090135091135092135093135094135095135096135097135098135099135100135101135102135103135104135105135106135107135108135109135110135111135112135113135114135115135116135117135118135119135120135121135122135123135124135125135126135127135128135129135130135131135132135133135134135135135136135137135138135139135140135141135142135143135144135145135146135147135148135149135150135151135152135153135154135155135156135157135158135159135160135161135162135163135164135165135166135167135168135169135170135171135172135173135174135175135176135177135178135179135180135181135182135183135184135185135186135187135188135189135190135191135192135193135194135195135196135197135198135199135200135201135202135203135204135205135206135207135208135209135210135211135212135213135214135215135216135217135218135219135220135221135222135223135224135225135226135227135228135229135230135231135232135233135234135235135236135237135238135239135240135241135242135243135244135245135246135247135248135249135250135251135252135253135254135255135256135257135258135259135260135261135262135263135264135265135266135267135268135269135270135271135272135273135274135275135276135277135278135279135280135281135282135283135284135285135286135287135288135289135290135291135292135293135294135295135296135297135298135299135300135301135302135303135304135305135306135307135308135309135310135311135312135313135314135315135316135317135318135319135320135321135322135323135324135325135326135327135328135329135330135331135332135333135334135335135336135337135338135339135340135341135342135343135344135345135346135347135348135349135350135351135352135353135354135355135356135357135358135359135360135361135362135363135364135365135366135367135368135369135370135371135372135373135374135375135376135377135378135379135380135381135382135383135384135385135386135387135388135389135390135391135392135393135394135395135396135397135398135399135400135401135402135403135404135405135406135407135408135409135410135411135412135413135414135415135416135417135418135419135420135421135422135423135424135425135426135427135428135429135430135431135432135433135434135435135436135437135438135439135440135441135442135443135444135445135446135447135448135449135450135451135452135453135454135455135456135457135458135459135460135461135462135463135464135465135466135467135468135469135470135471135472135473135474135475135476135477135478135479135480135481135482135483135484135485135486135487135488135489135490135491135492135493135494135495135496135497135498135499135500135501135502135503135504135505135506135507135508135509135510135511135512135513135514135515135516135517135518135519135520135521135522135523135524135525135526135527135528135529135530135531135532135533135534135535135536135537135538135539135540135541135542135543135544135545135546135547135548135549135550135551135552135553135554135555135556135557135558135559135560135561135562135563135564135565135566135567135568135569135570135571135572135573135574135575135576135577135578135579135580135581135582135583135584135585135586135587135588135589135590135591135592135593135594135595135596135597135598135599135600135601135602135603135604135605135606135607135608135609135610135611135612135613135614135615135616135617135618135619135620135621135622135623135624135625135626135627135628135629135630135631135632135633135634135635135636135637135638135639135640135641135642135643135644135645135646135647135648135649135650135651135652135653135654135655135656135657135658135659135660135661135662135663135664135665135666135667135668135669135670135671135672135673135674135675135676135677135678135679135680135681135682135683135684135685135686135687135688135689135690135691135692135693135694135695135696135697135698135699135700135701135702135703135704135705135706135707135708135709135710135711135712135713135714135715135716135717135718135719135720135721135722135723135724135725135726135727135728135729135730135731135732135733135734135735135736135737135738135739135740135741135742135743135744135745135746135747135748135749135750135751135752135753135754135755135756135757135758135759135760135761135762135763135764135765135766135767135768135769135770135771135772135773135774135775135776135777135778135779135780135781135782135783135784135785135786135787135788135789135790135791135792135793135794135795135796135797135798135799135800135801135802135803135804135805135806135807135808135809135810135811135812135813135814135815135816135817135818135819135820135821135822135823135824135825135826135827135828135829135830135831135832135833135834135835135836135837135838135839135840135841135842135843135844135845135846135847135848135849135850135851135852135853135854135855135856135857135858135859135860135861135862135863135864135865135866135867135868135869135870135871135872135873135874135875135876135877135878135879135880135881135882135883135884135885135886135887135888135889135890135891135892135893135894135895135896135897135898135899135900135901135902135903135904135905135906135907135908135909135910135911135912135913135914135915135916135917135918135919135920135921135922135923135924135925135926135927135928135929135930135931135932135933135934135935135936135937135938135939135940135941135942135943135944135945135946135947135948135949135950135951135952135953135954135955135956135957135958135959135960135961135962135963135964135965135966135967135968135969135970135971135972135973135974135975135976135977135978135979135980135981135982135983135984135985135986135987135988135989135990135991135992135993135994135995135996135997135998135999136000136001136002136003136004136005136006136007136008136009136010136011136012136013136014136015136016136017136018136019136020136021136022136023136024136025136026136027136028136029136030136031136032136033136034136035136036136037136038136039136040136041136042136043136044136045136046136047136048136049136050136051136052136053136054136055136056136057136058136059136060136061136062136063136064136065136066136067136068136069136070136071136072136073136074136075136076136077136078136079136080136081136082136083136084136085136086136087136088136089136090136091136092136093136094136095136096136097136098136099136100136101136102136103136104136105136106136107136108136109136110136111136112136113136114136115136116136117136118136119136120136121136122136123136124136125136126136127136128136129136130136131136132136133136134136135136136136137136138136139136140136141136142136143136144136145136146136147136148136149136150136151136152136153136154136155136156136157136158136159136160136161136162136163136164136165136166136167136168136169136170136171136172136173136174136175136176136177136178136179136180136181136182136183136184136185136186136187136188136189136190136191136192136193136194136195136196136197136198136199136200136201136202136203136204136205136206136207136208136209136210136211136212136213136214136215136216136217136218136219136220136221136222136223136224136225136226136227136228136229136230136231136232136233136234136235136236136237136238136239136240136241136242136243136244136245136246136247136248136249136250136251136252136253136254136255136256136257136258136259136260136261136262136263136264136265136266136267136268136269136270136271136272136273136274136275136276136277136278136279136280136281136282136283136284136285136286136287136288136289136290136291136292136293136294136295136296136297136298136299136300136301136302136303136304136305136306136307136308136309136310136311136312136313136314136315136316136317136318136319136320136321136322136323136324136325136326136327136328136329136330136331136332136333136334136335136336136337136338136339136340136341136342136343136344136345136346136347136348136349136350136351136352136353136354136355136356136357136358136359136360136361136362136363136364136365136366136367136368136369136370136371136372136373136374136375136376136377136378136379136380136381136382136383136384136385136386136387136388136389136390136391136392136393136394136395136396136397136398136399136400136401136402136403136404136405136406136407136408136409136410136411136412136413136414136415136416136417136418136419136420136421136422136423136424136425136426136427136428136429136430136431136432136433136434136435136436136437136438136439136440136441136442136443136444136445136446136447136448136449136450136451136452136453136454136455136456136457136458136459136460136461136462136463136464136465136466136467136468136469136470136471136472136473136474136475136476136477136478136479136480136481136482136483136484136485136486136487136488136489136490136491136492136493136494136495136496136497136498136499136500136501136502136503136504136505136506136507136508136509136510136511136512136513136514136515136516136517136518136519136520136521136522136523136524136525136526136527136528136529136530136531136532136533136534136535136536136537136538136539136540136541136542136543136544136545136546136547136548136549136550136551136552136553136554136555136556136557136558136559136560136561136562136563136564136565136566136567136568136569136570136571136572136573136574136575136576136577136578136579136580136581136582136583136584136585136586136587136588136589136590136591136592136593136594136595136596136597136598136599136600136601136602136603136604136605136606136607136608136609136610136611136612136613136614136615136616136617136618136619136620136621136622136623136624136625136626136627136628136629136630136631136632136633136634136635136636136637136638136639136640136641136642136643136644136645136646136647136648136649136650136651136652136653136654136655136656136657136658136659136660136661136662136663136664136665136666136667136668136669136670136671136672136673136674136675136676136677136678136679136680136681136682136683136684136685136686136687136688136689136690136691136692136693136694136695136696136697136698136699136700136701136702136703136704136705136706136707136708136709136710136711136712136713136714136715136716136717136718136719136720136721136722136723136724136725136726136727136728136729136730136731136732136733136734136735136736136737136738136739136740136741136742136743136744136745136746136747136748136749136750136751136752136753136754136755136756136757136758136759136760136761136762136763136764136765136766136767136768136769136770136771136772136773136774136775136776136777136778136779136780136781136782136783136784136785136786136787136788136789136790136791136792136793136794136795136796136797136798136799136800136801136802136803136804136805136806136807136808136809136810136811136812136813136814136815136816136817136818136819136820136821136822136823136824136825136826136827136828136829136830136831136832136833136834136835136836136837136838136839136840136841136842136843136844136845136846136847136848136849136850136851136852136853136854136855136856136857136858136859136860136861136862136863136864136865136866136867136868136869136870136871136872136873136874136875136876136877136878136879136880136881136882136883136884136885136886136887136888136889136890136891136892136893136894136895136896136897136898136899136900136901136902136903136904136905136906136907136908136909136910136911136912136913136914136915136916136917136918136919136920136921136922136923136924136925136926136927136928136929136930136931136932136933136934136935136936136937136938136939136940136941136942136943136944136945136946136947136948136949136950136951136952136953136954136955136956136957136958136959136960136961136962136963136964136965136966136967136968136969136970136971136972136973136974136975136976136977136978136979136980136981136982136983136984136985136986136987136988136989136990136991136992136993136994136995136996136997136998136999137000137001137002137003137004137005137006137007137008137009137010137011137012137013137014137015137016137017137018137019137020137021137022137023137024137025137026137027137028137029137030137031137032137033137034137035137036137037137038137039137040137041137042137043137044137045137046137047137048137049137050137051137052137053137054137055137056137057137058137059137060137061137062137063137064137065137066137067137068137069137070137071137072137073137074137075137076137077137078137079137080137081137082137083137084137085137086137087137088137089137090137091137092137093137094137095137096137097137098137099137100137101137102137103137104137105137106137107137108137109137110137111137112137113137114137115137116137117137118137119137120137121137122137123137124137125137126137127137128137129137130137131137132137133137134137135137136137137137138137139137140137141137142137143137144137145137146137147137148137149137150137151137152137153137154137155137156137157137158137159137160137161137162137163137164137165137166137167137168137169137170137171137172137173137174137175137176137177137178137179137180137181137182137183137184137185137186137187137188137189137190137191137192137193137194137195137196137197137198137199137200137201137202137203137204137205137206137207137208137209137210137211137212137213137214137215137216137217137218137219137220137221137222137223137224137225137226137227137228137229137230137231137232137233137234137235137236137237137238137239137240137241137242137243137244137245137246137247137248137249137250137251137252137253137254137255137256137257137258137259137260137261137262137263137264137265137266137267137268137269137270137271137272137273137274137275137276137277137278137279137280137281137282137283137284137285137286137287137288137289137290137291137292137293137294137295137296137297137298137299137300137301137302137303137304137305137306137307137308137309137310137311137312137313137314137315137316137317137318137319137320137321137322137323137324137325137326137327137328137329137330137331137332137333137334137335137336137337137338137339137340137341137342137343137344137345137346137347137348137349137350137351137352137353137354137355137356137357137358137359137360137361137362137363137364137365137366137367137368137369137370137371137372137373137374137375137376137377137378137379137380137381137382137383137384137385137386137387137388137389137390137391137392137393137394137395137396137397137398137399137400137401137402137403137404137405137406137407137408137409137410137411137412137413137414137415137416137417137418137419137420137421137422137423137424137425137426137427137428137429137430137431137432137433137434137435137436137437137438137439137440137441137442137443137444137445137446137447137448137449137450137451137452137453137454137455137456137457137458137459137460137461137462137463137464137465137466137467137468137469137470137471137472137473137474137475137476137477137478137479137480137481137482137483137484137485137486137487137488137489137490137491137492137493137494137495137496137497137498137499137500137501137502137503137504137505137506137507137508137509137510137511137512137513137514137515137516137517137518137519137520137521137522137523137524137525137526137527137528137529137530137531137532137533137534137535137536137537137538137539137540137541137542137543137544137545137546137547137548137549137550137551137552137553137554137555137556137557137558137559137560137561137562137563137564137565137566137567137568137569137570137571137572137573137574137575137576137577137578137579137580137581137582137583137584137585137586137587137588137589137590137591137592137593137594137595137596137597137598137599137600137601137602137603137604137605137606137607137608137609137610137611137612137613137614137615137616137617137618137619137620137621137622137623137624137625137626137627137628137629137630137631137632137633137634137635137636137637137638137639137640137641137642137643137644137645137646137647137648137649137650137651137652137653137654137655137656137657137658137659137660137661137662137663137664137665137666137667137668137669137670137671137672137673137674137675137676137677137678137679137680137681137682137683137684137685137686137687137688137689137690137691137692137693137694137695137696137697137698137699137700137701137702137703137704137705137706137707137708137709137710137711137712137713137714137715137716137717137718137719137720137721137722137723137724137725137726137727137728137729137730137731137732137733137734137735137736137737137738137739137740137741137742137743137744137745137746137747137748137749137750137751137752137753137754137755137756137757137758137759137760137761137762137763137764137765137766137767137768137769137770137771137772137773137774137775137776137777137778137779137780137781137782137783137784137785137786137787137788137789137790137791137792137793137794137795137796137797137798137799137800137801137802137803137804137805137806137807137808137809137810137811137812137813137814137815137816137817137818137819137820137821137822137823137824137825137826137827137828137829137830137831137832137833137834137835137836137837137838137839137840137841137842137843137844137845137846137847137848137849137850137851137852137853137854137855137856137857137858137859137860137861137862137863137864137865137866137867137868137869137870137871137872137873137874137875137876137877137878137879137880137881137882137883137884137885137886137887137888137889137890137891137892137893137894137895137896137897137898137899137900137901137902137903137904137905137906137907137908137909137910137911137912137913137914137915137916137917137918137919137920137921137922137923137924137925137926137927137928137929137930137931137932137933137934137935137936137937137938137939137940137941137942137943137944137945137946137947137948137949137950137951137952137953137954137955137956137957137958137959137960137961137962137963137964137965137966137967137968137969137970137971137972137973137974137975137976137977137978137979137980137981137982137983137984137985137986137987137988137989137990137991137992137993137994137995137996137997137998137999138000138001138002138003138004138005138006138007138008138009138010138011138012138013138014138015138016138017138018138019138020138021138022138023138024138025138026138027138028138029138030138031138032138033138034138035138036138037138038138039138040138041138042138043138044138045138046138047138048138049138050138051138052138053138054138055138056138057138058138059138060138061138062138063138064138065138066138067138068138069138070138071138072138073138074138075138076138077138078138079138080138081138082138083138084138085138086138087138088138089138090138091138092138093138094138095138096138097138098138099138100138101138102138103138104138105138106138107138108138109138110138111138112138113138114138115138116138117138118138119138120138121138122138123138124138125138126138127138128138129138130138131138132138133138134138135138136138137138138138139138140138141138142138143138144138145138146138147138148138149138150138151138152138153138154138155138156138157138158138159138160138161138162138163138164138165138166138167138168138169138170138171138172138173138174138175138176138177138178138179138180138181138182138183138184138185138186138187138188138189138190138191138192138193138194138195138196138197138198138199138200138201138202138203138204138205138206138207138208138209138210138211138212138213138214138215138216138217138218138219138220138221138222138223138224138225138226138227138228138229138230138231138232138233138234138235138236138237138238138239138240138241138242138243138244138245138246138247138248138249138250138251138252138253138254138255138256138257138258138259138260138261138262138263138264138265138266138267138268138269138270138271138272138273138274138275138276138277138278138279138280138281138282138283138284138285138286138287138288138289138290138291138292138293138294138295138296138297138298138299138300138301138302138303138304138305138306138307138308138309138310138311138312138313138314138315138316138317138318138319138320138321138322138323138324138325138326138327138328138329138330138331138332138333138334138335138336138337138338138339138340138341138342138343138344138345138346138347138348138349138350138351138352138353138354138355138356138357138358138359138360138361138362138363138364138365138366138367138368138369138370138371138372138373138374138375138376138377138378138379138380138381138382138383138384138385138386138387138388138389138390138391138392138393138394138395138396138397138398138399138400138401138402138403138404138405138406138407138408138409138410138411138412138413138414138415138416138417138418138419138420138421138422138423138424138425138426138427138428138429138430138431138432138433138434138435138436138437138438138439138440138441138442138443138444138445138446138447138448138449138450138451138452138453138454138455138456138457138458138459138460138461138462138463138464138465138466138467138468138469138470138471138472138473138474138475138476138477138478138479138480138481138482138483138484138485138486138487138488138489138490138491138492138493138494138495138496138497138498138499138500138501138502138503138504138505138506138507138508138509138510138511138512138513138514138515138516138517138518138519138520138521138522138523138524138525138526138527138528138529138530138531138532138533138534138535138536138537138538138539138540138541138542138543138544138545138546138547138548138549138550138551138552138553138554138555138556138557138558138559138560138561138562138563138564138565138566138567138568138569138570138571138572138573138574138575138576138577138578138579138580138581138582138583138584138585138586138587138588138589138590138591138592138593138594138595138596138597138598138599138600138601138602138603138604138605138606138607138608138609138610138611138612138613138614138615138616138617138618138619138620138621138622138623138624138625138626138627138628138629138630138631138632138633138634138635138636138637138638138639138640138641138642138643138644138645138646138647138648138649138650138651138652138653138654138655138656138657138658138659138660138661138662138663138664138665138666138667138668138669138670138671138672138673138674138675138676138677138678138679138680138681138682138683138684138685138686138687138688138689138690138691138692138693138694138695138696138697138698138699138700138701138702138703138704138705138706138707138708138709138710138711138712138713138714138715138716138717138718138719138720138721138722138723138724138725138726138727138728138729138730138731138732138733138734138735138736138737138738138739138740138741138742138743138744138745138746138747138748138749138750138751138752138753138754138755138756138757138758138759138760138761138762138763138764138765138766138767138768138769138770138771138772138773138774138775138776138777138778138779138780138781138782138783138784138785138786138787138788138789138790138791138792138793138794138795138796138797138798138799138800138801138802138803138804138805138806138807138808138809138810138811138812138813138814138815138816138817138818138819138820138821138822138823138824138825138826138827138828138829138830138831138832138833138834138835138836138837138838138839138840138841138842138843138844138845138846138847138848138849138850138851138852138853138854138855138856138857138858138859138860138861138862138863138864138865138866138867138868138869138870138871138872138873138874138875138876138877138878138879138880138881138882138883138884138885138886138887138888138889138890138891138892138893138894138895138896138897138898138899138900138901138902138903138904138905138906138907138908138909138910138911138912138913138914138915138916138917138918138919138920138921138922138923138924138925138926138927138928138929138930138931138932138933138934138935138936138937138938138939138940138941138942138943138944138945138946138947138948138949138950138951138952138953138954138955138956138957138958138959138960138961138962138963138964138965138966138967138968138969138970138971138972138973138974138975138976138977138978138979138980138981138982138983138984138985138986138987138988138989138990138991138992138993138994138995138996138997138998138999139000139001139002139003139004139005139006139007139008139009139010139011139012139013139014139015139016139017139018139019139020139021139022139023139024139025139026139027139028139029139030139031139032139033139034139035139036139037139038139039139040139041139042139043139044139045139046139047139048139049139050139051139052139053139054139055139056139057139058139059139060139061139062139063139064139065139066139067139068139069139070139071139072139073139074139075139076139077139078139079139080139081139082139083139084139085139086139087139088139089139090139091139092139093139094139095139096139097139098139099139100139101139102139103139104139105139106139107139108139109139110139111139112139113139114139115139116139117139118139119139120139121139122139123139124139125139126139127139128139129139130139131139132139133139134139135139136139137139138139139139140139141139142139143139144139145139146139147139148139149139150139151139152139153139154139155139156139157139158139159139160139161139162139163139164139165139166139167139168139169139170139171139172139173139174139175139176139177139178139179139180139181139182139183139184139185139186139187139188139189139190139191139192139193139194139195139196139197139198139199139200139201139202139203139204139205139206139207139208139209139210139211139212139213139214139215139216139217139218139219139220139221139222139223139224139225139226139227139228139229139230139231139232139233139234139235139236139237139238139239139240139241139242139243139244139245139246139247139248139249139250139251139252139253139254139255139256139257139258139259139260139261139262139263139264139265139266139267139268139269139270139271139272139273139274139275139276139277139278139279139280139281139282139283139284139285139286139287139288139289139290139291139292139293139294139295139296139297139298139299139300139301139302139303139304139305139306139307139308139309139310139311139312139313139314139315139316139317139318139319139320139321139322139323139324139325139326139327139328139329139330139331139332139333139334139335139336139337139338139339139340139341139342139343139344139345139346139347139348139349139350139351139352139353139354139355139356139357139358139359139360139361139362139363139364139365139366139367139368139369139370139371139372139373139374139375139376139377139378139379139380139381139382139383139384139385139386139387139388139389139390139391139392139393139394139395139396139397139398139399139400139401139402139403139404139405139406139407139408139409139410139411139412139413139414139415139416139417139418139419139420139421139422139423139424139425139426139427139428139429139430139431139432139433139434139435139436139437139438139439139440139441139442139443139444139445139446139447139448139449139450139451139452139453139454139455139456139457139458139459139460139461139462139463139464139465139466139467139468139469139470139471139472139473139474139475139476139477139478139479139480139481139482139483139484139485139486139487139488139489139490139491139492139493139494139495139496139497139498139499139500139501139502139503139504139505139506139507139508139509139510139511139512139513139514139515139516139517139518139519139520139521139522139523139524139525139526139527139528139529139530139531139532139533139534139535139536139537139538139539139540139541139542139543139544139545139546139547139548139549139550139551139552139553139554139555139556139557139558139559139560139561139562139563139564139565139566139567139568139569139570139571139572139573139574139575139576139577139578139579139580139581139582139583139584139585139586139587139588139589139590139591139592139593139594139595139596139597139598139599139600139601139602139603139604139605139606139607139608139609139610139611139612139613139614139615139616139617139618139619139620139621139622139623139624139625139626139627139628139629139630139631139632139633139634139635139636139637139638139639139640139641139642139643139644139645139646139647139648139649139650139651139652139653139654139655139656139657139658139659139660139661139662139663139664139665139666139667139668139669139670139671139672139673139674139675139676139677139678139679139680139681139682139683139684139685139686139687139688139689139690139691139692139693139694139695139696139697139698139699139700139701139702139703139704139705139706139707139708139709139710139711139712139713139714139715139716139717139718139719139720139721139722139723139724139725139726139727139728139729139730139731139732139733139734139735139736139737139738139739139740139741139742139743139744139745139746139747139748139749139750139751139752139753139754139755139756139757139758139759139760139761139762139763139764139765139766139767139768139769139770139771139772139773139774139775139776139777139778139779139780139781139782139783139784139785139786139787139788139789139790139791139792139793139794139795139796139797139798139799139800139801139802139803139804139805139806139807139808139809139810139811139812139813139814139815139816139817139818139819139820139821139822139823139824139825139826139827139828139829139830139831139832139833139834139835139836139837139838139839139840139841139842139843139844139845139846139847139848139849139850139851139852139853139854139855139856139857139858139859139860139861139862139863139864139865139866139867139868139869139870139871139872139873139874139875139876139877139878139879139880139881139882139883139884139885139886139887139888139889139890139891139892139893139894139895139896139897139898139899139900139901139902139903139904139905139906139907139908139909139910139911139912139913139914139915139916139917139918139919139920139921139922139923139924139925139926139927139928139929139930139931139932139933139934139935139936139937139938139939139940139941139942139943139944139945139946139947139948139949139950139951139952139953139954139955139956139957139958139959139960139961139962139963139964139965139966139967139968139969139970139971139972139973139974139975139976139977139978139979139980139981139982139983139984139985139986139987139988139989139990139991139992139993139994139995139996139997139998139999140000140001140002140003140004140005140006140007140008140009140010140011140012140013140014140015140016140017140018140019140020140021140022140023140024140025140026140027140028140029140030140031140032140033140034140035140036140037140038140039140040140041140042140043140044140045140046140047140048140049140050140051140052140053140054140055140056140057140058140059140060140061140062140063140064140065140066140067140068140069140070140071140072140073140074140075140076140077140078140079140080140081140082140083140084140085140086140087140088140089140090140091140092140093140094140095140096140097140098140099140100140101140102140103140104140105140106140107140108140109140110140111140112140113140114140115140116140117140118140119140120140121140122140123140124140125140126140127140128140129140130140131140132140133140134140135140136140137140138140139140140140141140142140143140144140145140146140147140148140149140150140151140152140153140154140155140156140157140158140159140160140161140162140163140164140165140166140167140168140169140170140171140172140173140174140175140176140177140178140179140180140181140182140183140184140185140186140187140188140189140190140191140192140193140194140195140196140197140198140199140200140201140202140203140204140205140206140207140208140209140210140211140212140213140214140215140216140217140218140219140220140221140222140223140224140225140226140227140228140229140230140231140232140233140234140235140236140237140238140239140240140241140242140243140244140245140246140247140248140249140250140251140252140253140254140255140256140257140258140259140260140261140262140263140264140265140266140267140268140269140270140271140272140273140274140275140276140277140278140279140280140281140282140283140284140285140286140287140288140289140290140291140292140293140294140295140296140297140298140299140300140301140302140303140304140305140306140307140308140309140310140311140312140313140314140315140316140317140318140319140320140321140322140323140324140325140326140327140328140329140330140331140332140333140334140335140336140337140338140339140340140341140342140343140344140345140346140347140348140349140350140351140352140353140354140355140356140357140358140359140360140361140362140363140364140365140366140367140368140369140370140371140372140373140374140375140376140377140378140379140380140381140382140383140384140385140386140387140388140389140390140391140392140393140394140395140396140397140398140399140400140401140402140403140404140405140406140407140408140409140410140411140412140413140414140415140416140417140418140419140420140421140422140423140424140425140426140427140428140429140430140431140432140433140434140435140436140437140438140439140440140441140442140443140444140445140446140447140448140449140450140451140452140453140454140455140456140457140458140459140460140461140462140463140464140465140466140467140468140469140470140471140472140473140474140475140476140477140478140479140480140481140482140483140484140485140486140487140488140489140490140491140492140493140494140495140496140497140498140499140500140501140502140503140504140505140506140507140508140509140510140511140512140513140514140515140516140517140518140519140520140521140522140523140524140525140526140527140528140529140530140531140532140533140534140535140536140537140538140539140540140541140542140543140544140545140546140547140548140549140550140551140552140553140554140555140556140557140558140559140560140561140562140563140564140565140566140567140568140569140570140571140572140573140574140575140576140577140578140579140580140581140582140583140584140585140586140587140588140589140590140591140592140593140594140595140596140597140598140599140600140601140602140603140604140605140606140607140608140609140610140611140612140613140614140615140616140617140618140619140620140621140622140623140624140625140626140627140628140629140630140631140632140633140634140635140636140637140638140639140640140641140642140643140644140645140646140647140648140649140650140651140652140653140654140655140656140657140658140659140660140661140662140663140664140665140666140667140668140669140670140671140672140673140674140675140676140677140678140679140680140681140682140683140684140685140686140687140688140689140690140691140692140693140694140695140696140697140698140699140700140701140702140703140704140705140706140707140708140709140710140711140712140713140714140715140716140717140718140719140720140721140722140723140724140725140726140727140728140729140730140731140732140733140734140735140736140737140738140739140740140741140742140743140744140745140746140747140748140749140750140751140752140753140754140755140756140757140758140759140760140761140762140763140764140765140766140767140768140769140770140771140772140773140774140775140776140777140778140779140780140781140782140783140784140785140786140787140788140789140790140791140792140793140794140795140796140797140798140799140800140801140802140803140804140805140806140807140808140809140810140811140812140813140814140815140816140817140818140819140820140821140822140823140824140825140826140827140828140829140830140831140832140833140834140835140836140837140838140839140840140841140842140843140844140845140846140847140848140849140850140851140852140853140854140855140856140857140858140859140860140861140862140863140864140865140866140867140868140869140870140871140872140873140874140875140876140877140878140879140880140881140882140883140884140885140886140887140888140889140890140891140892140893140894140895140896140897140898140899140900140901140902140903140904140905140906140907140908140909140910140911140912140913140914140915140916140917140918140919140920140921140922140923140924140925140926140927140928140929140930140931140932140933140934140935140936140937140938140939140940140941140942140943140944140945140946140947140948140949140950140951140952140953140954140955140956140957140958140959140960140961140962140963140964140965140966140967140968140969140970140971140972140973140974140975140976140977140978140979140980140981140982140983140984140985140986140987140988140989140990140991140992140993140994140995140996140997140998140999141000141001141002141003141004141005141006141007141008141009141010141011141012141013141014141015141016141017141018141019141020141021141022141023141024141025141026141027141028141029141030141031141032141033141034141035141036141037141038141039141040141041141042141043141044141045141046141047141048141049141050141051141052141053141054141055141056141057141058141059141060141061141062141063141064141065141066141067141068141069141070141071141072141073141074141075141076141077141078141079141080141081141082141083141084141085141086141087141088141089141090141091141092141093141094141095141096141097141098141099141100141101141102141103141104141105141106141107141108141109141110141111141112141113141114141115141116141117141118141119141120141121141122141123141124141125141126141127141128141129141130141131141132141133141134141135141136141137141138141139141140141141141142141143141144141145141146141147141148141149141150141151141152141153141154141155141156141157141158141159141160141161141162141163141164141165141166141167141168141169141170141171141172141173141174141175141176141177141178141179141180141181141182141183141184141185141186141187141188141189141190141191141192141193141194141195141196141197141198141199141200141201141202141203141204141205141206141207141208141209141210141211141212141213141214141215141216141217141218141219141220141221141222141223141224141225141226141227141228141229141230141231141232141233141234141235141236141237141238141239141240141241141242141243141244141245141246141247141248141249141250141251141252141253141254141255141256141257141258141259141260141261141262141263141264141265141266141267141268141269141270141271141272141273141274141275141276141277141278141279141280141281141282141283141284141285141286141287141288141289141290141291141292141293141294141295141296141297141298141299141300141301141302141303141304141305141306141307141308141309141310141311141312141313141314141315141316141317141318141319141320141321141322141323141324141325141326141327141328141329141330141331141332141333141334141335141336141337141338141339141340141341141342141343141344141345141346141347141348141349141350141351141352141353141354141355141356141357141358141359141360141361141362141363141364141365141366141367141368141369141370141371141372141373141374141375141376141377141378141379141380141381141382141383141384141385141386141387141388141389141390141391141392141393141394141395141396141397141398141399141400141401141402141403141404141405141406141407141408141409141410141411141412141413141414141415141416141417141418141419141420141421141422141423141424141425141426141427141428141429141430141431141432141433141434141435141436141437141438141439141440141441141442141443141444141445141446141447141448141449141450141451141452141453141454141455141456141457141458141459141460141461141462141463141464141465141466141467141468141469141470141471141472141473141474141475141476141477141478141479141480141481141482141483141484141485141486141487141488141489141490141491141492141493141494141495141496141497141498141499141500141501141502141503141504141505141506141507141508141509141510141511141512141513141514141515141516141517141518141519141520141521141522141523141524141525141526141527141528141529141530141531141532141533141534141535141536141537141538141539141540141541141542141543141544141545141546141547141548141549141550141551141552141553141554141555141556141557141558141559141560141561141562141563141564141565141566141567141568141569141570141571141572141573141574141575141576141577141578141579141580141581141582141583141584141585141586141587141588141589141590141591141592141593141594141595141596141597141598141599141600141601141602141603141604141605141606141607141608141609141610141611141612141613141614141615141616141617141618141619141620141621141622141623141624141625141626141627141628141629141630141631141632141633141634141635141636141637141638141639141640141641141642141643141644141645141646141647141648141649141650141651141652141653141654141655141656141657141658141659141660141661141662141663141664141665141666141667141668141669141670141671141672141673141674141675141676141677141678141679141680141681141682141683141684141685141686141687141688141689141690141691141692141693141694141695141696141697141698141699141700141701141702141703141704141705141706141707141708141709141710141711141712141713141714141715141716141717141718141719141720141721141722141723141724141725141726141727141728141729141730141731141732141733141734141735141736141737141738141739141740141741141742141743141744141745141746141747141748141749141750141751141752141753141754141755141756141757141758141759141760141761141762141763141764141765141766141767141768141769141770141771141772141773141774141775141776141777141778141779141780141781141782141783141784141785141786141787141788141789141790141791141792141793141794141795141796141797141798141799141800141801141802141803141804141805141806141807141808141809141810141811141812141813141814141815141816141817141818141819141820141821141822141823141824141825141826141827141828141829141830141831141832141833141834141835141836141837141838141839141840141841141842141843141844141845141846141847141848141849141850141851141852141853141854141855141856141857141858141859141860141861141862141863141864141865141866141867141868141869141870141871141872141873141874141875141876141877141878141879141880141881141882141883141884141885141886141887141888141889141890141891141892141893141894141895141896141897141898141899141900141901141902141903141904141905141906141907141908141909141910141911141912141913141914141915141916141917141918141919141920141921141922141923141924141925141926141927141928141929141930141931141932141933141934141935141936141937141938141939141940141941141942141943141944141945141946141947141948141949141950141951141952141953141954141955141956141957141958141959141960141961141962141963141964141965141966141967141968141969141970141971141972141973141974141975141976141977141978141979141980141981141982141983141984141985141986141987141988141989141990141991141992141993141994141995141996141997141998141999142000142001142002142003142004142005142006142007142008142009142010142011142012142013142014142015142016142017142018142019142020142021142022142023142024142025142026142027142028142029142030142031142032142033142034142035142036142037142038142039142040142041142042142043142044142045142046142047142048142049142050142051142052142053142054142055142056142057142058142059142060142061142062142063142064142065142066142067142068142069142070142071142072142073142074142075142076142077142078142079142080142081142082142083142084142085142086142087142088142089142090142091142092142093142094142095142096142097142098142099142100142101142102142103142104142105142106142107142108142109142110142111142112142113142114142115142116142117142118142119142120142121142122142123142124142125142126142127142128142129142130142131142132142133142134142135142136142137142138142139142140142141142142142143142144142145142146142147142148142149142150142151142152142153142154142155142156142157142158142159142160142161142162142163142164142165142166142167142168142169142170142171142172142173142174142175142176142177142178142179142180142181142182142183142184142185142186142187142188142189142190142191142192142193142194142195142196142197142198142199142200142201142202142203142204142205142206142207142208142209142210142211142212142213142214142215142216142217142218142219142220142221142222142223142224142225142226142227142228142229142230142231142232142233142234142235142236142237142238142239142240142241142242142243142244142245142246142247142248142249142250142251142252142253142254142255142256142257142258142259142260142261142262142263142264142265142266142267142268142269142270142271142272142273142274142275142276142277142278142279142280142281142282142283142284142285142286142287142288142289142290142291142292142293142294142295142296142297142298142299142300142301142302142303142304142305142306142307142308142309142310142311142312142313142314142315142316142317142318142319142320142321142322142323142324142325142326142327142328142329142330142331142332142333142334142335142336142337142338142339142340142341142342142343142344142345142346142347142348142349142350142351142352142353142354142355142356142357142358142359142360142361142362142363142364142365142366142367142368142369142370142371142372142373142374142375142376142377142378142379142380142381142382142383142384142385142386142387142388142389142390142391142392142393142394142395142396142397142398142399142400142401142402142403142404142405142406142407142408142409142410142411142412142413142414142415142416142417142418142419142420142421142422142423142424142425142426142427142428142429142430142431142432142433142434142435142436142437142438142439142440142441142442142443142444142445142446142447142448142449142450142451142452142453142454142455142456142457142458142459142460142461142462142463142464142465142466142467142468142469142470142471142472142473142474142475142476142477142478142479142480142481142482142483142484142485142486142487142488142489142490142491142492142493142494142495142496142497142498142499142500142501142502142503142504142505142506142507142508142509142510142511142512142513142514142515142516142517142518142519142520142521142522142523142524142525142526142527142528142529142530142531142532142533142534142535142536142537142538142539142540142541142542142543142544142545142546142547142548142549142550142551142552142553142554142555142556142557142558142559142560142561142562142563142564142565142566142567142568142569142570142571142572142573142574142575142576142577142578142579142580142581142582142583142584142585142586142587142588142589142590142591142592142593142594142595142596142597142598142599142600142601142602142603142604142605142606142607142608142609142610142611142612142613142614142615142616142617142618142619142620142621142622142623142624142625142626142627142628142629142630142631142632142633142634142635142636142637142638142639142640142641142642142643142644142645142646142647142648142649142650142651142652142653142654142655142656142657142658142659142660142661142662142663142664142665142666142667142668142669142670142671142672142673142674142675142676142677142678142679142680142681142682142683142684142685142686142687142688142689142690142691142692142693142694142695142696142697142698142699142700142701142702142703142704142705142706142707142708142709142710142711142712142713142714142715142716142717142718142719142720142721142722142723142724142725142726142727142728142729142730142731142732142733142734142735142736142737142738142739142740142741142742142743142744142745142746142747142748142749142750142751142752142753142754142755142756142757142758142759142760142761142762142763142764142765142766142767142768142769142770142771142772142773142774142775142776142777142778142779142780142781142782142783142784142785142786142787142788142789142790142791142792142793142794142795142796142797142798142799142800142801142802142803142804142805142806142807142808142809142810142811142812142813142814142815142816142817142818142819142820142821142822142823142824142825142826142827142828142829142830142831142832142833142834142835142836142837142838142839142840142841142842142843142844142845142846142847142848142849142850142851142852142853142854142855142856142857142858142859142860142861142862142863142864142865142866142867142868142869142870142871142872142873142874142875142876142877142878142879142880142881142882142883142884142885142886142887142888142889142890142891142892142893142894142895142896142897142898142899142900142901142902142903142904142905142906142907142908142909142910142911142912142913142914142915142916142917142918142919142920142921142922142923142924142925142926142927142928142929142930142931142932142933142934142935142936142937142938142939142940142941142942142943142944142945142946142947142948142949142950142951142952142953142954142955142956142957142958142959142960142961142962142963142964142965142966142967142968142969142970142971142972142973142974142975142976142977142978142979142980142981142982142983142984142985142986142987142988142989142990142991142992142993142994142995142996142997142998142999143000143001143002143003143004143005143006143007143008143009143010143011143012143013143014143015143016143017143018143019143020143021143022143023143024143025143026143027143028143029143030143031143032143033143034143035143036143037143038143039143040143041143042143043143044143045143046143047143048143049143050143051143052143053143054143055143056143057143058143059143060143061143062143063143064143065143066143067143068143069143070143071143072143073143074143075143076143077143078143079143080143081143082143083143084143085143086143087143088143089143090143091143092143093143094143095143096143097143098143099143100143101143102143103143104143105143106143107143108143109143110143111143112143113143114143115143116143117143118143119143120143121143122143123143124143125143126143127143128143129143130143131143132143133143134143135143136143137143138143139143140143141143142143143143144143145143146143147143148143149143150143151143152143153143154143155143156143157143158143159143160143161143162143163143164143165143166143167143168143169143170143171143172143173143174143175143176143177143178143179143180143181143182143183143184143185143186143187143188143189143190143191143192143193143194143195143196143197143198143199143200143201143202143203143204143205143206143207143208143209143210143211143212143213143214143215143216143217143218143219143220143221143222143223143224143225143226143227143228143229143230143231143232143233143234143235143236143237143238143239143240143241143242143243143244143245143246143247143248143249143250143251143252143253143254143255143256143257143258143259143260143261143262143263143264143265143266143267143268143269143270143271143272143273143274143275143276143277143278143279143280143281143282143283143284143285143286143287143288143289143290143291143292143293143294143295143296143297143298143299143300143301143302143303143304143305143306143307143308143309143310143311143312143313143314143315143316143317143318143319143320143321143322143323143324143325143326143327143328143329143330143331143332143333143334143335143336143337143338143339143340143341143342143343143344143345143346143347143348143349143350143351143352143353143354143355143356143357143358143359143360143361143362143363143364143365143366143367143368143369143370143371143372143373143374143375143376143377143378143379143380143381143382143383143384143385143386143387143388143389143390143391143392143393143394143395143396143397143398143399143400143401143402143403143404143405143406143407143408143409143410143411143412143413143414143415143416143417143418143419143420143421143422143423143424143425143426143427143428143429143430143431143432143433143434143435143436143437143438143439143440143441143442143443143444143445143446143447143448143449143450143451143452143453143454143455143456143457143458143459143460143461143462143463143464143465143466143467143468143469143470143471143472143473143474143475143476143477143478143479143480143481143482143483143484143485143486143487143488143489143490143491143492143493143494143495143496143497143498143499143500143501143502143503143504143505143506143507143508143509143510143511143512143513143514143515143516143517143518143519143520143521143522143523143524143525143526143527143528143529143530143531143532143533143534143535143536143537143538143539143540143541143542143543143544143545143546143547143548143549143550143551143552143553143554143555143556143557143558143559143560143561143562143563143564143565143566143567143568143569143570143571143572143573143574143575143576143577143578143579143580143581143582143583143584143585143586143587143588143589143590143591143592143593143594143595143596143597143598143599143600143601143602143603143604143605143606143607143608143609143610143611143612143613143614143615143616143617143618143619143620143621143622143623143624143625143626143627143628143629143630143631143632143633143634143635143636143637143638143639143640143641143642143643143644143645143646143647143648143649143650143651143652143653143654143655143656143657143658143659143660143661143662143663143664143665143666143667143668143669143670143671143672143673143674143675143676143677143678143679143680143681143682143683143684143685143686143687143688143689143690143691143692143693143694143695143696143697143698143699143700143701143702143703143704143705143706143707143708143709143710143711143712143713143714143715143716143717143718143719143720143721143722143723143724143725143726143727143728143729143730143731143732143733143734143735143736143737143738143739143740143741143742143743143744143745143746143747143748143749143750143751143752143753143754143755143756143757143758143759143760143761143762143763143764143765143766143767143768143769143770143771143772143773143774143775143776143777143778143779143780143781143782143783143784143785143786143787143788143789143790143791143792143793143794143795143796143797143798143799143800143801143802143803143804143805143806143807143808143809143810143811143812143813143814143815143816143817143818143819143820143821143822143823143824143825143826143827143828143829143830143831143832143833143834143835143836143837143838143839143840143841143842143843143844143845143846143847143848143849143850143851143852143853143854143855143856143857143858143859143860143861143862143863143864143865143866143867143868143869143870143871143872143873143874143875143876143877143878143879143880143881143882143883143884143885143886143887143888143889143890143891143892143893143894143895143896143897143898143899143900143901143902143903143904143905143906143907143908143909143910143911143912143913143914143915143916143917143918143919143920143921143922143923143924143925143926143927143928143929143930143931143932143933143934143935143936143937143938143939143940143941143942143943143944143945143946143947143948143949143950143951143952143953143954143955143956143957143958143959143960143961143962143963143964143965143966143967143968143969143970143971143972143973143974143975143976143977143978143979143980143981143982143983143984143985143986143987143988143989143990143991143992143993143994143995143996143997143998143999144000144001144002144003144004144005144006144007144008144009144010144011144012144013144014144015144016144017144018144019144020144021144022144023144024144025144026144027144028144029144030144031144032144033144034144035144036144037144038144039144040144041144042144043144044144045144046144047144048144049144050144051144052144053144054144055144056144057144058144059144060144061144062144063144064144065144066144067144068144069144070144071144072144073144074144075144076144077144078144079144080144081144082144083144084144085144086144087144088144089144090144091144092144093144094144095144096144097144098144099144100144101144102144103144104144105144106144107144108144109144110144111144112144113144114144115144116144117144118144119144120144121144122144123144124144125144126144127144128144129144130144131144132144133144134144135144136144137144138144139144140144141144142144143144144144145144146144147144148144149144150144151144152144153144154144155144156144157144158144159144160144161144162144163144164144165144166144167144168144169144170144171144172144173144174144175144176144177144178144179144180144181144182144183144184144185144186144187144188144189144190144191144192144193144194144195144196144197144198144199144200144201144202144203144204144205144206144207144208144209144210144211144212144213144214144215144216144217144218144219144220144221144222144223144224144225144226144227144228144229144230144231144232144233144234144235144236144237144238144239144240144241144242144243144244144245144246144247144248144249144250144251144252144253144254144255144256144257144258144259144260144261144262144263144264144265144266144267144268144269144270144271144272144273144274144275144276144277144278144279144280144281144282144283144284144285144286144287144288144289144290144291144292144293144294144295144296144297144298144299144300144301144302144303144304144305144306144307144308144309144310144311144312144313144314144315144316144317144318144319144320144321144322144323144324144325144326144327144328144329144330144331144332144333144334144335144336144337144338144339144340144341144342144343144344144345144346144347144348144349144350144351144352144353144354144355144356144357144358144359144360144361144362144363144364144365144366144367144368144369144370144371144372144373144374144375144376144377144378144379144380144381144382144383144384144385144386144387144388144389144390144391144392144393144394144395144396144397144398144399144400144401144402144403144404144405144406144407144408144409144410144411144412144413144414144415144416144417144418144419144420144421144422144423144424144425144426144427144428144429144430144431144432144433144434144435144436144437144438144439144440144441144442144443144444144445144446144447144448144449144450144451144452144453144454144455144456144457144458144459144460144461144462144463144464144465144466144467144468144469144470144471144472144473144474144475144476144477144478144479144480144481144482144483144484144485144486144487144488144489144490144491144492144493144494144495144496144497144498144499144500144501144502144503144504144505144506144507144508144509144510144511144512144513144514144515144516144517144518144519144520144521144522144523144524144525144526144527144528144529144530144531144532144533144534144535144536144537144538144539144540144541144542144543144544144545144546144547144548144549144550144551144552144553144554144555144556144557144558144559144560144561144562144563144564144565144566144567144568144569144570144571144572144573144574144575144576144577144578144579144580144581144582144583144584144585144586144587144588144589144590144591144592144593144594144595144596144597144598144599144600144601144602144603144604144605144606144607144608144609144610144611144612144613144614144615144616144617144618144619144620144621144622144623144624144625144626144627144628144629144630144631144632144633144634144635144636144637144638144639144640144641144642144643144644144645144646144647144648144649144650144651144652144653144654144655144656144657144658144659144660144661144662144663144664144665144666144667144668144669144670144671144672144673144674144675144676144677144678144679144680144681144682144683144684144685144686144687144688144689144690144691144692144693144694144695144696144697144698144699144700144701144702144703144704144705144706144707144708144709144710144711144712144713144714144715144716144717144718144719144720144721144722144723144724144725144726144727144728144729144730144731144732144733144734144735144736144737144738144739144740144741144742144743144744144745144746144747144748144749144750144751144752144753144754144755144756144757144758144759144760144761144762144763144764144765144766144767144768144769144770144771144772144773144774144775144776144777144778144779144780144781144782144783144784144785144786144787144788144789144790144791144792144793144794144795144796144797144798144799144800144801144802144803144804144805144806144807144808144809144810144811144812144813144814144815144816144817144818144819144820144821144822144823144824144825144826144827144828144829144830144831144832144833144834144835144836144837144838144839144840144841144842144843144844144845144846144847144848144849144850144851144852144853144854144855144856144857144858144859144860144861144862144863144864144865144866144867144868144869144870144871144872144873144874144875144876144877144878144879144880144881144882144883144884144885144886144887144888144889144890144891144892144893144894144895144896144897144898144899144900144901144902144903144904144905144906144907144908144909144910144911144912144913144914144915144916144917144918144919144920144921144922144923144924144925144926144927144928144929144930144931144932144933144934144935144936144937144938144939144940144941144942144943144944144945144946144947144948144949144950144951144952144953144954144955144956144957144958144959144960144961144962144963144964144965144966144967144968144969144970144971144972144973144974144975144976144977144978144979144980144981144982144983144984144985144986144987144988144989144990144991144992144993144994144995144996144997144998144999145000145001145002145003145004145005145006145007145008145009145010145011145012145013145014145015145016145017145018145019145020145021145022145023145024145025145026145027145028145029145030145031145032145033145034145035145036145037145038145039145040145041145042145043145044145045145046145047145048145049145050145051145052145053145054145055145056145057145058145059145060145061145062145063145064145065145066145067145068145069145070145071145072145073145074145075145076145077145078145079145080145081145082145083145084145085145086145087145088145089145090145091145092145093145094145095145096145097145098145099145100145101145102145103145104145105145106145107145108145109145110145111145112145113145114145115145116145117145118145119145120145121145122145123145124145125145126145127145128145129145130145131145132145133145134145135145136145137145138145139145140145141145142145143145144145145145146145147145148145149145150145151145152145153145154145155145156145157145158145159145160145161145162145163145164145165145166145167145168145169145170145171145172145173145174145175145176145177145178145179145180145181145182145183145184145185145186145187145188145189145190145191145192145193145194145195145196145197145198145199145200145201145202145203145204145205145206145207145208145209145210145211145212145213145214145215145216145217145218145219145220145221145222145223145224145225145226145227145228145229145230145231145232145233145234145235145236145237145238145239145240145241145242145243145244145245145246145247145248145249145250145251145252145253145254145255145256145257145258145259145260145261145262145263145264145265145266145267145268145269145270145271145272145273145274145275145276145277145278145279145280145281145282145283145284145285145286145287145288145289145290145291145292145293145294145295145296145297145298145299145300145301145302145303145304145305145306145307145308145309145310145311145312145313145314145315145316145317145318145319145320145321145322145323145324145325145326145327145328145329145330145331145332145333145334145335145336145337145338145339145340145341145342145343145344145345145346145347145348145349145350145351145352145353145354145355145356145357145358145359145360145361145362145363145364145365145366145367145368145369145370145371145372145373145374145375145376145377145378145379145380145381145382145383145384145385145386145387145388145389145390145391145392145393145394145395145396145397145398145399145400145401145402145403145404145405145406145407145408145409145410145411145412145413145414145415145416145417145418145419145420145421145422145423145424145425145426145427145428145429145430145431145432145433145434145435145436145437145438145439145440145441145442145443145444145445145446145447145448145449145450145451145452145453145454145455145456145457145458145459145460145461145462145463145464145465145466145467145468145469145470145471145472145473145474145475145476145477145478145479145480145481145482145483145484145485145486145487145488145489145490145491145492145493145494145495145496145497145498145499145500145501145502145503145504145505145506145507145508145509145510145511145512145513145514145515145516145517145518145519145520145521145522145523145524145525145526145527145528145529145530145531145532145533145534145535145536145537145538145539145540145541145542145543145544145545145546145547145548145549145550145551145552145553145554145555145556145557145558145559145560145561145562145563145564145565145566145567145568145569145570145571145572145573145574145575145576145577145578145579145580145581145582145583145584145585145586145587145588145589145590145591145592145593145594145595145596145597145598145599145600145601145602145603145604145605145606145607145608145609145610145611145612145613145614145615145616145617145618145619145620145621145622145623145624145625145626145627145628145629145630145631145632145633145634145635145636145637145638145639145640145641145642145643145644145645145646145647145648145649145650145651145652145653145654145655145656145657145658145659145660145661145662145663145664145665145666145667145668145669145670145671145672145673145674145675145676145677145678145679145680145681145682145683145684145685145686145687145688145689145690145691145692145693145694145695145696145697145698145699145700145701145702145703145704145705145706145707145708145709145710145711145712145713145714145715145716145717145718145719145720145721145722145723145724145725145726145727145728145729145730145731145732145733145734145735145736145737145738145739145740145741145742145743145744145745145746145747145748145749145750145751145752145753145754145755145756145757145758145759145760145761145762145763145764145765145766145767145768145769145770145771145772145773145774145775145776145777145778145779145780145781145782145783145784145785145786145787145788145789145790145791145792145793145794145795145796145797145798145799145800145801145802145803145804145805145806145807145808145809145810145811145812145813145814145815145816145817145818145819145820145821145822145823145824145825145826145827145828145829145830145831145832145833145834145835145836145837145838145839145840145841145842145843145844145845145846145847145848145849145850145851145852145853145854145855145856145857145858145859145860145861145862145863145864145865145866145867145868145869145870145871145872145873145874145875145876145877145878145879145880145881145882145883145884145885145886145887145888145889145890145891145892145893145894145895145896145897145898145899145900145901145902145903145904145905145906145907145908145909145910145911145912145913145914145915145916145917145918145919145920145921145922145923145924145925145926145927145928145929145930145931145932145933145934145935145936145937145938145939145940145941145942145943145944145945145946145947145948145949145950145951145952145953145954145955145956145957145958145959145960145961145962145963145964145965145966145967145968145969145970145971145972145973145974145975145976145977145978145979145980145981145982145983145984145985145986145987145988145989145990145991145992145993145994145995145996145997145998145999146000146001146002146003146004146005146006146007146008146009146010146011146012146013146014146015146016146017146018146019146020146021146022146023146024146025146026146027146028146029146030146031146032146033146034146035146036146037146038146039146040146041146042146043146044146045146046146047146048146049146050146051146052146053146054146055146056146057146058146059146060146061146062146063146064146065146066146067146068146069146070146071146072146073146074146075146076146077146078146079146080146081146082146083146084146085146086146087146088146089146090146091146092146093146094146095146096146097146098146099146100146101146102146103146104146105146106146107146108146109146110146111146112146113146114146115146116146117146118146119146120146121146122146123146124146125146126146127146128146129146130146131146132146133146134146135146136146137146138146139146140146141146142146143146144146145146146146147146148146149146150146151146152146153146154146155146156146157146158146159146160146161146162146163146164146165146166146167146168146169146170146171146172146173146174146175146176146177146178146179146180146181146182146183146184146185146186146187146188146189146190146191146192146193146194146195146196146197146198146199146200146201146202146203146204146205146206146207146208146209146210146211146212146213146214146215146216146217146218146219146220146221146222146223146224146225146226146227146228146229146230146231146232146233146234146235146236146237146238146239146240146241146242146243146244146245146246146247146248146249146250146251146252146253146254146255146256146257146258146259146260146261146262146263146264146265146266146267146268146269146270146271146272146273146274146275146276146277146278146279146280146281146282146283146284146285146286146287146288146289146290146291146292146293146294146295146296146297146298146299146300146301146302146303146304146305146306146307146308146309146310146311146312146313146314146315146316146317146318146319146320146321146322146323146324146325146326146327146328146329146330146331146332146333146334146335146336146337146338146339146340146341146342146343146344146345146346146347146348146349146350146351146352146353146354146355146356146357146358146359146360146361146362146363146364146365146366146367146368146369146370146371146372146373146374146375146376146377146378146379146380146381146382146383146384146385146386146387146388146389146390146391146392146393146394146395146396146397146398146399146400146401146402146403146404146405146406146407146408146409146410146411146412146413146414146415146416146417146418146419146420146421146422146423146424146425146426146427146428146429146430146431146432146433146434146435146436146437146438146439146440146441146442146443146444146445146446146447146448146449146450146451146452146453146454146455146456146457146458146459146460146461146462146463146464146465146466146467146468146469146470146471146472146473146474146475146476146477146478146479146480146481146482146483146484146485146486146487146488146489146490146491146492146493146494146495146496146497146498146499146500146501146502146503146504146505146506146507146508146509146510146511146512146513146514146515146516146517146518146519146520146521146522146523146524146525146526146527146528146529146530146531146532146533146534146535146536146537146538146539146540146541146542146543146544146545146546146547146548146549146550146551146552146553146554146555146556146557146558146559146560146561146562146563146564146565146566146567146568146569146570146571146572146573146574146575146576146577146578146579146580146581146582146583146584146585146586146587146588146589146590146591146592146593146594146595146596146597146598146599146600146601146602146603146604146605146606146607146608146609146610146611146612146613146614146615146616146617146618146619146620146621146622146623146624146625146626146627146628146629146630146631146632146633146634146635146636146637146638146639146640146641146642146643146644146645146646146647146648146649146650146651146652146653146654146655146656146657146658146659146660146661146662146663146664146665146666146667146668146669146670146671146672146673146674146675146676146677146678146679146680146681146682146683146684146685146686146687146688146689146690146691146692146693146694146695146696146697146698146699146700146701146702146703146704146705146706146707146708146709146710146711146712146713146714146715146716146717146718146719146720146721146722146723146724146725146726146727146728146729146730146731146732146733146734146735146736146737146738146739146740146741146742146743146744146745146746146747146748146749146750146751146752146753146754146755146756146757146758146759146760146761146762146763146764146765146766146767146768146769146770146771146772146773146774146775146776146777146778146779146780146781146782146783146784146785146786146787146788146789146790146791146792146793146794146795146796146797146798146799146800146801146802146803146804146805146806146807146808146809146810146811146812146813146814146815146816146817146818146819146820146821146822146823146824146825146826146827146828146829146830146831146832146833146834146835146836146837146838146839146840146841146842146843146844146845146846146847146848146849146850146851146852146853146854146855146856146857146858146859146860146861146862146863146864146865146866146867146868146869146870146871146872146873146874146875146876146877146878146879146880146881146882146883146884146885146886146887146888146889146890146891146892146893146894146895146896146897146898146899146900146901146902146903146904146905146906146907146908146909146910146911146912146913146914146915146916146917146918146919146920146921146922146923146924146925146926146927146928146929146930146931146932146933146934146935146936146937146938146939146940146941146942146943146944146945146946146947146948146949146950146951146952146953146954146955146956146957146958146959146960146961146962146963146964146965146966146967146968146969146970146971146972146973146974146975146976146977146978146979146980146981146982146983146984146985146986146987146988146989146990146991146992146993146994146995146996146997146998146999147000147001147002147003147004147005147006147007147008147009147010147011147012147013147014147015147016147017147018147019147020147021147022147023147024147025147026147027147028147029147030147031147032147033147034147035147036147037147038147039147040147041147042147043147044147045147046147047147048147049147050147051147052147053147054147055147056147057147058147059147060147061147062147063147064147065147066147067147068147069147070147071147072147073147074147075147076147077147078147079147080147081147082147083147084147085147086147087147088147089147090147091147092147093147094147095147096147097147098147099147100147101147102147103147104147105147106147107147108147109147110147111147112147113147114147115147116147117147118147119147120147121147122147123147124147125147126147127147128147129147130147131147132147133147134147135147136147137147138147139147140147141147142147143147144147145147146147147147148147149147150147151147152147153147154147155147156147157147158147159147160147161147162147163147164147165147166147167147168147169147170147171147172147173147174147175147176147177147178147179147180147181147182147183147184147185147186147187147188147189147190147191147192147193147194147195147196147197147198147199147200147201147202147203147204147205147206147207147208147209147210147211147212147213147214147215147216147217147218147219147220147221147222147223147224147225147226147227147228147229147230147231147232147233147234147235147236147237147238147239147240147241147242147243147244147245147246147247147248147249147250147251147252147253147254147255147256147257147258147259147260147261147262147263147264147265147266147267147268147269147270147271147272147273147274147275147276147277147278147279147280147281147282147283147284147285147286147287147288147289147290147291147292147293147294147295147296147297147298147299147300147301147302147303147304147305147306147307147308147309147310147311147312147313147314147315147316147317147318147319147320147321147322147323147324147325147326147327147328147329147330147331147332147333147334147335147336147337147338147339147340147341147342147343147344147345147346147347147348147349147350147351147352147353147354147355147356147357147358147359147360147361147362147363147364147365147366147367147368147369147370147371147372147373147374147375147376147377147378147379147380147381147382147383147384147385147386147387147388147389147390147391147392147393147394147395147396147397147398147399147400147401147402147403147404147405147406147407147408147409147410147411147412147413147414147415147416147417147418147419147420147421147422147423147424147425147426147427147428147429147430147431147432147433147434147435147436147437147438147439147440147441147442147443147444147445147446147447147448147449147450147451147452147453147454147455147456147457147458147459147460147461147462147463147464147465147466147467147468147469147470147471147472147473147474147475147476147477147478147479147480147481147482147483147484147485147486147487147488147489147490147491147492147493147494147495147496147497147498147499147500147501147502147503147504147505147506147507147508147509147510147511147512147513147514147515147516147517147518147519147520147521147522147523147524147525147526147527147528147529147530147531147532147533147534147535147536147537147538147539147540147541147542147543147544147545147546147547147548147549147550147551147552147553147554147555147556147557147558147559147560147561147562147563147564147565147566147567147568147569147570147571147572147573147574147575147576147577147578147579147580147581147582147583147584147585147586147587147588147589147590147591147592147593147594147595147596147597147598147599147600147601147602147603147604147605147606147607147608147609147610147611147612147613147614147615147616147617147618147619147620147621147622147623147624147625147626147627147628147629147630147631147632147633147634147635147636147637147638147639147640147641147642147643147644147645147646147647147648147649147650147651147652147653147654147655147656147657147658147659147660147661147662147663147664147665147666147667147668147669147670147671147672147673147674147675147676147677147678147679147680147681147682147683147684147685147686147687147688147689147690147691147692147693147694147695147696147697147698147699147700147701147702147703147704147705147706147707147708147709147710147711147712147713147714147715147716147717147718147719147720147721147722147723147724147725147726147727147728147729147730147731147732147733147734147735147736147737147738147739147740147741147742147743147744147745147746147747147748147749147750147751147752147753147754147755147756147757147758147759147760147761147762147763147764147765147766147767147768147769147770147771147772147773147774147775147776147777147778147779147780147781147782147783147784147785147786147787147788147789147790147791147792147793147794147795147796147797147798147799147800147801147802147803147804147805147806147807147808147809147810147811147812147813147814147815147816147817147818147819147820147821147822147823147824147825147826147827147828147829147830147831147832147833147834147835147836147837147838147839147840147841147842147843147844147845147846147847147848147849147850147851147852147853147854147855147856147857147858147859147860147861147862147863147864147865147866147867147868147869147870147871147872147873147874147875147876147877147878147879147880147881147882147883147884147885147886147887147888147889147890147891147892147893147894147895147896147897147898147899147900147901147902147903147904147905147906147907147908147909147910147911147912147913147914147915147916147917147918147919147920147921147922147923147924147925147926147927147928147929147930147931147932147933147934147935147936147937147938147939147940147941147942147943147944147945147946147947147948147949147950147951147952147953147954147955147956147957147958147959147960147961147962147963147964147965147966147967147968147969147970147971147972147973147974147975147976147977147978147979147980147981147982147983147984147985147986147987147988147989147990147991147992147993147994147995147996147997147998147999148000148001148002148003148004148005148006148007148008148009148010148011148012148013148014148015148016148017148018148019148020148021148022148023148024148025148026148027148028148029148030148031148032148033148034148035148036148037148038148039148040148041148042148043148044148045148046148047148048148049148050148051148052148053148054148055148056148057148058148059148060148061148062148063148064148065148066148067148068148069148070148071148072148073148074148075148076148077148078148079148080148081148082148083148084148085148086148087148088148089148090148091148092148093148094148095148096148097148098148099148100148101148102148103148104148105148106148107148108148109148110148111148112148113148114148115148116148117148118148119148120148121148122148123148124148125148126148127148128148129148130148131148132148133148134148135148136148137148138148139148140148141148142148143148144148145148146148147148148148149148150148151148152148153148154148155148156148157148158148159148160148161148162148163148164148165148166148167148168148169148170148171148172148173148174148175148176148177148178148179148180148181148182148183148184148185148186148187148188148189148190148191148192148193148194148195148196148197148198148199148200148201148202148203148204148205148206148207148208148209148210148211148212148213148214148215148216148217148218148219148220148221148222148223148224148225148226148227148228148229148230148231148232148233148234148235148236148237148238148239148240148241148242148243148244148245148246148247148248148249148250148251148252148253148254148255148256148257148258148259148260148261148262148263148264148265148266148267148268148269148270148271148272148273148274148275148276148277148278148279148280148281148282148283148284148285148286148287148288148289148290148291148292148293148294148295148296148297148298148299148300148301148302148303148304148305148306148307148308148309148310148311148312148313148314148315148316148317148318148319148320148321148322148323148324148325148326148327148328148329148330148331148332148333148334148335148336148337148338148339148340148341148342148343148344148345148346148347148348148349148350148351148352148353148354148355148356148357148358148359148360148361148362148363148364148365148366148367148368148369148370148371148372148373148374148375148376148377148378148379148380148381148382148383148384148385148386148387148388148389148390148391148392148393148394148395148396148397148398148399148400148401148402148403148404148405148406148407148408148409148410148411148412148413148414148415148416148417148418148419148420148421148422148423148424148425148426148427148428148429148430148431148432148433148434148435148436148437148438148439148440148441148442148443148444148445148446148447148448148449148450148451148452148453148454148455148456148457148458148459148460148461148462148463148464148465148466148467148468148469148470148471148472148473148474148475148476148477148478148479148480148481148482148483148484148485148486148487148488148489148490148491148492148493148494148495148496148497148498148499148500148501148502148503148504148505148506148507148508148509148510148511148512148513148514148515148516148517148518148519148520148521148522148523148524148525148526148527148528148529148530148531148532148533148534148535148536148537148538148539148540148541148542148543148544148545148546148547148548148549148550148551148552148553148554148555148556148557148558148559148560148561148562148563148564148565148566148567148568148569148570148571148572148573148574148575148576148577148578148579148580148581148582148583148584148585148586148587148588148589148590148591148592148593148594148595148596148597148598148599148600148601148602148603148604148605148606148607148608148609148610148611148612148613148614148615148616148617148618148619148620148621148622148623148624148625148626148627148628148629148630148631148632148633148634148635148636148637148638148639148640148641148642148643148644148645148646148647148648148649148650148651148652148653148654148655148656148657148658148659148660148661148662148663148664148665148666148667148668148669148670148671148672148673148674148675148676148677148678148679148680148681148682148683148684148685148686148687148688148689148690148691148692148693148694148695148696148697148698148699148700148701148702148703148704148705148706148707148708148709148710148711148712148713148714148715148716148717148718148719148720148721148722148723148724148725148726148727148728148729148730148731148732148733148734148735148736148737148738148739148740148741148742148743148744148745148746148747148748148749148750148751148752148753148754148755148756148757148758148759148760148761148762148763148764148765148766148767148768148769148770148771148772148773148774148775148776148777148778148779148780148781148782148783148784148785148786148787148788148789148790148791148792148793148794148795148796148797148798148799148800148801148802148803148804148805148806148807148808148809148810148811148812148813148814148815148816148817148818148819148820148821148822148823148824148825148826148827148828148829148830148831148832148833148834148835148836148837148838148839148840148841148842148843148844148845148846148847148848148849148850148851148852148853148854148855148856148857148858148859148860148861148862148863148864148865148866148867148868148869148870148871148872148873148874148875148876148877148878148879148880148881148882148883148884148885148886148887148888148889148890148891148892148893148894148895148896148897148898148899148900148901148902148903148904148905148906148907148908148909148910148911148912148913148914148915148916148917148918148919148920148921148922148923148924148925148926148927148928148929148930148931148932148933148934148935148936148937148938148939148940148941148942148943148944148945148946148947148948148949148950148951148952148953148954148955148956148957148958148959148960148961148962148963148964148965148966148967148968148969148970148971148972148973148974148975148976148977148978148979148980148981148982148983148984148985148986148987148988148989148990148991148992148993148994148995148996148997148998148999149000149001149002149003149004149005149006149007149008149009149010149011149012149013149014149015149016149017149018149019149020149021149022149023149024149025149026149027149028149029149030149031149032149033149034149035149036149037149038149039149040149041149042149043149044149045149046149047149048149049149050149051149052149053149054149055149056149057149058149059149060149061149062149063149064149065149066149067149068149069149070149071149072149073149074149075149076149077149078149079149080149081149082149083149084149085149086149087149088149089149090149091149092149093149094149095149096149097149098149099149100149101149102149103149104149105149106149107149108149109149110149111149112149113149114149115149116149117149118149119149120149121149122149123149124149125149126149127149128149129149130149131149132149133149134149135149136149137149138149139149140149141149142149143149144149145149146149147149148149149149150149151149152149153149154149155149156149157149158149159149160149161149162149163149164149165149166149167149168149169149170149171149172149173149174149175149176149177149178149179149180149181149182149183149184149185149186149187149188149189149190149191149192149193149194149195149196149197149198149199149200149201149202149203149204149205149206149207149208149209149210149211149212149213149214149215149216149217149218149219149220149221149222149223149224149225149226149227149228149229149230149231149232149233149234149235149236149237149238149239149240149241149242149243149244149245149246149247149248149249149250149251149252149253149254149255149256149257149258149259149260149261149262149263149264149265149266149267149268149269149270149271149272149273149274149275149276149277149278149279149280149281149282149283149284149285149286149287149288149289149290149291149292149293149294149295149296149297149298149299149300149301149302149303149304149305149306149307149308149309149310149311149312149313149314149315149316149317149318149319149320149321149322149323149324149325149326149327149328149329149330149331149332149333149334149335149336149337149338149339149340149341149342149343149344149345149346149347149348149349149350149351149352149353149354149355149356149357149358149359149360149361149362149363149364149365149366149367149368149369149370149371149372149373149374149375149376149377149378149379149380149381149382149383149384149385149386149387149388149389149390149391149392149393149394149395149396149397149398149399149400149401149402149403149404149405149406149407149408149409149410149411149412149413149414149415149416149417149418149419149420149421149422149423149424149425149426149427149428149429149430149431149432149433149434149435149436149437149438149439149440149441149442149443149444149445149446149447149448149449149450149451149452149453149454149455149456149457149458149459149460149461149462149463149464149465149466149467149468149469149470149471149472149473149474149475149476149477149478149479149480149481149482149483149484149485149486149487149488149489149490149491149492149493149494149495149496149497149498149499149500149501149502149503149504149505149506149507149508149509149510149511149512149513149514149515149516149517149518149519149520149521149522149523149524149525149526149527149528149529149530149531149532149533149534149535149536149537149538149539149540149541149542149543149544149545149546149547149548149549149550149551149552149553149554149555149556149557149558149559149560149561149562149563149564149565149566149567149568149569149570149571149572149573149574149575149576149577149578149579149580149581149582149583149584149585149586149587149588149589149590149591149592149593149594149595149596149597149598149599149600149601149602149603149604149605149606149607149608149609149610149611149612149613149614149615149616149617149618149619149620149621149622149623149624149625149626149627149628149629149630149631149632149633149634149635149636149637149638149639149640149641149642149643149644149645149646149647149648149649149650149651149652149653149654149655149656149657149658149659149660149661149662149663149664149665149666149667149668149669149670149671149672149673149674149675149676149677149678149679149680149681149682149683149684149685149686149687149688149689149690149691149692149693149694149695149696149697149698149699149700149701149702149703149704149705149706149707149708149709149710149711149712149713149714149715149716149717149718149719149720149721149722149723149724149725149726149727149728149729149730149731149732149733149734149735149736149737149738149739149740149741149742149743149744149745149746149747149748149749149750149751149752149753149754149755149756149757149758149759149760149761149762149763149764149765149766149767149768149769149770149771149772149773149774149775149776149777149778149779149780149781149782149783149784149785149786149787149788149789149790149791149792149793149794149795149796149797149798149799149800149801149802149803149804149805149806149807149808149809149810149811149812149813149814149815149816149817149818149819149820149821149822149823149824149825149826149827149828149829149830149831149832149833149834149835149836149837149838149839149840149841149842149843149844149845149846149847149848149849149850149851149852149853149854149855149856149857149858149859149860149861149862149863149864149865149866149867149868149869149870149871149872149873149874149875149876149877149878149879149880149881149882149883149884149885149886149887149888149889149890149891149892149893149894149895149896149897149898149899149900149901149902149903149904149905149906149907149908149909149910149911149912149913149914149915149916149917149918149919149920149921149922149923149924149925149926149927149928149929149930149931149932149933149934149935149936149937149938149939149940149941149942149943149944149945149946149947149948149949149950149951149952149953149954149955149956149957149958149959149960149961149962149963149964149965149966149967149968149969149970149971149972149973149974149975149976149977149978149979149980149981149982149983149984149985149986149987149988149989149990149991149992149993149994149995149996149997149998149999150000150001150002150003150004150005150006150007150008150009150010150011150012150013150014150015150016150017150018150019150020150021150022150023150024150025150026150027150028150029150030150031150032150033150034150035150036150037150038150039150040150041150042150043150044150045150046150047150048150049150050150051150052150053150054150055150056150057150058150059150060150061150062150063150064150065150066150067150068150069150070150071150072150073150074150075150076150077150078150079150080150081150082150083150084150085150086150087150088150089150090150091150092150093150094150095150096150097150098150099150100150101150102150103150104150105150106150107150108150109150110150111150112150113150114150115150116150117150118150119150120150121150122150123150124150125150126150127150128150129150130150131150132150133150134150135150136150137150138150139150140150141150142150143150144150145150146150147150148150149150150150151150152150153150154150155150156150157150158150159150160150161150162150163150164150165150166150167150168150169150170150171150172150173150174150175150176150177150178150179150180150181150182150183150184150185150186150187150188150189150190150191150192150193150194150195150196150197150198150199150200150201150202150203150204150205150206150207150208150209150210150211150212150213150214150215150216150217150218150219150220150221150222150223150224150225150226150227150228150229150230150231150232150233150234150235150236150237150238150239150240150241150242150243150244150245150246150247150248150249150250150251150252150253150254150255150256150257150258150259150260150261150262150263150264150265150266150267150268150269150270150271150272150273150274150275150276150277150278150279150280150281150282150283150284150285150286150287150288150289150290150291150292150293150294150295150296150297150298150299150300150301150302150303150304150305150306150307150308150309150310150311150312150313150314150315150316150317150318150319150320150321150322150323150324150325150326150327150328150329150330150331150332150333150334150335150336150337150338150339150340150341150342150343150344150345150346150347150348150349150350150351150352150353150354150355150356150357150358150359150360150361150362150363150364150365150366150367150368150369150370150371150372150373150374150375150376150377150378150379150380150381150382150383150384150385150386150387150388150389150390150391150392150393150394150395150396150397150398150399150400150401150402150403150404150405150406150407150408150409150410150411150412150413150414150415150416150417150418150419150420150421150422150423150424150425150426150427150428150429150430150431150432150433150434150435150436150437150438150439150440150441150442150443150444150445150446150447150448150449150450150451150452150453150454150455150456150457150458150459150460150461150462150463150464150465150466150467150468150469150470150471150472150473150474150475150476150477150478150479150480150481150482150483150484150485150486150487150488150489150490150491150492150493150494150495150496150497150498150499150500150501150502150503150504150505150506150507150508150509150510150511150512150513150514150515150516150517150518150519150520150521150522150523150524150525150526150527150528150529150530150531150532150533150534150535150536150537150538150539150540150541150542150543150544150545150546150547150548150549150550150551150552150553150554150555150556150557150558150559150560150561150562150563150564150565150566150567150568150569150570150571150572150573150574150575150576150577150578150579150580150581150582150583150584150585150586150587150588150589150590150591150592150593150594150595150596150597150598150599150600150601150602150603150604150605150606150607150608150609150610150611150612150613150614150615150616150617150618150619150620150621150622150623150624150625150626150627150628150629150630150631150632150633150634150635150636150637150638150639150640150641150642150643150644150645150646150647150648150649150650150651150652150653150654150655150656150657150658150659150660150661150662150663150664150665150666150667150668150669150670150671150672150673150674150675150676150677150678150679150680150681150682150683150684150685150686150687150688150689150690150691150692150693150694150695150696150697150698150699150700150701150702150703150704150705150706150707150708150709150710150711150712150713150714150715150716150717150718150719150720150721150722150723150724150725150726150727150728150729150730150731150732150733150734150735150736150737150738150739150740150741150742150743150744150745150746150747150748150749150750150751150752150753150754150755150756150757150758150759150760150761150762150763150764150765150766150767150768150769150770150771150772150773150774150775150776150777150778150779150780150781150782150783150784150785150786150787150788150789150790150791150792150793150794150795150796150797150798150799150800150801150802150803150804150805150806150807150808150809150810150811150812150813150814150815150816150817150818150819150820150821150822150823150824150825150826150827150828150829150830150831150832150833150834150835150836150837150838150839150840150841150842150843150844150845150846150847150848150849150850150851150852150853150854150855150856150857150858150859150860150861150862150863150864150865150866150867150868150869150870150871150872150873150874150875150876150877150878150879150880150881150882150883150884150885150886150887150888150889150890150891150892150893150894150895150896150897150898150899150900150901150902150903150904150905150906150907150908150909150910150911150912150913150914150915150916150917150918150919150920150921150922150923150924150925150926150927150928150929150930150931150932150933150934150935150936150937150938150939150940150941150942150943150944150945150946150947150948150949150950150951150952150953150954150955150956150957150958150959150960150961150962150963150964150965150966150967150968150969150970150971150972150973150974150975150976150977150978150979150980150981150982150983150984150985150986150987150988150989150990150991150992150993150994150995150996150997150998150999151000151001151002151003151004151005151006151007151008151009151010151011151012151013151014151015151016151017151018151019151020151021151022151023151024151025151026151027151028151029151030151031151032151033151034151035151036151037151038151039151040151041151042151043151044151045151046151047151048151049151050151051151052151053151054151055151056151057151058151059151060151061151062151063151064151065151066151067151068151069151070151071151072151073151074151075151076151077151078151079151080151081151082151083151084151085151086151087151088151089151090151091151092151093151094151095151096151097151098151099151100151101151102151103151104151105151106151107151108151109151110151111151112151113151114151115151116151117151118151119151120151121151122151123151124151125151126151127151128151129151130151131151132151133151134151135151136151137151138151139151140151141151142151143151144151145151146151147151148151149151150151151151152151153151154151155151156151157151158151159151160151161151162151163151164151165151166151167151168151169151170151171151172151173151174151175151176151177151178151179151180151181151182151183151184151185151186151187151188151189151190151191151192151193151194151195151196151197151198151199151200151201151202151203151204151205151206151207151208151209151210151211151212151213151214151215151216151217151218151219151220151221151222151223151224151225151226151227151228151229151230151231151232151233151234151235151236151237151238151239151240151241151242151243151244151245151246151247151248151249151250151251151252151253151254151255151256151257151258151259151260151261151262151263151264151265151266151267151268151269151270151271151272151273151274151275151276151277151278151279151280151281151282151283151284151285151286151287151288151289151290151291151292151293151294151295151296151297151298151299151300151301151302151303151304151305151306151307151308151309151310151311151312151313151314151315151316151317151318151319151320151321151322151323151324151325151326151327151328151329151330151331151332151333151334151335151336151337151338151339151340151341151342151343151344151345151346151347151348151349151350151351151352151353151354151355151356151357151358151359151360151361151362151363151364151365151366151367151368151369151370151371151372151373151374151375151376151377151378151379151380151381151382151383151384151385151386151387151388151389151390151391151392151393151394151395151396151397151398151399151400151401151402151403151404151405151406151407151408151409151410151411151412151413151414151415151416151417151418151419151420151421151422151423151424151425151426151427151428151429151430151431151432151433151434151435151436151437151438151439151440151441151442151443151444151445151446151447151448151449151450151451151452151453151454151455151456151457151458151459151460151461151462151463151464151465151466151467151468151469151470151471151472151473151474151475151476151477151478151479151480151481151482151483151484151485151486151487151488151489151490151491151492151493151494151495151496151497151498151499151500151501151502151503151504151505151506151507151508151509151510151511151512151513151514151515151516151517151518151519151520151521151522151523151524151525151526151527151528151529151530151531151532151533151534151535151536151537151538151539151540151541151542151543151544151545151546151547151548151549151550151551151552151553151554151555151556151557151558151559151560151561151562151563151564151565151566151567151568151569151570151571151572151573151574151575151576151577151578151579151580151581151582151583151584151585151586151587151588151589151590151591151592151593151594151595151596151597151598151599151600151601151602151603151604151605151606151607151608151609151610151611151612151613151614151615151616151617151618151619151620151621151622151623151624151625151626151627151628151629151630151631151632151633151634151635151636151637151638151639151640151641151642151643151644151645151646151647151648151649151650151651151652151653151654151655151656151657151658151659151660151661151662151663151664151665151666151667151668151669151670151671151672151673151674151675151676151677151678151679151680151681151682151683151684151685151686151687151688151689151690151691151692151693151694151695151696151697151698151699151700151701151702151703151704151705151706151707151708151709151710151711151712151713151714151715151716151717151718151719151720151721151722151723151724151725151726151727151728151729151730151731151732151733151734151735151736151737151738151739151740151741151742151743151744151745151746151747151748151749151750151751151752151753151754151755151756151757151758151759151760151761151762151763151764151765151766151767151768151769151770151771151772151773151774151775151776151777151778151779151780151781151782151783151784151785151786151787151788151789151790151791151792151793151794151795151796151797151798151799151800151801151802151803151804151805151806151807151808151809151810151811151812151813151814151815151816151817151818151819151820151821151822151823151824151825151826151827151828151829151830151831151832151833151834151835151836151837151838151839151840151841151842151843151844151845151846151847151848151849151850151851151852151853151854151855151856151857151858151859151860151861151862151863151864151865151866151867151868151869151870151871151872151873151874151875151876151877151878151879151880151881151882151883151884151885151886151887151888151889151890151891151892151893151894151895151896151897151898151899151900151901151902151903151904151905151906151907151908151909151910151911151912151913151914151915151916151917151918151919151920151921151922151923151924151925151926151927151928151929151930151931151932151933151934151935151936151937151938151939151940151941151942151943151944151945151946151947151948151949151950151951151952151953151954151955151956151957151958151959151960151961151962151963151964151965151966151967151968151969151970151971151972151973151974151975151976151977151978151979151980151981151982151983151984151985151986151987151988151989151990151991151992151993151994151995151996151997151998151999152000152001152002152003152004152005152006152007152008152009152010152011152012152013152014152015152016152017152018152019152020152021152022152023152024152025152026152027152028152029152030152031152032152033152034152035152036152037152038152039152040152041152042152043152044152045152046152047152048152049152050152051152052152053152054152055152056152057152058152059152060152061152062152063152064152065152066152067152068152069152070152071152072152073152074152075152076152077152078152079152080152081152082152083152084152085152086152087152088152089152090152091152092152093152094152095152096152097152098152099152100152101152102152103152104152105152106152107152108152109152110152111152112152113152114152115152116152117152118152119152120152121152122152123152124152125152126152127152128152129152130152131152132152133152134152135152136152137152138152139152140152141152142152143152144152145152146152147152148152149152150152151152152152153152154152155152156152157152158152159152160152161152162152163152164152165152166152167152168152169152170152171152172152173152174152175152176152177152178152179152180152181152182152183152184152185152186152187152188152189152190152191152192152193152194152195152196152197152198152199152200152201152202152203152204152205152206152207152208152209152210152211152212152213152214152215152216152217152218152219152220152221152222152223152224152225152226152227152228152229152230152231152232152233152234152235152236152237152238152239152240152241152242152243152244152245152246152247152248152249152250152251152252152253152254152255152256152257152258152259152260152261152262152263152264152265152266152267152268152269152270152271152272152273152274152275152276152277152278152279152280152281152282152283152284152285152286152287152288152289152290152291152292152293152294152295152296152297152298152299152300152301152302152303152304152305152306152307152308152309152310152311152312152313152314152315152316152317152318152319152320152321152322152323152324152325152326152327152328152329152330152331152332152333152334152335152336152337152338152339152340152341152342152343152344152345152346152347152348152349152350152351152352152353152354152355152356152357152358152359152360152361152362152363152364152365152366152367152368152369152370152371152372152373152374152375152376152377152378152379152380152381152382152383152384152385152386152387152388152389152390152391152392152393152394152395152396152397152398152399152400152401152402152403152404152405152406152407152408152409152410152411152412152413152414152415152416152417152418152419152420152421152422152423152424152425152426152427152428152429152430152431152432152433152434152435152436152437152438152439152440152441152442152443152444152445152446152447152448152449152450152451152452152453152454152455152456152457152458152459152460152461152462152463152464152465152466152467152468152469152470152471152472152473152474152475152476152477152478152479152480152481152482152483152484152485152486152487152488152489152490152491152492152493152494152495152496152497152498152499152500152501152502152503152504152505152506152507152508152509152510152511152512152513152514152515152516152517152518152519152520152521152522152523152524152525152526152527152528152529152530152531152532152533152534152535152536152537152538152539152540152541152542152543152544152545152546152547152548152549152550152551152552152553152554152555152556152557152558152559152560152561152562152563152564152565152566152567152568152569152570152571152572152573152574152575152576152577152578152579152580152581152582152583152584152585152586152587152588152589152590152591152592152593152594152595152596152597152598152599152600152601152602152603152604152605152606152607152608152609152610152611152612152613152614152615152616152617152618152619152620152621152622152623152624152625152626152627152628152629152630152631152632152633152634152635152636152637152638152639152640152641152642152643152644152645152646152647152648152649152650152651152652152653152654152655152656152657152658152659152660152661152662152663152664152665152666152667152668152669152670152671152672152673152674152675152676152677152678152679152680152681152682152683152684152685152686152687152688152689152690152691152692152693152694152695152696152697152698152699152700152701152702152703152704152705152706152707152708152709152710152711152712152713152714152715152716152717152718152719152720152721152722152723152724152725152726152727152728152729152730152731152732152733152734152735152736152737152738152739152740152741152742152743152744152745152746152747152748152749152750152751152752152753152754152755152756152757152758152759152760152761152762152763152764152765152766152767152768152769152770152771152772152773152774152775152776152777152778152779152780152781152782152783152784152785152786152787152788152789152790152791152792152793152794152795152796152797152798152799152800152801152802152803152804152805152806152807152808152809152810152811152812152813152814152815152816152817152818152819152820152821152822152823152824152825152826152827152828152829152830152831152832152833152834152835152836152837152838152839152840152841152842152843152844152845152846152847152848152849152850152851152852152853152854152855152856152857152858152859152860152861152862152863152864152865152866152867152868152869152870152871152872152873152874152875152876152877152878152879152880152881152882152883152884152885152886152887152888152889152890152891152892152893152894152895152896152897152898152899152900152901152902152903152904152905152906152907152908152909152910152911152912152913152914152915152916152917152918152919152920152921152922152923152924152925152926152927152928152929152930152931152932152933152934152935152936152937152938152939152940152941152942152943152944152945152946152947152948152949152950152951152952152953152954152955152956152957152958152959152960152961152962152963152964152965152966152967152968152969152970152971152972152973152974152975152976152977152978152979152980152981152982152983152984152985152986152987152988152989152990152991152992152993152994152995152996152997152998152999153000153001153002153003153004153005153006153007153008153009153010153011153012153013153014153015153016153017153018153019153020153021153022153023153024153025153026153027153028153029153030153031153032153033153034153035153036153037153038153039153040153041153042153043153044153045153046153047153048153049153050153051153052153053153054153055153056153057153058153059153060153061153062153063153064153065153066153067153068153069153070153071153072153073153074153075153076153077153078153079153080153081153082153083153084153085153086153087153088153089153090153091153092153093153094153095153096153097153098153099153100153101153102153103153104153105153106153107153108153109153110153111153112153113153114153115153116153117153118153119153120153121153122153123153124153125153126153127153128153129153130153131153132153133153134153135153136153137153138153139153140153141153142153143153144153145153146153147153148153149153150153151153152153153153154153155153156153157153158153159153160153161153162153163153164153165153166153167153168153169153170153171153172153173153174153175153176153177153178153179153180153181153182153183153184153185153186153187153188153189153190153191153192153193153194153195153196153197153198153199153200153201153202153203153204153205153206153207153208153209153210153211153212153213153214153215153216153217153218153219153220153221153222153223153224153225153226153227153228153229153230153231153232153233153234153235153236153237153238153239153240153241153242153243153244153245153246153247153248153249153250153251153252153253153254153255153256153257153258153259153260153261153262153263153264153265153266153267153268153269153270153271153272153273153274153275153276153277153278153279153280153281153282153283153284153285153286153287153288153289153290153291153292153293153294153295153296153297153298153299153300153301153302153303153304153305153306153307153308153309153310153311153312153313153314153315153316153317153318153319153320153321153322153323153324153325153326153327153328153329153330153331153332153333153334153335153336153337153338153339153340153341153342153343153344153345153346153347153348153349153350153351153352153353153354153355153356153357153358153359153360153361153362153363153364153365153366153367153368153369153370153371153372153373153374153375153376153377153378153379153380153381153382153383153384153385153386153387153388153389153390153391153392153393153394153395153396153397153398153399153400153401153402153403153404153405153406153407153408153409153410153411153412153413153414153415153416153417153418153419153420153421153422153423153424153425153426153427153428153429153430153431153432153433153434153435153436153437153438153439153440153441153442153443153444153445153446153447153448153449153450153451153452153453153454153455153456153457153458153459153460153461153462153463153464153465153466153467153468153469153470153471153472153473153474153475153476153477153478153479153480153481153482153483153484153485153486153487153488153489153490153491153492153493153494153495153496153497153498153499153500153501153502153503153504153505153506153507153508153509153510153511153512153513153514153515153516153517153518153519153520153521153522153523153524153525153526153527153528153529153530153531153532153533153534153535153536153537153538153539153540153541153542153543153544153545153546153547153548153549153550153551153552153553153554153555153556153557153558153559153560153561153562153563153564153565153566153567153568153569153570153571153572153573153574153575153576153577153578153579153580153581153582153583153584153585153586153587153588153589153590153591153592153593153594153595153596153597153598153599153600153601153602153603153604153605153606153607153608153609153610153611153612153613153614153615153616153617153618153619153620153621153622153623153624153625153626153627153628153629153630153631153632153633153634153635153636153637153638153639153640153641153642153643153644153645153646153647153648153649153650153651153652153653153654153655153656153657153658153659153660153661153662153663153664153665153666153667153668153669153670153671153672153673153674153675153676153677153678153679153680153681153682153683153684153685153686153687153688153689153690153691153692153693153694153695153696153697153698153699153700153701153702153703153704153705153706153707153708153709153710153711153712153713153714153715153716153717153718153719153720153721153722153723153724153725153726153727153728153729153730153731153732153733153734153735153736153737153738153739153740153741153742153743153744153745153746153747153748153749153750153751153752153753153754153755153756153757153758153759153760153761153762153763153764153765153766153767153768153769153770153771153772153773153774153775153776153777153778153779153780153781153782153783153784153785153786153787153788153789153790153791153792153793153794153795153796153797153798153799153800153801153802153803153804153805153806153807153808153809153810153811153812153813153814153815153816153817153818153819153820153821153822153823153824153825153826153827153828153829153830153831153832153833153834153835153836153837153838153839153840153841153842153843153844153845153846153847153848153849153850153851153852153853153854153855153856153857153858153859153860153861153862153863153864153865153866153867153868153869153870153871153872153873153874153875153876153877153878153879153880153881153882153883153884153885153886153887153888153889153890153891153892153893153894153895153896153897153898153899153900153901153902153903153904153905153906153907153908153909153910153911153912153913153914153915153916153917153918153919153920153921153922153923153924153925153926153927153928153929153930153931153932153933153934153935153936153937153938153939153940153941153942153943153944153945153946153947153948153949153950153951153952153953153954153955153956153957153958153959153960153961153962153963153964153965153966153967153968153969153970153971153972153973153974153975153976153977153978153979153980153981153982153983153984153985153986153987153988153989153990153991153992153993153994153995153996153997153998153999154000154001154002154003154004154005154006154007154008154009154010154011154012154013154014154015154016154017154018154019154020154021154022154023154024154025154026154027154028154029154030154031154032154033154034154035154036154037154038154039154040154041154042154043154044154045154046154047154048154049154050154051154052154053154054154055154056154057154058154059154060154061154062154063154064154065154066154067154068154069154070154071154072154073154074154075154076154077154078154079154080154081154082154083154084154085154086154087154088154089154090154091154092154093154094154095154096154097154098154099154100154101154102154103154104154105154106154107154108154109154110154111154112154113154114154115154116154117154118154119154120154121154122154123154124154125154126154127154128154129154130154131154132154133154134154135154136154137154138154139154140154141154142154143154144154145154146154147154148154149154150154151154152154153154154154155154156154157154158154159154160154161154162154163154164154165154166154167154168154169154170154171154172154173154174154175154176154177154178154179154180154181154182154183154184154185154186154187154188154189154190154191154192154193154194154195154196154197154198154199154200154201154202154203154204154205154206154207154208154209154210154211154212154213154214154215154216154217154218154219154220154221154222154223154224154225154226154227154228154229154230154231154232154233154234154235154236154237154238154239154240154241154242154243154244154245154246154247154248154249154250154251154252154253154254154255154256154257154258154259154260154261154262154263154264154265154266154267154268154269154270154271154272154273154274154275154276154277154278154279154280154281154282154283154284154285154286154287154288154289154290154291154292154293154294154295154296154297154298154299154300154301154302154303154304154305154306154307154308154309154310154311154312154313154314154315154316154317154318154319154320154321154322154323154324154325154326154327154328154329154330154331154332154333154334154335154336154337154338154339154340154341154342154343154344154345154346154347154348154349154350154351154352154353154354154355154356154357154358154359154360154361154362154363154364154365154366154367154368154369154370154371154372154373154374154375154376154377154378154379154380154381154382154383154384154385154386154387154388154389154390154391154392154393154394154395154396154397154398154399154400154401154402154403154404154405154406154407154408154409154410154411154412154413154414154415154416154417154418154419154420154421154422154423154424154425154426154427154428154429154430154431154432154433154434154435154436154437154438154439154440154441154442154443154444154445154446154447154448154449154450154451154452154453154454154455154456154457154458154459154460154461154462154463154464154465154466154467154468154469154470154471154472154473154474154475154476154477154478154479154480154481154482154483154484154485154486154487154488154489154490154491154492154493154494154495154496154497154498154499154500154501154502154503154504154505154506154507154508154509154510154511154512154513154514154515154516154517154518154519154520154521154522154523154524154525154526154527154528154529154530154531154532154533154534154535154536154537154538154539154540154541154542154543154544154545154546154547154548154549154550154551154552154553154554154555154556154557154558154559154560154561154562154563154564154565154566154567154568154569154570154571154572154573154574154575154576154577154578154579154580154581154582154583154584154585154586154587154588154589154590154591154592154593154594154595154596154597154598154599154600154601154602154603154604154605154606154607154608154609154610154611154612154613154614154615154616154617154618154619154620154621154622154623154624154625154626154627154628154629154630154631154632154633154634154635154636154637154638154639154640154641154642154643154644154645154646154647154648154649154650154651154652154653154654154655154656154657154658154659154660154661154662154663154664154665154666154667154668154669154670154671154672154673154674154675154676154677154678154679154680154681154682154683154684154685154686154687154688154689154690154691154692154693154694154695154696154697154698154699154700154701154702154703154704154705154706154707154708154709154710154711154712154713154714154715154716154717154718154719154720154721154722154723154724154725154726154727154728154729154730154731154732154733154734154735154736154737154738154739154740154741154742154743154744154745154746154747154748154749154750154751154752154753154754154755154756154757154758154759154760154761154762154763154764154765154766154767154768154769154770154771154772154773154774154775154776154777154778154779154780154781154782154783154784154785154786154787154788154789154790154791154792154793154794154795154796154797154798154799154800154801154802154803154804154805154806154807154808154809154810154811154812154813154814154815154816154817154818154819154820154821154822154823154824154825154826154827154828154829154830154831154832154833154834154835154836154837154838154839154840154841154842154843154844154845154846154847154848154849154850154851154852154853154854154855154856154857154858154859154860154861154862154863154864154865154866154867154868154869154870154871154872154873154874154875154876154877154878154879154880154881154882154883154884154885154886154887154888154889154890154891154892154893154894154895154896154897154898154899154900154901154902154903154904154905154906154907154908154909154910154911154912154913154914154915154916154917154918154919154920154921154922154923154924154925154926154927154928154929154930154931154932154933154934154935154936154937154938154939154940154941154942154943154944154945154946154947154948154949154950154951154952154953154954154955154956154957154958154959154960154961154962154963154964154965154966154967154968154969154970154971154972154973154974154975154976154977154978154979154980154981154982154983154984154985154986154987154988154989154990154991154992154993154994154995154996154997154998154999155000155001155002155003155004155005155006155007155008155009155010155011155012155013155014155015155016155017155018155019155020155021155022155023155024155025155026155027155028155029155030155031155032155033155034155035155036155037155038155039155040155041155042155043155044155045155046155047155048155049155050155051155052155053155054155055155056155057155058155059155060155061155062155063155064155065155066155067155068155069155070155071155072155073155074155075155076155077155078155079155080155081155082155083155084155085155086155087155088155089155090155091155092155093155094155095155096155097155098155099155100155101155102155103155104155105155106155107155108155109155110155111155112155113155114155115155116155117155118155119155120155121155122155123155124155125155126155127155128155129155130155131155132155133155134155135155136155137155138155139155140155141155142155143155144155145155146155147155148155149155150155151155152155153155154155155155156155157155158155159155160155161155162155163155164155165155166155167155168155169155170155171155172155173155174155175155176155177155178155179155180155181155182155183155184155185155186155187155188155189155190155191155192155193155194155195155196155197155198155199155200155201155202155203155204155205155206155207155208155209155210155211155212155213155214155215155216155217155218155219155220155221155222155223155224155225155226155227155228155229155230155231155232155233155234155235155236155237155238155239155240155241155242155243155244155245155246155247155248155249155250155251155252155253155254155255155256155257155258155259155260155261155262155263155264155265155266155267155268155269155270155271155272155273155274155275155276155277155278155279155280155281155282155283155284155285155286155287155288155289155290155291155292155293155294155295155296155297155298155299155300155301155302155303155304155305155306155307155308155309155310155311155312155313155314155315155316155317155318155319155320155321155322155323155324155325155326155327155328155329155330155331155332155333155334155335155336155337155338155339155340155341155342155343155344155345155346155347155348155349155350155351155352155353155354155355155356155357155358155359155360155361155362155363155364155365155366155367155368155369155370155371155372155373155374155375155376155377155378155379155380155381155382155383155384155385155386155387155388155389155390155391155392155393155394155395155396155397155398155399155400155401155402155403155404155405155406155407155408155409155410155411155412155413155414155415155416155417155418155419155420155421155422155423155424155425155426155427155428155429155430155431155432155433155434155435155436155437155438155439155440155441155442155443155444155445155446155447155448155449155450155451155452155453155454155455155456155457155458155459155460155461155462155463155464155465155466155467155468155469155470155471155472155473155474155475155476155477155478155479155480155481155482155483155484155485155486155487155488155489155490155491155492155493155494155495155496155497155498155499155500155501155502155503155504155505155506155507155508155509155510155511155512155513155514155515155516155517155518155519155520155521155522155523155524155525155526155527155528155529155530155531155532155533155534155535155536155537155538155539155540155541155542155543155544155545155546155547155548155549155550155551155552155553155554155555155556155557155558155559155560155561155562155563155564155565155566155567155568155569155570155571155572155573155574155575155576155577155578155579155580155581155582155583155584155585155586155587155588155589155590155591155592155593155594155595155596155597155598155599155600155601155602155603155604155605155606155607155608155609155610155611155612155613155614155615155616155617155618155619155620155621155622155623155624155625155626155627155628155629155630155631155632155633155634155635155636155637155638155639155640155641155642155643155644155645155646155647155648155649155650155651155652155653155654155655155656155657155658155659155660155661155662155663155664155665155666155667155668155669155670155671155672155673155674155675155676155677155678155679155680155681155682155683155684155685155686155687155688155689155690155691155692155693155694155695155696155697155698155699155700155701155702155703155704155705155706155707155708155709155710155711155712155713155714155715155716155717155718155719155720155721155722155723155724155725155726155727155728155729155730155731155732155733155734155735155736155737155738155739155740155741155742155743155744155745155746155747155748155749155750155751155752155753155754155755155756155757155758155759155760155761155762155763155764155765155766155767155768155769155770155771155772155773155774155775155776155777155778155779155780155781155782155783155784155785155786155787155788155789155790155791155792155793155794155795155796155797155798155799155800155801155802155803155804155805155806155807155808155809155810155811155812155813155814155815155816155817155818155819155820155821155822155823155824155825155826155827155828155829155830155831155832155833155834155835155836155837155838155839155840155841155842155843155844155845155846155847155848155849155850155851155852155853155854155855155856155857155858155859155860155861155862155863155864155865155866155867155868155869155870155871155872155873155874155875155876155877155878155879155880155881155882155883155884155885155886155887155888155889155890155891155892155893155894155895155896155897155898155899155900155901155902155903155904155905155906155907155908155909155910155911155912155913155914155915155916155917155918155919155920155921155922155923155924155925155926155927155928155929155930155931155932155933155934155935155936155937155938155939155940155941155942155943155944155945155946155947155948155949155950155951155952155953155954155955155956155957155958155959155960155961155962155963155964155965155966155967155968155969155970155971155972155973155974155975155976155977155978155979155980155981155982155983155984155985155986155987155988155989155990155991155992155993155994155995155996155997155998155999156000156001156002156003156004156005156006156007156008156009156010156011156012156013156014156015156016156017156018156019156020156021156022156023156024156025156026156027156028156029156030156031156032156033156034156035156036156037156038156039156040156041156042156043156044156045156046156047156048156049156050156051156052156053156054156055156056156057156058156059156060156061156062156063156064156065156066156067156068156069156070156071156072156073156074156075156076156077156078156079156080156081156082156083156084156085156086156087156088156089156090156091156092156093156094156095156096156097156098156099156100156101156102156103156104156105156106156107156108156109156110156111156112156113156114156115156116156117156118156119156120156121156122156123156124156125156126156127156128156129156130156131156132156133156134156135156136156137156138156139156140156141156142156143156144156145156146156147156148156149156150156151156152156153156154156155156156156157156158156159156160156161156162156163156164156165156166156167156168156169156170156171156172156173156174156175156176156177156178156179156180156181156182156183156184156185156186156187156188156189156190156191156192156193156194156195156196156197156198156199156200156201156202156203156204156205156206156207156208156209156210156211156212156213156214156215156216156217156218156219156220156221156222156223156224156225156226156227156228156229156230156231156232156233156234156235156236156237156238156239156240156241156242156243156244156245156246156247156248156249156250156251156252156253156254156255156256156257156258156259156260156261156262156263156264156265156266156267156268156269156270156271156272156273156274156275156276156277156278156279156280156281156282156283156284156285156286156287156288156289156290156291156292156293156294156295156296156297156298156299156300156301156302156303156304156305156306156307156308156309156310156311156312156313156314156315156316156317156318156319156320156321156322156323156324156325156326156327156328156329156330156331156332156333156334156335156336156337156338156339156340156341156342156343156344156345156346156347156348156349156350156351156352156353156354156355156356156357156358156359156360156361156362156363156364156365156366156367156368156369156370156371156372156373156374156375156376156377156378156379156380156381156382156383156384156385156386156387156388156389156390156391156392156393156394156395156396156397156398156399156400156401156402156403156404156405156406156407156408156409156410156411156412156413156414156415156416156417156418156419156420156421156422156423156424156425156426156427156428156429156430156431156432156433156434156435156436156437156438156439156440156441156442156443156444156445156446156447156448156449156450156451156452156453156454156455156456156457156458156459156460156461156462156463156464156465156466156467156468156469156470156471156472156473156474156475156476156477156478156479156480156481156482156483156484156485156486156487156488156489156490156491156492156493156494156495156496156497156498156499156500156501156502156503156504156505156506156507156508156509156510156511156512156513156514156515156516156517156518156519156520156521156522156523156524156525156526156527156528156529156530156531156532156533156534156535156536156537156538156539156540156541156542156543156544156545156546156547156548156549156550156551156552156553156554156555156556156557156558156559156560156561156562156563156564156565156566156567156568156569156570156571156572156573156574156575156576156577156578156579156580156581156582156583156584156585156586156587156588156589156590156591156592156593156594156595156596156597156598156599156600156601156602156603156604156605156606156607156608156609156610156611156612156613156614156615156616156617156618156619156620156621156622156623156624156625156626156627156628156629156630156631156632156633156634156635156636156637156638156639156640156641156642156643156644156645156646156647156648156649156650156651156652156653156654156655156656156657156658156659156660156661156662156663156664156665156666156667156668156669156670156671156672156673156674156675156676156677156678156679156680156681156682156683156684156685156686156687156688156689156690156691156692156693156694156695156696156697156698156699156700156701156702156703156704156705156706156707156708156709156710156711156712156713156714156715156716156717156718156719156720156721156722156723156724156725156726156727156728156729156730156731156732156733156734156735156736156737156738156739156740156741156742156743156744156745156746156747156748156749156750156751156752156753156754156755156756156757156758156759156760156761156762156763156764156765156766156767156768156769156770156771156772156773156774156775156776156777156778156779156780156781156782156783156784156785156786156787156788156789156790156791156792156793156794156795156796156797156798156799156800156801156802156803156804156805156806156807156808156809156810156811156812156813156814156815156816156817156818156819156820156821156822156823156824156825156826156827156828156829156830156831156832156833156834156835156836156837156838156839156840156841156842156843156844156845156846156847156848156849156850156851156852156853156854156855156856156857156858156859156860156861156862156863156864156865156866156867156868156869156870156871156872156873156874156875156876156877156878156879156880156881156882156883156884156885156886156887156888156889156890156891156892156893156894156895156896156897156898156899156900156901156902156903156904156905156906156907156908156909156910156911156912156913156914156915156916156917156918156919156920156921156922156923156924156925156926156927156928156929156930156931156932156933156934156935156936156937156938156939156940156941156942156943156944156945156946156947156948156949156950156951156952156953156954156955156956156957156958156959156960156961156962156963156964156965156966156967156968156969156970156971156972156973156974156975156976156977156978156979156980156981156982156983156984156985156986156987156988156989156990156991156992156993156994156995156996156997156998156999157000157001157002157003157004157005157006157007157008157009157010157011157012157013157014157015157016157017157018157019157020157021157022157023157024157025157026157027157028157029157030157031157032157033157034157035157036157037157038157039157040157041157042157043157044157045157046157047157048157049157050157051157052157053157054157055157056157057157058157059157060157061157062157063157064157065157066157067157068157069157070157071157072157073157074157075157076157077157078157079157080157081157082157083157084157085157086157087157088157089157090157091157092157093157094157095157096157097157098157099157100157101157102157103157104157105157106157107157108157109157110157111157112157113157114157115157116157117157118157119157120157121157122157123157124157125157126157127157128157129157130157131157132157133157134157135157136157137157138157139157140157141157142157143157144157145157146157147157148157149157150157151157152157153157154157155157156157157157158157159157160157161157162157163157164157165157166157167157168157169157170157171157172157173157174157175157176157177157178157179157180157181157182157183157184157185157186157187157188157189157190157191157192157193157194157195157196157197157198157199157200157201157202157203157204157205157206157207157208157209157210157211157212157213157214157215157216157217157218157219157220157221157222157223157224157225157226157227157228157229157230157231157232157233157234157235157236157237157238157239157240157241157242157243157244157245157246157247157248157249157250157251157252157253157254157255157256157257157258157259157260157261157262157263157264157265157266157267157268157269157270157271157272157273157274157275157276157277157278157279157280157281157282157283157284157285157286157287157288157289157290157291157292157293157294157295157296157297157298157299157300157301157302157303157304157305157306157307157308157309157310157311157312157313157314157315157316157317157318157319157320157321157322157323157324157325157326157327157328157329157330157331157332157333157334157335157336157337157338157339157340157341157342157343157344157345157346157347157348157349157350157351157352157353157354157355157356157357157358157359157360157361157362157363157364157365157366157367157368157369157370157371157372157373157374157375157376157377157378157379157380157381157382157383157384157385157386157387157388157389157390157391157392157393157394157395157396157397157398157399157400157401157402157403157404157405157406157407157408157409157410157411157412157413157414157415157416157417157418157419157420157421157422157423157424157425157426157427157428157429157430157431157432157433157434157435157436157437157438157439157440157441157442157443157444157445157446157447157448157449157450157451157452157453157454157455157456157457157458157459157460157461157462157463157464157465157466157467157468157469157470157471157472157473157474157475157476157477157478157479157480157481157482157483157484157485157486157487157488157489157490157491157492157493157494157495157496157497157498157499157500157501157502157503157504157505157506157507157508157509157510157511157512157513157514157515157516157517157518157519157520157521157522157523157524157525157526157527157528157529157530157531157532157533157534157535157536157537157538157539157540157541157542157543157544157545157546157547157548157549157550157551157552157553157554157555157556157557157558157559157560157561157562157563157564157565157566157567157568157569157570157571157572157573157574157575157576157577157578157579157580157581157582157583157584157585157586157587157588157589157590157591157592157593157594157595157596157597157598157599157600157601157602157603157604157605157606157607157608157609157610157611157612157613157614157615157616157617157618157619157620157621157622157623157624157625157626157627157628157629157630157631157632157633157634157635157636157637157638157639157640157641157642157643157644157645157646157647157648157649157650157651157652157653157654157655157656157657157658157659157660157661157662157663157664157665157666157667157668157669157670157671157672157673157674157675157676157677157678157679157680157681157682157683157684157685157686157687157688157689157690157691157692157693157694157695157696157697157698157699157700157701157702157703157704157705157706157707157708157709157710157711157712157713157714157715157716157717157718157719157720157721157722157723157724157725157726157727157728157729157730157731157732157733157734157735157736157737157738157739157740157741157742157743157744157745157746157747157748157749157750157751157752157753157754157755157756157757157758157759157760157761157762157763157764157765157766157767157768157769157770157771157772157773157774157775157776157777157778157779157780157781157782157783157784157785157786157787157788157789157790157791157792157793157794157795157796157797157798157799157800157801157802157803157804157805157806157807157808157809157810157811157812157813157814157815157816157817157818157819157820157821157822157823157824157825157826157827157828157829157830157831157832157833157834157835157836157837157838157839157840157841157842157843157844157845157846157847157848157849157850157851157852157853157854157855157856157857157858157859157860157861157862157863157864157865157866157867157868157869157870157871157872157873157874157875157876157877157878157879157880157881157882157883157884157885157886157887157888157889157890157891157892157893157894157895157896157897157898157899157900157901157902157903157904157905157906157907157908157909157910157911157912157913157914157915157916157917157918157919157920157921157922157923157924157925157926157927157928157929157930157931157932157933157934157935157936157937157938157939157940157941157942157943157944157945157946157947157948157949157950157951157952157953157954157955157956157957157958157959157960157961157962157963157964157965157966157967157968157969157970157971157972157973157974157975157976157977157978157979157980157981157982157983157984157985157986157987157988157989157990157991157992157993157994157995157996157997157998157999158000158001158002158003158004158005158006158007158008158009158010158011158012158013158014158015158016158017158018158019158020158021158022158023158024158025158026158027158028158029158030158031158032158033158034158035158036158037158038158039158040158041158042158043158044158045158046158047158048158049158050158051158052158053158054158055158056158057158058158059158060158061158062158063158064158065158066158067158068158069158070158071158072158073158074158075158076158077158078158079158080158081158082158083158084158085158086158087158088158089158090158091158092158093158094158095158096158097158098158099158100158101158102158103158104158105158106158107158108158109158110158111158112158113158114158115158116158117158118158119158120158121158122158123158124158125158126158127158128158129158130158131158132158133158134158135158136158137158138158139158140158141158142158143158144158145158146158147158148158149158150158151158152158153158154158155158156158157158158158159158160158161158162158163158164158165158166158167158168158169158170158171158172158173158174158175158176158177158178158179158180158181158182158183158184158185158186158187158188158189158190158191158192158193158194158195158196158197158198158199158200158201158202158203158204158205158206158207158208158209158210158211158212158213158214158215158216158217158218158219158220158221158222158223158224158225158226158227158228158229158230158231158232158233158234158235158236158237158238158239158240158241158242158243158244158245158246158247158248158249158250158251158252158253158254158255158256158257158258158259158260158261158262158263158264158265158266158267158268158269158270158271158272158273158274158275158276158277158278158279158280158281158282158283158284158285158286158287158288158289158290158291158292158293158294158295158296158297158298158299158300158301158302158303158304158305158306158307158308158309158310158311158312158313158314158315158316158317158318158319158320158321158322158323158324158325158326158327158328158329158330158331158332158333158334158335158336158337158338158339158340158341158342158343158344158345158346158347158348158349158350158351158352158353158354158355158356158357158358158359158360158361158362158363158364158365158366158367158368158369158370158371158372158373158374158375158376158377158378158379158380158381158382158383158384158385158386158387158388158389158390158391158392158393158394158395158396158397158398158399158400158401158402158403158404158405158406158407158408158409158410158411158412158413158414158415158416158417158418158419158420158421158422158423158424158425158426158427158428158429158430158431158432158433158434158435158436158437158438158439158440158441158442158443158444158445158446158447158448158449158450158451158452158453158454158455158456158457158458158459158460158461158462158463158464158465158466158467158468158469158470158471158472158473158474158475158476158477158478158479158480158481158482158483158484158485158486158487158488158489158490158491158492158493158494158495158496158497158498158499158500158501158502158503158504158505158506158507158508158509158510158511158512158513158514158515158516158517158518158519158520158521158522158523158524158525158526158527158528158529158530158531158532158533158534158535158536158537158538158539158540158541158542158543158544158545158546158547158548158549158550158551158552158553158554158555158556158557158558158559158560158561158562158563158564158565158566158567158568158569158570158571158572158573158574158575158576158577158578158579158580158581158582158583158584158585158586158587158588158589158590158591158592158593158594158595158596158597158598158599158600158601158602158603158604158605158606158607158608158609158610158611158612158613158614158615158616158617158618158619158620158621158622158623158624158625158626158627158628158629158630158631158632158633158634158635158636158637158638158639158640158641158642158643158644158645158646158647158648158649158650158651158652158653158654158655158656158657158658158659158660158661158662158663158664158665158666158667158668158669158670158671158672158673158674158675158676158677158678158679158680158681158682158683158684158685158686158687158688158689158690158691158692158693158694158695158696158697158698158699158700158701158702158703158704158705158706158707158708158709158710158711158712158713158714158715158716158717158718158719158720158721158722158723158724158725158726158727158728158729158730158731158732158733158734158735158736158737158738158739158740158741158742158743158744158745158746158747158748158749158750158751158752158753158754158755158756158757158758158759158760158761158762158763158764158765158766158767158768158769158770158771158772158773158774158775158776158777158778158779158780158781158782158783158784158785158786158787158788158789158790158791158792158793158794158795158796158797158798158799158800158801158802158803158804158805158806158807158808158809158810158811158812158813158814158815158816158817158818158819158820158821158822158823158824158825158826158827158828158829158830158831158832158833158834158835158836158837158838158839158840158841158842158843158844158845158846158847158848158849158850158851158852158853158854158855158856158857158858158859158860158861158862158863158864158865158866158867158868158869158870158871158872158873158874158875158876158877158878158879158880158881158882158883158884158885158886158887158888158889158890158891158892158893158894158895158896158897158898158899158900158901158902158903158904158905158906158907158908158909158910158911158912158913158914158915158916158917158918158919158920158921158922158923158924158925158926158927158928158929158930158931158932158933158934158935158936158937158938158939158940158941158942158943158944158945158946158947158948158949158950158951158952158953158954158955158956158957158958158959158960158961158962158963158964158965158966158967158968158969158970158971158972158973158974158975158976158977158978158979158980158981158982158983158984158985158986158987158988158989158990158991158992158993158994158995158996158997158998158999159000159001159002159003159004159005159006159007159008159009159010159011159012159013159014159015159016159017159018159019159020159021159022159023159024159025159026159027159028159029159030159031159032159033159034159035159036159037159038159039159040159041159042159043159044159045159046159047159048159049159050159051159052159053159054159055159056159057159058159059159060159061159062159063159064159065159066159067159068159069159070159071159072159073159074159075159076159077159078159079159080159081159082159083159084159085159086159087159088159089159090159091159092159093159094159095159096159097159098159099159100159101159102159103159104159105159106159107159108159109159110159111159112159113159114159115159116159117159118159119159120159121159122159123159124159125159126159127159128159129159130159131159132159133159134159135159136159137159138159139159140159141159142159143159144159145159146159147159148159149159150159151159152159153159154159155159156159157159158159159159160159161159162159163159164159165159166159167159168159169159170159171159172159173159174159175159176159177159178159179159180159181159182159183159184159185159186159187159188159189159190159191159192159193159194159195159196159197159198159199159200159201159202159203159204159205159206159207159208159209159210159211159212159213159214159215159216159217159218159219159220159221159222159223159224159225159226159227159228159229159230159231159232159233159234159235159236159237159238159239159240159241159242159243159244159245159246159247159248159249159250159251159252159253159254159255159256159257159258159259159260159261159262159263159264159265159266159267159268159269159270159271159272159273159274159275159276159277159278159279159280159281159282159283159284159285159286159287159288159289159290159291159292159293159294159295159296159297159298159299159300159301159302159303159304159305159306159307159308159309159310159311159312159313159314159315159316159317159318159319159320159321159322159323159324159325159326159327159328159329159330159331159332159333159334159335159336159337159338159339159340159341159342159343159344159345159346159347159348159349159350159351159352159353159354159355159356159357159358159359159360159361159362159363159364159365159366159367159368159369159370159371159372159373159374159375159376159377159378159379159380159381159382159383159384159385159386159387159388159389159390159391159392159393159394159395159396159397159398159399159400159401159402159403159404159405159406159407159408159409159410159411159412159413159414159415159416159417159418159419159420159421159422159423159424159425159426159427159428159429159430159431159432159433159434159435159436159437159438159439159440159441159442159443159444159445159446159447159448159449159450159451159452159453159454159455159456159457159458159459159460159461159462159463159464159465159466159467159468159469159470159471159472159473159474159475159476159477159478159479159480159481159482159483159484159485159486159487159488159489159490159491159492159493159494159495159496159497159498159499159500159501159502159503159504159505159506159507159508159509159510159511159512159513159514159515159516159517159518159519159520159521159522159523159524159525159526159527159528159529159530159531159532159533159534159535159536159537159538159539159540159541159542159543159544159545159546159547159548159549159550159551159552159553159554159555159556159557159558159559159560159561159562159563159564159565159566159567159568159569159570159571159572159573159574159575159576159577159578159579159580159581159582159583159584159585159586159587159588159589159590159591159592159593159594159595159596159597159598159599159600159601159602159603159604159605159606159607159608159609159610159611159612159613159614159615159616159617159618159619159620159621159622159623159624159625159626159627159628159629159630159631159632159633159634159635159636159637159638159639159640159641159642159643159644159645159646159647159648159649159650159651159652159653159654159655159656159657159658159659159660159661159662159663159664159665159666159667159668159669159670159671159672159673159674159675159676159677159678159679159680159681159682159683159684159685159686159687159688159689159690159691159692159693159694159695159696159697159698159699159700159701159702159703159704159705159706159707159708159709159710159711159712159713159714159715159716159717159718159719159720159721159722159723159724159725159726159727159728159729159730159731159732159733159734159735159736159737159738159739159740159741159742159743159744159745159746159747159748159749159750159751159752159753159754159755159756159757159758159759159760159761159762159763159764159765159766159767159768159769159770159771159772159773159774159775159776159777159778159779159780159781159782159783159784159785159786159787159788159789159790159791159792159793159794159795159796159797159798159799159800159801159802159803159804159805159806159807159808159809159810159811159812159813159814159815159816159817159818159819159820159821159822159823159824159825159826159827159828159829159830159831159832159833159834159835159836159837159838159839159840159841159842159843159844159845159846159847159848159849159850159851159852159853159854159855159856159857159858159859159860159861159862159863159864159865159866159867159868159869159870159871159872159873159874159875159876159877159878159879159880159881159882159883159884159885159886159887159888159889159890159891159892159893159894159895159896159897159898159899159900159901159902159903159904159905159906159907159908159909159910159911159912159913159914159915159916159917159918159919159920159921159922159923159924159925159926159927159928159929159930159931159932159933159934159935159936159937159938159939159940159941159942159943159944159945159946159947159948159949159950159951159952159953159954159955159956159957159958159959159960159961159962159963159964159965159966159967159968159969159970159971159972159973159974159975159976159977159978159979159980159981159982159983159984159985159986159987159988159989159990159991159992159993159994159995159996159997159998159999160000160001160002160003160004160005160006160007160008160009160010160011160012160013160014160015160016160017160018160019160020160021160022160023160024160025160026160027160028160029160030160031160032160033160034160035160036160037160038160039160040160041160042160043160044160045160046160047160048160049160050160051160052160053160054160055160056160057160058160059160060160061160062160063160064160065160066160067160068160069160070160071160072160073160074160075160076160077160078160079160080160081160082160083160084160085160086160087160088160089160090160091160092160093160094160095160096160097160098160099160100160101160102160103160104160105160106160107160108160109160110160111160112160113160114160115160116160117160118160119160120160121160122160123160124160125160126160127160128160129160130160131160132160133160134160135160136160137160138160139160140160141160142160143160144160145160146160147160148160149160150160151160152160153160154160155160156160157160158160159160160160161160162160163160164160165160166160167160168160169160170160171160172160173160174160175160176160177160178160179160180160181160182160183160184160185160186160187160188160189160190160191160192160193160194160195160196160197160198160199160200160201160202160203160204160205160206160207160208160209160210160211160212160213160214160215160216160217160218160219160220160221160222160223160224160225160226160227160228160229160230160231160232160233160234160235160236160237160238160239160240160241160242160243160244160245160246160247160248160249160250160251160252160253160254160255160256160257160258160259160260160261160262160263160264160265160266160267160268160269160270160271160272160273160274160275160276160277160278160279160280160281160282160283160284160285160286160287160288160289160290160291160292160293160294160295160296160297160298160299160300160301160302160303160304160305160306160307160308160309160310160311160312160313160314160315160316160317160318160319160320160321160322160323160324160325160326160327160328160329160330160331160332160333160334160335160336160337160338160339160340160341160342160343160344160345160346160347160348160349160350160351160352160353160354160355160356160357160358160359160360160361160362160363160364160365160366160367160368160369160370160371160372160373160374160375160376160377160378160379160380160381160382160383160384160385160386160387160388160389160390160391160392160393160394160395160396160397160398160399160400160401160402160403160404160405160406160407160408160409160410160411160412160413160414160415160416160417160418160419160420160421160422160423160424160425160426160427160428160429160430160431160432160433160434160435160436160437160438160439160440160441160442160443160444160445160446160447160448160449160450160451160452160453160454160455160456160457160458160459160460160461160462160463160464160465160466160467160468160469160470160471160472160473160474160475160476160477160478160479160480160481160482160483160484160485160486160487160488160489160490160491160492160493160494160495160496160497160498160499160500160501160502160503160504160505160506160507160508160509160510160511160512160513160514160515160516160517160518160519160520160521160522160523160524160525160526160527160528160529160530160531160532160533160534160535160536160537160538160539160540160541160542160543160544160545160546160547160548160549160550160551160552160553160554160555160556160557160558160559160560160561160562160563160564160565160566160567160568160569160570160571160572160573160574160575160576160577160578160579160580160581160582160583160584160585160586160587160588160589160590160591160592160593160594160595160596160597160598160599160600160601160602160603160604160605160606160607160608160609160610160611160612160613160614160615160616160617160618160619160620160621160622160623160624160625160626160627160628160629160630160631160632160633160634160635160636160637160638160639160640160641160642160643160644160645160646160647160648160649160650160651160652160653160654160655160656160657160658160659160660160661160662160663160664160665160666160667160668160669160670160671160672160673160674160675160676160677160678160679160680160681160682160683160684160685160686160687160688160689160690160691160692160693160694160695160696160697160698160699160700160701160702160703160704160705160706160707160708160709160710160711160712160713160714160715160716160717160718160719160720160721160722160723160724160725160726160727160728160729160730160731160732160733160734160735160736160737160738160739160740160741160742160743160744160745160746160747160748160749160750160751160752160753160754160755160756160757160758160759160760160761160762160763160764160765160766160767160768160769160770160771160772160773160774160775160776160777160778160779160780160781160782160783160784160785160786160787160788160789160790160791160792160793160794160795160796160797160798160799160800160801160802160803160804160805160806160807160808160809160810160811160812160813160814160815160816160817160818160819160820160821160822160823160824160825160826160827160828160829160830160831160832160833160834160835160836160837160838160839160840160841160842160843160844160845160846160847160848160849160850160851160852160853160854160855160856160857160858160859160860160861160862160863160864160865160866160867160868160869160870160871160872160873160874160875160876160877160878160879160880160881160882160883160884160885160886160887160888160889160890160891160892160893160894160895160896160897160898160899160900160901160902160903160904160905160906160907160908160909160910160911160912160913160914160915160916160917160918160919160920160921160922160923160924160925160926160927160928160929160930160931160932160933160934160935160936160937160938160939160940160941160942160943160944160945160946160947160948160949160950160951160952160953160954160955160956160957160958160959160960160961160962160963160964160965160966160967160968160969160970160971160972160973160974160975160976160977160978160979160980160981160982160983160984160985160986160987160988160989160990160991160992160993160994160995160996160997160998160999161000161001161002161003161004161005161006161007161008161009161010161011161012161013161014161015161016161017161018161019161020161021161022161023161024161025161026161027161028161029161030161031161032161033161034161035161036161037161038161039161040161041161042161043161044161045161046161047161048161049161050161051161052161053161054161055161056161057161058161059161060161061161062161063161064161065161066161067161068161069161070161071161072161073161074161075161076161077161078161079161080161081161082161083161084161085161086161087161088161089161090161091161092161093161094161095161096161097161098161099161100161101161102161103161104161105161106161107161108161109161110161111161112161113161114161115161116161117161118161119161120161121161122161123161124161125161126161127161128161129161130161131161132161133161134161135161136161137161138161139161140161141161142161143161144161145161146161147161148161149161150161151161152161153161154161155161156161157161158161159161160161161161162161163161164161165161166161167161168161169161170161171161172161173161174161175161176161177161178161179161180161181161182161183161184161185161186161187161188161189161190161191161192161193161194161195161196161197161198161199161200161201161202161203161204161205161206161207161208161209161210161211161212161213161214161215161216161217161218161219161220161221161222161223161224161225161226161227161228161229161230161231161232161233161234161235161236161237161238161239161240161241161242161243161244161245161246161247161248161249161250161251161252161253161254161255161256161257161258161259161260161261161262161263161264161265161266161267161268161269161270161271161272161273161274161275161276161277161278161279161280161281161282161283161284161285161286161287161288161289161290161291161292161293161294161295161296161297161298161299161300161301161302161303161304161305161306161307161308161309161310161311161312161313161314161315161316161317161318161319161320161321161322161323161324161325161326161327161328161329161330161331161332161333161334161335161336161337161338161339161340161341161342161343161344161345161346161347161348161349161350161351161352161353161354161355161356161357161358161359161360161361161362161363161364161365161366161367161368161369161370161371161372161373161374161375161376161377161378161379161380161381161382161383161384161385161386161387161388161389161390161391161392161393161394161395161396161397161398161399161400161401161402161403161404161405161406161407161408161409161410161411161412161413161414161415161416161417161418161419161420161421161422161423161424161425161426161427161428161429161430161431161432161433161434161435161436161437161438161439161440161441161442161443161444161445161446161447161448161449161450161451161452161453161454161455161456161457161458161459161460161461161462161463161464161465161466161467161468161469161470161471161472161473161474161475161476161477161478161479161480161481161482161483161484161485161486161487161488161489161490161491161492161493161494161495161496161497161498161499161500161501161502161503161504161505161506161507161508161509161510161511161512161513161514161515161516161517161518161519161520161521161522161523161524161525161526161527161528161529161530161531161532161533161534161535161536161537161538161539161540161541161542161543161544161545161546161547161548161549161550161551161552161553161554161555161556161557161558161559161560161561161562161563161564161565161566161567161568161569161570161571161572161573161574161575161576161577161578161579161580161581161582161583161584161585161586161587161588161589161590161591161592161593161594161595161596161597161598161599161600161601161602161603161604161605161606161607161608161609161610161611161612161613161614161615161616161617161618161619161620161621161622161623161624161625161626161627161628161629161630161631161632161633161634161635161636161637161638161639161640161641161642161643161644161645161646161647161648161649161650161651161652161653161654161655161656161657161658161659161660161661161662161663161664161665161666161667161668161669161670161671161672161673161674161675161676161677161678161679161680161681161682161683161684161685161686161687161688161689161690161691161692161693161694161695161696161697161698161699161700161701161702161703161704161705161706161707161708161709161710161711161712161713161714161715161716161717161718161719161720161721161722161723161724161725161726161727161728161729161730161731161732161733161734161735161736161737161738161739161740161741161742161743161744161745161746161747161748161749161750161751161752161753161754161755161756161757161758161759161760161761161762161763161764161765161766161767161768161769161770161771161772161773161774161775161776161777161778161779161780161781161782161783161784161785161786161787161788161789161790161791161792161793161794161795161796161797161798161799161800161801161802161803161804161805161806161807161808161809161810161811161812161813161814161815161816161817161818161819161820161821161822161823161824161825161826161827161828161829161830161831161832161833161834161835161836161837161838161839161840161841161842161843161844161845161846161847161848161849161850161851161852161853161854161855161856161857161858161859161860161861161862161863161864161865161866161867161868161869161870161871161872161873161874161875161876161877161878161879161880161881161882161883161884161885161886161887161888161889161890161891161892161893161894161895161896161897161898161899161900161901161902161903161904161905161906161907161908161909161910161911161912161913161914161915161916161917161918161919161920161921161922161923161924161925161926161927161928161929161930161931161932161933161934161935161936161937161938161939161940161941161942161943161944161945161946161947161948161949161950161951161952161953161954161955161956161957161958161959161960161961161962161963161964161965161966161967161968161969161970161971161972161973161974161975161976161977161978161979161980161981161982161983161984161985161986161987161988161989161990161991161992161993161994161995161996161997161998161999162000162001162002162003162004162005162006162007162008162009162010162011162012162013162014162015162016162017162018162019162020162021162022162023162024162025162026162027162028162029162030162031162032162033162034162035162036162037162038162039162040162041162042162043162044162045162046162047162048162049162050162051162052162053162054162055162056162057162058162059162060162061162062162063162064162065162066162067162068162069162070162071162072162073162074162075162076162077162078162079162080162081162082162083162084162085162086162087162088162089162090162091162092162093162094162095162096162097162098162099162100162101162102162103162104162105162106162107162108162109162110162111162112162113162114162115162116162117162118162119162120162121162122162123162124162125162126162127162128162129162130162131162132162133162134162135162136162137162138162139162140162141162142162143162144162145162146162147162148162149162150162151162152162153162154162155162156162157162158162159162160162161162162162163162164162165162166162167162168162169162170162171162172162173162174162175162176162177162178162179162180162181162182162183162184162185162186162187162188162189162190162191162192162193162194162195162196162197162198162199162200162201162202162203162204162205162206162207162208162209162210162211162212162213162214162215162216162217162218162219162220162221162222162223162224162225162226162227162228162229162230162231162232162233162234162235162236162237162238162239162240162241162242162243162244162245162246162247162248162249162250162251162252162253162254162255162256162257162258162259162260162261162262162263162264162265162266162267162268162269162270162271162272162273162274162275162276162277162278162279162280162281162282162283162284162285162286162287162288162289162290162291162292162293162294162295162296162297162298162299162300162301162302162303162304162305162306162307162308162309162310162311162312162313162314162315162316162317162318162319162320162321162322162323162324162325162326162327162328162329162330162331162332162333162334162335162336162337162338162339162340162341162342162343162344162345162346162347162348162349162350162351162352162353162354162355162356162357162358162359162360162361162362162363162364162365162366162367162368162369162370162371162372162373162374162375162376162377162378162379162380162381162382162383162384162385162386162387162388162389162390162391162392162393162394162395162396162397162398162399162400162401162402162403162404162405162406162407162408162409162410162411162412162413162414162415162416162417162418162419162420162421162422162423162424162425162426162427162428162429162430162431162432162433162434162435162436162437162438162439162440162441162442162443162444162445162446162447162448162449162450162451162452162453162454162455162456162457162458162459162460162461162462162463162464162465162466162467162468162469162470162471162472162473162474162475162476162477162478162479162480162481162482162483162484162485162486162487162488162489162490162491162492162493162494162495162496162497162498162499162500162501162502162503162504162505162506162507162508162509162510162511162512162513162514162515162516162517162518162519162520162521162522162523162524162525162526162527162528162529162530162531162532162533162534162535162536162537162538162539162540162541162542162543162544162545162546162547162548162549162550162551162552162553162554162555162556162557162558162559162560162561162562162563162564162565162566162567162568162569162570162571162572162573162574162575162576162577162578162579162580162581162582162583162584162585162586162587162588162589162590162591162592162593162594162595162596162597162598162599162600162601162602162603162604162605162606162607162608162609162610162611162612162613162614162615162616162617162618162619162620162621162622162623162624162625162626162627162628162629162630162631162632162633162634162635162636162637162638162639162640162641162642162643162644162645162646162647162648162649162650162651162652162653162654162655162656162657162658162659162660162661162662162663162664162665162666162667162668162669162670162671162672162673162674162675162676162677162678162679162680162681162682162683162684162685162686162687162688162689162690162691162692162693162694162695162696162697162698162699162700162701162702162703162704162705162706162707162708162709162710162711162712162713162714162715162716162717162718162719162720162721162722162723162724162725162726162727162728162729162730162731162732162733162734162735162736162737162738162739162740162741162742162743162744162745162746162747162748162749162750162751162752162753162754162755162756162757162758162759162760162761162762162763162764162765162766162767162768162769162770162771162772162773162774162775162776162777162778162779162780162781162782162783162784162785162786162787162788162789162790162791162792162793162794162795162796162797162798162799162800162801162802162803162804162805162806162807162808162809162810162811162812162813162814162815162816162817162818162819162820162821162822162823162824162825162826162827162828162829162830162831162832162833162834162835162836162837162838162839162840162841162842162843162844162845162846162847162848162849162850162851162852162853162854162855162856162857162858162859162860162861162862162863162864162865162866162867162868162869162870162871162872162873162874162875162876162877162878162879162880162881162882162883162884162885162886162887162888162889162890162891162892162893162894162895162896162897162898162899162900162901162902162903162904162905162906162907162908162909162910162911162912162913162914162915162916162917162918162919162920162921162922162923162924162925162926162927162928162929162930162931162932162933162934162935162936162937162938162939162940162941162942162943162944162945162946162947162948162949162950162951162952162953162954162955162956162957162958162959162960162961162962162963162964162965162966162967162968162969162970162971162972162973162974162975162976162977162978162979162980162981162982162983162984162985162986162987162988162989162990162991162992162993162994162995162996162997162998162999163000163001163002163003163004163005163006163007163008163009163010163011163012163013163014163015163016163017163018163019163020163021163022163023163024163025163026163027163028163029163030163031163032163033163034163035163036163037163038163039163040163041163042163043163044163045163046163047163048163049163050163051163052163053163054163055163056163057163058163059163060163061163062163063163064163065163066163067163068163069163070163071163072163073163074163075163076163077163078163079163080163081163082163083163084163085163086163087163088163089163090163091163092163093163094163095163096163097163098163099163100163101163102163103163104163105163106163107163108163109163110163111163112163113163114163115163116163117163118163119163120163121163122163123163124163125163126163127163128163129163130163131163132163133163134163135163136163137163138163139163140163141163142163143163144163145163146163147163148163149163150163151163152163153163154163155163156163157163158163159163160163161163162163163163164163165163166163167163168163169163170163171163172163173163174163175163176163177163178163179163180163181163182163183163184163185163186163187163188163189163190163191163192163193163194163195163196163197163198163199163200163201163202163203163204163205163206163207163208163209163210163211163212163213163214163215163216163217163218163219163220163221163222163223163224163225163226163227163228163229163230163231163232163233163234163235163236163237163238163239163240163241163242163243163244163245163246163247163248163249163250163251163252163253163254163255163256163257163258163259163260163261163262163263163264163265163266163267163268163269163270163271163272163273163274163275163276163277163278163279163280163281163282163283163284163285163286163287163288163289163290163291163292163293163294163295163296163297163298163299163300163301163302163303163304163305163306163307163308163309163310163311163312163313163314163315163316163317163318163319163320163321163322163323163324163325163326163327163328163329163330163331163332163333163334163335163336163337163338163339163340163341163342163343163344163345163346163347163348163349163350163351163352163353163354163355163356163357163358163359163360163361163362163363163364163365163366163367163368163369163370163371163372163373163374163375163376163377163378163379163380163381163382163383163384163385163386163387163388163389163390163391163392163393163394163395163396163397163398163399163400163401163402163403163404163405163406163407163408163409163410163411163412163413163414163415163416163417163418163419163420163421163422163423163424163425163426163427163428163429163430163431163432163433163434163435163436163437163438163439163440163441163442163443163444163445163446163447163448163449163450163451163452163453163454163455163456163457163458163459163460163461163462163463163464163465163466163467163468163469163470163471163472163473163474163475163476163477163478163479163480163481163482163483163484163485163486163487163488163489163490163491163492163493163494163495163496163497163498163499163500163501163502163503163504163505163506163507163508163509163510163511163512163513163514163515163516163517163518163519163520163521163522163523163524163525163526163527163528163529163530163531163532163533163534163535163536163537163538163539163540163541163542163543163544163545163546163547163548163549163550163551163552163553163554163555163556163557163558163559163560163561163562163563163564163565163566163567163568163569163570163571163572163573163574163575163576163577163578163579163580163581163582163583163584163585163586163587163588163589163590163591163592163593163594163595163596163597163598163599163600163601163602163603163604163605163606163607163608163609163610163611163612163613163614163615163616163617163618163619163620163621163622163623163624163625163626163627163628163629163630163631163632163633163634163635163636163637163638163639163640163641163642163643163644163645163646163647163648163649163650163651163652163653163654163655163656163657163658163659163660163661163662163663163664163665163666163667163668163669163670163671163672163673163674163675163676163677163678163679163680163681163682163683163684163685163686163687163688163689163690163691163692163693163694163695163696163697163698163699163700163701163702163703163704163705163706163707163708163709163710163711163712163713163714163715163716163717163718163719163720163721163722163723163724163725163726163727163728163729163730163731163732163733163734163735163736163737163738163739163740163741163742163743163744163745163746163747163748163749163750163751163752163753163754163755163756163757163758163759163760163761163762163763163764163765163766163767163768163769163770163771163772163773163774163775163776163777163778163779163780163781163782163783163784163785163786163787163788163789163790163791163792163793163794163795163796163797163798163799163800163801163802163803163804163805163806163807163808163809163810163811163812163813163814163815163816163817163818163819163820163821163822163823163824163825163826163827163828163829163830163831163832163833163834163835163836163837163838163839163840163841163842163843163844163845163846163847163848163849163850163851163852163853163854163855163856163857163858163859163860163861163862163863163864163865163866163867163868163869163870163871163872163873163874163875163876163877163878163879163880163881163882163883163884163885163886163887163888163889163890163891163892163893163894163895163896163897163898163899163900163901163902163903163904163905163906163907163908163909163910163911163912163913163914163915163916163917163918163919163920163921163922163923163924163925163926163927163928163929163930163931163932163933163934163935163936163937163938163939163940163941163942163943163944163945163946163947163948163949163950163951163952163953163954163955163956163957163958163959163960163961163962163963163964163965163966163967163968163969163970163971163972163973163974163975163976163977163978163979163980163981163982163983163984163985163986163987163988163989163990163991163992163993163994163995163996163997163998163999164000164001164002164003164004164005164006164007164008164009164010164011164012164013164014164015164016164017164018164019164020164021164022164023164024164025164026164027164028164029164030164031164032164033164034164035164036164037164038164039164040164041164042164043164044164045164046164047164048164049164050164051164052164053164054164055164056164057164058164059164060164061164062164063164064164065164066164067164068164069164070164071164072164073164074164075164076164077164078164079164080164081164082164083164084164085164086164087164088164089164090164091164092164093164094164095164096164097164098164099164100164101164102164103164104164105164106164107164108164109164110164111164112164113164114164115164116164117164118164119164120164121164122164123164124164125164126164127164128164129164130164131164132164133164134164135164136164137164138164139164140164141164142164143164144164145164146164147164148164149164150164151164152164153164154164155164156164157164158164159164160164161164162164163164164164165164166164167164168164169164170164171164172164173164174164175164176164177164178164179164180164181164182164183164184164185164186164187164188164189164190164191164192164193164194164195164196164197164198164199164200164201164202164203164204164205164206164207164208164209164210164211164212164213164214164215164216164217164218164219164220164221164222164223164224164225164226164227164228164229164230164231164232164233164234164235164236164237164238164239164240164241164242164243164244164245164246164247164248164249164250164251164252164253164254164255164256164257164258164259164260164261164262164263164264164265164266164267164268164269164270164271164272164273164274164275164276164277164278164279164280164281164282164283164284164285164286164287164288164289164290164291164292164293164294164295164296164297164298164299164300164301164302164303164304164305164306164307164308164309164310164311164312164313164314164315164316164317164318164319164320164321164322164323164324164325164326164327164328164329164330164331164332164333164334164335164336164337164338164339164340164341164342164343164344164345164346164347164348164349164350164351164352164353164354164355164356164357164358164359164360164361164362164363164364164365164366164367164368164369164370164371164372164373164374164375164376164377164378164379164380164381164382164383164384164385164386164387164388164389164390164391164392164393164394164395164396164397164398164399164400164401164402164403164404164405164406164407164408164409164410164411164412164413164414164415164416164417164418164419164420164421164422164423164424164425164426164427164428164429164430164431164432164433164434164435164436164437164438164439164440164441164442164443164444164445164446164447164448164449164450164451164452164453164454164455164456164457164458164459164460164461164462164463164464164465164466164467164468164469164470164471164472164473164474164475164476164477164478164479164480164481164482164483164484164485164486164487164488164489164490164491164492164493164494164495164496164497164498164499164500164501164502164503164504164505164506164507164508164509164510164511164512164513164514164515164516164517164518164519164520164521164522164523164524164525164526164527164528164529164530164531164532164533164534164535164536164537164538164539164540164541164542164543164544164545164546164547164548164549164550164551164552164553164554164555164556164557164558164559164560164561164562164563164564164565164566164567164568164569164570164571164572164573164574164575164576164577164578164579164580164581164582164583164584164585164586164587164588164589164590164591164592164593164594164595164596164597164598164599164600164601164602164603164604164605164606164607164608164609164610164611164612164613164614164615164616164617164618164619164620164621164622164623164624164625164626164627164628164629164630164631164632164633164634164635164636164637164638164639164640164641164642164643164644164645164646164647164648164649164650164651164652164653164654164655164656164657164658164659164660164661164662164663164664164665164666164667164668164669164670164671164672164673164674164675164676164677164678164679164680164681164682164683164684164685164686164687164688164689164690164691164692164693164694164695164696164697164698164699164700164701164702164703164704164705164706164707164708164709164710164711164712164713164714164715164716164717164718164719164720164721164722164723164724164725164726164727164728164729164730164731164732164733164734164735164736164737164738164739164740164741164742164743164744164745164746164747164748164749164750164751164752164753164754164755164756164757164758164759164760164761164762164763164764164765164766164767164768164769164770164771164772164773164774164775164776164777164778164779164780164781164782164783164784164785164786164787164788164789164790164791164792164793164794164795164796164797164798164799164800164801164802164803164804164805164806164807164808164809164810164811164812164813164814164815164816164817164818164819164820164821164822164823164824164825164826164827164828164829164830164831164832164833164834164835164836164837164838164839164840164841164842164843164844164845164846164847164848164849164850164851164852164853164854164855164856164857164858164859164860164861164862164863164864164865164866164867164868164869164870164871164872164873164874164875164876164877164878164879164880164881164882164883164884164885164886164887164888164889164890164891164892164893164894164895164896164897164898164899164900164901164902164903164904164905164906164907164908164909164910164911164912164913164914164915164916164917164918164919164920164921164922164923164924164925164926164927164928164929164930164931164932164933164934164935164936164937164938164939164940164941164942164943164944164945164946164947164948164949164950164951164952164953164954164955164956164957164958164959164960164961164962164963164964164965164966164967164968164969164970164971164972164973164974164975164976164977164978164979164980164981164982164983164984164985164986164987164988164989164990164991164992164993164994164995164996164997164998164999165000165001165002165003165004165005165006165007165008165009165010165011165012165013165014165015165016165017165018165019165020165021165022165023165024165025165026165027165028165029165030165031165032165033165034165035165036165037165038165039165040165041165042165043165044165045165046165047165048165049165050165051165052165053165054165055165056165057165058165059165060165061165062165063165064165065165066165067165068165069165070165071165072165073165074165075165076165077165078165079165080165081165082165083165084165085165086165087165088165089165090165091165092165093165094165095165096165097165098165099165100165101165102165103165104165105165106165107165108165109165110165111165112165113165114165115165116165117165118165119165120165121165122165123165124165125165126165127165128165129165130165131165132165133165134165135165136165137165138165139165140165141165142165143165144165145165146165147165148165149165150165151165152165153165154165155165156165157165158165159165160165161165162165163165164165165165166165167165168165169165170165171165172165173165174165175165176165177165178165179165180165181165182165183165184165185165186165187165188165189165190165191165192165193165194165195165196165197165198165199165200165201165202165203165204165205165206165207165208165209165210165211165212165213165214165215165216165217165218165219165220165221165222165223165224165225165226165227165228165229165230165231165232165233165234165235165236165237165238165239165240165241165242165243165244165245165246165247165248165249165250165251165252165253165254165255165256165257165258165259165260165261165262165263165264165265165266165267165268165269165270165271165272165273165274165275165276165277165278165279165280165281165282165283165284165285165286165287165288165289165290165291165292165293165294165295165296165297165298165299165300165301165302165303165304165305165306165307165308165309165310165311165312165313165314165315165316165317165318165319165320165321165322165323165324165325165326165327165328165329165330165331165332165333165334165335165336165337165338165339165340165341165342165343165344165345165346165347165348165349165350165351165352165353165354165355165356165357165358165359165360165361165362165363165364165365165366165367165368165369165370165371165372165373165374165375165376165377165378165379165380165381165382165383165384165385165386165387165388165389165390165391165392165393165394165395165396165397165398165399165400165401165402165403165404165405165406165407165408165409165410165411165412165413165414165415165416165417165418165419165420165421165422165423165424165425165426165427165428165429165430165431165432165433165434165435165436165437165438165439165440165441165442165443165444165445165446165447165448165449165450165451165452165453165454165455165456165457165458165459165460165461165462165463165464165465165466165467165468165469165470165471165472165473165474165475165476165477165478165479165480165481165482165483165484165485165486165487165488165489165490165491165492165493165494165495165496165497165498165499165500165501165502165503165504165505165506165507165508165509165510165511165512165513165514165515165516165517165518165519165520165521165522165523165524165525165526165527165528165529165530165531165532165533165534165535165536165537165538165539165540165541165542165543165544165545165546165547165548165549165550165551165552165553165554165555165556165557165558165559165560165561165562165563165564165565165566165567165568165569165570165571165572165573165574165575165576165577165578165579165580165581165582165583165584165585165586165587165588165589165590165591165592165593165594165595165596165597165598165599165600165601165602165603165604165605165606165607165608165609165610165611165612165613165614165615165616165617165618165619165620165621165622165623165624165625165626165627165628165629165630165631165632165633165634165635165636165637165638165639165640165641165642165643165644165645165646165647165648165649165650165651165652165653165654165655165656165657165658165659165660165661165662165663165664165665165666165667165668165669165670165671165672165673165674165675165676165677165678165679165680165681165682165683165684165685165686165687165688165689165690165691165692165693165694165695165696165697165698165699165700165701165702165703165704165705165706165707165708165709165710165711165712165713165714165715165716165717165718165719165720165721165722165723165724165725165726165727165728165729165730165731165732165733165734165735165736165737165738165739165740165741165742165743165744165745165746165747165748165749165750165751165752165753165754165755165756165757165758165759165760165761165762165763165764165765165766165767165768165769165770165771165772165773165774165775165776165777165778165779165780165781165782165783165784165785165786165787165788165789165790165791165792165793165794165795165796165797165798165799165800165801165802165803165804165805165806165807165808165809165810165811165812165813165814165815165816165817165818165819165820165821165822165823165824165825165826165827165828165829165830165831165832165833165834165835165836165837165838165839165840165841165842165843165844165845165846165847165848165849165850165851165852165853165854165855165856165857165858165859165860165861165862165863165864165865165866165867165868165869165870165871165872165873165874165875165876165877165878165879165880165881165882165883165884165885165886165887165888165889165890165891165892165893165894165895165896165897165898165899165900165901165902165903165904165905165906165907165908165909165910165911165912165913165914165915165916165917165918165919165920165921165922165923165924165925165926165927165928165929165930165931165932165933165934165935165936165937165938165939165940165941165942165943165944165945165946165947165948165949165950165951165952165953165954165955165956165957165958165959165960165961165962165963165964165965165966165967165968165969165970165971165972165973165974165975165976165977165978165979165980165981165982165983165984165985165986165987165988165989165990165991165992165993165994165995165996165997165998165999166000166001166002166003166004166005166006166007166008166009166010166011166012166013166014166015166016166017166018166019166020166021166022166023166024166025166026166027166028166029166030166031166032166033166034166035166036166037166038166039166040166041166042166043166044166045166046166047166048166049166050166051166052166053166054166055166056166057166058166059166060166061166062166063166064166065166066166067166068166069166070166071166072166073166074166075166076166077166078166079166080166081166082166083166084166085166086166087166088166089166090166091166092166093166094166095166096166097166098166099166100166101166102166103166104166105166106166107166108166109166110166111166112166113166114166115166116166117166118166119166120166121166122166123166124166125166126166127166128166129166130166131166132166133166134166135166136166137166138166139166140166141166142166143166144166145166146166147166148166149166150166151166152166153166154166155166156166157166158166159166160166161166162166163166164166165166166166167166168166169166170166171166172166173166174166175166176166177166178166179166180166181166182166183166184166185166186166187166188166189166190166191166192166193166194166195166196166197166198166199166200166201166202166203166204166205166206166207166208166209166210166211166212166213166214166215166216166217166218166219166220166221166222166223166224166225166226166227166228166229166230166231166232166233166234166235166236166237166238166239166240166241166242166243166244166245166246166247166248166249166250166251166252166253166254166255166256166257166258166259166260166261166262166263166264166265166266166267166268166269166270166271166272166273166274166275166276166277166278166279166280166281166282166283166284166285166286166287166288166289166290166291166292166293166294166295166296166297166298166299166300166301166302166303166304166305166306166307166308166309166310166311166312166313166314166315166316166317166318166319166320166321166322166323166324166325166326166327166328166329166330166331166332166333166334166335166336166337166338166339166340166341166342166343166344166345166346166347166348166349166350166351166352166353166354166355166356166357166358166359166360166361166362166363166364166365166366166367166368166369166370166371166372166373166374166375166376166377166378166379166380166381166382166383166384166385166386166387166388166389166390166391166392166393166394166395166396166397166398166399166400166401166402166403166404166405166406166407166408166409166410166411166412166413166414166415166416166417166418166419166420166421166422166423166424166425166426166427166428166429166430166431166432166433166434166435166436166437166438166439166440166441166442166443166444166445166446166447166448166449166450166451166452166453166454166455166456166457166458166459166460166461166462166463166464166465166466166467166468166469166470166471166472166473166474166475166476166477166478166479166480166481166482166483166484166485166486166487166488166489166490166491166492166493166494166495166496166497166498166499166500166501166502166503166504166505166506166507166508166509166510166511166512166513166514166515166516166517166518166519166520166521166522166523166524166525166526166527166528166529166530166531166532166533166534166535166536166537166538166539166540166541166542166543166544166545166546166547166548166549166550166551166552166553166554166555166556166557166558166559166560166561166562166563166564166565166566166567166568166569166570166571166572166573166574166575166576166577166578166579166580166581166582166583166584166585166586166587166588166589166590166591166592166593166594166595166596166597166598166599166600166601166602166603166604166605166606166607166608166609166610166611166612166613166614166615166616166617166618166619166620166621166622166623166624166625166626166627166628166629166630166631166632166633166634166635166636166637166638166639166640166641166642166643166644166645166646166647166648166649166650166651166652166653166654166655166656166657166658166659166660166661166662166663166664166665166666166667166668166669166670166671166672166673166674166675166676166677166678166679166680166681166682166683166684166685166686166687166688166689166690166691166692166693166694166695166696166697166698166699166700166701166702166703166704166705166706166707166708166709166710166711166712166713166714166715166716166717166718166719166720166721166722166723166724166725166726166727166728166729166730166731166732166733166734166735166736166737166738166739166740166741166742166743166744166745166746166747166748166749166750166751166752166753166754166755166756166757166758166759166760166761166762166763166764166765166766166767166768166769166770166771166772166773166774166775166776166777166778166779166780166781166782166783166784166785166786166787166788166789166790166791166792166793166794166795166796166797166798166799166800166801166802166803166804166805166806166807166808166809166810166811166812166813166814166815166816166817166818166819166820166821166822166823166824166825166826166827166828166829166830166831166832166833166834166835166836166837166838166839166840166841166842166843166844166845166846166847166848166849166850166851166852166853166854166855166856166857166858166859166860166861166862166863166864166865166866166867166868166869166870166871166872166873166874166875166876166877166878166879166880166881166882166883166884166885166886166887166888166889166890166891166892166893166894166895166896166897166898166899166900166901166902166903166904166905166906166907166908166909166910166911166912166913166914166915166916166917166918166919166920166921166922166923166924166925166926166927166928166929166930166931166932166933166934166935166936166937166938166939166940166941166942166943166944166945166946166947166948166949166950166951166952166953166954166955166956166957166958166959166960166961166962166963166964166965166966166967166968166969166970166971166972166973166974166975166976166977166978166979166980166981166982166983166984166985166986166987166988166989166990166991166992166993166994166995166996166997166998166999167000167001167002167003167004167005167006167007167008167009167010167011167012167013167014167015167016167017167018167019167020167021167022167023167024167025167026167027167028167029167030167031167032167033167034167035167036167037167038167039167040167041167042167043167044167045167046167047167048167049167050167051167052167053167054167055167056167057167058167059167060167061167062167063167064167065167066167067167068167069167070167071167072167073167074167075167076167077167078167079167080167081167082167083167084167085167086167087167088167089167090167091167092167093167094167095167096167097167098167099167100167101167102167103167104167105167106167107167108167109167110167111167112167113167114167115167116167117167118167119167120167121167122167123167124167125167126167127167128167129167130167131167132167133167134167135167136167137167138167139167140167141167142167143167144167145167146167147167148167149167150167151167152167153167154167155167156167157167158167159167160167161167162167163167164167165167166167167167168167169167170167171167172167173167174167175167176167177167178167179167180167181167182167183167184167185167186167187167188167189167190167191167192167193167194167195167196167197167198167199167200167201167202167203167204167205167206167207167208167209167210167211167212167213167214167215167216167217167218167219167220167221167222167223167224167225167226167227167228167229167230167231167232167233167234167235167236167237167238167239167240167241167242167243167244167245167246167247167248167249167250167251167252167253167254167255167256167257167258167259167260167261167262167263167264167265167266167267167268167269167270167271167272167273167274167275167276167277167278167279167280167281167282167283167284167285167286167287167288167289167290167291167292167293167294167295167296167297167298167299167300167301167302167303167304167305167306167307167308167309167310167311167312167313167314167315167316167317167318167319167320167321167322167323167324167325167326167327167328167329167330167331167332167333167334167335167336167337167338167339167340167341167342167343167344167345167346167347167348167349167350167351167352167353167354167355167356167357167358167359167360167361167362167363167364167365167366167367167368167369167370167371167372167373167374167375167376167377167378167379167380167381167382167383167384167385167386167387167388167389167390167391167392167393167394167395167396167397167398167399167400167401167402167403167404167405167406167407167408167409167410167411167412167413167414167415167416167417167418167419167420167421167422167423167424167425167426167427167428167429167430167431167432167433167434167435167436167437167438167439167440167441167442167443167444167445167446167447167448167449167450167451167452167453167454167455167456167457167458167459167460167461167462167463167464167465167466167467167468167469167470167471167472167473167474167475167476167477167478167479167480167481167482167483167484167485167486167487167488167489167490167491167492167493167494167495167496167497167498167499167500167501167502167503167504167505167506167507167508167509167510167511167512167513167514167515167516167517167518167519167520167521167522167523167524167525167526167527167528167529167530167531167532167533167534167535167536167537167538167539167540167541167542167543167544167545167546167547167548167549167550167551167552167553167554167555167556167557167558167559167560167561167562167563167564167565167566167567167568167569167570167571167572167573167574167575167576167577167578167579167580167581167582167583167584167585167586167587167588167589167590167591167592167593167594167595167596167597167598167599167600167601167602167603167604167605167606167607167608167609167610167611167612167613167614167615167616167617167618167619167620167621167622167623167624167625167626167627167628167629167630167631167632167633167634167635167636167637167638167639167640167641167642167643167644167645167646167647167648167649167650167651167652167653167654167655167656167657167658167659167660167661167662167663167664167665167666167667167668167669167670167671167672167673167674167675167676167677167678167679167680167681167682167683167684167685167686167687167688167689167690167691167692167693167694167695167696167697167698167699167700167701167702167703167704167705167706167707167708167709167710167711167712167713167714167715167716167717167718167719167720167721167722167723167724167725167726167727167728167729167730167731167732167733167734167735167736167737167738167739167740167741167742167743167744167745167746167747167748167749167750167751167752167753167754167755167756167757167758167759167760167761167762167763167764167765167766167767167768167769167770167771167772167773167774167775167776167777167778167779167780167781167782167783167784167785167786167787167788167789167790167791167792167793167794167795167796167797167798167799167800167801167802167803167804167805167806167807167808167809167810167811167812167813167814167815167816167817167818167819167820167821167822167823167824167825167826167827167828167829167830167831167832167833167834167835167836167837167838167839167840167841167842167843167844167845167846167847167848167849167850167851167852167853167854167855167856167857167858167859167860167861167862167863167864167865167866167867167868167869167870167871167872167873167874167875167876167877167878167879167880167881167882167883167884167885167886167887167888167889167890167891167892167893167894167895167896167897167898167899167900167901167902167903167904167905167906167907167908167909167910167911167912167913167914167915167916167917167918167919167920167921167922167923167924167925167926167927167928167929167930167931167932167933167934167935167936167937167938167939167940167941167942167943167944167945167946167947167948167949167950167951167952167953167954167955167956167957167958167959167960167961167962167963167964167965167966167967167968167969167970167971167972167973167974167975167976167977167978167979167980167981167982167983167984167985167986167987167988167989167990167991167992167993167994167995167996167997167998167999168000168001168002168003168004168005168006168007168008168009168010168011168012168013168014168015168016168017168018168019168020168021168022168023168024168025168026168027168028168029168030168031168032168033168034168035168036168037168038168039168040168041168042168043168044168045168046168047168048168049168050168051168052168053168054168055168056168057168058168059168060168061168062168063168064168065168066168067168068168069168070168071168072168073168074168075168076168077168078168079168080168081168082168083168084168085168086168087168088168089168090168091168092168093168094168095168096168097168098168099168100168101168102168103168104168105168106168107168108168109168110168111168112168113168114168115168116168117168118168119168120168121168122168123168124168125168126168127168128168129168130168131168132168133168134168135168136168137168138168139168140168141168142168143168144168145168146168147168148168149168150168151168152168153168154168155168156168157168158168159168160168161168162168163168164168165168166168167168168168169168170168171168172168173168174168175168176168177168178168179168180168181168182168183168184168185168186168187168188168189168190168191168192168193168194168195168196168197168198168199168200168201168202168203168204168205168206168207168208168209168210168211168212168213168214168215168216168217168218168219168220168221168222168223168224168225168226168227168228168229168230168231168232168233168234168235168236168237168238168239168240168241168242168243168244168245168246168247168248168249168250168251168252168253168254168255168256168257168258168259168260168261168262168263168264168265168266168267168268168269168270168271168272168273168274168275168276168277168278168279168280168281168282168283168284168285168286168287168288168289168290168291168292168293168294168295168296168297168298168299168300168301168302168303168304168305168306168307168308168309168310168311168312168313168314168315168316168317168318168319168320168321168322168323168324168325168326168327168328168329168330168331168332168333168334168335168336168337168338168339168340168341168342168343168344168345168346168347168348168349168350168351168352168353168354168355168356168357168358168359168360168361168362168363168364168365168366168367168368168369168370168371168372168373168374168375168376168377168378168379168380168381168382168383168384168385168386168387168388168389168390168391168392168393168394168395168396168397168398168399168400168401168402168403168404168405168406168407168408168409168410168411168412168413168414168415168416168417168418168419168420168421168422168423168424168425168426168427168428168429168430168431168432168433168434168435168436168437168438168439168440168441168442168443168444168445168446168447168448168449168450168451168452168453168454168455168456168457168458168459168460168461168462168463168464168465168466168467168468168469168470168471168472168473168474168475168476168477168478168479168480168481168482168483168484168485168486168487168488168489168490168491168492168493168494168495168496168497168498168499168500168501168502168503168504168505168506168507168508168509168510168511168512168513168514168515168516168517168518168519168520168521168522168523168524168525168526168527168528168529168530168531168532168533168534168535168536168537168538168539168540168541168542168543168544168545168546168547168548168549168550168551168552168553168554168555168556168557168558168559168560168561168562168563168564168565168566168567168568168569168570168571168572168573168574168575168576168577168578168579168580168581168582168583168584168585168586168587168588168589168590168591168592168593168594168595168596168597168598168599168600168601168602168603168604168605168606168607168608168609168610168611168612168613168614168615168616168617168618168619168620168621168622168623168624168625168626168627168628168629168630168631168632168633168634168635168636168637168638168639168640168641168642168643168644168645168646168647168648168649168650168651168652168653168654168655168656168657168658168659168660168661168662168663168664168665168666168667168668168669168670168671168672168673168674168675168676168677168678168679168680168681168682168683168684168685168686168687168688168689168690168691168692168693168694168695168696168697168698168699168700168701168702168703168704168705168706168707168708168709168710168711168712168713168714168715168716168717168718168719168720168721168722168723168724168725168726168727168728168729168730168731168732168733168734168735168736168737168738168739168740168741168742168743168744168745168746168747168748168749168750168751168752168753168754168755168756168757168758168759168760168761168762168763168764168765168766168767168768168769168770168771168772168773168774168775168776168777168778168779168780168781168782168783168784168785168786168787168788168789168790168791168792168793168794168795168796168797168798168799168800168801168802168803168804168805168806168807168808168809168810168811168812168813168814168815168816168817168818168819168820168821168822168823168824168825168826168827168828168829168830168831168832168833168834168835168836168837168838168839168840168841168842168843168844168845168846168847168848168849168850168851168852168853168854168855168856168857168858168859168860168861168862168863168864168865168866168867168868168869168870168871168872168873168874168875168876168877168878168879168880168881168882168883168884168885168886168887168888168889168890168891168892168893168894168895168896168897168898168899168900168901168902168903168904168905168906168907168908168909168910168911168912168913168914168915168916168917168918168919168920168921168922168923168924168925168926168927168928168929168930168931168932168933168934168935168936168937168938168939168940168941168942168943168944168945168946168947168948168949168950168951168952168953168954168955168956168957168958168959168960168961168962168963168964168965168966168967168968168969168970168971168972168973168974168975168976168977168978168979168980168981168982168983168984168985168986168987168988168989168990168991168992168993168994168995168996168997168998168999169000169001169002169003169004169005169006169007169008169009169010169011169012169013169014169015169016169017169018169019169020169021169022169023169024169025169026169027169028169029169030169031169032169033169034169035169036169037169038169039169040169041169042169043169044169045169046169047169048169049169050169051169052169053169054169055169056169057169058169059169060169061169062169063169064169065169066169067169068169069169070169071169072169073169074169075169076169077169078169079169080169081169082169083169084169085169086169087169088169089169090169091169092169093169094169095169096169097169098169099169100169101169102169103169104169105169106169107169108169109169110169111169112169113169114169115169116169117169118169119169120169121169122169123169124169125169126169127169128169129169130169131169132169133169134169135169136169137169138169139169140169141169142169143169144169145169146169147169148169149169150169151169152169153169154169155169156169157169158169159169160169161169162169163169164169165169166169167169168169169169170169171169172169173169174169175169176169177169178169179169180169181169182169183169184169185169186169187169188169189169190169191169192169193169194169195169196169197169198169199169200169201169202169203169204169205169206169207169208169209169210169211169212169213169214169215169216169217169218169219169220169221169222169223169224169225169226169227169228169229169230169231169232169233169234169235169236169237169238169239169240169241169242169243169244169245169246169247169248169249169250169251169252169253169254169255169256169257169258169259169260169261169262169263169264169265169266169267169268169269169270169271169272169273169274169275169276169277169278169279169280169281169282169283169284169285169286169287169288169289169290169291169292169293169294169295169296169297169298169299169300169301169302169303169304169305169306169307169308169309169310169311169312169313169314169315169316169317169318169319169320169321169322169323169324169325169326169327169328169329169330169331169332169333169334169335169336169337169338169339169340169341169342169343169344169345169346169347169348169349169350169351169352169353169354169355169356169357169358169359169360169361169362169363169364169365169366169367169368169369169370169371169372169373169374169375169376169377169378169379169380169381169382169383169384169385169386169387169388169389169390169391169392169393169394169395169396169397169398169399169400169401169402169403169404169405169406169407169408169409169410169411169412169413169414169415169416169417169418169419169420169421169422169423169424169425169426169427169428169429169430169431169432169433169434169435169436169437169438169439169440169441169442169443169444169445169446169447169448169449169450169451169452169453169454169455169456169457169458169459169460169461169462169463169464169465169466169467169468169469169470169471169472169473169474169475169476169477169478169479169480169481169482169483169484169485169486169487169488169489169490169491169492169493169494169495169496169497169498169499169500169501169502169503169504169505169506169507169508169509169510169511169512169513169514169515169516169517169518169519169520169521169522169523169524169525169526169527169528169529169530169531169532169533169534169535169536169537169538169539169540169541169542169543169544169545169546169547169548169549169550169551169552169553169554169555169556169557169558169559169560169561169562169563169564169565169566169567169568169569169570169571169572169573169574169575169576169577169578169579169580169581169582169583169584169585169586169587169588169589169590169591169592169593169594169595169596169597169598169599169600169601169602169603169604169605169606169607169608169609169610169611169612169613169614169615169616169617169618169619169620169621169622169623169624169625169626169627169628169629169630169631169632169633169634169635169636169637169638169639169640169641169642169643169644169645169646169647169648169649169650169651169652169653169654169655169656169657169658169659169660169661169662169663169664169665169666169667169668169669169670169671169672169673169674169675169676169677169678169679169680169681169682169683169684169685169686169687169688169689169690169691169692169693169694169695169696169697169698169699169700169701169702169703169704169705169706169707169708169709169710169711169712169713169714169715169716169717169718169719169720169721169722169723169724169725169726169727169728169729169730169731169732169733169734169735169736169737169738169739169740169741169742169743169744169745169746169747169748169749169750169751169752169753169754169755169756169757169758169759169760169761169762169763169764169765169766169767169768169769169770169771169772169773169774169775169776169777169778169779169780169781169782169783169784169785169786169787169788169789169790169791169792169793169794169795169796169797169798169799169800169801169802169803169804169805169806169807169808169809169810169811169812169813169814169815169816169817169818169819169820169821169822169823169824169825169826169827169828169829169830169831169832169833169834169835169836169837169838169839169840169841169842169843169844169845169846169847169848169849169850169851169852169853169854169855169856169857169858169859169860169861169862169863169864169865169866169867169868169869169870169871169872169873169874169875169876169877169878169879169880169881169882169883169884169885169886169887169888169889169890169891169892169893169894169895169896169897169898169899169900169901169902169903169904169905169906169907169908169909169910169911169912169913169914169915169916169917169918169919169920169921169922169923169924169925169926169927169928169929169930169931169932169933169934169935169936169937169938169939169940169941169942169943169944169945169946169947169948169949169950169951169952169953169954169955169956169957169958169959169960169961169962169963169964169965169966169967169968169969169970169971169972169973169974169975169976169977169978169979169980169981169982169983169984169985169986169987169988169989169990169991169992169993169994169995169996169997169998169999170000170001170002170003170004170005170006170007170008170009170010170011170012170013170014170015170016170017170018170019170020170021170022170023170024170025170026170027170028170029170030170031170032170033170034170035170036170037170038170039170040170041170042170043170044170045170046170047170048170049170050170051170052170053170054170055170056170057170058170059170060170061170062170063170064170065170066170067170068170069170070170071170072170073170074170075170076170077170078170079170080170081170082170083170084170085170086170087170088170089170090170091170092170093170094170095170096170097170098170099170100170101170102170103170104170105170106170107170108170109170110170111170112170113170114170115170116170117170118170119170120170121170122170123170124170125170126170127170128170129170130170131170132170133170134170135170136170137170138170139170140170141170142170143170144170145170146170147170148170149170150170151170152170153170154170155170156170157170158170159170160170161170162170163170164170165170166170167170168170169170170170171170172170173170174170175170176170177170178170179170180170181170182170183170184170185170186170187170188170189170190170191170192170193170194170195170196170197170198170199170200170201170202170203170204170205170206170207170208170209170210170211170212170213170214170215170216170217170218170219170220170221170222170223170224170225170226170227170228170229170230170231170232170233170234170235170236170237170238170239170240170241170242170243170244170245170246170247170248170249170250170251170252170253170254170255170256170257170258170259170260170261170262170263170264170265170266170267170268170269170270170271170272170273170274170275170276170277170278170279170280170281170282170283170284170285170286170287170288170289170290170291170292170293170294170295170296170297170298170299170300170301170302170303170304170305170306170307170308170309170310170311170312170313170314170315170316170317170318170319170320170321170322170323170324170325170326170327170328170329170330170331170332170333170334170335170336170337170338170339170340170341170342170343170344170345170346170347170348170349170350170351170352170353170354170355170356170357170358170359170360170361170362170363170364170365170366170367170368170369170370170371170372170373170374170375170376170377170378170379170380170381170382170383170384170385170386170387170388170389170390170391170392170393170394170395170396170397170398170399170400170401170402170403170404170405170406170407170408170409170410170411170412170413170414170415170416170417170418170419170420170421170422170423170424170425170426170427170428170429170430170431170432170433170434170435170436170437170438170439170440170441170442170443170444170445170446170447170448170449170450170451170452170453170454170455170456170457170458170459170460170461170462170463170464170465170466170467170468170469170470170471170472170473170474170475170476170477170478170479170480170481170482170483170484170485170486170487170488170489170490170491170492170493170494170495170496170497170498170499170500170501170502170503170504170505170506170507170508170509170510170511170512170513170514170515170516170517170518170519170520170521170522170523170524170525170526170527170528170529170530170531170532170533170534170535170536170537170538170539170540170541170542170543170544170545170546170547170548170549170550170551170552170553170554170555170556170557170558170559170560170561170562170563170564170565170566170567170568170569170570170571170572170573170574170575170576170577170578170579170580170581170582170583170584170585170586170587170588170589170590170591170592170593170594170595170596170597170598170599170600170601170602170603170604170605170606170607170608170609170610170611170612170613170614170615170616170617170618170619170620170621170622170623170624170625170626170627170628170629170630170631170632170633170634170635170636170637170638170639170640170641170642170643170644170645170646170647170648170649170650170651170652170653170654170655170656170657170658170659170660170661170662170663170664170665170666170667170668170669170670170671170672170673170674170675170676170677170678170679170680170681170682170683170684170685170686170687170688170689170690170691170692170693170694170695170696170697170698170699170700170701170702170703170704170705170706170707170708170709170710170711170712170713170714170715170716170717170718170719170720170721170722170723170724170725170726170727170728170729170730170731170732170733170734170735170736170737170738170739170740170741170742170743170744170745170746170747170748170749170750170751170752170753170754170755170756170757170758170759170760170761170762170763170764170765170766170767170768170769170770170771170772170773170774170775170776170777170778170779170780170781170782170783170784170785170786170787170788170789170790170791170792170793170794170795170796170797170798170799170800170801170802170803170804170805170806170807170808170809170810170811170812170813170814170815170816170817170818170819170820170821170822170823170824170825170826170827170828170829170830170831170832170833170834170835170836170837170838170839170840170841170842170843170844170845170846170847170848170849170850170851170852170853170854170855170856170857170858170859170860170861170862170863170864170865170866170867170868170869170870170871170872170873170874170875170876170877170878170879170880170881170882170883170884170885170886170887170888170889170890170891170892170893170894170895170896170897170898170899170900170901170902170903170904170905170906170907170908170909170910170911170912170913170914170915170916170917170918170919170920170921170922170923170924170925170926170927170928170929170930170931170932170933170934170935170936170937170938170939170940170941170942170943170944170945170946170947170948170949170950170951170952170953170954170955170956170957170958170959170960170961170962170963170964170965170966170967170968170969170970170971170972170973170974170975170976170977170978170979170980170981170982170983170984170985170986170987170988170989170990170991170992170993170994170995170996170997170998170999171000171001171002171003171004171005171006171007171008171009171010171011171012171013171014171015171016171017171018171019171020171021171022171023171024171025171026171027171028171029171030171031171032171033171034171035171036171037171038171039171040171041171042171043171044171045171046171047171048171049171050171051171052171053171054171055171056171057171058171059171060171061171062171063171064171065171066171067171068171069171070171071171072171073171074171075171076171077171078171079171080171081171082171083171084171085171086171087171088171089171090171091171092171093171094171095171096171097171098171099171100171101171102171103171104171105171106171107171108171109171110171111171112171113171114171115171116171117171118171119171120171121171122171123171124171125171126171127171128171129171130171131171132171133171134171135171136171137171138171139171140171141171142171143171144171145171146171147171148171149171150171151171152171153171154171155171156171157171158171159171160171161171162171163171164171165171166171167171168171169171170171171171172171173171174171175171176171177171178171179171180171181171182171183171184171185171186171187171188171189171190171191171192171193171194171195171196171197171198171199171200171201171202171203171204171205171206171207171208171209171210171211171212171213171214171215171216171217171218171219171220171221171222171223171224171225171226171227171228171229171230171231171232171233171234171235171236171237171238171239171240171241171242171243171244171245171246171247171248171249171250171251171252171253171254171255171256171257171258171259171260171261171262171263171264171265171266171267171268171269171270171271171272171273171274171275171276171277171278171279171280171281171282171283171284171285171286171287171288171289171290171291171292171293171294171295171296171297171298171299171300171301171302171303171304171305171306171307171308171309171310171311171312171313171314171315171316171317171318171319171320171321171322171323171324171325171326171327171328171329171330171331171332171333171334171335171336171337171338171339171340171341171342171343171344171345171346171347171348171349171350171351171352171353171354171355171356171357171358171359171360171361171362171363171364171365171366171367171368171369171370171371171372171373171374171375171376171377171378171379171380171381171382171383171384171385171386171387171388171389171390171391171392171393171394171395171396171397171398171399171400171401171402171403171404171405171406171407171408171409171410171411171412171413171414171415171416171417171418171419171420171421171422171423171424171425171426171427171428171429171430171431171432171433171434171435171436171437171438171439171440171441171442171443171444171445171446171447171448171449171450171451171452171453171454171455171456171457171458171459171460171461171462171463171464171465171466171467171468171469171470171471171472171473171474171475171476171477171478171479171480171481171482171483171484171485171486171487171488171489171490171491171492171493171494171495171496171497171498171499171500171501171502171503171504171505171506171507171508171509171510171511171512171513171514171515171516171517171518171519171520171521171522171523171524171525171526171527171528171529171530171531171532171533171534171535171536171537171538171539171540171541171542171543171544171545171546171547171548171549171550171551171552171553171554171555171556171557171558171559171560171561171562171563171564171565171566171567171568171569171570171571171572171573171574171575171576171577171578171579171580171581171582171583171584171585171586171587171588171589171590171591171592171593171594171595171596171597171598171599171600171601171602171603171604171605171606171607171608171609171610171611171612171613171614171615171616171617171618171619171620171621171622171623171624171625171626171627171628171629171630171631171632171633171634171635171636171637171638171639171640171641171642171643171644171645171646171647171648171649171650171651171652171653171654171655171656171657171658171659171660171661171662171663171664171665171666171667171668171669171670171671171672171673171674171675171676171677171678171679171680171681171682171683171684171685171686171687171688171689171690171691171692171693171694171695171696171697171698171699171700171701171702171703171704171705171706171707171708171709171710171711171712171713171714171715171716171717171718171719171720171721171722171723171724171725171726171727171728171729171730171731171732171733171734171735171736171737171738171739171740171741171742171743171744171745171746171747171748171749171750171751171752171753171754171755171756171757171758171759171760171761171762171763171764171765171766171767171768171769171770171771171772171773171774171775171776171777171778171779171780171781171782171783171784171785171786171787171788171789171790171791171792171793171794171795171796171797171798171799171800171801171802171803171804171805171806171807171808171809171810171811171812171813171814171815171816171817171818171819171820171821171822171823171824171825171826171827171828171829171830171831171832171833171834171835171836171837171838171839171840171841171842171843171844171845171846171847171848171849171850171851171852171853171854171855171856171857171858171859171860171861171862171863171864171865171866171867171868171869171870171871171872171873171874171875171876171877171878171879171880171881171882171883171884171885171886171887171888171889171890171891171892171893171894171895171896171897171898171899171900171901171902171903171904171905171906171907171908171909171910171911171912171913171914171915171916171917171918171919171920171921171922171923171924171925171926171927171928171929171930171931171932171933171934171935171936171937171938171939171940171941171942171943171944171945171946171947171948171949171950171951171952171953171954171955171956171957171958171959171960171961171962171963171964171965171966171967171968171969171970171971171972171973171974171975171976171977171978171979171980171981171982171983171984171985171986171987171988171989171990171991171992171993171994171995171996171997171998171999172000172001172002172003172004172005172006172007172008172009172010172011172012172013172014172015172016172017172018172019172020172021172022172023172024172025172026172027172028172029172030172031172032172033172034172035172036172037172038172039172040172041172042172043172044172045172046172047172048172049172050172051172052172053172054172055172056172057172058172059172060172061172062172063172064172065172066172067172068172069172070172071172072172073172074172075172076172077172078172079172080172081172082172083172084172085172086172087172088172089172090172091172092172093172094172095172096172097172098172099172100172101172102172103172104172105172106172107172108172109172110172111172112172113172114172115172116172117172118172119172120172121172122172123172124172125172126172127172128172129172130172131172132172133172134172135172136172137172138172139172140172141172142172143172144172145172146172147172148172149172150172151172152172153172154172155172156172157172158172159172160172161172162172163172164172165172166172167172168172169172170172171172172172173172174172175172176172177172178172179172180172181172182172183172184172185172186172187172188172189172190172191172192172193172194172195172196172197172198172199172200172201172202172203172204172205172206172207172208172209172210172211172212172213172214172215172216172217172218172219172220172221172222172223172224172225172226172227172228172229172230172231172232172233172234172235172236172237172238172239172240172241172242172243172244172245172246172247172248172249172250172251172252172253172254172255172256172257172258172259172260172261172262172263172264172265172266172267172268172269172270172271172272172273172274172275172276172277172278172279172280172281172282172283172284172285172286172287172288172289172290172291172292172293172294172295172296172297172298172299172300172301172302172303172304172305172306172307172308172309172310172311172312172313172314172315172316172317172318172319172320172321172322172323172324172325172326172327172328172329172330172331172332172333172334172335172336172337172338172339172340172341172342172343172344172345172346172347172348172349172350172351172352172353172354172355172356172357172358172359172360172361172362172363172364172365172366172367172368172369172370172371172372172373172374172375172376172377172378172379172380172381172382172383172384172385172386172387172388172389172390172391172392172393172394172395172396172397172398172399172400172401172402172403172404172405172406172407172408172409172410172411172412172413172414172415172416172417172418172419172420172421172422172423172424172425172426172427172428172429172430172431172432172433172434172435172436172437172438172439172440172441172442172443172444172445172446172447172448172449172450172451172452172453172454172455172456172457172458172459172460172461172462172463172464172465172466172467172468172469172470172471172472172473172474172475172476172477172478172479172480172481172482172483172484172485172486172487172488172489172490172491172492172493172494172495172496172497172498172499172500172501172502172503172504172505172506172507172508172509172510172511172512172513172514172515172516172517172518172519172520172521172522172523172524172525172526172527172528172529172530172531172532172533172534172535172536172537172538172539172540172541172542172543172544172545172546172547172548172549172550172551172552172553172554172555172556172557172558172559172560172561172562172563172564172565172566172567172568172569172570172571172572172573172574172575172576172577172578172579172580172581172582172583172584172585172586172587172588172589172590172591172592172593172594172595172596172597172598172599172600172601172602172603172604172605172606172607172608172609172610172611172612172613172614172615172616172617172618172619172620172621172622172623172624172625172626172627172628172629172630172631172632172633172634172635172636172637172638172639172640172641172642172643172644172645172646172647172648172649172650172651172652172653172654172655172656172657172658172659172660172661172662172663172664172665172666172667172668172669172670172671172672172673172674172675172676172677172678172679172680172681172682172683172684172685172686172687172688172689172690172691172692172693172694172695172696172697172698172699172700172701172702172703172704172705172706172707172708172709172710172711172712172713172714172715172716172717172718172719172720172721172722172723172724172725172726172727172728172729172730172731172732172733172734172735172736172737172738172739172740172741172742172743172744172745172746172747172748172749172750172751172752172753172754172755172756172757172758172759172760172761172762172763172764172765172766172767172768172769172770172771172772172773172774172775172776172777172778172779172780172781172782172783172784172785172786172787172788172789172790172791172792172793172794172795172796172797172798172799172800172801172802172803172804172805172806172807172808172809172810172811172812172813172814172815172816172817172818172819172820172821172822172823172824172825172826172827172828172829172830172831172832172833172834172835172836172837172838172839172840172841172842172843172844172845172846172847172848172849172850172851172852172853172854172855172856172857172858172859172860172861172862172863172864172865172866172867172868172869172870172871172872172873172874172875172876172877172878172879172880172881172882172883172884172885172886172887172888172889172890172891172892172893172894172895172896172897172898172899172900172901172902172903172904172905172906172907172908172909172910172911172912172913172914172915172916172917172918172919172920172921172922172923172924172925172926172927172928172929172930172931172932172933172934172935172936172937172938172939172940172941172942172943172944172945172946172947172948172949172950172951172952172953172954172955172956172957172958172959172960172961172962172963172964172965172966172967172968172969172970172971172972172973172974172975172976172977172978172979172980172981172982172983172984172985172986172987172988172989172990172991172992172993172994172995172996172997172998172999173000173001173002173003173004173005173006173007173008173009173010173011173012173013173014173015173016173017173018173019173020173021173022173023173024173025173026173027173028173029173030173031173032173033173034173035173036173037173038173039173040173041173042173043173044173045173046173047173048173049173050173051173052173053173054173055173056173057173058173059173060173061173062173063173064173065173066173067173068173069173070173071173072173073173074173075173076173077173078173079173080173081173082173083173084173085173086173087173088173089173090173091173092173093173094173095173096173097173098173099173100173101173102173103173104173105173106173107173108173109173110173111173112173113173114173115173116173117173118173119173120173121173122173123173124173125173126173127173128173129173130173131173132173133173134173135173136173137173138173139173140173141173142173143173144173145173146173147173148173149173150173151173152173153173154173155173156173157173158173159173160173161173162173163173164173165173166173167173168173169173170173171173172173173173174173175173176173177173178173179173180173181173182173183173184173185173186173187173188173189173190173191173192173193173194173195173196173197173198173199173200173201173202173203173204173205173206173207173208173209173210173211173212173213173214173215173216173217173218173219173220173221173222173223173224173225173226173227173228173229173230173231173232173233173234173235173236173237173238173239173240173241173242173243173244173245173246173247173248173249173250173251173252173253173254173255173256173257173258173259173260173261173262173263173264173265173266173267173268173269173270173271173272173273173274173275173276173277173278173279173280173281173282173283173284173285173286173287173288173289173290173291173292173293173294173295173296173297173298173299173300173301173302173303173304173305173306173307173308173309173310173311173312173313173314173315173316173317173318173319173320173321173322173323173324173325173326173327173328173329173330173331173332173333173334173335173336173337173338173339173340173341173342173343173344173345173346173347173348173349173350173351173352173353173354173355173356173357173358173359173360173361173362173363173364173365173366173367173368173369173370173371173372173373173374173375173376173377173378173379173380173381173382173383173384173385173386173387173388173389173390173391173392173393173394173395173396173397173398173399173400173401173402173403173404173405173406173407173408173409173410173411173412173413173414173415173416173417173418173419173420173421173422173423173424173425173426173427173428173429173430173431173432173433173434173435173436173437173438173439173440173441173442173443173444173445173446173447173448173449173450173451173452173453173454173455173456173457173458173459173460173461173462173463173464173465173466173467173468173469173470173471173472173473173474173475173476173477173478173479173480173481173482173483173484173485173486173487173488173489173490173491173492173493173494173495173496173497173498173499173500173501173502173503173504173505173506173507173508173509173510173511173512173513173514173515173516173517173518173519173520173521173522173523173524173525173526173527173528173529173530173531173532173533173534173535173536173537173538173539173540173541173542173543173544173545173546173547173548173549173550173551173552173553173554173555173556173557173558173559173560173561173562173563173564173565173566173567173568173569173570173571173572173573173574173575173576173577173578173579173580173581173582173583173584173585173586173587173588173589173590173591173592173593173594173595173596173597173598173599173600173601173602173603173604173605173606173607173608173609173610173611173612173613173614173615173616173617173618173619173620173621173622173623173624173625173626173627173628173629173630173631173632173633173634173635173636173637173638173639173640173641173642173643173644173645173646173647173648173649173650173651173652173653173654173655173656173657173658173659173660173661173662173663173664173665173666173667173668173669173670173671173672173673173674173675173676173677173678173679173680173681173682173683173684173685173686173687173688173689173690173691173692173693173694173695173696173697173698173699173700173701173702173703173704173705173706173707173708173709173710173711173712173713173714173715173716173717173718173719173720173721173722173723173724173725173726173727173728173729173730173731173732173733173734173735173736173737173738173739173740173741173742173743173744173745173746173747173748173749173750173751173752173753173754173755173756173757173758173759173760173761173762173763173764173765173766173767173768173769173770173771173772173773173774173775173776173777173778173779173780173781173782173783173784173785173786173787173788173789173790173791173792173793173794173795173796173797173798173799173800173801173802173803173804173805173806173807173808173809173810173811173812173813173814173815173816173817173818173819173820173821173822173823173824173825173826173827173828173829173830173831173832173833173834173835173836173837173838173839173840173841173842173843173844173845173846173847173848173849173850173851173852173853173854173855173856173857173858173859173860173861173862173863173864173865173866173867173868173869173870173871173872173873173874173875173876173877173878173879173880173881173882173883173884173885173886173887173888173889173890173891173892173893173894173895173896173897173898173899173900173901173902173903173904173905173906173907173908173909173910173911173912173913173914173915173916173917173918173919173920173921173922173923173924173925173926173927173928173929173930173931173932173933173934173935173936173937173938173939173940173941173942173943173944173945173946173947173948173949173950173951173952173953173954173955173956173957173958173959173960173961173962173963173964173965173966173967173968173969173970173971173972173973173974173975173976173977173978173979173980173981173982173983173984173985173986173987173988173989173990173991173992173993173994173995173996173997173998173999174000174001174002174003174004174005174006174007174008174009174010174011174012174013174014174015174016174017174018174019174020174021174022174023174024174025174026174027174028174029174030174031174032174033174034174035174036174037174038174039174040174041174042174043174044174045174046174047174048174049174050174051174052174053174054174055174056174057174058174059174060174061174062174063174064174065174066174067174068174069174070174071174072174073174074174075174076174077174078174079174080174081174082174083174084174085174086174087174088174089174090174091174092174093174094174095174096174097174098174099174100174101174102174103174104174105174106174107174108174109174110174111174112174113174114174115174116174117174118174119174120174121174122174123174124174125174126174127174128174129174130174131174132174133174134174135174136174137174138174139174140174141174142174143174144174145174146174147174148174149174150174151174152174153174154174155174156174157174158174159174160174161174162174163174164174165174166174167174168174169174170174171174172174173174174174175174176174177174178174179174180174181174182174183174184174185174186174187174188174189174190174191174192174193174194174195174196174197174198174199174200174201174202174203174204174205174206174207174208174209174210174211174212174213174214174215174216174217174218174219174220174221174222174223174224174225174226174227174228174229174230174231174232174233174234174235174236174237174238174239174240174241174242174243174244174245174246174247174248174249174250174251174252174253174254174255174256174257174258174259174260174261174262174263174264174265174266174267174268174269174270174271174272174273174274174275174276174277174278174279174280174281174282174283174284174285174286174287174288174289174290174291174292174293174294174295174296174297174298174299174300174301174302174303174304174305174306174307174308174309174310174311174312174313174314174315174316174317174318174319174320174321174322174323174324174325174326174327174328174329174330174331174332174333174334174335174336174337174338174339174340174341174342174343174344174345174346174347174348174349174350174351174352174353174354174355174356174357174358174359174360174361174362174363174364174365174366174367174368174369174370174371174372174373174374174375174376174377174378174379174380174381174382174383174384174385174386174387174388174389174390174391174392174393174394174395174396174397174398174399174400174401174402174403174404174405174406174407174408174409174410174411174412174413174414174415174416174417174418174419174420174421174422174423174424174425174426174427174428174429174430174431174432174433174434174435174436174437174438174439174440174441174442174443174444174445174446174447174448174449174450174451174452174453174454174455174456174457174458174459174460174461174462174463174464174465174466174467174468174469174470174471174472174473174474174475174476174477174478174479174480174481174482174483174484174485174486174487174488174489174490174491174492174493174494174495174496174497174498174499174500174501174502174503174504174505174506174507174508174509174510174511174512174513174514174515174516174517174518174519174520174521174522174523174524174525174526174527174528174529174530174531174532174533174534174535174536174537174538174539174540174541174542174543174544174545174546174547174548174549174550174551174552174553174554174555174556174557174558174559174560174561174562174563174564174565174566174567174568174569174570174571174572174573174574174575174576174577174578174579174580174581174582174583174584174585174586174587174588174589174590174591174592174593174594174595174596174597174598174599174600174601174602174603174604174605174606174607174608174609174610174611174612174613174614174615174616174617174618174619174620174621174622174623174624174625174626174627174628174629174630174631174632174633174634174635174636174637174638174639174640174641174642174643174644174645174646174647174648174649174650174651174652174653174654174655174656174657174658174659174660174661174662174663174664174665174666174667174668174669174670174671174672174673174674174675174676174677174678174679174680174681174682174683174684174685174686174687174688174689174690174691174692174693174694174695174696174697174698174699174700174701174702174703174704174705174706174707174708174709174710174711174712174713174714174715174716174717174718174719174720174721174722174723174724174725174726174727174728174729174730174731174732174733174734174735174736174737174738174739174740174741174742174743174744174745174746174747174748174749174750174751174752174753174754174755174756174757174758174759174760174761174762174763174764174765174766174767174768174769174770174771174772174773174774174775174776174777174778174779174780174781174782174783174784174785174786174787174788174789174790174791174792174793174794174795174796174797174798174799174800174801174802174803174804174805174806174807174808174809174810174811174812174813174814174815174816174817174818174819174820174821174822174823174824174825174826174827174828174829174830174831174832174833174834174835174836174837174838174839174840174841174842174843174844174845174846174847174848174849174850174851174852174853174854174855174856174857174858174859174860174861174862174863174864174865174866174867174868174869174870174871174872174873174874174875174876174877174878174879174880174881174882174883174884174885174886174887174888174889174890174891174892174893174894174895174896174897174898174899174900174901174902174903174904174905174906174907174908174909174910174911174912174913174914174915174916174917174918174919174920174921174922174923174924174925174926174927174928174929174930174931174932174933174934174935174936174937174938174939174940174941174942174943174944174945174946174947174948174949174950174951174952174953174954174955174956174957174958174959174960174961174962174963174964174965174966174967174968174969174970174971174972174973174974174975174976174977174978174979174980174981174982174983174984174985174986174987174988174989174990174991174992174993174994174995174996174997174998174999175000175001175002175003175004175005175006175007175008175009175010175011175012175013175014175015175016175017175018175019175020175021175022175023175024175025175026175027175028175029175030175031175032175033175034175035175036175037175038175039175040175041175042175043175044175045175046175047175048175049175050175051175052175053175054175055175056175057175058175059175060175061175062175063175064175065175066175067175068175069175070175071175072175073175074175075175076175077175078175079175080175081175082175083175084175085175086175087175088175089175090175091175092175093175094175095175096175097175098175099175100175101175102175103175104175105175106175107175108175109175110175111175112175113175114175115175116175117175118175119175120175121175122175123175124175125175126175127175128175129175130175131175132175133175134175135175136175137175138175139175140175141175142175143175144175145175146175147175148175149175150175151175152175153175154175155175156175157175158175159175160175161175162175163175164175165175166175167175168175169175170175171175172175173175174175175175176175177175178175179175180175181175182175183175184175185175186175187175188175189175190175191175192175193175194175195175196175197175198175199175200175201175202175203175204175205175206175207175208175209175210175211175212175213175214175215175216175217175218175219175220175221175222175223175224175225175226175227175228175229175230175231175232175233175234175235175236175237175238175239175240175241175242175243175244175245175246175247175248175249175250175251175252175253175254175255175256175257175258175259175260175261175262175263175264175265175266175267175268175269175270175271175272175273175274175275175276175277175278175279175280175281175282175283175284175285175286175287175288175289175290175291175292175293175294175295175296175297175298175299175300175301175302175303175304175305175306175307175308175309175310175311175312175313175314175315175316175317175318175319175320175321175322175323175324175325175326175327175328175329175330175331175332175333175334175335175336175337175338175339175340175341175342175343175344175345175346175347175348175349175350175351175352175353175354175355175356175357175358175359175360175361175362175363175364175365175366175367175368175369175370175371175372175373175374175375175376175377175378175379175380175381175382175383175384175385175386175387175388175389175390175391175392175393175394175395175396175397175398175399175400175401175402175403175404175405175406175407175408175409175410175411175412175413175414175415175416175417175418175419175420175421175422175423175424175425175426175427175428175429175430175431175432175433175434175435175436175437175438175439175440175441175442175443175444175445175446175447175448175449175450175451175452175453175454175455175456175457175458175459175460175461175462175463175464175465175466175467175468175469175470175471175472175473175474175475175476175477175478175479175480175481175482175483175484175485175486175487175488175489175490175491175492175493175494175495175496175497175498175499175500175501175502175503175504175505175506175507175508175509175510175511175512175513175514175515175516175517175518175519175520175521175522175523175524175525175526175527175528175529175530175531175532175533175534175535175536175537175538175539175540175541175542175543175544175545175546175547175548175549175550175551175552175553175554175555175556175557175558175559175560175561175562175563175564175565175566175567175568175569175570175571175572175573175574175575175576175577175578175579175580175581175582175583175584175585175586175587175588175589175590175591175592175593175594175595175596175597175598175599175600175601175602175603175604175605175606175607175608175609175610175611175612175613175614175615175616175617175618175619175620175621175622175623175624175625175626175627175628175629175630175631175632175633175634175635175636175637175638175639175640175641175642175643175644175645175646175647175648175649175650175651175652175653175654175655175656175657175658175659175660175661175662175663175664175665175666175667175668175669175670175671175672175673175674175675175676175677175678175679175680175681175682175683175684175685175686175687175688175689175690175691175692175693175694175695175696175697175698175699175700175701175702175703175704175705175706175707175708175709175710175711175712175713175714175715175716175717175718175719175720175721175722175723175724175725175726175727175728175729175730175731175732175733175734175735175736175737175738175739175740175741175742175743175744175745175746175747175748175749175750175751175752175753175754175755175756175757175758175759175760175761175762175763175764175765175766175767175768175769175770175771175772175773175774175775175776175777175778175779175780175781175782175783175784175785175786175787175788175789175790175791175792175793175794175795175796175797175798175799175800175801175802175803175804175805175806175807175808175809175810175811175812175813175814175815175816175817175818175819175820175821175822175823175824175825175826175827175828175829175830175831175832175833175834175835175836175837175838175839175840175841175842175843175844175845175846175847175848175849175850175851175852175853175854175855175856175857175858175859175860175861175862175863175864175865175866175867175868175869175870175871175872175873175874175875175876175877175878175879175880175881175882175883175884175885175886175887175888175889175890175891175892175893175894175895175896175897175898175899175900175901175902175903175904175905175906175907175908175909175910175911175912175913175914175915175916175917175918175919175920175921175922175923175924175925175926175927175928175929175930175931175932175933175934175935175936175937175938175939175940175941175942175943175944175945175946175947175948175949175950175951175952175953175954175955175956175957175958175959175960175961175962175963175964175965175966175967175968175969175970175971175972175973175974175975175976175977175978175979175980175981175982175983175984175985175986175987175988175989175990175991175992175993175994175995175996175997175998175999176000176001176002176003176004176005176006176007176008176009176010176011176012176013176014176015176016176017176018176019176020176021176022176023176024176025176026176027176028176029176030176031176032176033176034176035176036176037176038176039176040176041176042176043176044176045176046176047176048176049176050176051176052176053176054176055176056176057176058176059176060176061176062176063176064176065176066176067176068176069176070176071176072176073176074176075176076176077176078176079176080176081176082176083176084176085176086176087176088176089176090176091176092176093176094176095176096176097176098176099176100176101176102176103176104176105176106176107176108176109176110176111176112176113176114176115176116176117176118176119176120176121176122176123176124176125176126176127176128176129176130176131176132176133176134176135176136176137176138176139176140176141176142176143176144176145176146176147176148176149176150176151176152176153176154176155176156176157176158176159176160176161176162176163176164176165176166176167176168176169176170176171176172176173176174176175176176176177176178176179176180176181176182176183176184176185176186176187176188176189176190176191176192176193176194176195176196176197176198176199176200176201176202176203176204176205176206176207176208176209176210176211176212176213176214176215176216176217176218176219176220176221176222176223176224176225176226176227176228176229176230176231176232176233176234176235176236176237176238176239176240176241176242176243176244176245176246176247176248176249176250176251176252176253176254176255176256176257176258176259176260176261176262176263176264176265176266176267176268176269176270176271176272176273176274176275176276176277176278176279176280176281176282176283176284176285176286176287176288176289176290176291176292176293176294176295176296176297176298176299176300176301176302176303176304176305176306176307176308176309176310176311176312176313176314176315176316176317176318176319176320176321176322176323176324176325176326176327176328176329176330176331176332176333176334176335176336176337176338176339176340176341176342176343176344176345176346176347176348176349176350176351176352176353176354176355176356176357176358176359176360176361176362176363176364176365176366176367176368176369176370176371176372176373176374176375176376176377176378176379176380176381176382176383176384176385176386176387176388176389176390176391176392176393176394176395176396176397176398176399176400176401176402176403176404176405176406176407176408176409176410176411176412176413176414176415176416176417176418176419176420176421176422176423176424176425176426176427176428176429176430176431176432176433176434176435176436176437176438176439176440176441176442176443176444176445176446176447176448176449176450176451176452176453176454176455176456176457176458176459176460176461176462176463176464176465176466176467176468176469176470176471176472176473176474176475176476176477176478176479176480176481176482176483176484176485176486176487176488176489176490176491176492176493176494176495176496176497176498176499176500176501176502176503176504176505176506176507176508176509176510176511176512176513176514176515176516176517176518176519176520176521176522176523176524176525176526176527176528176529176530176531176532176533176534176535176536176537176538176539176540176541176542176543176544176545176546176547176548176549176550176551176552176553176554176555176556176557176558176559176560176561176562176563176564176565176566176567176568176569176570176571176572176573176574176575176576176577176578176579176580176581176582176583176584176585176586176587176588176589176590176591176592176593176594176595176596176597176598176599176600176601176602176603176604176605176606176607176608176609176610176611176612176613176614176615176616176617176618176619176620176621176622176623176624176625176626176627176628176629176630176631176632176633176634176635176636176637176638176639176640176641176642176643176644176645176646176647176648176649176650176651176652176653176654176655176656176657176658176659176660176661176662176663176664176665176666176667176668176669176670176671176672176673176674176675176676176677176678176679176680176681176682176683176684176685176686176687176688176689176690176691176692176693176694176695176696176697176698176699176700176701176702176703176704176705176706176707176708176709176710176711176712176713176714176715176716176717176718176719176720176721176722176723176724176725176726176727176728176729176730176731176732176733176734176735176736176737176738176739176740176741176742176743176744176745176746176747176748176749176750176751176752176753176754176755176756176757176758176759176760176761176762176763176764176765176766176767176768176769176770176771176772176773176774176775176776176777176778176779176780176781176782176783176784176785176786176787176788176789176790176791176792176793176794176795176796176797176798176799176800176801176802176803176804176805176806176807176808176809176810176811176812176813176814176815176816176817176818176819176820176821176822176823176824176825176826176827176828176829176830176831176832176833176834176835176836176837176838176839176840176841176842176843176844176845176846176847176848176849176850176851176852176853176854176855176856176857176858176859176860176861176862176863176864176865176866176867176868176869176870176871176872176873176874176875176876176877176878176879176880176881176882176883176884176885176886176887176888176889176890176891176892176893176894176895176896176897176898176899176900176901176902176903176904176905176906176907176908176909176910176911176912176913176914176915176916176917176918176919176920176921176922176923176924176925176926176927176928176929176930176931176932176933176934176935176936176937176938176939176940176941176942176943176944176945176946176947176948176949176950176951176952176953176954176955176956176957176958176959176960176961176962176963176964176965176966176967176968176969176970176971176972176973176974176975176976176977176978176979176980176981176982176983176984176985176986176987176988176989176990176991176992176993176994176995176996176997176998176999177000177001177002177003177004177005177006177007177008177009177010177011177012177013177014177015177016177017177018177019177020177021177022177023177024177025177026177027177028177029177030177031177032177033177034177035177036177037177038177039177040177041177042177043177044177045177046177047177048177049177050177051177052177053177054177055177056177057177058177059177060177061177062177063177064177065177066177067177068177069177070177071177072177073177074177075177076177077177078177079177080177081177082177083177084177085177086177087177088177089177090177091177092177093177094177095177096177097177098177099177100177101177102177103177104177105177106177107177108177109177110177111177112177113177114177115177116177117177118177119177120177121177122177123177124177125177126177127177128177129177130177131177132177133177134177135177136177137177138177139177140177141177142177143177144177145177146177147177148177149177150177151177152177153177154177155177156177157177158177159177160177161177162177163177164177165177166177167177168177169177170177171177172177173177174177175177176177177177178177179177180177181177182177183177184177185177186177187177188177189177190177191177192177193177194177195177196177197177198177199177200177201177202177203177204177205177206177207177208177209177210177211177212177213177214177215177216177217177218177219177220177221177222177223177224177225177226177227177228177229177230177231177232177233177234177235177236177237177238177239177240177241177242177243177244177245177246177247177248177249177250177251177252177253177254177255177256177257177258177259177260177261177262177263177264177265177266177267177268177269177270177271177272177273177274177275177276177277177278177279177280177281177282177283177284177285177286177287177288177289177290177291177292177293177294177295177296177297177298177299177300177301177302177303177304177305177306177307177308177309177310177311177312177313177314177315177316177317177318177319177320177321177322177323177324177325177326177327177328177329177330177331177332177333177334177335177336177337177338177339177340177341177342177343177344177345177346177347177348177349177350177351177352177353177354177355177356177357177358177359177360177361177362177363177364177365177366177367177368177369177370177371177372177373177374177375177376177377177378177379177380177381177382177383177384177385177386177387177388177389177390177391177392177393177394177395177396177397177398177399177400177401177402177403177404177405177406177407177408177409177410177411177412177413177414177415177416177417177418177419177420177421177422177423177424177425177426177427177428177429177430177431177432177433177434177435177436177437177438177439177440177441177442177443177444177445177446177447177448177449177450177451177452177453177454177455177456177457177458177459177460177461177462177463177464177465177466177467177468177469177470177471177472177473177474177475177476177477177478177479177480177481177482177483177484177485177486177487177488177489177490177491177492177493177494177495177496177497177498177499177500177501177502177503177504177505177506177507177508177509177510177511177512177513177514177515177516177517177518177519177520177521177522177523177524177525177526177527177528177529177530177531177532177533177534177535177536177537177538177539177540177541177542177543177544177545177546177547177548177549177550177551177552177553177554177555177556177557177558177559177560177561177562177563177564177565177566177567177568177569177570177571177572177573177574177575177576177577177578177579177580177581177582177583177584177585177586177587177588177589177590177591177592177593177594177595177596177597177598177599177600177601177602177603177604177605177606177607177608177609177610177611177612177613177614177615177616177617177618177619177620177621177622177623177624177625177626177627177628177629177630177631177632177633177634177635177636177637177638177639177640177641177642177643177644177645177646177647177648177649177650177651177652177653177654177655177656177657177658177659177660177661177662177663177664177665177666177667177668177669177670177671177672177673177674177675177676177677177678177679177680177681177682177683177684177685177686177687177688177689177690177691177692177693177694177695177696177697177698177699177700177701177702177703177704177705177706177707177708177709177710177711177712177713177714177715177716177717177718177719177720177721177722177723177724177725177726177727177728177729177730177731177732177733177734177735177736177737177738177739177740177741177742177743177744177745177746177747177748177749177750177751177752177753177754177755177756177757177758177759177760177761177762177763177764177765177766177767177768177769177770177771177772177773177774177775177776177777177778177779177780177781177782177783177784177785177786177787177788177789177790177791177792177793177794177795177796177797177798177799177800177801177802177803177804177805177806177807177808177809177810177811177812177813177814177815177816177817177818177819177820177821177822177823177824177825177826177827177828177829177830177831177832177833177834177835177836177837177838177839177840177841177842177843177844177845177846177847177848177849177850177851177852177853177854177855177856177857177858177859177860177861177862177863177864177865177866177867177868177869177870177871177872177873177874177875177876177877177878177879177880177881177882177883177884177885177886177887177888177889177890177891177892177893177894177895177896177897177898177899177900177901177902177903177904177905177906177907177908177909177910177911177912177913177914177915177916177917177918177919177920177921177922177923177924177925177926177927177928177929177930177931177932177933177934177935177936177937177938177939177940177941177942177943177944177945177946177947177948177949177950177951177952177953177954177955177956177957177958177959177960177961177962177963177964177965177966177967177968177969177970177971177972177973177974177975177976177977177978177979177980177981177982177983177984177985177986177987177988177989177990177991177992177993177994177995177996177997177998177999178000178001178002178003178004178005178006178007178008178009178010178011178012178013178014178015178016178017178018178019178020178021178022178023178024178025178026178027178028178029178030178031178032178033178034178035178036178037178038178039178040178041178042178043178044178045178046178047178048178049178050178051178052178053178054178055178056178057178058178059178060178061178062178063178064178065178066178067178068178069178070178071178072178073178074178075178076178077178078178079178080178081178082178083178084178085178086178087178088178089178090178091178092178093178094178095178096178097178098178099178100178101178102178103178104178105178106178107178108178109178110178111178112178113178114178115178116178117178118178119178120178121178122178123178124178125178126178127178128178129178130178131178132178133178134178135178136178137178138178139178140178141178142178143178144178145178146178147178148178149178150178151178152178153178154178155178156178157178158178159178160178161178162178163178164178165178166178167178168178169178170178171178172178173178174178175178176178177178178178179178180178181178182178183178184178185178186178187178188178189178190178191178192178193178194178195178196178197178198178199178200178201178202178203178204178205178206178207178208178209178210178211178212178213178214178215178216178217178218178219178220178221178222178223178224178225178226178227178228178229178230178231178232178233178234178235178236178237178238178239178240178241178242178243178244178245178246178247178248178249178250178251178252178253178254178255178256178257178258178259178260178261178262178263178264178265178266178267178268178269178270178271178272178273178274178275178276178277178278178279178280178281178282178283178284178285178286178287178288178289178290178291178292178293178294178295178296178297178298178299178300178301178302178303178304178305178306178307178308178309178310178311178312178313178314178315178316178317178318178319178320178321178322178323178324178325178326178327178328178329178330178331178332178333178334178335178336178337178338178339178340178341178342178343178344178345178346178347178348178349178350178351178352178353178354178355178356178357178358178359178360178361178362178363178364178365178366178367178368178369178370178371178372178373178374178375178376178377178378178379178380178381178382178383178384178385178386178387178388178389178390178391178392178393178394178395178396178397178398178399178400178401178402178403178404178405178406178407178408178409178410178411178412178413178414178415178416178417178418178419178420178421178422178423178424178425178426178427178428178429178430178431178432178433178434178435178436178437178438178439178440178441178442178443178444178445178446178447178448178449178450178451178452178453178454178455178456178457178458178459178460178461178462178463178464178465178466178467178468178469178470178471178472178473178474178475178476178477178478178479178480178481178482178483178484178485178486178487178488178489178490178491178492178493178494178495178496178497178498178499178500178501178502178503178504178505178506178507178508178509178510178511178512178513178514178515178516178517178518178519178520178521178522178523178524178525178526178527178528178529178530178531178532178533178534178535178536178537178538178539178540178541178542178543178544178545178546178547178548178549178550178551178552178553178554178555178556178557178558178559178560178561178562178563178564178565178566178567178568178569178570178571178572178573178574178575178576178577178578178579178580178581178582178583178584178585178586178587178588178589178590178591178592178593178594178595178596178597178598178599178600178601178602178603178604178605178606178607178608178609178610178611178612178613178614178615178616178617178618178619178620178621178622178623178624178625178626178627178628178629178630178631178632178633178634178635178636178637178638178639178640178641178642178643178644178645178646178647178648178649178650178651178652178653178654178655178656178657178658178659178660178661178662178663178664178665178666178667178668178669178670178671178672178673178674178675178676178677178678178679178680178681178682178683178684178685178686178687178688178689178690178691178692178693178694178695178696178697178698178699178700178701178702178703178704178705178706178707178708178709178710178711178712178713178714178715178716178717178718178719178720178721178722178723178724178725178726178727178728178729178730178731178732178733178734178735178736178737178738178739178740178741178742178743178744178745178746178747178748178749178750178751178752178753178754178755178756178757178758178759178760178761178762178763178764178765178766178767178768178769178770178771178772178773178774178775178776178777178778178779178780178781178782178783178784178785178786178787178788178789178790178791178792178793178794178795178796178797178798178799178800178801178802178803178804178805178806178807178808178809178810178811178812178813178814178815178816178817178818178819178820178821178822178823178824178825178826178827178828178829178830178831178832178833178834178835178836178837178838178839178840178841178842178843178844178845178846178847178848178849178850178851178852178853178854178855178856178857178858178859178860178861178862178863178864178865178866178867178868178869178870178871178872178873178874178875178876178877178878178879178880178881178882178883178884178885178886178887178888178889178890178891178892178893178894178895178896178897178898178899178900178901178902178903178904178905178906178907178908178909178910178911178912178913178914178915178916178917178918178919178920178921178922178923178924178925178926178927178928178929178930178931178932178933178934178935178936178937178938178939178940178941178942178943178944178945178946178947178948178949178950178951178952178953178954178955178956178957178958178959178960178961178962178963178964178965178966178967178968178969178970178971178972178973178974178975178976178977178978178979178980178981178982178983178984178985178986178987178988178989178990178991178992178993178994178995178996178997178998178999179000179001179002179003179004179005179006179007179008179009179010179011179012179013179014179015179016179017179018179019179020179021179022179023179024179025179026179027179028179029179030179031179032179033179034179035179036179037179038179039179040179041179042179043179044179045179046179047179048179049179050179051179052179053179054179055179056179057179058179059179060179061179062179063179064179065179066179067179068179069179070179071179072179073179074179075179076179077179078179079179080179081179082179083179084179085179086179087179088179089179090179091179092179093179094179095179096179097179098179099179100179101179102179103179104179105179106179107179108179109179110179111179112179113179114179115179116179117179118179119179120179121179122179123179124179125179126179127179128179129179130179131179132179133179134179135179136179137179138179139179140179141179142179143179144179145179146179147179148179149179150179151179152179153179154179155179156179157179158179159179160179161179162179163179164179165179166179167179168179169179170179171179172179173179174179175179176179177179178179179179180179181179182179183179184179185179186179187179188179189179190179191179192179193179194179195179196179197179198179199179200179201179202179203179204179205179206179207179208179209179210179211179212179213179214179215179216179217179218179219179220179221179222179223179224179225179226179227179228179229179230179231179232179233179234179235179236179237179238179239179240179241179242179243179244179245179246179247179248179249179250179251179252179253179254179255179256179257179258179259179260179261179262179263179264179265179266179267179268179269179270179271179272179273179274179275179276179277179278179279179280179281179282179283179284179285179286179287179288179289179290179291179292179293179294179295179296179297179298179299179300179301179302179303179304179305179306179307179308179309179310179311179312179313179314179315179316179317179318179319179320179321179322179323179324179325179326179327179328179329179330179331179332179333179334179335179336179337179338179339179340179341179342179343179344179345179346179347179348179349179350179351179352179353179354179355179356179357179358179359179360179361179362179363179364179365179366179367179368179369179370179371179372179373179374179375179376179377179378179379179380179381179382179383179384179385179386179387179388179389179390179391179392179393179394179395179396179397179398179399179400179401179402179403179404179405179406179407179408179409179410179411179412179413179414179415179416179417179418179419179420179421179422179423179424179425179426179427179428179429179430179431179432179433179434179435179436179437179438179439179440179441179442179443179444179445179446179447179448179449179450179451179452179453179454179455179456179457179458179459179460179461179462179463179464179465179466179467179468179469179470179471179472179473179474179475179476179477179478179479179480179481179482179483179484179485179486179487179488179489179490179491179492179493179494179495179496179497179498179499179500179501179502179503179504179505179506179507179508179509179510179511179512179513179514179515179516179517179518179519179520179521179522179523179524179525179526179527179528179529179530179531179532179533179534179535179536179537179538179539179540179541179542179543179544179545179546179547179548179549179550179551179552179553179554179555179556179557179558179559179560179561179562179563179564179565179566179567179568179569179570179571179572179573179574179575179576179577179578179579179580179581179582179583179584179585179586179587179588179589179590179591179592179593179594179595179596179597179598179599179600179601179602179603179604179605179606179607179608179609179610179611179612179613179614179615179616179617179618179619179620179621179622179623179624179625179626179627179628179629179630179631179632179633179634179635179636179637179638179639179640179641179642179643179644179645179646179647179648179649179650179651179652179653179654179655179656179657179658179659179660179661179662179663179664179665179666179667179668179669179670179671179672179673179674179675179676179677179678179679179680179681179682179683179684179685179686179687179688179689179690179691179692179693179694179695179696179697179698179699179700179701179702179703179704179705179706179707179708179709179710179711179712179713179714179715179716179717179718179719179720179721179722179723179724179725179726179727179728179729179730179731179732179733179734179735179736179737179738179739179740179741179742179743179744179745179746179747179748179749179750179751179752179753179754179755179756179757179758179759179760179761179762179763179764179765179766179767179768179769179770179771179772179773179774179775179776179777179778179779179780179781179782179783179784179785179786179787179788179789179790179791179792179793179794179795179796179797179798179799179800179801179802179803179804179805179806179807179808179809179810179811179812179813179814179815179816179817179818179819179820179821179822179823179824179825179826179827179828179829179830179831179832179833179834179835179836179837179838179839179840179841179842179843179844179845179846179847179848179849179850179851179852179853179854179855179856179857179858179859179860179861179862179863179864179865179866179867179868179869179870179871179872179873179874179875179876179877179878179879179880179881179882179883179884179885179886179887179888179889179890179891179892179893179894179895179896179897179898179899179900179901179902179903179904179905179906179907179908179909179910179911179912179913179914179915179916179917179918179919179920179921179922179923179924179925179926179927179928179929179930179931179932179933179934179935179936179937179938179939179940179941179942179943179944179945179946179947179948179949179950179951179952179953179954179955179956179957179958179959179960179961179962179963179964179965179966179967179968179969179970179971179972179973179974179975179976179977179978179979179980179981179982179983179984179985179986179987179988179989179990179991179992179993179994179995179996179997179998179999180000180001180002180003180004180005180006180007180008180009180010180011180012180013180014180015180016180017180018180019180020180021180022180023180024180025180026180027180028180029180030180031180032180033180034180035180036180037180038180039180040180041180042180043180044180045180046180047180048180049180050180051180052180053180054180055180056180057180058180059180060180061180062180063180064180065180066180067180068180069180070180071180072180073180074180075180076180077180078180079180080180081180082180083180084180085180086180087180088180089180090180091180092180093180094180095180096180097180098180099180100180101180102180103180104180105180106180107180108180109180110180111180112180113180114180115180116180117180118180119180120180121180122180123180124180125180126180127180128180129180130180131180132180133180134180135180136180137180138180139180140180141180142180143180144180145180146180147180148180149180150180151180152180153180154180155180156180157180158180159180160180161180162180163180164180165180166180167180168180169180170180171180172180173180174180175180176180177180178180179180180180181180182180183180184180185180186180187180188180189180190180191180192180193180194180195180196180197180198180199180200180201180202180203180204180205180206180207180208180209180210180211180212180213180214180215180216180217180218180219180220180221180222180223180224180225180226180227180228180229180230180231180232180233180234180235180236180237180238180239180240180241180242180243180244180245180246180247180248180249180250180251180252180253180254180255180256180257180258180259180260180261180262180263180264180265180266180267180268180269180270180271180272180273180274180275180276180277180278180279180280180281180282180283180284180285180286180287180288180289180290180291180292180293180294180295180296180297180298180299180300180301180302180303180304180305180306180307180308180309180310180311180312180313180314180315180316180317180318180319180320180321180322180323180324180325180326180327180328180329180330180331180332180333180334180335180336180337180338180339180340180341180342180343180344180345180346180347180348180349180350180351180352180353180354180355180356180357180358180359180360180361180362180363180364180365180366180367180368180369180370180371180372180373180374180375180376180377180378180379180380180381180382180383180384180385180386180387180388180389180390180391180392180393180394180395180396180397180398180399180400180401180402180403180404180405180406180407180408180409180410180411180412180413180414180415180416180417180418180419180420180421180422180423180424180425180426180427180428180429180430180431180432180433180434180435180436180437180438180439180440180441180442180443180444180445180446180447180448180449180450180451180452180453180454180455180456180457180458180459180460180461180462180463180464180465180466180467180468180469180470180471180472180473180474180475180476180477180478180479180480180481180482180483180484180485180486180487180488180489180490180491180492180493180494180495180496180497180498180499180500180501180502180503180504180505180506180507180508180509180510180511180512180513180514180515180516180517180518180519180520180521180522180523180524180525180526180527180528180529180530180531180532180533180534180535180536180537180538180539180540180541180542180543180544180545180546180547180548180549180550180551180552180553180554180555180556180557180558180559180560180561180562180563180564180565180566180567180568180569180570180571180572180573180574180575180576180577180578180579180580180581180582180583180584180585180586180587180588180589180590180591180592180593180594180595180596180597180598180599180600180601180602180603180604180605180606180607180608180609180610180611180612180613180614180615180616180617180618180619180620180621180622180623180624180625180626180627180628180629180630180631180632180633180634180635180636180637180638180639180640180641180642180643180644180645180646180647180648180649180650180651180652180653180654180655180656180657180658180659180660180661180662180663180664180665180666180667180668180669180670180671180672180673180674180675180676180677180678180679180680180681180682180683180684180685180686180687180688180689180690180691180692180693180694180695180696180697180698180699180700180701180702180703180704180705180706180707180708180709180710180711180712180713180714180715180716180717180718180719180720180721180722180723180724180725180726180727180728180729180730180731180732180733180734180735180736180737180738180739180740180741180742180743180744180745180746180747180748180749180750180751180752180753180754180755180756180757180758180759180760180761180762180763180764180765180766180767180768180769180770180771180772180773180774180775180776180777180778180779180780180781180782180783180784180785180786180787180788180789180790180791180792180793180794180795180796180797180798180799180800180801180802180803180804180805180806180807180808180809180810180811180812180813180814180815180816180817180818180819180820180821180822180823180824180825180826180827180828180829180830180831180832180833180834180835180836180837180838180839180840180841180842180843180844180845180846180847180848180849180850180851180852180853180854180855180856180857180858180859180860180861180862180863180864180865180866180867180868180869180870180871180872180873180874180875180876180877180878180879180880180881180882180883180884180885180886180887180888180889180890180891180892180893180894180895180896180897180898180899180900180901180902180903180904180905180906180907180908180909180910180911180912180913180914180915180916180917180918180919180920180921180922180923180924180925180926180927180928180929180930180931180932180933180934180935180936180937180938180939180940180941180942180943180944180945180946180947180948180949180950180951180952180953180954180955180956180957180958180959180960180961180962180963180964180965180966180967180968180969180970180971180972180973180974180975180976180977180978180979180980180981180982180983180984180985180986180987180988180989180990180991180992180993180994180995180996180997180998180999181000181001181002181003181004181005181006181007181008181009181010181011181012181013181014181015181016181017181018181019181020181021181022181023181024181025181026181027181028181029181030181031181032181033181034181035181036181037181038181039181040181041181042181043181044181045181046181047181048181049181050181051181052181053181054181055181056181057181058181059181060181061181062181063181064181065181066181067181068181069181070181071181072181073181074181075181076181077181078181079181080181081181082181083181084181085181086181087181088181089181090181091181092181093181094181095181096181097181098181099181100181101181102181103181104181105181106181107181108181109181110181111181112181113181114181115181116181117181118181119181120181121181122181123181124181125181126181127181128181129181130181131181132181133181134181135181136181137181138181139181140181141181142181143181144181145181146181147181148181149181150181151181152181153181154181155181156181157181158181159181160181161181162181163181164181165181166181167181168181169181170181171181172181173181174181175181176181177181178181179181180181181181182181183181184181185181186181187181188181189181190181191181192181193181194181195181196181197181198181199181200181201181202181203181204181205181206181207181208181209181210181211181212181213181214181215181216181217181218181219181220181221181222181223181224181225181226181227181228181229181230181231181232181233181234181235181236181237181238181239181240181241181242181243181244181245181246181247181248181249181250181251181252181253181254181255181256181257181258181259181260181261181262181263181264181265181266181267181268181269181270181271181272181273181274181275181276181277181278181279181280181281181282181283181284181285181286181287181288181289181290181291181292181293181294181295181296181297181298181299181300181301181302181303181304181305181306181307181308181309181310181311181312181313181314181315181316181317181318181319181320181321181322181323181324181325181326181327181328181329181330181331181332181333181334181335181336181337181338181339181340181341181342181343181344181345181346181347181348181349181350181351181352181353181354181355181356181357181358181359181360181361181362181363181364181365181366181367181368181369181370181371181372181373181374181375181376181377181378181379181380181381181382181383181384181385181386181387181388181389181390181391181392181393181394181395181396181397181398181399181400181401181402181403181404181405181406181407181408181409181410181411181412181413181414181415181416181417181418181419181420181421181422181423181424181425181426181427181428181429181430181431181432181433181434181435181436181437181438181439181440181441181442181443181444181445181446181447181448181449181450181451181452181453181454181455181456181457181458181459181460181461181462181463181464181465181466181467181468181469181470181471181472181473181474181475181476181477181478181479181480181481181482181483181484181485181486181487181488181489181490181491181492181493181494181495181496181497181498181499181500181501181502181503181504181505181506181507181508181509181510181511181512181513181514181515181516181517181518181519181520181521181522181523181524181525181526181527181528181529181530181531181532181533181534181535181536181537181538181539181540181541181542181543181544181545181546181547181548181549181550181551181552181553181554181555181556181557181558181559181560181561181562181563181564181565181566181567181568181569181570181571181572181573181574181575181576181577181578181579181580181581181582181583181584181585181586181587181588181589181590181591181592181593181594181595181596181597181598181599181600181601181602181603181604181605181606181607181608181609181610181611181612181613181614181615181616181617181618181619181620181621181622181623181624181625181626181627181628181629181630181631181632181633181634181635181636181637181638181639181640181641181642181643181644181645181646181647181648181649181650181651181652181653181654181655181656181657181658181659181660181661181662181663181664181665181666181667181668181669181670181671181672181673181674181675181676181677181678181679181680181681181682181683181684181685181686181687181688181689181690181691181692181693181694181695181696181697181698181699181700181701181702181703181704181705181706181707181708181709181710181711181712181713181714181715181716181717181718181719181720181721181722181723181724181725181726181727181728181729181730181731181732181733181734181735181736181737181738181739181740181741181742181743181744181745181746181747181748181749181750181751181752181753181754181755181756181757181758181759181760181761181762181763181764181765181766181767181768181769181770181771181772181773181774181775181776181777181778181779181780181781181782181783181784181785181786181787181788181789181790181791181792181793181794181795181796181797181798181799181800181801181802181803181804181805181806181807181808181809181810181811181812181813181814181815181816181817181818181819181820181821181822181823181824181825181826181827181828181829181830181831181832181833181834181835181836181837181838181839181840181841181842181843181844181845181846181847181848181849181850181851181852181853181854181855181856181857181858181859181860181861181862181863181864181865181866181867181868181869181870181871181872181873181874181875181876181877181878181879181880181881181882181883181884181885181886181887181888181889181890181891181892181893181894181895181896181897181898181899181900181901181902181903181904181905181906181907181908181909181910181911181912181913181914181915181916181917181918181919181920181921181922181923181924181925181926181927181928181929181930181931181932181933181934181935181936181937181938181939181940181941181942181943181944181945181946181947181948181949181950181951181952181953181954181955181956181957181958181959181960181961181962181963181964181965181966181967181968181969181970181971181972181973181974181975181976181977181978181979181980181981181982181983181984181985181986181987181988181989181990181991181992181993181994181995181996181997181998181999182000182001182002182003182004182005182006182007182008182009182010182011182012182013182014182015182016182017182018182019182020182021182022182023182024182025182026182027182028182029182030182031182032182033182034182035182036182037182038182039182040182041182042182043182044182045182046182047182048182049182050182051182052182053182054182055182056182057182058182059182060182061182062182063182064182065182066182067182068182069182070182071182072182073182074182075182076182077182078182079182080182081182082182083182084182085182086182087182088182089182090182091182092182093182094182095182096182097182098182099182100182101182102182103182104182105182106182107182108182109182110182111182112182113182114182115182116182117182118182119182120182121182122182123182124182125182126182127182128182129182130182131182132182133182134182135182136182137182138182139182140182141182142182143182144182145182146182147182148182149182150182151182152182153182154182155182156182157182158182159182160182161182162182163182164182165182166182167182168182169182170182171182172182173182174182175182176182177182178182179182180182181182182182183182184182185182186182187182188182189182190182191182192182193182194182195182196182197182198182199182200182201182202182203182204182205182206182207182208182209182210182211182212182213182214182215182216182217182218182219182220182221182222182223182224182225182226182227182228182229182230182231182232182233182234182235182236182237182238182239182240182241182242182243182244182245182246182247182248182249182250182251182252182253182254182255182256182257182258182259182260182261182262182263182264182265182266182267182268182269182270182271182272182273182274182275182276182277182278182279182280182281182282182283182284182285182286182287182288182289182290182291182292182293182294182295182296182297182298182299182300182301182302182303182304182305182306182307182308182309182310182311182312182313182314182315182316182317182318182319182320182321182322182323182324182325182326182327182328182329182330182331182332182333182334182335182336182337182338182339182340182341182342182343182344182345182346182347182348182349182350182351182352182353182354182355182356182357182358182359182360182361182362182363182364182365182366182367182368182369182370182371182372182373182374182375182376182377182378182379182380182381182382182383182384182385182386182387182388182389182390182391182392182393182394182395182396182397182398182399182400182401182402182403182404182405182406182407182408182409182410182411182412182413182414182415182416182417182418182419182420182421182422182423182424182425182426182427182428182429182430182431182432182433182434182435182436182437182438182439182440182441182442182443182444182445182446182447182448182449182450182451182452182453182454182455182456182457182458182459182460182461182462182463182464182465182466182467182468182469182470182471182472182473182474182475182476182477182478182479182480182481182482182483182484182485182486182487182488182489182490182491182492182493182494182495182496182497182498182499182500182501182502182503182504182505182506182507182508182509182510182511182512182513182514182515182516182517182518182519182520182521182522182523182524182525182526182527182528182529182530182531182532182533182534182535182536182537182538182539182540182541182542182543182544182545182546182547182548182549182550182551182552182553182554182555182556182557182558182559182560182561182562182563182564182565182566182567182568182569182570182571182572182573182574182575182576182577182578182579182580182581182582182583182584182585182586182587182588182589182590182591182592182593182594182595182596182597182598182599182600182601182602182603182604182605182606182607182608182609182610182611182612182613182614182615182616182617182618182619182620182621182622182623182624182625182626182627182628182629182630182631182632182633182634182635182636182637182638182639182640182641182642182643182644182645182646182647182648182649182650182651182652182653182654182655182656182657182658182659182660182661182662182663182664182665182666182667182668182669182670182671182672182673182674182675182676182677182678182679182680182681182682182683182684182685182686182687182688182689182690182691182692182693182694182695182696182697182698182699182700182701182702182703182704182705182706182707182708182709182710182711182712182713182714182715182716182717182718182719182720182721182722182723182724182725182726182727182728182729182730182731182732182733182734182735182736182737182738182739182740182741182742182743182744182745182746182747182748182749182750182751182752182753182754182755182756182757182758182759182760182761182762182763182764182765182766182767182768182769182770182771182772182773182774182775182776182777182778182779182780182781182782182783182784182785182786182787182788182789182790182791182792182793182794182795182796182797182798182799182800182801182802182803182804182805182806182807182808182809182810182811182812182813182814182815182816182817182818182819182820182821182822182823182824182825182826182827182828182829182830182831182832182833182834182835182836182837182838182839182840182841182842182843182844182845182846182847182848182849182850182851182852182853182854182855182856182857182858182859182860182861182862182863182864182865182866182867182868182869182870182871182872182873182874182875182876182877182878182879182880182881182882182883182884182885182886182887182888182889182890182891182892182893182894182895182896182897182898182899182900182901182902182903182904182905182906182907182908182909182910182911182912182913182914182915182916182917182918182919182920182921182922182923182924182925182926182927182928182929182930182931182932182933182934182935182936182937182938182939182940182941182942182943182944182945182946182947182948182949182950182951182952182953182954182955182956182957182958182959182960182961182962182963182964182965182966182967182968182969182970182971182972182973182974182975182976182977182978182979182980182981182982182983182984182985182986182987182988182989182990182991182992182993182994182995182996182997182998182999183000183001183002183003183004183005183006183007183008183009183010183011183012183013183014183015183016183017183018183019183020183021183022183023183024183025183026183027183028183029183030183031183032183033183034183035183036183037183038183039183040183041183042183043183044183045183046183047183048183049183050183051183052183053183054183055183056183057183058183059183060183061183062183063183064183065183066183067183068183069183070183071183072183073183074183075183076183077183078183079183080183081183082183083183084183085183086183087183088183089183090183091183092183093183094183095183096183097183098183099183100183101183102183103183104183105183106183107183108183109183110183111183112183113183114183115183116183117183118183119183120183121183122183123183124183125183126183127183128183129183130183131183132183133183134183135183136183137183138183139183140183141183142183143183144183145183146183147183148183149183150183151183152183153183154183155183156183157183158183159183160183161183162183163183164183165183166183167183168183169183170183171183172183173183174183175183176183177183178183179183180183181183182183183183184183185183186183187183188183189183190183191183192183193183194183195183196183197183198183199183200183201183202183203183204183205183206183207183208183209183210183211183212183213183214183215183216183217183218183219183220183221183222183223183224183225183226183227183228183229183230183231183232183233183234183235183236183237183238183239183240183241183242183243183244183245183246183247183248183249183250183251183252183253183254183255183256183257183258183259183260183261183262183263183264183265183266183267183268183269183270183271183272183273183274183275183276183277183278183279183280183281183282183283183284183285183286183287183288183289183290183291183292183293183294183295183296183297183298183299183300183301183302183303183304183305183306183307183308183309183310183311183312183313183314183315183316183317183318183319183320183321183322183323183324183325183326183327183328183329183330183331183332183333183334183335183336183337183338183339183340183341183342183343183344183345183346183347183348183349183350183351183352183353183354183355183356183357183358183359183360183361183362183363183364183365183366183367183368183369183370183371183372183373183374183375183376183377183378183379183380183381183382183383183384183385183386183387183388183389183390183391183392183393183394183395183396183397183398183399183400183401183402183403183404183405183406183407183408183409183410183411183412183413183414183415183416183417183418183419183420183421183422183423183424183425183426183427183428183429183430183431183432183433183434183435183436183437183438183439183440183441183442183443183444183445183446183447183448183449183450183451183452183453183454183455183456183457183458183459183460183461183462183463183464183465183466183467183468183469183470183471183472183473183474183475183476183477183478183479183480183481183482183483183484183485183486183487183488183489183490183491183492183493183494183495183496183497183498183499183500183501183502183503183504183505183506183507183508183509183510183511183512183513183514183515183516183517183518183519183520183521183522183523183524183525183526183527183528183529183530183531183532183533183534183535183536183537183538183539183540183541183542183543183544183545183546183547183548183549183550183551183552183553183554183555183556183557183558183559183560183561183562183563183564183565183566183567183568183569183570183571183572183573183574183575183576183577183578183579183580183581183582183583183584183585183586183587183588183589183590183591183592183593183594183595183596183597183598183599183600183601183602183603183604183605183606183607183608183609183610183611183612183613183614183615183616183617183618183619183620183621183622183623183624183625183626183627183628183629183630183631183632183633183634183635183636183637183638183639183640183641183642183643183644183645183646183647183648183649183650183651183652183653183654183655183656183657183658183659183660183661183662183663183664183665183666183667183668183669183670183671183672183673183674183675183676183677183678183679183680183681183682183683183684183685183686183687183688183689183690183691183692183693183694183695183696183697183698183699183700183701183702183703183704183705183706183707183708183709183710183711183712183713183714183715183716183717183718183719183720183721183722183723183724183725183726183727183728183729183730183731183732183733183734183735183736183737183738183739183740183741183742183743183744183745183746183747183748183749183750183751183752183753183754183755183756183757183758183759183760183761183762183763183764183765183766183767183768183769183770183771183772183773183774183775183776183777183778183779183780183781183782183783183784183785183786183787183788183789183790183791183792183793183794183795183796183797183798183799183800183801183802183803183804183805183806183807183808183809183810183811183812183813183814183815183816183817183818183819183820183821183822183823183824183825183826183827183828183829183830183831183832183833183834183835183836183837183838183839183840183841183842183843183844183845183846183847183848183849183850183851183852183853183854183855183856183857183858183859183860183861183862183863183864183865183866183867183868183869183870183871183872183873183874183875183876183877183878183879183880183881183882183883183884183885183886183887183888183889183890183891183892183893183894183895183896183897183898183899183900183901183902183903183904183905183906183907183908183909183910183911183912183913183914183915183916183917183918183919183920183921183922183923183924183925183926183927183928183929183930183931183932183933183934183935183936183937183938183939183940183941183942183943183944183945183946183947183948183949183950183951183952183953183954183955183956183957183958183959183960183961183962183963183964183965183966183967183968183969183970183971183972183973183974183975183976183977183978183979183980183981183982183983183984183985183986183987183988183989183990183991183992183993183994183995183996183997183998183999184000184001184002184003184004184005184006184007184008184009184010184011184012184013184014184015184016184017184018184019184020184021184022184023184024184025184026184027184028184029184030184031184032184033184034184035184036184037184038184039184040184041184042184043184044184045184046184047184048184049184050184051184052184053184054184055184056184057184058184059184060184061184062184063184064184065184066184067184068184069184070184071184072184073184074184075184076184077184078184079184080184081184082184083184084184085184086184087184088184089184090184091184092184093184094184095184096184097184098184099184100184101184102184103184104184105184106184107184108184109184110184111184112184113184114184115184116184117184118184119184120184121184122184123184124184125184126184127184128184129184130184131184132184133184134184135184136184137184138184139184140184141184142184143184144184145184146184147184148184149184150184151184152184153184154184155184156184157184158184159184160184161184162184163184164184165184166184167184168184169184170184171184172184173184174184175184176184177184178184179184180184181184182184183184184184185184186184187184188184189184190184191184192184193184194184195184196184197184198184199184200184201184202184203184204184205184206184207184208184209184210184211184212184213184214184215184216184217184218184219184220184221184222184223184224184225184226184227184228184229184230184231184232184233184234184235184236184237184238184239184240184241184242184243184244184245184246184247184248184249184250184251184252184253184254184255184256184257184258184259184260184261184262184263184264184265184266184267184268184269184270184271184272184273184274184275184276184277184278184279184280184281184282184283184284184285184286184287184288184289184290184291184292184293184294184295184296184297184298184299184300184301184302184303184304184305184306184307184308184309184310184311184312184313184314184315184316184317184318184319184320184321184322184323184324184325184326184327184328184329184330184331184332184333184334184335184336184337184338184339184340184341184342184343184344184345184346184347184348184349184350184351184352184353184354184355184356184357184358184359184360184361184362184363184364184365184366184367184368184369184370184371184372184373184374184375184376184377184378184379184380184381184382184383184384184385184386184387184388184389184390184391184392184393184394184395184396184397184398184399184400184401184402184403184404184405184406184407184408184409184410184411184412184413184414184415184416184417184418184419184420184421184422184423184424184425184426184427184428184429184430184431184432184433184434184435184436184437184438184439184440184441184442184443184444184445184446184447184448184449184450184451184452184453184454184455184456184457184458184459184460184461184462184463184464184465184466184467184468184469184470184471184472184473184474184475184476184477184478184479184480184481184482184483184484184485184486184487184488184489184490184491184492184493184494184495184496184497184498184499184500184501184502184503184504184505184506184507184508184509184510184511184512184513184514184515184516184517184518184519184520184521184522184523184524184525184526184527184528184529184530184531184532184533184534184535184536184537184538184539184540184541184542184543184544184545184546184547184548184549184550184551184552184553184554184555184556184557184558184559184560184561184562184563184564184565184566184567184568184569184570184571184572184573184574184575184576184577184578184579184580184581184582184583184584184585184586184587184588184589184590184591184592184593184594184595184596184597184598184599184600184601184602184603184604184605184606184607184608184609184610184611184612184613184614184615184616184617184618184619184620184621184622184623184624184625184626184627184628184629184630184631184632184633184634184635184636184637184638184639184640184641184642184643184644184645184646184647184648184649184650184651184652184653184654184655184656184657184658184659184660184661184662184663184664184665184666184667184668184669184670184671184672184673184674184675184676184677184678184679184680184681184682184683184684184685184686184687184688184689184690184691184692184693184694184695184696184697184698184699184700184701184702184703184704184705184706184707184708184709184710184711184712184713184714184715184716184717184718184719184720184721184722184723184724184725184726184727184728184729184730184731184732184733184734184735184736184737184738184739184740184741184742184743184744184745184746184747184748184749184750184751184752184753184754184755184756184757184758184759184760184761184762184763184764184765184766184767184768184769184770184771184772184773184774184775184776184777184778184779184780184781184782184783184784184785184786184787184788184789184790184791184792184793184794184795184796184797184798184799184800184801184802184803184804184805184806184807184808184809184810184811184812184813184814184815184816184817184818184819184820184821184822184823184824184825184826184827184828184829184830184831184832184833184834184835184836184837184838184839184840184841184842184843184844184845184846184847184848184849184850184851184852184853184854184855184856184857184858184859184860184861184862184863184864184865184866184867184868184869184870184871184872184873184874184875184876184877184878184879184880184881184882184883184884184885184886184887184888184889184890184891184892184893184894184895184896184897184898184899184900184901184902184903184904184905184906184907184908184909184910184911184912184913184914184915184916184917184918184919184920184921184922184923184924184925184926184927184928184929184930184931184932184933184934184935184936184937184938184939184940184941184942184943184944184945184946184947184948184949184950184951184952184953184954184955184956184957184958184959184960184961184962184963184964184965184966184967184968184969184970184971184972184973184974184975184976184977184978184979184980184981184982184983184984184985184986184987184988184989184990184991184992184993184994184995184996184997184998184999185000185001185002185003185004185005185006185007185008185009185010185011185012185013185014185015185016185017185018185019185020185021185022185023185024185025185026185027185028185029185030185031185032185033185034185035185036185037185038185039185040185041185042185043185044185045185046185047185048185049185050185051185052185053185054185055185056185057185058185059185060185061185062185063185064185065185066185067185068185069185070185071185072185073185074185075185076185077185078185079185080185081185082185083185084185085185086185087185088185089185090185091185092185093185094185095185096185097185098185099185100185101185102185103185104185105185106185107185108185109185110185111185112185113185114185115185116185117185118185119185120185121185122185123185124185125185126185127185128185129185130185131185132185133185134185135185136185137185138185139185140185141185142185143185144185145185146185147185148185149185150185151185152185153185154185155185156185157185158185159185160185161185162185163185164185165185166185167185168185169185170185171185172185173185174185175185176185177185178185179185180185181185182185183185184185185185186185187185188185189185190185191185192185193185194185195185196185197185198185199185200185201185202185203185204185205185206185207185208185209185210185211185212185213185214185215185216185217185218185219185220185221185222185223185224185225185226185227185228185229185230185231185232185233185234185235185236185237185238185239185240185241185242185243185244185245185246185247185248185249185250185251185252185253185254185255185256185257185258185259185260185261185262185263185264185265185266185267185268185269185270185271185272185273185274185275185276185277185278185279185280185281185282185283185284185285185286185287185288185289185290185291185292185293185294185295185296185297185298185299185300185301185302185303185304185305185306185307185308185309185310185311185312185313185314185315185316185317185318185319185320185321185322185323185324185325185326185327185328185329185330185331185332185333185334185335185336185337185338185339185340185341185342185343185344185345185346185347185348185349185350185351185352185353185354185355185356185357185358185359185360185361185362185363185364185365185366185367185368185369185370185371185372185373185374185375185376185377185378185379185380185381185382185383185384185385185386185387185388185389185390185391185392185393185394185395185396185397185398185399185400185401185402185403185404185405185406185407185408185409185410185411185412185413185414185415185416185417185418185419185420185421185422185423185424185425185426185427185428185429185430185431185432185433185434185435185436185437185438185439185440185441185442185443185444185445185446185447185448185449185450185451185452185453185454185455185456185457185458185459185460185461185462185463185464185465185466185467185468185469185470185471185472185473185474185475185476185477185478185479185480185481185482185483185484185485185486185487185488185489185490185491185492185493185494185495185496185497185498185499185500185501185502185503185504185505185506185507185508185509185510185511185512185513185514185515185516185517185518185519185520185521185522185523185524185525185526185527185528185529185530185531185532185533185534185535185536185537185538185539185540185541185542185543185544185545185546185547185548185549185550185551185552185553185554185555185556185557185558185559185560185561185562185563185564185565185566185567185568185569185570185571185572185573185574185575185576185577185578185579185580185581185582185583185584185585185586185587185588185589185590185591185592185593185594185595185596185597185598185599185600185601185602185603185604185605185606185607185608185609185610185611185612185613185614185615185616185617185618185619185620185621185622185623185624185625185626185627185628185629185630185631185632185633185634185635185636185637185638185639185640185641185642185643185644185645185646185647185648185649185650185651185652185653185654185655185656185657185658185659185660185661185662185663185664185665185666185667185668185669185670185671185672185673185674185675185676185677185678185679185680185681185682185683185684185685185686185687185688185689185690185691185692185693185694185695185696185697185698185699185700185701185702185703185704185705185706185707185708185709185710185711185712185713185714185715185716185717185718185719185720185721185722185723185724185725185726185727185728185729185730185731185732185733185734185735185736185737185738185739185740185741185742185743185744185745185746185747185748185749185750185751185752185753185754185755185756185757185758185759185760185761185762185763185764185765185766185767185768185769185770185771185772185773185774185775185776185777185778185779185780185781185782185783185784185785185786185787185788185789185790185791185792185793185794185795185796185797185798185799185800185801185802185803185804185805185806185807185808185809185810185811185812185813185814185815185816185817185818185819185820185821185822185823185824185825185826185827185828185829185830185831185832185833185834185835185836185837185838185839185840185841185842185843185844185845185846185847185848185849185850185851185852185853185854185855185856185857185858185859185860185861185862185863185864185865185866185867185868185869185870185871185872185873185874185875185876185877185878185879185880185881185882185883185884185885185886185887185888185889185890185891185892185893185894185895185896185897185898185899185900185901185902185903185904185905185906185907185908185909185910185911185912185913185914185915185916185917185918185919185920185921185922185923185924185925185926185927185928185929185930185931185932185933185934185935185936185937185938185939185940185941185942185943185944185945185946185947185948185949185950185951185952185953185954185955185956185957185958185959185960185961185962185963185964185965185966185967185968185969185970185971185972185973185974185975185976185977185978185979185980185981185982185983185984185985185986185987185988185989185990185991185992185993185994185995185996185997185998185999186000186001186002186003186004186005186006186007186008186009186010186011186012186013186014186015186016186017186018186019186020186021186022186023186024186025186026186027186028186029186030186031186032186033186034186035186036186037186038186039186040186041186042186043186044186045186046186047186048186049186050186051186052186053186054186055186056186057186058186059186060186061186062186063186064186065186066186067186068186069186070186071186072186073186074186075186076186077186078186079186080186081186082186083186084186085186086186087186088186089186090186091186092186093186094186095186096186097186098186099186100186101186102186103186104186105186106186107186108186109186110186111186112186113186114186115186116186117186118186119186120186121186122186123186124186125186126186127186128186129186130186131186132186133186134186135186136186137186138186139186140186141186142186143186144186145186146186147186148186149186150186151186152186153186154186155186156186157186158186159186160186161186162186163186164186165186166186167186168186169186170186171186172186173186174186175186176186177186178186179186180186181186182186183186184186185186186186187186188186189186190186191186192186193186194186195186196186197186198186199186200186201186202186203186204186205186206186207186208186209186210186211186212186213186214186215186216186217186218186219186220186221186222186223186224186225186226186227186228186229186230186231186232186233186234186235186236186237186238186239186240186241186242186243186244186245186246186247186248186249186250186251186252186253186254186255186256186257186258186259186260186261186262186263186264186265186266186267186268186269186270186271186272186273186274186275186276186277186278186279186280186281186282186283186284186285186286186287186288186289186290186291186292186293186294186295186296186297186298186299186300186301186302186303186304186305186306186307186308186309186310186311186312186313186314186315186316186317186318186319186320186321186322186323186324186325186326186327186328186329186330186331186332186333186334186335186336186337186338186339186340186341186342186343186344186345186346186347186348186349186350186351186352186353186354186355186356186357186358186359186360186361186362186363186364186365186366186367186368186369186370186371186372186373186374186375186376186377186378186379186380186381186382186383186384186385186386186387186388186389186390186391186392186393186394186395186396186397186398186399186400186401186402186403186404186405186406186407186408186409186410186411186412186413186414186415186416186417186418186419186420186421186422186423186424186425186426186427186428186429186430186431186432186433186434186435186436186437186438186439186440186441186442186443186444186445186446186447186448186449186450186451186452186453186454186455186456186457186458186459186460186461186462186463186464186465186466186467186468186469186470186471186472186473186474186475186476186477186478186479186480186481186482186483186484186485186486186487186488186489186490186491186492186493186494186495186496186497186498186499186500186501186502186503186504186505186506186507186508186509186510186511186512186513186514186515186516186517186518186519186520186521186522186523186524186525186526186527186528186529186530186531186532186533186534186535186536186537186538186539186540186541186542186543186544186545186546186547186548186549186550186551186552186553186554186555186556186557186558186559186560186561186562186563186564186565186566186567186568186569186570186571186572186573186574186575186576186577186578186579186580186581186582186583186584186585186586186587186588186589186590186591186592186593186594186595186596186597186598186599186600186601186602186603186604186605186606186607186608186609186610186611186612186613186614186615186616186617186618186619186620186621186622186623186624186625186626186627186628186629186630186631186632186633186634186635186636186637186638186639186640186641186642186643186644186645186646186647186648186649186650186651186652186653186654186655186656186657186658186659186660186661186662186663186664186665186666186667186668186669186670186671186672186673186674186675186676186677186678186679186680186681186682186683186684186685186686186687186688186689186690186691186692186693186694186695186696186697186698186699186700186701186702186703186704186705186706186707186708186709186710186711186712186713186714186715186716186717186718186719186720186721186722186723186724186725186726186727186728186729186730186731186732186733186734186735186736186737186738186739186740186741186742186743186744186745186746186747186748186749186750186751186752186753186754186755186756186757186758186759186760186761186762186763186764186765186766186767186768186769186770186771186772186773186774186775186776186777186778186779186780186781186782186783186784186785186786186787186788186789186790186791186792186793186794186795186796186797186798186799186800186801186802186803186804186805186806186807186808186809186810186811186812186813186814186815186816186817186818186819186820186821186822186823186824186825186826186827186828186829186830186831186832186833186834186835186836186837186838186839186840186841186842186843186844186845186846186847186848186849186850186851186852186853186854186855186856186857186858186859186860186861186862186863186864186865186866186867186868186869186870186871186872186873186874186875186876186877186878186879186880186881186882186883186884186885186886186887186888186889186890186891186892186893186894186895186896186897186898186899186900186901186902186903186904186905186906186907186908186909186910186911186912186913186914186915186916186917186918186919186920186921186922186923186924186925186926186927186928186929186930186931186932186933186934186935186936186937186938186939186940186941186942186943186944186945186946186947186948186949186950186951186952186953186954186955186956186957186958186959186960186961186962186963186964186965186966186967186968186969186970186971186972186973186974186975186976186977186978186979186980186981186982186983186984186985186986186987186988186989186990186991186992186993186994186995186996186997186998186999187000187001187002187003187004187005187006187007187008187009187010187011187012187013187014187015187016187017187018187019187020187021187022187023187024187025187026187027187028187029187030187031187032187033187034187035187036187037187038187039187040187041187042187043187044187045187046187047187048187049187050187051187052187053187054187055187056187057187058187059187060187061187062187063187064187065187066187067187068187069187070187071187072187073187074187075187076187077187078187079187080187081187082187083187084187085187086187087187088187089187090187091187092187093187094187095187096187097187098187099187100187101187102187103187104187105187106187107187108187109187110187111187112187113187114187115187116187117187118187119187120187121187122187123187124187125187126187127187128187129187130187131187132187133187134187135187136187137187138187139187140187141187142187143187144187145187146187147187148187149187150187151187152187153187154187155187156187157187158187159187160187161187162187163187164187165187166187167187168187169187170187171187172187173187174187175187176187177187178187179187180187181187182187183187184187185187186187187187188187189187190187191187192187193187194187195187196187197187198187199187200187201187202187203187204187205187206187207187208187209187210187211187212187213187214187215187216187217187218187219187220187221187222187223187224187225187226187227187228187229187230187231187232187233187234187235187236187237187238187239187240187241187242187243187244187245187246187247187248187249187250187251187252187253187254187255187256187257187258187259187260187261187262187263187264187265187266187267187268187269187270187271187272187273187274187275187276187277187278187279187280187281187282187283187284187285187286187287187288187289187290187291187292187293187294187295187296187297187298187299187300187301187302187303187304187305187306187307187308187309187310187311187312187313187314187315187316187317187318187319187320187321187322187323187324187325187326187327187328187329187330187331187332187333187334187335187336187337187338187339187340187341187342187343187344187345187346187347187348187349187350187351187352187353187354187355187356187357187358187359187360187361187362187363187364187365187366187367187368187369187370187371187372187373187374187375187376187377187378187379187380187381187382187383187384187385187386187387187388187389187390187391187392187393187394187395187396187397187398187399187400187401187402187403187404187405187406187407187408187409187410187411187412187413187414187415187416187417187418187419187420187421187422187423187424187425187426187427187428187429187430187431187432187433187434187435187436187437187438187439187440187441187442187443187444187445187446187447187448187449187450187451187452187453187454187455187456187457187458187459187460187461187462187463187464187465187466187467187468187469187470187471187472187473187474187475187476187477187478187479187480187481187482187483187484187485187486187487187488187489187490187491187492187493187494187495187496187497187498187499187500187501187502187503187504187505187506187507187508187509187510187511187512187513187514187515187516187517187518187519187520187521187522187523187524187525187526187527187528187529187530187531187532187533187534187535187536187537187538187539187540187541187542187543187544187545187546187547187548187549187550187551187552187553187554187555187556187557187558187559187560187561187562187563187564187565187566187567187568187569187570187571187572187573187574187575187576187577187578187579187580187581187582187583187584187585187586187587187588187589187590187591187592187593187594187595187596187597187598187599187600187601187602187603187604187605187606187607187608187609187610187611187612187613187614187615187616187617187618187619187620187621187622187623187624187625187626187627187628187629187630187631187632187633187634187635187636187637187638187639187640187641187642187643187644187645187646187647187648187649187650187651187652187653187654187655187656187657187658187659187660187661187662187663187664187665187666187667187668187669187670187671187672187673187674187675187676187677187678187679187680187681187682187683187684187685187686187687187688187689187690187691187692187693187694187695187696187697187698187699187700187701187702187703187704187705187706187707187708187709187710187711187712187713187714187715187716187717187718187719187720187721187722187723187724187725187726187727187728187729187730187731187732187733187734187735187736187737187738187739187740187741187742187743187744187745187746187747187748187749187750187751187752187753187754187755187756187757187758187759187760187761187762187763187764187765187766187767187768187769187770187771187772187773187774187775187776187777187778187779187780187781187782187783187784187785187786187787187788187789187790187791187792187793187794187795187796187797187798187799187800187801187802187803187804187805187806187807187808187809187810187811187812187813187814187815187816187817187818187819187820187821187822187823187824187825187826187827187828187829187830187831187832187833187834187835187836187837187838187839187840187841187842187843187844187845187846187847187848187849187850187851187852187853187854187855187856187857187858187859187860187861187862187863187864187865187866187867187868187869187870187871187872187873187874187875187876187877187878187879187880187881187882187883187884187885187886187887187888187889187890187891187892187893187894187895187896187897187898187899187900187901187902187903187904187905187906187907187908187909187910187911187912187913187914187915187916187917187918187919187920187921187922187923187924187925187926187927187928187929187930187931187932187933187934187935187936187937187938187939187940187941187942187943187944187945187946187947187948187949187950187951187952187953187954187955187956187957187958187959187960187961187962187963187964187965187966187967187968187969187970187971187972187973187974187975187976187977187978187979187980187981187982187983187984187985187986187987187988187989187990187991187992187993187994187995187996187997187998187999188000188001188002188003188004188005188006188007188008188009188010188011188012188013188014188015188016188017188018188019188020188021188022188023188024188025188026188027188028188029188030188031188032188033188034188035188036188037188038188039188040188041188042188043188044188045188046188047188048188049188050188051188052188053188054188055188056188057188058188059188060188061188062188063188064188065188066188067188068188069188070188071188072188073188074188075188076188077188078188079188080188081188082188083188084188085188086188087188088188089188090188091188092188093188094188095188096188097188098188099188100188101188102188103188104188105188106188107188108188109188110188111188112188113188114188115188116188117188118188119188120188121188122188123188124188125188126188127188128188129188130188131188132188133188134188135188136188137188138188139188140188141188142188143188144188145188146188147188148188149188150188151188152188153188154188155188156188157188158188159188160188161188162188163188164188165188166188167188168188169188170188171188172188173188174188175188176188177188178188179188180188181188182188183188184188185188186188187188188188189188190188191188192188193188194188195188196188197188198188199188200188201188202188203188204188205188206188207188208188209188210188211188212188213188214188215188216188217188218188219188220188221188222188223188224188225188226188227188228188229188230188231188232188233188234188235188236188237188238188239188240188241188242188243188244188245188246188247188248188249188250188251188252188253188254188255188256188257188258188259188260188261188262188263188264188265188266188267188268188269188270188271188272188273188274188275188276188277188278188279188280188281188282188283188284188285188286188287188288188289188290188291188292188293188294188295188296188297188298188299188300188301188302188303188304188305188306188307188308188309188310188311188312188313188314188315188316188317188318188319188320188321188322188323188324188325188326188327188328188329188330188331188332188333188334188335188336188337188338188339188340188341188342188343188344188345188346188347188348188349188350188351188352188353188354188355188356188357188358188359188360188361188362188363188364188365188366188367188368188369188370188371188372188373188374188375188376188377188378188379188380188381188382188383188384188385188386188387188388188389188390188391188392188393188394188395188396188397188398188399188400188401188402188403188404188405188406188407188408188409188410188411188412188413188414188415188416188417188418188419188420188421188422188423188424188425188426188427188428188429188430188431188432188433188434188435188436188437188438188439188440188441188442188443188444188445188446188447188448188449188450188451188452188453188454188455188456188457188458188459188460188461188462188463188464188465188466188467188468188469188470188471188472188473188474188475188476188477188478188479188480188481188482188483188484188485188486188487188488188489188490188491188492188493188494188495188496188497188498188499188500188501188502188503188504188505188506188507188508188509188510188511188512188513188514188515188516188517188518188519188520188521188522188523188524188525188526188527188528188529188530188531188532188533188534188535188536188537188538188539188540188541188542188543188544188545188546188547188548188549188550188551188552188553188554188555188556188557188558188559188560188561188562188563188564188565188566188567188568188569188570188571188572188573188574188575188576188577188578188579188580188581188582188583188584188585188586188587188588188589188590188591188592188593188594188595188596188597188598188599188600188601188602188603188604188605188606188607188608188609188610188611188612188613188614188615188616188617188618188619188620188621188622188623188624188625188626188627188628188629188630188631188632188633188634188635188636188637188638188639188640188641188642188643188644188645188646188647188648188649188650188651188652188653188654188655188656188657188658188659188660188661188662188663188664188665188666188667188668188669188670188671188672188673188674188675188676188677188678188679188680188681188682188683188684188685188686188687188688188689188690188691188692188693188694188695188696188697188698188699188700188701188702188703188704188705188706188707188708188709188710188711188712188713188714188715188716188717188718188719188720188721188722188723188724188725188726188727188728188729188730188731188732188733188734188735188736188737188738188739188740188741188742188743188744188745188746188747188748188749188750188751188752188753188754188755188756188757188758188759188760188761188762188763188764188765188766188767188768188769188770188771188772188773188774188775188776188777188778188779188780188781188782188783188784188785188786188787188788188789188790188791188792188793188794188795188796188797188798188799188800188801188802188803188804188805188806188807188808188809188810188811188812188813188814188815188816188817188818188819188820188821188822188823188824188825188826188827188828188829188830188831188832188833188834188835188836188837188838188839188840188841188842188843188844188845188846188847188848188849188850188851188852188853188854188855188856188857188858188859188860188861188862188863188864188865188866188867188868188869188870188871188872188873188874188875188876188877188878188879188880188881188882188883188884188885188886188887188888188889188890188891188892188893188894188895188896188897188898188899188900188901188902188903188904188905188906188907188908188909188910188911188912188913188914188915188916188917188918188919188920188921188922188923188924188925188926188927188928188929188930188931188932188933188934188935188936188937188938188939188940188941188942188943188944188945188946188947188948188949188950188951188952188953188954188955188956188957188958188959188960188961188962188963188964188965188966188967188968188969188970188971188972188973188974188975188976188977188978188979188980188981188982188983188984188985188986188987188988188989188990188991188992188993188994188995188996188997188998188999189000189001189002189003189004189005189006189007189008189009189010189011189012189013189014189015189016189017189018189019189020189021189022189023189024189025189026189027189028189029189030189031189032189033189034189035189036189037189038189039189040189041189042189043189044189045189046189047189048189049189050189051189052189053189054189055189056189057189058189059189060189061189062189063189064189065189066189067189068189069189070189071189072189073189074189075189076189077189078189079189080189081189082189083189084189085189086189087189088189089189090189091189092189093189094189095189096189097189098189099189100189101189102189103189104189105189106189107189108189109189110189111189112189113189114189115189116189117189118189119189120189121189122189123189124189125189126189127189128189129189130189131189132189133189134189135189136189137189138189139189140189141189142189143189144189145189146189147189148189149189150189151189152189153189154189155189156189157189158189159189160189161189162189163189164189165189166189167189168189169189170189171189172189173189174189175189176189177189178189179189180189181189182189183189184189185189186189187189188189189189190189191189192189193189194189195189196189197189198189199189200189201189202189203189204189205189206189207189208189209189210189211189212189213189214189215189216189217189218189219189220189221189222189223189224189225189226189227189228189229189230189231189232189233189234189235189236189237189238189239189240189241189242189243189244189245189246189247189248189249189250189251189252189253189254189255189256189257189258189259189260189261189262189263189264189265189266189267189268189269189270189271189272189273189274189275189276189277189278189279189280189281189282189283189284189285189286189287189288189289189290189291189292189293189294189295189296189297189298189299189300189301189302189303189304189305189306189307189308189309189310189311189312189313189314189315189316189317189318189319189320189321189322189323189324189325189326189327189328189329189330189331189332189333189334189335189336189337189338189339189340189341189342189343189344189345189346189347189348189349189350189351189352189353189354189355189356189357189358189359189360189361189362189363189364189365189366189367189368189369189370189371189372189373189374189375189376189377189378189379189380189381189382189383189384189385189386189387189388189389189390189391189392189393189394189395189396189397189398189399189400189401189402189403189404189405189406189407189408189409189410189411189412189413189414189415189416189417189418189419189420189421189422189423189424189425189426189427189428189429189430189431189432189433189434189435189436189437189438189439189440189441189442189443189444189445189446189447189448189449189450189451189452189453189454189455189456189457189458189459189460189461189462189463189464189465189466189467189468189469189470189471189472189473189474189475189476189477189478189479189480189481189482189483189484189485189486189487189488189489189490189491189492189493189494189495189496189497189498189499189500189501189502189503189504189505189506189507189508189509189510189511189512189513189514189515189516189517189518189519189520189521189522189523189524189525189526189527189528189529189530189531189532189533189534189535189536189537189538189539189540189541189542189543189544189545189546189547189548189549189550189551189552189553189554189555189556189557189558189559189560189561189562189563189564189565189566189567189568189569189570189571189572189573189574189575189576189577189578189579189580189581189582189583189584189585189586189587189588189589189590189591189592189593189594189595189596189597189598189599189600189601189602189603189604189605189606189607189608189609189610189611189612189613189614189615189616189617189618189619189620189621189622189623189624189625189626189627189628189629189630189631189632189633189634189635189636189637189638189639189640189641189642189643189644189645189646189647189648189649189650189651189652189653189654189655189656189657189658189659189660189661189662189663189664189665189666189667189668189669189670189671189672189673189674189675189676189677189678189679189680189681189682189683189684189685189686189687189688189689189690189691189692189693189694189695189696189697189698189699189700189701189702189703189704189705189706189707189708189709189710189711189712189713189714189715189716189717189718189719189720189721189722189723189724189725189726189727189728189729189730189731189732189733189734189735189736189737189738189739189740189741189742189743189744189745189746189747189748189749189750189751189752189753189754189755189756189757189758189759189760189761189762189763189764189765189766189767189768189769189770189771189772189773189774189775189776189777189778189779189780189781189782189783189784189785189786189787189788189789189790189791189792189793189794189795189796189797189798189799189800189801189802189803189804189805189806189807189808189809189810189811189812189813189814189815189816189817189818189819189820189821189822189823189824189825189826189827189828189829189830189831189832189833189834189835189836189837189838189839189840189841189842189843189844189845189846189847189848189849189850189851189852189853189854189855189856189857189858189859189860189861189862189863189864189865189866189867189868189869189870189871189872189873189874189875189876189877189878189879189880189881189882189883189884189885189886189887189888189889189890189891189892189893189894189895189896189897189898189899189900189901189902189903189904189905189906189907189908189909189910189911189912189913189914189915189916189917189918189919189920189921189922189923189924189925189926189927189928189929189930189931189932189933189934189935189936189937189938189939189940189941189942189943189944189945189946189947189948189949189950189951189952189953189954189955189956189957189958189959189960189961189962189963189964189965189966189967189968189969189970189971189972189973189974189975189976189977189978189979189980189981189982189983189984189985189986189987189988189989189990189991189992189993189994189995189996189997189998189999190000190001190002190003190004190005190006190007190008190009190010190011190012190013190014190015190016190017190018190019190020190021190022190023190024190025190026190027190028190029190030190031190032190033190034190035190036190037190038190039190040190041190042190043190044190045190046190047190048190049190050190051190052190053190054190055190056190057190058190059190060190061190062190063190064190065190066190067190068190069190070190071190072190073190074190075190076190077190078190079190080190081190082190083190084190085190086190087190088190089190090190091190092190093190094190095190096190097190098190099190100190101190102190103190104190105190106190107190108190109190110190111190112190113190114190115190116190117190118190119190120190121190122190123190124190125190126190127190128190129190130190131190132190133190134190135190136190137190138190139190140190141190142190143190144190145190146190147190148190149190150190151190152190153190154190155190156190157190158190159190160190161190162190163190164190165190166190167190168190169190170190171190172190173190174190175190176190177190178190179190180190181190182190183190184190185190186190187190188190189190190190191190192190193190194190195190196190197190198190199190200190201190202190203190204190205190206190207190208190209190210190211190212190213190214190215190216190217190218190219190220190221190222190223190224190225190226190227190228190229190230190231190232190233190234190235190236190237190238190239190240190241190242190243190244190245190246190247190248190249190250190251190252190253190254190255190256190257190258190259190260190261190262190263190264190265190266190267190268190269190270190271190272190273190274190275190276190277190278190279190280190281190282190283190284190285190286190287190288190289190290190291190292190293190294190295190296190297190298190299190300190301190302190303190304190305190306190307190308190309190310190311190312190313190314190315190316190317190318190319190320190321190322190323190324190325190326190327190328190329190330190331190332190333190334190335190336190337190338190339190340190341190342190343190344190345190346190347190348190349190350190351190352190353190354190355190356190357190358190359190360190361190362190363190364190365190366190367190368190369190370190371190372190373190374190375190376190377190378190379190380190381190382190383190384190385190386190387190388190389190390190391190392190393190394190395190396190397190398190399190400190401190402190403190404190405190406190407190408190409190410190411190412190413190414190415190416190417190418190419190420190421190422190423190424190425190426190427190428190429190430190431190432190433190434190435190436190437190438190439190440190441190442190443190444190445190446190447190448190449190450190451190452190453190454190455190456190457190458190459190460190461190462190463190464190465190466190467190468190469190470190471190472190473190474190475190476190477190478190479190480190481190482190483190484190485190486190487190488190489190490190491190492190493190494190495190496190497190498190499190500190501190502190503190504190505190506190507190508190509190510190511190512190513190514190515190516190517190518190519190520190521190522190523190524190525190526190527190528190529190530190531190532190533190534190535190536190537190538190539190540190541190542190543190544190545190546190547190548190549190550190551190552190553190554190555190556190557190558190559190560190561190562190563190564190565190566190567190568190569190570190571190572190573190574190575190576190577190578190579190580190581190582190583190584190585190586190587190588190589190590190591190592190593190594190595190596190597190598190599190600190601190602190603190604190605190606190607190608190609190610190611190612190613190614190615190616190617190618190619190620190621190622190623190624190625190626190627190628190629190630190631190632190633190634190635190636190637190638190639190640190641190642190643190644190645190646190647190648190649190650190651190652190653190654190655190656190657190658190659190660190661190662190663190664190665190666190667190668190669190670190671190672190673190674190675190676190677190678190679190680190681190682190683190684190685190686190687190688190689190690190691190692190693190694190695190696190697190698190699190700190701190702190703190704190705190706190707190708190709190710190711190712190713190714190715190716190717190718190719190720190721190722190723190724190725190726190727190728190729190730190731190732190733190734190735190736190737190738190739190740190741190742190743190744190745190746190747190748190749190750190751190752190753190754190755190756190757190758190759190760190761190762190763190764190765190766190767190768190769190770190771190772190773190774190775190776190777190778190779190780190781190782190783190784190785190786190787190788190789190790190791190792190793190794190795190796190797190798190799190800190801190802190803190804190805190806190807190808190809190810190811190812190813190814190815190816190817190818190819190820190821190822190823190824190825190826190827190828190829190830190831190832190833190834190835190836190837190838190839190840190841190842190843190844190845190846190847190848190849190850190851190852190853190854190855190856190857190858190859190860190861190862190863190864190865190866190867190868190869190870190871190872190873190874190875190876190877190878190879190880190881190882190883190884190885190886190887190888190889190890190891190892190893190894190895190896190897190898190899190900190901190902190903190904190905190906190907190908190909190910190911190912190913190914190915190916190917190918190919190920190921190922190923190924190925190926190927190928190929190930190931190932190933190934190935190936190937190938190939190940190941190942190943190944190945190946190947190948190949190950190951190952190953190954190955190956190957190958190959190960190961190962190963190964190965190966190967190968190969190970190971190972190973190974190975190976190977190978190979190980190981190982190983190984190985190986190987190988190989190990190991190992190993190994190995190996190997190998190999191000191001191002191003191004191005191006191007191008191009191010191011191012191013191014191015191016191017191018191019191020191021191022191023191024191025191026191027191028191029191030191031191032191033191034191035191036191037191038191039191040191041191042191043191044191045191046191047191048191049191050191051191052191053191054191055191056191057191058191059191060191061191062191063191064191065191066191067191068191069191070191071191072191073191074191075191076191077191078191079191080191081191082191083191084191085191086191087191088191089191090191091191092191093191094191095191096191097191098191099191100191101191102191103191104191105191106191107191108191109191110191111191112191113191114191115191116191117191118191119191120191121191122191123191124191125191126191127191128191129191130191131191132191133191134191135191136191137191138191139191140191141191142191143191144191145191146191147191148191149191150191151191152191153191154191155191156191157191158191159191160191161191162191163191164191165191166191167191168191169191170191171191172191173191174191175191176191177191178191179191180191181191182191183191184191185191186191187191188191189191190191191191192191193191194191195191196191197191198191199191200191201191202191203191204191205191206191207191208191209191210191211191212191213191214191215191216191217191218191219191220191221191222191223191224191225191226191227191228191229191230191231191232191233191234191235191236191237191238191239191240191241191242191243191244191245191246191247191248191249191250191251191252191253191254191255191256191257191258191259191260191261191262191263191264191265191266191267191268191269191270191271191272191273191274191275191276191277191278191279191280191281191282191283191284191285191286191287191288191289191290191291191292191293191294191295191296191297191298191299191300191301191302191303191304191305191306191307191308191309191310191311191312191313191314191315191316191317191318191319191320191321191322191323191324191325191326191327191328191329191330191331191332191333191334191335191336191337191338191339191340191341191342191343191344191345191346191347191348191349191350191351191352191353191354191355191356191357191358191359191360191361191362191363191364191365191366191367191368191369191370191371191372191373191374191375191376191377191378191379191380191381191382191383191384191385191386191387191388191389191390191391191392191393191394191395191396191397191398191399191400191401191402191403191404191405191406191407191408191409191410191411191412191413191414191415191416191417191418191419191420191421191422191423191424191425191426191427191428191429191430191431191432191433191434191435191436191437191438191439191440191441191442191443191444191445191446191447191448191449191450191451191452191453191454191455191456191457191458191459191460191461191462191463191464191465191466191467191468191469191470191471191472191473191474191475191476191477191478191479191480191481191482191483191484191485191486191487191488191489191490191491191492191493191494191495191496191497191498191499191500191501191502191503191504191505191506191507191508191509191510191511191512191513191514191515191516191517191518191519191520191521191522191523191524191525191526191527191528191529191530191531191532191533191534191535191536191537191538191539191540191541191542191543191544191545191546191547191548191549191550191551191552191553191554191555191556191557191558191559191560191561191562191563191564191565191566191567191568191569191570191571191572191573191574191575191576191577191578191579191580191581191582191583191584191585191586191587191588191589191590191591191592191593191594191595191596191597191598191599191600191601191602191603191604191605191606191607191608191609191610191611191612191613191614191615191616191617191618191619191620191621191622191623191624191625191626191627191628191629191630191631191632191633191634191635191636191637191638191639191640191641191642191643191644191645191646191647191648191649191650191651191652191653191654191655191656191657191658191659191660191661191662191663191664191665191666191667191668191669191670191671191672191673191674191675191676191677191678191679191680191681191682191683191684191685191686191687191688191689191690191691191692191693191694191695191696191697191698191699191700191701191702191703191704191705191706191707191708191709191710191711191712191713191714191715191716191717191718191719191720191721191722191723191724191725191726191727191728191729191730191731191732191733191734191735191736191737191738191739191740191741191742191743191744191745191746191747191748191749191750191751191752191753191754191755191756191757191758191759191760191761191762191763191764191765191766191767191768191769191770191771191772191773191774191775191776191777191778191779191780191781191782191783191784191785191786191787191788191789191790191791191792191793191794191795191796191797191798191799191800191801191802191803191804191805191806191807191808191809191810191811191812191813191814191815191816191817191818191819191820191821191822191823191824191825191826191827191828191829191830191831191832191833191834191835191836191837191838191839191840191841191842191843191844191845191846191847191848191849191850191851191852191853191854191855191856191857191858191859191860191861191862191863191864191865191866191867191868191869191870191871191872191873191874191875191876191877191878191879191880191881191882191883191884191885191886191887191888191889191890191891191892191893191894191895191896191897191898191899191900191901191902191903191904191905191906191907191908191909191910191911191912191913191914191915191916191917191918191919191920191921191922191923191924191925191926191927191928191929191930191931191932191933191934191935191936191937191938191939191940191941191942191943191944191945191946191947191948191949191950191951191952191953191954191955191956191957191958191959191960191961191962191963191964191965191966191967191968191969191970191971191972191973191974191975191976191977191978191979191980191981191982191983191984191985191986191987191988191989191990191991191992191993191994191995191996191997191998191999192000192001192002192003192004192005192006192007192008192009192010192011192012192013192014192015192016192017192018192019192020192021192022192023192024192025192026192027192028192029192030192031192032192033192034192035192036192037192038192039192040192041192042192043192044192045192046192047192048192049192050192051192052192053192054192055192056192057192058192059192060192061192062192063192064192065192066192067192068192069192070192071192072192073192074192075192076192077192078192079192080192081192082192083192084192085192086192087192088192089192090192091192092192093192094192095192096192097192098192099192100192101192102192103192104192105192106192107192108192109192110192111192112192113192114192115192116192117192118192119192120192121192122192123192124192125192126192127192128192129192130192131192132192133192134192135192136192137192138192139192140192141192142192143192144192145192146192147192148192149192150192151192152192153192154192155192156192157192158192159192160192161192162192163192164192165192166192167192168192169192170192171192172192173192174192175192176192177192178192179192180192181192182192183192184192185192186192187192188192189192190192191192192192193192194192195192196192197192198192199192200192201192202192203192204192205192206192207192208192209192210192211192212192213192214192215192216192217192218192219192220192221192222192223192224192225192226192227192228192229192230192231192232192233192234192235192236192237192238192239192240192241192242192243192244192245192246192247192248192249192250192251192252192253192254192255192256192257192258192259192260192261192262192263192264192265192266192267192268192269192270192271192272192273192274192275192276192277192278192279192280192281192282192283192284192285192286192287192288192289192290192291192292192293192294192295192296192297192298192299192300192301192302192303192304192305192306192307192308192309192310192311192312192313192314192315192316192317192318192319192320192321192322192323192324192325192326192327192328192329192330192331192332192333192334192335192336192337192338192339192340192341192342192343192344192345192346192347192348192349192350192351192352192353192354192355192356192357192358192359192360192361192362192363192364192365192366192367192368192369192370192371192372192373192374192375192376192377192378192379192380192381192382192383192384192385192386192387192388192389192390192391192392192393192394192395192396192397192398192399192400192401192402192403192404192405192406192407192408192409192410192411192412192413192414192415192416192417192418192419192420192421192422192423192424192425192426192427192428192429192430192431192432192433192434192435192436192437192438192439192440192441192442192443192444192445192446192447192448192449192450192451192452192453192454192455192456192457192458192459192460192461192462192463192464192465192466192467192468192469192470192471192472192473192474192475192476192477192478192479192480192481192482192483192484192485192486192487192488192489192490192491192492192493192494192495192496192497192498192499192500192501192502192503192504192505192506192507192508192509192510192511192512192513192514192515192516192517192518192519192520192521192522192523192524192525192526192527192528192529192530192531192532192533192534192535192536192537192538192539192540192541192542192543192544192545192546192547192548192549192550192551192552192553192554192555192556192557192558192559192560192561192562192563192564192565192566192567192568192569192570192571192572192573192574192575192576192577192578192579192580192581192582192583192584192585192586192587192588192589192590192591192592192593192594192595192596192597192598192599192600192601192602192603192604192605192606192607192608192609192610192611192612192613192614192615192616192617192618192619192620192621192622192623192624192625192626192627192628192629192630192631192632192633192634192635192636192637192638192639192640192641192642192643192644192645192646192647192648192649192650192651192652192653192654192655192656192657192658192659192660192661192662192663192664192665192666192667192668192669192670192671192672192673192674192675192676192677192678192679192680192681192682192683192684192685192686192687192688192689192690192691192692192693192694192695192696192697192698192699192700192701192702192703192704192705192706192707192708192709192710192711192712192713192714192715192716192717192718192719192720192721192722192723192724192725192726192727192728192729192730192731192732192733192734192735192736192737192738192739192740192741192742192743192744192745192746192747192748192749192750192751192752192753192754192755192756192757192758192759192760192761192762192763192764192765192766192767192768192769192770192771192772192773192774192775192776192777192778192779192780192781192782192783192784192785192786192787192788192789192790192791192792192793192794192795192796192797192798192799192800192801192802192803192804192805192806192807192808192809192810192811192812192813192814192815192816192817192818192819192820192821192822192823192824192825192826192827192828192829192830192831192832192833192834192835192836192837192838192839192840192841192842192843192844192845192846192847192848192849192850192851192852192853192854192855192856192857192858192859192860192861192862192863192864192865192866192867192868192869192870192871192872192873192874192875192876192877192878192879192880192881192882192883192884192885192886192887192888192889192890192891192892192893192894192895192896192897192898192899192900192901192902192903192904192905192906192907192908192909192910192911192912192913192914192915192916192917192918192919192920192921192922192923192924192925192926192927192928192929192930192931192932192933192934192935192936192937192938192939192940192941192942192943192944192945192946192947192948192949192950192951192952192953192954192955192956192957192958192959192960192961192962192963192964192965192966192967192968192969192970192971192972192973192974192975192976192977192978192979192980192981192982192983192984192985192986192987192988192989192990192991192992192993192994192995192996192997192998192999193000193001193002193003193004193005193006193007193008193009193010193011193012193013193014193015193016193017193018193019193020193021193022193023193024193025193026193027193028193029193030193031193032193033193034193035193036193037193038193039193040193041193042193043193044193045193046193047193048193049193050193051193052193053193054193055193056193057193058193059193060193061193062193063193064193065193066193067193068193069193070193071193072193073193074193075193076193077193078193079193080193081193082193083193084193085193086193087193088193089193090193091193092193093193094193095193096193097193098193099193100193101193102193103193104193105193106193107193108193109193110193111193112193113193114193115193116193117193118193119193120193121193122193123193124193125193126193127193128193129193130193131193132193133193134193135193136193137193138193139193140193141193142193143193144193145193146193147193148193149193150193151193152193153193154193155193156193157193158193159193160193161193162193163193164193165193166193167193168193169193170193171193172193173193174193175193176193177193178193179193180193181193182193183193184193185193186193187193188193189193190193191193192193193193194193195193196193197193198193199193200193201193202193203193204193205193206193207193208193209193210193211193212193213193214193215193216193217193218193219193220193221193222193223193224193225193226193227193228193229193230193231193232193233193234193235193236193237193238193239193240193241193242193243193244193245193246193247193248193249193250193251193252193253193254193255193256193257193258193259193260193261193262193263193264193265193266193267193268193269193270193271193272193273193274193275193276193277193278193279193280193281193282193283193284193285193286193287193288193289193290193291193292193293193294193295193296193297193298193299193300193301193302193303193304193305193306193307193308193309193310193311193312193313193314193315193316193317193318193319193320193321193322193323193324193325193326193327193328193329193330193331193332193333193334193335193336193337193338193339193340193341193342193343193344193345193346193347193348193349193350193351193352193353193354193355193356193357193358193359193360193361193362193363193364193365193366193367193368193369193370193371193372193373193374193375193376193377193378193379193380193381193382193383193384193385193386193387193388193389193390193391193392193393193394193395193396193397193398193399193400193401193402193403193404193405193406193407193408193409193410193411193412193413193414193415193416193417193418193419193420193421193422193423193424193425193426193427193428193429193430193431193432193433193434193435193436193437193438193439193440193441193442193443193444193445193446193447193448193449193450193451193452193453193454193455193456193457193458193459193460193461193462193463193464193465193466193467193468193469193470193471193472193473193474193475193476193477193478193479193480193481193482193483193484193485193486193487193488193489193490193491193492193493193494193495193496193497193498193499193500193501193502193503193504193505193506193507193508193509193510193511193512193513193514193515193516193517193518193519193520193521193522193523193524193525193526193527193528193529193530193531193532193533193534193535193536193537193538193539193540193541193542193543193544193545193546193547193548193549193550193551193552193553193554193555193556193557193558193559193560193561193562193563193564193565193566193567193568193569193570193571193572193573193574193575193576193577193578193579193580193581193582193583193584193585193586193587193588193589193590193591193592193593193594193595193596193597193598193599193600193601193602193603193604193605193606193607193608193609193610193611193612193613193614193615193616193617193618193619193620193621193622193623193624193625193626193627193628193629193630193631193632193633193634193635193636193637193638193639193640193641193642193643193644193645193646193647193648193649193650193651193652193653193654193655193656193657193658193659193660193661193662193663193664193665193666193667193668193669193670193671193672193673193674193675193676193677193678193679193680193681193682193683193684193685193686193687193688193689193690193691193692193693193694193695193696193697193698193699193700193701193702193703193704193705193706193707193708193709193710193711193712193713193714193715193716193717193718193719193720193721193722193723193724193725193726193727193728193729193730193731193732193733193734193735193736193737193738193739193740193741193742193743193744193745193746193747193748193749193750193751193752193753193754193755193756193757193758193759193760193761193762193763193764193765193766193767193768193769193770193771193772193773193774193775193776193777193778193779193780193781193782193783193784193785193786193787193788193789193790193791193792193793193794193795193796193797193798193799193800193801193802193803193804193805193806193807193808193809193810193811193812193813193814193815193816193817193818193819193820193821193822193823193824193825193826193827193828193829193830193831193832193833193834193835193836193837193838193839193840193841193842193843193844193845193846193847193848193849193850193851193852193853193854193855193856193857193858193859193860193861193862193863193864193865193866193867193868193869193870193871193872193873193874193875193876193877193878193879193880193881193882193883193884193885193886193887193888193889193890193891193892193893193894193895193896193897193898193899193900193901193902193903193904193905193906193907193908193909193910193911193912193913193914193915193916193917193918193919193920193921193922193923193924193925193926193927193928193929193930193931193932193933193934193935193936193937193938193939193940193941193942193943193944193945193946193947193948193949193950193951193952193953193954193955193956193957193958193959193960193961193962193963193964193965193966193967193968193969193970193971193972193973193974193975193976193977193978193979193980193981193982193983193984193985193986193987193988193989193990193991193992193993193994193995193996193997193998193999194000194001194002194003194004194005194006194007194008194009194010194011194012194013194014194015194016194017194018194019194020194021194022194023194024194025194026194027194028194029194030194031194032194033194034194035194036194037194038194039194040194041194042194043194044194045194046194047194048194049194050194051194052194053194054194055194056194057194058194059194060194061194062194063194064194065194066194067194068194069194070194071194072194073194074194075194076194077194078194079194080194081194082194083194084194085194086194087194088194089194090194091194092194093194094194095194096194097194098194099194100194101194102194103194104194105194106194107194108194109194110194111194112194113194114194115194116194117194118194119194120194121194122194123194124194125194126194127194128194129194130194131194132194133194134194135194136194137194138194139194140194141194142194143194144194145194146194147194148194149194150194151194152194153194154194155194156194157194158194159194160194161194162194163194164194165194166194167194168194169194170194171194172194173194174194175194176194177194178194179194180194181194182194183194184194185194186194187194188194189194190194191194192194193194194194195194196194197194198194199194200194201194202194203194204194205194206194207194208194209194210194211194212194213194214194215194216194217194218194219194220194221194222194223194224194225194226194227194228194229194230194231194232194233194234194235194236194237194238194239194240194241194242194243194244194245194246194247194248194249194250194251194252194253194254194255194256194257194258194259194260194261194262194263194264194265194266194267194268194269194270194271194272194273194274194275194276194277194278194279194280194281194282194283194284194285194286194287194288194289194290194291194292194293194294194295194296194297194298194299194300194301194302194303194304194305194306194307194308194309194310194311194312194313194314194315194316194317194318194319194320194321194322194323194324194325194326194327194328194329194330194331194332194333194334194335194336194337194338194339194340194341194342194343194344194345194346194347194348194349194350194351194352194353194354194355194356194357194358194359194360194361194362194363194364194365194366194367194368194369194370194371194372194373194374194375194376194377194378194379194380194381194382194383194384194385194386194387194388194389194390194391194392194393194394194395194396194397194398194399194400194401194402194403194404194405194406194407194408194409194410194411194412194413194414194415194416194417194418194419194420194421194422194423194424194425194426194427194428194429194430194431194432194433194434194435194436194437194438194439194440194441194442194443194444194445194446194447194448194449194450194451194452194453194454194455194456194457194458194459194460194461194462194463194464194465194466194467194468194469194470194471194472194473194474194475194476194477194478194479194480194481194482194483194484194485194486194487194488194489194490194491194492194493194494194495194496194497194498194499194500194501194502194503194504194505194506194507194508194509194510194511194512194513194514194515194516194517194518194519194520194521194522194523194524194525194526194527194528194529194530194531194532194533194534194535194536194537194538194539194540194541194542194543194544194545194546194547194548194549194550194551194552194553194554194555194556194557194558194559194560194561194562194563194564194565194566194567194568194569194570194571194572194573194574194575194576194577194578194579194580194581194582194583194584194585194586194587194588194589194590194591194592194593194594194595194596194597194598194599194600194601194602194603194604194605194606194607194608194609194610194611194612194613194614194615194616194617194618194619194620194621194622194623194624194625194626194627194628194629194630194631194632194633194634194635194636194637194638194639194640194641194642194643194644194645194646194647194648194649194650194651194652194653194654194655194656194657194658194659194660194661194662194663194664194665194666194667194668194669194670194671194672194673194674194675194676194677194678194679194680194681194682194683194684194685194686194687194688194689194690194691194692194693194694194695194696194697194698194699194700194701194702194703194704194705194706194707194708194709194710194711194712194713194714194715194716194717194718194719194720194721194722194723194724194725194726194727194728194729194730194731194732194733194734194735194736194737194738194739194740194741194742194743194744194745194746194747194748194749194750194751194752194753194754194755194756194757194758194759194760194761194762194763194764194765194766194767194768194769194770194771194772194773194774194775194776194777194778194779194780194781194782194783194784194785194786194787194788194789194790194791194792194793194794194795194796194797194798194799194800194801194802194803194804194805194806194807194808194809194810194811194812194813194814194815194816194817194818194819194820194821194822194823194824194825194826194827194828194829194830194831194832194833194834194835194836194837194838194839194840194841194842194843194844194845194846194847194848194849194850194851194852194853194854194855194856194857194858194859194860194861194862194863194864194865194866194867194868194869194870194871194872194873194874194875194876194877194878194879194880194881194882194883194884194885194886194887194888194889194890194891194892194893194894194895194896194897194898194899194900194901194902194903194904194905194906194907194908194909194910194911194912194913194914194915194916194917194918194919194920194921194922194923194924194925194926194927194928194929194930194931194932194933194934194935194936194937194938194939194940194941194942194943194944194945194946194947194948194949194950194951194952194953194954194955194956194957194958194959194960194961194962194963194964194965194966194967194968194969194970194971194972194973194974194975194976194977194978194979194980194981194982194983194984194985194986194987194988194989194990194991194992194993194994194995194996194997194998194999195000195001195002195003195004195005195006195007195008195009195010195011195012195013195014195015195016195017195018195019195020195021195022195023195024195025195026195027195028195029195030195031195032195033195034195035195036195037195038195039195040195041195042195043195044195045195046195047195048195049195050195051195052195053195054195055195056195057195058195059195060195061195062195063195064195065195066195067195068195069195070195071195072195073195074195075195076195077195078195079195080195081195082195083195084195085195086195087195088195089195090195091195092195093195094195095195096195097195098195099195100195101195102195103195104195105195106195107195108195109195110195111195112195113195114195115195116195117195118195119195120195121195122195123195124195125195126195127195128195129195130195131195132195133195134195135195136195137195138195139195140195141195142195143195144195145195146195147195148195149195150195151195152195153195154195155195156195157195158195159195160195161195162195163195164195165195166195167195168195169195170195171195172195173195174195175195176195177195178195179195180195181195182195183195184195185195186195187195188195189195190195191195192195193195194195195195196195197195198195199195200195201195202195203195204195205195206195207195208195209195210195211195212195213195214195215195216195217195218195219195220195221195222195223195224195225195226195227195228195229195230195231195232195233195234195235195236195237195238195239195240195241195242195243195244195245195246195247195248195249195250195251195252195253195254195255195256195257195258195259195260195261195262195263195264195265195266195267195268195269195270195271195272195273195274195275195276195277195278195279195280195281195282195283195284195285195286195287195288195289195290195291195292195293195294195295195296195297195298195299195300195301195302195303195304195305195306195307195308195309195310195311195312195313195314195315195316195317195318195319195320195321195322195323195324195325195326195327195328195329195330195331195332195333195334195335195336195337195338195339195340195341195342195343195344195345195346195347195348195349195350195351195352195353195354195355195356195357195358195359195360195361195362195363195364195365195366195367195368195369195370195371195372195373195374195375195376195377195378195379195380195381195382195383195384195385195386195387195388195389195390195391195392195393195394195395195396195397195398195399195400195401195402195403195404195405195406195407195408195409195410195411195412195413195414195415195416195417195418195419195420195421195422195423195424195425195426195427195428195429195430195431195432195433195434195435195436195437195438195439195440195441195442195443195444195445195446195447195448195449195450195451195452195453195454195455195456195457195458195459195460195461195462195463195464195465195466195467195468195469195470195471195472195473195474195475195476195477195478195479195480195481195482195483195484195485195486195487195488195489195490195491195492195493195494195495195496195497195498195499195500195501195502195503195504195505195506195507195508195509195510195511195512195513195514195515195516195517195518195519195520195521195522195523195524195525195526195527195528195529195530195531195532195533195534195535195536195537195538195539195540195541195542195543195544195545195546195547195548195549195550195551195552195553195554195555195556195557195558195559195560195561195562195563195564195565195566195567195568195569195570195571195572195573195574195575195576195577195578195579195580195581195582195583195584195585195586195587195588195589195590195591195592195593195594195595195596195597195598195599195600195601195602195603195604195605195606195607195608195609195610195611195612195613195614195615195616195617195618195619195620195621195622195623195624195625195626195627195628195629195630195631195632195633195634195635195636195637195638195639195640195641195642195643195644195645195646195647195648195649195650195651195652195653195654195655195656195657195658195659195660195661195662195663195664195665195666195667195668195669195670195671195672195673195674195675195676195677195678195679195680195681195682195683195684195685195686195687195688195689195690195691195692195693195694195695195696195697195698195699195700195701195702195703195704195705195706195707195708195709195710195711195712195713195714195715195716195717195718195719195720195721195722195723195724195725195726195727195728195729195730195731195732195733195734195735195736195737195738195739195740195741195742195743195744195745195746195747195748195749195750195751195752195753195754195755195756195757195758195759195760195761195762195763195764195765195766195767195768195769195770195771195772195773195774195775195776195777195778195779195780195781195782195783195784195785195786195787195788195789195790195791195792195793195794195795195796195797195798195799195800195801195802195803195804195805195806195807195808195809195810195811195812195813195814195815195816195817195818195819195820195821195822195823195824195825195826195827195828195829195830195831195832195833195834195835195836195837195838195839195840195841195842195843195844195845195846195847195848195849195850195851195852195853195854195855195856195857195858195859195860195861195862195863195864195865195866195867195868195869195870195871195872195873195874195875195876195877195878195879195880195881195882195883195884195885195886195887195888195889195890195891195892195893195894195895195896195897195898195899195900195901195902195903195904195905195906195907195908195909195910195911195912195913195914195915195916195917195918195919195920195921195922195923195924195925195926195927195928195929195930195931195932195933195934195935195936195937195938195939195940195941195942195943195944195945195946195947195948195949195950195951195952195953195954195955195956195957195958195959195960195961195962195963195964195965195966195967195968195969195970195971195972195973195974195975195976195977195978195979195980195981195982195983195984195985195986195987195988195989195990195991195992195993195994195995195996195997195998195999196000196001196002196003196004196005196006196007196008196009196010196011196012196013196014196015196016196017196018196019196020196021196022196023196024196025196026196027196028196029196030196031196032196033196034196035196036196037196038196039196040196041196042196043196044196045196046196047196048196049196050196051196052196053196054196055196056196057196058196059196060196061196062196063196064196065196066196067196068196069196070196071196072196073196074196075196076196077196078196079196080196081196082196083196084196085196086196087196088196089196090196091196092196093196094196095196096196097196098196099196100196101196102196103196104196105196106196107196108196109196110196111196112196113196114196115196116196117196118196119196120196121196122196123196124196125196126196127196128196129196130196131196132196133196134196135196136196137196138196139196140196141196142196143196144196145196146196147196148196149196150196151196152196153196154196155196156196157196158196159196160196161196162196163196164196165196166196167196168196169196170196171196172196173196174196175196176196177196178196179196180196181196182196183196184196185196186196187196188196189196190196191196192196193196194196195196196196197196198196199196200196201196202196203196204196205196206196207196208196209196210196211196212196213196214196215196216196217196218196219196220196221196222196223196224196225196226196227196228196229196230196231196232196233196234196235196236196237196238196239196240196241196242196243196244196245196246196247196248196249196250196251196252196253196254196255196256196257196258196259196260196261196262196263196264196265196266196267196268196269196270196271196272196273196274196275196276196277196278196279196280196281196282196283196284196285196286196287196288196289196290196291196292196293196294196295196296196297196298196299196300196301196302196303196304196305196306196307196308196309196310196311196312196313196314196315196316196317196318196319196320196321196322196323196324196325196326196327196328196329196330196331196332196333196334196335196336196337196338196339196340196341196342196343196344196345196346196347196348196349196350196351196352196353196354196355196356196357196358196359196360196361196362196363196364196365196366196367196368196369196370196371196372196373196374196375196376196377196378196379196380196381196382196383196384196385196386196387196388196389196390196391196392196393196394196395196396196397196398196399196400196401196402196403196404196405196406196407196408196409196410196411196412196413196414196415196416196417196418196419196420196421196422196423196424196425196426196427196428196429196430196431196432196433196434196435196436196437196438196439196440196441196442196443196444196445196446196447196448196449196450196451196452196453196454196455196456196457196458196459196460196461196462196463196464196465196466196467196468196469196470196471196472196473196474196475196476196477196478196479196480196481196482196483196484196485196486196487196488196489196490196491196492196493196494196495196496196497196498196499196500196501196502196503196504196505196506196507196508196509196510196511196512196513196514196515196516196517196518196519196520196521196522196523196524196525196526196527196528196529196530196531196532196533196534196535196536196537196538196539196540196541196542196543196544196545196546196547196548196549196550196551196552196553196554196555196556196557196558196559196560196561196562196563196564196565196566196567196568196569196570196571196572196573196574196575196576196577196578196579196580196581196582196583196584196585196586196587196588196589196590196591196592196593196594196595196596196597196598196599196600196601196602196603196604196605196606196607196608196609196610196611196612196613196614196615196616196617196618196619196620196621196622196623196624196625196626196627196628196629196630196631196632196633196634196635196636196637196638196639196640196641196642196643196644196645196646196647196648196649196650196651196652196653196654196655196656196657196658196659196660196661196662196663196664196665196666196667196668196669196670196671196672196673196674196675196676196677196678196679196680196681196682196683196684196685196686196687196688196689196690196691196692196693196694196695196696196697196698196699196700196701196702196703196704196705196706196707196708196709196710196711196712196713196714196715196716196717196718196719196720196721196722196723196724196725196726196727196728196729196730196731196732196733196734196735196736196737196738196739196740196741196742196743196744196745196746196747196748196749196750196751196752196753196754196755196756196757196758196759196760196761196762196763196764196765196766196767196768196769196770196771196772196773196774196775196776196777196778196779196780196781196782196783196784196785196786196787196788196789196790196791196792196793196794196795196796196797196798196799196800196801196802196803196804196805196806196807196808196809196810196811196812196813196814196815196816196817196818196819196820196821196822196823196824196825196826196827196828196829196830196831196832196833196834196835196836196837196838196839196840196841196842196843196844196845196846196847196848196849196850196851196852196853196854196855196856196857196858196859196860196861196862196863196864196865196866196867196868196869196870196871196872196873196874196875196876196877196878196879196880196881196882196883196884196885196886196887196888196889196890196891196892196893196894196895196896196897196898196899196900196901196902196903196904196905196906196907196908196909196910196911196912196913196914196915196916196917196918196919196920196921196922196923196924196925196926196927196928196929196930196931196932196933196934196935196936196937196938196939196940196941196942196943196944196945196946196947196948196949196950196951196952196953196954196955196956196957196958196959196960196961196962196963196964196965196966196967196968196969196970196971196972196973196974196975196976196977196978196979196980196981196982196983196984196985196986196987196988196989196990196991196992196993196994196995196996196997196998196999197000197001197002197003197004197005197006197007197008197009197010197011197012197013197014197015197016197017197018197019197020197021197022197023197024197025197026197027197028197029197030197031197032197033197034197035197036197037197038197039197040197041197042197043197044197045197046197047197048197049197050197051197052197053197054197055197056197057197058197059197060197061197062197063197064197065197066197067197068197069197070197071197072197073197074197075197076197077197078197079197080197081197082197083197084197085197086197087197088197089197090197091197092197093197094197095197096197097197098197099197100197101197102197103197104197105197106197107197108197109197110197111197112197113197114197115197116197117197118197119197120197121197122197123197124197125197126197127197128197129197130197131197132197133197134197135197136197137197138197139197140197141197142197143197144197145197146197147197148197149197150197151197152197153197154197155197156197157197158197159197160197161197162197163197164197165197166197167197168197169197170197171197172197173197174197175197176197177197178197179197180197181197182197183197184197185197186197187197188197189197190197191197192197193197194197195197196197197197198197199197200197201197202197203197204197205197206197207197208197209197210197211197212197213197214197215197216197217197218197219197220197221197222197223197224197225197226197227197228197229197230197231197232197233197234197235197236197237197238197239197240197241197242197243197244197245197246197247197248197249197250197251197252197253197254197255197256197257197258197259197260197261197262197263197264197265197266197267197268197269197270197271197272197273197274197275197276197277197278197279197280197281197282197283197284197285197286197287197288197289197290197291197292197293197294197295197296197297197298197299197300197301197302197303197304197305197306197307197308197309197310197311197312197313197314197315197316197317197318197319197320197321197322197323197324197325197326197327197328197329197330197331197332197333197334197335197336197337197338197339197340197341197342197343197344197345197346197347197348197349197350197351197352197353197354197355197356197357197358197359197360197361197362197363197364197365197366197367197368197369197370197371197372197373197374197375197376197377197378197379197380197381197382197383197384197385197386197387197388197389197390197391197392197393197394197395197396197397197398197399197400197401197402197403197404197405197406197407197408197409197410197411197412197413197414197415197416197417197418197419197420197421197422197423197424197425197426197427197428197429197430197431197432197433197434197435197436197437197438197439197440197441197442197443197444197445197446197447197448197449197450197451197452197453197454197455197456197457197458197459197460197461197462197463197464197465197466197467197468197469197470197471197472197473197474197475197476197477197478197479197480197481197482197483197484197485197486197487197488197489197490197491197492197493197494197495197496197497197498197499197500197501197502197503197504197505197506197507197508197509197510197511197512197513197514197515197516197517197518197519197520197521197522197523197524197525197526197527197528197529197530197531197532197533197534197535197536197537197538197539197540197541197542197543197544197545197546197547197548197549197550197551197552197553197554197555197556197557197558197559197560197561197562197563197564197565197566197567197568197569197570197571197572197573197574197575197576197577197578197579197580197581197582197583197584197585197586197587197588197589197590197591197592197593197594197595197596197597197598197599197600197601197602197603197604197605197606197607197608197609197610197611197612197613197614197615197616197617197618197619197620197621197622197623197624197625197626197627197628197629197630197631197632197633197634197635197636197637197638197639197640197641197642197643197644197645197646197647197648197649197650197651197652197653197654197655197656197657197658197659197660197661197662197663197664197665197666197667197668197669197670197671197672197673197674197675197676197677197678197679197680197681197682197683197684197685197686197687197688197689197690197691197692197693197694197695197696197697197698197699197700197701197702197703197704197705197706197707197708197709197710197711197712197713197714197715197716197717197718197719197720197721197722197723197724197725197726197727197728197729197730197731197732197733197734197735197736197737197738197739197740197741197742197743197744197745197746197747197748197749197750197751197752197753197754197755197756197757197758197759197760197761197762197763197764197765197766197767197768197769197770197771197772197773197774197775197776197777197778197779197780197781197782197783197784197785197786197787197788197789197790197791197792197793197794197795197796197797197798197799197800197801197802197803197804197805197806197807197808197809197810197811197812197813197814197815197816197817197818197819197820197821197822197823197824197825197826197827197828197829197830197831197832197833197834197835197836197837197838197839197840197841197842197843197844197845197846197847197848197849197850197851197852197853197854197855197856197857197858197859197860197861197862197863197864197865197866197867197868197869197870197871197872197873197874197875197876197877197878197879197880197881197882197883197884197885197886197887197888197889197890197891197892197893197894197895197896197897197898197899197900197901197902197903197904197905197906197907197908197909197910197911197912197913197914197915197916197917197918197919197920197921197922197923197924197925197926197927197928197929197930197931197932197933197934197935197936197937197938197939197940197941197942197943197944197945197946197947197948197949197950197951197952197953197954197955197956197957197958197959197960197961197962197963197964197965197966197967197968197969197970197971197972197973197974197975197976197977197978197979197980197981197982197983197984197985197986197987197988197989197990197991197992197993197994197995197996197997197998197999198000198001198002198003198004198005198006198007198008198009198010198011198012198013198014198015198016198017198018198019198020198021198022198023198024198025198026198027198028198029198030198031198032198033198034198035198036198037198038198039198040198041198042198043198044198045198046198047198048198049198050198051198052198053198054198055198056198057198058198059198060198061198062198063198064198065198066198067198068198069198070198071198072198073198074198075198076198077198078198079198080198081198082198083198084198085198086198087198088198089198090198091198092198093198094198095198096198097198098198099198100198101198102198103198104198105198106198107198108198109198110198111198112198113198114198115198116198117198118198119198120198121198122198123198124198125198126198127198128198129198130198131198132198133198134198135198136198137198138198139198140198141198142198143198144198145198146198147198148198149198150198151198152198153198154198155198156198157198158198159198160198161198162198163198164198165198166198167198168198169198170198171198172198173198174198175198176198177198178198179198180198181198182198183198184198185198186198187198188198189198190198191198192198193198194198195198196198197198198198199198200198201198202198203198204198205198206198207198208198209198210198211198212198213198214198215198216198217198218198219198220198221198222198223198224198225198226198227198228198229198230198231198232198233198234198235198236198237198238198239198240198241198242198243198244198245198246198247198248198249198250198251198252198253198254198255198256198257198258198259198260198261198262198263198264198265198266198267198268198269198270198271198272198273198274198275198276198277198278198279198280198281198282198283198284198285198286198287198288198289198290198291198292198293198294198295198296198297198298198299198300198301198302198303198304198305198306198307198308198309198310198311198312198313198314198315198316198317198318198319198320198321198322198323198324198325198326198327198328198329198330198331198332198333198334198335198336198337198338198339198340198341198342198343198344198345198346198347198348198349198350198351198352198353198354198355198356198357198358198359198360198361198362198363198364198365198366198367198368198369198370198371198372198373198374198375198376198377198378198379198380198381198382198383198384198385198386198387198388198389198390198391198392198393198394198395198396198397198398198399198400198401198402198403198404198405198406198407198408198409198410198411198412198413198414198415198416198417198418198419198420198421198422198423198424198425198426198427198428198429198430198431198432198433198434198435198436198437198438198439198440198441198442198443198444198445198446198447198448198449198450198451198452198453198454198455198456198457198458198459198460198461198462198463198464198465198466198467198468198469198470198471198472198473198474198475198476198477198478198479198480198481198482198483198484198485198486198487198488198489198490198491198492198493198494198495198496198497198498198499198500198501198502198503198504198505198506198507198508198509198510198511198512198513198514198515198516198517198518198519198520198521198522198523198524198525198526198527198528198529198530198531198532198533198534198535198536198537198538198539198540198541198542198543198544198545198546198547198548198549198550198551198552198553198554198555198556198557198558198559198560198561198562198563198564198565198566198567198568198569198570198571198572198573198574198575198576198577198578198579198580198581198582198583198584198585198586198587198588198589198590198591198592198593198594198595198596198597198598198599198600198601198602198603198604198605198606198607198608198609198610198611198612198613198614198615198616198617198618198619198620198621198622198623198624198625198626198627198628198629198630198631198632198633198634198635198636198637198638198639198640198641198642198643198644198645198646198647198648198649198650198651198652198653198654198655198656198657198658198659198660198661198662198663198664198665198666198667198668198669198670198671198672198673198674198675198676198677198678198679198680198681198682198683198684198685198686198687198688198689198690198691198692198693198694198695198696198697198698198699198700198701198702198703198704198705198706198707198708198709198710198711198712198713198714198715198716198717198718198719198720198721198722198723198724198725198726198727198728198729198730198731198732198733198734198735198736198737198738198739198740198741198742198743198744198745198746198747198748198749198750198751198752198753198754198755198756198757198758198759198760198761198762198763198764198765198766198767198768198769198770198771198772198773198774198775198776198777198778198779198780198781198782198783198784198785198786198787198788198789198790198791198792198793198794198795198796198797198798198799198800198801198802198803198804198805198806198807198808198809198810198811198812198813198814198815198816198817198818198819198820198821198822198823198824198825198826198827198828198829198830198831198832198833198834198835198836198837198838198839198840198841198842198843198844198845198846198847198848198849198850198851198852198853198854198855198856198857198858198859198860198861198862198863198864198865198866198867198868198869198870198871198872198873198874198875198876198877198878198879198880198881198882198883198884198885198886198887198888198889198890198891198892198893198894198895198896198897198898198899198900198901198902198903198904198905198906198907198908198909198910198911198912198913198914198915198916198917198918198919198920198921198922198923198924198925198926198927198928198929198930198931198932198933198934198935198936198937198938198939198940198941198942198943198944198945198946198947198948198949198950198951198952198953198954198955198956198957198958198959198960198961198962198963198964198965198966198967198968198969198970198971198972198973198974198975198976198977198978198979198980198981198982198983198984198985198986198987198988198989198990198991198992198993198994198995198996198997198998198999199000199001199002199003199004199005199006199007199008199009199010199011199012199013199014199015199016199017199018199019199020199021199022199023199024199025199026199027199028199029199030199031199032199033199034199035199036199037199038199039199040199041199042199043199044199045199046199047199048199049199050199051199052199053199054199055199056199057199058199059199060199061199062199063199064199065199066199067199068199069199070199071199072199073199074199075199076199077199078199079199080199081199082199083199084199085199086199087199088199089199090199091199092199093199094199095199096199097199098199099199100199101199102199103199104199105199106199107199108199109199110199111199112199113199114199115199116199117199118199119199120199121199122199123199124199125199126199127199128199129199130199131199132199133199134199135199136199137199138199139199140199141199142199143199144199145199146199147199148199149199150199151199152199153199154199155199156199157199158199159199160199161199162199163199164199165199166199167199168199169199170199171199172199173199174199175199176199177199178199179199180199181199182199183199184199185199186199187199188199189199190199191199192199193199194199195199196199197199198199199199200199201199202199203199204199205199206199207199208199209199210199211199212199213199214199215199216199217199218199219199220199221199222199223199224199225199226199227199228199229199230199231199232199233199234199235199236199237199238199239199240199241199242199243199244199245199246199247199248199249199250199251199252199253199254199255199256199257199258199259199260199261199262199263199264199265199266199267199268199269199270199271199272199273199274199275199276199277199278199279199280199281199282199283199284199285199286199287199288199289199290199291199292199293199294199295199296199297199298199299199300199301199302199303199304199305199306199307199308199309199310199311199312199313199314199315199316199317199318199319199320199321199322199323199324199325199326199327199328199329199330199331199332199333199334199335199336199337199338199339199340199341199342199343199344199345199346199347199348199349199350199351199352199353199354199355199356199357199358199359199360199361199362199363199364199365199366199367199368199369199370199371199372199373199374199375199376199377199378199379199380199381199382199383199384199385199386199387199388199389199390199391199392199393199394199395199396199397199398199399199400199401199402199403199404199405199406199407199408199409199410199411199412199413199414199415199416199417199418199419199420199421199422199423199424199425199426199427199428199429199430199431199432199433199434199435199436199437199438199439199440199441199442199443199444199445199446199447199448199449199450199451199452199453199454199455199456199457199458199459199460199461199462199463199464199465199466199467199468199469199470199471199472199473199474199475199476199477199478199479199480199481199482199483199484199485199486199487199488199489199490199491199492199493199494199495199496199497199498199499199500199501199502199503199504199505199506199507199508199509199510199511199512199513199514199515199516199517199518199519199520199521199522199523199524199525199526199527199528199529199530199531199532199533199534199535199536199537199538199539199540199541199542199543199544199545199546199547199548199549199550199551199552199553199554199555199556199557199558199559199560199561199562199563199564199565199566199567199568199569199570199571199572199573199574199575199576199577199578199579199580199581199582199583199584199585199586199587199588199589199590199591199592199593199594199595199596199597199598199599199600199601199602199603199604199605199606199607199608199609199610199611199612199613199614199615199616199617199618199619199620199621199622199623199624199625199626199627199628199629199630199631199632199633199634199635199636199637199638199639199640199641199642199643199644199645199646199647199648199649199650199651199652199653199654199655199656199657199658199659199660199661199662199663199664199665199666199667199668199669199670199671199672199673199674199675199676199677199678199679199680199681199682199683199684199685199686199687199688199689199690199691199692199693199694199695199696199697199698199699199700199701199702199703199704199705199706199707199708199709199710199711199712199713199714199715199716199717199718199719199720199721199722199723199724199725199726199727199728199729199730199731199732199733199734199735199736199737199738199739199740199741199742199743199744199745199746199747199748199749199750199751199752199753199754199755199756199757199758199759199760199761199762199763199764199765199766199767199768199769199770199771199772199773199774199775199776199777199778199779199780199781199782199783199784199785199786199787199788199789199790199791199792199793199794199795199796199797199798199799199800199801199802199803199804199805199806199807199808199809199810199811199812199813199814199815199816199817199818199819199820199821199822199823199824199825199826199827199828199829199830199831199832199833199834199835199836199837199838199839199840199841199842199843199844199845199846199847199848199849199850199851199852199853199854199855199856199857199858199859199860199861199862199863199864199865199866199867199868199869199870199871199872199873199874199875199876199877199878199879199880199881199882199883199884199885199886199887199888199889199890199891199892199893199894199895199896199897199898199899199900199901199902199903199904199905199906199907199908199909199910199911199912199913199914199915199916199917199918199919199920199921199922199923199924199925199926199927199928199929199930199931199932199933199934199935199936199937199938199939199940199941199942199943199944199945199946199947199948199949199950199951199952199953199954199955199956199957199958199959199960199961199962199963199964199965199966199967199968199969199970199971199972199973199974199975199976199977199978199979199980199981199982199983199984199985199986199987199988199989199990199991199992199993199994199995199996199997199998199999200000200001200002200003200004200005200006200007200008200009200010200011200012200013200014200015200016200017200018200019200020200021200022200023200024200025200026200027200028200029200030200031200032200033200034200035200036200037200038200039200040200041200042200043200044200045200046200047200048200049200050200051200052200053200054200055200056200057200058200059200060200061200062200063200064200065200066200067200068200069200070200071200072200073200074200075200076200077200078200079200080200081200082200083200084200085200086200087200088200089200090200091200092200093200094200095200096200097200098200099200100200101200102200103200104200105200106200107200108200109200110200111200112200113200114200115200116200117200118200119200120200121200122200123200124200125200126200127200128200129200130200131200132200133200134200135200136200137200138200139200140200141200142200143200144200145200146200147200148200149200150200151200152200153200154200155200156200157200158200159200160200161200162200163200164200165200166200167200168200169200170200171200172200173200174200175200176200177200178200179200180200181200182200183200184200185200186200187200188200189200190200191200192200193200194200195200196200197200198200199200200200201200202200203200204200205200206200207200208200209200210200211200212200213200214200215200216200217200218200219200220200221200222200223200224200225200226200227200228200229200230200231200232200233200234200235200236200237200238200239200240200241200242200243200244200245200246200247200248200249200250200251200252200253200254200255200256200257200258200259200260200261200262200263200264200265200266200267200268200269200270200271200272200273200274200275200276200277200278200279200280200281200282200283200284200285200286200287200288200289200290200291200292200293200294200295200296200297200298200299200300200301200302200303200304200305200306200307200308200309200310200311200312200313200314200315200316200317200318200319200320200321200322200323200324200325200326200327200328200329200330200331200332200333200334200335200336200337200338200339200340200341200342200343200344200345200346200347200348200349200350200351200352200353200354200355200356200357200358200359200360200361200362200363200364200365200366200367200368200369200370200371200372200373200374200375200376200377200378200379200380200381200382200383200384200385200386200387200388200389200390200391200392200393200394200395200396200397200398200399200400200401200402200403200404200405200406200407200408200409200410200411200412200413200414200415200416200417200418200419200420200421200422200423200424200425200426200427200428200429200430200431200432200433200434200435200436200437200438200439200440200441200442200443200444200445200446200447200448200449200450200451200452200453200454200455200456200457200458200459200460200461200462200463200464200465200466200467200468200469200470200471200472200473200474200475200476200477200478200479200480200481200482200483200484200485200486200487200488200489200490200491200492200493200494200495200496200497200498200499200500200501200502200503200504200505200506200507200508200509200510200511200512200513200514200515200516200517200518200519200520200521200522200523200524200525200526200527200528200529200530200531200532200533200534200535200536200537200538200539200540200541200542200543200544200545200546200547200548200549200550200551200552200553200554200555200556200557200558200559200560200561200562200563200564200565200566200567200568200569200570200571200572200573200574200575200576200577200578200579200580200581200582200583200584200585200586200587200588200589200590200591200592200593200594200595200596200597200598200599200600200601200602200603200604200605200606200607200608200609200610200611200612200613200614200615200616200617200618200619200620200621200622200623200624200625200626200627200628200629200630200631200632200633200634200635200636200637200638200639200640200641200642200643200644200645200646200647200648200649200650200651200652200653200654200655200656200657200658200659200660200661200662200663200664200665200666200667200668200669200670200671200672200673200674200675200676200677200678200679200680200681200682200683200684200685200686200687200688200689200690200691200692200693200694200695200696200697200698200699200700200701200702200703200704200705200706200707200708200709200710200711200712200713200714200715200716200717200718200719200720200721200722200723200724200725200726200727200728200729200730200731200732200733200734200735200736200737200738200739200740200741200742200743200744200745200746200747200748200749200750200751200752200753200754200755200756200757200758200759200760200761200762200763200764200765200766200767200768200769200770200771200772200773200774200775200776200777200778200779200780200781200782200783200784200785200786200787200788200789200790200791200792200793200794200795200796200797200798200799200800200801200802200803200804200805200806200807200808200809200810200811200812200813200814200815200816200817200818200819200820200821200822200823200824200825200826200827200828200829200830200831200832200833200834200835200836200837200838200839200840200841200842200843200844200845200846200847200848200849200850200851200852200853200854200855200856200857200858200859200860200861200862200863200864200865200866200867200868200869200870200871200872200873200874200875200876200877200878200879200880200881200882200883200884200885200886200887200888200889200890200891200892200893200894200895200896200897200898200899200900200901200902200903200904200905200906200907200908200909200910200911200912200913200914200915200916200917200918200919200920200921200922200923200924200925200926200927200928200929200930200931200932200933200934200935200936200937200938200939200940200941200942200943200944200945200946200947200948200949200950200951200952200953200954200955200956200957200958200959200960200961200962200963200964200965200966200967200968200969200970200971200972200973200974200975200976200977200978200979200980200981200982200983200984200985200986200987200988200989200990200991200992200993200994200995200996200997200998200999201000201001201002201003201004201005201006201007201008201009201010201011201012201013201014201015201016201017201018201019201020201021201022201023201024201025201026201027201028201029201030201031201032201033201034201035201036201037201038201039201040201041201042201043201044201045201046201047201048201049201050201051201052201053201054201055201056201057201058201059201060201061201062201063201064201065201066201067201068201069201070201071201072201073201074201075201076201077201078201079201080201081201082201083201084201085201086201087201088201089201090201091201092201093201094201095201096201097201098201099201100201101201102201103201104201105201106201107201108201109201110201111201112201113201114201115201116201117201118201119201120201121201122201123201124201125201126201127201128201129201130201131201132201133201134201135201136201137201138201139201140201141201142201143201144201145201146201147201148201149201150201151201152201153201154201155201156201157201158201159201160201161201162201163201164201165201166201167201168201169201170201171201172201173201174201175201176201177201178201179201180201181201182201183201184201185201186201187201188201189201190201191201192201193201194201195201196201197201198201199201200201201201202201203201204201205201206201207201208201209201210201211201212201213201214201215201216201217201218201219201220201221201222201223201224201225201226201227201228201229201230201231201232201233201234201235201236201237201238201239201240201241201242201243201244201245201246201247201248201249201250201251201252201253201254201255201256201257201258201259201260201261201262201263201264201265201266201267201268201269201270201271201272201273201274201275201276201277201278201279201280201281201282201283201284201285201286201287201288201289201290201291201292201293201294201295201296201297201298201299201300201301201302201303201304201305201306201307201308201309201310201311201312201313201314201315201316201317201318201319201320201321201322201323201324201325201326201327201328201329201330201331201332201333201334201335201336201337201338201339201340201341201342201343201344201345201346201347201348201349201350201351201352201353201354201355201356201357201358201359201360201361201362201363201364201365201366201367201368201369201370201371201372201373201374201375201376201377201378201379201380201381201382201383201384201385201386201387201388201389201390201391201392201393201394201395201396201397201398201399201400201401201402201403201404201405201406201407201408201409201410201411201412201413201414201415201416201417201418201419201420201421201422201423201424201425201426201427201428201429201430201431201432201433201434201435201436201437201438201439201440201441201442201443201444201445201446201447201448201449201450201451201452201453201454201455201456201457201458201459201460201461201462201463201464201465201466201467201468201469201470201471201472201473201474201475201476201477201478201479201480201481201482201483201484201485201486201487201488201489201490201491201492201493201494201495201496201497201498201499201500201501201502201503201504201505201506201507201508201509201510201511201512201513201514201515201516201517201518201519201520201521201522201523201524201525201526201527201528201529201530201531201532201533201534201535201536201537201538201539201540201541201542201543201544201545201546201547201548201549201550201551201552201553201554201555201556201557201558201559201560201561201562201563201564201565201566201567201568201569201570201571201572201573201574201575201576201577201578201579201580201581201582201583201584201585201586201587201588201589201590201591201592201593201594201595201596201597201598201599201600201601201602201603201604201605201606201607201608201609201610201611201612201613201614201615201616201617201618201619201620201621201622201623201624201625201626201627201628201629201630201631201632201633201634201635201636201637201638201639201640201641201642201643201644201645201646201647201648201649201650201651201652201653201654201655201656201657201658201659201660201661201662201663201664201665201666201667201668201669201670201671201672201673201674201675201676201677201678201679201680201681201682201683201684201685201686201687201688201689201690201691201692201693201694201695201696201697201698201699201700201701201702201703201704201705201706201707201708201709201710201711201712201713201714201715201716201717201718201719201720201721201722201723201724201725201726201727201728201729201730201731201732201733201734201735201736201737201738201739201740201741201742201743201744201745201746201747201748201749201750201751201752201753201754201755201756201757201758201759201760201761201762201763201764201765201766201767201768201769201770201771201772201773201774201775201776201777201778201779201780201781201782201783201784201785201786201787201788201789201790201791201792201793201794201795201796201797201798201799201800201801201802201803201804201805201806201807201808201809201810201811201812201813201814201815201816201817201818201819201820201821201822201823201824201825201826201827201828201829201830201831201832201833201834201835201836201837201838201839201840201841201842201843201844201845201846201847201848201849201850201851201852201853201854201855201856201857201858201859201860201861201862201863201864201865201866201867201868201869201870201871201872201873201874201875201876201877201878201879201880201881201882201883201884201885201886201887201888201889201890201891201892201893201894201895201896201897201898201899201900201901201902201903201904201905201906201907201908201909201910201911201912201913201914201915201916201917201918201919201920201921201922201923201924201925201926201927201928201929201930201931201932201933201934201935201936201937201938201939201940201941201942201943201944201945201946201947201948201949201950201951201952201953201954201955201956201957201958201959201960201961201962201963201964201965201966201967201968201969201970201971201972201973201974201975201976201977201978201979201980201981201982201983201984201985201986201987201988201989201990201991201992201993201994201995201996201997201998201999202000202001202002202003202004202005202006202007202008202009202010202011202012202013202014202015202016202017202018202019202020202021202022202023202024202025202026202027202028202029202030202031202032202033202034202035202036202037202038202039202040202041202042202043202044202045202046202047202048202049202050202051202052202053202054202055202056202057202058202059202060202061202062202063202064202065202066202067202068202069202070202071202072202073202074202075202076202077202078202079202080202081202082202083202084202085202086202087202088202089202090202091202092202093202094202095202096202097202098202099202100202101202102202103202104202105202106202107202108202109202110202111202112202113202114202115202116202117202118202119202120202121202122202123202124202125202126202127202128202129202130202131202132202133202134202135202136202137202138202139202140202141202142202143202144202145202146202147202148202149202150202151202152202153202154202155202156202157202158202159202160202161202162202163202164202165202166202167202168202169202170202171202172202173202174202175202176202177202178202179202180202181202182202183202184202185202186202187202188202189202190202191202192202193202194202195202196202197202198202199202200202201202202202203202204202205202206202207202208202209202210202211202212202213202214202215202216202217202218202219202220202221202222202223202224202225202226202227202228202229202230202231202232202233202234202235202236202237202238202239202240202241202242202243202244202245202246202247202248202249202250202251202252202253202254202255202256202257202258202259202260202261202262202263202264202265202266202267202268202269202270202271202272202273202274202275202276202277202278202279202280202281202282202283202284202285202286202287202288202289202290202291202292202293202294202295202296202297202298202299202300202301202302202303202304202305202306202307202308202309202310202311202312202313202314202315202316202317202318202319202320202321202322202323202324202325202326202327202328202329202330202331202332202333202334202335202336202337202338202339202340202341202342202343202344202345202346202347202348202349202350202351202352202353202354202355202356202357202358202359202360202361202362202363202364202365202366202367202368202369202370202371202372202373202374202375202376202377202378202379202380202381202382202383202384202385202386202387202388202389202390202391202392202393202394202395202396202397202398202399202400202401202402202403202404202405202406202407202408202409202410202411202412202413202414202415202416202417202418202419202420202421202422202423202424202425202426202427202428202429202430202431202432202433202434202435202436202437202438202439202440202441202442202443202444202445202446202447202448202449202450202451202452202453202454202455202456202457202458202459202460202461202462202463202464202465202466202467202468202469202470202471202472202473202474202475202476202477202478202479202480202481202482202483202484202485202486202487202488202489202490202491202492202493202494202495202496202497202498202499202500202501202502202503202504202505202506202507202508202509202510202511202512202513202514202515202516202517202518202519202520202521202522202523202524202525202526202527202528202529202530202531202532202533202534202535202536202537202538202539202540202541202542202543202544202545202546202547202548202549202550202551202552202553202554202555202556202557202558202559202560202561202562202563202564202565202566202567202568202569202570202571202572202573202574202575202576202577202578202579202580202581202582202583202584202585202586202587202588202589202590202591202592202593202594202595202596202597202598202599202600202601202602202603202604202605202606202607202608202609202610202611202612202613202614202615202616202617202618202619202620202621202622202623202624202625202626202627202628202629202630202631202632202633202634202635202636202637202638202639202640202641202642202643202644202645202646202647202648202649202650202651202652202653202654202655202656202657202658202659202660202661202662202663202664202665202666202667202668202669202670202671202672202673202674202675202676202677202678202679202680202681202682202683202684202685202686202687202688202689202690202691202692202693202694202695202696202697202698202699202700202701202702202703202704202705202706202707202708202709202710202711202712202713202714202715202716202717202718202719202720202721202722202723202724202725202726202727202728202729202730202731202732202733202734202735202736202737202738202739202740202741202742202743202744202745202746202747202748202749202750202751202752202753202754202755202756202757202758202759202760202761202762202763202764202765202766202767202768202769202770202771202772202773202774202775202776202777202778202779202780202781202782202783202784202785202786202787202788202789202790202791202792202793202794202795202796202797202798202799202800202801202802202803202804202805202806202807202808202809202810202811202812202813202814202815202816202817202818202819202820202821202822202823202824202825202826202827202828202829202830202831202832202833202834202835202836202837202838202839202840202841202842202843202844202845202846202847202848202849202850202851202852202853202854202855202856202857202858202859202860202861202862202863202864202865202866202867202868202869202870202871202872202873202874202875202876202877202878202879202880202881202882202883202884202885202886202887202888202889202890202891202892202893202894202895202896202897202898202899202900202901202902202903202904202905202906202907202908202909202910202911202912202913202914202915202916202917202918202919202920202921202922202923202924202925202926202927202928202929202930202931202932202933202934202935202936202937202938202939202940202941202942202943202944202945202946202947202948202949202950202951202952202953202954202955202956202957202958202959202960202961202962202963202964202965202966202967202968202969202970202971202972202973202974202975202976202977202978202979202980202981202982202983202984202985202986202987202988202989202990202991202992202993202994202995202996202997202998202999203000203001203002203003203004203005203006203007203008203009203010203011203012203013203014203015203016203017203018203019203020203021203022203023203024203025203026203027203028203029203030203031203032203033203034203035203036203037203038203039203040203041203042203043203044203045203046203047203048203049203050203051203052203053203054203055203056203057203058203059203060203061203062203063203064203065203066203067203068203069203070203071203072203073203074203075203076203077203078203079203080203081203082203083203084203085203086203087203088203089203090203091203092203093203094203095203096203097203098203099203100203101203102203103203104203105203106203107203108203109203110203111203112203113203114203115203116203117203118203119203120203121203122203123203124203125203126203127203128203129203130203131203132203133203134203135203136203137203138203139203140203141203142203143203144203145203146203147203148203149203150203151203152203153203154203155203156203157203158203159203160203161203162203163203164203165203166203167203168203169203170203171203172203173203174203175203176203177203178203179203180203181203182203183203184203185203186203187203188203189203190203191203192203193203194203195203196203197203198203199203200203201203202203203203204203205203206203207203208203209203210203211203212203213203214203215203216203217203218203219203220203221203222203223203224203225203226203227203228203229203230203231203232203233203234203235203236203237203238203239203240203241203242203243203244203245203246203247203248203249203250203251203252203253203254203255203256203257203258203259203260203261203262203263203264203265203266203267203268203269203270203271203272203273203274203275203276203277203278203279203280203281203282203283203284203285203286203287203288203289203290203291203292203293203294203295203296203297203298203299203300203301203302203303203304203305203306203307203308203309203310203311203312203313203314203315203316203317203318203319203320203321203322203323203324203325203326203327203328203329203330203331203332203333203334203335203336203337203338203339203340203341203342203343203344203345203346203347203348203349203350203351203352203353203354203355203356203357203358203359203360203361203362203363203364203365203366203367203368203369203370203371203372203373203374203375203376203377203378203379203380203381203382203383203384203385203386203387203388203389203390203391203392203393203394203395203396203397203398203399203400203401203402203403203404203405203406203407203408203409203410203411203412203413203414203415203416203417203418203419203420203421203422203423203424203425203426203427203428203429203430203431203432203433203434203435203436203437203438203439203440203441203442203443203444203445203446203447203448203449203450203451203452203453203454203455203456203457203458203459203460203461203462203463203464203465203466203467203468203469203470203471203472203473203474203475203476203477203478203479203480203481203482203483203484203485203486203487203488203489203490203491203492203493203494203495203496203497203498203499203500203501203502203503203504203505203506203507203508203509203510203511203512203513203514203515203516203517203518203519203520203521203522203523203524203525203526203527203528203529203530203531203532203533203534203535203536203537203538203539203540203541203542203543203544203545203546203547203548203549203550203551203552203553203554203555203556203557203558203559203560203561203562203563203564203565203566203567203568203569203570203571203572203573203574203575203576203577203578203579203580203581203582203583203584203585203586203587203588203589203590203591203592203593203594203595203596203597203598203599203600203601203602203603203604203605203606203607203608203609203610203611203612203613203614203615203616203617203618203619203620203621203622203623203624203625203626203627203628203629203630203631203632203633203634203635203636203637203638203639203640203641203642203643203644203645203646203647203648203649203650203651203652203653203654203655203656203657203658203659203660203661203662203663203664203665203666203667203668203669203670203671203672203673203674203675203676203677203678203679203680203681203682203683203684203685203686203687203688203689203690203691203692203693203694203695203696203697203698203699203700203701203702203703203704203705203706203707203708203709203710203711203712203713203714203715203716203717203718203719203720203721203722203723203724203725203726203727203728203729203730203731203732203733203734203735203736203737203738203739203740203741203742203743203744203745203746203747203748203749203750203751203752203753203754203755203756203757203758203759203760203761203762203763203764203765203766203767203768203769203770203771203772203773203774203775203776203777203778203779203780203781203782203783203784203785203786203787203788203789203790203791203792203793203794203795203796203797203798203799203800203801203802203803203804203805203806203807203808203809203810203811203812203813203814203815203816203817203818203819203820203821203822203823203824203825203826203827203828203829203830203831203832203833203834203835203836203837203838203839203840203841203842203843203844203845203846203847203848203849203850203851203852203853203854203855203856203857203858203859203860203861203862203863203864203865203866203867203868203869203870203871203872203873203874203875203876203877203878203879203880203881203882203883203884203885203886203887203888203889203890203891203892203893203894203895203896203897203898203899203900203901203902203903203904203905203906203907203908203909203910203911203912203913203914203915203916203917203918203919203920203921203922203923203924203925203926203927203928203929203930203931203932203933203934203935203936203937203938203939203940203941203942203943203944203945203946203947203948203949203950203951203952203953203954203955203956203957203958203959203960203961203962203963203964203965203966203967203968203969203970203971203972203973203974203975203976203977203978203979203980203981203982203983203984203985203986203987203988203989203990203991203992203993203994203995203996203997203998203999204000204001204002204003204004204005204006204007204008204009204010204011204012204013204014204015204016204017204018204019204020204021204022204023204024204025204026204027204028204029204030204031204032204033204034204035204036204037204038204039204040204041204042204043204044204045204046204047204048204049204050204051204052204053204054204055204056204057204058204059204060204061204062204063204064204065204066204067204068204069204070204071204072204073204074204075204076204077204078204079204080204081204082204083204084204085204086204087204088204089204090204091204092204093204094204095204096204097204098204099204100204101204102204103204104204105204106204107204108204109204110204111204112204113204114204115204116204117204118204119204120204121204122204123204124204125204126204127204128204129204130204131204132204133204134204135204136204137204138204139204140204141204142204143204144204145204146204147204148204149204150204151204152204153204154204155204156204157204158204159204160204161204162204163204164204165204166204167204168204169204170204171204172204173204174204175204176204177204178204179204180204181204182204183204184204185204186204187204188204189204190204191204192204193204194204195204196204197204198204199204200204201204202204203204204204205204206204207204208204209204210204211204212204213204214204215204216204217204218204219204220204221204222204223204224204225204226204227204228204229204230204231204232204233204234204235204236204237204238204239204240204241204242204243204244204245204246204247204248204249204250204251204252204253204254204255204256204257204258204259204260204261204262204263204264204265204266204267204268204269204270204271204272204273204274204275204276204277204278204279204280204281204282204283204284204285204286204287204288204289204290204291204292204293204294204295204296204297204298204299204300204301204302204303204304204305204306204307204308204309204310204311204312204313204314204315204316204317204318204319204320204321204322204323204324204325204326204327204328204329204330204331204332204333204334204335204336204337204338204339204340204341204342204343204344204345204346204347204348204349204350204351204352204353204354204355204356204357204358204359204360204361204362204363204364204365204366204367204368204369204370204371204372204373204374204375204376204377204378204379204380204381204382204383204384204385204386204387204388204389204390204391204392204393204394204395204396204397204398204399204400204401204402204403204404204405204406204407204408204409204410204411204412204413204414204415204416204417204418204419204420204421204422204423204424204425204426204427204428204429204430204431204432204433204434204435204436204437204438204439204440204441204442204443204444204445204446204447204448204449204450204451204452204453204454204455204456204457204458204459204460204461204462204463204464204465204466204467204468204469204470204471204472204473204474204475204476204477204478204479204480204481204482204483204484204485204486204487204488204489204490204491204492204493204494204495204496204497204498204499204500204501204502204503204504204505204506204507204508204509204510204511204512204513204514204515204516204517204518204519204520204521204522204523204524204525204526204527204528204529204530204531204532204533204534204535204536204537204538204539204540204541204542204543204544204545204546204547204548204549204550204551204552204553204554204555204556204557204558204559204560204561204562204563204564204565204566204567204568204569204570204571204572204573204574204575204576204577204578204579204580204581204582204583204584204585204586204587204588204589204590204591204592204593204594204595204596204597204598204599204600204601204602204603204604204605204606204607204608204609204610204611204612204613204614204615204616204617204618204619204620204621204622204623204624204625204626204627204628204629204630204631204632204633204634204635204636204637204638204639204640204641204642204643204644204645204646204647204648204649204650204651204652204653204654204655204656204657204658204659204660204661204662204663204664204665204666204667204668204669204670204671204672204673204674204675204676204677204678204679204680204681204682204683204684204685204686204687204688204689204690204691204692204693204694204695204696204697204698204699204700204701204702204703204704204705204706204707204708204709204710204711204712204713204714204715204716204717204718204719204720204721204722204723204724204725204726204727204728204729204730204731204732204733204734204735204736204737204738204739204740204741204742204743204744204745204746204747204748204749204750204751204752204753204754204755204756204757204758204759204760204761204762204763204764204765204766204767204768204769204770204771204772204773204774204775204776204777204778204779204780204781204782204783204784204785204786204787204788204789204790204791204792204793204794204795204796204797204798204799204800204801204802204803204804204805204806204807204808204809204810204811204812204813204814204815204816204817204818204819204820204821204822204823204824204825204826204827204828204829204830204831204832204833204834204835204836204837204838204839204840204841204842204843204844204845204846204847204848204849204850204851204852204853204854204855204856204857204858204859204860204861204862204863204864204865204866204867204868204869204870204871204872204873204874204875204876204877204878204879204880204881204882204883204884204885204886204887204888204889204890204891204892204893204894204895204896204897204898204899204900204901204902204903204904204905204906204907204908204909204910204911204912204913204914204915204916204917204918204919204920204921204922204923204924204925204926204927204928204929204930204931204932204933204934204935204936204937204938204939204940204941204942204943204944204945204946204947204948204949204950204951204952204953204954204955204956204957204958204959204960204961204962204963204964204965204966204967204968204969204970204971204972204973204974204975204976204977204978204979204980204981204982204983204984204985204986204987204988204989204990204991204992204993204994204995204996204997204998204999205000205001205002205003205004205005205006205007205008205009205010205011205012205013205014205015205016205017205018205019205020205021205022205023205024205025205026205027205028205029205030205031205032205033205034205035205036205037205038205039205040205041205042205043205044205045205046205047205048205049205050205051205052205053205054205055205056205057205058205059205060205061205062205063205064205065205066205067205068205069205070205071205072205073205074205075205076205077205078205079205080205081205082205083205084205085205086205087205088205089205090205091205092205093205094205095205096205097205098205099205100205101205102205103205104205105205106205107205108205109205110205111205112205113205114205115205116205117205118205119205120205121205122205123205124205125205126205127205128205129205130205131205132205133205134205135205136205137205138205139205140205141205142205143205144205145205146205147205148205149205150205151205152205153205154205155205156205157205158205159205160205161205162205163205164205165205166205167205168205169205170205171205172205173205174205175205176205177205178205179205180205181205182205183205184205185205186205187205188205189205190205191205192205193205194205195205196205197205198205199205200205201205202205203205204205205205206205207205208205209205210205211205212205213205214205215205216205217205218205219205220205221205222205223205224205225205226205227205228205229205230205231205232205233205234205235205236205237205238205239205240205241205242205243205244205245205246205247205248205249205250205251205252205253205254205255205256205257205258205259205260205261205262205263205264205265205266205267205268205269205270205271205272205273205274205275205276205277205278205279205280205281205282205283205284205285205286205287205288205289205290205291205292205293205294205295205296205297205298205299205300205301205302205303205304205305205306205307205308205309205310205311205312205313205314205315205316205317205318205319205320205321205322205323205324205325205326205327205328205329205330205331205332205333205334205335205336205337205338205339205340205341205342205343205344205345205346205347205348205349205350205351205352205353205354205355205356205357205358205359205360205361205362205363205364205365205366205367205368205369205370205371205372205373205374205375205376205377205378205379205380205381205382205383205384205385205386205387205388205389205390205391205392205393205394205395205396205397205398205399205400205401205402205403205404205405205406205407205408205409205410205411205412205413205414205415205416205417205418205419205420205421205422205423205424205425205426205427205428205429205430205431205432205433205434205435205436205437205438205439205440205441205442205443205444205445205446205447205448205449205450205451205452205453205454205455205456205457205458205459205460205461205462205463205464205465205466205467205468205469205470205471205472205473205474205475205476205477205478205479205480205481205482205483205484205485205486205487205488205489205490205491205492205493205494205495205496205497205498205499205500205501205502205503205504205505205506205507205508205509205510205511205512205513205514205515205516205517205518205519205520205521205522205523205524205525205526205527205528205529205530205531205532205533205534205535205536205537205538205539205540205541205542205543205544205545205546205547205548205549205550205551205552205553205554205555205556205557205558205559205560205561205562205563205564205565205566205567205568205569205570205571205572205573205574205575205576205577205578205579205580205581205582205583205584205585205586205587205588205589205590205591205592205593205594205595205596205597205598205599205600205601205602205603205604205605205606205607205608205609205610205611205612205613205614205615205616205617205618205619205620205621205622205623205624205625205626205627205628205629205630205631205632205633205634205635205636205637205638205639205640205641205642205643205644205645205646205647205648205649205650205651205652205653205654205655205656205657205658205659205660205661205662205663205664205665205666205667205668205669205670205671205672205673205674205675205676205677205678205679205680205681205682205683205684205685205686205687205688205689205690205691205692205693205694205695205696205697205698205699205700205701205702205703205704205705205706205707205708205709205710205711205712205713205714205715205716205717205718205719205720205721205722205723205724205725205726205727205728205729205730205731205732205733205734205735205736205737205738205739205740205741205742205743205744205745205746205747205748205749205750205751205752205753205754205755205756205757205758205759205760205761205762205763205764205765205766205767205768205769205770205771205772205773205774205775205776205777205778205779205780205781205782205783205784205785205786205787205788205789205790205791205792205793205794205795205796205797205798205799205800205801205802205803205804205805205806205807205808205809205810205811205812205813205814205815205816205817205818205819205820205821205822205823205824205825205826205827205828205829205830205831205832205833205834205835205836205837205838205839205840205841205842205843205844205845205846205847205848205849205850205851205852205853205854205855205856205857205858205859205860205861205862205863205864205865205866205867205868205869205870205871205872205873205874205875205876205877205878205879205880205881205882205883205884205885205886205887205888205889205890205891205892205893205894205895205896205897205898205899205900205901205902205903205904205905205906205907205908205909205910205911205912205913205914205915205916205917205918205919205920205921205922205923205924205925205926205927205928205929205930205931205932205933205934205935205936205937205938205939205940205941205942205943205944205945205946205947205948205949205950205951205952205953205954205955205956205957205958205959205960205961205962205963205964205965205966205967205968205969205970205971205972205973205974205975205976205977205978205979205980205981205982205983205984205985205986205987205988205989205990205991205992205993205994205995205996205997205998205999206000206001206002206003206004206005206006206007206008206009206010206011206012206013206014206015206016206017206018206019206020206021206022206023206024206025206026206027206028206029206030206031206032206033206034206035206036206037206038206039206040206041206042206043206044206045206046206047206048206049206050206051206052206053206054206055206056206057206058206059206060206061206062206063206064206065206066206067206068206069206070206071206072206073206074206075206076206077206078206079206080206081206082206083206084206085206086206087206088206089206090206091206092206093206094206095206096206097206098206099206100206101206102206103206104206105206106206107206108206109206110206111206112206113206114206115206116206117206118206119206120206121206122206123206124206125206126206127206128206129206130206131206132206133206134206135206136206137206138206139206140206141206142206143206144206145206146206147206148206149206150206151206152206153206154206155206156206157206158206159206160206161206162206163206164206165206166206167206168206169206170206171206172206173206174206175206176206177206178206179206180206181206182206183206184206185206186206187206188206189206190206191206192206193206194206195206196206197206198206199206200206201206202206203206204206205206206206207206208206209206210206211206212206213206214206215206216206217206218206219206220206221206222206223206224206225206226206227206228206229206230206231206232206233206234206235206236206237206238206239206240206241206242206243206244206245206246206247206248206249206250206251206252206253206254206255206256206257206258206259206260206261206262206263206264206265206266206267206268206269206270206271206272206273206274206275206276206277206278206279206280206281206282206283206284206285206286206287206288206289206290206291206292206293206294206295206296206297206298206299206300206301206302206303206304206305206306206307206308206309206310206311206312206313206314206315206316206317206318206319206320206321206322206323206324206325206326206327206328206329206330206331206332206333206334206335206336206337206338206339206340206341206342206343206344206345206346206347206348206349206350206351206352206353206354206355206356206357206358206359206360206361206362206363206364206365206366206367206368206369206370206371206372206373206374206375206376206377206378206379206380206381206382206383206384206385206386206387206388206389206390206391206392206393206394206395206396206397206398206399206400206401206402206403206404206405206406206407206408206409206410206411206412206413206414206415206416206417206418206419206420206421206422206423206424206425206426206427206428206429206430206431206432206433206434206435206436206437206438206439206440206441206442206443206444206445206446206447206448206449206450206451206452206453206454206455206456206457206458206459206460206461206462206463206464206465206466206467206468206469206470206471206472206473206474206475206476206477206478206479206480206481206482206483206484206485206486206487206488206489206490206491206492206493206494206495206496206497206498206499206500206501206502206503206504206505206506206507206508206509206510206511206512206513206514206515206516206517206518206519206520206521206522206523206524206525206526206527206528206529206530206531206532206533206534206535206536206537206538206539206540206541206542206543206544206545206546206547206548206549206550206551206552206553206554206555206556206557206558206559206560206561206562206563206564206565206566206567206568206569206570206571206572206573206574206575206576206577206578206579206580206581206582206583206584206585206586206587206588206589206590206591206592206593206594206595206596206597206598206599206600206601206602206603206604206605206606206607206608206609206610206611206612206613206614206615206616206617206618206619206620206621206622206623206624206625206626206627206628206629206630206631206632206633206634206635206636206637206638206639206640206641206642206643206644206645206646206647206648206649206650206651206652206653206654206655206656206657206658206659206660206661206662206663206664206665206666206667206668206669206670206671206672206673206674206675206676206677206678206679206680206681206682206683206684206685206686206687206688206689206690206691206692206693206694206695206696206697206698206699206700206701206702206703206704206705206706206707206708206709206710206711206712206713206714206715206716206717206718206719206720206721206722206723206724206725206726206727206728206729206730206731206732206733206734206735206736206737206738206739206740206741206742206743206744206745206746206747206748206749206750206751206752206753206754206755206756206757206758206759206760206761206762206763206764206765206766206767206768206769206770206771206772206773206774206775206776206777206778206779206780206781206782206783206784206785206786206787206788206789206790206791206792206793206794206795206796206797206798206799206800206801206802206803206804206805206806206807206808206809206810206811206812206813206814206815206816206817206818206819206820206821206822206823206824206825206826206827206828206829206830206831206832206833206834206835206836206837206838206839206840206841206842206843206844206845206846206847206848206849206850206851206852206853206854206855206856206857206858206859206860206861206862206863206864206865206866206867206868206869206870206871206872206873206874206875206876206877206878206879206880206881206882206883206884206885206886206887206888206889206890206891206892206893206894206895206896206897206898206899206900206901206902206903206904206905206906206907206908206909206910206911206912206913206914206915206916206917206918206919206920206921206922206923206924206925206926206927206928206929206930206931206932206933206934206935206936206937206938206939206940206941206942206943206944206945206946206947206948206949206950206951206952206953206954206955206956206957206958206959206960206961206962206963206964206965206966206967206968206969206970206971206972206973206974206975206976206977206978206979206980206981206982206983206984206985206986206987206988206989206990206991206992206993206994206995206996206997206998206999207000207001207002207003207004207005207006207007207008207009207010207011207012207013207014207015207016207017207018207019207020207021207022207023207024207025207026207027207028207029207030207031207032207033207034207035207036207037207038207039207040207041207042207043207044207045207046207047207048207049207050207051207052207053207054207055207056207057207058207059207060207061207062207063207064207065207066207067207068207069207070207071207072207073207074207075207076207077207078207079207080207081207082207083207084207085207086207087207088207089207090207091207092207093207094207095207096207097207098207099207100207101207102207103207104207105207106207107207108207109207110207111207112207113207114207115207116207117207118207119207120207121207122207123207124207125207126207127207128207129207130207131207132207133207134207135207136207137207138207139207140207141207142207143207144207145207146207147207148207149207150207151207152207153207154207155207156207157207158207159207160207161207162207163207164207165207166207167207168207169207170207171207172207173207174207175207176207177207178207179207180207181207182207183207184207185207186207187207188207189207190207191207192207193207194207195207196207197207198207199207200207201207202207203207204207205207206207207207208207209207210207211207212207213207214207215207216207217207218207219207220207221207222207223207224207225207226207227207228207229207230207231207232207233207234207235207236207237207238207239207240207241207242207243207244207245207246207247207248207249207250207251207252207253207254207255207256207257207258207259207260207261207262207263207264207265207266207267207268207269207270207271207272207273207274207275207276207277207278207279207280207281207282207283207284207285207286207287207288207289207290207291207292207293207294207295207296207297207298207299207300207301207302207303207304207305207306207307207308207309207310207311207312207313207314207315207316207317207318207319207320207321207322207323207324207325207326207327207328207329207330207331207332207333207334207335207336207337207338207339207340207341207342207343207344207345207346207347207348207349207350207351207352207353207354207355207356207357207358207359207360207361207362207363207364207365207366207367207368207369207370207371207372207373207374207375207376207377207378207379207380207381207382207383207384207385207386207387207388207389207390207391207392207393207394207395207396207397207398207399207400207401207402207403207404207405207406207407207408207409207410207411207412207413207414207415207416207417207418207419207420207421207422207423207424207425207426207427207428207429207430207431207432207433207434207435207436207437207438207439207440207441207442207443207444207445207446207447207448207449207450207451207452207453207454207455207456207457207458207459207460207461207462207463207464207465207466207467207468207469207470207471207472207473207474207475207476207477207478207479207480207481207482207483207484207485207486207487207488207489207490207491207492207493207494207495207496207497207498207499207500207501207502207503207504207505207506207507207508207509207510207511207512207513207514207515207516207517207518207519207520207521207522207523207524207525207526207527207528207529207530207531207532207533207534207535207536207537207538207539207540207541207542207543207544207545207546207547207548207549207550207551207552207553207554207555207556207557207558207559207560207561207562207563207564207565207566207567207568207569207570207571207572207573207574207575207576207577207578207579207580207581207582207583207584207585207586207587207588207589207590207591207592207593207594207595207596207597207598207599207600207601207602207603207604207605207606207607207608207609207610207611207612207613207614207615207616207617207618207619207620207621207622207623207624207625207626207627207628207629207630207631207632207633207634207635207636207637207638207639207640207641207642207643207644207645207646207647207648207649207650207651207652207653207654207655207656207657207658207659207660207661207662207663207664207665207666207667207668207669207670207671207672207673207674207675207676207677207678207679207680207681207682207683207684207685207686207687207688207689207690207691207692207693207694207695207696207697207698207699207700207701207702207703207704207705207706207707207708207709207710207711207712207713207714207715207716207717207718207719207720207721207722207723207724207725207726207727207728207729207730207731207732207733207734207735207736207737207738207739207740207741207742207743207744207745207746207747207748207749207750207751207752207753207754207755207756207757207758207759207760207761207762207763207764207765207766207767207768207769207770207771207772207773207774207775207776207777207778207779207780207781207782207783207784207785207786207787207788207789207790207791207792207793207794207795207796207797207798207799207800207801207802207803207804207805207806207807207808207809207810207811207812207813207814207815207816207817207818207819207820207821207822207823207824207825207826207827207828207829207830207831207832207833207834207835207836207837207838207839207840207841207842207843207844207845207846207847207848207849207850207851207852207853207854207855207856207857207858207859207860207861207862207863207864207865207866207867207868207869207870207871207872207873207874207875207876207877207878207879207880207881207882207883207884207885207886207887207888207889207890207891207892207893207894207895207896207897207898207899207900207901207902207903207904207905207906207907207908207909207910207911207912207913207914207915207916207917207918207919207920207921207922207923207924207925207926207927207928207929207930207931207932207933207934207935207936207937207938207939207940207941207942207943207944207945207946207947207948207949207950207951207952207953207954207955207956207957207958207959207960207961207962207963207964207965207966207967207968207969207970207971207972207973207974207975207976207977207978207979207980207981207982207983207984207985207986207987207988207989207990207991207992207993207994207995207996207997207998207999208000208001208002208003208004208005208006208007208008208009208010208011208012208013208014208015208016208017208018208019208020208021208022208023208024208025208026208027208028208029208030208031208032208033208034208035208036208037208038208039208040208041208042208043208044208045208046208047208048208049208050208051208052208053208054208055208056208057208058208059208060208061208062208063208064208065208066208067208068208069208070208071208072208073208074208075208076208077208078208079208080208081208082208083208084208085208086208087208088208089208090208091208092208093208094208095208096208097208098208099208100208101208102208103208104208105208106208107208108208109208110208111208112208113208114208115208116208117208118208119208120208121208122208123208124208125208126208127208128208129208130208131208132208133208134208135208136208137208138208139208140208141208142208143208144208145208146208147208148208149208150208151208152208153208154208155208156208157208158208159208160208161208162208163208164208165208166208167208168208169208170208171208172208173208174208175208176208177208178208179208180208181208182208183208184208185208186208187208188208189208190208191208192208193208194208195208196208197208198208199208200208201208202208203208204208205208206208207208208208209208210208211208212208213208214208215208216208217208218208219208220208221208222208223208224208225208226208227208228208229208230208231208232208233208234208235208236208237208238208239208240208241208242208243208244208245208246208247208248208249208250208251208252208253208254208255208256208257208258208259208260208261208262208263208264208265208266208267208268208269208270208271208272208273208274208275208276208277208278208279208280208281208282208283208284208285208286208287208288208289208290208291208292208293208294208295208296208297208298208299208300208301208302208303208304208305208306208307208308208309208310208311208312208313208314208315208316208317208318208319208320208321208322208323208324208325208326208327208328208329208330208331208332208333208334208335208336208337208338208339208340208341208342208343208344208345208346208347208348208349208350208351208352208353208354208355208356208357208358208359208360208361208362208363208364208365208366208367208368208369208370208371208372208373208374208375208376208377208378208379208380208381208382208383208384208385208386208387208388208389208390208391208392208393208394208395208396208397208398208399208400208401208402208403208404208405208406208407208408208409208410208411208412208413208414208415208416208417208418208419208420208421208422208423208424208425208426208427208428208429208430208431208432208433208434208435208436208437208438208439208440208441208442208443208444208445208446208447208448208449208450208451208452208453208454208455208456208457208458208459208460208461208462208463208464208465208466208467208468208469208470208471208472208473208474208475208476208477208478208479208480208481208482208483208484208485208486208487208488208489208490208491208492208493208494208495208496208497208498208499208500208501208502208503208504208505208506208507208508208509208510208511208512208513208514208515208516208517208518208519208520208521208522208523208524208525208526208527208528208529208530208531208532208533208534208535208536208537208538208539208540208541208542208543208544208545208546208547208548208549208550208551208552208553208554208555208556208557208558208559208560208561208562208563208564208565208566208567208568208569208570208571208572208573208574208575208576208577208578208579208580208581208582208583208584208585208586208587208588208589208590208591208592208593208594208595208596208597208598208599208600208601208602208603208604208605208606208607208608208609208610208611208612208613208614208615208616208617208618208619208620208621208622208623208624208625208626208627208628208629208630208631208632208633208634208635208636208637208638208639208640208641208642208643208644208645208646208647208648208649208650208651208652208653208654208655208656208657208658208659208660208661208662208663208664208665208666208667208668208669208670208671208672208673208674208675208676208677208678208679208680208681208682208683208684208685208686208687208688208689208690208691208692208693208694208695208696208697208698208699208700208701208702208703208704208705208706208707208708208709208710208711208712208713208714208715208716208717208718208719208720208721208722208723208724208725208726208727208728208729208730208731208732208733208734208735208736208737208738208739208740208741208742208743208744208745208746208747208748208749208750208751208752208753208754208755208756208757208758208759208760208761208762208763208764208765208766208767208768208769208770208771208772208773208774208775208776208777208778208779208780208781208782208783208784208785208786208787208788208789208790208791208792208793208794208795208796208797208798208799208800208801208802208803208804208805208806208807208808208809208810208811208812208813208814208815208816208817208818208819208820208821208822208823208824208825208826208827208828208829208830208831208832208833208834208835208836208837208838208839208840208841208842208843208844208845208846208847208848208849208850208851208852208853208854208855208856208857208858208859208860208861208862208863208864208865208866208867208868208869208870208871208872208873208874208875208876208877208878208879208880208881208882208883208884208885208886208887208888208889208890208891208892208893208894208895208896208897208898208899208900208901208902208903208904208905208906208907208908208909208910208911208912208913208914208915208916208917208918208919208920208921208922208923208924208925208926208927208928208929208930208931208932208933208934208935208936208937208938208939208940208941208942208943208944208945208946208947208948208949208950208951208952208953208954208955208956208957208958208959208960208961208962208963208964208965208966208967208968208969208970208971208972208973208974208975208976208977208978208979208980208981208982208983208984208985208986208987208988208989208990208991208992208993208994208995208996208997208998208999209000209001209002209003209004209005209006209007209008209009209010209011209012209013209014209015209016209017209018209019209020209021209022209023209024209025209026209027209028209029209030209031209032209033209034209035209036209037209038209039209040209041209042209043209044209045209046209047209048209049209050209051209052209053209054209055209056209057209058209059209060209061209062209063209064209065209066209067209068209069209070209071209072209073209074209075209076209077209078209079209080209081209082209083209084209085209086209087209088209089209090209091209092209093209094209095209096209097209098209099209100209101209102209103209104209105209106209107209108209109209110209111209112209113209114209115209116209117209118209119209120209121209122209123209124209125209126209127209128209129209130209131209132209133209134209135209136209137209138209139209140209141209142209143209144209145209146209147209148209149209150209151209152209153209154209155209156209157209158209159209160209161209162209163209164209165209166209167209168209169209170209171209172209173209174209175209176209177209178209179209180209181209182209183209184209185209186209187209188209189209190209191209192209193209194209195209196209197209198209199209200209201209202209203209204209205209206209207209208209209209210209211209212209213209214209215209216209217209218209219209220209221209222209223209224209225209226209227209228209229209230209231209232209233209234209235209236209237209238209239209240209241209242209243209244209245209246209247209248209249209250209251209252209253209254209255209256209257209258209259209260209261209262209263209264209265209266209267209268209269209270209271209272209273209274209275209276209277209278209279209280209281209282209283209284209285209286209287209288209289209290209291209292209293209294209295209296209297209298209299209300209301209302209303209304209305209306209307209308209309209310209311209312209313209314209315209316209317209318209319209320209321209322209323209324209325209326209327209328209329209330209331209332209333209334209335209336209337209338209339209340209341209342209343209344209345209346209347209348209349209350209351209352209353209354209355209356209357209358209359209360209361209362209363209364209365209366209367209368209369209370209371209372209373209374209375209376209377209378209379209380209381209382209383209384209385209386209387209388209389209390209391209392209393209394209395209396209397209398209399209400209401209402209403209404209405209406209407209408209409209410209411209412209413209414209415209416209417209418209419209420209421209422209423209424209425209426209427209428209429209430209431209432209433209434209435209436209437209438209439209440209441209442209443209444209445209446209447209448209449209450209451209452209453209454209455209456209457209458209459209460209461209462209463209464209465209466209467209468209469209470209471209472209473209474209475209476209477209478209479209480209481209482209483209484209485209486209487209488209489209490209491209492209493209494209495209496209497209498209499209500209501209502209503209504209505209506209507209508209509209510209511209512209513209514209515209516209517209518209519209520209521209522209523209524209525209526209527209528209529209530209531209532209533209534209535209536209537209538209539209540209541209542209543209544209545209546209547209548209549209550209551209552209553209554209555209556209557209558209559209560209561209562209563209564209565209566209567209568209569209570209571209572209573209574209575209576209577209578209579209580209581209582209583209584209585209586209587209588209589209590209591209592209593209594209595209596209597209598209599209600209601209602209603209604209605209606209607209608209609209610209611209612209613209614209615209616209617209618209619209620209621209622209623209624209625209626209627209628209629209630209631209632209633209634209635209636209637209638209639209640209641209642209643209644209645209646209647209648209649209650209651209652209653209654209655209656209657209658209659209660209661209662209663209664209665209666209667209668209669209670209671209672209673209674209675209676209677209678209679209680209681209682209683209684209685209686209687209688209689209690209691209692209693209694209695209696209697209698209699209700209701209702209703209704209705209706209707209708209709209710209711209712209713209714209715209716209717209718209719209720209721209722209723209724209725209726209727209728209729209730209731209732209733209734209735209736209737209738209739209740209741209742209743209744209745209746209747209748209749209750209751209752209753209754209755209756209757209758209759209760209761209762209763209764209765209766209767209768209769209770209771209772209773209774209775209776209777209778209779209780209781209782209783209784209785209786209787209788209789209790209791209792209793209794209795209796209797209798209799209800209801209802209803209804209805209806209807209808209809209810209811209812209813209814209815209816209817209818209819209820209821209822209823209824209825209826209827209828209829209830209831209832209833209834209835209836209837209838209839209840209841209842209843209844209845209846209847209848209849209850209851209852209853209854209855209856209857209858209859209860209861209862209863209864209865209866209867209868209869209870209871209872209873209874209875209876209877209878209879209880209881209882209883209884209885209886209887209888209889209890209891209892209893209894209895209896209897209898209899209900209901209902209903209904209905209906209907209908209909209910209911209912209913209914209915209916209917209918209919209920209921209922209923209924209925209926209927209928209929209930209931209932209933209934209935209936209937209938209939209940209941209942209943209944209945209946209947209948209949209950209951209952209953209954209955209956209957209958209959209960209961209962209963209964209965209966209967209968209969209970209971209972209973209974209975209976209977209978209979209980209981209982209983209984209985209986209987209988209989209990209991209992209993209994209995209996209997209998209999210000210001210002210003210004210005210006210007210008210009210010210011210012210013210014210015210016210017210018210019210020210021210022210023210024210025210026210027210028210029210030210031210032210033210034210035210036210037210038210039210040210041210042210043210044210045210046210047210048210049210050210051210052210053210054210055210056210057210058210059210060210061210062210063210064210065210066210067210068210069210070210071210072210073210074210075210076210077210078210079210080210081210082210083210084210085210086210087210088210089210090210091210092210093210094210095210096210097210098210099210100210101210102210103210104210105210106210107210108210109210110210111210112210113210114210115210116210117210118210119210120210121210122210123210124210125210126210127210128210129210130210131210132210133210134210135210136210137210138210139210140210141210142210143210144210145210146210147210148210149210150210151210152210153210154210155210156210157210158210159210160210161210162210163210164210165210166210167210168210169210170210171210172210173210174210175210176210177210178210179210180210181210182210183210184210185210186210187210188210189210190210191210192210193210194210195210196210197210198210199210200210201210202210203210204210205210206210207210208210209210210210211210212210213210214210215210216210217210218210219210220210221210222210223210224210225210226210227210228210229210230210231210232210233210234210235210236210237210238210239210240210241210242210243210244210245210246210247210248210249210250210251210252210253210254210255210256210257210258210259210260210261210262210263210264210265210266210267210268210269210270210271210272210273210274210275210276210277210278210279210280210281210282210283210284210285210286210287210288210289210290210291210292210293210294210295210296210297210298210299210300210301210302210303210304210305210306210307210308210309210310210311210312210313210314210315210316210317210318210319210320210321210322210323210324210325210326210327210328210329210330210331210332210333210334210335210336210337210338210339210340210341210342210343210344210345210346210347210348210349210350210351210352210353210354210355210356210357210358210359210360210361210362210363210364210365210366210367210368210369210370210371210372210373210374210375210376210377210378210379210380210381210382210383210384210385210386210387210388210389210390210391210392210393210394210395210396210397210398210399210400210401210402210403210404210405210406210407210408210409210410210411210412210413210414210415210416210417210418210419210420210421210422210423210424210425210426210427210428210429210430210431210432210433210434210435210436210437210438210439210440210441210442210443210444210445210446210447210448210449210450210451210452210453210454210455210456210457210458210459210460210461210462210463210464210465210466210467210468210469210470210471210472210473210474210475210476210477210478210479210480210481210482210483210484210485210486210487210488210489210490210491210492210493210494210495210496210497210498210499210500210501210502210503210504210505210506210507210508210509210510210511210512210513210514210515210516210517210518210519210520210521210522210523210524210525210526210527210528210529210530210531210532210533210534210535210536210537210538210539210540210541210542210543210544210545210546210547210548210549210550210551210552210553210554210555210556210557210558210559210560210561210562210563210564210565210566210567210568210569210570210571210572210573210574210575210576210577210578210579210580210581210582210583210584210585210586210587210588210589210590210591210592210593210594210595210596210597210598210599210600210601210602210603210604210605210606210607210608210609210610210611210612210613210614210615210616210617210618210619210620210621210622210623210624210625210626210627210628210629210630210631210632210633210634210635210636210637210638210639210640210641210642210643210644210645210646210647210648210649210650210651210652210653210654210655210656210657210658210659210660210661210662210663210664210665210666210667210668210669210670210671210672210673210674210675210676210677210678210679210680210681210682210683210684210685210686210687210688210689210690210691210692210693210694210695210696210697210698210699210700210701210702210703210704210705210706210707210708210709210710210711210712210713210714210715210716210717210718210719210720210721210722210723210724210725210726210727210728210729210730210731210732210733210734210735210736210737210738210739210740210741210742210743210744210745210746210747210748210749210750210751210752210753210754210755210756210757210758210759210760210761210762210763210764210765210766210767210768210769210770210771210772210773210774210775210776210777210778210779210780210781210782210783210784210785210786210787210788210789210790210791210792210793210794210795210796210797210798210799210800210801210802210803210804210805210806210807210808210809210810210811210812210813210814210815210816210817210818210819210820210821210822210823210824210825210826210827210828210829210830210831210832210833210834210835210836210837210838210839210840210841210842210843210844210845210846210847210848210849210850210851210852210853210854210855210856210857210858210859210860210861210862210863210864210865210866210867210868210869210870210871210872210873210874210875210876210877210878210879210880210881210882210883210884210885210886210887210888210889210890210891210892210893210894210895210896210897210898210899210900210901210902210903210904210905210906210907210908210909210910210911210912210913210914210915210916210917210918210919210920210921210922210923210924210925210926210927210928210929210930210931210932210933210934210935210936210937210938210939210940210941210942210943210944210945210946210947210948210949210950210951210952210953210954210955210956210957210958210959210960210961210962210963210964210965210966210967210968210969210970210971210972210973210974210975210976210977210978210979210980210981210982210983210984210985210986210987210988210989210990210991210992210993210994210995210996210997210998210999211000211001211002211003211004211005211006211007211008211009211010211011211012211013211014211015211016211017211018211019211020211021211022211023211024211025211026211027211028211029211030211031211032211033211034211035211036211037211038211039211040211041211042211043211044211045211046211047211048211049211050211051211052211053211054211055211056211057211058211059211060211061211062211063211064211065211066211067211068211069211070211071211072211073211074211075211076211077211078211079211080211081211082211083211084211085211086211087211088211089211090211091211092211093211094211095211096211097211098211099211100211101211102211103211104211105211106211107211108211109211110211111211112211113211114211115211116211117211118211119211120211121211122211123211124211125211126211127211128211129211130211131211132211133211134211135211136211137211138211139211140211141211142211143211144211145211146211147211148211149211150211151211152211153211154211155211156211157211158211159211160211161211162211163211164211165211166211167211168211169211170211171211172211173211174211175211176211177211178211179211180211181211182211183211184211185211186211187211188211189211190211191211192211193211194211195211196211197211198211199211200211201211202211203211204211205211206211207211208211209211210211211211212211213211214211215211216211217211218211219211220211221211222211223211224211225211226211227211228211229211230211231211232211233211234211235211236211237211238211239211240211241211242211243211244211245211246211247211248211249211250211251211252211253211254211255211256211257211258211259211260211261211262211263211264211265211266211267211268211269211270211271211272211273211274211275211276211277211278211279211280211281211282211283211284211285211286211287211288211289211290211291211292211293211294211295211296211297211298211299211300211301211302211303211304211305211306211307211308211309211310211311211312211313211314211315211316211317211318211319211320211321211322211323211324211325211326211327211328211329211330211331211332211333211334211335211336211337211338211339211340211341211342211343211344211345211346211347211348211349211350211351211352211353211354211355211356211357211358211359211360211361211362211363211364211365211366211367211368211369211370211371211372211373211374211375211376211377211378211379211380211381211382211383211384211385211386211387211388211389211390211391211392211393211394211395211396211397211398211399211400211401211402211403211404211405211406211407211408211409211410211411211412211413211414211415211416211417211418211419211420211421211422211423211424211425211426211427211428211429211430211431211432211433211434211435211436211437211438211439211440211441211442211443211444211445211446211447211448211449211450211451211452211453211454211455211456211457211458211459211460211461211462211463211464211465211466211467211468211469211470211471211472211473211474211475211476211477211478211479211480211481211482211483211484211485211486211487211488211489211490211491211492211493211494211495211496211497211498211499211500211501211502211503211504211505211506211507211508211509211510211511211512211513211514211515211516211517211518211519211520211521211522211523211524211525211526211527211528211529211530211531211532211533211534211535211536211537211538211539211540211541211542211543211544211545211546211547211548211549211550211551211552211553211554211555211556211557211558211559211560211561211562211563211564211565211566211567211568211569211570211571211572211573211574211575211576211577211578211579211580211581211582211583211584211585211586211587211588211589211590211591211592211593211594211595211596211597211598211599211600211601211602211603211604211605211606211607211608211609211610211611211612211613211614211615211616211617211618211619211620211621211622211623211624211625211626211627211628211629211630211631211632211633211634211635211636211637211638211639211640211641211642211643211644211645211646211647211648211649211650211651211652211653211654211655211656211657211658211659211660211661211662211663211664211665211666211667211668211669211670211671211672211673211674211675211676211677211678211679211680211681211682211683211684211685211686211687211688211689211690211691211692211693211694211695211696211697211698211699211700211701211702211703211704211705211706211707211708211709211710211711211712211713211714211715211716211717211718211719211720211721211722211723211724211725211726211727211728211729211730211731211732211733211734211735211736211737211738211739211740211741211742211743211744211745211746211747211748211749211750211751211752211753211754211755211756211757211758211759211760211761211762211763211764211765211766211767211768211769211770211771211772211773211774211775211776211777211778211779211780211781211782211783211784211785211786211787211788211789211790211791211792211793211794211795211796211797211798211799211800211801211802211803211804211805211806211807211808211809211810211811211812211813211814211815211816211817211818211819211820211821211822211823211824211825211826211827211828211829211830211831211832211833211834211835211836211837211838211839211840211841211842211843211844211845211846211847211848211849211850211851211852211853211854211855211856211857211858211859211860211861211862211863211864211865211866211867211868211869211870211871211872211873211874211875211876211877211878211879211880211881211882211883211884211885211886211887211888211889211890211891211892211893211894211895211896211897211898211899211900211901211902211903211904211905211906211907211908211909211910211911211912211913211914211915211916211917211918211919211920211921211922211923211924211925211926211927211928211929211930211931211932211933211934211935211936211937211938211939211940211941211942211943211944211945211946211947211948211949211950211951211952211953211954211955211956211957211958211959211960211961211962211963211964211965211966211967211968211969211970211971211972211973211974211975211976211977211978211979211980211981211982211983211984211985211986211987211988211989211990211991211992211993211994211995211996211997211998211999212000212001212002212003212004212005212006212007212008212009212010212011212012212013212014212015212016212017212018212019212020212021212022212023212024212025212026212027212028212029212030212031212032212033212034212035212036212037212038212039212040212041212042212043212044212045212046212047212048212049212050212051212052212053212054212055212056212057212058212059212060212061212062212063212064212065212066212067212068212069212070212071212072212073212074212075212076212077212078212079212080212081212082212083212084212085212086212087212088212089212090212091212092212093212094212095212096212097212098212099212100212101212102212103212104212105212106212107212108212109212110212111212112212113212114212115212116212117212118212119212120212121212122212123212124212125212126212127212128212129212130212131212132212133212134212135212136212137212138212139212140212141212142212143212144212145212146212147212148212149212150212151212152212153212154212155212156212157212158212159212160212161212162212163212164212165212166212167212168212169212170212171212172212173212174212175212176212177212178212179212180212181212182212183212184212185212186212187212188212189212190212191212192212193212194212195212196212197212198212199212200212201212202212203212204212205212206212207212208212209212210212211212212212213212214212215212216212217212218212219212220212221212222212223212224212225212226212227212228212229212230212231212232212233212234212235212236212237212238212239212240212241212242212243212244212245212246212247212248212249212250212251212252212253212254212255212256212257212258212259212260212261212262212263212264212265212266212267212268212269212270212271212272212273212274212275212276212277212278212279212280212281212282212283212284212285212286212287212288212289212290212291212292212293212294212295212296212297212298212299212300212301212302212303212304212305212306212307212308212309212310212311212312212313212314212315212316212317212318212319212320212321212322212323212324212325212326212327212328212329212330212331212332212333212334212335212336212337212338212339212340212341212342212343212344212345212346212347212348212349212350212351212352212353212354212355212356212357212358212359212360212361212362212363212364212365212366212367212368212369212370212371212372212373212374212375212376212377212378212379212380212381212382212383212384212385212386212387212388212389212390212391212392212393212394212395212396212397212398212399212400212401212402212403212404212405212406212407212408212409212410212411212412212413212414212415212416212417212418212419212420212421212422212423212424212425212426212427212428212429212430212431212432212433212434212435212436212437212438212439212440212441212442212443212444212445212446212447212448212449212450212451212452212453212454212455212456212457212458212459212460212461212462212463212464212465212466212467212468212469212470212471212472212473212474212475212476212477212478212479212480212481212482212483212484212485212486212487212488212489212490212491212492212493212494212495212496212497212498212499212500212501212502212503212504212505212506212507212508212509212510212511212512212513212514212515212516212517212518212519212520212521212522212523212524212525212526212527212528212529212530212531212532212533212534212535212536212537212538212539212540212541212542212543212544212545212546212547212548212549212550212551212552212553212554212555212556212557212558212559212560212561212562212563212564212565212566212567212568212569212570212571212572212573212574212575212576212577212578212579212580212581212582212583212584212585212586212587212588212589212590212591212592212593212594212595212596212597212598212599212600212601212602212603212604212605212606212607212608212609212610212611212612212613212614212615212616212617212618212619212620212621212622212623212624212625212626212627212628212629212630212631212632212633212634212635212636212637212638212639212640212641212642212643212644212645212646212647212648212649212650212651212652212653212654212655212656212657212658212659212660212661212662212663212664212665212666212667212668212669212670212671212672212673212674212675212676212677212678212679212680212681212682212683212684212685212686212687212688212689212690212691212692212693212694212695212696212697212698212699212700212701212702212703212704212705212706212707212708212709212710212711212712212713212714212715212716212717212718212719212720212721212722212723212724212725212726212727212728212729212730212731212732212733212734212735212736212737212738212739212740212741212742212743212744212745212746212747212748212749212750212751212752212753212754212755212756212757212758212759212760212761212762212763212764212765212766212767212768212769212770212771212772212773212774212775212776212777212778212779212780212781212782212783212784212785212786212787212788212789212790212791212792212793212794212795212796212797212798212799212800212801212802212803212804212805212806212807212808212809212810212811212812212813212814212815212816212817212818212819212820212821212822212823212824212825212826212827212828212829212830212831212832212833212834212835212836212837212838212839212840212841212842212843212844212845212846212847212848212849212850212851212852212853212854212855212856212857212858212859212860212861212862212863212864212865212866212867212868212869212870212871212872212873212874212875212876212877212878212879212880212881212882212883212884212885212886212887212888212889212890212891212892212893212894212895212896212897212898212899212900212901212902212903212904212905212906212907212908212909212910212911212912212913212914212915212916212917212918212919212920212921212922212923212924212925212926212927212928212929212930212931212932212933212934212935212936212937212938212939212940212941212942212943212944212945212946212947212948212949212950212951212952212953212954212955212956212957212958212959212960212961212962212963212964212965212966212967212968212969212970212971212972212973212974212975212976212977212978212979212980212981212982212983212984212985212986212987212988212989212990212991212992212993212994212995212996212997212998212999213000213001213002213003213004213005213006213007213008213009213010213011213012213013213014213015213016213017213018213019213020213021213022213023213024213025213026213027213028213029213030213031213032213033213034213035213036213037213038213039213040213041213042213043213044213045213046213047213048213049213050213051213052213053213054213055213056213057213058213059213060213061213062213063213064213065213066213067213068213069213070213071213072213073213074213075213076213077213078213079213080213081213082213083213084213085213086213087213088213089213090213091213092213093213094213095213096213097213098213099213100213101213102213103213104213105213106213107213108213109213110213111213112213113213114213115213116213117213118213119213120213121213122213123213124213125213126213127213128213129213130213131213132213133213134213135213136213137213138213139213140213141213142213143213144213145213146213147213148213149213150213151213152213153213154213155213156213157213158213159213160213161213162213163213164213165213166213167213168213169213170213171213172213173213174213175213176213177213178213179213180213181213182213183213184213185213186213187213188213189213190213191213192213193213194213195213196213197213198213199213200213201213202213203213204213205213206213207213208213209213210213211213212213213213214213215213216213217213218213219213220213221213222213223213224213225213226213227213228213229213230213231213232213233213234213235213236213237213238213239213240213241213242213243213244213245213246213247213248213249213250213251213252213253213254213255213256213257213258213259213260213261213262213263213264213265213266213267213268213269213270213271213272213273213274213275213276213277213278213279213280213281213282213283213284213285213286213287213288213289213290213291213292213293213294213295213296213297213298213299213300213301213302213303213304213305213306213307213308213309213310213311213312213313213314213315213316213317213318213319213320213321213322213323213324213325213326213327213328213329213330213331213332213333213334213335213336213337213338213339213340213341213342213343213344213345213346213347213348213349213350213351213352213353213354213355213356213357213358213359213360213361213362213363213364213365213366213367213368213369213370213371213372213373213374213375213376213377213378213379213380213381213382213383213384213385213386213387213388213389213390213391213392213393213394213395213396213397213398213399213400213401213402213403213404213405213406213407213408213409213410213411213412213413213414213415213416213417213418213419213420213421213422213423213424213425213426213427213428213429213430213431213432213433213434213435213436213437213438213439213440213441213442213443213444213445213446213447213448213449213450213451213452213453213454213455213456213457213458213459213460213461213462213463213464213465213466213467213468213469213470213471213472213473213474213475213476213477213478213479213480213481213482213483213484213485213486213487213488213489213490213491213492213493213494213495213496213497213498213499213500213501213502213503213504213505213506213507213508213509213510213511213512213513213514213515213516213517213518213519213520213521213522213523213524213525213526213527213528213529213530213531213532213533213534213535213536213537213538213539213540213541213542213543213544213545213546213547213548213549213550213551213552213553213554213555213556213557213558213559213560213561213562213563213564213565213566213567213568213569213570213571213572213573213574213575213576213577213578213579213580213581213582213583213584213585213586213587213588213589213590213591213592213593213594213595213596213597213598213599213600213601213602213603213604213605213606213607213608213609213610213611213612213613213614213615213616213617213618213619213620213621213622213623213624213625213626213627213628213629213630213631213632213633213634213635213636213637213638213639213640213641213642213643213644213645213646213647213648213649213650213651213652213653213654213655213656213657213658213659213660213661213662213663213664213665213666213667213668213669213670213671213672213673213674213675213676213677213678213679213680213681213682213683213684213685213686213687213688213689213690213691213692213693213694213695213696213697213698213699213700213701213702213703213704213705213706213707213708213709213710213711213712213713213714213715213716213717213718213719213720213721213722213723213724213725213726213727213728213729213730213731213732213733213734213735213736213737213738213739213740213741213742213743213744213745213746213747213748213749213750213751213752213753213754213755213756213757213758213759213760213761213762213763213764213765213766213767213768213769213770213771213772213773213774213775213776213777213778213779213780213781213782213783213784213785213786213787213788213789213790213791213792213793213794213795213796213797213798213799213800213801213802213803213804213805213806213807213808213809213810213811213812213813213814213815213816213817213818213819213820213821213822213823213824213825213826213827213828213829213830213831213832213833213834213835213836213837213838213839213840213841213842213843213844213845213846213847213848213849213850213851213852213853213854213855213856213857213858213859213860213861213862213863213864213865213866213867213868213869213870213871213872213873213874213875213876213877213878213879213880213881213882213883213884213885213886213887213888213889213890213891213892213893213894213895213896213897213898213899213900213901213902213903213904213905213906213907213908213909213910213911213912213913213914213915213916213917213918213919213920213921213922213923213924213925213926213927213928213929213930213931213932213933213934213935213936213937213938213939213940213941213942213943213944213945213946213947213948213949213950213951213952213953213954213955213956213957213958213959213960213961213962213963213964213965213966213967213968213969213970213971213972213973213974213975213976213977213978213979213980213981213982213983213984213985213986213987213988213989213990213991213992213993213994213995213996213997213998213999214000214001214002214003214004214005214006214007214008214009214010214011214012214013214014214015214016214017214018214019214020214021214022214023214024214025214026214027214028214029214030214031214032214033214034214035214036214037214038214039214040214041214042214043214044214045214046214047214048214049214050214051214052214053214054214055214056214057214058214059214060214061214062214063214064214065214066214067214068214069214070214071214072214073214074214075214076214077214078214079214080214081214082214083214084214085214086214087214088214089214090214091214092214093214094214095214096214097214098214099214100214101214102214103214104214105214106214107214108214109214110214111214112214113214114214115214116214117214118214119214120214121214122214123214124214125214126214127214128214129214130214131214132214133214134214135214136214137214138214139214140214141214142214143214144214145214146214147214148214149214150214151214152214153214154214155214156214157214158214159214160214161214162214163214164214165214166214167214168214169214170214171214172214173214174214175214176214177214178214179214180214181214182214183214184214185214186214187214188214189214190214191214192214193214194214195214196214197214198214199214200214201214202214203214204214205214206214207214208214209214210214211214212214213214214214215214216214217214218214219214220214221214222214223214224214225214226214227214228214229214230214231214232214233214234214235214236214237214238214239214240214241214242214243214244214245214246214247214248214249214250214251214252214253214254214255214256214257214258214259214260214261214262214263214264214265214266214267214268214269214270214271214272214273214274214275214276214277214278214279214280214281214282214283214284214285214286214287214288214289214290214291214292214293214294214295214296214297214298214299214300214301214302214303214304214305214306214307214308214309214310214311214312214313214314214315214316214317214318214319214320214321214322214323214324214325214326214327214328214329214330214331214332214333214334214335214336214337214338214339214340214341214342214343214344214345214346214347214348214349214350214351214352214353214354214355214356214357214358214359214360214361214362214363214364214365214366214367214368214369214370214371214372214373214374214375214376214377214378214379214380214381214382214383214384214385214386214387214388214389214390214391214392214393214394214395214396214397214398214399214400214401214402214403214404214405214406214407214408214409214410214411214412214413214414214415214416214417214418214419214420214421214422214423214424214425214426214427214428214429214430214431214432214433214434214435214436214437214438214439214440214441214442214443214444214445214446214447214448214449214450214451214452214453214454214455214456214457214458214459214460214461214462214463214464214465214466214467214468214469214470214471214472214473214474214475214476214477214478214479214480214481214482214483214484214485214486214487214488214489214490214491214492214493214494214495214496214497214498214499214500214501214502214503214504214505214506214507214508214509214510214511214512214513214514214515214516214517214518214519214520214521214522214523214524214525214526214527214528214529214530214531214532214533214534214535214536214537214538214539214540214541214542214543214544214545214546214547214548214549214550214551214552214553214554214555214556214557214558214559214560214561214562214563214564214565214566214567214568214569214570214571214572214573214574214575214576214577214578214579214580214581214582214583214584214585214586214587214588214589214590214591214592214593214594214595214596214597214598214599214600214601214602214603214604214605214606214607214608214609214610214611214612214613214614214615214616214617214618214619214620214621214622214623214624214625214626214627214628214629214630214631214632214633214634214635214636214637214638214639214640214641214642214643214644214645214646214647214648214649214650214651214652214653214654214655214656214657214658214659214660214661214662214663214664214665214666214667214668214669214670214671214672214673214674214675214676214677214678214679214680214681214682214683214684214685214686214687214688214689214690214691214692214693214694214695214696214697214698214699214700214701214702214703214704214705214706214707214708214709214710214711214712214713214714214715214716214717214718214719214720214721214722214723214724214725214726214727214728214729214730214731214732214733214734214735214736214737214738214739214740214741214742214743214744214745214746214747214748214749214750214751214752214753214754214755214756214757214758214759214760214761214762214763214764214765214766214767214768214769214770214771214772214773214774214775214776214777214778214779214780214781214782214783214784214785214786214787214788214789214790214791214792214793214794214795214796214797214798214799214800214801214802214803214804214805214806214807214808214809214810214811214812214813214814214815214816214817214818214819214820214821214822214823214824214825214826214827214828214829214830214831214832214833214834214835214836214837214838214839214840214841214842214843214844214845214846214847214848214849214850214851214852214853214854214855214856214857214858214859214860214861214862214863214864214865214866214867214868214869214870214871214872214873214874214875214876214877214878214879214880214881214882214883214884214885214886214887214888214889214890214891214892214893214894214895214896214897214898214899214900214901214902214903214904214905214906214907214908214909214910214911214912214913214914214915214916214917214918214919214920214921214922214923214924214925214926214927214928214929214930214931214932214933214934214935214936214937214938214939214940214941214942214943214944214945214946214947214948214949214950214951214952214953214954214955214956214957214958214959214960214961214962214963214964214965214966214967214968214969214970214971214972214973214974214975214976214977214978214979214980214981214982214983214984214985214986214987214988214989214990214991214992214993214994214995214996214997214998214999215000215001215002215003215004215005215006215007215008215009215010215011215012215013215014215015215016215017215018215019215020215021215022215023215024215025215026215027215028215029215030215031215032215033215034215035215036215037215038215039215040215041215042215043215044215045215046215047215048215049215050215051215052215053215054215055215056215057215058215059215060215061215062215063215064215065215066215067215068215069215070215071215072215073215074215075215076215077215078215079215080215081215082215083215084215085215086215087215088215089215090215091215092215093215094215095215096215097215098215099215100215101215102215103215104215105215106215107215108215109215110215111215112215113215114215115215116215117215118215119215120215121215122215123215124215125215126215127215128215129215130215131215132215133215134215135215136215137215138215139215140215141215142215143215144215145215146215147215148215149215150215151215152215153215154215155215156215157215158215159215160215161215162215163215164215165215166215167215168215169215170215171215172215173215174215175215176215177215178215179215180215181215182215183215184215185215186215187215188215189215190215191215192215193215194215195215196215197215198215199215200215201215202215203215204215205215206215207215208215209215210215211215212215213215214215215215216215217215218215219215220215221215222215223215224215225215226215227215228215229215230215231215232215233215234215235215236215237215238215239215240215241215242215243215244215245215246215247215248215249215250215251215252215253215254215255215256215257215258215259215260215261215262215263215264215265215266215267215268215269215270215271215272215273215274215275215276215277215278215279215280215281215282215283215284215285215286215287215288215289215290215291215292215293215294215295215296215297215298215299215300215301215302215303215304215305215306215307215308215309215310215311215312215313215314215315215316215317215318215319215320215321215322215323215324215325215326215327215328215329215330215331215332215333215334215335215336215337215338215339215340215341215342215343215344215345215346215347215348215349215350215351215352215353215354215355215356215357215358215359215360215361215362215363215364215365215366215367215368215369215370215371215372215373215374215375215376215377215378215379215380215381215382215383215384215385215386215387215388215389215390215391215392215393215394215395215396215397215398215399215400215401215402215403215404215405215406215407215408215409215410215411215412215413215414215415215416215417215418215419215420215421215422215423215424215425215426215427215428215429215430215431215432215433215434215435215436215437215438215439215440215441215442215443215444215445215446215447215448215449215450215451215452215453215454215455215456215457215458215459215460215461215462215463215464215465215466215467215468215469215470215471215472215473215474215475215476215477215478215479215480215481215482215483215484215485215486215487215488215489215490215491215492215493215494215495215496215497215498215499215500215501215502215503215504215505215506215507215508215509215510215511215512215513215514215515215516215517215518215519215520215521215522215523215524215525215526215527215528215529215530215531215532215533215534215535215536215537215538215539215540215541215542215543215544215545215546215547215548215549215550215551215552215553215554215555215556215557215558215559215560215561215562215563215564215565215566215567215568215569215570215571215572215573215574215575215576215577215578215579215580215581215582215583215584215585215586215587215588215589215590215591215592215593215594215595215596215597215598215599215600215601215602215603215604215605215606215607215608215609215610215611215612215613215614215615215616215617215618215619215620215621215622215623215624215625215626215627215628215629215630215631215632215633215634215635215636215637215638215639215640215641215642215643215644215645215646215647215648215649215650215651215652215653215654215655215656215657215658215659215660215661215662215663215664215665215666215667215668215669215670215671215672215673215674215675215676215677215678215679215680215681215682215683215684215685215686215687215688215689215690215691215692215693215694215695215696215697215698215699215700215701215702215703215704215705215706215707215708215709215710215711215712215713215714215715215716215717215718215719215720215721215722215723215724215725215726215727215728215729215730215731215732215733215734215735215736215737215738215739215740215741215742215743215744215745215746215747215748215749215750215751215752215753215754215755215756215757215758215759215760215761215762215763215764215765215766215767215768215769215770215771215772215773215774215775215776215777215778215779215780215781215782215783215784215785215786215787215788215789215790215791215792215793215794215795215796215797215798215799215800215801215802215803215804215805215806215807215808215809215810215811215812215813215814215815215816215817215818215819215820215821215822215823215824215825215826215827215828215829215830215831215832215833215834215835215836215837215838215839215840215841215842215843215844215845215846215847215848215849215850215851215852215853215854215855215856215857215858215859215860215861215862215863215864215865215866215867215868215869215870215871215872215873215874215875215876215877215878215879215880215881215882215883215884215885215886215887215888215889215890215891215892215893215894215895215896215897215898215899215900215901215902215903215904215905215906215907215908215909215910215911215912215913215914215915215916215917215918215919215920215921215922215923215924215925215926215927215928215929215930215931215932215933215934215935215936215937215938215939215940215941215942215943215944215945215946215947215948215949215950215951215952215953215954215955215956215957215958215959215960215961215962215963215964215965215966215967215968215969215970215971215972215973215974215975215976215977215978215979215980215981215982215983215984215985215986215987215988215989215990215991215992215993215994215995215996215997215998215999216000216001216002216003216004216005216006216007216008216009216010216011216012216013216014216015216016216017216018216019216020216021216022216023216024216025216026216027216028216029216030216031216032216033216034216035216036216037216038216039216040216041216042216043216044216045216046216047216048216049216050216051216052216053216054216055216056216057216058216059216060216061216062216063216064216065216066216067216068216069216070216071216072216073216074216075216076216077216078216079216080216081216082216083216084216085216086216087216088216089216090216091216092216093216094216095216096216097216098216099216100216101216102216103216104216105216106216107216108216109216110216111216112216113216114216115216116216117216118216119216120216121216122216123216124216125216126216127216128216129216130216131216132216133216134216135216136216137216138216139216140216141216142216143216144216145216146216147216148216149216150216151216152216153216154216155216156216157216158216159216160216161216162216163216164216165216166216167216168216169216170216171216172216173216174216175216176216177216178216179216180216181216182216183216184216185216186216187216188216189216190216191216192216193216194216195216196216197216198216199216200216201216202216203216204216205216206216207216208216209216210216211216212216213216214216215216216216217216218216219216220216221216222216223216224216225216226216227216228216229216230216231216232216233216234216235216236216237216238216239216240216241216242216243216244216245216246216247216248216249216250216251216252216253216254216255216256216257216258216259216260216261216262216263216264216265216266216267216268216269216270216271216272216273216274216275216276216277216278216279216280216281216282216283216284216285216286216287216288216289216290216291216292216293216294216295216296216297216298216299216300216301216302216303216304216305216306216307216308216309216310216311216312216313216314216315216316216317216318216319216320216321216322216323216324216325216326216327216328216329216330216331216332216333216334216335216336216337216338216339216340216341216342216343216344216345216346216347216348216349216350216351216352216353216354216355216356216357216358216359216360216361216362216363216364216365216366216367216368216369216370216371216372216373216374216375216376216377216378216379216380216381216382216383216384216385216386216387216388216389216390216391216392216393216394216395216396216397216398216399216400216401216402216403216404216405216406216407216408216409216410216411216412216413216414216415216416216417216418216419216420216421216422216423216424216425216426216427216428216429216430216431216432216433216434216435216436216437216438216439216440216441216442216443216444216445216446216447216448216449216450216451216452216453216454216455216456216457216458216459216460216461216462216463216464216465216466216467216468216469216470216471216472216473216474216475216476216477216478216479216480216481216482216483216484216485216486216487216488216489216490216491216492216493216494216495216496216497216498216499216500216501216502216503216504216505216506216507216508216509216510216511216512216513216514216515216516216517216518216519216520216521216522216523216524216525216526216527216528216529216530216531216532216533216534216535216536216537216538216539216540216541216542216543216544216545216546216547216548216549216550216551216552216553216554216555216556216557216558216559216560216561216562216563216564216565216566216567216568216569216570216571216572216573216574216575216576216577216578216579216580216581216582216583216584216585216586216587216588216589216590216591216592216593216594216595216596216597216598216599216600216601216602216603216604216605216606216607216608216609216610216611216612216613216614216615216616216617216618216619216620216621216622216623216624216625216626216627216628216629216630216631216632216633216634216635216636216637216638216639216640216641216642216643216644216645216646216647216648216649216650216651216652216653216654216655216656216657216658216659216660216661216662216663216664216665216666216667216668216669216670216671216672216673216674216675216676216677216678216679216680216681216682216683216684216685216686216687216688216689216690216691216692216693216694216695216696216697216698216699216700216701216702216703216704216705216706216707216708216709216710216711216712216713216714216715216716216717216718216719216720216721216722216723216724216725216726216727216728216729216730216731216732216733216734216735216736216737216738216739216740216741216742216743216744216745216746216747216748216749216750216751216752216753216754216755216756216757216758216759216760216761216762216763216764216765216766216767216768216769216770216771216772216773216774216775216776216777216778216779216780216781216782216783216784216785216786216787216788216789216790216791216792216793216794216795216796216797216798216799216800216801216802216803216804216805216806216807216808216809216810216811216812216813216814216815216816216817216818216819216820216821216822216823216824216825216826216827216828216829216830216831216832216833216834216835216836216837216838216839216840216841216842216843216844216845216846216847216848216849216850216851216852216853216854216855216856216857216858216859216860216861216862216863216864216865216866216867216868216869216870216871216872216873216874216875216876216877216878216879216880216881216882216883216884216885216886216887216888216889216890216891216892216893216894216895216896216897216898216899216900216901216902216903216904216905216906216907216908216909216910216911216912216913216914216915216916216917216918216919216920216921216922216923216924216925216926216927216928216929216930216931216932216933216934216935216936216937216938216939216940216941216942216943216944216945216946216947216948216949216950216951216952216953216954216955216956216957216958216959216960216961216962216963216964216965216966216967216968216969216970216971216972216973216974216975216976216977216978216979216980216981216982216983216984216985216986216987216988216989216990216991216992216993216994216995216996216997216998216999217000217001217002217003217004217005217006217007217008217009217010217011217012217013217014217015217016217017217018217019217020217021217022217023217024217025217026217027217028217029217030217031217032217033217034217035217036217037217038217039217040217041217042217043217044217045217046217047217048217049217050217051217052217053217054217055217056217057217058217059217060217061217062217063217064217065217066217067217068217069217070217071217072217073217074217075217076217077217078217079217080217081217082217083217084217085217086217087217088217089217090217091217092217093217094217095217096217097217098217099217100217101217102217103217104217105217106217107217108217109217110217111217112217113217114217115217116217117217118217119217120217121217122217123217124217125217126217127217128217129217130217131217132217133217134217135217136217137217138217139217140217141217142217143217144217145217146217147217148217149217150217151217152217153217154217155217156217157217158217159217160217161217162217163217164217165217166217167217168217169217170217171217172217173217174217175217176217177217178217179217180217181217182217183217184217185217186217187217188217189217190217191217192217193217194217195217196217197217198217199217200217201217202217203217204217205217206217207217208217209217210217211217212217213217214217215217216217217217218217219217220217221217222217223217224217225217226217227217228217229217230217231217232217233217234217235217236217237217238217239217240217241217242217243217244217245217246217247217248217249217250217251217252217253217254217255217256217257217258217259217260217261217262217263217264217265217266217267217268217269217270217271217272217273217274217275217276217277217278217279217280217281217282217283217284217285217286217287217288217289217290217291217292217293217294217295217296217297217298217299217300217301217302217303217304217305217306217307217308217309217310217311217312217313217314217315217316217317217318217319217320217321217322217323217324217325217326217327217328217329217330217331217332217333217334217335217336217337217338217339217340217341217342217343217344217345217346217347217348217349217350217351217352217353217354217355217356217357217358217359217360217361217362217363217364217365217366217367217368217369217370217371217372217373217374217375217376217377217378217379217380217381217382217383217384217385217386217387217388217389217390217391217392217393217394217395217396217397217398217399217400217401217402217403217404217405217406217407217408217409217410217411217412217413217414217415217416217417217418217419217420217421217422217423217424217425217426217427217428217429217430217431217432217433217434217435217436217437217438217439217440217441217442217443217444217445217446217447217448217449217450217451217452217453217454217455217456217457217458217459217460217461217462217463217464217465217466217467217468217469217470217471217472217473217474217475217476217477217478217479217480217481217482217483217484217485217486217487217488217489217490217491217492217493217494217495217496217497217498217499217500217501217502217503217504217505217506217507217508217509217510217511217512217513217514217515217516217517217518217519217520217521217522217523217524217525217526217527217528217529217530217531217532217533217534217535217536217537217538217539217540217541217542217543217544217545217546217547217548217549217550217551217552217553217554217555217556217557217558217559217560217561217562217563217564217565217566217567217568217569217570217571217572217573217574217575217576217577217578217579217580217581217582217583217584217585217586217587217588217589217590217591217592217593217594217595217596217597217598217599217600217601217602217603217604217605217606217607217608217609217610217611217612217613217614217615217616217617217618217619217620217621217622217623217624217625217626217627217628217629217630217631217632217633217634217635217636217637217638217639217640217641217642217643217644217645217646217647217648217649217650217651217652217653217654217655217656217657217658217659217660217661217662217663217664217665217666217667217668217669217670217671217672217673217674217675217676217677217678217679217680217681217682217683217684217685217686217687217688217689217690217691217692217693217694217695217696217697217698217699217700217701217702217703217704217705217706217707217708217709217710217711217712217713217714217715217716217717217718217719217720217721217722217723217724217725217726217727217728217729217730217731217732217733217734217735217736217737217738217739217740217741217742217743217744217745217746217747217748217749217750217751217752217753217754217755217756217757217758217759217760217761217762217763217764217765217766217767217768217769217770217771217772217773217774217775217776217777217778217779217780217781217782217783217784217785217786217787217788217789217790217791217792217793217794217795217796217797217798217799217800217801217802217803217804217805217806217807217808217809217810217811217812217813217814217815217816217817217818217819217820217821217822217823217824217825217826217827217828217829217830217831217832217833217834217835217836217837217838217839217840217841217842217843217844217845217846217847217848217849217850217851217852217853217854217855217856217857217858217859217860217861217862217863217864217865217866217867217868217869217870217871217872217873217874217875217876217877217878217879217880217881217882217883217884217885217886217887217888217889217890217891217892217893217894217895217896217897217898217899217900217901217902217903217904217905217906217907217908217909217910217911217912217913217914217915217916217917217918217919217920217921217922217923217924217925217926217927217928217929217930217931217932217933217934217935217936217937217938217939217940217941217942217943217944217945217946217947217948217949217950217951217952217953217954217955217956217957217958217959217960217961217962217963217964217965217966217967217968217969217970217971217972217973217974217975217976217977217978217979217980217981217982217983217984217985217986217987217988217989217990217991217992217993217994217995217996217997217998217999218000218001218002218003218004218005218006218007218008218009218010218011218012218013218014218015218016218017218018218019218020218021218022218023218024218025218026218027218028218029218030218031218032218033218034218035218036218037218038218039218040218041218042218043218044218045218046218047218048218049218050218051218052218053218054218055218056218057218058218059218060218061218062218063218064218065218066218067218068218069218070218071218072218073218074218075218076218077218078218079218080218081218082218083218084218085218086218087218088218089218090218091218092218093218094218095218096218097218098218099218100218101218102218103218104218105218106218107218108218109218110218111218112218113218114218115218116218117218118218119218120218121218122218123218124218125218126218127218128218129218130218131218132218133218134218135218136218137218138218139218140218141218142218143218144218145218146218147218148218149218150218151218152218153218154218155218156218157218158218159218160218161218162218163218164218165218166218167218168218169218170218171218172218173218174218175218176218177218178218179218180218181218182218183218184218185218186218187218188218189218190218191218192218193218194218195218196218197218198218199218200218201218202218203218204218205218206218207218208218209218210218211218212218213218214218215218216218217218218218219218220218221218222218223218224218225218226218227218228218229218230218231218232218233218234218235218236218237218238218239218240218241218242218243218244218245218246218247218248218249218250218251218252218253218254218255218256218257218258218259218260218261218262218263218264218265218266218267218268218269218270218271218272218273218274218275218276218277218278218279218280218281218282218283218284218285218286218287218288218289218290218291218292218293218294218295218296218297218298218299218300218301218302218303218304218305218306218307218308218309218310218311218312218313218314218315218316218317218318218319218320218321218322218323218324218325218326218327218328218329218330218331218332218333218334218335218336218337218338218339218340218341218342218343218344218345218346218347218348218349218350218351218352218353218354218355218356218357218358218359218360218361218362218363218364218365218366218367218368218369218370218371218372218373218374218375218376218377218378218379218380218381218382218383218384218385218386218387218388218389218390218391218392218393218394218395218396218397218398218399218400218401218402218403218404218405218406218407218408218409218410218411218412218413218414218415218416218417218418218419218420218421218422218423218424218425218426218427218428218429218430218431218432218433218434218435218436218437218438218439218440218441218442218443218444218445218446218447218448218449218450218451218452218453218454218455218456218457218458218459218460218461218462218463218464218465218466218467218468218469218470218471218472218473218474218475218476218477218478218479218480218481218482218483218484218485218486218487218488218489218490218491218492218493218494218495218496218497218498218499218500218501218502218503218504218505218506218507218508218509218510218511218512218513218514218515218516218517218518218519218520218521218522218523218524218525218526218527218528218529218530218531218532218533218534218535218536218537218538218539218540218541218542218543218544218545218546218547218548218549218550218551218552218553218554218555218556218557218558218559218560218561218562218563218564218565218566218567218568218569218570218571218572218573218574218575218576218577218578218579218580218581218582218583218584218585218586218587218588218589218590218591218592218593218594218595218596218597218598218599218600218601218602218603218604218605218606218607218608218609218610218611218612218613218614218615218616218617218618218619218620218621218622218623218624218625218626218627218628218629218630218631218632218633218634218635218636218637218638218639218640218641218642218643218644218645218646218647218648218649218650218651218652218653218654218655218656218657218658218659218660218661218662218663218664218665218666218667218668218669218670218671218672218673218674218675218676218677218678218679218680218681218682218683218684218685218686218687218688218689218690218691218692218693218694218695218696218697218698218699218700218701218702218703218704218705218706218707218708218709218710218711218712218713218714218715218716218717218718218719218720218721218722218723218724218725218726218727218728218729218730218731218732218733218734218735218736218737218738218739218740218741218742218743218744218745218746218747218748218749218750218751218752218753218754218755218756218757218758218759218760218761218762218763218764218765218766218767218768218769218770218771218772218773218774218775218776218777218778218779218780218781218782218783218784218785218786218787218788218789218790218791218792218793218794218795218796218797218798218799218800218801218802218803218804218805218806218807218808218809218810218811218812218813218814218815218816218817218818218819218820218821218822218823218824218825218826218827218828218829218830218831218832218833218834218835218836218837218838218839218840218841218842218843218844218845218846218847218848218849218850218851218852218853218854218855218856218857218858218859218860218861218862218863218864218865218866218867218868218869218870218871218872218873218874218875218876218877218878218879218880218881218882218883218884218885218886218887218888218889218890218891218892218893218894218895218896218897218898218899218900218901218902218903218904218905218906218907218908218909218910218911218912218913218914218915218916218917218918218919218920218921218922218923218924218925218926218927218928218929218930218931218932218933218934218935218936218937218938218939218940218941218942218943218944218945218946218947218948218949218950218951218952218953218954218955218956218957218958218959218960218961218962218963218964218965218966218967218968218969218970218971218972218973218974218975218976218977218978218979218980218981218982218983218984218985218986218987218988218989218990218991218992218993218994218995218996218997218998218999219000219001219002219003219004219005219006219007219008219009219010219011219012219013219014219015219016219017219018219019219020219021219022219023219024219025219026219027219028219029219030219031219032219033219034219035219036219037219038219039219040219041219042219043219044219045219046219047219048219049219050219051219052219053219054219055219056219057219058219059219060219061219062219063219064219065219066219067219068219069219070219071219072219073219074219075219076219077219078219079219080219081219082219083219084219085219086219087219088219089219090219091219092219093219094219095219096219097219098219099219100219101219102219103219104219105219106219107219108219109219110219111219112219113219114219115219116219117219118219119219120219121219122219123219124219125219126219127219128219129219130219131219132219133219134219135219136219137219138219139219140219141219142219143219144219145219146219147219148219149219150219151219152219153219154219155219156219157219158219159219160219161219162219163219164219165219166219167219168219169219170219171219172219173219174219175219176219177219178219179219180219181219182219183219184219185219186219187219188219189219190219191219192219193219194219195219196219197219198219199219200219201219202219203219204219205219206219207219208219209219210219211219212219213219214219215219216219217219218219219219220219221219222219223219224219225219226219227219228219229219230219231219232219233219234219235219236219237219238219239219240219241219242219243219244219245219246219247219248219249219250219251219252219253219254219255219256219257219258219259219260219261219262219263219264219265219266219267219268219269219270219271219272219273219274219275219276219277219278219279219280219281219282219283219284219285219286219287219288219289219290219291219292219293219294219295219296219297219298219299219300219301219302219303219304219305219306219307219308219309219310219311219312219313219314219315219316219317219318219319219320219321219322219323219324219325219326219327219328219329219330219331219332219333219334219335219336219337219338219339219340219341219342219343219344219345219346219347219348219349219350219351219352219353219354219355219356219357219358219359219360219361219362219363219364219365219366219367219368219369219370219371219372219373219374219375219376219377219378219379219380219381219382219383219384219385219386219387219388219389219390219391219392219393219394219395219396219397219398219399219400219401219402219403219404219405219406219407219408219409219410219411219412219413219414219415219416219417219418219419219420219421219422219423219424219425219426219427219428219429219430219431219432219433219434219435219436219437219438219439219440219441219442219443219444219445219446219447219448219449219450219451219452219453219454219455219456219457219458219459219460219461219462219463219464219465219466219467219468219469219470219471219472219473219474219475219476219477219478219479219480219481219482219483219484219485219486219487219488219489219490219491219492219493219494219495219496219497219498219499219500219501219502219503219504219505219506219507219508219509219510219511219512219513219514219515219516219517219518219519219520219521219522219523219524219525219526219527219528219529219530219531219532219533219534219535219536219537219538219539219540219541219542219543219544219545219546219547219548219549219550219551219552219553219554219555219556219557219558219559219560219561219562219563219564219565219566219567219568219569219570219571219572219573219574219575219576219577219578219579219580219581219582219583219584219585219586219587219588219589219590219591219592219593219594219595219596219597219598219599219600219601219602219603219604219605219606219607219608219609219610219611219612219613219614219615219616219617219618219619219620219621219622219623219624219625219626219627219628219629219630219631219632219633219634219635219636219637219638219639219640219641219642219643219644219645219646219647219648219649219650219651219652219653219654219655219656219657219658219659219660219661219662219663219664219665219666219667219668219669219670219671219672219673219674219675219676219677219678219679219680219681219682219683219684219685219686219687219688219689219690219691219692219693219694219695219696219697219698219699219700219701219702219703219704219705219706219707219708219709219710219711219712219713219714219715219716219717219718219719219720219721219722219723219724219725219726219727219728219729219730219731219732219733219734219735219736219737219738219739219740219741219742219743219744219745219746219747219748219749219750219751219752219753219754219755219756219757219758219759219760219761219762219763219764219765219766219767219768219769219770219771219772219773219774219775219776219777219778219779219780219781219782219783219784219785219786219787219788219789219790219791219792219793219794219795219796219797219798219799219800219801219802219803219804219805219806219807219808219809219810219811219812219813219814219815219816219817219818219819219820219821219822219823219824219825219826219827219828219829219830219831219832219833219834219835219836219837219838219839219840219841219842219843219844219845219846219847219848219849219850219851219852219853219854219855219856219857219858219859219860219861219862219863219864219865219866219867219868219869219870219871219872219873219874219875219876219877219878219879219880219881219882219883219884219885219886219887219888219889219890219891219892219893219894219895219896219897219898219899219900219901219902219903219904219905219906219907219908219909219910219911219912219913219914219915219916219917219918219919219920219921219922219923219924219925219926219927219928219929219930219931219932219933219934219935219936219937219938219939219940219941219942219943219944219945219946219947219948219949219950219951219952219953219954219955219956219957219958219959219960219961219962219963219964219965219966219967219968219969219970219971219972219973219974219975219976219977219978219979219980219981219982219983219984219985219986219987219988219989219990219991219992219993219994219995219996219997219998219999220000220001220002220003220004220005220006220007220008220009220010220011220012220013220014220015220016220017220018220019220020220021220022220023220024220025220026220027220028220029220030220031220032220033220034220035220036220037220038220039220040220041220042220043220044220045220046220047220048220049220050220051220052220053220054220055220056220057220058220059220060220061220062220063220064220065220066220067220068220069220070220071220072220073220074220075220076220077220078220079220080220081220082220083220084220085220086220087220088220089220090220091220092220093220094220095220096220097220098220099220100220101220102220103220104220105220106220107220108220109220110220111220112220113220114220115220116220117220118220119220120220121220122220123220124220125220126220127220128220129220130220131220132220133220134220135220136220137220138220139220140220141220142220143220144220145220146220147220148220149220150220151220152220153220154220155220156220157220158220159220160220161220162220163220164220165220166220167220168220169220170220171220172220173220174220175220176220177220178220179220180220181220182220183220184220185220186220187220188220189220190220191220192220193220194220195220196220197220198220199220200220201220202220203220204220205220206220207220208220209220210220211220212220213220214220215220216220217220218220219220220220221220222220223220224220225220226220227220228220229220230220231220232220233220234220235220236220237220238220239220240220241220242220243220244220245220246220247220248220249220250220251220252220253220254220255220256220257220258220259220260220261220262220263220264220265220266220267220268220269220270220271220272220273220274220275220276220277220278220279220280220281220282220283220284220285220286220287220288220289220290220291220292220293220294220295220296220297220298220299220300220301220302220303220304220305220306220307220308220309220310220311220312220313220314220315220316220317220318220319220320220321220322220323220324220325220326220327220328220329220330220331220332220333220334220335220336220337220338220339220340220341220342220343220344220345220346220347220348220349220350220351220352220353220354220355220356220357220358220359220360220361220362220363220364220365220366220367220368220369220370220371220372220373220374220375220376220377220378220379220380220381220382220383220384220385220386220387220388220389220390220391220392220393220394220395220396220397220398220399220400220401220402220403220404220405220406220407220408220409220410220411220412220413220414220415220416220417220418220419220420220421220422220423220424220425220426220427220428220429220430220431220432220433220434220435220436220437220438220439220440220441220442220443220444220445220446220447220448220449220450220451220452220453220454220455220456220457220458220459220460220461220462220463220464220465220466220467220468220469220470220471220472220473220474220475220476220477220478220479220480220481220482220483220484220485220486220487220488220489220490220491220492220493220494220495220496220497220498220499220500220501220502220503220504220505220506220507220508220509220510220511220512220513220514220515220516220517220518220519220520220521220522220523220524220525220526220527220528220529220530220531220532220533220534220535220536220537220538220539220540220541220542220543220544220545220546220547220548220549220550220551220552220553220554220555220556220557220558220559220560220561220562220563220564220565220566220567220568220569220570220571220572220573220574220575220576220577220578220579220580220581220582220583220584220585220586220587220588220589220590220591220592220593220594220595220596220597220598220599220600220601220602220603220604220605220606220607220608220609220610220611220612220613220614220615220616220617220618220619220620220621220622220623220624220625220626220627220628220629220630220631220632220633220634220635220636220637220638220639220640220641220642220643220644220645220646220647220648220649220650220651220652220653220654220655220656220657220658220659220660220661220662220663220664220665220666220667220668220669220670220671220672220673220674220675220676220677220678220679220680220681220682220683220684220685220686220687220688220689220690220691220692220693220694220695220696220697220698220699220700220701220702220703220704220705220706220707220708220709220710220711220712220713220714220715220716220717220718220719220720220721220722220723220724220725220726220727220728220729220730220731220732220733220734220735220736220737220738220739220740220741220742220743220744220745220746220747220748220749220750220751220752220753220754220755220756220757220758220759220760220761220762220763220764220765220766220767220768220769220770220771220772220773220774220775220776220777220778220779220780220781220782220783220784220785220786220787220788220789220790220791220792220793220794220795220796220797220798220799220800220801220802220803220804220805220806220807220808220809220810220811220812220813220814220815220816220817220818220819220820220821220822220823220824220825220826220827220828220829220830220831220832220833220834220835220836220837220838220839220840220841220842220843220844220845220846220847220848220849220850220851220852220853220854220855220856220857220858220859220860220861220862220863220864220865220866220867220868220869220870220871220872220873220874220875220876220877220878220879220880220881220882220883220884220885220886220887220888220889220890220891220892220893220894220895220896220897220898220899220900220901220902220903220904220905220906220907220908220909220910220911220912220913220914220915220916220917220918220919220920220921220922220923220924220925220926220927220928220929220930220931220932220933220934220935220936220937220938220939220940220941220942220943220944220945220946220947220948220949220950220951220952220953220954220955220956220957220958220959220960220961220962220963220964220965220966220967220968220969220970220971220972220973220974220975220976220977220978220979220980220981220982220983220984220985220986220987220988220989220990220991220992220993220994220995220996220997220998220999221000221001221002221003221004221005221006221007221008221009221010221011221012221013221014221015221016221017221018221019221020221021221022221023221024221025221026221027221028221029221030221031221032221033221034221035221036221037221038221039221040221041221042221043221044221045221046221047221048221049221050221051221052221053221054221055221056221057221058221059221060221061221062221063221064221065221066221067221068221069221070221071221072221073221074221075221076221077221078221079221080221081221082221083221084221085221086221087221088221089221090221091221092221093221094221095221096221097221098221099221100221101221102221103221104221105221106221107221108221109221110221111221112221113221114221115221116221117221118221119221120221121221122221123221124221125221126221127221128221129221130221131221132221133221134221135221136221137221138221139221140221141221142221143221144221145221146221147221148221149221150221151221152221153221154221155221156221157221158221159221160221161221162221163221164221165221166221167221168221169221170221171221172221173221174221175221176221177221178221179221180221181221182221183221184221185221186221187221188221189221190221191221192221193221194221195221196221197221198221199221200221201221202221203221204221205221206221207221208221209221210221211221212221213221214221215221216221217221218221219221220221221221222221223221224221225221226221227221228221229221230221231221232221233221234221235221236221237221238221239221240221241221242221243221244221245221246221247221248221249221250221251221252221253221254221255221256221257221258221259221260221261221262221263221264221265221266221267221268221269221270221271221272221273221274221275221276221277221278221279221280221281221282221283221284221285221286221287221288221289221290221291221292221293221294221295221296221297221298221299221300221301221302221303221304221305221306221307221308221309221310221311221312221313221314221315221316221317221318221319221320221321221322221323221324221325221326221327221328221329221330221331221332221333221334221335221336221337221338221339221340221341221342221343221344221345221346221347221348221349221350221351221352221353221354221355221356221357221358221359221360221361221362221363221364221365221366221367221368221369221370221371221372221373221374221375221376221377221378221379221380221381221382221383221384221385221386221387221388221389221390221391221392221393221394221395221396221397221398221399221400221401221402221403221404221405221406221407221408221409221410221411221412221413221414221415221416221417221418221419221420221421221422221423221424221425221426221427221428221429221430221431221432221433221434221435221436221437221438221439221440221441221442221443221444221445221446221447221448221449221450221451221452221453221454221455221456221457221458221459221460221461221462221463221464221465221466221467221468221469221470221471221472221473221474221475221476221477221478221479221480221481221482221483221484221485221486221487221488221489221490221491221492221493221494221495221496221497221498221499221500221501221502221503221504221505221506221507221508221509221510221511221512221513221514221515221516221517221518221519221520221521221522221523221524221525221526221527221528221529221530221531221532221533221534221535221536221537221538221539221540221541221542221543221544221545221546221547221548221549221550221551221552221553221554221555221556221557221558221559221560221561221562221563221564221565221566221567221568221569221570221571221572221573221574221575221576221577221578221579221580221581221582221583221584221585221586221587221588221589221590221591221592221593221594221595221596221597221598221599221600221601221602221603221604221605221606221607221608221609221610221611221612221613221614221615221616221617221618221619221620221621221622221623221624221625221626221627221628221629221630221631221632221633221634221635221636221637221638221639221640221641221642221643221644221645221646221647221648221649221650221651221652221653221654221655221656221657221658221659221660221661221662221663221664221665221666221667221668221669221670221671221672221673221674221675221676221677221678221679221680221681221682221683221684221685221686221687221688221689221690221691221692221693221694221695221696221697221698221699221700221701221702221703221704221705221706221707221708221709221710221711221712221713221714221715221716221717221718221719221720221721221722221723221724221725221726221727221728221729221730221731221732221733221734221735221736221737221738221739221740221741221742221743221744221745221746221747221748221749221750221751221752221753221754221755221756221757221758221759221760221761221762221763221764221765221766221767221768221769221770221771221772221773221774221775221776221777221778221779221780221781221782221783221784221785221786221787221788221789221790221791221792221793221794221795221796221797221798221799221800221801221802221803221804221805221806221807221808221809221810221811221812221813221814221815221816221817221818221819221820221821221822221823221824221825221826221827221828221829221830221831221832221833221834221835221836221837221838221839221840221841221842221843221844221845221846221847221848221849221850221851221852221853221854221855221856221857221858221859221860221861221862221863221864221865221866221867221868221869221870221871221872221873221874221875221876221877221878221879221880221881221882221883221884221885221886221887221888221889221890221891221892221893221894221895221896221897221898221899221900221901221902221903221904221905221906221907221908221909221910221911221912221913221914221915221916221917221918221919221920221921221922221923221924221925221926221927221928221929221930221931221932221933221934221935221936221937221938221939221940221941221942221943221944221945221946221947221948221949221950221951221952221953221954221955221956221957221958221959221960221961221962221963221964221965221966221967221968221969221970221971221972221973221974221975221976221977221978221979221980221981221982221983221984221985221986221987221988221989221990221991221992221993221994221995221996221997221998221999222000222001222002222003222004222005222006222007222008222009222010222011222012222013222014222015222016222017222018222019222020222021222022222023222024222025222026222027222028222029222030222031222032222033222034222035222036222037222038222039222040222041222042222043222044222045222046222047222048222049222050222051222052222053222054222055222056222057222058222059222060222061222062222063222064222065222066222067222068222069222070222071222072222073222074222075222076222077222078222079222080222081222082222083222084222085222086222087222088222089222090222091222092222093222094222095222096222097222098222099222100222101222102222103222104222105222106222107222108222109222110222111222112222113222114222115222116222117222118222119222120222121222122222123222124222125222126222127222128222129222130222131222132222133222134222135222136222137222138222139222140222141222142222143222144222145222146222147222148222149222150222151222152222153222154222155222156222157222158222159222160222161222162222163222164222165222166222167222168222169222170222171222172222173222174222175222176222177222178222179222180222181222182222183222184222185222186222187222188222189222190222191222192222193222194222195222196222197222198222199222200222201222202222203222204222205222206222207222208222209222210222211222212222213222214222215222216222217222218222219222220222221222222222223222224222225222226222227222228222229222230222231222232222233222234222235222236222237222238222239222240222241222242222243222244222245222246222247222248222249222250222251222252222253222254222255222256222257222258222259222260222261222262222263222264222265222266222267222268222269222270222271222272222273222274222275222276222277222278222279222280222281222282222283222284222285222286222287222288222289222290222291222292222293222294222295222296222297222298222299222300222301222302222303222304222305222306222307222308222309222310222311222312222313222314222315222316222317222318222319222320222321222322222323222324222325222326222327222328222329222330222331222332222333222334222335222336222337222338222339222340222341222342222343222344222345222346222347222348222349222350222351222352222353222354222355222356222357222358222359222360222361222362222363222364222365222366222367222368222369222370222371222372222373222374222375222376222377222378222379222380222381222382222383222384222385222386222387222388222389222390222391222392222393222394222395222396222397222398222399222400222401222402222403222404222405222406222407222408222409222410222411222412222413222414222415222416222417222418222419222420222421222422222423222424222425222426222427222428222429222430222431222432222433222434222435222436222437222438222439222440222441222442222443222444222445222446222447222448222449222450222451222452222453222454222455222456222457222458222459222460222461222462222463222464222465222466222467222468222469222470222471222472222473222474222475222476222477222478222479222480222481222482222483222484222485222486222487222488222489222490222491222492222493222494222495222496222497222498222499222500222501222502222503222504222505222506222507222508222509222510222511222512222513222514222515222516222517222518222519222520222521222522222523222524222525222526222527222528222529222530222531222532222533222534222535222536222537222538222539222540222541222542222543222544222545222546222547222548222549222550222551222552222553222554222555222556222557222558222559222560222561222562222563222564222565222566222567222568222569222570222571222572222573222574222575222576222577222578222579222580222581222582222583222584222585222586222587222588222589222590222591222592222593222594222595222596222597222598222599222600222601222602222603222604222605222606222607222608222609222610222611222612222613222614222615222616222617222618222619222620222621222622222623222624222625222626222627222628222629222630222631222632222633222634222635222636222637222638222639222640222641222642222643222644222645222646222647222648222649222650222651222652222653222654222655222656222657222658222659222660222661222662222663222664222665222666222667222668222669222670222671222672222673222674222675222676222677222678222679222680222681222682222683222684222685222686222687222688222689222690222691222692222693222694222695222696222697222698222699222700222701222702222703222704222705222706222707222708222709222710222711222712222713222714222715222716222717222718222719222720222721222722222723222724222725222726222727222728222729222730222731222732222733222734222735222736222737222738222739222740222741222742222743222744222745222746222747222748222749222750222751222752222753222754222755222756222757222758222759222760222761222762222763222764222765222766222767222768222769222770222771222772222773222774222775222776222777222778222779222780222781222782222783222784222785222786222787222788222789222790222791222792222793222794222795222796222797222798222799222800222801222802222803222804222805222806222807222808222809222810222811222812222813222814222815222816222817222818222819222820222821222822222823222824222825222826222827222828222829222830222831222832222833222834222835222836222837222838222839222840222841222842222843222844222845222846222847222848222849222850222851222852222853222854222855222856222857222858222859222860222861222862222863222864222865222866222867222868222869222870222871222872222873222874222875222876222877222878222879222880222881222882222883222884222885222886222887222888222889222890222891222892222893222894222895222896222897222898222899222900222901222902222903222904222905222906222907222908222909222910222911222912222913222914222915222916222917222918222919222920222921222922222923222924222925222926222927222928222929222930222931222932222933222934222935222936222937222938222939222940222941222942222943222944222945222946222947222948222949222950222951222952222953222954222955222956222957222958222959222960222961222962222963222964222965222966222967222968222969222970222971222972222973222974222975222976222977222978222979222980222981222982222983222984222985222986222987222988222989222990222991222992222993222994222995222996222997222998222999223000223001223002223003223004223005223006223007223008223009223010223011223012223013223014223015223016223017223018223019223020223021223022223023223024223025223026223027223028223029223030223031223032223033223034223035223036223037223038223039223040223041223042223043223044223045223046223047223048223049223050223051223052223053223054223055223056223057223058223059223060223061223062223063223064223065223066223067223068223069223070223071223072223073223074223075223076223077223078223079223080223081223082223083223084223085223086223087223088223089223090223091223092223093223094223095223096223097223098223099223100223101223102223103223104223105223106223107223108223109223110223111223112223113223114223115223116223117223118223119223120223121223122223123223124223125223126223127223128223129223130223131223132223133223134223135223136223137223138223139223140223141223142223143223144223145223146223147223148223149223150223151223152223153223154223155223156223157223158223159223160223161223162223163223164223165223166223167223168223169223170223171223172223173223174223175223176223177223178223179223180223181223182223183223184223185223186223187223188223189223190223191223192223193223194223195223196223197223198223199223200223201223202223203223204223205223206223207223208223209223210223211223212223213223214223215223216223217223218223219223220223221223222223223223224223225223226223227223228223229223230223231223232223233223234223235223236223237223238223239223240223241223242223243223244223245223246223247223248223249223250223251223252223253223254223255223256223257223258223259223260223261223262223263223264223265223266223267223268223269223270223271223272223273223274223275223276223277223278223279223280223281223282223283223284223285223286223287223288223289223290223291223292223293223294223295223296223297223298223299223300223301223302223303223304223305223306223307223308223309223310223311223312223313223314223315223316223317223318223319223320223321223322223323223324223325223326223327223328223329223330223331223332223333223334223335223336223337223338223339223340223341223342223343223344223345223346223347223348223349223350223351223352223353223354223355223356223357223358223359223360223361223362223363223364223365223366223367223368223369223370223371223372223373223374223375223376223377223378223379223380223381223382223383223384223385223386223387223388223389223390223391223392223393223394223395223396223397223398223399223400223401223402223403223404223405223406223407223408223409223410223411223412223413223414223415223416223417223418223419223420223421223422223423223424223425223426223427223428223429223430223431223432223433223434223435223436223437223438223439223440223441223442223443223444223445223446223447223448223449223450223451223452223453223454223455223456223457223458223459223460223461223462223463223464223465223466223467223468223469223470223471223472223473223474223475223476223477223478223479223480223481223482223483223484223485223486223487223488223489223490223491223492223493223494223495223496223497223498223499223500223501223502223503223504223505223506223507223508223509223510223511223512223513223514223515223516223517223518223519223520223521223522223523223524223525223526223527223528223529223530223531223532223533223534223535223536223537223538223539223540223541223542223543223544223545223546223547223548223549223550223551223552223553223554223555223556223557223558223559223560223561223562223563223564223565223566223567223568223569223570223571223572223573223574223575223576223577223578223579223580223581223582223583223584223585223586223587223588223589223590223591223592223593223594223595223596223597223598223599223600223601223602223603223604223605223606223607223608223609223610223611223612223613223614223615223616223617223618223619223620223621223622223623223624223625223626223627223628223629223630223631223632223633223634223635223636223637223638223639223640223641223642223643223644223645223646223647223648223649223650223651223652223653223654223655223656223657223658223659223660223661223662223663223664223665223666223667223668223669223670223671223672223673223674223675223676223677223678223679223680223681223682223683223684223685223686223687223688223689223690223691223692223693223694223695223696223697223698223699223700223701223702223703223704223705223706223707223708223709223710223711223712223713223714223715223716223717223718223719223720223721223722223723223724223725223726223727223728223729223730223731223732223733223734223735223736223737223738223739223740223741223742223743223744223745223746223747223748223749223750223751223752223753223754223755223756223757223758223759223760223761223762223763223764223765223766223767223768223769223770223771223772223773223774223775223776223777223778223779223780223781223782223783223784223785223786223787223788223789223790223791223792223793223794223795223796223797223798223799223800223801223802223803223804223805223806223807223808223809223810223811223812223813223814223815223816223817223818223819223820223821223822223823223824223825223826223827223828223829223830223831223832223833223834223835223836223837223838223839223840223841223842223843223844223845223846223847223848223849223850223851223852223853223854223855223856223857223858223859223860223861223862223863223864223865223866223867223868223869223870223871223872223873223874223875223876223877223878223879223880223881223882223883223884223885223886223887223888223889223890223891223892223893223894223895223896223897223898223899223900223901223902223903223904223905223906223907223908223909223910223911223912223913223914223915223916223917223918223919223920223921223922223923223924223925223926223927223928223929223930223931223932223933223934223935223936223937223938223939223940223941223942223943223944223945223946223947223948223949223950223951223952223953223954223955223956223957223958223959223960223961223962223963223964223965223966223967223968223969223970223971223972223973223974223975223976223977223978223979223980223981223982223983223984223985223986223987223988223989223990223991223992223993223994223995223996223997223998223999224000224001224002224003224004224005224006224007224008224009224010224011224012224013224014224015224016224017224018224019224020224021224022224023224024224025224026224027224028224029224030224031224032224033224034224035224036224037224038224039224040224041224042224043224044224045224046224047224048224049224050224051224052224053224054224055224056224057224058224059224060224061224062224063224064224065224066224067224068224069224070224071224072224073224074224075224076224077224078224079224080224081224082224083224084224085224086224087224088224089224090224091224092224093224094224095224096224097224098224099224100224101224102224103224104224105224106224107224108224109224110224111224112224113224114224115224116224117224118224119224120224121224122224123224124224125224126224127224128224129224130224131224132224133224134224135224136224137224138224139224140224141224142224143224144224145224146224147224148224149224150224151224152224153224154224155224156224157224158224159224160224161224162224163224164224165224166224167224168224169224170224171224172224173224174224175224176224177224178224179224180224181224182224183224184224185224186224187224188224189224190224191224192224193224194224195224196224197224198224199224200224201224202224203224204224205224206224207224208224209224210224211224212224213224214224215224216224217224218224219224220224221224222224223224224224225224226224227224228224229224230224231224232224233224234224235224236224237224238224239224240224241224242224243224244224245224246224247224248224249224250224251224252224253224254224255224256224257224258224259224260224261224262224263224264224265224266224267224268224269224270224271224272224273224274224275224276224277224278224279224280224281224282224283224284224285224286224287224288224289224290224291224292224293224294224295224296224297224298224299224300224301224302224303224304224305224306224307224308224309224310224311224312224313224314224315224316224317224318224319224320224321224322224323224324224325224326224327224328224329224330224331224332224333224334224335224336224337224338224339224340224341224342224343224344224345224346224347224348224349224350224351224352224353224354224355224356224357224358224359224360224361224362224363224364224365224366224367224368224369224370224371224372224373224374224375224376224377224378224379224380224381224382224383224384224385224386224387224388224389224390224391224392224393224394224395224396224397224398224399224400224401224402224403224404224405224406224407224408224409224410224411224412224413224414224415224416224417224418224419224420224421224422224423224424224425224426224427224428224429224430224431224432224433224434224435224436224437224438224439224440224441224442224443224444224445224446224447224448224449224450224451224452224453224454224455224456224457224458224459224460224461224462224463224464224465224466224467224468224469224470224471224472224473224474224475224476224477224478224479224480224481224482224483224484224485224486224487224488224489224490224491224492224493224494224495224496224497224498224499224500224501224502224503224504224505224506224507224508224509224510224511224512224513224514224515224516224517224518224519224520224521224522224523224524224525224526224527224528224529224530224531224532224533224534224535224536224537224538224539224540224541224542224543224544224545224546224547224548224549224550224551224552224553224554224555224556224557224558224559224560224561224562224563224564224565224566224567224568224569224570224571224572224573224574224575224576224577224578224579224580224581224582224583224584224585224586224587224588224589224590224591224592224593224594224595224596224597224598224599224600224601224602224603224604224605224606224607224608224609224610224611224612224613224614224615224616224617224618224619224620224621224622224623224624224625224626224627224628224629224630224631224632224633224634224635224636224637224638224639224640224641224642224643224644224645224646224647224648224649224650224651224652224653224654224655224656224657224658224659224660224661224662224663224664224665224666224667224668224669224670224671224672224673224674224675224676224677224678224679224680224681224682224683224684224685224686224687224688224689224690224691224692224693224694224695224696224697224698224699224700224701224702224703224704224705224706224707224708224709224710224711224712224713224714224715224716224717224718224719224720224721224722224723224724224725224726224727224728224729224730224731224732224733224734224735224736224737224738224739224740224741224742224743224744224745224746224747224748224749224750224751224752224753224754224755224756224757224758224759224760224761224762224763224764224765224766224767224768224769224770224771224772224773224774224775224776224777224778224779224780224781224782224783224784224785224786224787224788224789224790224791224792224793224794224795224796224797224798224799224800224801224802224803224804224805224806224807224808224809224810224811224812224813224814224815224816224817224818224819224820224821224822224823224824224825224826224827224828224829224830224831224832224833224834224835224836224837224838224839224840224841224842224843224844224845224846224847224848224849224850224851224852224853224854224855224856224857224858224859224860224861224862224863224864224865224866224867224868224869224870224871224872224873224874224875224876224877224878224879224880224881224882224883224884224885224886224887224888224889224890224891224892224893224894224895224896224897224898224899224900224901224902224903224904224905224906224907224908224909224910224911224912224913224914224915224916224917224918224919224920224921224922224923224924224925224926224927224928224929224930224931224932224933224934224935224936224937224938224939224940224941224942224943224944224945224946224947224948224949224950224951224952224953224954224955224956224957224958224959224960224961224962224963224964224965224966224967224968224969224970224971224972224973224974224975224976224977224978224979224980224981224982224983224984224985224986224987224988224989224990224991224992224993224994224995224996224997224998224999225000225001225002225003225004225005225006225007225008225009225010225011225012225013225014225015225016225017225018225019225020225021225022225023225024225025225026225027225028225029225030225031225032225033225034225035225036225037225038225039225040225041225042225043225044225045225046225047225048225049225050225051225052225053225054225055225056225057225058225059225060225061225062225063225064225065225066225067225068225069225070225071225072225073225074225075225076225077225078225079225080225081225082225083225084225085225086225087225088225089225090225091225092225093225094225095225096225097225098225099225100225101225102225103225104225105225106225107225108225109225110225111225112225113225114225115225116225117225118225119225120225121225122225123225124225125225126225127225128225129225130225131225132225133225134225135225136225137225138225139225140225141225142225143225144225145225146225147225148225149225150225151225152225153225154225155225156225157225158225159225160225161225162225163225164225165225166225167225168225169225170225171225172225173225174225175225176225177225178225179225180225181225182225183225184225185225186225187225188225189225190225191225192225193225194225195225196225197225198225199225200225201225202225203225204225205225206225207225208225209225210225211225212225213225214225215225216225217225218225219225220225221225222225223225224225225225226225227225228225229225230225231225232225233225234225235225236225237225238225239225240225241225242225243225244225245225246225247225248225249225250225251225252225253225254225255225256225257225258225259225260225261225262225263225264225265225266225267225268225269225270225271225272225273225274225275225276225277225278225279225280225281225282225283225284225285225286225287225288225289225290225291225292225293225294225295225296225297225298225299225300225301225302225303225304225305225306225307225308225309225310225311225312225313225314225315225316225317225318225319225320225321225322225323225324225325225326225327225328225329225330225331225332225333225334225335225336225337225338225339225340225341225342225343225344225345225346225347225348225349225350225351225352225353225354225355225356225357225358225359225360225361225362225363225364225365225366225367225368225369225370225371225372225373225374225375225376225377225378225379225380225381225382225383225384225385225386225387225388225389225390225391225392225393225394225395225396225397225398225399225400225401225402225403225404225405225406225407225408225409225410225411225412225413225414225415225416225417225418225419225420225421225422225423225424225425225426225427225428225429225430225431225432225433225434225435225436225437225438225439225440225441225442225443225444225445225446225447225448225449225450225451225452225453225454225455225456225457225458225459225460225461225462225463225464225465225466225467225468225469225470225471225472225473225474225475225476225477225478225479225480225481225482225483225484225485225486225487225488225489225490225491225492225493225494225495225496225497225498225499225500225501225502225503225504225505225506225507225508225509225510225511225512225513225514225515225516225517225518225519225520225521225522225523225524225525225526225527225528225529225530225531225532225533225534225535225536225537225538225539225540225541225542225543225544225545225546225547225548225549225550225551225552225553225554225555225556225557225558225559225560225561225562225563225564225565225566225567225568225569225570225571225572225573225574225575225576225577225578225579225580225581225582225583225584225585225586225587225588225589225590225591225592225593225594225595225596225597225598225599225600225601225602225603225604225605225606225607225608225609225610225611225612225613225614225615225616225617225618225619225620225621225622225623225624225625225626225627225628225629225630225631225632225633225634225635225636225637225638225639225640225641225642225643225644225645225646225647225648225649225650225651225652225653225654225655225656225657225658225659225660225661225662225663225664225665225666225667225668225669225670225671225672225673225674225675225676225677225678225679225680225681225682225683225684225685225686225687225688225689225690225691225692225693225694225695225696225697225698225699225700225701225702225703225704225705225706225707225708225709225710225711225712225713225714225715225716225717225718225719225720225721225722225723225724225725225726225727225728225729225730225731225732225733225734225735225736225737225738225739225740225741225742225743225744225745225746225747225748225749225750225751225752225753225754225755225756225757225758225759225760225761225762225763225764225765225766225767225768225769225770225771225772225773225774225775225776225777225778225779225780225781225782225783225784225785225786225787225788225789225790225791225792225793225794225795225796225797225798225799225800225801225802225803225804225805225806225807225808225809225810225811225812225813225814225815225816225817225818225819225820225821225822225823225824225825225826225827225828225829225830225831225832225833225834225835225836225837225838225839225840225841225842225843225844225845225846225847225848225849225850225851225852225853225854225855225856225857225858225859225860225861225862225863225864225865225866225867225868225869225870225871225872225873225874225875225876225877225878225879225880225881225882225883225884225885225886225887225888225889225890225891225892225893225894225895225896225897225898225899225900225901225902225903225904225905225906225907225908225909225910225911225912225913225914225915225916225917225918225919225920225921225922225923225924225925225926225927225928225929225930225931225932225933225934225935225936225937225938225939225940225941225942225943225944225945225946225947225948225949225950225951225952225953225954225955225956225957225958225959225960225961225962225963225964225965225966225967225968225969225970225971225972225973225974225975225976225977225978225979225980225981225982225983225984225985225986225987225988225989225990225991225992225993225994225995225996225997225998225999226000226001226002226003226004226005226006226007226008226009226010226011226012226013226014226015226016226017226018226019226020226021226022226023226024226025226026226027226028226029226030226031226032226033226034226035226036226037226038226039226040226041226042226043226044226045226046226047226048226049226050226051226052226053226054226055226056226057226058226059226060226061226062226063226064226065226066226067226068226069226070226071226072226073226074226075226076226077226078226079226080226081226082226083226084226085226086226087226088226089226090226091226092226093226094226095226096226097226098226099226100226101226102226103226104226105226106226107226108226109226110226111226112226113226114226115226116226117226118226119226120226121226122226123226124226125226126226127226128226129226130226131226132226133226134226135226136226137226138226139226140226141226142226143226144226145226146226147226148226149226150226151226152226153226154226155226156226157226158226159226160226161226162226163226164226165226166226167226168226169226170226171226172226173226174226175226176226177226178226179226180226181226182226183226184226185226186226187226188226189226190226191226192226193226194226195226196226197226198226199226200226201226202226203226204226205226206226207226208226209226210226211226212226213226214226215226216226217226218226219226220226221226222226223226224226225226226226227226228226229226230226231226232226233226234226235226236226237226238226239226240226241226242226243226244226245226246226247226248226249226250226251226252226253226254226255226256226257226258226259226260226261226262226263226264226265226266226267226268226269226270226271226272226273226274226275226276226277226278226279226280226281226282226283226284226285226286226287226288226289226290226291226292226293226294226295226296226297226298226299226300226301226302226303226304226305226306226307226308226309226310226311226312226313226314226315226316226317226318226319226320226321226322226323226324226325226326226327226328226329226330226331226332226333226334226335226336226337226338226339226340226341226342226343226344226345226346226347226348226349226350226351226352226353226354226355226356226357226358226359226360226361226362226363226364226365226366226367226368226369226370226371226372226373226374226375226376226377226378226379226380226381226382226383226384226385226386226387226388226389226390226391226392226393226394226395226396226397226398226399226400226401226402226403226404226405226406226407226408226409226410226411226412226413226414226415226416226417226418226419226420226421226422226423226424226425226426226427226428226429226430226431226432226433226434226435226436226437226438226439226440226441226442226443226444226445226446226447226448226449226450226451226452226453226454226455226456226457226458226459226460226461226462226463226464226465226466226467226468226469226470226471226472226473226474226475226476226477226478226479226480226481226482226483226484226485226486226487226488226489226490226491226492226493226494226495226496226497226498226499226500226501226502226503226504226505226506226507226508226509226510226511226512226513226514226515226516226517226518226519226520226521226522226523226524226525226526226527226528226529226530226531226532226533226534226535226536226537226538226539226540226541226542226543226544226545226546226547226548226549226550226551226552226553226554226555226556226557226558226559226560226561226562226563226564226565226566226567226568226569226570226571226572226573226574226575226576226577226578226579226580226581226582226583226584226585226586226587226588226589226590226591226592226593226594226595226596226597226598226599226600226601226602226603226604226605226606226607226608226609226610226611226612226613226614226615226616226617226618226619226620226621226622226623226624226625226626226627226628226629226630226631226632226633226634226635226636226637226638226639226640226641226642226643226644226645226646226647226648226649226650226651226652226653226654226655226656226657226658226659226660226661226662226663226664226665226666226667226668226669226670226671226672226673226674226675226676226677226678226679226680226681226682226683226684226685226686226687226688226689226690226691226692226693226694226695226696226697226698226699226700226701226702226703226704226705226706226707226708226709226710226711226712226713226714226715226716226717226718226719226720226721226722226723226724226725226726226727226728226729226730226731226732226733226734226735226736226737226738226739226740226741226742226743226744226745226746226747226748226749226750226751226752226753226754226755226756226757226758226759226760226761226762226763226764226765226766226767226768226769226770226771226772226773226774226775226776226777226778226779226780226781226782226783226784226785226786226787226788226789226790226791226792226793226794226795226796226797226798226799226800226801226802226803226804226805226806226807226808226809226810226811226812226813226814226815226816226817226818226819226820226821226822226823226824226825226826226827226828226829226830226831226832226833226834226835226836226837226838226839226840226841226842226843226844226845226846226847226848226849226850226851226852226853226854226855226856226857226858226859226860226861226862226863226864226865226866226867226868226869226870226871226872226873226874226875226876226877226878226879226880226881226882226883226884226885226886226887226888226889226890226891226892226893226894226895226896226897226898226899226900226901226902226903226904226905226906226907226908226909226910226911226912226913226914226915226916226917226918226919226920226921226922226923226924226925226926226927226928226929226930226931226932226933226934226935226936226937226938226939226940226941226942226943226944226945226946226947226948226949226950226951226952226953226954226955226956226957226958226959226960226961226962226963226964226965226966226967226968226969226970226971226972226973226974226975226976226977226978226979226980226981226982226983226984226985226986226987226988226989226990226991226992226993226994226995226996226997226998226999227000227001227002227003227004227005227006227007227008227009227010227011227012227013227014227015227016227017227018227019227020227021227022227023227024227025227026227027227028227029227030227031227032227033227034227035227036227037227038227039227040227041227042227043227044227045227046227047227048227049227050227051227052227053227054227055227056227057227058227059227060227061227062227063227064227065227066227067227068227069227070227071227072227073227074227075227076227077227078227079227080227081227082227083227084227085227086227087227088227089227090227091227092227093227094227095227096227097227098227099227100227101227102227103227104227105227106227107227108227109227110227111227112227113227114227115227116227117227118227119227120227121227122227123227124227125227126227127227128227129227130227131227132227133227134227135227136227137227138227139227140227141227142227143227144227145227146227147227148227149227150227151227152227153227154227155227156227157227158227159227160227161227162227163227164227165227166227167227168227169227170227171227172227173227174227175227176227177227178227179227180227181227182227183227184227185227186227187227188227189227190227191227192227193227194227195227196227197227198227199227200227201227202227203227204227205227206227207227208227209227210227211227212227213227214227215227216227217227218227219227220227221227222227223227224227225227226227227227228227229227230227231227232227233227234227235227236227237227238227239227240227241227242227243227244227245227246227247227248227249227250227251227252227253227254227255227256227257227258227259227260227261227262227263227264227265227266227267227268227269227270227271227272227273227274227275227276227277227278227279227280227281227282227283227284227285227286227287227288227289227290227291227292227293227294227295227296227297227298227299227300227301227302227303227304227305227306227307227308227309227310227311227312227313227314227315227316227317227318227319227320227321227322227323227324227325227326227327227328227329227330227331227332227333227334227335227336227337227338227339227340227341227342227343227344227345227346227347227348227349227350227351227352227353227354227355227356227357227358227359227360227361227362227363227364227365227366227367227368227369227370227371227372227373227374227375227376227377227378227379227380227381227382227383227384227385227386227387227388227389227390227391227392227393227394227395227396227397227398227399227400227401227402227403227404227405227406227407227408227409227410227411227412227413227414227415227416227417227418227419227420227421227422227423227424227425227426227427227428227429227430227431227432227433227434227435227436227437227438227439227440227441227442227443227444227445227446227447227448227449227450227451227452227453227454227455227456227457227458227459227460227461227462227463227464227465227466227467227468227469227470227471227472227473227474227475227476227477227478227479227480227481227482227483227484227485227486227487227488227489227490227491227492227493227494227495227496227497227498227499227500227501227502227503227504227505227506227507227508227509227510227511227512227513227514227515227516227517227518227519227520227521227522227523227524227525227526227527227528227529227530227531227532227533227534227535227536227537227538227539227540227541227542227543227544227545227546227547227548227549227550227551227552227553227554227555227556227557227558227559227560227561227562227563227564227565227566227567227568227569227570227571227572227573227574227575227576227577227578227579227580227581227582227583227584227585227586227587227588227589227590227591227592227593227594227595227596227597227598227599227600227601227602227603227604227605227606227607227608227609227610227611227612227613227614227615227616227617227618227619227620227621227622227623227624227625227626227627227628227629227630227631227632227633227634227635227636227637227638227639227640227641227642227643227644227645227646227647227648227649227650227651227652227653227654227655227656227657227658227659227660227661227662227663227664227665227666227667227668227669227670227671227672227673227674227675227676227677227678227679227680227681227682227683227684227685227686227687227688227689227690227691227692227693227694227695227696227697227698227699227700227701227702227703227704227705227706227707227708227709227710227711227712227713227714227715227716227717227718227719227720227721227722227723227724227725227726227727227728227729227730227731227732227733227734227735227736227737227738227739227740227741227742227743227744227745227746227747227748227749227750227751227752227753227754227755227756227757227758227759227760227761227762227763227764227765227766227767227768227769227770227771227772227773227774227775227776227777227778227779227780227781227782227783227784227785227786227787227788227789227790227791227792227793227794227795227796227797227798227799227800227801227802227803227804227805227806227807227808227809227810227811227812227813227814227815227816227817227818227819227820227821227822227823227824227825227826227827227828227829227830227831227832227833227834227835227836227837227838227839227840227841227842227843227844227845227846227847227848227849227850227851227852227853227854227855227856227857227858227859227860227861227862227863227864227865227866227867227868227869227870227871227872227873227874227875227876227877227878227879227880227881227882227883227884227885227886227887227888227889227890227891227892227893227894227895227896227897227898227899227900227901227902227903227904227905227906227907227908227909227910227911227912227913227914227915227916227917227918227919227920227921227922227923227924227925227926227927227928227929227930227931227932227933227934227935227936227937227938227939227940227941227942227943227944227945227946227947227948227949227950227951227952227953227954227955227956227957227958227959227960227961227962227963227964227965227966227967227968227969227970227971227972227973227974227975227976227977227978227979227980227981227982227983227984227985227986227987227988227989227990227991227992227993227994227995227996227997227998227999228000228001228002228003228004228005228006228007228008228009228010228011228012228013228014228015228016228017228018228019228020228021228022228023228024228025228026228027228028228029228030228031228032228033228034228035228036228037228038228039228040228041228042228043228044228045228046228047228048228049228050228051228052228053228054228055228056228057228058228059228060228061228062228063228064228065228066228067228068228069228070228071228072228073228074228075228076228077228078228079228080228081228082228083228084228085228086228087228088228089228090228091228092228093228094228095228096228097228098228099228100228101228102228103228104228105228106228107228108228109228110228111228112228113228114228115228116228117228118228119228120228121228122228123228124228125228126228127228128228129228130228131228132228133228134228135228136228137228138228139228140228141228142228143228144228145228146228147228148228149228150228151228152228153228154228155228156228157228158228159228160228161228162228163228164228165228166228167228168228169228170228171228172228173228174228175228176228177228178228179228180228181228182228183228184228185228186228187228188228189228190228191228192228193228194228195228196228197228198228199228200228201228202228203228204228205228206228207228208228209228210228211228212228213228214228215228216228217228218228219228220228221228222228223228224228225228226228227228228228229228230228231228232228233228234228235228236228237228238228239228240228241228242228243228244228245228246228247228248228249228250228251228252228253228254228255228256228257228258228259228260228261228262228263228264228265228266228267228268228269228270228271228272228273228274228275228276228277228278228279228280228281228282228283228284228285228286228287228288228289228290228291228292228293228294228295228296228297228298228299228300228301228302228303228304228305228306228307228308228309228310228311228312228313228314228315228316228317228318228319228320228321228322228323228324228325228326228327228328228329228330228331228332228333228334228335228336228337228338228339228340228341228342228343228344228345228346228347228348228349228350228351228352228353228354228355228356228357228358228359228360228361228362228363228364228365228366228367228368228369228370228371228372228373228374228375228376228377228378228379228380228381228382228383228384228385228386228387228388228389228390228391228392228393228394228395228396228397228398228399228400228401228402228403228404228405228406228407228408228409228410228411228412228413228414228415228416228417228418228419228420228421228422228423228424228425228426228427228428228429228430228431228432228433228434228435228436228437228438228439228440228441228442228443228444228445228446228447228448228449228450228451228452228453228454228455228456228457228458228459228460228461228462228463228464228465228466228467228468228469228470228471228472228473228474228475228476228477228478228479228480228481228482228483228484228485228486228487228488228489228490228491228492228493228494228495228496228497228498228499228500228501228502228503228504228505228506228507228508228509228510228511228512228513228514228515228516228517228518228519228520228521228522228523228524228525228526228527228528228529228530228531228532228533228534228535228536228537228538228539228540228541228542228543228544228545228546228547228548228549228550228551228552228553228554228555228556228557228558228559228560228561228562228563228564228565228566228567228568228569228570228571228572228573228574228575228576228577228578228579228580228581228582228583228584228585228586228587228588228589228590228591228592228593228594228595228596228597228598228599228600228601228602228603228604228605228606228607228608228609228610228611228612228613228614228615228616228617228618228619228620228621228622228623228624228625228626228627228628228629228630228631228632228633228634228635228636228637228638228639228640228641228642228643228644228645228646228647228648228649228650228651228652228653228654228655228656228657228658228659228660228661228662228663228664228665228666228667228668228669228670228671228672228673228674228675228676228677228678228679228680228681228682228683228684228685228686228687228688228689228690228691228692228693228694228695228696228697228698228699228700228701228702228703228704228705228706228707228708228709228710228711228712228713228714228715228716228717228718228719228720228721228722228723228724228725228726228727228728228729228730228731228732228733228734228735228736228737228738228739228740228741228742228743228744228745228746228747228748228749228750228751228752228753228754228755228756228757228758228759228760228761228762228763228764228765228766228767228768228769228770228771228772228773228774228775228776228777228778228779228780228781228782228783228784228785228786228787228788228789228790228791228792228793228794228795228796228797228798228799228800228801228802228803228804228805228806228807228808228809228810228811228812228813228814228815228816228817228818228819228820228821228822228823228824228825228826228827228828228829228830228831228832228833228834228835228836228837228838228839228840228841228842228843228844228845228846228847228848228849228850228851228852228853228854228855228856228857228858228859228860228861228862228863228864228865228866228867228868228869228870228871228872228873228874228875228876228877228878228879228880228881228882228883228884228885228886228887228888228889228890228891228892228893228894228895228896228897228898228899228900228901228902228903228904228905228906228907228908228909228910228911228912228913228914228915228916228917228918228919228920228921228922228923228924228925228926228927228928228929228930228931228932228933228934228935228936228937228938228939228940228941228942228943228944228945228946228947228948228949228950228951228952228953228954228955228956228957228958228959228960228961228962228963228964228965228966228967228968228969228970228971228972228973228974228975228976228977228978228979228980228981228982228983228984228985228986228987228988228989228990228991228992228993228994228995228996228997228998228999229000229001229002229003229004229005229006229007229008229009229010229011229012229013229014229015229016229017229018229019229020229021229022229023229024229025229026229027229028229029229030229031229032229033229034229035229036229037229038229039229040229041229042229043229044229045229046229047229048229049229050229051229052229053229054229055229056229057229058229059229060229061229062229063229064229065229066229067229068229069229070229071229072229073229074229075229076229077229078229079229080229081229082229083229084229085229086229087229088229089229090229091229092229093229094229095229096229097229098229099229100229101229102229103229104229105229106229107229108229109229110229111229112229113229114229115229116229117229118229119229120229121229122229123229124229125229126229127229128229129229130229131229132229133229134229135229136229137229138229139229140229141229142229143229144229145229146229147229148229149229150229151229152229153229154229155229156229157229158229159229160229161229162229163229164229165229166229167229168229169229170229171229172229173229174229175229176229177229178229179229180229181229182229183229184229185229186229187229188229189229190229191229192229193229194229195229196229197229198229199229200229201229202229203229204229205229206229207229208229209229210229211229212229213229214229215229216229217229218229219229220229221229222229223229224229225229226229227229228229229229230229231229232229233229234229235229236229237229238229239229240229241229242229243229244229245229246229247229248229249229250229251229252229253229254229255229256229257229258229259229260229261229262229263229264229265229266229267229268229269229270229271229272229273229274229275229276229277229278229279229280229281229282229283229284229285229286229287229288229289229290229291229292229293229294229295229296229297229298229299229300229301229302229303229304229305229306229307229308229309229310229311229312229313229314229315229316229317229318229319229320229321229322229323229324229325229326229327229328229329229330229331229332229333229334229335229336229337229338229339229340229341229342229343229344229345229346229347229348229349229350229351229352229353229354229355229356229357229358229359229360229361229362229363229364229365229366229367229368229369229370229371229372229373229374229375229376229377229378229379229380229381229382229383229384229385229386229387229388229389229390229391229392229393229394229395229396229397229398229399229400229401229402229403229404229405229406229407229408229409229410229411229412229413229414229415229416229417229418229419229420229421229422229423229424229425229426229427229428229429229430229431229432229433229434229435229436229437229438229439229440229441229442229443229444229445229446229447229448229449229450229451229452229453229454229455229456229457229458229459229460229461229462229463229464229465229466229467229468229469229470229471229472229473229474229475229476229477229478229479229480229481229482229483229484229485229486229487229488229489229490229491229492229493229494229495229496229497229498229499229500229501229502229503229504229505229506229507229508229509229510229511229512229513229514229515229516229517229518229519229520229521229522229523229524229525229526229527229528229529229530229531229532229533229534229535229536229537229538229539229540229541229542229543229544229545229546229547229548229549229550229551229552229553229554229555229556229557229558229559229560229561229562229563229564229565229566229567229568229569229570229571229572229573229574229575229576229577229578229579229580229581229582229583229584229585229586229587229588229589229590229591229592229593229594229595229596229597229598229599229600229601229602229603229604229605229606229607229608229609229610229611229612229613229614229615229616229617229618229619229620229621229622229623229624229625229626229627229628229629229630229631229632229633229634229635229636229637229638229639229640229641229642229643229644229645229646229647229648229649229650229651229652229653229654229655229656229657229658229659229660229661229662229663229664229665229666229667229668229669229670229671229672229673229674229675229676229677229678229679229680229681229682229683229684229685229686229687229688229689229690229691229692229693229694229695229696229697229698229699229700229701229702229703229704229705229706229707229708229709229710229711229712229713229714229715229716229717229718229719229720229721229722229723229724229725229726229727229728229729229730229731229732229733229734229735229736229737229738229739229740229741229742229743229744229745229746229747229748229749229750229751229752229753229754229755229756229757229758229759229760229761229762229763229764229765229766229767229768229769229770229771229772229773229774229775229776229777229778229779229780229781229782229783229784229785229786229787229788229789229790229791229792229793229794229795229796229797229798229799229800229801229802229803229804229805229806229807229808229809229810229811229812229813229814229815229816229817229818229819229820229821229822229823229824229825229826229827229828229829229830229831229832229833229834229835229836229837229838229839229840229841229842229843229844229845229846229847229848229849229850229851229852229853229854229855229856229857229858229859229860229861229862229863229864229865229866229867229868229869229870229871229872229873229874229875229876229877229878229879229880229881229882229883229884229885229886229887229888229889229890229891229892229893229894229895229896229897229898229899229900229901229902229903229904229905229906229907229908229909229910229911229912229913229914229915229916229917229918229919229920229921229922229923229924229925229926229927229928229929229930229931229932229933229934229935229936229937229938229939229940229941229942229943229944229945229946229947229948229949229950229951229952229953229954229955229956229957229958229959229960229961229962229963229964229965229966229967229968229969229970229971229972229973229974229975229976229977229978229979229980229981229982229983229984229985229986229987229988229989229990229991229992229993229994229995229996229997229998229999230000230001230002230003230004230005230006230007230008230009230010230011230012230013230014230015230016230017230018230019230020230021230022230023230024230025230026230027230028230029230030230031230032230033230034230035230036230037230038230039230040230041230042230043230044230045230046230047230048230049230050230051230052230053230054230055230056230057230058230059230060230061230062230063230064230065230066230067230068230069230070230071230072230073230074230075230076230077230078230079230080230081230082230083230084230085230086230087230088230089230090230091230092230093230094230095230096230097230098230099230100230101230102230103230104230105230106230107230108230109230110230111230112230113230114230115230116230117230118230119230120230121230122230123230124230125230126230127230128230129230130230131230132230133230134230135230136230137230138230139230140230141230142230143230144230145230146230147230148230149230150230151230152230153230154230155230156230157230158230159230160230161230162230163230164230165230166230167230168230169230170230171230172230173230174230175230176230177230178230179230180230181230182230183230184230185230186230187230188230189230190230191230192230193230194230195230196230197230198230199230200230201230202230203230204230205230206230207230208230209230210230211230212230213230214230215230216230217230218230219230220230221230222230223230224230225230226230227230228230229230230230231230232230233230234230235230236230237230238230239230240230241230242230243230244230245230246230247230248230249230250230251230252230253230254230255230256230257230258230259230260230261230262230263230264230265230266230267230268230269230270230271230272230273230274230275230276230277230278230279230280230281230282230283230284230285230286230287230288230289230290230291230292230293230294230295230296230297230298230299230300230301230302230303230304230305230306230307230308230309230310230311230312230313230314230315230316230317230318230319230320230321230322230323230324230325230326230327230328230329230330230331230332230333230334230335230336230337230338230339230340230341230342230343230344230345230346230347230348230349230350230351230352230353230354230355230356230357230358230359230360230361230362230363230364230365230366230367230368230369230370230371230372230373230374230375230376230377230378230379230380230381230382230383230384230385230386230387230388230389230390230391230392230393230394230395230396230397230398230399230400230401230402230403230404230405230406230407230408230409230410230411230412230413230414230415230416230417230418230419230420230421230422230423230424230425230426230427230428230429230430230431230432230433230434230435230436230437230438230439230440230441230442230443230444230445230446230447230448230449230450230451230452230453230454230455230456230457230458230459230460230461230462230463230464230465230466230467230468230469230470230471230472230473230474230475230476230477230478230479230480230481230482230483230484230485230486230487230488230489230490230491230492230493230494230495230496230497230498230499230500230501230502230503230504230505230506230507230508230509230510230511230512230513230514230515230516230517230518230519230520230521230522230523230524230525230526230527230528230529230530230531230532230533230534230535230536230537230538230539230540230541230542230543230544230545230546230547230548230549230550230551230552230553230554230555230556230557230558230559230560230561230562230563230564230565230566230567230568230569230570230571230572230573230574230575230576230577230578230579230580230581230582230583230584230585230586230587230588230589230590230591230592230593230594230595230596230597230598230599230600230601230602230603230604230605230606230607230608230609230610230611230612230613230614230615230616230617230618230619230620230621230622230623230624230625230626230627230628230629230630230631230632230633230634230635230636230637230638230639230640230641230642230643230644230645230646230647230648230649230650230651230652230653230654230655230656230657230658230659230660230661230662230663230664230665230666230667230668230669230670230671230672230673230674230675230676230677230678230679230680230681230682230683230684230685230686230687230688230689230690230691230692230693230694230695230696230697230698230699230700230701230702230703230704230705230706230707230708230709230710230711230712230713230714230715230716230717230718230719230720230721230722230723230724230725230726230727230728230729230730230731230732230733230734230735230736230737230738230739230740230741230742230743230744230745230746230747230748230749230750230751230752230753230754230755230756230757230758230759230760230761230762230763230764230765230766230767230768230769230770230771230772230773230774230775230776230777230778230779230780230781230782230783230784230785230786230787230788230789230790230791230792230793230794230795230796230797230798230799230800230801230802230803230804230805230806230807230808230809230810230811230812230813230814230815230816230817230818230819230820230821230822230823230824230825230826230827230828230829230830230831230832230833230834230835230836230837230838230839230840230841230842230843230844230845230846230847230848230849230850230851230852230853230854230855230856230857230858230859230860230861230862230863230864230865230866230867230868230869230870230871230872230873230874230875230876230877230878230879230880230881230882230883230884230885230886230887230888230889230890230891230892230893230894230895230896230897230898230899230900230901230902230903230904230905230906230907230908230909230910230911230912230913230914230915230916230917230918230919230920230921230922230923230924230925230926230927230928230929230930230931230932230933230934230935230936230937230938230939230940230941230942230943230944230945230946230947230948230949230950230951230952230953230954230955230956230957230958230959230960230961230962230963230964230965230966230967230968230969230970230971230972230973230974230975230976230977230978230979230980230981230982230983230984230985230986230987230988230989230990230991230992230993230994230995230996230997230998230999231000231001231002231003231004231005231006231007231008231009231010231011231012231013231014231015231016231017231018231019231020231021231022231023231024231025231026231027231028231029231030231031231032231033231034231035231036231037231038231039231040231041231042231043231044231045231046231047231048231049231050231051231052231053231054231055231056231057231058231059231060231061231062231063231064231065231066231067231068231069231070231071231072231073231074231075231076231077231078231079231080231081231082231083231084231085231086231087231088231089231090231091231092231093231094231095231096231097231098231099231100231101231102231103231104231105231106231107231108231109231110231111231112231113231114231115231116231117231118231119231120231121231122231123231124231125231126231127231128231129231130231131231132231133231134231135231136231137231138231139231140231141231142231143231144231145231146231147231148231149231150231151231152231153231154231155231156231157231158231159231160231161231162231163231164231165231166231167231168231169231170231171231172231173231174231175231176231177231178231179231180231181231182231183231184231185231186231187231188231189231190231191231192231193231194231195231196231197231198231199231200231201231202231203231204231205231206231207231208231209231210231211231212231213231214231215231216231217231218231219231220231221231222231223231224231225231226231227231228231229231230231231231232231233231234231235231236231237231238231239231240231241231242231243231244231245231246231247231248231249231250231251231252231253231254231255231256231257231258231259231260231261231262231263231264231265231266231267231268231269231270231271231272231273231274231275231276231277231278231279231280231281231282231283231284231285231286231287231288231289231290231291231292231293231294231295231296231297231298231299231300231301231302231303231304231305231306231307231308231309231310231311231312231313231314231315231316231317231318231319231320231321231322231323231324231325231326231327231328231329231330231331231332231333231334231335231336231337231338231339231340231341231342231343231344231345231346231347231348231349231350231351231352231353231354231355231356231357231358231359231360231361231362231363231364231365231366231367231368231369231370231371231372231373231374231375231376231377231378231379231380231381231382231383231384231385231386231387231388231389231390231391231392231393231394231395231396231397231398231399231400231401231402231403231404231405231406231407231408231409231410231411231412231413231414231415231416231417231418231419231420231421231422231423231424231425231426231427231428231429231430231431231432231433231434231435231436231437231438231439231440231441231442231443231444231445231446231447231448231449231450231451231452231453231454231455231456231457231458231459231460231461231462231463231464231465231466231467231468231469231470231471231472231473231474231475231476231477231478231479231480231481231482231483231484231485231486231487231488231489231490231491231492231493231494231495231496231497231498231499231500231501231502231503231504231505231506231507231508231509231510231511231512231513231514231515231516231517231518231519231520231521231522231523231524231525231526231527231528231529231530231531231532231533231534231535231536231537231538231539231540231541231542231543231544231545231546231547231548231549231550231551231552231553231554231555231556231557231558231559231560231561231562231563231564231565231566231567231568231569231570231571231572231573231574231575231576231577231578231579231580231581231582231583231584231585231586231587231588231589231590231591231592231593231594231595231596231597231598231599231600231601231602231603231604231605231606231607231608231609231610231611231612231613231614231615231616231617231618231619231620231621231622231623231624231625231626231627231628231629231630231631231632231633231634231635231636231637231638231639231640231641231642231643231644231645231646231647231648231649231650231651231652231653231654231655231656231657231658231659231660231661231662231663231664231665231666231667231668231669231670231671231672231673231674231675231676231677231678231679231680231681231682231683231684231685231686231687231688231689231690231691231692231693231694231695231696231697231698231699231700231701231702231703231704231705231706231707231708231709231710231711231712231713231714231715231716231717231718231719231720231721231722231723231724231725231726231727231728231729231730231731231732231733231734231735231736231737231738231739231740231741231742231743231744231745231746231747231748231749231750231751231752231753231754231755231756231757231758231759231760231761231762231763231764231765231766231767231768231769231770231771231772231773231774231775231776231777231778231779231780231781231782231783231784231785231786231787231788231789231790231791231792231793231794231795231796231797231798231799231800231801231802231803231804231805231806231807231808231809231810231811231812231813231814231815231816231817231818231819231820231821231822231823231824231825231826231827231828231829231830231831231832231833231834231835231836231837231838231839231840231841231842231843231844231845231846231847231848231849231850231851231852231853231854231855231856231857231858231859231860231861231862231863231864231865231866231867231868231869231870231871231872231873231874231875231876231877231878231879231880231881231882231883231884231885231886231887231888231889231890231891231892231893231894231895231896231897231898231899231900231901231902231903231904231905231906231907231908231909231910231911231912231913231914231915231916231917231918231919231920231921231922231923231924231925231926231927231928231929231930231931231932231933231934231935231936231937231938231939231940231941231942231943231944231945231946231947231948231949231950231951231952231953231954231955231956231957231958231959231960231961231962231963231964231965231966231967231968231969231970231971231972231973231974231975231976231977231978231979231980231981231982231983231984231985231986231987231988231989231990231991231992231993231994231995231996231997231998231999232000232001232002232003232004232005232006232007232008232009232010232011232012232013232014232015232016232017232018232019232020232021232022232023232024232025232026232027232028232029232030232031232032232033232034232035232036232037232038232039232040232041232042232043232044232045232046232047232048232049232050232051232052232053232054232055232056232057232058232059232060232061232062232063232064232065232066232067232068232069232070232071232072232073232074232075232076232077232078232079232080232081232082232083232084232085232086232087232088232089232090232091232092232093232094232095232096232097232098232099232100232101232102232103232104232105232106232107232108232109232110232111232112232113232114232115232116232117232118232119232120232121232122232123232124232125232126232127232128232129232130232131232132232133232134232135232136232137232138232139232140232141232142232143232144232145232146232147232148232149232150232151232152232153232154232155232156232157232158232159232160232161232162232163232164232165232166232167232168232169232170232171232172232173232174232175232176232177232178232179232180232181232182232183232184232185232186232187232188232189232190232191232192232193232194232195232196232197232198232199232200232201232202232203232204232205232206232207232208232209232210232211232212232213232214232215232216232217232218232219232220232221232222232223232224232225232226232227232228232229232230232231232232232233232234232235232236232237232238232239232240232241232242232243232244232245232246232247232248232249232250232251232252232253232254232255232256232257232258232259232260232261232262232263232264232265232266232267232268232269232270232271232272232273232274232275232276232277232278232279232280232281232282232283232284232285232286232287232288232289232290232291232292232293232294232295232296232297232298232299232300232301232302232303232304232305232306232307232308232309232310232311232312232313232314232315232316232317232318232319232320232321232322232323232324232325232326232327232328232329232330232331232332232333232334232335232336232337232338232339232340232341232342232343232344232345232346232347232348232349232350232351232352232353232354232355232356232357232358232359232360232361232362232363232364232365232366232367232368232369232370232371232372232373232374232375232376232377232378232379232380232381232382232383232384232385232386232387232388232389232390232391232392232393232394232395232396232397232398232399232400232401232402232403232404232405232406232407232408232409232410232411232412232413232414232415232416232417232418232419232420232421232422232423232424232425232426232427232428232429232430232431232432232433232434232435232436232437232438232439232440232441232442232443232444232445232446232447232448232449232450232451232452232453232454232455232456232457232458232459232460232461232462232463232464232465232466232467232468232469232470232471232472232473232474232475232476232477232478232479232480232481232482232483232484232485232486232487232488232489232490232491232492232493232494232495232496232497232498232499232500232501232502232503232504232505232506232507232508232509232510232511232512232513232514232515232516232517232518232519232520232521232522232523232524232525232526232527232528232529232530232531232532232533232534232535232536232537232538232539232540232541232542232543232544232545232546232547232548232549232550232551232552232553232554232555232556232557232558232559232560232561232562232563232564232565232566232567232568232569232570232571232572232573232574232575232576232577232578232579232580232581232582232583232584232585232586232587232588232589232590232591232592232593232594232595232596232597232598232599232600232601232602232603232604232605232606232607232608232609232610232611232612232613232614232615232616232617232618232619232620232621232622232623232624232625232626232627232628232629232630232631232632232633232634232635232636232637232638232639232640232641232642232643232644232645232646232647232648232649232650232651232652232653232654232655232656232657232658232659232660232661232662232663232664232665232666232667232668232669232670232671232672232673232674232675232676232677232678232679232680232681232682232683232684232685232686232687232688232689232690232691232692232693232694232695232696232697232698232699232700232701232702232703232704232705232706232707232708232709232710232711232712232713232714232715232716232717232718232719232720232721232722232723232724232725232726232727232728232729232730232731232732232733232734232735232736232737232738232739232740232741232742232743232744232745232746232747232748232749232750232751232752232753232754232755232756232757232758232759232760232761232762232763232764232765232766232767232768232769232770232771232772232773232774232775232776232777232778232779232780232781232782232783232784232785232786232787232788232789232790232791232792232793232794232795232796232797232798232799232800232801232802232803232804232805232806232807232808232809232810232811232812232813232814232815232816232817232818232819232820232821232822232823232824232825232826232827232828232829232830232831232832232833232834232835232836232837232838232839232840232841232842232843232844232845232846232847232848232849232850232851232852232853232854232855232856232857232858232859232860232861232862232863232864232865232866232867232868232869232870232871232872232873232874232875232876232877232878232879232880232881232882232883232884232885232886232887232888232889232890232891232892232893232894232895232896232897232898232899232900232901232902232903232904232905232906232907232908232909232910232911232912232913232914232915232916232917232918232919232920232921232922232923232924232925232926232927232928232929232930232931232932232933232934232935232936232937232938232939232940232941232942232943232944232945232946232947232948232949232950232951232952232953232954232955232956232957232958232959232960232961232962232963232964232965232966232967232968232969232970232971232972232973232974232975232976232977232978232979232980232981232982232983232984232985232986232987232988232989232990232991232992232993232994232995232996232997232998232999233000233001233002233003233004233005233006233007233008233009233010233011233012233013233014233015233016233017233018233019233020233021233022233023233024233025233026233027233028233029233030233031233032233033233034233035233036233037233038233039233040233041233042233043233044233045233046233047233048233049233050233051233052233053233054233055233056233057233058233059233060233061233062233063233064233065233066233067233068233069233070233071233072233073233074233075233076233077233078233079233080233081233082233083233084233085233086233087233088233089233090233091233092233093233094233095233096233097233098233099233100233101233102233103233104233105233106233107233108233109233110233111233112233113233114233115233116233117233118233119233120233121233122233123233124233125233126233127233128233129233130233131233132233133233134233135233136233137233138233139233140233141233142233143233144233145233146233147233148233149233150233151233152233153233154233155233156233157233158233159233160233161233162233163233164233165233166233167233168233169233170233171233172233173233174233175233176233177233178233179233180233181233182233183233184233185233186233187233188233189233190233191233192233193233194233195233196233197233198233199233200233201233202233203233204233205233206233207233208233209233210233211233212233213233214233215233216233217233218233219233220233221233222233223233224233225233226233227233228233229233230233231233232233233233234233235233236233237233238233239233240233241233242233243233244233245233246233247233248233249233250233251233252233253233254233255233256233257233258233259233260233261233262233263233264233265233266233267233268233269233270233271233272233273233274233275233276233277233278233279233280233281233282233283233284233285233286233287233288233289233290233291233292233293233294233295233296233297233298233299233300233301233302233303233304233305233306233307233308233309233310233311233312233313233314233315233316233317233318233319233320233321233322233323233324233325233326233327233328233329233330233331233332233333233334233335233336233337233338233339233340233341233342233343233344233345233346233347233348233349233350233351233352233353233354233355233356233357233358233359233360233361233362233363233364233365233366233367233368233369233370233371233372233373233374233375233376233377233378233379233380233381233382233383233384233385233386233387233388233389233390233391233392233393233394233395233396233397233398233399233400233401233402233403233404233405233406233407233408233409233410233411233412233413233414233415233416233417233418233419233420233421233422233423233424233425233426233427233428233429233430233431233432233433233434233435233436233437233438233439233440233441233442233443233444233445233446233447233448233449233450233451233452233453233454233455233456233457233458233459233460233461233462233463233464233465233466233467233468233469233470233471233472233473233474233475233476233477233478233479233480233481233482233483233484233485233486233487233488233489233490233491233492233493233494233495233496233497233498233499233500233501233502233503233504233505233506233507233508233509233510233511233512233513233514233515233516233517233518233519233520233521233522233523233524233525233526233527233528233529233530233531233532233533233534233535233536233537233538233539233540233541233542233543233544233545233546233547233548233549233550233551233552233553233554233555233556233557233558233559233560233561233562233563233564233565233566233567233568233569233570233571233572233573233574233575233576233577233578233579233580233581233582233583233584233585233586233587233588233589233590233591233592233593233594233595233596233597233598233599233600233601233602233603233604233605233606233607233608233609233610233611233612233613233614233615233616233617233618233619233620233621233622233623233624233625233626233627233628233629233630233631233632233633233634233635233636233637233638233639233640233641233642233643233644233645233646233647233648233649233650233651233652233653233654233655233656233657233658233659233660233661233662233663233664233665233666233667233668233669233670233671233672233673233674233675233676233677233678233679233680233681233682233683233684233685233686233687233688233689233690233691233692233693233694233695233696233697233698233699233700233701233702233703233704233705233706233707233708233709233710233711233712233713233714233715233716233717233718233719233720233721233722233723233724233725233726233727233728233729233730233731233732233733233734233735233736233737233738233739233740233741233742233743233744233745233746233747233748233749233750233751233752233753233754233755233756233757233758233759233760233761233762233763233764233765233766233767233768233769233770233771233772233773233774233775233776233777233778233779233780233781233782233783233784233785233786233787233788233789233790233791233792233793233794233795233796233797233798233799233800233801233802233803233804233805233806233807233808233809233810233811233812233813233814233815233816233817233818233819233820233821233822233823233824233825233826233827233828233829233830233831233832233833233834233835233836233837233838233839233840233841233842233843233844233845233846233847233848233849233850233851233852233853233854233855233856233857233858233859233860233861233862233863233864233865233866233867233868233869233870233871233872233873233874233875233876233877233878233879233880233881233882233883233884233885233886233887233888233889233890233891233892233893233894233895233896233897233898233899233900233901233902233903233904233905233906233907233908233909233910233911233912233913233914233915233916233917233918233919233920233921233922233923233924233925233926233927233928233929233930233931233932233933233934233935233936233937233938233939233940233941233942233943233944233945233946233947233948233949233950233951233952233953233954233955233956233957233958233959233960233961233962233963233964233965233966233967233968233969233970233971233972233973233974233975233976233977233978233979233980233981233982233983233984233985233986233987233988233989233990233991233992233993233994233995233996233997233998233999234000234001234002234003234004234005234006234007234008234009234010234011234012234013234014234015234016234017234018234019234020234021234022234023234024234025234026234027234028234029234030234031234032234033234034234035234036234037234038234039234040234041234042234043234044234045234046234047234048234049234050234051234052234053234054234055234056234057234058234059234060234061234062234063234064234065234066234067234068234069234070234071234072234073234074234075234076234077234078234079234080234081234082234083234084234085234086234087234088234089234090234091234092234093234094234095234096234097234098234099234100234101234102234103234104234105234106234107234108234109234110234111234112234113234114234115234116234117234118234119234120234121234122234123234124234125234126234127234128234129234130234131234132234133234134234135234136234137234138234139234140234141234142234143234144234145234146234147234148234149234150234151234152234153234154234155234156234157234158234159234160234161234162234163234164234165234166234167234168234169234170234171234172234173234174234175234176234177234178234179234180234181234182234183234184234185234186234187234188234189234190234191234192234193234194234195234196234197234198234199234200234201234202234203234204234205234206234207234208234209234210234211234212234213234214234215234216234217234218234219234220234221234222234223234224234225234226234227234228234229234230234231234232234233234234234235234236234237234238234239234240234241234242234243234244234245234246234247234248234249234250234251234252234253234254234255234256234257234258234259234260234261234262234263234264234265234266234267234268234269234270234271234272234273234274234275234276234277234278234279234280234281234282234283234284234285234286234287234288234289234290234291234292234293234294234295234296234297234298234299234300234301234302234303234304234305234306234307234308234309234310234311234312234313234314234315234316234317234318234319234320234321234322234323234324234325234326234327234328234329234330234331234332234333234334234335234336234337234338234339234340234341234342234343234344234345234346234347234348234349234350234351234352234353234354234355234356234357234358234359234360234361234362234363234364234365234366234367234368234369234370234371234372234373234374234375234376234377234378234379234380234381234382234383234384234385234386234387234388234389234390234391234392234393234394234395234396234397234398234399234400234401234402234403234404234405234406234407234408234409234410234411234412234413234414234415234416234417234418234419234420234421234422234423234424234425234426234427234428234429234430234431234432234433234434234435234436234437234438234439234440234441234442234443234444234445234446234447234448234449234450234451234452234453234454234455234456234457234458234459234460234461234462234463234464234465234466234467234468234469234470234471234472234473234474234475234476234477234478234479234480234481234482234483234484234485234486234487234488234489234490234491234492234493234494234495234496234497234498234499234500234501234502234503234504234505234506234507234508234509234510234511234512234513234514234515234516234517234518234519234520234521234522234523234524234525234526234527234528234529234530234531234532234533234534234535234536234537234538234539234540234541234542234543234544234545234546234547234548234549234550234551234552234553234554234555234556234557234558234559234560234561234562234563234564234565234566234567234568234569234570234571234572234573234574234575234576234577234578234579234580234581234582234583234584234585234586234587234588234589234590234591234592234593234594234595234596234597234598234599234600234601234602234603234604234605234606234607234608234609234610234611234612234613234614234615234616234617234618234619234620234621234622234623234624234625234626234627234628234629234630234631234632234633234634234635234636234637234638234639234640234641234642234643234644234645234646234647234648234649234650234651234652234653234654234655234656234657234658234659234660234661234662234663234664234665234666234667234668234669234670234671234672234673234674234675234676234677234678234679234680234681234682234683234684234685234686234687234688234689234690234691234692234693234694234695234696234697234698234699234700234701234702234703234704234705234706234707234708234709234710234711234712234713234714234715234716234717234718234719234720234721234722234723234724234725234726234727234728234729234730234731234732234733234734234735234736234737234738234739234740234741234742234743234744234745234746234747234748234749234750234751234752234753234754234755234756234757234758234759234760234761234762234763234764234765234766234767234768234769234770234771234772234773234774234775234776234777234778234779234780234781234782234783234784234785234786234787234788234789234790234791234792234793234794234795234796234797234798234799234800234801234802234803234804234805234806234807234808234809234810234811234812234813234814234815234816234817234818234819234820234821234822234823234824234825234826234827234828234829234830234831234832234833234834234835234836234837234838234839234840234841234842234843234844234845234846234847234848234849234850234851234852234853234854234855234856234857234858234859234860234861234862234863234864234865234866234867234868234869234870234871234872234873234874234875234876234877234878234879234880234881234882234883234884234885234886234887234888234889234890234891234892234893234894234895234896234897234898234899234900234901234902234903234904234905234906234907234908234909234910234911234912234913234914234915234916234917234918234919234920234921234922234923234924234925234926234927234928234929234930234931234932234933234934234935234936234937234938234939234940234941234942234943234944234945234946234947234948234949234950234951234952234953234954234955234956234957234958234959234960234961234962234963234964234965234966234967234968234969234970234971234972234973234974234975234976234977234978234979234980234981234982234983234984234985234986234987234988234989234990234991234992234993234994234995234996234997234998234999235000235001235002235003235004235005235006235007235008235009235010235011235012235013235014235015235016235017235018235019235020235021235022235023235024235025235026235027235028235029235030235031235032235033235034235035235036235037235038235039235040235041235042235043235044235045235046235047235048235049235050235051235052235053235054235055235056235057235058235059235060235061235062235063235064235065235066235067235068235069235070235071235072235073235074235075235076235077235078235079235080235081235082235083235084235085235086235087235088235089235090235091235092235093235094235095235096235097235098235099235100235101235102235103235104235105235106235107235108235109235110235111235112235113235114235115235116235117235118235119235120235121235122235123235124235125235126235127235128235129235130235131235132235133235134235135235136235137235138235139235140235141235142235143235144235145235146235147235148235149235150235151235152235153235154235155235156235157235158235159235160235161235162235163235164235165235166235167235168235169235170235171235172235173235174235175235176235177235178235179235180235181235182235183235184235185235186235187235188235189235190235191235192235193235194235195235196235197235198235199235200235201235202235203235204235205235206235207235208235209235210235211235212235213235214235215235216235217235218235219235220235221235222235223235224235225235226235227235228235229235230235231235232235233235234235235235236235237235238235239235240235241235242235243235244235245235246235247235248235249235250235251235252235253235254235255235256235257235258235259235260235261235262235263235264235265235266235267235268235269235270235271235272235273235274235275235276235277235278235279235280235281235282235283235284235285235286235287235288235289235290235291235292235293235294235295235296235297235298235299235300235301235302235303235304235305235306235307235308235309235310235311235312235313235314235315235316235317235318235319235320235321235322235323235324235325235326235327235328235329235330235331235332235333235334235335235336235337235338235339235340235341235342235343235344235345235346235347235348235349235350235351235352235353235354235355235356235357235358235359235360235361235362235363235364235365235366235367235368235369235370235371235372235373235374235375235376235377235378235379235380235381235382235383235384235385235386235387235388235389235390235391235392235393235394235395235396235397235398235399235400235401235402235403235404235405235406235407235408235409235410235411235412235413235414235415235416235417235418235419235420235421235422235423235424235425235426235427235428235429235430235431235432235433235434235435235436235437235438235439235440235441235442235443235444235445235446235447235448235449235450235451235452235453235454235455235456235457235458235459235460235461235462235463235464235465235466235467235468235469235470235471235472235473235474235475235476235477235478235479235480235481235482235483235484235485235486235487235488235489235490235491235492235493235494235495235496235497235498235499235500235501235502235503235504235505235506235507235508235509235510235511235512235513235514235515235516235517235518235519235520235521235522235523235524235525235526235527235528235529235530235531235532235533235534235535235536235537235538235539235540235541235542235543235544235545235546235547235548235549235550235551235552235553235554235555235556235557235558235559235560235561235562235563235564235565235566235567235568235569235570235571235572235573235574235575235576235577235578235579235580235581235582235583235584235585235586235587235588235589235590235591235592235593235594235595235596235597235598235599235600235601235602235603235604235605235606235607235608235609235610235611235612235613235614235615235616235617235618235619235620235621235622235623235624235625235626235627235628235629235630235631235632235633235634235635235636235637235638235639235640235641235642235643235644235645235646235647235648235649235650235651235652235653235654235655235656235657235658235659235660235661235662235663235664235665235666235667235668235669235670235671235672235673235674235675235676235677235678235679235680235681235682235683235684235685235686235687235688235689235690235691235692235693235694235695235696235697235698235699235700235701235702235703235704235705235706235707235708235709235710235711235712235713235714235715235716235717235718235719235720235721235722235723235724235725235726235727235728235729235730235731235732235733235734235735235736235737235738235739235740235741235742235743235744235745235746235747235748235749235750235751235752235753235754235755235756235757235758235759235760235761235762235763235764235765235766235767235768235769235770235771235772235773235774235775235776235777235778235779235780235781235782235783235784235785235786235787235788235789235790235791235792235793235794235795235796235797235798235799235800235801235802235803235804235805235806235807235808235809235810235811235812235813235814235815235816235817235818235819235820235821235822235823235824235825235826235827235828235829235830235831235832235833235834235835235836235837235838235839235840235841235842235843235844235845235846235847235848235849235850235851235852235853235854235855235856235857235858235859235860235861235862235863235864235865235866235867235868235869235870235871235872235873235874235875235876235877235878235879235880235881235882235883235884235885235886235887235888235889235890235891235892235893235894235895235896235897235898235899235900235901235902235903235904235905235906235907235908235909235910235911235912235913235914235915235916235917235918235919235920235921235922235923235924235925235926235927235928235929235930235931235932235933235934235935235936235937235938235939235940235941235942235943235944235945235946235947235948235949235950235951235952235953235954235955235956235957235958235959235960235961235962235963235964235965235966235967235968235969235970235971235972235973235974235975235976235977235978235979235980235981235982235983235984235985235986235987235988235989235990235991235992235993235994235995235996235997235998235999236000236001236002236003236004236005236006236007236008236009236010236011236012236013236014236015236016236017236018236019236020236021236022236023236024236025236026236027236028236029236030236031236032236033236034236035236036236037236038236039236040236041236042236043236044236045236046236047236048236049236050236051236052236053236054236055236056236057236058236059236060236061236062236063236064236065236066236067236068236069236070236071236072236073236074236075236076236077236078236079236080236081236082236083236084236085236086236087236088236089236090236091236092236093236094236095236096236097236098236099236100236101236102236103236104236105236106236107236108236109236110236111236112236113236114236115236116236117236118236119236120236121236122236123236124236125236126236127236128236129236130236131236132236133236134236135236136236137236138236139236140236141236142236143236144236145236146236147236148236149236150236151236152236153236154236155236156236157236158236159236160236161236162236163236164236165236166236167236168236169236170236171236172236173236174236175236176236177236178236179236180236181236182236183236184236185236186236187236188236189236190236191236192236193236194236195236196236197236198236199236200236201236202236203236204236205236206236207236208236209236210236211236212236213236214236215236216236217236218236219236220236221236222236223236224236225236226236227236228236229236230236231236232236233236234236235236236236237236238236239236240236241236242236243236244236245236246236247236248236249236250236251236252236253236254236255236256236257236258236259236260236261236262236263236264236265236266236267236268236269236270236271236272236273236274236275236276236277236278236279236280236281236282236283236284236285236286236287236288236289236290236291236292236293236294236295236296236297236298236299236300236301236302236303236304236305236306236307236308236309236310236311236312236313236314236315236316236317236318236319236320236321236322236323236324236325236326236327236328236329236330236331236332236333236334236335236336236337236338236339236340236341236342236343236344236345236346236347236348236349236350236351236352236353236354236355236356236357236358236359236360236361236362236363236364236365236366236367236368236369236370236371236372236373236374236375236376236377236378236379236380236381236382236383236384236385236386236387236388236389236390236391236392236393236394236395236396236397236398236399236400236401236402236403236404236405236406236407236408236409236410236411236412236413236414236415236416236417236418236419236420236421236422236423236424236425236426236427236428236429236430236431236432236433236434236435236436236437236438236439236440236441236442236443236444236445236446236447236448236449236450236451236452236453236454236455236456236457236458236459236460236461236462236463236464236465236466236467236468236469236470236471236472236473236474236475236476236477236478236479236480236481236482236483236484236485236486236487236488236489236490236491236492236493236494236495236496236497236498236499236500236501236502236503236504236505236506236507236508236509236510236511236512236513236514236515236516236517236518236519236520236521236522236523236524236525236526236527236528236529236530236531236532236533236534236535236536236537236538236539236540236541236542236543236544236545236546236547236548236549236550236551236552236553236554236555236556236557236558236559236560236561236562236563236564236565236566236567236568236569236570236571236572236573236574236575236576236577236578236579236580236581236582236583236584236585 |
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/clcd-panels.dtsi linux-3.14.35/arch/arm/boot/dts/clcd-panels.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/clcd-panels.dtsi 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/clcd-panels.dtsi 2015-03-08 14:27:37.381684503 -0500
- @@ -0,0 +1,52 @@
- +/*
- + * ARM Ltd. Versatile Express
- + *
- + */
- +
- +/ {
- + panels {
- + panel@0 {
- + compatible = "panel";
- + mode = "VGA";
- + refresh = <60>;
- + xres = <640>;
- + yres = <480>;
- + pixclock = <39721>;
- + left_margin = <40>;
- + right_margin = <24>;
- + upper_margin = <32>;
- + lower_margin = <11>;
- + hsync_len = <96>;
- + vsync_len = <2>;
- + sync = <0>;
- + vmode = "FB_VMODE_NONINTERLACED";
- +
- + tim2 = "TIM2_BCD", "TIM2_IPC";
- + cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)";
- + caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888";
- + bpp = <16>;
- + };
- +
- + panel@1 {
- + compatible = "panel";
- + mode = "XVGA";
- + refresh = <60>;
- + xres = <1024>;
- + yres = <768>;
- + pixclock = <15748>;
- + left_margin = <152>;
- + right_margin = <48>;
- + upper_margin = <23>;
- + lower_margin = <3>;
- + hsync_len = <104>;
- + vsync_len = <4>;
- + sync = <0>;
- + vmode = "FB_VMODE_NONINTERLACED";
- +
- + tim2 = "TIM2_BCD", "TIM2_IPC";
- + cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)";
- + caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888";
- + bpp = <16>;
- + };
- + };
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/efm32gg-dk3750.dts linux-3.14.35/arch/arm/boot/dts/efm32gg-dk3750.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/efm32gg-dk3750.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/efm32gg-dk3750.dts 2015-03-08 14:27:37.381684503 -0500
- @@ -26,7 +26,7 @@
- };
-
- i2c@4000a000 {
- - location = <3>;
- + efm32,location = <3>;
- status = "ok";
-
- temp@48 {
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx23.dtsi linux-3.14.35/arch/arm/boot/dts/imx23.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx23.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx23.dtsi 2015-03-08 14:27:37.381684503 -0500
- @@ -363,7 +363,8 @@
- compatible = "fsl,imx23-lcdif";
- reg = <0x80030000 2000>;
- interrupts = <46 45>;
- - clocks = <&clks 38>;
- + clocks = <&clks 38>, <&clks 38>;
- + clock-names = "pix", "axi";
- status = "disabled";
- };
-
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx25.dtsi linux-3.14.35/arch/arm/boot/dts/imx25.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx25.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx25.dtsi 2015-03-08 14:27:37.381684503 -0500
- @@ -13,6 +13,7 @@
-
- / {
- aliases {
- + ethernet0 = &fec;
- gpio0 = &gpio1;
- gpio1 = &gpio2;
- gpio2 = &gpio3;
- @@ -56,6 +57,7 @@
-
- osc {
- compatible = "fsl,imx-osc", "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <24000000>;
- };
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx25-karo-tx25.dts linux-3.14.35/arch/arm/boot/dts/imx25-karo-tx25.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx25-karo-tx25.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx25-karo-tx25.dts 2015-03-08 14:27:37.385684503 -0500
- @@ -16,6 +16,10 @@
- model = "Ka-Ro TX25";
- compatible = "karo,imx25-tx25", "fsl,imx25";
-
- + chosen {
- + stdout-path = &uart1;
- + };
- +
- memory {
- reg = <0x80000000 0x02000000 0x90000000 0x02000000>;
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx27-apf27.dts linux-3.14.35/arch/arm/boot/dts/imx27-apf27.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx27-apf27.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx27-apf27.dts 2015-03-08 14:27:37.385684503 -0500
- @@ -29,6 +29,7 @@
-
- osc26m {
- compatible = "fsl,imx-osc26m", "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <0>;
- };
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx27.dtsi linux-3.14.35/arch/arm/boot/dts/imx27.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx27.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx27.dtsi 2015-03-08 14:27:37.385684503 -0500
- @@ -13,6 +13,7 @@
-
- / {
- aliases {
- + ethernet0 = &fec;
- gpio0 = &gpio1;
- gpio1 = &gpio2;
- gpio2 = &gpio3;
- @@ -46,6 +47,7 @@
-
- osc26m {
- compatible = "fsl,imx-osc26m", "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <26000000>;
- };
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts linux-3.14.35/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts 2015-03-08 14:27:37.385684503 -0500
- @@ -15,6 +15,10 @@
- model = "Phytec pca100 rapid development kit";
- compatible = "phytec,imx27-pca100-rdk", "phytec,imx27-pca100", "fsl,imx27";
-
- + chosen {
- + stdout-path = &uart1;
- + };
- +
- display: display {
- model = "Primeview-PD050VL1";
- native-mode = <&timing0>;
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx28.dtsi linux-3.14.35/arch/arm/boot/dts/imx28.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx28.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx28.dtsi 2015-03-08 14:27:37.385684503 -0500
- @@ -840,7 +840,8 @@
- compatible = "fsl,imx28-lcdif";
- reg = <0x80030000 0x2000>;
- interrupts = <38>;
- - clocks = <&clks 55>;
- + clocks = <&clks 55>, <&clks 55>;
- + clock-names = "pix", "axi";
- dmas = <&dma_apbh 13>;
- dma-names = "rx";
- status = "disabled";
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx51-babbage.dts linux-3.14.35/arch/arm/boot/dts/imx51-babbage.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx51-babbage.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx51-babbage.dts 2015-03-08 14:27:37.385684503 -0500
- @@ -17,6 +17,10 @@
- model = "Freescale i.MX51 Babbage Board";
- compatible = "fsl,imx51-babbage", "fsl,imx51";
-
- + chosen {
- + stdout-path = &uart1;
- + };
- +
- memory {
- reg = <0x90000000 0x20000000>;
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx51.dtsi linux-3.14.35/arch/arm/boot/dts/imx51.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx51.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx51.dtsi 2015-03-08 14:27:37.385684503 -0500
- @@ -15,6 +15,7 @@
-
- / {
- aliases {
- + ethernet0 = &fec;
- gpio0 = &gpio1;
- gpio1 = &gpio2;
- gpio2 = &gpio3;
- @@ -43,21 +44,25 @@
-
- ckil {
- compatible = "fsl,imx-ckil", "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <32768>;
- };
-
- ckih1 {
- compatible = "fsl,imx-ckih1", "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <0>;
- };
-
- ckih2 {
- compatible = "fsl,imx-ckih2", "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <0>;
- };
-
- osc {
- compatible = "fsl,imx-osc", "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <24000000>;
- };
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx53.dtsi linux-3.14.35/arch/arm/boot/dts/imx53.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx53.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx53.dtsi 2015-03-08 14:27:37.389684503 -0500
- @@ -15,6 +15,7 @@
-
- / {
- aliases {
- + ethernet0 = &fec;
- gpio0 = &gpio1;
- gpio1 = &gpio2;
- gpio2 = &gpio3;
- @@ -59,21 +60,25 @@
-
- ckil {
- compatible = "fsl,imx-ckil", "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <32768>;
- };
-
- ckih1 {
- compatible = "fsl,imx-ckih1", "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <22579200>;
- };
-
- ckih2 {
- compatible = "fsl,imx-ckih2", "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <0>;
- };
-
- osc {
- compatible = "fsl,imx-osc", "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <24000000>;
- };
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx53-mba53.dts linux-3.14.35/arch/arm/boot/dts/imx53-mba53.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx53-mba53.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx53-mba53.dts 2015-03-08 14:27:37.389684503 -0500
- @@ -25,6 +25,10 @@
- enable-active-low;
- };
-
- + chosen {
- + stdout-path = &uart2;
- + };
- +
- backlight {
- compatible = "pwm-backlight";
- pwms = <&pwm2 0 50000>;
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-dfi-fs700-m60.dts linux-3.14.35/arch/arm/boot/dts/imx6dl-dfi-fs700-m60.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-dfi-fs700-m60.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6dl-dfi-fs700-m60.dts 2015-03-08 14:27:37.389684503 -0500
- @@ -0,0 +1,23 @@
- +/*
- + * Copyright 2013 Sascha Hauer <s.hauer@pengutronix.de>
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#ifndef __DTS_V1__
- +#define __DTS_V1__
- +/dts-v1/;
- +#endif
- +
- +#include "imx6dl.dtsi"
- +#include "imx6qdl-dfi-fs700-m60.dtsi"
- +
- +/ {
- + model = "DFI FS700-M60-6DL i.MX6dl Q7 Board";
- + compatible = "dfi,fs700-m60-6dl", "dfi,fs700e-m60", "fsl,imx6dl";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6dl.dtsi linux-3.14.35/arch/arm/boot/dts/imx6dl.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6dl.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6dl.dtsi 2015-03-08 14:27:37.389684503 -0500
- @@ -8,6 +8,7 @@
- *
- */
-
- +#include <dt-bindings/interrupt-controller/irq.h>
- #include "imx6dl-pinfunc.h"
- #include "imx6qdl.dtsi"
-
- @@ -21,6 +22,26 @@
- device_type = "cpu";
- reg = <0>;
- next-level-cache = <&L2>;
- + operating-points = <
- + /* kHz uV */
- + 996000 1275000
- + 792000 1175000
- + 396000 1075000
- + >;
- + fsl,soc-operating-points = <
- + /* ARM kHz SOC-PU uV */
- + 996000 1175000
- + 792000 1175000
- + 396000 1175000
- + >;
- + clock-latency = <61036>; /* two CLK32 periods */
- + clocks = <&clks 104>, <&clks 6>, <&clks 16>,
- + <&clks 17>, <&clks 170>;
- + clock-names = "arm", "pll2_pfd2_396m", "step",
- + "pll1_sw", "pll1_sys";
- + arm-supply = <®_arm>;
- + pu-supply = <®_pu>;
- + soc-supply = <®_soc>;
- };
-
- cpu@1 {
- @@ -32,40 +53,124 @@
- };
-
- soc {
- +
- + busfreq { /* BUSFREQ */
- + compatible = "fsl,imx6_busfreq";
- + clocks = <&clks 171>, <&clks 6>, <&clks 11>, <&clks 104>, <&clks 172>, <&clks 58>,
- + <&clks 18>, <&clks 60>, <&clks 20>, <&clks 3>, <&clks 22> , <&clks 8>;
- + clock-names = "pll2_bus", "pll2_pfd2_396m", "pll2_198m", "arm", "pll3_usb_otg", "periph",
- + "periph_pre", "periph_clk2", "periph_clk2_sel", "osc", "axi_sel", "pll3_pfd1_540m";
- + interrupts = <0 107 0x04>, <0 112 0x4>;
- + interrupt-names = "irq_busfreq_0", "irq_busfreq_1";
- + fsl,max_ddr_freq = <400000000>;
- + };
- +
- + gpu@00130000 {
- + compatible = "fsl,imx6dl-gpu", "fsl,imx6q-gpu";
- + reg = <0x00130000 0x4000>, <0x00134000 0x4000>,
- + <0x0 0x0>;
- + reg-names = "iobase_3d", "iobase_2d",
- + "phys_baseaddr";
- + interrupts = <0 9 0x04>, <0 10 0x04>;
- + interrupt-names = "irq_3d", "irq_2d";
- + clocks = <&clks 143>, <&clks 27>,
- + <&clks 121>, <&clks 122>,
- + <&clks 0>;
- + clock-names = "gpu2d_axi_clk", "gpu3d_axi_clk",
- + "gpu2d_clk", "gpu3d_clk",
- + "gpu3d_shader_clk";
- + resets = <&src 0>, <&src 3>;
- + reset-names = "gpu3d", "gpu2d";
- + pu-supply = <®_pu>;
- + };
- +
- ocram: sram@00900000 {
- compatible = "mmio-sram";
- reg = <0x00900000 0x20000>;
- clocks = <&clks 142>;
- };
-
- + hdmi_core: hdmi_core@00120000 {
- + compatible = "fsl,imx6dl-hdmi-core";
- + reg = <0x00120000 0x9000>;
- + clocks = <&clks 124>, <&clks 123>;
- + clock-names = "hdmi_isfr", "hdmi_iahb";
- + status = "disabled";
- + };
- +
- + hdmi_video: hdmi_video@020e0000 {
- + compatible = "fsl,imx6dl-hdmi-video";
- + reg = <0x020e0000 0x1000>;
- + reg-names = "hdmi_gpr";
- + interrupts = <0 115 0x04>;
- + clocks = <&clks 124>, <&clks 123>;
- + clock-names = "hdmi_isfr", "hdmi_iahb";
- + status = "disabled";
- + };
- +
- + hdmi_audio: hdmi_audio@00120000 {
- + compatible = "fsl,imx6dl-hdmi-audio";
- + clocks = <&clks 124>, <&clks 123>;
- + clock-names = "hdmi_isfr", "hdmi_iahb";
- + dmas = <&sdma 2 23 0>;
- + dma-names = "tx";
- + status = "disabled";
- + };
- +
- + hdmi_cec: hdmi_cec@00120000 {
- + compatible = "fsl,imx6dl-hdmi-cec";
- + interrupts = <0 115 0x04>;
- + status = "disabled";
- + };
- +
- aips1: aips-bus@02000000 {
- + vpu@02040000 {
- + iramsize = <0>;
- + status = "okay";
- + };
- +
- iomuxc: iomuxc@020e0000 {
- compatible = "fsl,imx6dl-iomuxc";
- };
-
- pxp: pxp@020f0000 {
- + compatible = "fsl,imx6dl-pxp-dma";
- reg = <0x020f0000 0x4000>;
- - interrupts = <0 98 0x04>;
- + interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&clks 133>;
- + clock-names = "pxp-axi";
- + status = "disabled";
- };
-
- epdc: epdc@020f4000 {
- reg = <0x020f4000 0x4000>;
- - interrupts = <0 97 0x04>;
- + interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- lcdif: lcdif@020f8000 {
- reg = <0x020f8000 0x4000>;
- - interrupts = <0 39 0x04>;
- + interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
- };
- };
-
- aips2: aips-bus@02100000 {
- + mipi_dsi: mipi@021e0000 {
- + compatible = "fsl,imx6dl-mipi-dsi";
- + reg = <0x021e0000 0x4000>;
- + interrupts = <0 102 0x04>;
- + gpr = <&gpr>;
- + clocks = <&clks 138>, <&clks 209>;
- + clock-names = "mipi_pllref_clk", "mipi_cfg_clk";
- + status = "disabled";
- + };
- +
- i2c4: i2c@021f8000 {
- #address-cells = <1>;
- #size-cells = <0>;
- - compatible = "fsl,imx1-i2c";
- + compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
- reg = <0x021f8000 0x4000>;
- - interrupts = <0 35 0x04>;
- + interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&clks 116>;
- status = "disabled";
- };
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-gw51xx.dts linux-3.14.35/arch/arm/boot/dts/imx6dl-gw51xx.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-gw51xx.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6dl-gw51xx.dts 2015-03-08 14:27:37.389684503 -0500
- @@ -0,0 +1,19 @@
- +/*
- + * Copyright 2013 Gateworks Corporation
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/dts-v1/;
- +#include "imx6dl.dtsi"
- +#include "imx6qdl-gw51xx.dtsi"
- +
- +/ {
- + model = "Gateworks Ventana i.MX6 DualLite GW51XX";
- + compatible = "gw,imx6dl-gw51xx", "gw,ventana", "fsl,imx6dl";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-gw52xx.dts linux-3.14.35/arch/arm/boot/dts/imx6dl-gw52xx.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-gw52xx.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6dl-gw52xx.dts 2015-03-08 14:27:37.389684503 -0500
- @@ -0,0 +1,19 @@
- +/*
- + * Copyright 2013 Gateworks Corporation
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/dts-v1/;
- +#include "imx6dl.dtsi"
- +#include "imx6qdl-gw52xx.dtsi"
- +
- +/ {
- + model = "Gateworks Ventana i.MX6 DualLite GW52XX";
- + compatible = "gw,imx6dl-gw52xx", "gw,ventana", "fsl,imx6dl";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-gw53xx.dts linux-3.14.35/arch/arm/boot/dts/imx6dl-gw53xx.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-gw53xx.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6dl-gw53xx.dts 2015-03-08 14:27:37.389684503 -0500
- @@ -0,0 +1,19 @@
- +/*
- + * Copyright 2013 Gateworks Corporation
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/dts-v1/;
- +#include "imx6dl.dtsi"
- +#include "imx6qdl-gw53xx.dtsi"
- +
- +/ {
- + model = "Gateworks Ventana i.MX6 DualLite GW53XX";
- + compatible = "gw,imx6dl-gw53xx", "gw,ventana", "fsl,imx6dl";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-gw54xx.dts linux-3.14.35/arch/arm/boot/dts/imx6dl-gw54xx.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-gw54xx.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6dl-gw54xx.dts 2015-03-08 14:27:37.389684503 -0500
- @@ -0,0 +1,19 @@
- +/*
- + * Copyright 2013 Gateworks Corporation
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/dts-v1/;
- +#include "imx6dl.dtsi"
- +#include "imx6qdl-gw54xx.dtsi"
- +
- +/ {
- + model = "Gateworks Ventana i.MX6 DualLite GW54XX";
- + compatible = "gw,imx6dl-gw54xx", "gw,ventana", "fsl,imx6dl";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-hummingboard.dts linux-3.14.35/arch/arm/boot/dts/imx6dl-hummingboard.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-hummingboard.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6dl-hummingboard.dts 2015-03-08 14:27:37.393684503 -0500
- @@ -1,163 +1,13 @@
- /*
- - * Copyright (C) 2013,2014 Russell King
- + * Copyright (C) 2014 Rabeeh Khoury (rabeeh@solid-run.com)
- + * Based on work by Russell King
- */
- /dts-v1/;
-
- #include "imx6dl.dtsi"
- -#include "imx6qdl-microsom.dtsi"
- -#include "imx6qdl-microsom-ar8035.dtsi"
- +#include "imx6qdl-hummingboard.dtsi"
-
- / {
- - model = "SolidRun HummingBoard DL/Solo";
- - compatible = "solidrun,hummingboard", "fsl,imx6dl";
- -
- - ir_recv: ir-receiver {
- - compatible = "gpio-ir-receiver";
- - gpios = <&gpio1 2 1>;
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_hummingboard_gpio1_2>;
- - };
- -
- - regulators {
- - compatible = "simple-bus";
- -
- - reg_3p3v: 3p3v {
- - compatible = "regulator-fixed";
- - regulator-name = "3P3V";
- - regulator-min-microvolt = <3300000>;
- - regulator-max-microvolt = <3300000>;
- - regulator-always-on;
- - };
- -
- - reg_usbh1_vbus: usb-h1-vbus {
- - compatible = "regulator-fixed";
- - enable-active-high;
- - gpio = <&gpio1 0 0>;
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_hummingboard_usbh1_vbus>;
- - regulator-name = "usb_h1_vbus";
- - regulator-min-microvolt = <5000000>;
- - regulator-max-microvolt = <5000000>;
- - };
- -
- - reg_usbotg_vbus: usb-otg-vbus {
- - compatible = "regulator-fixed";
- - enable-active-high;
- - gpio = <&gpio3 22 0>;
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_hummingboard_usbotg_vbus>;
- - regulator-name = "usb_otg_vbus";
- - regulator-min-microvolt = <5000000>;
- - regulator-max-microvolt = <5000000>;
- - };
- - };
- -
- - sound-spdif {
- - compatible = "fsl,imx-audio-spdif";
- - model = "imx-spdif";
- - /* IMX6 doesn't implement this yet */
- - spdif-controller = <&spdif>;
- - spdif-out;
- - };
- -};
- -
- -&can1 {
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_hummingboard_flexcan1>;
- - status = "okay";
- -};
- -
- -&i2c1 {
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_hummingboard_i2c1>;
- -
- - /*
- - * Not fitted on Carrier-1 board... yet
- - status = "okay";
- -
- - rtc: pcf8523@68 {
- - compatible = "nxp,pcf8523";
- - reg = <0x68>;
- - };
- - */
- -};
- -
- -&iomuxc {
- - hummingboard {
- - pinctrl_hummingboard_flexcan1: hummingboard-flexcan1 {
- - fsl,pins = <
- - MX6QDL_PAD_SD3_CLK__FLEXCAN1_RX 0x80000000
- - MX6QDL_PAD_SD3_CMD__FLEXCAN1_TX 0x80000000
- - >;
- - };
- -
- - pinctrl_hummingboard_gpio1_2: hummingboard-gpio1_2 {
- - fsl,pins = <
- - MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000
- - >;
- - };
- -
- - pinctrl_hummingboard_i2c1: hummingboard-i2c1 {
- - fsl,pins = <
- - MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- - MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- - >;
- - };
- -
- - pinctrl_hummingboard_spdif: hummingboard-spdif {
- - fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
- - };
- -
- - pinctrl_hummingboard_usbh1_vbus: hummingboard-usbh1-vbus {
- - fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0>;
- - };
- -
- - pinctrl_hummingboard_usbotg_vbus: hummingboard-usbotg-vbus {
- - fsl,pins = <MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0>;
- - };
- -
- - pinctrl_hummingboard_usdhc2_aux: hummingboard-usdhc2-aux {
- - fsl,pins = <
- - MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071
- - >;
- - };
- -
- - pinctrl_hummingboard_usdhc2: hummingboard-usdhc2 {
- - fsl,pins = <
- - MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- - MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- - MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- - MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- - MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- - MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
- - >;
- - };
- - };
- -};
- -
- -&spdif {
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_hummingboard_spdif>;
- - status = "okay";
- -};
- -
- -&usbh1 {
- - vbus-supply = <®_usbh1_vbus>;
- - status = "okay";
- -};
- -
- -&usbotg {
- - vbus-supply = <®_usbotg_vbus>;
- - status = "okay";
- -};
- -
- -&usdhc2 {
- - pinctrl-names = "default";
- - pinctrl-0 = <
- - &pinctrl_hummingboard_usdhc2_aux
- - &pinctrl_hummingboard_usdhc2
- - >;
- - vmmc-supply = <®_3p3v>;
- - cd-gpios = <&gpio1 4 0>;
- - status = "okay";
- + model = "SolidRun HummingBoard Solo/DualLite";
- + compatible = "solidrun,hummingboard/dl", "fsl,imx6dl";
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-nitrogen6x.dts linux-3.14.35/arch/arm/boot/dts/imx6dl-nitrogen6x.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-nitrogen6x.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6dl-nitrogen6x.dts 2015-03-08 14:27:37.393684503 -0500
- @@ -0,0 +1,21 @@
- +/*
- + * Copyright 2013 Boundary Devices, Inc.
- + * Copyright 2012 Freescale Semiconductor, Inc.
- + * Copyright 2011 Linaro Ltd.
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/dts-v1/;
- +#include "imx6dl.dtsi"
- +#include "imx6qdl-nitrogen6x.dtsi"
- +
- +/ {
- + model = "Freescale i.MX6 DualLite Nitrogen6x Board";
- + compatible = "fsl,imx6dl-nitrogen6x", "fsl,imx6dl";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-phytec-pbab01.dts linux-3.14.35/arch/arm/boot/dts/imx6dl-phytec-pbab01.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-phytec-pbab01.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6dl-phytec-pbab01.dts 2015-03-08 14:27:37.393684503 -0500
- @@ -0,0 +1,19 @@
- +/*
- + * Copyright 2013 Christian Hemp, Phytec Messtechnik GmbH
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/dts-v1/;
- +#include "imx6dl-phytec-pfla02.dtsi"
- +#include "imx6qdl-phytec-pbab01.dtsi"
- +
- +/ {
- + model = "Phytec phyFLEX-i.MX6 DualLite/Solo Carrier-Board";
- + compatible = "phytec,imx6dl-pbab01", "phytec,imx6dl-pfla02", "fsl,imx6dl";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-phytec-pfla02.dtsi linux-3.14.35/arch/arm/boot/dts/imx6dl-phytec-pfla02.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-phytec-pfla02.dtsi 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6dl-phytec-pfla02.dtsi 2015-03-08 14:27:37.393684503 -0500
- @@ -0,0 +1,22 @@
- +/*
- + * Copyright 2013 Christian Hemp, Phytec Messtechnik GmbH
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#include "imx6dl.dtsi"
- +#include "imx6qdl-phytec-pfla02.dtsi"
- +
- +/ {
- + model = "Phytec phyFLEX-i.MX6 DualLite/Solo";
- + compatible = "phytec,imx6dl-pfla02", "fsl,imx6dl";
- +
- + memory {
- + reg = <0x10000000 0x20000000>;
- + };
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-pinfunc.h linux-3.14.35/arch/arm/boot/dts/imx6dl-pinfunc.h
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-pinfunc.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6dl-pinfunc.h 2015-03-08 14:27:37.393684503 -0500
- @@ -755,6 +755,7 @@
- #define MX6QDL_PAD_GPIO_5__I2C3_SCL 0x230 0x600 0x878 0x6 0x2
- #define MX6QDL_PAD_GPIO_5__ARM_EVENTI 0x230 0x600 0x000 0x7 0x0
- #define MX6QDL_PAD_GPIO_6__ESAI_TX_CLK 0x234 0x604 0x840 0x0 0x1
- +#define MX6QDL_PAD_GPIO_6__ENET_IRQ 0x234 0x604 0x03c 0x11 0xff000609
- #define MX6QDL_PAD_GPIO_6__I2C3_SDA 0x234 0x604 0x87c 0x2 0x2
- #define MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x234 0x604 0x000 0x5 0x0
- #define MX6QDL_PAD_GPIO_6__SD2_LCTL 0x234 0x604 0x000 0x6 0x0
- @@ -950,6 +951,7 @@
- #define MX6QDL_PAD_RGMII_TXC__GPIO6_IO19 0x2d8 0x6c0 0x000 0x5 0x0
- #define MX6QDL_PAD_RGMII_TXC__XTALOSC_REF_CLK_24M 0x2d8 0x6c0 0x000 0x7 0x0
- #define MX6QDL_PAD_SD1_CLK__SD1_CLK 0x2dc 0x6c4 0x928 0x0 0x1
- +#define MX6QDL_PAD_SD1_CLK__OSC32K_32K_OUT 0x2dc 0x6c4 0x000 0x2 0x0
- #define MX6QDL_PAD_SD1_CLK__GPT_CLKIN 0x2dc 0x6c4 0x000 0x3 0x0
- #define MX6QDL_PAD_SD1_CLK__GPIO1_IO20 0x2dc 0x6c4 0x000 0x5 0x0
- #define MX6QDL_PAD_SD1_CMD__SD1_CMD 0x2e0 0x6c8 0x000 0x0 0x0
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-sabreauto.dts linux-3.14.35/arch/arm/boot/dts/imx6dl-sabreauto.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-sabreauto.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6dl-sabreauto.dts 2015-03-08 14:27:37.393684503 -0500
- @@ -15,3 +15,16 @@
- model = "Freescale i.MX6 DualLite/Solo SABRE Automotive Board";
- compatible = "fsl,imx6dl-sabreauto", "fsl,imx6dl";
- };
- +
- +&ldb {
- + ipu_id = <0>;
- + sec_ipu_id = <0>;
- +};
- +
- +&mxcfb1 {
- + status = "okay";
- +};
- +
- +&mxcfb2 {
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-sabrelite.dts linux-3.14.35/arch/arm/boot/dts/imx6dl-sabrelite.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-sabrelite.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6dl-sabrelite.dts 2015-03-08 14:27:37.393684503 -0500
- @@ -0,0 +1,20 @@
- +/*
- + * Copyright 2011 Freescale Semiconductor, Inc.
- + * Copyright 2011 Linaro Ltd.
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/dts-v1/;
- +#include "imx6dl.dtsi"
- +#include "imx6qdl-sabrelite.dtsi"
- +
- +/ {
- + model = "Freescale i.MX6 DualLite SABRE Lite Board";
- + compatible = "fsl,imx6dl-sabrelite", "fsl,imx6dl";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-sabresd.dts linux-3.14.35/arch/arm/boot/dts/imx6dl-sabresd.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-sabresd.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6dl-sabresd.dts 2015-03-08 14:27:37.393684503 -0500
- @@ -15,3 +15,20 @@
- model = "Freescale i.MX6 DualLite SABRE Smart Device Board";
- compatible = "fsl,imx6dl-sabresd", "fsl,imx6dl";
- };
- +
- +&ldb {
- + ipu_id = <0>;
- + sec_ipu_id = <0>;
- +};
- +
- +&pxp {
- + status = "okay";
- +};
- +
- +&mxcfb1 {
- + status = "okay";
- +};
- +
- +&mxcfb2 {
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-sabresd-hdcp.dts linux-3.14.35/arch/arm/boot/dts/imx6dl-sabresd-hdcp.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6dl-sabresd-hdcp.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6dl-sabresd-hdcp.dts 2015-03-08 14:27:37.393684503 -0500
- @@ -0,0 +1,19 @@
- +/*
- + * Copyright (C) 2013 Freescale Semiconductor, Inc.
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include "imx6dl-sabresd.dts"
- +
- +&hdmi_video {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hdmi_hdcp>;
- + fsl,hdcp;
- +};
- +
- +&i2c2 {
- + status = "disable";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-arm2.dts linux-3.14.35/arch/arm/boot/dts/imx6q-arm2.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-arm2.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-arm2.dts 2015-03-08 14:27:37.393684503 -0500
- @@ -23,14 +23,27 @@
-
- regulators {
- compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
-
- - reg_3p3v: 3p3v {
- + reg_3p3v: regulator@0 {
- compatible = "regulator-fixed";
- + reg = <0>;
- regulator-name = "3P3V";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
- +
- + reg_usb_otg_vbus: regulator@1 {
- + compatible = "regulator-fixed";
- + reg = <1>;
- + regulator-name = "usb_otg_vbus";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + gpio = <&gpio3 22 0>;
- + enable-active-high;
- + };
- };
-
- leds {
- @@ -46,7 +59,7 @@
-
- &gpmi {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_gpmi_nand_1>;
- + pinctrl-0 = <&pinctrl_gpmi_nand>;
- status = "disabled"; /* gpmi nand conflicts with SD */
- };
-
- @@ -54,28 +67,131 @@
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_hog>;
-
- - hog {
- + imx6q-arm2 {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D25__GPIO3_IO25 0x80000000
- >;
- };
- - };
-
- - arm2 {
- - pinctrl_usdhc3_arm2: usdhc3grp-arm2 {
- + pinctrl_enet: enetgrp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL1__ENET_MDIO 0x1b0b0
- + MX6QDL_PAD_KEY_COL2__ENET_MDC 0x1b0b0
- + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- + MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
- + >;
- + };
- +
- + pinctrl_gpmi_nand: gpminandgrp {
- + fsl,pins = <
- + MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
- + MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
- + MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
- + MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
- + MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
- + MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
- + MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
- + MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
- + MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
- + MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
- + MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
- + MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
- + MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
- + MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
- + MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
- + MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
- + MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1
- + >;
- + };
- +
- + pinctrl_uart2: uart2grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D26__UART2_RX_DATA 0x1b0b1
- + MX6QDL_PAD_EIM_D27__UART2_TX_DATA 0x1b0b1
- + MX6QDL_PAD_EIM_D28__UART2_DTE_CTS_B 0x1b0b1
- + MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart4: uart4grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
- + MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usbotg: usbotggrp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc3: usdhc3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- + MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
- + MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
- + MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
- + MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc3_cdwp: usdhc3cdwp {
- fsl,pins = <
- MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x80000000
- MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x80000000
- >;
- };
- +
- + pinctrl_usdhc4: usdhc4grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- + MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- + MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- + MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- + MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- + MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- + MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
- + MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
- + MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
- + MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
- + >;
- + };
- };
- };
-
- &fec {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_enet_2>;
- + pinctrl-0 = <&pinctrl_enet>;
- phy-mode = "rgmii";
- + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
- + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
- + status = "okay";
- +};
- +
- +&usbotg {
- + vbus-supply = <®_usb_otg_vbus>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usbotg>;
- + disable-over-current;
- status = "okay";
- };
-
- @@ -84,8 +200,8 @@
- wp-gpios = <&gpio6 14 0>;
- vmmc-supply = <®_3p3v>;
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usdhc3_1
- - &pinctrl_usdhc3_arm2>;
- + pinctrl-0 = <&pinctrl_usdhc3
- + &pinctrl_usdhc3_cdwp>;
- status = "okay";
- };
-
- @@ -93,13 +209,13 @@
- non-removable;
- vmmc-supply = <®_3p3v>;
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usdhc4_1>;
- + pinctrl-0 = <&pinctrl_usdhc4>;
- status = "okay";
- };
-
- &uart2 {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_uart2_2>;
- + pinctrl-0 = <&pinctrl_uart2>;
- fsl,dte-mode;
- fsl,uart-has-rtscts;
- status = "okay";
- @@ -107,6 +223,6 @@
-
- &uart4 {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_uart4_1>;
- + pinctrl-0 = <&pinctrl_uart4>;
- status = "okay";
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-arm2-hsic.dts linux-3.14.35/arch/arm/boot/dts/imx6q-arm2-hsic.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-arm2-hsic.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-arm2-hsic.dts 2015-03-08 14:27:37.393684503 -0500
- @@ -0,0 +1,32 @@
- +/*
- + * Copyright 2013 Freescale Semiconductor, Inc.
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#include "imx6q-arm2.dts"
- +
- +&fec {
- + status = "disabled";
- +};
- +
- +&usbh2 {
- + pinctrl-names = "idle", "active";
- + pinctrl-0 = <&pinctrl_usbh2_1>;
- + pinctrl-1 = <&pinctrl_usbh2_2>;
- + osc-clkgate-delay = <0x3>;
- + status = "okay";
- +};
- +
- +&usbh3 {
- + pinctrl-names = "idle", "active";
- + pinctrl-0 = <&pinctrl_usbh3_1>;
- + pinctrl-1 = <&pinctrl_usbh3_2>;
- + osc-clkgate-delay = <0x3>;
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-cm-fx6.dts linux-3.14.35/arch/arm/boot/dts/imx6q-cm-fx6.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-cm-fx6.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-cm-fx6.dts 2015-03-08 14:27:37.393684503 -0500
- @@ -0,0 +1,107 @@
- +/*
- + * Copyright 2013 CompuLab Ltd.
- + *
- + * Author: Valentin Raevsky <valentin@compulab.co.il>
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/dts-v1/;
- +#include "imx6q.dtsi"
- +
- +/ {
- + model = "CompuLab CM-FX6";
- + compatible = "compulab,cm-fx6", "fsl,imx6q";
- +
- + memory {
- + reg = <0x10000000 0x80000000>;
- + };
- +
- + leds {
- + compatible = "gpio-leds";
- +
- + heartbeat-led {
- + label = "Heartbeat";
- + gpios = <&gpio2 31 0>;
- + linux,default-trigger = "heartbeat";
- + };
- + };
- +};
- +
- +&fec {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_enet>;
- + phy-mode = "rgmii";
- + status = "okay";
- +};
- +
- +&gpmi {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_gpmi_nand>;
- + status = "okay";
- +};
- +
- +&iomuxc {
- + imx6q-cm-fx6 {
- + pinctrl_enet: enetgrp {
- + fsl,pins = <
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- + >;
- + };
- +
- + pinctrl_gpmi_nand: gpminandgrp {
- + fsl,pins = <
- + MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
- + MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
- + MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
- + MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
- + MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
- + MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
- + MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
- + MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
- + MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
- + MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
- + MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
- + MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
- + MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
- + MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
- + MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
- + MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
- + MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1
- + >;
- + };
- +
- + pinctrl_uart4: uart4grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
- + MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
- + >;
- + };
- + };
- +};
- +
- +&uart4 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart4>;
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-cubox-i.dts linux-3.14.35/arch/arm/boot/dts/imx6q-cubox-i.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-cubox-i.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-cubox-i.dts 2015-03-08 14:27:37.393684503 -0500
- @@ -13,4 +13,8 @@
-
- &sata {
- status = "okay";
- + fsl,transmit-level-mV = <1104>;
- + fsl,transmit-boost-mdB = <0>;
- + fsl,transmit-atten-16ths = <9>;
- + fsl,no-spread-spectrum;
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-dfi-fs700-m60.dts linux-3.14.35/arch/arm/boot/dts/imx6q-dfi-fs700-m60.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-dfi-fs700-m60.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-dfi-fs700-m60.dts 2015-03-08 14:27:37.393684503 -0500
- @@ -0,0 +1,23 @@
- +/*
- + * Copyright 2013 Sascha Hauer <s.hauer@pengutronix.de>
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#ifndef __DTS_V1__
- +#define __DTS_V1__
- +/dts-v1/;
- +#endif
- +
- +#include "imx6q.dtsi"
- +#include "imx6qdl-dfi-fs700-m60.dtsi"
- +
- +/ {
- + model = "DFI FS700-M60-6QD i.MX6qd Q7 Board";
- + compatible = "dfi,fs700-m60-6qd", "dfi,fs700e-m60", "fsl,imx6q";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi linux-3.14.35/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi 2015-03-08 14:27:37.393684503 -0500
- @@ -5,11 +5,33 @@
- #include "imx6qdl-microsom-ar8035.dtsi"
-
- / {
- + chosen {
- + bootargs = "quiet console=ttymxc0,115200 root=/dev/mmcblk0p2 rw";
- + };
- +
- + aliases {
- + mxcfb0 = &mxcfb1;
- + };
- +
- ir_recv: ir-receiver {
- compatible = "gpio-ir-receiver";
- gpios = <&gpio3 9 1>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_cubox_i_ir>;
- + linux,rc-map-name = "rc-rc6-mce";
- + };
- +
- + pwmleds {
- + compatible = "pwm-leds";
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_cubox_i_pwm1>;
- +
- + front {
- + active-low;
- + label = "imx6:red:front";
- + max-brightness = <248>;
- + pwms = <&pwm1 0 50000>;
- + };
- };
-
- regulators {
- @@ -49,10 +71,62 @@
- sound-spdif {
- compatible = "fsl,imx-audio-spdif";
- model = "imx-spdif";
- - /* IMX6 doesn't implement this yet */
- spdif-controller = <&spdif>;
- spdif-out;
- };
- +
- + sound-hdmi {
- + compatible = "fsl,imx6q-audio-hdmi",
- + "fsl,imx-audio-hdmi";
- + model = "imx-audio-hdmi";
- + hdmi-controller = <&hdmi_audio>;
- + };
- +
- + mxcfb1: fb@0 {
- + compatible = "fsl,mxc_sdc_fb";
- + disp_dev = "hdmi";
- + interface_pix_fmt = "RGB24";
- + mode_str ="1920x1080M@60";
- + default_bpp = <32>;
- + int_clk = <0>;
- + late_init = <0>;
- + status = "okay";
- + };
- +};
- +
- +&hdmi_core {
- + ipu_id = <0>;
- + disp_id = <0>;
- + status = "okay";
- +};
- +
- +&hdmi_video {
- + fsl,phy_reg_vlev = <0x0294>;
- + fsl,phy_reg_cksymtx = <0x800d>;
- + status = "okay";
- +};
- +
- +&hdmi_audio {
- + status = "okay";
- +};
- +
- +&hdmi_cec {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_cubox_i_hdmi>;
- + status = "okay";
- +};
- +
- +&i2c2 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_cubox_i_i2c2>;
- +
- + status = "okay";
- +
- + ddc: imx6_hdmi_i2c@50 {
- + compatible = "fsl,imx6-hdmi-i2c";
- + reg = <0x50>;
- + };
- };
-
- &i2c3 {
- @@ -69,6 +143,19 @@
-
- &iomuxc {
- cubox_i {
- + pinctrl_cubox_i_hdmi: cubox-i-hdmi {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
- + >;
- + };
- +
- + pinctrl_cubox_i_i2c2: cubox-i-i2c2 {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- + >;
- + };
- +
- pinctrl_cubox_i_i2c3: cubox-i-i2c3 {
- fsl,pins = <
- MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
- @@ -82,16 +169,35 @@
- >;
- };
-
- + pinctrl_cubox_i_pwm1: cubox-i-pwm1-front-led {
- + fsl,pins = <MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b0>;
- + };
- +
- pinctrl_cubox_i_spdif: cubox-i-spdif {
- fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
- };
-
- + pinctrl_cubox_i_usbh1: cubox-i-usbh1 {
- + fsl,pins = <MX6QDL_PAD_GPIO_3__USB_H1_OC 0x1b0b0>;
- + };
- +
- pinctrl_cubox_i_usbh1_vbus: cubox-i-usbh1-vbus {
- - fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x4001b0b0>;
- + fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0>;
- + };
- +
- + pinctrl_cubox_i_usbotg: cubox-i-usbotg {
- + /*
- + * The Cubox-i pulls ID low, but as it's pointless
- + * leaving it as a pull-up, even if it is just 10uA.
- + */
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059
- + MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
- + >;
- };
-
- pinctrl_cubox_i_usbotg_vbus: cubox-i-usbotg-vbus {
- - fsl,pins = <MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x4001b0b0>;
- + fsl,pins = <MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0>;
- };
-
- pinctrl_cubox_i_usdhc2_aux: cubox-i-usdhc2-aux {
- @@ -111,29 +217,76 @@
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
- >;
- };
- +
- + pinctrl_cubox_i_usdhc2_100mhz: cubox-i-usdhc2-100mhz {
- + fsl,pins = <
- + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170b9
- + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100b9
- + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170b9
- + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170b9
- + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170b9
- + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130b9
- + >;
- + };
- +
- + pinctrl_cubox_i_usdhc2_200mhz: cubox-i-usdhc2-200mhz {
- + fsl,pins = <
- + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170f9
- + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100f9
- + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170f9
- + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170f9
- + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170f9
- + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130f9
- + >;
- + };
- };
- };
-
- &spdif {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_cubox_i_spdif>;
- + clocks = <&clks 197>, <&clks 0>,
- + <&clks 197>, <&clks 0>,
- + <&clks 0>, <&clks 0>,
- + <&clks 0>, <&clks 0>,
- + <&clks 0>;
- + clock-names = "core", "rxtx0",
- + "rxtx1", "rxtx2",
- + "rxtx3", "rxtx4",
- + "rxtx5", "rxtx6",
- + "rxtx7";
- status = "okay";
- };
-
- &usbh1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_cubox_i_usbh1>;
- vbus-supply = <®_usbh1_vbus>;
- status = "okay";
- };
-
- &usbotg {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_cubox_i_usbotg>;
- vbus-supply = <®_usbotg_vbus>;
- status = "okay";
- };
-
- &usdhc2 {
- - pinctrl-names = "default";
- + pinctrl-names = "default", "state_100mhz", "state_200mhz";
- pinctrl-0 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2>;
- + pinctrl-1 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_100mhz>;
- + pinctrl-2 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_200mhz>;
- vmmc-supply = <®_3p3v>;
- cd-gpios = <&gpio1 4 0>;
- + no-1-8-v;
- status = "okay";
- };
- +
- +
- +&gpc {
- + fsl,cpu_pupscr_sw2iso = <0xf>;
- + fsl,cpu_pupscr_sw = <0xf>;
- + fsl,cpu_pdnscr_iso2sw = <0x1>;
- + fsl,cpu_pdnscr_iso = <0x1>;
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi linux-3.14.35/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi 2015-03-08 14:27:37.393684503 -0500
- @@ -0,0 +1,199 @@
- +/ {
- + regulators {
- + compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + dummy_reg: regulator@0 {
- + compatible = "regulator-fixed";
- + reg = <0>;
- + regulator-name = "dummy-supply";
- + };
- +
- + reg_usb_otg_vbus: regulator@1 {
- + compatible = "regulator-fixed";
- + reg = <1>;
- + regulator-name = "usb_otg_vbus";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + gpio = <&gpio3 22 0>;
- + enable-active-high;
- + };
- + };
- +
- + chosen {
- + stdout-path = &uart1;
- + };
- +};
- +
- +&ecspi3 {
- + fsl,spi-num-chipselects = <1>;
- + cs-gpios = <&gpio4 24 0>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_ecspi3>;
- + status = "okay";
- +
- + flash: m25p80@0 {
- + #address-cells = <1>;
- + #size-cells = <1>;
- + compatible = "sst,sst25vf040b", "m25p80";
- + spi-max-frequency = <20000000>;
- + reg = <0>;
- + };
- +};
- +
- +&fec {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_enet>;
- + status = "okay";
- + phy-mode = "rgmii";
- +};
- +
- +&iomuxc {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hog>;
- +
- + imx6qdl-dfi-fs700-m60 {
- + pinctrl_hog: hoggrp {
- + fsl,pins = <
- + MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x80000000
- + MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x80000000 /* PMIC irq */
- + MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x80000000 /* MAX11801 irq */
- + MX6QDL_PAD_NANDF_D5__GPIO2_IO05 0x000030b0 /* Backlight enable */
- + >;
- + };
- +
- + pinctrl_enet: enetgrp {
- + fsl,pins = <
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- + >;
- + };
- +
- + pinctrl_i2c2: i2c2grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
- + MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_uart1: uart1grp {
- + fsl,pins = <
- + MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
- + MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usbotg: usbotggrp {
- + fsl,pins = <
- + MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc2: usdhc2grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- + MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x80000000 /* card detect */
- + >;
- + };
- +
- + pinctrl_usdhc3: usdhc3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc4: usdhc4grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- + MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- + MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- + MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- + MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- + MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- + MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
- + MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
- + MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
- + MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
- + >;
- + };
- +
- + pinctrl_ecspi3: ecspi3grp {
- + fsl,pins = <
- + MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
- + MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
- + MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
- + MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */
- + >;
- + };
- + };
- +};
- +
- +&i2c2 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c2>;
- + status = "okay";
- +};
- +
- +&uart1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart1>;
- + status = "okay";
- +};
- +
- +&usbh1 {
- + status = "okay";
- +};
- +
- +&usbotg {
- + vbus-supply = <®_usb_otg_vbus>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usbotg>;
- + disable-over-current;
- + dr_mode = "host";
- + status = "okay";
- +};
- +
- +&usdhc2 { /* module slot */
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc2>;
- + cd-gpios = <&gpio2 2 0>;
- + status = "okay";
- +};
- +
- +&usdhc3 { /* baseboard slot */
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc3>;
- +};
- +
- +&usdhc4 { /* eMMC */
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc4>;
- + bus-width = <8>;
- + non-removable;
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl.dtsi linux-3.14.35/arch/arm/boot/dts/imx6qdl.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6qdl.dtsi 2015-03-08 14:27:37.393684503 -0500
- @@ -10,10 +10,16 @@
- * http://www.gnu.org/copyleft/gpl.html
- */
-
- +#include <dt-bindings/interrupt-controller/arm-gic.h>
- +
- #include "skeleton.dtsi"
- +#include <dt-bindings/gpio/gpio.h>
-
- / {
- aliases {
- + ethernet0 = &fec;
- + can0 = &can1;
- + can1 = &can2;
- gpio0 = &gpio1;
- gpio1 = &gpio2;
- gpio2 = &gpio3;
- @@ -24,6 +30,11 @@
- i2c0 = &i2c1;
- i2c1 = &i2c2;
- i2c2 = &i2c3;
- + ipu0 = &ipu1;
- + mmc0 = &usdhc1;
- + mmc1 = &usdhc2;
- + mmc2 = &usdhc3;
- + mmc3 = &usdhc4;
- serial0 = &uart1;
- serial1 = &uart2;
- serial2 = &uart3;
- @@ -33,13 +44,13 @@
- spi1 = &ecspi2;
- spi2 = &ecspi3;
- spi3 = &ecspi4;
- + usbphy0 = &usbphy1;
- + usbphy1 = &usbphy2;
- };
-
- intc: interrupt-controller@00a01000 {
- compatible = "arm,cortex-a9-gic";
- #interrupt-cells = <3>;
- - #address-cells = <1>;
- - #size-cells = <1>;
- interrupt-controller;
- reg = <0x00a01000 0x1000>,
- <0x00a00100 0x100>;
- @@ -51,20 +62,27 @@
-
- ckil {
- compatible = "fsl,imx-ckil", "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <32768>;
- };
-
- ckih1 {
- compatible = "fsl,imx-ckih1", "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <0>;
- };
-
- osc {
- compatible = "fsl,imx-osc", "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <24000000>;
- };
- };
-
- + pu_dummy: pudummy_reg {
- + compatible = "fsl,imx6-dummy-pureg"; /* only used in ldo-bypass */
- + };
- +
- soc {
- #address-cells = <1>;
- #size-cells = <1>;
- @@ -75,7 +93,10 @@
- dma_apbh: dma-apbh@00110000 {
- compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh";
- reg = <0x00110000 0x2000>;
- - interrupts = <0 13 0x04>, <0 13 0x04>, <0 13 0x04>, <0 13 0x04>;
- + interrupts = <0 13 IRQ_TYPE_LEVEL_HIGH>,
- + <0 13 IRQ_TYPE_LEVEL_HIGH>,
- + <0 13 IRQ_TYPE_LEVEL_HIGH>,
- + <0 13 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3";
- #dma-cells = <1>;
- dma-channels = <4>;
- @@ -88,7 +109,7 @@
- #size-cells = <1>;
- reg = <0x00112000 0x2000>, <0x00114000 0x2000>;
- reg-names = "gpmi-nand", "bch";
- - interrupts = <0 15 0x04>;
- + interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "bch";
- clocks = <&clks 152>, <&clks 153>, <&clks 151>,
- <&clks 150>, <&clks 149>;
- @@ -109,11 +130,13 @@
- L2: l2-cache@00a02000 {
- compatible = "arm,pl310-cache";
- reg = <0x00a02000 0x1000>;
- - interrupts = <0 92 0x04>;
- + interrupts = <0 92 IRQ_TYPE_LEVEL_HIGH>;
- cache-unified;
- cache-level = <2>;
- arm,tag-latency = <4 2 3>;
- arm,data-latency = <4 2 3>;
- + arm,dynamic-clk-gating;
- + arm,standby-mode;
- };
-
- pcie: pcie@0x01000000 {
- @@ -126,15 +149,22 @@
- 0x81000000 0 0 0x01f80000 0 0x00010000 /* downstream I/O */
- 0x82000000 0 0x01000000 0x01000000 0 0x00f00000>; /* non-prefetchable memory */
- num-lanes = <1>;
- - interrupts = <0 123 0x04>;
- - clocks = <&clks 189>, <&clks 187>, <&clks 206>, <&clks 144>;
- - clock-names = "pcie_ref_125m", "sata_ref_100m", "lvds_gate", "pcie_axi";
- + interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
- + interrupt-names = "pme";
- + #interrupt-cells = <1>;
- + interrupt-map-mask = <0 0 0 0x7>;
- + interrupt-map = <0 0 0 1 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
- + <0 0 0 2 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
- + <0 0 0 3 &intc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
- + <0 0 0 4 &intc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&clks 144>, <&clks 221>, <&clks 189>, <&clks 187>;
- + clock-names = "pcie_axi", "lvds_gate", "pcie_ref_125m", "sata_ref_100m";
- status = "disabled";
- };
-
- pmu {
- compatible = "arm,cortex-a9-pmu";
- - interrupts = <0 94 0x04>;
- + interrupts = <0 94 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- aips-bus@02000000 { /* AIPS1 */
- @@ -154,7 +184,7 @@
- spdif: spdif@02004000 {
- compatible = "fsl,imx35-spdif";
- reg = <0x02004000 0x4000>;
- - interrupts = <0 52 0x04>;
- + interrupts = <0 52 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&sdma 14 18 0>,
- <&sdma 15 18 0>;
- dma-names = "rx", "tx";
- @@ -176,9 +206,11 @@
- #size-cells = <0>;
- compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
- reg = <0x02008000 0x4000>;
- - interrupts = <0 31 0x04>;
- + interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 112>, <&clks 112>;
- clock-names = "ipg", "per";
- + dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
- + dma-names = "rx", "tx";
- status = "disabled";
- };
-
- @@ -187,9 +219,11 @@
- #size-cells = <0>;
- compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
- reg = <0x0200c000 0x4000>;
- - interrupts = <0 32 0x04>;
- + interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 113>, <&clks 113>;
- clock-names = "ipg", "per";
- + dmas = <&sdma 5 7 1>, <&sdma 6 7 2>;
- + dma-names = "rx", "tx";
- status = "disabled";
- };
-
- @@ -198,9 +232,11 @@
- #size-cells = <0>;
- compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
- reg = <0x02010000 0x4000>;
- - interrupts = <0 33 0x04>;
- + interrupts = <0 33 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 114>, <&clks 114>;
- clock-names = "ipg", "per";
- + dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;
- + dma-names = "rx", "tx";
- status = "disabled";
- };
-
- @@ -209,16 +245,18 @@
- #size-cells = <0>;
- compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
- reg = <0x02014000 0x4000>;
- - interrupts = <0 34 0x04>;
- + interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 115>, <&clks 115>;
- clock-names = "ipg", "per";
- + dmas = <&sdma 9 7 1>, <&sdma 10 7 2>;
- + dma-names = "rx", "tx";
- status = "disabled";
- };
-
- uart1: serial@02020000 {
- compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
- reg = <0x02020000 0x4000>;
- - interrupts = <0 26 0x04>;
- + interrupts = <0 26 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 160>, <&clks 161>;
- clock-names = "ipg", "per";
- dmas = <&sdma 25 4 0>, <&sdma 26 4 0>;
- @@ -227,15 +265,23 @@
- };
-
- esai: esai@02024000 {
- + compatible = "fsl,imx6q-esai";
- reg = <0x02024000 0x4000>;
- - interrupts = <0 51 0x04>;
- + interrupts = <0 51 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&clks 118>;
- + fsl,esai-dma-events = <24 23>;
- + fsl,flags = <1>;
- + status = "disabled";
- };
-
- ssi1: ssi@02028000 {
- - compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
- + compatible = "fsl,imx6q-ssi",
- + "fsl,imx51-ssi",
- + "fsl,imx21-ssi";
- reg = <0x02028000 0x4000>;
- - interrupts = <0 46 0x04>;
- - clocks = <&clks 178>;
- + interrupts = <0 46 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&clks 178>, <&clks 157>;
- + clock-names = "ipg", "baud";
- dmas = <&sdma 37 1 0>,
- <&sdma 38 1 0>;
- dma-names = "rx", "tx";
- @@ -245,10 +291,13 @@
- };
-
- ssi2: ssi@0202c000 {
- - compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
- + compatible = "fsl,imx6q-ssi",
- + "fsl,imx51-ssi",
- + "fsl,imx21-ssi";
- reg = <0x0202c000 0x4000>;
- - interrupts = <0 47 0x04>;
- - clocks = <&clks 179>;
- + interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&clks 179>, <&clks 158>;
- + clock-names = "ipg", "baud";
- dmas = <&sdma 41 1 0>,
- <&sdma 42 1 0>;
- dma-names = "rx", "tx";
- @@ -258,10 +307,13 @@
- };
-
- ssi3: ssi@02030000 {
- - compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
- + compatible = "fsl,imx6q-ssi",
- + "fsl,imx51-ssi",
- + "fsl,imx21-ssi";
- reg = <0x02030000 0x4000>;
- - interrupts = <0 48 0x04>;
- - clocks = <&clks 180>;
- + interrupts = <0 48 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&clks 180>, <&clks 159>;
- + clock-names = "ipg", "baud";
- dmas = <&sdma 45 1 0>,
- <&sdma 46 1 0>;
- dma-names = "rx", "tx";
- @@ -271,8 +323,25 @@
- };
-
- asrc: asrc@02034000 {
- + compatible = "fsl,imx53-asrc";
- reg = <0x02034000 0x4000>;
- - interrupts = <0 50 0x04>;
- + interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&clks 107>, <&clks 156>;
- + clock-names = "core", "dma";
- + dmas = <&sdma 17 20 1>, <&sdma 18 20 1>, <&sdma 19 20 1>,
- + <&sdma 20 20 1>, <&sdma 21 20 1>, <&sdma 22 20 1>;
- + dma-names = "rxa", "rxb", "rxc",
- + "txa", "txb", "txc";
- + status = "okay";
- + };
- +
- + asrc_p2p: asrc_p2p {
- + compatible = "fsl,imx6q-asrc-p2p";
- + fsl,output-rate = <48000>;
- + fsl,output-width = <16>;
- + fsl,asrc-dma-rx-events = <17 18 19>;
- + fsl,asrc-dma-tx-events = <20 21 22>;
- + status = "okay";
- };
-
- spba@0203c000 {
- @@ -281,8 +350,19 @@
- };
-
- vpu: vpu@02040000 {
- + compatible = "fsl,imx6-vpu";
- reg = <0x02040000 0x3c000>;
- - interrupts = <0 3 0x04 0 12 0x04>;
- + reg-names = "vpu_regs";
- + interrupts = <0 3 IRQ_TYPE_LEVEL_HIGH>,
- + <0 12 IRQ_TYPE_LEVEL_HIGH>;
- + interrupt-names = "vpu_jpu_irq", "vpu_ipi_irq";
- + clocks = <&clks 168>, <&clks 140>, <&clks 142>;
- + clock-names = "vpu_clk", "mmdc_ch0_axi", "ocram";
- + iramsize = <0x21000>;
- + iram = <&ocram>;
- + resets = <&src 1>;
- + pu-supply = <®_pu>;
- + status = "disabled";
- };
-
- aipstz@0207c000 { /* AIPSTZ1 */
- @@ -293,7 +373,7 @@
- #pwm-cells = <2>;
- compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
- reg = <0x02080000 0x4000>;
- - interrupts = <0 83 0x04>;
- + interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 62>, <&clks 145>;
- clock-names = "ipg", "per";
- };
- @@ -302,7 +382,7 @@
- #pwm-cells = <2>;
- compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
- reg = <0x02084000 0x4000>;
- - interrupts = <0 84 0x04>;
- + interrupts = <0 84 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 62>, <&clks 146>;
- clock-names = "ipg", "per";
- };
- @@ -311,7 +391,7 @@
- #pwm-cells = <2>;
- compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
- reg = <0x02088000 0x4000>;
- - interrupts = <0 85 0x04>;
- + interrupts = <0 85 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 62>, <&clks 147>;
- clock-names = "ipg", "per";
- };
- @@ -320,7 +400,7 @@
- #pwm-cells = <2>;
- compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
- reg = <0x0208c000 0x4000>;
- - interrupts = <0 86 0x04>;
- + interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 62>, <&clks 148>;
- clock-names = "ipg", "per";
- };
- @@ -328,23 +408,25 @@
- can1: flexcan@02090000 {
- compatible = "fsl,imx6q-flexcan";
- reg = <0x02090000 0x4000>;
- - interrupts = <0 110 0x04>;
- + interrupts = <0 110 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 108>, <&clks 109>;
- clock-names = "ipg", "per";
- + status = "disabled";
- };
-
- can2: flexcan@02094000 {
- compatible = "fsl,imx6q-flexcan";
- reg = <0x02094000 0x4000>;
- - interrupts = <0 111 0x04>;
- + interrupts = <0 111 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 110>, <&clks 111>;
- clock-names = "ipg", "per";
- + status = "disabled";
- };
-
- gpt: gpt@02098000 {
- compatible = "fsl,imx6q-gpt", "fsl,imx31-gpt";
- reg = <0x02098000 0x4000>;
- - interrupts = <0 55 0x04>;
- + interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 119>, <&clks 120>;
- clock-names = "ipg", "per";
- };
- @@ -352,7 +434,8 @@
- gpio1: gpio@0209c000 {
- compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
- reg = <0x0209c000 0x4000>;
- - interrupts = <0 66 0x04 0 67 0x04>;
- + interrupts = <0 66 IRQ_TYPE_LEVEL_HIGH>,
- + <0 67 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- @@ -362,7 +445,8 @@
- gpio2: gpio@020a0000 {
- compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
- reg = <0x020a0000 0x4000>;
- - interrupts = <0 68 0x04 0 69 0x04>;
- + interrupts = <0 68 IRQ_TYPE_LEVEL_HIGH>,
- + <0 69 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- @@ -372,7 +456,8 @@
- gpio3: gpio@020a4000 {
- compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
- reg = <0x020a4000 0x4000>;
- - interrupts = <0 70 0x04 0 71 0x04>;
- + interrupts = <0 70 IRQ_TYPE_LEVEL_HIGH>,
- + <0 71 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- @@ -382,7 +467,8 @@
- gpio4: gpio@020a8000 {
- compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
- reg = <0x020a8000 0x4000>;
- - interrupts = <0 72 0x04 0 73 0x04>;
- + interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>,
- + <0 73 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- @@ -392,7 +478,8 @@
- gpio5: gpio@020ac000 {
- compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
- reg = <0x020ac000 0x4000>;
- - interrupts = <0 74 0x04 0 75 0x04>;
- + interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>,
- + <0 75 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- @@ -402,7 +489,8 @@
- gpio6: gpio@020b0000 {
- compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
- reg = <0x020b0000 0x4000>;
- - interrupts = <0 76 0x04 0 77 0x04>;
- + interrupts = <0 76 IRQ_TYPE_LEVEL_HIGH>,
- + <0 77 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- @@ -412,7 +500,8 @@
- gpio7: gpio@020b4000 {
- compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
- reg = <0x020b4000 0x4000>;
- - interrupts = <0 78 0x04 0 79 0x04>;
- + interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>,
- + <0 79 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- @@ -421,20 +510,20 @@
-
- kpp: kpp@020b8000 {
- reg = <0x020b8000 0x4000>;
- - interrupts = <0 82 0x04>;
- + interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- wdog1: wdog@020bc000 {
- compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
- reg = <0x020bc000 0x4000>;
- - interrupts = <0 80 0x04>;
- + interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 0>;
- };
-
- wdog2: wdog@020c0000 {
- compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
- reg = <0x020c0000 0x4000>;
- - interrupts = <0 81 0x04>;
- + interrupts = <0 81 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 0>;
- status = "disabled";
- };
- @@ -442,14 +531,17 @@
- clks: ccm@020c4000 {
- compatible = "fsl,imx6q-ccm";
- reg = <0x020c4000 0x4000>;
- - interrupts = <0 87 0x04 0 88 0x04>;
- + interrupts = <0 87 IRQ_TYPE_LEVEL_HIGH>,
- + <0 88 IRQ_TYPE_LEVEL_HIGH>;
- #clock-cells = <1>;
- };
-
- anatop: anatop@020c8000 {
- compatible = "fsl,imx6q-anatop", "syscon", "simple-bus";
- reg = <0x020c8000 0x1000>;
- - interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
- + interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>,
- + <0 54 IRQ_TYPE_LEVEL_HIGH>,
- + <0 127 IRQ_TYPE_LEVEL_HIGH>;
-
- regulator-1p1@110 {
- compatible = "fsl,anatop-regulator";
- @@ -495,7 +587,7 @@
-
- reg_arm: regulator-vddcore@140 {
- compatible = "fsl,anatop-regulator";
- - regulator-name = "cpu";
- + regulator-name = "vddarm";
- regulator-min-microvolt = <725000>;
- regulator-max-microvolt = <1450000>;
- regulator-always-on;
- @@ -515,7 +607,6 @@
- regulator-name = "vddpu";
- regulator-min-microvolt = <725000>;
- regulator-max-microvolt = <1450000>;
- - regulator-always-on;
- anatop-reg-offset = <0x140>;
- anatop-vol-bit-shift = <9>;
- anatop-vol-bit-width = <5>;
- @@ -547,23 +638,38 @@
-
- tempmon: tempmon {
- compatible = "fsl,imx6q-tempmon";
- - interrupts = <0 49 0x04>;
- + interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>;
- fsl,tempmon = <&anatop>;
- fsl,tempmon-data = <&ocotp>;
- + clocks = <&clks 172>;
- };
-
- usbphy1: usbphy@020c9000 {
- compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
- reg = <0x020c9000 0x1000>;
- - interrupts = <0 44 0x04>;
- + interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 182>;
- + fsl,anatop = <&anatop>;
- };
-
- usbphy2: usbphy@020ca000 {
- compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
- reg = <0x020ca000 0x1000>;
- - interrupts = <0 45 0x04>;
- + interrupts = <0 45 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 183>;
- + fsl,anatop = <&anatop>;
- + };
- +
- + usbphy_nop1: usbphy_nop1 {
- + compatible = "usb-nop-xceiv";
- + clocks = <&clks 182>;
- + clock-names = "main_clk";
- + };
- +
- + usbphy_nop2: usbphy_nop2 {
- + compatible = "usb-nop-xceiv";
- + clocks = <&clks 182>;
- + clock-names = "main_clk";
- };
-
- snvs@020cc000 {
- @@ -575,31 +681,39 @@
- snvs-rtc-lp@34 {
- compatible = "fsl,sec-v4.0-mon-rtc-lp";
- reg = <0x34 0x58>;
- - interrupts = <0 19 0x04 0 20 0x04>;
- + interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>,
- + <0 20 IRQ_TYPE_LEVEL_HIGH>;
- };
- };
-
- epit1: epit@020d0000 { /* EPIT1 */
- reg = <0x020d0000 0x4000>;
- - interrupts = <0 56 0x04>;
- + interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- epit2: epit@020d4000 { /* EPIT2 */
- reg = <0x020d4000 0x4000>;
- - interrupts = <0 57 0x04>;
- + interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- src: src@020d8000 {
- compatible = "fsl,imx6q-src", "fsl,imx51-src";
- reg = <0x020d8000 0x4000>;
- - interrupts = <0 91 0x04 0 96 0x04>;
- + interrupts = <0 91 IRQ_TYPE_LEVEL_HIGH>,
- + <0 96 IRQ_TYPE_LEVEL_HIGH>;
- #reset-cells = <1>;
- };
-
- gpc: gpc@020dc000 {
- compatible = "fsl,imx6q-gpc";
- reg = <0x020dc000 0x4000>;
- - interrupts = <0 89 0x04 0 90 0x04>;
- + interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
- + <0 90 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&clks 122>, <&clks 74>, <&clks 121>,
- + <&clks 26>, <&clks 143>, <&clks 168>, <&clks 62>;
- + clock-names = "gpu3d_core", "gpu3d_shader", "gpu2d_core",
- + "gpu2d_axi", "openvg_axi", "vpu_axi", "ipg";
- + pu-supply = <®_pu>;
- };
-
- gpr: iomuxc-gpr@020e0000 {
- @@ -610,778 +724,40 @@
- iomuxc: iomuxc@020e0000 {
- compatible = "fsl,imx6dl-iomuxc", "fsl,imx6q-iomuxc";
- reg = <0x020e0000 0x4000>;
- -
- - audmux {
- - pinctrl_audmux_1: audmux-1 {
- - fsl,pins = <
- - MX6QDL_PAD_SD2_DAT0__AUD4_RXD 0x80000000
- - MX6QDL_PAD_SD2_DAT3__AUD4_TXC 0x80000000
- - MX6QDL_PAD_SD2_DAT2__AUD4_TXD 0x80000000
- - MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x80000000
- - >;
- - };
- -
- - pinctrl_audmux_2: audmux-2 {
- - fsl,pins = <
- - MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x80000000
- - MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x80000000
- - MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x80000000
- - MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x80000000
- - >;
- - };
- -
- - pinctrl_audmux_3: audmux-3 {
- - fsl,pins = <
- - MX6QDL_PAD_DISP0_DAT16__AUD5_TXC 0x80000000
- - MX6QDL_PAD_DISP0_DAT18__AUD5_TXFS 0x80000000
- - MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x80000000
- - >;
- - };
- - };
- -
- - ecspi1 {
- - pinctrl_ecspi1_1: ecspi1grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
- - MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
- - MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
- - >;
- - };
- -
- - pinctrl_ecspi1_2: ecspi1grp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_KEY_COL1__ECSPI1_MISO 0x100b1
- - MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI 0x100b1
- - MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK 0x100b1
- - >;
- - };
- - };
- -
- - ecspi3 {
- - pinctrl_ecspi3_1: ecspi3grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
- - MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
- - MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
- - >;
- - };
- - };
- -
- - enet {
- - pinctrl_enet_1: enetgrp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- - MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- - MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- - MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- - MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- - MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- - MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- - MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- - MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- - MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- - MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- - MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- - MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- - MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- - MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- - MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- - >;
- - };
- -
- - pinctrl_enet_2: enetgrp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_KEY_COL1__ENET_MDIO 0x1b0b0
- - MX6QDL_PAD_KEY_COL2__ENET_MDC 0x1b0b0
- - MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- - MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- - MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- - MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- - MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- - MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- - MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- - MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- - MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- - MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- - MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- - MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- - MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- - >;
- - };
- -
- - pinctrl_enet_3: enetgrp-3 {
- - fsl,pins = <
- - MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- - MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- - MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- - MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- - MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- - MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- - MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- - MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- - MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- - MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- - MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- - MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- - MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- - MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- - MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- - MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0
- - >;
- - };
- - };
- -
- - esai {
- - pinctrl_esai_1: esaigrp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_ENET_RXD0__ESAI_TX_HF_CLK 0x1b030
- - MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK 0x1b030
- - MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS 0x1b030
- - MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2 0x1b030
- - MX6QDL_PAD_ENET_TXD1__ESAI_TX2_RX3 0x1b030
- - MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1 0x1b030
- - MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0 0x1b030
- - MX6QDL_PAD_NANDF_CS2__ESAI_TX0 0x1b030
- - MX6QDL_PAD_NANDF_CS3__ESAI_TX1 0x1b030
- - >;
- - };
- -
- - pinctrl_esai_2: esaigrp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK 0x1b030
- - MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS 0x1b030
- - MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2 0x1b030
- - MX6QDL_PAD_GPIO_5__ESAI_TX2_RX3 0x1b030
- - MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1 0x1b030
- - MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0 0x1b030
- - MX6QDL_PAD_GPIO_17__ESAI_TX0 0x1b030
- - MX6QDL_PAD_NANDF_CS3__ESAI_TX1 0x1b030
- - MX6QDL_PAD_ENET_MDIO__ESAI_RX_CLK 0x1b030
- - MX6QDL_PAD_GPIO_9__ESAI_RX_FS 0x1b030
- - >;
- - };
- - };
- -
- - flexcan1 {
- - pinctrl_flexcan1_1: flexcan1grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x80000000
- - MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x80000000
- - >;
- - };
- -
- - pinctrl_flexcan1_2: flexcan1grp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_GPIO_7__FLEXCAN1_TX 0x80000000
- - MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x80000000
- - >;
- - };
- - };
- -
- - flexcan2 {
- - pinctrl_flexcan2_1: flexcan2grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x80000000
- - MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x80000000
- - >;
- - };
- - };
- -
- - gpmi-nand {
- - pinctrl_gpmi_nand_1: gpmi-nand-1 {
- - fsl,pins = <
- - MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
- - MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
- - MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
- - MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
- - MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
- - MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
- - MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
- - MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
- - MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
- - MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
- - MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
- - MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
- - MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
- - MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
- - MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
- - MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
- - MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1
- - >;
- - };
- - };
- -
- - hdmi_hdcp {
- - pinctrl_hdmi_hdcp_1: hdmihdcpgrp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_KEY_COL3__HDMI_TX_DDC_SCL 0x4001b8b1
- - MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 0x4001b8b1
- - >;
- - };
- -
- - pinctrl_hdmi_hdcp_2: hdmihdcpgrp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_EIM_EB2__HDMI_TX_DDC_SCL 0x4001b8b1
- - MX6QDL_PAD_EIM_D16__HDMI_TX_DDC_SDA 0x4001b8b1
- - >;
- - };
- -
- - pinctrl_hdmi_hdcp_3: hdmihdcpgrp-3 {
- - fsl,pins = <
- - MX6QDL_PAD_EIM_EB2__HDMI_TX_DDC_SCL 0x4001b8b1
- - MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 0x4001b8b1
- - >;
- - };
- - };
- -
- - hdmi_cec {
- - pinctrl_hdmi_cec_1: hdmicecgrp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_EIM_A25__HDMI_TX_CEC_LINE 0x1f8b0
- - >;
- - };
- -
- - pinctrl_hdmi_cec_2: hdmicecgrp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
- - >;
- - };
- - };
- -
- - i2c1 {
- - pinctrl_i2c1_1: i2c1grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- - MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- - >;
- - };
- -
- - pinctrl_i2c1_2: i2c1grp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
- - MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
- - >;
- - };
- - };
- -
- - i2c2 {
- - pinctrl_i2c2_1: i2c2grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
- - MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1
- - >;
- - };
- -
- - pinctrl_i2c2_2: i2c2grp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- - MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- - >;
- - };
- -
- - pinctrl_i2c2_3: i2c2grp-3 {
- - fsl,pins = <
- - MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
- - MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- - >;
- - };
- - };
- -
- - i2c3 {
- - pinctrl_i2c3_1: i2c3grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
- - MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
- - >;
- - };
- -
- - pinctrl_i2c3_2: i2c3grp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
- - MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
- - >;
- - };
- -
- - pinctrl_i2c3_3: i2c3grp-3 {
- - fsl,pins = <
- - MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
- - MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
- - >;
- - };
- -
- - pinctrl_i2c3_4: i2c3grp-4 {
- - fsl,pins = <
- - MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
- - MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
- - >;
- - };
- - };
- -
- - ipu1 {
- - pinctrl_ipu1_1: ipu1grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
- - MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10
- - MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10
- - MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10
- - MX6QDL_PAD_DI0_PIN4__IPU1_DI0_PIN04 0x80000000
- - MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10
- - MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10
- - MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10
- - MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10
- - MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10
- - MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10
- - MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10
- - MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10
- - MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10
- - MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10
- - MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10
- - MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10
- - MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10
- - MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10
- - MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10
- - MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10
- - MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10
- - MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10
- - MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10
- - MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10
- - MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10
- - MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10
- - MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10
- - MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10
- - >;
- - };
- -
- - pinctrl_ipu1_2: ipu1grp-2 { /* parallel camera */
- - fsl,pins = <
- - MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x80000000
- - MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13 0x80000000
- - MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14 0x80000000
- - MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15 0x80000000
- - MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16 0x80000000
- - MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17 0x80000000
- - MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18 0x80000000
- - MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19 0x80000000
- - MX6QDL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN 0x80000000
- - MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x80000000
- - MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC 0x80000000
- - MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC 0x80000000
- - >;
- - };
- -
- - pinctrl_ipu1_3: ipu1grp-3 { /* parallel port 16-bit */
- - fsl,pins = <
- - MX6QDL_PAD_CSI0_DAT4__IPU1_CSI0_DATA04 0x80000000
- - MX6QDL_PAD_CSI0_DAT5__IPU1_CSI0_DATA05 0x80000000
- - MX6QDL_PAD_CSI0_DAT6__IPU1_CSI0_DATA06 0x80000000
- - MX6QDL_PAD_CSI0_DAT7__IPU1_CSI0_DATA07 0x80000000
- - MX6QDL_PAD_CSI0_DAT8__IPU1_CSI0_DATA08 0x80000000
- - MX6QDL_PAD_CSI0_DAT9__IPU1_CSI0_DATA09 0x80000000
- - MX6QDL_PAD_CSI0_DAT10__IPU1_CSI0_DATA10 0x80000000
- - MX6QDL_PAD_CSI0_DAT11__IPU1_CSI0_DATA11 0x80000000
- - MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x80000000
- - MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13 0x80000000
- - MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14 0x80000000
- - MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15 0x80000000
- - MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16 0x80000000
- - MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17 0x80000000
- - MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18 0x80000000
- - MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19 0x80000000
- - MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x80000000
- - MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC 0x80000000
- - MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC 0x80000000
- - >;
- - };
- - };
- -
- - mlb {
- - pinctrl_mlb_1: mlbgrp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_GPIO_3__MLB_CLK 0x71
- - MX6QDL_PAD_GPIO_6__MLB_SIG 0x71
- - MX6QDL_PAD_GPIO_2__MLB_DATA 0x71
- - >;
- - };
- -
- - pinctrl_mlb_2: mlbgrp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_ENET_TXD1__MLB_CLK 0x71
- - MX6QDL_PAD_GPIO_6__MLB_SIG 0x71
- - MX6QDL_PAD_GPIO_2__MLB_DATA 0x71
- - >;
- - };
- - };
- -
- - pwm0 {
- - pinctrl_pwm0_1: pwm0grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
- - >;
- - };
- - };
- -
- - pwm3 {
- - pinctrl_pwm3_1: pwm3grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1
- - >;
- - };
- - };
- -
- - spdif {
- - pinctrl_spdif_1: spdifgrp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_KEY_COL3__SPDIF_IN 0x1b0b0
- - >;
- - };
- -
- - pinctrl_spdif_2: spdifgrp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_GPIO_16__SPDIF_IN 0x1b0b0
- - MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x1b0b0
- - >;
- - };
- -
- - pinctrl_spdif_3: spdifgrp-3 {
- - fsl,pins = <
- - MX6QDL_PAD_ENET_RXD0__SPDIF_OUT 0x1b0b0
- - >;
- - };
- - };
- -
- - uart1 {
- - pinctrl_uart1_1: uart1grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
- - MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
- - >;
- - };
- - };
- -
- - uart2 {
- - pinctrl_uart2_1: uart2grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
- - MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
- - >;
- - };
- -
- - pinctrl_uart2_2: uart2grp-2 { /* DTE mode */
- - fsl,pins = <
- - MX6QDL_PAD_EIM_D26__UART2_RX_DATA 0x1b0b1
- - MX6QDL_PAD_EIM_D27__UART2_TX_DATA 0x1b0b1
- - MX6QDL_PAD_EIM_D28__UART2_DTE_CTS_B 0x1b0b1
- - MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B 0x1b0b1
- - >;
- - };
- - };
- -
- - uart3 {
- - pinctrl_uart3_1: uart3grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_SD4_CLK__UART3_RX_DATA 0x1b0b1
- - MX6QDL_PAD_SD4_CMD__UART3_TX_DATA 0x1b0b1
- - MX6QDL_PAD_EIM_D30__UART3_CTS_B 0x1b0b1
- - MX6QDL_PAD_EIM_EB3__UART3_RTS_B 0x1b0b1
- - >;
- - };
- -
- - pinctrl_uart3_2: uart3grp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
- - MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
- - MX6QDL_PAD_EIM_D23__UART3_CTS_B 0x1b0b1
- - MX6QDL_PAD_EIM_EB3__UART3_RTS_B 0x1b0b1
- - >;
- - };
- - };
- -
- - uart4 {
- - pinctrl_uart4_1: uart4grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
- - MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
- - >;
- - };
- - };
- -
- - usbotg {
- - pinctrl_usbotg_1: usbotggrp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- - >;
- - };
- -
- - pinctrl_usbotg_2: usbotggrp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
- - >;
- - };
- - };
- -
- - usbh2 {
- - pinctrl_usbh2_1: usbh2grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_RGMII_TXC__USB_H2_DATA 0x40013030
- - MX6QDL_PAD_RGMII_TX_CTL__USB_H2_STROBE 0x40013030
- - >;
- - };
- -
- - pinctrl_usbh2_2: usbh2grp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_RGMII_TX_CTL__USB_H2_STROBE 0x40017030
- - >;
- - };
- - };
- -
- - usbh3 {
- - pinctrl_usbh3_1: usbh3grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_RGMII_RX_CTL__USB_H3_DATA 0x40013030
- - MX6QDL_PAD_RGMII_RXC__USB_H3_STROBE 0x40013030
- - >;
- - };
- -
- - pinctrl_usbh3_2: usbh3grp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_RGMII_RXC__USB_H3_STROBE 0x40017030
- - >;
- - };
- - };
- -
- - usdhc1 {
- - pinctrl_usdhc1_1: usdhc1grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059
- - MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059
- - MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
- - MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
- - MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
- - MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
- - MX6QDL_PAD_NANDF_D0__SD1_DATA4 0x17059
- - MX6QDL_PAD_NANDF_D1__SD1_DATA5 0x17059
- - MX6QDL_PAD_NANDF_D2__SD1_DATA6 0x17059
- - MX6QDL_PAD_NANDF_D3__SD1_DATA7 0x17059
- - >;
- - };
- -
- - pinctrl_usdhc1_2: usdhc1grp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059
- - MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059
- - MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
- - MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
- - MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
- - MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
- - >;
- - };
- - };
- -
- - usdhc2 {
- - pinctrl_usdhc2_1: usdhc2grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- - MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- - MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- - MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- - MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- - MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- - MX6QDL_PAD_NANDF_D4__SD2_DATA4 0x17059
- - MX6QDL_PAD_NANDF_D5__SD2_DATA5 0x17059
- - MX6QDL_PAD_NANDF_D6__SD2_DATA6 0x17059
- - MX6QDL_PAD_NANDF_D7__SD2_DATA7 0x17059
- - >;
- - };
- -
- - pinctrl_usdhc2_2: usdhc2grp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- - MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- - MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- - MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- - MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- - MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- - >;
- - };
- - };
- -
- - usdhc3 {
- - pinctrl_usdhc3_1: usdhc3grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- - MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- - MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- - MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- - MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- - MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- - MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
- - MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
- - MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
- - MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
- - >;
- - };
- -
- - pinctrl_usdhc3_1_100mhz: usdhc3grp-1-100mhz { /* 100Mhz */
- - fsl,pins = <
- - MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9
- - MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9
- - MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170b9
- - MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170b9
- - MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170b9
- - MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170b9
- - MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170b9
- - MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170b9
- - MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170b9
- - MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170b9
- - >;
- - };
- -
- - pinctrl_usdhc3_1_200mhz: usdhc3grp-1-200mhz { /* 200Mhz */
- - fsl,pins = <
- - MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9
- - MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9
- - MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170f9
- - MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170f9
- - MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170f9
- - MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
- - MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170f9
- - MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170f9
- - MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170f9
- - MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170f9
- - >;
- - };
- -
- - pinctrl_usdhc3_2: usdhc3grp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- - MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- - MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- - MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- - MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- - MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- - >;
- - };
- - };
- -
- - usdhc4 {
- - pinctrl_usdhc4_1: usdhc4grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- - MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- - MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- - MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- - MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- - MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- - MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
- - MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
- - MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
- - MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
- - >;
- - };
- -
- - pinctrl_usdhc4_2: usdhc4grp-2 {
- - fsl,pins = <
- - MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- - MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- - MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- - MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- - MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- - MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- - >;
- - };
- - };
- -
- - weim {
- - pinctrl_weim_cs0_1: weim_cs0grp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_EIM_CS0__EIM_CS0_B 0xb0b1
- - >;
- - };
- -
- - pinctrl_weim_nor_1: weim_norgrp-1 {
- - fsl,pins = <
- - MX6QDL_PAD_EIM_OE__EIM_OE_B 0xb0b1
- - MX6QDL_PAD_EIM_RW__EIM_RW 0xb0b1
- - MX6QDL_PAD_EIM_WAIT__EIM_WAIT_B 0xb060
- - /* data */
- - MX6QDL_PAD_EIM_D16__EIM_DATA16 0x1b0b0
- - MX6QDL_PAD_EIM_D17__EIM_DATA17 0x1b0b0
- - MX6QDL_PAD_EIM_D18__EIM_DATA18 0x1b0b0
- - MX6QDL_PAD_EIM_D19__EIM_DATA19 0x1b0b0
- - MX6QDL_PAD_EIM_D20__EIM_DATA20 0x1b0b0
- - MX6QDL_PAD_EIM_D21__EIM_DATA21 0x1b0b0
- - MX6QDL_PAD_EIM_D22__EIM_DATA22 0x1b0b0
- - MX6QDL_PAD_EIM_D23__EIM_DATA23 0x1b0b0
- - MX6QDL_PAD_EIM_D24__EIM_DATA24 0x1b0b0
- - MX6QDL_PAD_EIM_D25__EIM_DATA25 0x1b0b0
- - MX6QDL_PAD_EIM_D26__EIM_DATA26 0x1b0b0
- - MX6QDL_PAD_EIM_D27__EIM_DATA27 0x1b0b0
- - MX6QDL_PAD_EIM_D28__EIM_DATA28 0x1b0b0
- - MX6QDL_PAD_EIM_D29__EIM_DATA29 0x1b0b0
- - MX6QDL_PAD_EIM_D30__EIM_DATA30 0x1b0b0
- - MX6QDL_PAD_EIM_D31__EIM_DATA31 0x1b0b0
- - /* address */
- - MX6QDL_PAD_EIM_A23__EIM_ADDR23 0xb0b1
- - MX6QDL_PAD_EIM_A22__EIM_ADDR22 0xb0b1
- - MX6QDL_PAD_EIM_A21__EIM_ADDR21 0xb0b1
- - MX6QDL_PAD_EIM_A20__EIM_ADDR20 0xb0b1
- - MX6QDL_PAD_EIM_A19__EIM_ADDR19 0xb0b1
- - MX6QDL_PAD_EIM_A18__EIM_ADDR18 0xb0b1
- - MX6QDL_PAD_EIM_A17__EIM_ADDR17 0xb0b1
- - MX6QDL_PAD_EIM_A16__EIM_ADDR16 0xb0b1
- - MX6QDL_PAD_EIM_DA15__EIM_AD15 0xb0b1
- - MX6QDL_PAD_EIM_DA14__EIM_AD14 0xb0b1
- - MX6QDL_PAD_EIM_DA13__EIM_AD13 0xb0b1
- - MX6QDL_PAD_EIM_DA12__EIM_AD12 0xb0b1
- - MX6QDL_PAD_EIM_DA11__EIM_AD11 0xb0b1
- - MX6QDL_PAD_EIM_DA10__EIM_AD10 0xb0b1
- - MX6QDL_PAD_EIM_DA9__EIM_AD09 0xb0b1
- - MX6QDL_PAD_EIM_DA8__EIM_AD08 0xb0b1
- - MX6QDL_PAD_EIM_DA7__EIM_AD07 0xb0b1
- - MX6QDL_PAD_EIM_DA6__EIM_AD06 0xb0b1
- - MX6QDL_PAD_EIM_DA5__EIM_AD05 0xb0b1
- - MX6QDL_PAD_EIM_DA4__EIM_AD04 0xb0b1
- - MX6QDL_PAD_EIM_DA3__EIM_AD03 0xb0b1
- - MX6QDL_PAD_EIM_DA2__EIM_AD02 0xb0b1
- - MX6QDL_PAD_EIM_DA1__EIM_AD01 0xb0b1
- - MX6QDL_PAD_EIM_DA0__EIM_AD00 0xb0b1
- - >;
- - };
- - };
- };
-
- ldb: ldb@020e0008 {
- - #address-cells = <1>;
- - #size-cells = <0>;
- compatible = "fsl,imx6q-ldb", "fsl,imx53-ldb";
- - gpr = <&gpr>;
- + reg = <0x020e0000 0x4000>;
- + clocks = <&clks 135>, <&clks 136>,
- + <&clks 39>, <&clks 40>,
- + <&clks 41>, <&clks 42>,
- + <&clks 184>, <&clks 185>,
- + <&clks 210>, <&clks 211>,
- + <&clks 212>, <&clks 213>;
- + clock-names = "ldb_di0", "ldb_di1",
- + "ipu1_di0_sel", "ipu1_di1_sel",
- + "ipu2_di0_sel", "ipu2_di1_sel",
- + "di0_div_3_5", "di1_div_3_5",
- + "di0_div_7", "di1_div_7",
- + "di0_div_sel", "di1_div_sel";
- status = "disabled";
- -
- - lvds-channel@0 {
- - reg = <0>;
- - status = "disabled";
- - };
- -
- - lvds-channel@1 {
- - reg = <1>;
- - status = "disabled";
- - };
- };
-
- dcic1: dcic@020e4000 {
- reg = <0x020e4000 0x4000>;
- - interrupts = <0 124 0x04>;
- + interrupts = <0 124 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- dcic2: dcic@020e8000 {
- reg = <0x020e8000 0x4000>;
- - interrupts = <0 125 0x04>;
- + interrupts = <0 125 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- sdma: sdma@020ec000 {
- compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma";
- reg = <0x020ec000 0x4000>;
- - interrupts = <0 2 0x04>;
- + interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 155>, <&clks 155>;
- clock-names = "ipg", "ahb";
- #dma-cells = <3>;
- @@ -1396,9 +772,29 @@
- reg = <0x02100000 0x100000>;
- ranges;
-
- - caam@02100000 {
- - reg = <0x02100000 0x40000>;
- - interrupts = <0 105 0x04 0 106 0x04>;
- + crypto: caam@02100000 {
- + compatible = "fsl,sec-v4.0";
- + #address-cells = <1>;
- + #size-cells = <1>;
- + reg = <0x2100000 0x40000>;
- + ranges = <0 0x2100000 0x40000>;
- + interrupt-parent = <&intc>; /* interrupts = <0 92 0x4>; */
- + clocks = <&clks 214>, <&clks 215>, <&clks 216>, <&clks 196>;
- + clock-names = "caam_mem", "caam_aclk", "caam_ipg", "caam_emi_slow";
- +
- + sec_jr0: jr0@1000 {
- + compatible = "fsl,sec-v4.0-job-ring";
- + reg = <0x1000 0x1000>;
- + interrupt-parent = <&intc>;
- + interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>;
- + };
- +
- + sec_jr1: jr1@2000 {
- + compatible = "fsl,sec-v4.0-job-ring";
- + reg = <0x2000 0x1000>;
- + interrupt-parent = <&intc>;
- + interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>;
- + };
- };
-
- aipstz@0217c000 { /* AIPSTZ2 */
- @@ -1408,7 +804,7 @@
- usbotg: usb@02184000 {
- compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
- reg = <0x02184000 0x200>;
- - interrupts = <0 43 0x04>;
- + interrupts = <0 43 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 162>;
- fsl,usbphy = <&usbphy1>;
- fsl,usbmisc = <&usbmisc 0>;
- @@ -1418,7 +814,7 @@
- usbh1: usb@02184200 {
- compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
- reg = <0x02184200 0x200>;
- - interrupts = <0 40 0x04>;
- + interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 162>;
- fsl,usbphy = <&usbphy2>;
- fsl,usbmisc = <&usbmisc 1>;
- @@ -1428,18 +824,24 @@
- usbh2: usb@02184400 {
- compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
- reg = <0x02184400 0x200>;
- - interrupts = <0 41 0x04>;
- + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 162>;
- fsl,usbmisc = <&usbmisc 2>;
- + phy_type = "hsic";
- + fsl,usbphy = <&usbphy_nop1>;
- + fsl,anatop = <&anatop>;
- status = "disabled";
- };
-
- usbh3: usb@02184600 {
- compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
- reg = <0x02184600 0x200>;
- - interrupts = <0 42 0x04>;
- + interrupts = <0 42 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 162>;
- fsl,usbmisc = <&usbmisc 3>;
- + phy_type = "hsic";
- + fsl,usbphy = <&usbphy_nop2>;
- + fsl,anatop = <&anatop>;
- status = "disabled";
- };
-
- @@ -1453,7 +855,9 @@
- fec: ethernet@02188000 {
- compatible = "fsl,imx6q-fec";
- reg = <0x02188000 0x4000>;
- - interrupts = <0 118 0x04 0 119 0x04>;
- + interrupts-extended =
- + <&intc 0 118 IRQ_TYPE_LEVEL_HIGH>,
- + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 117>, <&clks 117>, <&clks 190>;
- clock-names = "ipg", "ahb", "ptp";
- status = "disabled";
- @@ -1461,13 +865,15 @@
-
- mlb@0218c000 {
- reg = <0x0218c000 0x4000>;
- - interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>;
- + interrupts = <0 53 IRQ_TYPE_LEVEL_HIGH>,
- + <0 117 IRQ_TYPE_LEVEL_HIGH>,
- + <0 126 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- usdhc1: usdhc@02190000 {
- compatible = "fsl,imx6q-usdhc";
- reg = <0x02190000 0x4000>;
- - interrupts = <0 22 0x04>;
- + interrupts = <0 22 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 163>, <&clks 163>, <&clks 163>;
- clock-names = "ipg", "ahb", "per";
- bus-width = <4>;
- @@ -1477,7 +883,7 @@
- usdhc2: usdhc@02194000 {
- compatible = "fsl,imx6q-usdhc";
- reg = <0x02194000 0x4000>;
- - interrupts = <0 23 0x04>;
- + interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 164>, <&clks 164>, <&clks 164>;
- clock-names = "ipg", "ahb", "per";
- bus-width = <4>;
- @@ -1487,7 +893,7 @@
- usdhc3: usdhc@02198000 {
- compatible = "fsl,imx6q-usdhc";
- reg = <0x02198000 0x4000>;
- - interrupts = <0 24 0x04>;
- + interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 165>, <&clks 165>, <&clks 165>;
- clock-names = "ipg", "ahb", "per";
- bus-width = <4>;
- @@ -1497,7 +903,7 @@
- usdhc4: usdhc@0219c000 {
- compatible = "fsl,imx6q-usdhc";
- reg = <0x0219c000 0x4000>;
- - interrupts = <0 25 0x04>;
- + interrupts = <0 25 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 166>, <&clks 166>, <&clks 166>;
- clock-names = "ipg", "ahb", "per";
- bus-width = <4>;
- @@ -1509,7 +915,7 @@
- #size-cells = <0>;
- compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
- reg = <0x021a0000 0x4000>;
- - interrupts = <0 36 0x04>;
- + interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 125>;
- status = "disabled";
- };
- @@ -1519,7 +925,7 @@
- #size-cells = <0>;
- compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
- reg = <0x021a4000 0x4000>;
- - interrupts = <0 37 0x04>;
- + interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 126>;
- status = "disabled";
- };
- @@ -1529,7 +935,7 @@
- #size-cells = <0>;
- compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
- reg = <0x021a8000 0x4000>;
- - interrupts = <0 38 0x04>;
- + interrupts = <0 38 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 127>;
- status = "disabled";
- };
- @@ -1538,6 +944,11 @@
- reg = <0x021ac000 0x4000>;
- };
-
- + mmdc0-1@021b0000 { /* MMDC0-1 */
- + compatible = "fsl,imx6q-mmdc-combine";
- + reg = <0x021b0000 0x8000>;
- + };
- +
- mmdc0: mmdc@021b0000 { /* MMDC0 */
- compatible = "fsl,imx6q-mmdc";
- reg = <0x021b0000 0x4000>;
- @@ -1550,23 +961,29 @@
- weim: weim@021b8000 {
- compatible = "fsl,imx6q-weim";
- reg = <0x021b8000 0x4000>;
- - interrupts = <0 14 0x04>;
- + interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 196>;
- };
-
- - ocotp: ocotp@021bc000 {
- - compatible = "fsl,imx6q-ocotp", "syscon";
- + ocotp: ocotp-ctrl@021bc000 {
- + compatible = "syscon";
- reg = <0x021bc000 0x4000>;
- };
-
- + ocotp-fuse@021bc000 {
- + compatible = "fsl,imx6q-ocotp";
- + reg = <0x021bc000 0x4000>;
- + clocks = <&clks 128>;
- + };
- +
- tzasc@021d0000 { /* TZASC1 */
- reg = <0x021d0000 0x4000>;
- - interrupts = <0 108 0x04>;
- + interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- tzasc@021d4000 { /* TZASC2 */
- reg = <0x021d4000 0x4000>;
- - interrupts = <0 109 0x04>;
- + interrupts = <0 109 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- audmux: audmux@021d8000 {
- @@ -1575,23 +992,32 @@
- status = "disabled";
- };
-
- - mipi@021dc000 { /* MIPI-CSI */
- + mipi_csi: mipi_csi@021dc000 {
- + compatible = "fsl,imx6q-mipi-csi2";
- reg = <0x021dc000 0x4000>;
- - };
- -
- - mipi@021e0000 { /* MIPI-DSI */
- - reg = <0x021e0000 0x4000>;
- + interrupts = <0 100 0x04>, <0 101 0x04>;
- + clocks = <&clks 138>, <&clks 53>, <&clks 204>;
- + /* Note: clks 138 is hsi_tx, however, the dphy_c
- + * hsi_tx and pll_refclk use the same clk gate.
- + * In current clk driver, open/close clk gate do
- + * use hsi_tx for a temporary debug purpose.
- + */
- + clock-names = "dphy_clk", "pixel_clk", "cfg_clk";
- + status = "disabled";
- };
-
- vdoa@021e4000 {
- + compatible = "fsl,imx6q-vdoa";
- reg = <0x021e4000 0x4000>;
- - interrupts = <0 18 0x04>;
- + interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&clks 202>;
- + iram = <&ocram>;
- };
-
- uart2: serial@021e8000 {
- compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
- reg = <0x021e8000 0x4000>;
- - interrupts = <0 27 0x04>;
- + interrupts = <0 27 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 160>, <&clks 161>;
- clock-names = "ipg", "per";
- dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
- @@ -1602,7 +1028,7 @@
- uart3: serial@021ec000 {
- compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
- reg = <0x021ec000 0x4000>;
- - interrupts = <0 28 0x04>;
- + interrupts = <0 28 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 160>, <&clks 161>;
- clock-names = "ipg", "per";
- dmas = <&sdma 29 4 0>, <&sdma 30 4 0>;
- @@ -1613,7 +1039,7 @@
- uart4: serial@021f0000 {
- compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
- reg = <0x021f0000 0x4000>;
- - interrupts = <0 29 0x04>;
- + interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 160>, <&clks 161>;
- clock-names = "ipg", "per";
- dmas = <&sdma 31 4 0>, <&sdma 32 4 0>;
- @@ -1624,7 +1050,7 @@
- uart5: serial@021f4000 {
- compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
- reg = <0x021f4000 0x4000>;
- - interrupts = <0 30 0x04>;
- + interrupts = <0 30 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 160>, <&clks 161>;
- clock-names = "ipg", "per";
- dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
- @@ -1634,13 +1060,18 @@
- };
-
- ipu1: ipu@02400000 {
- - #crtc-cells = <1>;
- compatible = "fsl,imx6q-ipu";
- reg = <0x02400000 0x400000>;
- - interrupts = <0 6 0x4 0 5 0x4>;
- - clocks = <&clks 130>, <&clks 131>, <&clks 132>;
- - clock-names = "bus", "di0", "di1";
- + interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>,
- + <0 5 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&clks 130>, <&clks 131>, <&clks 132>,
- + <&clks 39>, <&clks 40>,
- + <&clks 135>, <&clks 136>;
- + clock-names = "bus", "di0", "di1",
- + "di0_sel", "di1_sel",
- + "ldb_di0", "ldb_di1";
- resets = <&src 2>;
- + bypass_reset = <0>;
- };
- };
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi linux-3.14.35/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi 2015-03-08 14:27:37.393684503 -0500
- @@ -0,0 +1,374 @@
- +/*
- + * Copyright 2013 Gateworks Corporation
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/ {
- + /* these are used by bootloader for disabling nodes */
- + aliases {
- + can0 = &can1;
- + ethernet0 = &fec;
- + led0 = &led0;
- + led1 = &led1;
- + nand = &gpmi;
- + usb0 = &usbh1;
- + usb1 = &usbotg;
- + };
- +
- + chosen {
- + bootargs = "console=ttymxc1,115200";
- + };
- +
- + leds {
- + compatible = "gpio-leds";
- +
- + led0: user1 {
- + label = "user1";
- + gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */
- + default-state = "on";
- + linux,default-trigger = "heartbeat";
- + };
- +
- + led1: user2 {
- + label = "user2";
- + gpios = <&gpio4 7 0>; /* 103 -> MX6_PANLEDR */
- + default-state = "off";
- + };
- + };
- +
- + memory {
- + reg = <0x10000000 0x20000000>;
- + };
- +
- + pps {
- + compatible = "pps-gpio";
- + gpios = <&gpio1 26 0>;
- + status = "okay";
- + };
- +
- + regulators {
- + compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + reg_3p3v: regulator@0 {
- + compatible = "regulator-fixed";
- + reg = <0>;
- + regulator-name = "3P3V";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + reg_5p0v: regulator@1 {
- + compatible = "regulator-fixed";
- + reg = <1>;
- + regulator-name = "5P0V";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + regulator-always-on;
- + };
- +
- + reg_usb_otg_vbus: regulator@2 {
- + compatible = "regulator-fixed";
- + reg = <2>;
- + regulator-name = "usb_otg_vbus";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + gpio = <&gpio3 22 0>;
- + enable-active-high;
- + };
- + };
- +};
- +
- +&fec {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_enet>;
- + phy-mode = "rgmii";
- + phy-reset-gpios = <&gpio1 30 0>;
- + status = "okay";
- +};
- +
- +&gpmi {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_gpmi_nand>;
- + status = "okay";
- +};
- +
- +&i2c1 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c1>;
- + status = "okay";
- +
- + eeprom1: eeprom@50 {
- + compatible = "atmel,24c02";
- + reg = <0x50>;
- + pagesize = <16>;
- + };
- +
- + eeprom2: eeprom@51 {
- + compatible = "atmel,24c02";
- + reg = <0x51>;
- + pagesize = <16>;
- + };
- +
- + eeprom3: eeprom@52 {
- + compatible = "atmel,24c02";
- + reg = <0x52>;
- + pagesize = <16>;
- + };
- +
- + eeprom4: eeprom@53 {
- + compatible = "atmel,24c02";
- + reg = <0x53>;
- + pagesize = <16>;
- + };
- +
- + gpio: pca9555@23 {
- + compatible = "nxp,pca9555";
- + reg = <0x23>;
- + gpio-controller;
- + #gpio-cells = <2>;
- + };
- +
- + hwmon: gsc@29 {
- + compatible = "gw,gsp";
- + reg = <0x29>;
- + };
- +
- + rtc: ds1672@68 {
- + compatible = "dallas,ds1672";
- + reg = <0x68>;
- + };
- +};
- +
- +&i2c2 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c2>;
- + status = "okay";
- +
- + pmic: ltc3676@3c {
- + compatible = "ltc,ltc3676";
- + reg = <0x3c>;
- +
- + regulators {
- + sw1_reg: ltc3676__sw1 {
- + regulator-min-microvolt = <1175000>;
- + regulator-max-microvolt = <1175000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw2_reg: ltc3676__sw2 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <1800000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw3_reg: ltc3676__sw3 {
- + regulator-min-microvolt = <1175000>;
- + regulator-max-microvolt = <1175000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw4_reg: ltc3676__sw4 {
- + regulator-min-microvolt = <1500000>;
- + regulator-max-microvolt = <1500000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + ldo2_reg: ltc3676__ldo2 {
- + regulator-min-microvolt = <2500000>;
- + regulator-max-microvolt = <2500000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + ldo4_reg: ltc3676__ldo4 {
- + regulator-min-microvolt = <3000000>;
- + regulator-max-microvolt = <3000000>;
- + };
- + };
- + };
- +};
- +
- +&i2c3 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c3>;
- + status = "okay";
- +
- + videoin: adv7180@20 {
- + compatible = "adi,adv7180";
- + reg = <0x20>;
- + };
- +};
- +
- +&iomuxc {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hog>;
- +
- + imx6qdl-gw51xx {
- + pinctrl_hog: hoggrp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x80000000 /* MEZZ_DIO0 */
- + MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x80000000 /* MEZZ_DIO1 */
- + MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000 /* OTG_PWR_EN */
- + MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000 /* GPS_PPS */
- + MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* PHY Reset */
- + MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x80000000 /* PCIE_RST# */
- + MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x80000000 /* user1 led */
- + MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x80000000 /* user2 led */
- + >;
- + };
- +
- + pinctrl_enet: enetgrp {
- + fsl,pins = <
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- + >;
- + };
- +
- + pinctrl_gpmi_nand: gpminandgrp {
- + fsl,pins = <
- + MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
- + MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
- + MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
- + MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
- + MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
- + MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
- + MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
- + MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
- + MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
- + MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
- + MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
- + MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
- + MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
- + MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
- + MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
- + MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
- + >;
- + };
- +
- + pinctrl_i2c1: i2c1grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- + MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_i2c2: i2c2grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_i2c3: i2c3grp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
- + MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_uart1: uart1grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
- + MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart2: uart2grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1
- + MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart3: uart3grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
- + MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart5: uart5grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1
- + MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usbotg: usbotggrp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- + >;
- + };
- + };
- +};
- +
- +&pcie {
- + reset-gpio = <&gpio1 0 0>;
- + status = "okay";
- +};
- +
- +&uart1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart1>;
- + status = "okay";
- +};
- +
- +&uart2 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart2>;
- + status = "okay";
- +};
- +
- +&uart3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart3>;
- + status = "okay";
- +};
- +
- +&uart5 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart5>;
- + status = "okay";
- +};
- +
- +&usbotg {
- + vbus-supply = <®_usb_otg_vbus>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usbotg>;
- + disable-over-current;
- + status = "okay";
- +};
- +
- +&usbh1 {
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi linux-3.14.35/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi 2015-03-08 14:27:37.393684503 -0500
- @@ -0,0 +1,527 @@
- +/*
- + * Copyright 2013 Gateworks Corporation
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/ {
- + /* these are used by bootloader for disabling nodes */
- + aliases {
- + ethernet0 = &fec;
- + led0 = &led0;
- + led1 = &led1;
- + led2 = &led2;
- + nand = &gpmi;
- + ssi0 = &ssi1;
- + usb0 = &usbh1;
- + usb1 = &usbotg;
- + usdhc2 = &usdhc3;
- + };
- +
- + chosen {
- + bootargs = "console=ttymxc1,115200";
- + };
- +
- + backlight {
- + compatible = "pwm-backlight";
- + pwms = <&pwm4 0 5000000>;
- + brightness-levels = <0 4 8 16 32 64 128 255>;
- + default-brightness-level = <7>;
- + };
- +
- + leds {
- + compatible = "gpio-leds";
- +
- + led0: user1 {
- + label = "user1";
- + gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */
- + default-state = "on";
- + linux,default-trigger = "heartbeat";
- + };
- +
- + led1: user2 {
- + label = "user2";
- + gpios = <&gpio4 7 0>; /* 103 -> MX6_PANLEDR */
- + default-state = "off";
- + };
- +
- + led2: user3 {
- + label = "user3";
- + gpios = <&gpio4 15 1>; /* 111 - MX6_LOCLED# */
- + default-state = "off";
- + };
- + };
- +
- + memory {
- + reg = <0x10000000 0x20000000>;
- + };
- +
- + pps {
- + compatible = "pps-gpio";
- + gpios = <&gpio1 26 0>;
- + status = "okay";
- + };
- +
- + regulators {
- + compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + reg_1p0v: regulator@0 {
- + compatible = "regulator-fixed";
- + reg = <0>;
- + regulator-name = "1P0V";
- + regulator-min-microvolt = <1000000>;
- + regulator-max-microvolt = <1000000>;
- + regulator-always-on;
- + };
- +
- + /* remove this fixed regulator once ltc3676__sw2 driver available */
- + reg_1p8v: regulator@1 {
- + compatible = "regulator-fixed";
- + reg = <1>;
- + regulator-name = "1P8V";
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <1800000>;
- + regulator-always-on;
- + };
- +
- + reg_3p3v: regulator@2 {
- + compatible = "regulator-fixed";
- + reg = <2>;
- + regulator-name = "3P3V";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + reg_5p0v: regulator@3 {
- + compatible = "regulator-fixed";
- + reg = <3>;
- + regulator-name = "5P0V";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + regulator-always-on;
- + };
- +
- + reg_usb_otg_vbus: regulator@4 {
- + compatible = "regulator-fixed";
- + reg = <4>;
- + regulator-name = "usb_otg_vbus";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + gpio = <&gpio3 22 0>;
- + enable-active-high;
- + };
- + };
- +
- + sound {
- + compatible = "fsl,imx6q-sabrelite-sgtl5000",
- + "fsl,imx-audio-sgtl5000";
- + model = "imx6q-sabrelite-sgtl5000";
- + ssi-controller = <&ssi1>;
- + audio-codec = <&codec>;
- + audio-routing =
- + "MIC_IN", "Mic Jack",
- + "Mic Jack", "Mic Bias",
- + "Headphone Jack", "HP_OUT";
- + mux-int-port = <1>;
- + mux-ext-port = <4>;
- + };
- +};
- +
- +&audmux {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_audmux>;
- + status = "okay";
- +};
- +
- +&fec {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_enet>;
- + phy-mode = "rgmii";
- + phy-reset-gpios = <&gpio1 30 0>;
- + status = "okay";
- +};
- +
- +&gpmi {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_gpmi_nand>;
- + status = "okay";
- +};
- +
- +&i2c1 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c1>;
- + status = "okay";
- +
- + eeprom1: eeprom@50 {
- + compatible = "atmel,24c02";
- + reg = <0x50>;
- + pagesize = <16>;
- + };
- +
- + eeprom2: eeprom@51 {
- + compatible = "atmel,24c02";
- + reg = <0x51>;
- + pagesize = <16>;
- + };
- +
- + eeprom3: eeprom@52 {
- + compatible = "atmel,24c02";
- + reg = <0x52>;
- + pagesize = <16>;
- + };
- +
- + eeprom4: eeprom@53 {
- + compatible = "atmel,24c02";
- + reg = <0x53>;
- + pagesize = <16>;
- + };
- +
- + gpio: pca9555@23 {
- + compatible = "nxp,pca9555";
- + reg = <0x23>;
- + gpio-controller;
- + #gpio-cells = <2>;
- + };
- +
- + hwmon: gsc@29 {
- + compatible = "gw,gsp";
- + reg = <0x29>;
- + };
- +
- + rtc: ds1672@68 {
- + compatible = "dallas,ds1672";
- + reg = <0x68>;
- + };
- +};
- +
- +&i2c2 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c2>;
- + status = "okay";
- +
- + pciswitch: pex8609@3f {
- + compatible = "plx,pex8609";
- + reg = <0x3f>;
- + };
- +
- + pmic: ltc3676@3c {
- + compatible = "ltc,ltc3676";
- + reg = <0x3c>;
- +
- + regulators {
- + sw1_reg: ltc3676__sw1 {
- + regulator-min-microvolt = <1175000>;
- + regulator-max-microvolt = <1175000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw2_reg: ltc3676__sw2 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <1800000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw3_reg: ltc3676__sw3 {
- + regulator-min-microvolt = <1175000>;
- + regulator-max-microvolt = <1175000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw4_reg: ltc3676__sw4 {
- + regulator-min-microvolt = <1500000>;
- + regulator-max-microvolt = <1500000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + ldo2_reg: ltc3676__ldo2 {
- + regulator-min-microvolt = <2500000>;
- + regulator-max-microvolt = <2500000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + ldo3_reg: ltc3676__ldo3 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <1800000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + ldo4_reg: ltc3676__ldo4 {
- + regulator-min-microvolt = <3000000>;
- + regulator-max-microvolt = <3000000>;
- + };
- + };
- + };
- +};
- +
- +&i2c3 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c3>;
- + status = "okay";
- +
- + accelerometer: fxos8700@1e {
- + compatible = "fsl,fxos8700";
- + reg = <0x13>;
- + };
- +
- + codec: sgtl5000@0a {
- + compatible = "fsl,sgtl5000";
- + reg = <0x0a>;
- + clocks = <&clks 169>;
- + VDDA-supply = <®_1p8v>;
- + VDDIO-supply = <®_3p3v>;
- + };
- +
- + touchscreen: egalax_ts@04 {
- + compatible = "eeti,egalax_ts";
- + reg = <0x04>;
- + interrupt-parent = <&gpio7>;
- + interrupts = <12 2>; /* gpio7_12 active low */
- + wakeup-gpios = <&gpio7 12 0>;
- + };
- +
- + videoin: adv7180@20 {
- + compatible = "adi,adv7180";
- + reg = <0x20>;
- + };
- +};
- +
- +&iomuxc {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hog>;
- +
- + imx6qdl-gw52xx {
- + pinctrl_hog: hoggrp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x80000000 /* MEZZ_DIO0 */
- + MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x80000000 /* MEZZ_DIO1 */
- + MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000 /* OTG_PWR_EN */
- + MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x80000000 /* VIDDEC_PDN# */
- + MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* PHY Reset */
- + MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* PCIE_RST# */
- + MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000 /* GPS_PWDN */
- + MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000 /* GPS_PPS */
- + MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x000130b0 /* AUD4_MCK */
- + MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* USB_SEL_PCI */
- + MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000 /* TOUCH_IRQ# */
- + MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x80000000 /* user1 led */
- + MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x80000000 /* user2 led */
- + MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x80000000 /* user3 led */
- + MX6QDL_PAD_SD2_CMD__GPIO1_IO11 0x80000000 /* LVDS_TCH# */
- + MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x80000000 /* SD3_CD# */
- + MX6QDL_PAD_SD4_DAT3__GPIO2_IO11 0x80000000 /* UART2_EN# */
- + >;
- + };
- +
- + pinctrl_audmux: audmuxgrp {
- + fsl,pins = <
- + MX6QDL_PAD_SD2_DAT0__AUD4_RXD 0x130b0
- + MX6QDL_PAD_SD2_DAT3__AUD4_TXC 0x130b0
- + MX6QDL_PAD_SD2_DAT2__AUD4_TXD 0x110b0
- + MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x130b0
- + >;
- + };
- +
- + pinctrl_enet: enetgrp {
- + fsl,pins = <
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- + >;
- + };
- +
- + pinctrl_gpmi_nand: gpminandgrp {
- + fsl,pins = <
- + MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
- + MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
- + MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
- + MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
- + MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
- + MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
- + MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
- + MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
- + MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
- + MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
- + MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
- + MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
- + MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
- + MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
- + MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
- + MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
- + >;
- + };
- +
- + pinctrl_i2c1: i2c1grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- + MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_i2c2: i2c2grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_i2c3: i2c3grp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
- + MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_pwm4: pwm4grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart1: uart1grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
- + MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart2: uart2grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1
- + MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart5: uart5grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1
- + MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usbotg: usbotggrp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc3: usdhc3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- + >;
- + };
- + };
- +};
- +
- +&ldb {
- + status = "okay";
- +
- + lvds-channel@0 {
- + fsl,data-mapping = "spwg";
- + fsl,data-width = <18>;
- + status = "okay";
- +
- + display-timings {
- + native-mode = <&timing0>;
- + timing0: hsd100pxn1 {
- + clock-frequency = <65000000>;
- + hactive = <1024>;
- + vactive = <768>;
- + hback-porch = <220>;
- + hfront-porch = <40>;
- + vback-porch = <21>;
- + vfront-porch = <7>;
- + hsync-len = <60>;
- + vsync-len = <10>;
- + };
- + };
- + };
- +};
- +
- +&pcie {
- + reset-gpio = <&gpio1 29 0>;
- + status = "okay";
- +};
- +
- +&pwm4 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_pwm4>;
- + status = "okay";
- +};
- +
- +&ssi1 {
- + fsl,mode = "i2s-slave";
- + status = "okay";
- +};
- +
- +&uart1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart1>;
- + status = "okay";
- +};
- +
- +&uart2 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart2>;
- + status = "okay";
- +};
- +
- +&uart5 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart5>;
- + status = "okay";
- +};
- +
- +&usbotg {
- + vbus-supply = <®_usb_otg_vbus>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usbotg>;
- + disable-over-current;
- + status = "okay";
- +};
- +
- +&usbh1 {
- + status = "okay";
- +};
- +
- +&usdhc3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc3>;
- + cd-gpios = <&gpio7 0 0>;
- + vmmc-supply = <®_3p3v>;
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi linux-3.14.35/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi 2015-03-08 14:27:37.397684503 -0500
- @@ -0,0 +1,572 @@
- +/*
- + * Copyright 2013 Gateworks Corporation
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/ {
- + /* these are used by bootloader for disabling nodes */
- + aliases {
- + can0 = &can1;
- + ethernet0 = &fec;
- + ethernet1 = ð1;
- + led0 = &led0;
- + led1 = &led1;
- + led2 = &led2;
- + nand = &gpmi;
- + sky2 = ð1;
- + ssi0 = &ssi1;
- + usb0 = &usbh1;
- + usb1 = &usbotg;
- + usdhc2 = &usdhc3;
- + };
- +
- + chosen {
- + bootargs = "console=ttymxc1,115200";
- + };
- +
- + backlight {
- + compatible = "pwm-backlight";
- + pwms = <&pwm4 0 5000000>;
- + brightness-levels = <0 4 8 16 32 64 128 255>;
- + default-brightness-level = <7>;
- + };
- +
- + leds {
- + compatible = "gpio-leds";
- +
- + led0: user1 {
- + label = "user1";
- + gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */
- + default-state = "on";
- + linux,default-trigger = "heartbeat";
- + };
- +
- + led1: user2 {
- + label = "user2";
- + gpios = <&gpio4 7 0>; /* 103 -> MX6_PANLEDR */
- + default-state = "off";
- + };
- +
- + led2: user3 {
- + label = "user3";
- + gpios = <&gpio4 15 1>; /* 111 -> MX6_LOCLED# */
- + default-state = "off";
- + };
- + };
- +
- + memory {
- + reg = <0x10000000 0x40000000>;
- + };
- +
- + pps {
- + compatible = "pps-gpio";
- + gpios = <&gpio1 26 0>;
- + status = "okay";
- + };
- +
- + regulators {
- + compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + reg_1p0v: regulator@0 {
- + compatible = "regulator-fixed";
- + reg = <0>;
- + regulator-name = "1P0V";
- + regulator-min-microvolt = <1000000>;
- + regulator-max-microvolt = <1000000>;
- + regulator-always-on;
- + };
- +
- + /* remove when pmic 1p8 regulator available */
- + reg_1p8v: regulator@1 {
- + compatible = "regulator-fixed";
- + reg = <1>;
- + regulator-name = "1P8V";
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <1800000>;
- + regulator-always-on;
- + };
- +
- + reg_3p3v: regulator@2 {
- + compatible = "regulator-fixed";
- + reg = <2>;
- + regulator-name = "3P3V";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + reg_usb_h1_vbus: regulator@3 {
- + compatible = "regulator-fixed";
- + reg = <3>;
- + regulator-name = "usb_h1_vbus";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + regulator-always-on;
- + };
- +
- + reg_usb_otg_vbus: regulator@4 {
- + compatible = "regulator-fixed";
- + reg = <4>;
- + regulator-name = "usb_otg_vbus";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + gpio = <&gpio3 22 0>;
- + enable-active-high;
- + };
- + };
- +
- + sound {
- + compatible = "fsl,imx6q-sabrelite-sgtl5000",
- + "fsl,imx-audio-sgtl5000";
- + model = "imx6q-sabrelite-sgtl5000";
- + ssi-controller = <&ssi1>;
- + audio-codec = <&codec>;
- + audio-routing =
- + "MIC_IN", "Mic Jack",
- + "Mic Jack", "Mic Bias",
- + "Headphone Jack", "HP_OUT";
- + mux-int-port = <1>;
- + mux-ext-port = <4>;
- + };
- +};
- +
- +&audmux {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_audmux>;
- + status = "okay";
- +};
- +
- +&can1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_flexcan1>;
- + status = "okay";
- +};
- +
- +&fec {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_enet>;
- + phy-mode = "rgmii";
- + phy-reset-gpios = <&gpio1 30 0>;
- + status = "okay";
- +};
- +
- +&gpmi {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_gpmi_nand>;
- + status = "okay";
- +};
- +
- +&i2c1 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c1>;
- + status = "okay";
- +
- + eeprom1: eeprom@50 {
- + compatible = "atmel,24c02";
- + reg = <0x50>;
- + pagesize = <16>;
- + };
- +
- + eeprom2: eeprom@51 {
- + compatible = "atmel,24c02";
- + reg = <0x51>;
- + pagesize = <16>;
- + };
- +
- + eeprom3: eeprom@52 {
- + compatible = "atmel,24c02";
- + reg = <0x52>;
- + pagesize = <16>;
- + };
- +
- + eeprom4: eeprom@53 {
- + compatible = "atmel,24c02";
- + reg = <0x53>;
- + pagesize = <16>;
- + };
- +
- + gpio: pca9555@23 {
- + compatible = "nxp,pca9555";
- + reg = <0x23>;
- + gpio-controller;
- + #gpio-cells = <2>;
- + };
- +
- + hwmon: gsc@29 {
- + compatible = "gw,gsp";
- + reg = <0x29>;
- + };
- +
- + rtc: ds1672@68 {
- + compatible = "dallas,ds1672";
- + reg = <0x68>;
- + };
- +};
- +
- +&i2c2 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c2>;
- + status = "okay";
- +
- + pciclkgen: si53156@6b {
- + compatible = "sil,si53156";
- + reg = <0x6b>;
- + };
- +
- + pciswitch: pex8606@3f {
- + compatible = "plx,pex8606";
- + reg = <0x3f>;
- + };
- +
- + pmic: ltc3676@3c {
- + compatible = "ltc,ltc3676";
- + reg = <0x3c>;
- +
- + regulators {
- + /* VDD_SOC */
- + sw1_reg: ltc3676__sw1 {
- + regulator-min-microvolt = <1175000>;
- + regulator-max-microvolt = <1175000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + /* VDD_1P8 */
- + sw2_reg: ltc3676__sw2 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <1800000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + /* VDD_ARM */
- + sw3_reg: ltc3676__sw3 {
- + regulator-min-microvolt = <1175000>;
- + regulator-max-microvolt = <1175000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + /* VDD_DDR */
- + sw4_reg: ltc3676__sw4 {
- + regulator-min-microvolt = <1500000>;
- + regulator-max-microvolt = <1500000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + /* VDD_2P5 */
- + ldo2_reg: ltc3676__ldo2 {
- + regulator-min-microvolt = <2500000>;
- + regulator-max-microvolt = <2500000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + /* VDD_1P8 */
- + ldo3_reg: ltc3676__ldo3 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <1800000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + /* VDD_HIGH */
- + ldo4_reg: ltc3676__ldo4 {
- + regulator-min-microvolt = <3000000>;
- + regulator-max-microvolt = <3000000>;
- + };
- + };
- + };
- +};
- +
- +&i2c3 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c3>;
- + status = "okay";
- +
- + accelerometer: fxos8700@1e {
- + compatible = "fsl,fxos8700";
- + reg = <0x1e>;
- + };
- +
- + codec: sgtl5000@0a {
- + compatible = "fsl,sgtl5000";
- + reg = <0x0a>;
- + clocks = <&clks 201>;
- + VDDA-supply = <®_1p8v>;
- + VDDIO-supply = <®_3p3v>;
- + };
- +
- + hdmiin: adv7611@4c {
- + compatible = "adi,adv7611";
- + reg = <0x4c>;
- + };
- +
- + touchscreen: egalax_ts@04 {
- + compatible = "eeti,egalax_ts";
- + reg = <0x04>;
- + interrupt-parent = <&gpio1>;
- + interrupts = <11 2>; /* gpio1_11 active low */
- + wakeup-gpios = <&gpio1 11 0>;
- + };
- +
- + videoout: adv7393@2a {
- + compatible = "adi,adv7393";
- + reg = <0x2a>;
- + };
- +
- + videoin: adv7180@20 {
- + compatible = "adi,adv7180";
- + reg = <0x20>;
- + };
- +};
- +
- +&iomuxc {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hog>;
- +
- + imx6qdl-gw53xx {
- + pinctrl_hog: hoggrp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x80000000 /* PCIE6EXP_DIO0 */
- + MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x80000000 /* PCIE6EXP_DIO1 */
- + MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000 /* OTG_PWR_EN */
- + MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000 /* GPS_SHDN */
- + MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000 /* GPS_PPS */
- + MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x80000000 /* PCIE IRQ */
- + MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* PCIE RST */
- + MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x000130b0 /* AUD4_MCK */
- + MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* CAN_STBY */
- + MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x80000000 /* PMIC_IRQ# */
- + MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x80000000 /* HUB_RST# */
- + MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000 /* PCIE_WDIS# */
- + MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x80000000 /* ACCEL_IRQ# */
- + MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x80000000 /* user1 led */
- + MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x80000000 /* USBOTG_OC# */
- + MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x80000000 /* user2 led */
- + MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x80000000 /* user3 led */
- + MX6QDL_PAD_SD2_CMD__GPIO1_IO11 0x80000000 /* TOUCH_IRQ# */
- + MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x80000000 /* SD3_DET# */
- + >;
- + };
- +
- + pinctrl_audmux: audmuxgrp {
- + fsl,pins = <
- + MX6QDL_PAD_SD2_DAT0__AUD4_RXD 0x130b0
- + MX6QDL_PAD_SD2_DAT3__AUD4_TXC 0x130b0
- + MX6QDL_PAD_SD2_DAT2__AUD4_TXD 0x110b0
- + MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x130b0
- + >;
- + };
- +
- + pinctrl_enet: enetgrp {
- + fsl,pins = <
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- + >;
- + };
- +
- + pinctrl_flexcan1: flexcan1grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x80000000
- + MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x80000000
- + >;
- + };
- +
- + pinctrl_gpmi_nand: gpminandgrp {
- + fsl,pins = <
- + MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
- + MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
- + MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
- + MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
- + MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
- + MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
- + MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
- + MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
- + MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
- + MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
- + MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
- + MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
- + MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
- + MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
- + MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
- + MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
- + >;
- + };
- +
- + pinctrl_i2c1: i2c1grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- + MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_i2c2: i2c2grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_i2c3: i2c3grp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
- + MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_pwm4: pwm4grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart1: uart1grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
- + MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart2: uart2grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1
- + MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart5: uart5grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1
- + MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usbotg: usbotggrp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc3: usdhc3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- + >;
- + };
- + };
- +};
- +
- +&ldb {
- + status = "okay";
- +
- + lvds-channel@1 {
- + fsl,data-mapping = "spwg";
- + fsl,data-width = <18>;
- + status = "okay";
- +
- + display-timings {
- + native-mode = <&timing0>;
- + timing0: hsd100pxn1 {
- + clock-frequency = <65000000>;
- + hactive = <1024>;
- + vactive = <768>;
- + hback-porch = <220>;
- + hfront-porch = <40>;
- + vback-porch = <21>;
- + vfront-porch = <7>;
- + hsync-len = <60>;
- + vsync-len = <10>;
- + };
- + };
- + };
- +};
- +
- +&pcie {
- + reset-gpio = <&gpio1 29 0>;
- + status = "okay";
- +
- + eth1: sky2@8 { /* MAC/PHY on bus 8 */
- + compatible = "marvell,sky2";
- + };
- +};
- +
- +&pwm4 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_pwm4>;
- + status = "okay";
- +};
- +
- +&ssi1 {
- + fsl,mode = "i2s-slave";
- + status = "okay";
- +};
- +
- +&uart1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart1>;
- + status = "okay";
- +};
- +
- +&uart2 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart2>;
- + status = "okay";
- +};
- +
- +&uart5 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart5>;
- + status = "okay";
- +};
- +
- +&usbotg {
- + vbus-supply = <®_usb_otg_vbus>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usbotg>;
- + disable-over-current;
- + status = "okay";
- +};
- +
- +&usbh1 {
- + vbus-supply = <®_usb_h1_vbus>;
- + status = "okay";
- +};
- +
- +&usdhc3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc3>;
- + cd-gpios = <&gpio7 0 0>;
- + vmmc-supply = <®_3p3v>;
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi linux-3.14.35/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi 2015-03-08 14:27:37.397684503 -0500
- @@ -0,0 +1,599 @@
- +/*
- + * Copyright 2013 Gateworks Corporation
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/ {
- + /* these are used by bootloader for disabling nodes */
- + aliases {
- + can0 = &can1;
- + ethernet0 = &fec;
- + ethernet1 = ð1;
- + led0 = &led0;
- + led1 = &led1;
- + led2 = &led2;
- + nand = &gpmi;
- + sky2 = ð1;
- + ssi0 = &ssi1;
- + usb0 = &usbh1;
- + usb1 = &usbotg;
- + usdhc2 = &usdhc3;
- + };
- +
- + chosen {
- + bootargs = "console=ttymxc1,115200";
- + };
- +
- + backlight {
- + compatible = "pwm-backlight";
- + pwms = <&pwm4 0 5000000>;
- + brightness-levels = <0 4 8 16 32 64 128 255>;
- + default-brightness-level = <7>;
- + };
- +
- + leds {
- + compatible = "gpio-leds";
- +
- + led0: user1 {
- + label = "user1";
- + gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */
- + default-state = "on";
- + linux,default-trigger = "heartbeat";
- + };
- +
- + led1: user2 {
- + label = "user2";
- + gpios = <&gpio4 7 0>; /* 103 -> MX6_PANLEDR */
- + default-state = "off";
- + };
- +
- + led2: user3 {
- + label = "user3";
- + gpios = <&gpio4 15 1>; /* 111 -> MX6_LOCLED# */
- + default-state = "off";
- + };
- + };
- +
- + memory {
- + reg = <0x10000000 0x40000000>;
- + };
- +
- + pps {
- + compatible = "pps-gpio";
- + gpios = <&gpio1 26 0>;
- + status = "okay";
- + };
- +
- + regulators {
- + compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + reg_1p0v: regulator@0 {
- + compatible = "regulator-fixed";
- + reg = <0>;
- + regulator-name = "1P0V";
- + regulator-min-microvolt = <1000000>;
- + regulator-max-microvolt = <1000000>;
- + regulator-always-on;
- + };
- +
- + reg_3p3v: regulator@1 {
- + compatible = "regulator-fixed";
- + reg = <1>;
- + regulator-name = "3P3V";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + reg_usb_h1_vbus: regulator@2 {
- + compatible = "regulator-fixed";
- + reg = <2>;
- + regulator-name = "usb_h1_vbus";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + regulator-always-on;
- + };
- +
- + reg_usb_otg_vbus: regulator@3 {
- + compatible = "regulator-fixed";
- + reg = <3>;
- + regulator-name = "usb_otg_vbus";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + gpio = <&gpio3 22 0>;
- + enable-active-high;
- + };
- + };
- +
- + sound {
- + compatible = "fsl,imx6q-sabrelite-sgtl5000",
- + "fsl,imx-audio-sgtl5000";
- + model = "imx6q-sabrelite-sgtl5000";
- + ssi-controller = <&ssi1>;
- + audio-codec = <&codec>;
- + audio-routing =
- + "MIC_IN", "Mic Jack",
- + "Mic Jack", "Mic Bias",
- + "Headphone Jack", "HP_OUT";
- + mux-int-port = <1>;
- + mux-ext-port = <4>;
- + };
- +};
- +
- +&audmux {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_audmux>; /* AUD4<->sgtl5000 */
- + status = "okay";
- +};
- +
- +&can1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_flexcan1>;
- + status = "okay";
- +};
- +
- +&fec {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_enet>;
- + phy-mode = "rgmii";
- + phy-reset-gpios = <&gpio1 30 0>;
- + status = "okay";
- +};
- +
- +&gpmi {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_gpmi_nand>;
- + status = "okay";
- +};
- +
- +&i2c1 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c1>;
- + status = "okay";
- +
- + eeprom1: eeprom@50 {
- + compatible = "atmel,24c02";
- + reg = <0x50>;
- + pagesize = <16>;
- + };
- +
- + eeprom2: eeprom@51 {
- + compatible = "atmel,24c02";
- + reg = <0x51>;
- + pagesize = <16>;
- + };
- +
- + eeprom3: eeprom@52 {
- + compatible = "atmel,24c02";
- + reg = <0x52>;
- + pagesize = <16>;
- + };
- +
- + eeprom4: eeprom@53 {
- + compatible = "atmel,24c02";
- + reg = <0x53>;
- + pagesize = <16>;
- + };
- +
- + gpio: pca9555@23 {
- + compatible = "nxp,pca9555";
- + reg = <0x23>;
- + gpio-controller;
- + #gpio-cells = <2>;
- + };
- +
- + hwmon: gsc@29 {
- + compatible = "gw,gsp";
- + reg = <0x29>;
- + };
- +
- + rtc: ds1672@68 {
- + compatible = "dallas,ds1672";
- + reg = <0x68>;
- + };
- +};
- +
- +&i2c2 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c2>;
- + status = "okay";
- +
- + pmic: pfuze100@08 {
- + compatible = "fsl,pfuze100";
- + reg = <0x08>;
- +
- + regulators {
- + sw1a_reg: sw1ab {
- + regulator-min-microvolt = <300000>;
- + regulator-max-microvolt = <1875000>;
- + regulator-boot-on;
- + regulator-always-on;
- + regulator-ramp-delay = <6250>;
- + };
- +
- + sw1c_reg: sw1c {
- + regulator-min-microvolt = <300000>;
- + regulator-max-microvolt = <1875000>;
- + regulator-boot-on;
- + regulator-always-on;
- + regulator-ramp-delay = <6250>;
- + };
- +
- + sw2_reg: sw2 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <3950000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw3a_reg: sw3a {
- + regulator-min-microvolt = <400000>;
- + regulator-max-microvolt = <1975000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw3b_reg: sw3b {
- + regulator-min-microvolt = <400000>;
- + regulator-max-microvolt = <1975000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw4_reg: sw4 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <3300000>;
- + };
- +
- + swbst_reg: swbst {
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5150000>;
- + };
- +
- + snvs_reg: vsnvs {
- + regulator-min-microvolt = <1000000>;
- + regulator-max-microvolt = <3000000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + vref_reg: vrefddr {
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + vgen1_reg: vgen1 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <1550000>;
- + };
- +
- + vgen2_reg: vgen2 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <1550000>;
- + };
- +
- + vgen3_reg: vgen3 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + };
- +
- + vgen4_reg: vgen4 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vgen5_reg: vgen5 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vgen6_reg: vgen6 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- + };
- + };
- +
- + pciswitch: pex8609@3f {
- + compatible = "plx,pex8609";
- + reg = <0x3f>;
- + };
- +
- + pciclkgen: si52147@6b {
- + compatible = "sil,si52147";
- + reg = <0x6b>;
- + };
- +};
- +
- +&i2c3 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c3>;
- + status = "okay";
- +
- + accelerometer: fxos8700@1e {
- + compatible = "fsl,fxos8700";
- + reg = <0x1e>;
- + };
- +
- + codec: sgtl5000@0a {
- + compatible = "fsl,sgtl5000";
- + reg = <0x0a>;
- + clocks = <&clks 201>;
- + VDDA-supply = <&sw4_reg>;
- + VDDIO-supply = <®_3p3v>;
- + };
- +
- + hdmiin: adv7611@4c {
- + compatible = "adi,adv7611";
- + reg = <0x4c>;
- + };
- +
- + touchscreen: egalax_ts@04 {
- + compatible = "eeti,egalax_ts";
- + reg = <0x04>;
- + interrupt-parent = <&gpio7>;
- + interrupts = <12 2>; /* gpio7_12 active low */
- + wakeup-gpios = <&gpio7 12 0>;
- + };
- +
- + videoout: adv7393@2a {
- + compatible = "adi,adv7393";
- + reg = <0x2a>;
- + };
- +
- + videoin: adv7180@20 {
- + compatible = "adi,adv7180";
- + reg = <0x20>;
- + };
- +};
- +
- +&iomuxc {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hog>;
- +
- + imx6qdl-gw54xx {
- + pinctrl_hog: hoggrp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000 /* OTG_PWR_EN */
- + MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x80000000 /* SPINOR_CS0# */
- + MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000 /* GPS_PPS */
- + MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x80000000 /* PCIE IRQ */
- + MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* PCIE RST */
- + MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x000130b0 /* AUD4_MCK */
- + MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* CAN_STBY */
- + MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000 /* TOUCH_IRQ# */
- + MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x80000000 /* user1 led */
- + MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x80000000 /* user2 led */
- + MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x80000000 /* user3 led */
- + MX6QDL_PAD_SD1_DAT0__GPIO1_IO16 0x80000000 /* USBHUB_RST# */
- + MX6QDL_PAD_SD1_DAT3__GPIO1_IO21 0x80000000 /* MIPI_DIO */
- + >;
- + };
- +
- + pinctrl_audmux: audmuxgrp {
- + fsl,pins = <
- + MX6QDL_PAD_SD2_DAT0__AUD4_RXD 0x130b0
- + MX6QDL_PAD_SD2_DAT3__AUD4_TXC 0x130b0
- + MX6QDL_PAD_SD2_DAT2__AUD4_TXD 0x110b0
- + MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x130b0
- + >;
- + };
- +
- + pinctrl_enet: enetgrp {
- + fsl,pins = <
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- + >;
- + };
- +
- + pinctrl_flexcan1: flexcan1grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x80000000
- + MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x80000000
- + >;
- + };
- +
- + pinctrl_gpmi_nand: gpminandgrp {
- + fsl,pins = <
- + MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
- + MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
- + MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
- + MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
- + MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
- + MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
- + MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
- + MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
- + MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
- + MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
- + MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
- + MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
- + MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
- + MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
- + MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
- + MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
- + >;
- + };
- +
- + pinctrl_i2c1: i2c1grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- + MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_i2c2: i2c2grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_i2c3: i2c3grp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
- + MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_pwm4: pwm4grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart1: uart1grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
- + MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart2: uart2grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1
- + MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart5: uart5grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1
- + MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usbotg: usbotggrp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc3: usdhc3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- + >;
- + };
- + };
- +};
- +
- +&ldb {
- + status = "okay";
- +
- + lvds-channel@1 {
- + fsl,data-mapping = "spwg";
- + fsl,data-width = <18>;
- + status = "okay";
- +
- + display-timings {
- + native-mode = <&timing0>;
- + timing0: hsd100pxn1 {
- + clock-frequency = <65000000>;
- + hactive = <1024>;
- + vactive = <768>;
- + hback-porch = <220>;
- + hfront-porch = <40>;
- + vback-porch = <21>;
- + vfront-porch = <7>;
- + hsync-len = <60>;
- + vsync-len = <10>;
- + };
- + };
- + };
- +};
- +
- +&pcie {
- + reset-gpio = <&gpio1 29 0>;
- + status = "okay";
- +
- + eth1: sky2@8 { /* MAC/PHY on bus 8 */
- + compatible = "marvell,sky2";
- + };
- +};
- +
- +&pwm4 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_pwm4>;
- + status = "okay";
- +};
- +
- +&ssi1 {
- + fsl,mode = "i2s-slave";
- + status = "okay";
- +};
- +
- +&ssi2 {
- + fsl,mode = "i2s-slave";
- + status = "okay";
- +};
- +
- +&uart1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart1>;
- + status = "okay";
- +};
- +
- +&uart2 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart2>;
- + status = "okay";
- +};
- +
- +&uart5 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart5>;
- + status = "okay";
- +};
- +
- +&usbotg {
- + vbus-supply = <®_usb_otg_vbus>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usbotg>;
- + disable-over-current;
- + status = "okay";
- +};
- +
- +&usbh1 {
- + vbus-supply = <®_usb_h1_vbus>;
- + status = "okay";
- +};
- +
- +&usdhc3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc3>;
- + cd-gpios = <&gpio7 0 0>;
- + vmmc-supply = <®_3p3v>;
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi linux-3.14.35/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi 2015-03-08 14:27:37.397684503 -0500
- @@ -0,0 +1,367 @@
- +/*
- + * Copyright (C) 2013,2014 Russell King
- + */
- +#include "imx6qdl-microsom.dtsi"
- +#include "imx6qdl-microsom-ar8035.dtsi"
- +
- +/ {
- + chosen {
- + bootargs = "quiet console=ttymxc0,115200 root=/dev/mmcblk0p2 rw";
- + };
- +
- + aliases {
- + mxcfb0 = &mxcfb1;
- + };
- +
- + ir_recv: ir-receiver {
- + compatible = "gpio-ir-receiver";
- + gpios = <&gpio3 5 1>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hummingboard_gpio3_5>;
- + linux,rc-map-name = "rc-rc6-mce";
- + };
- +
- + regulators {
- + compatible = "simple-bus";
- +
- + reg_3p3v: 3p3v {
- + compatible = "regulator-fixed";
- + regulator-name = "3P3V";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + reg_usbh1_vbus: usb-h1-vbus {
- + compatible = "regulator-fixed";
- + enable-active-high;
- + gpio = <&gpio1 0 0>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hummingboard_usbh1_vbus>;
- + regulator-name = "usb_h1_vbus";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + };
- +
- + reg_usbotg_vbus: usb-otg-vbus {
- + compatible = "regulator-fixed";
- + enable-active-high;
- + gpio = <&gpio3 22 0>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hummingboard_usbotg_vbus>;
- + regulator-name = "usb_otg_vbus";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + };
- + };
- +
- + sound-sgtl5000 {
- + audio-codec = <&sgtl5000>;
- + audio-routing =
- + "MIC_IN", "Mic Jack",
- + "Mic Jack", "Mic Bias",
- + "Headphone Jack", "HP_OUT";
- + compatible = "fsl,imx-audio-sgtl5000";
- + model = "On-board Codec";
- + mux-ext-port = <5>;
- + mux-int-port = <1>;
- + ssi-controller = <&ssi1>;
- + };
- +
- + sound-spdif {
- + compatible = "fsl,imx-audio-spdif";
- + model = "imx-spdif";
- + spdif-controller = <&spdif>;
- + spdif-out;
- + };
- +
- + sound-hdmi {
- + compatible = "fsl,imx6q-audio-hdmi",
- + "fsl,imx-audio-hdmi";
- + model = "imx-audio-hdmi";
- + hdmi-controller = <&hdmi_audio>;
- + };
- +
- + mxcfb1: fb@0 {
- + compatible = "fsl,mxc_sdc_fb";
- + disp_dev = "hdmi";
- + interface_pix_fmt = "RGB24";
- + mode_str ="1920x1080M@60";
- + default_bpp = <32>;
- + int_clk = <0>;
- + late_init = <0>;
- + status = "okay";
- + };
- +};
- +
- +&hdmi_core {
- + ipu_id = <0>;
- + disp_id = <0>;
- + status = "okay";
- +};
- +
- +&hdmi_video {
- + fsl,phy_reg_vlev = <0x0294>;
- + fsl,phy_reg_cksymtx = <0x800d>;
- + status = "okay";
- +};
- +
- +&hdmi_audio {
- + status = "okay";
- +};
- +
- +&hdmi_cec {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hummingboard_hdmi>;
- + status = "okay";
- +};
- +
- +&i2c2 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hummingboard_i2c2>;
- + status = "okay";
- +
- + ddc: imx6_hdmi_i2c@50 {
- + compatible = "fsl,imx6-hdmi-i2c";
- + reg = <0x50>;
- + };
- +};
- +
- +&audmux {
- + status = "okay";
- +};
- +
- +&can1 {
- + pinctrl-names = "default";
- + status = "okay";
- +};
- +
- +&i2c1 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hummingboard_i2c1>;
- + status = "okay";
- +
- + /* Pro model */
- + rtc: pcf8523@68 {
- + compatible = "nxp,pcf8523";
- + reg = <0x68>;
- + };
- +
- + /* Pro model */
- + sgtl5000: sgtl5000@0a {
- + clocks = <&clks 201>;
- + compatible = "fsl,sgtl5000";
- + pinctrl-0 = <&pinctrl_hummingboard_sgtl5000>;
- + pinctrl-names = "default";
- + reg = <0x0a>;
- + VDDA-supply = <®_3p3v>;
- + VDDIO-supply = <®_3p3v>;
- + };
- +};
- +
- +&iomuxc {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hog>;
- + hummingboard {
- + pinctrl_hog: hoggrp {
- + fsl,pins = <
- + /*
- + * 26 pin header GPIO description. The pins
- + * numbering as following -
- + * GPIO number | GPIO (bank,num) | PIN number
- + * ------------+-----------------+------------
- + * gpio1 | (1,1) | IO7
- + * gpio73 | (3,9) | IO11
- + * gpio72 | (3,8) | IO12
- + * gpio71 | (3,7) | IO13
- + * gpio70 | (3,6) | IO15
- + * gpio194 | (7,2) | IO16
- + * gpio195 | (7,3) | IO18
- + * gpio67 | (3,3) | IO22
- + *
- + * Notice the gpioX and GPIO (Y,Z) mapping forumla :
- + * X = (Y-1) * 32 + Z
- + */
- + MX6QDL_PAD_GPIO_1__GPIO1_IO01 0x400130b1
- + MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x400130b1
- + MX6QDL_PAD_EIM_DA8__GPIO3_IO08 0x400130b1
- + MX6QDL_PAD_EIM_DA7__GPIO3_IO07 0x400130b1
- + MX6QDL_PAD_EIM_DA6__GPIO3_IO06 0x400130b1
- + MX6QDL_PAD_SD3_CMD__GPIO7_IO02 0x400130b1
- + MX6QDL_PAD_SD3_CLK__GPIO7_IO03 0x400130b1
- + MX6QDL_PAD_EIM_DA3__GPIO3_IO03 0x400130b1
- + >;
- + };
- +
- + pinctrl_hummingboard_gpio3_5: hummingboard-gpio3_5 {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_DA5__GPIO3_IO05 0x80000000
- + >;
- + };
- +
- + pinctrl_hummingboard_hdmi: hummingboard-hdmi {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
- + >;
- + };
- +
- + pinctrl_hummingboard_i2c1: hummingboard-i2c1 {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- + MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_hummingboard_i2c2: hummingboard-i2c2 {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_hummingboard_sgtl5000: hummingboard-sgtl5000 {
- + fsl,pins = <
- + MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x130b0 /*brk*/
- + MX6QDL_PAD_KEY_COL0__AUD5_TXC 0x130b0 /*ok*/
- + MX6QDL_PAD_KEY_ROW0__AUD5_TXD 0x110b0 /*brk*/
- + MX6QDL_PAD_KEY_COL1__AUD5_TXFS 0x130b0 /*ok*/
- + MX6QDL_PAD_GPIO_5__CCM_CLKO1 0x130b0
- + >;
- + };
- +
- + pinctrl_hummingboard_spdif: hummingboard-spdif {
- + fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
- + };
- +
- + pinctrl_hummingboard_usbh1_vbus: hummingboard-usbh1-vbus {
- + fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0>;
- + };
- +
- + pinctrl_hummingboard_usbotg_id: hummingboard-usbotg-id {
- + /*
- + * Similar to pinctrl_usbotg_2, but we want it
- + * pulled down for a fixed host connection.
- + */
- + fsl,pins = <MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x13059>;
- + };
- +
- + pinctrl_hummingboard_usbotg_vbus: hummingboard-usbotg-vbus {
- + fsl,pins = <MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0>;
- + };
- +
- + pinctrl_hummingboard_usdhc2_aux: hummingboard-usdhc2-aux {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071
- + >;
- + };
- +
- + pinctrl_hummingboard_usdhc2: hummingboard-usdhc2 {
- + fsl,pins = <
- + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
- + >;
- + };
- +
- + pinctrl_hummingboard_pcie_reset: hummingboard-pcie-reset {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_DA4__GPIO3_IO04 0x80000000
- + >;
- + };
- +
- + pinctrl_pwm1: pwm1grp {
- + fsl,pins = <
- + MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b1
- + >;
- + };
- +
- + };
- +};
- +
- +&spdif {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hummingboard_spdif>;
- + clocks = <&clks 197>, <&clks 0>,
- + <&clks 197>, <&clks 0>,
- + <&clks 0>, <&clks 0>,
- + <&clks 0>, <&clks 0>,
- + <&clks 0>;
- + clock-names = "core", "rxtx0",
- + "rxtx1", "rxtx2",
- + "rxtx3", "rxtx4",
- + "rxtx5", "rxtx6",
- + "rxtx7";
- + status = "okay";
- +};
- +
- +&ssi1 {
- + fsl,mode = "i2s-slave";
- + status = "okay";
- +};
- +
- +&usbh1 {
- + disable-over-current;
- + vbus-supply = <®_usbh1_vbus>;
- + status = "okay";
- +};
- +
- +&usbotg {
- + disable-over-current;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hummingboard_usbotg_id>;
- + vbus-supply = <®_usbotg_vbus>;
- + status = "okay";
- +};
- +
- +&usdhc2 {
- + pinctrl-names = "default";
- + pinctrl-0 = <
- + &pinctrl_hummingboard_usdhc2_aux
- + &pinctrl_hummingboard_usdhc2
- + >;
- + vmmc-supply = <®_3p3v>;
- + cd-gpios = <&gpio1 4 0>;
- + status = "okay";
- +};
- +
- +&gpc {
- + fsl,cpu_pupscr_sw2iso = <0xf>;
- + fsl,cpu_pupscr_sw = <0xf>;
- + fsl,cpu_pdnscr_iso2sw = <0x1>;
- + fsl,cpu_pdnscr_iso = <0x1>;
- +};
- +
- +&pcie {
- + pinctrl-names = "default";
- + pinctrl-0 = <
- + &pinctrl_hummingboard_pcie_reset
- + >;
- + reset-gpio = <&gpio3 4 0>;
- + status = "okay";
- + no-msi;
- +};
- +
- +&pwm1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_pwm1>;
- + status = "okay";
- +};
- +
- +&pwm2 {
- + pinctrl-names = "default";
- + status = "okay";
- +};
- +
- +&pwm3 {
- + status = "disabled";
- +};
- +
- +&pwm4 {
- + status = "disabled";
- +};
- +
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi linux-3.14.35/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi 2015-03-08 14:27:37.397684503 -0500
- @@ -17,7 +17,7 @@
- enet {
- pinctrl_microsom_enet_ar8035: microsom-enet-ar8035 {
- fsl,pins = <
- - MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b8b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- /* AR8035 reset */
- MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x130b0
- @@ -26,25 +26,25 @@
- /* GPIO16 -> AR8035 25MHz */
- MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0xc0000000
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x80000000
- - MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- - MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- - MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- - MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- - MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
- /* AR8035 CLK_25M --> ENET_REF_CLK (V22) */
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x0a0b1
- /* AR8035 pin strapping: IO voltage: pull up */
- - MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- /* AR8035 pin strapping: PHYADDR#0: pull down */
- - MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x130b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x13030
- /* AR8035 pin strapping: PHYADDR#1: pull down */
- - MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x130b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x13030
- /* AR8035 pin strapping: MODE#1: pull up */
- - MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- /* AR8035 pin strapping: MODE#3: pull up */
- - MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- /* AR8035 pin strapping: MODE#0: pull down */
- - MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x130b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x13030
-
- /*
- * As the RMII pins are also connected to RGMII
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-microsom.dtsi linux-3.14.35/arch/arm/boot/dts/imx6qdl-microsom.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-microsom.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6qdl-microsom.dtsi 2015-03-08 14:27:37.397684503 -0500
- @@ -1,9 +1,69 @@
- /*
- * Copyright (C) 2013,2014 Russell King
- */
- +#include <dt-bindings/gpio/gpio.h>
- +/ {
- + regulators {
- + compatible = "simple-bus";
- +
- + reg_brcm_osc: brcm-osc-reg {
- + compatible = "regulator-fixed";
- + enable-active-high;
- + gpio = <&gpio5 5 0>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_microsom_brcm_osc_reg>;
- + regulator-name = "brcm_osc_reg";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + regulator-boot-on;
- + };
- +
- + reg_brcm: brcm-reg {
- + compatible = "regulator-fixed";
- + enable-active-high;
- + gpio = <&gpio3 19 0>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_microsom_brcm_reg>;
- + regulator-name = "brcm_reg";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + startup-delay-us = <200000>;
- + };
- + };
- +};
-
- &iomuxc {
- microsom {
- + pinctrl_microsom_brcm_bt: microsom-brcm-bt {
- + fsl,pins = <
- + MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00 0x40013070
- + MX6QDL_PAD_CSI0_DAT15__GPIO6_IO01 0x40013070
- + MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04 0x40013070
- + >;
- + };
- +
- + pinctrl_microsom_brcm_osc_reg: microsom-brcm-osc-reg {
- + fsl,pins = <
- + MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05 0x40013070
- + >;
- + };
- +
- + pinctrl_microsom_brcm_reg: microsom-brcm-reg {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x40013070
- + >;
- + };
- +
- + pinctrl_microsom_brcm_wifi: microsom-brcm-wifi {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_8__XTALOSC_REF_CLK_32K 0x1b0b0
- + MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x40013070
- + MX6QDL_PAD_CSI0_DAT8__GPIO5_IO26 0x40013070
- + MX6QDL_PAD_CSI0_DAT9__GPIO5_IO27 0x40013070
- + >;
- + };
- +
- pinctrl_microsom_uart1: microsom-uart1 {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
- @@ -11,12 +71,24 @@
- >;
- };
-
- - pinctrl_microsom_usbotg: microsom-usbotg {
- - /*
- - * Similar to pinctrl_usbotg_2, but we want it
- - * pulled down for a fixed host connection.
- - */
- - fsl,pins = <MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059>;
- + pinctrl_microsom_uart4_1: microsom-uart4 {
- + fsl,pins = <
- + MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
- + MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
- + MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1
- + MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1
- + >;
- + };
- +
- + pinctrl_microsom_usdhc1: microsom-usdhc1 {
- + fsl,pins = <
- + MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059
- + MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059
- + MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
- + MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
- + MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
- + MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
- + >;
- };
- };
- };
- @@ -27,7 +99,23 @@
- status = "okay";
- };
-
- -&usbotg {
- +/* UART4 - Connected to optional BRCM Wifi/BT/FM */
- +&uart4 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_microsom_brcm_bt &pinctrl_microsom_uart4_1>;
- + fsl,uart-has-rtscts;
- + status = "okay";
- +};
- +
- +/* USDHC1 - Connected to optional BRCM Wifi/BT/FM */
- +&usdhc1 {
- + card-external-vcc-supply = <®_brcm>;
- + card-reset-gpios = <&gpio5 26 GPIO_ACTIVE_LOW>, <&gpio6 0 GPIO_ACTIVE_LOW>;
- + keep-power-in-suspend;
- + non-removable;
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_microsom_usbotg>;
- + pinctrl-0 = <&pinctrl_microsom_brcm_wifi &pinctrl_microsom_usdhc1>;
- + vmmc-supply = <®_brcm>;
- + status = "okay";
- };
- +
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi linux-3.14.35/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi 2015-03-08 14:27:37.397684503 -0500
- @@ -0,0 +1,426 @@
- +/*
- + * Copyright 2013 Boundary Devices, Inc.
- + * Copyright 2011 Freescale Semiconductor, Inc.
- + * Copyright 2011 Linaro Ltd.
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +#include <dt-bindings/gpio/gpio.h>
- +#include <dt-bindings/input/input.h>
- +
- +/ {
- + chosen {
- + stdout-path = &uart2;
- + };
- +
- + memory {
- + reg = <0x10000000 0x40000000>;
- + };
- +
- + regulators {
- + compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + reg_2p5v: regulator@0 {
- + compatible = "regulator-fixed";
- + reg = <0>;
- + regulator-name = "2P5V";
- + regulator-min-microvolt = <2500000>;
- + regulator-max-microvolt = <2500000>;
- + regulator-always-on;
- + };
- +
- + reg_3p3v: regulator@1 {
- + compatible = "regulator-fixed";
- + reg = <1>;
- + regulator-name = "3P3V";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + reg_usb_otg_vbus: regulator@2 {
- + compatible = "regulator-fixed";
- + reg = <2>;
- + regulator-name = "usb_otg_vbus";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + gpio = <&gpio3 22 0>;
- + enable-active-high;
- + };
- + };
- +
- + gpio-keys {
- + compatible = "gpio-keys";
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_gpio_keys>;
- +
- + power {
- + label = "Power Button";
- + gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
- + linux,code = <KEY_POWER>;
- + gpio-key,wakeup;
- + };
- +
- + menu {
- + label = "Menu";
- + gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
- + linux,code = <KEY_MENU>;
- + };
- +
- + home {
- + label = "Home";
- + gpios = <&gpio2 4 GPIO_ACTIVE_LOW>;
- + linux,code = <KEY_HOME>;
- + };
- +
- + back {
- + label = "Back";
- + gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
- + linux,code = <KEY_BACK>;
- + };
- +
- + volume-up {
- + label = "Volume Up";
- + gpios = <&gpio7 13 GPIO_ACTIVE_LOW>;
- + linux,code = <KEY_VOLUMEUP>;
- + };
- +
- + volume-down {
- + label = "Volume Down";
- + gpios = <&gpio4 5 GPIO_ACTIVE_LOW>;
- + linux,code = <KEY_VOLUMEDOWN>;
- + };
- + };
- +
- + sound {
- + compatible = "fsl,imx6q-nitrogen6x-sgtl5000",
- + "fsl,imx-audio-sgtl5000";
- + model = "imx6q-nitrogen6x-sgtl5000";
- + ssi-controller = <&ssi1>;
- + audio-codec = <&codec>;
- + audio-routing =
- + "MIC_IN", "Mic Jack",
- + "Mic Jack", "Mic Bias",
- + "Headphone Jack", "HP_OUT";
- + mux-int-port = <1>;
- + mux-ext-port = <3>;
- + };
- +
- + backlight_lcd {
- + compatible = "pwm-backlight";
- + pwms = <&pwm1 0 5000000>;
- + brightness-levels = <0 4 8 16 32 64 128 255>;
- + default-brightness-level = <7>;
- + power-supply = <®_3p3v>;
- + status = "okay";
- + };
- +
- + backlight_lvds {
- + compatible = "pwm-backlight";
- + pwms = <&pwm4 0 5000000>;
- + brightness-levels = <0 4 8 16 32 64 128 255>;
- + default-brightness-level = <7>;
- + power-supply = <®_3p3v>;
- + status = "okay";
- + };
- +};
- +
- +&audmux {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_audmux>;
- + status = "okay";
- +};
- +
- +&ecspi1 {
- + fsl,spi-num-chipselects = <1>;
- + cs-gpios = <&gpio3 19 0>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_ecspi1>;
- + status = "okay";
- +
- + flash: m25p80@0 {
- + compatible = "sst,sst25vf016b";
- + spi-max-frequency = <20000000>;
- + reg = <0>;
- + };
- +};
- +
- +&fec {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_enet>;
- + phy-mode = "rgmii";
- + phy-reset-gpios = <&gpio1 27 0>;
- + txen-skew-ps = <0>;
- + txc-skew-ps = <3000>;
- + rxdv-skew-ps = <0>;
- + rxc-skew-ps = <3000>;
- + rxd0-skew-ps = <0>;
- + rxd1-skew-ps = <0>;
- + rxd2-skew-ps = <0>;
- + rxd3-skew-ps = <0>;
- + txd0-skew-ps = <0>;
- + txd1-skew-ps = <0>;
- + txd2-skew-ps = <0>;
- + txd3-skew-ps = <0>;
- + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
- + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
- + status = "okay";
- +};
- +
- +&i2c1 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c1>;
- + status = "okay";
- +
- + codec: sgtl5000@0a {
- + compatible = "fsl,sgtl5000";
- + reg = <0x0a>;
- + clocks = <&clks 201>;
- + VDDA-supply = <®_2p5v>;
- + VDDIO-supply = <®_3p3v>;
- + };
- +};
- +
- +&iomuxc {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hog>;
- +
- + imx6q-nitrogen6x {
- + pinctrl_hog: hoggrp {
- + fsl,pins = <
- + /* SGTL5000 sys_mclk */
- + MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x030b0
- + >;
- + };
- +
- + pinctrl_audmux: audmuxgrp {
- + fsl,pins = <
- + MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
- + MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
- + MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
- + MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
- + >;
- + };
- +
- + pinctrl_ecspi1: ecspi1grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
- + MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
- + MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
- + MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x000b1 /* CS */
- + >;
- + };
- +
- + pinctrl_enet: enetgrp {
- + fsl,pins = <
- + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x100b0
- + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x100b0
- + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x100b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x100b0
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x100b0
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x100b0
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x100b0
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x100b0
- + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x100b0
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- + /* Phy reset */
- + MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x000b0
- + MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
- + >;
- + };
- +
- + pinctrl_gpio_keys: gpio_keysgrp {
- + fsl,pins = <
- + /* Power Button */
- + MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0
- + /* Menu Button */
- + MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0
- + /* Home Button */
- + MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x1b0b0
- + /* Back Button */
- + MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
- + /* Volume Up Button */
- + MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x1b0b0
- + /* Volume Down Button */
- + MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x1b0b0
- + >;
- + };
- +
- + pinctrl_i2c1: i2c1grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- + MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_pwm1: pwm1grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
- + >;
- + };
- +
- + pinctrl_pwm3: pwm3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x1b0b1
- + >;
- + };
- +
- + pinctrl_pwm4: pwm4grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart1: uart1grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
- + MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart2: uart2grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
- + MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usbotg: usbotggrp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- + MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
- + /* power enable, high active */
- + MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x000b0
- + >;
- + };
- +
- + pinctrl_usdhc3: usdhc3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- + MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0 /* CD */
- + >;
- + };
- +
- + pinctrl_usdhc4: usdhc4grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- + MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- + MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- + MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- + MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- + MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- + MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x1b0b0 /* CD */
- + >;
- + };
- + };
- +};
- +
- +&ldb {
- + status = "okay";
- +
- + lvds-channel@0 {
- + fsl,data-mapping = "spwg";
- + fsl,data-width = <18>;
- + status = "okay";
- +
- + display-timings {
- + native-mode = <&timing0>;
- + timing0: hsd100pxn1 {
- + clock-frequency = <65000000>;
- + hactive = <1024>;
- + vactive = <768>;
- + hback-porch = <220>;
- + hfront-porch = <40>;
- + vback-porch = <21>;
- + vfront-porch = <7>;
- + hsync-len = <60>;
- + vsync-len = <10>;
- + };
- + };
- + };
- +};
- +
- +&pcie {
- + status = "okay";
- +};
- +
- +&pwm1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_pwm1>;
- + status = "okay";
- +};
- +
- +&pwm3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_pwm3>;
- + status = "okay";
- +};
- +
- +&pwm4 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_pwm4>;
- + status = "okay";
- +};
- +
- +&ssi1 {
- + fsl,mode = "i2s-slave";
- + status = "okay";
- +};
- +
- +&uart1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart1>;
- + status = "okay";
- +};
- +
- +&uart2 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart2>;
- + status = "okay";
- +};
- +
- +&usbh1 {
- + status = "okay";
- +};
- +
- +&usbotg {
- + vbus-supply = <®_usb_otg_vbus>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usbotg>;
- + disable-over-current;
- + status = "okay";
- +};
- +
- +&usdhc3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc3>;
- + cd-gpios = <&gpio7 0 0>;
- + vmmc-supply = <®_3p3v>;
- + status = "okay";
- +};
- +
- +&usdhc4 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc4>;
- + cd-gpios = <&gpio2 6 0>;
- + vmmc-supply = <®_3p3v>;
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi linux-3.14.35/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi 2015-03-08 14:27:37.397684503 -0500
- @@ -0,0 +1,98 @@
- +/*
- + * Copyright 2013 Christian Hemp, Phytec Messtechnik GmbH
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/ {
- + chosen {
- + linux,stdout-path = &uart4;
- + };
- +};
- +
- +&fec {
- + status = "okay";
- +};
- +
- +&gpmi {
- + status = "okay";
- +};
- +
- +&i2c2 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c2>;
- + clock-frequency = <100000>;
- + status = "okay";
- +
- + tlv320@18 {
- + compatible = "ti,tlv320aic3x";
- + reg = <0x18>;
- + };
- +
- + stmpe@41 {
- + compatible = "st,stmpe811";
- + reg = <0x41>;
- + };
- +
- + rtc@51 {
- + compatible = "nxp,rtc8564";
- + reg = <0x51>;
- + };
- +
- + adc@64 {
- + compatible = "maxim,max1037";
- + reg = <0x64>;
- + };
- +};
- +
- +&i2c3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c3>;
- + clock-frequency = <100000>;
- + status = "okay";
- +};
- +
- +&uart3 {
- + status = "okay";
- +};
- +
- +&uart4 {
- + status = "okay";
- +};
- +
- +&usbh1 {
- + status = "okay";
- +};
- +
- +&usbotg {
- + status = "okay";
- +};
- +
- +&usdhc2 {
- + status = "okay";
- +};
- +
- +&usdhc3 {
- + status = "okay";
- +};
- +
- +&iomuxc {
- + pinctrl_i2c2: i2c2grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
- + MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_i2c3: i2c3grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
- + MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
- + >;
- + };
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi linux-3.14.35/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi 2015-03-08 14:27:37.397684503 -0500
- @@ -0,0 +1,356 @@
- +/*
- + * Copyright 2013 Christian Hemp, Phytec Messtechnik GmbH
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#include <dt-bindings/gpio/gpio.h>
- +
- +/ {
- + model = "Phytec phyFLEX-i.MX6 Ouad";
- + compatible = "phytec,imx6q-pfla02", "fsl,imx6q";
- +
- + memory {
- + reg = <0x10000000 0x80000000>;
- + };
- +
- + regulators {
- + compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + reg_usb_otg_vbus: regulator@0 {
- + compatible = "regulator-fixed";
- + reg = <0>;
- + regulator-name = "usb_otg_vbus";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + gpio = <&gpio4 15 0>;
- + };
- +
- + reg_usb_h1_vbus: regulator@1 {
- + compatible = "regulator-fixed";
- + reg = <1>;
- + regulator-name = "usb_h1_vbus";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + gpio = <&gpio1 0 0>;
- + };
- + };
- +
- + gpio_leds: leds {
- + compatible = "gpio-leds";
- +
- + green {
- + label = "phyflex:green";
- + gpios = <&gpio1 30 0>;
- + };
- +
- + red {
- + label = "phyflex:red";
- + gpios = <&gpio2 31 0>;
- + };
- + };
- +};
- +
- +&ecspi3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_ecspi3>;
- + status = "okay";
- + fsl,spi-num-chipselects = <1>;
- + cs-gpios = <&gpio4 24 0>;
- +
- + flash@0 {
- + compatible = "m25p80";
- + spi-max-frequency = <20000000>;
- + reg = <0>;
- + };
- +};
- +
- +&i2c1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c1>;
- + status = "okay";
- +
- + eeprom@50 {
- + compatible = "atmel,24c32";
- + reg = <0x50>;
- + };
- +
- + pmic@58 {
- + compatible = "dialog,da9063";
- + reg = <0x58>;
- + interrupt-parent = <&gpio4>;
- + interrupts = <17 0x8>; /* active-low GPIO4_17 */
- +
- + regulators {
- + vddcore_reg: bcore1 {
- + regulator-min-microvolt = <730000>;
- + regulator-max-microvolt = <1380000>;
- + regulator-always-on;
- + };
- +
- + vddsoc_reg: bcore2 {
- + regulator-min-microvolt = <730000>;
- + regulator-max-microvolt = <1380000>;
- + regulator-always-on;
- + };
- +
- + vdd_ddr3_reg: bpro {
- + regulator-min-microvolt = <1500000>;
- + regulator-max-microvolt = <1500000>;
- + regulator-always-on;
- + };
- +
- + vdd_3v3_reg: bperi {
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vdd_buckmem_reg: bmem {
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vdd_eth_reg: bio {
- + regulator-min-microvolt = <1200000>;
- + regulator-max-microvolt = <1200000>;
- + regulator-always-on;
- + };
- +
- + vdd_eth_io_reg: ldo4 {
- + regulator-min-microvolt = <2500000>;
- + regulator-max-microvolt = <2500000>;
- + regulator-always-on;
- + };
- +
- + vdd_mx6_snvs_reg: ldo5 {
- + regulator-min-microvolt = <3000000>;
- + regulator-max-microvolt = <3000000>;
- + regulator-always-on;
- + };
- +
- + vdd_3v3_pmic_io_reg: ldo6 {
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vdd_sd0_reg: ldo9 {
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + };
- +
- + vdd_sd1_reg: ldo10 {
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + };
- +
- + vdd_mx6_high_reg: ldo11 {
- + regulator-min-microvolt = <3000000>;
- + regulator-max-microvolt = <3000000>;
- + regulator-always-on;
- + };
- + };
- + };
- +};
- +
- +&iomuxc {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hog>;
- +
- + imx6q-phytec-pfla02 {
- + pinctrl_hog: hoggrp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000
- + MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */
- + MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x80000000 /* PMIC interrupt */
- + MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* Green LED */
- + MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x80000000 /* Red LED */
- + >;
- + };
- +
- + pinctrl_ecspi3: ecspi3grp {
- + fsl,pins = <
- + MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
- + MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
- + MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
- + >;
- + };
- +
- + pinctrl_enet: enetgrp {
- + fsl,pins = <
- + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- + MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0
- + >;
- + };
- +
- + pinctrl_gpmi_nand: gpminandgrp {
- + fsl,pins = <
- + MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
- + MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
- + MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
- + MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
- + MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
- + MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
- + MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
- + MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
- + MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
- + MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
- + MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
- + MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
- + MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
- + MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
- + MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
- + MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
- + MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1
- + >;
- + };
- +
- + pinctrl_i2c1: i2c1grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- + MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_uart3: uart3grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
- + MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
- + MX6QDL_PAD_EIM_D30__UART3_RTS_B 0x1b0b1
- + MX6QDL_PAD_EIM_D31__UART3_CTS_B 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart4: uart4grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
- + MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usbh1: usbh1grp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_0__USB_H1_PWR 0x80000000
- + >;
- + };
- +
- + pinctrl_usbotg: usbotggrp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- + MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
- + MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x80000000
- + >;
- + };
- +
- + pinctrl_usdhc2: usdhc2grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc3: usdhc3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc3_cdwp: usdhc3cdwp {
- + fsl,pins = <
- + MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000
- + MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
- + >;
- + };
- + };
- +};
- +
- +&fec {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_enet>;
- + phy-mode = "rgmii";
- + phy-reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
- + status = "disabled";
- +};
- +
- +&gpmi {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_gpmi_nand>;
- + nand-on-flash-bbt;
- + status = "disabled";
- +};
- +
- +&uart3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart3>;
- + status = "disabled";
- +};
- +
- +&uart4 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart4>;
- + status = "disabled";
- +};
- +
- +&usbh1 {
- + vbus-supply = <®_usb_h1_vbus>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usbh1>;
- + status = "disabled";
- +};
- +
- +&usbotg {
- + vbus-supply = <®_usb_otg_vbus>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usbotg>;
- + disable-over-current;
- + status = "disabled";
- +};
- +
- +&usdhc2 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc2>;
- + cd-gpios = <&gpio1 4 0>;
- + wp-gpios = <&gpio1 2 0>;
- + status = "disabled";
- +};
- +
- +&usdhc3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc3
- + &pinctrl_usdhc3_cdwp>;
- + cd-gpios = <&gpio1 27 0>;
- + wp-gpios = <&gpio1 29 0>;
- + status = "disabled";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi linux-3.14.35/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi 2015-03-08 14:27:37.397684503 -0500
- @@ -10,17 +10,146 @@
- * http://www.gnu.org/copyleft/gpl.html
- */
-
- +#include <dt-bindings/gpio/gpio.h>
- +
- / {
- + aliases {
- + mxcfb0 = &mxcfb1;
- + mxcfb1 = &mxcfb2;
- + mxcfb2 = &mxcfb3;
- + mxcfb3 = &mxcfb4;
- + };
- +
- memory {
- reg = <0x10000000 0x80000000>;
- };
- +
- + leds {
- + compatible = "gpio-leds";
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_gpio_leds>;
- +
- + user {
- + label = "debug";
- + gpios = <&gpio5 15 GPIO_ACTIVE_HIGH>;
- + };
- + };
- +
- + sound-spdif {
- + compatible = "fsl,imx-audio-spdif",
- + "fsl,imx-sabreauto-spdif";
- + model = "imx-spdif";
- + spdif-controller = <&spdif>;
- + spdif-in;
- + };
- +
- + backlight {
- + compatible = "pwm-backlight";
- + pwms = <&pwm3 0 5000000>;
- + brightness-levels = <0 4 8 16 32 64 128 255>;
- + default-brightness-level = <7>;
- + status = "okay";
- + };
- +
- + max7310_reset: max7310-reset {
- + compatible = "gpio-reset";
- + reset-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
- + reset-delay-us = <1>;
- + #reset-cells = <0>;
- + };
- +
- + mxcfb1: fb@0 {
- + compatible = "fsl,mxc_sdc_fb";
- + disp_dev = "ldb";
- + interface_pix_fmt = "RGB666";
- + mode_str ="LDB-XGA";
- + default_bpp = <16>;
- + int_clk = <0>;
- + late_init = <0>;
- + status = "disabled";
- + };
- +
- + mxcfb2: fb@1 {
- + compatible = "fsl,mxc_sdc_fb";
- + disp_dev = "hdmi";
- + interface_pix_fmt = "RGB24";
- + mode_str ="1920x1080M@60";
- + default_bpp = <24>;
- + int_clk = <0>;
- + late_init = <0>;
- + status = "disabled";
- + };
- +
- + mxcfb3: fb@2 {
- + compatible = "fsl,mxc_sdc_fb";
- + disp_dev = "lcd";
- + interface_pix_fmt = "RGB565";
- + mode_str ="CLAA-WVGA";
- + default_bpp = <16>;
- + int_clk = <0>;
- + late_init = <0>;
- + status = "disabled";
- + };
- +
- + mxcfb4: fb@3 {
- + compatible = "fsl,mxc_sdc_fb";
- + disp_dev = "ldb";
- + interface_pix_fmt = "RGB666";
- + mode_str ="LDB-XGA";
- + default_bpp = <16>;
- + int_clk = <0>;
- + late_init = <0>;
- + status = "disabled";
- + };
- +
- + backlight {
- + compatible = "pwm-backlight";
- + pwms = <&pwm3 0 5000000>;
- + brightness-levels = <0 4 8 16 32 64 128 255>;
- + default-brightness-level = <7>;
- + };
- +
- + regulators {
- + compatible = "simple-bus";
- + reg_audio: cs42888_supply {
- + compatible = "regulator-fixed";
- + regulator-name = "cs42888_supply";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- + };
- +
- + sound-cs42888 {
- + compatible = "fsl,imx6-sabreauto-cs42888",
- + "fsl,imx-audio-cs42888";
- + model = "imx-cs42888";
- + esai-controller = <&esai>;
- + asrc-controller = <&asrc_p2p>;
- + audio-codec = <&codec>;
- + };
- +
- + sound-hdmi {
- + compatible = "fsl,imx6q-audio-hdmi",
- + "fsl,imx-audio-hdmi";
- + model = "imx-audio-hdmi";
- + hdmi-controller = <&hdmi_audio>;
- + };
- +
- + clocks {
- + codec_osc: anaclk2 {
- + compatible = "fixed-clock";
- + #clock-cells = <0>;
- + clock-frequency = <24576000>;
- + };
- + };
- };
-
- &ecspi1 {
- fsl,spi-num-chipselects = <1>;
- cs-gpios = <&gpio3 19 0>;
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_ecspi1_1 &pinctrl_ecspi1_sabreauto>;
- + pinctrl-0 = <&pinctrl_ecspi1 &pinctrl_ecspi1_cs>;
- status = "disabled"; /* pin conflict with WEIM NOR */
-
- flash: m25p80@0 {
- @@ -34,51 +163,481 @@
-
- &fec {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_enet_2>;
- + pinctrl-0 = <&pinctrl_enet>;
- phy-mode = "rgmii";
- + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
- + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
- status = "okay";
- };
-
- &gpmi {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_gpmi_nand_1>;
- + pinctrl-0 = <&pinctrl_gpmi_nand>;
- + status = "okay";
- +};
- +
- +&i2c2 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c2>;
- + status = "okay";
- +
- + egalax_ts@04 {
- + compatible = "eeti,egalax_ts";
- + reg = <0x04>;
- + interrupt-parent = <&gpio2>;
- + interrupts = <28 2>;
- + wakeup-gpios = <&gpio2 28 0>;
- + };
- +
- + pmic: pfuze100@08 {
- + compatible = "fsl,pfuze100";
- + reg = <0x08>;
- +
- + regulators {
- + sw1a_reg: sw1ab {
- + regulator-min-microvolt = <300000>;
- + regulator-max-microvolt = <1875000>;
- + regulator-boot-on;
- + regulator-always-on;
- + regulator-ramp-delay = <6250>;
- + };
- +
- + sw1c_reg: sw1c {
- + regulator-min-microvolt = <300000>;
- + regulator-max-microvolt = <1875000>;
- + regulator-boot-on;
- + regulator-always-on;
- + regulator-ramp-delay = <6250>;
- + };
- +
- + sw2_reg: sw2 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw3a_reg: sw3a {
- + regulator-min-microvolt = <400000>;
- + regulator-max-microvolt = <1975000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw3b_reg: sw3b {
- + regulator-min-microvolt = <400000>;
- + regulator-max-microvolt = <1975000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw4_reg: sw4 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <3300000>;
- + };
- +
- + swbst_reg: swbst {
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5150000>;
- + };
- +
- + snvs_reg: vsnvs {
- + regulator-min-microvolt = <1000000>;
- + regulator-max-microvolt = <3000000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + vref_reg: vrefddr {
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + vgen1_reg: vgen1 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <1550000>;
- + };
- +
- + vgen2_reg: vgen2 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <1550000>;
- + };
- +
- + vgen3_reg: vgen3 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + };
- +
- + vgen4_reg: vgen4 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vgen5_reg: vgen5 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vgen6_reg: vgen6 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- + };
- + };
- +
- + codec: cs42888@048 {
- + compatible = "cirrus,cs42888";
- + reg = <0x048>;
- + clocks = <&codec_osc 0>;
- + clock-names = "codec_osc";
- + VA-supply = <®_audio>;
- + VD-supply = <®_audio>;
- + VLS-supply = <®_audio>;
- + VLC-supply = <®_audio>;
- + };
- +
- + hdmi: edid@50 {
- + compatible = "fsl,imx6-hdmi-i2c";
- + reg = <0x50>;
- + };
- +};
- +
- +&i2c3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c3>;
- + pinctrl-assert-gpios = <&gpio5 4 GPIO_ACTIVE_HIGH>;
- status = "okay";
- +
- + max7310_a: gpio@30 {
- + compatible = "maxim,max7310";
- + reg = <0x30>;
- + gpio-controller;
- + #gpio-cells = <2>;
- + resets = <&max7310_reset>;
- + };
- +
- + max7310_b: gpio@32 {
- + compatible = "maxim,max7310";
- + reg = <0x32>;
- + gpio-controller;
- + #gpio-cells = <2>;
- + };
- +
- + max7310_c: gpio@34 {
- + compatible = "maxim,max7310";
- + reg = <0x34>;
- + gpio-controller;
- + #gpio-cells = <2>;
- + };
- };
-
- &iomuxc {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_hog>;
-
- - hog {
- + imx6qdl-sabreauto {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x80000000
- MX6QDL_PAD_SD2_DAT2__GPIO1_IO13 0x80000000
- + MX6QDL_PAD_EIM_A24__GPIO5_IO04 0x80000000
- + MX6QDL_PAD_SD2_DAT0__GPIO1_IO15 0x80000000
- MX6QDL_PAD_GPIO_18__SD3_VSELECT 0x17059
- >;
- };
- - };
-
- - ecspi1 {
- - pinctrl_ecspi1_sabreauto: ecspi1-sabreauto {
- + pinctrl_esai1: esai1grp {
- + fsl,pins = <
- + MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK 0x1b030
- + MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS 0x1b030
- + MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2 0x1b030
- + MX6QDL_PAD_GPIO_5__ESAI_TX2_RX3 0x1b030
- + MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1 0x1b030
- + MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0 0x1b030
- + MX6QDL_PAD_GPIO_17__ESAI_TX0 0x1b030
- + MX6QDL_PAD_NANDF_CS3__ESAI_TX1 0x1b030
- + MX6QDL_PAD_ENET_MDIO__ESAI_RX_CLK 0x1b030
- + MX6QDL_PAD_GPIO_9__ESAI_RX_FS 0x1b030
- + >;
- + };
- +
- + pinctrl_ecspi1: ecspi1grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
- + MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
- + MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
- + >;
- + };
- +
- + pinctrl_ecspi1_cs: ecspi1cs {
- fsl,pins = <
- MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x80000000
- >;
- };
- +
- + pinctrl_enet: enetgrp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL1__ENET_MDIO 0x1b0b0
- + MX6QDL_PAD_KEY_COL2__ENET_MDC 0x1b0b0
- + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- + MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
- + >;
- + };
- +
- + pinctrl_gpio_leds: gpioledsgrp {
- + fsl,pins = <
- + MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15 0x80000000
- + >;
- + };
- +
- + pinctrl_gpmi_nand: gpminandgrp {
- + fsl,pins = <
- + MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
- + MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
- + MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
- + MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
- + MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
- + MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
- + MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
- + MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
- + MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
- + MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
- + MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
- + MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
- + MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
- + MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
- + MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
- + MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
- + MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1
- + >;
- + };
- +
- + pinctrl_hdmi_cec_2: hdmicecgrp-2 {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
- + >;
- + };
- +
- + pinctrl_i2c2: i2c2grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
- + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_i2c3: i2c3grp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
- + MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_pwm1: pwm1grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1
- + >;
- + };
- +
- + pinctrl_spdif: spdifgrp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL3__SPDIF_IN 0x1b0b0
- + >;
- + };
- +
- + pinctrl_uart3: uart3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD4_CLK__UART3_RX_DATA 0x1b0b1
- + MX6QDL_PAD_SD4_CMD__UART3_TX_DATA 0x1b0b1
- + MX6QDL_PAD_EIM_D30__UART3_CTS_B 0x1b0b1
- + MX6QDL_PAD_EIM_EB3__UART3_RTS_B 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart4: uart4grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
- + MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usdhc3: usdhc3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- + MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
- + MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
- + MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
- + MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170b9
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170b9
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170b9
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170b9
- + MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170b9
- + MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170b9
- + MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170b9
- + MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170b9
- + >;
- + };
- +
- + pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170f9
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170f9
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170f9
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
- + MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170f9
- + MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170f9
- + MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170f9
- + MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170f9
- + >;
- + };
- +
- + pinctrl_weim_cs0: weimcs0grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_CS0__EIM_CS0_B 0xb0b1
- + >;
- + };
- +
- + pinctrl_weim_nor: weimnorgrp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_OE__EIM_OE_B 0xb0b1
- + MX6QDL_PAD_EIM_RW__EIM_RW 0xb0b1
- + MX6QDL_PAD_EIM_WAIT__EIM_WAIT_B 0xb060
- + MX6QDL_PAD_EIM_D16__EIM_DATA16 0x1b0b0
- + MX6QDL_PAD_EIM_D17__EIM_DATA17 0x1b0b0
- + MX6QDL_PAD_EIM_D18__EIM_DATA18 0x1b0b0
- + MX6QDL_PAD_EIM_D19__EIM_DATA19 0x1b0b0
- + MX6QDL_PAD_EIM_D20__EIM_DATA20 0x1b0b0
- + MX6QDL_PAD_EIM_D21__EIM_DATA21 0x1b0b0
- + MX6QDL_PAD_EIM_D22__EIM_DATA22 0x1b0b0
- + MX6QDL_PAD_EIM_D23__EIM_DATA23 0x1b0b0
- + MX6QDL_PAD_EIM_D24__EIM_DATA24 0x1b0b0
- + MX6QDL_PAD_EIM_D25__EIM_DATA25 0x1b0b0
- + MX6QDL_PAD_EIM_D26__EIM_DATA26 0x1b0b0
- + MX6QDL_PAD_EIM_D27__EIM_DATA27 0x1b0b0
- + MX6QDL_PAD_EIM_D28__EIM_DATA28 0x1b0b0
- + MX6QDL_PAD_EIM_D29__EIM_DATA29 0x1b0b0
- + MX6QDL_PAD_EIM_D30__EIM_DATA30 0x1b0b0
- + MX6QDL_PAD_EIM_D31__EIM_DATA31 0x1b0b0
- + MX6QDL_PAD_EIM_A23__EIM_ADDR23 0xb0b1
- + MX6QDL_PAD_EIM_A22__EIM_ADDR22 0xb0b1
- + MX6QDL_PAD_EIM_A21__EIM_ADDR21 0xb0b1
- + MX6QDL_PAD_EIM_A20__EIM_ADDR20 0xb0b1
- + MX6QDL_PAD_EIM_A19__EIM_ADDR19 0xb0b1
- + MX6QDL_PAD_EIM_A18__EIM_ADDR18 0xb0b1
- + MX6QDL_PAD_EIM_A17__EIM_ADDR17 0xb0b1
- + MX6QDL_PAD_EIM_A16__EIM_ADDR16 0xb0b1
- + MX6QDL_PAD_EIM_DA15__EIM_AD15 0xb0b1
- + MX6QDL_PAD_EIM_DA14__EIM_AD14 0xb0b1
- + MX6QDL_PAD_EIM_DA13__EIM_AD13 0xb0b1
- + MX6QDL_PAD_EIM_DA12__EIM_AD12 0xb0b1
- + MX6QDL_PAD_EIM_DA11__EIM_AD11 0xb0b1
- + MX6QDL_PAD_EIM_DA10__EIM_AD10 0xb0b1
- + MX6QDL_PAD_EIM_DA9__EIM_AD09 0xb0b1
- + MX6QDL_PAD_EIM_DA8__EIM_AD08 0xb0b1
- + MX6QDL_PAD_EIM_DA7__EIM_AD07 0xb0b1
- + MX6QDL_PAD_EIM_DA6__EIM_AD06 0xb0b1
- + MX6QDL_PAD_EIM_DA5__EIM_AD05 0xb0b1
- + MX6QDL_PAD_EIM_DA4__EIM_AD04 0xb0b1
- + MX6QDL_PAD_EIM_DA3__EIM_AD03 0xb0b1
- + MX6QDL_PAD_EIM_DA2__EIM_AD02 0xb0b1
- + MX6QDL_PAD_EIM_DA1__EIM_AD01 0xb0b1
- + MX6QDL_PAD_EIM_DA0__EIM_AD00 0xb0b1
- + >;
- + };
- + };
- +};
- +
- +&ldb {
- + status = "okay";
- +
- + lvds-channel@0 {
- + fsl,data-mapping = "spwg";
- + fsl,data-width = <18>;
- + status = "okay";
- +
- + display-timings {
- + native-mode = <&timing0>;
- + timing0: hsd100pxn1 {
- + clock-frequency = <65000000>;
- + hactive = <1024>;
- + vactive = <768>;
- + hback-porch = <220>;
- + hfront-porch = <40>;
- + vback-porch = <21>;
- + vfront-porch = <7>;
- + hsync-len = <60>;
- + vsync-len = <10>;
- + };
- + };
- };
- };
-
- +&pcie {
- + status = "okay";
- +};
- +
- +&pwm3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_pwm1>;
- + status = "okay";
- +};
- +
- +&spdif {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_spdif>;
- + status = "okay";
- +};
- +
- +&uart3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart3>;
- + pinctrl-assert-gpios = <&max7310_b 4 GPIO_ACTIVE_HIGH>, /* CTS */
- + <&max7310_c 3 GPIO_ACTIVE_HIGH>; /* RXD and TXD */
- + fsl,uart-has-rtscts;
- + status = "okay";
- +};
- +
- &uart4 {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_uart4_1>;
- + pinctrl-0 = <&pinctrl_uart4>;
- status = "okay";
- };
-
- &usdhc3 {
- pinctrl-names = "default", "state_100mhz", "state_200mhz";
- - pinctrl-0 = <&pinctrl_usdhc3_1>;
- - pinctrl-1 = <&pinctrl_usdhc3_1_100mhz>;
- - pinctrl-2 = <&pinctrl_usdhc3_1_200mhz>;
- + pinctrl-0 = <&pinctrl_usdhc3>;
- + pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
- + pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
- cd-gpios = <&gpio6 15 0>;
- wp-gpios = <&gpio1 13 0>;
- status = "okay";
- @@ -86,7 +645,7 @@
-
- &weim {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_weim_nor_1 &pinctrl_weim_cs0_1>;
- + pinctrl-0 = <&pinctrl_weim_nor &pinctrl_weim_cs0>;
- #address-cells = <2>;
- #size-cells = <1>;
- ranges = <0 0 0x08000000 0x08000000>;
- @@ -102,3 +661,48 @@
- 0x0000c000 0x1404a38e 0x00000000>;
- };
- };
- +
- +&ldb {
- + ipu_id = <1>;
- + disp_id = <0>;
- + ext_ref = <1>;
- + mode = "sep0";
- + sec_ipu_id = <1>;
- + sec_disp_id = <1>;
- + status = "okay";
- +};
- +
- +&esai {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_esai1>;
- + status = "okay";
- +};
- +
- +&hdmi_core {
- + ipu_id = <0>;
- + disp_id = <1>;
- + status = "okay";
- +};
- +
- +&hdmi_video {
- + fsl,phy_reg_vlev = <0x0294>;
- + fsl,phy_reg_cksymtx = <0x800d>;
- + status = "okay";
- +};
- +
- +&hdmi_audio {
- + status = "okay";
- +};
- +
- +&hdmi_cec {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hdmi_cec_2>;
- + status = "okay";
- +};
- +
- +&gpc {
- + fsl,cpu_pupscr_sw2iso = <0xf>;
- + fsl,cpu_pupscr_sw = <0xf>;
- + fsl,cpu_pdnscr_iso2sw = <0x1>;
- + fsl,cpu_pdnscr_iso = <0x1>;
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi linux-3.14.35/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi 2015-03-08 14:27:37.397684503 -0500
- @@ -0,0 +1,427 @@
- +/*
- + * Copyright 2011 Freescale Semiconductor, Inc.
- + * Copyright 2011 Linaro Ltd.
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +#include <dt-bindings/gpio/gpio.h>
- +#include <dt-bindings/input/input.h>
- +
- +/ {
- + chosen {
- + stdout-path = &uart2;
- + };
- +
- + memory {
- + reg = <0x10000000 0x40000000>;
- + };
- +
- + regulators {
- + compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + reg_2p5v: regulator@0 {
- + compatible = "regulator-fixed";
- + reg = <0>;
- + regulator-name = "2P5V";
- + regulator-min-microvolt = <2500000>;
- + regulator-max-microvolt = <2500000>;
- + regulator-always-on;
- + };
- +
- + reg_3p3v: regulator@1 {
- + compatible = "regulator-fixed";
- + reg = <1>;
- + regulator-name = "3P3V";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + reg_usb_otg_vbus: regulator@2 {
- + compatible = "regulator-fixed";
- + reg = <2>;
- + regulator-name = "usb_otg_vbus";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + gpio = <&gpio3 22 0>;
- + enable-active-high;
- + };
- + };
- +
- + gpio-keys {
- + compatible = "gpio-keys";
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_gpio_keys>;
- +
- + power {
- + label = "Power Button";
- + gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
- + linux,code = <KEY_POWER>;
- + gpio-key,wakeup;
- + };
- +
- + menu {
- + label = "Menu";
- + gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
- + linux,code = <KEY_MENU>;
- + };
- +
- + home {
- + label = "Home";
- + gpios = <&gpio2 4 GPIO_ACTIVE_LOW>;
- + linux,code = <KEY_HOME>;
- + };
- +
- + back {
- + label = "Back";
- + gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
- + linux,code = <KEY_BACK>;
- + };
- +
- + volume-up {
- + label = "Volume Up";
- + gpios = <&gpio7 13 GPIO_ACTIVE_LOW>;
- + linux,code = <KEY_VOLUMEUP>;
- + };
- +
- + volume-down {
- + label = "Volume Down";
- + gpios = <&gpio4 5 GPIO_ACTIVE_LOW>;
- + linux,code = <KEY_VOLUMEDOWN>;
- + };
- + };
- +
- + sound {
- + compatible = "fsl,imx6q-sabrelite-sgtl5000",
- + "fsl,imx-audio-sgtl5000";
- + model = "imx6q-sabrelite-sgtl5000";
- + ssi-controller = <&ssi1>;
- + audio-codec = <&codec>;
- + audio-routing =
- + "MIC_IN", "Mic Jack",
- + "Mic Jack", "Mic Bias",
- + "Headphone Jack", "HP_OUT";
- + mux-int-port = <1>;
- + mux-ext-port = <4>;
- + };
- +
- + backlight_lcd {
- + compatible = "pwm-backlight";
- + pwms = <&pwm1 0 5000000>;
- + brightness-levels = <0 4 8 16 32 64 128 255>;
- + default-brightness-level = <7>;
- + power-supply = <®_3p3v>;
- + status = "okay";
- + };
- +
- + backlight_lvds {
- + compatible = "pwm-backlight";
- + pwms = <&pwm4 0 5000000>;
- + brightness-levels = <0 4 8 16 32 64 128 255>;
- + default-brightness-level = <7>;
- + power-supply = <®_3p3v>;
- + status = "okay";
- + };
- +};
- +
- +&audmux {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_audmux>;
- + status = "okay";
- +};
- +
- +&ecspi1 {
- + fsl,spi-num-chipselects = <1>;
- + cs-gpios = <&gpio3 19 0>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_ecspi1>;
- + status = "okay";
- +
- + flash: m25p80@0 {
- + compatible = "sst,sst25vf016b";
- + spi-max-frequency = <20000000>;
- + reg = <0>;
- + };
- +};
- +
- +&fec {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_enet>;
- + phy-mode = "rgmii";
- + phy-reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
- + txen-skew-ps = <0>;
- + txc-skew-ps = <3000>;
- + rxdv-skew-ps = <0>;
- + rxc-skew-ps = <3000>;
- + rxd0-skew-ps = <0>;
- + rxd1-skew-ps = <0>;
- + rxd2-skew-ps = <0>;
- + rxd3-skew-ps = <0>;
- + txd0-skew-ps = <0>;
- + txd1-skew-ps = <0>;
- + txd2-skew-ps = <0>;
- + txd3-skew-ps = <0>;
- + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
- + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
- + status = "okay";
- +};
- +
- +&i2c1 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c1>;
- + status = "okay";
- +
- + codec: sgtl5000@0a {
- + compatible = "fsl,sgtl5000";
- + reg = <0x0a>;
- + clocks = <&clks 201>;
- + VDDA-supply = <®_2p5v>;
- + VDDIO-supply = <®_3p3v>;
- + };
- +};
- +
- +&iomuxc {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hog>;
- +
- + imx6q-sabrelite {
- + pinctrl_hog: hoggrp {
- + fsl,pins = <
- + /* SGTL5000 sys_mclk */
- + MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x030b0
- + >;
- + };
- +
- + pinctrl_audmux: audmuxgrp {
- + fsl,pins = <
- + MX6QDL_PAD_SD2_DAT0__AUD4_RXD 0x130b0
- + MX6QDL_PAD_SD2_DAT3__AUD4_TXC 0x130b0
- + MX6QDL_PAD_SD2_DAT2__AUD4_TXD 0x110b0
- + MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x130b0
- + >;
- + };
- +
- + pinctrl_ecspi1: ecspi1grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
- + MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
- + MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
- + MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x000b1 /* CS */
- + >;
- + };
- +
- + pinctrl_enet: enetgrp {
- + fsl,pins = <
- + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x100b0
- + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x100b0
- + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x100b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x100b0
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x100b0
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x100b0
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x100b0
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x100b0
- + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x100b0
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- + /* Phy reset */
- + MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x000b0
- + MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
- + >;
- + };
- +
- + pinctrl_gpio_keys: gpio_keysgrp {
- + fsl,pins = <
- + /* Power Button */
- + MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0
- + /* Menu Button */
- + MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0
- + /* Home Button */
- + MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x1b0b0
- + /* Back Button */
- + MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
- + /* Volume Up Button */
- + MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x1b0b0
- + /* Volume Down Button */
- + MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x1b0b0
- + >;
- + };
- +
- + pinctrl_i2c1: i2c1grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- + MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_pwm1: pwm1grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
- + >;
- + };
- +
- + pinctrl_pwm3: pwm3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x1b0b1
- + >;
- + };
- +
- + pinctrl_pwm4: pwm4grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart1: uart1grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
- + MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart2: uart2grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
- + MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usbotg: usbotggrp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- + MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
- + /* power enable, high active */
- + MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x000b0
- + >;
- + };
- +
- + pinctrl_usdhc3: usdhc3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- + MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0 /* CD */
- + MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1f0b0 /* WP */
- + >;
- + };
- +
- + pinctrl_usdhc4: usdhc4grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- + MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- + MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- + MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- + MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- + MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- + MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x1b0b0 /* CD */
- + >;
- + };
- + };
- +};
- +
- +&ldb {
- + status = "okay";
- +
- + lvds-channel@0 {
- + fsl,data-mapping = "spwg";
- + fsl,data-width = <18>;
- + status = "okay";
- +
- + display-timings {
- + native-mode = <&timing0>;
- + timing0: hsd100pxn1 {
- + clock-frequency = <65000000>;
- + hactive = <1024>;
- + vactive = <768>;
- + hback-porch = <220>;
- + hfront-porch = <40>;
- + vback-porch = <21>;
- + vfront-porch = <7>;
- + hsync-len = <60>;
- + vsync-len = <10>;
- + };
- + };
- + };
- +};
- +
- +&pcie {
- + status = "okay";
- +};
- +
- +&pwm1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_pwm1>;
- + status = "okay";
- +};
- +
- +&pwm3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_pwm3>;
- + status = "okay";
- +};
- +
- +&pwm4 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_pwm4>;
- + status = "okay";
- +};
- +
- +&ssi1 {
- + fsl,mode = "i2s-slave";
- + status = "okay";
- +};
- +
- +&uart1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart1>;
- + status = "okay";
- +};
- +
- +&uart2 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart2>;
- + status = "okay";
- +};
- +
- +&usbh1 {
- + status = "okay";
- +};
- +
- +&usbotg {
- + vbus-supply = <®_usb_otg_vbus>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usbotg>;
- + disable-over-current;
- + status = "okay";
- +};
- +
- +&usdhc3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc3>;
- + cd-gpios = <&gpio7 0 0>;
- + wp-gpios = <&gpio7 1 0>;
- + vmmc-supply = <®_3p3v>;
- + status = "okay";
- +};
- +
- +&usdhc4 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc4>;
- + cd-gpios = <&gpio2 6 0>;
- + vmmc-supply = <®_3p3v>;
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-sabresd.dtsi linux-3.14.35/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-sabresd.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6qdl-sabresd.dtsi 2015-03-08 14:27:37.397684503 -0500
- @@ -10,16 +10,33 @@
- * http://www.gnu.org/copyleft/gpl.html
- */
-
- +#include <dt-bindings/gpio/gpio.h>
- +#include <dt-bindings/input/input.h>
- +
- / {
- + aliases {
- + mxcfb0 = &mxcfb1;
- + mxcfb1 = &mxcfb2;
- + mxcfb2 = &mxcfb3;
- + mxcfb3 = &mxcfb4;
- + };
- +
- + chosen {
- + stdout-path = &uart1;
- + };
- +
- memory {
- reg = <0x10000000 0x40000000>;
- };
-
- regulators {
- compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
-
- - reg_usb_otg_vbus: usb_otg_vbus {
- + reg_usb_otg_vbus: regulator@0 {
- compatible = "regulator-fixed";
- + reg = <0>;
- regulator-name = "usb_otg_vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- @@ -27,8 +44,9 @@
- enable-active-high;
- };
-
- - reg_usb_h1_vbus: usb_h1_vbus {
- + reg_usb_h1_vbus: regulator@1 {
- compatible = "regulator-fixed";
- + reg = <1>;
- regulator-name = "usb_h1_vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- @@ -36,29 +54,46 @@
- enable-active-high;
- };
-
- - reg_audio: wm8962_supply {
- + reg_audio: regulator@2 {
- compatible = "regulator-fixed";
- + reg = <2>;
- regulator-name = "wm8962-supply";
- gpio = <&gpio4 10 0>;
- enable-active-high;
- };
- +
- + reg_mipi_dsi_pwr_on: mipi_dsi_pwr_on {
- + compatible = "regulator-fixed";
- + regulator-name = "mipi_dsi_pwr_on";
- + gpio = <&gpio6 14 0>;
- + enable-active-high;
- + };
- };
-
- gpio-keys {
- compatible = "gpio-keys";
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_gpio_keys>;
- +
- + power {
- + label = "Power Button";
- + gpios = <&gpio3 29 GPIO_ACTIVE_LOW>;
- + gpio-key,wakeup;
- + linux,code = <KEY_POWER>;
- + };
-
- volume-up {
- label = "Volume Up";
- - gpios = <&gpio1 4 0>;
- + gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
- gpio-key,wakeup;
- - linux,code = <115>; /* KEY_VOLUMEUP */
- + linux,code = <KEY_VOLUMEUP>;
- };
-
- volume-down {
- label = "Volume Down";
- - gpios = <&gpio1 5 0>;
- + gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
- gpio-key,wakeup;
- - linux,code = <114>; /* KEY_VOLUMEDOWN */
- + linux,code = <KEY_VOLUMEDOWN>;
- };
- };
-
- @@ -88,11 +123,107 @@
- default-brightness-level = <7>;
- status = "okay";
- };
- +
- + leds {
- + compatible = "gpio-leds";
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_gpio_leds>;
- +
- + red {
- + gpios = <&gpio1 2 0>;
- + default-state = "on";
- + };
- + };
- +
- + sound-hdmi {
- + compatible = "fsl,imx6q-audio-hdmi",
- + "fsl,imx-audio-hdmi";
- + model = "imx-audio-hdmi";
- + hdmi-controller = <&hdmi_audio>;
- + };
- +
- + mxcfb1: fb@0 {
- + compatible = "fsl,mxc_sdc_fb";
- + disp_dev = "ldb";
- + interface_pix_fmt = "RGB666";
- + mode_str ="LDB-XGA";
- + default_bpp = <16>;
- + int_clk = <0>;
- + late_init = <0>;
- + status = "disabled";
- + };
- +
- + mxcfb2: fb@1 {
- + compatible = "fsl,mxc_sdc_fb";
- + disp_dev = "hdmi";
- + interface_pix_fmt = "RGB24";
- + mode_str ="1920x1080M@60";
- + default_bpp = <24>;
- + int_clk = <0>;
- + late_init = <0>;
- + status = "disabled";
- + };
- +
- + mxcfb3: fb@2 {
- + compatible = "fsl,mxc_sdc_fb";
- + disp_dev = "lcd";
- + interface_pix_fmt = "RGB565";
- + mode_str ="CLAA-WVGA";
- + default_bpp = <16>;
- + int_clk = <0>;
- + late_init = <0>;
- + status = "disabled";
- + };
- +
- + mxcfb4: fb@3 {
- + compatible = "fsl,mxc_sdc_fb";
- + disp_dev = "ldb";
- + interface_pix_fmt = "RGB666";
- + mode_str ="LDB-XGA";
- + default_bpp = <16>;
- + int_clk = <0>;
- + late_init = <0>;
- + status = "disabled";
- + };
- +
- + lcd@0 {
- + compatible = "fsl,lcd";
- + ipu_id = <0>;
- + disp_id = <0>;
- + default_ifmt = "RGB565";
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_ipu1>;
- + status = "okay";
- + };
- +
- + backlight {
- + compatible = "pwm-backlight";
- + pwms = <&pwm1 0 5000000>;
- + brightness-levels = <0 4 8 16 32 64 128 255>;
- + default-brightness-level = <7>;
- + };
- +
- + v4l2_out {
- + compatible = "fsl,mxc_v4l2_output";
- + status = "okay";
- + };
- +
- + lvds_cabc_ctrl {
- + lvds0-gpios = <&gpio6 15 0>;
- + lvds1-gpios = <&gpio6 16 0>;
- + };
- +
- + mipi_dsi_reset: mipi-dsi-reset {
- + compatible = "gpio-reset";
- + reset-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>;
- + reset-delay-us = <50>;
- + #reset-cells = <0>;
- + };
- };
-
- &audmux {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_audmux_2>;
- + pinctrl-0 = <&pinctrl_audmux>;
- status = "okay";
- };
-
- @@ -100,7 +231,7 @@
- fsl,spi-num-chipselects = <1>;
- cs-gpios = <&gpio4 9 0>;
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_ecspi1_2>;
- + pinctrl-0 = <&pinctrl_ecspi1>;
- status = "okay";
-
- flash: m25p80@0 {
- @@ -114,7 +245,7 @@
-
- &fec {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_enet_1>;
- + pinctrl-0 = <&pinctrl_enet>;
- phy-mode = "rgmii";
- phy-reset-gpios = <&gpio1 25 0>;
- status = "okay";
- @@ -123,7 +254,7 @@
- &i2c1 {
- clock-frequency = <100000>;
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_i2c1_2>;
- + pinctrl-0 = <&pinctrl_i2c1>;
- status = "okay";
-
- codec: wm8962@1a {
- @@ -149,10 +280,121 @@
- };
- };
-
- +&i2c2 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c2>;
- + status = "okay";
- +
- + hdmi: edid@50 {
- + compatible = "fsl,imx6-hdmi-i2c";
- + reg = <0x50>;
- + };
- +
- + pmic: pfuze100@08 {
- + compatible = "fsl,pfuze100";
- + reg = <0x08>;
- +
- + regulators {
- + sw1a_reg: sw1ab {
- + regulator-min-microvolt = <300000>;
- + regulator-max-microvolt = <1875000>;
- + regulator-boot-on;
- + regulator-always-on;
- + regulator-ramp-delay = <6250>;
- + };
- +
- + sw1c_reg: sw1c {
- + regulator-min-microvolt = <300000>;
- + regulator-max-microvolt = <1875000>;
- + regulator-boot-on;
- + regulator-always-on;
- + regulator-ramp-delay = <6250>;
- + };
- +
- + sw2_reg: sw2 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw3a_reg: sw3a {
- + regulator-min-microvolt = <400000>;
- + regulator-max-microvolt = <1975000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw3b_reg: sw3b {
- + regulator-min-microvolt = <400000>;
- + regulator-max-microvolt = <1975000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw4_reg: sw4 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <3300000>;
- + };
- +
- + swbst_reg: swbst {
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5150000>;
- + };
- +
- + snvs_reg: vsnvs {
- + regulator-min-microvolt = <1000000>;
- + regulator-max-microvolt = <3000000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + vref_reg: vrefddr {
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + vgen1_reg: vgen1 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <1550000>;
- + };
- +
- + vgen2_reg: vgen2 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <1550000>;
- + };
- +
- + vgen3_reg: vgen3 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + };
- +
- + vgen4_reg: vgen4 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vgen5_reg: vgen5 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vgen6_reg: vgen6 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- + };
- + };
- +};
- +
- &i2c3 {
- clock-frequency = <100000>;
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_i2c3_2>;
- + pinctrl-0 = <&pinctrl_i2c3>;
- status = "okay";
-
- egalax_ts@04 {
- @@ -168,11 +410,9 @@
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_hog>;
-
- - hog {
- + imx6qdl-sabresd {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- - MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x80000000
- - MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x80000000
- MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x80000000
- MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x80000000
- MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x80000000
- @@ -182,6 +422,202 @@
- MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
- MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000
- MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x80000000
- + MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x80000000
- + MX6QDL_PAD_NANDF_CS3__GPIO6_IO16 0x80000000
- + MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x80000000
- + MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x80000000
- + >;
- + };
- +
- + pinctrl_audmux: audmuxgrp {
- + fsl,pins = <
- + MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
- + MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
- + MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
- + MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
- + >;
- + };
- +
- + pinctrl_ecspi1: ecspi1grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL1__ECSPI1_MISO 0x100b1
- + MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI 0x100b1
- + MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK 0x100b1
- + >;
- + };
- +
- + pinctrl_enet: enetgrp {
- + fsl,pins = <
- + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- + >;
- + };
- +
- + pinctrl_gpio_keys: gpio_keysgrp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x80000000
- + MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x80000000
- + MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x80000000
- + >;
- + };
- +
- + pinctrl_hdmi_cec: hdmi_cecgrp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
- + >;
- + };
- +
- + pinctrl_hdmi_hdcp: hdmi_hdcpgrp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL3__HDMI_TX_DDC_SCL 0x4001b8b1
- + MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_i2c1: i2c1grp {
- + fsl,pins = <
- + MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
- + MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_i2c2: i2c2grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_i2c3: i2c3grp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
- + MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_ipu1: ipu1grp {
- + fsl,pins = <
- + MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
- + MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10
- + MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10
- + MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10
- + MX6QDL_PAD_DI0_PIN4__IPU1_DI0_PIN04 0x80000000
- + MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10
- + MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10
- + MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10
- + MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10
- + MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10
- + MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10
- + MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10
- + MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10
- + MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10
- + MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10
- + MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10
- + MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10
- + MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10
- + MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10
- + MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10
- + MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10
- + MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10
- + MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10
- + MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10
- + MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10
- + MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10
- + MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10
- + MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10
- + MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10
- + >;
- + };
- +
- + pinctrl_pcie: pciegrp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000
- + >;
- + };
- +
- + pinctrl_pwm1: pwm1grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart1: uart1grp {
- + fsl,pins = <
- + MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
- + MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usbotg: usbotggrp {
- + fsl,pins = <
- + MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc2: usdhc2grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- + MX6QDL_PAD_NANDF_D4__SD2_DATA4 0x17059
- + MX6QDL_PAD_NANDF_D5__SD2_DATA5 0x17059
- + MX6QDL_PAD_NANDF_D6__SD2_DATA6 0x17059
- + MX6QDL_PAD_NANDF_D7__SD2_DATA7 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc3: usdhc3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- + MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
- + MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
- + MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
- + MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc4: usdhc4grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- + MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- + MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- + MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- + MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- + MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- + MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
- + MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
- + MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
- + MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
- + >;
- + };
- + };
- +
- + gpio_leds {
- + pinctrl_gpio_leds: gpioledsgrp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000
- >;
- };
- };
- @@ -212,9 +648,33 @@
- };
- };
-
- +&pcie {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_pcie>;
- + reset-gpio = <&gpio7 12 0>;
- + status = "okay";
- +};
- +
- +&pcie {
- + power-on-gpio = <&gpio3 19 0>;
- + reset-gpio = <&gpio7 12 0>;
- + status = "okay";
- +};
- +
- +
- &pwm1 {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_pwm0_1>;
- + pinctrl-0 = <&pinctrl_pwm1>;
- + status = "okay";
- +};
- +
- +&ldb {
- + ipu_id = <1>;
- + disp_id = <1>;
- + ext_ref = <1>;
- + mode = "sep1";
- + sec_ipu_id = <1>;
- + sec_disp_id = <0>;
- status = "okay";
- };
-
- @@ -225,7 +685,16 @@
-
- &uart1 {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_uart1_1>;
- + pinctrl-0 = <&pinctrl_uart1>;
- + status = "okay";
- +};
- +
- +&mipi_dsi {
- + dev_id = <0>;
- + disp_id = <0>;
- + lcd_panel = "TRULY-WVGA";
- + disp-power-on-supply = <®_mipi_dsi_pwr_on>;
- + resets = <&mipi_dsi_reset>;
- status = "okay";
- };
-
- @@ -237,14 +706,14 @@
- &usbotg {
- vbus-supply = <®_usb_otg_vbus>;
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usbotg_2>;
- + pinctrl-0 = <&pinctrl_usbotg>;
- disable-over-current;
- status = "okay";
- };
-
- &usdhc2 {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usdhc2_1>;
- + pinctrl-0 = <&pinctrl_usdhc2>;
- bus-width = <8>;
- cd-gpios = <&gpio2 2 0>;
- wp-gpios = <&gpio2 3 0>;
- @@ -253,9 +722,47 @@
-
- &usdhc3 {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usdhc3_1>;
- + pinctrl-0 = <&pinctrl_usdhc3>;
- bus-width = <8>;
- cd-gpios = <&gpio2 0 0>;
- wp-gpios = <&gpio2 1 0>;
- status = "okay";
- };
- +
- +&usdhc4 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc4>;
- + bus-width = <8>;
- + non-removable;
- + no-1-8-v;
- + status = "okay";
- +};
- +
- +&hdmi_core {
- + ipu_id = <0>;
- + disp_id = <0>;
- + status = "okay";
- +};
- +
- +&hdmi_video {
- + fsl,phy_reg_vlev = <0x0294>;
- + fsl,phy_reg_cksymtx = <0x800d>;
- + status = "okay";
- +};
- +
- +&hdmi_audio {
- + status = "okay";
- +};
- +
- +&hdmi_cec {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hdmi_cec>;
- + status = "okay";
- +};
- +
- +&gpc {
- + fsl,cpu_pupscr_sw2iso = <0xf>;
- + fsl,cpu_pupscr_sw = <0xf>;
- + fsl,cpu_pdnscr_iso2sw = <0x1>;
- + fsl,cpu_pdnscr_iso = <0x1>;
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-wandboard.dtsi linux-3.14.35/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6qdl-wandboard.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6qdl-wandboard.dtsi 2015-03-08 14:27:37.397684503 -0500
- @@ -12,17 +12,21 @@
- / {
- regulators {
- compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
-
- - reg_2p5v: 2p5v {
- + reg_2p5v: regulator@0 {
- compatible = "regulator-fixed";
- + reg = <0>;
- regulator-name = "2P5V";
- regulator-min-microvolt = <2500000>;
- regulator-max-microvolt = <2500000>;
- regulator-always-on;
- };
-
- - reg_3p3v: 3p3v {
- + reg_3p3v: regulator@1 {
- compatible = "regulator-fixed";
- + reg = <1>;
- regulator-name = "3P3V";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- @@ -54,14 +58,14 @@
-
- &audmux {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_audmux_2>;
- + pinctrl-0 = <&pinctrl_audmux>;
- status = "okay";
- };
-
- &i2c2 {
- clock-frequency = <100000>;
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_i2c2_2>;
- + pinctrl-0 = <&pinctrl_i2c2>;
- status = "okay";
-
- codec: sgtl5000@0a {
- @@ -77,7 +81,7 @@
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_hog>;
-
- - hog {
- + imx6qdl-wandboard {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0
- @@ -91,20 +95,121 @@
- MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x80000000
- >;
- };
- +
- + pinctrl_audmux: audmuxgrp {
- + fsl,pins = <
- + MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
- + MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
- + MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
- + MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
- + >;
- + };
- +
- + pinctrl_enet: enetgrp {
- + fsl,pins = <
- + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- + MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
- + >;
- + };
- +
- + pinctrl_i2c2: i2c2grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_spdif: spdifgrp {
- + fsl,pins = <
- + MX6QDL_PAD_ENET_RXD0__SPDIF_OUT 0x1b0b0
- + >;
- + };
- +
- + pinctrl_uart1: uart1grp {
- + fsl,pins = <
- + MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
- + MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart3: uart3grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
- + MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
- + MX6QDL_PAD_EIM_D23__UART3_CTS_B 0x1b0b1
- + MX6QDL_PAD_EIM_EB3__UART3_RTS_B 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usbotg: usbotggrp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc1: usdhc1grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059
- + MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059
- + MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
- + MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
- + MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
- + MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc2: usdhc2grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc3: usdhc3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- + >;
- + };
- };
- };
-
- &fec {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_enet_1>;
- + pinctrl-0 = <&pinctrl_enet>;
- phy-mode = "rgmii";
- phy-reset-gpios = <&gpio3 29 0>;
- + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
- + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
- status = "okay";
- };
-
- &spdif {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_spdif_3>;
- + pinctrl-0 = <&pinctrl_spdif>;
- status = "okay";
- };
-
- @@ -115,13 +220,13 @@
-
- &uart1 {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_uart1_1>;
- + pinctrl-0 = <&pinctrl_uart1>;
- status = "okay";
- };
-
- &uart3 {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_uart3_2>;
- + pinctrl-0 = <&pinctrl_uart3>;
- fsl,uart-has-rtscts;
- status = "okay";
- };
- @@ -132,7 +237,7 @@
-
- &usbotg {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usbotg_1>;
- + pinctrl-0 = <&pinctrl_usbotg>;
- disable-over-current;
- dr_mode = "peripheral";
- status = "okay";
- @@ -140,21 +245,21 @@
-
- &usdhc1 {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usdhc1_2>;
- + pinctrl-0 = <&pinctrl_usdhc1>;
- cd-gpios = <&gpio1 2 0>;
- status = "okay";
- };
-
- &usdhc2 {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usdhc2_2>;
- + pinctrl-0 = <&pinctrl_usdhc2>;
- non-removable;
- status = "okay";
- };
-
- &usdhc3 {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usdhc3_2>;
- + pinctrl-0 = <&pinctrl_usdhc3>;
- cd-gpios = <&gpio3 9 0>;
- status = "okay";
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts linux-3.14.35/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts 2015-03-08 14:27:37.397684503 -0500
- @@ -0,0 +1,432 @@
- +/*
- + * Copyright 2013 Data Modul AG
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/dts-v1/;
- +
- +#include <dt-bindings/gpio/gpio.h>
- +#include "imx6q.dtsi"
- +
- +/ {
- + model = "Data Modul eDM-QMX6 Board";
- + compatible = "dmo,imx6q-edmqmx6", "fsl,imx6q";
- +
- + chosen {
- + stdout-path = &uart2;
- + };
- +
- + aliases {
- + gpio7 = &stmpe_gpio1;
- + gpio8 = &stmpe_gpio2;
- + stmpe-i2c0 = &stmpe1;
- + stmpe-i2c1 = &stmpe2;
- + };
- +
- + memory {
- + reg = <0x10000000 0x80000000>;
- + };
- +
- + regulators {
- + compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + reg_3p3v: regulator@0 {
- + compatible = "regulator-fixed";
- + reg = <0>;
- + regulator-name = "3P3V";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + reg_usb_otg_switch: regulator@1 {
- + compatible = "regulator-fixed";
- + reg = <1>;
- + regulator-name = "usb_otg_switch";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + gpio = <&gpio7 12 0>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + reg_usb_host1: regulator@2 {
- + compatible = "regulator-fixed";
- + reg = <2>;
- + regulator-name = "usb_host1_en";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + gpio = <&gpio3 31 0>;
- + enable-active-high;
- + };
- + };
- +
- + gpio-leds {
- + compatible = "gpio-leds";
- +
- + led-blue {
- + label = "blue";
- + gpios = <&stmpe_gpio1 8 GPIO_ACTIVE_HIGH>;
- + linux,default-trigger = "heartbeat";
- + };
- +
- + led-green {
- + label = "green";
- + gpios = <&stmpe_gpio1 9 GPIO_ACTIVE_HIGH>;
- + };
- +
- + led-pink {
- + label = "pink";
- + gpios = <&stmpe_gpio1 10 GPIO_ACTIVE_HIGH>;
- + };
- +
- + led-red {
- + label = "red";
- + gpios = <&stmpe_gpio1 11 GPIO_ACTIVE_HIGH>;
- + };
- + };
- +};
- +
- +&ecspi5 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_ecspi5>;
- + fsl,spi-num-chipselects = <1>;
- + cs-gpios = <&gpio1 12 0>;
- + status = "okay";
- +
- + flash: m25p80@0 {
- + compatible = "m25p80";
- + spi-max-frequency = <40000000>;
- + reg = <0>;
- + };
- +};
- +
- +&fec {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_enet>;
- + phy-mode = "rgmii";
- + phy-reset-gpios = <&gpio3 23 0>;
- + phy-supply = <&vgen2_1v2_eth>;
- + status = "okay";
- +};
- +
- +&i2c2 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c2
- + &pinctrl_stmpe1
- + &pinctrl_stmpe2
- + &pinctrl_pfuze>;
- + status = "okay";
- +
- + pmic: pfuze100@08 {
- + compatible = "fsl,pfuze100";
- + reg = <0x08>;
- + interrupt-parent = <&gpio3>;
- + interrupts = <20 8>;
- +
- + regulators {
- + sw1a_reg: sw1ab {
- + regulator-min-microvolt = <300000>;
- + regulator-max-microvolt = <1875000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw1c_reg: sw1c {
- + regulator-min-microvolt = <300000>;
- + regulator-max-microvolt = <1875000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw2_reg: sw2 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw3a_reg: sw3a {
- + regulator-min-microvolt = <400000>;
- + regulator-max-microvolt = <1975000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw3b_reg: sw3b {
- + regulator-min-microvolt = <400000>;
- + regulator-max-microvolt = <1975000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw4_reg: sw4 {
- + regulator-min-microvolt = <400000>;
- + regulator-max-microvolt = <1975000>;
- + regulator-always-on;
- + };
- +
- + swbst_reg: swbst {
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5150000>;
- + regulator-always-on;
- + };
- +
- + snvs_reg: vsnvs {
- + regulator-min-microvolt = <1000000>;
- + regulator-max-microvolt = <3000000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + vref_reg: vrefddr {
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + vgen1_reg: vgen1 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <1550000>;
- + };
- +
- + vgen2_1v2_eth: vgen2 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <1550000>;
- + };
- +
- + vdd_high_in: vgen3 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + vgen4_reg: vgen4 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vgen5_reg: vgen5 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vgen6_reg: vgen6 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- + };
- + };
- +
- + stmpe1: stmpe1601@40 {
- + compatible = "st,stmpe1601";
- + reg = <0x40>;
- + interrupts = <30 0>;
- + interrupt-parent = <&gpio3>;
- + vcc-supply = <&sw2_reg>;
- + vio-supply = <&sw2_reg>;
- +
- + stmpe_gpio1: stmpe_gpio {
- + #gpio-cells = <2>;
- + compatible = "st,stmpe-gpio";
- + };
- + };
- +
- + stmpe2: stmpe1601@44 {
- + compatible = "st,stmpe1601";
- + reg = <0x44>;
- + interrupts = <2 0>;
- + interrupt-parent = <&gpio5>;
- + vcc-supply = <&sw2_reg>;
- + vio-supply = <&sw2_reg>;
- +
- + stmpe_gpio2: stmpe_gpio {
- + #gpio-cells = <2>;
- + compatible = "st,stmpe-gpio";
- + };
- + };
- +
- + temp1: ad7414@4c {
- + compatible = "ad,ad7414";
- + reg = <0x4c>;
- + };
- +
- + temp2: ad7414@4d {
- + compatible = "ad,ad7414";
- + reg = <0x4d>;
- + };
- +
- + rtc: m41t62@68 {
- + compatible = "stm,m41t62";
- + reg = <0x68>;
- + };
- +};
- +
- +&iomuxc {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hog>;
- +
- + imx6q-dmo-edmqmx6 {
- + pinctrl_hog: hoggrp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x80000000
- + MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x80000000
- + >;
- + };
- +
- + pinctrl_ecspi5: ecspi5rp-1 {
- + fsl,pins = <
- + MX6QDL_PAD_SD1_DAT0__ECSPI5_MISO 0x80000000
- + MX6QDL_PAD_SD1_CMD__ECSPI5_MOSI 0x80000000
- + MX6QDL_PAD_SD1_CLK__ECSPI5_SCLK 0x80000000
- + MX6QDL_PAD_SD2_DAT3__GPIO1_IO12 0x80000000
- + >;
- + };
- +
- + pinctrl_enet: enetgrp {
- + fsl,pins = <
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- + >;
- + };
- +
- + pinctrl_i2c2: i2c2grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
- + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_pfuze: pfuze100grp1 {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x80000000
- + >;
- + };
- +
- + pinctrl_stmpe1: stmpe1grp {
- + fsl,pins = <MX6QDL_PAD_EIM_D30__GPIO3_IO30 0x80000000>;
- + };
- +
- + pinctrl_stmpe2: stmpe2grp {
- + fsl,pins = <MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x80000000>;
- + };
- +
- + pinctrl_uart1: uart1grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
- + MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart2: uart2grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
- + MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usbotg: usbotggrp {
- + fsl,pins = <
- + MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc3: usdhc3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc4: usdhc4grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- + MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- + MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- + MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- + MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- + MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- + MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
- + MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
- + MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
- + MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
- + >;
- + };
- + };
- +};
- +
- +&sata {
- + status = "okay";
- +};
- +
- +&uart1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart1>;
- + status = "okay";
- +};
- +
- +&uart2 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart2>;
- + status = "okay";
- +};
- +
- +&usbh1 {
- + vbus-supply = <®_usb_host1>;
- + disable-over-current;
- + dr_mode = "host";
- + status = "okay";
- +};
- +
- +&usbotg {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usbotg>;
- + disable-over-current;
- + status = "okay";
- +};
- +
- +&usdhc3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc3>;
- + vmmc-supply = <®_3p3v>;
- + status = "okay";
- +};
- +
- +&usdhc4 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc4>;
- + vmmc-supply = <®_3p3v>;
- + non-removable;
- + bus-width = <8>;
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q.dtsi linux-3.14.35/arch/arm/boot/dts/imx6q.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q.dtsi 2015-03-08 14:27:37.397684503 -0500
- @@ -8,10 +8,16 @@
- *
- */
-
- +#include <dt-bindings/interrupt-controller/irq.h>
- #include "imx6q-pinfunc.h"
- #include "imx6qdl.dtsi"
-
- / {
- + aliases {
- + ipu1 = &ipu2;
- + spi4 = &ecspi5;
- + };
- +
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
- @@ -25,8 +31,17 @@
- /* kHz uV */
- 1200000 1275000
- 996000 1250000
- + 852000 1250000
- 792000 1150000
- - 396000 950000
- + 396000 975000
- + >;
- + fsl,soc-operating-points = <
- + /* ARM kHz SOC-PU uV */
- + 1200000 1275000
- + 996000 1250000
- + 852000 1250000
- + 792000 1175000
- + 396000 1175000
- >;
- clock-latency = <61036>; /* two CLK32 periods */
- clocks = <&clks 104>, <&clks 6>, <&clks 16>,
- @@ -61,12 +76,77 @@
- };
-
- soc {
- +
- + busfreq { /* BUSFREQ */
- + compatible = "fsl,imx6_busfreq";
- + clocks = <&clks 171>, <&clks 6>, <&clks 11>, <&clks 104>, <&clks 172>, <&clks 58>,
- + <&clks 18>, <&clks 60>, <&clks 20>, <&clks 3>;
- + clock-names = "pll2_bus", "pll2_pfd2_396m", "pll2_198m", "arm", "pll3_usb_otg", "periph",
- + "periph_pre", "periph_clk2", "periph_clk2_sel", "osc";
- + interrupts = <0 107 0x04>, <0 112 0x4>, <0 113 0x4>, <0 114 0x4>;
- + interrupt-names = "irq_busfreq_0", "irq_busfreq_1", "irq_busfreq_2", "irq_busfreq_3";
- + fsl,max_ddr_freq = <528000000>;
- + };
- +
- + gpu@00130000 {
- + compatible = "fsl,imx6q-gpu";
- + reg = <0x00130000 0x4000>, <0x00134000 0x4000>,
- + <0x02204000 0x4000>, <0x0 0x0>;
- + reg-names = "iobase_3d", "iobase_2d",
- + "iobase_vg", "phys_baseaddr";
- + interrupts = <0 9 0x04>, <0 10 0x04>,<0 11 0x04>;
- + interrupt-names = "irq_3d", "irq_2d", "irq_vg";
- + clocks = <&clks 26>, <&clks 143>,
- + <&clks 27>, <&clks 121>,
- + <&clks 122>, <&clks 74>;
- + clock-names = "gpu2d_axi_clk", "openvg_axi_clk",
- + "gpu3d_axi_clk", "gpu2d_clk",
- + "gpu3d_clk", "gpu3d_shader_clk";
- + resets = <&src 0>, <&src 3>, <&src 3>;
- + reset-names = "gpu3d", "gpu2d", "gpuvg";
- + pu-supply = <®_pu>;
- + };
- +
- ocram: sram@00900000 {
- compatible = "mmio-sram";
- reg = <0x00900000 0x40000>;
- clocks = <&clks 142>;
- };
-
- + hdmi_core: hdmi_core@00120000 {
- + compatible = "fsl,imx6q-hdmi-core";
- + reg = <0x00120000 0x9000>;
- + clocks = <&clks 124>, <&clks 123>;
- + clock-names = "hdmi_isfr", "hdmi_iahb";
- + status = "disabled";
- + };
- +
- + hdmi_video: hdmi_video@020e0000 {
- + compatible = "fsl,imx6q-hdmi-video";
- + reg = <0x020e0000 0x1000>;
- + reg-names = "hdmi_gpr";
- + interrupts = <0 115 0x04>;
- + clocks = <&clks 124>, <&clks 123>;
- + clock-names = "hdmi_isfr", "hdmi_iahb";
- + status = "disabled";
- + };
- +
- + hdmi_audio: hdmi_audio@00120000 {
- + compatible = "fsl,imx6q-hdmi-audio";
- + clocks = <&clks 124>, <&clks 123>;
- + clock-names = "hdmi_isfr", "hdmi_iahb";
- + dmas = <&sdma 2 23 0>;
- + dma-names = "tx";
- + status = "disabled";
- + };
- +
- + hdmi_cec: hdmi_cec@00120000 {
- + compatible = "fsl,imx6q-hdmi-cec";
- + interrupts = <0 115 0x04>;
- + status = "disabled";
- + };
- +
- +
- aips-bus@02000000 { /* AIPS1 */
- spba-bus@02000000 {
- ecspi5: ecspi@02018000 {
- @@ -74,13 +154,17 @@
- #size-cells = <0>;
- compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
- reg = <0x02018000 0x4000>;
- - interrupts = <0 35 0x04>;
- + interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 116>, <&clks 116>;
- clock-names = "ipg", "per";
- status = "disabled";
- };
- };
-
- + vpu@02040000 {
- + status = "okay";
- + };
- +
- iomuxc: iomuxc@020e0000 {
- compatible = "fsl,imx6q-iomuxc";
-
- @@ -122,40 +206,40 @@
- };
- };
-
- + aips-bus@02100000 { /* AIPS2 */
- + mipi_dsi: mipi@021e0000 {
- + compatible = "fsl,imx6q-mipi-dsi";
- + reg = <0x021e0000 0x4000>;
- + interrupts = <0 102 0x04>;
- + gpr = <&gpr>;
- + clocks = <&clks 138>, <&clks 209>;
- + clock-names = "mipi_pllref_clk", "mipi_cfg_clk";
- + status = "disabled";
- + };
- + };
- +
- sata: sata@02200000 {
- compatible = "fsl,imx6q-ahci";
- reg = <0x02200000 0x4000>;
- - interrupts = <0 39 0x04>;
- + interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 154>, <&clks 187>, <&clks 105>;
- clock-names = "sata", "sata_ref", "ahb";
- status = "disabled";
- };
-
- ipu2: ipu@02800000 {
- - #crtc-cells = <1>;
- compatible = "fsl,imx6q-ipu";
- reg = <0x02800000 0x400000>;
- - interrupts = <0 8 0x4 0 7 0x4>;
- - clocks = <&clks 133>, <&clks 134>, <&clks 137>;
- - clock-names = "bus", "di0", "di1";
- + interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>,
- + <0 7 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&clks 133>, <&clks 134>, <&clks 137>,
- + <&clks 41>, <&clks 42>,
- + <&clks 135>, <&clks 136>;
- + clock-names = "bus", "di0", "di1",
- + "di0_sel", "di1_sel",
- + "ldb_di0", "ldb_di1";
- resets = <&src 4>;
- + bypass_reset = <0>;
- };
- };
- };
- -
- -&ldb {
- - clocks = <&clks 33>, <&clks 34>,
- - <&clks 39>, <&clks 40>, <&clks 41>, <&clks 42>,
- - <&clks 135>, <&clks 136>;
- - clock-names = "di0_pll", "di1_pll",
- - "di0_sel", "di1_sel", "di2_sel", "di3_sel",
- - "di0", "di1";
- -
- - lvds-channel@0 {
- - crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
- - };
- -
- - lvds-channel@1 {
- - crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
- - };
- -};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-gk802.dts linux-3.14.35/arch/arm/boot/dts/imx6q-gk802.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-gk802.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-gk802.dts 2015-03-08 14:27:37.397684503 -0500
- @@ -0,0 +1,229 @@
- +/*
- + * Copyright (C) 2013 Philipp Zabel
- + *
- + * This file is licensed under the terms of the GNU General Public License
- + * version 2. This program is licensed "as is" without any warranty of any
- + * kind, whether express or implied.
- + */
- +
- +/dts-v1/;
- +#include "imx6q.dtsi"
- +
- +/ {
- + model = "Zealz GK802";
- + compatible = "zealz,imx6q-gk802", "fsl,imx6q";
- +
- + aliases {
- + mxcfb0 = &mxcfb1;
- + };
- +
- + chosen {
- + stdout-path = &uart4;
- + };
- +
- + memory {
- + reg = <0x10000000 0x40000000>;
- + };
- +
- + regulators {
- + compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + reg_3p3v: regulator@0 {
- + compatible = "regulator-fixed";
- + reg = <0>;
- + regulator-name = "3P3V";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + reg_usb_h1_vbus: usb_h1_vbus {
- + compatible = "regulator-fixed";
- + regulator-name = "usb_h1_vbus";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + gpio = <&gpio2 0 0>;
- + };
- + };
- +
- + gpio-keys {
- + compatible = "gpio-keys";
- +
- + recovery-button {
- + label = "recovery";
- + gpios = <&gpio3 16 1>;
- + linux,code = <0x198>; /* KEY_RESTART */
- + gpio-key,wakeup;
- + };
- +
- + };
- +
- + sound-hdmi {
- + compatible = "fsl,imx6q-audio-hdmi",
- + "fsl,imx-audio-hdmi";
- + model = "imx-audio-hdmi";
- + hdmi-controller = <&hdmi_audio>;
- + };
- +
- + mxcfb1: fb@0 {
- + compatible = "fsl,mxc_sdc_fb";
- + disp_dev = "hdmi";
- + interface_pix_fmt = "RGB24";
- + mode_str ="1920x1080M@60";
- + default_bpp = <32>;
- + int_clk = <0>;
- + late_init = <0>;
- + status = "okay";
- + };
- +};
- +
- +&hdmi_core {
- + ipu_id = <0>;
- + disp_id = <0>;
- + status = "okay";
- +};
- +
- +&hdmi_video {
- + fsl,phy_reg_vlev = <0x0294>;
- + fsl,phy_reg_cksymtx = <0x800d>;
- + status = "okay";
- +};
- +
- +&hdmi_audio {
- + status = "okay";
- +};
- +
- +
- +/* Internal I2C */
- +&i2c2 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c2>;
- + clock-frequency = <100000>;
- + status = "okay";
- +
- + /* SDMC DM2016 1024 bit EEPROM + 128 bit OTP */
- + eeprom: dm2016@51 {
- + compatible = "sdmc,dm2016";
- + reg = <0x51>;
- + };
- +};
- +
- +/* External I2C via HDMI */
- +&i2c3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c3>;
- + clock-frequency = <100000>;
- + status = "okay";
- +
- + ddc: imx6_hdmi_i2c@50 {
- + compatible = "fsl,imx6-hdmi-i2c";
- + reg = <0x50>;
- + };
- +};
- +
- +&iomuxc {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hog>;
- +
- + imx6q-gk802 {
- + pinctrl_hog: hoggrp {
- + fsl,pins = <
- + /* Recovery button, active-low */
- + MX6QDL_PAD_EIM_D16__GPIO3_IO16 0x100b1
- + /* RTL8192CU enable GPIO, active-low */
- + MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x1b0b0
- + >;
- + };
- +
- + pinctrl_i2c2: i2c2grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_i2c3: i2c3grp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
- + MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_uart4: uart4grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
- + MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usdhc3: usdhc3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc4: usdhc4grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- + MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- + MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- + MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- + MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- + MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- + >;
- + };
- + };
- +};
- +
- +&uart2 {
- + status = "okay";
- +};
- +
- +&uart4 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart4>;
- + status = "okay";
- +};
- +
- +/* External USB-A port (USBOTG) */
- +&usbotg {
- + phy_type = "utmi";
- + dr_mode = "host";
- + disable-over-current;
- + status = "okay";
- +};
- +
- +/* Internal USB port (USBH1), connected to RTL8192CU */
- +&usbh1 {
- + phy_type = "utmi";
- + dr_mode = "host";
- + vbus-supply = <®_usb_h1_vbus>;
- + disable-over-current;
- + status = "okay";
- +};
- +
- +/* External microSD */
- +&usdhc3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc3>;
- + bus-width = <4>;
- + cd-gpios = <&gpio6 11 0>;
- + vmmc-supply = <®_3p3v>;
- + status = "okay";
- +};
- +
- +/* Internal microSD */
- +&usdhc4 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc4>;
- + bus-width = <4>;
- + vmmc-supply = <®_3p3v>;
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-gw51xx.dts linux-3.14.35/arch/arm/boot/dts/imx6q-gw51xx.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-gw51xx.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-gw51xx.dts 2015-03-08 14:27:37.397684503 -0500
- @@ -0,0 +1,19 @@
- +/*
- + * Copyright 2013 Gateworks Corporation
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/dts-v1/;
- +#include "imx6q.dtsi"
- +#include "imx6qdl-gw54xx.dtsi"
- +
- +/ {
- + model = "Gateworks Ventana i.MX6 Quad GW51XX";
- + compatible = "gw,imx6q-gw51xx", "gw,ventana", "fsl,imx6q";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-gw52xx.dts linux-3.14.35/arch/arm/boot/dts/imx6q-gw52xx.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-gw52xx.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-gw52xx.dts 2015-03-08 14:27:37.397684503 -0500
- @@ -0,0 +1,23 @@
- +/*
- + * Copyright 2013 Gateworks Corporation
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/dts-v1/;
- +#include "imx6q.dtsi"
- +#include "imx6qdl-gw52xx.dtsi"
- +
- +/ {
- + model = "Gateworks Ventana i.MX6 Quad GW52XX";
- + compatible = "gw,imx6q-gw52xx", "gw,ventana", "fsl,imx6q";
- +};
- +
- +&sata {
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-gw53xx.dts linux-3.14.35/arch/arm/boot/dts/imx6q-gw53xx.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-gw53xx.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-gw53xx.dts 2015-03-08 14:27:37.397684503 -0500
- @@ -0,0 +1,23 @@
- +/*
- + * Copyright 2013 Gateworks Corporation
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/dts-v1/;
- +#include "imx6q.dtsi"
- +#include "imx6qdl-gw53xx.dtsi"
- +
- +/ {
- + model = "Gateworks Ventana i.MX6 Quad GW53XX";
- + compatible = "gw,imx6q-gw53xx", "gw,ventana", "fsl,imx6q";
- +};
- +
- +&sata {
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-gw5400-a.dts linux-3.14.35/arch/arm/boot/dts/imx6q-gw5400-a.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-gw5400-a.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-gw5400-a.dts 2015-03-08 14:27:37.401684503 -0500
- @@ -0,0 +1,543 @@
- +/*
- + * Copyright 2013 Gateworks Corporation
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/dts-v1/;
- +#include "imx6q.dtsi"
- +
- +/ {
- + model = "Gateworks Ventana GW5400-A";
- + compatible = "gw,imx6q-gw5400-a", "gw,ventana", "fsl,imx6q";
- +
- + /* these are used by bootloader for disabling nodes */
- + aliases {
- + ethernet0 = &fec;
- + ethernet1 = ð1;
- + i2c0 = &i2c1;
- + i2c1 = &i2c2;
- + i2c2 = &i2c3;
- + led0 = &led0;
- + led1 = &led1;
- + led2 = &led2;
- + sky2 = ð1;
- + ssi0 = &ssi1;
- + spi0 = &ecspi1;
- + usb0 = &usbh1;
- + usb1 = &usbotg;
- + usdhc2 = &usdhc3;
- + };
- +
- + chosen {
- + bootargs = "console=ttymxc1,115200";
- + };
- +
- + leds {
- + compatible = "gpio-leds";
- +
- + led0: user1 {
- + label = "user1";
- + gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */
- + default-state = "on";
- + linux,default-trigger = "heartbeat";
- + };
- +
- + led1: user2 {
- + label = "user2";
- + gpios = <&gpio4 10 0>; /* 106 -> MX6_PANLEDR */
- + default-state = "off";
- + };
- +
- + led2: user3 {
- + label = "user3";
- + gpios = <&gpio4 15 1>; /* 111 -> MX6_LOCLED# */
- + default-state = "off";
- + };
- + };
- +
- + memory {
- + reg = <0x10000000 0x40000000>;
- + };
- +
- + pps {
- + compatible = "pps-gpio";
- + gpios = <&gpio1 5 0>;
- + status = "okay";
- + };
- +
- + regulators {
- + compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + reg_1p0v: regulator@0 {
- + compatible = "regulator-fixed";
- + reg = <0>;
- + regulator-name = "1P0V";
- + regulator-min-microvolt = <1000000>;
- + regulator-max-microvolt = <1000000>;
- + regulator-always-on;
- + };
- +
- + reg_3p3v: regulator@1 {
- + compatible = "regulator-fixed";
- + reg = <1>;
- + regulator-name = "3P3V";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + reg_usb_h1_vbus: regulator@2 {
- + compatible = "regulator-fixed";
- + reg = <2>;
- + regulator-name = "usb_h1_vbus";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + regulator-always-on;
- + };
- +
- + reg_usb_otg_vbus: regulator@3 {
- + compatible = "regulator-fixed";
- + reg = <3>;
- + regulator-name = "usb_otg_vbus";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + gpio = <&gpio3 22 0>;
- + enable-active-high;
- + };
- + };
- +
- + sound {
- + compatible = "fsl,imx6q-sabrelite-sgtl5000",
- + "fsl,imx-audio-sgtl5000";
- + model = "imx6q-sabrelite-sgtl5000";
- + ssi-controller = <&ssi1>;
- + audio-codec = <&codec>;
- + audio-routing =
- + "MIC_IN", "Mic Jack",
- + "Mic Jack", "Mic Bias",
- + "Headphone Jack", "HP_OUT";
- + mux-int-port = <1>;
- + mux-ext-port = <4>;
- + };
- +};
- +
- +&audmux {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_audmux>;
- + status = "okay";
- +};
- +
- +&ecspi1 {
- + fsl,spi-num-chipselects = <1>;
- + cs-gpios = <&gpio3 19 0>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_ecspi1>;
- + status = "okay";
- +
- + flash: m25p80@0 {
- + compatible = "sst,w25q256";
- + spi-max-frequency = <30000000>;
- + reg = <0>;
- + };
- +};
- +
- +&fec {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_enet>;
- + phy-mode = "rgmii";
- + phy-reset-gpios = <&gpio1 30 0>;
- + status = "okay";
- +};
- +
- +&i2c1 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c1>;
- + status = "okay";
- +
- + eeprom1: eeprom@50 {
- + compatible = "atmel,24c02";
- + reg = <0x50>;
- + pagesize = <16>;
- + };
- +
- + eeprom2: eeprom@51 {
- + compatible = "atmel,24c02";
- + reg = <0x51>;
- + pagesize = <16>;
- + };
- +
- + eeprom3: eeprom@52 {
- + compatible = "atmel,24c02";
- + reg = <0x52>;
- + pagesize = <16>;
- + };
- +
- + eeprom4: eeprom@53 {
- + compatible = "atmel,24c02";
- + reg = <0x53>;
- + pagesize = <16>;
- + };
- +
- + gpio: pca9555@23 {
- + compatible = "nxp,pca9555";
- + reg = <0x23>;
- + gpio-controller;
- + #gpio-cells = <2>;
- + };
- +
- + hwmon: gsc@29 {
- + compatible = "gw,gsp";
- + reg = <0x29>;
- + };
- +
- + rtc: ds1672@68 {
- + compatible = "dallas,ds1672";
- + reg = <0x68>;
- + };
- +};
- +
- +&i2c2 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c2>;
- + status = "okay";
- +
- + pmic: pfuze100@08 {
- + compatible = "fsl,pfuze100";
- + reg = <0x08>;
- +
- + regulators {
- + sw1a_reg: sw1ab {
- + regulator-min-microvolt = <300000>;
- + regulator-max-microvolt = <1875000>;
- + regulator-boot-on;
- + regulator-always-on;
- + regulator-ramp-delay = <6250>;
- + };
- +
- + sw1c_reg: sw1c {
- + regulator-min-microvolt = <300000>;
- + regulator-max-microvolt = <1875000>;
- + regulator-boot-on;
- + regulator-always-on;
- + regulator-ramp-delay = <6250>;
- + };
- +
- + sw2_reg: sw2 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <3950000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw3a_reg: sw3a {
- + regulator-min-microvolt = <400000>;
- + regulator-max-microvolt = <1975000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw3b_reg: sw3b {
- + regulator-min-microvolt = <400000>;
- + regulator-max-microvolt = <1975000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw4_reg: sw4 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <3300000>;
- + };
- +
- + swbst_reg: swbst {
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5150000>;
- + };
- +
- + snvs_reg: vsnvs {
- + regulator-min-microvolt = <1000000>;
- + regulator-max-microvolt = <3000000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + vref_reg: vrefddr {
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + vgen1_reg: vgen1 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <1550000>;
- + };
- +
- + vgen2_reg: vgen2 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <1550000>;
- + };
- +
- + vgen3_reg: vgen3 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + };
- +
- + vgen4_reg: vgen4 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vgen5_reg: vgen5 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vgen6_reg: vgen6 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- + };
- + };
- +
- + pciswitch: pex8609@3f {
- + compatible = "plx,pex8609";
- + reg = <0x3f>;
- + };
- +
- + pciclkgen: si52147@6b {
- + compatible = "sil,si52147";
- + reg = <0x6b>;
- + };
- +};
- +
- +&i2c3 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c3>;
- + status = "okay";
- +
- + accelerometer: mma8450@1c {
- + compatible = "fsl,mma8450";
- + reg = <0x1c>;
- + };
- +
- + codec: sgtl5000@0a {
- + compatible = "fsl,sgtl5000";
- + reg = <0x0a>;
- + clocks = <&clks 201>;
- + VDDA-supply = <&sw4_reg>;
- + VDDIO-supply = <®_3p3v>;
- + };
- +
- + hdmiin: adv7611@4c {
- + compatible = "adi,adv7611";
- + reg = <0x4c>;
- + };
- +
- + touchscreen: egalax_ts@04 {
- + compatible = "eeti,egalax_ts";
- + reg = <0x04>;
- + interrupt-parent = <&gpio7>;
- + interrupts = <12 2>; /* gpio7_12 active low */
- + wakeup-gpios = <&gpio7 12 0>;
- + };
- +
- + videoout: adv7393@2a {
- + compatible = "adi,adv7393";
- + reg = <0x2a>;
- + };
- +
- + videoin: adv7180@20 {
- + compatible = "adi,adv7180";
- + reg = <0x20>;
- + };
- +};
- +
- +&iomuxc {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hog>;
- +
- + imx6q-gw5400-a {
- + pinctrl_hog: hoggrp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000 /* OTG_PWR_EN */
- + MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x80000000 /* SPINOR_CS0# */
- + MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x80000000 /* PCIE IRQ */
- + MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* PCIE RST */
- + MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x000130b0 /* AUD4_MCK */
- + MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x80000000 /* GPS_PPS */
- + MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000 /* TOUCH_IRQ# */
- + MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x80000000 /* user1 led */
- + MX6QDL_PAD_KEY_COL2__GPIO4_IO10 0x80000000 /* user2 led */
- + MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x80000000 /* user3 led */
- + MX6QDL_PAD_SD1_DAT0__GPIO1_IO16 0x80000000 /* USBHUB_RST# */
- + MX6QDL_PAD_SD1_DAT3__GPIO1_IO21 0x80000000 /* MIPI_DIO */
- + >;
- + };
- +
- + pinctrl_audmux: audmuxgrp {
- + fsl,pins = <
- + MX6QDL_PAD_SD2_DAT0__AUD4_RXD 0x130b0
- + MX6QDL_PAD_SD2_DAT3__AUD4_TXC 0x130b0
- + MX6QDL_PAD_SD2_DAT2__AUD4_TXD 0x110b0
- + MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x130b0
- + >;
- + };
- +
- + pinctrl_ecspi1: ecspi1grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
- + MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
- + MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
- + >;
- + };
- +
- + pinctrl_enet: enetgrp {
- + fsl,pins = <
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- + >;
- + };
- +
- + pinctrl_i2c1: i2c1grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- + MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_i2c2: i2c2grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_i2c3: i2c3grp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
- + MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_uart1: uart1grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
- + MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart2: uart2grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1
- + MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_uart5: uart5grp {
- + fsl,pins = <
- + MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1
- + MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usbotg: usbotggrp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc3: usdhc3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- + >;
- + };
- + };
- +};
- +
- +&ldb {
- + status = "okay";
- +};
- +
- +&pcie {
- + reset-gpio = <&gpio1 29 0>;
- + status = "okay";
- +
- + eth1: sky2@8 { /* MAC/PHY on bus 8 */
- + compatible = "marvell,sky2";
- + };
- +};
- +
- +&ssi1 {
- + fsl,mode = "i2s-slave";
- + status = "okay";
- +};
- +
- +&uart1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart1>;
- + status = "okay";
- +};
- +
- +&uart2 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart2>;
- + status = "okay";
- +};
- +
- +&uart5 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart5>;
- + status = "okay";
- +};
- +
- +&usbotg {
- + vbus-supply = <®_usb_otg_vbus>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usbotg>;
- + disable-over-current;
- + status = "okay";
- +};
- +
- +&usbh1 {
- + vbus-supply = <®_usb_h1_vbus>;
- + status = "okay";
- +};
- +
- +&usdhc3 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_usdhc3>;
- + cd-gpios = <&gpio7 0 0>;
- + vmmc-supply = <®_3p3v>;
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-gw54xx.dts linux-3.14.35/arch/arm/boot/dts/imx6q-gw54xx.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-gw54xx.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-gw54xx.dts 2015-03-08 14:27:37.401684503 -0500
- @@ -0,0 +1,23 @@
- +/*
- + * Copyright 2013 Gateworks Corporation
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/dts-v1/;
- +#include "imx6q.dtsi"
- +#include "imx6qdl-gw54xx.dtsi"
- +
- +/ {
- + model = "Gateworks Ventana i.MX6 Quad GW54XX";
- + compatible = "gw,imx6q-gw54xx", "gw,ventana", "fsl,imx6q";
- +};
- +
- +&sata {
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-hummingboard.dts linux-3.14.35/arch/arm/boot/dts/imx6q-hummingboard.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-hummingboard.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-hummingboard.dts 2015-03-08 14:27:37.401684503 -0500
- @@ -0,0 +1,21 @@
- +/*
- + * Copyright (C) 2014 Rabeeh Khoury (rabeeh@solid-run.com)
- + * Based on work by Russell King
- + */
- +/dts-v1/;
- +
- +#include "imx6q.dtsi"
- +#include "imx6qdl-hummingboard.dtsi"
- +
- +/ {
- + model = "SolidRun HummingBoard Dual/Quad";
- + compatible = "solidrun,hummingboard/q", "fsl,imx6q";
- +};
- +
- +&sata {
- + status = "okay";
- + fsl,transmit-level-mV = <1104>;
- + fsl,transmit-boost-mdB = <0>;
- + fsl,transmit-atten-16ths = <9>;
- + fsl,no-spread-spectrum;
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-nitrogen6x.dts linux-3.14.35/arch/arm/boot/dts/imx6q-nitrogen6x.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-nitrogen6x.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-nitrogen6x.dts 2015-03-08 14:27:37.401684503 -0500
- @@ -0,0 +1,25 @@
- +/*
- + * Copyright 2013 Boundary Devices, Inc.
- + * Copyright 2012 Freescale Semiconductor, Inc.
- + * Copyright 2011 Linaro Ltd.
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/dts-v1/;
- +#include "imx6q.dtsi"
- +#include "imx6qdl-nitrogen6x.dtsi"
- +
- +/ {
- + model = "Freescale i.MX6 Quad Nitrogen6x Board";
- + compatible = "fsl,imx6q-nitrogen6x", "fsl,imx6q";
- +};
- +
- +&sata {
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-phytec-pbab01.dts linux-3.14.35/arch/arm/boot/dts/imx6q-phytec-pbab01.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-phytec-pbab01.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-phytec-pbab01.dts 2015-03-08 14:27:37.401684503 -0500
- @@ -11,24 +11,17 @@
-
- /dts-v1/;
- #include "imx6q-phytec-pfla02.dtsi"
- +#include "imx6qdl-phytec-pbab01.dtsi"
-
- / {
- model = "Phytec phyFLEX-i.MX6 Quad Carrier-Board";
- compatible = "phytec,imx6q-pbab01", "phytec,imx6q-pfla02", "fsl,imx6q";
- -};
- -
- -&fec {
- - status = "okay";
- -};
- -
- -&uart4 {
- - status = "okay";
- -};
-
- -&usdhc2 {
- - status = "okay";
- + chosen {
- + stdout-path = &uart4;
- + };
- };
-
- -&usdhc3 {
- - status = "okay";
- +&sata {
- + status = "okay";
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi linux-3.14.35/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi 2015-03-08 14:27:37.401684503 -0500
- @@ -10,171 +10,13 @@
- */
-
- #include "imx6q.dtsi"
- +#include "imx6qdl-phytec-pfla02.dtsi"
-
- / {
- - model = "Phytec phyFLEX-i.MX6 Ouad";
- + model = "Phytec phyFLEX-i.MX6 Quad";
- compatible = "phytec,imx6q-pfla02", "fsl,imx6q";
-
- memory {
- reg = <0x10000000 0x80000000>;
- };
- };
- -
- -&ecspi3 {
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_ecspi3_1>;
- - status = "okay";
- - fsl,spi-num-chipselects = <1>;
- - cs-gpios = <&gpio4 24 0>;
- -
- - flash@0 {
- - compatible = "m25p80";
- - spi-max-frequency = <20000000>;
- - reg = <0>;
- - };
- -};
- -
- -&i2c1 {
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_i2c1_1>;
- - status = "okay";
- -
- - eeprom@50 {
- - compatible = "atmel,24c32";
- - reg = <0x50>;
- - };
- -
- - pmic@58 {
- - compatible = "dialog,da9063";
- - reg = <0x58>;
- - interrupt-parent = <&gpio4>;
- - interrupts = <17 0x8>; /* active-low GPIO4_17 */
- -
- - regulators {
- - vddcore_reg: bcore1 {
- - regulator-min-microvolt = <730000>;
- - regulator-max-microvolt = <1380000>;
- - regulator-always-on;
- - };
- -
- - vddsoc_reg: bcore2 {
- - regulator-min-microvolt = <730000>;
- - regulator-max-microvolt = <1380000>;
- - regulator-always-on;
- - };
- -
- - vdd_ddr3_reg: bpro {
- - regulator-min-microvolt = <1500000>;
- - regulator-max-microvolt = <1500000>;
- - regulator-always-on;
- - };
- -
- - vdd_3v3_reg: bperi {
- - regulator-min-microvolt = <3300000>;
- - regulator-max-microvolt = <3300000>;
- - regulator-always-on;
- - };
- -
- - vdd_buckmem_reg: bmem {
- - regulator-min-microvolt = <3300000>;
- - regulator-max-microvolt = <3300000>;
- - regulator-always-on;
- - };
- -
- - vdd_eth_reg: bio {
- - regulator-min-microvolt = <1200000>;
- - regulator-max-microvolt = <1200000>;
- - regulator-always-on;
- - };
- -
- - vdd_eth_io_reg: ldo4 {
- - regulator-min-microvolt = <2500000>;
- - regulator-max-microvolt = <2500000>;
- - regulator-always-on;
- - };
- -
- - vdd_mx6_snvs_reg: ldo5 {
- - regulator-min-microvolt = <3000000>;
- - regulator-max-microvolt = <3000000>;
- - regulator-always-on;
- - };
- -
- - vdd_3v3_pmic_io_reg: ldo6 {
- - regulator-min-microvolt = <3300000>;
- - regulator-max-microvolt = <3300000>;
- - regulator-always-on;
- - };
- -
- - vdd_sd0_reg: ldo9 {
- - regulator-min-microvolt = <3300000>;
- - regulator-max-microvolt = <3300000>;
- - };
- -
- - vdd_sd1_reg: ldo10 {
- - regulator-min-microvolt = <3300000>;
- - regulator-max-microvolt = <3300000>;
- - };
- -
- - vdd_mx6_high_reg: ldo11 {
- - regulator-min-microvolt = <3000000>;
- - regulator-max-microvolt = <3000000>;
- - regulator-always-on;
- - };
- - };
- - };
- -};
- -
- -&iomuxc {
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_hog>;
- -
- - hog {
- - pinctrl_hog: hoggrp {
- - fsl,pins = <
- - MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000
- - MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */
- - MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x80000000 /* PMIC interrupt */
- - >;
- - };
- - };
- -
- - pfla02 {
- - pinctrl_usdhc3_pfla02: usdhc3grp-pfla02 {
- - fsl,pins = <
- - MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000
- - MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
- - >;
- - };
- - };
- -};
- -
- -&fec {
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_enet_3>;
- - phy-mode = "rgmii";
- - phy-reset-gpios = <&gpio3 23 0>;
- - status = "disabled";
- -};
- -
- -&uart4 {
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_uart4_1>;
- - status = "disabled";
- -};
- -
- -&usdhc2 {
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usdhc2_2>;
- - cd-gpios = <&gpio1 4 0>;
- - wp-gpios = <&gpio1 2 0>;
- - status = "disabled";
- -};
- -
- -&usdhc3 {
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usdhc3_2
- - &pinctrl_usdhc3_pfla02>;
- - cd-gpios = <&gpio1 27 0>;
- - wp-gpios = <&gpio1 29 0>;
- - status = "disabled";
- -};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-pinfunc.h linux-3.14.35/arch/arm/boot/dts/imx6q-pinfunc.h
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-pinfunc.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-pinfunc.h 2015-03-08 14:27:37.401684503 -0500
- @@ -673,6 +673,7 @@
- #define MX6QDL_PAD_GPIO_3__USB_H1_OC 0x22c 0x5fc 0x948 0x6 0x1
- #define MX6QDL_PAD_GPIO_3__MLB_CLK 0x22c 0x5fc 0x900 0x7 0x1
- #define MX6QDL_PAD_GPIO_6__ESAI_TX_CLK 0x230 0x600 0x870 0x0 0x1
- +#define MX6QDL_PAD_GPIO_6__ENET_IRQ 0x230 0x600 0x03c 0x11 0xff000609
- #define MX6QDL_PAD_GPIO_6__I2C3_SDA 0x230 0x600 0x8ac 0x2 0x1
- #define MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x230 0x600 0x000 0x5 0x0
- #define MX6QDL_PAD_GPIO_6__SD2_LCTL 0x230 0x600 0x000 0x6 0x0
- @@ -1024,6 +1025,7 @@
- #define MX6QDL_PAD_SD1_DAT2__WDOG1_RESET_B_DEB 0x34c 0x734 0x000 0x6 0x0
- #define MX6QDL_PAD_SD1_CLK__SD1_CLK 0x350 0x738 0x000 0x0 0x0
- #define MX6QDL_PAD_SD1_CLK__ECSPI5_SCLK 0x350 0x738 0x828 0x1 0x0
- +#define MX6QDL_PAD_SD1_CLK__OSC32K_32K_OUT 0x350 0x738 0x000 0x2 0x0
- #define MX6QDL_PAD_SD1_CLK__GPT_CLKIN 0x350 0x738 0x000 0x3 0x0
- #define MX6QDL_PAD_SD1_CLK__GPIO1_IO20 0x350 0x738 0x000 0x5 0x0
- #define MX6QDL_PAD_SD2_CLK__SD2_CLK 0x354 0x73c 0x000 0x0 0x0
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-sabreauto.dts linux-3.14.35/arch/arm/boot/dts/imx6q-sabreauto.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-sabreauto.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-sabreauto.dts 2015-03-08 14:27:37.401684503 -0500
- @@ -20,6 +20,22 @@
- compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
- };
-
- +&mxcfb1 {
- + status = "okay";
- +};
- +
- +&mxcfb2 {
- + status = "okay";
- +};
- +
- +&mxcfb3 {
- + status = "okay";
- +};
- +
- +&mxcfb4 {
- + status = "okay";
- +};
- +
- &sata {
- status = "okay";
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-sabrelite.dts linux-3.14.35/arch/arm/boot/dts/imx6q-sabrelite.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-sabrelite.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-sabrelite.dts 2015-03-08 14:27:37.401684503 -0500
- @@ -12,189 +12,13 @@
-
- /dts-v1/;
- #include "imx6q.dtsi"
- +#include "imx6qdl-sabrelite.dtsi"
-
- / {
- model = "Freescale i.MX6 Quad SABRE Lite Board";
- compatible = "fsl,imx6q-sabrelite", "fsl,imx6q";
- -
- - memory {
- - reg = <0x10000000 0x40000000>;
- - };
- -
- - regulators {
- - compatible = "simple-bus";
- -
- - reg_2p5v: 2p5v {
- - compatible = "regulator-fixed";
- - regulator-name = "2P5V";
- - regulator-min-microvolt = <2500000>;
- - regulator-max-microvolt = <2500000>;
- - regulator-always-on;
- - };
- -
- - reg_3p3v: 3p3v {
- - compatible = "regulator-fixed";
- - regulator-name = "3P3V";
- - regulator-min-microvolt = <3300000>;
- - regulator-max-microvolt = <3300000>;
- - regulator-always-on;
- - };
- -
- - reg_usb_otg_vbus: usb_otg_vbus {
- - compatible = "regulator-fixed";
- - regulator-name = "usb_otg_vbus";
- - regulator-min-microvolt = <5000000>;
- - regulator-max-microvolt = <5000000>;
- - gpio = <&gpio3 22 0>;
- - enable-active-high;
- - };
- - };
- -
- - sound {
- - compatible = "fsl,imx6q-sabrelite-sgtl5000",
- - "fsl,imx-audio-sgtl5000";
- - model = "imx6q-sabrelite-sgtl5000";
- - ssi-controller = <&ssi1>;
- - audio-codec = <&codec>;
- - audio-routing =
- - "MIC_IN", "Mic Jack",
- - "Mic Jack", "Mic Bias",
- - "Headphone Jack", "HP_OUT";
- - mux-int-port = <1>;
- - mux-ext-port = <4>;
- - };
- -};
- -
- -&audmux {
- - status = "okay";
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_audmux_1>;
- -};
- -
- -&ecspi1 {
- - fsl,spi-num-chipselects = <1>;
- - cs-gpios = <&gpio3 19 0>;
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_ecspi1_1>;
- - status = "okay";
- -
- - flash: m25p80@0 {
- - compatible = "sst,sst25vf016b";
- - spi-max-frequency = <20000000>;
- - reg = <0>;
- - };
- -};
- -
- -&fec {
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_enet_1>;
- - phy-mode = "rgmii";
- - phy-reset-gpios = <&gpio3 23 0>;
- - status = "okay";
- -};
- -
- -&i2c1 {
- - status = "okay";
- - clock-frequency = <100000>;
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_i2c1_1>;
- -
- - codec: sgtl5000@0a {
- - compatible = "fsl,sgtl5000";
- - reg = <0x0a>;
- - clocks = <&clks 201>;
- - VDDA-supply = <®_2p5v>;
- - VDDIO-supply = <®_3p3v>;
- - };
- -};
- -
- -&iomuxc {
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_hog>;
- -
- - hog {
- - pinctrl_hog: hoggrp {
- - fsl,pins = <
- - MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x80000000
- - MX6QDL_PAD_NANDF_D7__GPIO2_IO07 0x80000000
- - MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x80000000
- - MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000
- - MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000
- - MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x80000000
- - MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1f0b0
- - MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x80000000
- - MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000
- - >;
- - };
- - };
- -};
- -
- -&ldb {
- - status = "okay";
- -
- - lvds-channel@0 {
- - fsl,data-mapping = "spwg";
- - fsl,data-width = <18>;
- - status = "okay";
- -
- - display-timings {
- - native-mode = <&timing0>;
- - timing0: hsd100pxn1 {
- - clock-frequency = <65000000>;
- - hactive = <1024>;
- - vactive = <768>;
- - hback-porch = <220>;
- - hfront-porch = <40>;
- - vback-porch = <21>;
- - vfront-porch = <7>;
- - hsync-len = <60>;
- - vsync-len = <10>;
- - };
- - };
- - };
- };
-
- &sata {
- status = "okay";
- };
- -
- -&ssi1 {
- - fsl,mode = "i2s-slave";
- - status = "okay";
- -};
- -
- -&uart2 {
- - status = "okay";
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_uart2_1>;
- -};
- -
- -&usbh1 {
- - status = "okay";
- -};
- -
- -&usbotg {
- - vbus-supply = <®_usb_otg_vbus>;
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usbotg_1>;
- - disable-over-current;
- - status = "okay";
- -};
- -
- -&usdhc3 {
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usdhc3_2>;
- - cd-gpios = <&gpio7 0 0>;
- - wp-gpios = <&gpio7 1 0>;
- - vmmc-supply = <®_3p3v>;
- - status = "okay";
- -};
- -
- -&usdhc4 {
- - pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usdhc4_2>;
- - cd-gpios = <&gpio2 6 0>;
- - wp-gpios = <&gpio2 7 0>;
- - vmmc-supply = <®_3p3v>;
- - status = "okay";
- -};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-sabresd.dts linux-3.14.35/arch/arm/boot/dts/imx6q-sabresd.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-sabresd.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-sabresd.dts 2015-03-08 14:27:37.401684503 -0500
- @@ -23,3 +23,19 @@
- &sata {
- status = "okay";
- };
- +
- +&mxcfb1 {
- + status = "okay";
- +};
- +
- +&mxcfb2 {
- + status = "okay";
- +};
- +
- +&mxcfb3 {
- + status = "okay";
- +};
- +
- +&mxcfb4 {
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-sabresd-hdcp.dts linux-3.14.35/arch/arm/boot/dts/imx6q-sabresd-hdcp.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-sabresd-hdcp.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-sabresd-hdcp.dts 2015-03-08 14:27:37.401684503 -0500
- @@ -0,0 +1,23 @@
- +/*
- + * Copyright 2012-2013 Freescale Semiconductor, Inc.
- + * Copyright 2011 Linaro Ltd.
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#include "imx6q-sabresd.dts"
- +
- +&hdmi_video {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hdmi_hdcp>;
- + fsl,hdcp;
- +};
- +
- +&i2c2 {
- + status = "disable";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-sbc6x.dts linux-3.14.35/arch/arm/boot/dts/imx6q-sbc6x.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-sbc6x.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-sbc6x.dts 2015-03-08 14:27:37.401684503 -0500
- @@ -17,28 +17,78 @@
- };
- };
-
- +
- &fec {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_enet_1>;
- + pinctrl-0 = <&pinctrl_enet>;
- phy-mode = "rgmii";
- status = "okay";
- };
-
- +&iomuxc {
- + imx6q-sbc6x {
- + pinctrl_enet: enetgrp {
- + fsl,pins = <
- + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- + >;
- + };
- +
- + pinctrl_uart1: uart1grp {
- + fsl,pins = <
- + MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
- + MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usbotg: usbotggrp {
- + fsl,pins = <
- + MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc3: usdhc3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- + >;
- + };
- + };
- +};
- +
- &uart1 {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_uart1_1>;
- + pinctrl-0 = <&pinctrl_uart1>;
- status = "okay";
- };
-
- &usbotg {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usbotg_1>;
- + pinctrl-0 = <&pinctrl_usbotg>;
- disable-over-current;
- status = "okay";
- };
-
- &usdhc3 {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usdhc3_2>;
- + pinctrl-0 = <&pinctrl_usdhc3>;
- status = "okay";
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6q-udoo.dts linux-3.14.35/arch/arm/boot/dts/imx6q-udoo.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6q-udoo.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6q-udoo.dts 2015-03-08 14:27:37.401684503 -0500
- @@ -16,24 +16,78 @@
- model = "Udoo i.MX6 Quad Board";
- compatible = "udoo,imx6q-udoo", "fsl,imx6q";
-
- + chosen {
- + stdout-path = &uart2;
- + };
- +
- memory {
- reg = <0x10000000 0x40000000>;
- };
- };
-
- +&fec {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_enet>;
- + phy-mode = "rgmii";
- + status = "okay";
- +};
- +
- +&iomuxc {
- + imx6q-udoo {
- + pinctrl_enet: enetgrp {
- + fsl,pins = <
- + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
- + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
- + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
- + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
- + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
- + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
- + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
- + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
- + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- + >;
- + };
- +
- + pinctrl_uart2: uart2grp {
- + fsl,pins = <
- + MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
- + MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usdhc3: usdhc3grp {
- + fsl,pins = <
- + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- + >;
- + };
- + };
- +};
- +
- &sata {
- status = "okay";
- };
-
- &uart2 {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_uart2_1>;
- + pinctrl-0 = <&pinctrl_uart2>;
- status = "okay";
- };
-
- &usdhc3 {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usdhc3_2>;
- + pinctrl-0 = <&pinctrl_usdhc3>;
- non-removable;
- status = "okay";
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6sl.dtsi linux-3.14.35/arch/arm/boot/dts/imx6sl.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6sl.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6sl.dtsi 2015-03-08 14:27:37.401684503 -0500
- @@ -7,12 +7,14 @@
- *
- */
-
- +#include <dt-bindings/interrupt-controller/irq.h>
- #include "skeleton.dtsi"
- #include "imx6sl-pinfunc.h"
- #include <dt-bindings/clock/imx6sl-clock.h>
-
- / {
- aliases {
- + ethernet0 = &fec;
- gpio0 = &gpio1;
- gpio1 = &gpio2;
- gpio2 = &gpio3;
- @@ -27,25 +29,46 @@
- spi1 = &ecspi2;
- spi2 = &ecspi3;
- spi3 = &ecspi4;
- + usbphy0 = &usbphy1;
- + usbphy1 = &usbphy2;
- };
-
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
-
- - cpu@0 {
- + cpu0: cpu@0 {
- compatible = "arm,cortex-a9";
- device_type = "cpu";
- reg = <0x0>;
- next-level-cache = <&L2>;
- + operating-points = <
- + /* kHz uV */
- + 996000 1275000
- + 792000 1175000
- + 396000 975000
- + >;
- + fsl,soc-operating-points = <
- + /* ARM kHz SOC-PU uV */
- + 996000 1225000
- + 792000 1175000
- + 396000 1175000
- + >;
- + clock-latency = <61036>; /* two CLK32 periods */
- + clocks = <&clks IMX6SL_CLK_ARM>, <&clks IMX6SL_CLK_PLL2_PFD2>,
- + <&clks IMX6SL_CLK_STEP>, <&clks IMX6SL_CLK_PLL1_SW>,
- + <&clks IMX6SL_CLK_PLL1_SYS>;
- + clock-names = "arm", "pll2_pfd2_396m", "step",
- + "pll1_sw", "pll1_sys";
- + arm-supply = <®_arm>;
- + pu-supply = <®_pu>;
- + soc-supply = <®_soc>;
- };
- };
-
- intc: interrupt-controller@00a01000 {
- compatible = "arm,cortex-a9-gic";
- #interrupt-cells = <3>;
- - #address-cells = <1>;
- - #size-cells = <1>;
- interrupt-controller;
- reg = <0x00a01000 0x1000>,
- <0x00a00100 0x100>;
- @@ -57,15 +80,21 @@
-
- ckil {
- compatible = "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <32768>;
- };
-
- osc {
- compatible = "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <24000000>;
- };
- };
-
- + pu_dummy: pudummy_reg {
- + compatible = "fsl,imx6-dummy-pureg"; /* only used in ldo-bypass */
- + };
- +
- soc {
- #address-cells = <1>;
- #size-cells = <1>;
- @@ -73,19 +102,45 @@
- interrupt-parent = <&intc>;
- ranges;
-
- + ocram: sram@00900000 {
- + compatible = "mmio-sram";
- + reg = <0x00900000 0x20000>;
- + clocks = <&clks IMX6SL_CLK_OCRAM>;
- + };
- +
- + busfreq { /* BUSFREQ */
- + compatible = "fsl,imx6_busfreq";
- + clocks = <&clks IMX6SL_CLK_PLL2_BUS>, <&clks IMX6SL_CLK_PLL2_PFD2>,
- + <&clks IMX6SL_CLK_PLL2_198M>, <&clks IMX6SL_CLK_ARM>,
- + <&clks IMX6SL_CLK_PLL3_USB_OTG>, <&clks IMX6SL_CLK_PERIPH>,
- + <&clks IMX6SL_CLK_PRE_PERIPH_SEL>, <&clks IMX6SL_CLK_PERIPH_CLK2>,
- + <&clks IMX6SL_CLK_PERIPH_CLK2_SEL>, <&clks IMX6SL_CLK_OSC>,
- + <&clks IMX6SL_CLK_PLL1_SYS>, <&clks IMX6SL_CLK_PERIPH2>,
- + <&clks IMX6SL_CLK_AHB>, <&clks IMX6SL_CLK_OCRAM>,
- + <&clks IMX6SL_CLK_PLL1_SW>, <&clks IMX6SL_CLK_PRE_PERIPH2_SEL>,
- + <&clks IMX6SL_CLK_PERIPH2_CLK2_SEL>, <&clks IMX6SL_CLK_PERIPH2_CLK2>,
- + <&clks IMX6SL_CLK_STEP>;
- + clock-names = "pll2_bus", "pll2_pfd2_396m", "pll2_198m", "arm", "pll3_usb_otg", "periph",
- + "periph_pre", "periph_clk2", "periph_clk2_sel", "osc", "pll1_sys", "periph2", "ahb", "ocram", "pll1_sw",
- + "periph2_pre", "periph2_clk2_sel", "periph2_clk2", "step";
- + fsl,max_ddr_freq = <400000000>;
- + };
- +
- L2: l2-cache@00a02000 {
- compatible = "arm,pl310-cache";
- reg = <0x00a02000 0x1000>;
- - interrupts = <0 92 0x04>;
- + interrupts = <0 92 IRQ_TYPE_LEVEL_HIGH>;
- cache-unified;
- cache-level = <2>;
- arm,tag-latency = <4 2 3>;
- arm,data-latency = <4 2 3>;
- + arm,dynamic-clk-gating;
- + arm,standby-mode;
- };
-
- pmu {
- compatible = "arm,cortex-a9-pmu";
- - interrupts = <0 94 0x04>;
- + interrupts = <0 94 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- aips1: aips-bus@02000000 {
- @@ -104,7 +159,7 @@
-
- spdif: spdif@02004000 {
- reg = <0x02004000 0x4000>;
- - interrupts = <0 52 0x04>;
- + interrupts = <0 52 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- ecspi1: ecspi@02008000 {
- @@ -112,7 +167,7 @@
- #size-cells = <0>;
- compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi";
- reg = <0x02008000 0x4000>;
- - interrupts = <0 31 0x04>;
- + interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_ECSPI1>,
- <&clks IMX6SL_CLK_ECSPI1>;
- clock-names = "ipg", "per";
- @@ -124,7 +179,7 @@
- #size-cells = <0>;
- compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi";
- reg = <0x0200c000 0x4000>;
- - interrupts = <0 32 0x04>;
- + interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_ECSPI2>,
- <&clks IMX6SL_CLK_ECSPI2>;
- clock-names = "ipg", "per";
- @@ -136,7 +191,7 @@
- #size-cells = <0>;
- compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi";
- reg = <0x02010000 0x4000>;
- - interrupts = <0 33 0x04>;
- + interrupts = <0 33 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_ECSPI3>,
- <&clks IMX6SL_CLK_ECSPI3>;
- clock-names = "ipg", "per";
- @@ -148,7 +203,7 @@
- #size-cells = <0>;
- compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi";
- reg = <0x02014000 0x4000>;
- - interrupts = <0 34 0x04>;
- + interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_ECSPI4>,
- <&clks IMX6SL_CLK_ECSPI4>;
- clock-names = "ipg", "per";
- @@ -159,7 +214,7 @@
- compatible = "fsl,imx6sl-uart",
- "fsl,imx6q-uart", "fsl,imx21-uart";
- reg = <0x02018000 0x4000>;
- - interrupts = <0 30 0x04>;
- + interrupts = <0 30 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_UART>,
- <&clks IMX6SL_CLK_UART_SERIAL>;
- clock-names = "ipg", "per";
- @@ -172,7 +227,7 @@
- compatible = "fsl,imx6sl-uart",
- "fsl,imx6q-uart", "fsl,imx21-uart";
- reg = <0x02020000 0x4000>;
- - interrupts = <0 26 0x04>;
- + interrupts = <0 26 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_UART>,
- <&clks IMX6SL_CLK_UART_SERIAL>;
- clock-names = "ipg", "per";
- @@ -185,7 +240,7 @@
- compatible = "fsl,imx6sl-uart",
- "fsl,imx6q-uart", "fsl,imx21-uart";
- reg = <0x02024000 0x4000>;
- - interrupts = <0 27 0x04>;
- + interrupts = <0 27 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_UART>,
- <&clks IMX6SL_CLK_UART_SERIAL>;
- clock-names = "ipg", "per";
- @@ -195,9 +250,11 @@
- };
-
- ssi1: ssi@02028000 {
- - compatible = "fsl,imx6sl-ssi","fsl,imx21-ssi";
- + compatible = "fsl,imx6sl-ssi",
- + "fsl,imx51-ssi",
- + "fsl,imx21-ssi";
- reg = <0x02028000 0x4000>;
- - interrupts = <0 46 0x04>;
- + interrupts = <0 46 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_SSI1>;
- dmas = <&sdma 37 1 0>,
- <&sdma 38 1 0>;
- @@ -207,9 +264,11 @@
- };
-
- ssi2: ssi@0202c000 {
- - compatible = "fsl,imx6sl-ssi","fsl,imx21-ssi";
- + compatible = "fsl,imx6sl-ssi",
- + "fsl,imx51-ssi",
- + "fsl,imx21-ssi";
- reg = <0x0202c000 0x4000>;
- - interrupts = <0 47 0x04>;
- + interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_SSI2>;
- dmas = <&sdma 41 1 0>,
- <&sdma 42 1 0>;
- @@ -219,9 +278,11 @@
- };
-
- ssi3: ssi@02030000 {
- - compatible = "fsl,imx6sl-ssi","fsl,imx21-ssi";
- + compatible = "fsl,imx6sl-ssi",
- + "fsl,imx51-ssi",
- + "fsl,imx21-ssi";
- reg = <0x02030000 0x4000>;
- - interrupts = <0 48 0x04>;
- + interrupts = <0 48 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_SSI3>;
- dmas = <&sdma 45 1 0>,
- <&sdma 46 1 0>;
- @@ -234,7 +295,7 @@
- compatible = "fsl,imx6sl-uart",
- "fsl,imx6q-uart", "fsl,imx21-uart";
- reg = <0x02034000 0x4000>;
- - interrupts = <0 28 0x04>;
- + interrupts = <0 28 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_UART>,
- <&clks IMX6SL_CLK_UART_SERIAL>;
- clock-names = "ipg", "per";
- @@ -247,7 +308,7 @@
- compatible = "fsl,imx6sl-uart",
- "fsl,imx6q-uart", "fsl,imx21-uart";
- reg = <0x02038000 0x4000>;
- - interrupts = <0 29 0x04>;
- + interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_UART>,
- <&clks IMX6SL_CLK_UART_SERIAL>;
- clock-names = "ipg", "per";
- @@ -261,7 +322,7 @@
- #pwm-cells = <2>;
- compatible = "fsl,imx6sl-pwm", "fsl,imx27-pwm";
- reg = <0x02080000 0x4000>;
- - interrupts = <0 83 0x04>;
- + interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_PWM1>,
- <&clks IMX6SL_CLK_PWM1>;
- clock-names = "ipg", "per";
- @@ -271,7 +332,7 @@
- #pwm-cells = <2>;
- compatible = "fsl,imx6sl-pwm", "fsl,imx27-pwm";
- reg = <0x02084000 0x4000>;
- - interrupts = <0 84 0x04>;
- + interrupts = <0 84 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_PWM2>,
- <&clks IMX6SL_CLK_PWM2>;
- clock-names = "ipg", "per";
- @@ -281,7 +342,7 @@
- #pwm-cells = <2>;
- compatible = "fsl,imx6sl-pwm", "fsl,imx27-pwm";
- reg = <0x02088000 0x4000>;
- - interrupts = <0 85 0x04>;
- + interrupts = <0 85 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_PWM3>,
- <&clks IMX6SL_CLK_PWM3>;
- clock-names = "ipg", "per";
- @@ -291,7 +352,7 @@
- #pwm-cells = <2>;
- compatible = "fsl,imx6sl-pwm", "fsl,imx27-pwm";
- reg = <0x0208c000 0x4000>;
- - interrupts = <0 86 0x04>;
- + interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_PWM4>,
- <&clks IMX6SL_CLK_PWM4>;
- clock-names = "ipg", "per";
- @@ -300,7 +361,7 @@
- gpt: gpt@02098000 {
- compatible = "fsl,imx6sl-gpt";
- reg = <0x02098000 0x4000>;
- - interrupts = <0 55 0x04>;
- + interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_GPT>,
- <&clks IMX6SL_CLK_GPT_SERIAL>;
- clock-names = "ipg", "per";
- @@ -309,7 +370,8 @@
- gpio1: gpio@0209c000 {
- compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio";
- reg = <0x0209c000 0x4000>;
- - interrupts = <0 66 0x04 0 67 0x04>;
- + interrupts = <0 66 IRQ_TYPE_LEVEL_HIGH>,
- + <0 67 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- @@ -319,7 +381,8 @@
- gpio2: gpio@020a0000 {
- compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio";
- reg = <0x020a0000 0x4000>;
- - interrupts = <0 68 0x04 0 69 0x04>;
- + interrupts = <0 68 IRQ_TYPE_LEVEL_HIGH>,
- + <0 69 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- @@ -329,7 +392,8 @@
- gpio3: gpio@020a4000 {
- compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio";
- reg = <0x020a4000 0x4000>;
- - interrupts = <0 70 0x04 0 71 0x04>;
- + interrupts = <0 70 IRQ_TYPE_LEVEL_HIGH>,
- + <0 71 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- @@ -339,7 +403,8 @@
- gpio4: gpio@020a8000 {
- compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio";
- reg = <0x020a8000 0x4000>;
- - interrupts = <0 72 0x04 0 73 0x04>;
- + interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>,
- + <0 73 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- @@ -349,7 +414,8 @@
- gpio5: gpio@020ac000 {
- compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio";
- reg = <0x020ac000 0x4000>;
- - interrupts = <0 74 0x04 0 75 0x04>;
- + interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>,
- + <0 75 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- @@ -357,21 +423,23 @@
- };
-
- kpp: kpp@020b8000 {
- + compatible = "fsl,imx6sl-kpp", "fsl,imx21-kpp";
- reg = <0x020b8000 0x4000>;
- - interrupts = <0 82 0x04>;
- + interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&clks IMX6SL_CLK_DUMMY>;
- };
-
- wdog1: wdog@020bc000 {
- compatible = "fsl,imx6sl-wdt", "fsl,imx21-wdt";
- reg = <0x020bc000 0x4000>;
- - interrupts = <0 80 0x04>;
- + interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_DUMMY>;
- };
-
- wdog2: wdog@020c0000 {
- compatible = "fsl,imx6sl-wdt", "fsl,imx21-wdt";
- reg = <0x020c0000 0x4000>;
- - interrupts = <0 81 0x04>;
- + interrupts = <0 81 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_DUMMY>;
- status = "disabled";
- };
- @@ -379,7 +447,8 @@
- clks: ccm@020c4000 {
- compatible = "fsl,imx6sl-ccm";
- reg = <0x020c4000 0x4000>;
- - interrupts = <0 87 0x04 0 88 0x04>;
- + interrupts = <0 87 IRQ_TYPE_LEVEL_HIGH>,
- + <0 88 IRQ_TYPE_LEVEL_HIGH>;
- #clock-cells = <1>;
- };
-
- @@ -388,7 +457,9 @@
- "fsl,imx6q-anatop",
- "syscon", "simple-bus";
- reg = <0x020c8000 0x1000>;
- - interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
- + interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>,
- + <0 54 IRQ_TYPE_LEVEL_HIGH>,
- + <0 127 IRQ_TYPE_LEVEL_HIGH>;
-
- regulator-1p1@110 {
- compatible = "fsl,anatop-regulator";
- @@ -434,7 +505,7 @@
-
- reg_arm: regulator-vddcore@140 {
- compatible = "fsl,anatop-regulator";
- - regulator-name = "cpu";
- + regulator-name = "vddarm";
- regulator-min-microvolt = <725000>;
- regulator-max-microvolt = <1450000>;
- regulator-always-on;
- @@ -454,7 +525,6 @@
- regulator-name = "vddpu";
- regulator-min-microvolt = <725000>;
- regulator-max-microvolt = <1450000>;
- - regulator-always-on;
- anatop-reg-offset = <0x140>;
- anatop-vol-bit-shift = <9>;
- anatop-vol-bit-width = <5>;
- @@ -484,18 +554,34 @@
- };
- };
-
- + tempmon: tempmon {
- + compatible = "fsl,imx6sl-tempmon", "fsl,imx6q-tempmon";
- + interrupts = <0 49 0x04>;
- + fsl,tempmon = <&anatop>;
- + fsl,tempmon-data = <&ocotp>;
- + clocks = <&clks IMX6SL_CLK_PLL3_USB_OTG>;
- + };
- +
- usbphy1: usbphy@020c9000 {
- compatible = "fsl,imx6sl-usbphy", "fsl,imx23-usbphy";
- reg = <0x020c9000 0x1000>;
- - interrupts = <0 44 0x04>;
- + interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_USBPHY1>;
- + fsl,anatop = <&anatop>;
- };
-
- usbphy2: usbphy@020ca000 {
- compatible = "fsl,imx6sl-usbphy", "fsl,imx23-usbphy";
- reg = <0x020ca000 0x1000>;
- - interrupts = <0 45 0x04>;
- + interrupts = <0 45 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_USBPHY2>;
- + fsl,anatop = <&anatop>;
- + };
- +
- + usbphy_nop1: usbphy_nop1 {
- + compatible = "usb-nop-xceiv";
- + clocks = <&clks IMX6SL_CLK_USBPHY1>;
- + clock-names = "main_clk";
- };
-
- snvs@020cc000 {
- @@ -507,271 +593,165 @@
- snvs-rtc-lp@34 {
- compatible = "fsl,sec-v4.0-mon-rtc-lp";
- reg = <0x34 0x58>;
- - interrupts = <0 19 0x04 0 20 0x04>;
- + interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>,
- + <0 20 IRQ_TYPE_LEVEL_HIGH>;
- };
- - };
- -
- - epit1: epit@020d0000 {
- - reg = <0x020d0000 0x4000>;
- - interrupts = <0 56 0x04>;
- - };
-
- - epit2: epit@020d4000 {
- - reg = <0x020d4000 0x4000>;
- - interrupts = <0 57 0x04>;
- - };
- -
- - src: src@020d8000 {
- - compatible = "fsl,imx6sl-src", "fsl,imx51-src";
- - reg = <0x020d8000 0x4000>;
- - interrupts = <0 91 0x04 0 96 0x04>;
- - #reset-cells = <1>;
- - };
- -
- - gpc: gpc@020dc000 {
- - compatible = "fsl,imx6sl-gpc", "fsl,imx6q-gpc";
- - reg = <0x020dc000 0x4000>;
- - interrupts = <0 89 0x04>;
- - };
- -
- - gpr: iomuxc-gpr@020e0000 {
- - compatible = "fsl,imx6sl-iomuxc-gpr",
- - "fsl,imx6q-iomuxc-gpr", "syscon";
- - reg = <0x020e0000 0x38>;
- - };
- -
- - iomuxc: iomuxc@020e0000 {
- - compatible = "fsl,imx6sl-iomuxc";
- - reg = <0x020e0000 0x4000>;
- -
- - ecspi1 {
- - pinctrl_ecspi1_1: ecspi1grp-1 {
- + csi {
- + pinctrl_csi_0: csigrp-0 {
- fsl,pins = <
- - MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO 0x100b1
- - MX6SL_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x100b1
- - MX6SL_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x100b1
- + MX6SL_PAD_EPDC_GDRL__CSI_MCLK 0x110b0
- + MX6SL_PAD_EPDC_GDCLK__CSI_PIXCLK 0x110b0
- + MX6SL_PAD_EPDC_GDSP__CSI_VSYNC 0x110b0
- + MX6SL_PAD_EPDC_GDOE__CSI_HSYNC 0x110b0
- + MX6SL_PAD_EPDC_SDLE__CSI_DATA09 0x110b0
- + MX6SL_PAD_EPDC_SDCLK__CSI_DATA08 0x110b0
- + MX6SL_PAD_EPDC_D7__CSI_DATA07 0x110b0
- + MX6SL_PAD_EPDC_D6__CSI_DATA06 0x110b0
- + MX6SL_PAD_EPDC_D5__CSI_DATA05 0x110b0
- + MX6SL_PAD_EPDC_D4__CSI_DATA04 0x110b0
- + MX6SL_PAD_EPDC_D3__CSI_DATA03 0x110b0
- + MX6SL_PAD_EPDC_D2__CSI_DATA02 0x110b0
- + MX6SL_PAD_EPDC_D1__CSI_DATA01 0x110b0
- + MX6SL_PAD_EPDC_D0__CSI_DATA00 0x110b0
- + MX6SL_PAD_EPDC_SDSHR__GPIO1_IO26 0x80000000
- + MX6SL_PAD_EPDC_SDOE__GPIO1_IO25 0x80000000
- >;
- };
- };
-
- - fec {
- - pinctrl_fec_1: fecgrp-1 {
- + i2c1 {
- + pinctrl_i2c1_1: i2c1grp-1 {
- fsl,pins = <
- - MX6SL_PAD_FEC_MDC__FEC_MDC 0x1b0b0
- - MX6SL_PAD_FEC_MDIO__FEC_MDIO 0x1b0b0
- - MX6SL_PAD_FEC_CRS_DV__FEC_RX_DV 0x1b0b0
- - MX6SL_PAD_FEC_RXD0__FEC_RX_DATA0 0x1b0b0
- - MX6SL_PAD_FEC_RXD1__FEC_RX_DATA1 0x1b0b0
- - MX6SL_PAD_FEC_TX_EN__FEC_TX_EN 0x1b0b0
- - MX6SL_PAD_FEC_TXD0__FEC_TX_DATA0 0x1b0b0
- - MX6SL_PAD_FEC_TXD1__FEC_TX_DATA1 0x1b0b0
- - MX6SL_PAD_FEC_REF_CLK__FEC_REF_OUT 0x4001b0a8
- + MX6SL_PAD_I2C1_SCL__I2C1_SCL 0x4001b8b1
- + MX6SL_PAD_I2C1_SDA__I2C1_SDA 0x4001b8b1
- >;
- };
- };
-
- - uart1 {
- - pinctrl_uart1_1: uart1grp-1 {
- + i2c2 {
- + pinctrl_i2c2_1: i2c2grp-1 {
- fsl,pins = <
- - MX6SL_PAD_UART1_RXD__UART1_RX_DATA 0x1b0b1
- - MX6SL_PAD_UART1_TXD__UART1_TX_DATA 0x1b0b1
- + MX6SL_PAD_I2C2_SCL__I2C2_SCL 0x4001b8b1
- + MX6SL_PAD_I2C2_SDA__I2C2_SDA 0x4001b8b1
- >;
- };
- };
-
- - usbotg1 {
- - pinctrl_usbotg1_1: usbotg1grp-1 {
- - fsl,pins = <
- - MX6SL_PAD_EPDC_PWRCOM__USB_OTG1_ID 0x17059
- - >;
- - };
- -
- - pinctrl_usbotg1_2: usbotg1grp-2 {
- + i2c3 {
- + pinctrl_i2c3_1: i2c3grp-1 {
- fsl,pins = <
- - MX6SL_PAD_FEC_RXD0__USB_OTG1_ID 0x17059
- - >;
- - };
- -
- - pinctrl_usbotg1_3: usbotg1grp-3 {
- - fsl,pins = <
- - MX6SL_PAD_LCD_DAT1__USB_OTG1_ID 0x17059
- - >;
- - };
- -
- - pinctrl_usbotg1_4: usbotg1grp-4 {
- - fsl,pins = <
- - MX6SL_PAD_REF_CLK_32K__USB_OTG1_ID 0x17059
- - >;
- - };
- -
- - pinctrl_usbotg1_5: usbotg1grp-5 {
- - fsl,pins = <
- - MX6SL_PAD_SD3_DAT0__USB_OTG1_ID 0x17059
- + MX6SL_PAD_EPDC_SDCE2__I2C3_SCL 0x4001b8b1
- + MX6SL_PAD_EPDC_SDCE3__I2C3_SDA 0x4001b8b1
- >;
- };
- };
-
- - usbotg2 {
- - pinctrl_usbotg2_1: usbotg2grp-1 {
- - fsl,pins = <
- - MX6SL_PAD_ECSPI1_SCLK__USB_OTG2_OC 0x17059
- - >;
- - };
- -
- - pinctrl_usbotg2_2: usbotg2grp-2 {
- + lcdif {
- + pinctrl_lcdif_dat_0: lcdifdatgrp-0 {
- fsl,pins = <
- - MX6SL_PAD_ECSPI2_SCLK__USB_OTG2_OC 0x17059
- + MX6SL_PAD_LCD_DAT0__LCD_DATA00 0x1b0b0
- + MX6SL_PAD_LCD_DAT1__LCD_DATA01 0x1b0b0
- + MX6SL_PAD_LCD_DAT2__LCD_DATA02 0x1b0b0
- + MX6SL_PAD_LCD_DAT3__LCD_DATA03 0x1b0b0
- + MX6SL_PAD_LCD_DAT4__LCD_DATA04 0x1b0b0
- + MX6SL_PAD_LCD_DAT5__LCD_DATA05 0x1b0b0
- + MX6SL_PAD_LCD_DAT6__LCD_DATA06 0x1b0b0
- + MX6SL_PAD_LCD_DAT7__LCD_DATA07 0x1b0b0
- + MX6SL_PAD_LCD_DAT8__LCD_DATA08 0x1b0b0
- + MX6SL_PAD_LCD_DAT9__LCD_DATA09 0x1b0b0
- + MX6SL_PAD_LCD_DAT10__LCD_DATA10 0x1b0b0
- + MX6SL_PAD_LCD_DAT11__LCD_DATA11 0x1b0b0
- + MX6SL_PAD_LCD_DAT12__LCD_DATA12 0x1b0b0
- + MX6SL_PAD_LCD_DAT13__LCD_DATA13 0x1b0b0
- + MX6SL_PAD_LCD_DAT14__LCD_DATA14 0x1b0b0
- + MX6SL_PAD_LCD_DAT15__LCD_DATA15 0x1b0b0
- + MX6SL_PAD_LCD_DAT16__LCD_DATA16 0x1b0b0
- + MX6SL_PAD_LCD_DAT17__LCD_DATA17 0x1b0b0
- + MX6SL_PAD_LCD_DAT18__LCD_DATA18 0x1b0b0
- + MX6SL_PAD_LCD_DAT19__LCD_DATA19 0x1b0b0
- + MX6SL_PAD_LCD_DAT20__LCD_DATA20 0x1b0b0
- + MX6SL_PAD_LCD_DAT21__LCD_DATA21 0x1b0b0
- + MX6SL_PAD_LCD_DAT22__LCD_DATA22 0x1b0b0
- + MX6SL_PAD_LCD_DAT23__LCD_DATA23 0x1b0b0
- >;
- };
-
- - pinctrl_usbotg2_3: usbotg2grp-3 {
- + pinctrl_lcdif_ctrl_0: lcdifctrlgrp-0 {
- fsl,pins = <
- - MX6SL_PAD_KEY_ROW5__USB_OTG2_OC 0x17059
- - >;
- - };
- -
- - pinctrl_usbotg2_4: usbotg2grp-4 {
- - fsl,pins = <
- - MX6SL_PAD_SD3_DAT2__USB_OTG2_OC 0x17059
- + MX6SL_PAD_LCD_CLK__LCD_CLK 0x1b0b0
- + MX6SL_PAD_LCD_ENABLE__LCD_ENABLE 0x1b0b0
- + MX6SL_PAD_LCD_HSYNC__LCD_HSYNC 0x1b0b0
- + MX6SL_PAD_LCD_VSYNC__LCD_VSYNC 0x1b0b0
- + MX6SL_PAD_LCD_RESET__LCD_RESET 0x1b0b0
- >;
- };
- };
-
- - usdhc1 {
- - pinctrl_usdhc1_1: usdhc1grp-1 {
- + pwm1 {
- + pinctrl_pwm1_0: pwm1grp-0 {
- fsl,pins = <
- - MX6SL_PAD_SD1_CMD__SD1_CMD 0x17059
- - MX6SL_PAD_SD1_CLK__SD1_CLK 0x10059
- - MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x17059
- - MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x17059
- - MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x17059
- - MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x17059
- - MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x17059
- - MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x17059
- - MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x17059
- - MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x17059
- + MX6SL_PAD_PWM1__PWM1_OUT 0x110b0
- >;
- };
- -
- - pinctrl_usdhc1_1_100mhz: usdhc1grp-1-100mhz {
- - fsl,pins = <
- - MX6SL_PAD_SD1_CMD__SD1_CMD 0x170b9
- - MX6SL_PAD_SD1_CLK__SD1_CLK 0x100b9
- - MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170b9
- - MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170b9
- - MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170b9
- - MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170b9
- - MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170b9
- - MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170b9
- - MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170b9
- - MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170b9
- - >;
- - };
- -
- - pinctrl_usdhc1_1_200mhz: usdhc1grp-1-200mhz {
- - fsl,pins = <
- - MX6SL_PAD_SD1_CMD__SD1_CMD 0x170f9
- - MX6SL_PAD_SD1_CLK__SD1_CLK 0x100f9
- - MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170f9
- - MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170f9
- - MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170f9
- - MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170f9
- - MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170f9
- - MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170f9
- - MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170f9
- - MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170f9
- - >;
- - };
- -
- -
- };
- + };
-
- - usdhc2 {
- - pinctrl_usdhc2_1: usdhc2grp-1 {
- - fsl,pins = <
- - MX6SL_PAD_SD2_CMD__SD2_CMD 0x17059
- - MX6SL_PAD_SD2_CLK__SD2_CLK 0x10059
- - MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- - MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- - MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- - MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- - >;
- - };
- -
- - pinctrl_usdhc2_1_100mhz: usdhc2grp-1-100mhz {
- - fsl,pins = <
- - MX6SL_PAD_SD2_CMD__SD2_CMD 0x170b9
- - MX6SL_PAD_SD2_CLK__SD2_CLK 0x100b9
- - MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x170b9
- - MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x170b9
- - MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x170b9
- - MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x170b9
- - >;
- - };
- + epit1: epit@020d0000 {
- + reg = <0x020d0000 0x4000>;
- + interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>;
- + };
-
- - pinctrl_usdhc2_1_200mhz: usdhc2grp-1-200mhz {
- - fsl,pins = <
- - MX6SL_PAD_SD2_CMD__SD2_CMD 0x170f9
- - MX6SL_PAD_SD2_CLK__SD2_CLK 0x100f9
- - MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x170f9
- - MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x170f9
- - MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x170f9
- - MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x170f9
- - >;
- - };
- + epit2: epit@020d4000 {
- + reg = <0x020d4000 0x4000>;
- + interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>;
- + };
-
- - };
- + src: src@020d8000 {
- + compatible = "fsl,imx6sl-src", "fsl,imx51-src";
- + reg = <0x020d8000 0x4000>;
- + interrupts = <0 91 IRQ_TYPE_LEVEL_HIGH>,
- + <0 96 IRQ_TYPE_LEVEL_HIGH>;
- + #reset-cells = <1>;
- + };
-
- - usdhc3 {
- - pinctrl_usdhc3_1: usdhc3grp-1 {
- - fsl,pins = <
- - MX6SL_PAD_SD3_CMD__SD3_CMD 0x17059
- - MX6SL_PAD_SD3_CLK__SD3_CLK 0x10059
- - MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- - MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- - MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- - MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- - >;
- - };
- + gpc: gpc@020dc000 {
- + compatible = "fsl,imx6sl-gpc", "fsl,imx6q-gpc";
- + reg = <0x020dc000 0x4000>;
- + interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&clks IMX6SL_CLK_GPU2D_PODF>, <&clks IMX6SL_CLK_GPU2D_OVG>,
- + <&clks IMX6SL_CLK_IPG>;
- + clock-names = "gpu2d_podf", "gpu2d_ovg", "ipg";
- + pu-supply = <®_pu>;
- + };
-
- - pinctrl_usdhc3_1_100mhz: usdhc3grp-1-100mhz {
- - fsl,pins = <
- - MX6SL_PAD_SD3_CMD__SD3_CMD 0x170b9
- - MX6SL_PAD_SD3_CLK__SD3_CLK 0x100b9
- - MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x170b9
- - MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x170b9
- - MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x170b9
- - MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x170b9
- - >;
- - };
- + gpr: iomuxc-gpr@020e0000 {
- + compatible = "fsl,imx6sl-iomuxc-gpr",
- + "fsl,imx6q-iomuxc-gpr", "syscon";
- + reg = <0x020e0000 0x38>;
- + };
-
- - pinctrl_usdhc3_1_200mhz: usdhc3grp-1-200mhz {
- - fsl,pins = <
- - MX6SL_PAD_SD3_CMD__SD3_CMD 0x170f9
- - MX6SL_PAD_SD3_CLK__SD3_CLK 0x100f9
- - MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x170f9
- - MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x170f9
- - MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x170f9
- - MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
- - >;
- - };
- - };
- + iomuxc: iomuxc@020e0000 {
- + compatible = "fsl,imx6sl-iomuxc";
- + reg = <0x020e0000 0x4000>;
- };
-
- csi: csi@020e4000 {
- + compatible = "fsl,imx6sl-csi";
- reg = <0x020e4000 0x4000>;
- - interrupts = <0 7 0x04>;
- + interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
- + status = "disabled";
- };
-
- spdc: spdc@020e8000 {
- reg = <0x020e8000 0x4000>;
- - interrupts = <0 6 0x04>;
- + interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- sdma: sdma@020ec000 {
- compatible = "fsl,imx6sl-sdma", "fsl,imx35-sdma";
- reg = <0x020ec000 0x4000>;
- - interrupts = <0 2 0x04>;
- + interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_SDMA>,
- <&clks IMX6SL_CLK_SDMA>;
- clock-names = "ipg", "ahb";
- @@ -781,23 +761,32 @@
- };
-
- pxp: pxp@020f0000 {
- + compatible = "fsl,imx6sl-pxp-dma", "fsl,imx6dl-pxp-dma";
- reg = <0x020f0000 0x4000>;
- - interrupts = <0 98 0x04>;
- + interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&clks 111>;
- + clock-names = "pxp-axi";
- + status = "disabled";
- };
-
- epdc: epdc@020f4000 {
- reg = <0x020f4000 0x4000>;
- - interrupts = <0 97 0x04>;
- + interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- lcdif: lcdif@020f8000 {
- + compatible = "fsl,imx6sl-lcdif", "fsl,imx28-lcdif";
- reg = <0x020f8000 0x4000>;
- - interrupts = <0 39 0x04>;
- + interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&clks IMX6SL_CLK_LCDIF_PIX>,
- + <&clks IMX6SL_CLK_LCDIF_AXI>;
- + clock-names = "pix", "axi";
- + status = "disabled";
- };
-
- dcp: dcp@020fc000 {
- reg = <0x020fc000 0x4000>;
- - interrupts = <0 99 0x04>;
- + interrupts = <0 99 IRQ_TYPE_LEVEL_HIGH>;
- };
- };
-
- @@ -811,7 +800,7 @@
- usbotg1: usb@02184000 {
- compatible = "fsl,imx6sl-usb", "fsl,imx27-usb";
- reg = <0x02184000 0x200>;
- - interrupts = <0 43 0x04>;
- + interrupts = <0 43 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_USBOH3>;
- fsl,usbphy = <&usbphy1>;
- fsl,usbmisc = <&usbmisc 0>;
- @@ -821,7 +810,7 @@
- usbotg2: usb@02184200 {
- compatible = "fsl,imx6sl-usb", "fsl,imx27-usb";
- reg = <0x02184200 0x200>;
- - interrupts = <0 42 0x04>;
- + interrupts = <0 42 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_USBOH3>;
- fsl,usbphy = <&usbphy2>;
- fsl,usbmisc = <&usbmisc 1>;
- @@ -831,9 +820,12 @@
- usbh: usb@02184400 {
- compatible = "fsl,imx6sl-usb", "fsl,imx27-usb";
- reg = <0x02184400 0x200>;
- - interrupts = <0 40 0x04>;
- + interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_USBOH3>;
- fsl,usbmisc = <&usbmisc 2>;
- + phy_type = "hsic";
- + fsl,usbphy = <&usbphy_nop1>;
- + fsl,anatop = <&anatop>;
- status = "disabled";
- };
-
- @@ -847,7 +839,7 @@
- fec: ethernet@02188000 {
- compatible = "fsl,imx6sl-fec", "fsl,imx25-fec";
- reg = <0x02188000 0x4000>;
- - interrupts = <0 114 0x04>;
- + interrupts = <0 114 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_ENET_REF>,
- <&clks IMX6SL_CLK_ENET_REF>;
- clock-names = "ipg", "ahb";
- @@ -857,7 +849,7 @@
- usdhc1: usdhc@02190000 {
- compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc";
- reg = <0x02190000 0x4000>;
- - interrupts = <0 22 0x04>;
- + interrupts = <0 22 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_USDHC1>,
- <&clks IMX6SL_CLK_USDHC1>,
- <&clks IMX6SL_CLK_USDHC1>;
- @@ -869,7 +861,7 @@
- usdhc2: usdhc@02194000 {
- compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc";
- reg = <0x02194000 0x4000>;
- - interrupts = <0 23 0x04>;
- + interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_USDHC2>,
- <&clks IMX6SL_CLK_USDHC2>,
- <&clks IMX6SL_CLK_USDHC2>;
- @@ -881,7 +873,7 @@
- usdhc3: usdhc@02198000 {
- compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc";
- reg = <0x02198000 0x4000>;
- - interrupts = <0 24 0x04>;
- + interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_USDHC3>,
- <&clks IMX6SL_CLK_USDHC3>,
- <&clks IMX6SL_CLK_USDHC3>;
- @@ -893,7 +885,7 @@
- usdhc4: usdhc@0219c000 {
- compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc";
- reg = <0x0219c000 0x4000>;
- - interrupts = <0 25 0x04>;
- + interrupts = <0 25 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_USDHC4>,
- <&clks IMX6SL_CLK_USDHC4>,
- <&clks IMX6SL_CLK_USDHC4>;
- @@ -907,7 +899,7 @@
- #size-cells = <0>;
- compatible = "fsl,imx6sl-i2c", "fsl,imx21-i2c";
- reg = <0x021a0000 0x4000>;
- - interrupts = <0 36 0x04>;
- + interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_I2C1>;
- status = "disabled";
- };
- @@ -917,7 +909,7 @@
- #size-cells = <0>;
- compatible = "fsl,imx6sl-i2c", "fsl,imx21-i2c";
- reg = <0x021a4000 0x4000>;
- - interrupts = <0 37 0x04>;
- + interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_I2C2>;
- status = "disabled";
- };
- @@ -927,7 +919,7 @@
- #size-cells = <0>;
- compatible = "fsl,imx6sl-i2c", "fsl,imx21-i2c";
- reg = <0x021a8000 0x4000>;
- - interrupts = <0 38 0x04>;
- + interrupts = <0 38 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_I2C3>;
- status = "disabled";
- };
- @@ -939,17 +931,23 @@
-
- rngb: rngb@021b4000 {
- reg = <0x021b4000 0x4000>;
- - interrupts = <0 5 0x04>;
- + interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- weim: weim@021b8000 {
- reg = <0x021b8000 0x4000>;
- - interrupts = <0 14 0x04>;
- + interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
- + };
- +
- + ocotp: ocotp-ctrl@021bc000 {
- + compatible = "syscon";
- + reg = <0x021bc000 0x4000>;
- };
-
- - ocotp: ocotp@021bc000 {
- - compatible = "fsl,imx6sl-ocotp";
- + ocotp-fuse@021bc000 {
- + compatible = "fsl,imx6sl-ocotp", "fsl,imx6q-ocotp";
- reg = <0x021bc000 0x4000>;
- + clocks = <&clks IMX6SL_CLK_OCOTP>;
- };
-
- audmux: audmux@021d8000 {
- @@ -957,6 +955,25 @@
- reg = <0x021d8000 0x4000>;
- status = "disabled";
- };
- +
- + gpu: gpu@02200000 {
- + compatible = "fsl,imx6sl-gpu", "fsl,imx6q-gpu";
- + reg = <0x02200000 0x4000>, <0x02204000 0x4000>,
- + <0x80000000 0x0>;
- + reg-names = "iobase_2d", "iobase_vg",
- + "phys_baseaddr";
- + interrupts = <0 10 0x04>, <0 11 0x04>;
- + interrupt-names = "irq_2d", "irq_vg";
- + clocks = <&clks IMX6SL_CLK_MMDC_ROOT>,
- + <&clks IMX6SL_CLK_MMDC_ROOT>,
- + <&clks IMX6SL_CLK_GPU2D_OVG>;
- + clock-names = "gpu2d_axi_clk", "openvg_axi_clk",
- + "gpu2d_clk";
- + resets = <&src 3>, <&src 3>;
- + reset-names = "gpu2d", "gpuvg";
- + pu-supply = <®_pu>;
- + };
- +
- };
- };
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6sl-evk-csi.dts linux-3.14.35/arch/arm/boot/dts/imx6sl-evk-csi.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6sl-evk-csi.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6sl-evk-csi.dts 2015-03-08 14:27:37.401684503 -0500
- @@ -0,0 +1,27 @@
- +/*
- + * Copyright (C) 2013 Freescale Semiconductor, Inc.
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include "imx6sl-evk.dts"
- +
- +/ {
- + csi_v4l2_cap {
- + status = "okay";
- + };
- +};
- +
- +&csi {
- + status = "okay";
- +};
- +
- +&i2c3 {
- + status = "okay";
- +};
- +
- +&epdc {
- + status = "disabled";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/imx6sl-evk.dts linux-3.14.35/arch/arm/boot/dts/imx6sl-evk.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/imx6sl-evk.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/imx6sl-evk.dts 2015-03-08 14:27:37.401684503 -0500
- @@ -8,6 +8,8 @@
-
- /dts-v1/;
-
- +#include <dt-bindings/gpio/gpio.h>
- +#include <dt-bindings/input/input.h>
- #include "imx6sl.dtsi"
-
- / {
- @@ -18,11 +20,26 @@
- reg = <0x80000000 0x40000000>;
- };
-
- + leds {
- + compatible = "gpio-leds";
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_led>;
- +
- + user {
- + label = "debug";
- + gpios = <&gpio3 20 GPIO_ACTIVE_HIGH>;
- + linux,default-trigger = "heartbeat";
- + };
- + };
- +
- regulators {
- compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
-
- - reg_usb_otg1_vbus: usb_otg1_vbus {
- + reg_usb_otg1_vbus: regulator@0 {
- compatible = "regulator-fixed";
- + reg = <0>;
- regulator-name = "usb_otg1_vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- @@ -30,22 +47,63 @@
- enable-active-high;
- };
-
- - reg_usb_otg2_vbus: usb_otg2_vbus {
- + reg_usb_otg2_vbus: regulator@1 {
- compatible = "regulator-fixed";
- + reg = <1>;
- regulator-name = "usb_otg2_vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- gpio = <&gpio4 2 0>;
- enable-active-high;
- };
- +
- + reg_aud3v: regulator@2 {
- + compatible = "regulator-fixed";
- + reg = <2>;
- + regulator-name = "wm8962-supply-3v15";
- + regulator-min-microvolt = <3150000>;
- + regulator-max-microvolt = <3150000>;
- + regulator-boot-on;
- + };
- +
- + reg_aud4v: regulator@3 {
- + compatible = "regulator-fixed";
- + reg = <3>;
- + regulator-name = "wm8962-supply-4v2";
- + regulator-min-microvolt = <4325000>;
- + regulator-max-microvolt = <4325000>;
- + regulator-boot-on;
- + };
- };
- +
- + sound {
- + compatible = "fsl,imx6sl-evk-wm8962", "fsl,imx-audio-wm8962";
- + model = "wm8962-audio";
- + ssi-controller = <&ssi2>;
- + audio-codec = <&codec>;
- + audio-routing =
- + "Headphone Jack", "HPOUTL",
- + "Headphone Jack", "HPOUTR",
- + "Ext Spk", "SPKOUTL",
- + "Ext Spk", "SPKOUTR",
- + "AMIC", "MICBIAS",
- + "IN3R", "AMIC";
- + mux-int-port = <2>;
- + mux-ext-port = <3>;
- + };
- +};
- +
- +&audmux {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_audmux3>;
- + status = "okay";
- };
-
- &ecspi1 {
- fsl,spi-num-chipselects = <1>;
- cs-gpios = <&gpio4 11 0>;
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_ecspi1_1>;
- + pinctrl-0 = <&pinctrl_ecspi1>;
- status = "okay";
-
- flash: m25p80@0 {
- @@ -57,18 +115,326 @@
- };
- };
-
- +&csi {
- + status = "okay";
- +};
- +
- +&cpu0 {
- + arm-supply = <&sw1a_reg>;
- + soc-supply = <&sw1c_reg>;
- + pu-supply = <&pu_dummy>; /* use pu_dummy if VDDSOC share with VDDPU */
- +};
- +
- &fec {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_fec_1>;
- + pinctrl-0 = <&pinctrl_fec>;
- phy-mode = "rmii";
- status = "okay";
- };
-
- +&i2c1 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c1>;
- + status = "okay";
- +
- + pmic: pfuze100@08 {
- + compatible = "fsl,pfuze100";
- + reg = <0x08>;
- +
- + regulators {
- + sw1a_reg: sw1ab {
- + regulator-min-microvolt = <300000>;
- + regulator-max-microvolt = <1875000>;
- + regulator-boot-on;
- + regulator-always-on;
- + regulator-ramp-delay = <6250>;
- + };
- +
- + sw1c_reg: sw1c {
- + regulator-min-microvolt = <300000>;
- + regulator-max-microvolt = <1875000>;
- + regulator-boot-on;
- + regulator-always-on;
- + regulator-ramp-delay = <6250>;
- + };
- +
- + sw2_reg: sw2 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw3a_reg: sw3a {
- + regulator-min-microvolt = <400000>;
- + regulator-max-microvolt = <1975000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw3b_reg: sw3b {
- + regulator-min-microvolt = <400000>;
- + regulator-max-microvolt = <1975000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw4_reg: sw4 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <3300000>;
- + };
- +
- + swbst_reg: swbst {
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5150000>;
- + };
- +
- + snvs_reg: vsnvs {
- + regulator-min-microvolt = <1000000>;
- + regulator-max-microvolt = <3000000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + vref_reg: vrefddr {
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + vgen1_reg: vgen1 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <1550000>;
- + regulator-always-on;
- + };
- +
- + vgen2_reg: vgen2 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <1550000>;
- + };
- +
- + vgen3_reg: vgen3 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + };
- +
- + vgen4_reg: vgen4 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vgen5_reg: vgen5 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vgen6_reg: vgen6 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- + };
- + };
- +
- + regulators {
- + compatible = "simple-bus";
- +
- + reg_lcd_3v3: lcd-3v3 {
- + compatible = "regulator-fixed";
- + regulator-name = "lcd-3v3";
- + gpio = <&gpio4 3 0>;
- + enable-active-high;
- + };
- + };
- +
- + backlight {
- + compatible = "pwm-backlight";
- + pwms = <&pwm1 0 5000000>;
- + brightness-levels = <0 4 8 16 32 64 128 255>;
- + default-brightness-level = <6>;
- + };
- +
- + csi_v4l2_cap {
- + compatible = "fsl,imx6sl-csi-v4l2";
- + status = "okay";
- + };
- +
- + pxp_v4l2_out {
- + compatible = "fsl,imx6sl-pxp-v4l2";
- + status = "okay";
- + };
- +};
- +
- +&i2c2 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c2>;
- + status = "okay";
- +
- + codec: wm8962@1a {
- + compatible = "wlf,wm8962";
- + reg = <0x1a>;
- + clocks = <&clks IMX6SL_CLK_EXTERN_AUDIO>;
- + DCVDD-supply = <&vgen3_reg>;
- + DBVDD-supply = <®_aud3v>;
- + AVDD-supply = <&vgen3_reg>;
- + CPVDD-supply = <&vgen3_reg>;
- + MICVDD-supply = <®_aud3v>;
- + PLLVDD-supply = <&vgen3_reg>;
- + SPKVDD1-supply = <®_aud4v>;
- + SPKVDD2-supply = <®_aud4v>;
- + };
- +};
- +
- +&i2c1 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c1_1>;
- + status = "okay";
- +
- + pmic: pfuze100@08 {
- + compatible = "fsl,pfuze100";
- + reg = <0x08>;
- +
- + regulators {
- + sw1a_reg: sw1ab {
- + regulator-min-microvolt = <300000>;
- + regulator-max-microvolt = <1875000>;
- + regulator-boot-on;
- + regulator-always-on;
- + regulator-ramp-delay = <6250>;
- + };
- +
- + sw1c_reg: sw1c {
- + regulator-min-microvolt = <300000>;
- + regulator-max-microvolt = <1875000>;
- + regulator-boot-on;
- + regulator-always-on;
- + regulator-ramp-delay = <6250>;
- + };
- +
- + sw2_reg: sw2 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw3a_reg: sw3a {
- + regulator-min-microvolt = <400000>;
- + regulator-max-microvolt = <1975000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw3b_reg: sw3b {
- + regulator-min-microvolt = <400000>;
- + regulator-max-microvolt = <1975000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + sw4_reg: sw4 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <3300000>;
- + };
- +
- + swbst_reg: swbst {
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5150000>;
- + };
- +
- + snvs_reg: vsnvs {
- + regulator-min-microvolt = <1000000>;
- + regulator-max-microvolt = <3000000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + vref_reg: vrefddr {
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + vgen1_reg: vgen1 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <1550000>;
- + };
- +
- + vgen2_reg: vgen2 {
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <1550000>;
- + };
- +
- + vgen3_reg: vgen3 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vgen4_reg: vgen4 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vgen5_reg: vgen5 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + vgen6_reg: vgen6 {
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- + };
- + };
- +
- + mma8450@1c {
- + compatible = "fsl,mma8450";
- + reg = <0x1c>;
- + };
- +};
- +
- +&i2c2 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c2_1>;
- + status = "okay";
- +};
- +
- +&i2c3 {
- + clock-frequency = <100000>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_i2c3_1>;
- + status = "okay";
- +
- + ov564x: ov564x@3c {
- + compatible = "ovti,ov564x";
- + reg = <0x3c>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_csi_0>;
- + clocks = <&clks IMX6SL_CLK_CSI>;
- + clock-names = "csi_mclk";
- + AVDD-supply = <&vgen6_reg>; /* 2.8v */
- + DVDD-supply = <&vgen2_reg>; /* 1.5v*/
- + pwn-gpios = <&gpio1 25 1>;
- + rst-gpios = <&gpio1 26 0>;
- + csi_id = <0>;
- + mclk = <24000000>;
- + mclk_source = <0>;
- + };
- +};
- +
- &iomuxc {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_hog>;
-
- - hog {
- + imx6sl-evk {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX6SL_PAD_KEY_ROW7__GPIO4_IO07 0x17059
- @@ -78,21 +444,270 @@
- MX6SL_PAD_REF_CLK_32K__GPIO3_IO22 0x17059
- MX6SL_PAD_KEY_COL4__GPIO4_IO00 0x80000000
- MX6SL_PAD_KEY_COL5__GPIO4_IO02 0x80000000
- + MX6SL_PAD_AUD_MCLK__AUDIO_CLK_OUT 0x4130b0
- + >;
- + };
- +
- + pinctrl_audmux3: audmux3grp {
- + fsl,pins = <
- + MX6SL_PAD_AUD_RXD__AUD3_RXD 0x4130b0
- + MX6SL_PAD_AUD_TXC__AUD3_TXC 0x4130b0
- + MX6SL_PAD_AUD_TXD__AUD3_TXD 0x4110b0
- + MX6SL_PAD_AUD_TXFS__AUD3_TXFS 0x4130b0
- + >;
- + };
- +
- + pinctrl_ecspi1: ecspi1grp {
- + fsl,pins = <
- + MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO 0x100b1
- + MX6SL_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x100b1
- + MX6SL_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x100b1
- + MX6SL_PAD_ECSPI1_SS0__GPIO4_IO11 0x80000000
- + >;
- + };
- +
- + pinctrl_fec: fecgrp {
- + fsl,pins = <
- + MX6SL_PAD_FEC_MDC__FEC_MDC 0x1b0b0
- + MX6SL_PAD_FEC_MDIO__FEC_MDIO 0x1b0b0
- + MX6SL_PAD_FEC_CRS_DV__FEC_RX_DV 0x1b0b0
- + MX6SL_PAD_FEC_RXD0__FEC_RX_DATA0 0x1b0b0
- + MX6SL_PAD_FEC_RXD1__FEC_RX_DATA1 0x1b0b0
- + MX6SL_PAD_FEC_TX_EN__FEC_TX_EN 0x1b0b0
- + MX6SL_PAD_FEC_TXD0__FEC_TX_DATA0 0x1b0b0
- + MX6SL_PAD_FEC_TXD1__FEC_TX_DATA1 0x1b0b0
- + MX6SL_PAD_FEC_REF_CLK__FEC_REF_OUT 0x4001b0a8
- + >;
- + };
- +
- + pinctrl_i2c1: i2c1grp {
- + fsl,pins = <
- + MX6SL_PAD_I2C1_SCL__I2C1_SCL 0x4001b8b1
- + MX6SL_PAD_I2C1_SDA__I2C1_SDA 0x4001b8b1
- + >;
- + };
- +
- +
- + pinctrl_i2c2: i2c2grp {
- + fsl,pins = <
- + MX6SL_PAD_I2C2_SCL__I2C2_SCL 0x4001b8b1
- + MX6SL_PAD_I2C2_SDA__I2C2_SDA 0x4001b8b1
- + >;
- + };
- +
- + pinctrl_led: ledgrp {
- + fsl,pins = <
- + MX6SL_PAD_HSIC_STROBE__GPIO3_IO20 0x17059
- + >;
- + };
- +
- + pinctrl_kpp: kppgrp {
- + fsl,pins = <
- + MX6SL_PAD_KEY_ROW0__KEY_ROW0 0x1b010
- + MX6SL_PAD_KEY_ROW1__KEY_ROW1 0x1b010
- + MX6SL_PAD_KEY_ROW2__KEY_ROW2 0x1b0b0
- + MX6SL_PAD_KEY_COL0__KEY_COL0 0x110b0
- + MX6SL_PAD_KEY_COL1__KEY_COL1 0x110b0
- + MX6SL_PAD_KEY_COL2__KEY_COL2 0x110b0
- + >;
- + };
- +
- + pinctrl_uart1: uart1grp {
- + fsl,pins = <
- + MX6SL_PAD_UART1_RXD__UART1_RX_DATA 0x1b0b1
- + MX6SL_PAD_UART1_TXD__UART1_TX_DATA 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usbotg1: usbotg1grp {
- + fsl,pins = <
- + MX6SL_PAD_EPDC_PWRCOM__USB_OTG1_ID 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc1: usdhc1grp {
- + fsl,pins = <
- + MX6SL_PAD_SD1_CMD__SD1_CMD 0x17059
- + MX6SL_PAD_SD1_CLK__SD1_CLK 0x10059
- + MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x17059
- + MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x17059
- + MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x17059
- + MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x17059
- + MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x17059
- + MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x17059
- + MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x17059
- + MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
- + fsl,pins = <
- + MX6SL_PAD_SD1_CMD__SD1_CMD 0x170b9
- + MX6SL_PAD_SD1_CLK__SD1_CLK 0x100b9
- + MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170b9
- + MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170b9
- + MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170b9
- + MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170b9
- + MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170b9
- + MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170b9
- + MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170b9
- + MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170b9
- + >;
- + };
- +
- + pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
- + fsl,pins = <
- + MX6SL_PAD_SD1_CMD__SD1_CMD 0x170f9
- + MX6SL_PAD_SD1_CLK__SD1_CLK 0x100f9
- + MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170f9
- + MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170f9
- + MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170f9
- + MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170f9
- + MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170f9
- + MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170f9
- + MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170f9
- + MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170f9
- + >;
- + };
- +
- + pinctrl_usdhc2: usdhc2grp {
- + fsl,pins = <
- + MX6SL_PAD_SD2_CMD__SD2_CMD 0x17059
- + MX6SL_PAD_SD2_CLK__SD2_CLK 0x10059
- + MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- + MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- + MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- + MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
- + fsl,pins = <
- + MX6SL_PAD_SD2_CMD__SD2_CMD 0x170b9
- + MX6SL_PAD_SD2_CLK__SD2_CLK 0x100b9
- + MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x170b9
- + MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x170b9
- + MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x170b9
- + MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x170b9
- + >;
- + };
- +
- + pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
- + fsl,pins = <
- + MX6SL_PAD_SD2_CMD__SD2_CMD 0x170f9
- + MX6SL_PAD_SD2_CLK__SD2_CLK 0x100f9
- + MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x170f9
- + MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x170f9
- + MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x170f9
- + MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x170f9
- + >;
- + };
- +
- + pinctrl_usdhc3: usdhc3grp {
- + fsl,pins = <
- + MX6SL_PAD_SD3_CMD__SD3_CMD 0x17059
- + MX6SL_PAD_SD3_CLK__SD3_CLK 0x10059
- + MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- + MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- + MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- + MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
- + fsl,pins = <
- + MX6SL_PAD_SD3_CMD__SD3_CMD 0x170b9
- + MX6SL_PAD_SD3_CLK__SD3_CLK 0x100b9
- + MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x170b9
- + MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x170b9
- + MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x170b9
- + MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x170b9
- + >;
- + };
- +
- + pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
- + fsl,pins = <
- + MX6SL_PAD_SD3_CMD__SD3_CMD 0x170f9
- + MX6SL_PAD_SD3_CLK__SD3_CLK 0x100f9
- + MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x170f9
- + MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x170f9
- + MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x170f9
- + MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
- >;
- };
- };
- };
-
- +&kpp {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_kpp>;
- + linux,keymap = <
- + MATRIX_KEY(0x0, 0x0, KEY_UP) /* ROW0, COL0 */
- + MATRIX_KEY(0x0, 0x1, KEY_DOWN) /* ROW0, COL1 */
- + MATRIX_KEY(0x0, 0x2, KEY_ENTER) /* ROW0, COL2 */
- + MATRIX_KEY(0x1, 0x0, KEY_HOME) /* ROW1, COL0 */
- + MATRIX_KEY(0x1, 0x1, KEY_RIGHT) /* ROW1, COL1 */
- + MATRIX_KEY(0x1, 0x2, KEY_LEFT) /* ROW1, COL2 */
- + MATRIX_KEY(0x2, 0x0, KEY_VOLUMEDOWN) /* ROW2, COL0 */
- + MATRIX_KEY(0x2, 0x1, KEY_VOLUMEUP) /* ROW2, COL1 */
- + >;
- + status = "okay";
- +};
- +
- +&ssi2 {
- + fsl,mode = "i2s-slave";
- + status = "okay";
- +};
- +
- +&lcdif {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_lcdif_dat_0
- + &pinctrl_lcdif_ctrl_0>;
- + lcd-supply = <®_lcd_3v3>;
- + display = <&display>;
- + status = "okay";
- +
- + display: display {
- + bits-per-pixel = <16>;
- + bus-width = <24>;
- +
- + display-timings {
- + native-mode = <&timing0>;
- + timing0: timing0 {
- + clock-frequency = <33500000>;
- + hactive = <800>;
- + vactive = <480>;
- + hback-porch = <89>;
- + hfront-porch = <164>;
- + vback-porch = <23>;
- + vfront-porch = <10>;
- + hsync-len = <10>;
- + vsync-len = <10>;
- + hsync-active = <0>;
- + vsync-active = <0>;
- + de-active = <1>;
- + pixelclk-active = <0>;
- + };
- + };
- + };
- +};
- +
- +&pwm1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_pwm1_0>;
- + status = "okay";
- +};
- +
- &uart1 {
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_uart1_1>;
- + pinctrl-0 = <&pinctrl_uart1>;
- status = "okay";
- };
-
- &usbotg1 {
- vbus-supply = <®_usb_otg1_vbus>;
- pinctrl-names = "default";
- - pinctrl-0 = <&pinctrl_usbotg1_1>;
- + pinctrl-0 = <&pinctrl_usbotg1>;
- disable-over-current;
- status = "okay";
- };
- @@ -106,9 +721,9 @@
-
- &usdhc1 {
- pinctrl-names = "default", "state_100mhz", "state_200mhz";
- - pinctrl-0 = <&pinctrl_usdhc1_1>;
- - pinctrl-1 = <&pinctrl_usdhc1_1_100mhz>;
- - pinctrl-2 = <&pinctrl_usdhc1_1_200mhz>;
- + pinctrl-0 = <&pinctrl_usdhc1>;
- + pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
- + pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
- bus-width = <8>;
- cd-gpios = <&gpio4 7 0>;
- wp-gpios = <&gpio4 6 0>;
- @@ -117,9 +732,9 @@
-
- &usdhc2 {
- pinctrl-names = "default", "state_100mhz", "state_200mhz";
- - pinctrl-0 = <&pinctrl_usdhc2_1>;
- - pinctrl-1 = <&pinctrl_usdhc2_1_100mhz>;
- - pinctrl-2 = <&pinctrl_usdhc2_1_200mhz>;
- + pinctrl-0 = <&pinctrl_usdhc2>;
- + pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
- + pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
- cd-gpios = <&gpio5 0 0>;
- wp-gpios = <&gpio4 29 0>;
- status = "okay";
- @@ -127,9 +742,26 @@
-
- &usdhc3 {
- pinctrl-names = "default", "state_100mhz", "state_200mhz";
- - pinctrl-0 = <&pinctrl_usdhc3_1>;
- - pinctrl-1 = <&pinctrl_usdhc3_1_100mhz>;
- - pinctrl-2 = <&pinctrl_usdhc3_1_200mhz>;
- + pinctrl-0 = <&pinctrl_usdhc3>;
- + pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
- + pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
- cd-gpios = <&gpio3 22 0>;
- status = "okay";
- };
- +
- +&pxp {
- + status = "okay";
- +};
- +
- +&gpc {
- + fsl,cpu_pupscr_sw2iso = <0xf>;
- + fsl,cpu_pupscr_sw = <0xf>;
- + fsl,cpu_pdnscr_iso2sw = <0x1>;
- + fsl,cpu_pdnscr_iso = <0x1>;
- + fsl,ldo-bypass; /* use ldo-bypass, u-boot will check it and configure */
- + pu-supply = <&pu_dummy>; /* ldo-bypass:use pu_dummy if VDDSOC share with VDDPU */
- +};
- +
- +&gpu {
- + pu-supply = <&pu_dummy>; /* ldo-bypass:use pu_dummy if VDDSOC share with VDDPU */
- +};
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/Makefile linux-3.14.35/arch/arm/boot/dts/Makefile
- --- linux-3.14.35.orig/arch/arm/boot/dts/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/Makefile 2015-03-08 14:27:37.401684503 -0500
- @@ -154,16 +154,37 @@
- imx53-qsb.dtb \
- imx53-smd.dtb \
- imx6dl-cubox-i.dtb \
- + imx6dl-dfi-fs700-m60.dtb \
- + imx6dl-gw51xx.dtb \
- + imx6dl-gw52xx.dtb \
- + imx6dl-gw53xx.dtb \
- + imx6dl-gw54xx.dtb \
- imx6dl-hummingboard.dtb \
- + imx6dl-nitrogen6x.dtb \
- + imx6dl-phytec-pbab01.dtb \
- imx6dl-sabreauto.dtb \
- + imx6dl-sabrelite.dtb \
- imx6dl-sabresd.dtb \
- + imx6dl-sabresd-hdcp.dtb \
- imx6dl-wandboard.dtb \
- imx6q-arm2.dtb \
- + imx6q-cm-fx6.dtb \
- imx6q-cubox-i.dtb \
- + imx6q-hummingboard.dtb \
- + imx6q-dfi-fs700-m60.dtb \
- + imx6q-dmo-edmqmx6.dtb \
- + imx6q-gk802.dtb \
- + imx6q-gw51xx.dtb \
- + imx6q-gw52xx.dtb \
- + imx6q-gw53xx.dtb \
- + imx6q-gw5400-a.dtb \
- + imx6q-gw54xx.dtb \
- + imx6q-nitrogen6x.dtb \
- imx6q-phytec-pbab01.dtb \
- imx6q-sabreauto.dtb \
- imx6q-sabrelite.dtb \
- imx6q-sabresd.dtb \
- + imx6q-sabresd-hdcp.dtb \
- imx6q-sbc6x.dtb \
- imx6q-udoo.dtb \
- imx6q-wandboard.dtb \
- @@ -312,7 +333,14 @@
- dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \
- vexpress-v2p-ca9.dtb \
- vexpress-v2p-ca15-tc1.dtb \
- - vexpress-v2p-ca15_a7.dtb
- + vexpress-v2p-ca15_a7.dtb \
- + rtsm_ve-cortex_a9x2.dtb \
- + rtsm_ve-cortex_a9x4.dtb \
- + rtsm_ve-cortex_a15x1.dtb \
- + rtsm_ve-cortex_a15x2.dtb \
- + rtsm_ve-cortex_a15x4.dtb \
- + rtsm_ve-v2p-ca15x1-ca7x1.dtb \
- + rtsm_ve-v2p-ca15x4-ca7x4.dtb
- dtb-$(CONFIG_ARCH_VIRT) += xenvm-4.2.dtb
- dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \
- wm8505-ref.dtb \
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/marco.dtsi linux-3.14.35/arch/arm/boot/dts/marco.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/marco.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/marco.dtsi 2015-03-08 14:27:37.401684503 -0500
- @@ -36,7 +36,7 @@
- ranges = <0x40000000 0x40000000 0xa0000000>;
-
- l2-cache-controller@c0030000 {
- - compatible = "sirf,marco-pl310-cache", "arm,pl310-cache";
- + compatible = "arm,pl310-cache";
- reg = <0xc0030000 0x1000>;
- interrupts = <0 59 0>;
- arm,tag-latency = <1 1 1>;
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/prima2.dtsi linux-3.14.35/arch/arm/boot/dts/prima2.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/prima2.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/prima2.dtsi 2015-03-08 14:27:37.401684503 -0500
- @@ -48,7 +48,7 @@
- ranges = <0x40000000 0x40000000 0x80000000>;
-
- l2-cache-controller@80040000 {
- - compatible = "arm,pl310-cache", "sirf,prima2-pl310-cache";
- + compatible = "arm,pl310-cache";
- reg = <0x80040000 0x1000>;
- interrupts = <59>;
- arm,tag-latency = <1 1 1>;
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/rtsm_ve-cortex_a15x1.dts linux-3.14.35/arch/arm/boot/dts/rtsm_ve-cortex_a15x1.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/rtsm_ve-cortex_a15x1.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/rtsm_ve-cortex_a15x1.dts 2015-03-08 14:27:37.401684503 -0500
- @@ -0,0 +1,159 @@
- +/*
- + * ARM Ltd. Fast Models
- + *
- + * Versatile Express (VE) system model
- + * ARMCortexA15x1CT
- + *
- + * RTSM_VE_Cortex_A15x1.lisa
- + */
- +
- +/dts-v1/;
- +
- +/ {
- + model = "RTSM_VE_CortexA15x1";
- + arm,vexpress,site = <0xf>;
- + compatible = "arm,rtsm_ve,cortex_a15x1", "arm,vexpress";
- + interrupt-parent = <&gic>;
- + #address-cells = <2>;
- + #size-cells = <2>;
- +
- + chosen { };
- +
- + aliases {
- + serial0 = &v2m_serial0;
- + serial1 = &v2m_serial1;
- + serial2 = &v2m_serial2;
- + serial3 = &v2m_serial3;
- + };
- +
- + cpus {
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + cpu@0 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a15";
- + reg = <0>;
- + };
- + };
- +
- + memory@80000000 {
- + device_type = "memory";
- + reg = <0 0x80000000 0 0x80000000>;
- + };
- +
- + gic: interrupt-controller@2c001000 {
- + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
- + #interrupt-cells = <3>;
- + #address-cells = <0>;
- + interrupt-controller;
- + reg = <0 0x2c001000 0 0x1000>,
- + <0 0x2c002000 0 0x1000>,
- + <0 0x2c004000 0 0x2000>,
- + <0 0x2c006000 0 0x2000>;
- + interrupts = <1 9 0xf04>;
- + };
- +
- + timer {
- + compatible = "arm,armv7-timer";
- + interrupts = <1 13 0xf08>,
- + <1 14 0xf08>,
- + <1 11 0xf08>,
- + <1 10 0xf08>;
- + };
- +
- + dcc {
- + compatible = "arm,vexpress,config-bus";
- + arm,vexpress,config-bridge = <&v2m_sysreg>;
- +
- + osc@0 {
- + /* ACLK clock to the AXI master port on the test chip */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 0>;
- + freq-range = <30000000 50000000>;
- + #clock-cells = <0>;
- + clock-output-names = "extsaxiclk";
- + };
- +
- + oscclk1: osc@1 {
- + /* Reference clock for the CLCD */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 1>;
- + freq-range = <10000000 80000000>;
- + #clock-cells = <0>;
- + clock-output-names = "clcdclk";
- + };
- +
- + smbclk: oscclk2: osc@2 {
- + /* Reference clock for the test chip internal PLLs */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 2>;
- + freq-range = <33000000 100000000>;
- + #clock-cells = <0>;
- + clock-output-names = "tcrefclk";
- + };
- + };
- +
- + smb {
- + compatible = "simple-bus";
- +
- + #address-cells = <2>;
- + #size-cells = <1>;
- + ranges = <0 0 0 0x08000000 0x04000000>,
- + <1 0 0 0x14000000 0x04000000>,
- + <2 0 0 0x18000000 0x04000000>,
- + <3 0 0 0x1c000000 0x04000000>,
- + <4 0 0 0x0c000000 0x04000000>,
- + <5 0 0 0x10000000 0x04000000>;
- +
- + #interrupt-cells = <1>;
- + interrupt-map-mask = <0 0 63>;
- + interrupt-map = <0 0 0 &gic 0 0 4>,
- + <0 0 1 &gic 0 1 4>,
- + <0 0 2 &gic 0 2 4>,
- + <0 0 3 &gic 0 3 4>,
- + <0 0 4 &gic 0 4 4>,
- + <0 0 5 &gic 0 5 4>,
- + <0 0 6 &gic 0 6 4>,
- + <0 0 7 &gic 0 7 4>,
- + <0 0 8 &gic 0 8 4>,
- + <0 0 9 &gic 0 9 4>,
- + <0 0 10 &gic 0 10 4>,
- + <0 0 11 &gic 0 11 4>,
- + <0 0 12 &gic 0 12 4>,
- + <0 0 13 &gic 0 13 4>,
- + <0 0 14 &gic 0 14 4>,
- + <0 0 15 &gic 0 15 4>,
- + <0 0 16 &gic 0 16 4>,
- + <0 0 17 &gic 0 17 4>,
- + <0 0 18 &gic 0 18 4>,
- + <0 0 19 &gic 0 19 4>,
- + <0 0 20 &gic 0 20 4>,
- + <0 0 21 &gic 0 21 4>,
- + <0 0 22 &gic 0 22 4>,
- + <0 0 23 &gic 0 23 4>,
- + <0 0 24 &gic 0 24 4>,
- + <0 0 25 &gic 0 25 4>,
- + <0 0 26 &gic 0 26 4>,
- + <0 0 27 &gic 0 27 4>,
- + <0 0 28 &gic 0 28 4>,
- + <0 0 29 &gic 0 29 4>,
- + <0 0 30 &gic 0 30 4>,
- + <0 0 31 &gic 0 31 4>,
- + <0 0 32 &gic 0 32 4>,
- + <0 0 33 &gic 0 33 4>,
- + <0 0 34 &gic 0 34 4>,
- + <0 0 35 &gic 0 35 4>,
- + <0 0 36 &gic 0 36 4>,
- + <0 0 37 &gic 0 37 4>,
- + <0 0 38 &gic 0 38 4>,
- + <0 0 39 &gic 0 39 4>,
- + <0 0 40 &gic 0 40 4>,
- + <0 0 41 &gic 0 41 4>,
- + <0 0 42 &gic 0 42 4>;
- +
- + /include/ "rtsm_ve-motherboard.dtsi"
- + };
- +};
- +
- +/include/ "clcd-panels.dtsi"
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/rtsm_ve-cortex_a15x2.dts linux-3.14.35/arch/arm/boot/dts/rtsm_ve-cortex_a15x2.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/rtsm_ve-cortex_a15x2.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/rtsm_ve-cortex_a15x2.dts 2015-03-08 14:27:37.405684503 -0500
- @@ -0,0 +1,165 @@
- +/*
- + * ARM Ltd. Fast Models
- + *
- + * Versatile Express (VE) system model
- + * ARMCortexA15x2CT
- + *
- + * RTSM_VE_Cortex_A15x2.lisa
- + */
- +
- +/dts-v1/;
- +
- +/ {
- + model = "RTSM_VE_CortexA15x2";
- + arm,vexpress,site = <0xf>;
- + compatible = "arm,rtsm_ve,cortex_a15x2", "arm,vexpress";
- + interrupt-parent = <&gic>;
- + #address-cells = <2>;
- + #size-cells = <2>;
- +
- + chosen { };
- +
- + aliases {
- + serial0 = &v2m_serial0;
- + serial1 = &v2m_serial1;
- + serial2 = &v2m_serial2;
- + serial3 = &v2m_serial3;
- + };
- +
- + cpus {
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + cpu@0 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a15";
- + reg = <0>;
- + };
- +
- + cpu@1 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a15";
- + reg = <1>;
- + };
- + };
- +
- + memory@80000000 {
- + device_type = "memory";
- + reg = <0 0x80000000 0 0x80000000>;
- + };
- +
- + gic: interrupt-controller@2c001000 {
- + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
- + #interrupt-cells = <3>;
- + #address-cells = <0>;
- + interrupt-controller;
- + reg = <0 0x2c001000 0 0x1000>,
- + <0 0x2c002000 0 0x1000>,
- + <0 0x2c004000 0 0x2000>,
- + <0 0x2c006000 0 0x2000>;
- + interrupts = <1 9 0xf04>;
- + };
- +
- + timer {
- + compatible = "arm,armv7-timer";
- + interrupts = <1 13 0xf08>,
- + <1 14 0xf08>,
- + <1 11 0xf08>,
- + <1 10 0xf08>;
- + };
- +
- + dcc {
- + compatible = "arm,vexpress,config-bus";
- + arm,vexpress,config-bridge = <&v2m_sysreg>;
- +
- + osc@0 {
- + /* ACLK clock to the AXI master port on the test chip */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 0>;
- + freq-range = <30000000 50000000>;
- + #clock-cells = <0>;
- + clock-output-names = "extsaxiclk";
- + };
- +
- + oscclk1: osc@1 {
- + /* Reference clock for the CLCD */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 1>;
- + freq-range = <10000000 80000000>;
- + #clock-cells = <0>;
- + clock-output-names = "clcdclk";
- + };
- +
- + smbclk: oscclk2: osc@2 {
- + /* Reference clock for the test chip internal PLLs */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 2>;
- + freq-range = <33000000 100000000>;
- + #clock-cells = <0>;
- + clock-output-names = "tcrefclk";
- + };
- + };
- +
- + smb {
- + compatible = "simple-bus";
- +
- + #address-cells = <2>;
- + #size-cells = <1>;
- + ranges = <0 0 0 0x08000000 0x04000000>,
- + <1 0 0 0x14000000 0x04000000>,
- + <2 0 0 0x18000000 0x04000000>,
- + <3 0 0 0x1c000000 0x04000000>,
- + <4 0 0 0x0c000000 0x04000000>,
- + <5 0 0 0x10000000 0x04000000>;
- +
- + #interrupt-cells = <1>;
- + interrupt-map-mask = <0 0 63>;
- + interrupt-map = <0 0 0 &gic 0 0 4>,
- + <0 0 1 &gic 0 1 4>,
- + <0 0 2 &gic 0 2 4>,
- + <0 0 3 &gic 0 3 4>,
- + <0 0 4 &gic 0 4 4>,
- + <0 0 5 &gic 0 5 4>,
- + <0 0 6 &gic 0 6 4>,
- + <0 0 7 &gic 0 7 4>,
- + <0 0 8 &gic 0 8 4>,
- + <0 0 9 &gic 0 9 4>,
- + <0 0 10 &gic 0 10 4>,
- + <0 0 11 &gic 0 11 4>,
- + <0 0 12 &gic 0 12 4>,
- + <0 0 13 &gic 0 13 4>,
- + <0 0 14 &gic 0 14 4>,
- + <0 0 15 &gic 0 15 4>,
- + <0 0 16 &gic 0 16 4>,
- + <0 0 17 &gic 0 17 4>,
- + <0 0 18 &gic 0 18 4>,
- + <0 0 19 &gic 0 19 4>,
- + <0 0 20 &gic 0 20 4>,
- + <0 0 21 &gic 0 21 4>,
- + <0 0 22 &gic 0 22 4>,
- + <0 0 23 &gic 0 23 4>,
- + <0 0 24 &gic 0 24 4>,
- + <0 0 25 &gic 0 25 4>,
- + <0 0 26 &gic 0 26 4>,
- + <0 0 27 &gic 0 27 4>,
- + <0 0 28 &gic 0 28 4>,
- + <0 0 29 &gic 0 29 4>,
- + <0 0 30 &gic 0 30 4>,
- + <0 0 31 &gic 0 31 4>,
- + <0 0 32 &gic 0 32 4>,
- + <0 0 33 &gic 0 33 4>,
- + <0 0 34 &gic 0 34 4>,
- + <0 0 35 &gic 0 35 4>,
- + <0 0 36 &gic 0 36 4>,
- + <0 0 37 &gic 0 37 4>,
- + <0 0 38 &gic 0 38 4>,
- + <0 0 39 &gic 0 39 4>,
- + <0 0 40 &gic 0 40 4>,
- + <0 0 41 &gic 0 41 4>,
- + <0 0 42 &gic 0 42 4>;
- +
- + /include/ "rtsm_ve-motherboard.dtsi"
- + };
- +};
- +
- +/include/ "clcd-panels.dtsi"
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/rtsm_ve-cortex_a15x4.dts linux-3.14.35/arch/arm/boot/dts/rtsm_ve-cortex_a15x4.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/rtsm_ve-cortex_a15x4.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/rtsm_ve-cortex_a15x4.dts 2015-03-08 14:27:37.405684503 -0500
- @@ -0,0 +1,177 @@
- +/*
- + * ARM Ltd. Fast Models
- + *
- + * Versatile Express (VE) system model
- + * ARMCortexA15x4CT
- + *
- + * RTSM_VE_Cortex_A15x4.lisa
- + */
- +
- +/dts-v1/;
- +
- +/ {
- + model = "RTSM_VE_CortexA15x4";
- + arm,vexpress,site = <0xf>;
- + compatible = "arm,rtsm_ve,cortex_a15x4", "arm,vexpress";
- + interrupt-parent = <&gic>;
- + #address-cells = <2>;
- + #size-cells = <2>;
- +
- + chosen { };
- +
- + aliases {
- + serial0 = &v2m_serial0;
- + serial1 = &v2m_serial1;
- + serial2 = &v2m_serial2;
- + serial3 = &v2m_serial3;
- + };
- +
- + cpus {
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + cpu@0 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a15";
- + reg = <0>;
- + };
- +
- + cpu@1 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a15";
- + reg = <1>;
- + };
- +
- + cpu@2 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a15";
- + reg = <2>;
- + };
- +
- + cpu@3 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a15";
- + reg = <3>;
- + };
- + };
- +
- + memory@80000000 {
- + device_type = "memory";
- + reg = <0 0x80000000 0 0x80000000>;
- + };
- +
- + gic: interrupt-controller@2c001000 {
- + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
- + #interrupt-cells = <3>;
- + #address-cells = <0>;
- + interrupt-controller;
- + reg = <0 0x2c001000 0 0x1000>,
- + <0 0x2c002000 0 0x1000>,
- + <0 0x2c004000 0 0x2000>,
- + <0 0x2c006000 0 0x2000>;
- + interrupts = <1 9 0xf04>;
- + };
- +
- + timer {
- + compatible = "arm,armv7-timer";
- + interrupts = <1 13 0xf08>,
- + <1 14 0xf08>,
- + <1 11 0xf08>,
- + <1 10 0xf08>;
- + };
- +
- + dcc {
- + compatible = "arm,vexpress,config-bus";
- + arm,vexpress,config-bridge = <&v2m_sysreg>;
- +
- + osc@0 {
- + /* ACLK clock to the AXI master port on the test chip */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 0>;
- + freq-range = <30000000 50000000>;
- + #clock-cells = <0>;
- + clock-output-names = "extsaxiclk";
- + };
- +
- + oscclk1: osc@1 {
- + /* Reference clock for the CLCD */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 1>;
- + freq-range = <10000000 80000000>;
- + #clock-cells = <0>;
- + clock-output-names = "clcdclk";
- + };
- +
- + smbclk: oscclk2: osc@2 {
- + /* Reference clock for the test chip internal PLLs */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 2>;
- + freq-range = <33000000 100000000>;
- + #clock-cells = <0>;
- + clock-output-names = "tcrefclk";
- + };
- + };
- +
- + smb {
- + compatible = "simple-bus";
- +
- + #address-cells = <2>;
- + #size-cells = <1>;
- + ranges = <0 0 0 0x08000000 0x04000000>,
- + <1 0 0 0x14000000 0x04000000>,
- + <2 0 0 0x18000000 0x04000000>,
- + <3 0 0 0x1c000000 0x04000000>,
- + <4 0 0 0x0c000000 0x04000000>,
- + <5 0 0 0x10000000 0x04000000>;
- +
- + #interrupt-cells = <1>;
- + interrupt-map-mask = <0 0 63>;
- + interrupt-map = <0 0 0 &gic 0 0 4>,
- + <0 0 1 &gic 0 1 4>,
- + <0 0 2 &gic 0 2 4>,
- + <0 0 3 &gic 0 3 4>,
- + <0 0 4 &gic 0 4 4>,
- + <0 0 5 &gic 0 5 4>,
- + <0 0 6 &gic 0 6 4>,
- + <0 0 7 &gic 0 7 4>,
- + <0 0 8 &gic 0 8 4>,
- + <0 0 9 &gic 0 9 4>,
- + <0 0 10 &gic 0 10 4>,
- + <0 0 11 &gic 0 11 4>,
- + <0 0 12 &gic 0 12 4>,
- + <0 0 13 &gic 0 13 4>,
- + <0 0 14 &gic 0 14 4>,
- + <0 0 15 &gic 0 15 4>,
- + <0 0 16 &gic 0 16 4>,
- + <0 0 17 &gic 0 17 4>,
- + <0 0 18 &gic 0 18 4>,
- + <0 0 19 &gic 0 19 4>,
- + <0 0 20 &gic 0 20 4>,
- + <0 0 21 &gic 0 21 4>,
- + <0 0 22 &gic 0 22 4>,
- + <0 0 23 &gic 0 23 4>,
- + <0 0 24 &gic 0 24 4>,
- + <0 0 25 &gic 0 25 4>,
- + <0 0 26 &gic 0 26 4>,
- + <0 0 27 &gic 0 27 4>,
- + <0 0 28 &gic 0 28 4>,
- + <0 0 29 &gic 0 29 4>,
- + <0 0 30 &gic 0 30 4>,
- + <0 0 31 &gic 0 31 4>,
- + <0 0 32 &gic 0 32 4>,
- + <0 0 33 &gic 0 33 4>,
- + <0 0 34 &gic 0 34 4>,
- + <0 0 35 &gic 0 35 4>,
- + <0 0 36 &gic 0 36 4>,
- + <0 0 37 &gic 0 37 4>,
- + <0 0 38 &gic 0 38 4>,
- + <0 0 39 &gic 0 39 4>,
- + <0 0 40 &gic 0 40 4>,
- + <0 0 41 &gic 0 41 4>,
- + <0 0 42 &gic 0 42 4>;
- +
- + /include/ "rtsm_ve-motherboard.dtsi"
- + };
- +};
- +
- +/include/ "clcd-panels.dtsi"
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/rtsm_ve-cortex_a9x2.dts linux-3.14.35/arch/arm/boot/dts/rtsm_ve-cortex_a9x2.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/rtsm_ve-cortex_a9x2.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/rtsm_ve-cortex_a9x2.dts 2015-03-08 14:27:37.405684503 -0500
- @@ -0,0 +1,171 @@
- +/*
- + * ARM Ltd. Fast Models
- + *
- + * Versatile Express (VE) system model
- + * ARMCortexA9MPx2CT
- + *
- + * RTSM_VE_Cortex_A9x2.lisa
- + */
- +
- +/dts-v1/;
- +
- +/ {
- + model = "RTSM_VE_CortexA9x2";
- + arm,vexpress,site = <0xf>;
- + compatible = "arm,rtsm_ve,cortex_a9x2", "arm,vexpress";
- + interrupt-parent = <&gic>;
- + #address-cells = <1>;
- + #size-cells = <1>;
- +
- + chosen { };
- +
- + aliases {
- + serial0 = &v2m_serial0;
- + serial1 = &v2m_serial1;
- + serial2 = &v2m_serial2;
- + serial3 = &v2m_serial3;
- + };
- +
- + cpus {
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + cpu@0 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a9";
- + reg = <0>;
- + };
- +
- + cpu@1 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a9";
- + reg = <1>;
- + };
- + };
- +
- + memory@80000000 {
- + device_type = "memory";
- + reg = <0x80000000 0x80000000>;
- + };
- +
- + scu@2c000000 {
- + compatible = "arm,cortex-a9-scu";
- + reg = <0x2c000000 0x58>;
- + };
- +
- + timer@2c000600 {
- + compatible = "arm,cortex-a9-twd-timer";
- + reg = <0x2c000600 0x20>;
- + interrupts = <1 13 0xf04>;
- + };
- +
- + watchdog@2c000620 {
- + compatible = "arm,cortex-a9-twd-wdt";
- + reg = <0x2c000620 0x20>;
- + interrupts = <1 14 0xf04>;
- + };
- +
- + gic: interrupt-controller@2c001000 {
- + compatible = "arm,cortex-a9-gic";
- + #interrupt-cells = <3>;
- + #address-cells = <0>;
- + interrupt-controller;
- + reg = <0x2c001000 0x1000>,
- + <0x2c000100 0x100>;
- + };
- +
- + dcc {
- + compatible = "arm,vexpress,config-bus";
- + arm,vexpress,config-bridge = <&v2m_sysreg>;
- +
- + osc@0 {
- + /* ACLK clock to the AXI master port on the test chip */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 0>;
- + freq-range = <30000000 50000000>;
- + #clock-cells = <0>;
- + clock-output-names = "extsaxiclk";
- + };
- +
- + oscclk1: osc@1 {
- + /* Reference clock for the CLCD */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 1>;
- + freq-range = <10000000 80000000>;
- + #clock-cells = <0>;
- + clock-output-names = "clcdclk";
- + };
- +
- + smbclk: oscclk2: osc@2 {
- + /* Reference clock for the test chip internal PLLs */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 2>;
- + freq-range = <33000000 100000000>;
- + #clock-cells = <0>;
- + clock-output-names = "tcrefclk";
- + };
- + };
- +
- + smb {
- + compatible = "simple-bus";
- +
- + #address-cells = <2>;
- + #size-cells = <1>;
- + ranges = <0 0 0x08000000 0x04000000>,
- + <1 0 0x14000000 0x04000000>,
- + <2 0 0x18000000 0x04000000>,
- + <3 0 0x1c000000 0x04000000>,
- + <4 0 0x0c000000 0x04000000>,
- + <5 0 0x10000000 0x04000000>;
- +
- + #interrupt-cells = <1>;
- + interrupt-map-mask = <0 0 63>;
- + interrupt-map = <0 0 0 &gic 0 0 4>,
- + <0 0 1 &gic 0 1 4>,
- + <0 0 2 &gic 0 2 4>,
- + <0 0 3 &gic 0 3 4>,
- + <0 0 4 &gic 0 4 4>,
- + <0 0 5 &gic 0 5 4>,
- + <0 0 6 &gic 0 6 4>,
- + <0 0 7 &gic 0 7 4>,
- + <0 0 8 &gic 0 8 4>,
- + <0 0 9 &gic 0 9 4>,
- + <0 0 10 &gic 0 10 4>,
- + <0 0 11 &gic 0 11 4>,
- + <0 0 12 &gic 0 12 4>,
- + <0 0 13 &gic 0 13 4>,
- + <0 0 14 &gic 0 14 4>,
- + <0 0 15 &gic 0 15 4>,
- + <0 0 16 &gic 0 16 4>,
- + <0 0 17 &gic 0 17 4>,
- + <0 0 18 &gic 0 18 4>,
- + <0 0 19 &gic 0 19 4>,
- + <0 0 20 &gic 0 20 4>,
- + <0 0 21 &gic 0 21 4>,
- + <0 0 22 &gic 0 22 4>,
- + <0 0 23 &gic 0 23 4>,
- + <0 0 24 &gic 0 24 4>,
- + <0 0 25 &gic 0 25 4>,
- + <0 0 26 &gic 0 26 4>,
- + <0 0 27 &gic 0 27 4>,
- + <0 0 28 &gic 0 28 4>,
- + <0 0 29 &gic 0 29 4>,
- + <0 0 30 &gic 0 30 4>,
- + <0 0 31 &gic 0 31 4>,
- + <0 0 32 &gic 0 32 4>,
- + <0 0 33 &gic 0 33 4>,
- + <0 0 34 &gic 0 34 4>,
- + <0 0 35 &gic 0 35 4>,
- + <0 0 36 &gic 0 36 4>,
- + <0 0 37 &gic 0 37 4>,
- + <0 0 38 &gic 0 38 4>,
- + <0 0 39 &gic 0 39 4>,
- + <0 0 40 &gic 0 40 4>,
- + <0 0 41 &gic 0 41 4>,
- + <0 0 42 &gic 0 42 4>;
- +
- + /include/ "rtsm_ve-motherboard.dtsi"
- + };
- +};
- +
- +/include/ "clcd-panels.dtsi"
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/rtsm_ve-cortex_a9x4.dts linux-3.14.35/arch/arm/boot/dts/rtsm_ve-cortex_a9x4.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/rtsm_ve-cortex_a9x4.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/rtsm_ve-cortex_a9x4.dts 2015-03-08 14:27:37.405684503 -0500
- @@ -0,0 +1,183 @@
- +/*
- + * ARM Ltd. Fast Models
- + *
- + * Versatile Express (VE) system model
- + * ARMCortexA9MPx4CT
- + *
- + * RTSM_VE_Cortex_A9x4.lisa
- + */
- +
- +/dts-v1/;
- +
- +/ {
- + model = "RTSM_VE_CortexA9x4";
- + arm,vexpress,site = <0xf>;
- + compatible = "arm,rtsm_ve,cortex_a9x4", "arm,vexpress";
- + interrupt-parent = <&gic>;
- + #address-cells = <1>;
- + #size-cells = <1>;
- +
- + chosen { };
- +
- + aliases {
- + serial0 = &v2m_serial0;
- + serial1 = &v2m_serial1;
- + serial2 = &v2m_serial2;
- + serial3 = &v2m_serial3;
- + };
- +
- + cpus {
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + cpu@0 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a9";
- + reg = <0>;
- + };
- +
- + cpu@1 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a9";
- + reg = <1>;
- + };
- +
- + cpu@2 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a9";
- + reg = <2>;
- + };
- +
- + cpu@3 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a9";
- + reg = <3>;
- + };
- + };
- +
- + memory@80000000 {
- + device_type = "memory";
- + reg = <0x80000000 0x80000000>;
- + };
- +
- + scu@2c000000 {
- + compatible = "arm,cortex-a9-scu";
- + reg = <0x2c000000 0x58>;
- + };
- +
- + timer@2c000600 {
- + compatible = "arm,cortex-a9-twd-timer";
- + reg = <0x2c000600 0x20>;
- + interrupts = <1 13 0xf04>;
- + };
- +
- + watchdog@2c000620 {
- + compatible = "arm,cortex-a9-twd-wdt";
- + reg = <0x2c000620 0x20>;
- + interrupts = <1 14 0xf04>;
- + };
- +
- + gic: interrupt-controller@2c001000 {
- + compatible = "arm,cortex-a9-gic";
- + #interrupt-cells = <3>;
- + #address-cells = <0>;
- + interrupt-controller;
- + reg = <0x2c001000 0x1000>,
- + <0x2c000100 0x100>;
- + };
- +
- + dcc {
- + compatible = "arm,vexpress,config-bus";
- + arm,vexpress,config-bridge = <&v2m_sysreg>;
- +
- + osc@0 {
- + /* ACLK clock to the AXI master port on the test chip */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 0>;
- + freq-range = <30000000 50000000>;
- + #clock-cells = <0>;
- + clock-output-names = "extsaxiclk";
- + };
- +
- + oscclk1: osc@1 {
- + /* Reference clock for the CLCD */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 1>;
- + freq-range = <10000000 80000000>;
- + #clock-cells = <0>;
- + clock-output-names = "clcdclk";
- + };
- +
- + smbclk: oscclk2: osc@2 {
- + /* Reference clock for the test chip internal PLLs */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 2>;
- + freq-range = <33000000 100000000>;
- + #clock-cells = <0>;
- + clock-output-names = "tcrefclk";
- + };
- + };
- +
- + smb {
- + compatible = "simple-bus";
- +
- + #address-cells = <2>;
- + #size-cells = <1>;
- + ranges = <0 0 0x08000000 0x04000000>,
- + <1 0 0x14000000 0x04000000>,
- + <2 0 0x18000000 0x04000000>,
- + <3 0 0x1c000000 0x04000000>,
- + <4 0 0x0c000000 0x04000000>,
- + <5 0 0x10000000 0x04000000>;
- +
- + #interrupt-cells = <1>;
- + interrupt-map-mask = <0 0 63>;
- + interrupt-map = <0 0 0 &gic 0 0 4>,
- + <0 0 1 &gic 0 1 4>,
- + <0 0 2 &gic 0 2 4>,
- + <0 0 3 &gic 0 3 4>,
- + <0 0 4 &gic 0 4 4>,
- + <0 0 5 &gic 0 5 4>,
- + <0 0 6 &gic 0 6 4>,
- + <0 0 7 &gic 0 7 4>,
- + <0 0 8 &gic 0 8 4>,
- + <0 0 9 &gic 0 9 4>,
- + <0 0 10 &gic 0 10 4>,
- + <0 0 11 &gic 0 11 4>,
- + <0 0 12 &gic 0 12 4>,
- + <0 0 13 &gic 0 13 4>,
- + <0 0 14 &gic 0 14 4>,
- + <0 0 15 &gic 0 15 4>,
- + <0 0 16 &gic 0 16 4>,
- + <0 0 17 &gic 0 17 4>,
- + <0 0 18 &gic 0 18 4>,
- + <0 0 19 &gic 0 19 4>,
- + <0 0 20 &gic 0 20 4>,
- + <0 0 21 &gic 0 21 4>,
- + <0 0 22 &gic 0 22 4>,
- + <0 0 23 &gic 0 23 4>,
- + <0 0 24 &gic 0 24 4>,
- + <0 0 25 &gic 0 25 4>,
- + <0 0 26 &gic 0 26 4>,
- + <0 0 27 &gic 0 27 4>,
- + <0 0 28 &gic 0 28 4>,
- + <0 0 29 &gic 0 29 4>,
- + <0 0 30 &gic 0 30 4>,
- + <0 0 31 &gic 0 31 4>,
- + <0 0 32 &gic 0 32 4>,
- + <0 0 33 &gic 0 33 4>,
- + <0 0 34 &gic 0 34 4>,
- + <0 0 35 &gic 0 35 4>,
- + <0 0 36 &gic 0 36 4>,
- + <0 0 37 &gic 0 37 4>,
- + <0 0 38 &gic 0 38 4>,
- + <0 0 39 &gic 0 39 4>,
- + <0 0 40 &gic 0 40 4>,
- + <0 0 41 &gic 0 41 4>,
- + <0 0 42 &gic 0 42 4>;
- +
- + /include/ "rtsm_ve-motherboard.dtsi"
- + };
- +};
- +
- +/include/ "clcd-panels.dtsi"
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/rtsm_ve-motherboard.dtsi linux-3.14.35/arch/arm/boot/dts/rtsm_ve-motherboard.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/rtsm_ve-motherboard.dtsi 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/rtsm_ve-motherboard.dtsi 2015-03-08 14:27:37.405684503 -0500
- @@ -0,0 +1,231 @@
- +/*
- + * ARM Ltd. Fast Models
- + *
- + * Versatile Express (VE) system model
- + * Motherboard component
- + *
- + * VEMotherBoard.lisa
- + */
- +
- + motherboard {
- + compatible = "arm,vexpress,v2m-p1", "simple-bus";
- + arm,hbi = <0x190>;
- + arm,vexpress,site = <0>;
- + arm,v2m-memory-map = "rs1";
- + #address-cells = <2>; /* SMB chipselect number and offset */
- + #size-cells = <1>;
- + #interrupt-cells = <1>;
- + ranges;
- +
- + flash@0,00000000 {
- + compatible = "arm,vexpress-flash", "cfi-flash";
- + reg = <0 0x00000000 0x04000000>,
- + <4 0x00000000 0x04000000>;
- + bank-width = <4>;
- + };
- +
- + vram@2,00000000 {
- + compatible = "arm,vexpress-vram";
- + reg = <2 0x00000000 0x00800000>;
- + };
- +
- + ethernet@2,02000000 {
- + compatible = "smsc,lan91c111";
- + reg = <2 0x02000000 0x10000>;
- + interrupts = <15>;
- + };
- +
- + iofpga@3,00000000 {
- + compatible = "arm,amba-bus", "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <1>;
- + ranges = <0 3 0 0x200000>;
- +
- + v2m_sysreg: sysreg@010000 {
- + compatible = "arm,vexpress-sysreg";
- + reg = <0x010000 0x1000>;
- + gpio-controller;
- + #gpio-cells = <2>;
- + };
- +
- + v2m_sysctl: sysctl@020000 {
- + compatible = "arm,sp810", "arm,primecell";
- + reg = <0x020000 0x1000>;
- + clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>;
- + clock-names = "refclk", "timclk", "apb_pclk";
- + #clock-cells = <1>;
- + clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
- + };
- +
- + aaci@040000 {
- + compatible = "arm,pl041", "arm,primecell";
- + reg = <0x040000 0x1000>;
- + interrupts = <11>;
- + clocks = <&smbclk>;
- + clock-names = "apb_pclk";
- + };
- +
- + mmci@050000 {
- + compatible = "arm,pl180", "arm,primecell";
- + reg = <0x050000 0x1000>;
- + interrupts = <9 10>;
- + cd-gpios = <&v2m_sysreg 0 0>;
- + wp-gpios = <&v2m_sysreg 1 0>;
- + max-frequency = <12000000>;
- + vmmc-supply = <&v2m_fixed_3v3>;
- + clocks = <&v2m_clk24mhz>, <&smbclk>;
- + clock-names = "mclk", "apb_pclk";
- + };
- +
- + kmi@060000 {
- + compatible = "arm,pl050", "arm,primecell";
- + reg = <0x060000 0x1000>;
- + interrupts = <12>;
- + clocks = <&v2m_clk24mhz>, <&smbclk>;
- + clock-names = "KMIREFCLK", "apb_pclk";
- + };
- +
- + kmi@070000 {
- + compatible = "arm,pl050", "arm,primecell";
- + reg = <0x070000 0x1000>;
- + interrupts = <13>;
- + clocks = <&v2m_clk24mhz>, <&smbclk>;
- + clock-names = "KMIREFCLK", "apb_pclk";
- + };
- +
- + v2m_serial0: uart@090000 {
- + compatible = "arm,pl011", "arm,primecell";
- + reg = <0x090000 0x1000>;
- + interrupts = <5>;
- + clocks = <&v2m_clk24mhz>, <&smbclk>;
- + clock-names = "uartclk", "apb_pclk";
- + };
- +
- + v2m_serial1: uart@0a0000 {
- + compatible = "arm,pl011", "arm,primecell";
- + reg = <0x0a0000 0x1000>;
- + interrupts = <6>;
- + clocks = <&v2m_clk24mhz>, <&smbclk>;
- + clock-names = "uartclk", "apb_pclk";
- + };
- +
- + v2m_serial2: uart@0b0000 {
- + compatible = "arm,pl011", "arm,primecell";
- + reg = <0x0b0000 0x1000>;
- + interrupts = <7>;
- + clocks = <&v2m_clk24mhz>, <&smbclk>;
- + clock-names = "uartclk", "apb_pclk";
- + };
- +
- + v2m_serial3: uart@0c0000 {
- + compatible = "arm,pl011", "arm,primecell";
- + reg = <0x0c0000 0x1000>;
- + interrupts = <8>;
- + clocks = <&v2m_clk24mhz>, <&smbclk>;
- + clock-names = "uartclk", "apb_pclk";
- + };
- +
- + wdt@0f0000 {
- + compatible = "arm,sp805", "arm,primecell";
- + reg = <0x0f0000 0x1000>;
- + interrupts = <0>;
- + clocks = <&v2m_refclk32khz>, <&smbclk>;
- + clock-names = "wdogclk", "apb_pclk";
- + };
- +
- + v2m_timer01: timer@110000 {
- + compatible = "arm,sp804", "arm,primecell";
- + reg = <0x110000 0x1000>;
- + interrupts = <2>;
- + clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&smbclk>;
- + clock-names = "timclken1", "timclken2", "apb_pclk";
- + };
- +
- + v2m_timer23: timer@120000 {
- + compatible = "arm,sp804", "arm,primecell";
- + reg = <0x120000 0x1000>;
- + interrupts = <3>;
- + clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&smbclk>;
- + clock-names = "timclken1", "timclken2", "apb_pclk";
- + };
- +
- + rtc@170000 {
- + compatible = "arm,pl031", "arm,primecell";
- + reg = <0x170000 0x1000>;
- + interrupts = <4>;
- + clocks = <&smbclk>;
- + clock-names = "apb_pclk";
- + };
- +
- + clcd@1f0000 {
- + compatible = "arm,pl111", "arm,primecell";
- + reg = <0x1f0000 0x1000>;
- + interrupts = <14>;
- + clocks = <&v2m_oscclk1>, <&smbclk>;
- + clock-names = "v2m:oscclk1", "apb_pclk";
- + mode = "VGA";
- + use_dma = <0>;
- + framebuffer = <0x18000000 0x00180000>;
- + };
- +
- + virtio_block@0130000 {
- + compatible = "virtio,mmio";
- + reg = <0x130000 0x200>;
- + interrupts = <42>;
- + };
- +
- + };
- +
- + v2m_fixed_3v3: fixedregulator@0 {
- + compatible = "regulator-fixed";
- + regulator-name = "3V3";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + v2m_clk24mhz: clk24mhz {
- + compatible = "fixed-clock";
- + #clock-cells = <0>;
- + clock-frequency = <24000000>;
- + clock-output-names = "v2m:clk24mhz";
- + };
- +
- + v2m_refclk1mhz: refclk1mhz {
- + compatible = "fixed-clock";
- + #clock-cells = <0>;
- + clock-frequency = <1000000>;
- + clock-output-names = "v2m:refclk1mhz";
- + };
- +
- + v2m_refclk32khz: refclk32khz {
- + compatible = "fixed-clock";
- + #clock-cells = <0>;
- + clock-frequency = <32768>;
- + clock-output-names = "v2m:refclk32khz";
- + };
- +
- + mcc {
- + compatible = "simple-bus";
- + arm,vexpress,config-bridge = <&v2m_sysreg>;
- +
- + v2m_oscclk1: osc@1 {
- + /* CLCD clock */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 1>;
- + freq-range = <23750000 63500000>;
- + #clock-cells = <0>;
- + clock-output-names = "v2m:oscclk1";
- + };
- +
- + muxfpga@0 {
- + compatible = "arm,vexpress-muxfpga";
- + arm,vexpress-sysreg,func = <7 0>;
- + };
- +
- + shutdown@0 {
- + compatible = "arm,vexpress-shutdown";
- + arm,vexpress-sysreg,func = <8 0>;
- + };
- + };
- + };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/rtsm_ve-v2p-ca15x1-ca7x1.dts linux-3.14.35/arch/arm/boot/dts/rtsm_ve-v2p-ca15x1-ca7x1.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/rtsm_ve-v2p-ca15x1-ca7x1.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/rtsm_ve-v2p-ca15x1-ca7x1.dts 2015-03-08 14:27:37.405684503 -0500
- @@ -0,0 +1,233 @@
- +/*
- + * ARM Ltd. Fast Models
- + *
- + * Versatile Express (VE) system model
- + * ARMCortexA15x4CT
- + * ARMCortexA7x4CT
- + * RTSM_VE_Cortex_A15x1_A7x1.lisa
- + */
- +
- +/dts-v1/;
- +
- +/memreserve/ 0xff000000 0x01000000;
- +
- +/ {
- + model = "RTSM_VE_CortexA15x1-A7x1";
- + arm,vexpress,site = <0xf>;
- + compatible = "arm,rtsm_ve,cortex_a15x1_a7x1", "arm,vexpress";
- + interrupt-parent = <&gic>;
- + #address-cells = <2>;
- + #size-cells = <2>;
- +
- + chosen { };
- +
- + aliases {
- + serial0 = &v2m_serial0;
- + serial1 = &v2m_serial1;
- + serial2 = &v2m_serial2;
- + serial3 = &v2m_serial3;
- + };
- +
- + clusters {
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + cluster0: cluster@0 {
- + reg = <0>;
- +// freqs = <500000000 600000000 700000000 800000000 900000000 1000000000 1100000000 1200000000>;
- + cores {
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + core0: core@0 {
- + reg = <0>;
- + };
- +
- + };
- + };
- +
- + cluster1: cluster@1 {
- + reg = <1>;
- +// freqs = <350000000 400000000 500000000 600000000 700000000 800000000 900000000 1000000000>;
- + cores {
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + core1: core@0 {
- + reg = <0>;
- + };
- +
- + };
- + };
- + };
- +
- + cpus {
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + cpu0: cpu@0 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a15";
- + reg = <0>;
- + cluster = <&cluster0>;
- + core = <&core0>;
- +// clock-frequency = <1000000000>;
- + cci-control-port = <&cci_control1>;
- + };
- +
- + cpu1: cpu@1 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a7";
- + reg = <0x100>;
- + cluster = <&cluster1>;
- + core = <&core1>;
- +// clock-frequency = <800000000>;
- + cci-control-port = <&cci_control2>;
- + };
- + };
- +
- + memory@80000000 {
- + device_type = "memory";
- + reg = <0 0x80000000 0 0x80000000>;
- + };
- +
- + cci@2c090000 {
- + compatible = "arm,cci-400", "arm,cci";
- + #address-cells = <1>;
- + #size-cells = <1>;
- + reg = <0 0x2c090000 0 0x1000>;
- + ranges = <0x0 0x0 0x2c090000 0x10000>;
- +
- + cci_control1: slave-if@4000 {
- + compatible = "arm,cci-400-ctrl-if";
- + interface-type = "ace";
- + reg = <0x4000 0x1000>;
- + };
- +
- + cci_control2: slave-if@5000 {
- + compatible = "arm,cci-400-ctrl-if";
- + interface-type = "ace";
- + reg = <0x5000 0x1000>;
- + };
- + };
- +
- + dcscb@60000000 {
- + compatible = "arm,rtsm,dcscb";
- + reg = <0 0x60000000 0 0x1000>;
- + };
- +
- + gic: interrupt-controller@2c001000 {
- + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
- + #interrupt-cells = <3>;
- + #address-cells = <0>;
- + interrupt-controller;
- + reg = <0 0x2c001000 0 0x1000>,
- + <0 0x2c002000 0 0x1000>,
- + <0 0x2c004000 0 0x2000>,
- + <0 0x2c006000 0 0x2000>;
- + interrupts = <1 9 0xf04>;
- + };
- +
- + timer {
- + compatible = "arm,armv7-timer";
- + interrupts = <1 13 0xf08>,
- + <1 14 0xf08>,
- + <1 11 0xf08>,
- + <1 10 0xf08>;
- + };
- +
- + dcc {
- + compatible = "arm,vexpress,config-bus";
- + arm,vexpress,config-bridge = <&v2m_sysreg>;
- +
- + osc@0 {
- + /* ACLK clock to the AXI master port on the test chip */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 0>;
- + freq-range = <30000000 50000000>;
- + #clock-cells = <0>;
- + clock-output-names = "extsaxiclk";
- + };
- +
- + oscclk1: osc@1 {
- + /* Reference clock for the CLCD */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 1>;
- + freq-range = <10000000 80000000>;
- + #clock-cells = <0>;
- + clock-output-names = "clcdclk";
- + };
- +
- + smbclk: oscclk2: osc@2 {
- + /* Reference clock for the test chip internal PLLs */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 2>;
- + freq-range = <33000000 100000000>;
- + #clock-cells = <0>;
- + clock-output-names = "tcrefclk";
- + };
- + };
- +
- + smb {
- + compatible = "simple-bus";
- +
- + #address-cells = <2>;
- + #size-cells = <1>;
- + ranges = <0 0 0 0x08000000 0x04000000>,
- + <1 0 0 0x14000000 0x04000000>,
- + <2 0 0 0x18000000 0x04000000>,
- + <3 0 0 0x1c000000 0x04000000>,
- + <4 0 0 0x0c000000 0x04000000>,
- + <5 0 0 0x10000000 0x04000000>;
- +
- + #interrupt-cells = <1>;
- + interrupt-map-mask = <0 0 63>;
- + interrupt-map = <0 0 0 &gic 0 0 4>,
- + <0 0 1 &gic 0 1 4>,
- + <0 0 2 &gic 0 2 4>,
- + <0 0 3 &gic 0 3 4>,
- + <0 0 4 &gic 0 4 4>,
- + <0 0 5 &gic 0 5 4>,
- + <0 0 6 &gic 0 6 4>,
- + <0 0 7 &gic 0 7 4>,
- + <0 0 8 &gic 0 8 4>,
- + <0 0 9 &gic 0 9 4>,
- + <0 0 10 &gic 0 10 4>,
- + <0 0 11 &gic 0 11 4>,
- + <0 0 12 &gic 0 12 4>,
- + <0 0 13 &gic 0 13 4>,
- + <0 0 14 &gic 0 14 4>,
- + <0 0 15 &gic 0 15 4>,
- + <0 0 16 &gic 0 16 4>,
- + <0 0 17 &gic 0 17 4>,
- + <0 0 18 &gic 0 18 4>,
- + <0 0 19 &gic 0 19 4>,
- + <0 0 20 &gic 0 20 4>,
- + <0 0 21 &gic 0 21 4>,
- + <0 0 22 &gic 0 22 4>,
- + <0 0 23 &gic 0 23 4>,
- + <0 0 24 &gic 0 24 4>,
- + <0 0 25 &gic 0 25 4>,
- + <0 0 26 &gic 0 26 4>,
- + <0 0 27 &gic 0 27 4>,
- + <0 0 28 &gic 0 28 4>,
- + <0 0 29 &gic 0 29 4>,
- + <0 0 30 &gic 0 30 4>,
- + <0 0 31 &gic 0 31 4>,
- + <0 0 32 &gic 0 32 4>,
- + <0 0 33 &gic 0 33 4>,
- + <0 0 34 &gic 0 34 4>,
- + <0 0 35 &gic 0 35 4>,
- + <0 0 36 &gic 0 36 4>,
- + <0 0 37 &gic 0 37 4>,
- + <0 0 38 &gic 0 38 4>,
- + <0 0 39 &gic 0 39 4>,
- + <0 0 40 &gic 0 40 4>,
- + <0 0 41 &gic 0 41 4>,
- + <0 0 42 &gic 0 42 4>;
- +
- + /include/ "rtsm_ve-motherboard.dtsi"
- + };
- +};
- +
- +/include/ "clcd-panels.dtsi"
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/rtsm_ve-v2p-ca15x4-ca7x4.dts linux-3.14.35/arch/arm/boot/dts/rtsm_ve-v2p-ca15x4-ca7x4.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/rtsm_ve-v2p-ca15x4-ca7x4.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/rtsm_ve-v2p-ca15x4-ca7x4.dts 2015-03-08 14:27:37.405684503 -0500
- @@ -0,0 +1,317 @@
- +/*
- + * ARM Ltd. Fast Models
- + *
- + * Versatile Express (VE) system model
- + * ARMCortexA15x4CT
- + * ARMCortexA7x4CT
- + * RTSM_VE_Cortex_A15x4_A7x4.lisa
- + */
- +
- +/dts-v1/;
- +
- +/memreserve/ 0xff000000 0x01000000;
- +
- +/ {
- + model = "RTSM_VE_CortexA15x4-A7x4";
- + arm,vexpress,site = <0xf>;
- + compatible = "arm,rtsm_ve,cortex_a15x4_a7x4", "arm,vexpress";
- + interrupt-parent = <&gic>;
- + #address-cells = <2>;
- + #size-cells = <2>;
- +
- + chosen { };
- +
- + aliases {
- + serial0 = &v2m_serial0;
- + serial1 = &v2m_serial1;
- + serial2 = &v2m_serial2;
- + serial3 = &v2m_serial3;
- + };
- +
- + clusters {
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + cluster0: cluster@0 {
- + reg = <0>;
- +// freqs = <500000000 600000000 700000000 800000000 900000000 1000000000 1100000000 1200000000>;
- + cores {
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + core0: core@0 {
- + reg = <0>;
- + };
- +
- + core1: core@1 {
- + reg = <1>;
- + };
- +
- + core2: core@2 {
- + reg = <2>;
- + };
- +
- + core3: core@3 {
- + reg = <3>;
- + };
- +
- + };
- + };
- +
- + cluster1: cluster@1 {
- + reg = <1>;
- +// freqs = <350000000 400000000 500000000 600000000 700000000 800000000 900000000 1000000000>;
- + cores {
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + core4: core@0 {
- + reg = <0>;
- + };
- +
- + core5: core@1 {
- + reg = <1>;
- + };
- +
- + core6: core@2 {
- + reg = <2>;
- + };
- +
- + core7: core@3 {
- + reg = <3>;
- + };
- +
- + };
- + };
- + };
- +
- + cpus {
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + cpu0: cpu@0 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a15";
- + reg = <0>;
- + cluster = <&cluster0>;
- + core = <&core0>;
- +// clock-frequency = <1000000000>;
- + cci-control-port = <&cci_control1>;
- + };
- +
- + cpu1: cpu@1 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a15";
- + reg = <1>;
- + cluster = <&cluster0>;
- + core = <&core1>;
- +// clock-frequency = <1000000000>;
- + cci-control-port = <&cci_control1>;
- + };
- +
- + cpu2: cpu@2 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a15";
- + reg = <2>;
- + cluster = <&cluster0>;
- + core = <&core2>;
- +// clock-frequency = <1000000000>;
- + cci-control-port = <&cci_control1>;
- + };
- +
- + cpu3: cpu@3 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a15";
- + reg = <3>;
- + cluster = <&cluster0>;
- + core = <&core3>;
- +// clock-frequency = <1000000000>;
- + cci-control-port = <&cci_control1>;
- + };
- +
- + cpu4: cpu@4 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a7";
- + reg = <0x100>;
- + cluster = <&cluster1>;
- + core = <&core4>;
- +// clock-frequency = <800000000>;
- + cci-control-port = <&cci_control2>;
- + };
- +
- + cpu5: cpu@5 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a7";
- + reg = <0x101>;
- + cluster = <&cluster1>;
- + core = <&core5>;
- +// clock-frequency = <800000000>;
- + cci-control-port = <&cci_control2>;
- + };
- +
- + cpu6: cpu@6 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a7";
- + reg = <0x102>;
- + cluster = <&cluster1>;
- + core = <&core6>;
- +// clock-frequency = <800000000>;
- + cci-control-port = <&cci_control2>;
- + };
- +
- + cpu7: cpu@7 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a7";
- + reg = <0x103>;
- + cluster = <&cluster1>;
- + core = <&core7>;
- +// clock-frequency = <800000000>;
- + cci-control-port = <&cci_control2>;
- + };
- + };
- +
- + memory@80000000 {
- + device_type = "memory";
- + reg = <0 0x80000000 0 0x80000000>;
- + };
- +
- + cci@2c090000 {
- + compatible = "arm,cci-400", "arm,cci";
- + #address-cells = <1>;
- + #size-cells = <1>;
- + reg = <0 0x2c090000 0 0x1000>;
- + ranges = <0x0 0x0 0x2c090000 0x10000>;
- +
- + cci_control1: slave-if@4000 {
- + compatible = "arm,cci-400-ctrl-if";
- + interface-type = "ace";
- + reg = <0x4000 0x1000>;
- + };
- +
- + cci_control2: slave-if@5000 {
- + compatible = "arm,cci-400-ctrl-if";
- + interface-type = "ace";
- + reg = <0x5000 0x1000>;
- + };
- + };
- +
- + dcscb@60000000 {
- + compatible = "arm,rtsm,dcscb";
- + reg = <0 0x60000000 0 0x1000>;
- + };
- +
- + gic: interrupt-controller@2c001000 {
- + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
- + #interrupt-cells = <3>;
- + #address-cells = <0>;
- + interrupt-controller;
- + reg = <0 0x2c001000 0 0x1000>,
- + <0 0x2c002000 0 0x1000>,
- + <0 0x2c004000 0 0x2000>,
- + <0 0x2c006000 0 0x2000>;
- + interrupts = <1 9 0xf04>;
- + };
- +
- + timer {
- + compatible = "arm,armv7-timer";
- + interrupts = <1 13 0xf08>,
- + <1 14 0xf08>,
- + <1 11 0xf08>,
- + <1 10 0xf08>;
- + };
- +
- + dcc {
- + compatible = "arm,vexpress,config-bus";
- + arm,vexpress,config-bridge = <&v2m_sysreg>;
- +
- + osc@0 {
- + /* ACLK clock to the AXI master port on the test chip */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 0>;
- + freq-range = <30000000 50000000>;
- + #clock-cells = <0>;
- + clock-output-names = "extsaxiclk";
- + };
- +
- + oscclk1: osc@1 {
- + /* Reference clock for the CLCD */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 1>;
- + freq-range = <10000000 80000000>;
- + #clock-cells = <0>;
- + clock-output-names = "clcdclk";
- + };
- +
- + smbclk: oscclk2: osc@2 {
- + /* Reference clock for the test chip internal PLLs */
- + compatible = "arm,vexpress-osc";
- + arm,vexpress-sysreg,func = <1 2>;
- + freq-range = <33000000 100000000>;
- + #clock-cells = <0>;
- + clock-output-names = "tcrefclk";
- + };
- + };
- +
- + smb {
- + compatible = "simple-bus";
- +
- + #address-cells = <2>;
- + #size-cells = <1>;
- + ranges = <0 0 0 0x08000000 0x04000000>,
- + <1 0 0 0x14000000 0x04000000>,
- + <2 0 0 0x18000000 0x04000000>,
- + <3 0 0 0x1c000000 0x04000000>,
- + <4 0 0 0x0c000000 0x04000000>,
- + <5 0 0 0x10000000 0x04000000>;
- +
- + #interrupt-cells = <1>;
- + interrupt-map-mask = <0 0 63>;
- + interrupt-map = <0 0 0 &gic 0 0 4>,
- + <0 0 1 &gic 0 1 4>,
- + <0 0 2 &gic 0 2 4>,
- + <0 0 3 &gic 0 3 4>,
- + <0 0 4 &gic 0 4 4>,
- + <0 0 5 &gic 0 5 4>,
- + <0 0 6 &gic 0 6 4>,
- + <0 0 7 &gic 0 7 4>,
- + <0 0 8 &gic 0 8 4>,
- + <0 0 9 &gic 0 9 4>,
- + <0 0 10 &gic 0 10 4>,
- + <0 0 11 &gic 0 11 4>,
- + <0 0 12 &gic 0 12 4>,
- + <0 0 13 &gic 0 13 4>,
- + <0 0 14 &gic 0 14 4>,
- + <0 0 15 &gic 0 15 4>,
- + <0 0 16 &gic 0 16 4>,
- + <0 0 17 &gic 0 17 4>,
- + <0 0 18 &gic 0 18 4>,
- + <0 0 19 &gic 0 19 4>,
- + <0 0 20 &gic 0 20 4>,
- + <0 0 21 &gic 0 21 4>,
- + <0 0 22 &gic 0 22 4>,
- + <0 0 23 &gic 0 23 4>,
- + <0 0 24 &gic 0 24 4>,
- + <0 0 25 &gic 0 25 4>,
- + <0 0 26 &gic 0 26 4>,
- + <0 0 27 &gic 0 27 4>,
- + <0 0 28 &gic 0 28 4>,
- + <0 0 29 &gic 0 29 4>,
- + <0 0 30 &gic 0 30 4>,
- + <0 0 31 &gic 0 31 4>,
- + <0 0 32 &gic 0 32 4>,
- + <0 0 33 &gic 0 33 4>,
- + <0 0 34 &gic 0 34 4>,
- + <0 0 35 &gic 0 35 4>,
- + <0 0 36 &gic 0 36 4>,
- + <0 0 37 &gic 0 37 4>,
- + <0 0 38 &gic 0 38 4>,
- + <0 0 39 &gic 0 39 4>,
- + <0 0 40 &gic 0 40 4>,
- + <0 0 41 &gic 0 41 4>,
- + <0 0 42 &gic 0 42 4>;
- +
- + /include/ "rtsm_ve-motherboard.dtsi"
- + };
- +};
- +
- +/include/ "clcd-panels.dtsi"
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/vexpress-v2m.dtsi linux-3.14.35/arch/arm/boot/dts/vexpress-v2m.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/vexpress-v2m.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/vexpress-v2m.dtsi 2015-03-08 14:27:37.405684503 -0500
- @@ -227,6 +227,7 @@
- };
-
- clcd@1f000 {
- + status = "disabled";
- compatible = "arm,pl111", "arm,primecell";
- reg = <0x1f000 0x1000>;
- interrupts = <14>;
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi linux-3.14.35/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi 2015-03-08 14:27:37.405684503 -0500
- @@ -228,6 +228,7 @@
- };
-
- clcd@1f0000 {
- + status = "disabled";
- compatible = "arm,pl111", "arm,primecell";
- reg = <0x1f0000 0x1000>;
- interrupts = <14>;
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts linux-3.14.35/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts 2015-03-08 14:27:37.405684503 -0500
- @@ -9,6 +9,8 @@
-
- /dts-v1/;
-
- +/memreserve/ 0xff000000 0x01000000;
- +
- / {
- model = "V2P-CA15_CA7";
- arm,hbi = <0x249>;
- @@ -29,29 +31,60 @@
- i2c1 = &v2m_i2c_pcie;
- };
-
- - cpus {
- + clusters {
- #address-cells = <1>;
- #size-cells = <0>;
-
- - cpu0: cpu@0 {
- - device_type = "cpu";
- - compatible = "arm,cortex-a15";
- + cluster0: cluster@0 {
- reg = <0>;
- - cci-control-port = <&cci_control1>;
- + cores {
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + core0: core@0 {
- + reg = <0>;
- + };
- +
- + core1: core@1 {
- + reg = <1>;
- + };
- +
- + };
- };
-
- - cpu1: cpu@1 {
- - device_type = "cpu";
- - compatible = "arm,cortex-a15";
- + cluster1: cluster@1 {
- reg = <1>;
- - cci-control-port = <&cci_control1>;
- + cores {
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + core2: core@0 {
- + reg = <0>;
- + };
- +
- + core3: core@1 {
- + reg = <1>;
- + };
- +
- + core4: core@2 {
- + reg = <2>;
- + };
- + };
- };
- + };
- +
- + cpus {
- + #address-cells = <1>;
- + #size-cells = <0>;
-
- cpu2: cpu@2 {
- device_type = "cpu";
- compatible = "arm,cortex-a7";
- reg = <0x100>;
- cci-control-port = <&cci_control2>;
- + cluster = <&cluster1>;
- + core = <&core2>;
- + clock-frequency = <800000000>;
- };
-
- cpu3: cpu@3 {
- @@ -59,6 +92,9 @@
- compatible = "arm,cortex-a7";
- reg = <0x101>;
- cci-control-port = <&cci_control2>;
- + cluster = <&cluster1>;
- + core = <&core3>;
- + clock-frequency = <800000000>;
- };
-
- cpu4: cpu@4 {
- @@ -66,12 +102,35 @@
- compatible = "arm,cortex-a7";
- reg = <0x102>;
- cci-control-port = <&cci_control2>;
- + cluster = <&cluster1>;
- + core = <&core4>;
- + clock-frequency = <800000000>;
- + };
- +
- + cpu0: cpu@0 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a15";
- + reg = <0>;
- + cci-control-port = <&cci_control1>;
- + cluster = <&cluster0>;
- + core = <&core0>;
- + clock-frequency = <1000000000>;
- + };
- +
- + cpu1: cpu@1 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a15";
- + reg = <1>;
- + cci-control-port = <&cci_control1>;
- + cluster = <&cluster0>;
- + core = <&core1>;
- + clock-frequency = <1000000000>;
- };
- };
-
- memory@80000000 {
- device_type = "memory";
- - reg = <0 0x80000000 0 0x40000000>;
- + reg = <0 0x80000000 0 0x80000000>;
- };
-
- wdt@2a490000 {
- @@ -86,6 +145,8 @@
- compatible = "arm,hdlcd";
- reg = <0 0x2b000000 0 0x1000>;
- interrupts = <0 85 4>;
- + mode = "1024x768-16@60";
- + framebuffer = <0 0xff000000 0 0x01000000>;
- clocks = <&oscclk5>;
- clock-names = "pxlclk";
- };
- @@ -127,6 +188,16 @@
- interface-type = "ace";
- reg = <0x5000 0x1000>;
- };
- +
- + pmu@9000 {
- + compatible = "arm,cci-400-pmu";
- + reg = <0x9000 0x5000>;
- + interrupts = <0 101 4>,
- + <0 102 4>,
- + <0 103 4>,
- + <0 104 4>,
- + <0 105 4>;
- + };
- };
-
- memory-controller@7ffd0000 {
- @@ -164,12 +235,21 @@
- <1 10 0xf08>;
- };
-
- - pmu {
- + pmu_a15 {
- compatible = "arm,cortex-a15-pmu";
- + cluster = <&cluster0>;
- interrupts = <0 68 4>,
- <0 69 4>;
- };
-
- + pmu_a7 {
- + compatible = "arm,cortex-a7-pmu";
- + cluster = <&cluster1>;
- + interrupts = <0 128 4>,
- + <0 129 4>,
- + <0 130 4>;
- + };
- +
- oscclk6a: oscclk6a {
- /* Reference 24MHz clock */
- compatible = "fixed-clock";
- @@ -178,6 +258,19 @@
- clock-output-names = "oscclk6a";
- };
-
- +/* PSCI requires support from firmware and is not present in the normal TC2
- + * distribution, so this node is commented out by default...
- +
- + psci {
- + compatible = "arm,psci";
- + method = "smc";
- + cpu_suspend = <0x80100001>;
- + cpu_off = <0x80100002>;
- + cpu_on = <0x80100003>;
- + migrate = <0x80100004>;
- + };
- +*/
- +
- dcc {
- compatible = "arm,vexpress,config-bus";
- arm,vexpress,config-bridge = <&v2m_sysreg>;
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts linux-3.14.35/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts 2015-03-08 14:27:37.405684503 -0500
- @@ -9,6 +9,8 @@
-
- /dts-v1/;
-
- +/memreserve/ 0xbf000000 0x01000000;
- +
- / {
- model = "V2P-CA15";
- arm,hbi = <0x237>;
- @@ -57,6 +59,8 @@
- interrupts = <0 85 4>;
- clocks = <&oscclk5>;
- clock-names = "pxlclk";
- + mode = "1024x768-16@60";
- + framebuffer = <0 0xbf000000 0 0x01000000>;
- };
-
- memory-controller@2b0a0000 {
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/vexpress-v2p-ca5s.dts linux-3.14.35/arch/arm/boot/dts/vexpress-v2p-ca5s.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/vexpress-v2p-ca5s.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/vexpress-v2p-ca5s.dts 2015-03-08 14:27:37.405684503 -0500
- @@ -9,6 +9,8 @@
-
- /dts-v1/;
-
- +/memreserve/ 0xbf000000 0x01000000;
- +
- / {
- model = "V2P-CA5s";
- arm,hbi = <0x225>;
- @@ -59,6 +61,8 @@
- interrupts = <0 85 4>;
- clocks = <&oscclk3>;
- clock-names = "pxlclk";
- + mode = "640x480-16@60";
- + framebuffer = <0xbf000000 0x01000000>;
- };
-
- memory-controller@2a150000 {
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/vexpress-v2p-ca9.dts linux-3.14.35/arch/arm/boot/dts/vexpress-v2p-ca9.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/vexpress-v2p-ca9.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/vexpress-v2p-ca9.dts 2015-03-08 14:27:37.405684503 -0500
- @@ -9,6 +9,8 @@
-
- /dts-v1/;
-
- +/include/ "clcd-panels.dtsi"
- +
- / {
- model = "V2P-CA9";
- arm,hbi = <0x191>;
- @@ -73,6 +75,8 @@
- interrupts = <0 44 4>;
- clocks = <&oscclk1>, <&oscclk2>;
- clock-names = "clcdclk", "apb_pclk";
- + mode = "XVGA";
- + use_dma = <1>;
- };
-
- memory-controller@100e0000 {
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/vf610.dtsi linux-3.14.35/arch/arm/boot/dts/vf610.dtsi
- --- linux-3.14.35.orig/arch/arm/boot/dts/vf610.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/vf610.dtsi 2015-03-08 14:27:37.405684503 -0500
- @@ -44,11 +44,13 @@
-
- sxosc {
- compatible = "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <32768>;
- };
-
- fxosc {
- compatible = "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <24000000>;
- };
- };
- diff -Nur linux-3.14.35.orig/arch/arm/boot/dts/vf610-twr.dts linux-3.14.35/arch/arm/boot/dts/vf610-twr.dts
- --- linux-3.14.35.orig/arch/arm/boot/dts/vf610-twr.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/boot/dts/vf610-twr.dts 2015-03-08 14:27:37.405684503 -0500
- @@ -25,11 +25,13 @@
- clocks {
- audio_ext {
- compatible = "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <24576000>;
- };
-
- enet_ext {
- compatible = "fixed-clock";
- + #clock-cells = <0>;
- clock-frequency = <50000000>;
- };
- };
- diff -Nur linux-3.14.35.orig/arch/arm/common/Makefile linux-3.14.35/arch/arm/common/Makefile
- --- linux-3.14.35.orig/arch/arm/common/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/common/Makefile 2015-03-08 14:27:37.405684503 -0500
- @@ -13,6 +13,7 @@
- obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o
- obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
- obj-$(CONFIG_MCPM) += mcpm_head.o mcpm_entry.o mcpm_platsmp.o vlock.o
- +CFLAGS_REMOVE_mcpm_entry.o = -pg
- AFLAGS_mcpm_head.o := -march=armv7-a
- AFLAGS_vlock.o := -march=armv7-a
- obj-$(CONFIG_TI_PRIV_EDMA) += edma.o
- diff -Nur linux-3.14.35.orig/arch/arm/configs/imx_v6_v7_defconfig linux-3.14.35/arch/arm/configs/imx_v6_v7_defconfig
- --- linux-3.14.35.orig/arch/arm/configs/imx_v6_v7_defconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/configs/imx_v6_v7_defconfig 2015-03-08 14:27:37.405684503 -0500
- @@ -45,6 +45,9 @@
- CONFIG_AEABI=y
- CONFIG_HIGHMEM=y
- CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
- +CONFIG_CPU_FREQ=y
- +CONFIG_ARM_IMX6Q_CPUFREQ=y
- +CONFIG_CPU_IDLE=y
- CONFIG_VFP=y
- CONFIG_NEON=y
- CONFIG_BINFMT_MISC=m
- @@ -70,6 +73,8 @@
- CONFIG_DEVTMPFS=y
- CONFIG_DEVTMPFS_MOUNT=y
- # CONFIG_STANDALONE is not set
- +CONFIG_CMA=y
- +CONFIG_CMA_SIZE_MBYTES=256
- CONFIG_IMX_WEIM=y
- CONFIG_CONNECTOR=y
- CONFIG_MTD=y
- @@ -154,7 +159,12 @@
- CONFIG_SPI_IMX=y
- CONFIG_GPIO_SYSFS=y
- CONFIG_GPIO_MC9S08DZ60=y
- +CONFIG_GPIO_PCA953X=y
- # CONFIG_HWMON is not set
- +CONFIG_THERMAL=y
- +CONFIG_CPU_THERMAL=y
- +CONFIG_IMX_THERMAL=y
- +CONFIG_DEVICE_THERMAL=y
- CONFIG_WATCHDOG=y
- CONFIG_IMX2_WDT=y
- CONFIG_MFD_DA9052_I2C=y
- @@ -170,32 +180,44 @@
- CONFIG_REGULATOR_PFUZE100=y
- CONFIG_MEDIA_SUPPORT=y
- CONFIG_MEDIA_CAMERA_SUPPORT=y
- +CONFIG_MEDIA_USB_SUPPORT=y
- +CONFIG_USB_VIDEO_CLASS=m
- CONFIG_MEDIA_RC_SUPPORT=y
- CONFIG_RC_DEVICES=y
- CONFIG_IR_GPIO_CIR=y
- CONFIG_V4L_PLATFORM_DRIVERS=y
- +CONFIG_VIDEO_MXC_OUTPUT=y
- +CONFIG_VIDEO_MXC_IPU_OUTPUT=y
- CONFIG_SOC_CAMERA=y
- CONFIG_VIDEO_MX3=y
- CONFIG_V4L_MEM2MEM_DRIVERS=y
- CONFIG_VIDEO_CODA=y
- CONFIG_SOC_CAMERA_OV2640=y
- CONFIG_DRM=y
- +CONFIG_DRM_VIVANTE=y
- CONFIG_BACKLIGHT_LCD_SUPPORT=y
- CONFIG_LCD_CLASS_DEVICE=y
- CONFIG_LCD_L4F00242T03=y
- CONFIG_LCD_PLATFORM=y
- CONFIG_BACKLIGHT_CLASS_DEVICE=y
- CONFIG_BACKLIGHT_PWM=y
- +CONFIG_FB_MXC_SYNC_PANEL=y
- +CONFIG_FB_MXC_LDB=y
- +CONFIG_FB_MXC_HDMI=y
- +CONFIG_FB_MXC_MIPI_DSI=y
- +CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL=y
- CONFIG_FRAMEBUFFER_CONSOLE=y
- CONFIG_LOGO=y
- CONFIG_SOUND=y
- CONFIG_SND=y
- +CONFIG_SND_USB_AUDIO=m
- CONFIG_SND_SOC=y
- CONFIG_SND_IMX_SOC=y
- CONFIG_SND_SOC_PHYCORE_AC97=y
- CONFIG_SND_SOC_EUKREA_TLV320=y
- CONFIG_SND_SOC_IMX_WM8962=y
- CONFIG_SND_SOC_IMX_SGTL5000=y
- +CONFIG_SND_SOC_IMX_CS42888=y
- CONFIG_SND_SOC_IMX_SPDIF=y
- CONFIG_SND_SOC_IMX_MC13783=y
- CONFIG_USB=y
- @@ -208,12 +230,18 @@
- CONFIG_NOP_USB_XCEIV=y
- CONFIG_USB_MXS_PHY=y
- CONFIG_USB_GADGET=y
- +CONFIG_USB_ZERO=m
- CONFIG_USB_ETH=m
- CONFIG_USB_MASS_STORAGE=m
- +CONFIG_USB_G_SERIAL=m
- CONFIG_MMC=y
- +CONFIG_MMC_UNSAFE_RESUME=y
- CONFIG_MMC_SDHCI=y
- CONFIG_MMC_SDHCI_PLTFM=y
- CONFIG_MMC_SDHCI_ESDHC_IMX=y
- +CONFIG_MXC_IPU=y
- +CONFIG_MXC_GPU_VIV=y
- +CONFIG_MXC_ASRC=y
- CONFIG_NEW_LEDS=y
- CONFIG_LEDS_CLASS=y
- CONFIG_LEDS_GPIO=y
- @@ -229,16 +257,10 @@
- CONFIG_RTC_DRV_MXC=y
- CONFIG_RTC_DRV_SNVS=y
- CONFIG_DMADEVICES=y
- +CONFIG_MXC_PXP_V2=y
- CONFIG_IMX_SDMA=y
- CONFIG_MXS_DMA=y
- CONFIG_STAGING=y
- -CONFIG_DRM_IMX=y
- -CONFIG_DRM_IMX_FB_HELPER=y
- -CONFIG_DRM_IMX_PARALLEL_DISPLAY=y
- -CONFIG_DRM_IMX_TVE=y
- -CONFIG_DRM_IMX_LDB=y
- -CONFIG_DRM_IMX_IPUV3_CORE=y
- -CONFIG_DRM_IMX_IPUV3=y
- CONFIG_COMMON_CLK_DEBUG=y
- # CONFIG_IOMMU_SUPPORT is not set
- CONFIG_PWM=y
- diff -Nur linux-3.14.35.orig/arch/arm/configs/imx_v7_cbi_hb_base_defconfig linux-3.14.35/arch/arm/configs/imx_v7_cbi_hb_base_defconfig
- --- linux-3.14.35.orig/arch/arm/configs/imx_v7_cbi_hb_base_defconfig 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/configs/imx_v7_cbi_hb_base_defconfig 2015-03-08 14:27:37.405684503 -0500
- @@ -0,0 +1,367 @@
- +# CONFIG_LOCALVERSION_AUTO is not set
- +CONFIG_KERNEL_LZO=y
- +CONFIG_SYSVIPC=y
- +CONFIG_FHANDLE=y
- +CONFIG_NO_HZ=y
- +CONFIG_HIGH_RES_TIMERS=y
- +CONFIG_LOG_BUF_SHIFT=18
- +CONFIG_CGROUPS=y
- +CONFIG_RELAY=y
- +CONFIG_BLK_DEV_INITRD=y
- +CONFIG_EXPERT=y
- +CONFIG_PERF_EVENTS=y
- +CONFIG_CLEANCACHE=y
- +CONFIG_FRONTSWAP=y
- +CONFIG_ZSWAP=y
- +CONFIG_ZSMALLOC=y
- +# CONFIG_SLUB_DEBUG is not set
- +# CONFIG_COMPAT_BRK is not set
- +CONFIG_MODULES=y
- +CONFIG_MODULE_UNLOAD=y
- +CONFIG_MODVERSIONS=y
- +CONFIG_MODULE_SRCVERSION_ALL=y
- +# CONFIG_BLK_DEV_BSG is not set
- +CONFIG_GPIO_PCA953X=y
- +CONFIG_ARCH_MXC=y
- +CONFIG_MXC_DEBUG_BOARD=y
- +CONFIG_SOC_IMX6Q=y
- +CONFIG_SOC_IMX6SL=y
- +# CONFIG_SWP_EMULATE is not set
- +CONFIG_PCI=y
- +CONFIG_PCIE_DW=y
- +CONFIG_PCI_IMX6=y
- +CONFIG_SMP=y
- +CONFIG_VMSPLIT_2G=y
- +CONFIG_PREEMPT_VOLUNTARY=y
- +CONFIG_AEABI=y
- +# CONFIG_OABI_COMPAT is not set
- +CONFIG_HIGHMEM=y
- +CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
- +CONFIG_CPU_FREQ=y
- +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y
- +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
- +CONFIG_CPU_FREQ_GOV_POWERSAVE=y
- +CONFIG_CPU_FREQ_GOV_USERSPACE=y
- +CONFIG_CPU_FREQ_GOV_ONDEMAND=y
- +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
- +CONFIG_ARM_IMX6_CPUFREQ=y
- +CONFIG_CPU_IDLE=y
- +CONFIG_VFP=y
- +CONFIG_VFPv3=y
- +CONFIG_NEON=y
- +CONFIG_KERNEL_MODE_NEON=y
- +CONFIG_BINFMT_MISC=m
- +CONFIG_PM_RUNTIME=y
- +CONFIG_PM_DEBUG=y
- +CONFIG_PM_TEST_SUSPEND=y
- +CONFIG_IOSCHED_BFQ=y
- +CONFIG_CGROUP_BFQIO=y
- +CONFIG_DEFAULT_BFQ=y
- +CONFIG_DEFAULT_IOSCHED="bfq"
- +CONFIG_NET=y
- +CONFIG_PACKET=y
- +CONFIG_UNIX=y
- +CONFIG_INET=y
- +CONFIG_IP_PNP=y
- +CONFIG_IP_PNP_DHCP=y
- +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
- +# CONFIG_INET_XFRM_MODE_TUNNEL is not set
- +# CONFIG_INET_XFRM_MODE_BEET is not set
- +# CONFIG_INET_LRO is not set
- +CONFIG_IPV6=y
- +CONFIG_NETFILTER=y
- +CONFIG_VLAN_8021Q=y
- +CONFIG_WIRELESS=y
- +CONFIG_WIRELESS_EXT=y
- +CONFIG_WEXT_CORE=y
- +CONFIG_WEXT_PROC=y
- +CONFIG_WEXT_SPY=y
- +CONFIG_WEXT_PRIV=y
- +CONFIG_CFG80211=y
- +CONFIG_ETHERNET=y
- +# CONFIG_NET_VENDOR_BROADCOM is not set
- +# CONFIG_NET_VENDOR_CIRRUS is not set
- +# CONFIG_NET_VENDOR_FARADAY
- +# CONFIG_NET_VENDOR_INTEL
- +# CONFIG_NET_VENDOR_I825XX
- +# CONFIG_NET_VENDOR_MARVELL
- +# CONFIG_NET_VENDOR_MICROCHIP
- +# CONFIG_NET_VENDOR_MICROCHIP=y
- +# CONFIG_ENC28J60 is not set
- +# CONFIG_NET_VENDOR_NATSEMI=y
- +# CONFIG_NET_VENDOR_8390=y
- +# CONFIG_AX88796 is not set
- +# CONFIG_ETHOC is not set
- +# CONFIG_SH_ETH is not set
- +# CONFIG_NET_VENDOR_SEEQ=y
- +# CONFIG_NET_VENDOR_SMSC=y
- +# CONFIG_SMC91X is not set
- +# CONFIG_SMC911X is not set
- +# CONFIG_SMSC911X is not set
- +# CONFIG_NET_VENDOR_STMICRO=y
- +# CONFIG_STMMAC_ETH is not set
- +# CONFIG_NET_VENDOR_VIA=y
- +# CONFIG_VIA_VELOCITY is not set
- +# CONFIG_NET_VENDOR_WIZNET=y
- +CONFIG_NET_VENDOR_FREESCALE=y
- +CONFIG_FEC=y
- +CONFIG_PHYLIB=y
- +CONFIG_AT803X_PHY=y
- +CONFIG_WLAN=y
- +CONFIG_BRCMUTIL=m
- +CONFIG_BRCMFMAC=m
- +CONFIG_BRCMFMAC_SDIO=y
- +CONFIG_DEVTMPFS=y
- +CONFIG_DEVTMPFS_MOUNT=y
- +# CONFIG_STANDALONE is not set
- +CONFIG_DMA_CMA=y
- +CONFIG_CMA=y
- +CONFIG_CMA_SIZE_MBYTES=256
- +CONFIG_CONNECTOR=y
- +# CONFIG_MTD is not set
- +CONFIG_BLK_DEV_LOOP=y
- +CONFIG_BLK_DEV_RAM=y
- +CONFIG_BLK_DEV_RAM_SIZE=65536
- +# CONFIG_SCSI_PROC_FS is not set
- +CONFIG_BLK_DEV_SD=y
- +CONFIG_SCSI_MULTI_LUN=y
- +CONFIG_SCSI_CONSTANTS=y
- +CONFIG_SCSI_LOGGING=y
- +CONFIG_SCSI_SCAN_ASYNC=y
- +# CONFIG_SCSI_LOWLEVEL is not set
- +CONFIG_ATA=y
- +CONFIG_SATA_AHCI_PLATFORM=y
- +CONFIG_AHCI_IMX=y
- +CONFIG_NETDEVICES=y
- +CONFIG_INPUT_EVDEV=y
- +# CONFIG_INPUT_EVBUG is not set
- +CONFIG_KEYBOARD_GPIO=y
- +CONFIG_KEYBOARD_IMX=y
- +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
- +# CONFIG_KEYBOARD_ATKBD is not set
- +# CONFIG_MOUSE_PS2 is not set
- +CONFIG_INPUT_MISC=y
- +CONFIG_SERIO_SERPORT=m
- +CONFIG_VT_HW_CONSOLE_BINDING=y
- +# CONFIG_LEGACY_PTYS is not set
- +# CONFIG_DEVKMEM is not set
- +CONFIG_SERIAL_IMX=y
- +CONFIG_SERIAL_IMX_CONSOLE=y
- +CONFIG_SERIAL_FSL_LPUART=y
- +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
- +CONFIG_FSL_OTP=y
- +CONFIG_GPIO_MXC=y
- +# CONFIG_I2C_COMPAT is not set
- +CONFIG_I2C_CHARDEV=y
- +# CONFIG_I2C_HELPER_AUTO is not set
- +CONFIG_I2C_ALGOPCF=m
- +CONFIG_I2C_ALGOPCA=m
- +CONFIG_I2C_IMX=y
- +CONFIG_SPI=y
- +CONFIG_SPI_IMX=y
- +CONFIG_GPIO_SYSFS=y
- +CONFIG_POWER_SUPPLY=y
- +CONFIG_THERMAL=y
- +CONFIG_CPU_THERMAL=y
- +CONFIG_IMX_THERMAL=y
- +CONFIG_DEVICE_THERMAL=y
- +CONFIG_WATCHDOG=y
- +CONFIG_IMX2_WDT=y
- +CONFIG_MFD_DA9052_I2C=y
- +CONFIG_MFD_MC13XXX_SPI=y
- +CONFIG_MFD_MC13XXX_I2C=y
- +CONFIG_MFD_SI476X_CORE=y
- +CONFIG_REGULATOR=y
- +CONFIG_REGULATOR_FIXED_VOLTAGE=y
- +CONFIG_REGULATOR_ANATOP=y
- +CONFIG_REGULATOR_PFUZE100=y
- +CONFIG_MEDIA_SUPPORT=y
- +CONFIG_MEDIA_CAMERA_SUPPORT=y
- +# CONFIG_MEDIA_RADIO_SUPPORT is not set
- +CONFIG_VIDEO_V4L2_INT_DEVICE=y
- +# CONFIG_MEDIA_USB_SUPPORT isnot set
- +# CONFIG_USB_VIDEO_CLASS is not set
- +# CONFIG_RADIO_ADAPTERS is not set
- +CONFIG_V4L_PLATFORM_DRIVERS=y
- +CONFIG_VIDEO_MXC_OUTPUT=y
- +CONFIG_VIDEO_MXC_CAPTURE=m
- +CONFIG_VIDEO_MXC_CSI_CAMERA=m
- +CONFIG_MXC_CAMERA_OV5640=m
- +CONFIG_MXC_CAMERA_OV5642=m
- +CONFIG_MXC_CAMERA_OV5640_MIPI=m
- +CONFIG_MXC_TVIN_ADV7180=m
- +CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m
- +CONFIG_VIDEO_MXC_IPU_OUTPUT=y
- +CONFIG_VIDEO_MXC_PXP_V4L2=y
- +CONFIG_SOC_CAMERA=y
- +CONFIG_SOC_CAMERA_OV2640=y
- +CONFIG_DRM=y
- +CONFIG_DRM_VIVANTE=y
- +CONFIG_FB=y
- +# CONFIG_FB_MX3 is not set
- +CONFIG_FB_MXC_SYNC_PANEL=y
- +CONFIG_FB_MXC_LDB=y
- +CONFIG_FB_MXC_HDMI=y
- +CONFIG_FRAMEBUFFER_CONSOLE=y
- +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
- +CONFIG_FONTS=y
- +CONFIG_FONT_8x8=y
- +CONFIG_FONT_8x16=y
- +CONFIG_LOGO=y
- +CONFIG_SOUND=y
- +CONFIG_SND=y
- +CONFIG_SND_USB_AUDIO=m
- +CONFIG_SND_SOC=y
- +CONFIG_SND_IMX_SOC=y
- +CONFIG_SND_SOC_IMX_SGTL5000=y
- +CONFIG_SND_SOC_IMX_SPDIF=y
- +CONFIG_SND_SOC_IMX_HDMI=y
- +CONFIG_USB=y
- +CONFIG_USB_EHCI_HCD=y
- +CONFIG_USB_STORAGE=y
- +CONFIG_USB_CHIPIDEA=y
- +CONFIG_USB_CHIPIDEA_UDC=y
- +CONFIG_USB_CHIPIDEA_HOST=y
- +CONFIG_USB_PHY=y
- +CONFIG_NOP_USB_XCEIV=y
- +CONFIG_USB_MXS_PHY=y
- +CONFIG_USB_GADGET=y
- +CONFIG_USB_ZERO=m
- +CONFIG_USB_ETH=m
- +CONFIG_USB_MASS_STORAGE=m
- +CONFIG_USB_G_SERIAL=m
- +CONFIG_MMC=y
- +CONFIG_MMC_UNSAFE_RESUME=y
- +CONFIG_MMC_SDHCI=y
- +CONFIG_MMC_SDHCI_PLTFM=y
- +CONFIG_MMC_SDHCI_ESDHC_IMX=y
- +CONFIG_MXC_IPU=y
- +CONFIG_MXC_GPU_VIV=y
- +CONFIG_MXC_ASRC=y
- +CONFIG_MXC_HDMI_CEC=y
- +CONFIG_MXC_MIPI_CSI2=y
- +CONFIG_MXC_MLB150=m
- +CONFIG_NEW_LEDS=y
- +CONFIG_LEDS_CLASS=y
- +CONFIG_LEDS_GPIO=y
- +CONFIG_LEDS_TRIGGERS=y
- +CONFIG_LEDS_TRIGGER_GPIO=y
- +CONFIG_RTC_CLASS=y
- +CONFIG_RTC_DRV_MXC=y
- +CONFIG_RTC_DRV_SNVS=y
- +CONFIG_RTC_DRV_PCF8523=y
- +CONFIG_DMADEVICES=y
- +CONFIG_MXC_PXP_V2=y
- +CONFIG_IMX_SDMA=y
- +CONFIG_MXS_DMA=y
- +CONFIG_SRAM=y
- +CONFIG_STAGING=y
- +CONFIG_COMMON_CLK_DEBUG=y
- +# CONFIG_IOMMU_SUPPORT is not set
- +CONFIG_PWM=y
- +CONFIG_PWM_SYSFS=y
- +CONFIG_PWM_IMX=y
- +CONFIG_IRQCHIP=y
- +CONFIG_ARM_GIC=y
- +# CONFIG_IPACK_BUS is not set
- +CONFIG_ARCH_HAS_RESET_CONTROLLER=y
- +CONFIG_RESET_CONTROLLER=y
- +CONFIG_RESET_GPIO=y
- +CONFIG_EXT4_FS=y
- +CONFIG_EXT4_USE_FOR_EXT23=y
- +CONFIG_EXT4_FS_XATTR=y
- +CONFIG_EXT4_FS_POSIX_ACL=y
- +CONFIG_EXT4_FS_SECURITY=y
- +CONFIG_QUOTA=y
- +CONFIG_QUOTA_NETLINK_INTERFACE=y
- +# CONFIG_PRINT_QUOTA_WARNING is not set
- +CONFIG_AUTOFS4_FS=y
- +CONFIG_FUSE_FS=y
- +CONFIG_ISO9660_FS=m
- +CONFIG_JOLIET=y
- +CONFIG_ZISOFS=y
- +CONFIG_UDF_FS=m
- +CONFIG_MSDOS_FS=m
- +CONFIG_VFAT_FS=y
- +CONFIG_TMPFS=y
- +CONFIG_JFFS2_FS=y
- +CONFIG_UBIFS_FS=y
- +CONFIG_NFS_FS=y
- +CONFIG_NFS_V3_ACL=y
- +CONFIG_NFS_V4=y
- +CONFIG_ROOT_NFS=y
- +CONFIG_NLS_DEFAULT="cp437"
- +CONFIG_NLS_CODEPAGE_437=y
- +CONFIG_NLS_ASCII=y
- +CONFIG_NLS_ISO8859_1=y
- +CONFIG_NLS_ISO8859_15=m
- +CONFIG_NLS_UTF8=y
- +CONFIG_MAGIC_SYSRQ=y
- +# CONFIG_SCHED_DEBUG is not set
- +# CONFIG_DEBUG_BUGVERBOSE is not set
- +# CONFIG_FTRACE is not set
- +CONFIG_SECURITYFS=y
- +CONFIG_CRYPTO_USER=y
- +CONFIG_CRYPTO_TEST=m
- +CONFIG_CRYPTO_CCM=y
- +CONFIG_CRYPTO_GCM=y
- +CONFIG_CRYPTO_CBC=y
- +CONFIG_CRYPTO_CTS=y
- +CONFIG_CRYPTO_ECB=y
- +CONFIG_CRYPTO_LRW=y
- +CONFIG_CRYPTO_XTS=y
- +CONFIG_CRYPTO_MD4=y
- +CONFIG_CRYPTO_MD5=y
- +CONFIG_CRYPTO_MICHAEL_MIC=y
- +CONFIG_CRYPTO_RMD128=y
- +CONFIG_CRYPTO_RMD160=y
- +CONFIG_CRYPTO_RMD256=y
- +CONFIG_CRYPTO_RMD320=y
- +CONFIG_CRYPTO_SHA1=y
- +CONFIG_CRYPTO_SHA256=y
- +CONFIG_CRYPTO_SHA512=y
- +CONFIG_CRYPTO_TGR192=y
- +CONFIG_CRYPTO_WP512=y
- +CONFIG_CRYPTO_BLOWFISH=y
- +CONFIG_CRYPTO_CAMELLIA=y
- +CONFIG_CRYPTO_DES=y
- +CONFIG_CRYPTO_TWOFISH=y
- +# CONFIG_CRYPTO_ANSI_CPRNG is not set
- +CONFIG_CRYPTO_DEV_FSL_CAAM=y
- +CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y
- +CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=y
- +CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=y
- +CONFIG_CRYPTO_AES_ARM_BS=y
- +CONFIG_CRC_CCITT=m
- +CONFIG_CRC_T10DIF=y
- +CONFIG_CRC7=m
- +CONFIG_LIBCRC32C=m
- +# CONFIG_MXC_MMA8451 is not set
- +CONFIG_RC_CORE=m
- +CONFIG_RC_DECODERS=y
- +CONFIG_LIRC=m
- +CONFIG_RC_LOOPBACK=m
- +CONFIG_RC_MAP=m
- +CONFIG_RC_DEVICES=y
- +CONFIG_RC_ATI_REMOTE=m
- +CONFIG_IR_NEC_DECODER=m
- +CONFIG_IR_RC5_DECODER=m
- +CONFIG_IR_RC6_DECODER=m
- +CONFIG_IR_JVC_DECODER=m
- +CONFIG_IR_SONY_DECODER=m
- +CONFIG_IR_RC5_SZ_DECODER=m
- +CONFIG_IR_SANYO_DECODER=m
- +CONFIG_IR_MCE_KBD_DECODER=m
- +CONFIG_IR_LIRC_CODEC=m
- +CONFIG_IR_IMON=m
- +CONFIG_IR_MCEUSB=m
- +CONFIG_IR_ITE_CIR=m
- +CONFIG_IR_NUVOTON=m
- +CONFIG_IR_FINTEK=m
- +CONFIG_IR_REDRAT3=m
- +CONFIG_IR_ENE=m
- +CONFIG_IR_STREAMZAP=m
- +CONFIG_IR_WINBOND_CIR=m
- +CONFIG_IR_IGUANA=m
- +CONFIG_IR_TTUSBIR=m
- +CONFIG_IR_GPIO_CIR=m
- diff -Nur linux-3.14.35.orig/arch/arm/configs/imx_v7_cbi_hb_defconfig linux-3.14.35/arch/arm/configs/imx_v7_cbi_hb_defconfig
- --- linux-3.14.35.orig/arch/arm/configs/imx_v7_cbi_hb_defconfig 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/configs/imx_v7_cbi_hb_defconfig 2015-03-08 14:27:37.409684502 -0500
- @@ -0,0 +1,5138 @@
- +#
- +# Automatically generated make config: don't edit
- +#
- +CONFIG_MMU=y
- +CONFIG_HOTPLUG_CPU=y
- +# CONFIG_BOOTPARAM_HOTPLUG_CPU0 is not set
- +# CONFIG_DEBUG_HOTPLUG_CPU0 is not set
- +CONFIG_LOCALVERSION=""
- +CONFIG_CROSS_COMPILE=""
- +CONFIG_DEFAULT_HOSTNAME="(none)"
- +
- +#
- +# Code maturity level options
- +#
- +CONFIG_EXPERIMENTAL=y
- +CONFIG_HOTPLUG=y
- +CONFIG_UEVENT_HELPER_PATH=""
- +CONFIG_PREVENT_FIRMWARE_BUILD=y
- +
- +CONFIG_BUILD_DOCSRC=y
- +
- +#
- +# General setup
- +#
- +CONFIG_KERNEL_LZO=y
- +# CONFIG_KERNEL_BZIP2 is not set
- +# CONFIG_KERNEL_LZMA is not set
- +CONFIG_SWAP=y
- +CONFIG_BSD_PROCESS_ACCT=y
- +CONFIG_BSD_PROCESS_ACCT_V3=y
- +# CONFIG_COMPILE_TEST is not set
- +CONFIG_TASKSTATS=y
- +CONFIG_TASK_DELAY_ACCT=y
- +CONFIG_TASK_XACCT=y
- +CONFIG_TASK_IO_ACCOUNTING=y
- +CONFIG_SYSCTL=y
- +# CONFIG_IKCONFIG is not set
- +# CONFIG_EMBEDDED is not set
- +CONFIG_KALLSYMS=y
- +CONFIG_KALLSYMS_ALL=y
- +CONFIG_FUTEX=y
- +CONFIG_EPOLL=y
- +CONFIG_IOSCHED_NOOP=y
- +CONFIG_IOSCHED_DEADLINE=y
- +CONFIG_IOSCHED_CFQ=y
- +CONFIG_CFQ_GROUP_IOSCHED=y
- +CONFIG_IOSCHED_BFQ=y
- +CONFIG_CGROUP_BFQIO=y
- +CONFIG_DEFAULT_BFQ=y
- +CONFIG_DEFAULT_IOSCHED="bfq"
- +# CONFIG_CHECKPOINT_RESTORE is not set
- +CONFIG_NAMESPACES=y
- +CONFIG_PID_NS=y
- +CONFIG_UTS_NS=y
- +CONFIG_IPC_NS=y
- +CONFIG_NET_NS=y
- +CONFIG_USER_NS=y
- +# CONFIG_UIDGID_STRICT_TYPE_CHECKS is not set
- +CONFIG_SYSVIPC=y
- +CONFIG_FHANDLE=y
- +CONFIG_NO_HZ=y
- +CONFIG_HIGH_RES_TIMERS=y
- +CONFIG_LOG_BUF_SHIFT=18
- +CONFIG_CGROUPS=y
- +CONFIG_RELAY=y
- +CONFIG_BLK_DEV_INITRD=y
- +CONFIG_EXPERT=y
- +CONFIG_PERF_EVENTS=y
- +# CONFIG_SLUB_DEBUG is not set
- +# CONFIG_COMPAT_BRK is not set
- +CONFIG_MODULES=y
- +CONFIG_MODULE_UNLOAD=y
- +CONFIG_MODVERSIONS=y
- +CONFIG_MODULE_SRCVERSION_ALL=y
- +
- +CONFIG_POSIX_MQUEUE=y
- +CONFIG_PREEMPT_VOLUNTARY=y
- +
- +CONFIG_SLUB=y
- +CONFIG_SLUB_CPU_PARTIAL=y
- +# CONFIG_SLUB_STATS is not set
- +# CONFIG_SLUB_DEBUG_ON is not set
- +
- +# CONFIG_AD525X_DPOT is not set
- +# CONFIG_ATMEL_PWM is not set
- +# CONFIG_IWMC3200TOP is not set
- +# CONFIG_BLK_DEV_BSG is not set
- +
- +# MX6 specific kernel configuration
- +CONFIG_GPIO_PCA953X=y
- +CONFIG_ARCH_MXC=y
- +CONFIG_MXC_DEBUG_BOARD=y
- +CONFIG_SOC_IMX6Q=y
- +CONFIG_SOC_IMX6SL=y
- +# CONFIG_SWP_EMULATE is not set
- +CONFIG_PCI=y
- +CONFIG_PCIE_DW=y
- +CONFIG_PCI_IMX6=y
- +CONFIG_SMP=y
- +CONFIG_VMSPLIT_2G=y
- +CONFIG_AEABI=y
- +# CONFIG_OABI_COMPAT is not set
- +CONFIG_HIGHMEM=y
- +CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
- +CONFIG_CPU_FREQ=y
- +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y
- +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
- +CONFIG_CPU_FREQ_GOV_POWERSAVE=y
- +CONFIG_CPU_FREQ_GOV_USERSPACE=y
- +CONFIG_CPU_FREQ_GOV_ONDEMAND=y
- +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
- +CONFIG_ARM_IMX6_CPUFREQ=y
- +CONFIG_CPU_IDLE=y
- +CONFIG_VFP=y
- +CONFIG_VFPv3=y
- +CONFIG_NEON=y
- +CONFIG_KERNEL_MODE_NEON=y
- +CONFIG_BINFMT_MISC=m
- +CONFIG_PM_RUNTIME=y
- +CONFIG_PM_DEBUG=y
- +CONFIG_PM_TEST_SUSPEND=y
- +CONFIG_NET=y
- +CONFIG_PACKET=y
- +CONFIG_UNIX=y
- +CONFIG_INET=y
- +CONFIG_IP_PNP=y
- +CONFIG_IP_PNP_DHCP=y
- +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
- +# CONFIG_INET_XFRM_MODE_TUNNEL is not set
- +# CONFIG_INET_XFRM_MODE_BEET is not set
- +# CONFIG_INET_LRO is not set
- +CONFIG_IPV6=y
- +CONFIG_NETFILTER=y
- +CONFIG_VLAN_8021Q=y
- +CONFIG_WIRELESS=y
- +CONFIG_WIRELESS_EXT=y
- +CONFIG_WEXT_CORE=y
- +CONFIG_WEXT_PROC=y
- +CONFIG_WEXT_SPY=y
- +CONFIG_WEXT_PRIV=y
- +CONFIG_CFG80211=y
- +CONFIG_ETHERNET=y
- +# CONFIG_NET_VENDOR_BROADCOM is not set
- +# CONFIG_NET_VENDOR_CIRRUS is not set
- +# CONFIG_NET_VENDOR_FARADAY
- +# CONFIG_NET_VENDOR_INTEL
- +# CONFIG_NET_VENDOR_I825XX
- +# CONFIG_NET_VENDOR_MARVELL
- +# CONFIG_NET_VENDOR_MICROCHIP
- +# CONFIG_NET_VENDOR_MICROCHIP=y
- +# CONFIG_ENC28J60 is not set
- +# CONFIG_NET_VENDOR_NATSEMI=y
- +# CONFIG_NET_VENDOR_8390=y
- +# CONFIG_AX88796 is not set
- +# CONFIG_ETHOC is not set
- +# CONFIG_SH_ETH is not set
- +# CONFIG_NET_VENDOR_SEEQ=y
- +# CONFIG_NET_VENDOR_SMSC=y
- +# CONFIG_SMC91X is not set
- +# CONFIG_SMC911X is not set
- +# CONFIG_SMSC911X is not set
- +# CONFIG_NET_VENDOR_STMICRO=y
- +# CONFIG_STMMAC_ETH is not set
- +# CONFIG_NET_VENDOR_VIA=y
- +# CONFIG_VIA_VELOCITY is not set
- +# CONFIG_NET_VENDOR_WIZNET=y
- +CONFIG_NET_VENDOR_FREESCALE=y
- +CONFIG_FEC=y
- +CONFIG_PHYLIB=y
- +CONFIG_AT803X_PHY=y
- +CONFIG_WLAN=y
- +CONFIG_BRCMUTIL=m
- +CONFIG_BRCMFMAC=m
- +CONFIG_BRCMFMAC_SDIO=y
- +CONFIG_DEVTMPFS=y
- +CONFIG_DEVTMPFS_MOUNT=y
- +# CONFIG_STANDALONE is not set
- +CONFIG_DMA_CMA=y
- +CONFIG_CMA=y
- +CONFIG_CMA_SIZE_MBYTES=256
- +CONFIG_CONNECTOR=y
- +# CONFIG_MTD is not set
- +CONFIG_BLK_DEV_LOOP=y
- +CONFIG_BLK_DEV_RAM=y
- +CONFIG_BLK_DEV_RAM_SIZE=65536
- +# CONFIG_SCSI_PROC_FS is not set
- +CONFIG_BLK_DEV_SD=y
- +CONFIG_SCSI_MULTI_LUN=y
- +CONFIG_SCSI_CONSTANTS=y
- +CONFIG_SCSI_LOGGING=y
- +CONFIG_SCSI_SCAN_ASYNC=y
- +# CONFIG_SCSI_LOWLEVEL is not set
- +CONFIG_ATA=y
- +CONFIG_SATA_AHCI_PLATFORM=y
- +CONFIG_AHCI_IMX=y
- +CONFIG_NETDEVICES=y
- +CONFIG_INPUT_EVDEV=y
- +# CONFIG_INPUT_EVBUG is not set
- +CONFIG_KEYBOARD_GPIO=y
- +CONFIG_KEYBOARD_IMX=y
- +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
- +# CONFIG_KEYBOARD_ATKBD is not set
- +# CONFIG_MOUSE_PS2 is not set
- +CONFIG_INPUT_MISC=y
- +CONFIG_SERIO_SERPORT=m
- +CONFIG_VT_HW_CONSOLE_BINDING=y
- +# CONFIG_LEGACY_PTYS is not set
- +# CONFIG_DEVKMEM is not set
- +CONFIG_SERIAL_IMX=y
- +CONFIG_SERIAL_IMX_CONSOLE=y
- +CONFIG_SERIAL_FSL_LPUART=y
- +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
- +CONFIG_FSL_OTP=y
- +CONFIG_GPIO_MXC=y
- +# CONFIG_I2C_COMPAT is not set
- +CONFIG_I2C_CHARDEV=y
- +# CONFIG_I2C_HELPER_AUTO is not set
- +CONFIG_I2C_ALGOPCF=m
- +CONFIG_I2C_ALGOPCA=m
- +CONFIG_I2C_IMX=y
- +CONFIG_SPI=y
- +CONFIG_SPI_IMX=y
- +CONFIG_GPIO_SYSFS=y
- +CONFIG_POWER_SUPPLY=y
- +CONFIG_THERMAL=y
- +CONFIG_CPU_THERMAL=y
- +CONFIG_IMX_THERMAL=y
- +CONFIG_DEVICE_THERMAL=y
- +CONFIG_WATCHDOG=y
- +CONFIG_IMX2_WDT=y
- +CONFIG_MFD_DA9052_I2C=y
- +CONFIG_MFD_MC13XXX_SPI=y
- +CONFIG_MFD_MC13XXX_I2C=y
- +CONFIG_MFD_SI476X_CORE=y
- +CONFIG_REGULATOR=y
- +CONFIG_REGULATOR_FIXED_VOLTAGE=y
- +CONFIG_REGULATOR_ANATOP=y
- +CONFIG_REGULATOR_PFUZE100=y
- +CONFIG_MEDIA_SUPPORT=y
- +CONFIG_MEDIA_CAMERA_SUPPORT=y
- +# CONFIG_MEDIA_RADIO_SUPPORT is not set
- +CONFIG_VIDEO_V4L2_INT_DEVICE=y
- +CONFIG_MEDIA_USB_SUPPORT=y
- +CONFIG_USB_VIDEO_CLASS=m
- +# CONFIG_RADIO_ADAPTERS is not set
- +CONFIG_V4L_PLATFORM_DRIVERS=y
- +CONFIG_VIDEO_MXC_OUTPUT=y
- +CONFIG_VIDEO_MXC_CAPTURE=m
- +CONFIG_VIDEO_MXC_CSI_CAMERA=m
- +CONFIG_MXC_CAMERA_OV5640=m
- +CONFIG_MXC_CAMERA_OV5642=m
- +CONFIG_MXC_CAMERA_OV5640_MIPI=m
- +CONFIG_MXC_TVIN_ADV7180=m
- +CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m
- +CONFIG_VIDEO_MXC_IPU_OUTPUT=y
- +CONFIG_VIDEO_MXC_PXP_V4L2=y
- +CONFIG_SOC_CAMERA=y
- +CONFIG_SOC_CAMERA_OV2640=y
- +CONFIG_DRM=y
- +CONFIG_DRM_VIVANTE=y
- +CONFIG_FB=y
- +# CONFIG_FB_MX3 is not set
- +CONFIG_FB_MXC_SYNC_PANEL=y
- +CONFIG_FB_MXC_LDB=y
- +CONFIG_FB_MXC_HDMI=y
- +CONFIG_FRAMEBUFFER_CONSOLE=y
- +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
- +CONFIG_FONTS=y
- +CONFIG_FONT_8x8=y
- +CONFIG_FONT_8x16=y
- +CONFIG_LOGO=y
- +CONFIG_SOUND=y
- +CONFIG_SND=y
- +CONFIG_SND_USB_AUDIO=m
- +CONFIG_SND_SOC=y
- +CONFIG_SND_IMX_SOC=y
- +CONFIG_SND_SOC_IMX_SGTL5000=y
- +CONFIG_SND_SOC_IMX_SPDIF=y
- +CONFIG_SND_SOC_IMX_HDMI=y
- +CONFIG_USB=y
- +CONFIG_USB_EHCI_HCD=y
- +CONFIG_USB_STORAGE=y
- +CONFIG_USB_CHIPIDEA=y
- +CONFIG_USB_CHIPIDEA_UDC=y
- +CONFIG_USB_CHIPIDEA_HOST=y
- +CONFIG_USB_PHY=y
- +CONFIG_NOP_USB_XCEIV=y
- +CONFIG_USB_MXS_PHY=y
- +CONFIG_USB_GADGET=y
- +CONFIG_USB_ZERO=m
- +CONFIG_USB_ETH=m
- +CONFIG_USB_MASS_STORAGE=m
- +CONFIG_USB_G_SERIAL=m
- +CONFIG_MMC=y
- +CONFIG_MMC_UNSAFE_RESUME=y
- +CONFIG_MMC_SDHCI=y
- +CONFIG_MMC_SDHCI_PLTFM=y
- +CONFIG_MMC_SDHCI_ESDHC_IMX=y
- +CONFIG_MXC_IPU=y
- +CONFIG_MXC_GPU_VIV=y
- +CONFIG_MXC_ASRC=y
- +CONFIG_MXC_HDMI_CEC=y
- +CONFIG_MXC_MIPI_CSI2=y
- +CONFIG_MXC_MLB150=m
- +CONFIG_NEW_LEDS=y
- +CONFIG_LEDS_CLASS=y
- +CONFIG_LEDS_GPIO=y
- +CONFIG_LEDS_TRIGGERS=y
- +CONFIG_LEDS_TRIGGER_GPIO=y
- +CONFIG_RTC_CLASS=y
- +CONFIG_RTC_DRV_MXC=y
- +CONFIG_RTC_DRV_SNVS=y
- +CONFIG_RTC_DRV_PCF8523=y
- +CONFIG_DMADEVICES=y
- +CONFIG_MXC_PXP_V2=y
- +CONFIG_IMX_SDMA=y
- +CONFIG_MXS_DMA=y
- +CONFIG_SRAM=y
- +CONFIG_STAGING=y
- +CONFIG_COMMON_CLK_DEBUG=y
- +# CONFIG_IOMMU_SUPPORT is not set
- +CONFIG_PWM=y
- +CONFIG_PWM_SYSFS=y
- +CONFIG_PWM_IMX=y
- +CONFIG_IRQCHIP=y
- +CONFIG_ARM_GIC=y
- +CONFIG_ARCH_HAS_RESET_CONTROLLER=y
- +CONFIG_RESET_CONTROLLER=y
- +CONFIG_RESET_GPIO=y
- +CONFIG_EXT4_FS=y
- +CONFIG_EXT4_USE_FOR_EXT23=y
- +CONFIG_EXT4_FS_XATTR=y
- +CONFIG_EXT4_FS_POSIX_ACL=y
- +CONFIG_EXT4_FS_SECURITY=y
- +CONFIG_QUOTA=y
- +CONFIG_QUOTA_NETLINK_INTERFACE=y
- +# CONFIG_PRINT_QUOTA_WARNING is not set
- +CONFIG_AUTOFS4_FS=y
- +CONFIG_FUSE_FS=y
- +CONFIG_ISO9660_FS=m
- +CONFIG_JOLIET=y
- +CONFIG_ZISOFS=y
- +CONFIG_UDF_FS=m
- +CONFIG_MSDOS_FS=m
- +CONFIG_VFAT_FS=y
- +CONFIG_TMPFS=y
- +CONFIG_JFFS2_FS=y
- +CONFIG_UBIFS_FS=y
- +CONFIG_NFS_FS=y
- +CONFIG_NFS_V3_ACL=y
- +CONFIG_NFS_V4=y
- +CONFIG_ROOT_NFS=y
- +CONFIG_NLS_DEFAULT="cp437"
- +CONFIG_NLS_CODEPAGE_437=y
- +CONFIG_NLS_ASCII=y
- +CONFIG_NLS_ISO8859_1=y
- +CONFIG_NLS_ISO8859_15=m
- +CONFIG_NLS_UTF8=y
- +CONFIG_MAGIC_SYSRQ=y
- +# CONFIG_SCHED_DEBUG is not set
- +# CONFIG_DEBUG_BUGVERBOSE is not set
- +# CONFIG_FTRACE is not set
- +CONFIG_SECURITYFS=y
- +CONFIG_CRYPTO_USER=y
- +CONFIG_CRYPTO_TEST=m
- +CONFIG_CRYPTO_CCM=y
- +CONFIG_CRYPTO_GCM=y
- +CONFIG_CRYPTO_CBC=y
- +CONFIG_CRYPTO_CTS=y
- +CONFIG_CRYPTO_ECB=y
- +CONFIG_CRYPTO_LRW=y
- +CONFIG_CRYPTO_XTS=y
- +CONFIG_CRYPTO_MD4=y
- +CONFIG_CRYPTO_MD5=y
- +CONFIG_CRYPTO_MICHAEL_MIC=y
- +CONFIG_CRYPTO_RMD128=y
- +CONFIG_CRYPTO_RMD160=y
- +CONFIG_CRYPTO_RMD256=y
- +CONFIG_CRYPTO_RMD320=y
- +CONFIG_CRYPTO_SHA1=y
- +CONFIG_CRYPTO_SHA256=y
- +CONFIG_CRYPTO_SHA512=y
- +CONFIG_CRYPTO_TGR192=y
- +CONFIG_CRYPTO_WP512=y
- +CONFIG_CRYPTO_BLOWFISH=y
- +CONFIG_CRYPTO_CAMELLIA=y
- +CONFIG_CRYPTO_DES=y
- +CONFIG_CRYPTO_TWOFISH=y
- +# CONFIG_CRYPTO_ANSI_CPRNG is not set
- +CONFIG_CRYPTO_DEV_FSL_CAAM=y
- +CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y
- +CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=y
- +CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=y
- +CONFIG_CRYPTO_AES_ARM_BS=y
- +CONFIG_CRC_CCITT=m
- +CONFIG_CRC_T10DIF=y
- +CONFIG_CRC7=m
- +CONFIG_LIBCRC32C=m
- +# CONFIG_MXC_MMA8451 is not set
- +
- +#
- +# Loadable module support
- +#
- +# CONFIG_MODULE_FORCE_LOAD is not set
- +# -- MODULE_FORCE_UNLOAD is controlled by config-debug/nodebug
- +
- +# CONFIG_PCI_DEBUG is not set
- +CONFIG_PCI_STUB=y
- +CONFIG_PCI_IOV=y
- +CONFIG_PCI_PRI=y
- +CONFIG_PCI_PASID=y
- +CONFIG_HT_IRQ=y
- +CONFIG_PCI_MSI=y
- +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
- +CONFIG_PCIEPORTBUS=y
- +CONFIG_PCIEAER=y
- +CONFIG_PCIEASPM=y
- +# CONFIG_PCIEASPM_DEBUG is not set
- +CONFIG_PCIE_ECRC=y
- +CONFIG_PCIEAER_INJECT=m
- +CONFIG_HOTPLUG_PCI_PCIE=y
- +CONFIG_HOTPLUG_PCI_FAKE=m
- +
- +# CONFIG_SGI_IOC4 is not set
- +
- +# CONFIG_ISA is not set
- +# CONFIG_SCx200 is not set
- +
- +#
- +# PCMCIA/CardBus support
- +# FIXME: Deprecate Cardbus ?
- +#
- +CONFIG_PCMCIA=y
- +CONFIG_PCMCIA_LOAD_CIS=y
- +# CONFIG_PCMCIA_DEBUG is not set
- +CONFIG_YENTA=m
- +CONFIG_CARDBUS=y
- +CONFIG_I82092=m
- +CONFIG_PD6729=m
- +
- +CONFIG_PCCARD=y
- +CONFIG_SDIO_UART=m
- +# CONFIG_MMC_TEST is not set
- +# CONFIG_MMC_DEBUG is not set
- +# https://lists.fedoraproject.org/pipermail/kernel/2014-February/004889.html
- +# CONFIG_MMC_CLKGATE is not set
- +CONFIG_MMC_BLOCK=y
- +CONFIG_MMC_BLOCK_MINORS=8
- +CONFIG_MMC_BLOCK_BOUNCE=y
- +CONFIG_MMC_SDHCI_PCI=m
- +CONFIG_MMC_SDHCI_ACPI=m
- +CONFIG_MMC_SDRICOH_CS=m
- +CONFIG_MMC_TIFM_SD=m
- +CONFIG_MMC_WBSD=m
- +CONFIG_MMC_VIA_SDMMC=m
- +CONFIG_MMC_CB710=m
- +CONFIG_MMC_RICOH_MMC=y
- +CONFIG_MMC_USHC=m
- +CONFIG_MMC_REALTEK_PCI=m
- +CONFIG_MMC_VUB300=m
- +# CONFIG_MMC_SDHCI_PXAV2 is not set
- +# CONFIG_MMC_SDHCI_PXAV3 is not set
- +# CONFIG_MMC_SDHCI_OF_ARASAN is not set
- +
- +
- +CONFIG_CB710_CORE=m
- +# CONFIG_CB710_DEBUG is not set
- +
- +CONFIG_INFINIBAND=m
- +CONFIG_INFINIBAND_MTHCA=m
- +# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
- +CONFIG_INFINIBAND_IPOIB=m
- +CONFIG_INFINIBAND_IPOIB_DEBUG=y
- +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
- +CONFIG_INFINIBAND_IPOIB_CM=y
- +CONFIG_INFINIBAND_SRP=m
- +CONFIG_INFINIBAND_SRPT=m
- +CONFIG_INFINIBAND_USER_MAD=m
- +CONFIG_INFINIBAND_USER_ACCESS=m
- +# CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING is not set #staging
- +CONFIG_INFINIBAND_IPATH=m
- +CONFIG_INFINIBAND_ISER=m
- +CONFIG_INFINIBAND_ISERT=m
- +CONFIG_INFINIBAND_AMSO1100=m
- +# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set
- +CONFIG_INFINIBAND_CXGB3=m
- +CONFIG_INFINIBAND_CXGB4=m
- +CONFIG_SCSI_CXGB3_ISCSI=m
- +CONFIG_SCSI_CXGB4_ISCSI=m
- +# CONFIG_INFINIBAND_CXGB3_DEBUG is not set
- +CONFIG_MLX4_INFINIBAND=m
- +CONFIG_MLX5_INFINIBAND=m
- +CONFIG_INFINIBAND_NES=m
- +# CONFIG_INFINIBAND_NES_DEBUG is not set
- +CONFIG_INFINIBAND_QIB=m
- +CONFIG_INFINIBAND_QIB_DCA=y
- +# CONFIG_INFINIBAND_OCRDMA is not set
- +# CONFIG_INFINIBAND_USNIC is not set
- +
- +#
- +# Executable file formats
- +#
- +CONFIG_BINFMT_ELF=y
- +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
- +# CONFIG_BINFMT_AOUT is not set
- +CONFIG_BINFMT_SCRIPT=y
- +
- +#
- +# Device Drivers
- +#
- +
- +# CONFIG_COMMON_CLK_SI5351 is not set
- +
- +#
- +# Generic Driver Options
- +#
- +CONFIG_FW_LOADER=y
- +# CONFIG_FIRMWARE_IN_KERNEL is not set
- +CONFIG_EXTRA_FIRMWARE=""
- +
- +# Give this a try in rawhide for now
- +# CONFIG_FW_LOADER_USER_HELPER is not set
- +
- +
- +
- +#
- +# Memory Technology Devices (MTD)
- +#
- +# CONFIG_MTD_TESTS is not set
- +# CONFIG_MTD_REDBOOT_PARTS is not set
- +# CONFIG_MTD_AR7_PARTS is not set
- +# CONFIG_MTD_CMDLINE_PARTS is not set
- +
- +#
- +# User Modules And Translation Layers
- +#
- +# CONFIG_MTD_CHAR is not set
- +# CONFIG_MTD_BLKDEVS is not set
- +# CONFIG_MTD_BLOCK is not set
- +# CONFIG_MTD_BLOCK_RO is not set
- +# CONFIG_FTL is not set
- +# CONFIG_NFTL is not set
- +# CONFIG_INFTL is not set
- +# CONFIG_RFD_FTL is not set
- +# CONFIG_SSFDC is not set
- +# CONFIG_SM_FTL is not set
- +# CONFIG_MTD_OOPS is not set
- +# CONFIG_MTD_SWAP is not set
- +
- +#
- +# RAM/ROM/Flash chip drivers
- +#
- +# CONFIG_MTD_CFI is not set
- +# CONFIG_MTD_JEDECPROBE is not set
- +CONFIG_MTD_MAP_BANK_WIDTH_1=y
- +CONFIG_MTD_MAP_BANK_WIDTH_2=y
- +CONFIG_MTD_MAP_BANK_WIDTH_4=y
- +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
- +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
- +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
- +CONFIG_MTD_CFI_I1=y
- +CONFIG_MTD_CFI_I2=y
- +# CONFIG_MTD_CFI_I4 is not set
- +# CONFIG_MTD_CFI_I8 is not set
- +# CONFIG_MTD_RAM is not set
- +# CONFIG_MTD_ROM is not set
- +# CONFIG_MTD_ABSENT is not set
- +
- +#
- +# Mapping drivers for chip access
- +#
- +# CONFIG_MTD_COMPLEX_MAPPINGS is not set
- +# CONFIG_MTD_TS5500 is not set
- +# CONFIG_MTD_INTEL_VR_NOR is not set
- +# CONFIG_MTD_PLATRAM is not set
- +
- +# Self-contained MTD device drivers
- +# CONFIG_MTD_PMC551 is not set
- +# CONFIG_MTD_SLRAM is not set
- +# CONFIG_MTD_PHRAM is not set
- +# CONFIG_MTD_MTDRAM is not set
- +# CONFIG_MTD_BLOCK2MTD is not set
- +
- +#
- +# Disk-On-Chip Device Drivers
- +#
- +# CONFIG_MTD_DOCG3 is not set
- +# CONFIG_MTD_NAND is not set
- +# CONFIG_MTD_ONENAND is not set
- +# CONFIG_MTD_NAND_VERIFY_WRITE is not set
- +# CONFIG_MTD_NAND_ECC_BCH is not set
- +# CONFIG_MTD_NAND_MUSEUM_IDS is not set
- +# CONFIG_MTD_NAND_DISKONCHIP is not set
- +# CONFIG_MTD_LPDDR is not set
- +CONFIG_MTD_UBI=m
- +CONFIG_MTD_UBI_WL_THRESHOLD=4096
- +CONFIG_MTD_UBI_BEB_LIMIT=20
- +# CONFIG_MTD_UBI_FASTMAP is not set
- +# CONFIG_MTD_UBI_GLUEBI is not set
- +
- +#
- +# Parallel port support
- +#
- +CONFIG_PARPORT=m
- +CONFIG_PARPORT_PC=m
- +CONFIG_PARPORT_SERIAL=m
- +# CONFIG_PARPORT_PC_FIFO is not set
- +# CONFIG_PARPORT_PC_SUPERIO is not set
- +CONFIG_PARPORT_PC_PCMCIA=m
- +CONFIG_PARPORT_1284=y
- +# CONFIG_PARPORT_AX88796 is not set
- +
- +CONFIG_ACPI_PCI_SLOT=y
- +CONFIG_HOTPLUG_PCI_ACPI=y
- +CONFIG_HOTPLUG_PCI_ACPI_IBM=m
- +
- +#
- +# Block devices
- +#
- +CONFIG_BLK_DEV=y
- +CONFIG_BLK_DEV_NULL_BLK=m
- +CONFIG_BLK_DEV_FD=m
- +# CONFIG_PARIDE is not set
- +CONFIG_ZRAM=m
- +# CONFIG_ZRAM_DEBUG is not set
- +CONFIG_ENHANCEIO=m
- +
- +CONFIG_BLK_CPQ_DA=m
- +CONFIG_BLK_CPQ_CISS_DA=m
- +CONFIG_CISS_SCSI_TAPE=y
- +CONFIG_BLK_DEV_DAC960=m
- +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set
- +CONFIG_BLK_DEV_DRBD=m
- +CONFIG_BLK_DEV_UMEM=m
- +CONFIG_BLK_DEV_LOOP_MIN_COUNT=0
- +# Fedora 18 util-linux is the last release that supports cryptoloop devices
- +# CONFIG_BLK_DEV_CRYPTOLOOP is not set
- +CONFIG_BLK_DEV_NBD=m
- +CONFIG_BLK_DEV_NVME=m
- +CONFIG_BLK_DEV_SKD=m # 64-bit only but easier to put here
- +CONFIG_BLK_DEV_OSD=m
- +CONFIG_BLK_DEV_RAM_COUNT=16
- +CONFIG_BLK_DEV_IO_TRACE=y
- +
- +CONFIG_BLK_DEV_BSGLIB=y
- +CONFIG_BLK_DEV_INTEGRITY=y
- +CONFIG_BLK_DEV_THROTTLING=y
- +# CONFIG_BLK_CMDLINE_PARSER is not set
- +
- +
- +#
- +# ATA/ATAPI/MFM/RLL support
- +#
- +# CONFIG_IDE is not set
- +
- +# CONFIG_BLK_DEV_HD is not set
- +# CONFIG_BLK_DEV_RSXX is not set
- +
- +CONFIG_SCSI_VIRTIO=m
- +CONFIG_VIRTIO_BLK=m
- +CONFIG_VIRTIO_PCI=m
- +CONFIG_VIRTIO_BALLOON=m
- +CONFIG_VIRTIO_MMIO=m
- +# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set
- +CONFIG_VIRTIO_NET=m
- +CONFIG_HW_RANDOM_VIRTIO=m
- +CONFIG_VIRTIO_CONSOLE=m
- +CONFIG_VHOST_NET=m
- +CONFIG_TCM_VHOST=m
- +CONFIG_VHOST_SCSI=m
- +
- +#
- +# SCSI device support
- +#
- +CONFIG_SCSI=y
- +
- +CONFIG_SCSI_ENCLOSURE=m
- +CONFIG_SCSI_SRP=m
- +CONFIG_SCSI_SRP_ATTRS=m
- +CONFIG_SCSI_TGT=m
- +CONFIG_SCSI_ISCI=m
- +CONFIG_SCSI_CHELSIO_FCOE=m
- +
- +CONFIG_SCSI_DH=y
- +CONFIG_SCSI_DH_RDAC=m
- +CONFIG_SCSI_DH_HP_SW=m
- +CONFIG_SCSI_DH_EMC=m
- +CONFIG_SCSI_DH_ALUA=m
- +
- +#
- +# SCSI support type (disk, tape, CD-ROM)
- +#
- +CONFIG_CHR_DEV_ST=m
- +CONFIG_CHR_DEV_OSST=m
- +CONFIG_BLK_DEV_SR=y
- +CONFIG_BLK_DEV_SR_VENDOR=y
- +CONFIG_CHR_DEV_SG=y
- +CONFIG_CHR_DEV_SCH=m
- +
- +#
- +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
- +#
- +CONFIG_SCSI_SPI_ATTRS=m
- +CONFIG_SCSI_FC_ATTRS=m
- +CONFIG_SCSI_FC_TGT_ATTRS=y
- +CONFIG_SCSI_ISCSI_ATTRS=m
- +CONFIG_SCSI_SAS_ATTRS=m
- +CONFIG_SCSI_SRP_TGT_ATTRS=y
- +CONFIG_SCSI_SAS_LIBSAS=m
- +CONFIG_SCSI_SAS_ATA=y
- +CONFIG_SCSI_SAS_HOST_SMP=y
- +CONFIG_RAID_ATTRS=m
- +
- +CONFIG_ISCSI_TCP=m
- +CONFIG_ISCSI_BOOT_SYSFS=m
- +
- +#
- +# SCSI low-level drivers
- +#
- +CONFIG_BLK_DEV_3W_XXXX_RAID=m
- +CONFIG_SCSI_3W_9XXX=m
- +CONFIG_SCSI_ACARD=m
- +CONFIG_SCSI_AACRAID=m
- +CONFIG_SCSI_AIC7XXX=m
- +# http://lists.fedoraproject.org/pipermail/kernel/2013-February/004102.html
- +# CONFIG_SCSI_AIC7XXX_OLD is not set
- +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
- +CONFIG_AIC7XXX_RESET_DELAY_MS=15000
- +# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
- +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
- +CONFIG_AIC7XXX_DEBUG_MASK=0
- +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
- +CONFIG_SCSI_AIC79XX=m
- +CONFIG_AIC79XX_CMDS_PER_DEVICE=4
- +CONFIG_AIC79XX_RESET_DELAY_MS=15000
- +# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
- +# CONFIG_AIC79XX_DEBUG_ENABLE is not set
- +CONFIG_AIC79XX_DEBUG_MASK=0
- +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
- +CONFIG_SCSI_AIC94XX=m
- +# CONFIG_AIC94XX_DEBUG is not set
- +# CONFIG_SCSI_ADVANSYS is not set
- +CONFIG_SCSI_BFA_FC=m
- +CONFIG_MEGARAID_NEWGEN=y
- +CONFIG_MEGARAID_MM=m
- +CONFIG_MEGARAID_MAILBOX=m
- +CONFIG_MEGARAID_LEGACY=m
- +CONFIG_MEGARAID_SAS=m
- +CONFIG_SCSI_ESAS2R=m
- +CONFIG_SCSI_MVSAS=m
- +# CONFIG_SCSI_MVSAS_DEBUG is not set
- +CONFIG_SCSI_MVSAS_TASKLET=y
- +CONFIG_SCSI_MPT2SAS=m
- +CONFIG_SCSI_MPT2SAS_MAX_SGE=128
- +CONFIG_SCSI_MPT2SAS_LOGGING=y
- +CONFIG_SCSI_MPT3SAS=m
- +CONFIG_SCSI_MPT3SAS_MAX_SGE=128
- +CONFIG_SCSI_MPT3SAS_LOGGING=y
- +
- +CONFIG_SCSI_UFSHCD=m
- +CONFIG_SCSI_UFSHCD_PCI=m
- +# CONFIG_SCSI_UFSHCD_PLATFORM is not set
- +
- +CONFIG_SCSI_MVUMI=m
- +
- +CONFIG_SCSI_OSD_INITIATOR=m
- +CONFIG_SCSI_OSD_ULD=m
- +CONFIG_SCSI_OSD_DPRINT_SENSE=1
- +# CONFIG_SCSI_OSD_DEBUG is not set
- +
- +CONFIG_SCSI_BNX2_ISCSI=m
- +CONFIG_SCSI_BNX2X_FCOE=m
- +CONFIG_BE2ISCSI=m
- +CONFIG_SCSI_PMCRAID=m
- +
- +CONFIG_SCSI_HPSA=m
- +CONFIG_SCSI_3W_SAS=m
- +CONFIG_SCSI_PM8001=m
- +CONFIG_VMWARE_PVSCSI=m
- +CONFIG_VMWARE_BALLOON=m
- +
- +CONFIG_SCSI_ARCMSR=m
- +CONFIG_SCSI_BUSLOGIC=m
- +CONFIG_SCSI_INITIO=m
- +CONFIG_SCSI_FLASHPOINT=y
- +CONFIG_SCSI_DMX3191D=m
- +# CONFIG_SCSI_EATA is not set
- +# CONFIG_SCSI_EATA_PIO is not set
- +# CONFIG_SCSI_FUTURE_DOMAIN is not set
- +CONFIG_SCSI_GDTH=m
- +CONFIG_SCSI_HPTIOP=m
- +CONFIG_SCSI_IPS=m
- +CONFIG_SCSI_INIA100=m
- +# CONFIG_SCSI_PPA is not set
- +# CONFIG_SCSI_IMM is not set
- +# CONFIG_SCSI_IZIP_EPP16 is not set
- +# CONFIG_SCSI_IZIP_SLOW_CTR is not set
- +CONFIG_SCSI_STEX=m
- +CONFIG_SCSI_SYM53C8XX_2=m
- +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
- +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
- +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
- +CONFIG_SCSI_SYM53C8XX_MMIO=y
- +CONFIG_SCSI_QLOGIC_1280=m
- +CONFIG_SCSI_DC395x=m
- +# CONFIG_SCSI_NSP32 is not set
- +CONFIG_SCSI_DEBUG=m
- +CONFIG_SCSI_DC390T=m
- +CONFIG_SCSI_QLA_FC=m
- +CONFIG_TCM_QLA2XXX=m
- +CONFIG_SCSI_QLA_ISCSI=m
- +CONFIG_SCSI_IPR=m
- +CONFIG_SCSI_IPR_TRACE=y
- +CONFIG_SCSI_IPR_DUMP=y
- +# CONFIG_SCSI_DPT_I2O is not set
- +CONFIG_SCSI_LPFC=m
- +# CONFIG_SCSI_LPFC_DEBUG_FS is not set
- +
- +# PCMCIA SCSI adapter support
- +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
- +
- +CONFIG_ATA_BMDMA=y
- +CONFIG_ATA_VERBOSE_ERROR=y
- +CONFIG_ATA_SFF=y
- +CONFIG_ATA_PIIX=y
- +# CONFIG_SATA_HIGHBANK is not set
- +CONFIG_ATA_ACPI=y
- +CONFIG_BLK_DEV_SX8=m
- +CONFIG_PDC_ADMA=m
- +CONFIG_SATA_AHCI=y
- +CONFIG_SATA_INIC162X=m
- +CONFIG_SATA_MV=m
- +CONFIG_SATA_NV=m
- +CONFIG_SATA_PMP=y
- +CONFIG_SATA_PROMISE=m
- +CONFIG_SATA_QSTOR=m
- +CONFIG_SATA_RCAR=m
- +CONFIG_SATA_SIL=m
- +CONFIG_SATA_SIL24=m
- +CONFIG_SATA_SIS=m
- +CONFIG_SATA_SVW=m
- +CONFIG_SATA_SX4=m
- +CONFIG_SATA_ULI=m
- +CONFIG_SATA_VIA=m
- +CONFIG_SATA_VITESSE=m
- +# CONFIG_SATA_ZPODD is not set
- +CONFIG_SATA_ACARD_AHCI=m
- +
- +# CONFIG_PATA_LEGACY is not set
- +CONFIG_PATA_ACPI=m
- +CONFIG_PATA_ALI=m
- +CONFIG_PATA_AMD=m
- +CONFIG_PATA_ARASAN_CF=m
- +CONFIG_PATA_ARTOP=m
- +CONFIG_PATA_ATIIXP=m
- +CONFIG_PATA_CMD640_PCI=m
- +CONFIG_PATA_CMD64X=m
- +CONFIG_PATA_CS5520=m
- +CONFIG_PATA_CS5530=m
- +CONFIG_PATA_CS5535=m
- +CONFIG_PATA_CS5536=m
- +CONFIG_PATA_CYPRESS=m
- +CONFIG_PATA_EFAR=m
- +CONFIG_ATA_GENERIC=m
- +CONFIG_PATA_HPT366=m
- +CONFIG_PATA_HPT37X=m
- +CONFIG_PATA_HPT3X2N=m
- +CONFIG_PATA_HPT3X3=m
- +# CONFIG_PATA_HPT3X3_DMA is not set
- +CONFIG_PATA_IT821X=m
- +CONFIG_PATA_IT8213=m
- +CONFIG_PATA_JMICRON=m
- +CONFIG_PATA_NINJA32=m
- +CONFIG_PATA_MARVELL=m
- +CONFIG_PATA_MPIIX=m
- +CONFIG_PATA_NETCELL=m
- +CONFIG_PATA_NS87410=m
- +CONFIG_PATA_NS87415=m
- +CONFIG_PATA_OLDPIIX=m
- +CONFIG_PATA_OPTI=m
- +CONFIG_PATA_OPTIDMA=m
- +CONFIG_PATA_PCMCIA=m
- +CONFIG_PATA_PDC_OLD=m
- +# CONFIG_PATA_RADISYS is not set
- +CONFIG_PATA_RDC=m
- +# CONFIG_PATA_RZ1000 is not set
- +# CONFIG_PATA_SC1200 is not set
- +CONFIG_PATA_SERVERWORKS=m
- +CONFIG_PATA_PDC2027X=m
- +CONFIG_PATA_SCH=m
- +CONFIG_PATA_SIL680=m
- +CONFIG_PATA_SIS=m
- +CONFIG_PATA_TOSHIBA=m
- +CONFIG_PATA_TRIFLEX=m
- +CONFIG_PATA_VIA=m
- +CONFIG_PATA_WINBOND=m
- +CONFIG_PATA_ATP867X=m
- +
- +
- +#
- +# Multi-device support (RAID and LVM)
- +#
- +CONFIG_MD=y
- +CONFIG_BLK_DEV_MD=y
- +CONFIG_MD_AUTODETECT=y
- +CONFIG_MD_FAULTY=m
- +CONFIG_MD_LINEAR=m
- +CONFIG_MD_MULTIPATH=m
- +CONFIG_MD_RAID0=m
- +CONFIG_MD_RAID1=m
- +CONFIG_MD_RAID10=m
- +CONFIG_MD_RAID456=m
- +
- +CONFIG_BCACHE=m
- +# CONFIG_BCACHE_DEBUG is not set
- +# CONFIG_BCACHE_EDEBUG is not set
- +# CONFIG_BCACHE_CLOSURES_DEBUG is not set
- +
- +# CONFIG_MULTICORE_RAID456 is not set
- +CONFIG_ASYNC_RAID6_TEST=m
- +CONFIG_BLK_DEV_DM=y
- +CONFIG_DM_CRYPT=m
- +CONFIG_DM_DEBUG=y
- +CONFIG_DM_DELAY=m
- +CONFIG_DM_MIRROR=y
- +CONFIG_DM_MULTIPATH=m
- +CONFIG_DM_SNAPSHOT=y
- +CONFIG_DM_THIN_PROVISIONING=m
- +CONFIG_DM_CACHE=m
- +CONFIG_DM_CACHE_MQ=m
- +CONFIG_DM_CACHE_CLEANER=m
- +# CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set
- +# CONFIG_DM_DEBUG_SPACE_MAPS is not set
- +CONFIG_DM_UEVENT=y
- +CONFIG_DM_ZERO=y
- +CONFIG_DM_LOG_USERSPACE=m
- +CONFIG_DM_MULTIPATH_QL=m
- +CONFIG_DM_MULTIPATH_ST=m
- +CONFIG_DM_RAID=m
- +CONFIG_DM_FLAKEY=m
- +CONFIG_DM_VERITY=m
- +CONFIG_DM_SWITCH=m
- +
- +#
- +# Fusion MPT device support
- +#
- +CONFIG_FUSION=y
- +CONFIG_FUSION_SPI=m
- +CONFIG_FUSION_FC=m
- +CONFIG_FUSION_MAX_SGE=40
- +CONFIG_FUSION_CTL=m
- +CONFIG_FUSION_LAN=m
- +CONFIG_FUSION_SAS=m
- +CONFIG_FUSION_LOGGING=y
- +
- +#
- +# IEEE 1394 (FireWire) support (JUJU alternative stack)
- +#
- +CONFIG_FIREWIRE=m
- +CONFIG_FIREWIRE_OHCI=m
- +CONFIG_FIREWIRE_SBP2=m
- +CONFIG_FIREWIRE_NET=m
- +CONFIG_FIREWIRE_OHCI_DEBUG=y
- +CONFIG_FIREWIRE_NOSY=m
- +# CONFIG_FIREWIRE_SERIAL is not set
- +# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set
- +
- +#
- +# IEEE 1394 (FireWire) support
- +#
- +
- +#
- +# I2O device support
- +#
- +# CONFIG_I2O is not set
- +# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set
- +
- +#
- +# Virtualization support drivers
- +#
- +# CONFIG_VIRT_DRIVERS is not set
- +
- +# Networking support
- +#
- +
- +CONFIG_NET_DMA=y
- +
- +CONFIG_NETLINK_MMAP=y
- +CONFIG_NETLINK_DIAG=m
- +
- +CONFIG_TCP_CONG_ADVANCED=y
- +CONFIG_TCP_CONG_BIC=m
- +CONFIG_TCP_CONG_CUBIC=y
- +CONFIG_TCP_CONG_HTCP=m
- +CONFIG_TCP_CONG_HSTCP=m
- +CONFIG_TCP_CONG_HYBLA=m
- +CONFIG_TCP_CONG_ILLINOIS=m
- +CONFIG_TCP_CONG_LP=m
- +CONFIG_TCP_CONG_SCALABLE=m
- +CONFIG_TCP_CONG_VEGAS=m
- +CONFIG_TCP_CONG_VENO=m
- +CONFIG_TCP_CONG_WESTWOOD=m
- +CONFIG_TCP_CONG_YEAH=m
- +
- +CONFIG_TCP_MD5SIG=y
- +
- +#
- +# Networking options
- +#
- +CONFIG_PACKET_DIAG=m
- +CONFIG_UNIX_DIAG=m
- +CONFIG_NET_KEY=m
- +CONFIG_NET_KEY_MIGRATE=y
- +CONFIG_INET_TUNNEL=m
- +CONFIG_INET_DIAG=m
- +CONFIG_INET_UDP_DIAG=m
- +CONFIG_IP_MULTICAST=y
- +CONFIG_IP_ADVANCED_ROUTER=y
- +CONFIG_IP_FIB_TRIE_STATS=y
- +CONFIG_IP_MULTIPLE_TABLES=y
- +CONFIG_IP_ROUTE_MULTIPATH=y
- +CONFIG_IP_ROUTE_VERBOSE=y
- +CONFIG_IP_NF_SECURITY=m
- +CONFIG_NET_IPIP=m
- +CONFIG_NET_IPGRE_DEMUX=m
- +CONFIG_NET_IPGRE=m
- +CONFIG_NET_IPGRE_BROADCAST=y
- +CONFIG_IP_MROUTE=y
- +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
- +CONFIG_IP_PIMSM_V1=y
- +CONFIG_IP_PIMSM_V2=y
- +CONFIG_ARPD=y
- +CONFIG_SYN_COOKIES=y
- +CONFIG_NET_IPVTI=m
- +CONFIG_INET_AH=m
- +CONFIG_INET_ESP=m
- +CONFIG_INET_IPCOMP=m
- +CONFIG_NETCONSOLE=m
- +CONFIG_NETCONSOLE_DYNAMIC=y
- +CONFIG_NETPOLL_TRAP=y
- +CONFIG_NET_POLL_CONTROLLER=y
- +
- +#
- +# IP: Virtual Server Configuration
- +#
- +CONFIG_IP_VS=m
- +# CONFIG_IP_VS_DEBUG is not set
- +CONFIG_IP_VS_TAB_BITS=12
- +CONFIG_IP_VS_PROTO_TCP=y
- +CONFIG_IP_VS_PROTO_UDP=y
- +CONFIG_IP_VS_PROTO_ESP=y
- +CONFIG_IP_VS_PROTO_AH=y
- +CONFIG_IP_VS_PROTO_SCTP=y
- +CONFIG_IP_VS_IPV6=y
- +CONFIG_IP_VS_RR=m
- +CONFIG_IP_VS_WRR=m
- +CONFIG_IP_VS_LC=m
- +CONFIG_IP_VS_WLC=m
- +CONFIG_IP_VS_LBLC=m
- +CONFIG_IP_VS_LBLCR=m
- +CONFIG_IP_VS_DH=m
- +CONFIG_IP_VS_SH=m
- +CONFIG_IP_VS_SED=m
- +CONFIG_IP_VS_NQ=m
- +
- +#
- +# IPVS SH scheduler
- +#
- +CONFIG_IP_VS_SH_TAB_BITS=8
- +
- +CONFIG_IP_VS_FTP=m
- +CONFIG_IP_VS_PE_SIP=m
- +
- +CONFIG_IPV6_PRIVACY=y
- +CONFIG_IPV6_ROUTER_PREF=y
- +CONFIG_IPV6_ROUTE_INFO=y
- +CONFIG_IPV6_OPTIMISTIC_DAD=y
- +CONFIG_INET6_AH=m
- +CONFIG_INET6_ESP=m
- +CONFIG_INET6_IPCOMP=m
- +CONFIG_IPV6_MIP6=y
- +CONFIG_IPV6_VTI=m
- +CONFIG_IPV6_SIT=m
- +CONFIG_IPV6_SIT_6RD=y
- +CONFIG_IPV6_TUNNEL=m
- +# CONFIG_IPV6_GRE is not set
- +CONFIG_IPV6_SUBTREES=y
- +CONFIG_IPV6_MULTIPLE_TABLES=y
- +CONFIG_IPV6_MROUTE=y
- +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
- +CONFIG_IPV6_PIMSM_V2=y
- +
- +CONFIG_RDS=m
- +# CONFIG_RDS_DEBUG is not set
- +CONFIG_RDS_RDMA=m
- +CONFIG_RDS_TCP=m
- +
- +CONFIG_NET_9P=m
- +CONFIG_NET_9P_VIRTIO=m
- +# CONFIG_NET_9P_DEBUG is not set
- +CONFIG_NET_9P_RDMA=m
- +
- +# CONFIG_DECNET is not set
- +CONFIG_BRIDGE=m
- +CONFIG_BRIDGE_IGMP_SNOOPING=y
- +CONFIG_BRIDGE_VLAN_FILTERING=y
- +
- +# PHY timestamping adds overhead
- +CONFIG_NETWORK_PHY_TIMESTAMPING=y
- +
- +CONFIG_NETFILTER_ADVANCED=y
- +CONFIG_NF_CONNTRACK=m
- +CONFIG_NETFILTER_NETLINK=m
- +CONFIG_NETFILTER_NETLINK_ACCT=m
- +CONFIG_NETFILTER_NETLINK_QUEUE=m
- +CONFIG_NETFILTER_NETLINK_QUEUE_CT=y
- +CONFIG_NETFILTER_NETLINK_LOG=m
- +CONFIG_NETFILTER_TPROXY=m
- +CONFIG_NETFILTER_XTABLES=y
- +CONFIG_NETFILTER_XT_SET=m
- +CONFIG_NETFILTER_XT_MARK=m
- +CONFIG_NETFILTER_XT_CONNMARK=m
- +
- +CONFIG_NETFILTER_XT_TARGET_AUDIT=m
- +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
- +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
- +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
- +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
- +CONFIG_NETFILTER_XT_TARGET_CT=m
- +CONFIG_NETFILTER_XT_TARGET_DSCP=m
- +CONFIG_NETFILTER_XT_TARGET_HMARK=m
- +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
- +CONFIG_NETFILTER_XT_TARGET_LED=m
- +CONFIG_NETFILTER_XT_TARGET_LOG=m
- +CONFIG_NETFILTER_XT_TARGET_MARK=m
- +CONFIG_NETFILTER_XT_TARGET_NFLOG=m
- +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
- +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
- +CONFIG_NETFILTER_XT_TARGET_RATEEST=m
- +CONFIG_NETFILTER_XT_TARGET_SECMARK=m
- +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
- +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
- +CONFIG_NETFILTER_XT_TARGET_TRACE=m
- +CONFIG_NETFILTER_XT_TARGET_TEE=m
- +CONFIG_NETFILTER_XT_TARGET_TPROXY=m
- +
- +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
- +CONFIG_NETFILTER_XT_MATCH_BPF=m
- +CONFIG_NETFILTER_XT_MATCH_CGROUP=m
- +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
- +CONFIG_NETFILTER_XT_MATCH_COMMENT=m
- +CONFIG_NETFILTER_XT_MATCH_CPU=m
- +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
- +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
- +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
- +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
- +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
- +CONFIG_NETFILTER_XT_MATCH_DCCP=m
- +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
- +CONFIG_NETFILTER_XT_MATCH_DSCP=m
- +CONFIG_NETFILTER_XT_MATCH_ECN=m
- +CONFIG_NETFILTER_XT_MATCH_ESP=m
- +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
- +CONFIG_NETFILTER_XT_MATCH_HELPER=m
- +CONFIG_NETFILTER_XT_MATCH_HL=m
- +CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
- +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
- +CONFIG_NETFILTER_XT_MATCH_IPVS=m
- +CONFIG_NETFILTER_XT_MATCH_L2TP=m
- +CONFIG_NETFILTER_XT_MATCH_LENGTH=m
- +CONFIG_NETFILTER_XT_MATCH_LIMIT=m
- +CONFIG_NETFILTER_XT_MATCH_MAC=m
- +CONFIG_NETFILTER_XT_MATCH_MARK=m
- +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
- +CONFIG_NETFILTER_XT_MATCH_NFACCT=m
- +CONFIG_NETFILTER_XT_MATCH_OSF=m
- +CONFIG_NETFILTER_XT_MATCH_OWNER=m
- +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
- +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
- +CONFIG_NETFILTER_XT_MATCH_POLICY=m
- +CONFIG_NETFILTER_XT_MATCH_QUOTA=m
- +CONFIG_NETFILTER_XT_MATCH_RATEEST=m
- +CONFIG_NETFILTER_XT_MATCH_REALM=m
- +CONFIG_NETFILTER_XT_MATCH_RECENT=m
- +CONFIG_NETFILTER_XT_MATCH_SCTP=m
- +CONFIG_NETFILTER_XT_MATCH_SOCKET=m
- +CONFIG_NETFILTER_XT_MATCH_STATE=y
- +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
- +CONFIG_NETFILTER_XT_MATCH_STRING=m
- +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
- +CONFIG_NETFILTER_XT_MATCH_TIME=m
- +CONFIG_NETFILTER_XT_MATCH_U32=m
- +
- +# CONFIG_NETFILTER_DEBUG is not set
- +CONFIG_BRIDGE_NETFILTER=y
- +
- +#
- +# IP: Netfilter Configuration
- +#
- +
- +CONFIG_NF_CONNTRACK_MARK=y
- +CONFIG_NF_CONNTRACK_SECMARK=y
- +CONFIG_NF_CONNTRACK_EVENTS=y
- +CONFIG_NF_CONNTRACK_ZONES=y
- +CONFIG_NF_CONNTRACK_PROCFS=y # check if contrack(8) in f17 supports netlink
- +# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
- +CONFIG_NF_CONNTRACK_AMANDA=m
- +CONFIG_NF_CONNTRACK_FTP=m
- +CONFIG_NF_CONNTRACK_H323=m
- +CONFIG_NF_CONNTRACK_IRC=m
- +CONFIG_NF_CONNTRACK_NETBIOS_NS=m
- +CONFIG_NF_CONNTRACK_PPTP=m
- +CONFIG_NF_CONNTRACK_SANE=m
- +CONFIG_NF_CONNTRACK_SIP=m
- +CONFIG_NF_CONNTRACK_TFTP=m
- +CONFIG_NF_CONNTRACK_IPV4=y
- +CONFIG_NF_CONNTRACK_IPV6=y
- +# CONFIG_NF_CONNTRACK_TIMEOUT is not set
- +CONFIG_NF_CONNTRACK_TIMESTAMP=y
- +CONFIG_NF_CONNTRACK_SNMP=m
- +CONFIG_NF_NAT=m
- +CONFIG_NF_NAT_SNMP_BASIC=m
- +CONFIG_NF_CT_PROTO_DCCP=m
- +CONFIG_NF_CT_PROTO_SCTP=m
- +CONFIG_NF_CT_NETLINK=m
- +# CONFIG_NF_CT_NETLINK_TIMEOUT is not set
- +CONFIG_NF_CT_NETLINK_HELPER=m
- +CONFIG_NF_CT_PROTO_UDPLITE=m
- +
- +CONFIG_IP_NF_MATCH_AH=m
- +CONFIG_IP_NF_MATCH_ECN=m
- +CONFIG_IP_NF_MATCH_RPFILTER=m
- +CONFIG_IP_NF_MATCH_TTL=m
- +CONFIG_IP_NF_TARGET_CLUSTERIP=m
- +CONFIG_IP_NF_TARGET_REDIRECT=m
- +CONFIG_IP_NF_TARGET_NETMAP=m
- +CONFIG_IP_NF_TARGET_ECN=m
- +CONFIG_IP_NF_TARGET_LOG=m
- +CONFIG_IP_NF_TARGET_ULOG=m
- +CONFIG_IP_NF_TARGET_REJECT=y
- +CONFIG_IP_NF_TARGET_SYNPROXY=m
- +CONFIG_IP_NF_TARGET_TTL=m
- +CONFIG_NF_NAT_IPV4=m
- +CONFIG_IP_NF_TARGET_MASQUERADE=m
- +CONFIG_IP_NF_MANGLE=m
- +CONFIG_IP_NF_ARPTABLES=m
- +CONFIG_IP_NF_ARPFILTER=m
- +CONFIG_IP_NF_ARP_MANGLE=m
- +CONFIG_IP_NF_QUEUE=m
- +CONFIG_IP_NF_RAW=m
- +
- +CONFIG_IP_NF_IPTABLES=y
- +CONFIG_IP_NF_FILTER=y
- +
- +#
- +# IPv6: Netfilter Configuration
- +#
- +CONFIG_IP6_NF_FILTER=m
- +CONFIG_IP6_NF_IPTABLES=m
- +CONFIG_IP6_NF_MANGLE=m
- +CONFIG_IP6_NF_MATCH_AH=m
- +CONFIG_IP6_NF_MATCH_EUI64=m
- +CONFIG_IP6_NF_MATCH_FRAG=m
- +CONFIG_IP6_NF_MATCH_HL=m
- +CONFIG_IP6_NF_MATCH_IPV6HEADER=m
- +CONFIG_IP6_NF_MATCH_MH=m
- +CONFIG_IP6_NF_MATCH_RPFILTER=m
- +CONFIG_IP6_NF_MATCH_OPTS=m
- +CONFIG_IP6_NF_MATCH_RT=m
- +CONFIG_IP6_NF_QUEUE=m
- +CONFIG_IP6_NF_RAW=m
- +CONFIG_IP6_NF_SECURITY=m
- +CONFIG_IP6_NF_TARGET_LOG=m
- +CONFIG_IP6_NF_TARGET_REJECT=m
- +CONFIG_IP6_NF_TARGET_SYNPROXY=m
- +CONFIG_IP6_NF_TARGET_HL=m
- +CONFIG_NF_NAT_IPV6=m
- +CONFIG_IP6_NF_TARGET_MASQUERADE=m
- +# CONFIG_IP6_NF_TARGET_NPT is not set
- +
- +# nf_tables support
- +CONFIG_NF_TABLES=m
- +CONFIG_NF_TABLES_INET=m
- +CONFIG_NFT_EXTHDR=m
- +CONFIG_NFT_META=m
- +CONFIG_NFT_CT=m
- +CONFIG_NFT_RBTREE=m
- +CONFIG_NFT_HASH=m
- +CONFIG_NFT_COUNTER=m
- +CONFIG_NFT_LOG=m
- +CONFIG_NFT_LIMIT=m
- +CONFIG_NFT_NAT=m
- +CONFIG_NFT_QUEUE=m
- +CONFIG_NFT_REJECT=m
- +CONFIG_NFT_COMPAT=m
- +
- +CONFIG_NF_TABLES_IPV4=m
- +CONFIG_NFT_REJECT_IPV4=m
- +CONFIG_NFT_CHAIN_ROUTE_IPV4=m
- +CONFIG_NFT_CHAIN_NAT_IPV4=m
- +CONFIG_NF_TABLES_ARP=m
- +
- +CONFIG_NF_TABLES_IPV6=m
- +CONFIG_NFT_CHAIN_ROUTE_IPV6=m
- +CONFIG_NFT_CHAIN_NAT_IPV6=m
- +
- +CONFIG_NF_TABLES_BRIDGE=m
- +#
- +# Bridge: Netfilter Configuration
- +#
- +CONFIG_BRIDGE_NF_EBTABLES=m
- +CONFIG_BRIDGE_EBT_802_3=m
- +CONFIG_BRIDGE_EBT_AMONG=m
- +CONFIG_BRIDGE_EBT_ARP=m
- +CONFIG_BRIDGE_EBT_ARPREPLY=m
- +CONFIG_BRIDGE_EBT_BROUTE=m
- +CONFIG_BRIDGE_EBT_DNAT=m
- +CONFIG_BRIDGE_EBT_IP=m
- +CONFIG_BRIDGE_EBT_IP6=m
- +CONFIG_BRIDGE_EBT_LIMIT=m
- +CONFIG_BRIDGE_EBT_LOG=m
- +CONFIG_BRIDGE_EBT_MARK=m
- +CONFIG_BRIDGE_EBT_MARK_T=m
- +CONFIG_BRIDGE_EBT_NFLOG=m
- +CONFIG_BRIDGE_EBT_PKTTYPE=m
- +CONFIG_BRIDGE_EBT_REDIRECT=m
- +CONFIG_BRIDGE_EBT_SNAT=m
- +CONFIG_BRIDGE_EBT_STP=m
- +CONFIG_BRIDGE_EBT_T_FILTER=m
- +CONFIG_BRIDGE_EBT_T_NAT=m
- +CONFIG_BRIDGE_EBT_ULOG=m
- +CONFIG_BRIDGE_EBT_VLAN=m
- +CONFIG_XFRM=y
- +CONFIG_XFRM_MIGRATE=y
- +CONFIG_XFRM_SUB_POLICY=y
- +CONFIG_XFRM_STATISTICS=y
- +CONFIG_XFRM_USER=y
- +CONFIG_INET6_XFRM_MODE_TRANSPORT=m
- +CONFIG_INET6_XFRM_MODE_TUNNEL=m
- +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
- +CONFIG_INET6_XFRM_MODE_BEET=m
- +
- +CONFIG_IP_SET=m
- +CONFIG_IP_SET_MAX=256
- +CONFIG_IP_SET_BITMAP_IP=m
- +CONFIG_IP_SET_BITMAP_IPMAC=m
- +CONFIG_IP_SET_BITMAP_PORT=m
- +CONFIG_IP_SET_HASH_IP=m
- +CONFIG_IP_SET_HASH_IPPORT=m
- +CONFIG_IP_SET_HASH_IPPORTIP=m
- +CONFIG_IP_SET_HASH_IPPORTNET=m
- +CONFIG_IP_SET_HASH_NETPORTNET=m
- +CONFIG_IP_SET_HASH_NET=m
- +CONFIG_IP_SET_HASH_NETNET=m
- +CONFIG_IP_SET_HASH_NETPORT=m
- +CONFIG_IP_SET_HASH_NETIFACE=m
- +CONFIG_IP_SET_LIST_SET=m
- +
- +#
- +# SCTP Configuration (EXPERIMENTAL)
- +#
- +CONFIG_IP_SCTP=m
- +CONFIG_NET_SCTPPROBE=m
- +# CONFIG_SCTP_DBG_MSG is not set
- +# CONFIG_SCTP_DBG_OBJCNT is not set
- +CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1=y
- +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5 is not set
- +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set
- +CONFIG_SCTP_COOKIE_HMAC_MD5=y
- +CONFIG_SCTP_COOKIE_HMAC_SHA1=y
- +CONFIG_ATM=m
- +CONFIG_VLAN_8021Q_GVRP=y
- +CONFIG_VLAN_8021Q_MVRP=y
- +CONFIG_LLC=m
- +# CONFIG_LLC2 is not set
- +CONFIG_IPX=m
- +# CONFIG_IPX_INTERN is not set
- +CONFIG_ATALK=m
- +CONFIG_DEV_APPLETALK=m
- +CONFIG_IPDDP=m
- +CONFIG_IPDDP_ENCAP=y
- +CONFIG_IPDDP_DECAP=y
- +# CONFIG_X25 is not set
- +# CONFIG_LAPB is not set
- +# CONFIG_ECONET is not set
- +CONFIG_WAN_ROUTER=m
- +CONFIG_IP_DCCP=m
- +CONFIG_IP_DCCP_CCID2=m
- +# CONFIG_IP_DCCP_CCID2_DEBUG is not set
- +CONFIG_IP_DCCP_CCID3=y
- +# CONFIG_IP_DCCP_CCID3_DEBUG is not set
- +# CONFIG_IP_DCCP_DEBUG is not set
- +# CONFIG_NET_DCCPPROBE is not set
- +
- +#
- +# TIPC Configuration (EXPERIMENTAL)
- +#
- +CONFIG_TIPC=m
- +CONFIG_TIPC_PORTS=8192
- +# CONFIG_TIPC_MEDIA_IB is not set
- +# CONFIG_TIPC_ADVANCED is not set
- +# CONFIG_TIPC_DEBUG is not set
- +
- +CONFIG_NETLABEL=y
- +
- +#
- +# QoS and/or fair queueing
- +#
- +CONFIG_NET_SCHED=y
- +CONFIG_NET_SCH_CBQ=m
- +CONFIG_NET_SCH_DSMARK=m
- +CONFIG_NET_SCH_DRR=m
- +CONFIG_NET_SCH_GRED=m
- +CONFIG_NET_SCH_HFSC=m
- +CONFIG_NET_SCH_HTB=m
- +CONFIG_NET_SCH_INGRESS=m
- +CONFIG_NET_SCH_NETEM=m
- +CONFIG_NET_SCH_PRIO=m
- +CONFIG_NET_SCH_RED=m
- +CONFIG_NET_SCH_SFQ=m
- +CONFIG_NET_SCH_TBF=m
- +CONFIG_NET_SCH_TEQL=m
- +CONFIG_NET_SCH_SFB=m
- +CONFIG_NET_SCH_MQPRIO=m
- +CONFIG_NET_SCH_MULTIQ=m
- +CONFIG_NET_SCH_CHOKE=m
- +CONFIG_NET_SCH_QFQ=m
- +CONFIG_NET_SCH_CODEL=m
- +CONFIG_NET_SCH_FQ_CODEL=m
- +CONFIG_NET_SCH_FQ=m
- +CONFIG_NET_SCH_HHF=m
- +CONFIG_NET_SCH_PIE=m
- +CONFIG_NET_SCH_PLUG=m
- +CONFIG_NET_CLS=y
- +CONFIG_NET_CLS_ACT=y
- +CONFIG_NET_CLS_BASIC=m
- +CONFIG_NET_CLS_CGROUP=y
- +CONFIG_NET_CLS_BPF=m
- +CONFIG_NET_CLS_FLOW=m
- +CONFIG_NET_CLS_FW=m
- +CONFIG_NET_CLS_IND=y
- +CONFIG_NET_CLS_ROUTE4=m
- +CONFIG_NET_CLS_ROUTE=y
- +CONFIG_NET_CLS_RSVP=m
- +CONFIG_NET_CLS_RSVP6=m
- +CONFIG_NET_CLS_TCINDEX=m
- +CONFIG_NET_CLS_U32=m
- +CONFIG_CLS_U32_MARK=y
- +CONFIG_CLS_U32_PERF=y
- +CONFIG_NET_EMATCH=y
- +CONFIG_NET_EMATCH_CMP=m
- +CONFIG_NET_EMATCH_META=m
- +CONFIG_NET_EMATCH_NBYTE=m
- +CONFIG_NET_EMATCH_STACK=32
- +CONFIG_NET_EMATCH_TEXT=m
- +CONFIG_NET_EMATCH_IPSET=m
- +CONFIG_NET_EMATCH_U32=m
- +
- +CONFIG_NET_ACT_CSUM=m
- +CONFIG_NET_ACT_GACT=m
- +CONFIG_GACT_PROB=y
- +CONFIG_NET_ACT_IPT=m
- +CONFIG_NET_ACT_MIRRED=m
- +CONFIG_NET_ACT_NAT=m
- +CONFIG_NET_ACT_PEDIT=m
- +CONFIG_NET_ACT_POLICE=m
- +CONFIG_NET_ACT_SIMP=m
- +CONFIG_NET_ACT_SKBEDIT=m
- +
- +CONFIG_DCB=y
- +CONFIG_DNS_RESOLVER=m
- +CONFIG_BATMAN_ADV=m
- +CONFIG_BATMAN_ADV_BLA=y
- +CONFIG_BATMAN_ADV_DAT=y
- +CONFIG_BATMAN_ADV_NC=y
- +
- +# CONFIG_BATMAN_ADV_DEBUG is not set
- +CONFIG_OPENVSWITCH=m
- +CONFIG_OPENVSWITCH_GRE=y
- +CONFIG_OPENVSWITCH_VXLAN=y
- +CONFIG_VSOCKETS=m
- +
- +
- +#
- +# Network testing
- +#
- +CONFIG_NET_PKTGEN=m
- +# CONFIG_NET_TCPPROBE is not set
- +CONFIG_NET_DROP_MONITOR=y
- +
- +# disable later --kyle
- +
- +#
- +# ARCnet devices
- +#
- +# CONFIG_ARCNET is not set
- +CONFIG_IFB=m
- +CONFIG_NET_TEAM=m
- +CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
- +CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
- +CONFIG_NET_TEAM_MODE_LOADBALANCE=m
- +CONFIG_NET_TEAM_MODE_BROADCAST=m
- +CONFIG_NET_TEAM_MODE_RANDOM=m
- +CONFIG_DUMMY=m
- +CONFIG_BONDING=m
- +CONFIG_MACVLAN=m
- +CONFIG_MACVTAP=m
- +CONFIG_VXLAN=m
- +CONFIG_EQUALIZER=m
- +CONFIG_TUN=m
- +CONFIG_VETH=m
- +CONFIG_NLMON=m
- +
- +#
- +# ATM
- +#
- +CONFIG_ATM_DRIVERS=y
- +# CONFIG_ATM_DUMMY is not set
- +CONFIG_ATM_CLIP=m
- +CONFIG_ATM_LANE=m
- +CONFIG_ATM_BR2684=m
- +CONFIG_NET_SCH_ATM=m
- +CONFIG_ATM_TCP=m
- +# CONFIG_ATM_LANAI is not set
- +CONFIG_ATM_ENI=m
- +CONFIG_ATM_FIRESTREAM=m
- +# CONFIG_ATM_ZATM is not set
- +# CONFIG_ATM_IDT77252 is not set
- +# CONFIG_ATM_AMBASSADOR is not set
- +# CONFIG_ATM_HORIZON is not set
- +# CONFIG_ATM_FORE200E is not set
- +# CONFIG_ATM_FORE200E_USE_TASKLET is not set
- +CONFIG_ATM_FORE200E_TX_RETRY=16
- +CONFIG_ATM_FORE200E_DEBUG=0
- +
- +CONFIG_ATM_HE=m
- +CONFIG_PPTP=m
- +CONFIG_PPPOATM=m
- +CONFIG_PPPOL2TP=m
- +CONFIG_ATM_NICSTAR=m
- +# CONFIG_ATM_IA is not set
- +# CONFIG_ATM_CLIP_NO_ICMP is not set
- +# CONFIG_ATM_MPOA is not set
- +# CONFIG_ATM_BR2684_IPFILTER is not set
- +# CONFIG_ATM_ENI_DEBUG is not set
- +# CONFIG_ATM_ENI_TUNE_BURST is not set
- +# CONFIG_ATM_ZATM_DEBUG is not set
- +# CONFIG_ATM_IDT77252_DEBUG is not set
- +# CONFIG_ATM_IDT77252_RCV_ALL is not set
- +# CONFIG_ATM_AMBASSADOR_DEBUG is not set
- +# CONFIG_ATM_HORIZON_DEBUG is not set
- +# CONFIG_ATM_HE_USE_SUNI is not set
- +# CONFIG_ATM_NICSTAR_USE_SUNI is not set
- +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
- +# CONFIG_ATM_IA_DEBUG is not set
- +CONFIG_ATM_SOLOS=m
- +
- +CONFIG_L2TP=m
- +CONFIG_L2TP_V3=y
- +CONFIG_L2TP_IP=m
- +CONFIG_L2TP_ETH=m
- +
- +# CONFIG_CAIF is not set
- +
- +CONFIG_RFKILL=m
- +CONFIG_RFKILL_GPIO=m
- +CONFIG_RFKILL_INPUT=y
- +
- +
- +#
- +# Ethernet (10 or 100Mbit)
- +#
- +
- +CONFIG_NET_VENDOR_ADAPTEC=y
- +CONFIG_ADAPTEC_STARFIRE=m
- +
- +CONFIG_NET_VENDOR_ALTEON=y
- +CONFIG_ACENIC=m
- +# CONFIG_ACENIC_OMIT_TIGON_I is not set
- +
- +CONFIG_NET_VENDOR_AMD=y
- +CONFIG_PCNET32=m
- +CONFIG_AMD8111_ETH=m
- +CONFIG_PCMCIA_NMCLAN=m
- +
- +CONFIG_NET_VENDOR_ARC=y
- +CONFIG_ARC_EMAC=m
- +
- +CONFIG_NET_VENDOR_ATHEROS=y
- +CONFIG_ALX=m
- +CONFIG_ATL2=m
- +CONFIG_ATL1=m
- +CONFIG_ATL1C=m
- +CONFIG_ATL1E=m
- +CONFIG_NET_CADENCE=y
- +CONFIG_ARM_AT91_ETHER=m
- +CONFIG_MACB=m
- +
- +CONFIG_NET_VENDOR_BROCADE=y
- +CONFIG_BNA=m
- +CONFIG_NET_CALXEDA_XGMAC=m
- +
- +CONFIG_NET_VENDOR_CHELSIO=y
- +CONFIG_CHELSIO_T1=m
- +CONFIG_CHELSIO_T1_1G=y
- +CONFIG_CHELSIO_T3=m
- +CONFIG_CHELSIO_T4=m
- +CONFIG_CHELSIO_T4VF=m
- +
- +CONFIG_NET_VENDOR_CISCO=y
- +CONFIG_ENIC=m
- +
- +CONFIG_NET_VENDOR_DEC=y
- +#
- +# Tulip family network device support
- +#
- +CONFIG_NET_TULIP=y
- +CONFIG_DE2104X=m
- +CONFIG_DE2104X_DSL=0
- +CONFIG_TULIP=m
- +# CONFIG_TULIP_NAPI is not set
- +# CONFIG_TULIP_MWI is not set
- +CONFIG_TULIP_MMIO=y
- +# CONFIG_NI5010 is not set
- +CONFIG_DE4X5=m
- +CONFIG_WINBOND_840=m
- +CONFIG_DM9102=m
- +CONFIG_PCMCIA_XIRCOM=m
- +CONFIG_ULI526X=m
- +
- +CONFIG_NET_VENDOR_DLINK=y
- +CONFIG_DE600=m
- +CONFIG_DE620=m
- +CONFIG_DL2K=m
- +CONFIG_SUNDANCE=m
- +# CONFIG_SUNDANCE_MMIO is not set
- +
- +CONFIG_NET_VENDOR_EMULEX=y
- +CONFIG_BE2NET=m
- +
- +CONFIG_NET_VENDOR_EXAR=y
- +CONFIG_S2IO=m
- +CONFIG_VXGE=m
- +# CONFIG_VXGE_DEBUG_TRACE_ALL is not set
- +
- +# CONFIG_NET_VENDOR_FARADAY is not set
- +# CONFIG_NET_VENDOR_FUJITSU is not set
- +# CONFIG_NET_VENDOR_HP is not set
- +CONFIG_NET_VENDOR_INTEL=y
- +CONFIG_E100=m
- +CONFIG_E1000=m
- +CONFIG_E1000E=m
- +CONFIG_IGB=m
- +CONFIG_IGB_HWMON=y
- +CONFIG_IGB_DCA=y
- +CONFIG_IGB_PTP=y
- +CONFIG_IGBVF=m
- +CONFIG_IXGB=m
- +CONFIG_IXGBEVF=m
- +CONFIG_IXGBE=m
- +CONFIG_IXGBE_DCA=y
- +CONFIG_IXGBE_DCB=y
- +CONFIG_IXGBE_HWMON=y
- +CONFIG_IXGBE_PTP=y
- +CONFIG_I40E=m
- +# CONFIG_I40E_VXLAN is not set
- +# CONFIG_I40E_DCB is not set
- +# CONFIG_I40EVF is not set
- +
- +
- +# CONFIG_NET_VENDOR_I825XX is not set
- +CONFIG_NET_VENDOR_MARVELL=y
- +CONFIG_MVMDIO=m
- +CONFIG_SKGE=m
- +# CONFIG_SKGE_DEBUG is not set
- +CONFIG_SKGE_GENESIS=y
- +CONFIG_SKY2=m
- +# CONFIG_SKY2_DEBUG is not set
- +
- +CONFIG_NET_VENDOR_MICREL=y
- +CONFIG_KSZ884X_PCI=m
- +# CONFIG_KS8842 is not set
- +# CONFIG_KS8851_MLL is not set
- +
- +CONFIG_NET_VENDOR_MYRI=y
- +CONFIG_MYRI10GE=m
- +CONFIG_MYRI10GE_DCA=y
- +
- +CONFIG_NATSEMI=m
- +CONFIG_NS83820=m
- +
- +CONFIG_PCMCIA_AXNET=m
- +CONFIG_NE2K_PCI=m
- +CONFIG_NE3210=m
- +CONFIG_PCMCIA_PCNET=m
- +
- +CONFIG_NET_VENDOR_NVIDIA=y
- +CONFIG_FORCEDETH=m
- +
- +CONFIG_NET_VENDOR_OKI=y
- +# CONFIG_PCH_GBE is not set
- +# CONFIG_PCH_PTP is not set
- +
- +CONFIG_NET_PACKET_ENGINE=y
- +CONFIG_HAMACHI=m
- +CONFIG_YELLOWFIN=m
- +
- +CONFIG_NET_VENDOR_QLOGIC=y
- +CONFIG_QLA3XXX=m
- +CONFIG_QLCNIC=m
- +CONFIG_QLCNIC_SRIOV=y
- +CONFIG_QLCNIC_DCB=y
- +CONFIG_QLGE=m
- +CONFIG_NETXEN_NIC=m
- +
- +CONFIG_NET_VENDOR_REALTEK=y
- +CONFIG_ATP=m
- +CONFIG_8139CP=m
- +CONFIG_8139TOO=m
- +# CONFIG_8139TOO_PIO is not set
- +# CONFIG_8139TOO_TUNE_TWISTER is not set
- +CONFIG_8139TOO_8129=y
- +# CONFIG_8139_OLD_RX_RESET is not set
- +CONFIG_R8169=m
- +
- +
- +CONFIG_NET_VENDOR_RDC=y
- +CONFIG_R6040=m
- +
- +
- +CONFIG_NET_VENDOR_SILAN=y
- +CONFIG_SC92031=m
- +
- +CONFIG_NET_VENDOR_SIS=y
- +CONFIG_SIS900=m
- +CONFIG_SIS190=m
- +
- +CONFIG_PCMCIA_SMC91C92=m
- +CONFIG_EPIC100=m
- +CONFIG_SMSC9420=m
- +
- +# CONFIG_STMMAC_PLATFORM is not set
- +# CONFIG_STMMAC_PCI is not set
- +# CONFIG_STMMAC_DA is not set
- +# CONFIG_STMMAC_DUAL_MAC is not set
- +# CONFIG_STMMAC_TIMER is not set
- +# CONFIG_STMMAC_DEBUG_FS is not set
- +
- +CONFIG_NET_VENDOR_SUN=y
- +CONFIG_HAPPYMEAL=m
- +CONFIG_SUNGEM=m
- +CONFIG_CASSINI=m
- +CONFIG_NIU=m
- +
- +CONFIG_NET_VENDOR_TEHUTI=y
- +CONFIG_TEHUTI=m
- +
- +CONFIG_NET_VENDOR_TI=y
- +CONFIG_TLAN=m
- +
- +CONFIG_VIA_RHINE=m
- +CONFIG_VIA_RHINE_MMIO=y
- +
- +CONFIG_WIZNET_W5100=m
- +CONFIG_WIZNET_W5300=m
- +CONFIG_NET_VENDOR_XIRCOM=y
- +CONFIG_PCMCIA_XIRC2PS=m
- +
- +CONFIG_AMD_PHY=m
- +CONFIG_BROADCOM_PHY=m
- +CONFIG_BCM87XX_PHY=m
- +CONFIG_CICADA_PHY=m
- +CONFIG_DAVICOM_PHY=m
- +CONFIG_DP83640_PHY=m
- +CONFIG_FIXED_PHY=y
- +CONFIG_MDIO_BITBANG=m
- +CONFIG_NATIONAL_PHY=m
- +CONFIG_ICPLUS_PHY=m
- +CONFIG_BCM63XX_PHY=m
- +CONFIG_LSI_ET1011C_PHY=m
- +CONFIG_LXT_PHY=m
- +CONFIG_MARVELL_PHY=m
- +CONFIG_QSEMI_PHY=m
- +CONFIG_REALTEK_PHY=m
- +CONFIG_SMSC_PHY=m
- +CONFIG_STE10XP=m
- +CONFIG_VITESSE_PHY=m
- +CONFIG_MICREL_PHY=m
- +
- +CONFIG_MII=m
- +CONFIG_NET_CORE=y
- +CONFIG_NET_VENDOR_3COM=y
- +CONFIG_VORTEX=m
- +CONFIG_TYPHOON=m
- +CONFIG_DNET=m
- +
- +
- +CONFIG_LNE390=m
- +CONFIG_ES3210=m
- +CONFIG_NET_PCI=y
- +CONFIG_B44=m
- +CONFIG_B44_PCI=y
- +CONFIG_BNX2=m
- +CONFIG_BNX2X=m
- +CONFIG_BNX2X_SRIOV=y
- +CONFIG_CNIC=m
- +CONFIG_FEALNX=m
- +CONFIG_NET_POCKET=y
- +
- +#
- +# Ethernet (1000 Mbit)
- +#
- +CONFIG_TIGON3=m
- +CONFIG_JME=m
- +
- +#
- +# Ethernet (10000 Mbit)
- +#
- +# CONFIG_IP1000 is not set
- +# CONFIG_MLX4_EN is not set
- +# CONFIG_SFC is not set
- +
- +# CONFIG_FDDI is not set
- +# CONFIG_DEFXX is not set
- +# CONFIG_SKFP is not set
- +# CONFIG_HIPPI is not set
- +# CONFIG_PLIP is not set
- +CONFIG_PPP=m
- +CONFIG_PPP_MULTILINK=y
- +CONFIG_PPP_FILTER=y
- +CONFIG_PPP_ASYNC=m
- +CONFIG_PPP_SYNC_TTY=m
- +CONFIG_PPP_DEFLATE=m
- +CONFIG_IPPP_FILTER=y
- +CONFIG_PPP_BSDCOMP=y
- +CONFIG_PPPOE=m
- +CONFIG_PPP_MPPE=m
- +CONFIG_SLIP=m
- +CONFIG_SLIP_COMPRESSED=y
- +CONFIG_SLIP_SMART=y
- +# CONFIG_SLIP_MODE_SLIP6 is not set
- +
- +#
- +# Wireless LAN
- +#
- +#
- +# CONFIG_STRIP is not set
- +# CONFIG_PCMCIA_RAYCS is not set
- +
- +CONFIG_CFG80211_WEXT=y
- +# CONFIG_CFG80211_REG_DEBUG is not set
- +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
- +CONFIG_CFG80211_DEFAULT_PS=y
- +CONFIG_NL80211=y
- +# CONFIG_NL80211_TESTMODE is not set
- +# CONFIG_WIRELESS_EXT_SYSFS is not set
- +CONFIG_LIB80211=m
- +CONFIG_LIB80211_CRYPT_WEP=m
- +CONFIG_LIB80211_CRYPT_CCMP=m
- +CONFIG_LIB80211_CRYPT_TKIP=m
- +# CONFIG_LIB80211_DEBUG is not set
- +
- +CONFIG_MAC80211=m
- +CONFIG_MAC80211_RC_MINSTREL=y
- +# CONFIG_MAC80211_RC_DEFAULT_PID is not set
- +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
- +CONFIG_MAC80211_RC_DEFAULT="minstrel"
- +CONFIG_MAC80211_MESH=y
- +CONFIG_MAC80211_LEDS=y
- +# CONFIG_MAC80211_DEBUG_MENU is not set
- +
- +# CONFIG_WIMAX is not set
- +
- +# CONFIG_ADM8211 is not set
- +CONFIG_ATH_COMMON=m
- +CONFIG_ATH_CARDS=m
- +CONFIG_ATH5K=m
- +CONFIG_ATH5K_DEBUG=y
- +# CONFIG_ATH5K_TRACER is not set
- +CONFIG_ATH6KL=m
- +CONFIG_ATH6KL_DEBUG=y
- +CONFIG_ATH6KL_SDIO=m
- +CONFIG_ATH6KL_USB=m
- +# CONFIG_ATH6KL_TRACING is not set
- +CONFIG_AR5523=m
- +CONFIG_ATH9K=m
- +CONFIG_ATH9K_PCI=y
- +CONFIG_ATH9K_AHB=y
- +# CONFIG_ATH9K_DEBUG is not set
- +# CONFIG_ATH9K_MAC_DEBUG is not set
- +CONFIG_ATH9K_HTC=m
- +CONFIG_ATH9K_BTCOEX_SUPPORT=y
- +# CONFIG_ATH9K_LEGACY_RATE_CONTROL is not set
- +# CONFIG_ATH9K_WOW is not set
- +#
- +CONFIG_ATH10K=m
- +CONFIG_ATH10K_PCI=m
- +# CONFIG_ATH10K_DEBUG is not set
- +# CONFIG_ATH10K_TRACING is not set
- +CONFIG_ATH10K_DEBUGFS=y
- +CONFIG_WCN36XX=m
- +# CONFIG_WCN36XX_DEBUGFS is not set
- +CONFIG_WIL6210=m
- +CONFIG_WIL6210_ISR_COR=y
- +# CONFIG_WIL6210_TRACING is not set
- +CONFIG_CARL9170=m
- +CONFIG_CARL9170_LEDS=y
- +# CONFIG_CARL9170_HWRNG is not set
- +CONFIG_AT76C50X_USB=m
- +# CONFIG_AIRO is not set
- +# CONFIG_AIRO_CS is not set
- +# CONFIG_ATMEL is not set
- +CONFIG_B43=m
- +CONFIG_B43_PCMCIA=y
- +CONFIG_B43_SDIO=y
- +CONFIG_B43_BCMA=y
- +# CONFIG_B43_BCMA_EXTRA is not set
- +CONFIG_B43_BCMA_PIO=y
- +# CONFIG_B43_DEBUG is not set
- +CONFIG_B43_PHY_LP=y
- +CONFIG_B43_PHY_N=y
- +CONFIG_B43_PHY_HT=y
- +# CONFIG_B43_FORCE_PIO is not set
- +CONFIG_B43LEGACY=m
- +# CONFIG_B43LEGACY_DEBUG is not set
- +CONFIG_B43LEGACY_DMA=y
- +CONFIG_B43LEGACY_PIO=y
- +CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
- +# CONFIG_B43LEGACY_DMA_MODE is not set
- +# CONFIG_B43LEGACY_PIO_MODE is not set
- +CONFIG_BRCMSMAC=m
- +# CONFIG_BRCMFMAC_SDIO_OOB is not set
- +CONFIG_BRCMFMAC_USB=y
- +# CONFIG_BRCM_TRACING is not set
- +# CONFIG_BRCMISCAN is not set
- +# CONFIG_BRCMDBG is not set
- +CONFIG_HERMES=m
- +CONFIG_HERMES_CACHE_FW_ON_INIT=y
- +# CONFIG_HERMES_PRISM is not set
- +CONFIG_NORTEL_HERMES=m
- +CONFIG_PCI_HERMES=m
- +CONFIG_PLX_HERMES=m
- +CONFIG_PCMCIA_HERMES=m
- +CONFIG_ORINOCO_USB=m
- +# CONFIG_TMD_HERMES is not set
- +# CONFIG_PCMCIA_SPECTRUM is not set
- +CONFIG_CW1200=m
- +CONFIG_CW1200_WLAN_SDIO=m
- +CONFIG_CW1200_WLAN_SPI=m
- +# CONFIG_HOSTAP is not set
- +# CONFIG_IPW2100 is not set
- +# CONFIG_IPW2200 is not set
- +# CONFIG_IPW2100_DEBUG is not set
- +# CONFIG_IPW2200_DEBUG is not set
- +# CONFIG_LIBIPW_DEBUG is not set
- +CONFIG_LIBERTAS=m
- +CONFIG_LIBERTAS_USB=m
- +CONFIG_LIBERTAS_CS=m
- +CONFIG_LIBERTAS_SDIO=m
- +# CONFIG_LIBERTAS_DEBUG is not set
- +# CONFIG_LIBERTAS_THINFIRM is not set
- +CONFIG_LIBERTAS_MESH=y
- +CONFIG_IWLWIFI=m
- +CONFIG_IWLDVM=m
- +CONFIG_IWLMVM=m
- +CONFIG_IWLWIFI_DEBUG=y
- +CONFIG_IWLWIFI_DEVICE_SVTOOL=y
- +# CONFIG_IWLWIFI_EXPERIMENTAL_MFP is not set
- +CONFIG_IWLWIFI_UCODE16=y
- +# CONFIG_IWLWIFI_P2P is not set
- +CONFIG_IWLEGACY=m
- +CONFIG_IWLEGACY_DEBUG=y
- +# CONFIG_IWLWIFI_LEGACY_DEVICE_TRACING is not set
- +CONFIG_IWL4965=y
- +CONFIG_IWL3945=m
- +# CONFIG_IWM is not set
- +# CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE is not set
- +CONFIG_MAC80211_HWSIM=m
- +CONFIG_P54_COMMON=m
- +CONFIG_P54_USB=m
- +CONFIG_P54_PCI=m
- +CONFIG_MWL8K=m
- +# CONFIG_PRISM54 is not set
- +# CONFIG_PCMCIA_WL3501 is not set
- +CONFIG_RT2X00=m
- +# CONFIG_RT2X00_DEBUG is not set
- +CONFIG_RT2400PCI=m
- +CONFIG_RT2500PCI=m
- +CONFIG_RT61PCI=m
- +CONFIG_RT2500USB=m
- +CONFIG_RT2800USB=m
- +CONFIG_RT2800USB_RT33XX=y
- +CONFIG_RT2800USB_RT35XX=y
- +CONFIG_RT2800USB_RT3573=y
- +CONFIG_RT2800USB_RT53XX=y
- +CONFIG_RT2800USB_RT55XX=y
- +CONFIG_RT2800USB_UNKNOWN=y
- +CONFIG_RT2800PCI=m
- +CONFIG_RT2800PCI_RT3290=y
- +CONFIG_RT2800PCI_RT33XX=y
- +CONFIG_RT2800PCI_RT35XX=y
- +CONFIG_RT2800PCI_RT53XX=y
- +CONFIG_RT73USB=m
- +CONFIG_RTL8180=m
- +CONFIG_RTL8187=m
- +# CONFIG_USB_ZD1201 is not set
- +# CONFIG_USB_NET_SR9800 is not set
- +CONFIG_USB_NET_RNDIS_WLAN=m
- +CONFIG_USB_NET_KALMIA=m
- +CONFIG_USB_NET_QMI_WWAN=m
- +CONFIG_USB_NET_SMSC75XX=m
- +# CONFIG_WL_TI is not set
- +CONFIG_ZD1211RW=m
- +# CONFIG_ZD1211RW_DEBUG is not set
- +
- +CONFIG_WL12XX=m
- +CONFIG_WL12XX_SPI=m
- +CONFIG_WL12XX_SDIO=m
- +
- +CONFIG_WL1251=m
- +CONFIG_WL1251_SPI=m
- +CONFIG_WL1251_SDIO=m
- +
- +CONFIG_RTL_CARDS=m
- +CONFIG_RTLWIFI=m
- +CONFIG_RTL8192CE=m
- +CONFIG_RTL8192SE=m
- +CONFIG_RTL8192CU=m
- +CONFIG_RTL8192DE=m
- +CONFIG_RTL8723AE=m
- +CONFIG_RTL8188EE=m
- +
- +CONFIG_MWIFIEX=m
- +CONFIG_MWIFIEX_SDIO=m
- +CONFIG_MWIFIEX_PCIE=m
- +CONFIG_MWIFIEX_USB=m
- +
- +#
- +# Token Ring devices
- +#
- +# CONFIG_TR is not set
- +
- +CONFIG_NET_FC=y
- +
- +#
- +# Wan interfaces
- +#
- +# CONFIG_WAN is not set
- +
- +#
- +# PCMCIA network device support
- +#
- +CONFIG_NET_PCMCIA=y
- +CONFIG_PCMCIA_3C589=m
- +CONFIG_PCMCIA_3C574=m
- +CONFIG_PCMCIA_FMVJ18X=m
- +
- +#
- +# Amateur Radio support
- +#
- +CONFIG_HAMRADIO=y
- +CONFIG_AX25=m
- +CONFIG_AX25_DAMA_SLAVE=y
- +
- +# CONFIG_CAN is not set
- +
- +CONFIG_NETROM=m
- +CONFIG_ROSE=m
- +CONFIG_MKISS=m
- +CONFIG_6PACK=m
- +CONFIG_BPQETHER=m
- +CONFIG_BAYCOM_SER_FDX=m
- +CONFIG_BAYCOM_SER_HDX=m
- +CONFIG_BAYCOM_PAR=m
- +CONFIG_BAYCOM_EPP=m
- +CONFIG_YAM=m
- +
- +CONFIG_NFC=m
- +CONFIG_NFC_DIGITAL=m
- +CONFIG_NFC_NCI=m
- +CONFIG_NFC_HCI=m
- +CONFIG_NFC_SHDLC=y
- +CONFIG_NFC_LLCP=y
- +CONFIG_NFC_SIM=m
- +CONFIG_NFC_MRVL=m
- +CONFIG_NFC_MRVL_USB=m
- +
- +#
- +# Near Field Communication (NFC) devices
- +#
- +CONFIG_NFC_PORT100=m
- +CONFIG_NFC_PN544=m
- +CONFIG_NFC_PN544_I2C=m
- +CONFIG_NFC_PN533=m
- +CONFIG_NFC_MICROREAD=m
- +CONFIG_NFC_MICROREAD_I2C=m
- +
- +#
- +# IrDA (infrared) support
- +#
- +CONFIG_IRDA=m
- +# CONFIG_IRDA_DEBUG is not set
- +CONFIG_IRLAN=m
- +CONFIG_IRNET=m
- +CONFIG_IRCOMM=m
- +# CONFIG_IRDA_ULTRA is not set
- +CONFIG_IRDA_CACHE_LAST_LSAP=y
- +CONFIG_IRDA_FAST_RR=y
- +CONFIG_IRTTY_SIR=m
- +CONFIG_DONGLE=y
- +CONFIG_ACTISYS_DONGLE=m
- +CONFIG_ACT200L_DONGLE=m
- +CONFIG_ESI_DONGLE=m
- +CONFIG_GIRBIL_DONGLE=m
- +CONFIG_KINGSUN_DONGLE=m
- +CONFIG_KSDAZZLE_DONGLE=m
- +CONFIG_KS959_DONGLE=m
- +CONFIG_LITELINK_DONGLE=m
- +CONFIG_MA600_DONGLE=m
- +CONFIG_MCP2120_DONGLE=m
- +CONFIG_OLD_BELKIN_DONGLE=m
- +CONFIG_TEKRAM_DONGLE=m
- +CONFIG_TOIM3232_DONGLE=m
- +
- +CONFIG_ALI_FIR=m
- +CONFIG_MCS_FIR=m
- +CONFIG_NSC_FIR=m
- +CONFIG_SIGMATEL_FIR=m
- +CONFIG_SMC_IRCC_FIR=m
- +# CONFIG_TOSHIBA_FIR is not set
- +CONFIG_USB_IRDA=m
- +CONFIG_VLSI_FIR=m
- +CONFIG_VIA_FIR=m
- +CONFIG_WINBOND_FIR=m
- +
- +#
- +# Bluetooth support
- +#
- +CONFIG_BT=m
- +CONFIG_BT_L2CAP=y
- +CONFIG_BT_SCO=y
- +CONFIG_BT_CMTP=m
- +CONFIG_BT_RFCOMM=m
- +CONFIG_BT_RFCOMM_TTY=y
- +CONFIG_BT_BNEP=m
- +CONFIG_BT_BNEP_MC_FILTER=y
- +CONFIG_BT_BNEP_PROTO_FILTER=y
- +CONFIG_BT_HIDP=m
- +
- +#
- +# Bluetooth device drivers
- +#
- +CONFIG_BT_HCIBTUSB=m
- +# Disable the BT_HCIUSB driver.
- +# It sucks more power than BT_HCIBTUSB which has the same functionality.
- +CONFIG_BT_HCIUART=m
- +CONFIG_BT_HCIUART_H4=y
- +CONFIG_BT_HCIUART_BCSP=y
- +CONFIG_BT_HCIUART_ATH3K=y
- +CONFIG_BT_HCIUART_3WIRE=y
- +CONFIG_BT_HCIDTL1=m
- +CONFIG_BT_HCIBT3C=m
- +CONFIG_BT_HCIBLUECARD=m
- +CONFIG_BT_HCIBTUART=m
- +CONFIG_BT_HCIVHCI=m
- +CONFIG_BT_HCIBCM203X=m
- +CONFIG_BT_HCIBFUSB=m
- +CONFIG_BT_HCIBPA10X=m
- +CONFIG_BT_HCIBTSDIO=m
- +CONFIG_BT_HCIUART_LL=y
- +CONFIG_BT_MRVL=m
- +CONFIG_BT_MRVL_SDIO=m
- +CONFIG_BT_ATH3K=m
- +CONFIG_BT_WILINK=m
- +
- +#
- +# ISDN subsystem
- +#
- +CONFIG_ISDN=y
- +CONFIG_MISDN=m
- +CONFIG_MISDN_DSP=m
- +CONFIG_MISDN_L1OIP=m
- +CONFIG_MISDN_AVMFRITZ=m
- +CONFIG_MISDN_SPEEDFAX=m
- +CONFIG_MISDN_INFINEON=m
- +CONFIG_MISDN_W6692=m
- +CONFIG_MISDN_NETJET=m
- +
- +#
- +# mISDN hardware drivers
- +#
- +CONFIG_MISDN_HFCPCI=m
- +CONFIG_MISDN_HFCMULTI=m
- +CONFIG_ISDN_I4L=m
- +CONFIG_ISDN_DRV_AVMB1_B1PCI=m
- +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
- +CONFIG_ISDN_DRV_AVMB1_T1PCI=m
- +CONFIG_ISDN_DRV_AVMB1_C4=m
- +
- +CONFIG_MISDN_HFCUSB=m
- +
- +CONFIG_ISDN_PPP=y
- +CONFIG_ISDN_PPP_VJ=y
- +CONFIG_ISDN_MPP=y
- +# CONFIG_ISDN_PPP_BSDCOMP is not set
- +CONFIG_ISDN_TTY_FAX=y
- +CONFIG_DE_AOC=y
- +
- +CONFIG_ISDN_AUDIO=y
- +
- +CONFIG_ISDN_DRV_HISAX=m
- +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
- +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
- +
- +CONFIG_ISDN_CAPI_CAPIDRV=m
- +CONFIG_ISDN_DIVERSION=m
- +
- +CONFIG_HISAX_EURO=y
- +CONFIG_HISAX_1TR6=y
- +CONFIG_HISAX_NI1=y
- +CONFIG_HISAX_MAX_CARDS=8
- +CONFIG_HISAX_16_3=y
- +CONFIG_HISAX_TELESPCI=y
- +CONFIG_HISAX_S0BOX=y
- +CONFIG_HISAX_FRITZPCI=y
- +CONFIG_HISAX_AVM_A1_PCMCIA=y
- +CONFIG_HISAX_ELSA=y
- +CONFIG_HISAX_DIEHLDIVA=y
- +CONFIG_HISAX_SEDLBAUER=y
- +CONFIG_HISAX_NETJET=y
- +CONFIG_HISAX_NETJET_U=y
- +CONFIG_HISAX_NICCY=y
- +CONFIG_HISAX_BKM_A4T=y
- +CONFIG_HISAX_SCT_QUADRO=y
- +CONFIG_HISAX_GAZEL=y
- +CONFIG_HISAX_HFC_PCI=y
- +CONFIG_HISAX_W6692=y
- +CONFIG_HISAX_HFC_SX=y
- +CONFIG_HISAX_ENTERNOW_PCI=y
- +# CONFIG_HISAX_DEBUG is not set
- +CONFIG_HISAX_AVM_A1_CS=m
- +CONFIG_HISAX_ST5481=m
- +# CONFIG_HISAX_HFCUSB is not set
- +CONFIG_HISAX_FRITZ_PCIPNP=m
- +CONFIG_HISAX_NO_SENDCOMPLETE=y
- +CONFIG_HISAX_NO_LLC=y
- +CONFIG_HISAX_NO_KEYPAD=y
- +CONFIG_HISAX_SEDLBAUER_CS=m
- +CONFIG_HISAX_ELSA_CS=m
- +CONFIG_HISAX_TELES_CS=m
- +CONFIG_HISAX_HFC4S8S=m
- +
- +CONFIG_ISDN_DRV_LOOP=m
- +CONFIG_HYSDN=m
- +CONFIG_HYSDN_CAPI=y
- +
- +
- +#
- +# CAPI subsystem
- +#
- +CONFIG_ISDN_CAPI=m
- +# CONFIG_CAPI_TRACE is not set
- +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
- +CONFIG_ISDN_CAPI_MIDDLEWARE=y
- +CONFIG_ISDN_CAPI_CAPI20=m
- +
- +#
- +# CAPI hardware drivers
- +#
- +
- +#
- +# Active AVM cards
- +#
- +CONFIG_CAPI_AVM=y
- +
- +#
- +# Active Eicon DIVA Server cards
- +#
- +# CONFIG_CAPI_EICON is not set
- +CONFIG_ISDN_DIVAS=m
- +CONFIG_ISDN_DIVAS_BRIPCI=y
- +CONFIG_ISDN_DIVAS_PRIPCI=y
- +CONFIG_ISDN_DIVAS_DIVACAPI=m
- +CONFIG_ISDN_DIVAS_USERIDI=m
- +CONFIG_ISDN_DIVAS_MAINT=m
- +
- +CONFIG_ISDN_DRV_GIGASET=m
- +CONFIG_GIGASET_CAPI=y
- +CONFIG_GIGASET_BASE=m
- +CONFIG_GIGASET_M101=m
- +CONFIG_GIGASET_M105=m
- +# CONFIG_GIGASET_DEBUG is not set
- +
- +#
- +# Telephony Support
- +#
- +# CONFIG_PHONE is not set
- +
- +#
- +# Input device support
- +#
- +CONFIG_INPUT=y
- +CONFIG_INPUT_FF_MEMLESS=m
- +
- +#
- +# Userland interfaces
- +#
- +CONFIG_INPUT_MOUSEDEV=y
- +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
- +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
- +CONFIG_INPUT_JOYDEV=m
- +# CONFIG_INPUT_MATRIXKMAP is not set
- +
- +CONFIG_INPUT_TABLET=y
- +CONFIG_TABLET_USB_ACECAD=m
- +CONFIG_TABLET_USB_AIPTEK=m
- +CONFIG_TABLET_USB_GTCO=m
- +CONFIG_TABLET_USB_HANWANG=m
- +CONFIG_TABLET_USB_KBTAB=m
- +CONFIG_TABLET_USB_WACOM=m
- +
- +CONFIG_INPUT_POWERMATE=m
- +CONFIG_INPUT_YEALINK=m
- +CONFIG_INPUT_CM109=m
- +CONFIG_INPUT_POLLDEV=m
- +CONFIG_INPUT_SPARSEKMAP=m
- +# CONFIG_INPUT_ADXL34X is not set
- +# CONFIG_INPUT_BMA150 is not set
- +# CONFIG_INPUT_IMS_PCU is not set
- +CONFIG_INPUT_CMA3000=m
- +CONFIG_INPUT_CMA3000_I2C=m
- +CONFIG_INPUT_IDEAPAD_SLIDEBAR=m
- +
- +#
- +# Input I/O drivers
- +#
- +CONFIG_GAMEPORT=m
- +CONFIG_GAMEPORT_NS558=m
- +CONFIG_GAMEPORT_L4=m
- +CONFIG_GAMEPORT_EMU10K1=m
- +CONFIG_GAMEPORT_FM801=m
- +CONFIG_SERIO=y
- +CONFIG_SERIO_I8042=y
- +CONFIG_SERIO_RAW=m
- +CONFIG_SERIO_ALTERA_PS2=m
- +# CONFIG_SERIO_PS2MULT is not set
- +CONFIG_SERIO_ARC_PS2=m
- +# CONFIG_SERIO_APBPS2 is not set
- +
- +# CONFIG_SERIO_CT82C710 is not set
- +# CONFIG_SERIO_OLPC_APSP is not set
- +# CONFIG_SERIO_PARKBD is not set
- +# CONFIG_SERIO_PCIPS2 is not set
- +# CONFIG_SERIO_LIBPS2 is not set
- +
- +#
- +# Input Device Drivers
- +#
- +CONFIG_INPUT_KEYBOARD=y
- +# CONFIG_KEYBOARD_SUNKBD is not set
- +# CONFIG_KEYBOARD_SH_KEYSC is not set
- +# CONFIG_KEYBOARD_XTKBD is not set
- +# CONFIG_KEYBOARD_MATRIX is not set
- +# CONFIG_KEYBOARD_NEWTON is not set
- +# CONFIG_KEYBOARD_STOWAWAY is not set
- +# CONFIG_KEYBOARD_LKKBD is not set
- +# CONFIG_KEYBOARD_LM8323 is not set
- +# CONFIG_KEYBOARD_LM8333 is not set
- +# CONFIG_KEYBOARD_MAX7359 is not set
- +# CONFIG_KEYBOARD_ADP5589 is not set
- +# CONFIG_KEYBOARD_MPR121 is not set
- +# CONFIG_KEYBOARD_QT1070 is not set
- +# CONFIG_KEYBOARD_MCS is not set
- +# CONFIG_KEYBOARD_OPENCORES is not set
- +# CONFIG_KEYBOARD_SAMSUNG is not set
- +# CONFIG_KEYBOARD_QT2160 is not set
- +# CONFIG_KEYBOARD_TCA6416 is not set
- +# CONFIG_KEYBOARD_TCA8418 is not set
- +# CONFIG_KEYBOARD_OMAP4 is not set
- +CONFIG_INPUT_MOUSE=y
- +# CONFIG_MOUSE_PS2_TOUCHKIT is not set
- +CONFIG_MOUSE_PS2_ELANTECH=y
- +CONFIG_MOUSE_PS2_SENTELIC=y
- +CONFIG_MOUSE_SERIAL=m
- +CONFIG_MOUSE_VSXXXAA=m
- +CONFIG_MOUSE_APPLETOUCH=m
- +CONFIG_MOUSE_BCM5974=m
- +CONFIG_MOUSE_SYNAPTICS_I2C=m
- +CONFIG_MOUSE_SYNAPTICS_USB=m
- +CONFIG_MOUSE_CYAPA=m
- +CONFIG_INPUT_JOYSTICK=y
- +CONFIG_JOYSTICK_ANALOG=m
- +CONFIG_JOYSTICK_A3D=m
- +CONFIG_JOYSTICK_ADI=m
- +CONFIG_JOYSTICK_COBRA=m
- +CONFIG_JOYSTICK_GF2K=m
- +CONFIG_JOYSTICK_GRIP=m
- +CONFIG_JOYSTICK_GRIP_MP=m
- +CONFIG_JOYSTICK_GUILLEMOT=m
- +CONFIG_JOYSTICK_INTERACT=m
- +CONFIG_JOYSTICK_SIDEWINDER=m
- +CONFIG_JOYSTICK_TMDC=m
- +CONFIG_JOYSTICK_IFORCE=m
- +CONFIG_JOYSTICK_IFORCE_USB=y
- +CONFIG_JOYSTICK_IFORCE_232=y
- +CONFIG_JOYSTICK_WARRIOR=m
- +CONFIG_JOYSTICK_MAGELLAN=m
- +CONFIG_JOYSTICK_SPACEORB=m
- +CONFIG_JOYSTICK_SPACEBALL=m
- +CONFIG_JOYSTICK_STINGER=m
- +CONFIG_JOYSTICK_DB9=m
- +CONFIG_JOYSTICK_GAMECON=m
- +CONFIG_JOYSTICK_TURBOGRAFX=m
- +CONFIG_JOYSTICK_JOYDUMP=m
- +CONFIG_JOYSTICK_TWIDJOY=m
- +CONFIG_JOYSTICK_WALKERA0701=m
- +CONFIG_JOYSTICK_XPAD=m
- +CONFIG_JOYSTICK_XPAD_FF=y
- +CONFIG_JOYSTICK_XPAD_LEDS=y
- +CONFIG_JOYSTICK_ZHENHUA=m
- +# CONFIG_JOYSTICK_AS5011 is not set
- +
- +CONFIG_INPUT_TOUCHSCREEN=y
- +# CONFIG_TOUCHSCREEN_AD7879 is not set
- +CONFIG_TOUCHSCREEN_AD7879_I2C=m
- +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
- +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set
- +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set
- +CONFIG_TOUCHSCREEN_DYNAPRO=m
- +CONFIG_TOUCHSCREEN_EDT_FT5X06=m
- +CONFIG_TOUCHSCREEN_EETI=m
- +CONFIG_TOUCHSCREEN_EGALAX=m
- +CONFIG_TOUCHSCREEN_ELO=m
- +CONFIG_TOUCHSCREEN_FUJITSU=m
- +CONFIG_TOUCHSCREEN_GUNZE=m
- +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
- +CONFIG_TOUCHSCREEN_INEXIO=m
- +CONFIG_TOUCHSCREEN_ILI210X=m
- +CONFIG_TOUCHSCREEN_MMS114=m
- +CONFIG_TOUCHSCREEN_MTOUCH=m
- +CONFIG_TOUCHSCREEN_MCS5000=m
- +CONFIG_TOUCHSCREEN_MK712=m
- +CONFIG_TOUCHSCREEN_PENMOUNT=m
- +# CONFIG_TOUCHSCREEN_SUR40 is not set
- +# CONFIG_TOUCHSCREEN_TPS6507X is not set
- +CONFIG_TOUCHSCREEN_TSC_SERIO=m
- +CONFIG_TOUCHSCREEN_TSC2007=m
- +CONFIG_TOUCHSCREEN_TOUCHIT213=m
- +CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
- +CONFIG_TOUCHSCREEN_TOUCHWIN=m
- +CONFIG_TOUCHSCREEN_PIXCIR=m
- +CONFIG_TOUCHSCREEN_UCB1400=m
- +CONFIG_TOUCHSCREEN_WACOM_W8001=m
- +CONFIG_TOUCHSCREEN_WACOM_I2C=m
- +CONFIG_TOUCHSCREEN_USB_E2I=y
- +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
- +# CONFIG_TOUCHSCREEN_WM97XX is not set
- +CONFIG_TOUCHSCREEN_W90X900=m
- +# CONFIG_TOUCHSCREEN_BU21013 is not set
- +CONFIG_TOUCHSCREEN_ST1232=m
- +CONFIG_TOUCHSCREEN_ATMEL_MXT=m
- +# CONFIG_TOUCHSCREEN_MAX11801 is not set
- +CONFIG_TOUCHSCREEN_AUO_PIXCIR=m
- +CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m
- +CONFIG_TOUCHSCREEN_ZFORCE=m
- +
- +CONFIG_INPUT_PCSPKR=m
- +CONFIG_INPUT_RETU_PWRBUTTON=m
- +CONFIG_INPUT_UINPUT=m
- +CONFIG_INPUT_WISTRON_BTNS=m
- +CONFIG_INPUT_ATLAS_BTNS=m
- +
- +CONFIG_INPUT_ATI_REMOTE2=m
- +CONFIG_INPUT_KEYSPAN_REMOTE=m
- +
- +CONFIG_MAC_EMUMOUSEBTN=y
- +
- +CONFIG_INPUT_WM831X_ON=m
- +
- +
- +# CONFIG_INPUT_AD714X is not set
- +# CONFIG_INPUT_PCF8574 is not set
- +CONFIG_INPUT_MMA8450=m
- +CONFIG_INPUT_MPU3050=m
- +CONFIG_INPUT_KXTJ9=m
- +# CONFIG_INPUT_KXTJ9_POLLED_MODE is not set
- +
- +#
- +# Character devices
- +#
- +CONFIG_VT=y
- +CONFIG_VT_CONSOLE=y
- +CONFIG_HW_CONSOLE=y
- +CONFIG_SERIAL_NONSTANDARD=y
- +CONFIG_ROCKETPORT=m
- +CONFIG_SYNCLINK=m
- +CONFIG_SYNCLINKMP=m
- +CONFIG_SYNCLINK_GT=m
- +CONFIG_N_HDLC=m
- +CONFIG_N_GSM=m
- +# CONFIG_TRACE_SINK is not set
- +# CONFIG_STALDRV is not set
- +# CONFIG_DUMMY_IRQ is not set
- +# CONFIG_IBM_ASM is not set
- +CONFIG_TIFM_CORE=m
- +CONFIG_TIFM_7XX1=m
- +CONFIG_TCG_TPM=m
- +CONFIG_TCG_TIS=m
- +# CONFIG_TCG_TIS_I2C_INFINEON is not set
- +# CONFIG_TCG_TIS_I2C_ATMEL is not set
- +# CONFIG_TCG_TIS_I2C_NUVOTON is not set
- +CONFIG_TCG_NSC=m
- +CONFIG_TCG_ATMEL=m
- +# CONFIG_TCG_INFINEON is not set
- +# CONFIG_TCG_ST33_I2C is not set
- +# CONFIG_TCG_XEN is not set
- +CONFIG_TELCLOCK=m
- +
- +#
- +# Serial drivers
- +#
- +CONFIG_SERIAL_8250=y
- +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
- +CONFIG_SERIAL_8250_CONSOLE=y
- +CONFIG_SERIAL_8250_CS=m
- +CONFIG_SERIAL_8250_NR_UARTS=32
- +CONFIG_SERIAL_8250_RUNTIME_UARTS=4
- +CONFIG_SERIAL_8250_EXTENDED=y
- +CONFIG_SERIAL_8250_MANY_PORTS=y
- +CONFIG_SERIAL_8250_SHARE_IRQ=y
- +# CONFIG_SERIAL_8250_DETECT_IRQ is not set
- +CONFIG_SERIAL_8250_RSA=y
- +# CONFIG_SERIAL_8250_DW is not set
- +CONFIG_CYCLADES=m
- +# CONFIG_CYZ_INTR is not set
- +# CONFIG_MOXA_INTELLIO is not set
- +# CONFIG_MOXA_SMARTIO is not set
- +# CONFIG_ISI is not set
- +# CONFIG_RIO is not set
- +CONFIG_SERIAL_JSM=m
- +# CONFIG_SERIAL_SCCNXP is not set
- +# CONFIG_SERIAL_MFD_HSU is not set
- +
- +# CONFIG_SERIAL_ALTERA_JTAGUART is not set
- +# CONFIG_SERIAL_ALTERA_UART is not set
- +
- +#
- +# Non-8250 serial port support
- +#
- +CONFIG_SERIAL_CORE=y
- +CONFIG_SERIAL_CORE_CONSOLE=y
- +# CONFIG_SERIAL_XILINX_PS_UART is not set
- +# CONFIG_SERIAL_TIMBERDALE is not set
- +CONFIG_SERIAL_ARC=m
- +CONFIG_SERIAL_ARC_NR_PORTS=1
- +# CONFIG_SERIAL_RP2 is not set
- +# CONFIG_SERIAL_ST_ASC is not set
- +# CONFIG_SERIAL_PCH_UART is not set
- +
- +CONFIG_UNIX98_PTYS=y
- +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
- +CONFIG_PRINTER=m
- +CONFIG_LP_CONSOLE=y
- +CONFIG_PPDEV=m
- +
- +#
- +# I2C support
- +#
- +CONFIG_I2C=y
- +# CONFIG_I2C_MUX is not set
- +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set
- +# CONFIG_I2C_MUX_PCA954x is not set
- +# CONFIG_I2C_MUX_GPIO is not set
- +# CONFIG_I2C_MUX_PCA9541 is not set
- +# CONFIG_I2C_MUX_PINCTRL is not set
- +#
- +
- +#
- +# I2C Algorithms
- +#
- +# CONFIG_I2C_DEBUG_ALGO is not set
- +CONFIG_I2C_ALGOBIT=m
- +
- +#
- +# I2C Hardware Bus support
- +#
- +
- +# CONFIG_I2C_ALI1535 is not set
- +# CONFIG_I2C_ALI1563 is not set
- +# CONFIG_I2C_ALI15X3 is not set
- +# CONFIG_I2C_AMD756 is not set
- +# CONFIG_I2C_AMD756_S4882 is not set
- +# CONFIG_I2C_AMD8111 is not set
- +# CONFIG_I2C_DEBUG_CORE is not set
- +# CONFIG_I2C_DEBUG_BUS is not set
- +# CONFIG_I2C_I801 is not set
- +# CONFIG_I2C_ISCH is not set
- +# CONFIG_I2C_NFORCE2_S4985 is not set
- +# CONFIG_I2C_INTEL_MID is not set
- +# CONFIG_I2C_EG20T is not set
- +# CONFIG_I2C_CBUS_GPIO is not set
- +CONFIG_I2C_VIPERBOARD=m
- +
- +CONFIG_EEPROM_AT24=m
- +CONFIG_EEPROM_LEGACY=m
- +CONFIG_EEPROM_93CX6=m
- +CONFIG_EEPROM_MAX6875=m
- +
- +CONFIG_I2C_NFORCE2=m
- +# CONFIG_I2C_OCORES is not set
- +CONFIG_I2C_PARPORT=m
- +CONFIG_I2C_PARPORT_LIGHT=m
- +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
- +CONFIG_I2C_PASEMI=m
- +CONFIG_I2C_PCA_PLATFORM=m
- +# CONFIG_I2C_PIIX4 is not set
- +# CONFIG_SCx200_ACB is not set
- +# CONFIG_I2C_SIS5595 is not set
- +# CONFIG_I2C_SIS630 is not set
- +# CONFIG_I2C_SIS96X is not set
- +CONFIG_I2C_SIMTEC=m
- +CONFIG_I2C_STUB=m
- +CONFIG_I2C_TINY_USB=m
- +# CONFIG_I2C_TAOS_EVM is not set
- +# CONFIG_I2C_VIA is not set
- +# CONFIG_I2C_VIAPRO is not set
- +# CONFIG_I2C_DESIGNWARE is not set
- +# CONFIG_I2C_XILINX is not set
- +
- +CONFIG_I2C_DIOLAN_U2C=m
- +
- +#
- +# I2C Hardware Sensors Chip support
- +#
- +CONFIG_SENSORS_ATK0110=m
- +CONFIG_SENSORS_ABITUGURU=m
- +CONFIG_SENSORS_ABITUGURU3=m
- +CONFIG_SENSORS_AD7414=m
- +CONFIG_SENSORS_AD7418=m
- +CONFIG_SENSORS_ADM1021=m
- +CONFIG_SENSORS_ADM1025=m
- +CONFIG_SENSORS_ADM1026=m
- +CONFIG_SENSORS_ADM1029=m
- +CONFIG_SENSORS_ADM1031=m
- +CONFIG_SENSORS_ADM9240=m
- +CONFIG_SENSORS_ADT7310=m
- +CONFIG_SENSORS_ADT7410=m
- +CONFIG_SENSORS_ADS7828=m
- +CONFIG_SENSORS_ADT7462=m
- +CONFIG_SENSORS_ADT7470=m
- +CONFIG_SENSORS_ADT7475=m
- +CONFIG_SENSORS_APPLESMC=m
- +CONFIG_SENSORS_ASB100=m
- +CONFIG_SENSORS_ATXP1=m
- +CONFIG_SENSORS_CORETEMP=m
- +CONFIG_SENSORS_DME1737=m
- +CONFIG_SENSORS_DS1621=m
- +# CONFIG_DS1682 is not set
- +CONFIG_SENSORS_F71805F=m
- +CONFIG_SENSORS_F71882FG=m
- +CONFIG_SENSORS_F75375S=m
- +CONFIG_SENSORS_FSCHMD=m
- +CONFIG_SENSORS_G760A=m
- +CONFIG_SENSORS_G762=m
- +CONFIG_SENSORS_GL518SM=m
- +CONFIG_SENSORS_GL520SM=m
- +CONFIG_SENSORS_HDAPS=m
- +# CONFIG_SENSORS_HIH6130 is not set
- +# CONFIG_SENSORS_HTU21 is not set
- +# CONFIG_SENSORS_I5K_AMB is not set
- +# FIXME: IBMAEM x86 only?
- +CONFIG_SENSORS_IBMAEM=m
- +CONFIG_SENSORS_IBMPEX=m
- +# CONFIG_SENSORS_IIO_HWMON is not set
- +CONFIG_SENSORS_IT87=m
- +CONFIG_SENSORS_K8TEMP=m
- +CONFIG_SENSORS_K10TEMP=m
- +CONFIG_SENSORS_LIS3LV02D=m
- +CONFIG_SENSORS_LIS3_SPI=m
- +CONFIG_SENSORS_LIS3_I2C=m
- +CONFIG_SENSORS_LM63=m
- +CONFIG_SENSORS_LM75=m
- +CONFIG_SENSORS_LM77=m
- +CONFIG_SENSORS_LM78=m
- +CONFIG_SENSORS_LM80=m
- +CONFIG_SENSORS_LM83=m
- +CONFIG_SENSORS_LM85=m
- +CONFIG_SENSORS_LM87=m
- +CONFIG_SENSORS_LM90=m
- +CONFIG_SENSORS_LM92=m
- +CONFIG_SENSORS_LM93=m
- +CONFIG_SENSORS_LM95234=m
- +CONFIG_SENSORS_LTC4245=m
- +CONFIG_SENSORS_MAX1619=m
- +CONFIG_SENSORS_MAX6650=m
- +CONFIG_SENSORS_MAX6697=m
- +CONFIG_SENSORS_MCP3021=m
- +CONFIG_SENSORS_NCT6775=m
- +CONFIG_SENSORS_NTC_THERMISTOR=m
- +CONFIG_SENSORS_PC87360=m
- +CONFIG_SENSORS_PC87427=m
- +CONFIG_SENSORS_PCF8591=m
- +CONFIG_SENSORS_SHT15=m
- +CONFIG_SENSORS_SIS5595=m
- +CONFIG_CHARGER_SMB347=m
- +CONFIG_SENSORS_SMSC47M1=m
- +CONFIG_SENSORS_SMSC47M192=m
- +CONFIG_SENSORS_SMSC47B397=m
- +CONFIG_SENSORS_THMC50=m
- +CONFIG_SENSORS_TMP401=m
- +CONFIG_APDS9802ALS=m
- +CONFIG_ISL29020=m
- +CONFIG_ISL29003=m
- +CONFIG_SENSORS_BH1770=m
- +CONFIG_SENSORS_APDS990X=m
- +CONFIG_SENSORS_TSL2550=m
- +CONFIG_SENSORS_VIA686A=m
- +CONFIG_SENSORS_VIA_CPUTEMP=m
- +CONFIG_SENSORS_VT1211=m
- +CONFIG_SENSORS_VT8231=m
- +CONFIG_SENSORS_W83627HF=m
- +CONFIG_SENSORS_W83781D=m
- +CONFIG_SENSORS_W83L785TS=m
- +CONFIG_SENSORS_W83L786NG=m
- +CONFIG_SENSORS_W83627EHF=m
- +CONFIG_SENSORS_W83791D=m
- +CONFIG_SENSORS_W83792D=m
- +CONFIG_SENSORS_W83793=m
- +CONFIG_SENSORS_LTC4215=m
- +CONFIG_SENSORS_LM95241=m
- +CONFIG_SENSORS_LM95245=m
- +CONFIG_SENSORS_TMP421=m
- +CONFIG_SENSORS_WM8350=m
- +CONFIG_SENSORS_WM831X=m
- +CONFIG_SENSORS_LM73=m
- +CONFIG_SENSORS_AMC6821=m
- +CONFIG_SENSORS_INA2XX=m
- +CONFIG_SENSORS_INA209=m
- +CONFIG_SENSORS_ADT7411=m
- +CONFIG_SENSORS_ASC7621=m
- +CONFIG_SENSORS_EMC1403=m
- +CONFIG_SENSORS_TMP102=m
- +CONFIG_SENSORS_LTC4261=m
- +# CONFIG_SENSORS_BH1780 is not set
- +# CONFIG_SENSORS_JC42 is not set
- +# CONFIG_SENSORS_SMM665 is not set
- +# CONFIG_SENSORS_EMC2103 is not set
- +# CONFIG_SENSORS_GPIO_FAN is not set
- +CONFIG_SENSORS_W83795=m
- +# CONFIG_SENSORS_W83795_FANCTRL is not set
- +CONFIG_SENSORS_DS620=m
- +CONFIG_SENSORS_SHT21=m
- +CONFIG_SENSORS_LINEAGE=m
- +CONFIG_SENSORS_LTC4151=m
- +CONFIG_SENSORS_MAX6639=m
- +CONFIG_SENSORS_SCH5627=m
- +CONFIG_SENSORS_SCH5636=m
- +CONFIG_SENSORS_ADS1015=m
- +CONFIG_SENSORS_MAX16065=m
- +CONFIG_SENSORS_MAX6642=m
- +CONFIG_SENSORS_ADM1275=m
- +CONFIG_SENSORS_UCD9000=m
- +CONFIG_SENSORS_UCD9200=m
- +CONFIG_SENSORS_ZL6100=m
- +CONFIG_SENSORS_EMC6W201=m
- +
- +CONFIG_PMBUS=m
- +CONFIG_SENSORS_PMBUS=m
- +CONFIG_SENSORS_MAX16064=m
- +CONFIG_SENSORS_LM25066=m
- +CONFIG_SENSORS_LTC2978=m
- +CONFIG_SENSORS_MAX34440=m
- +CONFIG_SENSORS_MAX8688=m
- +CONFIG_SENSORS_MAX1668=m
- +CONFIG_SENSORS_MAX197=m
- +
- +# Industrial I/O subsystem configuration
- +CONFIG_IIO=m
- +CONFIG_IIO_BUFFER=y
- +CONFIG_IIO_BUFFER_CB=y
- +# CONFIG_IIO_KFIFO_BUF is not set
- +CONFIG_IIO_TRIGGERED_BUFFER=m
- +CONFIG_IIO_TRIGGER=y
- +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2
- +CONFIG_IIO_INTERRUPT_TRIGGER=m
- +CONFIG_HID_SENSOR_IIO_COMMON=m
- +CONFIG_HID_SENSOR_IIO_TRIGGER=m
- +CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS=y
- +# CONFIG_IIO_SYSFS_TRIGGER is not set
- +# CONFIG_AD5446 is not set
- +# CONFIG_AD5380 is not set
- +# CONFIG_AD5064 is not set
- +# CONFIG_BMA180 is not set
- +# CONFIG_MAX1363 is not set
- +# CONFIG_MAX517 is not set
- +# CONFIG_MCP4725 is not set
- +# CONFIG_ITG3200 is not set
- +# CONFIG_APDS9300 is not set
- +# CONFIG_CM32181 is not set
- +# CONFIG_CM36651 is not set
- +# CONFIG_GP2AP020A00F is not set
- +# CONFIG_TSL2583 is not set
- +# CONFIG_TSL2x7x is not set
- +# CONFIG_TCS3472 is not set
- +# CONFIG_TSL4531 is not set
- +# CONFIG_NAU7802 is not set
- +# CONFIG_TI_ADC081C is not set
- +# CONFIG_EXYNOS_ADC is not set
- +# CONFIG_VIPERBOARD_ADC is not set
- +# CONFIG_INV_MPU6050_IIO is not set
- +CONFIG_IIO_ST_GYRO_3AXIS=m
- +CONFIG_IIO_ST_MAGN_3AXIS=m
- +CONFIG_IIO_ST_ACCEL_3AXIS=m
- +CONFIG_HID_SENSOR_INCLINOMETER_3D=m
- +# CONFIG_ADJD_S311 is not set
- +# CONFIG_SENSORS_TSL2563 is not set
- +# CONFIG_VCNL4000 is not set
- +# CONFIG_AK8975 is not set
- +# CONFIG_MAG3110 is not set
- +# CONFIG_TMP006 is not set
- +# CONFIG_IIO_ST_PRESS is not set
- +# CONFIG_KXSD9 is not set
- +# CONFIG_AD7266 is not set
- +# CONFIG_AD7298 is not set
- +# CONFIG_AD7476 is not set
- +# CONFIG_AD7791 is not set
- +# CONFIG_AD7793 is not set
- +# CONFIG_AD7887 is not set
- +# CONFIG_AD7923 is not set
- +# CONFIG_MCP320X is not set
- +# CONFIG_MCP3422 is not set
- +# CONFIG_AD8366 is not set
- +# CONFIG_AD5360 is not set
- +# CONFIG_AD5421 is not set
- +# CONFIG_AD5449 is not set
- +# CONFIG_AD5504 is not set
- +# CONFIG_AD5624R_SPI is not set
- +# CONFIG_AD5686 is not set
- +# CONFIG_AD5755 is not set
- +# CONFIG_AD5764 is not set
- +# CONFIG_AD5791 is not set
- +# CONFIG_AD7303 is not set
- +# CONFIG_AD9523 is not set
- +# CONFIG_ADF4350 is not set
- +# CONFIG_ADIS16080 is not set
- +# CONFIG_ADIS16130 is not set
- +# CONFIG_ADIS16136 is not set
- +# CONFIG_ADIS16260 is not set
- +# CONFIG_ADXRS450 is not set
- +# CONFIG_ADIS16400 is not set
- +# CONFIG_ADIS16480 is not set
- +# CONFIG_DHT11 is not set
- +# CONFIG_MPL3115 is not set
- +
- +# staging IIO drivers
- +# CONFIG_AD7291 is not set
- +# CONFIG_AD7606 is not set
- +# CONFIG_AD799X is not set
- +# CONFIG_ADT7316 is not set
- +# CONFIG_AD7150 is not set
- +# CONFIG_AD7152 is not set
- +# CONFIG_AD7746 is not set
- +# CONFIG_AD5933 is not set
- +# CONFIG_ADE7854 is not set
- +# CONFIG_SENSORS_ISL29018 is not set
- +# CONFIG_SENSORS_ISL29028 is not set
- +# CONFIG_SENSORS_HMC5843 is not set
- +# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set
- +# CONFIG_IIO_SIMPLE_DUMMY is not set
- +# CONFIG_ADIS16201 is not set
- +# CONFIG_ADIS16203 is not set
- +# CONFIG_ADIS16204 is not set
- +# CONFIG_ADIS16209 is not set
- +# CONFIG_ADIS16220 is not set
- +# CONFIG_ADIS16240 is not set
- +# CONFIG_LIS3L02DQ is not set
- +# CONFIG_SCA3000 is not set
- +# CONFIG_AD7780 is not set
- +# CONFIG_AD7816 is not set
- +# CONFIG_AD7192 is not set
- +# CONFIG_AD7280 is not set
- +# CONFIG_AD5930 is not set
- +# CONFIG_AD9832 is not set
- +# CONFIG_AD9834 is not set
- +# CONFIG_AD9850 is not set
- +# CONFIG_AD9852 is not set
- +# CONFIG_AD9910 is not set
- +# CONFIG_AD9951 is not set
- +# CONFIG_ADIS16060 is not set
- +# CONFIG_ADE7753 is not set
- +# CONFIG_ADE7754 is not set
- +# CONFIG_ADE7758 is not set
- +# CONFIG_ADE7759 is not set
- +# CONFIG_AD2S90 is not set
- +# CONFIG_AD2S1200 is not set
- +# CONFIG_AD2S1210 is not set
- +
- +
- +
- +# CONFIG_HMC6352 is not set
- +# CONFIG_BMP085 is not set
- +# CONFIG_BMP085_I2C is not set
- +# CONFIG_PCH_PHUB is not set
- +# CONFIG_USB_SWITCH_FSA9480 is not set
- +
- +CONFIG_W1=m
- +CONFIG_W1_CON=y
- +# CONFIG_W1_MASTER_MATROX is not set
- +CONFIG_W1_MASTER_DS2490=m
- +CONFIG_W1_MASTER_DS2482=m
- +CONFIG_W1_MASTER_DS1WM=m
- +CONFIG_W1_MASTER_GPIO=m
- +# CONFIG_HDQ_MASTER_OMAP is not set
- +CONFIG_W1_SLAVE_THERM=m
- +CONFIG_W1_SLAVE_SMEM=m
- +CONFIG_W1_SLAVE_DS2408=m
- +# CONFIG_W1_SLAVE_DS2408_READBACK is not set
- +CONFIG_W1_SLAVE_DS2413=m
- +CONFIG_W1_SLAVE_DS2423=m
- +CONFIG_W1_SLAVE_DS2431=m
- +CONFIG_W1_SLAVE_DS2433=m
- +CONFIG_W1_SLAVE_DS2433_CRC=y
- +CONFIG_W1_SLAVE_DS2760=m
- +CONFIG_W1_SLAVE_DS2780=m
- +CONFIG_W1_SLAVE_DS2781=m
- +CONFIG_W1_SLAVE_DS28E04=m
- +CONFIG_W1_SLAVE_BQ27000=m
- +
- +#
- +# Mice
- +#
- +
- +#
- +# IPMI
- +#
- +CONFIG_IPMI_HANDLER=m
- +# CONFIG_IPMI_PANIC_EVENT is not set
- +CONFIG_IPMI_DEVICE_INTERFACE=m
- +CONFIG_IPMI_WATCHDOG=m
- +CONFIG_IPMI_SI=m
- +CONFIG_IPMI_POWEROFF=m
- +
- +#
- +# Watchdog Cards
- +#
- +CONFIG_WATCHDOG_CORE=y
- +# CONFIG_WATCHDOG_NOWAYOUT is not set
- +CONFIG_SOFT_WATCHDOG=m
- +CONFIG_WDTPCI=m
- +# CONFIG_ACQUIRE_WDT is not set
- +# CONFIG_ADVANTECH_WDT is not set
- +# CONFIG_EUROTECH_WDT is not set
- +CONFIG_IB700_WDT=m
- +# CONFIG_SCx200_WDT is not set
- +# CONFIG_60XX_WDT is not set
- +CONFIG_W83877F_WDT=m
- +CONFIG_W83627HF_WDT=m
- +CONFIG_MACHZ_WDT=m
- +# CONFIG_SC520_WDT is not set
- +CONFIG_ALIM7101_WDT=m
- +CONFIG_ALIM1535_WDT=m
- +CONFIG_IT87_WDT=m
- +CONFIG_ITCO_WDT=m
- +CONFIG_ITCO_VENDOR_SUPPORT=y
- +# CONFIG_SC1200_WDT is not set
- +# CONFIG_PC87413_WDT is not set
- +# CONFIG_WAFER_WDT is not set
- +# CONFIG_CPU5_WDT is not set
- +CONFIG_I6300ESB_WDT=m
- +CONFIG_IT8712F_WDT=m
- +# CONFIG_SBC8360_WDT is not set
- +# CONFIG_SBC7240_WDT is not set
- +CONFIG_SMSC_SCH311X_WDT=m
- +CONFIG_W83977F_WDT=m
- +CONFIG_PCIPCWATCHDOG=m
- +CONFIG_USBPCWATCHDOG=m
- +# CONFIG_SBC_EPX_C3_WATCHDOG is not set
- +CONFIG_WM8350_WATCHDOG=m
- +CONFIG_WM831X_WATCHDOG=m
- +# CONFIG_MAX63XX_WATCHDOG is not set
- +# CONFIG_DW_WATCHDOG is not set
- +CONFIG_W83697UG_WDT=m
- +# CONFIG_MEN_A21_WDT is not set
- +# CONFIG_GPIO_WATCHDOG is not set
- +
- +CONFIG_HW_RANDOM=y
- +CONFIG_HW_RANDOM_TIMERIOMEM=m
- +CONFIG_HW_RANDOM_TPM=m
- +# CONFIG_HW_RANDOM_ATMEL is not set
- +# CONFIG_HW_RANDOM_EXYNOS is not set
- +# CONFIG_NVRAM is not set
- +# CONFIG_RTC is not set
- +# CONFIG_RTC_DEBUG is not set
- +# CONFIG_GEN_RTC is not set
- +CONFIG_RTC_HCTOSYS=y
- +# CONFIG_RTC_SYSTOHC is not set
- +CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
- +CONFIG_RTC_INTF_SYSFS=y
- +CONFIG_RTC_INTF_PROC=y
- +CONFIG_RTC_INTF_DEV=y
- +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
- +CONFIG_RTC_DRV_CMOS=y
- +CONFIG_RTC_DRV_DS1307=m
- +CONFIG_RTC_DRV_DS1511=m
- +CONFIG_RTC_DRV_DS1553=m
- +CONFIG_RTC_DRV_DS1672=m
- +CONFIG_RTC_DRV_DS1742=m
- +CONFIG_RTC_DRV_DS1374=m
- +# CONFIG_RTC_DRV_EP93XX is not set
- +CONFIG_RTC_DRV_FM3130=m
- +CONFIG_RTC_DRV_ISL1208=m
- +CONFIG_RTC_DRV_M41T80=m
- +CONFIG_RTC_DRV_M41T80_WDT=y
- +CONFIG_RTC_DRV_M48T59=m
- +CONFIG_RTC_DRV_MAX6900=m
- +# CONFIG_RTC_DRV_M48T86 is not set
- +CONFIG_RTC_DRV_PCF2127=m
- +CONFIG_RTC_DRV_PCF8563=m
- +CONFIG_RTC_DRV_PCF8583=m
- +CONFIG_RTC_DRV_RS5C372=m
- +# CONFIG_RTC_DRV_SA1100 is not set
- +# CONFIG_RTC_DRV_TEST is not set
- +CONFIG_RTC_DRV_X1205=m
- +CONFIG_RTC_DRV_V3020=m
- +CONFIG_RTC_DRV_DS2404=m
- +CONFIG_RTC_DRV_STK17TA8=m
- +# CONFIG_RTC_DRV_S35390A is not set
- +CONFIG_RTC_DRV_RX8581=m
- +CONFIG_RTC_DRV_RX8025=m
- +CONFIG_RTC_DRV_DS1286=m
- +CONFIG_RTC_DRV_M48T35=m
- +CONFIG_RTC_DRV_BQ4802=m
- +CONFIG_RTC_DRV_WM8350=m
- +# CONFIG_RTC_DRV_AB3100 is not set
- +CONFIG_RTC_DRV_WM831X=m
- +CONFIG_RTC_DRV_BQ32K=m
- +CONFIG_RTC_DRV_MSM6242=m
- +CONFIG_RTC_DRV_RP5C01=m
- +CONFIG_RTC_DRV_EM3027=m
- +CONFIG_RTC_DRV_RV3029C2=m
- +CONFIG_RTC_DRV_PCF50633=m
- +CONFIG_RTC_DRV_DS3232=m
- +CONFIG_RTC_DRV_ISL12022=m
- +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set
- +# CONFIG_RTC_DRV_MOXART is not set
- +# CONFIG_RTC_DRV_ISL12057 is not set
- +
- +CONFIG_R3964=m
- +# CONFIG_APPLICOM is not set
- +# CONFIG_SONYPI is not set
- +
- +#
- +# Ftape, the floppy tape device driver
- +#
- +CONFIG_AGP=y
- +CONFIG_AGP_ALI=y
- +CONFIG_AGP_ATI=y
- +CONFIG_AGP_AMD=y
- +CONFIG_AGP_AMD64=y
- +CONFIG_AGP_INTEL=y
- +CONFIG_AGP_NVIDIA=y
- +CONFIG_AGP_SIS=y
- +CONFIG_AGP_SWORKS=y
- +CONFIG_AGP_VIA=y
- +CONFIG_AGP_EFFICEON=y
- +
- +CONFIG_VGA_ARB=y
- +CONFIG_VGA_ARB_MAX_GPUS=16
- +
- +# CONFIG_STUB_POULSBO is not set
- +
- +#
- +# PCMCIA character devices
- +#
- +# CONFIG_SYNCLINK_CS is not set
- +
- +CONFIG_CARDMAN_4000=m
- +CONFIG_CARDMAN_4040=m
- +
- +CONFIG_MWAVE=m
- +CONFIG_RAW_DRIVER=y
- +CONFIG_MAX_RAW_DEVS=8192
- +CONFIG_HANGCHECK_TIMER=m
- +
- +CONFIG_MEDIA_PCI_SUPPORT=y
- +#
- +# Multimedia devices
- +#
- +CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
- +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
- +CONFIG_MEDIA_RC_SUPPORT=y
- +CONFIG_MEDIA_CONTROLLER=y
- +CONFIG_VIDEO_DEV=m
- +# CONFIG_VIDEO_ADV_DEBUG is not set
- +CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
- +CONFIG_VIDEO_V4L2=y
- +CONFIG_VIDEO_V4L2_SUBDEV_API=y
- +# CONFIG_VIDEO_VIVI is not set
- +# CONFIG_USB_SI4713 is not set
- +# CONFIG_PLATFORM_SI4713 is not set
- +# CONFIG_I2C_SI4713 is not set
- +# CONFIG_USB_RAREMONO is not set
- +
- +#
- +# Video For Linux
- +#
- +
- +#
- +# Video Adapters
- +#
- +CONFIG_V4L_USB_DRIVERS=y
- +CONFIG_VIDEO_CAPTURE_DRIVERS=y
- +CONFIG_V4L_PCI_DRIVERS=y
- +CONFIG_VIDEO_AU0828=m
- +CONFIG_VIDEO_AU0828_V4L2=y
- +CONFIG_VIDEO_BT848=m
- +CONFIG_VIDEO_BT848_DVB=y
- +CONFIG_VIDEO_BWQCAM=m
- +CONFIG_VIDEO_SR030PC30=m
- +CONFIG_VIDEO_NOON010PC30=m
- +CONFIG_VIDEO_CAFE_CCIC=m
- +# CONFIG_VIDEO_CPIA is not set
- +CONFIG_VIDEO_CPIA2=m
- +CONFIG_VIDEO_CQCAM=m
- +CONFIG_VIDEO_CX23885=m
- +CONFIG_MEDIA_ALTERA_CI=m
- +CONFIG_VIDEO_CX18=m
- +CONFIG_VIDEO_CX18_ALSA=m
- +CONFIG_VIDEO_CX88=m
- +CONFIG_VIDEO_CX88_DVB=m
- +CONFIG_VIDEO_CX88_ALSA=m
- +CONFIG_VIDEO_CX88_BLACKBIRD=m
- +CONFIG_VIDEO_CX88_ENABLE_VP3054=y
- +CONFIG_VIDEO_CX88_VP3054=m
- +CONFIG_VIDEO_EM28XX=m
- +CONFIG_VIDEO_EM28XX_V4L2=m
- +CONFIG_VIDEO_EM28XX_ALSA=m
- +CONFIG_VIDEO_EM28XX_DVB=m
- +CONFIG_VIDEO_EM28XX_RC=y
- +CONFIG_VIDEO_CX231XX=m
- +CONFIG_VIDEO_CX231XX_ALSA=m
- +CONFIG_VIDEO_CX231XX_DVB=m
- +CONFIG_VIDEO_CX231XX_RC=y
- +CONFIG_VIDEO_HEXIUM_ORION=m
- +CONFIG_VIDEO_HEXIUM_GEMINI=m
- +CONFIG_VIDEO_IVTV=m
- +# CONFIG_VIDEO_IVTV_ALSA is not set
- +CONFIG_VIDEO_MEYE=m
- +CONFIG_VIDEO_MXB=m
- +CONFIG_VIDEO_PVRUSB2_DVB=y
- +# CONFIG_VIDEO_PMS is not set
- +CONFIG_VIDEO_HDPVR=m
- +CONFIG_VIDEO_SAA6588=m
- +CONFIG_VIDEO_SAA7134=m
- +CONFIG_VIDEO_SAA7134_ALSA=m
- +CONFIG_VIDEO_SAA7134_DVB=m
- +CONFIG_VIDEO_SAA7134_RC=y
- +CONFIG_VIDEO_USBVISION=m
- +CONFIG_VIDEO_STK1160_COMMON=m
- +CONFIG_VIDEO_STK1160=m
- +CONFIG_VIDEO_STK1160_AC97=y
- +CONFIG_VIDEO_W9966=m
- +CONFIG_VIDEO_ZORAN=m
- +CONFIG_VIDEO_ZORAN_AVS6EYES=m
- +CONFIG_VIDEO_ZORAN_BUZ=m
- +CONFIG_VIDEO_ZORAN_DC10=m
- +CONFIG_VIDEO_ZORAN_DC30=m
- +CONFIG_VIDEO_ZORAN_LML33=m
- +CONFIG_VIDEO_ZORAN_LML33R10=m
- +CONFIG_VIDEO_ZORAN_ZR36060=m
- +# CONFIG_V4L_ISA_PARPORT_DRIVERS is not set
- +CONFIG_VIDEO_FB_IVTV=m
- +CONFIG_VIDEO_SAA7164=m
- +CONFIG_VIDEO_TM6000=m
- +CONFIG_VIDEO_TM6000_ALSA=m
- +CONFIG_VIDEO_TM6000_DVB=m
- +CONFIG_VIDEO_TLG2300=m
- +CONFIG_VIDEO_USBTV=m
- +
- +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
- +
- +#
- +# Radio Adapters
- +#
- +CONFIG_RADIO_MAXIRADIO=m
- +CONFIG_RADIO_SHARK=m
- +CONFIG_RADIO_SHARK2=m
- +CONFIG_RADIO_WL1273=m
- +
- +CONFIG_MEDIA_ATTACH=y
- +
- +#
- +# V4L/DVB tuners
- +# Selected automatically by not setting CONFIG_MEDIA_TUNER_CUSTOMISE
- +#
- +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
- +
- +#
- +# Digital Video Broadcasting Devices
- +#
- +CONFIG_DVB_CAPTURE_DRIVERS=y
- +CONFIG_DVB_CORE=m
- +CONFIG_DVB_NET=y
- +CONFIG_DVB_MAX_ADAPTERS=8
- +CONFIG_DVB_DYNAMIC_MINORS=y
- +
- +#
- +# DVB frontends
- +# Selected automatically by not setting CONFIG_DVB_FE_CUSTOMISE
- +#
- +# CONFIG_DVB_FE_CUSTOMISE is not set
- +
- +#
- +# Supported DVB bridge Modules
- +#
- +CONFIG_DVB_BT8XX=m
- +CONFIG_DVB_BUDGET_CORE=m
- +CONFIG_DVB_PLUTO2=m
- +CONFIG_SMS_SIANO_MDTV=m
- +CONFIG_SMS_SIANO_RC=y
- +# CONFIG_SMS_SIANO_DEBUGFS is not set
- +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
- +CONFIG_SMS_USB_DRV=m
- +CONFIG_SMS_SDIO_DRV=m
- +CONFIG_DVB_TTUSB_DEC=m
- +CONFIG_DVB_USB_DTV5100=m
- +CONFIG_DVB_USB_AF9015=m
- +CONFIG_DVB_USB_ANYSEE=m
- +CONFIG_DVB_USB_DW2102=m
- +CONFIG_DVB_USB_FRIIO=m
- +CONFIG_DVB_USB_EC168=m
- +CONFIG_DVB_USB_PCTV452E=m
- +CONFIG_DVB_USB_IT913X=m
- +CONFIG_DVB_USB_MXL111SF=m
- +CONFIG_DVB_DM1105=m
- +CONFIG_DVB_FIREDTV=m
- +CONFIG_DVB_NGENE=m
- +CONFIG_DVB_DDBRIDGE=m
- +CONFIG_DVB_USB_TECHNISAT_USB2=m
- +CONFIG_DVB_USB_V2=m
- +
- +CONFIG_DVB_AV7110=m
- +CONFIG_DVB_AV7110_OSD=y
- +CONFIG_DVB_BUDGET=m
- +CONFIG_DVB_BUDGET_CI=m
- +CONFIG_DVB_BUDGET_AV=m
- +CONFIG_DVB_BUDGET_PATCH=m
- +
- +CONFIG_DVB_TTUSB_BUDGET=m
- +
- +CONFIG_DVB_USB_CINERGY_T2=m
- +CONFIG_DVB_B2C2_FLEXCOP=m
- +# CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG is not set
- +
- +CONFIG_DVB_B2C2_FLEXCOP_PCI=m
- +# CONFIG_DVB_B2C2_FLEXCOP_PCI_DEBUG is not set
- +CONFIG_DVB_B2C2_FLEXCOP_USB=m
- +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
- +CONFIG_DVB_USB=m
- +# CONFIG_DVB_USB_DEBUG is not set
- +CONFIG_DVB_USB_A800=m
- +CONFIG_DVB_USB_AF9005=m
- +CONFIG_DVB_USB_AF9005_REMOTE=m
- +CONFIG_DVB_USB_AU6610=m
- +CONFIG_DVB_USB_CXUSB=m
- +CONFIG_DVB_USB_DIBUSB_MB=m
- +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
- +CONFIG_DVB_USB_DIBUSB_MC=m
- +CONFIG_DVB_USB_DIB0700=m
- +CONFIG_DVB_USB_DIGITV=m
- +CONFIG_DVB_USB_DTT200U=m
- +CONFIG_DVB_USB_GL861=m
- +CONFIG_DVB_USB_GP8PSK=m
- +CONFIG_DVB_USB_M920X=m
- +CONFIG_DVB_USB_NOVA_T_USB2=m
- +CONFIG_DVB_USB_CE6230=m
- +CONFIG_DVB_USB_OPERA1=m
- +CONFIG_DVB_USB_TTUSB2=m
- +CONFIG_DVB_USB_UMT_010=m
- +CONFIG_DVB_USB_VP702X=m
- +CONFIG_DVB_USB_VP7045=m
- +CONFIG_DVB_USB_AZ6027=m
- +CONFIG_DVB_USB_AZ6007=m
- +CONFIG_DVB_USB_LME2510=m
- +CONFIG_DVB_USB_RTL28XXU=m
- +CONFIG_DVB_USB_AF9035=m
- +
- +CONFIG_DVB_PT1=m
- +
- +CONFIG_MANTIS_CORE=m
- +CONFIG_DVB_MANTIS=m
- +CONFIG_DVB_HOPPER=m
- +
- +CONFIG_VIDEO_SAA7146=m
- +CONFIG_VIDEO_SAA7146_VV=m
- +CONFIG_VIDEO_TVP5150=m
- +CONFIG_VIDEO_TUNER=m
- +CONFIG_VIDEO_BTCX=m
- +CONFIG_VIDEO_PVRUSB2=m
- +CONFIG_VIDEO_PVRUSB2_SYSFS=y
- +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
- +
- +CONFIG_RC_CORE=m
- +CONFIG_RC_DECODERS=y
- +CONFIG_LIRC=m
- +CONFIG_RC_LOOPBACK=m
- +CONFIG_RC_MAP=m
- +CONFIG_RC_DEVICES=y
- +CONFIG_RC_ATI_REMOTE=m
- +CONFIG_IR_NEC_DECODER=m
- +CONFIG_IR_RC5_DECODER=m
- +CONFIG_IR_RC6_DECODER=m
- +CONFIG_IR_JVC_DECODER=m
- +CONFIG_IR_SONY_DECODER=m
- +CONFIG_IR_RC5_SZ_DECODER=m
- +CONFIG_IR_SANYO_DECODER=m
- +CONFIG_IR_MCE_KBD_DECODER=m
- +CONFIG_IR_LIRC_CODEC=m
- +CONFIG_IR_IMON=m
- +CONFIG_IR_MCEUSB=m
- +CONFIG_IR_ITE_CIR=m
- +CONFIG_IR_NUVOTON=m
- +CONFIG_IR_FINTEK=m
- +CONFIG_IR_REDRAT3=m
- +CONFIG_IR_ENE=m
- +CONFIG_IR_STREAMZAP=m
- +CONFIG_IR_WINBOND_CIR=m
- +CONFIG_IR_IGUANA=m
- +CONFIG_IR_TTUSBIR=m
- +CONFIG_IR_GPIO_CIR=m
- +
- +CONFIG_V4L_MEM2MEM_DRIVERS=y
- +# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set
- +# CONFIG_VIDEO_SH_VEU is not set
- +# CONFIG_VIDEO_RENESAS_VSP1 is not set
- +# CONFIG_V4L_TEST_DRIVERS is not set
- +
- +# CONFIG_VIDEO_MEM2MEM_TESTDEV is not set
- +
- +#
- +# Broadcom Crystal HD video decoder driver
- +#
- +CONFIG_CRYSTALHD=m
- +
- +#
- +# Graphics support
- +#
- +
- +CONFIG_DISPLAY_SUPPORT=m
- +CONFIG_VIDEO_OUTPUT_CONTROL=m
- +
- +#
- +# Console display driver support
- +#
- +CONFIG_VGA_CONSOLE=y
- +CONFIG_VGACON_SOFT_SCROLLBACK=y
- +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
- +CONFIG_DUMMY_CONSOLE=y
- +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
- +
- +#
- +# Logo configuration
- +#
- +# CONFIG_LOGO_LINUX_MONO is not set
- +# CONFIG_LOGO_LINUX_VGA16 is not set
- +CONFIG_LOGO_LINUX_CLUT224=y
- +
- +#
- +# Sound
- +#
- +
- +#
- +# Advanced Linux Sound Architecture
- +#
- +CONFIG_SOUND_OSS_CORE_PRECLAIM=y
- +# CONFIG_SND_DEBUG_VERBOSE is not set
- +CONFIG_SND_VERBOSE_PROCFS=y
- +CONFIG_SND_SEQUENCER=y
- +CONFIG_SND_HRTIMER=y
- +CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
- +CONFIG_SND_SEQ_DUMMY=m
- +CONFIG_SND_SEQUENCER_OSS=y
- +CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
- +CONFIG_SND_OSSEMUL=y
- +CONFIG_SND_MIXER_OSS=y
- +CONFIG_SND_PCM_OSS=y
- +CONFIG_SND_PCM_OSS_PLUGINS=y
- +CONFIG_SND_RTCTIMER=y
- +CONFIG_SND_DYNAMIC_MINORS=y
- +CONFIG_SND_MAX_CARDS=32
- +# CONFIG_SND_SUPPORT_OLD_API is not set
- +
- +#
- +# Generic devices
- +#
- +CONFIG_SND_DUMMY=m
- +CONFIG_SND_ALOOP=m
- +CONFIG_SND_VIRMIDI=m
- +CONFIG_SND_MTPAV=m
- +CONFIG_SND_MTS64=m
- +CONFIG_SND_SERIAL_U16550=m
- +CONFIG_SND_MPU401=m
- +CONFIG_SND_PORTMAN2X4=m
- +CONFIG_SND_AC97_POWER_SAVE=y
- +CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0
- +
- +CONFIG_SND_DRIVERS=y
- +
- +#
- +# ISA devices
- +#
- +CONFIG_SND_AD1889=m
- +
- +#
- +# PCI devices
- +#
- +CONFIG_SND_PCI=y
- +CONFIG_SND_ALI5451=m
- +CONFIG_SND_ALS300=m
- +CONFIG_SND_ALS4000=m
- +CONFIG_SND_ATIIXP=m
- +CONFIG_SND_ATIIXP_MODEM=m
- +CONFIG_SND_AU8810=m
- +CONFIG_SND_AU8820=m
- +CONFIG_SND_AU8830=m
- +# CONFIG_SND_AW2 is not set
- +CONFIG_SND_AZT3328=m
- +CONFIG_SND_BT87X=m
- +# CONFIG_SND_BT87X_OVERCLOCK is not set
- +CONFIG_SND_CA0106=m
- +CONFIG_SND_CMIPCI=m
- +CONFIG_SND_CS46XX=m
- +CONFIG_SND_CS46XX_NEW_DSP=y
- +CONFIG_SND_CS4281=m
- +CONFIG_SND_CS5530=m
- +CONFIG_SND_CS5535AUDIO=m
- +CONFIG_SND_EMU10K1=m
- +CONFIG_SND_EMU10K1X=m
- +CONFIG_SND_ENS1370=m
- +CONFIG_SND_ENS1371=m
- +CONFIG_SND_ES1938=m
- +CONFIG_SND_ES1968=m
- +CONFIG_SND_ES1968_INPUT=y
- +CONFIG_SND_ES1968_RADIO=y
- +CONFIG_SND_FM801=m
- +CONFIG_SND_FM801_TEA575X_BOOL=y
- +CONFIG_SND_CTXFI=m
- +CONFIG_SND_LX6464ES=m
- +CONFIG_SND_HDA_INTEL=y
- +CONFIG_SND_HDA_INPUT_BEEP=y
- +CONFIG_SND_HDA_INPUT_BEEP_MODE=0
- +CONFIG_SND_HDA_INPUT_JACK=y
- +CONFIG_SND_HDA_PATCH_LOADER=y
- +CONFIG_SND_HDA_HWDEP=y
- +CONFIG_SND_HDA_CODEC_REALTEK=y
- +CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS=y
- +CONFIG_SND_HDA_CODEC_CA0110=y
- +CONFIG_SND_HDA_CODEC_ANALOG=y
- +CONFIG_SND_HDA_CODEC_SIGMATEL=y
- +CONFIG_SND_HDA_CODEC_VIA=y
- +CONFIG_SND_HDA_CODEC_CIRRUS=y
- +CONFIG_SND_HDA_CODEC_CONEXANT=y
- +CONFIG_SND_HDA_CODEC_CMEDIA=y
- +CONFIG_SND_HDA_CODEC_SI3054=y
- +CONFIG_SND_HDA_CODEC_HDMI=y
- +CONFIG_SND_HDA_I915=y
- +CONFIG_SND_HDA_CODEC_CA0132=y
- +CONFIG_SND_HDA_CODEC_CA0132_DSP=y
- +CONFIG_SND_HDA_GENERIC=y
- +CONFIG_SND_HDA_POWER_SAVE=y
- +CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0
- +CONFIG_SND_HDA_RECONFIG=y
- +CONFIG_SND_HDA_PREALLOC_SIZE=4096
- +CONFIG_SND_HDSPM=m
- +CONFIG_SND_ICE1712=m
- +CONFIG_SND_ICE1724=m
- +CONFIG_SND_INTEL8X0=y
- +CONFIG_SND_INTEL8X0M=m
- +CONFIG_SND_KORG1212=m
- +CONFIG_SND_MAESTRO3=m
- +CONFIG_SND_MAESTRO3_INPUT=y
- +CONFIG_SND_MIXART=m
- +CONFIG_SND_NM256=m
- +CONFIG_SND_OXYGEN=m
- +CONFIG_SND_RME32=m
- +CONFIG_SND_PCSP=m
- +CONFIG_SND_PCXHR=m
- +CONFIG_SND_RIPTIDE=m
- +CONFIG_SND_RME96=m
- +CONFIG_SND_RME9652=m
- +CONFIG_SND_SIS7019=m
- +CONFIG_SND_SONICVIBES=m
- +CONFIG_SND_HDSP=m
- +CONFIG_SND_TRIDENT=m
- +CONFIG_SND_VIA82XX=m
- +CONFIG_SND_VIA82XX_MODEM=m
- +CONFIG_SND_VIRTUOSO=m
- +CONFIG_SND_VX222=m
- +CONFIG_SND_YMFPCI=m
- +CONFIG_SND_ASIHPI=m
- +CONFIG_SND_LOLA=m
- +
- +#
- +# ALSA USB devices
- +#
- +CONFIG_SND_USB=y
- +CONFIG_SND_USB_CAIAQ=m
- +CONFIG_SND_USB_CAIAQ_INPUT=y
- +CONFIG_SND_USB_USX2Y=m
- +CONFIG_SND_USB_US122L=m
- +CONFIG_SND_USB_UA101=m
- +CONFIG_SND_USB_6FIRE=m
- +CONFIG_SND_USB_HIFACE=m
- +
- +#
- +# PCMCIA devices
- +#
- +# CONFIG_SND_PCMCIA is not set
- +
- +CONFIG_SND_FIREWIRE=y
- +CONFIG_SND_FIREWIRE_SPEAKERS=m
- +CONFIG_SND_ISIGHT=m
- +CONFIG_SND_SCS1X=m
- +CONFIG_SND_DICE=m
- +
- +#
- +# Open Sound System
- +#
- +# CONFIG_SOUND_PRIME is not set
- +
- +#
- +# USB support
- +#
- +CONFIG_USB_SUPPORT=y
- +# CONFIG_USB_DEBUG is not set
- +
- +# DEPRECATED: See bug 362221. Fix udev.
- +# CONFIG_USB_DEVICE_CLASS is not set
- +
- +
- +#
- +# Miscellaneous USB options
- +#
- +
- +# Deprecated.
- +# CONFIG_USB_DEVICEFS is not set
- +
- +CONFIG_USB_DEFAULT_PERSIST=y
- +# CONFIG_USB_DYNAMIC_MINORS is not set
- +CONFIG_USB_SUSPEND=y
- +
- +#
- +# USB Host Controller Drivers
- +#
- +CONFIG_USB_EHCI_ROOT_HUB_TT=y
- +CONFIG_USB_EHCI_TT_NEWSCHED=y
- +# CONFIG_USB_EHCI_MV is not set
- +# CONFIG_USB_EHCI_HCD_PLATFORM is not set
- +# CONFIG_USB_ISP116X_HCD is not set
- +# CONFIG_USB_ISP1760_HCD is not set
- +CONFIG_USB_ISP1362_HCD=m
- +CONFIG_USB_FUSBH200_HCD=m
- +# CONFIG_USB_FOTG210_HCD is not set
- +# CONFIG_USB_GR_UDC is not set
- +CONFIG_USB_OHCI_HCD=y
- +CONFIG_USB_OHCI_HCD_PCI=y
- +# CONFIG_USB_OHCI_HCD_SSB is not set
- +# CONFIG_USB_HCD_TEST_MODE is not set
- +# CONFIG_USB_OHCI_HCD_PLATFORM is not set
- +CONFIG_USB_UHCI_HCD=y
- +CONFIG_USB_SL811_HCD=m
- +CONFIG_USB_SL811_HCD_ISO=y
- +# CONFIG_USB_SL811_CS is not set
- +# CONFIG_USB_R8A66597_HCD is not set
- +CONFIG_USB_XHCI_HCD=y
- +# CONFIG_USB_XHCI_HCD_DEBUGGING is not set
- +
- +#
- +# USB Device Class drivers
- +#
- +
- +#
- +# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
- +#
- +CONFIG_USB_ACM=m
- +CONFIG_USB_PRINTER=m
- +CONFIG_USB_WDM=m
- +CONFIG_USB_TMC=m
- +# CONFIG_BLK_DEV_UB is not set
- +# CONFIG_USB_STORAGE_DEBUG is not set
- +CONFIG_USB_STORAGE_CYPRESS_ATACB=m
- +CONFIG_USB_STORAGE_DATAFAB=m
- +CONFIG_USB_STORAGE_FREECOM=m
- +CONFIG_USB_STORAGE_ISD200=m
- +CONFIG_USB_STORAGE_SDDR09=m
- +CONFIG_USB_STORAGE_SDDR55=m
- +CONFIG_USB_STORAGE_JUMPSHOT=m
- +CONFIG_USB_STORAGE_USBAT=y
- +CONFIG_USB_STORAGE_ONETOUCH=m
- +CONFIG_USB_STORAGE_ALAUDA=m
- +CONFIG_USB_STORAGE_KARMA=m
- +CONFIG_USB_STORAGE_REALTEK=m
- +CONFIG_REALTEK_AUTOPM=y
- +CONFIG_USB_STORAGE_ENE_UB6250=m
- +# CONFIG_USB_LIBUSUAL is not set
- +# CONFIG_USB_UAS is not set
- +
- +
- +#
- +# USB Human Interface Devices (HID)
- +#
- +CONFIG_USB_HID=y
- +
- +CONFIG_HID_SUPPORT=y
- +
- +CONFIG_HID=y
- +CONFIG_I2C_HID=m
- +CONFIG_HID_BATTERY_STRENGTH=y
- +# debugging default is y upstream now
- +CONFIG_HIDRAW=y
- +CONFIG_UHID=m
- +CONFIG_HID_PID=y
- +CONFIG_LOGITECH_FF=y
- +CONFIG_HID_LOGITECH_DJ=m
- +CONFIG_LOGIWII_FF=y
- +CONFIG_LOGIRUMBLEPAD2_FF=y
- +CONFIG_PANTHERLORD_FF=y
- +CONFIG_THRUSTMASTER_FF=y
- +CONFIG_HID_WACOM=m
- +CONFIG_HID_WACOM_POWER_SUPPLY=y
- +CONFIG_ZEROPLUS_FF=y
- +CONFIG_USB_HIDDEV=y
- +CONFIG_USB_IDMOUSE=m
- +CONFIG_DRAGONRISE_FF=y
- +CONFIG_GREENASIA_FF=y
- +CONFIG_SMARTJOYPLUS_FF=y
- +CONFIG_LOGIG940_FF=y
- +CONFIG_LOGIWHEELS_FF=y
- +CONFIG_HID_MAGICMOUSE=y
- +CONFIG_HID_MULTITOUCH=m
- +CONFIG_HID_NTRIG=y
- +CONFIG_HID_QUANTA=y
- +CONFIG_HID_PRIMAX=m
- +CONFIG_HID_PS3REMOTE=m
- +CONFIG_HID_PRODIKEYS=m
- +CONFIG_HID_DRAGONRISE=m
- +CONFIG_HID_GYRATION=m
- +CONFIG_HID_ICADE=m
- +CONFIG_HID_TWINHAN=m
- +CONFIG_HID_ORTEK=m
- +CONFIG_HID_PANTHERLORD=m
- +CONFIG_HID_PETALYNX=m
- +CONFIG_HID_PICOLCD=m
- +CONFIG_HID_RMI=m
- +CONFIG_HID_ROCCAT=m
- +CONFIG_HID_ROCCAT_KONE=m
- +CONFIG_HID_SAMSUNG=m
- +CONFIG_HID_SONY=m
- +CONFIG_SONY_FF=y
- +CONFIG_HID_SUNPLUS=m
- +CONFIG_HID_STEELSERIES=m
- +CONFIG_HID_GREENASIA=m
- +CONFIG_HID_SMARTJOYPLUS=m
- +CONFIG_HID_TOPSEED=m
- +CONFIG_HID_THINGM=m
- +CONFIG_HID_THRUSTMASTER=m
- +CONFIG_HID_XINMO=m
- +CONFIG_HID_ZEROPLUS=m
- +CONFIG_HID_ZYDACRON=m
- +CONFIG_HID_SENSOR_HUB=m
- +CONFIG_HID_SENSOR_GYRO_3D=m
- +CONFIG_HID_SENSOR_MAGNETOMETER_3D=m
- +CONFIG_HID_SENSOR_ALS=m
- +CONFIG_HID_SENSOR_ACCEL_3D=m
- +CONFIG_HID_EMS_FF=m
- +CONFIG_HID_ELECOM=m
- +CONFIG_HID_ELO=m
- +CONFIG_HID_UCLOGIC=m
- +CONFIG_HID_WALTOP=m
- +CONFIG_HID_ROCCAT_PYRA=m
- +CONFIG_HID_ROCCAT_KONEPLUS=m
- +CONFIG_HID_ACRUX=m
- +CONFIG_HID_ACRUX_FF=y
- +CONFIG_HID_KEYTOUCH=m
- +CONFIG_HID_LCPOWER=m
- +CONFIG_HID_LENOVO_TPKBD=m
- +CONFIG_HID_ROCCAT_ARVO=m
- +CONFIG_HID_ROCCAT_ISKU=m
- +CONFIG_HID_ROCCAT_KOVAPLUS=m
- +CONFIG_HID_HOLTEK=m
- +CONFIG_HOLTEK_FF=y
- +CONFIG_HID_HUION=m
- +CONFIG_HID_SPEEDLINK=m
- +CONFIG_HID_WIIMOTE=m
- +CONFIG_HID_WIIMOTE_EXT=y
- +CONFIG_HID_KYE=m
- +CONFIG_HID_SAITEK=m
- +CONFIG_HID_TIVO=m
- +CONFIG_HID_GENERIC=y
- +CONFIG_HID_AUREAL=m
- +CONFIG_HID_APPLEIR=m
- +
- +
- +#
- +# USB Imaging devices
- +#
- +CONFIG_USB_MDC800=m
- +CONFIG_USB_MICROTEK=m
- +
- +#
- +# USB Multimedia devices
- +#
- +
- +CONFIG_USB_DSBR=m
- +# CONFIG_USB_ET61X251 is not set
- +CONFIG_USB_M5602=m
- +CONFIG_USB_STV06XX=m
- +CONFIG_USB_GSPCA=m
- +CONFIG_USB_GSPCA_MR97310A=m
- +CONFIG_USB_GSPCA_BENQ=m
- +CONFIG_USB_GSPCA_CONEX=m
- +CONFIG_USB_GSPCA_CPIA1=m
- +CONFIG_USB_GSPCA_ETOMS=m
- +CONFIG_USB_GSPCA_FINEPIX=m
- +CONFIG_USB_GSPCA_MARS=m
- +CONFIG_USB_GSPCA_OV519=m
- +CONFIG_USB_GSPCA_OV534=m
- +CONFIG_USB_GSPCA_OV534_9=m
- +CONFIG_USB_GSPCA_PAC207=m
- +CONFIG_USB_GSPCA_PAC7311=m
- +CONFIG_USB_GSPCA_SN9C2028=m
- +CONFIG_USB_GSPCA_SN9C20X=m
- +CONFIG_USB_GSPCA_SONIXB=m
- +CONFIG_USB_GSPCA_SONIXJ=m
- +CONFIG_USB_GSPCA_SPCA500=m
- +CONFIG_USB_GSPCA_SPCA501=m
- +CONFIG_USB_GSPCA_SPCA505=m
- +CONFIG_USB_GSPCA_SPCA506=m
- +CONFIG_USB_GSPCA_SPCA508=m
- +CONFIG_USB_GSPCA_SPCA561=m
- +CONFIG_USB_GSPCA_STK014=m
- +CONFIG_USB_GSPCA_STK1135=m
- +CONFIG_USB_GSPCA_SUNPLUS=m
- +CONFIG_USB_GSPCA_T613=m
- +CONFIG_USB_GSPCA_TOPRO=m
- +CONFIG_USB_GSPCA_TV8532=m
- +CONFIG_USB_GSPCA_VC032X=m
- +CONFIG_USB_GSPCA_ZC3XX=m
- +CONFIG_USB_GSPCA_SQ905=m
- +CONFIG_USB_GSPCA_SQ905C=m
- +CONFIG_USB_GSPCA_PAC7302=m
- +CONFIG_USB_GSPCA_STV0680=m
- +CONFIG_USB_GL860=m
- +CONFIG_USB_GSPCA_JEILINJ=m
- +CONFIG_USB_GSPCA_JL2005BCD=m
- +CONFIG_USB_GSPCA_KONICA=m
- +CONFIG_USB_GSPCA_XIRLINK_CIT=m
- +CONFIG_USB_GSPCA_SPCA1528=m
- +CONFIG_USB_GSPCA_SQ930X=m
- +CONFIG_USB_GSPCA_NW80X=m
- +CONFIG_USB_GSPCA_VICAM=m
- +CONFIG_USB_GSPCA_KINECT=m
- +CONFIG_USB_GSPCA_SE401=m
- +
- +CONFIG_USB_S2255=m
- +# CONFIG_VIDEO_SH_MOBILE_CEU is not set
- +# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set
- +# CONFIG_USB_SN9C102 is not set
- +CONFIG_USB_ZR364XX=m
- +
- +#
- +# USB Network adaptors
- +#
- +CONFIG_USB_CATC=m
- +CONFIG_USB_HSO=m
- +CONFIG_USB_KAWETH=m
- +CONFIG_USB_PEGASUS=m
- +CONFIG_USB_RTL8150=m
- +CONFIG_USB_RTL8152=m
- +CONFIG_USB_USBNET=m
- +CONFIG_USB_SPEEDTOUCH=m
- +CONFIG_USB_NET_AX8817X=m
- +CONFIG_USB_NET_AX88179_178A=m
- +CONFIG_USB_NET_DM9601=m
- +CONFIG_USB_NET_SR9700=m
- +CONFIG_USB_NET_SMSC95XX=m
- +CONFIG_USB_NET_GL620A=m
- +CONFIG_USB_NET_NET1080=m
- +CONFIG_USB_NET_PLUSB=m
- +CONFIG_USB_NET_MCS7830=m
- +CONFIG_USB_NET_RNDIS_HOST=m
- +CONFIG_USB_NET_CDC_SUBSET=m
- +CONFIG_USB_NET_CDC_EEM=m
- +CONFIG_USB_NET_CDC_NCM=m
- +CONFIG_USB_NET_HUAWEI_CDC_NCM=m
- +CONFIG_USB_NET_CDC_MBIM=m
- +CONFIG_USB_NET_ZAURUS=m
- +CONFIG_USB_NET_CX82310_ETH=m
- +CONFIG_USB_NET_INT51X1=m
- +CONFIG_USB_CDC_PHONET=m
- +CONFIG_USB_IPHETH=m
- +CONFIG_USB_SIERRA_NET=m
- +CONFIG_USB_VL600=m
- +
- +#
- +# USB Host-to-Host Cables
- +#
- +CONFIG_USB_AN2720=y
- +CONFIG_USB_BELKIN=y
- +
- +#
- +# Intelligent USB Devices/Gadgets
- +#
- +CONFIG_USB_ARMLINUX=y
- +CONFIG_USB_EPSON2888=y
- +CONFIG_USB_KC2190=y
- +
- +# CONFIG_USB_MUSB_HDRC is not set
- +
- +#
- +# USB port drivers
- +#
- +CONFIG_USB_USS720=m
- +
- +#
- +# USB Serial Converter support
- +#
- +CONFIG_USB_SERIAL=y
- +CONFIG_USB_SERIAL_GENERIC=y
- +CONFIG_USB_SERIAL_SIMPLE=m
- +CONFIG_USB_SERIAL_AIRCABLE=m
- +CONFIG_USB_SERIAL_ARK3116=m
- +CONFIG_USB_SERIAL_BELKIN=m
- +CONFIG_USB_SERIAL_CH341=m
- +CONFIG_USB_SERIAL_CYPRESS_M8=m
- +CONFIG_USB_SERIAL_CYBERJACK=m
- +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
- +CONFIG_USB_SERIAL_CP210X=m
- +CONFIG_USB_SERIAL_QUALCOMM=m
- +CONFIG_USB_SERIAL_SYMBOL=m
- +CONFIG_USB_SERIAL_EDGEPORT=m
- +CONFIG_USB_SERIAL_EDGEPORT_TI=m
- +CONFIG_USB_SERIAL_EMPEG=m
- +# CONFIG_USB_SERIAL_F81232 is not set
- +CONFIG_USB_SERIAL_FTDI_SIO=m
- +CONFIG_USB_SERIAL_FUNSOFT=m
- +CONFIG_USB_SERIAL_GARMIN=m
- +CONFIG_USB_SERIAL_HP4X=m
- +CONFIG_USB_SERIAL_IPAQ=m
- +CONFIG_USB_SERIAL_IPW=m
- +CONFIG_USB_SERIAL_IR=m
- +CONFIG_USB_SERIAL_IUU=m
- +CONFIG_USB_SERIAL_KEYSPAN_PDA=m
- +CONFIG_USB_SERIAL_KEYSPAN=m
- +CONFIG_USB_SERIAL_KEYSPAN_MPR=y
- +CONFIG_USB_SERIAL_KEYSPAN_USA28=y
- +CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
- +CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
- +CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
- +CONFIG_USB_SERIAL_KEYSPAN_USA19=y
- +CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
- +CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
- +CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
- +CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
- +CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
- +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
- +CONFIG_USB_SERIAL_KLSI=m
- +CONFIG_USB_SERIAL_KOBIL_SCT=m
- +CONFIG_USB_SERIAL_MCT_U232=m
- +# CONFIG_USB_SERIAL_METRO is not set
- +CONFIG_USB_SERIAL_MOS7720=m
- +CONFIG_USB_SERIAL_MOS7715_PARPORT=y
- +# CONFIG_USB_SERIAL_ZIO is not set
- +# CONFIG_USB_SERIAL_WISHBONE is not set
- +# CONFIG_USB_SERIAL_ZTE is not set
- +CONFIG_USB_SERIAL_MOS7840=m
- +CONFIG_USB_SERIAL_MOTOROLA=m
- +# CONFIG_USB_SERIAL_MXUPORT is not set
- +CONFIG_USB_SERIAL_NAVMAN=m
- +CONFIG_USB_SERIAL_OPTION=m
- +CONFIG_USB_SERIAL_OTI6858=m
- +CONFIG_USB_SERIAL_OPTICON=m
- +CONFIG_USB_SERIAL_OMNINET=m
- +CONFIG_USB_SERIAL_PL2303=m
- +# CONFIG_USB_SERIAL_QUATECH2 is not set
- +CONFIG_USB_SERIAL_SAFE=m
- +CONFIG_USB_SERIAL_SAFE_PADDED=y
- +CONFIG_USB_SERIAL_SIERRAWIRELESS=m
- +CONFIG_USB_SERIAL_SIEMENS_MPI=m
- +CONFIG_USB_SERIAL_SPCP8X5=m
- +CONFIG_USB_SERIAL_TI=m
- +CONFIG_USB_SERIAL_VISOR=m
- +CONFIG_USB_SERIAL_WHITEHEAT=m
- +CONFIG_USB_SERIAL_XIRCOM=m
- +CONFIG_USB_SERIAL_QCAUX=m
- +CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
- +CONFIG_USB_SERIAL_XSENS_MT=m
- +CONFIG_USB_SERIAL_DEBUG=m
- +CONFIG_USB_SERIAL_SSU100=m
- +CONFIG_USB_SERIAL_QT2=m
- +CONFIG_USB_SERIAL_FLASHLOADER=m
- +CONFIG_USB_SERIAL_SUUNTO=m
- +CONFIG_USB_SERIAL_CONSOLE=y
- +
- +CONFIG_USB_EZUSB=y
- +CONFIG_USB_EMI62=m
- +CONFIG_USB_LED=m
- +# CONFIG_USB_CYPRESS_CY7C63 is not set
- +
- +#
- +# USB Miscellaneous drivers
- +#
- +
- +CONFIG_USB_ADUTUX=m
- +CONFIG_USB_SEVSEG=m
- +CONFIG_USB_ALI_M5632=y
- +CONFIG_USB_APPLEDISPLAY=m
- +
- +# Physical Layer USB driver
- +# CONFIG_USB_OTG_FSM is not set
- +
- +# CONFIG_GENERIC_PHY is not set
- +# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set
- +# CONFIG_PHY_EXYNOS_DP_VIDEO is not set
- +# CONFIG_OMAP_USB2 is not set
- +# CONFIG_OMAP_USB3 is not set
- +# CONFIG_OMAP_CONTROL_USB is not set
- +# CONFIG_AM335X_PHY_USB is not set
- +# CONFIG_SAMSUNG_USBPHY is not set
- +# CONFIG_SAMSUNG_USB2PHY is not set
- +# CONFIG_SAMSUNG_USB3PHY is not set
- +# CONFIG_BCM_KONA_USB2_PHY is not set
- +CONFIG_USB_RCAR_PHY=m
- +CONFIG_USB_ATM=m
- +CONFIG_USB_CXACRU=m
- +# CONFIG_USB_C67X00_HCD is not set
- +# CONFIG_USB_CYTHERM is not set
- +CONFIG_USB_EMI26=m
- +CONFIG_USB_FTDI_ELAN=m
- +CONFIG_USB_FILE_STORAGE=m
- +# CONFIG_USB_FILE_STORAGE_TEST is not set
- +# CONFIG_USB_DWC3 is not set
- +# CONFIG_USB_GADGETFS is not set
- +# CONFIG_USB_OXU210HP_HCD is not set
- +CONFIG_USB_IOWARRIOR=m
- +CONFIG_USB_ISIGHTFW=m
- +CONFIG_USB_YUREX=m
- +CONFIG_USB_EZUSB_FX2=m
- +CONFIG_USB_HSIC_USB3503=m
- +CONFIG_USB_LCD=m
- +CONFIG_USB_LD=m
- +CONFIG_USB_LEGOTOWER=m
- +CONFIG_USB_MON=y
- +CONFIG_USB_PWC=m
- +CONFIG_USB_PWC_INPUT_EVDEV=y
- +# CONFIG_USB_PWC_DEBUG is not set
- +# CONFIG_USB_RIO500 is not set
- +CONFIG_USB_SISUSBVGA=m
- +CONFIG_USB_SISUSBVGA_CON=y
- +CONFIG_RADIO_SI470X=y
- +CONFIG_USB_KEENE=m
- +CONFIG_USB_MA901=m
- +CONFIG_USB_SI470X=m
- +CONFIG_I2C_SI470X=m
- +CONFIG_RADIO_SI4713=m
- +# CONFIG_RADIO_TEF6862 is not set
- +CONFIG_USB_MR800=m
- +CONFIG_USB_STKWEBCAM=m
- +# CONFIG_USB_TEST is not set
- +# CONFIG_USB_EHSET_TEST_FIXTURE is not set
- +CONFIG_USB_TRANCEVIBRATOR=m
- +CONFIG_USB_U132_HCD=m
- +CONFIG_USB_UEAGLEATM=m
- +CONFIG_USB_XUSBATM=m
- +
- +# CONFIG_USB_DWC2 is not set
- +
- +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
- +
- +# CONFIG_USB_ISP1301 is not set
- +
- +# CONFIG_USB_OTG is not set
- +
- +#
- +# Sonics Silicon Backplane
- +#
- +CONFIG_SSB=m
- +CONFIG_SSB_PCIHOST=y
- +CONFIG_SSB_SDIOHOST=y
- +CONFIG_SSB_PCMCIAHOST=y
- +# CONFIG_SSB_SILENT is not set
- +# CONFIG_SSB_DEBUG is not set
- +CONFIG_SSB_DRIVER_PCICORE=y
- +CONFIG_SSB_DRIVER_GPIO=y
- +
- +# Multifunction USB devices
- +# CONFIG_MFD_PCF50633 is not set
- +CONFIG_PCF50633_ADC=m
- +CONFIG_PCF50633_GPIO=m
- +# CONFIG_AB3100_CORE is not set
- +CONFIG_INPUT_PCF50633_PMU=m
- +CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
- +
- +CONFIG_MFD_SUPPORT=y
- +CONFIG_MFD_VX855=m
- +CONFIG_MFD_SM501=m
- +CONFIG_MFD_SM501_GPIO=y
- +CONFIG_MFD_RTSX_PCI=m
- +# CONFIG_MFD_TI_AM335X_TSCADC is not set
- +CONFIG_MFD_VIPERBOARD=m
- +# CONFIG_MFD_RETU is not set
- +# CONFIG_MFD_TC6393XB is not set
- +# CONFIG_MFD_WM8400 is not set
- +# CONFIG_MFD_WM8350_I2C is not set
- +# CONFIG_MFD_WM8350 is not set
- +# CONFIG_MFD_WM831X is not set
- +# CONFIG_AB3100_OTP is not set
- +# CONFIG_MFD_TIMBERDALE is not set
- +# CONFIG_MFD_WM8994 is not set
- +# CONFIG_MFD_88PM860X is not set
- +# CONFIG_LPC_SCH is not set
- +# CONFIG_LPC_ICH is not set
- +# CONFIG_HTC_I2CPLD is not set
- +# CONFIG_MFD_MAX8925 is not set
- +# CONFIG_MFD_ASIC3 is not set
- +# CONFIG_MFD_AS3722 is not set
- +# CONFIG_HTC_EGPIO is not set
- +# CONFIG_TPS6507X is not set
- +# CONFIG_ABX500_CORE is not set
- +# CONFIG_MFD_RDC321X is not set
- +# CONFIG_MFD_JANZ_CMODIO is not set
- +# CONFIG_MFD_KEMPLD is not set
- +# CONFIG_MFD_WM831X_I2C is not set
- +# CONFIG_MFD_CS5535 is not set
- +# CONFIG_MFD_STMPE is not set
- +# CONFIG_MFD_MAX8998 is not set
- +# CONFIG_MFD_TPS6586X is not set
- +# CONFIG_MFD_TC3589X is not set
- +# CONFIG_MFD_WL1273_CORE is not set
- +# CONFIG_MFD_TPS65217 is not set
- +# CONFIG_MFD_LM3533 is not set
- +# CONFIG_MFD_ARIZONA is not set
- +# CONFIG_MFD_ARIZONA_I2C is not set
- +# CONFIG_MFD_CROS_EC is not set
- +# CONFIG_MFD_TPS65912 is not set
- +# CONFIG_MFD_SYSCON is not set
- +# CONFIG_MFD_DA9063 is not set
- +# CONFIG_MFD_LP3943 is not set
- +
- +#
- +# File systems
- +#
- +CONFIG_MISC_FILESYSTEMS=y
- +
- +# ext4 is used for ext2 and ext3 filesystems
- +CONFIG_JBD2=y
- +CONFIG_FS_MBCACHE=y
- +CONFIG_REISERFS_FS=m
- +# CONFIG_REISERFS_CHECK is not set
- +CONFIG_REISERFS_PROC_INFO=y
- +CONFIG_REISERFS_FS_XATTR=y
- +CONFIG_REISERFS_FS_POSIX_ACL=y
- +CONFIG_REISERFS_FS_SECURITY=y
- +CONFIG_JFS_FS=m
- +# CONFIG_JFS_DEBUG is not set
- +# CONFIG_JFS_STATISTICS is not set
- +CONFIG_JFS_POSIX_ACL=y
- +CONFIG_JFS_SECURITY=y
- +CONFIG_XFS_FS=m
- +# CONFIG_XFS_DEBUG is not set
- +# CONFIG_XFS_RT is not set
- +CONFIG_XFS_QUOTA=y
- +CONFIG_XFS_POSIX_ACL=y
- +CONFIG_MINIX_FS=m
- +CONFIG_ROMFS_FS=m
- +# CONFIG_QFMT_V1 is not set
- +CONFIG_QFMT_V2=y
- +CONFIG_QUOTACTL=y
- +CONFIG_DNOTIFY=y
- +# Autofsv3 is obsolete.
- +# systemd is dependant upon AUTOFS, so build it in.
- +# CONFIG_EXOFS_FS is not set
- +# CONFIG_EXOFS_DEBUG is not set
- +CONFIG_NILFS2_FS=m
- +# CONFIG_LOGFS is not set
- +CONFIG_CEPH_FS=m
- +CONFIG_CEPH_FSCACHE=y
- +CONFIG_BLK_DEV_RBD=m
- +CONFIG_CEPH_LIB=m
- +CONFIG_CEPH_FS_POSIX_ACL=y
- +# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set
- +
- +CONFIG_FSCACHE=m
- +CONFIG_FSCACHE_STATS=y
- +# CONFIG_FSCACHE_HISTOGRAM is not set
- +# CONFIG_FSCACHE_DEBUG is not set
- +CONFIG_FSCACHE_OBJECT_LIST=y
- +
- +CONFIG_CACHEFILES=m
- +# CONFIG_CACHEFILES_DEBUG is not set
- +# CONFIG_CACHEFILES_HISTOGRAM is not set
- +
- +#
- +# CD-ROM/DVD Filesystems
- +#
- +
- +#
- +# DOS/FAT/NT Filesystems
- +#
- +CONFIG_FAT_FS=m
- +CONFIG_FAT_DEFAULT_CODEPAGE=437
- +CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
- +# CONFIG_NTFS_FS is not set
- +
- +#
- +# Pseudo filesystems
- +#
- +CONFIG_PROC_FS=y
- +CONFIG_PROC_KCORE=y
- +CONFIG_PROC_VMCORE=y
- +CONFIG_TMPFS_POSIX_ACL=y
- +CONFIG_TMPFS_XATTR=y
- +CONFIG_HUGETLBFS=y
- +CONFIG_HUGETLB_PAGE=y
- +# CONFIG_DEBUG_FS is not set
- +
- +#
- +# Miscellaneous filesystems
- +#
- +# CONFIG_ADFS_FS is not set
- +CONFIG_AFFS_FS=m
- +CONFIG_ECRYPT_FS=m
- +# CONFIG_ECRYPT_FS_MESSAGING is not set
- +CONFIG_HFS_FS=m
- +CONFIG_HFSPLUS_FS=m
- +# CONFIG_HFSPLUS_FS_POSIX_ACL is not set
- +CONFIG_BEFS_FS=m
- +# CONFIG_BEFS_DEBUG is not set
- +# CONFIG_BFS_FS is not set
- +# CONFIG_EFS_FS is not set
- +
- +CONFIG_CRAMFS=m
- +CONFIG_SQUASHFS=m
- +CONFIG_SQUASHFS_XATTR=y
- +CONFIG_SQUASHFS_LZO=y
- +CONFIG_SQUASHFS_XZ=y
- +CONFIG_SQUASHFS_ZLIB=y
- +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set
- +# CONFIG_SQUASHFS_EMBEDDED is not set
- +# CONFIG_VXFS_FS is not set
- +# CONFIG_HPFS_FS is not set
- +# CONFIG_QNX4FS_FS is not set
- +# CONFIG_QNX6FS_FS is not set
- +CONFIG_SYSV_FS=m
- +CONFIG_UFS_FS=m
- +# CONFIG_UFS_FS_WRITE is not set
- +# CONFIG_UFS_DEBUG is not set
- +CONFIG_9P_FS=m
- +CONFIG_9P_FSCACHE=y
- +CONFIG_9P_FS_POSIX_ACL=y
- +CONFIG_9P_FS_SECURITY=y
- +# CONFIG_OMFS_FS is not set
- +CONFIG_CUSE=m
- +# CONFIG_F2FS_FS is not set
- +
- +#
- +# Network File Systems
- +#
- +CONFIG_NETWORK_FILESYSTEMS=y
- +# CONFIG_NFS_V2 is not set
- +CONFIG_NFS_V3=y
- +CONFIG_NFS_SWAP=y
- +CONFIG_NFS_V4_1=y
- +CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
- +# CONFIG_NFS_V4_1_MIGRATION is not set
- +CONFIG_NFS_V4_2=y
- +CONFIG_NFSD=m
- +CONFIG_NFSD_V3=y
- +CONFIG_NFSD_V3_ACL=y
- +CONFIG_NFSD_V4=y
- +CONFIG_NFSD_V4_SECURITY_LABEL=y
- +CONFIG_NFS_FSCACHE=y
- +# CONFIG_NFS_USE_LEGACY_DNS is not set
- +CONFIG_PNFS_OBJLAYOUT=m
- +CONFIG_PNFS_BLOCK=m
- +CONFIG_LOCKD=m
- +CONFIG_LOCKD_V4=y
- +CONFIG_EXPORTFS=y
- +CONFIG_SUNRPC=m
- +CONFIG_SUNRPC_GSS=m
- +CONFIG_SUNRPC_XPRT_RDMA=m
- +CONFIG_SUNRPC_DEBUG=y
- +CONFIG_RPCSEC_GSS_KRB5=m
- +CONFIG_CIFS=m
- +CONFIG_CIFS_STATS=y
- +# CONFIG_CIFS_STATS2 is not set
- +CONFIG_CIFS_SMB2=y
- +CONFIG_CIFS_UPCALL=y
- +CONFIG_CIFS_XATTR=y
- +CONFIG_CIFS_POSIX=y
- +CONFIG_CIFS_FSCACHE=y
- +CONFIG_CIFS_ACL=y
- +CONFIG_CIFS_WEAK_PW_HASH=y
- +CONFIG_CIFS_DEBUG=y
- +# CONFIG_CIFS_DEBUG2 is not set
- +CONFIG_CIFS_DFS_UPCALL=y
- +CONFIG_CIFS_NFSD_EXPORT=y
- +CONFIG_NCP_FS=m
- +CONFIG_NCPFS_PACKET_SIGNING=y
- +CONFIG_NCPFS_IOCTL_LOCKING=y
- +CONFIG_NCPFS_STRONG=y
- +CONFIG_NCPFS_NFS_NS=y
- +CONFIG_NCPFS_OS2_NS=y
- +CONFIG_NCPFS_SMALLDOS=y
- +CONFIG_NCPFS_NLS=y
- +CONFIG_NCPFS_EXTRAS=y
- +CONFIG_CODA_FS=m
- +# CONFIG_AFS_FS is not set
- +# CONFIG_AF_RXRPC is not set
- +
- +CONFIG_OCFS2_FS=m
- +# CONFIG_OCFS2_DEBUG_FS is not set
- +# CONFIG_OCFS2_DEBUG_MASKLOG is not set
- +CONFIG_OCFS2_FS_O2CB=m
- +CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
- +# CONFIG_OCFS2_FS_STATS is not set
- +
- +CONFIG_BTRFS_FS=m
- +CONFIG_BTRFS_FS_POSIX_ACL=y
- +# Maybe see if we want this on for debug kernels?
- +# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set
- +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set
- +# CONFIG_BTRFS_DEBUG is not set
- +# CONFIG_BTRFS_ASSERT is not set
- +
- +CONFIG_CONFIGFS_FS=y
- +
- +CONFIG_DLM=m
- +CONFIG_DLM_DEBUG=y
- +CONFIG_GFS2_FS=m
- +CONFIG_GFS2_FS_LOCKING_DLM=y
- +
- +
- +CONFIG_UBIFS_FS_XATTR=y
- +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
- +# CONFIG_UBIFS_FS_DEBUG is not set
- +
- +#
- +# Partition Types
- +#
- +CONFIG_PARTITION_ADVANCED=y
- +# CONFIG_ACORN_PARTITION is not set
- +CONFIG_AIX_PARTITION=y
- +CONFIG_AMIGA_PARTITION=y
- +# CONFIG_ATARI_PARTITION is not set
- +CONFIG_BSD_DISKLABEL=y
- +CONFIG_EFI_PARTITION=y
- +CONFIG_KARMA_PARTITION=y
- +CONFIG_LDM_PARTITION=y
- +# CONFIG_LDM_DEBUG is not set
- +CONFIG_MAC_PARTITION=y
- +CONFIG_MSDOS_PARTITION=y
- +CONFIG_MINIX_SUBPARTITION=y
- +CONFIG_OSF_PARTITION=y
- +CONFIG_SGI_PARTITION=y
- +CONFIG_SOLARIS_X86_PARTITION=y
- +CONFIG_SUN_PARTITION=y
- +# CONFIG_SYSV68_PARTITION is not set
- +CONFIG_UNIXWARE_DISKLABEL=y
- +# CONFIG_ULTRIX_PARTITION is not set
- +# CONFIG_CMDLINE_PARTITION is not set
- +
- +CONFIG_NLS=y
- +
- +#
- +# Native Language Support
- +#
- +CONFIG_NLS_CODEPAGE_737=m
- +CONFIG_NLS_CODEPAGE_775=m
- +CONFIG_NLS_CODEPAGE_850=m
- +CONFIG_NLS_CODEPAGE_852=m
- +CONFIG_NLS_CODEPAGE_855=m
- +CONFIG_NLS_CODEPAGE_857=m
- +CONFIG_NLS_CODEPAGE_860=m
- +CONFIG_NLS_CODEPAGE_861=m
- +CONFIG_NLS_CODEPAGE_862=m
- +CONFIG_NLS_CODEPAGE_863=m
- +CONFIG_NLS_CODEPAGE_864=m
- +CONFIG_NLS_CODEPAGE_865=m
- +CONFIG_NLS_CODEPAGE_866=m
- +CONFIG_NLS_CODEPAGE_869=m
- +CONFIG_NLS_CODEPAGE_936=m
- +CONFIG_NLS_CODEPAGE_950=m
- +CONFIG_NLS_CODEPAGE_932=m
- +CONFIG_NLS_CODEPAGE_949=m
- +CONFIG_NLS_CODEPAGE_874=m
- +CONFIG_NLS_ISO8859_8=m
- +CONFIG_NLS_CODEPAGE_1250=m
- +CONFIG_NLS_CODEPAGE_1251=m
- +CONFIG_NLS_ISO8859_2=m
- +CONFIG_NLS_ISO8859_3=m
- +CONFIG_NLS_ISO8859_4=m
- +CONFIG_NLS_ISO8859_5=m
- +CONFIG_NLS_ISO8859_6=m
- +CONFIG_NLS_ISO8859_7=m
- +CONFIG_NLS_ISO8859_9=m
- +CONFIG_NLS_ISO8859_13=m
- +CONFIG_NLS_ISO8859_14=m
- +CONFIG_NLS_KOI8_R=m
- +CONFIG_NLS_KOI8_U=m
- +CONFIG_NLS_MAC_ROMAN=m
- +CONFIG_NLS_MAC_CELTIC=m
- +CONFIG_NLS_MAC_CENTEURO=m
- +CONFIG_NLS_MAC_CROATIAN=m
- +CONFIG_NLS_MAC_CYRILLIC=m
- +CONFIG_NLS_MAC_GAELIC=m
- +CONFIG_NLS_MAC_GREEK=m
- +CONFIG_NLS_MAC_ICELAND=m
- +CONFIG_NLS_MAC_INUIT=m
- +CONFIG_NLS_MAC_ROMANIAN=m
- +CONFIG_NLS_MAC_TURKISH=m
- +
- +#
- +# Profiling support
- +#
- +CONFIG_PROFILING=y
- +CONFIG_OPROFILE=m
- +CONFIG_OPROFILE_EVENT_MULTIPLEX=y
- +
- +#
- +# Kernel hacking
- +#
- +CONFIG_DEBUG_KERNEL=y
- +CONFIG_FRAME_WARN=1024
- +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x0
- +# CONFIG_DEBUG_INFO is not set
- +CONFIG_FRAME_POINTER=y
- +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
- +# CONFIG_DEBUG_DRIVER is not set
- +CONFIG_HEADERS_CHECK=y
- +# CONFIG_LKDTM is not set
- +# CONFIG_NOTIFIER_ERROR_INJECTION is not set
- +# CONFIG_READABLE_ASM is not set
- +
- +# CONFIG_RT_MUTEX_TESTER is not set
- +# CONFIG_DEBUG_LOCKDEP is not set
- +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
- +
- +# DEBUG options that don't get enabled/disabled with 'make debug/release'
- +
- +# This generates a huge amount of dmesg spew
- +# CONFIG_DEBUG_KOBJECT is not set
- +#
- +# This breaks booting until the module patches are in-tree
- +# CONFIG_DEBUG_KOBJECT_RELEASE is not set
- +#
- +#
- +# These debug options are deliberatly left on (even in 'make release' kernels).
- +# They aren't that much of a performance impact, and the value
- +# from getting useful bug-reports makes it worth leaving them on.
- +# CONFIG_DEBUG_HIGHMEM is not set
- +# CONFIG_DEBUG_SHIRQ is not set
- +CONFIG_BOOT_PRINTK_DELAY=y
- +CONFIG_DEBUG_DEVRES=y
- +CONFIG_DEBUG_RODATA_TEST=y
- +CONFIG_DEBUG_NX_TEST=m
- +CONFIG_DEBUG_SET_MODULE_RONX=y
- +CONFIG_DEBUG_BOOT_PARAMS=y
- +# CONFIG_DEBUG_VM is not set
- +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set
- +CONFIG_LOCKUP_DETECTOR=y
- +# CONFIG_DEBUG_INFO_REDUCED is not set
- +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
- +# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set
- +# CONFIG_PANIC_ON_OOPS is not set
- +CONFIG_PANIC_TIMEOUT=0
- +CONFIG_ATOMIC64_SELFTEST=y
- +CONFIG_MEMORY_FAILURE=y
- +CONFIG_HWPOISON_INJECT=m
- +CONFIG_CROSS_MEMORY_ATTACH=y
- +# CONFIG_DEBUG_SECTION_MISMATCH is not set
- +# CONFIG_BACKTRACE_SELF_TEST is not set
- +CONFIG_RESOURCE_COUNTERS=y
- +# CONFIG_DEBUG_VIRTUAL is not set
- +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
- +CONFIG_EARLY_PRINTK_DBGP=y
- +# CONFIG_PAGE_POISONING is not set
- +# CONFIG_CRASH_DUMP is not set
- +# CONFIG_CRASH is not set
- +# CONFIG_GCOV_KERNEL is not set
- +# CONFIG_RAMOOPS is not set
- +
- +
- +#
- +# Security options
- +#
- +CONFIG_SECURITY=y
- +# CONFIG_SECURITY_DMESG_RESTRICT is not set
- +CONFIG_SECURITY_NETWORK=y
- +CONFIG_SECURITY_NETWORK_XFRM=y
- +# CONFIG_SECURITY_PATH is not set
- +CONFIG_SECURITY_SELINUX=y
- +CONFIG_SECURITY_SELINUX_BOOTPARAM=y
- +CONFIG_SECURITY_SELINUX_DISABLE=y
- +CONFIG_SECURITY_SELINUX_DEVELOP=y
- +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
- +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
- +CONFIG_SECURITY_SELINUX_AVC_STATS=y
- +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
- +# CONFIG_SECURITY_SMACK is not set
- +# CONFIG_SECURITY_TOMOYO is not set
- +# CONFIG_SECURITY_APPARMOR is not set
- +# CONFIG_SECURITY_YAMA is not set
- +CONFIG_AUDIT=y
- +CONFIG_AUDITSYSCALL=y
- +# http://lists.fedoraproject.org/pipermail/kernel/2013-February/004125.html
- +CONFIG_AUDIT_LOGINUID_IMMUTABLE=y
- +
- +CONFIG_SECCOMP=y
- +
- +# CONFIG_SSBI is not set
- +
- +#
- +# Cryptographic options
- +#
- +CONFIG_CRYPTO=y
- +CONFIG_CRYPTO_FIPS=y
- +CONFIG_CRYPTO_USER_API_HASH=y
- +CONFIG_CRYPTO_USER_API_SKCIPHER=y
- +CONFIG_CRYPTO_MANAGER=y
- +# Note, CONFIG_CRYPTO_MANAGER_DISABLE_TESTS needs to be unset, or FIPS will be disabled.
- +# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
- +CONFIG_CRYPTO_HW=y
- +CONFIG_CRYPTO_BLKCIPHER=y
- +# CONFIG_CRYPTO_CRYPTD is not set
- +CONFIG_CRYPTO_AES=y
- +CONFIG_CRYPTO_ARC4=m
- +CONFIG_CRYPTO_ANUBIS=m
- +CONFIG_CRYPTO_AUTHENC=m
- +CONFIG_CRYPTO_CAST5=m
- +CONFIG_CRYPTO_CAST6=m
- +CONFIG_CRYPTO_CRC32C=y
- +CONFIG_CRYPTO_CRC32=m
- +CONFIG_CRYPTO_CTR=y
- +CONFIG_CRYPTO_DEFLATE=m
- +CONFIG_CRYPTO_FCRYPT=m
- +CONFIG_CRYPTO_GF128MUL=m
- +CONFIG_CRYPTO_CMAC=m
- +CONFIG_CRYPTO_HMAC=y
- +CONFIG_CRYPTO_KHAZAD=m
- +CONFIG_CRYPTO_LZO=m
- +CONFIG_CRYPTO_LZ4=m
- +CONFIG_CRYPTO_LZ4HC=m
- +CONFIG_CRYPTO_NULL=m
- +CONFIG_CRYPTO_PCBC=m
- +CONFIG_CRYPTO_SALSA20=m
- +CONFIG_CRYPTO_SALSA20_586=m
- +CONFIG_CRYPTO_SEED=m
- +CONFIG_CRYPTO_SEQIV=m
- +CONFIG_CRYPTO_SERPENT=m
- +CONFIG_CRYPTO_TEA=m
- +CONFIG_CRYPTO_XCBC=m
- +CONFIG_CRYPTO_VMAC=m
- +CONFIG_CRYPTO_CRC32C_INTEL=m
- +CONFIG_CRYPTO_GHASH=m
- +CONFIG_CRYPTO_DEV_HIFN_795X=m
- +CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y
- +CONFIG_CRYPTO_PCRYPT=m
- +
- +
- +
- +# Random number generation
- +
- +#
- +# Library routines
- +#
- +CONFIG_CRC16=y
- +CONFIG_CRC32=m
- +# CONFIG_CRC32_SELFTEST is not set
- +CONFIG_CRC_ITU_T=m
- +CONFIG_CRC8=m
- +# CONFIG_RANDOM32_SELFTEST is not set
- +CONFIG_CORDIC=m
- +# CONFIG_DDR is not set
- +
- +CONFIG_CRYPTO_ZLIB=m
- +CONFIG_ZLIB_INFLATE=y
- +CONFIG_ZLIB_DEFLATE=m
- +
- +CONFIG_INITRAMFS_SOURCE=""
- +CONFIG_KEYS=y
- +CONFIG_PERSISTENT_KEYRINGS=y
- +CONFIG_BIG_KEYS=y
- +CONFIG_TRUSTED_KEYS=m
- +CONFIG_ENCRYPTED_KEYS=m
- +CONFIG_KEYS_DEBUG_PROC_KEYS=y
- +CONFIG_CDROM_PKTCDVD=m
- +CONFIG_CDROM_PKTCDVD_BUFFERS=8
- +# CONFIG_CDROM_PKTCDVD_WCACHE is not set
- +
- +CONFIG_ATA_OVER_ETH=m
- +CONFIG_BACKLIGHT_LCD_SUPPORT=y
- +CONFIG_BACKLIGHT_CLASS_DEVICE=m
- +# CONFIG_BACKLIGHT_GENERIC is not set
- +CONFIG_BACKLIGHT_PROGEAR=m
- +
- +CONFIG_LCD_CLASS_DEVICE=m
- +CONFIG_LCD_PLATFORM=m
- +
- +CONFIG_FAIR_GROUP_SCHED=y
- +CONFIG_CFS_BANDWIDTH=y
- +CONFIG_SCHED_OMIT_FRAME_POINTER=y
- +CONFIG_RT_GROUP_SCHED=y
- +CONFIG_SCHED_AUTOGROUP=y
- +
- +CONFIG_CPUSETS=y
- +CONFIG_PROC_PID_CPUSET=y
- +
- +# CONFIG_CGROUP_DEBUG is not set
- +CONFIG_CGROUP_CPUACCT=y
- +CONFIG_CGROUP_DEVICE=y
- +CONFIG_CGROUP_FREEZER=y
- +CONFIG_CGROUP_SCHED=y
- +CONFIG_MEMCG=y
- +CONFIG_MEMCG_SWAP=y
- +CONFIG_MEMCG_SWAP_ENABLED=y
- +CONFIG_MEMCG_KMEM=y
- +# CONFIG_CGROUP_HUGETLB is not set
- +CONFIG_CGROUP_PERF=y
- +CONFIG_CGROUP_NET_PRIO=m
- +# CONFIG_CGROUP_NET_CLASSID is not set
- +CONFIG_BLK_CGROUP=y
- +
- +# CONFIG_SYSFS_DEPRECATED is not set
- +# CONFIG_SYSFS_DEPRECATED_V2 is not set
- +
- +CONFIG_PRINTK_TIME=y
- +
- +CONFIG_ENABLE_MUST_CHECK=y
- +# CONFIG_ENABLE_WARN_DEPRECATED is not set
- +
- +CONFIG_KEXEC=y
- +
- +CONFIG_HWMON=y
- +# CONFIG_HWMON_DEBUG_CHIP is not set
- +CONFIG_THERMAL_HWMON=y
- +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
- +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
- +CONFIG_THERMAL_GOV_FAIR_SHARE=y
- +# CONFIG_THERMAL_GOV_USER_SPACE is not set
- +CONFIG_THERMAL_GOV_STEP_WISE=y
- +# CONFIG_THERMAL_EMULATION is not set
- +
- +CONFIG_INOTIFY=y
- +CONFIG_INOTIFY_USER=y
- +
- +#
- +# Bus devices
- +#
- +# CONFIG_OMAP_OCP2SCP is not set
- +CONFIG_PROC_EVENTS=y
- +
- +CONFIG_IBMASR=m
- +
- +CONFIG_PM=y
- +CONFIG_PM_STD_PARTITION=""
- +# CONFIG_DPM_WATCHDOG is not set # revisit this in debug
- +CONFIG_PM_TRACE=y
- +CONFIG_PM_TRACE_RTC=y
- +# CONFIG_PM_OPP is not set
- +# CONFIG_PM_AUTOSLEEP is not set
- +# CONFIG_PM_WAKELOCKS is not set
- +CONFIG_HIBERNATION=y
- +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
- +CONFIG_SUSPEND=y
- +
- +CONFIG_CPU_FREQ_TABLE=y
- +CONFIG_CPU_FREQ_STAT=m
- +CONFIG_CPU_FREQ_STAT_DETAILS=y
- +
- +
- +CONFIG_NET_VENDOR_SMC=y
- +# CONFIG_IBMTR is not set
- +# CONFIG_SKISA is not set
- +# CONFIG_PROTEON is not set
- +# CONFIG_SMCTR is not set
- +
- +# CONFIG_MOUSE_ATIXL is not set
- +
- +# CONFIG_MEDIA_PARPORT_SUPPORT is not set
- +
- +CONFIG_RADIO_TEA5764=m
- +CONFIG_RADIO_SAA7706H=m
- +CONFIG_RADIO_CADET=m
- +CONFIG_RADIO_RTRACK=m
- +CONFIG_RADIO_RTRACK2=m
- +CONFIG_RADIO_AZTECH=m
- +CONFIG_RADIO_GEMTEK=m
- +CONFIG_RADIO_SF16FMI=m
- +CONFIG_RADIO_SF16FMR2=m
- +CONFIG_RADIO_TERRATEC=m
- +CONFIG_RADIO_TRUST=m
- +CONFIG_RADIO_TYPHOON=m
- +CONFIG_RADIO_ZOLTRIX=m
- +
- +CONFIG_SND_DARLA20=m
- +CONFIG_SND_GINA20=m
- +CONFIG_SND_LAYLA20=m
- +CONFIG_SND_DARLA24=m
- +CONFIG_SND_GINA24=m
- +CONFIG_SND_LAYLA24=m
- +CONFIG_SND_MONA=m
- +CONFIG_SND_MIA=m
- +CONFIG_SND_ECHO3G=m
- +CONFIG_SND_INDIGO=m
- +CONFIG_SND_INDIGOIO=m
- +CONFIG_SND_INDIGODJ=m
- +CONFIG_SND_INDIGOIOX=m
- +CONFIG_SND_INDIGODJX=m
- +
- +CONFIG_BALLOON_COMPACTION=y
- +CONFIG_COMPACTION=y
- +CONFIG_MIGRATION=y
- +CONFIG_BOUNCE=y
- +# CONFIG_LEDS_AMS_DELTA is not set
- +# CONFIG_LEDS_LOCOMO is not set
- +# CONFIG_LEDS_NET48XX is not set
- +# CONFIG_LEDS_NET5501 is not set
- +# CONFIG_LEDS_PCA9532 is not set
- +# CONFIG_LEDS_PCA955X is not set
- +# CONFIG_LEDS_BD2802 is not set
- +# CONFIG_LEDS_S3C24XX is not set
- +# CONFIG_LEDS_PCA9633 is not set
- +CONFIG_LEDS_DELL_NETBOOKS=m
- +# CONFIG_LEDS_TCA6507 is not set
- +# CONFIG_LEDS_LM355x is not set
- +# CONFIG_LEDS_OT200 is not set
- +# CONFIG_LEDS_PWM is not set
- +# CONFIG_LEDS_LP8501 is not set
- +# CONFIG_LEDS_PCA963X is not set
- +# CONFIG_LEDS_PCA9685 is not set
- +CONFIG_LEDS_TRIGGER_TIMER=m
- +CONFIG_LEDS_TRIGGER_ONESHOT=m
- +CONFIG_LEDS_TRIGGER_IDE_DISK=y
- +CONFIG_LEDS_TRIGGER_HEARTBEAT=m
- +CONFIG_LEDS_TRIGGER_BACKLIGHT=m
- +# CONFIG_LEDS_TRIGGER_CPU is not set
- +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
- +CONFIG_LEDS_TRIGGER_TRANSIENT=m
- +CONFIG_LEDS_TRIGGER_CAMERA=m
- +CONFIG_LEDS_ALIX2=m
- +CONFIG_LEDS_CLEVO_MAIL=m
- +CONFIG_LEDS_INTEL_SS4200=m
- +CONFIG_LEDS_LM3530=m
- +# CONFIG_LEDS_LM3642 is not set
- +CONFIG_LEDS_LM3556=m
- +CONFIG_LEDS_BLINKM=m
- +CONFIG_LEDS_LP3944=m
- +CONFIG_LEDS_LP5521=m
- +CONFIG_LEDS_LP5523=m
- +CONFIG_LEDS_LP5562=m
- +CONFIG_LEDS_LT3593=m
- +CONFIG_LEDS_REGULATOR=m
- +CONFIG_LEDS_WM8350=m
- +CONFIG_LEDS_WM831X_STATUS=m
- +
- +CONFIG_DMA_ENGINE=y
- +CONFIG_DW_DMAC_CORE=m
- +CONFIG_DW_DMAC=m
- +CONFIG_DW_DMAC_PCI=m
- +# CONFIG_DW_DMAC_BIG_ENDIAN_IO is not set
- +# CONFIG_TIMB_DMA is not set
- +# CONFIG_DMATEST is not set
- +CONFIG_ASYNC_TX_DMA=y
- +
- +CONFIG_UNUSED_SYMBOLS=y
- +
- +CONFIG_UPROBE_EVENT=y
- +
- +CONFIG_DYNAMIC_FTRACE=y
- +# CONFIG_IRQSOFF_TRACER is not set
- +CONFIG_SCHED_TRACER=y
- +CONFIG_CONTEXT_SWITCH_TRACER=y
- +CONFIG_TRACER_SNAPSHOT=y
- +# CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP is not set
- +CONFIG_FTRACE_SYSCALLS=y
- +CONFIG_FTRACE_MCOUNT_RECORD=y
- +# CONFIG_FTRACE_STARTUP_TEST is not set
- +# CONFIG_TRACE_BRANCH_PROFILING is not set
- +CONFIG_FUNCTION_PROFILER=y
- +CONFIG_RING_BUFFER_BENCHMARK=m
- +# CONFIG_RING_BUFFER_STARTUP_TEST is not set
- +# CONFIG_RBTREE_TEST is not set
- +# CONFIG_INTERVAL_TREE_TEST is not set
- +CONFIG_FUNCTION_TRACER=y
- +CONFIG_STACK_TRACER=y
- +# CONFIG_FUNCTION_GRAPH_TRACER is not set
- +
- +CONFIG_KPROBES=y
- +CONFIG_KPROBE_EVENT=y
- +# CONFIG_KPROBES_SANITY_TEST is not set
- +# CONFIG_JUMP_LABEL is not set
- +CONFIG_OPTPROBES=y
- +
- +CONFIG_HZ_1000=y
- +
- +CONFIG_TIMER_STATS=y
- +CONFIG_PERF_COUNTERS=y
- +
- +# Auxillary displays
- +CONFIG_KS0108=m
- +CONFIG_KS0108_PORT=0x378
- +CONFIG_KS0108_DELAY=2
- +CONFIG_CFAG12864B=y
- +CONFIG_CFAG12864B_RATE=20
- +
- +# CONFIG_PHANTOM is not set
- +
- +# CONFIG_POWER_SUPPLY_DEBUG is not set
- +
- +# CONFIG_TEST_POWER is not set
- +CONFIG_APM_POWER=m
- +# CONFIG_GENERIC_ADC_BATTERY is not set
- +# CONFIG_WM831X_POWER is not set
- +
- +# CONFIG_BATTERY_DS2760 is not set
- +# CONFIG_BATTERY_DS2781 is not set
- +# CONFIG_BATTERY_DS2782 is not set
- +# CONFIG_BATTERY_SBS is not set
- +# CONFIG_BATTERY_BQ20Z75 is not set
- +# CONFIG_BATTERY_DS2780 is not set
- +# CONFIG_BATTERY_BQ27x00 is not set
- +# CONFIG_BATTERY_MAX17040 is not set
- +# CONFIG_BATTERY_MAX17042 is not set
- +# CONFIG_BATTERY_GOLDFISH is not set
- +
- +# CONFIG_CHARGER_ISP1704 is not set
- +# CONFIG_CHARGER_MAX8903 is not set
- +# CONFIG_CHARGER_LP8727 is not set
- +# CONFIG_CHARGER_GPIO is not set
- +# CONFIG_CHARGER_PCF50633 is not set
- +# CONFIG_CHARGER_BQ2415X is not set
- +# CONFIG_CHARGER_BQ24190 is not set
- +# CONFIG_CHARGER_BQ24735 is not set
- +CONFIG_POWER_RESET=y
- +
- +# CONFIG_PDA_POWER is not set
- +
- +CONFIG_AUXDISPLAY=y
- +
- +CONFIG_UIO=m
- +CONFIG_UIO_CIF=m
- +# CONFIG_UIO_PDRV is not set
- +# CONFIG_UIO_PDRV_GENIRQ is not set
- +# CONFIG_UIO_DMEM_GENIRQ is not set
- +CONFIG_UIO_AEC=m
- +CONFIG_UIO_SERCOS3=m
- +CONFIG_UIO_PCI_GENERIC=m
- +# CONFIG_UIO_NETX is not set
- +# CONFIG_UIO_MF624 is not set
- +
- +CONFIG_VFIO=m
- +CONFIG_VFIO_IOMMU_TYPE1=m
- +CONFIG_VFIO_PCI=m
- +
- +
- +# LIRC
- +CONFIG_LIRC_STAGING=y
- +CONFIG_LIRC_BT829=m
- +CONFIG_LIRC_IGORPLUGUSB=m
- +CONFIG_LIRC_IMON=m
- +CONFIG_LIRC_ZILOG=m
- +CONFIG_LIRC_PARALLEL=m
- +CONFIG_LIRC_SERIAL=m
- +CONFIG_LIRC_SERIAL_TRANSMITTER=y
- +CONFIG_LIRC_SASEM=m
- +CONFIG_LIRC_SIR=m
- +CONFIG_LIRC_TTUSBIR=m
- +
- +# CONFIG_SAMPLES is not set
- +
- +
- +CONFIG_NOZOMI=m
- +# CONFIG_TPS65010 is not set
- +
- +CONFIG_INPUT_APANEL=m
- +CONFIG_INPUT_GP2A=m
- +# CONFIG_INPUT_GPIO_TILT_POLLED is not set
- +# CONFIG_INPUT_GPIO_BEEPER is not set
- +
- +# CONFIG_INTEL_MENLOW is not set
- +CONFIG_ENCLOSURE_SERVICES=m
- +CONFIG_IPWIRELESS=m
- +
- +# CONFIG_BLK_DEV_XIP is not set
- +CONFIG_MEMSTICK=m
- +# CONFIG_MEMSTICK_DEBUG is not set
- +# CONFIG_MEMSTICK_UNSAFE_RESUME is not set
- +CONFIG_MSPRO_BLOCK=m
- +# CONFIG_MS_BLOCK is not set
- +CONFIG_MEMSTICK_TIFM_MS=m
- +CONFIG_MEMSTICK_JMICRON_38X=m
- +CONFIG_MEMSTICK_R592=m
- +CONFIG_MEMSTICK_REALTEK_PCI=m
- +
- +CONFIG_ACCESSIBILITY=y
- +CONFIG_A11Y_BRAILLE_CONSOLE=y
- +
- +# CONFIG_HTC_PASIC3 is not set
- +
- +# MT9V022_PCA9536_SWITCH is not set
- +
- +CONFIG_OPTIMIZE_INLINING=y
- +
- +# FIXME: This should be x86/ia64 only
- +# CONFIG_HP_ILO is not set
- +
- +CONFIG_GPIOLIB=y
- +# CONFIG_PINCTRL is not set
- +# CONFIG_DEBUG_PINCTRL is not set
- +# CONFIG_PINMUX is not set
- +# CONFIG_PINCONF is not set
- +
- +CONFIG_NET_DSA=m
- +CONFIG_NET_DSA_MV88E6060=m
- +CONFIG_NET_DSA_MV88E6131=m
- +CONFIG_NET_DSA_MV88E6123_61_65=m
- +
- +# Used by Maemo, we don't care.
- +# CONFIG_PHONET is not set
- +
- +# CONFIG_ICS932S401 is not set
- +# CONFIG_ATMEL_SSC is not set
- +
- +# CONFIG_C2PORT is not set
- +
- +# CONFIG_REGULATOR_DEBUG is not set
- +
- +CONFIG_WM8350_POWER=m
- +
- +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
- +
- +CONFIG_USB_WUSB=m
- +CONFIG_USB_WUSB_CBAF=m
- +# CONFIG_USB_WUSB_CBAF_DEBUG is not set
- +CONFIG_USB_WHCI_HCD=m
- +CONFIG_USB_HWA_HCD=m
- +# CONFIG_USB_HCD_BCMA is not set
- +# CONFIG_USB_HCD_SSB is not set
- +
- +CONFIG_UWB=m
- +CONFIG_UWB_HWA=m
- +CONFIG_UWB_WHCI=m
- +CONFIG_UWB_I1480U=m
- +
- +# CONFIG_ANDROID is not set
- +CONFIG_STAGING_MEDIA=y
- +# CONFIG_DVB_AS102 is not set
- +# CONFIG_ET131X is not set
- +# CONFIG_SLICOSS is not set
- +# CONFIG_WLAGS49_H2 is not set
- +# CONFIG_WLAGS49_H25 is not set
- +# CONFIG_VIDEO_DT3155 is not set
- +# CONFIG_TI_ST is not set
- +# CONFIG_FB_XGI is not set
- +# CONFIG_VIDEO_GO7007 is not set
- +# CONFIG_I2C_BCM2048 is not set
- +# CONFIG_VIDEO_TCM825X is not set
- +# CONFIG_VIDEO_OMAP4 is not set
- +# CONFIG_USB_MSI3101 is not set
- +# CONFIG_DT3155 is not set
- +# CONFIG_W35UND is not set
- +# CONFIG_PRISM2_USB is not set
- +# CONFIG_ECHO is not set
- +CONFIG_USB_ATMEL=m
- +# CONFIG_COMEDI is not set
- +# CONFIG_ASUS_OLED is not set
- +# CONFIG_PANEL is not set
- +# CONFIG_TRANZPORT is not set
- +# CONFIG_POHMELFS is not set
- +# CONFIG_IDE_PHISON is not set
- +# CONFIG_LINE6_USB is not set
- +# CONFIG_VME_BUS is not set
- +# CONFIG_RAR_REGISTER is not set
- +# CONFIG_VT6656 is not set
- +# CONFIG_USB_SERIAL_QUATECH_USB2 is not set
- +# Larry Finger maintains these (rhbz 913753)
- +CONFIG_RTLLIB=m
- +CONFIG_RTLLIB_CRYPTO_CCMP=m
- +CONFIG_RTLLIB_CRYPTO_TKIP=m
- +CONFIG_RTLLIB_CRYPTO_WEP=m
- +CONFIG_RTL8192E=m
- +# CONFIG_INPUT_GPIO is not set
- +# CONFIG_VIDEO_CX25821 is not set
- +# CONFIG_R8187SE is not set
- +# CONFIG_R8188EU is not set
- +# CONFIG_R8821AE is not set
- +# CONFIG_RTL8192U is not set
- +# CONFIG_FB_SM7XX is not set
- +# CONFIG_SPECTRA is not set
- +# CONFIG_EASYCAP is not set
- +# CONFIG_SOLO6X10 is not set
- +# CONFIG_ACPI_QUICKSTART is not set
- +# CONFIG_LTE_GDM724X is not set
- +CONFIG_R8712U=m # Larry Finger maintains this (rhbz 699618)
- +# CONFIG_R8712_AP is not set
- +# CONFIG_ATH6K_LEGACY is not set
- +# CONFIG_USB_ENESTORAGE is not set
- +# CONFIG_BCM_WIMAX is not set
- +# CONFIG_USB_BTMTK is not set
- +# CONFIG_FT1000 is not set
- +# CONFIG_SPEAKUP is not set
- +# CONFIG_DX_SEP is not set
- +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set
- +# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set
- +# CONFIG_RTS_PSTOR is not set
- +CONFIG_ALTERA_STAPL=m
- +# CONFIG_DVB_CXD2099 is not set
- +# CONFIG_USBIP_CORE is not set
- +# CONFIG_INTEL_MEI is not set
- +# CONFIG_ZCACHE is not set
- +# CONFIG_RTS5139 is not set
- +# CONFIG_NVEC_LEDS is not set
- +# CONFIG_VT6655 is not set
- +# CONFIG_RAMSTER is not set
- +# CONFIG_USB_WPAN_HCD is not set
- +# CONFIG_WIMAX_GDM72XX is not set
- +# CONFIG_IPACK_BUS is not set
- +# CONFIG_CSR_WIFI is not set
- +# CONFIG_ZCACHE2 is not set
- +# CONFIG_NET_VENDOR_SILICOM is not set
- +# CONFIG_SBYPASS is not set
- +# CONFIG_BPCTL is not set
- +# CONFIG_CED1401 is not set
- +# CONFIG_DGRP is not set
- +# CONFIG_SB105X is not set
- +# CONFIG_LUSTRE_FS is not set
- +# CONFIG_XILLYBUS is not set
- +# CONFIG_DGAP is not set
- +# CONFIG_DGNC is not set
- +# CONFIG_RTS5208 is not set
- +# END OF STAGING
- +
- +#
- +# Remoteproc drivers (EXPERIMENTAL)
- +#
- +# CONFIG_STE_MODEM_RPROC is not set
- +
- +CONFIG_LIBFC=m
- +CONFIG_LIBFCOE=m
- +CONFIG_FCOE=m
- +CONFIG_FCOE_FNIC=m
- +
- +
- +# CONFIG_IMA is not set
- +CONFIG_IMA_MEASURE_PCR_IDX=10
- +CONFIG_IMA_AUDIT=y
- +CONFIG_IMA_LSM_RULES=y
- +
- +# CONFIG_EVM is not set
- +# CONFIG_PWM_PCA9685 is not set
- +
- +CONFIG_LSM_MMAP_MIN_ADDR=65536
- +
- +CONFIG_STRIP_ASM_SYMS=y
- +
- +# CONFIG_RCU_FANOUT_EXACT is not set
- +# FIXME: Revisit FAST_NO_HZ after it's fixed
- +# CONFIG_RCU_FAST_NO_HZ is not set
- +# CONFIG_RCU_NOCB_CPU is not set
- +CONFIG_RCU_CPU_STALL_TIMEOUT=60
- +# CONFIG_RCU_TORTURE_TEST is not set
- +# CONFIG_RCU_TRACE is not set
- +# CONFIG_RCU_CPU_STALL_INFO is not set
- +# CONFIG_RCU_USER_QS is not set
- +
- +CONFIG_KSM=y
- +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
- +
- +CONFIG_FSNOTIFY=y
- +CONFIG_FANOTIFY=y
- +CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
- +
- +CONFIG_IEEE802154=m
- +CONFIG_IEEE802154_6LOWPAN=m
- +CONFIG_IEEE802154_DRIVERS=m
- +CONFIG_IEEE802154_FAKEHARD=m
- +CONFIG_IEEE802154_FAKELB=m
- +
- +CONFIG_MAC802154=m
- +CONFIG_NET_MPLS_GSO=m
- +
- +# CONFIG_HSR is not set
- +
- +# CONFIG_EXTCON is not set
- +# CONFIG_EXTCON_ADC_JACK is not set
- +# CONFIG_MEMORY is not set
- +
- +CONFIG_PPS=m
- +# CONFIG_PPS_CLIENT_KTIMER is not set
- +CONFIG_PPS_CLIENT_LDISC=m
- +# CONFIG_PPS_DEBUG is not set
- +CONFIG_PPS_CLIENT_PARPORT=m
- +CONFIG_PPS_GENERATOR_PARPORT=m
- +CONFIG_PPS_CLIENT_GPIO=m
- +CONFIG_NTP_PPS=y
- +
- +CONFIG_PTP_1588_CLOCK=m
- +CONFIG_PTP_1588_CLOCK_PCH=m
- +
- +CONFIG_CLEANCACHE=y
- +CONFIG_FRONTSWAP=y
- +CONFIG_ZSWAP=y
- +CONFIG_ZSMALLOC=y
- +# CONFIG_PGTABLE_MAPPING is not set
- +
- +# CONFIG_MDIO_GPIO is not set
- +# CONFIG_KEYBOARD_GPIO_POLLED is not set
- +# CONFIG_MOUSE_GPIO is not set
- +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
- +# CONFIG_I2C_DESIGNWARE_PCI is not set
- +# CONFIG_I2C_GPIO is not set
- +# CONFIG_DEBUG_GPIO is not set
- +# CONFIG_GPIO_GENERIC_PLATFORM is not set
- +# CONFIG_GPIO_CS5535 is not set
- +# CONFIG_GPIO_IT8761E is not set
- +# CONFIG SB105x is not set
- +# CONFIG_GPIO_TS5500 is not set
- +CONFIG_GPIO_VIPERBOARD=m
- +# CONFIG_UCB1400_CORE is not set
- +# CONFIG_TPS6105X is not set
- +# CONFIG_RADIO_MIROPCM20 is not set
- +# CONFIG_USB_GPIO_VBUS is not set
- +# CONFIG_GPIO_SCH is not set
- +# CONFIG_GPIO_LANGWELL is not set
- +# CONFIG_GPIO_RDC321X is not set
- +# CONFIG_GPIO_VX855 is not set
- +# CONFIG_GPIO_PCH is not set
- +# CONFIG_GPIO_ML_IOH is not set
- +# CONFIG_GPIO_AMD8111 is not set
- +# CONFIG_GPIO_BT8XX is not set
- +# CONFIG_GPIO_GRGPIO is not set
- +# CONFIG_GPIO_PL061 is not set
- +# CONFIG_GPIO_BCM_KONA is not set
- +# CONFIG_GPIO_SCH311X is not set
- +CONFIG_GPIO_MAX730X=m
- +CONFIG_GPIO_MAX7300=m
- +CONFIG_GPIO_MAX732X=m
- +CONFIG_GPIO_PCF857X=m
- +CONFIG_GPIO_SX150X=y
- +CONFIG_GPIO_ADP5588=m
- +CONFIG_GPIO_ADNP=m
- +CONFIG_GPIO_MAX7301=m
- +CONFIG_GPIO_MCP23S08=m
- +CONFIG_GPIO_MC33880=m
- +CONFIG_GPIO_74X164=m
- +
- +# FIXME: Why?
- +CONFIG_EVENT_POWER_TRACING_DEPRECATED=y
- +
- +CONFIG_TEST_KSTRTOX=y
- +CONFIG_XZ_DEC=y
- +CONFIG_XZ_DEC_X86=y
- +CONFIG_XZ_DEC_POWERPC=y
- +# CONFIG_XZ_DEC_IA64 is not set
- +CONFIG_XZ_DEC_ARM=y
- +# CONFIG_XZ_DEC_ARMTHUMB is not set
- +# CONFIG_XZ_DEC_SPARC is not set
- +# CONFIG_XZ_DEC_TEST is not set
- +
- +# CONFIG_POWER_AVS is not set
- +
- +CONFIG_TARGET_CORE=m
- +CONFIG_ISCSI_TARGET=m
- +CONFIG_LOOPBACK_TARGET=m
- +CONFIG_SBP_TARGET=m
- +CONFIG_TCM_IBLOCK=m
- +CONFIG_TCM_FILEIO=m
- +CONFIG_TCM_PSCSI=m
- +CONFIG_TCM_FC=m
- +
- +CONFIG_HWSPINLOCK=m
- +
- +CONFIG_PSTORE=y
- +CONFIG_PSTORE_RAM=m
- +# CONFIG_PSTORE_CONSOLE is not set
- +# CONFIG_PSTORE_FTRACE is not set
- +
- +# CONFIG_TEST_MODULE is not set
- +# CONFIG_TEST_USER_COPY is not set
- +
- +# CONFIG_AVERAGE is not set
- +# CONFIG_VMXNET3 is not set
- +
- +# CONFIG_SIGMA is not set
- +
- +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
- +
- +CONFIG_BCMA=m
- +CONFIG_BCMA_BLOCKIO=y
- +CONFIG_BCMA_HOST_PCI_POSSIBLE=y
- +CONFIG_BCMA_HOST_PCI=y
- +# CONFIG_BCMA_HOST_SOC is not set
- +CONFIG_BCMA_DRIVER_GMAC_CMN=y
- +CONFIG_BCMA_DRIVER_GPIO=y
- +# CONFIG_BCMA_DEBUG is not set
- +
- +# CONFIG_GOOGLE_FIRMWARE is not set
- +# CONFIG_INTEL_MID_PTI is not set
- +
- +# CONFIG_MAILBOX is not set
- +
- +CONFIG_FMC=m
- +CONFIG_FMC_FAKEDEV=m
- +CONFIG_FMC_TRIVIAL=m
- +CONFIG_FMC_WRITE_EEPROM=m
- +CONFIG_FMC_CHARDEV=m
- +
- +# CONFIG_GENWQE is not set
- +
- +# CONFIG_POWERCAP is not set
- +
- +# CONFIG_HSI is not set
- +
- +
- +# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set
- +
- +# CONFIG_PM_DEVFREQ is not set
- +# CONFIG_MODULE_SIG is not set
- +# CONFIG_SYSTEM_TRUSTED_KEYRING is not set
- +# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set
- +# CONFIG_MODULE_VERIFY_ELF is not set
- +# CONFIG_CRYPTO_KEY_TYPE is not set
- +# CONFIG_PGP_LIBRARY is not set
- +# CONFIG_PGP_PRELOAD is not set
- +# CONFIG_LOCALVERSION_AUTO is not set
- +CONFIG_PROC_DEVICETREE=y
- +
- diff -Nur linux-3.14.35.orig/arch/arm/configs/imx_v7_defconfig linux-3.14.35/arch/arm/configs/imx_v7_defconfig
- --- linux-3.14.35.orig/arch/arm/configs/imx_v7_defconfig 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/configs/imx_v7_defconfig 2015-03-08 14:27:37.409684502 -0500
- @@ -0,0 +1,343 @@
- +# CONFIG_LOCALVERSION_AUTO is not set
- +CONFIG_KERNEL_LZO=y
- +CONFIG_SYSVIPC=y
- +CONFIG_NO_HZ=y
- +CONFIG_HIGH_RES_TIMERS=y
- +CONFIG_LOG_BUF_SHIFT=18
- +CONFIG_CGROUPS=y
- +CONFIG_RELAY=y
- +CONFIG_BLK_DEV_INITRD=y
- +CONFIG_EXPERT=y
- +CONFIG_PERF_EVENTS=y
- +# CONFIG_SLUB_DEBUG is not set
- +# CONFIG_COMPAT_BRK is not set
- +CONFIG_MODULES=y
- +CONFIG_MODULE_UNLOAD=y
- +CONFIG_MODVERSIONS=y
- +CONFIG_MODULE_SRCVERSION_ALL=y
- +# CONFIG_BLK_DEV_BSG is not set
- +CONFIG_GPIO_PCA953X=y
- +CONFIG_ARCH_MXC=y
- +CONFIG_MXC_DEBUG_BOARD=y
- +CONFIG_MACH_IMX51_DT=y
- +CONFIG_MACH_EUKREA_CPUIMX51SD=y
- +CONFIG_SOC_IMX53=y
- +CONFIG_SOC_IMX6Q=y
- +CONFIG_SOC_IMX6SL=y
- +CONFIG_SOC_VF610=y
- +# CONFIG_SWP_EMULATE is not set
- +CONFIG_SMP=y
- +CONFIG_VMSPLIT_2G=y
- +CONFIG_PREEMPT=y
- +CONFIG_AEABI=y
- +# CONFIG_OABI_COMPAT is not set
- +CONFIG_HIGHMEM=y
- +CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
- +CONFIG_CPU_FREQ=y
- +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y
- +CONFIG_CPU_FREQ_GOV_POWERSAVE=y
- +CONFIG_CPU_FREQ_GOV_USERSPACE=y
- +CONFIG_CPU_FREQ_GOV_ONDEMAND=y
- +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
- +CONFIG_ARM_IMX6_CPUFREQ=y
- +CONFIG_CPU_IDLE=y
- +CONFIG_VFP=y
- +CONFIG_NEON=y
- +CONFIG_BINFMT_MISC=m
- +CONFIG_PM_RUNTIME=y
- +CONFIG_PM_DEBUG=y
- +CONFIG_PM_TEST_SUSPEND=y
- +CONFIG_NET=y
- +CONFIG_PACKET=y
- +CONFIG_UNIX=y
- +CONFIG_INET=y
- +CONFIG_IP_PNP=y
- +CONFIG_IP_PNP_DHCP=y
- +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
- +# CONFIG_INET_XFRM_MODE_TUNNEL is not set
- +# CONFIG_INET_XFRM_MODE_BEET is not set
- +# CONFIG_INET_LRO is not set
- +CONFIG_IPV6=y
- +CONFIG_NETFILTER=y
- +CONFIG_VLAN_8021Q=y
- +# CONFIG_WIRELESS is not set
- +CONFIG_DEVTMPFS=y
- +CONFIG_DEVTMPFS_MOUNT=y
- +# CONFIG_STANDALONE is not set
- +CONFIG_CMA=y
- +CONFIG_CMA_SIZE_MBYTES=320
- +CONFIG_IMX_WEIM=y
- +CONFIG_CONNECTOR=y
- +CONFIG_MTD=y
- +CONFIG_MTD_CMDLINE_PARTS=y
- +CONFIG_MTD_BLOCK=y
- +CONFIG_MTD_CFI=y
- +CONFIG_MTD_JEDECPROBE=y
- +CONFIG_MTD_CFI_INTELEXT=y
- +CONFIG_MTD_CFI_AMDSTD=y
- +CONFIG_MTD_CFI_STAA=y
- +CONFIG_MTD_PHYSMAP_OF=y
- +CONFIG_MTD_DATAFLASH=y
- +CONFIG_MTD_M25P80=y
- +CONFIG_MTD_SST25L=y
- +CONFIG_MTD_NAND=y
- +CONFIG_MTD_NAND_GPMI_NAND=y
- +CONFIG_MTD_NAND_MXC=y
- +CONFIG_MTD_UBI=y
- +CONFIG_BLK_DEV_LOOP=y
- +CONFIG_BLK_DEV_RAM=y
- +CONFIG_BLK_DEV_RAM_SIZE=65536
- +CONFIG_EEPROM_AT24=y
- +CONFIG_EEPROM_AT25=y
- +# CONFIG_SCSI_PROC_FS is not set
- +CONFIG_BLK_DEV_SD=y
- +CONFIG_SCSI_MULTI_LUN=y
- +CONFIG_SCSI_CONSTANTS=y
- +CONFIG_SCSI_LOGGING=y
- +CONFIG_SCSI_SCAN_ASYNC=y
- +# CONFIG_SCSI_LOWLEVEL is not set
- +CONFIG_ATA=y
- +CONFIG_SATA_AHCI_PLATFORM=y
- +CONFIG_AHCI_IMX=y
- +CONFIG_PATA_IMX=y
- +CONFIG_NETDEVICES=y
- +# CONFIG_NET_VENDOR_BROADCOM is not set
- +CONFIG_CS89x0=y
- +CONFIG_CS89x0_PLATFORM=y
- +# CONFIG_NET_VENDOR_FARADAY is not set
- +# CONFIG_NET_VENDOR_INTEL is not set
- +# CONFIG_NET_VENDOR_MARVELL is not set
- +# CONFIG_NET_VENDOR_MICREL is not set
- +# CONFIG_NET_VENDOR_MICROCHIP is not set
- +# CONFIG_NET_VENDOR_NATSEMI is not set
- +# CONFIG_NET_VENDOR_SEEQ is not set
- +CONFIG_SMC91X=y
- +CONFIG_SMC911X=y
- +CONFIG_SMSC911X=y
- +# CONFIG_NET_VENDOR_STMICRO is not set
- +# CONFIG_WLAN is not set
- +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
- +CONFIG_INPUT_EVDEV=y
- +CONFIG_INPUT_EVBUG=m
- +CONFIG_KEYBOARD_GPIO=y
- +CONFIG_KEYBOARD_IMX=y
- +CONFIG_MOUSE_PS2=m
- +CONFIG_MOUSE_PS2_ELANTECH=y
- +CONFIG_INPUT_TOUCHSCREEN=y
- +CONFIG_TOUCHSCREEN_EGALAX=y
- +CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH=y
- +CONFIG_TOUCHSCREEN_MAX11801=y
- +CONFIG_TOUCHSCREEN_MC13783=y
- +CONFIG_INPUT_MISC=y
- +CONFIG_INPUT_MMA8450=y
- +CONFIG_INPUT_ISL29023=y
- +CONFIG_SERIO_SERPORT=m
- +CONFIG_VT_HW_CONSOLE_BINDING=y
- +# CONFIG_LEGACY_PTYS is not set
- +# CONFIG_DEVKMEM is not set
- +CONFIG_SERIAL_IMX=y
- +CONFIG_SERIAL_IMX_CONSOLE=y
- +CONFIG_SERIAL_FSL_LPUART=y
- +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
- +CONFIG_FSL_OTP=y
- +# CONFIG_I2C_COMPAT is not set
- +CONFIG_I2C_CHARDEV=y
- +# CONFIG_I2C_HELPER_AUTO is not set
- +CONFIG_I2C_ALGOPCF=m
- +CONFIG_I2C_ALGOPCA=m
- +CONFIG_I2C_IMX=y
- +CONFIG_SPI=y
- +CONFIG_SPI_IMX=y
- +CONFIG_GPIO_SYSFS=y
- +CONFIG_POWER_SUPPLY=y
- +CONFIG_SABRESD_MAX8903=y
- +CONFIG_IMX6_USB_CHARGER=y
- +CONFIG_SENSORS_MAG3110=y
- +CONFIG_THERMAL=y
- +CONFIG_CPU_THERMAL=y
- +CONFIG_IMX_THERMAL=y
- +CONFIG_DEVICE_THERMAL=y
- +CONFIG_WATCHDOG=y
- +CONFIG_IMX2_WDT=y
- +CONFIG_MFD_DA9052_I2C=y
- +CONFIG_MFD_MC13XXX_SPI=y
- +CONFIG_MFD_MC13XXX_I2C=y
- +CONFIG_MFD_SI476X_CORE=y
- +CONFIG_REGULATOR=y
- +CONFIG_REGULATOR_FIXED_VOLTAGE=y
- +CONFIG_REGULATOR_DA9052=y
- +CONFIG_REGULATOR_ANATOP=y
- +CONFIG_REGULATOR_MC13783=y
- +CONFIG_REGULATOR_MC13892=y
- +CONFIG_REGULATOR_PFUZE100=y
- +CONFIG_MEDIA_SUPPORT=y
- +CONFIG_MEDIA_CAMERA_SUPPORT=y
- +CONFIG_MEDIA_RADIO_SUPPORT=y
- +CONFIG_VIDEO_V4L2_INT_DEVICE=y
- +CONFIG_MEDIA_USB_SUPPORT=y
- +CONFIG_USB_VIDEO_CLASS=m
- +CONFIG_V4L_PLATFORM_DRIVERS=y
- +CONFIG_VIDEO_MXC_OUTPUT=y
- +CONFIG_VIDEO_MXC_CAPTURE=m
- +CONFIG_VIDEO_MXC_CSI_CAMERA=m
- +CONFIG_MXC_CAMERA_OV5640=m
- +CONFIG_MXC_CAMERA_OV5642=m
- +CONFIG_MXC_CAMERA_OV5640_MIPI=m
- +CONFIG_MXC_TVIN_ADV7180=m
- +CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m
- +CONFIG_VIDEO_MXC_IPU_OUTPUT=y
- +CONFIG_VIDEO_MXC_PXP_V4L2=y
- +CONFIG_SOC_CAMERA=y
- +CONFIG_VIDEO_MX3=y
- +CONFIG_RADIO_SI476X=y
- +CONFIG_SOC_CAMERA_OV2640=y
- +CONFIG_DRM=y
- +CONFIG_DRM_VIVANTE=y
- +CONFIG_FB=y
- +CONFIG_FB_MXS=y
- +CONFIG_BACKLIGHT_LCD_SUPPORT=y
- +CONFIG_LCD_CLASS_DEVICE=y
- +CONFIG_LCD_L4F00242T03=y
- +CONFIG_LCD_PLATFORM=y
- +CONFIG_BACKLIGHT_CLASS_DEVICE=y
- +CONFIG_BACKLIGHT_PWM=y
- +CONFIG_FB_MXC_SYNC_PANEL=y
- +CONFIG_FB_MXC_LDB=y
- +CONFIG_FB_MXC_MIPI_DSI=y
- +CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL=y
- +CONFIG_FB_MXC_HDMI=y
- +CONFIG_FRAMEBUFFER_CONSOLE=y
- +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
- +CONFIG_FONTS=y
- +CONFIG_FONT_8x8=y
- +CONFIG_FONT_8x16=y
- +CONFIG_LOGO=y
- +CONFIG_SOUND=y
- +CONFIG_SND=y
- +CONFIG_SND_USB_AUDIO=m
- +CONFIG_SND_SOC=y
- +CONFIG_SND_IMX_SOC=y
- +CONFIG_SND_SOC_EUKREA_TLV320=y
- +CONFIG_SND_SOC_IMX_CS42888=y
- +CONFIG_SND_SOC_IMX_WM8962=y
- +CONFIG_SND_SOC_IMX_SGTL5000=y
- +CONFIG_SND_SOC_IMX_SPDIF=y
- +CONFIG_SND_SOC_IMX_MC13783=y
- +CONFIG_SND_SOC_IMX_HDMI=y
- +CONFIG_SND_SOC_IMX_SI476X=y
- +CONFIG_USB=y
- +CONFIG_USB_EHCI_HCD=y
- +CONFIG_USB_STORAGE=y
- +CONFIG_USB_CHIPIDEA=y
- +CONFIG_USB_CHIPIDEA_UDC=y
- +CONFIG_USB_CHIPIDEA_HOST=y
- +CONFIG_USB_PHY=y
- +CONFIG_NOP_USB_XCEIV=y
- +CONFIG_USB_MXS_PHY=y
- +CONFIG_USB_GADGET=y
- +CONFIG_USB_ZERO=m
- +CONFIG_USB_ETH=m
- +CONFIG_USB_MASS_STORAGE=m
- +CONFIG_USB_G_SERIAL=m
- +CONFIG_MMC=y
- +CONFIG_MMC_UNSAFE_RESUME=y
- +CONFIG_MMC_SDHCI=y
- +CONFIG_MMC_SDHCI_PLTFM=y
- +CONFIG_MMC_SDHCI_ESDHC_IMX=y
- +CONFIG_MXC_IPU=y
- +CONFIG_MXC_GPU_VIV=y
- +CONFIG_MXC_ASRC=y
- +CONFIG_MXC_MIPI_CSI2=y
- +CONFIG_MXC_MLB150=m
- +CONFIG_NEW_LEDS=y
- +CONFIG_LEDS_CLASS=y
- +CONFIG_LEDS_GPIO=y
- +CONFIG_LEDS_TRIGGERS=y
- +CONFIG_LEDS_TRIGGER_GPIO=y
- +CONFIG_RTC_CLASS=y
- +CONFIG_RTC_INTF_DEV_UIE_EMUL=y
- +CONFIG_RTC_DRV_MC13XXX=y
- +CONFIG_RTC_DRV_MXC=y
- +CONFIG_RTC_DRV_SNVS=y
- +CONFIG_DMADEVICES=y
- +CONFIG_MXC_PXP_V2=y
- +CONFIG_IMX_SDMA=y
- +CONFIG_MXS_DMA=y
- +CONFIG_STAGING=y
- +CONFIG_COMMON_CLK_DEBUG=y
- +# CONFIG_IOMMU_SUPPORT is not set
- +CONFIG_PWM=y
- +CONFIG_PWM_IMX=y
- +CONFIG_EXT2_FS=y
- +CONFIG_EXT2_FS_XATTR=y
- +CONFIG_EXT2_FS_POSIX_ACL=y
- +CONFIG_EXT2_FS_SECURITY=y
- +CONFIG_EXT3_FS=y
- +CONFIG_EXT3_FS_POSIX_ACL=y
- +CONFIG_EXT3_FS_SECURITY=y
- +CONFIG_EXT4_FS=y
- +CONFIG_EXT4_FS_POSIX_ACL=y
- +CONFIG_EXT4_FS_SECURITY=y
- +CONFIG_QUOTA=y
- +CONFIG_QUOTA_NETLINK_INTERFACE=y
- +# CONFIG_PRINT_QUOTA_WARNING is not set
- +CONFIG_AUTOFS4_FS=y
- +CONFIG_FUSE_FS=y
- +CONFIG_ISO9660_FS=m
- +CONFIG_JOLIET=y
- +CONFIG_ZISOFS=y
- +CONFIG_UDF_FS=m
- +CONFIG_MSDOS_FS=m
- +CONFIG_VFAT_FS=y
- +CONFIG_TMPFS=y
- +CONFIG_JFFS2_FS=y
- +CONFIG_UBIFS_FS=y
- +CONFIG_NFS_FS=y
- +CONFIG_NFS_V3_ACL=y
- +CONFIG_NFS_V4=y
- +CONFIG_ROOT_NFS=y
- +CONFIG_NLS_DEFAULT="cp437"
- +CONFIG_NLS_CODEPAGE_437=y
- +CONFIG_NLS_ASCII=y
- +CONFIG_NLS_ISO8859_1=y
- +CONFIG_NLS_ISO8859_15=m
- +CONFIG_NLS_UTF8=y
- +CONFIG_MAGIC_SYSRQ=y
- +# CONFIG_SCHED_DEBUG is not set
- +# CONFIG_DEBUG_BUGVERBOSE is not set
- +# CONFIG_FTRACE is not set
- +CONFIG_SECURITYFS=y
- +CONFIG_CRYPTO_USER=y
- +CONFIG_CRYPTO_TEST=m
- +CONFIG_CRYPTO_CCM=y
- +CONFIG_CRYPTO_GCM=y
- +CONFIG_CRYPTO_CBC=y
- +CONFIG_CRYPTO_CTS=y
- +CONFIG_CRYPTO_ECB=y
- +CONFIG_CRYPTO_LRW=y
- +CONFIG_CRYPTO_XTS=y
- +CONFIG_CRYPTO_MD4=y
- +CONFIG_CRYPTO_MD5=y
- +CONFIG_CRYPTO_MICHAEL_MIC=y
- +CONFIG_CRYPTO_RMD128=y
- +CONFIG_CRYPTO_RMD160=y
- +CONFIG_CRYPTO_RMD256=y
- +CONFIG_CRYPTO_RMD320=y
- +CONFIG_CRYPTO_SHA1=y
- +CONFIG_CRYPTO_SHA256=y
- +CONFIG_CRYPTO_SHA512=y
- +CONFIG_CRYPTO_TGR192=y
- +CONFIG_CRYPTO_WP512=y
- +CONFIG_CRYPTO_BLOWFISH=y
- +CONFIG_CRYPTO_CAMELLIA=y
- +CONFIG_CRYPTO_DES=y
- +CONFIG_CRYPTO_TWOFISH=y
- +# CONFIG_CRYPTO_ANSI_CPRNG is not set
- +CONFIG_CRYPTO_DEV_FSL_CAAM=y
- +CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y
- +CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=y
- +CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=y
- +CONFIG_CRC_CCITT=m
- +CONFIG_CRC_T10DIF=y
- +CONFIG_CRC7=m
- +CONFIG_LIBCRC32C=m
- diff -Nur linux-3.14.35.orig/arch/arm/configs/imx_v7_mfg_defconfig linux-3.14.35/arch/arm/configs/imx_v7_mfg_defconfig
- --- linux-3.14.35.orig/arch/arm/configs/imx_v7_mfg_defconfig 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/configs/imx_v7_mfg_defconfig 2015-03-08 14:27:37.409684502 -0500
- @@ -0,0 +1,341 @@
- +CONFIG_KERNEL_LZO=y
- +CONFIG_SYSVIPC=y
- +CONFIG_NO_HZ=y
- +CONFIG_HIGH_RES_TIMERS=y
- +CONFIG_IKCONFIG=y
- +CONFIG_IKCONFIG_PROC=y
- +CONFIG_LOG_BUF_SHIFT=18
- +CONFIG_CGROUPS=y
- +CONFIG_RELAY=y
- +CONFIG_BLK_DEV_INITRD=y
- +CONFIG_EXPERT=y
- +CONFIG_PERF_EVENTS=y
- +# CONFIG_SLUB_DEBUG is not set
- +# CONFIG_COMPAT_BRK is not set
- +CONFIG_MODULES=y
- +CONFIG_MODULE_UNLOAD=y
- +CONFIG_MODVERSIONS=y
- +CONFIG_MODULE_SRCVERSION_ALL=y
- +# CONFIG_BLK_DEV_BSG is not set
- +CONFIG_GPIO_PCA953X=y
- +CONFIG_ARCH_MXC=y
- +CONFIG_MXC_DEBUG_BOARD=y
- +CONFIG_MACH_IMX51_DT=y
- +CONFIG_MACH_EUKREA_CPUIMX51SD=y
- +CONFIG_SOC_IMX53=y
- +CONFIG_SOC_IMX6Q=y
- +CONFIG_SOC_IMX6SL=y
- +CONFIG_SOC_VF610=y
- +# CONFIG_SWP_EMULATE is not set
- +CONFIG_SMP=y
- +CONFIG_VMSPLIT_2G=y
- +CONFIG_PREEMPT_VOLUNTARY=y
- +CONFIG_AEABI=y
- +# CONFIG_OABI_COMPAT is not set
- +CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
- +CONFIG_CPU_FREQ=y
- +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y
- +CONFIG_CPU_FREQ_GOV_POWERSAVE=y
- +CONFIG_CPU_FREQ_GOV_USERSPACE=y
- +CONFIG_CPU_FREQ_GOV_ONDEMAND=y
- +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
- +CONFIG_ARM_IMX6_CPUFREQ=y
- +CONFIG_CPU_IDLE=y
- +CONFIG_VFP=y
- +CONFIG_NEON=y
- +CONFIG_BINFMT_MISC=m
- +CONFIG_PM_RUNTIME=y
- +CONFIG_PM_DEBUG=y
- +CONFIG_PM_TEST_SUSPEND=y
- +CONFIG_NET=y
- +CONFIG_PACKET=y
- +CONFIG_UNIX=y
- +CONFIG_INET=y
- +CONFIG_IP_PNP=y
- +CONFIG_IP_PNP_DHCP=y
- +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
- +# CONFIG_INET_XFRM_MODE_TUNNEL is not set
- +# CONFIG_INET_XFRM_MODE_BEET is not set
- +# CONFIG_INET_LRO is not set
- +CONFIG_IPV6=y
- +CONFIG_NETFILTER=y
- +CONFIG_VLAN_8021Q=y
- +CONFIG_CFG80211=y
- +CONFIG_CFG80211_WEXT=y
- +CONFIG_MAC80211=y
- +CONFIG_DEVTMPFS=y
- +CONFIG_DEVTMPFS_MOUNT=y
- +# CONFIG_STANDALONE is not set
- +CONFIG_CMA=y
- +CONFIG_CMA_SIZE_MBYTES=320
- +CONFIG_IMX_WEIM=y
- +CONFIG_CONNECTOR=y
- +CONFIG_MTD=y
- +CONFIG_MTD_CMDLINE_PARTS=y
- +CONFIG_MTD_BLOCK=y
- +CONFIG_MTD_CFI=y
- +CONFIG_MTD_JEDECPROBE=y
- +CONFIG_MTD_CFI_INTELEXT=y
- +CONFIG_MTD_CFI_AMDSTD=y
- +CONFIG_MTD_CFI_STAA=y
- +CONFIG_MTD_PHYSMAP_OF=y
- +CONFIG_MTD_DATAFLASH=y
- +CONFIG_MTD_M25P80=y
- +CONFIG_MTD_SST25L=y
- +CONFIG_MTD_NAND=y
- +CONFIG_MTD_NAND_GPMI_NAND=y
- +CONFIG_MTD_NAND_MXC=y
- +CONFIG_MTD_UBI=y
- +CONFIG_BLK_DEV_LOOP=y
- +CONFIG_BLK_DEV_RAM=y
- +CONFIG_BLK_DEV_RAM_SIZE=65536
- +CONFIG_EEPROM_AT24=y
- +CONFIG_EEPROM_AT25=y
- +# CONFIG_SCSI_PROC_FS is not set
- +CONFIG_BLK_DEV_SD=y
- +CONFIG_SCSI_MULTI_LUN=y
- +CONFIG_SCSI_CONSTANTS=y
- +CONFIG_SCSI_LOGGING=y
- +CONFIG_SCSI_SCAN_ASYNC=y
- +# CONFIG_SCSI_LOWLEVEL is not set
- +CONFIG_ATA=y
- +CONFIG_SATA_AHCI_PLATFORM=y
- +CONFIG_AHCI_IMX=y
- +CONFIG_PATA_IMX=y
- +CONFIG_NETDEVICES=y
- +# CONFIG_NET_VENDOR_BROADCOM is not set
- +CONFIG_CS89x0=y
- +CONFIG_CS89x0_PLATFORM=y
- +# CONFIG_NET_VENDOR_FARADAY is not set
- +# CONFIG_NET_VENDOR_INTEL is not set
- +# CONFIG_NET_VENDOR_MARVELL is not set
- +# CONFIG_NET_VENDOR_MICREL is not set
- +# CONFIG_NET_VENDOR_MICROCHIP is not set
- +# CONFIG_NET_VENDOR_NATSEMI is not set
- +# CONFIG_NET_VENDOR_SEEQ is not set
- +CONFIG_SMC91X=y
- +CONFIG_SMC911X=y
- +CONFIG_SMSC911X=y
- +# CONFIG_NET_VENDOR_STMICRO is not set
- +CONFIG_ATH_CARDS=y
- +CONFIG_ATH6KL=m
- +CONFIG_ATH6KL_SDIO=m
- +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
- +CONFIG_INPUT_EVDEV=y
- +CONFIG_INPUT_EVBUG=m
- +CONFIG_KEYBOARD_GPIO=y
- +CONFIG_KEYBOARD_IMX=y
- +CONFIG_MOUSE_PS2=m
- +CONFIG_MOUSE_PS2_ELANTECH=y
- +CONFIG_INPUT_TOUCHSCREEN=y
- +CONFIG_TOUCHSCREEN_EGALAX=y
- +CONFIG_TOUCHSCREEN_ELAN=y
- +CONFIG_TOUCHSCREEN_MAX11801=y
- +CONFIG_TOUCHSCREEN_MC13783=y
- +CONFIG_INPUT_MISC=y
- +CONFIG_INPUT_MMA8450=y
- +CONFIG_INPUT_ISL29023=y
- +CONFIG_SERIO_SERPORT=m
- +CONFIG_VT_HW_CONSOLE_BINDING=y
- +# CONFIG_LEGACY_PTYS is not set
- +# CONFIG_DEVKMEM is not set
- +CONFIG_SERIAL_IMX=y
- +CONFIG_SERIAL_IMX_CONSOLE=y
- +CONFIG_SERIAL_FSL_LPUART=y
- +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
- +CONFIG_FSL_OTP=y
- +# CONFIG_I2C_COMPAT is not set
- +CONFIG_I2C_CHARDEV=y
- +# CONFIG_I2C_HELPER_AUTO is not set
- +CONFIG_I2C_ALGOPCF=m
- +CONFIG_I2C_ALGOPCA=m
- +CONFIG_I2C_IMX=y
- +CONFIG_SPI=y
- +CONFIG_SPI_IMX=y
- +CONFIG_GPIO_SYSFS=y
- +CONFIG_POWER_SUPPLY=y
- +CONFIG_SABRESD_MAX8903=y
- +CONFIG_SENSORS_MAX17135=y
- +CONFIG_SENSORS_MAG3110=y
- +CONFIG_THERMAL=y
- +CONFIG_CPU_THERMAL=y
- +CONFIG_IMX_THERMAL=y
- +CONFIG_DEVICE_THERMAL=y
- +CONFIG_WATCHDOG=y
- +CONFIG_IMX2_WDT=y
- +CONFIG_MFD_DA9052_I2C=y
- +CONFIG_MFD_MC13XXX_SPI=y
- +CONFIG_MFD_MC13XXX_I2C=y
- +CONFIG_MFD_MAX17135=y
- +CONFIG_MFD_SI476X_CORE=y
- +CONFIG_REGULATOR=y
- +CONFIG_REGULATOR_FIXED_VOLTAGE=y
- +CONFIG_REGULATOR_DA9052=y
- +CONFIG_REGULATOR_ANATOP=y
- +CONFIG_REGULATOR_MC13783=y
- +CONFIG_REGULATOR_MC13892=y
- +CONFIG_REGULATOR_MAX17135=y
- +CONFIG_REGULATOR_PFUZE100=y
- +CONFIG_MEDIA_SUPPORT=y
- +CONFIG_MEDIA_CAMERA_SUPPORT=y
- +CONFIG_MEDIA_RADIO_SUPPORT=y
- +CONFIG_VIDEO_V4L2_INT_DEVICE=y
- +CONFIG_MEDIA_USB_SUPPORT=y
- +CONFIG_USB_VIDEO_CLASS=m
- +CONFIG_V4L_PLATFORM_DRIVERS=y
- +CONFIG_VIDEO_MXC_OUTPUT=y
- +CONFIG_VIDEO_MXC_CAPTURE=m
- +CONFIG_VIDEO_MXC_CSI_CAMERA=m
- +CONFIG_MXC_CAMERA_OV5640=m
- +CONFIG_MXC_CAMERA_OV5642=m
- +CONFIG_MXC_CAMERA_OV5640_MIPI=m
- +CONFIG_MXC_TVIN_ADV7180=m
- +CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m
- +CONFIG_VIDEO_MXC_IPU_OUTPUT=y
- +CONFIG_VIDEO_MXC_PXP_V4L2=y
- +CONFIG_SOC_CAMERA=y
- +CONFIG_VIDEO_MX3=y
- +CONFIG_RADIO_SI476X=y
- +CONFIG_SOC_CAMERA_OV2640=y
- +CONFIG_DRM=y
- +CONFIG_DRM_VIVANTE=y
- +CONFIG_FB=y
- +CONFIG_FB_MXS=y
- +CONFIG_BACKLIGHT_LCD_SUPPORT=y
- +CONFIG_LCD_CLASS_DEVICE=y
- +CONFIG_LCD_L4F00242T03=y
- +CONFIG_LCD_PLATFORM=y
- +CONFIG_BACKLIGHT_CLASS_DEVICE=y
- +CONFIG_BACKLIGHT_PWM=y
- +CONFIG_FB_MXC_SYNC_PANEL=y
- +CONFIG_FB_MXC_LDB=y
- +CONFIG_FB_MXC_MIPI_DSI=y
- +CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL=y
- +CONFIG_FB_MXC_HDMI=y
- +CONFIG_FB_MXC_EINK_PANEL=y
- +CONFIG_FB_MXS_SII902X=y
- +CONFIG_FRAMEBUFFER_CONSOLE=y
- +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
- +CONFIG_FONTS=y
- +CONFIG_FONT_8x8=y
- +CONFIG_FONT_8x16=y
- +CONFIG_LOGO=y
- +CONFIG_SOUND=y
- +CONFIG_SND=y
- +CONFIG_SND_USB_AUDIO=m
- +CONFIG_SND_SOC=y
- +CONFIG_SND_IMX_SOC=y
- +CONFIG_SND_SOC_EUKREA_TLV320=y
- +CONFIG_SND_SOC_IMX_CS42888=y
- +CONFIG_SND_SOC_IMX_WM8962=y
- +CONFIG_SND_SOC_IMX_SGTL5000=y
- +CONFIG_SND_SOC_IMX_SPDIF=y
- +CONFIG_SND_SOC_IMX_MC13783=y
- +CONFIG_SND_SOC_IMX_HDMI=y
- +CONFIG_SND_SOC_IMX_SI476X=y
- +CONFIG_USB=y
- +CONFIG_USB_EHCI_HCD=y
- +CONFIG_USB_STORAGE=y
- +CONFIG_USB_CHIPIDEA=y
- +CONFIG_USB_CHIPIDEA_UDC=y
- +CONFIG_USB_CHIPIDEA_HOST=y
- +CONFIG_USB_PHY=y
- +CONFIG_USB_MXS_PHY=y
- +CONFIG_USB_GADGET=y
- +# CONFIG_USB_ZERO is not set
- +# CONFIG_USB_AUDIO is not set
- +# CONFIG_USB_ETH is not set
- +# CONFIG_USB_G_NCM is not set
- +# CONFIG_USB_GADGETFS is not set
- +# CONFIG_USB_FUNCTIONFS is not set
- +CONFIG_USB_MASS_STORAGE=y
- +CONFIG_FSL_UTP=y
- +# CONFIG_USB_G_SERIAL is not set
- +# CONFIG_USB_MIDI_GADGET is not set
- +# CONFIG_USB_G_PRINTER is not set
- +# CONFIG_USB_CDC_COMPOSITE is not set
- +# CONFIG_USB_G_ACM_MS is not set
- +# CONFIG_USB_G_MULTI is not set
- +# CONFIG_USB_G_HID is not set
- +# CONFIG_USB_G_DBGP is not set
- +# CONFIG_USB_G_WEBCAM is not set
- +CONFIG_MMC=y
- +CONFIG_MMC_UNSAFE_RESUME=y
- +CONFIG_MMC_SDHCI=y
- +CONFIG_MMC_SDHCI_PLTFM=y
- +CONFIG_MMC_SDHCI_ESDHC_IMX=y
- +CONFIG_MXC_IPU=y
- +CONFIG_MXC_GPU_VIV=y
- +CONFIG_MXC_ASRC=y
- +CONFIG_MXC_MIPI_CSI2=y
- +CONFIG_NEW_LEDS=y
- +CONFIG_LEDS_CLASS=y
- +CONFIG_RTC_CLASS=y
- +CONFIG_RTC_INTF_DEV_UIE_EMUL=y
- +CONFIG_RTC_DRV_MC13XXX=y
- +CONFIG_RTC_DRV_MXC=y
- +CONFIG_RTC_DRV_SNVS=y
- +CONFIG_DMADEVICES=y
- +CONFIG_MXC_PXP_V2=y
- +CONFIG_IMX_SDMA=y
- +CONFIG_MXS_DMA=y
- +CONFIG_STAGING=y
- +CONFIG_COMMON_CLK_DEBUG=y
- +# CONFIG_IOMMU_SUPPORT is not set
- +CONFIG_PWM=y
- +CONFIG_PWM_IMX=y
- +CONFIG_EXT2_FS=y
- +CONFIG_EXT2_FS_XATTR=y
- +CONFIG_EXT2_FS_POSIX_ACL=y
- +CONFIG_EXT2_FS_SECURITY=y
- +CONFIG_EXT3_FS=y
- +CONFIG_EXT3_FS_POSIX_ACL=y
- +CONFIG_EXT3_FS_SECURITY=y
- +CONFIG_EXT4_FS=y
- +CONFIG_EXT4_FS_POSIX_ACL=y
- +CONFIG_EXT4_FS_SECURITY=y
- +CONFIG_QUOTA=y
- +CONFIG_QUOTA_NETLINK_INTERFACE=y
- +# CONFIG_PRINT_QUOTA_WARNING is not set
- +CONFIG_AUTOFS4_FS=y
- +CONFIG_FUSE_FS=y
- +CONFIG_ISO9660_FS=m
- +CONFIG_JOLIET=y
- +CONFIG_ZISOFS=y
- +CONFIG_UDF_FS=m
- +CONFIG_MSDOS_FS=m
- +CONFIG_VFAT_FS=y
- +CONFIG_TMPFS=y
- +CONFIG_JFFS2_FS=y
- +CONFIG_UBIFS_FS=y
- +CONFIG_NFS_FS=y
- +CONFIG_NFS_V3_ACL=y
- +CONFIG_NFS_V4=y
- +CONFIG_ROOT_NFS=y
- +CONFIG_NLS_DEFAULT="cp437"
- +CONFIG_NLS_CODEPAGE_437=y
- +CONFIG_NLS_ASCII=y
- +CONFIG_NLS_ISO8859_1=y
- +CONFIG_NLS_ISO8859_15=m
- +CONFIG_NLS_UTF8=y
- +CONFIG_MAGIC_SYSRQ=y
- +# CONFIG_SCHED_DEBUG is not set
- +# CONFIG_DEBUG_BUGVERBOSE is not set
- +# CONFIG_FTRACE is not set
- +CONFIG_SECURITYFS=y
- +CONFIG_CRYPTO_USER=y
- +CONFIG_CRYPTO_CCM=y
- +CONFIG_CRYPTO_GCM=y
- +CONFIG_CRYPTO_CBC=y
- +CONFIG_CRYPTO_CTS=y
- +CONFIG_CRYPTO_ECB=y
- +CONFIG_CRYPTO_LRW=y
- +# CONFIG_CRYPTO_ANSI_CPRNG is not set
- +CONFIG_CRYPTO_DEV_FSL_CAAM=y
- +CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y
- +CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=y
- +CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=y
- +CONFIG_CRC_CCITT=m
- +CONFIG_CRC_T10DIF=y
- +CONFIG_CRC7=m
- +CONFIG_LIBCRC32C=m
- diff -Nur linux-3.14.35.orig/arch/arm/include/asm/arch_timer.h linux-3.14.35/arch/arm/include/asm/arch_timer.h
- --- linux-3.14.35.orig/arch/arm/include/asm/arch_timer.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/include/asm/arch_timer.h 2015-03-08 14:27:37.409684502 -0500
- @@ -107,7 +107,6 @@
- /* Also disable virtual event stream */
- cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN
- | ARCH_TIMER_USR_VT_ACCESS_EN
- - | ARCH_TIMER_VIRT_EVT_EN
- | ARCH_TIMER_USR_VCT_ACCESS_EN
- | ARCH_TIMER_USR_PCT_ACCESS_EN);
- arch_timer_set_cntkctl(cntkctl);
- diff -Nur linux-3.14.35.orig/arch/arm/include/asm/atomic.h linux-3.14.35/arch/arm/include/asm/atomic.h
- --- linux-3.14.35.orig/arch/arm/include/asm/atomic.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/include/asm/atomic.h 2015-03-08 14:27:37.409684502 -0500
- @@ -60,6 +60,7 @@
- int result;
-
- smp_mb();
- + prefetchw(&v->counter);
-
- __asm__ __volatile__("@ atomic_add_return\n"
- "1: ldrex %0, [%3]\n"
- @@ -99,6 +100,7 @@
- int result;
-
- smp_mb();
- + prefetchw(&v->counter);
-
- __asm__ __volatile__("@ atomic_sub_return\n"
- "1: ldrex %0, [%3]\n"
- @@ -121,6 +123,7 @@
- unsigned long res;
-
- smp_mb();
- + prefetchw(&ptr->counter);
-
- do {
- __asm__ __volatile__("@ atomic_cmpxchg\n"
- @@ -138,6 +141,33 @@
- return oldval;
- }
-
- +static inline int __atomic_add_unless(atomic_t *v, int a, int u)
- +{
- + int oldval, newval;
- + unsigned long tmp;
- +
- + smp_mb();
- + prefetchw(&v->counter);
- +
- + __asm__ __volatile__ ("@ atomic_add_unless\n"
- +"1: ldrex %0, [%4]\n"
- +" teq %0, %5\n"
- +" beq 2f\n"
- +" add %1, %0, %6\n"
- +" strex %2, %1, [%4]\n"
- +" teq %2, #0\n"
- +" bne 1b\n"
- +"2:"
- + : "=&r" (oldval), "=&r" (newval), "=&r" (tmp), "+Qo" (v->counter)
- + : "r" (&v->counter), "r" (u), "r" (a)
- + : "cc");
- +
- + if (oldval != u)
- + smp_mb();
- +
- + return oldval;
- +}
- +
- #else /* ARM_ARCH_6 */
-
- #ifdef CONFIG_SMP
- @@ -186,10 +216,6 @@
- return ret;
- }
-
- -#endif /* __LINUX_ARM_ARCH__ */
- -
- -#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
- -
- static inline int __atomic_add_unless(atomic_t *v, int a, int u)
- {
- int c, old;
- @@ -200,6 +226,10 @@
- return c;
- }
-
- +#endif /* __LINUX_ARM_ARCH__ */
- +
- +#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
- +
- #define atomic_inc(v) atomic_add(1, v)
- #define atomic_dec(v) atomic_sub(1, v)
-
- @@ -299,6 +329,7 @@
- unsigned long tmp;
-
- smp_mb();
- + prefetchw(&v->counter);
-
- __asm__ __volatile__("@ atomic64_add_return\n"
- "1: ldrexd %0, %H0, [%3]\n"
- @@ -340,6 +371,7 @@
- unsigned long tmp;
-
- smp_mb();
- + prefetchw(&v->counter);
-
- __asm__ __volatile__("@ atomic64_sub_return\n"
- "1: ldrexd %0, %H0, [%3]\n"
- @@ -364,6 +396,7 @@
- unsigned long res;
-
- smp_mb();
- + prefetchw(&ptr->counter);
-
- do {
- __asm__ __volatile__("@ atomic64_cmpxchg\n"
- @@ -388,6 +421,7 @@
- unsigned long tmp;
-
- smp_mb();
- + prefetchw(&ptr->counter);
-
- __asm__ __volatile__("@ atomic64_xchg\n"
- "1: ldrexd %0, %H0, [%3]\n"
- @@ -409,6 +443,7 @@
- unsigned long tmp;
-
- smp_mb();
- + prefetchw(&v->counter);
-
- __asm__ __volatile__("@ atomic64_dec_if_positive\n"
- "1: ldrexd %0, %H0, [%3]\n"
- @@ -436,6 +471,7 @@
- int ret = 1;
-
- smp_mb();
- + prefetchw(&v->counter);
-
- __asm__ __volatile__("@ atomic64_add_unless\n"
- "1: ldrexd %0, %H0, [%4]\n"
- diff -Nur linux-3.14.35.orig/arch/arm/include/asm/cmpxchg.h linux-3.14.35/arch/arm/include/asm/cmpxchg.h
- --- linux-3.14.35.orig/arch/arm/include/asm/cmpxchg.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/include/asm/cmpxchg.h 2015-03-08 14:27:37.409684502 -0500
- @@ -2,6 +2,7 @@
- #define __ASM_ARM_CMPXCHG_H
-
- #include <linux/irqflags.h>
- +#include <linux/prefetch.h>
- #include <asm/barrier.h>
-
- #if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
- @@ -35,6 +36,7 @@
- #endif
-
- smp_mb();
- + prefetchw((const void *)ptr);
-
- switch (size) {
- #if __LINUX_ARM_ARCH__ >= 6
- @@ -138,6 +140,8 @@
- {
- unsigned long oldval, res;
-
- + prefetchw((const void *)ptr);
- +
- switch (size) {
- #ifndef CONFIG_CPU_V6 /* min ARCH >= ARMv6K */
- case 1:
- @@ -230,6 +234,8 @@
- unsigned long long oldval;
- unsigned long res;
-
- + prefetchw(ptr);
- +
- __asm__ __volatile__(
- "1: ldrexd %1, %H1, [%3]\n"
- " teq %1, %4\n"
- diff -Nur linux-3.14.35.orig/arch/arm/include/asm/ftrace.h linux-3.14.35/arch/arm/include/asm/ftrace.h
- --- linux-3.14.35.orig/arch/arm/include/asm/ftrace.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/include/asm/ftrace.h 2015-03-08 14:27:37.409684502 -0500
- @@ -52,15 +52,7 @@
-
- #endif
-
- -#define HAVE_ARCH_CALLER_ADDR
- -
- -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
- -#define CALLER_ADDR1 ((unsigned long)return_address(1))
- -#define CALLER_ADDR2 ((unsigned long)return_address(2))
- -#define CALLER_ADDR3 ((unsigned long)return_address(3))
- -#define CALLER_ADDR4 ((unsigned long)return_address(4))
- -#define CALLER_ADDR5 ((unsigned long)return_address(5))
- -#define CALLER_ADDR6 ((unsigned long)return_address(6))
- +#define ftrace_return_address(n) return_address(n)
-
- #endif /* ifndef __ASSEMBLY__ */
-
- diff -Nur linux-3.14.35.orig/arch/arm/include/asm/futex.h linux-3.14.35/arch/arm/include/asm/futex.h
- --- linux-3.14.35.orig/arch/arm/include/asm/futex.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/include/asm/futex.h 2015-03-08 14:27:37.409684502 -0500
- @@ -23,6 +23,7 @@
-
- #define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg) \
- smp_mb(); \
- + prefetchw(uaddr); \
- __asm__ __volatile__( \
- "1: ldrex %1, [%3]\n" \
- " " insn "\n" \
- @@ -46,6 +47,8 @@
- return -EFAULT;
-
- smp_mb();
- + /* Prefetching cannot fault */
- + prefetchw(uaddr);
- __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
- "1: ldrex %1, [%4]\n"
- " teq %1, %2\n"
- diff -Nur linux-3.14.35.orig/arch/arm/include/asm/glue-cache.h linux-3.14.35/arch/arm/include/asm/glue-cache.h
- --- linux-3.14.35.orig/arch/arm/include/asm/glue-cache.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/include/asm/glue-cache.h 2015-03-08 14:27:37.409684502 -0500
- @@ -102,19 +102,19 @@
- #endif
-
- #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
- -# ifdef _CACHE
- +//# ifdef _CACHE
- # define MULTI_CACHE 1
- -# else
- -# define _CACHE v6
- -# endif
- +//# else
- +//# define _CACHE v6
- +//# endif
- #endif
-
- #if defined(CONFIG_CPU_V7)
- -# ifdef _CACHE
- +//# ifdef _CACHE
- # define MULTI_CACHE 1
- -# else
- -# define _CACHE v7
- -# endif
- +//# else
- +//# define _CACHE v7
- +//# endif
- #endif
-
- #if defined(CONFIG_CPU_V7M)
- diff -Nur linux-3.14.35.orig/arch/arm/include/asm/hardware/cache-l2x0.h linux-3.14.35/arch/arm/include/asm/hardware/cache-l2x0.h
- --- linux-3.14.35.orig/arch/arm/include/asm/hardware/cache-l2x0.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/include/asm/hardware/cache-l2x0.h 2015-03-08 14:27:37.409684502 -0500
- @@ -26,8 +26,8 @@
- #define L2X0_CACHE_TYPE 0x004
- #define L2X0_CTRL 0x100
- #define L2X0_AUX_CTRL 0x104
- -#define L2X0_TAG_LATENCY_CTRL 0x108
- -#define L2X0_DATA_LATENCY_CTRL 0x10C
- +#define L310_TAG_LATENCY_CTRL 0x108
- +#define L310_DATA_LATENCY_CTRL 0x10C
- #define L2X0_EVENT_CNT_CTRL 0x200
- #define L2X0_EVENT_CNT1_CFG 0x204
- #define L2X0_EVENT_CNT0_CFG 0x208
- @@ -54,53 +54,93 @@
- #define L2X0_LOCKDOWN_WAY_D_BASE 0x900
- #define L2X0_LOCKDOWN_WAY_I_BASE 0x904
- #define L2X0_LOCKDOWN_STRIDE 0x08
- -#define L2X0_ADDR_FILTER_START 0xC00
- -#define L2X0_ADDR_FILTER_END 0xC04
- +#define L310_ADDR_FILTER_START 0xC00
- +#define L310_ADDR_FILTER_END 0xC04
- #define L2X0_TEST_OPERATION 0xF00
- #define L2X0_LINE_DATA 0xF10
- #define L2X0_LINE_TAG 0xF30
- #define L2X0_DEBUG_CTRL 0xF40
- -#define L2X0_PREFETCH_CTRL 0xF60
- -#define L2X0_POWER_CTRL 0xF80
- -#define L2X0_DYNAMIC_CLK_GATING_EN (1 << 1)
- -#define L2X0_STNDBY_MODE_EN (1 << 0)
- +#define L310_PREFETCH_CTRL 0xF60
- +#define L310_POWER_CTRL 0xF80
- +#define L310_DYNAMIC_CLK_GATING_EN (1 << 1)
- +#define L310_STNDBY_MODE_EN (1 << 0)
-
- /* Registers shifts and masks */
- #define L2X0_CACHE_ID_PART_MASK (0xf << 6)
- #define L2X0_CACHE_ID_PART_L210 (1 << 6)
- +#define L2X0_CACHE_ID_PART_L220 (2 << 6)
- #define L2X0_CACHE_ID_PART_L310 (3 << 6)
- #define L2X0_CACHE_ID_RTL_MASK 0x3f
- -#define L2X0_CACHE_ID_RTL_R0P0 0x0
- -#define L2X0_CACHE_ID_RTL_R1P0 0x2
- -#define L2X0_CACHE_ID_RTL_R2P0 0x4
- -#define L2X0_CACHE_ID_RTL_R3P0 0x5
- -#define L2X0_CACHE_ID_RTL_R3P1 0x6
- -#define L2X0_CACHE_ID_RTL_R3P2 0x8
- -
- -#define L2X0_AUX_CTRL_MASK 0xc0000fff
- +#define L210_CACHE_ID_RTL_R0P2_02 0x00
- +#define L210_CACHE_ID_RTL_R0P1 0x01
- +#define L210_CACHE_ID_RTL_R0P2_01 0x02
- +#define L210_CACHE_ID_RTL_R0P3 0x03
- +#define L210_CACHE_ID_RTL_R0P4 0x0b
- +#define L210_CACHE_ID_RTL_R0P5 0x0f
- +#define L220_CACHE_ID_RTL_R1P7_01REL0 0x06
- +#define L310_CACHE_ID_RTL_R0P0 0x00
- +#define L310_CACHE_ID_RTL_R1P0 0x02
- +#define L310_CACHE_ID_RTL_R2P0 0x04
- +#define L310_CACHE_ID_RTL_R3P0 0x05
- +#define L310_CACHE_ID_RTL_R3P1 0x06
- +#define L310_CACHE_ID_RTL_R3P1_50REL0 0x07
- +#define L310_CACHE_ID_RTL_R3P2 0x08
- +#define L310_CACHE_ID_RTL_R3P3 0x09
- +
- +/* L2C auxiliary control register - bits common to L2C-210/220/310 */
- +#define L2C_AUX_CTRL_WAY_SIZE_SHIFT 17
- +#define L2C_AUX_CTRL_WAY_SIZE_MASK (7 << 17)
- +#define L2C_AUX_CTRL_WAY_SIZE(n) ((n) << 17)
- +#define L2C_AUX_CTRL_EVTMON_ENABLE BIT(20)
- +#define L2C_AUX_CTRL_PARITY_ENABLE BIT(21)
- +#define L2C_AUX_CTRL_SHARED_OVERRIDE BIT(22)
- +/* L2C-210/220 common bits */
- #define L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT 0
- -#define L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK 0x7
- +#define L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK (7 << 0)
- #define L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT 3
- -#define L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK (0x7 << 3)
- +#define L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK (7 << 3)
- #define L2X0_AUX_CTRL_TAG_LATENCY_SHIFT 6
- -#define L2X0_AUX_CTRL_TAG_LATENCY_MASK (0x7 << 6)
- +#define L2X0_AUX_CTRL_TAG_LATENCY_MASK (7 << 6)
- #define L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT 9
- -#define L2X0_AUX_CTRL_DIRTY_LATENCY_MASK (0x7 << 9)
- -#define L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT 16
- -#define L2X0_AUX_CTRL_WAY_SIZE_SHIFT 17
- -#define L2X0_AUX_CTRL_WAY_SIZE_MASK (0x7 << 17)
- -#define L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT 22
- -#define L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT 26
- -#define L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT 27
- -#define L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT 28
- -#define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT 29
- -#define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT 30
- -
- -#define L2X0_LATENCY_CTRL_SETUP_SHIFT 0
- -#define L2X0_LATENCY_CTRL_RD_SHIFT 4
- -#define L2X0_LATENCY_CTRL_WR_SHIFT 8
- -
- -#define L2X0_ADDR_FILTER_EN 1
- +#define L2X0_AUX_CTRL_DIRTY_LATENCY_MASK (7 << 9)
- +#define L2X0_AUX_CTRL_ASSOC_SHIFT 13
- +#define L2X0_AUX_CTRL_ASSOC_MASK (15 << 13)
- +/* L2C-210 specific bits */
- +#define L210_AUX_CTRL_WRAP_DISABLE BIT(12)
- +#define L210_AUX_CTRL_WA_OVERRIDE BIT(23)
- +#define L210_AUX_CTRL_EXCLUSIVE_ABORT BIT(24)
- +/* L2C-220 specific bits */
- +#define L220_AUX_CTRL_EXCLUSIVE_CACHE BIT(12)
- +#define L220_AUX_CTRL_FWA_SHIFT 23
- +#define L220_AUX_CTRL_FWA_MASK (3 << 23)
- +#define L220_AUX_CTRL_NS_LOCKDOWN BIT(26)
- +#define L220_AUX_CTRL_NS_INT_CTRL BIT(27)
- +/* L2C-310 specific bits */
- +#define L310_AUX_CTRL_FULL_LINE_ZERO BIT(0) /* R2P0+ */
- +#define L310_AUX_CTRL_HIGHPRIO_SO_DEV BIT(10) /* R2P0+ */
- +#define L310_AUX_CTRL_STORE_LIMITATION BIT(11) /* R2P0+ */
- +#define L310_AUX_CTRL_EXCLUSIVE_CACHE BIT(12)
- +#define L310_AUX_CTRL_ASSOCIATIVITY_16 BIT(16)
- +#define L310_AUX_CTRL_CACHE_REPLACE_RR BIT(25) /* R2P0+ */
- +#define L310_AUX_CTRL_NS_LOCKDOWN BIT(26)
- +#define L310_AUX_CTRL_NS_INT_CTRL BIT(27)
- +#define L310_AUX_CTRL_DATA_PREFETCH BIT(28)
- +#define L310_AUX_CTRL_INSTR_PREFETCH BIT(29)
- +#define L310_AUX_CTRL_EARLY_BRESP BIT(30) /* R2P0+ */
- +
- +#define L310_LATENCY_CTRL_SETUP(n) ((n) << 0)
- +#define L310_LATENCY_CTRL_RD(n) ((n) << 4)
- +#define L310_LATENCY_CTRL_WR(n) ((n) << 8)
- +
- +#define L310_ADDR_FILTER_EN 1
- +
- +#define L310_PREFETCH_CTRL_OFFSET_MASK 0x1f
- +#define L310_PREFETCH_CTRL_DBL_LINEFILL_INCR BIT(23)
- +#define L310_PREFETCH_CTRL_PREFETCH_DROP BIT(24)
- +#define L310_PREFETCH_CTRL_DBL_LINEFILL_WRAP BIT(27)
- +#define L310_PREFETCH_CTRL_DATA_PREFETCH BIT(28)
- +#define L310_PREFETCH_CTRL_INSTR_PREFETCH BIT(29)
- +#define L310_PREFETCH_CTRL_DBL_LINEFILL BIT(30)
-
- #define L2X0_CTRL_EN 1
-
- diff -Nur linux-3.14.35.orig/arch/arm/include/asm/outercache.h linux-3.14.35/arch/arm/include/asm/outercache.h
- --- linux-3.14.35.orig/arch/arm/include/asm/outercache.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/include/asm/outercache.h 2015-03-08 14:27:37.409684502 -0500
- @@ -21,6 +21,7 @@
- #ifndef __ASM_OUTERCACHE_H
- #define __ASM_OUTERCACHE_H
-
- +#include <linux/bug.h>
- #include <linux/types.h>
-
- struct outer_cache_fns {
- @@ -28,53 +29,84 @@
- void (*clean_range)(unsigned long, unsigned long);
- void (*flush_range)(unsigned long, unsigned long);
- void (*flush_all)(void);
- - void (*inv_all)(void);
- void (*disable)(void);
- #ifdef CONFIG_OUTER_CACHE_SYNC
- void (*sync)(void);
- #endif
- - void (*set_debug)(unsigned long);
- void (*resume)(void);
- +
- + /* This is an ARM L2C thing */
- + void (*write_sec)(unsigned long, unsigned);
- };
-
- extern struct outer_cache_fns outer_cache;
-
- #ifdef CONFIG_OUTER_CACHE
- -
- +/**
- + * outer_inv_range - invalidate range of outer cache lines
- + * @start: starting physical address, inclusive
- + * @end: end physical address, exclusive
- + */
- static inline void outer_inv_range(phys_addr_t start, phys_addr_t end)
- {
- if (outer_cache.inv_range)
- outer_cache.inv_range(start, end);
- }
- +
- +/**
- + * outer_clean_range - clean dirty outer cache lines
- + * @start: starting physical address, inclusive
- + * @end: end physical address, exclusive
- + */
- static inline void outer_clean_range(phys_addr_t start, phys_addr_t end)
- {
- if (outer_cache.clean_range)
- outer_cache.clean_range(start, end);
- }
- +
- +/**
- + * outer_flush_range - clean and invalidate outer cache lines
- + * @start: starting physical address, inclusive
- + * @end: end physical address, exclusive
- + */
- static inline void outer_flush_range(phys_addr_t start, phys_addr_t end)
- {
- if (outer_cache.flush_range)
- outer_cache.flush_range(start, end);
- }
-
- +/**
- + * outer_flush_all - clean and invalidate all cache lines in the outer cache
- + *
- + * Note: depending on implementation, this may not be atomic - it must
- + * only be called with interrupts disabled and no other active outer
- + * cache masters.
- + *
- + * It is intended that this function is only used by implementations
- + * needing to override the outer_cache.disable() method due to security.
- + * (Some implementations perform this as a clean followed by an invalidate.)
- + */
- static inline void outer_flush_all(void)
- {
- if (outer_cache.flush_all)
- outer_cache.flush_all();
- }
-
- -static inline void outer_inv_all(void)
- -{
- - if (outer_cache.inv_all)
- - outer_cache.inv_all();
- -}
- -
- -static inline void outer_disable(void)
- -{
- - if (outer_cache.disable)
- - outer_cache.disable();
- -}
- -
- +/**
- + * outer_disable - clean, invalidate and disable the outer cache
- + *
- + * Disable the outer cache, ensuring that any data contained in the outer
- + * cache is pushed out to lower levels of system memory. The note and
- + * conditions above concerning outer_flush_all() applies here.
- + */
- +extern void outer_disable(void);
- +
- +/**
- + * outer_resume - restore the cache configuration and re-enable outer cache
- + *
- + * Restore any configuration that the cache had when previously enabled,
- + * and re-enable the outer cache.
- + */
- static inline void outer_resume(void)
- {
- if (outer_cache.resume)
- @@ -90,13 +122,18 @@
- static inline void outer_flush_range(phys_addr_t start, phys_addr_t end)
- { }
- static inline void outer_flush_all(void) { }
- -static inline void outer_inv_all(void) { }
- static inline void outer_disable(void) { }
- static inline void outer_resume(void) { }
-
- #endif
-
- #ifdef CONFIG_OUTER_CACHE_SYNC
- +/**
- + * outer_sync - perform a sync point for outer cache
- + *
- + * Ensure that all outer cache operations are complete and any store
- + * buffers are drained.
- + */
- static inline void outer_sync(void)
- {
- if (outer_cache.sync)
- diff -Nur linux-3.14.35.orig/arch/arm/include/asm/pmu.h linux-3.14.35/arch/arm/include/asm/pmu.h
- --- linux-3.14.35.orig/arch/arm/include/asm/pmu.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/include/asm/pmu.h 2015-03-08 14:27:37.409684502 -0500
- @@ -62,9 +62,19 @@
- raw_spinlock_t pmu_lock;
- };
-
- +struct cpupmu_regs {
- + u32 pmc;
- + u32 pmcntenset;
- + u32 pmuseren;
- + u32 pmintenset;
- + u32 pmxevttype[8];
- + u32 pmxevtcnt[8];
- +};
- +
- struct arm_pmu {
- struct pmu pmu;
- cpumask_t active_irqs;
- + cpumask_t valid_cpus;
- char *name;
- irqreturn_t (*handle_irq)(int irq_num, void *dev);
- void (*enable)(struct perf_event *event);
- @@ -81,6 +91,8 @@
- int (*request_irq)(struct arm_pmu *, irq_handler_t handler);
- void (*free_irq)(struct arm_pmu *);
- int (*map_event)(struct perf_event *event);
- + void (*save_regs)(struct arm_pmu *, struct cpupmu_regs *);
- + void (*restore_regs)(struct arm_pmu *, struct cpupmu_regs *);
- int num_events;
- atomic_t active_events;
- struct mutex reserve_mutex;
- diff -Nur linux-3.14.35.orig/arch/arm/include/asm/psci.h linux-3.14.35/arch/arm/include/asm/psci.h
- --- linux-3.14.35.orig/arch/arm/include/asm/psci.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/include/asm/psci.h 2015-03-08 14:27:37.409684502 -0500
- @@ -16,6 +16,10 @@
-
- #define PSCI_POWER_STATE_TYPE_STANDBY 0
- #define PSCI_POWER_STATE_TYPE_POWER_DOWN 1
- +#define PSCI_POWER_STATE_AFFINITY_LEVEL0 0
- +#define PSCI_POWER_STATE_AFFINITY_LEVEL1 1
- +#define PSCI_POWER_STATE_AFFINITY_LEVEL2 2
- +#define PSCI_POWER_STATE_AFFINITY_LEVEL3 3
-
- struct psci_power_state {
- u16 id;
- @@ -42,4 +46,12 @@
- static inline bool psci_smp_available(void) { return false; }
- #endif
-
- +#ifdef CONFIG_ARM_PSCI
- +extern int psci_probe(void);
- +#else
- +static inline int psci_probe(void)
- +{
- + return -ENODEV;
- +}
- +#endif
- #endif /* __ASM_ARM_PSCI_H */
- diff -Nur linux-3.14.35.orig/arch/arm/include/asm/topology.h linux-3.14.35/arch/arm/include/asm/topology.h
- --- linux-3.14.35.orig/arch/arm/include/asm/topology.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/include/asm/topology.h 2015-03-08 14:27:37.409684502 -0500
- @@ -26,11 +26,14 @@
- void init_cpu_topology(void);
- void store_cpu_topology(unsigned int cpuid);
- const struct cpumask *cpu_coregroup_mask(int cpu);
- +int cluster_to_logical_mask(unsigned int socket_id, cpumask_t *cluster_mask);
-
- #else
-
- static inline void init_cpu_topology(void) { }
- static inline void store_cpu_topology(unsigned int cpuid) { }
- +static inline int cluster_to_logical_mask(unsigned int socket_id,
- + cpumask_t *cluster_mask) { return -EINVAL; }
-
- #endif
-
- diff -Nur linux-3.14.35.orig/arch/arm/Kconfig linux-3.14.35/arch/arm/Kconfig
- --- linux-3.14.35.orig/arch/arm/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/Kconfig 2015-03-08 14:27:37.409684502 -0500
- @@ -1216,19 +1216,6 @@
- register of the Cortex-A9 which reduces the linefill issuing
- capabilities of the processor.
-
- -config PL310_ERRATA_588369
- - bool "PL310 errata: Clean & Invalidate maintenance operations do not invalidate clean lines"
- - depends on CACHE_L2X0
- - help
- - The PL310 L2 cache controller implements three types of Clean &
- - Invalidate maintenance operations: by Physical Address
- - (offset 0x7F0), by Index/Way (0x7F8) and by Way (0x7FC).
- - They are architecturally defined to behave as the execution of a
- - clean operation followed immediately by an invalidate operation,
- - both performing to the same memory location. This functionality
- - is not correctly implemented in PL310 as clean lines are not
- - invalidated as a result of these operations.
- -
- config ARM_ERRATA_643719
- bool "ARM errata: LoUIS bit field in CLIDR register is incorrect"
- depends on CPU_V7 && SMP
- @@ -1251,17 +1238,6 @@
- tables. The workaround changes the TLB flushing routines to invalidate
- entries regardless of the ASID.
-
- -config PL310_ERRATA_727915
- - bool "PL310 errata: Background Clean & Invalidate by Way operation can cause data corruption"
- - depends on CACHE_L2X0
- - help
- - PL310 implements the Clean & Invalidate by Way L2 cache maintenance
- - operation (offset 0x7FC). This operation runs in background so that
- - PL310 can handle normal accesses while it is in progress. Under very
- - rare circumstances, due to this erratum, write data can be lost when
- - PL310 treats a cacheable write transaction during a Clean &
- - Invalidate by Way operation.
- -
- config ARM_ERRATA_743622
- bool "ARM errata: Faulty hazard checking in the Store Buffer may lead to data corruption"
- depends on CPU_V7
- @@ -1287,21 +1263,6 @@
- operation is received by a CPU before the ICIALLUIS has completed,
- potentially leading to corrupted entries in the cache or TLB.
-
- -config PL310_ERRATA_753970
- - bool "PL310 errata: cache sync operation may be faulty"
- - depends on CACHE_PL310
- - help
- - This option enables the workaround for the 753970 PL310 (r3p0) erratum.
- -
- - Under some condition the effect of cache sync operation on
- - the store buffer still remains when the operation completes.
- - This means that the store buffer is always asked to drain and
- - this prevents it from merging any further writes. The workaround
- - is to replace the normal offset of cache sync operation (0x730)
- - by another offset targeting an unmapped PL310 register 0x740.
- - This has the same effect as the cache sync operation: store buffer
- - drain and waiting for all buffers empty.
- -
- config ARM_ERRATA_754322
- bool "ARM errata: possible faulty MMU translations following an ASID switch"
- depends on CPU_V7
- @@ -1350,18 +1311,6 @@
- relevant cache maintenance functions and sets a specific bit
- in the diagnostic control register of the SCU.
-
- -config PL310_ERRATA_769419
- - bool "PL310 errata: no automatic Store Buffer drain"
- - depends on CACHE_L2X0
- - help
- - On revisions of the PL310 prior to r3p2, the Store Buffer does
- - not automatically drain. This can cause normal, non-cacheable
- - writes to be retained when the memory system is idle, leading
- - to suboptimal I/O performance for drivers using coherent DMA.
- - This option adds a write barrier to the cpu_idle loop so that,
- - on systems with an outer cache, the store buffer is drained
- - explicitly.
- -
- config ARM_ERRATA_775420
- bool "ARM errata: A data cache maintenance operation which aborts, might lead to deadlock"
- depends on CPU_V7
- @@ -1391,6 +1340,29 @@
- loop buffer may deliver incorrect instructions. This
- workaround disables the loop buffer to avoid the erratum.
-
- +config ARM_ERRATA_794072
- + bool "ARM errata: A short loop including a DMB instruction might cause a denial of service"
- + depends on CPU_V7 && SMP
- + help
- + This option enables the workaround for the 794072 Cortex-A9
- + (all revisions). A processor which continuously executes a short
- + loop containing a DMB instruction might prevent a CP15 operation
- + broadcast by another processor making further progress, causing
- + a denial of service. This erratum can be worked around by setting
- + bit[4] of the undocumented Diagnostic Control Register to 1.
- +
- +config ARM_ERRATA_761320
- + bool "Full cache line writes to the same memory region from at least two processors might deadlock processor"
- + depends on CPU_V7 && SMP
- + help
- + This option enables the workaround for the 761320 Cortex-A9 (r0..r3).
- + Under very rare circumstances, full cache line writes
- + from (at least) 2 processors on cache lines in hazard with
- + other requests may cause arbitration issues in the SCU,
- + leading to processor deadlock. This erratum can be
- + worked around by setting bit[21] of the undocumented
- + Diagnostic Control Register to 1.
- +
- endmenu
-
- source "arch/arm/common/Kconfig"
- @@ -1835,6 +1807,7 @@
- range 11 64 if ARCH_SHMOBILE_LEGACY
- default "12" if SOC_AM33XX
- default "9" if SA1111 || ARCH_EFM32
- + default "14" if ARCH_MXC
- default "11"
- help
- The kernel memory allocator divides physically contiguous memory
- diff -Nur linux-3.14.35.orig/arch/arm/kernel/perf_event.c linux-3.14.35/arch/arm/kernel/perf_event.c
- --- linux-3.14.35.orig/arch/arm/kernel/perf_event.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/kernel/perf_event.c 2015-03-08 14:27:37.409684502 -0500
- @@ -12,6 +12,7 @@
- */
- #define pr_fmt(fmt) "hw perfevents: " fmt
-
- +#include <linux/cpumask.h>
- #include <linux/kernel.h>
- #include <linux/platform_device.h>
- #include <linux/pm_runtime.h>
- @@ -86,6 +87,9 @@
- return armpmu_map_cache_event(cache_map, config);
- case PERF_TYPE_RAW:
- return armpmu_map_raw_event(raw_event_mask, config);
- + default:
- + if (event->attr.type >= PERF_TYPE_MAX)
- + return armpmu_map_raw_event(raw_event_mask, config);
- }
-
- return -ENOENT;
- @@ -159,6 +163,8 @@
- struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
- struct hw_perf_event *hwc = &event->hw;
-
- + if (!cpumask_test_cpu(smp_processor_id(), &armpmu->valid_cpus))
- + return;
- /*
- * ARM pmu always has to update the counter, so ignore
- * PERF_EF_UPDATE, see comments in armpmu_start().
- @@ -175,6 +181,8 @@
- struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
- struct hw_perf_event *hwc = &event->hw;
-
- + if (!cpumask_test_cpu(smp_processor_id(), &armpmu->valid_cpus))
- + return;
- /*
- * ARM pmu always has to reprogram the period, so ignore
- * PERF_EF_RELOAD, see the comment below.
- @@ -202,6 +210,9 @@
- struct hw_perf_event *hwc = &event->hw;
- int idx = hwc->idx;
-
- + if (!cpumask_test_cpu(smp_processor_id(), &armpmu->valid_cpus))
- + return;
- +
- armpmu_stop(event, PERF_EF_UPDATE);
- hw_events->events[idx] = NULL;
- clear_bit(idx, hw_events->used_mask);
- @@ -218,6 +229,10 @@
- int idx;
- int err = 0;
-
- + /* An event following a process won't be stopped earlier */
- + if (!cpumask_test_cpu(smp_processor_id(), &armpmu->valid_cpus))
- + return 0;
- +
- perf_pmu_disable(event->pmu);
-
- /* If we don't have a space for the counter then finish early. */
- @@ -419,6 +434,10 @@
- int err = 0;
- atomic_t *active_events = &armpmu->active_events;
-
- + if (event->cpu != -1 &&
- + !cpumask_test_cpu(event->cpu, &armpmu->valid_cpus))
- + return -ENOENT;
- +
- /* does not support taken branch sampling */
- if (has_branch_stack(event))
- return -EOPNOTSUPP;
- diff -Nur linux-3.14.35.orig/arch/arm/kernel/perf_event_cpu.c linux-3.14.35/arch/arm/kernel/perf_event_cpu.c
- --- linux-3.14.35.orig/arch/arm/kernel/perf_event_cpu.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/kernel/perf_event_cpu.c 2015-03-08 14:27:37.413684502 -0500
- @@ -19,6 +19,7 @@
- #define pr_fmt(fmt) "CPU PMU: " fmt
-
- #include <linux/bitmap.h>
- +#include <linux/cpu_pm.h>
- #include <linux/export.h>
- #include <linux/kernel.h>
- #include <linux/of.h>
- @@ -31,33 +32,36 @@
- #include <asm/pmu.h>
-
- /* Set at runtime when we know what CPU type we are. */
- -static struct arm_pmu *cpu_pmu;
- +static DEFINE_PER_CPU(struct arm_pmu *, cpu_pmu);
-
- static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events);
- static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask);
- static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
-
- +static DEFINE_PER_CPU(struct cpupmu_regs, cpu_pmu_regs);
- +
- /*
- * Despite the names, these two functions are CPU-specific and are used
- * by the OProfile/perf code.
- */
- const char *perf_pmu_name(void)
- {
- - if (!cpu_pmu)
- + struct arm_pmu *pmu = per_cpu(cpu_pmu, 0);
- + if (!pmu)
- return NULL;
-
- - return cpu_pmu->name;
- + return pmu->name;
- }
- EXPORT_SYMBOL_GPL(perf_pmu_name);
-
- int perf_num_counters(void)
- {
- - int max_events = 0;
- + struct arm_pmu *pmu = per_cpu(cpu_pmu, 0);
-
- - if (cpu_pmu != NULL)
- - max_events = cpu_pmu->num_events;
- + if (!pmu)
- + return 0;
-
- - return max_events;
- + return pmu->num_events;
- }
- EXPORT_SYMBOL_GPL(perf_num_counters);
-
- @@ -75,11 +79,13 @@
- {
- int i, irq, irqs;
- struct platform_device *pmu_device = cpu_pmu->plat_device;
- + int cpu = -1;
-
- irqs = min(pmu_device->num_resources, num_possible_cpus());
-
- for (i = 0; i < irqs; ++i) {
- - if (!cpumask_test_and_clear_cpu(i, &cpu_pmu->active_irqs))
- + cpu = cpumask_next(cpu, &cpu_pmu->valid_cpus);
- + if (!cpumask_test_and_clear_cpu(cpu, &cpu_pmu->active_irqs))
- continue;
- irq = platform_get_irq(pmu_device, i);
- if (irq >= 0)
- @@ -91,6 +97,7 @@
- {
- int i, err, irq, irqs;
- struct platform_device *pmu_device = cpu_pmu->plat_device;
- + int cpu = -1;
-
- if (!pmu_device)
- return -ENODEV;
- @@ -103,6 +110,7 @@
-
- for (i = 0; i < irqs; ++i) {
- err = 0;
- + cpu = cpumask_next(cpu, &cpu_pmu->valid_cpus);
- irq = platform_get_irq(pmu_device, i);
- if (irq < 0)
- continue;
- @@ -112,7 +120,7 @@
- * assume that we're running on a uniprocessor machine and
- * continue. Otherwise, continue without this interrupt.
- */
- - if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) {
- + if (irq_set_affinity(irq, cpumask_of(cpu)) && irqs > 1) {
- pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
- irq, i);
- continue;
- @@ -127,7 +135,7 @@
- return err;
- }
-
- - cpumask_set_cpu(i, &cpu_pmu->active_irqs);
- + cpumask_set_cpu(cpu, &cpu_pmu->active_irqs);
- }
-
- return 0;
- @@ -136,7 +144,7 @@
- static void cpu_pmu_init(struct arm_pmu *cpu_pmu)
- {
- int cpu;
- - for_each_possible_cpu(cpu) {
- + for_each_cpu_mask(cpu, cpu_pmu->valid_cpus) {
- struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu);
- events->events = per_cpu(hw_events, cpu);
- events->used_mask = per_cpu(used_mask, cpu);
- @@ -149,7 +157,7 @@
-
- /* Ensure the PMU has sane values out of reset. */
- if (cpu_pmu->reset)
- - on_each_cpu(cpu_pmu->reset, cpu_pmu, 1);
- + on_each_cpu_mask(&cpu_pmu->valid_cpus, cpu_pmu->reset, cpu_pmu, 1);
- }
-
- /*
- @@ -161,21 +169,46 @@
- static int cpu_pmu_notify(struct notifier_block *b, unsigned long action,
- void *hcpu)
- {
- + struct arm_pmu *pmu = per_cpu(cpu_pmu, (long)hcpu);
- +
- if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
- return NOTIFY_DONE;
-
- - if (cpu_pmu && cpu_pmu->reset)
- - cpu_pmu->reset(cpu_pmu);
- + if (pmu && pmu->reset)
- + pmu->reset(pmu);
- else
- return NOTIFY_DONE;
-
- return NOTIFY_OK;
- }
-
- +static int cpu_pmu_pm_notify(struct notifier_block *b,
- + unsigned long action, void *hcpu)
- +{
- + int cpu = smp_processor_id();
- + struct arm_pmu *pmu = per_cpu(cpu_pmu, cpu);
- + struct cpupmu_regs *pmuregs = &per_cpu(cpu_pmu_regs, cpu);
- +
- + if (!pmu)
- + return NOTIFY_DONE;
- +
- + if (action == CPU_PM_ENTER && pmu->save_regs) {
- + pmu->save_regs(pmu, pmuregs);
- + } else if (action == CPU_PM_EXIT && pmu->restore_regs) {
- + pmu->restore_regs(pmu, pmuregs);
- + }
- +
- + return NOTIFY_OK;
- +}
- +
- static struct notifier_block cpu_pmu_hotplug_notifier = {
- .notifier_call = cpu_pmu_notify,
- };
-
- +static struct notifier_block cpu_pmu_pm_notifier = {
- + .notifier_call = cpu_pmu_pm_notify,
- +};
- +
- /*
- * PMU platform driver and devicetree bindings.
- */
- @@ -247,6 +280,9 @@
- }
- }
-
- + /* assume PMU support all the CPUs in this case */
- + cpumask_setall(&pmu->valid_cpus);
- +
- put_cpu();
- return ret;
- }
- @@ -254,15 +290,10 @@
- static int cpu_pmu_device_probe(struct platform_device *pdev)
- {
- const struct of_device_id *of_id;
- - const int (*init_fn)(struct arm_pmu *);
- struct device_node *node = pdev->dev.of_node;
- struct arm_pmu *pmu;
- - int ret = -ENODEV;
- -
- - if (cpu_pmu) {
- - pr_info("attempt to register multiple PMU devices!");
- - return -ENOSPC;
- - }
- + int ret = 0;
- + int cpu;
-
- pmu = kzalloc(sizeof(struct arm_pmu), GFP_KERNEL);
- if (!pmu) {
- @@ -271,8 +302,28 @@
- }
-
- if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) {
- - init_fn = of_id->data;
- - ret = init_fn(pmu);
- + smp_call_func_t init_fn = (smp_call_func_t)of_id->data;
- + struct device_node *ncluster;
- + int cluster = -1;
- + cpumask_t sibling_mask;
- +
- + ncluster = of_parse_phandle(node, "cluster", 0);
- + if (ncluster) {
- + int len;
- + const u32 *hwid;
- + hwid = of_get_property(ncluster, "reg", &len);
- + if (hwid && len == 4)
- + cluster = be32_to_cpup(hwid);
- + }
- + /* set sibling mask to all cpu mask if socket is not specified */
- + if (cluster == -1 ||
- + cluster_to_logical_mask(cluster, &sibling_mask))
- + cpumask_setall(&sibling_mask);
- +
- + smp_call_function_any(&sibling_mask, init_fn, pmu, 1);
- +
- + /* now set the valid_cpus after init */
- + cpumask_copy(&pmu->valid_cpus, &sibling_mask);
- } else {
- ret = probe_current_pmu(pmu);
- }
- @@ -282,10 +333,12 @@
- goto out_free;
- }
-
- - cpu_pmu = pmu;
- - cpu_pmu->plat_device = pdev;
- - cpu_pmu_init(cpu_pmu);
- - ret = armpmu_register(cpu_pmu, PERF_TYPE_RAW);
- + for_each_cpu_mask(cpu, pmu->valid_cpus)
- + per_cpu(cpu_pmu, cpu) = pmu;
- +
- + pmu->plat_device = pdev;
- + cpu_pmu_init(pmu);
- + ret = armpmu_register(pmu, -1);
-
- if (!ret)
- return 0;
- @@ -314,9 +367,17 @@
- if (err)
- return err;
-
- + err = cpu_pm_register_notifier(&cpu_pmu_pm_notifier);
- + if (err) {
- + unregister_cpu_notifier(&cpu_pmu_hotplug_notifier);
- + return err;
- + }
- +
- err = platform_driver_register(&cpu_pmu_driver);
- - if (err)
- + if (err) {
- + cpu_pm_unregister_notifier(&cpu_pmu_pm_notifier);
- unregister_cpu_notifier(&cpu_pmu_hotplug_notifier);
- + }
-
- return err;
- }
- diff -Nur linux-3.14.35.orig/arch/arm/kernel/perf_event_v7.c linux-3.14.35/arch/arm/kernel/perf_event_v7.c
- --- linux-3.14.35.orig/arch/arm/kernel/perf_event_v7.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/kernel/perf_event_v7.c 2015-03-08 14:27:37.413684502 -0500
- @@ -950,6 +950,51 @@
- }
- #endif
-
- +static void armv7pmu_save_regs(struct arm_pmu *cpu_pmu,
- + struct cpupmu_regs *regs)
- +{
- + unsigned int cnt;
- + asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (regs->pmc));
- + if (!(regs->pmc & ARMV7_PMNC_E))
- + return;
- +
- + asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (regs->pmcntenset));
- + asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r" (regs->pmuseren));
- + asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (regs->pmintenset));
- + asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (regs->pmxevtcnt[0]));
- + for (cnt = ARMV7_IDX_COUNTER0;
- + cnt <= ARMV7_IDX_COUNTER_LAST(cpu_pmu); cnt++) {
- + armv7_pmnc_select_counter(cnt);
- + asm volatile("mrc p15, 0, %0, c9, c13, 1"
- + : "=r"(regs->pmxevttype[cnt]));
- + asm volatile("mrc p15, 0, %0, c9, c13, 2"
- + : "=r"(regs->pmxevtcnt[cnt]));
- + }
- + return;
- +}
- +
- +static void armv7pmu_restore_regs(struct arm_pmu *cpu_pmu,
- + struct cpupmu_regs *regs)
- +{
- + unsigned int cnt;
- + if (!(regs->pmc & ARMV7_PMNC_E))
- + return;
- +
- + asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (regs->pmcntenset));
- + asm volatile("mcr p15, 0, %0, c9, c14, 0" : : "r" (regs->pmuseren));
- + asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (regs->pmintenset));
- + asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (regs->pmxevtcnt[0]));
- + for (cnt = ARMV7_IDX_COUNTER0;
- + cnt <= ARMV7_IDX_COUNTER_LAST(cpu_pmu); cnt++) {
- + armv7_pmnc_select_counter(cnt);
- + asm volatile("mcr p15, 0, %0, c9, c13, 1"
- + : : "r"(regs->pmxevttype[cnt]));
- + asm volatile("mcr p15, 0, %0, c9, c13, 2"
- + : : "r"(regs->pmxevtcnt[cnt]));
- + }
- + asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r" (regs->pmc));
- +}
- +
- static void armv7pmu_enable_event(struct perf_event *event)
- {
- unsigned long flags;
- @@ -1223,6 +1268,8 @@
- cpu_pmu->start = armv7pmu_start;
- cpu_pmu->stop = armv7pmu_stop;
- cpu_pmu->reset = armv7pmu_reset;
- + cpu_pmu->save_regs = armv7pmu_save_regs;
- + cpu_pmu->restore_regs = armv7pmu_restore_regs;
- cpu_pmu->max_period = (1LLU << 32) - 1;
- };
-
- @@ -1240,7 +1287,7 @@
- static int armv7_a8_pmu_init(struct arm_pmu *cpu_pmu)
- {
- armv7pmu_init(cpu_pmu);
- - cpu_pmu->name = "ARMv7 Cortex-A8";
- + cpu_pmu->name = "ARMv7_Cortex_A8";
- cpu_pmu->map_event = armv7_a8_map_event;
- cpu_pmu->num_events = armv7_read_num_pmnc_events();
- return 0;
- @@ -1249,7 +1296,7 @@
- static int armv7_a9_pmu_init(struct arm_pmu *cpu_pmu)
- {
- armv7pmu_init(cpu_pmu);
- - cpu_pmu->name = "ARMv7 Cortex-A9";
- + cpu_pmu->name = "ARMv7_Cortex_A9";
- cpu_pmu->map_event = armv7_a9_map_event;
- cpu_pmu->num_events = armv7_read_num_pmnc_events();
- return 0;
- @@ -1258,7 +1305,7 @@
- static int armv7_a5_pmu_init(struct arm_pmu *cpu_pmu)
- {
- armv7pmu_init(cpu_pmu);
- - cpu_pmu->name = "ARMv7 Cortex-A5";
- + cpu_pmu->name = "ARMv7_Cortex_A5";
- cpu_pmu->map_event = armv7_a5_map_event;
- cpu_pmu->num_events = armv7_read_num_pmnc_events();
- return 0;
- @@ -1267,7 +1314,7 @@
- static int armv7_a15_pmu_init(struct arm_pmu *cpu_pmu)
- {
- armv7pmu_init(cpu_pmu);
- - cpu_pmu->name = "ARMv7 Cortex-A15";
- + cpu_pmu->name = "ARMv7_Cortex_A15";
- cpu_pmu->map_event = armv7_a15_map_event;
- cpu_pmu->num_events = armv7_read_num_pmnc_events();
- cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
- @@ -1277,7 +1324,7 @@
- static int armv7_a7_pmu_init(struct arm_pmu *cpu_pmu)
- {
- armv7pmu_init(cpu_pmu);
- - cpu_pmu->name = "ARMv7 Cortex-A7";
- + cpu_pmu->name = "ARMv7_Cortex_A7";
- cpu_pmu->map_event = armv7_a7_map_event;
- cpu_pmu->num_events = armv7_read_num_pmnc_events();
- cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
- diff -Nur linux-3.14.35.orig/arch/arm/kernel/process.c linux-3.14.35/arch/arm/kernel/process.c
- --- linux-3.14.35.orig/arch/arm/kernel/process.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/kernel/process.c 2015-03-08 14:27:37.413684502 -0500
- @@ -172,8 +172,10 @@
- */
- void arch_cpu_idle(void)
- {
- + idle_notifier_call_chain(IDLE_START);
- if (cpuidle_idle_call())
- default_idle();
- + idle_notifier_call_chain(IDLE_END);
- }
-
- /*
- diff -Nur linux-3.14.35.orig/arch/arm/kernel/psci.c linux-3.14.35/arch/arm/kernel/psci.c
- --- linux-3.14.35.orig/arch/arm/kernel/psci.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/kernel/psci.c 2015-03-08 14:27:37.413684502 -0500
- @@ -42,6 +42,7 @@
- #define PSCI_RET_EOPNOTSUPP -1
- #define PSCI_RET_EINVAL -2
- #define PSCI_RET_EPERM -3
- +#define PSCI_RET_EALREADYON -4
-
- static int psci_to_linux_errno(int errno)
- {
- @@ -54,6 +55,8 @@
- return -EINVAL;
- case PSCI_RET_EPERM:
- return -EPERM;
- + case PSCI_RET_EALREADYON:
- + return -EAGAIN;
- };
-
- return -EINVAL;
- @@ -153,7 +156,7 @@
- return psci_to_linux_errno(err);
- }
-
- -static const struct of_device_id psci_of_match[] __initconst = {
- +static const struct of_device_id psci_of_match[] = {
- { .compatible = "arm,psci", },
- {},
- };
- @@ -208,3 +211,16 @@
- of_node_put(np);
- return;
- }
- +
- +int psci_probe(void)
- +{
- + struct device_node *np;
- + int ret = -ENODEV;
- +
- + np = of_find_matching_node(NULL, psci_of_match);
- + if (np)
- + ret = 0;
- +
- + of_node_put(np);
- + return ret;
- +}
- diff -Nur linux-3.14.35.orig/arch/arm/kernel/setup.c linux-3.14.35/arch/arm/kernel/setup.c
- --- linux-3.14.35.orig/arch/arm/kernel/setup.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/kernel/setup.c 2015-03-08 14:27:37.413684502 -0500
- @@ -273,6 +273,19 @@
- int aliasing_icache;
- unsigned int id_reg, num_sets, line_size;
-
- +#ifdef CONFIG_BIG_LITTLE
- + /*
- + * We expect a combination of Cortex-A15 and Cortex-A7 cores.
- + * A7 = VIPT aliasing I-cache
- + * A15 = PIPT (non-aliasing) I-cache
- + * To cater for this discrepancy, let's assume aliasing I-cache
- + * all the time. This means unneeded extra work on the A15 but
- + * only ptrace is affected which is not performance critical.
- + */
- + if ((read_cpuid_id() & 0xff0ffff0) == 0x410fc0f0)
- + return 1;
- +#endif
- +
- /* PIPT caches never alias. */
- if (icache_is_pipt())
- return 0;
- diff -Nur linux-3.14.35.orig/arch/arm/kernel/topology.c linux-3.14.35/arch/arm/kernel/topology.c
- --- linux-3.14.35.orig/arch/arm/kernel/topology.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/kernel/topology.c 2015-03-08 14:27:37.413684502 -0500
- @@ -267,6 +267,33 @@
- }
-
- /*
- + * cluster_to_logical_mask - return cpu logical mask of CPUs in a cluster
- + * @socket_id: cluster HW identifier
- + * @cluster_mask: the cpumask location to be initialized, modified by the
- + * function only if return value == 0
- + *
- + * Return:
- + *
- + * 0 on success
- + * -EINVAL if cluster_mask is NULL or there is no record matching socket_id
- + */
- +int cluster_to_logical_mask(unsigned int socket_id, cpumask_t *cluster_mask)
- +{
- + int cpu;
- +
- + if (!cluster_mask)
- + return -EINVAL;
- +
- + for_each_online_cpu(cpu)
- + if (socket_id == topology_physical_package_id(cpu)) {
- + cpumask_copy(cluster_mask, topology_core_cpumask(cpu));
- + return 0;
- + }
- +
- + return -EINVAL;
- +}
- +
- +/*
- * init_cpu_topology is called at boot when only one cpu is running
- * which prevent simultaneous write access to cpu_topology array
- */
- diff -Nur linux-3.14.35.orig/arch/arm/lib/bitops.h linux-3.14.35/arch/arm/lib/bitops.h
- --- linux-3.14.35.orig/arch/arm/lib/bitops.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/lib/bitops.h 2015-03-08 14:27:37.413684502 -0500
- @@ -37,6 +37,11 @@
- add r1, r1, r0, lsl #2 @ Get word offset
- mov r3, r2, lsl r3 @ create mask
- smp_dmb
- +#if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
- + .arch_extension mp
- + ALT_SMP(W(pldw) [r1])
- + ALT_UP(W(nop))
- +#endif
- 1: ldrex r2, [r1]
- ands r0, r2, r3 @ save old value of bit
- \instr r2, r2, r3 @ toggle bit
- diff -Nur linux-3.14.35.orig/arch/arm/mach-berlin/berlin.c linux-3.14.35/arch/arm/mach-berlin/berlin.c
- --- linux-3.14.35.orig/arch/arm/mach-berlin/berlin.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-berlin/berlin.c 2015-03-08 14:27:37.413684502 -0500
- @@ -24,7 +24,7 @@
- * with DT probing for L2CCs, berlin_init_machine can be removed.
- * Note: 88DE3005 (Armada 1500-mini) uses pl310 l2cc
- */
- - l2x0_of_init(0x70c00000, 0xfeffffff);
- + l2x0_of_init(0x30c00000, 0xfeffffff);
- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
- }
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-cns3xxx/core.c linux-3.14.35/arch/arm/mach-cns3xxx/core.c
- --- linux-3.14.35.orig/arch/arm/mach-cns3xxx/core.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-cns3xxx/core.c 2015-03-08 14:27:37.413684502 -0500
- @@ -240,9 +240,9 @@
- *
- * 1 cycle of latency for setup, read and write accesses
- */
- - val = readl(base + L2X0_TAG_LATENCY_CTRL);
- + val = readl(base + L310_TAG_LATENCY_CTRL);
- val &= 0xfffff888;
- - writel(val, base + L2X0_TAG_LATENCY_CTRL);
- + writel(val, base + L310_TAG_LATENCY_CTRL);
-
- /*
- * Data RAM Control register
- @@ -253,12 +253,12 @@
- *
- * 1 cycle of latency for setup, read and write accesses
- */
- - val = readl(base + L2X0_DATA_LATENCY_CTRL);
- + val = readl(base + L310_DATA_LATENCY_CTRL);
- val &= 0xfffff888;
- - writel(val, base + L2X0_DATA_LATENCY_CTRL);
- + writel(val, base + L310_DATA_LATENCY_CTRL);
-
- /* 32 KiB, 8-way, parity disable */
- - l2x0_init(base, 0x00540000, 0xfe000fff);
- + l2x0_init(base, 0x00500000, 0xfe0f0fff);
- }
-
- #endif /* CONFIG_CACHE_L2X0 */
- diff -Nur linux-3.14.35.orig/arch/arm/mach-exynos/common.c linux-3.14.35/arch/arm/mach-exynos/common.c
- --- linux-3.14.35.orig/arch/arm/mach-exynos/common.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-exynos/common.c 2015-03-08 14:27:37.413684502 -0500
- @@ -45,9 +45,6 @@
- #include "common.h"
- #include "regs-pmu.h"
-
- -#define L2_AUX_VAL 0x7C470001
- -#define L2_AUX_MASK 0xC200ffff
- -
- static const char name_exynos4210[] = "EXYNOS4210";
- static const char name_exynos4212[] = "EXYNOS4212";
- static const char name_exynos4412[] = "EXYNOS4412";
- @@ -400,7 +397,7 @@
- {
- int ret;
-
- - ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK);
- + ret = l2x0_of_init(0x3c400001, 0xc20fffff);
- if (ret)
- return ret;
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-highbank/highbank.c linux-3.14.35/arch/arm/mach-highbank/highbank.c
- --- linux-3.14.35.orig/arch/arm/mach-highbank/highbank.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-highbank/highbank.c 2015-03-08 14:27:37.413684502 -0500
- @@ -20,7 +20,7 @@
- #include <linux/input.h>
- #include <linux/io.h>
- #include <linux/irqchip.h>
- -#include <linux/mailbox.h>
- +#include <linux/pl320-ipc.h>
- #include <linux/of.h>
- #include <linux/of_irq.h>
- #include <linux/of_platform.h>
- @@ -51,11 +51,13 @@
- }
-
-
- -static void highbank_l2x0_disable(void)
- +static void highbank_l2c310_write_sec(unsigned long val, unsigned reg)
- {
- - outer_flush_all();
- - /* Disable PL310 L2 Cache controller */
- - highbank_smc1(0x102, 0x0);
- + if (reg == L2X0_CTRL)
- + highbank_smc1(0x102, val);
- + else
- + WARN_ONCE(1, "Highbank L2C310: ignoring write to reg 0x%x\n",
- + reg);
- }
-
- static void __init highbank_init_irq(void)
- @@ -66,11 +68,9 @@
- highbank_scu_map_io();
-
- /* Enable PL310 L2 Cache controller */
- - if (IS_ENABLED(CONFIG_CACHE_L2X0) &&
- - of_find_compatible_node(NULL, NULL, "arm,pl310-cache")) {
- - highbank_smc1(0x102, 0x1);
- - l2x0_of_init(0, ~0UL);
- - outer_cache.disable = highbank_l2x0_disable;
- + if (IS_ENABLED(CONFIG_CACHE_L2X0)) {
- + outer_cache.write_sec = highbank_l2c310_write_sec;
- + l2x0_of_init(0, ~0);
- }
- }
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/anatop.c linux-3.14.35/arch/arm/mach-imx/anatop.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/anatop.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/anatop.c 2015-03-08 14:27:37.413684502 -0500
- @@ -9,6 +9,7 @@
- * http://www.gnu.org/copyleft/gpl.html
- */
-
- +#include <linux/delay.h>
- #include <linux/err.h>
- #include <linux/io.h>
- #include <linux/of.h>
- @@ -35,6 +36,10 @@
- #define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B 0x80000
- #define BM_ANADIG_USB_CHRG_DETECT_EN_B 0x100000
-
- +#define ANADIG_REG_TARG_MASK 0x1f
- +#define ANADIG_REG1_TARG_SHIFT 9 /* VDDPU */
- +#define ANADIG_REG2_TARG_SHIFT 18 /* VDDSOC */
- +
- static struct regmap *anatop;
-
- static void imx_anatop_enable_weak2p5(bool enable)
- @@ -78,6 +83,28 @@
- BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
- }
-
- +void imx_anatop_pu_enable(bool enable)
- +{
- + u32 val;
- +
- + regmap_read(anatop, ANADIG_REG_CORE, &val);
- + val &= ANADIG_REG_TARG_MASK << ANADIG_REG2_TARG_SHIFT;
- + /*
- + * set pu regulator only in LDO_BYPASS mode(know by VDDSOC reg 0x1f),
- + * else handled by anatop regulator driver.
- + */
- + if (((val >> (ANADIG_REG2_TARG_SHIFT)) & ANADIG_REG_TARG_MASK)
- + == ANADIG_REG_TARG_MASK) {
- + if (enable) {
- + regmap_write(anatop, ANADIG_REG_CORE + REG_SET,
- + ANADIG_REG_TARG_MASK << ANADIG_REG1_TARG_SHIFT);
- + udelay(70); /* bypass need 70us to be stable */
- + } else {
- + regmap_write(anatop, ANADIG_REG_CORE + REG_CLR,
- + ANADIG_REG_TARG_MASK << ANADIG_REG1_TARG_SHIFT);
- + }
- + }
- +}
- void __init imx_init_revision_from_anatop(void)
- {
- struct device_node *np;
- @@ -104,6 +131,15 @@
- case 2:
- revision = IMX_CHIP_REVISION_1_2;
- break;
- + case 3:
- + revision = IMX_CHIP_REVISION_1_3;
- + break;
- + case 4:
- + revision = IMX_CHIP_REVISION_1_4;
- + break;
- + case 5:
- + revision = IMX_CHIP_REVISION_1_5;
- + break;
- default:
- revision = IMX_CHIP_REVISION_UNKNOWN;
- }
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/busfreq_ddr3.c linux-3.14.35/arch/arm/mach-imx/busfreq_ddr3.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/busfreq_ddr3.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/busfreq_ddr3.c 2015-03-08 14:27:37.413684502 -0500
- @@ -0,0 +1,471 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file busfreq_ddr3.c
- + *
- + * @brief iMX6 DDR3 frequency change specific file.
- + *
- + * @ingroup PM
- + */
- +#include <asm/cacheflush.h>
- +#include <asm/fncpy.h>
- +#include <asm/io.h>
- +#include <asm/mach/map.h>
- +#include <asm/mach-types.h>
- +#include <asm/tlb.h>
- +#include <linux/clk.h>
- +#include <linux/cpumask.h>
- +#include <linux/delay.h>
- +#include <linux/genalloc.h>
- +#include <linux/interrupt.h>
- +#include <linux/irqchip/arm-gic.h>
- +#include <linux/kernel.h>
- +#include <linux/mutex.h>
- +#include <linux/of.h>
- +#include <linux/of_address.h>
- +#include <linux/of_device.h>
- +#include <linux/platform_device.h>
- +#include <linux/proc_fs.h>
- +#include <linux/sched.h>
- +#include <linux/smp.h>
- +
- +#include "hardware.h"
- +
- +/* DDR settings */
- +static unsigned long (*iram_ddr_settings)[2];
- +static unsigned long (*normal_mmdc_settings)[2];
- +static unsigned long (*iram_iomux_settings)[2];
- +static void __iomem *mmdc_base;
- +static void __iomem *iomux_base;
- +static void __iomem *ccm_base;
- +static void __iomem *l2_base;
- +static void __iomem *gic_dist_base;
- +static u32 *irqs_used;
- +
- +static void *ddr_freq_change_iram_base;
- +static int ddr_settings_size;
- +static int iomux_settings_size;
- +static volatile unsigned int cpus_in_wfe;
- +static volatile bool wait_for_ddr_freq_update;
- +static int curr_ddr_rate;
- +
- +void (*mx6_change_ddr_freq)(u32 freq, void *ddr_settings,
- + bool dll_mode, void *iomux_offsets) = NULL;
- +
- +extern unsigned int ddr_med_rate;
- +extern unsigned int ddr_normal_rate;
- +extern int low_bus_freq_mode;
- +extern int audio_bus_freq_mode;
- +extern void mx6_ddr3_freq_change(u32 freq, void *ddr_settings,
- + bool dll_mode, void *iomux_offsets);
- +
- +#define MIN_DLL_ON_FREQ 333000000
- +#define MAX_DLL_OFF_FREQ 125000000
- +#define DDR_FREQ_CHANGE_SIZE 0x2000
- +
- +unsigned long ddr3_dll_mx6q[][2] = {
- + {0x0c, 0x0},
- + {0x10, 0x0},
- + {0x1C, 0x04088032},
- + {0x1C, 0x0408803a},
- + {0x1C, 0x08408030},
- + {0x1C, 0x08408038},
- + {0x818, 0x0},
- +};
- +
- +unsigned long ddr3_calibration[][2] = {
- + {0x83c, 0x0},
- + {0x840, 0x0},
- + {0x483c, 0x0},
- + {0x4840, 0x0},
- + {0x848, 0x0},
- + {0x4848, 0x0},
- + {0x850, 0x0},
- + {0x4850, 0x0},
- +};
- +
- +unsigned long ddr3_dll_mx6dl[][2] = {
- + {0x0c, 0x0},
- + {0x10, 0x0},
- + {0x1C, 0x04008032},
- + {0x1C, 0x0400803a},
- + {0x1C, 0x07208030},
- + {0x1C, 0x07208038},
- + {0x818, 0x0},
- +};
- +
- +unsigned long iomux_offsets_mx6q[][2] = {
- + {0x5A8, 0x0},
- + {0x5B0, 0x0},
- + {0x524, 0x0},
- + {0x51C, 0x0},
- + {0x518, 0x0},
- + {0x50C, 0x0},
- + {0x5B8, 0x0},
- + {0x5C0, 0x0},
- +};
- +
- +unsigned long iomux_offsets_mx6dl[][2] = {
- + {0x4BC, 0x0},
- + {0x4C0, 0x0},
- + {0x4C4, 0x0},
- + {0x4C8, 0x0},
- + {0x4CC, 0x0},
- + {0x4D0, 0x0},
- + {0x4D4, 0x0},
- + {0x4D8, 0x0},
- +};
- +
- +unsigned long ddr3_400[][2] = {
- + {0x83c, 0x42490249},
- + {0x840, 0x02470247},
- + {0x483c, 0x42570257},
- + {0x4840, 0x02400240},
- + {0x848, 0x4039363C},
- + {0x4848, 0x3A39333F},
- + {0x850, 0x38414441},
- + {0x4850, 0x472D4833}
- +};
- +
- +int can_change_ddr_freq(void)
- +{
- + return 1;
- +}
- +
- +/*
- + * each active core apart from the one changing
- + * the DDR frequency will execute this function.
- + * the rest of the cores have to remain in WFE
- + * state until the frequency is changed.
- + */
- +irqreturn_t wait_in_wfe_irq(int irq, void *dev_id)
- +{
- + u32 me = smp_processor_id();
- +
- + *((char *)(&cpus_in_wfe) + (u8)me) = 0xff;
- +
- + while (wait_for_ddr_freq_update)
- + wfe();
- +
- + *((char *)(&cpus_in_wfe) + (u8)me) = 0;
- +
- + return IRQ_HANDLED;
- +}
- +
- +/* change the DDR frequency. */
- +int update_ddr_freq(int ddr_rate)
- +{
- + int i, j;
- + unsigned int reg;
- + bool dll_off = false;
- + unsigned int online_cpus = 0;
- + int cpu = 0;
- + int me;
- +
- + if (!can_change_ddr_freq())
- + return -1;
- +
- + if (ddr_rate == curr_ddr_rate)
- + return 0;
- +
- + pr_debug("Bus freq set to %d start...\n", ddr_rate);
- +
- + if (low_bus_freq_mode || audio_bus_freq_mode)
- + dll_off = true;
- +
- + iram_ddr_settings[0][0] = ddr_settings_size;
- + iram_iomux_settings[0][0] = iomux_settings_size;
- + if (ddr_rate == ddr_med_rate && cpu_is_imx6q()) {
- + for (i = 0; i < ARRAY_SIZE(ddr3_dll_mx6q); i++) {
- + iram_ddr_settings[i + 1][0] =
- + normal_mmdc_settings[i][0];
- + iram_ddr_settings[i + 1][1] =
- + normal_mmdc_settings[i][1];
- + }
- + for (j = 0, i = ARRAY_SIZE(ddr3_dll_mx6q);
- + i < iram_ddr_settings[0][0]; j++, i++) {
- + iram_ddr_settings[i + 1][0] =
- + ddr3_400[j][0];
- + iram_ddr_settings[i + 1][1] =
- + ddr3_400[j][1];
- + }
- + } else if (ddr_rate == ddr_normal_rate) {
- + for (i = 0; i < iram_ddr_settings[0][0]; i++) {
- + iram_ddr_settings[i + 1][0] =
- + normal_mmdc_settings[i][0];
- + iram_ddr_settings[i + 1][1] =
- + normal_mmdc_settings[i][1];
- + }
- + }
- +
- + /* ensure that all Cores are in WFE. */
- + local_irq_disable();
- +
- + me = smp_processor_id();
- +
- + *((char *)(&cpus_in_wfe) + (u8)me) = 0xff;
- + wait_for_ddr_freq_update = true;
- + for_each_online_cpu(cpu) {
- + *((char *)(&online_cpus) + (u8)cpu) = 0xff;
- + if (cpu != me) {
- + /* set the interrupt to be pending in the GIC. */
- + reg = 1 << (irqs_used[cpu] % 32);
- + writel_relaxed(reg, gic_dist_base + GIC_DIST_PENDING_SET
- + + (irqs_used[cpu] / 32) * 4);
- + }
- + }
- + while (cpus_in_wfe != online_cpus)
- + udelay(5);
- +
- + /*
- + * Flush the TLB, to ensure no TLB maintenance occurs
- + * when DDR is in self-refresh.
- + */
- + local_flush_tlb_all();
- + /* Now we can change the DDR frequency. */
- + mx6_change_ddr_freq(ddr_rate, iram_ddr_settings,
- + dll_off, iram_iomux_settings);
- +
- + curr_ddr_rate = ddr_rate;
- +
- + /* DDR frequency change is done . */
- + wait_for_ddr_freq_update = false;
- +
- + /* wake up all the cores. */
- + sev();
- +
- + *((char *)(&cpus_in_wfe) + (u8)me) = 0;
- +
- + local_irq_enable();
- +
- + pr_debug("Bus freq set to %d done!\n", ddr_rate);
- +
- + return 0;
- +}
- +
- +int init_mmdc_ddr3_settings(struct platform_device *busfreq_pdev)
- +{
- + struct device *dev = &busfreq_pdev->dev;
- + struct platform_device *ocram_dev;
- + unsigned int iram_paddr;
- + int i, err;
- + u32 cpu;
- + struct device_node *node;
- + struct gen_pool *iram_pool;
- +
- + node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-mmdc-combine");
- + if (!node) {
- + pr_err("failed to find imx6q-mmdc device tree data!\n");
- + return -EINVAL;
- + }
- + mmdc_base = of_iomap(node, 0);
- + WARN(!mmdc_base, "unable to map mmdc registers\n");
- +
- + node = NULL;
- + if (cpu_is_imx6q())
- + node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-iomuxc");
- + if (cpu_is_imx6dl())
- + node = of_find_compatible_node(NULL, NULL,
- + "fsl,imx6dl-iomuxc");
- + if (!node) {
- + pr_err("failed to find imx6q-iomux device tree data!\n");
- + return -EINVAL;
- + }
- + iomux_base = of_iomap(node, 0);
- + WARN(!iomux_base, "unable to map iomux registers\n");
- +
- + node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ccm");
- + if (!node) {
- + pr_err("failed to find imx6q-ccm device tree data!\n");
- + return -EINVAL;
- + }
- + ccm_base = of_iomap(node, 0);
- + WARN(!ccm_base, "unable to map mmdc registers\n");
- +
- + node = of_find_compatible_node(NULL, NULL, "arm,pl310-cache");
- + if (!node) {
- + pr_err("failed to find imx6q-pl310-cache device tree data!\n");
- + return -EINVAL;
- + }
- + l2_base = of_iomap(node, 0);
- + WARN(!ccm_base, "unable to map mmdc registers\n");
- +
- + node = NULL;
- + node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-gic");
- + if (!node) {
- + pr_err("failed to find imx6q-a9-gic device tree data!\n");
- + return -EINVAL;
- + }
- + gic_dist_base = of_iomap(node, 0);
- + WARN(!gic_dist_base, "unable to map gic dist registers\n");
- +
- + if (cpu_is_imx6q())
- + ddr_settings_size = ARRAY_SIZE(ddr3_dll_mx6q) +
- + ARRAY_SIZE(ddr3_calibration);
- + if (cpu_is_imx6dl())
- + ddr_settings_size = ARRAY_SIZE(ddr3_dll_mx6dl) +
- + ARRAY_SIZE(ddr3_calibration);
- +
- + normal_mmdc_settings = kmalloc((ddr_settings_size * 8), GFP_KERNEL);
- + if (cpu_is_imx6q()) {
- + memcpy(normal_mmdc_settings, ddr3_dll_mx6q,
- + sizeof(ddr3_dll_mx6q));
- + memcpy(((char *)normal_mmdc_settings + sizeof(ddr3_dll_mx6q)),
- + ddr3_calibration, sizeof(ddr3_calibration));
- + }
- + if (cpu_is_imx6dl()) {
- + memcpy(normal_mmdc_settings, ddr3_dll_mx6dl,
- + sizeof(ddr3_dll_mx6dl));
- + memcpy(((char *)normal_mmdc_settings + sizeof(ddr3_dll_mx6dl)),
- + ddr3_calibration, sizeof(ddr3_calibration));
- + }
- + /* store the original DDR settings at boot. */
- + for (i = 0; i < ddr_settings_size; i++) {
- + /*
- + * writes via command mode register cannot be read back.
- + * hence hardcode them in the initial static array.
- + * this may require modification on a per customer basis.
- + */
- + if (normal_mmdc_settings[i][0] != 0x1C)
- + normal_mmdc_settings[i][1] =
- + readl_relaxed(mmdc_base
- + + normal_mmdc_settings[i][0]);
- + }
- +
- + irqs_used = devm_kzalloc(dev, sizeof(u32) * num_present_cpus(),
- + GFP_KERNEL);
- +
- + for_each_online_cpu(cpu) {
- + int irq;
- +
- + /*
- + * set up a reserved interrupt to get all
- + * the active cores into a WFE state
- + * before changing the DDR frequency.
- + */
- + irq = platform_get_irq(busfreq_pdev, cpu);
- + err = request_irq(irq, wait_in_wfe_irq,
- + IRQF_PERCPU, "mmdc_1", NULL);
- + if (err) {
- + dev_err(dev,
- + "Busfreq:request_irq failed %d, err = %d\n",
- + irq, err);
- + return err;
- + }
- + err = irq_set_affinity(irq, cpumask_of(cpu));
- + if (err) {
- + dev_err(dev,
- + "Busfreq: Cannot set irq affinity irq=%d,\n",
- + irq);
- + return err;
- + }
- + irqs_used[cpu] = irq;
- + }
- +
- + node = NULL;
- + node = of_find_compatible_node(NULL, NULL, "mmio-sram");
- + if (!node) {
- + dev_err(dev, "%s: failed to find ocram node\n",
- + __func__);
- + return -EINVAL;
- + }
- +
- + ocram_dev = of_find_device_by_node(node);
- + if (!ocram_dev) {
- + dev_err(dev, "failed to find ocram device!\n");
- + return -EINVAL;
- + }
- +
- + iram_pool = dev_get_gen_pool(&ocram_dev->dev);
- + if (!iram_pool) {
- + dev_err(dev, "iram pool unavailable!\n");
- + return -EINVAL;
- + }
- +
- + iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6q);
- + iram_iomux_settings = gen_pool_alloc(iram_pool,
- + (iomux_settings_size * 8) + 8);
- + if (!iram_iomux_settings) {
- + dev_err(dev, "unable to alloc iram for IOMUX settings!\n");
- + return -ENOMEM;
- + }
- +
- + /*
- + * Allocate extra space to store the number of entries in the
- + * ddr_settings plus 4 extra regsiter information that needs
- + * to be passed to the frequency change code.
- + * sizeof(iram_ddr_settings) = sizeof(ddr_settings) +
- + * entries in ddr_settings + 16.
- + * The last 4 enties store the addresses of the registers:
- + * CCM_BASE_ADDR
- + * MMDC_BASE_ADDR
- + * IOMUX_BASE_ADDR
- + * L2X0_BASE_ADDR
- + */
- + iram_ddr_settings = gen_pool_alloc(iram_pool,
- + (ddr_settings_size * 8) + 8 + 32);
- + if (!iram_ddr_settings) {
- + dev_err(dev, "unable to alloc iram for ddr settings!\n");
- + return -ENOMEM;
- + }
- + i = ddr_settings_size + 1;
- + iram_ddr_settings[i][0] = (unsigned long)mmdc_base;
- + iram_ddr_settings[i+1][0] = (unsigned long)ccm_base;
- + iram_ddr_settings[i+2][0] = (unsigned long)iomux_base;
- + iram_ddr_settings[i+3][0] = (unsigned long)l2_base;
- +
- + if (cpu_is_imx6q()) {
- + /* store the IOMUX settings at boot. */
- + for (i = 0; i < iomux_settings_size; i++) {
- + iomux_offsets_mx6q[i][1] =
- + readl_relaxed(iomux_base +
- + iomux_offsets_mx6q[i][0]);
- + iram_iomux_settings[i+1][0] = iomux_offsets_mx6q[i][0];
- + iram_iomux_settings[i+1][1] = iomux_offsets_mx6q[i][1];
- + }
- + }
- +
- + if (cpu_is_imx6dl()) {
- + for (i = 0; i < iomux_settings_size; i++) {
- + iomux_offsets_mx6dl[i][1] =
- + readl_relaxed(iomux_base +
- + iomux_offsets_mx6dl[i][0]);
- + iram_iomux_settings[i+1][0] = iomux_offsets_mx6dl[i][0];
- + iram_iomux_settings[i+1][1] = iomux_offsets_mx6dl[i][1];
- + }
- + }
- +
- + ddr_freq_change_iram_base = gen_pool_alloc(iram_pool,
- + DDR_FREQ_CHANGE_SIZE);
- + if (!ddr_freq_change_iram_base) {
- + dev_err(dev, "Cannot alloc iram for ddr freq change code!\n");
- + return -ENOMEM;
- + }
- +
- + iram_paddr = gen_pool_virt_to_phys(iram_pool,
- + (unsigned long)ddr_freq_change_iram_base);
- + /*
- + * Need to remap the area here since we want
- + * the memory region to be executable.
- + */
- + ddr_freq_change_iram_base = __arm_ioremap(iram_paddr,
- + DDR_FREQ_CHANGE_SIZE,
- + MT_MEMORY_RWX_NONCACHED);
- + mx6_change_ddr_freq = (void *)fncpy(ddr_freq_change_iram_base,
- + &mx6_ddr3_freq_change, DDR_FREQ_CHANGE_SIZE);
- +
- + curr_ddr_rate = ddr_normal_rate;
- +
- + return 0;
- +}
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/busfreq-imx6.c linux-3.14.35/arch/arm/mach-imx/busfreq-imx6.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/busfreq-imx6.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/busfreq-imx6.c 2015-03-08 14:27:37.413684502 -0500
- @@ -0,0 +1,952 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +/*!
- + * @file busfreq-imx6.c
- + *
- + * @brief A common API for the Freescale Semiconductor iMX6 Busfreq API
- + *
- + * The APIs are for setting bus frequency to different values based on the
- + * highest freqeuncy requested.
- + *
- + * @ingroup PM
- + */
- +
- +#include <asm/cacheflush.h>
- +#include <asm/io.h>
- +#include <asm/mach/map.h>
- +#include <asm/mach-types.h>
- +#include <asm/tlb.h>
- +#include <linux/busfreq-imx6.h>
- +#include <linux/clk.h>
- +#include <linux/clk-provider.h>
- +#include <linux/delay.h>
- +#include <linux/module.h>
- +#include <linux/mutex.h>
- +#include <linux/of.h>
- +#include <linux/platform_device.h>
- +#include <linux/proc_fs.h>
- +#include <linux/reboot.h>
- +#include <linux/regulator/consumer.h>
- +#include <linux/sched.h>
- +#include <linux/suspend.h>
- +#include "hardware.h"
- +
- +#define LPAPM_CLK 24000000
- +#define DDR3_AUDIO_CLK 50000000
- +#define LPDDR2_AUDIO_CLK 100000000
- +
- +int high_bus_freq_mode;
- +int med_bus_freq_mode;
- +int audio_bus_freq_mode;
- +int low_bus_freq_mode;
- +int ultra_low_bus_freq_mode;
- +unsigned int ddr_med_rate;
- +unsigned int ddr_normal_rate;
- +
- +#ifdef CONFIG_ARM_IMX6_CPUFREQ
- +static int bus_freq_scaling_initialized;
- +static struct device *busfreq_dev;
- +static int busfreq_suspended;
- +static u32 org_arm_rate;
- +static int bus_freq_scaling_is_active;
- +static int high_bus_count, med_bus_count, audio_bus_count, low_bus_count;
- +static unsigned int ddr_low_rate;
- +
- +extern int init_mmdc_lpddr2_settings(struct platform_device *dev);
- +extern int init_mmdc_ddr3_settings(struct platform_device *dev);
- +extern int update_ddr_freq(int ddr_rate);
- +extern int update_lpddr2_freq(int ddr_rate);
- +
- +DEFINE_MUTEX(bus_freq_mutex);
- +static DEFINE_SPINLOCK(freq_lock);
- +
- +static struct clk *pll2_400;
- +static struct clk *periph_clk;
- +static struct clk *periph_pre_clk;
- +static struct clk *periph_clk2_sel;
- +static struct clk *periph_clk2;
- +static struct clk *osc_clk;
- +static struct clk *cpu_clk;
- +static struct clk *pll3;
- +static struct clk *pll2;
- +static struct clk *pll2_200;
- +static struct clk *pll1_sys;
- +static struct clk *periph2_clk;
- +static struct clk *ocram_clk;
- +static struct clk *ahb_clk;
- +static struct clk *pll1_sw_clk;
- +static struct clk *periph2_pre_clk;
- +static struct clk *periph2_clk2_sel;
- +static struct clk *periph2_clk2;
- +static struct clk *step_clk;
- +static struct clk *axi_sel_clk;
- +static struct clk *pll3_pfd1_540m;
- +
- +static u32 pll2_org_rate;
- +static struct delayed_work low_bus_freq_handler;
- +static struct delayed_work bus_freq_daemon;
- +
- +static void enter_lpm_imx6sl(void)
- +{
- + unsigned long flags;
- +
- + if (high_bus_freq_mode) {
- + pll2_org_rate = clk_get_rate(pll2);
- + /* Set periph_clk to be sourced from OSC_CLK */
- + clk_set_parent(periph_clk2_sel, osc_clk);
- + clk_set_parent(periph_clk, periph_clk2);
- + /* Ensure AHB/AXI clks are at 24MHz. */
- + clk_set_rate(ahb_clk, LPAPM_CLK);
- + clk_set_rate(ocram_clk, LPAPM_CLK);
- + }
- + if (audio_bus_count) {
- + /* Set AHB to 8MHz to lower pwer.*/
- + clk_set_rate(ahb_clk, LPAPM_CLK / 3);
- +
- + /* Set up DDR to 100MHz. */
- + spin_lock_irqsave(&freq_lock, flags);
- + update_lpddr2_freq(LPDDR2_AUDIO_CLK);
- + spin_unlock_irqrestore(&freq_lock, flags);
- +
- + /* Fix the clock tree in kernel */
- + clk_set_rate(pll2, pll2_org_rate);
- + clk_set_parent(periph2_pre_clk, pll2_200);
- + clk_set_parent(periph2_clk, periph2_pre_clk);
- +
- + if (low_bus_freq_mode || ultra_low_bus_freq_mode) {
- + /*
- + * Swtich ARM to run off PLL2_PFD2_400MHz
- + * since DDR is anyway at 100MHz.
- + */
- + clk_set_parent(step_clk, pll2_400);
- + clk_set_parent(pll1_sw_clk, step_clk);
- + /*
- + * Ensure that the clock will be
- + * at original speed.
- + */
- + clk_set_rate(cpu_clk, org_arm_rate);
- + }
- + low_bus_freq_mode = 0;
- + ultra_low_bus_freq_mode = 0;
- + audio_bus_freq_mode = 1;
- + } else {
- + u32 arm_div, pll1_rate;
- + org_arm_rate = clk_get_rate(cpu_clk);
- + if (low_bus_freq_mode && low_bus_count == 0) {
- + /*
- + * We are already in DDR @ 24MHz state, but
- + * no one but ARM needs the DDR. In this case,
- + * we can lower the DDR freq to 1MHz when ARM
- + * enters WFI in this state. Keep track of this state.
- + */
- + ultra_low_bus_freq_mode = 1;
- + low_bus_freq_mode = 0;
- + audio_bus_freq_mode = 0;
- + } else {
- + if (!ultra_low_bus_freq_mode && !low_bus_freq_mode) {
- + /*
- + * Set DDR to 24MHz.
- + * Since we are going to bypass PLL2,
- + * we need to move ARM clk off PLL2_PFD2
- + * to PLL1. Make sure the PLL1 is running
- + * at the lowest possible freq.
- + */
- + clk_set_rate(pll1_sys,
- + clk_round_rate(pll1_sys, org_arm_rate));
- + pll1_rate = clk_get_rate(pll1_sys);
- + arm_div = pll1_rate / org_arm_rate + 1;
- + /*
- + * Ensure ARM CLK is lower before
- + * changing the parent.
- + */
- + clk_set_rate(cpu_clk, org_arm_rate / arm_div);
- + /* Now set the ARM clk parent to PLL1_SYS. */
- + clk_set_parent(pll1_sw_clk, pll1_sys);
- +
- + /*
- + * Set STEP_CLK back to OSC to save power and
- + * also to maintain the parent.The WFI iram code
- + * will switch step_clk to osc, but the clock API
- + * is not aware of the change and when a new request
- + * to change the step_clk parent to pll2_pfd2_400M
- + * is requested sometime later, the change is ignored.
- + */
- + clk_set_parent(step_clk, osc_clk);
- + /* Now set DDR to 24MHz. */
- + spin_lock_irqsave(&freq_lock, flags);
- + update_lpddr2_freq(LPAPM_CLK);
- + spin_unlock_irqrestore(&freq_lock, flags);
- +
- + /*
- + * Fix the clock tree in kernel.
- + * Make sure PLL2 rate is updated as it gets
- + * bypassed in the DDR freq change code.
- + */
- + clk_set_rate(pll2, LPAPM_CLK);
- + clk_set_parent(periph2_clk2_sel, pll2);
- + clk_set_parent(periph2_clk, periph2_clk2_sel);
- +
- + }
- + if (low_bus_count == 0) {
- + ultra_low_bus_freq_mode = 1;
- + low_bus_freq_mode = 0;
- + } else {
- + ultra_low_bus_freq_mode = 0;
- + low_bus_freq_mode = 1;
- + }
- + audio_bus_freq_mode = 0;
- + }
- + }
- +}
- +
- +static void exit_lpm_imx6sl(void)
- +{
- + unsigned long flags;
- +
- + spin_lock_irqsave(&freq_lock, flags);
- + /* Change DDR freq in IRAM. */
- + update_lpddr2_freq(ddr_normal_rate);
- + spin_unlock_irqrestore(&freq_lock, flags);
- +
- + /*
- + * Fix the clock tree in kernel.
- + * Make sure PLL2 rate is updated as it gets
- + * un-bypassed in the DDR freq change code.
- + */
- + clk_set_rate(pll2, pll2_org_rate);
- + clk_set_parent(periph2_pre_clk, pll2_400);
- + clk_set_parent(periph2_clk, periph2_pre_clk);
- +
- + /* Ensure that periph_clk is sourced from PLL2_400. */
- + clk_set_parent(periph_pre_clk, pll2_400);
- + /*
- + * Before switching the perhiph_clk, ensure that the
- + * AHB/AXI will not be too fast.
- + */
- + clk_set_rate(ahb_clk, LPAPM_CLK / 3);
- + clk_set_rate(ocram_clk, LPAPM_CLK / 2);
- + clk_set_parent(periph_clk, periph_pre_clk);
- +
- + if (low_bus_freq_mode || ultra_low_bus_freq_mode) {
- + /* Move ARM from PLL1_SW_CLK to PLL2_400. */
- + clk_set_parent(step_clk, pll2_400);
- + clk_set_parent(pll1_sw_clk, step_clk);
- + clk_set_rate(cpu_clk, org_arm_rate);
- + ultra_low_bus_freq_mode = 0;
- + }
- +}
- +
- +int reduce_bus_freq(void)
- +{
- + int ret = 0;
- + clk_prepare_enable(pll3);
- + if (cpu_is_imx6sl())
- + enter_lpm_imx6sl();
- + else {
- + if (cpu_is_imx6dl() && (clk_get_parent(axi_sel_clk)
- + != periph_clk))
- + /* Set axi to periph_clk */
- + clk_set_parent(axi_sel_clk, periph_clk);
- +
- + if (audio_bus_count) {
- + /* Need to ensure that PLL2_PFD_400M is kept ON. */
- + clk_prepare_enable(pll2_400);
- + update_ddr_freq(DDR3_AUDIO_CLK);
- + /* Make sure periph clk's parent also got updated */
- + ret = clk_set_parent(periph_clk2_sel, pll3);
- + if (ret)
- + dev_WARN(busfreq_dev,
- + "%s: %d: clk set parent fail!\n",
- + __func__, __LINE__);
- + ret = clk_set_parent(periph_pre_clk, pll2_200);
- + if (ret)
- + dev_WARN(busfreq_dev,
- + "%s: %d: clk set parent fail!\n",
- + __func__, __LINE__);
- + ret = clk_set_parent(periph_clk, periph_pre_clk);
- + if (ret)
- + dev_WARN(busfreq_dev,
- + "%s: %d: clk set parent fail!\n",
- + __func__, __LINE__);
- + audio_bus_freq_mode = 1;
- + low_bus_freq_mode = 0;
- + } else {
- + update_ddr_freq(LPAPM_CLK);
- + /* Make sure periph clk's parent also got updated */
- + ret = clk_set_parent(periph_clk2_sel, osc_clk);
- + if (ret)
- + dev_WARN(busfreq_dev,
- + "%s: %d: clk set parent fail!\n",
- + __func__, __LINE__);
- + /* Set periph_clk parent to OSC via periph_clk2_sel */
- + ret = clk_set_parent(periph_clk, periph_clk2);
- + if (ret)
- + dev_WARN(busfreq_dev,
- + "%s: %d: clk set parent fail!\n",
- + __func__, __LINE__);
- + if (audio_bus_freq_mode)
- + clk_disable_unprepare(pll2_400);
- + low_bus_freq_mode = 1;
- + audio_bus_freq_mode = 0;
- + }
- + }
- + clk_disable_unprepare(pll3);
- +
- + med_bus_freq_mode = 0;
- + high_bus_freq_mode = 0;
- +
- + if (audio_bus_freq_mode)
- + dev_dbg(busfreq_dev, "Bus freq set to audio mode. Count:\
- + high %d, med %d, audio %d\n",
- + high_bus_count, med_bus_count, audio_bus_count);
- + if (low_bus_freq_mode)
- + dev_dbg(busfreq_dev, "Bus freq set to low mode. Count:\
- + high %d, med %d, audio %d\n",
- + high_bus_count, med_bus_count, audio_bus_count);
- +
- + return ret;
- +}
- +
- +static void reduce_bus_freq_handler(struct work_struct *work)
- +{
- + mutex_lock(&bus_freq_mutex);
- +
- + reduce_bus_freq();
- +
- + mutex_unlock(&bus_freq_mutex);
- +}
- +
- +/*
- + * Set the DDR, AHB to 24MHz.
- + * This mode will be activated only when none of the modules that
- + * need a higher DDR or AHB frequency are active.
- + */
- +int set_low_bus_freq(void)
- +{
- + if (busfreq_suspended)
- + return 0;
- +
- + if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active)
- + return 0;
- +
- + /*
- + * Check to see if we need to got from
- + * low bus freq mode to audio bus freq mode.
- + * If so, the change needs to be done immediately.
- + */
- + if (audio_bus_count && (low_bus_freq_mode || ultra_low_bus_freq_mode))
- + reduce_bus_freq();
- + else
- + /*
- + * Don't lower the frequency immediately. Instead
- + * scheduled a delayed work and drop the freq if
- + * the conditions still remain the same.
- + */
- + schedule_delayed_work(&low_bus_freq_handler,
- + usecs_to_jiffies(3000000));
- + return 0;
- +}
- +
- +/*
- + * Set the DDR to either 528MHz or 400MHz for iMX6qd
- + * or 400MHz for iMX6dl.
- + */
- +int set_high_bus_freq(int high_bus_freq)
- +{
- + int ret = 0;
- + struct clk *periph_clk_parent;
- +
- + if (bus_freq_scaling_initialized && bus_freq_scaling_is_active)
- + cancel_delayed_work_sync(&low_bus_freq_handler);
- +
- + if (busfreq_suspended)
- + return 0;
- +
- + if (cpu_is_imx6q())
- + periph_clk_parent = pll2;
- + else
- + periph_clk_parent = pll2_400;
- +
- + if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active)
- + return 0;
- +
- + if (high_bus_freq_mode)
- + return 0;
- +
- + /* medium bus freq is only supported for MX6DQ */
- + if (med_bus_freq_mode && !high_bus_freq)
- + return 0;
- +
- + clk_prepare_enable(pll3);
- + if (cpu_is_imx6sl())
- + exit_lpm_imx6sl();
- + else {
- + if (high_bus_freq) {
- + update_ddr_freq(ddr_normal_rate);
- + /* Make sure periph clk's parent also got updated */
- + ret = clk_set_parent(periph_clk2_sel, pll3);
- + if (ret)
- + dev_WARN(busfreq_dev,
- + "%s: %d: clk set parent fail!\n",
- + __func__, __LINE__);
- + ret = clk_set_parent(periph_pre_clk, periph_clk_parent);
- + if (ret)
- + dev_WARN(busfreq_dev,
- + "%s: %d: clk set parent fail!\n",
- + __func__, __LINE__);
- + ret = clk_set_parent(periph_clk, periph_pre_clk);
- + if (ret)
- + dev_WARN(busfreq_dev,
- + "%s: %d: clk set parent fail!\n",
- + __func__, __LINE__);
- + if (cpu_is_imx6dl() && (clk_get_parent(axi_sel_clk)
- + != pll3_pfd1_540m))
- + /* Set axi to pll3_pfd1_540m */
- + clk_set_parent(axi_sel_clk, pll3_pfd1_540m);
- + } else {
- + update_ddr_freq(ddr_med_rate);
- + /* Make sure periph clk's parent also got updated */
- + ret = clk_set_parent(periph_clk2_sel, pll3);
- + if (ret)
- + dev_WARN(busfreq_dev,
- + "%s: %d: clk set parent fail!\n",
- + __func__, __LINE__);
- + ret = clk_set_parent(periph_pre_clk, pll2_400);
- + if (ret)
- + dev_WARN(busfreq_dev,
- + "%s: %d: clk set parent fail!\n",
- + __func__, __LINE__);
- + ret = clk_set_parent(periph_clk, periph_pre_clk);
- + if (ret)
- + dev_WARN(busfreq_dev,
- + "%s: %d: clk set parent fail!\n",
- + __func__, __LINE__);
- + }
- + if (audio_bus_freq_mode)
- + clk_disable_unprepare(pll2_400);
- + }
- +
- + high_bus_freq_mode = 1;
- + med_bus_freq_mode = 0;
- + low_bus_freq_mode = 0;
- + audio_bus_freq_mode = 0;
- +
- + clk_disable_unprepare(pll3);
- +
- + if (high_bus_freq_mode)
- + dev_dbg(busfreq_dev, "Bus freq set to high mode. Count:\
- + high %d, med %d, audio %d\n",
- + high_bus_count, med_bus_count, audio_bus_count);
- + if (med_bus_freq_mode)
- + dev_dbg(busfreq_dev, "Bus freq set to med mode. Count:\
- + high %d, med %d, audio %d\n",
- + high_bus_count, med_bus_count, audio_bus_count);
- +
- + return 0;
- +}
- +#endif
- +
- +void request_bus_freq(enum bus_freq_mode mode)
- +{
- +#ifdef CONFIG_ARM_IMX6_CPUFREQ
- + mutex_lock(&bus_freq_mutex);
- +
- + if (mode == BUS_FREQ_HIGH)
- + high_bus_count++;
- + else if (mode == BUS_FREQ_MED)
- + med_bus_count++;
- + else if (mode == BUS_FREQ_AUDIO)
- + audio_bus_count++;
- + else if (mode == BUS_FREQ_LOW)
- + low_bus_count++;
- +
- + if (busfreq_suspended || !bus_freq_scaling_initialized ||
- + !bus_freq_scaling_is_active) {
- + mutex_unlock(&bus_freq_mutex);
- + return;
- + }
- + cancel_delayed_work_sync(&low_bus_freq_handler);
- +
- + if (cpu_is_imx6dl()) {
- + /* No support for medium setpoint on MX6DL. */
- + if (mode == BUS_FREQ_MED) {
- + high_bus_count++;
- + mode = BUS_FREQ_HIGH;
- + }
- + }
- +
- + if ((mode == BUS_FREQ_HIGH) && (!high_bus_freq_mode)) {
- + set_high_bus_freq(1);
- + mutex_unlock(&bus_freq_mutex);
- + return;
- + }
- +
- + if ((mode == BUS_FREQ_MED) && (!high_bus_freq_mode) &&
- + (!med_bus_freq_mode)) {
- + set_high_bus_freq(0);
- + mutex_unlock(&bus_freq_mutex);
- + return;
- + }
- + if ((mode == BUS_FREQ_AUDIO) && (!high_bus_freq_mode) &&
- + (!med_bus_freq_mode) && (!audio_bus_freq_mode)) {
- + set_low_bus_freq();
- + mutex_unlock(&bus_freq_mutex);
- + return;
- + }
- + mutex_unlock(&bus_freq_mutex);
- +#endif
- + return;
- +}
- +EXPORT_SYMBOL(request_bus_freq);
- +
- +void release_bus_freq(enum bus_freq_mode mode)
- +{
- +#ifdef CONFIG_ARM_IMX6_CPUFREQ
- + mutex_lock(&bus_freq_mutex);
- +
- + if (mode == BUS_FREQ_HIGH) {
- + if (high_bus_count == 0) {
- + dev_err(busfreq_dev, "high bus count mismatch!\n");
- + dump_stack();
- + mutex_unlock(&bus_freq_mutex);
- + return;
- + }
- + high_bus_count--;
- + } else if (mode == BUS_FREQ_MED) {
- + if (med_bus_count == 0) {
- + dev_err(busfreq_dev, "med bus count mismatch!\n");
- + dump_stack();
- + mutex_unlock(&bus_freq_mutex);
- + return;
- + }
- + med_bus_count--;
- + } else if (mode == BUS_FREQ_AUDIO) {
- + if (audio_bus_count == 0) {
- + dev_err(busfreq_dev, "audio bus count mismatch!\n");
- + dump_stack();
- + mutex_unlock(&bus_freq_mutex);
- + return;
- + }
- + audio_bus_count--;
- + } else if (mode == BUS_FREQ_LOW) {
- + if (low_bus_count == 0) {
- + dev_err(busfreq_dev, "low bus count mismatch!\n");
- + dump_stack();
- + mutex_unlock(&bus_freq_mutex);
- + return;
- + }
- + low_bus_count--;
- + }
- +
- + if (busfreq_suspended || !bus_freq_scaling_initialized ||
- + !bus_freq_scaling_is_active) {
- + mutex_unlock(&bus_freq_mutex);
- + return;
- + }
- +
- + if (cpu_is_imx6dl()) {
- + /* No support for medium setpoint on MX6DL. */
- + if (mode == BUS_FREQ_MED) {
- + high_bus_count--;
- + mode = BUS_FREQ_HIGH;
- + }
- + }
- +
- + if ((!audio_bus_freq_mode) && (high_bus_count == 0) &&
- + (med_bus_count == 0) && (audio_bus_count != 0)) {
- + set_low_bus_freq();
- + mutex_unlock(&bus_freq_mutex);
- + return;
- + }
- + if ((!low_bus_freq_mode) && (high_bus_count == 0) &&
- + (med_bus_count == 0) && (audio_bus_count == 0) &&
- + (low_bus_count != 0)) {
- + set_low_bus_freq();
- + mutex_unlock(&bus_freq_mutex);
- + return;
- + }
- + if ((!ultra_low_bus_freq_mode) && (high_bus_count == 0) &&
- + (med_bus_count == 0) && (audio_bus_count == 0) &&
- + (low_bus_count == 0)) {
- + set_low_bus_freq();
- + mutex_unlock(&bus_freq_mutex);
- + return;
- + }
- +
- + mutex_unlock(&bus_freq_mutex);
- +#endif
- + return;
- +}
- +EXPORT_SYMBOL(release_bus_freq);
- +
- +#ifdef CONFIG_ARM_IMX6_CPUFREQ
- +static void bus_freq_daemon_handler(struct work_struct *work)
- +{
- + mutex_lock(&bus_freq_mutex);
- + if ((!low_bus_freq_mode) && (high_bus_count == 0) &&
- + (med_bus_count == 0) && (audio_bus_count == 0))
- + set_low_bus_freq();
- + mutex_unlock(&bus_freq_mutex);
- +}
- +
- +static ssize_t bus_freq_scaling_enable_show(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + if (bus_freq_scaling_is_active)
- + return sprintf(buf, "Bus frequency scaling is enabled\n");
- + else
- + return sprintf(buf, "Bus frequency scaling is disabled\n");
- +}
- +
- +static ssize_t bus_freq_scaling_enable_store(struct device *dev,
- + struct device_attribute *attr,
- + const char *buf, size_t size)
- +{
- + if (strncmp(buf, "1", 1) == 0) {
- + bus_freq_scaling_is_active = 1;
- + set_high_bus_freq(1);
- + /*
- + * We set bus freq to highest at the beginning,
- + * so we use this daemon thread to make sure system
- + * can enter low bus mode if
- + * there is no high bus request pending
- + */
- + schedule_delayed_work(&bus_freq_daemon,
- + usecs_to_jiffies(5000000));
- + } else if (strncmp(buf, "0", 1) == 0) {
- + if (bus_freq_scaling_is_active)
- + set_high_bus_freq(1);
- + bus_freq_scaling_is_active = 0;
- + }
- + return size;
- +}
- +
- +static int bus_freq_pm_notify(struct notifier_block *nb, unsigned long event,
- + void *dummy)
- +{
- + mutex_lock(&bus_freq_mutex);
- +
- + if (event == PM_SUSPEND_PREPARE) {
- + high_bus_count++;
- + set_high_bus_freq(1);
- + busfreq_suspended = 1;
- + } else if (event == PM_POST_SUSPEND) {
- + busfreq_suspended = 0;
- + high_bus_count--;
- + schedule_delayed_work(&bus_freq_daemon,
- + usecs_to_jiffies(5000000));
- + }
- +
- + mutex_unlock(&bus_freq_mutex);
- +
- + return NOTIFY_OK;
- +}
- +
- +static int busfreq_reboot_notifier_event(struct notifier_block *this,
- + unsigned long event, void *ptr)
- +{
- + /* System is rebooting. Set the system into high_bus_freq_mode. */
- + request_bus_freq(BUS_FREQ_HIGH);
- +
- + return 0;
- +}
- +
- +static struct notifier_block imx_bus_freq_pm_notifier = {
- + .notifier_call = bus_freq_pm_notify,
- +};
- +
- +static struct notifier_block imx_busfreq_reboot_notifier = {
- + .notifier_call = busfreq_reboot_notifier_event,
- +};
- +
- +
- +static DEVICE_ATTR(enable, 0644, bus_freq_scaling_enable_show,
- + bus_freq_scaling_enable_store);
- +#endif
- +
- +/*!
- + * This is the probe routine for the bus frequency driver.
- + *
- + * @param pdev The platform device structure
- + *
- + * @return The function returns 0 on success
- + *
- + */
- +
- +static int busfreq_probe(struct platform_device *pdev)
- +{
- +#ifdef CONFIG_ARM_IMX6_CPUFREQ
- + u32 err;
- +
- + busfreq_dev = &pdev->dev;
- +
- + pll2_400 = devm_clk_get(&pdev->dev, "pll2_pfd2_396m");
- + if (IS_ERR(pll2_400)) {
- + dev_err(busfreq_dev, "%s: failed to get pll2_pfd2_396m\n",
- + __func__);
- + return PTR_ERR(pll2_400);
- + }
- +
- + pll2_200 = devm_clk_get(&pdev->dev, "pll2_198m");
- + if (IS_ERR(pll2_200)) {
- + dev_err(busfreq_dev, "%s: failed to get pll2_198m\n",
- + __func__);
- + return PTR_ERR(pll2_200);
- + }
- +
- + pll2 = devm_clk_get(&pdev->dev, "pll2_bus");
- + if (IS_ERR(pll2)) {
- + dev_err(busfreq_dev, "%s: failed to get pll2_bus\n",
- + __func__);
- + return PTR_ERR(pll2);
- + }
- +
- + cpu_clk = devm_clk_get(&pdev->dev, "arm");
- + if (IS_ERR(cpu_clk)) {
- + dev_err(busfreq_dev, "%s: failed to get cpu_clk\n",
- + __func__);
- + return PTR_ERR(cpu_clk);
- + }
- +
- + pll3 = devm_clk_get(&pdev->dev, "pll3_usb_otg");
- + if (IS_ERR(pll3)) {
- + dev_err(busfreq_dev, "%s: failed to get pll3_usb_otg\n",
- + __func__);
- + return PTR_ERR(pll3);
- + }
- +
- + periph_clk = devm_clk_get(&pdev->dev, "periph");
- + if (IS_ERR(periph_clk)) {
- + dev_err(busfreq_dev, "%s: failed to get periph\n",
- + __func__);
- + return PTR_ERR(periph_clk);
- + }
- +
- + periph_pre_clk = devm_clk_get(&pdev->dev, "periph_pre");
- + if (IS_ERR(periph_pre_clk)) {
- + dev_err(busfreq_dev, "%s: failed to get periph_pre\n",
- + __func__);
- + return PTR_ERR(periph_pre_clk);
- + }
- +
- + periph_clk2 = devm_clk_get(&pdev->dev, "periph_clk2");
- + if (IS_ERR(periph_clk2)) {
- + dev_err(busfreq_dev, "%s: failed to get periph_clk2\n",
- + __func__);
- + return PTR_ERR(periph_clk2);
- + }
- +
- + periph_clk2_sel = devm_clk_get(&pdev->dev, "periph_clk2_sel");
- + if (IS_ERR(periph_clk2_sel)) {
- + dev_err(busfreq_dev, "%s: failed to get periph_clk2_sel\n",
- + __func__);
- + return PTR_ERR(periph_clk2_sel);
- + }
- +
- + osc_clk = devm_clk_get(&pdev->dev, "osc");
- + if (IS_ERR(osc_clk)) {
- + dev_err(busfreq_dev, "%s: failed to get osc_clk\n",
- + __func__);
- + return PTR_ERR(osc_clk);
- + }
- +
- + if (cpu_is_imx6dl()) {
- + axi_sel_clk = devm_clk_get(&pdev->dev, "axi_sel");
- + if (IS_ERR(axi_sel_clk)) {
- + dev_err(busfreq_dev, "%s: failed to get axi_sel_clk\n",
- + __func__);
- + return PTR_ERR(axi_sel_clk);
- + }
- +
- + pll3_pfd1_540m = devm_clk_get(&pdev->dev, "pll3_pfd1_540m");
- + if (IS_ERR(pll3_pfd1_540m)) {
- + dev_err(busfreq_dev,
- + "%s: failed to get pll3_pfd1_540m\n", __func__);
- + return PTR_ERR(pll3_pfd1_540m);
- + }
- + }
- +
- + if (cpu_is_imx6sl()) {
- + pll1_sys = devm_clk_get(&pdev->dev, "pll1_sys");
- + if (IS_ERR(pll1_sys)) {
- + dev_err(busfreq_dev, "%s: failed to get pll1_sys\n",
- + __func__);
- + return PTR_ERR(pll1_sys);
- + }
- +
- + ahb_clk = devm_clk_get(&pdev->dev, "ahb");
- + if (IS_ERR(ahb_clk)) {
- + dev_err(busfreq_dev, "%s: failed to get ahb_clk\n",
- + __func__);
- + return PTR_ERR(ahb_clk);
- + }
- +
- + ocram_clk = devm_clk_get(&pdev->dev, "ocram");
- + if (IS_ERR(ocram_clk)) {
- + dev_err(busfreq_dev, "%s: failed to get ocram_clk\n",
- + __func__);
- + return PTR_ERR(ocram_clk);
- + }
- +
- + pll1_sw_clk = devm_clk_get(&pdev->dev, "pll1_sw");
- + if (IS_ERR(pll1_sw_clk)) {
- + dev_err(busfreq_dev, "%s: failed to get pll1_sw_clk\n",
- + __func__);
- + return PTR_ERR(pll1_sw_clk);
- + }
- +
- + periph2_clk = devm_clk_get(&pdev->dev, "periph2");
- + if (IS_ERR(periph2_clk)) {
- + dev_err(busfreq_dev, "%s: failed to get periph2\n",
- + __func__);
- + return PTR_ERR(periph2_clk);
- + }
- +
- + periph2_pre_clk = devm_clk_get(&pdev->dev, "periph2_pre");
- + if (IS_ERR(periph2_pre_clk)) {
- + dev_err(busfreq_dev,
- + "%s: failed to get periph2_pre_clk\n",
- + __func__);
- + return PTR_ERR(periph2_pre_clk);
- + }
- +
- + periph2_clk2 = devm_clk_get(&pdev->dev, "periph2_clk2");
- + if (IS_ERR(periph2_clk2)) {
- + dev_err(busfreq_dev,
- + "%s: failed to get periph2_clk2\n",
- + __func__);
- + return PTR_ERR(periph2_clk2);
- + }
- +
- + periph2_clk2_sel = devm_clk_get(&pdev->dev, "periph2_clk2_sel");
- + if (IS_ERR(periph2_clk2_sel)) {
- + dev_err(busfreq_dev,
- + "%s: failed to get periph2_clk2_sel\n",
- + __func__);
- + return PTR_ERR(periph2_clk2_sel);
- + }
- +
- + step_clk = devm_clk_get(&pdev->dev, "step");
- + if (IS_ERR(step_clk)) {
- + dev_err(busfreq_dev,
- + "%s: failed to get step_clk\n",
- + __func__);
- + return PTR_ERR(periph2_clk2_sel);
- + }
- +
- + }
- +
- + err = sysfs_create_file(&busfreq_dev->kobj, &dev_attr_enable.attr);
- + if (err) {
- + dev_err(busfreq_dev,
- + "Unable to register sysdev entry for BUSFREQ");
- + return err;
- + }
- +
- + if (of_property_read_u32(pdev->dev.of_node, "fsl,max_ddr_freq",
- + &ddr_normal_rate)) {
- + dev_err(busfreq_dev, "max_ddr_freq entry missing\n");
- + return -EINVAL;
- + }
- +#endif
- +
- + high_bus_freq_mode = 1;
- + med_bus_freq_mode = 0;
- + low_bus_freq_mode = 0;
- + audio_bus_freq_mode = 0;
- + ultra_low_bus_freq_mode = 0;
- +
- +#ifdef CONFIG_ARM_IMX6_CPUFREQ
- + bus_freq_scaling_is_active = 1;
- + bus_freq_scaling_initialized = 1;
- +
- + ddr_low_rate = LPAPM_CLK;
- + if (cpu_is_imx6q()) {
- + if (of_property_read_u32(pdev->dev.of_node, "fsl,med_ddr_freq",
- + &ddr_med_rate)) {
- + dev_info(busfreq_dev,
- + "DDR medium rate not supported.\n");
- + ddr_med_rate = ddr_normal_rate;
- + }
- + }
- +
- + INIT_DELAYED_WORK(&low_bus_freq_handler, reduce_bus_freq_handler);
- + INIT_DELAYED_WORK(&bus_freq_daemon, bus_freq_daemon_handler);
- + register_pm_notifier(&imx_bus_freq_pm_notifier);
- + register_reboot_notifier(&imx_busfreq_reboot_notifier);
- +
- + if (cpu_is_imx6sl())
- + err = init_mmdc_lpddr2_settings(pdev);
- + else
- + err = init_mmdc_ddr3_settings(pdev);
- + if (err) {
- + dev_err(busfreq_dev, "Busfreq init of MMDC failed\n");
- + return err;
- + }
- +#endif
- + return 0;
- +}
- +
- +static const struct of_device_id imx6_busfreq_ids[] = {
- + { .compatible = "fsl,imx6_busfreq", },
- + { /* sentinel */ }
- +};
- +
- +static struct platform_driver busfreq_driver = {
- + .driver = {
- + .name = "imx6_busfreq",
- + .owner = THIS_MODULE,
- + .of_match_table = imx6_busfreq_ids,
- + },
- + .probe = busfreq_probe,
- +};
- +
- +/*!
- + * Initialise the busfreq_driver.
- + *
- + * @return The function always returns 0.
- + */
- +
- +static int __init busfreq_init(void)
- +{
- + if (platform_driver_register(&busfreq_driver) != 0)
- + return -ENODEV;
- +
- + printk(KERN_INFO "Bus freq driver module loaded\n");
- +
- + return 0;
- +}
- +
- +static void __exit busfreq_cleanup(void)
- +{
- +#ifdef CONFIG_ARM_IMX6_CPUFREQ
- + sysfs_remove_file(&busfreq_dev->kobj, &dev_attr_enable.attr);
- +
- + bus_freq_scaling_initialized = 0;
- +#endif
- + /* Unregister the device structure */
- + platform_driver_unregister(&busfreq_driver);
- +}
- +
- +module_init(busfreq_init);
- +module_exit(busfreq_cleanup);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("BusFreq driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/busfreq_lpddr2.c linux-3.14.35/arch/arm/mach-imx/busfreq_lpddr2.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/busfreq_lpddr2.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/busfreq_lpddr2.c 2015-03-08 14:27:37.413684502 -0500
- @@ -0,0 +1,183 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file busfreq_lpddr2.c
- + *
- + * @brief iMX6 LPDDR2 frequency change specific file.
- + *
- + * @ingroup PM
- + */
- +#include <asm/cacheflush.h>
- +#include <asm/fncpy.h>
- +#include <asm/io.h>
- +#include <asm/mach/map.h>
- +#include <asm/mach-types.h>
- +#include <asm/tlb.h>
- +#include <linux/clk.h>
- +#include <linux/cpumask.h>
- +#include <linux/delay.h>
- +#include <linux/genalloc.h>
- +#include <linux/interrupt.h>
- +#include <linux/irqchip/arm-gic.h>
- +#include <linux/kernel.h>
- +#include <linux/mutex.h>
- +#include <linux/of.h>
- +#include <linux/of_address.h>
- +#include <linux/of_device.h>
- +#include <linux/platform_device.h>
- +#include <linux/proc_fs.h>
- +#include <linux/sched.h>
- +#include <linux/smp.h>
- +
- +#include "hardware.h"
- +
- +/* DDR settings */
- +static void __iomem *mmdc_base;
- +static void __iomem *anatop_base;
- +static void __iomem *ccm_base;
- +static void __iomem *l2_base;
- +static struct device *busfreq_dev;
- +static void *ddr_freq_change_iram_base;
- +static int curr_ddr_rate;
- +
- +unsigned long reg_addrs[4];
- +
- +void (*mx6_change_lpddr2_freq)(u32 ddr_freq, int bus_freq_mode,
- + void *iram_addr) = NULL;
- +
- +extern unsigned int ddr_normal_rate;
- +extern int low_bus_freq_mode;
- +extern int ultra_low_bus_freq_mode;
- +extern void mx6_lpddr2_freq_change(u32 freq, int bus_freq_mode,
- + void *iram_addr);
- +
- +
- +#define LPDDR2_FREQ_CHANGE_SIZE 0x1000
- +
- +
- +/* change the DDR frequency. */
- +int update_lpddr2_freq(int ddr_rate)
- +{
- + if (ddr_rate == curr_ddr_rate)
- + return 0;
- +
- + dev_dbg(busfreq_dev, "\nBus freq set to %d start...\n", ddr_rate);
- +
- + /*
- + * Flush the TLB, to ensure no TLB maintenance occurs
- + * when DDR is in self-refresh.
- + */
- + local_flush_tlb_all();
- + /* Now change DDR frequency. */
- + mx6_change_lpddr2_freq(ddr_rate,
- + (low_bus_freq_mode | ultra_low_bus_freq_mode),
- + reg_addrs);
- +
- + curr_ddr_rate = ddr_rate;
- +
- + dev_dbg(busfreq_dev, "\nBus freq set to %d done...\n", ddr_rate);
- +
- + return 0;
- +}
- +
- +int init_mmdc_lpddr2_settings(struct platform_device *busfreq_pdev)
- +{
- + struct platform_device *ocram_dev;
- + unsigned int iram_paddr;
- + struct device_node *node;
- + struct gen_pool *iram_pool;
- +
- + busfreq_dev = &busfreq_pdev->dev;
- + node = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-mmdc");
- + if (!node) {
- + printk(KERN_ERR "failed to find imx6sl-mmdc device tree data!\n");
- + return -EINVAL;
- + }
- + mmdc_base = of_iomap(node, 0);
- + WARN(!mmdc_base, "unable to map mmdc registers\n");
- +
- + node = NULL;
- + node = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-ccm");
- + if (!node) {
- + printk(KERN_ERR "failed to find imx6sl-ccm device tree data!\n");
- + return -EINVAL;
- + }
- + ccm_base = of_iomap(node, 0);
- + WARN(!ccm_base, "unable to map ccm registers\n");
- +
- + node = of_find_compatible_node(NULL, NULL, "arm,pl310-cache");
- + if (!node) {
- + printk(KERN_ERR "failed to find imx6sl-pl310-cache device tree data!\n");
- + return -EINVAL;
- + }
- + l2_base = of_iomap(node, 0);
- + WARN(!l2_base, "unable to map PL310 registers\n");
- +
- + node = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-anatop");
- + if (!node) {
- + printk(KERN_ERR "failed to find imx6sl-pl310-cache device tree data!\n");
- + return -EINVAL;
- + }
- + anatop_base = of_iomap(node, 0);
- + WARN(!anatop_base, "unable to map anatop registers\n");
- +
- + node = NULL;
- + node = of_find_compatible_node(NULL, NULL, "mmio-sram");
- + if (!node) {
- + dev_err(busfreq_dev, "%s: failed to find ocram node\n",
- + __func__);
- + return -EINVAL;
- + }
- +
- + ocram_dev = of_find_device_by_node(node);
- + if (!ocram_dev) {
- + dev_err(busfreq_dev, "failed to find ocram device!\n");
- + return -EINVAL;
- + }
- +
- + iram_pool = dev_get_gen_pool(&ocram_dev->dev);
- + if (!iram_pool) {
- + dev_err(busfreq_dev, "iram pool unavailable!\n");
- + return -EINVAL;
- + }
- +
- + reg_addrs[0] = (unsigned long)anatop_base;
- + reg_addrs[1] = (unsigned long)ccm_base;
- + reg_addrs[2] = (unsigned long)mmdc_base;
- + reg_addrs[3] = (unsigned long)l2_base;
- +
- + ddr_freq_change_iram_base = (void *)gen_pool_alloc(iram_pool,
- + LPDDR2_FREQ_CHANGE_SIZE);
- + if (!ddr_freq_change_iram_base) {
- + dev_err(busfreq_dev,
- + "Cannot alloc iram for ddr freq change code!\n");
- + return -ENOMEM;
- + }
- +
- + iram_paddr = gen_pool_virt_to_phys(iram_pool,
- + (unsigned long)ddr_freq_change_iram_base);
- + /*
- + * Need to remap the area here since we want
- + * the memory region to be executable.
- + */
- + ddr_freq_change_iram_base = __arm_ioremap(iram_paddr,
- + LPDDR2_FREQ_CHANGE_SIZE,
- + MT_MEMORY_RWX_NONCACHED);
- + mx6_change_lpddr2_freq = (void *)fncpy(ddr_freq_change_iram_base,
- + &mx6_lpddr2_freq_change, LPDDR2_FREQ_CHANGE_SIZE);
- +
- + curr_ddr_rate = ddr_normal_rate;
- +
- + return 0;
- +}
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/clk.h linux-3.14.35/arch/arm/mach-imx/clk.h
- --- linux-3.14.35.orig/arch/arm/mach-imx/clk.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/clk.h 2015-03-08 14:27:37.413684502 -0500
- @@ -23,7 +23,8 @@
- };
-
- struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
- - const char *parent_name, void __iomem *base, u32 div_mask);
- + const char *parent_name, void __iomem *base,
- + u32 div_mask, bool always_on);
-
- struct clk *clk_register_gate2(struct device *dev, const char *name,
- const char *parent_name, unsigned long flags,
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/clk-imx6q.c linux-3.14.35/arch/arm/mach-imx/clk-imx6q.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/clk-imx6q.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/clk-imx6q.c 2015-03-08 14:27:37.413684502 -0500
- @@ -1,5 +1,5 @@
- /*
- - * Copyright 2011-2013 Freescale Semiconductor, Inc.
- + * Copyright 2011-2014 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * The code contained herein is licensed under the GNU General Public
- @@ -24,6 +24,8 @@
- #include "common.h"
- #include "hardware.h"
-
- +#define CCM_CCGR_OFFSET(index) (index * 2)
- +
- static const char *step_sels[] = { "osc", "pll2_pfd2_396m", };
- static const char *pll1_sw_sels[] = { "pll1_sys", "step", };
- static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", };
- @@ -39,6 +41,8 @@
- static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll3_pfd0_720m", };
- static const char *ipu_sels[] = { "mmdc_ch0_axi", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
- static const char *ldb_di_sels[] = { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_usb_otg", };
- +static const char *ldb_di0_div_sels[] = { "ldb_di0_div_3_5", "ldb_di0_div_7", };
- +static const char *ldb_di1_div_sels[] = { "ldb_di1_div_3_5", "ldb_di1_div_7", };
- static const char *ipu_di_pre_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", };
- static const char *ipu1_di0_sels[] = { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
- static const char *ipu1_di1_sels[] = { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
- @@ -72,6 +76,10 @@
- "pll4_audio", "pll5_video", "pll8_mlb", "enet_ref",
- "pcie_ref", "sata_ref",
- };
- +static const char *pll_av_sels[] = { "osc", "lvds1_in", "lvds2_in", "dummy", };
- +static void __iomem *anatop_base;
- +static void __iomem *ccm_base;
- +
-
- enum mx6q_clks {
- dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m,
- @@ -88,11 +96,11 @@
- periph_clk2, periph2_clk2, ipg, ipg_per, esai_pred, esai_podf,
- asrc_pred, asrc_podf, spdif_pred, spdif_podf, can_root, ecspi_root,
- gpu2d_core_podf, gpu3d_core_podf, gpu3d_shader, ipu1_podf, ipu2_podf,
- - ldb_di0_podf, ldb_di1_podf, ipu1_di0_pre, ipu1_di1_pre, ipu2_di0_pre,
- - ipu2_di1_pre, hsi_tx_podf, ssi1_pred, ssi1_podf, ssi2_pred, ssi2_podf,
- - ssi3_pred, ssi3_podf, uart_serial_podf, usdhc1_podf, usdhc2_podf,
- - usdhc3_podf, usdhc4_podf, enfc_pred, enfc_podf, emi_podf,
- - emi_slow_podf, vpu_axi_podf, cko1_podf, axi, mmdc_ch0_axi_podf,
- + ldb_di0_podf_unused, ldb_di1_podf_unused, ipu1_di0_pre, ipu1_di1_pre,
- + ipu2_di0_pre, ipu2_di1_pre, hsi_tx_podf, ssi1_pred, ssi1_podf,
- + ssi2_pred, ssi2_podf, ssi3_pred, ssi3_podf, uart_serial_podf,
- + usdhc1_podf, usdhc2_podf, usdhc3_podf, usdhc4_podf, enfc_pred, enfc_podf,
- + emi_podf, emi_slow_podf, vpu_axi_podf, cko1_podf, axi, mmdc_ch0_axi_podf,
- mmdc_ch1_axi_podf, arm, ahb, apbh_dma, asrc, can1_ipg, can1_serial,
- can2_ipg, can2_serial, ecspi1, ecspi2, ecspi3, ecspi4, ecspi5, enet,
- esai, gpt_ipg, gpt_ipg_per, gpu2d_core, gpu3d_core, hdmi_iahb,
- @@ -107,7 +115,10 @@
- sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate,
- usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow,
- spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, pll4_audio_div,
- - lvds1_sel, lvds2_sel, lvds1_gate, lvds2_gate, clk_max
- + lvds1_sel, lvds2_sel, lvds1_gate, lvds2_gate, gpt_3m, video_27m,
- + ldb_di0_div_7, ldb_di1_div_7, ldb_di0_div_sel, ldb_di1_div_sel,
- + caam_mem, caam_aclk, caam_ipg, epit1, epit2, tzasc2, lvds1_in, lvds1_out,
- + pll4_sel, lvds2_in, lvds2_out, anaclk1, anaclk2, clk_max
- };
-
- static struct clk *clk[clk_max];
- @@ -140,20 +151,131 @@
- { /* sentinel */ }
- };
-
- +static void init_ldb_clks(enum mx6q_clks new_parent)
- +{
- + u32 reg;
- +
- + /*
- + * Need to follow a strict procedure when changing the LDB
- + * clock, else we can introduce a glitch. Things to keep in
- + * mind:
- + * 1. The current and new parent clocks must be disabled.
- + * 2. The default clock for ldb_dio_clk is mmdc_ch1 which has
- + * no CG bit.
- + * 3. In the RTL implementation of the LDB_DI_CLK_SEL mux
- + * the top four options are in one mux and the PLL3 option along
- + * with another option is in the second mux. There is third mux
- + * used to decide between the first and second mux.
- + * The code below switches the parent to the bottom mux first
- + * and then manipulates the top mux. This ensures that no glitch
- + * will enter the divider.
- + *
- + * Need to disable MMDC_CH1 clock manually as there is no CG bit
- + * for this clock. The only way to disable this clock is to move
- + * it topll3_sw_clk and then to disable pll3_sw_clk
- + * Make sure periph2_clk2_sel is set to pll3_sw_clk
- + */
- + reg = readl_relaxed(ccm_base + 0x18);
- + reg &= ~(1 << 20);
- + writel_relaxed(reg, ccm_base + 0x18);
- +
- + /*
- + * Set MMDC_CH1 mask bit.
- + */
- + reg = readl_relaxed(ccm_base + 0x4);
- + reg |= 1 << 16;
- + writel_relaxed(reg, ccm_base + 0x4);
- +
- + /*
- + * Set the periph2_clk_sel to the top mux so that
- + * mmdc_ch1 is from pll3_sw_clk.
- + */
- + reg = readl_relaxed(ccm_base + 0x14);
- + reg |= 1 << 26;
- + writel_relaxed(reg, ccm_base + 0x14);
- +
- + /*
- + * Wait for the clock switch.
- + */
- + while (readl_relaxed(ccm_base + 0x48))
- + ;
- +
- + /*
- + * Disable pll3_sw_clk by selecting the bypass clock source.
- + */
- + reg = readl_relaxed(ccm_base + 0xc);
- + reg |= 1 << 0;
- + writel_relaxed(reg, ccm_base + 0xc);
- +
- + /*
- + * Set the ldb_di0_clk and ldb_di1_clk to 111b.
- + */
- + reg = readl_relaxed(ccm_base + 0x2c);
- + reg |= ((7 << 9) | (7 << 12));
- + writel_relaxed(reg, ccm_base + 0x2c);
- +
- + /*
- + * Set the ldb_di0_clk and ldb_di1_clk to 100b.
- + */
- + reg = readl_relaxed(ccm_base + 0x2c);
- + reg &= ~((7 << 9) | (7 << 12));
- + reg |= ((4 << 9) | (4 << 12));
- + writel_relaxed(reg, ccm_base + 0x2c);
- +
- + /*
- + * Perform the LDB parent clock switch.
- + */
- + clk_set_parent(clk[ldb_di0_sel], clk[new_parent]);
- + clk_set_parent(clk[ldb_di1_sel], clk[new_parent]);
- +
- + /*
- + * Unbypass pll3_sw_clk.
- + */
- + reg = readl_relaxed(ccm_base + 0xc);
- + reg &= ~(1 << 0);
- + writel_relaxed(reg, ccm_base + 0xc);
- +
- + /*
- + * Set the periph2_clk_sel back to the bottom mux so that
- + * mmdc_ch1 is from its original parent.
- + */
- + reg = readl_relaxed(ccm_base + 0x14);
- + reg &= ~(1 << 26);
- + writel_relaxed(reg, ccm_base + 0x14);
- +
- + /*
- + * Wait for the clock switch.
- + */
- + while (readl_relaxed(ccm_base + 0x48))
- + ;
- +
- + /*
- + * Clear MMDC_CH1 mask bit.
- + */
- + reg = readl_relaxed(ccm_base + 0x4);
- + reg &= ~(1 << 16);
- + writel_relaxed(reg, ccm_base + 0x4);
- +
- +}
- +
- static void __init imx6q_clocks_init(struct device_node *ccm_node)
- {
- struct device_node *np;
- void __iomem *base;
- int i, irq;
- int ret;
- + u32 reg;
-
- clk[dummy] = imx_clk_fixed("dummy", 0);
- clk[ckil] = imx_obtain_fixed_clock("ckil", 0);
- clk[ckih] = imx_obtain_fixed_clock("ckih1", 0);
- clk[osc] = imx_obtain_fixed_clock("osc", 0);
- + /* Clock source from external clock via ANACLK1/2 PADs */
- + clk[anaclk1] = imx_obtain_fixed_clock("anaclk1", 0);
- + clk[anaclk2] = imx_obtain_fixed_clock("anaclk2", 0);
-
- np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
- - base = of_iomap(np, 0);
- + anatop_base = base = of_iomap(np, 0);
- WARN_ON(!base);
-
- /* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */
- @@ -165,13 +287,18 @@
- }
-
- /* type name parent_name base div_mask */
- - clk[pll1_sys] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f);
- - clk[pll2_bus] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x1);
- - clk[pll3_usb_otg] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc", base + 0x10, 0x3);
- - clk[pll4_audio] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4_audio", "osc", base + 0x70, 0x7f);
- - clk[pll5_video] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "osc", base + 0xa0, 0x7f);
- - clk[pll6_enet] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6_enet", "osc", base + 0xe0, 0x3);
- - clk[pll7_usb_host] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host","osc", base + 0x20, 0x3);
- + clk[pll1_sys] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f, false);
- + clk[pll2_bus] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x1, false);
- + clk[pll3_usb_otg] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc", base + 0x10, 0x3, false);
- + clk[pll4_audio] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4_audio", "pll4_sel", base + 0x70, 0x7f, false);
- + clk[pll5_video] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "osc", base + 0xa0, 0x7f, false);
- + clk[pll6_enet] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6_enet", "osc", base + 0xe0, 0x3, false);
- + clk[pll7_usb_host] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host", "osc", base + 0x20, 0x3, false);
- +
- + /* name reg shift width parent_names num_parents */
- + clk[lvds1_sel] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
- + clk[lvds2_sel] = imx_clk_mux("lvds2_sel", base + 0x160, 5, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
- + clk[pll4_sel] = imx_clk_mux("pll4_sel", base + 0x70, 14, 2, pll_av_sels, ARRAY_SIZE(pll_av_sels));
-
- /*
- * Bit 20 is the reserved and read-only bit, we do this only for:
- @@ -191,6 +318,11 @@
-
- clk[sata_ref] = imx_clk_fixed_factor("sata_ref", "pll6_enet", 1, 5);
- clk[pcie_ref] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 4);
- + /* NOTICE: The gate of the lvds1/2 in/out is used to select the clk direction */
- + clk[lvds1_in] = imx_clk_gate("lvds1_in", "anaclk1", base + 0x160, 12);
- + clk[lvds2_in] = imx_clk_gate("lvds2_in", "anaclk2", base + 0x160, 13);
- + clk[lvds1_out] = imx_clk_gate("lvds1_out", "lvds1_sel", base + 0x160, 10);
- + clk[lvds2_out] = imx_clk_gate("lvds2_out", "lvds2_sel", base + 0x160, 11);
-
- clk[sata_ref_100m] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20);
- clk[pcie_ref_125m] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);
- @@ -199,18 +331,6 @@
- base + 0xe0, 0, 2, 0, clk_enet_ref_table,
- &imx_ccm_lock);
-
- - clk[lvds1_sel] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
- - clk[lvds2_sel] = imx_clk_mux("lvds2_sel", base + 0x160, 5, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
- -
- - /*
- - * lvds1_gate and lvds2_gate are pseudo-gates. Both can be
- - * independently configured as clock inputs or outputs. We treat
- - * the "output_enable" bit as a gate, even though it's really just
- - * enabling clock output.
- - */
- - clk[lvds1_gate] = imx_clk_gate("lvds1_gate", "dummy", base + 0x160, 10);
- - clk[lvds2_gate] = imx_clk_gate("lvds2_gate", "dummy", base + 0x160, 11);
- -
- /* name parent_name reg idx */
- clk[pll2_pfd0_352m] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0);
- clk[pll2_pfd1_594m] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus", base + 0x100, 1);
- @@ -226,6 +346,8 @@
- clk[pll3_80m] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6);
- clk[pll3_60m] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8);
- clk[twd] = imx_clk_fixed_factor("twd", "arm", 1, 2);
- + clk[gpt_3m] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8);
- + clk[video_27m] = imx_clk_fixed_factor("video_27m", "pll3_pfd1_540m", 1, 20);
-
- clk[pll4_post_div] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
- clk[pll4_audio_div] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
- @@ -233,7 +355,7 @@
- clk[pll5_video_div] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
-
- np = ccm_node;
- - base = of_iomap(np, 0);
- + ccm_base = base = of_iomap(np, 0);
- WARN_ON(!base);
-
- imx6q_pm_set_ccm_base(base);
- @@ -258,14 +380,16 @@
- clk[ipu2_sel] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
- clk[ldb_di0_sel] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
- clk[ldb_di1_sel] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
- - clk[ipu1_di0_pre_sel] = imx_clk_mux("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
- - clk[ipu1_di1_pre_sel] = imx_clk_mux("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
- - clk[ipu2_di0_pre_sel] = imx_clk_mux("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
- - clk[ipu2_di1_pre_sel] = imx_clk_mux("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
- - clk[ipu1_di0_sel] = imx_clk_mux("ipu1_di0_sel", base + 0x34, 0, 3, ipu1_di0_sels, ARRAY_SIZE(ipu1_di0_sels));
- - clk[ipu1_di1_sel] = imx_clk_mux("ipu1_di1_sel", base + 0x34, 9, 3, ipu1_di1_sels, ARRAY_SIZE(ipu1_di1_sels));
- - clk[ipu2_di0_sel] = imx_clk_mux("ipu2_di0_sel", base + 0x38, 0, 3, ipu2_di0_sels, ARRAY_SIZE(ipu2_di0_sels));
- - clk[ipu2_di1_sel] = imx_clk_mux("ipu2_di1_sel", base + 0x38, 9, 3, ipu2_di1_sels, ARRAY_SIZE(ipu2_di1_sels));
- + clk[ldb_di0_div_sel] = imx_clk_mux_flags("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels), CLK_SET_RATE_PARENT);
- + clk[ldb_di1_div_sel] = imx_clk_mux_flags("ldb_di1_div_sel", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels), CLK_SET_RATE_PARENT);
- + clk[ipu1_di0_pre_sel] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
- + clk[ipu1_di1_pre_sel] = imx_clk_mux_flags("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
- + clk[ipu2_di0_pre_sel] = imx_clk_mux_flags("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
- + clk[ipu2_di1_pre_sel] = imx_clk_mux_flags("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
- + clk[ipu1_di0_sel] = imx_clk_mux_flags("ipu1_di0_sel", base + 0x34, 0, 3, ipu1_di0_sels, ARRAY_SIZE(ipu1_di0_sels), CLK_SET_RATE_PARENT);
- + clk[ipu1_di1_sel] = imx_clk_mux_flags("ipu1_di1_sel", base + 0x34, 9, 3, ipu1_di1_sels, ARRAY_SIZE(ipu1_di1_sels), CLK_SET_RATE_PARENT);
- + clk[ipu2_di0_sel] = imx_clk_mux_flags("ipu2_di0_sel", base + 0x38, 0, 3, ipu2_di0_sels, ARRAY_SIZE(ipu2_di0_sels), CLK_SET_RATE_PARENT);
- + clk[ipu2_di1_sel] = imx_clk_mux_flags("ipu2_di1_sel", base + 0x38, 9, 3, ipu2_di1_sels, ARRAY_SIZE(ipu2_di1_sels), CLK_SET_RATE_PARENT);
- clk[hsi_tx_sel] = imx_clk_mux("hsi_tx_sel", base + 0x30, 28, 1, hsi_tx_sels, ARRAY_SIZE(hsi_tx_sels));
- clk[pcie_axi_sel] = imx_clk_mux("pcie_axi_sel", base + 0x18, 10, 1, pcie_axi_sels, ARRAY_SIZE(pcie_axi_sels));
- clk[ssi1_sel] = imx_clk_fixup_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup);
- @@ -307,9 +431,9 @@
- clk[ipu1_podf] = imx_clk_divider("ipu1_podf", "ipu1_sel", base + 0x3c, 11, 3);
- clk[ipu2_podf] = imx_clk_divider("ipu2_podf", "ipu2_sel", base + 0x3c, 16, 3);
- clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
- - clk[ldb_di0_podf] = imx_clk_divider_flags("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1, 0);
- + clk[ldb_di0_div_7] = imx_clk_fixed_factor("ldb_di0_div_7", "ldb_di0_sel", 1, 7);
- clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
- - clk[ldb_di1_podf] = imx_clk_divider_flags("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1, 0);
- + clk[ldb_di1_div_7] = imx_clk_fixed_factor("ldb_di1_div_7", "ldb_di1_sel", 1, 7);
- clk[ipu1_di0_pre] = imx_clk_divider("ipu1_di0_pre", "ipu1_di0_pre_sel", base + 0x34, 3, 3);
- clk[ipu1_di1_pre] = imx_clk_divider("ipu1_di1_pre", "ipu1_di1_pre_sel", base + 0x34, 12, 3);
- clk[ipu2_di0_pre] = imx_clk_divider("ipu2_di0_pre", "ipu2_di0_pre_sel", base + 0x38, 3, 3);
- @@ -344,6 +468,9 @@
- /* name parent_name reg shift */
- clk[apbh_dma] = imx_clk_gate2("apbh_dma", "usdhc3", base + 0x68, 4);
- clk[asrc] = imx_clk_gate2("asrc", "asrc_podf", base + 0x68, 6);
- + clk[caam_mem] = imx_clk_gate2("caam_mem", "ahb", base + 0x68, 8);
- + clk[caam_aclk] = imx_clk_gate2("caam_aclk", "ahb", base + 0x68, 10);
- + clk[caam_ipg] = imx_clk_gate2("caam_ipg", "ipg", base + 0x68, 12);
- clk[can1_ipg] = imx_clk_gate2("can1_ipg", "ipg", base + 0x68, 14);
- clk[can1_serial] = imx_clk_gate2("can1_serial", "can_root", base + 0x68, 16);
- clk[can2_ipg] = imx_clk_gate2("can2_ipg", "ipg", base + 0x68, 18);
- @@ -354,6 +481,8 @@
- clk[ecspi4] = imx_clk_gate2("ecspi4", "ecspi_root", base + 0x6c, 6);
- clk[ecspi5] = imx_clk_gate2("ecspi5", "ecspi_root", base + 0x6c, 8);
- clk[enet] = imx_clk_gate2("enet", "ipg", base + 0x6c, 10);
- + clk[epit1] = imx_clk_gate2("epit1", "ipg", base + 0x6c, 12);
- + clk[epit2] = imx_clk_gate2("epit2", "ipg", base + 0x6c, 14);
- clk[esai] = imx_clk_gate2("esai", "esai_podf", base + 0x6c, 16);
- clk[gpt_ipg] = imx_clk_gate2("gpt_ipg", "ipg", base + 0x6c, 20);
- clk[gpt_ipg_per] = imx_clk_gate2("gpt_ipg_per", "ipg_per", base + 0x6c, 22);
- @@ -373,15 +502,16 @@
- clk[i2c3] = imx_clk_gate2("i2c3", "ipg_per", base + 0x70, 10);
- clk[iim] = imx_clk_gate2("iim", "ipg", base + 0x70, 12);
- clk[enfc] = imx_clk_gate2("enfc", "enfc_podf", base + 0x70, 14);
- + clk[tzasc2] = imx_clk_gate2("tzasc2", "mmdc_ch0_axi_podf", base + 0x70, 24);
- clk[vdoa] = imx_clk_gate2("vdoa", "vdo_axi", base + 0x70, 26);
- clk[ipu1] = imx_clk_gate2("ipu1", "ipu1_podf", base + 0x74, 0);
- clk[ipu1_di0] = imx_clk_gate2("ipu1_di0", "ipu1_di0_sel", base + 0x74, 2);
- clk[ipu1_di1] = imx_clk_gate2("ipu1_di1", "ipu1_di1_sel", base + 0x74, 4);
- clk[ipu2] = imx_clk_gate2("ipu2", "ipu2_podf", base + 0x74, 6);
- clk[ipu2_di0] = imx_clk_gate2("ipu2_di0", "ipu2_di0_sel", base + 0x74, 8);
- - clk[ldb_di0] = imx_clk_gate2("ldb_di0", "ldb_di0_podf", base + 0x74, 12);
- - clk[ldb_di1] = imx_clk_gate2("ldb_di1", "ldb_di1_podf", base + 0x74, 14);
- clk[ipu2_di1] = imx_clk_gate2("ipu2_di1", "ipu2_di1_sel", base + 0x74, 10);
- + clk[ldb_di0] = imx_clk_gate2("ldb_di0", "ldb_di0_div_sel", base + 0x74, 12);
- + clk[ldb_di1] = imx_clk_gate2("ldb_di1", "ldb_di1_div_sel", base + 0x74, 14);
- clk[hsi_tx] = imx_clk_gate2("hsi_tx", "hsi_tx_podf", base + 0x74, 16);
- if (cpu_is_imx6dl())
- /*
- @@ -413,6 +543,9 @@
- clk[ssi1_ipg] = imx_clk_gate2("ssi1_ipg", "ipg", base + 0x7c, 18);
- clk[ssi2_ipg] = imx_clk_gate2("ssi2_ipg", "ipg", base + 0x7c, 20);
- clk[ssi3_ipg] = imx_clk_gate2("ssi3_ipg", "ipg", base + 0x7c, 22);
- + clk[ssi1] = imx_clk_gate2("ssi1", "ssi1_podf", base + 0x7c, 18);
- + clk[ssi2] = imx_clk_gate2("ssi2", "ssi2_podf", base + 0x7c, 20);
- + clk[ssi3] = imx_clk_gate2("ssi3", "ssi3_podf", base + 0x7c, 22);
- clk[uart_ipg] = imx_clk_gate2("uart_ipg", "ipg", base + 0x7c, 24);
- clk[uart_serial] = imx_clk_gate2("uart_serial", "uart_serial_podf", base + 0x7c, 26);
- clk[usboh3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0);
- @@ -431,25 +564,79 @@
- pr_err("i.MX6q clk %d: register failed with %ld\n",
- i, PTR_ERR(clk[i]));
-
- + /* Initialize clock gate status */
- + writel_relaxed(1 << CCM_CCGR_OFFSET(11) |
- + 3 << CCM_CCGR_OFFSET(1) |
- + 3 << CCM_CCGR_OFFSET(0), base + 0x68);
- + if (cpu_is_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0)
- + writel_relaxed(3 << CCM_CCGR_OFFSET(11) |
- + 3 << CCM_CCGR_OFFSET(10), base + 0x6c);
- + else
- + writel_relaxed(3 << CCM_CCGR_OFFSET(10), base + 0x6c);
- + writel_relaxed(1 << CCM_CCGR_OFFSET(12) |
- + 3 << CCM_CCGR_OFFSET(11) |
- + 3 << CCM_CCGR_OFFSET(10) |
- + 3 << CCM_CCGR_OFFSET(9) |
- + 3 << CCM_CCGR_OFFSET(8), base + 0x70);
- + writel_relaxed(3 << CCM_CCGR_OFFSET(14) |
- + 1 << CCM_CCGR_OFFSET(13) |
- + 3 << CCM_CCGR_OFFSET(12) |
- + 1 << CCM_CCGR_OFFSET(11) |
- + 3 << CCM_CCGR_OFFSET(10), base + 0x74);
- + writel_relaxed(3 << CCM_CCGR_OFFSET(7) |
- + 3 << CCM_CCGR_OFFSET(6) |
- + 3 << CCM_CCGR_OFFSET(4), base + 0x78);
- + writel_relaxed(1 << CCM_CCGR_OFFSET(0), base + 0x7c);
- + writel_relaxed(0, base + 0x80);
- +
- + /* Make sure PFDs are disabled at boot. */
- + reg = readl_relaxed(anatop_base + 0x100);
- + /* Cannot disable pll2_pfd2_396M, as it is the MMDC clock in iMX6DL */
- + if (cpu_is_imx6dl())
- + reg |= 0x80008080;
- + else
- + reg |= 0x80808080;
- + writel_relaxed(reg, anatop_base + 0x100);
- +
- + /* Disable PLL3 PFDs. */
- + reg = readl_relaxed(anatop_base + 0xF0);
- + reg |= 0x80808080;
- + writel_relaxed(reg, anatop_base + 0xF0);
- +
- + /* Make sure PLLs is disabled */
- + reg = readl_relaxed(anatop_base + 0xA0);
- + reg &= ~(1 << 13);
- + writel_relaxed(reg, anatop_base + 0xA0);
- +
- clk_data.clks = clk;
- clk_data.clk_num = ARRAY_SIZE(clk);
- of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
-
- clk_register_clkdev(clk[gpt_ipg], "ipg", "imx-gpt.0");
- clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
- + clk_register_clkdev(clk[gpt_3m], "gpt_3m", "imx-gpt.0");
- clk_register_clkdev(clk[cko1_sel], "cko1_sel", NULL);
- clk_register_clkdev(clk[ahb], "ahb", NULL);
- clk_register_clkdev(clk[cko1], "cko1", NULL);
- clk_register_clkdev(clk[arm], NULL, "cpu0");
- - clk_register_clkdev(clk[pll4_post_div], "pll4_post_div", NULL);
- - clk_register_clkdev(clk[pll4_audio], "pll4_audio", NULL);
- + clk_register_clkdev(clk[pll4_audio_div], "pll4_audio_div", NULL);
- + clk_register_clkdev(clk[pll4_sel], "pll4_sel", NULL);
- + clk_register_clkdev(clk[lvds2_in], "lvds2_in", NULL);
- + clk_register_clkdev(clk[esai], "esai", NULL);
-
- - if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) ||
- - cpu_is_imx6dl()) {
- - clk_set_parent(clk[ldb_di0_sel], clk[pll5_video_div]);
- - clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]);
- + if (cpu_is_imx6dl()) {
- + clk_set_parent(clk[ipu1_sel], clk[pll3_pfd1_540m]);
- }
-
- + clk_set_parent(clk[ipu1_di0_pre_sel], clk[pll5_video_div]);
- + clk_set_parent(clk[ipu1_di1_pre_sel], clk[pll5_video_div]);
- + clk_set_parent(clk[ipu2_di0_pre_sel], clk[pll5_video_div]);
- + clk_set_parent(clk[ipu2_di1_pre_sel], clk[pll5_video_div]);
- + clk_set_parent(clk[ipu1_di0_sel], clk[ipu1_di0_pre]);
- + clk_set_parent(clk[ipu1_di1_sel], clk[ipu1_di1_pre]);
- + clk_set_parent(clk[ipu2_di0_sel], clk[ipu2_di0_pre]);
- + clk_set_parent(clk[ipu2_di1_sel], clk[ipu2_di1_pre]);
- +
- /*
- * The gpmi needs 100MHz frequency in the EDO/Sync mode,
- * We can not get the 100MHz from the pll2_pfd0_352m.
- @@ -457,6 +644,19 @@
- */
- clk_set_parent(clk[enfc_sel], clk[pll2_pfd2_396m]);
-
- + /* Set the parent clks of PCIe lvds1 and pcie_axi to be sata ref, axi */
- + if (clk_set_parent(clk[lvds1_sel], clk[sata_ref]))
- + pr_err("Failed to set PCIe bus parent clk.\n");
- + if (clk_set_parent(clk[pcie_axi_sel], clk[axi]))
- + pr_err("Failed to set PCIe parent clk.\n");
- +
- + /* gpu clock initilazation */
- + clk_set_parent(clk[gpu3d_shader_sel], clk[pll2_pfd1_594m]);
- + clk_set_rate(clk[gpu3d_shader], 594000000);
- + clk_set_parent(clk[gpu3d_core_sel], clk[mmdc_ch0_axi]);
- + clk_set_rate(clk[gpu3d_core], 528000000);
- + clk_set_parent(clk[gpu2d_core_sel], clk[pll3_usb_otg]);
- +
- for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
- clk_prepare_enable(clk[clks_init_on[i]]);
-
- @@ -465,6 +665,25 @@
- clk_prepare_enable(clk[usbphy2_gate]);
- }
-
- + /* ipu clock initialization */
- + init_ldb_clks(pll2_pfd0_352m);
- + clk_set_parent(clk[ipu1_di0_pre_sel], clk[pll5_video_div]);
- + clk_set_parent(clk[ipu1_di1_pre_sel], clk[pll5_video_div]);
- + clk_set_parent(clk[ipu2_di0_pre_sel], clk[pll5_video_div]);
- + clk_set_parent(clk[ipu2_di1_pre_sel], clk[pll5_video_div]);
- + clk_set_parent(clk[ipu1_di0_sel], clk[ipu1_di0_pre]);
- + clk_set_parent(clk[ipu1_di1_sel], clk[ipu1_di1_pre]);
- + clk_set_parent(clk[ipu2_di0_sel], clk[ipu2_di0_pre]);
- + clk_set_parent(clk[ipu2_di1_sel], clk[ipu2_di1_pre]);
- + if (cpu_is_imx6dl()) {
- + clk_set_rate(clk[pll3_pfd1_540m], 540000000);
- + clk_set_parent(clk[ipu1_sel], clk[pll3_pfd1_540m]);
- + clk_set_parent(clk[axi_sel], clk[pll3_pfd1_540m]);
- + } else if (cpu_is_imx6q()) {
- + clk_set_parent(clk[ipu1_sel], clk[mmdc_ch0_axi]);
- + clk_set_parent(clk[ipu2_sel], clk[mmdc_ch0_axi]);
- + }
- +
- /*
- * Let's initially set up CLKO with OSC24M, since this configuration
- * is widely used by imx6q board designs to clock audio codec.
- @@ -482,6 +701,18 @@
- if (IS_ENABLED(CONFIG_PCI_IMX6))
- clk_set_parent(clk[lvds1_sel], clk[sata_ref]);
-
- + /* Audio clocks */
- + clk_set_parent(clk[ssi1_sel], clk[pll4_audio_div]);
- + clk_set_parent(clk[ssi2_sel], clk[pll4_audio_div]);
- + clk_set_parent(clk[ssi3_sel], clk[pll4_audio_div]);
- + clk_set_parent(clk[esai_sel], clk[pll4_audio_div]);
- + clk_set_parent(clk[spdif_sel], clk[pll3_pfd3_454m]);
- + clk_set_parent(clk[asrc_sel], clk[pll3_usb_otg]);
- + clk_set_rate(clk[asrc_sel], 7500000);
- +
- + /* Set pll4_audio to a value that can derive 5K-88.2KHz and 8K-96KHz */
- + clk_set_rate(clk[pll4_audio_div], 541900800);
- +
- /* Set initial power mode */
- imx6q_set_lpm(WAIT_CLOCKED);
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/clk-imx6sl.c linux-3.14.35/arch/arm/mach-imx/clk-imx6sl.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/clk-imx6sl.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/clk-imx6sl.c 2015-03-08 14:27:37.417684503 -0500
- @@ -7,9 +7,29 @@
- *
- */
-
- +#define CCM_CCDR_OFFSET 0x4
- +#define ANATOP_PLL_USB1 0x10
- +#define ANATOP_PLL_USB2 0x20
- +#define ANATOP_PLL_ENET 0xE0
- +#define ANATOP_PLL_BYPASS_OFFSET (1 << 16)
- +#define ANATOP_PLL_ENABLE_OFFSET (1 << 13)
- +#define ANATOP_PLL_POWER_OFFSET (1 << 12)
- +#define ANATOP_PFD_480n_OFFSET 0xf0
- +#define ANATOP_PFD_528n_OFFSET 0x100
- +#define PFD0_CLKGATE (1 << 7)
- +#define PFD1_CLK_GATE (1 << 15)
- +#define PFD2_CLK_GATE (1 << 23)
- +#define PFD3_CLK_GATE (1 << 31)
- +#define CCDR_CH0_HS_BYP 17
- +#define OSC_RATE 24000000
- +
- +#define CCM_CCGR_OFFSET(index) (index * 2)
- +
- #include <linux/clk.h>
- #include <linux/clkdev.h>
- #include <linux/err.h>
- +#include <linux/init.h>
- +#include <linux/io.h>
- #include <linux/of.h>
- #include <linux/of_address.h>
- #include <linux/of_irq.h>
- @@ -18,6 +38,7 @@
- #include "clk.h"
- #include "common.h"
-
- +static bool uart_from_osc;
- static const char const *step_sels[] = { "osc", "pll2_pfd2", };
- static const char const *pll1_sw_sels[] = { "pll1_sys", "step", };
- static const char const *ocram_alt_sels[] = { "pll2_pfd2", "pll3_pfd1", };
- @@ -25,8 +46,8 @@
- static const char const *pre_periph_sels[] = { "pll2_bus", "pll2_pfd2", "pll2_pfd0", "pll2_198m", };
- static const char const *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", "dummy", };
- static const char const *periph2_clk2_sels[] = { "pll3_usb_otg", "pll2_bus", };
- -static const char const *periph_sels[] = { "pre_periph_sel", "periph_clk2_podf", };
- -static const char const *periph2_sels[] = { "pre_periph2_sel", "periph2_clk2_podf", };
- +static const char const *periph_sels[] = { "pre_periph_sel", "periph_clk2", };
- +static const char const *periph2_sels[] = { "pre_periph2_sel", "periph2_clk2", };
- static const char const *csi_lcdif_sels[] = { "mmdc", "pll2_pfd2", "pll3_120m", "pll3_pfd1", };
- static const char const *usdhc_sels[] = { "pll2_pfd2", "pll2_pfd0", };
- static const char const *ssi_sels[] = { "pll3_pfd2", "pll3_pfd3", "pll4_audio_div", "dummy", };
- @@ -38,7 +59,7 @@
- static const char const *epdc_pix_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd1", "pll3_pfd1", };
- static const char const *audio_sels[] = { "pll4_audio_div", "pll3_pfd2", "pll3_pfd3", "pll3_usb_otg", };
- static const char const *ecspi_sels[] = { "pll3_60m", "osc", };
- -static const char const *uart_sels[] = { "pll3_80m", "osc", };
- +static const char const *uart_sels[] = { "pll3_80m", "uart_osc_4M", };
-
- static struct clk_div_table clk_enet_ref_table[] = {
- { .val = 0, .div = 20, },
- @@ -65,6 +86,80 @@
-
- static struct clk *clks[IMX6SL_CLK_END];
- static struct clk_onecell_data clk_data;
- +static u32 cur_arm_podf;
- +static u32 pll1_org_rate;
- +
- +extern int low_bus_freq_mode;
- +extern int audio_bus_freq_mode;
- +
- +/*
- + * On MX6SL, need to ensure that the ARM:IPG clock ratio is maintained
- + * within 12:5 when the clocks to ARM are gated when the SOC enters
- + * WAIT mode. This is necessary to avoid WAIT mode issue (an early
- + * interrupt waking up the ARM).
- + * This function will set the ARM clk to max value within the 12:5 limit.
- + */
- +void imx6sl_set_wait_clk(bool enter)
- +{
- + u32 parent_rate;
- +
- + if (enter) {
- + u32 wait_podf;
- + u32 new_parent_rate = OSC_RATE;
- + u32 ipg_rate = clk_get_rate(clks[IMX6SL_CLK_IPG]);
- + u32 max_arm_wait_clk = (12 * ipg_rate) / 5;
- + parent_rate = clk_get_rate(clks[IMX6SL_CLK_PLL1_SW]);
- + cur_arm_podf = parent_rate / clk_get_rate(clks[IMX6SL_CLK_ARM]);
- + if (low_bus_freq_mode) {
- + /*
- + * IPG clk is at 12MHz at this point, we can only run
- + * ARM at a max of 28.8MHz. So we need to set ARM
- + * to run from the 24MHz OSC, as there is no way to
- + * get 28.8MHz when ARM is sourced from PLL1.
- + */
- + clk_set_parent(clks[IMX6SL_CLK_STEP],
- + clks[IMX6SL_CLK_OSC]);
- + clk_set_parent(clks[IMX6SL_CLK_PLL1_SW],
- + clks[IMX6SL_CLK_STEP]);
- + } else if (audio_bus_freq_mode) {
- + /*
- + * In this mode ARM is from PLL2_PFD2 (396MHz),
- + * but IPG is at 12MHz. Need to switch ARM to run
- + * from the bypassed PLL1 clocks so that we can run
- + * ARM at 24MHz.
- + */
- + pll1_org_rate = clk_get_rate(clks[IMX6SL_CLK_PLL1_SYS]);
- + /* Ensure PLL1 is at 24MHz. */
- + clk_set_rate(clks[IMX6SL_CLK_PLL1_SYS], OSC_RATE);
- + clk_set_parent(clks[IMX6SL_CLK_PLL1_SW], clks[IMX6SL_CLK_PLL1_SYS]);
- + } else
- + new_parent_rate = clk_get_rate(clks[IMX6SL_CLK_PLL1_SW]);
- + wait_podf = (new_parent_rate + max_arm_wait_clk - 1) /
- + max_arm_wait_clk;
- +
- + clk_set_rate(clks[IMX6SL_CLK_ARM], new_parent_rate / wait_podf);
- + } else {
- + if (low_bus_freq_mode)
- + /* Move ARM back to PLL1. */
- + clk_set_parent(clks[IMX6SL_CLK_PLL1_SW],
- + clks[IMX6SL_CLK_PLL1_SYS]);
- + else if (audio_bus_freq_mode) {
- + /* Move ARM back to PLL2_PFD2 via STEP_CLK. */
- + clk_set_parent(clks[IMX6SL_CLK_PLL1_SW], clks[IMX6SL_CLK_STEP]);
- + clk_set_rate(clks[IMX6SL_CLK_PLL1_SYS], pll1_org_rate);
- + }
- + parent_rate = clk_get_rate(clks[IMX6SL_CLK_PLL1_SW]);
- + clk_set_rate(clks[IMX6SL_CLK_ARM], parent_rate / cur_arm_podf);
- + }
- +}
- +
- +static int __init setup_uart_clk(char *uart_rate)
- +{
- + uart_from_osc = true;
- + return 1;
- +}
- +
- +__setup("uart_at_4M", setup_uart_clk);
-
- static void __init imx6sl_clocks_init(struct device_node *ccm_node)
- {
- @@ -72,6 +167,8 @@
- void __iomem *base;
- int irq;
- int i;
- + int ret;
- + u32 reg;
-
- clks[IMX6SL_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
- clks[IMX6SL_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0);
- @@ -82,13 +179,18 @@
- WARN_ON(!base);
-
- /* type name parent base div_mask */
- - clks[IMX6SL_CLK_PLL1_SYS] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f);
- - clks[IMX6SL_CLK_PLL2_BUS] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x1);
- - clks[IMX6SL_CLK_PLL3_USB_OTG] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc", base + 0x10, 0x3);
- - clks[IMX6SL_CLK_PLL4_AUDIO] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4_audio", "osc", base + 0x70, 0x7f);
- - clks[IMX6SL_CLK_PLL5_VIDEO] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "osc", base + 0xa0, 0x7f);
- - clks[IMX6SL_CLK_PLL6_ENET] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6_enet", "osc", base + 0xe0, 0x3);
- - clks[IMX6SL_CLK_PLL7_USB_HOST] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host", "osc", base + 0x20, 0x3);
- + clks[IMX6SL_CLK_PLL1_SYS] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f, true);
- + clks[IMX6SL_CLK_PLL2_BUS] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x1, true);
- + clks[IMX6SL_CLK_PLL3_USB_OTG] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc", base + 0x10, 0x3, false);
- + clks[IMX6SL_CLK_PLL4_AUDIO] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4_audio", "osc", base + 0x70, 0x7f, false);
- + clks[IMX6SL_CLK_PLL5_VIDEO] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "osc", base + 0xa0, 0x7f, false);
- + clks[IMX6SL_CLK_PLL6_ENET] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6_enet", "osc", base + 0xe0, 0x3, false);
- + clks[IMX6SL_CLK_PLL7_USB_HOST] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host", "osc", base + 0x20, 0x3, false);
- +
- + /* Ensure the AHB clk is at 132MHz. */
- + ret = clk_set_rate(clks[IMX6SL_CLK_AHB], 132000000);
- + if (ret)
- + pr_warn("%s: failed to set AHB clock rate %d\n", __func__, ret);
-
- /*
- * usbphy1 and usbphy2 are implemented as dummy gates using reserve
- @@ -118,11 +220,36 @@
- clks[IMX6SL_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2", "pll3_usb_otg", base + 0xf0, 2);
- clks[IMX6SL_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3", "pll3_usb_otg", base + 0xf0, 3);
-
- - /* name parent_name mult div */
- - clks[IMX6SL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2", 1, 2);
- - clks[IMX6SL_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg", 1, 4);
- - clks[IMX6SL_CLK_PLL3_80M] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6);
- - clks[IMX6SL_CLK_PLL3_60M] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8);
- + /* name parent_name mult div */
- + clks[IMX6SL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2", 1, 2);
- + clks[IMX6SL_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg", 1, 4);
- + clks[IMX6SL_CLK_PLL3_80M] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6);
- + clks[IMX6SL_CLK_PLL3_60M] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8);
- + clks[IMX6SL_CLK_UART_OSC_4M] = imx_clk_fixed_factor("uart_osc_4M", "osc", 1, 6);
- +
- + /* Ensure all PFDs but PLL2_PFD2 are disabled. */
- + reg = readl_relaxed(base + ANATOP_PFD_480n_OFFSET);
- + reg |= (PFD0_CLKGATE | PFD1_CLK_GATE | PFD2_CLK_GATE | PFD3_CLK_GATE);
- + writel_relaxed(reg, base + ANATOP_PFD_480n_OFFSET);
- + reg = readl_relaxed(base + ANATOP_PFD_528n_OFFSET);
- + reg |= (PFD0_CLKGATE | PFD1_CLK_GATE);
- + writel_relaxed(reg, base + ANATOP_PFD_528n_OFFSET);
- +
- + /* Ensure Unused PLLs are disabled. */
- + reg = readl_relaxed(base + ANATOP_PLL_USB1);
- + reg |= ANATOP_PLL_BYPASS_OFFSET;
- + reg &= ~(ANATOP_PLL_ENABLE_OFFSET | ANATOP_PLL_POWER_OFFSET);
- + writel_relaxed(reg, base + ANATOP_PLL_USB1);
- +
- + reg = readl_relaxed(base + ANATOP_PLL_USB2);
- + reg |= ANATOP_PLL_BYPASS_OFFSET;
- + reg &= ~(ANATOP_PLL_ENABLE_OFFSET | ANATOP_PLL_POWER_OFFSET);
- + writel_relaxed(reg, base + ANATOP_PLL_USB2);
- +
- + reg = readl_relaxed(base + ANATOP_PLL_ENET);
- + reg |= (ANATOP_PLL_BYPASS_OFFSET | ANATOP_PLL_POWER_OFFSET);
- + reg &= ~ANATOP_PLL_ENABLE_OFFSET;
- + writel_relaxed(reg, base + ANATOP_PLL_ENET);
-
- np = ccm_node;
- base = of_iomap(np, 0);
- @@ -158,7 +285,7 @@
- clks[IMX6SL_CLK_EPDC_PIX_SEL] = imx_clk_mux("epdc_pix_sel", base + 0x38, 15, 3, epdc_pix_sels, ARRAY_SIZE(epdc_pix_sels));
- clks[IMX6SL_CLK_SPDIF0_SEL] = imx_clk_mux("spdif0_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels));
- clks[IMX6SL_CLK_SPDIF1_SEL] = imx_clk_mux("spdif1_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels));
- - clks[IMX6SL_CLK_EXTERN_AUDIO_SEL] = imx_clk_mux("extern_audio_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels));
- + clks[IMX6SL_CLK_EXTERN_AUDIO_SEL] = imx_clk_mux_flags("extern_audio_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels), CLK_SET_RATE_PARENT);
- clks[IMX6SL_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels));
- clks[IMX6SL_CLK_UART_SEL] = imx_clk_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels));
-
- @@ -168,8 +295,8 @@
-
- /* name parent_name reg shift width */
- clks[IMX6SL_CLK_OCRAM_PODF] = imx_clk_divider("ocram_podf", "ocram_sel", base + 0x14, 16, 3);
- - clks[IMX6SL_CLK_PERIPH_CLK2_PODF] = imx_clk_divider("periph_clk2_podf", "periph_clk2_sel", base + 0x14, 27, 3);
- - clks[IMX6SL_CLK_PERIPH2_CLK2_PODF] = imx_clk_divider("periph2_clk2_podf", "periph2_clk2_sel", base + 0x14, 0, 3);
- + clks[IMX6SL_CLK_PERIPH_CLK2] = imx_clk_divider("periph_clk2", "periph_clk2_sel", base + 0x14, 27, 3);
- + clks[IMX6SL_CLK_PERIPH2_CLK2] = imx_clk_divider("periph2_clk2", "periph2_clk2_sel", base + 0x14, 0, 3);
- clks[IMX6SL_CLK_IPG] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2);
- clks[IMX6SL_CLK_CSI_PODF] = imx_clk_divider("csi_podf", "csi_sel", base + 0x3c, 11, 3);
- clks[IMX6SL_CLK_LCDIF_AXI_PODF] = imx_clk_divider("lcdif_axi_podf", "lcdif_axi_sel", base + 0x3c, 16, 3);
- @@ -251,6 +378,25 @@
- pr_err("i.MX6SL clk %d: register failed with %ld\n",
- i, PTR_ERR(clks[i]));
-
- + /* Initialize clock gate status */
- + writel_relaxed(1 << CCM_CCGR_OFFSET(11) |
- + 3 << CCM_CCGR_OFFSET(1) |
- + 3 << CCM_CCGR_OFFSET(0), base + 0x68);
- + writel_relaxed(3 << CCM_CCGR_OFFSET(10), base + 0x6c);
- + writel_relaxed(1 << CCM_CCGR_OFFSET(11) |
- + 3 << CCM_CCGR_OFFSET(10) |
- + 3 << CCM_CCGR_OFFSET(9) |
- + 3 << CCM_CCGR_OFFSET(8), base + 0x70);
- + writel_relaxed(3 << CCM_CCGR_OFFSET(14) |
- + 3 << CCM_CCGR_OFFSET(13) |
- + 3 << CCM_CCGR_OFFSET(12) |
- + 3 << CCM_CCGR_OFFSET(11) |
- + 3 << CCM_CCGR_OFFSET(10), base + 0x74);
- + writel_relaxed(3 << CCM_CCGR_OFFSET(7) |
- + 3 << CCM_CCGR_OFFSET(4), base + 0x78);
- + writel_relaxed(1 << CCM_CCGR_OFFSET(0), base + 0x7c);
- + writel_relaxed(0, base + 0x80);
- +
- clk_data.clks = clks;
- clk_data.clk_num = ARRAY_SIZE(clks);
- of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
- @@ -258,17 +404,58 @@
- clk_register_clkdev(clks[IMX6SL_CLK_GPT], "ipg", "imx-gpt.0");
- clk_register_clkdev(clks[IMX6SL_CLK_GPT_SERIAL], "per", "imx-gpt.0");
-
- + /*
- + * Make sure the ARM clk is enabled to maintain the correct usecount
- + * and enabling/disabling of parent PLLs.
- + */
- + ret = clk_prepare_enable(clks[IMX6SL_CLK_ARM]);
- + if (ret)
- + pr_warn("%s: failed to enable ARM core clock %d\n",
- + __func__, ret);
- +
- + /*
- + * Make sure the MMDC clk is enabled to maintain the correct usecount
- + * and enabling/disabling of parent PLLs.
- + */
- + ret = clk_prepare_enable(clks[IMX6SL_CLK_MMDC_ROOT]);
- + if (ret)
- + pr_warn("%s: failed to enable MMDC clock %d\n",
- + __func__, ret);
- +
- if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
- clk_prepare_enable(clks[IMX6SL_CLK_USBPHY1_GATE]);
- clk_prepare_enable(clks[IMX6SL_CLK_USBPHY2_GATE]);
- }
-
- + clk_set_parent(clks[IMX6SL_CLK_GPU2D_OVG_SEL],
- + clks[IMX6SL_CLK_PLL2_BUS]);
- + clk_set_parent(clks[IMX6SL_CLK_GPU2D_SEL], clks[IMX6SL_CLK_PLL2_BUS]);
- +
- /* Audio-related clocks configuration */
- clk_set_parent(clks[IMX6SL_CLK_SPDIF0_SEL], clks[IMX6SL_CLK_PLL3_PFD3]);
-
- + /* set extern_audio to be sourced from PLL4/audio PLL */
- + clk_set_parent(clks[IMX6SL_CLK_EXTERN_AUDIO_SEL], clks[IMX6SL_CLK_PLL4_AUDIO_DIV]);
- + /* set extern_audio to 24MHz */
- + clk_set_rate(clks[IMX6SL_CLK_PLL4_AUDIO], 24000000);
- + clk_set_rate(clks[IMX6SL_CLK_EXTERN_AUDIO], 24000000);
- +
- + /* set SSI2 parent to PLL4 */
- + clk_set_parent(clks[IMX6SL_CLK_SSI2_SEL], clks[IMX6SL_CLK_PLL4_AUDIO_DIV]);
- + clk_set_rate(clks[IMX6SL_CLK_SSI2], 24000000);
- +
- /* Set initial power mode */
- imx6q_set_lpm(WAIT_CLOCKED);
-
- + /* Ensure that CH0 handshake is bypassed. */
- + reg = readl_relaxed(base + CCM_CCDR_OFFSET);
- + reg |= 1 << CCDR_CH0_HS_BYP;
- + writel_relaxed(reg, base + CCM_CCDR_OFFSET);
- +
- + /* Set the UART parent if needed. */
- + if (uart_from_osc)
- + ret = clk_set_parent(clks[IMX6SL_CLK_UART_SEL], clks[IMX6SL_CLK_UART_OSC_4M]);
- +
- np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-gpt");
- base = of_iomap(np, 0);
- WARN_ON(!base);
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/clk-pfd.c linux-3.14.35/arch/arm/mach-imx/clk-pfd.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/clk-pfd.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/clk-pfd.c 2015-03-08 14:27:37.417684503 -0500
- @@ -1,5 +1,5 @@
- /*
- - * Copyright 2012 Freescale Semiconductor, Inc.
- + * Copyright 2012-2013 Freescale Semiconductor, Inc.
- * Copyright 2012 Linaro Ltd.
- *
- * The code contained herein is licensed under the GNU General Public
- @@ -17,6 +17,8 @@
- #include <linux/err.h>
- #include "clk.h"
-
- +#define BYPASS_RATE 24000000
- +
- /**
- * struct clk_pfd - IMX PFD clock
- * @clk_hw: clock source
- @@ -62,9 +64,14 @@
- u64 tmp = parent_rate;
- u8 frac = (readl_relaxed(pfd->reg) >> (pfd->idx * 8)) & 0x3f;
-
- - tmp *= 18;
- - do_div(tmp, frac);
- -
- + /*
- + * If the parent PLL is in bypass state, the PFDs
- + * are also in bypass state.
- + */
- + if (tmp != BYPASS_RATE) {
- + tmp *= 18;
- + do_div(tmp, frac);
- + }
- return tmp;
- }
-
- @@ -74,17 +81,22 @@
- u64 tmp = *prate;
- u8 frac;
-
- - tmp = tmp * 18 + rate / 2;
- - do_div(tmp, rate);
- - frac = tmp;
- - if (frac < 12)
- - frac = 12;
- - else if (frac > 35)
- - frac = 35;
- - tmp = *prate;
- - tmp *= 18;
- - do_div(tmp, frac);
- -
- + /*
- + * If the parent PLL is in bypass state, the PFDs
- + * are also in bypass state.
- + */
- + if (tmp != BYPASS_RATE) {
- + tmp = tmp * 18 + rate / 2;
- + do_div(tmp, rate);
- + frac = tmp;
- + if (frac < 12)
- + frac = 12;
- + else if (frac > 35)
- + frac = 35;
- + tmp = *prate;
- + tmp *= 18;
- + do_div(tmp, frac);
- + }
- return tmp;
- }
-
- @@ -95,6 +107,9 @@
- u64 tmp = parent_rate;
- u8 frac;
-
- + if (tmp == BYPASS_RATE)
- + return 0;
- +
- tmp = tmp * 18 + rate / 2;
- do_div(tmp, rate);
- frac = tmp;
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/clk-pllv3.c linux-3.14.35/arch/arm/mach-imx/clk-pllv3.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/clk-pllv3.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/clk-pllv3.c 2015-03-08 14:27:37.417684503 -0500
- @@ -26,12 +26,15 @@
- #define BM_PLL_ENABLE (0x1 << 13)
- #define BM_PLL_BYPASS (0x1 << 16)
- #define BM_PLL_LOCK (0x1 << 31)
- +#define BYPASS_RATE 24000000
- +#define BYPASS_MASK 0x10000
-
- /**
- * struct clk_pllv3 - IMX PLL clock version 3
- * @clk_hw: clock source
- * @base: base address of PLL registers
- * @powerup_set: set POWER bit to power up the PLL
- + * @always_on : Leave the PLL powered up all the time.
- * @div_mask: mask of divider bits
- *
- * IMX PLL clock version 3, found on i.MX6 series. Divider for pllv3
- @@ -41,7 +44,9 @@
- struct clk_hw hw;
- void __iomem *base;
- bool powerup_set;
- + bool always_on;
- u32 div_mask;
- + u32 rate_req;
- };
-
- #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw)
- @@ -61,54 +66,53 @@
- break;
- if (time_after(jiffies, timeout))
- break;
- - usleep_range(50, 500);
- + udelay(100);
- } while (1);
-
- return readl_relaxed(pll->base) & BM_PLL_LOCK ? 0 : -ETIMEDOUT;
- }
-
- -static int clk_pllv3_prepare(struct clk_hw *hw)
- +static int clk_pllv3_power_up_down(struct clk_hw *hw, bool enable)
- {
- struct clk_pllv3 *pll = to_clk_pllv3(hw);
- - u32 val;
- - int ret;
- -
- - val = readl_relaxed(pll->base);
- - if (pll->powerup_set)
- - val |= BM_PLL_POWER;
- - else
- - val &= ~BM_PLL_POWER;
- - writel_relaxed(val, pll->base);
- -
- - ret = clk_pllv3_wait_lock(pll);
- - if (ret)
- - return ret;
- + u32 val, ret = 0;
-
- - val = readl_relaxed(pll->base);
- - val &= ~BM_PLL_BYPASS;
- - writel_relaxed(val, pll->base);
- -
- - return 0;
- -}
- + if (enable) {
- + val = readl_relaxed(pll->base);
- + val &= ~BM_PLL_BYPASS;
- + if (pll->powerup_set)
- + val |= BM_PLL_POWER;
- + else
- + val &= ~BM_PLL_POWER;
- + writel_relaxed(val, pll->base);
- +
- + ret = clk_pllv3_wait_lock(pll);
- + } else {
- + val = readl_relaxed(pll->base);
- + val |= BM_PLL_BYPASS;
- + if (pll->powerup_set)
- + val &= ~BM_PLL_POWER;
- + else
- + val |= BM_PLL_POWER;
- + writel_relaxed(val, pll->base);
- + }
-
- -static void clk_pllv3_unprepare(struct clk_hw *hw)
- -{
- - struct clk_pllv3 *pll = to_clk_pllv3(hw);
- - u32 val;
- + if (!ret) {
- + val = readl_relaxed(pll->base);
- + val &= ~BM_PLL_BYPASS;
- + writel_relaxed(val, pll->base);
- + }
-
- - val = readl_relaxed(pll->base);
- - val |= BM_PLL_BYPASS;
- - if (pll->powerup_set)
- - val &= ~BM_PLL_POWER;
- - else
- - val |= BM_PLL_POWER;
- - writel_relaxed(val, pll->base);
- + return ret;
- }
-
- static int clk_pllv3_enable(struct clk_hw *hw)
- {
- struct clk_pllv3 *pll = to_clk_pllv3(hw);
- u32 val;
- +
- + if (pll->rate_req != BYPASS_RATE)
- + clk_pllv3_power_up_down(hw, true);
-
- val = readl_relaxed(pll->base);
- val |= BM_PLL_ENABLE;
- @@ -123,8 +127,12 @@
- u32 val;
-
- val = readl_relaxed(pll->base);
- - val &= ~BM_PLL_ENABLE;
- + if (!pll->always_on)
- + val &= ~BM_PLL_ENABLE;
- writel_relaxed(val, pll->base);
- +
- + if (pll->rate_req != BYPASS_RATE)
- + clk_pllv3_power_up_down(hw, false);
- }
-
- static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw,
- @@ -132,8 +140,15 @@
- {
- struct clk_pllv3 *pll = to_clk_pllv3(hw);
- u32 div = readl_relaxed(pll->base) & pll->div_mask;
- + u32 bypass = readl_relaxed(pll->base) & BYPASS_MASK;
- + u32 rate;
- +
- + if (pll->rate_req == BYPASS_RATE && bypass)
- + rate = BYPASS_RATE;
- + else
- + rate = (div == 1) ? parent_rate * 22 : parent_rate * 20;
-
- - return (div == 1) ? parent_rate * 22 : parent_rate * 20;
- + return rate;
- }
-
- static long clk_pllv3_round_rate(struct clk_hw *hw, unsigned long rate,
- @@ -141,6 +156,10 @@
- {
- unsigned long parent_rate = *prate;
-
- + /* If the PLL is bypassed, its rate is 24MHz. */
- + if (rate == BYPASS_RATE)
- + return BYPASS_RATE;
- +
- return (rate >= parent_rate * 22) ? parent_rate * 22 :
- parent_rate * 20;
- }
- @@ -151,6 +170,22 @@
- struct clk_pllv3 *pll = to_clk_pllv3(hw);
- u32 val, div;
-
- + pll->rate_req = rate;
- + val = readl_relaxed(pll->base);
- +
- + /* If the PLL is bypassed, its rate is 24MHz. */
- + if (rate == BYPASS_RATE) {
- + /* Set the bypass bit. */
- + val |= BM_PLL_BYPASS;
- + /* Power down the PLL. */
- + if (pll->powerup_set)
- + val &= ~BM_PLL_POWER;
- + else
- + val |= BM_PLL_POWER;
- + writel_relaxed(val, pll->base);
- +
- + return 0;
- + }
- if (rate == parent_rate * 22)
- div = 1;
- else if (rate == parent_rate * 20)
- @@ -167,8 +202,6 @@
- }
-
- static const struct clk_ops clk_pllv3_ops = {
- - .prepare = clk_pllv3_prepare,
- - .unprepare = clk_pllv3_unprepare,
- .enable = clk_pllv3_enable,
- .disable = clk_pllv3_disable,
- .recalc_rate = clk_pllv3_recalc_rate,
- @@ -181,6 +214,10 @@
- {
- struct clk_pllv3 *pll = to_clk_pllv3(hw);
- u32 div = readl_relaxed(pll->base) & pll->div_mask;
- + u32 bypass = readl_relaxed(pll->base) & BYPASS_MASK;
- +
- + if (pll->rate_req == BYPASS_RATE && bypass)
- + return BYPASS_RATE;
-
- return parent_rate * div / 2;
- }
- @@ -193,6 +230,9 @@
- unsigned long max_rate = parent_rate * 108 / 2;
- u32 div;
-
- + if (rate == BYPASS_RATE)
- + return BYPASS_RATE;
- +
- if (rate > max_rate)
- rate = max_rate;
- else if (rate < min_rate)
- @@ -210,9 +250,26 @@
- unsigned long max_rate = parent_rate * 108 / 2;
- u32 val, div;
-
- - if (rate < min_rate || rate > max_rate)
- + if (rate != BYPASS_RATE && (rate < min_rate || rate > max_rate))
- return -EINVAL;
-
- + pll->rate_req = rate;
- + val = readl_relaxed(pll->base);
- +
- + if (rate == BYPASS_RATE) {
- + /*
- + * Set the PLL in bypass mode if rate requested is
- + * BYPASS_RATE.
- + */
- + val |= BM_PLL_BYPASS;
- + /* Power down the PLL. */
- + if (pll->powerup_set)
- + val &= ~BM_PLL_POWER;
- + else
- + val |= BM_PLL_POWER;
- + writel_relaxed(val, pll->base);
- + return 0;
- + }
- div = rate * 2 / parent_rate;
- val = readl_relaxed(pll->base);
- val &= ~pll->div_mask;
- @@ -223,8 +280,6 @@
- }
-
- static const struct clk_ops clk_pllv3_sys_ops = {
- - .prepare = clk_pllv3_prepare,
- - .unprepare = clk_pllv3_unprepare,
- .enable = clk_pllv3_enable,
- .disable = clk_pllv3_disable,
- .recalc_rate = clk_pllv3_sys_recalc_rate,
- @@ -239,6 +294,10 @@
- u32 mfn = readl_relaxed(pll->base + PLL_NUM_OFFSET);
- u32 mfd = readl_relaxed(pll->base + PLL_DENOM_OFFSET);
- u32 div = readl_relaxed(pll->base) & pll->div_mask;
- + u32 bypass = readl_relaxed(pll->base) & BYPASS_MASK;
- +
- + if (pll->rate_req == BYPASS_RATE && bypass)
- + return BYPASS_RATE;
-
- return (parent_rate * div) + ((parent_rate / mfd) * mfn);
- }
- @@ -253,6 +312,9 @@
- u32 mfn, mfd = 1000000;
- s64 temp64;
-
- + if (rate == BYPASS_RATE)
- + return BYPASS_RATE;
- +
- if (rate > max_rate)
- rate = max_rate;
- else if (rate < min_rate)
- @@ -273,13 +335,36 @@
- struct clk_pllv3 *pll = to_clk_pllv3(hw);
- unsigned long min_rate = parent_rate * 27;
- unsigned long max_rate = parent_rate * 54;
- - u32 val, div;
- + u32 val, newval, div;
- u32 mfn, mfd = 1000000;
- s64 temp64;
- + int ret;
-
- - if (rate < min_rate || rate > max_rate)
- + if (rate != BYPASS_RATE && (rate < min_rate || rate > max_rate))
- return -EINVAL;
-
- + pll->rate_req = rate;
- + val = readl_relaxed(pll->base);
- +
- + if (rate == BYPASS_RATE) {
- + /*
- + * Set the PLL in bypass mode if rate requested is
- + * BYPASS_RATE.
- + */
- + /* Bypass the PLL */
- + val |= BM_PLL_BYPASS;
- + /* Power down the PLL. */
- + if (pll->powerup_set)
- + val &= ~BM_PLL_POWER;
- + else
- + val |= BM_PLL_POWER;
- + writel_relaxed(val, pll->base);
- + return 0;
- + }
- + /* Else clear the bypass bit. */
- + val &= ~BM_PLL_BYPASS;
- + writel_relaxed(val, pll->base);
- +
- div = rate / parent_rate;
- temp64 = (u64) (rate - div * parent_rate);
- temp64 *= mfd;
- @@ -287,18 +372,30 @@
- mfn = temp64;
-
- val = readl_relaxed(pll->base);
- - val &= ~pll->div_mask;
- - val |= div;
- - writel_relaxed(val, pll->base);
- +
- + /* set the PLL into bypass mode */
- + newval = val | BM_PLL_BYPASS;
- + writel_relaxed(newval, pll->base);
- +
- + /* configure the new frequency */
- + newval &= ~pll->div_mask;
- + newval |= div;
- + writel_relaxed(newval, pll->base);
- writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET);
- - writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET);
- + writel(mfd, pll->base + PLL_DENOM_OFFSET);
-
- - return clk_pllv3_wait_lock(pll);
- + ret = clk_pllv3_wait_lock(pll);
- + if (ret == 0 && val & BM_PLL_POWER) {
- + /* only if it locked can we switch back to the PLL */
- + newval &= ~BM_PLL_BYPASS;
- + newval |= val & BM_PLL_BYPASS;
- + writel(newval, pll->base);
- + }
- +
- + return ret;
- }
-
- static const struct clk_ops clk_pllv3_av_ops = {
- - .prepare = clk_pllv3_prepare,
- - .unprepare = clk_pllv3_unprepare,
- .enable = clk_pllv3_enable,
- .disable = clk_pllv3_disable,
- .recalc_rate = clk_pllv3_av_recalc_rate,
- @@ -313,8 +410,6 @@
- }
-
- static const struct clk_ops clk_pllv3_enet_ops = {
- - .prepare = clk_pllv3_prepare,
- - .unprepare = clk_pllv3_unprepare,
- .enable = clk_pllv3_enable,
- .disable = clk_pllv3_disable,
- .recalc_rate = clk_pllv3_enet_recalc_rate,
- @@ -322,7 +417,7 @@
-
- struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
- const char *parent_name, void __iomem *base,
- - u32 div_mask)
- + u32 div_mask, bool always_on)
- {
- struct clk_pllv3 *pll;
- const struct clk_ops *ops;
- @@ -352,6 +447,7 @@
- }
- pll->base = base;
- pll->div_mask = div_mask;
- + pll->always_on = always_on;
-
- init.name = name;
- init.ops = ops;
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/common.h linux-3.14.35/arch/arm/mach-imx/common.h
- --- linux-3.14.35.orig/arch/arm/mach-imx/common.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/common.h 2015-03-08 14:27:37.417684503 -0500
- @@ -1,5 +1,5 @@
- /*
- - * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
- /*
- @@ -116,7 +116,6 @@
- void imx_set_cpu_jump(int cpu, void *jump_addr);
- u32 imx_get_cpu_arg(int cpu);
- void imx_set_cpu_arg(int cpu, u32 arg);
- -void v7_cpu_resume(void);
- #ifdef CONFIG_SMP
- void v7_secondary_startup(void);
- void imx_scu_map_io(void);
- @@ -129,7 +128,7 @@
- #endif
- void imx_src_init(void);
- void imx_gpc_init(void);
- -void imx_gpc_pre_suspend(void);
- +void imx_gpc_pre_suspend(bool arm_power_off);
- void imx_gpc_post_resume(void);
- void imx_gpc_mask_all(void);
- void imx_gpc_restore_all(void);
- @@ -138,14 +137,28 @@
- void imx_anatop_init(void);
- void imx_anatop_pre_suspend(void);
- void imx_anatop_post_resume(void);
- +void imx_anatop_pu_enable(bool enable);
- int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
- -void imx6q_set_chicken_bit(void);
- +void imx6q_set_cache_lpm_in_wait(bool enable);
- +void imx6sl_set_wait_clk(bool enter);
- +void imx6_enet_mac_init(const char *compatible);
-
- void imx_cpu_die(unsigned int cpu);
- int imx_cpu_kill(unsigned int cpu);
-
- +#ifdef CONFIG_SUSPEND
- +void v7_cpu_resume(void);
- +void imx6_suspend(void __iomem *ocram_vbase);
- +#else
- +static inline void v7_cpu_resume(void) {}
- +static inline void imx6_suspend(void __iomem *ocram_vbase) {}
- +#endif
- +
- void imx6q_pm_init(void);
- +void imx6dl_pm_init(void);
- +void imx6sl_pm_init(void);
- void imx6q_pm_set_ccm_base(void __iomem *base);
- +
- #ifdef CONFIG_PM
- void imx5_pm_init(void);
- #else
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/cpuidle.h linux-3.14.35/arch/arm/mach-imx/cpuidle.h
- --- linux-3.14.35.orig/arch/arm/mach-imx/cpuidle.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/cpuidle.h 2015-03-08 14:27:37.417684503 -0500
- @@ -1,5 +1,5 @@
- /*
- - * Copyright 2012 Freescale Semiconductor, Inc.
- + * Copyright 2012-2013 Freescale Semiconductor, Inc.
- * Copyright 2012 Linaro Ltd.
- *
- * The code contained herein is licensed under the GNU General Public
- @@ -13,6 +13,7 @@
- #ifdef CONFIG_CPU_IDLE
- extern int imx5_cpuidle_init(void);
- extern int imx6q_cpuidle_init(void);
- +extern int imx6sl_cpuidle_init(void);
- #else
- static inline int imx5_cpuidle_init(void)
- {
- @@ -22,4 +23,8 @@
- {
- return 0;
- }
- +static inline int imx6sl_cpuidle_init(void)
- +{
- + return 0;
- +}
- #endif
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/cpuidle-imx6q.c linux-3.14.35/arch/arm/mach-imx/cpuidle-imx6q.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/cpuidle-imx6q.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/cpuidle-imx6q.c 2015-03-08 14:27:37.417684503 -0500
- @@ -1,5 +1,5 @@
- /*
- - * Copyright (C) 2012 Freescale Semiconductor, Inc.
- + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- @@ -68,8 +68,8 @@
- /* Need to enable SCU standby for entering WAIT modes */
- imx_scu_standby_enable();
-
- - /* Set chicken bit to get a reliable WAIT mode support */
- - imx6q_set_chicken_bit();
- + /* Set cache lpm bit for reliable WAIT mode support */
- + imx6q_set_cache_lpm_in_wait(true);
-
- return cpuidle_register(&imx6q_cpuidle_driver, NULL);
- }
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/cpuidle-imx6sl.c linux-3.14.35/arch/arm/mach-imx/cpuidle-imx6sl.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/cpuidle-imx6sl.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/cpuidle-imx6sl.c 2015-03-08 14:27:37.417684503 -0500
- @@ -0,0 +1,149 @@
- +/*
- + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc.
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <linux/cpuidle.h>
- +#include <linux/genalloc.h>
- +#include <linux/module.h>
- +#include <linux/of.h>
- +#include <linux/of_address.h>
- +#include <linux/of_device.h>
- +#include <asm/cpuidle.h>
- +#include <asm/fncpy.h>
- +#include <asm/mach/map.h>
- +#include <asm/proc-fns.h>
- +#include <asm/tlb.h>
- +
- +#include "common.h"
- +#include "cpuidle.h"
- +
- +extern u32 audio_bus_freq_mode;
- +extern u32 ultra_low_bus_freq_mode;
- +extern unsigned long reg_addrs[];
- +extern void imx6sl_low_power_wfi(void);
- +
- +static void __iomem *iomux_base;
- +static void *wfi_iram_base;
- +
- +void (*imx6sl_wfi_in_iram_fn)(void *wfi_iram_base,
- + void *iomux_addr, void *regs_addr, u32 audio_mode) = NULL;
- +
- +#define WFI_IN_IRAM_SIZE 0x1000
- +
- +static int imx6sl_enter_wait(struct cpuidle_device *dev,
- + struct cpuidle_driver *drv, int index)
- +{
- + imx6q_set_lpm(WAIT_UNCLOCKED);
- +#ifdef CONFIG_ARM_IMX6_CPUFREQ
- + if (ultra_low_bus_freq_mode || audio_bus_freq_mode) {
- + /*
- + * Flush the TLB, to ensure no TLB maintenance occurs
- + * when DDR is in self-refresh.
- + */
- + local_flush_tlb_all();
- + /*
- + * Run WFI code from IRAM.
- + * Drop the DDR freq to 1MHz and AHB to 3MHz
- + * Also float DDR IO pads.
- + */
- + imx6sl_wfi_in_iram_fn(wfi_iram_base, iomux_base, reg_addrs, audio_bus_freq_mode);
- + }
- + else
- +#endif
- + {
- + imx6sl_set_wait_clk(true);
- + cpu_do_idle();
- + imx6sl_set_wait_clk(false);
- + }
- + imx6q_set_lpm(WAIT_CLOCKED);
- +
- + return index;
- +}
- +
- +static struct cpuidle_driver imx6sl_cpuidle_driver = {
- + .name = "imx6sl_cpuidle",
- + .owner = THIS_MODULE,
- + .states = {
- + /* WFI */
- + ARM_CPUIDLE_WFI_STATE,
- + /* WAIT */
- + {
- + .exit_latency = 50,
- + .target_residency = 75,
- + .flags = CPUIDLE_FLAG_TIME_VALID |
- + CPUIDLE_FLAG_TIMER_STOP,
- + .enter = imx6sl_enter_wait,
- + .name = "WAIT",
- + .desc = "Clock off",
- + },
- + },
- + .state_count = 2,
- + .safe_state_index = 0,
- +};
- +
- +int __init imx6sl_cpuidle_init(void)
- +{
- + struct platform_device *ocram_dev;
- + unsigned int iram_paddr;
- + struct device_node *node;
- + struct gen_pool *iram_pool;
- +
- + node = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-iomuxc");
- + if (!node) {
- + pr_err("failed to find imx6sl-iomuxc device tree data!\n");
- + return -EINVAL;
- + }
- + iomux_base = of_iomap(node, 0);
- + WARN(!iomux_base, "unable to map iomux registers\n");
- +
- + node = NULL;
- + node = of_find_compatible_node(NULL, NULL, "mmio-sram");
- + if (!node) {
- + pr_err("%s: failed to find ocram node\n",
- + __func__);
- + return -EINVAL;
- + }
- +
- + ocram_dev = of_find_device_by_node(node);
- + if (!ocram_dev) {
- + pr_err("failed to find ocram device!\n");
- + return -EINVAL;
- + }
- +
- + iram_pool = dev_get_gen_pool(&ocram_dev->dev);
- + if (!iram_pool) {
- + pr_err("iram pool unavailable!\n");
- + return -EINVAL;
- + }
- + /*
- + * Allocate IRAM memory when ARM executes WFI in
- + * ultra_low_power_mode.
- + */
- + wfi_iram_base = (void *)gen_pool_alloc(iram_pool,
- + WFI_IN_IRAM_SIZE);
- + if (!wfi_iram_base) {
- + pr_err("Cannot alloc iram for wfi code!\n");
- + return -ENOMEM;
- + }
- +
- + iram_paddr = gen_pool_virt_to_phys(iram_pool,
- + (unsigned long)wfi_iram_base);
- + /*
- + * Need to remap the area here since we want
- + * the memory region to be executable.
- + */
- + wfi_iram_base = __arm_ioremap(iram_paddr,
- + WFI_IN_IRAM_SIZE,
- + MT_MEMORY_RWX_NONCACHED);
- + if (!wfi_iram_base)
- + pr_err("wfi_ram_base NOT remapped\n");
- +
- + imx6sl_wfi_in_iram_fn = (void *)fncpy(wfi_iram_base,
- + &imx6sl_low_power_wfi, WFI_IN_IRAM_SIZE);
- +
- + return cpuidle_register(&imx6sl_cpuidle_driver, NULL);
- +}
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/ddr3_freq_imx6.S linux-3.14.35/arch/arm/mach-imx/ddr3_freq_imx6.S
- --- linux-3.14.35.orig/arch/arm/mach-imx/ddr3_freq_imx6.S 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/ddr3_freq_imx6.S 2015-03-08 14:27:37.417684503 -0500
- @@ -0,0 +1,893 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#include <linux/linkage.h>
- +
- +#define MMDC0_MDPDC 0x4
- +#define MMDC0_MDCF0 0x0c
- +#define MMDC0_MDCF1 0x10
- +#define MMDC0_MDMISC 0x18
- +#define MMDC0_MDSCR 0x1c
- +#define MMDC0_MAPSR 0x404
- +#define MMDC0_MADPCR0 0x410
- +#define MMDC0_MPZQHWCTRL 0x800
- +#define MMDC1_MPZQHWCTRL 0x4800
- +#define MMDC0_MPODTCTRL 0x818
- +#define MMDC1_MPODTCTRL 0x4818
- +#define MMDC0_MPDGCTRL0 0x83c
- +#define MMDC1_MPDGCTRL0 0x483c
- +#define MMDC0_MPMUR0 0x8b8
- +#define MMDC1_MPMUR0 0x48b8
- +
- +#define CCM_CBCDR 0x14
- +#define CCM_CBCMR 0x18
- +#define CCM_CSCMR1 0x1c
- +#define CCM_CDHIPR 0x48
- +
- +#define L2_CACHE_SYNC 0x730
- +
- + .align 3
- +
- + .macro switch_to_528MHz
- +
- + /* check if periph_clk_sel is already set */
- + ldr r0, [r6, #CCM_CBCDR]
- + and r0, r0, #(1 << 25)
- + cmp r0, #(1 << 25)
- + beq set_ahb_podf_before_switch
- +
- + /* change periph_clk to be sourced from pll3_clk. */
- + ldr r0, [r6, #CCM_CBCMR]
- + bic r0, r0, #(3 << 12)
- + str r0, [r6, #CCM_CBCMR]
- +
- + ldr r0, [r6, #CCM_CBCDR]
- + bic r0, r0, #(0x38 << 20)
- + str r0, [r6, #CCM_CBCDR]
- +
- + /*
- + * set the AHB dividers before the switch,
- + * don't change AXI clock divider,
- + * set the MMDC_DIV=1, AXI_DIV = 2, AHB_DIV=4,
- + */
- + ldr r0, [r6, #CCM_CBCDR]
- + ldr r2, =0x3f1f00
- + bic r0, r0, r2
- + orr r0, r0, #0xd00
- + orr r0, r0, #(1 << 16)
- + str r0, [r6, #CCM_CBCDR]
- +
- +wait_div_update528:
- + ldr r0, [r6, #CCM_CDHIPR]
- + cmp r0, #0
- + bne wait_div_update528
- +
- + /* now switch periph_clk to pll3_main_clk. */
- + ldr r0, [r6, #CCM_CBCDR]
- + orr r0, r0, #(1 << 25)
- + str r0, [r6, #CCM_CBCDR]
- +
- +periph_clk_switch3:
- + ldr r0, [r6, #CCM_CDHIPR]
- + cmp r0, #0
- + bne periph_clk_switch3
- +
- + b switch_pre_periph_clk_528
- +
- +set_ahb_podf_before_switch:
- + /*
- + * set the MMDC_DIV=1, AXI_DIV = 2, AHB_DIV=4,
- + */
- + ldr r0, [r6, #CCM_CBCDR]
- + ldr r2, =0x3f1f00
- + bic r0, r0, r2
- + orr r0, r0, #0xd00
- + orr r0, r0, #(1 << 16)
- + str r0, [r6, #CCM_CBCDR]
- +
- +wait_div_update528_1:
- + ldr r0, [r6, #CCM_CDHIPR]
- + cmp r0, #0
- + bne wait_div_update528_1
- +
- +switch_pre_periph_clk_528:
- +
- + /* now switch pre_periph_clk to PLL2_528MHz. */
- + ldr r0, [r6, #CCM_CBCMR]
- + bic r0, r0, #(0xc << 16)
- + str r0, [r6, #CCM_CBCMR]
- +
- + /* now switch periph_clk back. */
- + ldr r0, [r6, #CCM_CBCDR]
- + bic r0, r0, #(1 << 25)
- + str r0, [r6, #CCM_CBCDR]
- +
- +periph_clk_switch4:
- + ldr r0, [r6, #CCM_CDHIPR]
- + cmp r0, #0
- + bne periph_clk_switch4
- +
- + .endm
- +
- + .macro switch_to_400MHz
- +
- + /* check if periph_clk_sel is already set. */
- + ldr r0, [r6, #CCM_CBCDR]
- + and r0, r0, #(1 << 25)
- + cmp r0, #(1 << 25)
- + beq set_ahb_podf_before_switch1
- +
- + /* change periph_clk to be sourced from pll3_clk. */
- + ldr r0, [r6, #CCM_CBCMR]
- + bic r0, r0, #(3 << 12)
- + str r0, [r6, #CCM_CBCMR]
- +
- + ldr r0, [r6, #CCM_CBCDR]
- + bic r0, r0, #(0x38 << 24)
- + str r0, [r6, #CCM_CBCDR]
- +
- + /* now switch periph_clk to pll3_main_clk. */
- + ldr r0, [r6, #CCM_CBCDR]
- + orr r0, r0, #(1 << 25)
- + str r0, [r6, #CCM_CBCDR]
- +
- +periph_clk_switch5:
- + ldr r0, [r6, #CCM_CDHIPR]
- + cmp r0, #0
- + bne periph_clk_switch5
- +
- + b switch_pre_periph_clk_400
- +
- +set_ahb_podf_before_switch1:
- + /*
- + * set the MMDC_DIV=1, AXI_DIV = 2, AHB_DIV=4,
- + */
- + ldr r0, [r6, #CCM_CBCDR]
- + ldr r2, =0x3f1f00
- + bic r0, r0, r2
- + orr r0, r0, #(0x9 << 8)
- + orr r0, r0, #(1 << 16)
- + str r0, [r6, #CCM_CBCDR]
- +
- +wait_div_update400_1:
- + ldr r0, [r6, #CCM_CDHIPR]
- + cmp r0, #0
- + bne wait_div_update400_1
- +
- +switch_pre_periph_clk_400:
- +
- + /* now switch pre_periph_clk to PFD_400MHz. */
- + ldr r0, [r6, #CCM_CBCMR]
- + bic r0, r0, #(0xc << 16)
- + orr r0, r0, #(0x4 << 16)
- + str r0, [r6, #CCM_CBCMR]
- +
- + /* now switch periph_clk back. */
- + ldr r0, [r6, #CCM_CBCDR]
- + bic r0, r0, #(1 << 25)
- + str r0, [r6, #CCM_CBCDR]
- +
- +periph_clk_switch6:
- + ldr r0, [r6, #CCM_CDHIPR]
- + cmp r0, #0
- + bne periph_clk_switch6
- +
- + /*
- + * change AHB divider so that we are at 400/3=133MHz.
- + * don't change AXI clock divider.
- + * set the MMDC_DIV=1, AXI_DIV=2, AHB_DIV=3,
- + */
- + ldr r0, [r6, #CCM_CBCDR]
- + ldr r2, =0x3f1f00
- + bic r0, r0, r2
- + orr r0, r0, #(0x9 << 8)
- + orr r0, r0, #(1 << 16)
- + str r0, [r6, #CCM_CBCDR]
- +
- +wait_div_update400_2:
- + ldr r0, [r6, #CCM_CDHIPR]
- + cmp r0, #0
- + bne wait_div_update400_2
- +
- + .endm
- +
- + .macro switch_to_50MHz
- +
- + /* check if periph_clk_sel is already set. */
- + ldr r0, [r6, #CCM_CBCDR]
- + and r0, r0, #(1 << 25)
- + cmp r0, #(1 << 25)
- + beq switch_pre_periph_clk_50
- +
- + /*
- + * set the periph_clk to be sourced from PLL2_PFD_200M
- + * change periph_clk to be sourced from pll3_clk.
- + * ensure PLL3 is the source and set the divider to 1.
- + */
- + ldr r0, [r6, #CCM_CBCMR]
- + bic r0, r0, #(0x3 << 12)
- + str r0, [r6, #CCM_CBCMR]
- +
- + ldr r0, [r6, #CCM_CBCDR]
- + bic r0, r0, #(0x38 << 24)
- + str r0, [r6, #CCM_CBCDR]
- +
- + /* now switch periph_clk to pll3_main_clk. */
- + ldr r0, [r6, #CCM_CBCDR]
- + orr r0, r0, #(1 << 25)
- + str r0, [r6, #CCM_CBCDR]
- +
- +periph_clk_switch_50:
- + ldr r0, [r6, #CCM_CDHIPR]
- + cmp r0, #0
- + bne periph_clk_switch_50
- +
- +switch_pre_periph_clk_50:
- +
- + /* now switch pre_periph_clk to PFD_200MHz. */
- + ldr r0, [r6, #CCM_CBCMR]
- + orr r0, r0, #(0xc << 16)
- + str r0, [r6, #CCM_CBCMR]
- +
- + /*
- + * set the MMDC_DIV=4, AXI_DIV = 4, AHB_DIV=8,
- + */
- + ldr r0, [r6, #CCM_CBCDR]
- + ldr r2, =0x3f1f00
- + bic r0, r0, r2
- + orr r0, r0, #(0x18 << 16)
- + orr r0, r0, #(0x3 << 16)
- +
- + /*
- + * if changing AHB divider remember to change
- + * the IPGPER divider too below.
- + */
- + orr r0, r0, #0x1d00
- + str r0, [r6, #CCM_CBCDR]
- +
- +wait_div_update_50:
- + ldr r0, [r6, #CCM_CDHIPR]
- + cmp r0, #0
- + bne wait_div_update_50
- +
- + /* now switch periph_clk back. */
- + ldr r0, [r6, #CCM_CBCDR]
- + bic r0, r0, #(1 << 25)
- + str r0, [r6, #CCM_CBCDR]
- +
- +periph_clk_switch2:
- + ldr r0, [r6, #CCM_CDHIPR]
- + cmp r0, #0
- + bne periph_clk_switch2
- +
- + .endm
- +
- + .macro switch_to_24MHz
- + /*
- + * change the freq now try setting DDR to 24MHz.
- + * source it from the periph_clk2 ensure the
- + * periph_clk2 is sourced from 24MHz and the
- + * divider is 1.
- + */
- +
- + ldr r0, [r6, #CCM_CBCMR]
- + bic r0, r0, #(0x3 << 12)
- + orr r0, r0, #(1 << 12)
- + str r0, [r6, #CCM_CBCMR]
- +
- + ldr r0, [r6, #CCM_CBCDR]
- + bic r0, r0, #(0x38 << 24)
- + str r0, [r6, #CCM_CBCDR]
- +
- + /* now switch periph_clk to 24MHz. */
- + ldr r0, [r6, #CCM_CBCDR]
- + orr r0, r0, #(1 << 25)
- + str r0, [r6, #CCM_CBCDR]
- +
- +periph_clk_switch1:
- + ldr r0, [r6, #CCM_CDHIPR]
- + cmp r0, #0
- + bne periph_clk_switch1
- +
- + /* change all the dividers to 1. */
- + ldr r0, [r6, #CCM_CBCDR]
- + ldr r2, =0x3f1f00
- + bic r0, r0, r2
- + orr r0, r0, #(1 << 8)
- + str r0, [r6, #CCM_CBCDR]
- +
- + /* Wait for the divider to change. */
- +wait_div_update:
- + ldr r0, [r6, #CCM_CDHIPR]
- + cmp r0, #0
- + bne wait_div_update
- +
- + .endm
- +
- +/*
- + * mx6_ddr3_freq_change
- + *
- + * idle the processor (eg, wait for interrupt).
- + * make sure DDR is in self-refresh.
- + * IRQs are already disabled.
- + */
- +ENTRY(mx6_ddr3_freq_change)
- +
- + stmfd sp!, {r4-r12}
- +
- + /*
- + * r5 -> mmdc_base
- + * r6 -> ccm_base
- + * r7 -> iomux_base
- + * r12 -> l2_base
- + */
- + mov r4, r0
- + mov r8, r1
- + mov r9, r2
- + mov r11, r3
- +
- + /*
- + * Get the addresses of the registers.
- + * They are last few entries in the
- + * ddr_settings parameter.
- + * The first entry contains the count,
- + * and each entry is 2 words.
- + */
- + ldr r0, [r1]
- + add r0, r0, #1
- + lsl r0, r0, #3
- + add r1, r0, r1
- + /* mmdc_base. */
- + ldr r5, [r1]
- + add r1, #8
- + /* ccm_base */
- + ldr r6, [r1]
- + add r1, #8
- + /*iomux_base */
- + ldr r7, [r1]
- + add r1, #8
- + /*l2_base */
- + ldr r12, [r1]
- +
- +ddr_freq_change:
- + /*
- + * make sure no TLB miss will occur when
- + * the DDR is in self refresh. invalidate
- + * TLB single entry to ensure that the
- + * address is not already in the TLB.
- + */
- +
- + adr r10, ddr_freq_change
- +
- + ldr r2, [r6]
- + ldr r2, [r5]
- + ldr r2, [r7]
- + ldr r2, [r8]
- + ldr r2, [r10]
- + ldr r2, [r11]
- + ldr r2, [r12]
- +
- +#ifdef CONFIG_CACHE_L2X0
- + /*
- + * Make sure the L2 buffers are drained.
- + * Sync operation on L2 drains the buffers.
- + */
- + mov r1, #0x0
- + str r1, [r12, #L2_CACHE_SYNC]
- +#endif
- +
- + /* disable automatic power saving. */
- + ldr r0, [r5, #MMDC0_MAPSR]
- + orr r0, r0, #0x01
- + str r0, [r5, #MMDC0_MAPSR]
- +
- + /* disable MMDC power down timer. */
- + ldr r0, [r5, #MMDC0_MDPDC]
- + bic r0, r0, #(0xff << 8)
- + str r0, [r5, #MMDC0_MDPDC]
- +
- + /* delay for a while */
- + ldr r1, =4
- +delay1:
- + ldr r2, =0
- +cont1:
- + ldr r0, [r5, r2]
- + add r2, r2, #4
- + cmp r2, #16
- + bne cont1
- + sub r1, r1, #1
- + cmp r1, #0
- + bgt delay1
- +
- + /* set CON_REG */
- + ldr r0, =0x8000
- + str r0, [r5, #MMDC0_MDSCR]
- +poll_conreq_set_1:
- + ldr r0, [r5, #MMDC0_MDSCR]
- + and r0, r0, #(0x4 << 12)
- + cmp r0, #(0x4 << 12)
- + bne poll_conreq_set_1
- +
- + ldr r0, =0x00008010
- + str r0, [r5, #MMDC0_MDSCR]
- + ldr r0, =0x00008018
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + /*
- + * if requested frequency is greater than
- + * 300MHz go to DLL on mode.
- + */
- + ldr r1, =300000000
- + cmp r4, r1
- + bge dll_on_mode
- +
- +dll_off_mode:
- +
- + /* if DLL is currently on, turn it off. */
- + cmp r9, #1
- + beq continue_dll_off_1
- +
- + ldr r0, =0x00018031
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + ldr r0, =0x00018039
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + ldr r1, =10
- +delay1a:
- + ldr r2, =0
- +cont1a:
- + ldr r0, [r5, r2]
- + add r2, r2, #4
- + cmp r2, #16
- + bne cont1a
- + sub r1, r1, #1
- + cmp r1, #0
- + bgt delay1a
- +
- +continue_dll_off_1:
- + /* set DVFS - enter self refresh mode */
- + ldr r0, [r5, #MMDC0_MAPSR]
- + orr r0, r0, #(1 << 21)
- + str r0, [r5, #MMDC0_MAPSR]
- +
- + /* de-assert con_req */
- + mov r0, #0x0
- + str r0, [r5, #MMDC0_MDSCR]
- +
- +poll_dvfs_set_1:
- + ldr r0, [r5, #MMDC0_MAPSR]
- + and r0, r0, #(1 << 25)
- + cmp r0, #(1 << 25)
- + bne poll_dvfs_set_1
- +
- + ldr r1, =24000000
- + cmp r4, r1
- + beq switch_freq_24
- +
- + switch_to_50MHz
- + b continue_dll_off_2
- +
- +switch_freq_24:
- + switch_to_24MHz
- +
- +continue_dll_off_2:
- +
- + /* set SBS - block ddr accesses */
- + ldr r0, [r5, #MMDC0_MADPCR0]
- + orr r0, r0, #(1 << 8)
- + str r0, [r5, #MMDC0_MADPCR0]
- +
- + /* clear DVFS - exit from self refresh mode */
- + ldr r0, [r5, #MMDC0_MAPSR]
- + bic r0, r0, #(1 << 21)
- + str r0, [r5, #MMDC0_MAPSR]
- +
- +poll_dvfs_clear_1:
- + ldr r0, [r5, #MMDC0_MAPSR]
- + and r0, r0, #(1 << 25)
- + cmp r0, #(1 << 25)
- + beq poll_dvfs_clear_1
- +
- + /* if DLL was previously on, continue DLL off routine. */
- + cmp r9, #1
- + beq continue_dll_off_3
- +
- + ldr r0, =0x00018031
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + ldr r0, =0x00018039
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + ldr r0, =0x08208030
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + ldr r0, =0x08208038
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + ldr r0, =0x00088032
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + ldr r0, =0x0008803A
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + /* delay for a while. */
- + ldr r1, =4
- +delay_1:
- + ldr r2, =0
- +cont_1:
- + ldr r0, [r5, r2]
- + add r2, r2, #4
- + cmp r2, #16
- + bne cont_1
- + sub r1, r1, #1
- + cmp r1, #0
- + bgt delay_1
- +
- + ldr r0, [r5, #MMDC0_MDCF0]
- + bic r0, r0, #0xf
- + orr r0, r0, #0x3
- + str r0, [r5, #MMDC0_MDCF0]
- +
- + ldr r0, [r5, #MMDC0_MDCF1]
- + bic r0, r0, #0x7
- + orr r0, r0, #0x4
- + str r0, [r5, #MMDC0_MDCF1]
- +
- + ldr r0, =0x00091680
- + str r0, [r5, #MMDC0_MDMISC]
- +
- + /* enable dqs pull down in the IOMUX. */
- + ldr r1, [r11]
- + add r11, r11, #8
- + ldr r2, =0x3028
- +update_iomux:
- + ldr r0, [r11, #0x0]
- + ldr r3, [r7, r0]
- + bic r3, r3, r2
- + orr r3, r3, #(0x3 << 12)
- + orr r3, r3, #0x28
- + str r3, [r7, r0]
- + add r11, r11, #8
- + sub r1, r1, #1
- + cmp r1, #0
- + bgt update_iomux
- +
- + /* ODT disabled. */
- + ldr r0, =0x0
- + ldr r2, =MMDC0_MPODTCTRL
- + str r0, [r5, r2]
- + ldr r2, =MMDC1_MPODTCTRL
- + str r0, [r5, r2]
- +
- + /* DQS gating disabled. */
- + ldr r2, =MMDC0_MPDGCTRL0
- + ldr r0, [r5, r2]
- + orr r0, r0, #(1 << 29)
- + str r0, [r5, r2]
- +
- + ldr r2, =MMDC1_MPDGCTRL0
- + ldr r0, [r5, r2]
- + orr r0, r0, #(0x1 << 29)
- + str r0, [r5, r2]
- +
- + /* MMDC0_MAPSR adopt power down enable. */
- + ldr r0, [r5, #MMDC0_MAPSR]
- + bic r0, r0, #0x01
- + str r0, [r5, #MMDC0_MAPSR]
- +
- + /* frc_msr + mu bypass */
- + ldr r0, =0x00000060
- + str r0, [r5, #MMDC0_MPMUR0]
- + ldr r2, =MMDC1_MPMUR0
- + str r0, [r5, r2]
- + ldr r0, =0x00000460
- + str r0, [r5, #MMDC0_MPMUR0]
- + ldr r2, =MMDC1_MPMUR0
- + str r0, [r5, r2]
- + ldr r0, =0x00000c60
- + str r0, [r5, #MMDC0_MPMUR0]
- + ldr r2, =MMDC1_MPMUR0
- + str r0, [r5, r2]
- +
- +continue_dll_off_3:
- + /* clear SBS - unblock accesses to DDR. */
- + ldr r0, [r5, #MMDC0_MADPCR0]
- + bic r0, r0, #(0x1 << 8)
- + str r0, [r5, #MMDC0_MADPCR0]
- +
- + mov r0, #0x0
- + str r0, [r5, #MMDC0_MDSCR]
- +poll_conreq_clear_1:
- + ldr r0, [r5, #MMDC0_MDSCR]
- + and r0, r0, #(0x4 << 12)
- + cmp r0, #(0x4 << 12)
- + beq poll_conreq_clear_1
- +
- + b done
- +
- +dll_on_mode:
- + /* assert DVFS - enter self refresh mode. */
- + ldr r0, [r5, #MMDC0_MAPSR]
- + orr r0, r0, #(1 << 21)
- + str r0, [r5, #MMDC0_MAPSR]
- +
- + /* de-assert CON_REQ. */
- + mov r0, #0x0
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + /* poll DVFS ack. */
- +poll_dvfs_set_2:
- + ldr r0, [r5, #MMDC0_MAPSR]
- + and r0, r0, #(1 << 25)
- + cmp r0, #(1 << 25)
- + bne poll_dvfs_set_2
- +
- + ldr r1, =528000000
- + cmp r4, r1
- + beq switch_freq_528
- +
- + switch_to_400MHz
- +
- + b continue_dll_on
- +
- +switch_freq_528:
- + switch_to_528MHz
- +
- +continue_dll_on:
- +
- + /* set SBS step-by-step mode. */
- + ldr r0, [r5, #MMDC0_MADPCR0]
- + orr r0, r0, #( 1 << 8)
- + str r0, [r5, #MMDC0_MADPCR0]
- +
- + /* clear DVFS - exit self refresh mode. */
- + ldr r0, [r5, #MMDC0_MAPSR]
- + bic r0, r0, #(1 << 21)
- + str r0, [r5, #MMDC0_MAPSR]
- +
- +poll_dvfs_clear_2:
- + ldr r0, [r5, #MMDC0_MAPSR]
- + and r0, r0, #(1 << 25)
- + cmp r0, #(1 << 25)
- + beq poll_dvfs_clear_2
- +
- + /* if DLL is currently off, turn it back on. */
- + cmp r9, #0
- + beq update_calibration_only
- +
- + ldr r0, =0xa5390003
- + str r0, [r5, #MMDC0_MPZQHWCTRL]
- + ldr r2, =MMDC1_MPZQHWCTRL
- + str r0, [r5, r2]
- +
- + /* enable DQS gating. */
- + ldr r2, =MMDC0_MPDGCTRL0
- + ldr r0, [r5, r2]
- + bic r0, r0, #(1 << 29)
- + str r0, [r5, r2]
- +
- + ldr r2, =MMDC1_MPDGCTRL0
- + ldr r0, [r5, r2]
- + bic r0, r0, #(1 << 29)
- + str r0, [r5, r2]
- +
- + /* force measure. */
- + ldr r0, =0x00000800
- + str r0, [r5, #MMDC0_MPMUR0]
- + ldr r2, =MMDC1_MPMUR0
- + str r0, [r5, r2]
- +
- + /* delay for while. */
- + ldr r1, =4
- +delay5:
- + ldr r2, =0
- +cont5:
- + ldr r0, [r5, r2]
- + add r2, r2, #4
- + cmp r2, #16
- + bne cont5
- + sub r1, r1, #1
- + cmp r1, #0
- + bgt delay5
- +
- + /* disable dqs pull down in the IOMUX. */
- + ldr r1, [r11]
- + add r11, r11, #8
- +update_iomux1:
- + ldr r0, [r11, #0x0]
- + ldr r3, [r11, #0x4]
- + str r3, [r7, r0]
- + add r11, r11, #8
- + sub r1, r1, #1
- + cmp r1, #0
- + bgt update_iomux1
- +
- + /* config MMDC timings to 528MHz. */
- + ldr r9, [r8]
- + add r8, r8, #8
- + ldr r0, [r8, #0x0]
- + ldr r3, [r8, #0x4]
- + str r3, [r5, r0]
- + add r8, r8, #8
- +
- + ldr r0, [r8, #0x0]
- + ldr r3, [r8, #0x4]
- + str r3, [r5, r0]
- + add r8, r8, #8
- +
- + /* update MISC register: WALAT, RALAT */
- + ldr r0, =0x00081740
- + str r0, [r5, #MMDC0_MDMISC]
- +
- + /* configure ddr devices to dll on, odt. */
- + ldr r0, =0x00028031
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + ldr r0, =0x00028039
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + /* delay for while. */
- + ldr r1, =4
- +delay7:
- + ldr r2, =0
- +cont7:
- + ldr r0, [r5, r2]
- + add r2, r2, #4
- + cmp r2, #16
- + bne cont7
- + sub r1, r1, #1
- + cmp r1, #0
- + bgt delay7
- +
- + /* reset dll. */
- + ldr r0, =0x09208030
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + ldr r0, =0x09208038
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + /* delay for while. */
- + ldr r1, =100
- +delay8:
- + ldr r2, =0
- +cont8:
- + ldr r0, [r5, r2]
- + add r2, r2, #4
- + cmp r2, #16
- + bne cont8
- + sub r1, r1, #1
- + cmp r1, #0
- + bgt delay8
- +
- + ldr r0, [r8, #0x0]
- + ldr r3, [r8, #0x4]
- + str r3, [r5, r0]
- + add r8, r8, #8
- +
- + ldr r0, [r8, #0x0]
- + ldr r3, [r8, #0x4]
- + str r3, [r5, r0]
- + add r8, r8, #8
- +
- + ldr r0, =0x00428031
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + ldr r0, =0x00428039
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + ldr r0, [r8, #0x0]
- + ldr r3, [r8, #0x4]
- + str r3, [r5, r0]
- + add r8, r8, #8
- +
- + ldr r0, [r8, #0x0]
- + ldr r3, [r8, #0x4]
- + str r3, [r5, r0]
- + add r8, r8, #8
- +
- + /* issue a zq command. */
- + ldr r0, =0x04008040
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + ldr r0, =0x04008048
- + str r0, [r5, #MMDC0_MDSCR]
- +
- + /* MMDC ODT enable. */
- + ldr r0, [r8, #0x0]
- + ldr r3, [r8, #0x4]
- + str r3, [r5, r0]
- + add r8, r8, #8
- +
- + ldr r2, =0x4818
- + str r0, [r5, r2]
- +
- + /* delay for while. */
- + ldr r1, =40
- +delay15:
- + ldr r2, =0
- +cont15:
- + ldr r0, [r5, r2]
- + add r2, r2, #4
- + cmp r2, #16
- + bne cont15
- + sub r1, r1, #1
- + cmp r1, #0
- + bgt delay15
- +
- + /* MMDC0_MAPSR adopt power down enable. */
- + ldr r0, [r5, #MMDC0_MAPSR]
- + bic r0, r0, #0x01
- + str r0, [r5, #MMDC0_MAPSR]
- +
- + /* enable MMDC power down timer. */
- + ldr r0, [r5, #MMDC0_MDPDC]
- + orr r0, r0, #(0x55 << 8)
- + str r0, [r5, #MMDC0_MDPDC]
- +
- + b update_calibration
- +
- +update_calibration_only:
- + ldr r1, [r8]
- + sub r1, r1, #7
- + add r8, r8, #64
- + b update_calib
- +
- +update_calibration:
- + /* write the new calibration values. */
- + mov r1, r9
- + sub r1, r1, #7
- +
- +update_calib:
- + ldr r0, [r8, #0x0]
- + ldr r3, [r8, #0x4]
- + str r3, [r5, r0]
- + add r8, r8, #8
- + sub r1, r1, #1
- + cmp r1, #0
- + bgt update_calib
- +
- + /* perform a force measurement. */
- + ldr r0, =0x800
- + str r0, [r5, #MMDC0_MPMUR0]
- + ldr r2, =MMDC1_MPMUR0
- + str r0, [r5, r2]
- +
- + /* clear SBS - unblock DDR accesses. */
- + ldr r0, [r5, #MMDC0_MADPCR0]
- + bic r0, r0, #(1 << 8)
- + str r0, [r5, #MMDC0_MADPCR0]
- +
- + mov r0, #0x0
- + str r0, [r5, #MMDC0_MDSCR]
- +poll_conreq_clear_2:
- + ldr r0, [r5, #MMDC0_MDSCR]
- + and r0, r0, #(0x4 << 12)
- + cmp r0, #(0x4 << 12)
- + beq poll_conreq_clear_2
- +
- +done:
- + /* restore registers */
- +
- + ldmfd sp!, {r4-r12}
- + mov pc, lr
- +
- + .type mx6_do_ddr3_freq_change, #object
- +ENTRY(mx6_do_ddr_freq_change)
- + .word mx6_ddr3_freq_change
- + .size mx6_ddr3_freq_change, . - mx6_ddr3_freq_change
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/gpc.c linux-3.14.35/arch/arm/mach-imx/gpc.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/gpc.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/gpc.c 2015-03-08 14:27:37.417684503 -0500
- @@ -10,30 +10,69 @@
- * http://www.gnu.org/copyleft/gpl.html
- */
-
- +#include <linux/clk.h>
- +#include <linux/delay.h>
- #include <linux/io.h>
- #include <linux/irq.h>
- +#include <linux/module.h>
- #include <linux/of.h>
- #include <linux/of_address.h>
- #include <linux/of_irq.h>
- +#include <linux/platform_device.h>
- #include <linux/irqchip/arm-gic.h>
- +#include <linux/regulator/consumer.h>
- +#include <linux/regulator/driver.h>
- +#include <linux/regulator/machine.h>
- #include "common.h"
- +#include "hardware.h"
-
- #define GPC_IMR1 0x008
- #define GPC_PGC_CPU_PDN 0x2a0
- +#define GPC_PGC_GPU_PDN 0x260
- +#define GPC_PGC_GPU_PUPSCR 0x264
- +#define GPC_PGC_GPU_PDNSCR 0x268
- +#define GPC_PGC_GPU_SW_SHIFT 0
- +#define GPC_PGC_GPU_SW_MASK 0x3f
- +#define GPC_PGC_GPU_SW2ISO_SHIFT 8
- +#define GPC_PGC_GPU_SW2ISO_MASK 0x3f
- +#define GPC_PGC_CPU_PUPSCR 0x2a4
- +#define GPC_PGC_CPU_PDNSCR 0x2a8
- +#define GPC_PGC_CPU_SW_SHIFT 0
- +#define GPC_PGC_CPU_SW_MASK 0x3f
- +#define GPC_PGC_CPU_SW2ISO_SHIFT 8
- +#define GPC_PGC_CPU_SW2ISO_MASK 0x3f
- +#define GPC_CNTR 0x0
- +#define GPC_CNTR_PU_UP_REQ_SHIFT 0x1
- +#define GPC_CNTR_PU_DOWN_REQ_SHIFT 0x0
-
- #define IMR_NUM 4
-
- static void __iomem *gpc_base;
- static u32 gpc_wake_irqs[IMR_NUM];
- static u32 gpc_saved_imrs[IMR_NUM];
- +static struct clk *gpu3d_clk, *gpu3d_shader_clk, *gpu2d_clk, *gpu2d_axi_clk;
- +static struct clk *openvg_axi_clk, *vpu_clk, *ipg_clk;
- +static struct device *gpc_dev;
- +struct regulator *pu_reg;
- +struct notifier_block nb;
- +static struct regulator_dev *pu_dummy_regulator_rdev;
- +static struct regulator_init_data pu_dummy_initdata = {
- + .constraints = {
- + .max_uV = 1450000, /* allign with real max of anatop */
- + .valid_ops_mask = REGULATOR_CHANGE_STATUS |
- + REGULATOR_CHANGE_VOLTAGE,
- + },
- +};
- +static int pu_dummy_enable;
-
- -void imx_gpc_pre_suspend(void)
- +void imx_gpc_pre_suspend(bool arm_power_off)
- {
- void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
- int i;
-
- - /* Tell GPC to power off ARM core when suspend */
- - writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
- + if (arm_power_off)
- + /* Tell GPC to power off ARM core when suspend */
- + writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
-
- for (i = 0; i < IMR_NUM; i++) {
- gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
- @@ -120,10 +159,119 @@
- writel_relaxed(val, reg);
- }
-
- +static void imx_pu_clk(bool enable)
- +{
- + if (enable) {
- + if (cpu_is_imx6sl()) {
- + clk_prepare_enable(gpu2d_clk);
- + clk_prepare_enable(openvg_axi_clk);
- + } else {
- + clk_prepare_enable(vpu_clk);
- + clk_prepare_enable(gpu3d_clk);
- + clk_prepare_enable(gpu3d_shader_clk);
- + clk_prepare_enable(gpu2d_clk);
- + clk_prepare_enable(gpu2d_axi_clk);
- + clk_prepare_enable(openvg_axi_clk);
- + }
- + } else {
- + if (cpu_is_imx6sl()) {
- + clk_disable_unprepare(gpu2d_clk);
- + clk_disable_unprepare(openvg_axi_clk);
- + } else {
- + clk_disable_unprepare(openvg_axi_clk);
- + clk_disable_unprepare(gpu2d_axi_clk);
- + clk_disable_unprepare(gpu2d_clk);
- + clk_disable_unprepare(gpu3d_shader_clk);
- + clk_disable_unprepare(gpu3d_clk);
- + clk_disable_unprepare(vpu_clk);
- + }
- + }
- +}
- +
- +static void imx_gpc_pu_enable(bool enable)
- +{
- + u32 rate, delay_us;
- + u32 gpu_pupscr_sw2iso, gpu_pdnscr_iso2sw;
- + u32 gpu_pupscr_sw, gpu_pdnscr_iso;
- +
- + /* get ipg clk rate for PGC delay */
- + rate = clk_get_rate(ipg_clk);
- +
- + if (enable) {
- + imx_anatop_pu_enable(true);
- + /*
- + * need to add necessary delay between powering up PU LDO and
- + * disabling PU isolation in PGC, the counter of PU isolation
- + * is based on ipg clk.
- + */
- + gpu_pupscr_sw2iso = (readl_relaxed(gpc_base +
- + GPC_PGC_GPU_PUPSCR) >> GPC_PGC_GPU_SW2ISO_SHIFT)
- + & GPC_PGC_GPU_SW2ISO_MASK;
- + gpu_pupscr_sw = (readl_relaxed(gpc_base +
- + GPC_PGC_GPU_PUPSCR) >> GPC_PGC_GPU_SW_SHIFT)
- + & GPC_PGC_GPU_SW_MASK;
- + delay_us = (gpu_pupscr_sw2iso + gpu_pupscr_sw) * 1000000
- + / rate + 1;
- + udelay(delay_us);
- +
- + imx_pu_clk(true);
- + writel_relaxed(1, gpc_base + GPC_PGC_GPU_PDN);
- + writel_relaxed(1 << GPC_CNTR_PU_UP_REQ_SHIFT,
- + gpc_base + GPC_CNTR);
- + while (readl_relaxed(gpc_base + GPC_CNTR) &
- + (1 << GPC_CNTR_PU_UP_REQ_SHIFT))
- + ;
- + imx_pu_clk(false);
- + } else {
- + writel_relaxed(1, gpc_base + GPC_PGC_GPU_PDN);
- + writel_relaxed(1 << GPC_CNTR_PU_DOWN_REQ_SHIFT,
- + gpc_base + GPC_CNTR);
- + while (readl_relaxed(gpc_base + GPC_CNTR) &
- + (1 << GPC_CNTR_PU_DOWN_REQ_SHIFT))
- + ;
- + /*
- + * need to add necessary delay between enabling PU isolation
- + * in PGC and powering down PU LDO , the counter of PU isolation
- + * is based on ipg clk.
- + */
- + gpu_pdnscr_iso2sw = (readl_relaxed(gpc_base +
- + GPC_PGC_GPU_PDNSCR) >> GPC_PGC_GPU_SW2ISO_SHIFT)
- + & GPC_PGC_GPU_SW2ISO_MASK;
- + gpu_pdnscr_iso = (readl_relaxed(gpc_base +
- + GPC_PGC_GPU_PDNSCR) >> GPC_PGC_GPU_SW_SHIFT)
- + & GPC_PGC_GPU_SW_MASK;
- + delay_us = (gpu_pdnscr_iso2sw + gpu_pdnscr_iso) * 1000000
- + / rate + 1;
- + udelay(delay_us);
- + imx_anatop_pu_enable(false);
- + }
- +}
- +
- +static int imx_gpc_regulator_notify(struct notifier_block *nb,
- + unsigned long event,
- + void *ignored)
- +{
- + switch (event) {
- + case REGULATOR_EVENT_PRE_DISABLE:
- + imx_gpc_pu_enable(false);
- + break;
- + case REGULATOR_EVENT_ENABLE:
- + imx_gpc_pu_enable(true);
- + break;
- + default:
- + break;
- + }
- +
- + return NOTIFY_OK;
- +}
- +
- void __init imx_gpc_init(void)
- {
- struct device_node *np;
- int i;
- + u32 val;
- + u32 cpu_pupscr_sw2iso, cpu_pupscr_sw;
- + u32 cpu_pdnscr_iso2sw, cpu_pdnscr_iso;
-
- np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
- gpc_base = of_iomap(np, 0);
- @@ -137,4 +285,190 @@
- gic_arch_extn.irq_mask = imx_gpc_irq_mask;
- gic_arch_extn.irq_unmask = imx_gpc_irq_unmask;
- gic_arch_extn.irq_set_wake = imx_gpc_irq_set_wake;
- +
- + /*
- + * If there are CPU isolation timing settings in dts,
- + * update them according to dts, otherwise, keep them
- + * with default value in registers.
- + */
- + cpu_pupscr_sw2iso = cpu_pupscr_sw =
- + cpu_pdnscr_iso2sw = cpu_pdnscr_iso = 0;
- +
- + /* Read CPU isolation setting for GPC */
- + of_property_read_u32(np, "fsl,cpu_pupscr_sw2iso", &cpu_pupscr_sw2iso);
- + of_property_read_u32(np, "fsl,cpu_pupscr_sw", &cpu_pupscr_sw);
- + of_property_read_u32(np, "fsl,cpu_pdnscr_iso2sw", &cpu_pdnscr_iso2sw);
- + of_property_read_u32(np, "fsl,cpu_pdnscr_iso", &cpu_pdnscr_iso);
- +
- + /* Update CPU PUPSCR timing if it is defined in dts */
- + val = readl_relaxed(gpc_base + GPC_PGC_CPU_PUPSCR);
- + if (cpu_pupscr_sw2iso)
- + val &= ~(GPC_PGC_CPU_SW2ISO_MASK << GPC_PGC_CPU_SW2ISO_SHIFT);
- + if (cpu_pupscr_sw)
- + val &= ~(GPC_PGC_CPU_SW_MASK << GPC_PGC_CPU_SW_SHIFT);
- + val |= cpu_pupscr_sw2iso << GPC_PGC_CPU_SW2ISO_SHIFT;
- + val |= cpu_pupscr_sw << GPC_PGC_CPU_SW_SHIFT;
- + writel_relaxed(val, gpc_base + GPC_PGC_CPU_PUPSCR);
- +
- + /* Update CPU PDNSCR timing if it is defined in dts */
- + val = readl_relaxed(gpc_base + GPC_PGC_CPU_PDNSCR);
- + if (cpu_pdnscr_iso2sw)
- + val &= ~(GPC_PGC_CPU_SW2ISO_MASK << GPC_PGC_CPU_SW2ISO_SHIFT);
- + if (cpu_pdnscr_iso)
- + val &= ~(GPC_PGC_CPU_SW_MASK << GPC_PGC_CPU_SW_SHIFT);
- + val |= cpu_pdnscr_iso2sw << GPC_PGC_CPU_SW2ISO_SHIFT;
- + val |= cpu_pdnscr_iso << GPC_PGC_CPU_SW_SHIFT;
- + writel_relaxed(val, gpc_base + GPC_PGC_CPU_PDNSCR);
- +}
- +
- +static int imx_pureg_set_voltage(struct regulator_dev *reg, int min_uV,
- + int max_uV, unsigned *selector)
- +{
- + return 0;
- +}
- +
- +static int imx_pureg_enable(struct regulator_dev *rdev)
- +{
- + pu_dummy_enable = 1;
- +
- + return 0;
- +}
- +
- +static int imx_pureg_disable(struct regulator_dev *rdev)
- +{
- + pu_dummy_enable = 0;
- +
- + return 0;
- }
- +
- +static int imx_pureg_is_enable(struct regulator_dev *rdev)
- +{
- + return pu_dummy_enable;
- +}
- +
- +static int imx_pureg_list_voltage(struct regulator_dev *rdev,
- + unsigned int selector)
- +{
- + return 0;
- +}
- +
- +static struct regulator_ops pu_dummy_ops = {
- + .set_voltage = imx_pureg_set_voltage,
- + .enable = imx_pureg_enable,
- + .disable = imx_pureg_disable,
- + .is_enabled = imx_pureg_is_enable,
- + .list_voltage = imx_pureg_list_voltage,
- +};
- +
- +static struct regulator_desc pu_dummy_desc = {
- + .name = "pureg-dummy",
- + .id = -1,
- + .type = REGULATOR_VOLTAGE,
- + .owner = THIS_MODULE,
- + .ops = &pu_dummy_ops,
- +};
- +
- +static int pu_dummy_probe(struct platform_device *pdev)
- +{
- + struct regulator_config config = { };
- + int ret;
- +
- + config.dev = &pdev->dev;
- + config.init_data = &pu_dummy_initdata;
- + config.of_node = pdev->dev.of_node;
- +
- + pu_dummy_regulator_rdev = regulator_register(&pu_dummy_desc, &config);
- + if (IS_ERR(pu_dummy_regulator_rdev)) {
- + ret = PTR_ERR(pu_dummy_regulator_rdev);
- + dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
- + return ret;
- + }
- +
- + return 0;
- +}
- +
- +static const struct of_device_id imx_pudummy_ids[] = {
- + { .compatible = "fsl,imx6-dummy-pureg" },
- +};
- +MODULE_DEVICE_TABLE(of, imx_pudummy_ids);
- +
- +static struct platform_driver pu_dummy_driver = {
- + .probe = pu_dummy_probe,
- + .driver = {
- + .name = "pu-dummy",
- + .owner = THIS_MODULE,
- + .of_match_table = imx_pudummy_ids,
- + },
- +};
- +
- +static int imx_gpc_probe(struct platform_device *pdev)
- +{
- + int ret;
- +
- + gpc_dev = &pdev->dev;
- +
- + pu_reg = devm_regulator_get(gpc_dev, "pu");
- + if (IS_ERR(pu_reg)) {
- + ret = PTR_ERR(pu_reg);
- + dev_info(gpc_dev, "pu regulator not ready.\n");
- + return ret;
- + }
- + nb.notifier_call = &imx_gpc_regulator_notify;
- +
- + /* Get gpu&vpu clk for power up PU by GPC */
- + if (cpu_is_imx6sl()) {
- + gpu2d_clk = devm_clk_get(gpc_dev, "gpu2d_podf");
- + openvg_axi_clk = devm_clk_get(gpc_dev, "gpu2d_ovg");
- + ipg_clk = devm_clk_get(gpc_dev, "ipg");
- + if (IS_ERR(gpu2d_clk) || IS_ERR(openvg_axi_clk)
- + || IS_ERR(ipg_clk)) {
- + dev_err(gpc_dev, "failed to get clk!\n");
- + return -ENOENT;
- + }
- + } else {
- + gpu3d_clk = devm_clk_get(gpc_dev, "gpu3d_core");
- + gpu3d_shader_clk = devm_clk_get(gpc_dev, "gpu3d_shader");
- + gpu2d_clk = devm_clk_get(gpc_dev, "gpu2d_core");
- + gpu2d_axi_clk = devm_clk_get(gpc_dev, "gpu2d_axi");
- + openvg_axi_clk = devm_clk_get(gpc_dev, "openvg_axi");
- + vpu_clk = devm_clk_get(gpc_dev, "vpu_axi");
- + ipg_clk = devm_clk_get(gpc_dev, "ipg");
- + if (IS_ERR(gpu3d_clk) || IS_ERR(gpu3d_shader_clk)
- + || IS_ERR(gpu2d_clk) || IS_ERR(gpu2d_axi_clk)
- + || IS_ERR(openvg_axi_clk) || IS_ERR(vpu_clk)
- + || IS_ERR(ipg_clk)) {
- + dev_err(gpc_dev, "failed to get clk!\n");
- + return -ENOENT;
- + }
- + }
- +
- + ret = regulator_register_notifier(pu_reg, &nb);
- + if (ret) {
- + dev_err(gpc_dev,
- + "regulator notifier request failed\n");
- + return ret;
- + }
- +
- + return 0;
- +}
- +
- +static const struct of_device_id imx_gpc_ids[] = {
- + { .compatible = "fsl,imx6q-gpc" },
- +};
- +MODULE_DEVICE_TABLE(of, imx_gpc_ids);
- +
- +static struct platform_driver imx_gpc_platdrv = {
- + .driver = {
- + .name = "imx-gpc",
- + .owner = THIS_MODULE,
- + .of_match_table = imx_gpc_ids,
- + },
- + .probe = imx_gpc_probe,
- +};
- +module_platform_driver(imx_gpc_platdrv);
- +
- +module_platform_driver(pu_dummy_driver);
- +
- +MODULE_AUTHOR("Anson Huang <b20788@freescale.com>");
- +MODULE_DESCRIPTION("Freescale i.MX GPC driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/hardware.h linux-3.14.35/arch/arm/mach-imx/hardware.h
- --- linux-3.14.35.orig/arch/arm/mach-imx/hardware.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/hardware.h 2015-03-08 14:27:37.417684503 -0500
- @@ -1,5 +1,5 @@
- /*
- - * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- + * Copyright 2004-2007, 2014 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * This program is free software; you can redistribute it and/or
- @@ -20,7 +20,9 @@
- #ifndef __ASM_ARCH_MXC_HARDWARE_H__
- #define __ASM_ARCH_MXC_HARDWARE_H__
-
- +#ifndef __ASSEMBLY__
- #include <asm/io.h>
- +#endif
- #include <asm/sizes.h>
-
- #define addr_in_module(addr, mod) \
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/headsmp.S linux-3.14.35/arch/arm/mach-imx/headsmp.S
- --- linux-3.14.35.orig/arch/arm/mach-imx/headsmp.S 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/headsmp.S 2015-03-08 14:27:37.417684503 -0500
- @@ -12,8 +12,6 @@
-
- #include <linux/linkage.h>
- #include <linux/init.h>
- -#include <asm/asm-offsets.h>
- -#include <asm/hardware/cache-l2x0.h>
-
- .section ".text.head", "ax"
-
- @@ -35,37 +33,3 @@
- b secondary_startup
- ENDPROC(v7_secondary_startup)
- #endif
- -
- -#ifdef CONFIG_ARM_CPU_SUSPEND
- -/*
- - * The following code must assume it is running from physical address
- - * where absolute virtual addresses to the data section have to be
- - * turned into relative ones.
- - */
- -
- -#ifdef CONFIG_CACHE_L2X0
- - .macro pl310_resume
- - adr r0, l2x0_saved_regs_offset
- - ldr r2, [r0]
- - add r2, r2, r0
- - ldr r0, [r2, #L2X0_R_PHY_BASE] @ get physical base of l2x0
- - ldr r1, [r2, #L2X0_R_AUX_CTRL] @ get aux_ctrl value
- - str r1, [r0, #L2X0_AUX_CTRL] @ restore aux_ctrl
- - mov r1, #0x1
- - str r1, [r0, #L2X0_CTRL] @ re-enable L2
- - .endm
- -
- -l2x0_saved_regs_offset:
- - .word l2x0_saved_regs - .
- -
- -#else
- - .macro pl310_resume
- - .endm
- -#endif
- -
- -ENTRY(v7_cpu_resume)
- - bl v7_invalidate_l1
- - pl310_resume
- - b cpu_resume
- -ENDPROC(v7_cpu_resume)
- -#endif
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/imx6sl_wfi.S linux-3.14.35/arch/arm/mach-imx/imx6sl_wfi.S
- --- linux-3.14.35.orig/arch/arm/mach-imx/imx6sl_wfi.S 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/imx6sl_wfi.S 2015-03-08 14:27:37.417684503 -0500
- @@ -0,0 +1,639 @@
- +/*
- + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#include <linux/linkage.h>
- +#define IRAM_WAIT_SIZE (1 << 11)
- +
- + .macro sl_ddr_io_save
- +
- + ldr r4, [r1, #0x30c] /* DRAM_DQM0 */
- + ldr r5, [r1, #0x310] /* DRAM_DQM1 */
- + ldr r6, [r1, #0x314] /* DRAM_DQM2 */
- + ldr r7, [r1, #0x318] /* DRAM_DQM3 */
- + stmfd r9!, {r4-r7}
- +
- + ldr r4, [r1, #0x5c4] /* GPR_B0DS */
- + ldr r5, [r1, #0x5cc] /* GPR_B1DS */
- + ldr r6, [r1, #0x5d4] /* GPR_B2DS */
- + ldr r7, [r1, #0x5d8] /* GPR_B3DS */
- + stmfd r9!, {r4-r7}
- +
- + ldr r4, [r1, #0x300] /* DRAM_CAS */
- + ldr r5, [r1, #0x31c] /* DRAM_RAS */
- + ldr r6, [r1, #0x338] /* DRAM_SDCLK_0 */
- + ldr r7, [r1, #0x5ac] /* GPR_ADDS*/
- + stmfd r9!, {r4-r7}
- +
- + ldr r4, [r1, #0x5b0] /* DDRMODE_CTL */
- + ldr r5, [r1, #0x5c0] /* DDRMODE */
- + ldr r6, [r1, #0x33c] /* DRAM_SODT0*/
- + ldr r7, [r1, #0x340] /* DRAM_SODT1*/
- + stmfd r9!, {r4-r7}
- +
- + ldr r4, [r1, #0x330] /* DRAM_SDCKE0 */
- + ldr r5, [r1, #0x334] /* DRAM_SDCKE1 */
- + ldr r6, [r1, #0x320] /* DRAM_RESET */
- + stmfd r9!, {r4-r6}
- +
- + .endm
- +
- + .macro sl_ddr_io_restore
- +
- + /*
- + * r9 points to IRAM stack.
- + * r1 points to IOMUX base address.
- + * r8 points to MMDC base address.
- + */
- + ldmea r9!, {r4-r7}
- + str r4, [r1, #0x30c] /* DRAM_DQM0 */
- + str r5, [r1, #0x310] /* DRAM_DQM1 */
- + str r6, [r1, #0x314] /* DRAM_DQM2 */
- + str r7, [r1, #0x318] /* DRAM_DQM3 */
- +
- + ldmea r9!, {r4-r7}
- + str r4, [r1, #0x5c4] /* GPR_B0DS */
- + str r5, [r1, #0x5cc] /* GPR_B1DS */
- + str r6, [r1, #0x5d4] /* GPR_B2DS */
- + str r7, [r1, #0x5d8] /* GPR_B3DS */
- +
- + ldmea r9!, {r4-r7}
- + str r4, [r1, #0x300] /* DRAM_CAS */
- + str r5, [r1, #0x31c] /* DRAM_RAS */
- + str r6, [r1, #0x338] /* DRAM_SDCLK_0 */
- + str r7, [r1, #0x5ac] /* GPR_ADDS*/
- +
- + ldmea r9!, {r4-r7}
- + str r4, [r1, #0x5b0] /* DDRMODE_CTL */
- + str r5, [r1, #0x5c0] /* DDRMODE */
- + str r6, [r1, #0x33c] /* DRAM_SODT0*/
- + str r7, [r1, #0x340] /* DRAM_SODT1*/
- +
- + ldmea r9!, {r4-r6}
- + str r4, [r1, #0x330] /* DRAM_SDCKE0 */
- + str r5, [r1, #0x334] /* DRAM_SDCKE1 */
- + str r6, [r1, #0x320] /* DRAM_RESET */
- +
- + /*
- + * Need to reset the FIFO to avoid MMDC lockup
- + * caused because of floating/changing the
- + * configuration of many DDR IO pads.
- + */
- + ldr r7, =0x83c
- + ldr r6, [r8, r7]
- + orr r6, r6, #0x80000000
- + str r6, [r8, r7]
- +fifo_reset1_wait:
- + ldr r6, [r8, r7]
- + and r6, r6, #0x80000000
- + cmp r6, #0
- + bne fifo_reset1_wait
- +
- + /* reset FIFO a second time */
- + ldr r6, [r8, r7]
- + orr r6, r6, #0x80000000
- + str r6, [r8, r7]
- +fifo_reset2_wait:
- + ldr r6, [r8, r7]
- + and r6, r6, #0x80000000
- + cmp r6, #0
- + bne fifo_reset2_wait
- +
- + .endm
- +
- + .macro sl_ddr_io_set_lpm
- +
- + mov r4, #0
- + str r4, [r1, #0x30c] /* DRAM_DQM0 */
- + str r4, [r1, #0x310] /* DRAM_DQM1 */
- + str r4, [r1, #0x314] /* DRAM_DQM2 */
- + str r4, [r1, #0x318] /* DRAM_DQM3 */
- +
- + str r4, [r1, #0x5c4] /* GPR_B0DS */
- + str r4, [r1, #0x5cc] /* GPR_B1DS */
- + str r4, [r1, #0x5d4] /* GPR_B2DS */
- + str r4, [r1, #0x5d8] /* GPR_B3DS */
- +
- + str r4, [r1, #0x300] /* DRAM_CAS */
- + str r4, [r1, #0x31c] /* DRAM_RAS */
- + str r4, [r1, #0x338] /* DRAM_SDCLK_0 */
- + str r4, [r1, #0x5ac] /* GPR_ADDS*/
- +
- + str r4, [r1, #0x5b0] /* DDRMODE_CTL */
- + str r4, [r1, #0x5c0] /* DDRMODE */
- + str r4, [r1, #0x33c] /* DRAM_SODT0*/
- + str r4, [r1, #0x340] /* DRAM_SODT1*/
- +
- + mov r4, #0x80000
- + str r4, [r1, #0x320] /* DRAM_RESET */
- + mov r4, #0x1000
- + str r4, [r1, #0x330] /* DRAM_SDCKE0 */
- + str r4, [r1, #0x334] /* DRAM_SDCKE1 */
- +
- + .endm
- +
- +/*
- + * imx6sl_low_power_wfi
- + *
- + * Idle the processor (eg, wait for interrupt).
- + * Make sure DDR is in self-refresh.
- + * IRQs are already disabled.
- + * r0: WFI IRAMcode base address.
- + * r1: IOMUX base address
- + * r2: Base address of CCM, ANATOP and MMDC
- + * r3: 1 if in audio_bus_freq_mode
- + */
- + .align 3
- +ENTRY(imx6sl_low_power_wfi)
- +
- + push {r4-r11}
- +
- +mx6sl_lpm_wfi:
- + /* Store audio_bus_freq_mode */
- + mov r11, r3
- +
- + mov r4,r2
- + /* Get the IRAM data storage address. */
- + mov r10, r0
- + mov r9, r0 /* get suspend_iram_base */
- + add r9, r9, #IRAM_WAIT_SIZE
- +
- + /* Anatop Base address in r3. */
- + ldr r3, [r4]
- + /* CCM Base Address in r2 */
- + ldr r2, [r4, #0x4]
- + /* MMDC Base Address in r8 */
- + ldr r8, [r4, #0x8]
- + /* L2 Base Address in r7 */
- + ldr r7, [r4, #0xC]
- +
- + ldr r6, [r8]
- + ldr r6, [r3]
- + ldr r6, [r2]
- + ldr r6, [r1]
- +
- + /* Store the original ARM PODF. */
- + ldr r0, [r2, #0x10]
- +
- + /* Drain all the L1 buffers. */
- + dsb
- +
- +#ifdef CONFIG_CACHE_L2X0
- + /*
- + * Need to make sure the buffers in L2 are drained.
- + * Performing a sync operation does this.
- + */
- + mov r6, #0x0
- + str r6, [r7, #0x730]
- +#endif
- +
- + /*
- + * The second dsb might be needed to keep cache sync (device write)
- + * ordering with the memory accesses before it.
- + */
- + dsb
- + isb
- +
- + /* Save the DDR IO state. */
- + sl_ddr_io_save
- +
- + /* Disable Automatic power savings. */
- + ldr r6, [r8, #0x404]
- + orr r6, r6, #0x01
- + str r6, [r8, #0x404]
- +
- + /* Make the DDR explicitly enter self-refresh. */
- + ldr r6, [r8, #0x404]
- + orr r6, r6, #0x200000
- + str r6, [r8, #0x404]
- +
- +poll_dvfs_set_1:
- + ldr r6, [r8, #0x404]
- + and r6, r6, #0x2000000
- + cmp r6, #0x2000000
- + bne poll_dvfs_set_1
- +
- + /* set SBS step-by-step mode */
- + ldr r6, [r8, #0x410]
- + orr r6, r6, #0x100
- + str r6, [r8, #0x410]
- +
- + cmp r11, #1
- + beq audio_mode
- + /*
- + * Now set DDR rate to 1MHz.
- + * DDR is from bypassed PLL2 on periph2_clk2 path.
- + * Set the periph2_clk2_podf to divide by 8.
- + */
- + ldr r6, [r2, #0x14]
- + orr r6, r6, #0x07
- + str r6, [r2, #0x14]
- +
- + /* Now set MMDC PODF to divide by 3. */
- + ldr r6, [r2, #0x14]
- + bic r6, r6, #0x38
- + orr r6, r6, #0x10
- + str r6, [r2, #0x14]
- + b mmdc_podf
- +
- +audio_mode:
- + /* MMDC is from PLL2_200M.
- + * Set the mmdc_podf to div by 8.
- + */
- + ldr r6, [r2, #0x14]
- + orr r6, r6, #0x38
- + str r6, [r2, #0x14]
- +
- + /* Loop till podf is accepted. */
- +mmdc_podf:
- + ldr r6, [r2, #0x48]
- + cmp r6, #0x0
- + bne mmdc_podf
- +
- + /* Set the DDR IO in LPM state. */
- + sl_ddr_io_set_lpm
- +
- + cmp r11, #1
- + beq do_audio_arm_clk
- +
- + /*
- + * Check if none of the PLLs are
- + * locked, except PLL1 which will get
- + * bypassed below.
- + * We should not be here if PLL2 is not
- + * bypassed.
- + */
- + ldr r7, =1
- + /* USB1 PLL3 */
- + ldr r6, [r3, #0x10]
- + and r6, r6, #0x80000000
- + cmp r6, #0x80000000
- + beq no_analog_saving
- +
- + /* USB2 PLL7 */
- + ldr r6, [r3, #0x20]
- + and r6, r6, #0x80000000
- + cmp r6, #0x80000000
- + beq no_analog_saving
- +
- + /* Audio PLL4 */
- + ldr r6, [r3, #0x70]
- + and r6, r6, #0x80000000
- + cmp r6, #0x80000000
- + beq no_analog_saving
- +
- + /* Video PLL5 */
- + ldr r6, [r3, #0xA0]
- + and r6, r6, #0x80000000
- + cmp r6, #0x80000000
- + beq no_analog_saving
- +
- + /* ENET PLL8 */
- + ldr r6, [r3, #0xE0]
- + and r6, r6, #0x80000000
- + cmp r6, #0x80000000
- + beq no_analog_saving
- +
- + b cont
- +
- +no_analog_saving:
- + ldr r7, =0
- +
- +cont:
- + /* Set the AHB to 3MHz. AXI to 3MHz. */
- + ldr r9, [r2, #0x14]
- + mov r6, r9
- + orr r6, r6, #0x1c00
- + orr r6, r6, #0x70000
- + str r6, [r2, #0x14]
- +
- + /* Loop till podf is accepted. */
- +ahb_podf:
- + ldr r6, [r2, #0x48]
- + cmp r6, #0x0
- + bne podf_loop
- +
- + /*
- + * Now set ARM to 24MHz.
- + * Move ARM to be sourced from STEP_CLK
- + * after setting STEP_CLK to 24MHz.
- + */
- + ldr r6, [r2, #0xc]
- + bic r6, r6, #0x100
- + str r6, [r2, #0x0c]
- + /* Now PLL1_SW_CLK to step_clk. */
- + ldr r6, [r2, #0x0c]
- + orr r6, r6, #0x4
- + str r6, [r2, #0x0c]
- +
- + /* Bypass PLL1 and power it down. */
- + ldr r6, =(1 << 16)
- + orr r6, r6, #0x1000
- + str r6, [r3, #0x04]
- +
- + /*
- + * Set the ARM PODF to divide by 8.
- + * IPG is at 1.5MHz here, we need ARM to
- + * run at the 12:5 ratio (WAIT mode issue).
- + */
- + ldr r6, =0x7
- + str r6, [r2, #0x10]
- +
- + /* Loop till podf is accepted. */
- +podf_loop:
- + ldr r6, [r2, #0x48]
- + cmp r6, #0x0
- + bne podf_loop
- +
- + /*
- + * Check if we can save some
- + * power in the Analog section.
- + */
- + cmp r7, #0x1
- + bne do_wfi
- +
- + /* Disable 1p1 brown out. */
- + ldr r6, [r3, #0x110]
- + bic r6, r6, #0x2
- + str r6, [r3, #0x110]
- +
- + /* Enable the weak 2P5 */
- + ldr r6, [r3, #0x130]
- + orr r6, r6, #0x40000
- + str r6, [r3, #0x130]
- +
- + /* Disable main 2p5. */
- + ldr r6, [r3, #0x130]
- + bic r6, r6, #0x1
- + str r6, [r3, #0x130]
- +
- + /*
- + * Set the OSC bias current to -37.5%
- + * to drop the power on VDDHIGH.
- + */
- + ldr r6, [r3, #0x150]
- + orr r6, r6, #0xC000
- + str r6, [r3, #0x150]
- +
- + /* Enable low power bandgap */
- + ldr r6, [r3, #0x260]
- + orr r6, r6, #0x20
- + str r6, [r3, #0x260]
- +
- + /*
- + * Turn off the bias current
- + * from the regular bandgap.
- + */
- + ldr r6, [r3, #0x260]
- + orr r6, r6, #0x80
- + str r6, [r3, #0x260]
- +
- + /*
- + * Clear the REFTOP_SELFBIASOFF,
- + * self-bias circuit of the band gap.
- + * Per RM, should be cleared when
- + * band gap is powered down.
- + */
- + ldr r6, [r3, #0x150]
- + bic r6, r6, #0x8
- + str r6, [r3, #0x150]
- +
- + /* Power down the regular bandgap. */
- + ldr r6, [r3, #0x150]
- + orr r6, r6, #0x1
- + str r6, [r3, #0x150]
- +
- + b do_wfi
- +
- +do_audio_arm_clk:
- + /*
- + * ARM is from PLL2_PFD2_400M here.
- + * Switch ARM to bypassed PLL1.
- + */
- + ldr r6, [r2, #0xC]
- + bic r6, r6, #0x4
- + str r6, [r2, #0xC]
- +
- + /*
- + * Set the ARM_PODF to divide by 2
- + * as IPG is at 4MHz, we cannot run
- + * ARM_CLK above 9.6MHz when
- + * system enters WAIT mode.
- + */
- + ldr r6, =0x2
- + str r6, [r2, #0x10]
- +
- + /* Loop till podf is accepted. */
- +podf_loop_audio:
- + ldr r6, [r2, #0x48]
- + cmp r6, #0x0
- + bne podf_loop_audio
- +
- +do_wfi:
- + /* Now do WFI. */
- + wfi
- +
- + /* Set original ARM PODF back. */
- + str r0, [r2, #0x10]
- +
- + /* Loop till podf is accepted. */
- +podf_loop1:
- + ldr r6, [r2, #0x48]
- + cmp r6, #0x0
- + bne podf_loop1
- +
- + cmp r11, #1
- + beq audio_arm_clk_restore
- +
- + /*
- + * Check if powered down
- + * analog components.
- + */
- + cmp r7, #0x1
- + bne skip_analog_restore
- +
- + /* Power up the regular bandgap. */
- + ldr r6, [r3, #0x150]
- + bic r6, r6, #0x1
- + str r6, [r3, #0x150]
- +
- + /*
- + * Turn on the bias current
- + * from the regular bandgap.
- + */
- + ldr r6, [r3, #0x260]
- + bic r6, r6, #0x80
- + str r6, [r3, #0x260]
- +
- + /* Disable the low power bandgap */
- + ldr r6, [r3, #0x260]
- + bic r6, r6, #0x20
- + str r6, [r3, #0x260]
- +
- + /*
- + * Set the OSC bias current to max
- + * value for normal operation.
- + */
- + ldr r6, [r3, #0x150]
- + bic r6, r6, #0xC000
- + str r6, [r3, #0x150]
- +
- + /* Enable main 2p5. */
- + ldr r6, [r3, #0x130]
- + orr r6, r6, #0x1
- + str r6, [r3, #0x130]
- +
- + /* Ensure the 2P5 is up. */
- +loop_2p5:
- + ldr r6, [r3, #0x130]
- + and r6, r6, #0x20000
- + cmp r6, #0x20000
- + bne loop_2p5
- +
- + /* Disable the weak 2P5 */
- + ldr r6, [r3, #0x130]
- + bic r6, r6, #0x40000
- + str r6, [r3, #0x130]
- +
- + /* Enable 1p1 brown out. */
- + ldr r6, [r3, #0x110]
- + orr r6, r6, #0x2
- + str r6, [r3, #0x110]
- +
- +skip_analog_restore:
- +
- + /* Power up PLL1 and un-bypass it. */
- + ldr r6, =(1 << 12)
- + str r6, [r3, #0x08]
- +
- + /* Wait for PLL1 to relock. */
- +wait_for_pll_lock:
- + ldr r6, [r3, #0x0]
- + and r6, r6, #0x80000000
- + cmp r6, #0x80000000
- + bne wait_for_pll_lock
- +
- + ldr r6, =(1 << 16)
- + str r6, [r3, #0x08]
- +
- + /* Set PLL1_sw_clk back to PLL1. */
- + ldr r6, [r2, #0x0c]
- + bic r6, r6, #0x4
- + str r6, [r2, #0xc]
- +
- + /* Restore AHB/AXI back. */
- + str r9, [r2, #0x14]
- +
- + /* Loop till podf is accepted. */
- +ahb_podf1:
- + ldr r6, [r2, #0x48]
- + cmp r6, #0x0
- + bne podf_loop1
- +
- + b wfi_restore
- +
- + audio_arm_clk_restore:
- + /* Move ARM back to PLL2_PFD2_400M */
- + ldr r6, [r2, #0xC]
- + orr r6, r6, #0x4
- + str r6, [r2, #0xC]
- +
- +wfi_restore:
- + /* get suspend_iram_base */
- + mov r9, r10
- + add r9, r9, #IRAM_WAIT_SIZE
- +
- + /* Restore the DDR IO before exiting self-refresh. */
- + sl_ddr_io_restore
- +
- + /*
- + * Set MMDC back to 24MHz.
- + * Set periph2_clk2_podf to divide by 1
- + * Now set MMDC PODF to divide by 1.
- + */
- + ldr r6, [r2, #0x14]
- + bic r6, r6, #0x3f
- + str r6, [r2, #0x14]
- +
- +mmdc_podf1:
- + ldr r6, [r2, #0x48]
- + cmp r6, #0x0
- + bne mmdc_podf1
- +
- + /* clear DVFS - exit from self refresh mode */
- + ldr r6, [r8, #0x404]
- + bic r6, r6, #0x200000
- + str r6, [r8, #0x404]
- +
- +poll_dvfs_clear_1:
- + ldr r6, [r8, #0x404]
- + and r6, r6, #0x2000000
- + cmp r6, #0x2000000
- + beq poll_dvfs_clear_1
- +
- + /*
- + * Add these nops so that the
- + * prefetcher will not try to get
- + * any instructions from DDR.
- + * The prefetch depth is about 23
- + * on A9, so adding 25 nops.
- + */
- + nop
- + nop
- + nop
- + nop
- + nop
- +
- + nop
- + nop
- + nop
- + nop
- + nop
- +
- + nop
- + nop
- + nop
- + nop
- + nop
- +
- + nop
- + nop
- + nop
- + nop
- + nop
- +
- + nop
- + nop
- + nop
- + nop
- + nop
- +
- + /* Enable Automatic power savings. */
- + ldr r6, [r8, #0x404]
- + bic r6, r6, #0x01
- + str r6, [r8, #0x404]
- +
- + /* clear SBS - unblock DDR accesses */
- + ldr r6, [r8, #0x410]
- + bic r6, r6, #0x100
- + str r6, [r8, #0x410]
- +
- +
- + pop {r4-r11}
- +
- + /* Restore registers */
- + mov pc, lr
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/Kconfig linux-3.14.35/arch/arm/mach-imx/Kconfig
- --- linux-3.14.35.orig/arch/arm/mach-imx/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/Kconfig 2015-03-08 14:27:37.417684503 -0500
- @@ -1,5 +1,6 @@
- config ARCH_MXC
- bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7
- + select ARCH_HAS_RESET_CONTROLLER
- select ARCH_REQUIRE_GPIOLIB
- select ARM_CPU_SUSPEND if PM
- select ARM_PATCH_PHYS_VIRT
- @@ -13,6 +14,7 @@
- select PINCTRL
- select SOC_BUS
- select SPARSE_IRQ
- + select SRAM
- select USE_OF
- help
- Support for Freescale MXC/iMX-based family of processors
- @@ -63,7 +65,6 @@
-
- config HAVE_IMX_SRC
- def_bool y if SMP
- - select ARCH_HAS_RESET_CONTROLLER
-
- config IMX_HAVE_IOMUX_V1
- bool
- @@ -791,6 +792,8 @@
- select ARM_ERRATA_754322
- select ARM_ERRATA_764369 if SMP
- select ARM_ERRATA_775420
- + select ARM_ERRATA_794072 if SMP
- + select ARM_ERRATA_761320 if SMP
- select ARM_GIC
- select CPU_V7
- select HAVE_ARM_SCU if SMP
- @@ -803,11 +806,13 @@
- select MFD_SYSCON
- select MIGHT_HAVE_PCI
- select PCI_DOMAINS if PCI
- + select ARCH_SUPPORTS_MSI
- select PINCTRL_IMX6Q
- select PL310_ERRATA_588369 if CACHE_PL310
- select PL310_ERRATA_727915 if CACHE_PL310
- select PL310_ERRATA_769419 if CACHE_PL310
- select PM_OPP if PM
- + select ZONE_DMA
-
- help
- This enables support for Freescale i.MX6 Quad processor.
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/lpddr2_freq_imx6.S linux-3.14.35/arch/arm/mach-imx/lpddr2_freq_imx6.S
- --- linux-3.14.35.orig/arch/arm/mach-imx/lpddr2_freq_imx6.S 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/lpddr2_freq_imx6.S 2015-03-08 14:27:37.417684503 -0500
- @@ -0,0 +1,484 @@
- +/*
- + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#include <linux/linkage.h>
- +
- + .macro mx6sl_switch_to_24MHz
- +
- + /*
- + * Set MMDC clock to be sourced from PLL3.
- + * Ensure first periph2_clk2 is sourced from PLL3.
- + * Set the PERIPH2_CLK2_PODF to divide by 2.
- + */
- + ldr r6, [r2, #0x14]
- + bic r6, r6, #0x7
- + orr r6, r6, #0x1
- + str r6, [r2, #0x14]
- +
- + /* Select PLL3 to source MMDC. */
- + ldr r6, [r2, #0x18]
- + bic r6, r6, #0x100000
- + str r6, [r2, #0x18]
- +
- + /* Swtich periph2_clk_sel to run from PLL3. */
- + ldr r6, [r2, #0x14]
- + orr r6, r6, #0x4000000
- + str r6, [r2, #0x14]
- +
- +periph2_clk_switch1:
- + ldr r6, [r2, #0x48]
- + cmp r6, #0
- + bne periph2_clk_switch1
- +
- + /*
- + * Need to clock gate the 528 PFDs before
- + * powering down PLL2.
- + * Only the PLL2_PFD2_400M should be ON
- + * at this time, so only clock gate that one.
- + */
- + ldr r6, [r3, #0x100]
- + orr r6, r6, #0x800000
- + str r6, [r3, #0x100]
- +
- + /*
- + * Set PLL2 to bypass state. We should be here
- + * only if MMDC is not sourced from PLL2.
- + */
- + ldr r6, [r3, #0x30]
- + orr r6, r6, #0x10000
- + str r6, [r3, #0x30]
- +
- + ldr r6, [r3, #0x30]
- + orr r6, r6, #0x1000
- + str r6, [r3, #0x30]
- +
- + /* Ensure pre_periph2_clk_mux is set to pll2 */
- + ldr r6, [r2, #0x18]
- + bic r6, r6, #0x600000
- + str r6, [r2, #0x18]
- +
- + /* Set MMDC clock to be sourced from the bypassed PLL2. */
- + ldr r6, [r2, #0x14]
- + bic r6, r6, #0x4000000
- + str r6, [r2, #0x14]
- +
- +periph2_clk_switch2:
- + ldr r6, [r2, #0x48]
- + cmp r6, #0
- + bne periph2_clk_switch2
- +
- + /*
- + * Now move MMDC back to periph2_clk2 source.
- + * after selecting PLL2 as the option.
- + * Select PLL2 as the source.
- + */
- + ldr r6, [r2, #0x18]
- + orr r6, r6, #0x100000
- + str r6, [r2, #0x18]
- +
- + /* set periph2_clk2_podf to divide by 1. */
- + ldr r6, [r2, #0x14]
- + bic r6, r6, #0x7
- + str r6, [r2, #0x14]
- +
- + /* Now move periph2_clk to periph2_clk2 source */
- + ldr r6, [r2, #0x14]
- + orr r6, r6, #0x4000000
- + str r6, [r2, #0x14]
- +
- +periph2_clk_switch3:
- + ldr r6, [r2, #0x48]
- + cmp r6, #0
- + bne periph2_clk_switch3
- +
- + /* Now set the MMDC PODF back to 1.*/
- + ldr r6, [r2, #0x14]
- + bic r6, r6, #0x38
- + str r6, [r2, #0x14]
- +
- +mmdc_podf0:
- + ldr r6, [r2, #0x48]
- + cmp r6, #0
- + bne mmdc_podf0
- +
- + .endm
- +
- + .macro ddr_switch_400MHz
- +
- + /* Set MMDC divider first, in case PLL3 is at 480MHz. */
- + ldr r6, [r3, #0x10]
- + and r6, r6, #0x10000
- + cmp r6, #0x10000
- + beq pll3_in_bypass
- +
- + /* Set MMDC divder to divide by 2. */
- + ldr r6, [r2, #0x14]
- + bic r6, r6, #0x38
- + orr r6, r6, #0x8
- + str r6, [r2, #0x14]
- +
- +mmdc_podf:
- + ldr r6, [r2, #0x48]
- + cmp r6, #0
- + bne mmdc_podf
- +
- +pll3_in_bypass:
- + /*
- + * Check if we are switching between
- + * 400Mhz <-> 100MHz.If so, we should
- + * try to source MMDC from PLL2_200M.
- + */
- + cmp r1, #0
- + beq not_low_bus_freq
- +
- + /* Ensure that MMDC is sourced from PLL2 mux first. */
- + ldr r6, [r2, #0x14]
- + bic r6, r6, #0x4000000
- + str r6, [r2, #0x14]
- +
- +periph2_clk_switch4:
- + ldr r6, [r2, #0x48]
- + cmp r6, #0
- + bne periph2_clk_switch4
- +
- +not_low_bus_freq:
- + /* Now ensure periph2_clk2_sel mux is set to PLL3 */
- + ldr r6, [r2, #0x18]
- + bic r6, r6, #0x100000
- + str r6, [r2, #0x18]
- +
- + /* Now switch MMDC to PLL3. */
- + ldr r6, [r2, #0x14]
- + orr r6, r6, #0x4000000
- + str r6, [r2, #0x14]
- +
- +periph2_clk_switch5:
- + ldr r6, [r2, #0x48]
- + cmp r6, #0
- + bne periph2_clk_switch5
- +
- + /*
- + * Check if PLL2 is already unlocked.
- + * If so do nothing with PLL2.
- + */
- + cmp r1, #0
- + beq pll2_already_on
- +
- + /* Now power up PLL2 and unbypass it. */
- + ldr r6, [r3, #0x30]
- + bic r6, r6, #0x1000
- + str r6, [r3, #0x30]
- +
- + /* Make sure PLL2 has locked.*/
- +wait_for_pll_lock:
- + ldr r6, [r3, #0x30]
- + and r6, r6, #0x80000000
- + cmp r6, #0x80000000
- + bne wait_for_pll_lock
- +
- + ldr r6, [r3, #0x30]
- + bic r6, r6, #0x10000
- + str r6, [r3, #0x30]
- +
- + /*
- + * Need to enable the 528 PFDs after
- + * powering up PLL2.
- + * Only the PLL2_PFD2_400M should be ON
- + * as it feeds the MMDC. Rest should have
- + * been managed by clock code.
- + */
- + ldr r6, [r3, #0x100]
- + bic r6, r6, #0x800000
- + str r6, [r3, #0x100]
- +
- +pll2_already_on:
- + /*
- + * Now switch MMDC clk back to pll2_mux option.
- + * Ensure pre_periph2_clk2 is set to pll2_pfd_400M.
- + * If switching to audio DDR freq, set the
- + * pre_periph2_clk2 to PLL2_PFD_200M
- + */
- + ldr r6, =400000000
- + cmp r6, r0
- + bne use_pll2_pfd_200M
- +
- + ldr r6, [r2, #0x18]
- + bic r6, r6, #0x600000
- + orr r6, r6, #0x200000
- + str r6, [r2, #0x18]
- + ldr r6, =400000000
- + b cont2
- +
- +use_pll2_pfd_200M:
- + ldr r6, [r2, #0x18]
- + orr r6, r6, #0x600000
- + str r6, [r2, #0x18]
- + ldr r6, =200000000
- +
- +cont2:
- + ldr r4, [r2, #0x14]
- + bic r4, r4, #0x4000000
- + str r4, [r2, #0x14]
- +
- +periph2_clk_switch6:
- + ldr r4, [r2, #0x48]
- + cmp r4, #0
- + bne periph2_clk_switch6
- +
- +change_divider_only:
- + /*
- + * Calculate the MMDC divider
- + * based on the requested freq.
- + */
- + ldr r4, =0
- +Loop2:
- + sub r6, r6, r0
- + cmp r6, r0
- + blt Div_Found
- + add r4, r4, #1
- + bgt Loop2
- +
- + /* Shift divider into correct offset. */
- + lsl r4, r4, #3
- +Div_Found:
- + /* Set the MMDC PODF. */
- + ldr r6, [r2, #0x14]
- + bic r6, r6, #0x38
- + orr r6, r6, r4
- + str r6, [r2, #0x14]
- +
- +mmdc_podf1:
- + ldr r6, [r2, #0x48]
- + cmp r6, #0
- + bne mmdc_podf1
- +
- + .endm
- +
- + .macro mmdc_clk_lower_100MHz
- +
- + /*
- + * Prior to reducing the DDR frequency (at 528/400 MHz),
- + * read the Measure unit count bits (MU_UNIT_DEL_NUM)
- + */
- + ldr r5, =0x8B8
- + ldr r6, [r8, r5]
- + /* Original MU unit count */
- + mov r6, r6, LSR #16
- + ldr r4, =0x3FF
- + and r6, r6, r4
- + /* Original MU unit count * 2 */
- + mov r7, r6, LSL #1
- + /*
- + * Bypass the automatic measure unit when below 100 MHz
- + * by setting the Measure unit bypass enable bit (MU_BYP_EN)
- + */
- + ldr r6, [r8, r5]
- + orr r6, r6, #0x400
- + str r6, [r8, r5]
- + /*
- + * Double the measure count value read in step 1 and program it in the
- + * measurement bypass bits (MU_BYP_VAL) of the MMDC PHY Measure Unit
- + * Register for the reduced frequency operation below 100 MHz
- + */
- + ldr r6, [r8, r5]
- + ldr r4, =0x3FF
- + bic r6, r6, r4
- + orr r6, r6, r7
- + str r6, [r8, r5]
- + /* Now perform a Force Measurement. */
- + ldr r6, [r8, r5]
- + orr r6, r6, #0x800
- + str r6, [r8, r5]
- + /* Wait for FRC_MSR to clear. */
- +force_measure:
- + ldr r6, [r8, r5]
- + and r6, r6, #0x800
- + cmp r6, #0x0
- + bne force_measure
- +
- + .endm
- +
- + .macro mmdc_clk_above_100MHz
- +
- + /* Make sure that the PHY measurement unit is NOT in bypass mode */
- + ldr r5, =0x8B8
- + ldr r6, [r8, r5]
- + bic r6, r6, #0x400
- + str r6, [r8, r5]
- + /* Now perform a Force Measurement. */
- + ldr r6, [r8, r5]
- + orr r6, r6, #0x800
- + str r6, [r8, r5]
- + /* Wait for FRC_MSR to clear. */
- +force_measure1:
- + ldr r6, [r8, r5]
- + and r6, r6, #0x800
- + cmp r6, #0x0
- + bne force_measure1
- + .endm
- +
- +/*
- + * mx6_lpddr2_freq_change
- + *
- + * Make sure DDR is in self-refresh.
- + * IRQs are already disabled.
- + * r0 : DDR freq.
- + * r1: low_bus_freq_mode flag
- + * r2: Pointer to array containing addresses of registers.
- + */
- + .align 3
- +ENTRY(mx6_lpddr2_freq_change)
- +
- + push {r4-r10}
- +
- + mov r4, r2
- + ldr r3, [r4] @ANATOP_BASE_ADDR
- + ldr r2, [r4, #0x4] @CCM_BASE_ADDR
- + ldr r8, [r4, #0x8] @MMDC_P0_BASE_ADDR
- + ldr r7, [r4, #0xC] @L2_BASE_ADDR
- +
- +lpddr2_freq_change:
- + adr r9, lpddr2_freq_change
- +
- + /* Prime all TLB entries. */
- + ldr r6, [r9]
- + ldr r6, [r8]
- + ldr r6, [r3]
- + ldr r6, [r2]
- +
- + /* Drain all the L1 buffers. */
- + dsb
- +
- +#ifdef CONFIG_CACHE_L2X0
- + /*
- + * Need to make sure the buffers in L2 are drained.
- + * Performing a sync operation does this.
- + */
- + mov r6, #0x0
- + str r6, [r7, #0x730]
- +#endif
- +
- + /*
- + * The second dsb might be needed to keep cache sync (device write)
- + * ordering with the memory accesses before it.
- + */
- + dsb
- + isb
- +
- + /* Disable Automatic power savings. */
- + ldr r6, [r8, #0x404]
- + orr r6, r6, #0x01
- + str r6, [r8, #0x404]
- +
- + /* MMDC0_MDPDC disable power down timer */
- + ldr r6, [r8, #0x4]
- + bic r6, r6, #0xff00
- + str r6, [r8, #0x4]
- +
- + /* Delay for a while */
- + ldr r10, =10
- +delay1:
- + ldr r7, =0
- +cont1:
- + ldr r6, [r8, r7]
- + add r7, r7, #4
- + cmp r7, #16
- + bne cont1
- + sub r10, r10, #1
- + cmp r10, #0
- + bgt delay1
- +
- + /* Make the DDR explicitly enter self-refresh. */
- + ldr r6, [r8, #0x404]
- + orr r6, r6, #0x200000
- + str r6, [r8, #0x404]
- +
- +poll_dvfs_set_1:
- + ldr r6, [r8, #0x404]
- + and r6, r6, #0x2000000
- + cmp r6, #0x2000000
- + bne poll_dvfs_set_1
- +
- + /* set SBS step-by-step mode */
- + ldr r6, [r8, #0x410]
- + orr r6, r6, #0x100
- + str r6, [r8, #0x410]
- +
- + ldr r10, =100000000
- + cmp r0, r10
- + bgt set_ddr_mu_above_100
- + mmdc_clk_lower_100MHz
- +
- +set_ddr_mu_above_100:
- + ldr r10, =24000000
- + cmp r0, r10
- + beq set_to_24MHz
- +
- + ddr_switch_400MHz
- +
- + ldr r10,=100000000
- + cmp r0, r10
- + blt done
- + mmdc_clk_above_100MHz
- +
- + b done
- +
- +set_to_24MHz:
- + mx6sl_switch_to_24MHz
- +
- +done:
- + /* clear DVFS - exit from self refresh mode */
- + ldr r6, [r8, #0x404]
- + bic r6, r6, #0x200000
- + str r6, [r8, #0x404]
- +
- +poll_dvfs_clear_1:
- + ldr r6, [r8, #0x404]
- + and r6, r6, #0x2000000
- + cmp r6, #0x2000000
- + beq poll_dvfs_clear_1
- +
- + /* Enable Automatic power savings. */
- + ldr r6, [r8, #0x404]
- + bic r6, r6, #0x01
- + str r6, [r8, #0x404]
- +
- + ldr r10, =24000000
- + cmp r0, r10
- + beq skip_power_down
- +
- + /* Enable MMDC power down timer. */
- + ldr r6, [r8, #0x4]
- + orr r6, r6, #0x5500
- + str r6, [r8, #0x4]
- +
- +skip_power_down:
- + /* clear SBS - unblock DDR accesses */
- + ldr r6, [r8, #0x410]
- + bic r6, r6, #0x100
- + str r6, [r8, #0x410]
- +
- + pop {r4-r10}
- +
- + /* Restore registers */
- + mov pc, lr
- +
- + .type mx6_lpddr2_do_iram, #object
- +ENTRY(mx6_lpddr2_do_iram)
- + .word mx6_lpddr2_freq_change
- + .size mx6_lpddr2_freq_change, . - mx6_lpddr2_freq_change
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/mach-imx6q.c linux-3.14.35/arch/arm/mach-imx/mach-imx6q.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/mach-imx6q.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/mach-imx6q.c 2015-03-08 14:27:37.417684503 -0500
- @@ -1,5 +1,5 @@
- /*
- - * Copyright 2011-2013 Freescale Semiconductor, Inc.
- + * Copyright 2011-2014 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * The code contained herein is licensed under the GNU General Public
- @@ -15,6 +15,7 @@
- #include <linux/cpu.h>
- #include <linux/delay.h>
- #include <linux/export.h>
- +#include <linux/gpio.h>
- #include <linux/init.h>
- #include <linux/io.h>
- #include <linux/irq.h>
- @@ -22,15 +23,18 @@
- #include <linux/of.h>
- #include <linux/of_address.h>
- #include <linux/of_irq.h>
- +#include <linux/of_gpio.h>
- #include <linux/of_platform.h>
- #include <linux/pm_opp.h>
- #include <linux/pci.h>
- #include <linux/phy.h>
- +#include <linux/pm_opp.h>
- #include <linux/reboot.h>
- #include <linux/regmap.h>
- #include <linux/micrel_phy.h>
- #include <linux/mfd/syscon.h>
- #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
- +#include <linux/of_net.h>
- #include <asm/mach/arch.h>
- #include <asm/mach/map.h>
- #include <asm/system_misc.h>
- @@ -194,6 +198,101 @@
-
- }
-
- +static void __init imx6q_csi_mux_init(void)
- +{
- + /*
- + * MX6Q SabreSD board:
- + * IPU1 CSI0 connects to parallel interface.
- + * Set GPR1 bit 19 to 0x1.
- + *
- + * MX6DL SabreSD board:
- + * IPU1 CSI0 connects to parallel interface.
- + * Set GPR13 bit 0-2 to 0x4.
- + * IPU1 CSI1 connects to MIPI CSI2 virtual channel 1.
- + * Set GPR13 bit 3-5 to 0x1.
- + */
- + struct regmap *gpr;
- +
- + gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
- + if (!IS_ERR(gpr)) {
- + if (of_machine_is_compatible("fsl,imx6q-sabresd") ||
- + of_machine_is_compatible("fsl,imx6q-sabreauto"))
- + regmap_update_bits(gpr, IOMUXC_GPR1, 1 << 19, 1 << 19);
- + else if (of_machine_is_compatible("fsl,imx6dl-sabresd") ||
- + of_machine_is_compatible("fsl,imx6dl-sabreauto"))
- + regmap_update_bits(gpr, IOMUXC_GPR13, 0x3F, 0x0C);
- + } else {
- + pr_err("%s(): failed to find fsl,imx6q-iomux-gpr regmap\n",
- + __func__);
- + }
- +}
- +
- +#define OCOTP_MACn(n) (0x00000620 + (n) * 0x10)
- +void __init imx6_enet_mac_init(const char *compatible)
- +{
- + struct device_node *ocotp_np, *enet_np;
- + void __iomem *base;
- + struct property *newmac;
- + u32 macaddr_low, macaddr_high;
- + u8 *macaddr;
- +
- + enet_np = of_find_compatible_node(NULL, NULL, compatible);
- + if (!enet_np)
- + return;
- +
- + if (of_get_mac_address(enet_np))
- + goto put_enet_node;
- +
- + ocotp_np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ocotp");
- + if (!ocotp_np) {
- + pr_warn("failed to find ocotp node\n");
- + goto put_enet_node;
- + }
- +
- + base = of_iomap(ocotp_np, 0);
- + if (!base) {
- + pr_warn("failed to map ocotp\n");
- + goto put_ocotp_node;
- + }
- +
- + macaddr_high = readl_relaxed(base + OCOTP_MACn(0));
- + macaddr_low = readl_relaxed(base + OCOTP_MACn(1));
- +
- + newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL);
- + if (!newmac)
- + goto put_ocotp_node;
- +
- + newmac->value = newmac + 1;
- + newmac->length = 6;
- + newmac->name = kstrdup("local-mac-address", GFP_KERNEL);
- + if (!newmac->name) {
- + kfree(newmac);
- + goto put_ocotp_node;
- + }
- +
- + macaddr = newmac->value;
- + macaddr[5] = macaddr_high & 0xff;
- + macaddr[4] = (macaddr_high >> 8) & 0xff;
- + macaddr[3] = (macaddr_high >> 16) & 0xff;
- + macaddr[2] = (macaddr_high >> 24) & 0xff;
- + macaddr[1] = macaddr_low & 0xff;
- + macaddr[0] = (macaddr_low >> 8) & 0xff;
- +
- + of_update_property(enet_np, newmac);
- +
- +put_ocotp_node:
- + of_node_put(ocotp_np);
- +put_enet_node:
- + of_node_put(enet_np);
- +}
- +
- +static inline void imx6q_enet_init(void)
- +{
- + imx6_enet_mac_init("fsl,imx6q-fec");
- + imx6q_enet_phy_init();
- + imx6q_1588_init();
- +}
- +
- static void __init imx6q_init_machine(void)
- {
- struct device *parent;
- @@ -207,20 +306,22 @@
- if (parent == NULL)
- pr_warn("failed to initialize soc device\n");
-
- - imx6q_enet_phy_init();
- -
- of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
-
- + imx6q_enet_init();
- imx_anatop_init();
- - imx6q_pm_init();
- - imx6q_1588_init();
- + cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init();
- + imx6q_csi_mux_init();
- }
-
- #define OCOTP_CFG3 0x440
- #define OCOTP_CFG3_SPEED_SHIFT 16
- #define OCOTP_CFG3_SPEED_1P2GHZ 0x3
- +#define OCOTP_CFG3_SPEED_1GHZ 0x2
- +#define OCOTP_CFG3_SPEED_850MHZ 0x1
- +#define OCOTP_CFG3_SPEED_800MHZ 0x0
-
- -static void __init imx6q_opp_check_1p2ghz(struct device *cpu_dev)
- +static void __init imx6q_opp_check_speed_grading(struct device *cpu_dev)
- {
- struct device_node *np;
- void __iomem *base;
- @@ -238,11 +339,31 @@
- goto put_node;
- }
-
- + /*
- + * SPEED_GRADING[1:0] defines the max speed of ARM:
- + * 2b'11: 1200000000Hz; -- i.MX6Q only.
- + * 2b'10: 1000000000Hz;
- + * 2b'01: 850000000Hz; -- i.MX6Q Only, exclusive with 1GHz.
- + * 2b'00: 800000000Hz;
- + * We need to set the max speed of ARM according to fuse map.
- + */
- +
- val = readl_relaxed(base + OCOTP_CFG3);
- val >>= OCOTP_CFG3_SPEED_SHIFT;
- - if ((val & 0x3) != OCOTP_CFG3_SPEED_1P2GHZ)
- - if (dev_pm_opp_disable(cpu_dev, 1200000000))
- - pr_warn("failed to disable 1.2 GHz OPP\n");
- + if (cpu_is_imx6q()) {
- + if ((val & 0x3) < OCOTP_CFG3_SPEED_1P2GHZ)
- + if (dev_pm_opp_disable(cpu_dev, 1200000000))
- + pr_warn("failed to disable 1.2 GHz OPP\n");
- + }
- + if ((val & 0x3) < OCOTP_CFG3_SPEED_1GHZ)
- + if (dev_pm_opp_disable(cpu_dev, 996000000))
- + pr_warn("failed to disable 1 GHz OPP\n");
- + if (cpu_is_imx6q()) {
- + if ((val & 0x3) < OCOTP_CFG3_SPEED_850MHZ ||
- + (val & 0x3) == OCOTP_CFG3_SPEED_1GHZ)
- + if (dev_pm_opp_disable(cpu_dev, 852000000))
- + pr_warn("failed to disable 850 MHz OPP\n");
- + }
-
- put_node:
- of_node_put(np);
- @@ -268,29 +389,70 @@
- goto put_node;
- }
-
- - imx6q_opp_check_1p2ghz(cpu_dev);
- + imx6q_opp_check_speed_grading(cpu_dev);
-
- put_node:
- of_node_put(np);
- }
-
- +#define ESAI_AUDIO_MCLK 24576000
- +
- +static void __init imx6q_audio_lvds2_init(void)
- +{
- + struct clk *pll4_sel, *lvds2_in, *pll4_audio_div, *esai;
- +
- + pll4_audio_div = clk_get_sys(NULL, "pll4_audio_div");
- + pll4_sel = clk_get_sys(NULL, "pll4_sel");
- + lvds2_in = clk_get_sys(NULL, "lvds2_in");
- + esai = clk_get_sys(NULL, "esai");
- + if (IS_ERR(pll4_audio_div) || IS_ERR(pll4_sel) ||
- + IS_ERR(lvds2_in) || IS_ERR(esai))
- + return;
- +
- + if (clk_get_rate(lvds2_in) != ESAI_AUDIO_MCLK)
- + return;
- +
- + clk_set_parent(pll4_sel, lvds2_in);
- + clk_set_rate(pll4_audio_div, 786432000);
- + clk_set_rate(esai, ESAI_AUDIO_MCLK);
- +}
- +
- static struct platform_device imx6q_cpufreq_pdev = {
- - .name = "imx6q-cpufreq",
- + .name = "imx6-cpufreq",
- };
-
- static void __init imx6q_init_late(void)
- {
- + struct regmap *gpr;
- +
- + /*
- + * Need to force IOMUXC irq pending to meet CCM low power mode
- + * restriction, this is recommended by hardware team.
- + */
- + gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
- + if (!IS_ERR(gpr))
- + regmap_update_bits(gpr, IOMUXC_GPR1,
- + IMX6Q_GPR1_GINT_MASK,
- + IMX6Q_GPR1_GINT_ASSERT);
- +
- /*
- * WAIT mode is broken on TO 1.0 and 1.1, so there is no point
- * to run cpuidle on them.
- */
- - if (imx_get_soc_revision() > IMX_CHIP_REVISION_1_1)
- + if ((cpu_is_imx6q() && imx_get_soc_revision() > IMX_CHIP_REVISION_1_1)
- + || (cpu_is_imx6dl() && imx_get_soc_revision() >
- + IMX_CHIP_REVISION_1_0))
- imx6q_cpuidle_init();
-
- - if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) {
- + if (IS_ENABLED(CONFIG_ARM_IMX6_CPUFREQ)) {
- imx6q_opp_init();
- platform_device_register(&imx6q_cpufreq_pdev);
- }
- +
- + if (of_machine_is_compatible("fsl,imx6q-sabreauto")
- + || of_machine_is_compatible("fsl,imx6dl-sabreauto")) {
- + imx6q_audio_lvds2_init();
- + }
- }
-
- static void __init imx6q_map_io(void)
- @@ -315,6 +477,12 @@
- };
-
- DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)")
- + /*
- + * i.MX6Q/DL maps system memory at 0x10000000 (offset 256MiB), and
- + * GPU has a limit on physical address that it accesses, which must
- + * be below 2GiB.
- + */
- + .dma_zone_size = (SZ_2G - SZ_256M),
- .smp = smp_ops(imx_smp_ops),
- .map_io = imx6q_map_io,
- .init_irq = imx6q_init_irq,
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/mach-imx6sl.c linux-3.14.35/arch/arm/mach-imx/mach-imx6sl.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/mach-imx6sl.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/mach-imx6sl.c 2015-03-08 14:27:37.417684503 -0500
- @@ -17,8 +17,9 @@
- #include <asm/mach/map.h>
-
- #include "common.h"
- +#include "cpuidle.h"
-
- -static void __init imx6sl_fec_init(void)
- +static void __init imx6sl_fec_clk_init(void)
- {
- struct regmap *gpr;
-
- @@ -34,8 +35,17 @@
- }
- }
-
- +static inline void imx6sl_fec_init(void)
- +{
- + imx6sl_fec_clk_init();
- + imx6_enet_mac_init("fsl,imx6sl-fec");
- +}
- +
- static void __init imx6sl_init_late(void)
- {
- + /* Init CPUIDLE */
- + imx6sl_cpuidle_init();
- +
- /* imx6sl reuses imx6q cpufreq driver */
- if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
- platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
- @@ -55,8 +65,7 @@
-
- imx6sl_fec_init();
- imx_anatop_init();
- - /* Reuse imx6q pm code */
- - imx6q_pm_init();
- + imx6sl_pm_init();
- }
-
- static void __init imx6sl_init_irq(void)
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/mach-vf610.c linux-3.14.35/arch/arm/mach-imx/mach-vf610.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/mach-vf610.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/mach-vf610.c 2015-03-08 14:27:37.417684503 -0500
- @@ -22,7 +22,7 @@
-
- static void __init vf610_init_irq(void)
- {
- - l2x0_of_init(0, ~0UL);
- + l2x0_of_init(0, ~0);
- irqchip_init();
- }
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/Makefile linux-3.14.35/arch/arm/mach-imx/Makefile
- --- linux-3.14.35.orig/arch/arm/mach-imx/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/Makefile 2015-03-08 14:27:37.417684503 -0500
- @@ -30,6 +30,7 @@
- ifeq ($(CONFIG_CPU_IDLE),y)
- obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o
- obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o
- +obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o
- endif
-
- ifdef CONFIG_SND_IMX_SOC
- @@ -101,9 +102,18 @@
- obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o
- obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o
-
- -obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o
- -# i.MX6SL reuses i.MX6Q code
- -obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o headsmp.o
- +AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a
- +obj-$(CONFIG_PM) += suspend-imx6.o pm-imx6.o headsmp.o
- +
- +obj-y += busfreq-imx6.o
- +ifeq ($(CONFIG_ARM_IMX6_CPUFREQ),y)
- +obj-$(CONFIG_SOC_IMX6Q) += ddr3_freq_imx6.o busfreq_ddr3.o
- +obj-$(CONFIG_SOC_IMX6SL) += lpddr2_freq_imx6.o busfreq_lpddr2.o
- +endif
- +ifeq ($(CONFIG_CPU_IDLE), y)
- +obj-$(CONFIG_SOC_IMX6SL) += imx6sl_wfi.o
- +endif
- +
-
- # i.MX5 based machines
- obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/mx6.h linux-3.14.35/arch/arm/mach-imx/mx6.h
- --- linux-3.14.35.orig/arch/arm/mach-imx/mx6.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/mx6.h 2015-03-08 14:27:37.417684503 -0500
- @@ -0,0 +1,35 @@
- +/*
- + * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#ifndef __ASM_ARCH_MXC_IOMAP_H__
- +#define __ASM_ARCH_MXC_IOMAP_H__
- +
- +#define MX6Q_IO_P2V(x) IMX_IO_P2V(x)
- +#define MX6Q_IO_ADDRESS(x) IOMEM(MX6Q_IO_P2V(x))
- +
- +#define MX6Q_L2_BASE_ADDR 0x00a02000
- +#define MX6Q_L2_SIZE 0x1000
- +#define MX6Q_IOMUXC_BASE_ADDR 0x020e0000
- +#define MX6Q_IOMUXC_SIZE 0x4000
- +#define MX6Q_SRC_BASE_ADDR 0x020d8000
- +#define MX6Q_SRC_SIZE 0x4000
- +#define MX6Q_CCM_BASE_ADDR 0x020c4000
- +#define MX6Q_CCM_SIZE 0x4000
- +#define MX6Q_ANATOP_BASE_ADDR 0x020c8000
- +#define MX6Q_ANATOP_SIZE 0x1000
- +#define MX6Q_GPC_BASE_ADDR 0x020dc000
- +#define MX6Q_GPC_SIZE 0x4000
- +#define MX6Q_MMDC_P0_BASE_ADDR 0x021b0000
- +#define MX6Q_MMDC_P0_SIZE 0x4000
- +#define MX6Q_MMDC_P1_BASE_ADDR 0x021b4000
- +#define MX6Q_MMDC_P1_SIZE 0x4000
- +
- +#define MX6_SUSPEND_IRAM_SIZE 0x1000
- +#endif
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/mxc.h linux-3.14.35/arch/arm/mach-imx/mxc.h
- --- linux-3.14.35.orig/arch/arm/mach-imx/mxc.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/mxc.h 2015-03-08 14:27:37.417684503 -0500
- @@ -42,6 +42,8 @@
- #define IMX_CHIP_REVISION_1_1 0x11
- #define IMX_CHIP_REVISION_1_2 0x12
- #define IMX_CHIP_REVISION_1_3 0x13
- +#define IMX_CHIP_REVISION_1_4 0x14
- +#define IMX_CHIP_REVISION_1_5 0x15
- #define IMX_CHIP_REVISION_2_0 0x20
- #define IMX_CHIP_REVISION_2_1 0x21
- #define IMX_CHIP_REVISION_2_2 0x22
- @@ -177,6 +179,7 @@
- extern struct cpu_op *(*get_cpu_op)(int *op);
- #endif
-
- +#define cpu_is_imx6() (cpu_is_imx6q() || cpu_is_imx6dl() || cpu_is_imx6sl())
- #define cpu_is_mx3() (cpu_is_mx31() || cpu_is_mx35())
- #define cpu_is_mx2() (cpu_is_mx21() || cpu_is_mx27())
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/pm-imx6.c linux-3.14.35/arch/arm/mach-imx/pm-imx6.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/pm-imx6.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/pm-imx6.c 2015-03-08 14:27:37.421684503 -0500
- @@ -0,0 +1,580 @@
- +/*
- + * Copyright 2011-2014 Freescale Semiconductor, Inc.
- + * Copyright 2011 Linaro Ltd.
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#include <linux/delay.h>
- +#include <linux/init.h>
- +#include <linux/io.h>
- +#include <linux/irq.h>
- +#include <linux/genalloc.h>
- +#include <linux/mfd/syscon.h>
- +#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
- +#include <linux/of.h>
- +#include <linux/of_address.h>
- +#include <linux/of_platform.h>
- +#include <linux/regmap.h>
- +#include <linux/suspend.h>
- +#include <linux/regmap.h>
- +#include <linux/mfd/syscon.h>
- +#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
- +#include <asm/cacheflush.h>
- +#include <asm/fncpy.h>
- +#include <asm/proc-fns.h>
- +#include <asm/suspend.h>
- +#include <asm/tlb.h>
- +
- +#include "common.h"
- +#include "hardware.h"
- +
- +#define CCR 0x0
- +#define BM_CCR_WB_COUNT (0x7 << 16)
- +#define BM_CCR_RBC_BYPASS_COUNT (0x3f << 21)
- +#define BM_CCR_RBC_EN (0x1 << 27)
- +
- +#define CLPCR 0x54
- +#define BP_CLPCR_LPM 0
- +#define BM_CLPCR_LPM (0x3 << 0)
- +#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2)
- +#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
- +#define BM_CLPCR_SBYOS (0x1 << 6)
- +#define BM_CLPCR_DIS_REF_OSC (0x1 << 7)
- +#define BM_CLPCR_VSTBY (0x1 << 8)
- +#define BP_CLPCR_STBY_COUNT 9
- +#define BM_CLPCR_STBY_COUNT (0x3 << 9)
- +#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11)
- +#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16)
- +#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17)
- +#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19)
- +#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21)
- +#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22)
- +#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23)
- +#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24)
- +#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25)
- +#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26)
- +#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27)
- +
- +#define CGPR 0x64
- +#define BM_CGPR_INT_MEM_CLK_LPM (0x1 << 17)
- +
- +#define MX6Q_SUSPEND_OCRAM_SIZE 0x1000
- +#define MX6_MAX_MMDC_IO_NUM 33
- +
- +static void __iomem *ccm_base;
- +static void __iomem *suspend_ocram_base;
- +static void (*imx6_suspend_in_ocram_fn)(void __iomem *ocram_vbase);
- +
- +/*
- + * suspend ocram space layout:
- + * ======================== high address ======================
- + * .
- + * .
- + * .
- + * ^
- + * ^
- + * ^
- + * imx6_suspend code
- + * PM_INFO structure(imx6_cpu_pm_info)
- + * ======================== low address =======================
- + */
- +
- +struct imx6_pm_base {
- + phys_addr_t pbase;
- + void __iomem *vbase;
- +};
- +
- +struct imx6_pm_socdata {
- + u32 cpu_type;
- + const char *mmdc_compat;
- + const char *src_compat;
- + const char *iomuxc_compat;
- + const char *gpc_compat;
- + const u32 mmdc_io_num;
- + const u32 *mmdc_io_offset;
- +};
- +
- +static const u32 imx6q_mmdc_io_offset[] __initconst = {
- + 0x5ac, 0x5b4, 0x528, 0x520, /* DQM0 ~ DQM3 */
- + 0x514, 0x510, 0x5bc, 0x5c4, /* DQM4 ~ DQM7 */
- + 0x56c, 0x578, 0x588, 0x594, /* CAS, RAS, SDCLK_0, SDCLK_1 */
- + 0x5a8, 0x5b0, 0x524, 0x51c, /* SDQS0 ~ SDQS3 */
- + 0x518, 0x50c, 0x5b8, 0x5c0, /* SDQS4 ~ SDQS7 */
- + 0x784, 0x788, 0x794, 0x79c, /* GPR_B0DS ~ GPR_B3DS */
- + 0x7a0, 0x7a4, 0x7a8, 0x748, /* GPR_B4DS ~ GPR_B7DS */
- + 0x59c, 0x5a0, 0x750, 0x774, /* SODT0, SODT1, MODE_CTL, MODE */
- + 0x74c, /* GPR_ADDS */
- +};
- +
- +static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
- + .cpu_type = MXC_CPU_IMX6Q,
- + .mmdc_compat = "fsl,imx6q-mmdc",
- + .src_compat = "fsl,imx6q-src",
- + .iomuxc_compat = "fsl,imx6q-iomuxc",
- + .gpc_compat = "fsl,imx6q-gpc",
- + .mmdc_io_num = ARRAY_SIZE(imx6q_mmdc_io_offset),
- + .mmdc_io_offset = imx6q_mmdc_io_offset,
- +};
- +
- +/*
- + * This structure is for passing necessary data for low level ocram
- + * suspend code(arch/arm/mach-imx/suspend-imx6.S), if this struct
- + * definition is changed, the offset definition in
- + * arch/arm/mach-imx/suspend-imx6.S must be also changed accordingly,
- + * otherwise, the suspend to ocram function will be broken!
- + */
- +struct imx6_cpu_pm_info {
- + phys_addr_t pbase; /* The physical address of pm_info. */
- + phys_addr_t resume_addr; /* The physical resume address for asm code */
- + u32 cpu_type;
- + u32 pm_info_size; /* Size of pm_info. */
- + struct imx6_pm_base mmdc_base;
- + struct imx6_pm_base src_base;
- + struct imx6_pm_base iomuxc_base;
- + struct imx6_pm_base ccm_base;
- + struct imx6_pm_base gpc_base;
- + struct imx6_pm_base l2_base;
- + u32 mmdc_io_num; /* Number of MMDC IOs which need saved/restored. */
- + u32 mmdc_io_val[MX6_MAX_MMDC_IO_NUM][2]; /* To save offset and value */
- +} __aligned(8);
- +
- +void imx6q_set_cache_lpm_in_wait(bool enable)
- +{
- + if ((cpu_is_imx6q() && imx_get_soc_revision() >
- + IMX_CHIP_REVISION_1_1) ||
- + (cpu_is_imx6dl() && imx_get_soc_revision() >
- + IMX_CHIP_REVISION_1_0)) {
- + u32 val;
- +
- + val = readl_relaxed(ccm_base + CGPR);
- + if (enable)
- + val |= BM_CGPR_INT_MEM_CLK_LPM;
- + else
- + val &= ~BM_CGPR_INT_MEM_CLK_LPM;
- + writel_relaxed(val, ccm_base + CGPR);
- + }
- +}
- +
- +static void imx6q_enable_rbc(bool enable)
- +{
- + u32 val;
- +
- + /*
- + * need to mask all interrupts in GPC before
- + * operating RBC configurations
- + */
- + imx_gpc_mask_all();
- +
- + /* configure RBC enable bit */
- + val = readl_relaxed(ccm_base + CCR);
- + val &= ~BM_CCR_RBC_EN;
- + val |= enable ? BM_CCR_RBC_EN : 0;
- + writel_relaxed(val, ccm_base + CCR);
- +
- + /* configure RBC count */
- + val = readl_relaxed(ccm_base + CCR);
- + val &= ~BM_CCR_RBC_BYPASS_COUNT;
- + val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0;
- + writel(val, ccm_base + CCR);
- +
- + /*
- + * need to delay at least 2 cycles of CKIL(32K)
- + * due to hardware design requirement, which is
- + * ~61us, here we use 65us for safe
- + */
- + udelay(65);
- +
- + /* restore GPC interrupt mask settings */
- + imx_gpc_restore_all();
- +}
- +
- +static void imx6q_enable_wb(bool enable)
- +{
- + u32 val;
- +
- + /* configure well bias enable bit */
- + val = readl_relaxed(ccm_base + CLPCR);
- + val &= ~BM_CLPCR_WB_PER_AT_LPM;
- + val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0;
- + writel_relaxed(val, ccm_base + CLPCR);
- +
- + /* configure well bias count */
- + val = readl_relaxed(ccm_base + CCR);
- + val &= ~BM_CCR_WB_COUNT;
- + val |= enable ? BM_CCR_WB_COUNT : 0;
- + writel_relaxed(val, ccm_base + CCR);
- +}
- +
- +int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
- +{
- + struct irq_desc *iomuxc_irq_desc;
- + u32 val = readl_relaxed(ccm_base + CLPCR);
- +
- + val &= ~BM_CLPCR_LPM;
- + switch (mode) {
- + case WAIT_CLOCKED:
- + break;
- + case WAIT_UNCLOCKED:
- + val |= 0x1 << BP_CLPCR_LPM;
- + val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
- + val &= ~BM_CLPCR_VSTBY;
- + val &= ~BM_CLPCR_SBYOS;
- + if (cpu_is_imx6sl())
- + val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
- + else
- + val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
- + break;
- + case STOP_POWER_ON:
- + val |= 0x2 << BP_CLPCR_LPM;
- + val &= ~BM_CLPCR_VSTBY;
- + val &= ~BM_CLPCR_SBYOS;
- + val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
- + break;
- + case WAIT_UNCLOCKED_POWER_OFF:
- + val |= 0x1 << BP_CLPCR_LPM;
- + val &= ~BM_CLPCR_VSTBY;
- + val &= ~BM_CLPCR_SBYOS;
- + break;
- + case STOP_POWER_OFF:
- + val |= 0x2 << BP_CLPCR_LPM;
- + val |= 0x3 << BP_CLPCR_STBY_COUNT;
- + val |= BM_CLPCR_VSTBY;
- + val |= BM_CLPCR_SBYOS;
- + if (cpu_is_imx6sl()) {
- + val |= BM_CLPCR_BYPASS_PMIC_READY;
- + val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
- + } else {
- + val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
- + }
- + break;
- + default:
- + return -EINVAL;
- + }
- +
- + /*
- + * ERR007265: CCM: When improper low-power sequence is used,
- + * the SoC enters low power mode before the ARM core executes WFI.
- + *
- + * Software workaround:
- + * 1) Software should trigger IRQ #32 (IOMUX) to be always pending
- + * by setting IOMUX_GPR1_GINT.
- + * 2) Software should then unmask IRQ #32 in GPC before setting CCM
- + * Low-Power mode.
- + * 3) Software should mask IRQ #32 right after CCM Low-Power mode
- + * is set (set bits 0-1 of CCM_CLPCR).
- + */
- + iomuxc_irq_desc = irq_to_desc(32);
- + imx_gpc_irq_unmask(&iomuxc_irq_desc->irq_data);
- + writel_relaxed(val, ccm_base + CLPCR);
- + imx_gpc_irq_mask(&iomuxc_irq_desc->irq_data);
- +
- + return 0;
- +}
- +
- +static int imx6q_suspend_finish(unsigned long val)
- +{
- + if (!imx6_suspend_in_ocram_fn) {
- + cpu_do_idle();
- + } else {
- + /*
- + * call low level suspend function in ocram,
- + * as we need to float DDR IO.
- + */
- + local_flush_tlb_all();
- + imx6_suspend_in_ocram_fn(suspend_ocram_base);
- + }
- +
- + return 0;
- +}
- +
- +static int imx6q_pm_enter(suspend_state_t state)
- +{
- + struct regmap *g;
- +
- + /*
- + * L2 can exit by 'reset' or Inband beacon (from remote EP)
- + * toggling phy_powerdown has same effect as 'inband beacon'
- + * So, toggle bit18 of GPR1, used as a workaround of errata
- + * "PCIe PCIe does not support L2 Power Down"
- + */
- + if (IS_ENABLED(CONFIG_PCI_IMX6)) {
- + g = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
- + if (IS_ERR(g)) {
- + pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n");
- + return PTR_ERR(g);
- + }
- + regmap_update_bits(g, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_TEST_PD,
- + IMX6Q_GPR1_PCIE_TEST_PD);
- + }
- +
- + switch (state) {
- + case PM_SUSPEND_STANDBY:
- + imx6q_set_lpm(STOP_POWER_ON);
- + imx6q_set_cache_lpm_in_wait(true);
- + imx_gpc_pre_suspend(false);
- + if (cpu_is_imx6sl())
- + imx6sl_set_wait_clk(true);
- + /* Zzz ... */
- + cpu_do_idle();
- + if (cpu_is_imx6sl())
- + imx6sl_set_wait_clk(false);
- + imx_gpc_post_resume();
- + imx6q_set_lpm(WAIT_CLOCKED);
- + break;
- + case PM_SUSPEND_MEM:
- + imx6q_set_cache_lpm_in_wait(false);
- + imx6q_set_lpm(STOP_POWER_OFF);
- + imx6q_enable_wb(true);
- + /*
- + * For suspend into ocram, asm code already take care of
- + * RBC setting, so we do NOT need to do that here.
- + */
- + if (!imx6_suspend_in_ocram_fn)
- + imx6q_enable_rbc(true);
- + imx_gpc_pre_suspend(true);
- + imx_anatop_pre_suspend();
- + imx_set_cpu_jump(0, v7_cpu_resume);
- + /* Zzz ... */
- + cpu_suspend(0, imx6q_suspend_finish);
- + if (cpu_is_imx6q() || cpu_is_imx6dl())
- + imx_smp_prepare();
- + imx_anatop_post_resume();
- + imx_gpc_post_resume();
- + imx6q_enable_wb(false);
- + imx6q_set_lpm(WAIT_CLOCKED);
- + break;
- + default:
- + return -EINVAL;
- + }
- +
- + /*
- + * L2 can exit by 'reset' or Inband beacon (from remote EP)
- + * toggling phy_powerdown has same effect as 'inband beacon'
- + * So, toggle bit18 of GPR1, used as a workaround of errata
- + * "PCIe PCIe does not support L2 Power Down"
- + */
- + if (IS_ENABLED(CONFIG_PCI_IMX6)) {
- + regmap_update_bits(g, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_TEST_PD,
- + !IMX6Q_GPR1_PCIE_TEST_PD);
- + }
- +
- + return 0;
- +}
- +
- +static int imx6q_pm_valid(suspend_state_t state)
- +{
- + return (state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM);
- +}
- +
- +static const struct platform_suspend_ops imx6q_pm_ops = {
- + .enter = imx6q_pm_enter,
- + .valid = imx6q_pm_valid,
- +};
- +
- +void __init imx6q_pm_set_ccm_base(void __iomem *base)
- +{
- + ccm_base = base;
- +}
- +
- +static int __init imx6_pm_get_base(struct imx6_pm_base *base,
- + const char *compat)
- +{
- + struct device_node *node;
- + struct resource res;
- + int ret = 0;
- +
- + node = of_find_compatible_node(NULL, NULL, compat);
- + if (!node) {
- + ret = -ENODEV;
- + goto out;
- + }
- +
- + ret = of_address_to_resource(node, 0, &res);
- + if (ret)
- + goto put_node;
- +
- + base->pbase = res.start;
- + base->vbase = ioremap(res.start, resource_size(&res));
- + if (!base->vbase)
- + ret = -ENOMEM;
- +
- +put_node:
- + of_node_put(node);
- +out:
- + return ret;
- +}
- +
- +static int __init imx6q_ocram_suspend_init(const struct imx6_pm_socdata
- + *socdata)
- +{
- + phys_addr_t ocram_pbase;
- + struct device_node *node;
- + struct platform_device *pdev;
- + struct imx6_cpu_pm_info *pm_info;
- + struct gen_pool *ocram_pool;
- + unsigned long ocram_base;
- + int i, ret = 0;
- + const u32 *mmdc_offset_array;
- +
- + if (!socdata) {
- + pr_warn("%s: invalid argument!\n", __func__);
- + return -EINVAL;
- + }
- +
- + node = of_find_compatible_node(NULL, NULL, "mmio-sram");
- + if (!node) {
- + pr_warn("%s: failed to find ocram node!\n", __func__);
- + return -ENODEV;
- + }
- +
- + pdev = of_find_device_by_node(node);
- + if (!pdev) {
- + pr_warn("%s: failed to find ocram device!\n", __func__);
- + ret = -ENODEV;
- + goto put_node;
- + }
- +
- + ocram_pool = dev_get_gen_pool(&pdev->dev);
- + if (!ocram_pool) {
- + pr_warn("%s: ocram pool unavailable!\n", __func__);
- + ret = -ENODEV;
- + goto put_node;
- + }
- +
- + ocram_base = gen_pool_alloc(ocram_pool, MX6Q_SUSPEND_OCRAM_SIZE);
- + if (!ocram_base) {
- + pr_warn("%s: unable to alloc ocram!\n", __func__);
- + ret = -ENOMEM;
- + goto put_node;
- + }
- +
- + ocram_pbase = gen_pool_virt_to_phys(ocram_pool, ocram_base);
- +
- + suspend_ocram_base = __arm_ioremap_exec(ocram_pbase,
- + MX6Q_SUSPEND_OCRAM_SIZE, false);
- +
- + pm_info = suspend_ocram_base;
- + pm_info->pbase = ocram_pbase;
- + pm_info->resume_addr = virt_to_phys(v7_cpu_resume);
- + pm_info->pm_info_size = sizeof(*pm_info);
- +
- + /*
- + * ccm physical address is not used by asm code currently,
- + * so get ccm virtual address directly, as we already have
- + * it from ccm driver.
- + */
- + pm_info->ccm_base.vbase = ccm_base;
- +
- + ret = imx6_pm_get_base(&pm_info->mmdc_base, socdata->mmdc_compat);
- + if (ret) {
- + pr_warn("%s: failed to get mmdc base %d!\n", __func__, ret);
- + goto put_node;
- + }
- +
- + ret = imx6_pm_get_base(&pm_info->src_base, socdata->src_compat);
- + if (ret) {
- + pr_warn("%s: failed to get src base %d!\n", __func__, ret);
- + goto src_map_failed;
- + }
- +
- + ret = imx6_pm_get_base(&pm_info->iomuxc_base, socdata->iomuxc_compat);
- + if (ret) {
- + pr_warn("%s: failed to get iomuxc base %d!\n", __func__, ret);
- + goto iomuxc_map_failed;
- + }
- +
- + ret = imx6_pm_get_base(&pm_info->gpc_base, socdata->gpc_compat);
- + if (ret) {
- + pr_warn("%s: failed to get gpc base %d!\n", __func__, ret);
- + goto gpc_map_failed;
- + }
- +
- + ret = imx6_pm_get_base(&pm_info->l2_base, "arm,pl310-cache");
- + if (ret) {
- + pr_warn("%s: failed to get pl310-cache base %d!\n",
- + __func__, ret);
- + goto pl310_cache_map_failed;
- + }
- +
- + pm_info->cpu_type = socdata->cpu_type;
- + pm_info->mmdc_io_num = socdata->mmdc_io_num;
- + mmdc_offset_array = socdata->mmdc_io_offset;
- +
- + for (i = 0; i < pm_info->mmdc_io_num; i++) {
- + pm_info->mmdc_io_val[i][0] =
- + mmdc_offset_array[i];
- + pm_info->mmdc_io_val[i][1] =
- + readl_relaxed(pm_info->iomuxc_base.vbase +
- + mmdc_offset_array[i]);
- + }
- +
- + imx6_suspend_in_ocram_fn = fncpy(
- + suspend_ocram_base + sizeof(*pm_info),
- + &imx6_suspend,
- + MX6Q_SUSPEND_OCRAM_SIZE - sizeof(*pm_info));
- +
- + goto put_node;
- +
- +pl310_cache_map_failed:
- + iounmap(&pm_info->gpc_base.vbase);
- +gpc_map_failed:
- + iounmap(&pm_info->iomuxc_base.vbase);
- +iomuxc_map_failed:
- + iounmap(&pm_info->src_base.vbase);
- +src_map_failed:
- + iounmap(&pm_info->mmdc_base.vbase);
- +put_node:
- + of_node_put(node);
- +
- + return ret;
- +}
- +
- +static void __init imx6_pm_common_init(const struct imx6_pm_socdata
- + *socdata)
- +{
- + struct regmap *gpr;
- + int ret;
- +
- + WARN_ON(!ccm_base);
- +
- + ret = imx6q_ocram_suspend_init(socdata);
- + if (ret)
- + pr_warn("%s: failed to initialize ocram suspend %d!\n",
- + __func__, ret);
- +
- + /*
- + * This is for SW workaround step #1 of ERR007265, see comments
- + * in imx6q_set_lpm for details of this errata.
- + * Force IOMUXC irq pending, so that the interrupt to GPC can be
- + * used to deassert dsm_request signal when the signal gets
- + * asserted unexpectedly.
- + */
- + gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
- + if (!IS_ERR(gpr))
- + regmap_update_bits(gpr, IOMUXC_GPR1, IMX6Q_GPR1_GINT_MASK,
- + IMX6Q_GPR1_GINT_MASK);
- +
- +
- + suspend_set_ops(&imx6q_pm_ops);
- +}
- +
- +void __init imx6q_pm_init(void)
- +{
- + imx6_pm_common_init(&imx6q_pm_data);
- +}
- +
- +void __init imx6dl_pm_init(void)
- +{
- + imx6_pm_common_init(NULL);
- +}
- +
- +void __init imx6sl_pm_init(void)
- +{
- + imx6_pm_common_init(NULL);
- +}
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/pm-imx6q.c linux-3.14.35/arch/arm/mach-imx/pm-imx6q.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/pm-imx6q.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/pm-imx6q.c 1969-12-31 18:00:00.000000000 -0600
- @@ -1,241 +0,0 @@
- -/*
- - * Copyright 2011-2013 Freescale Semiconductor, Inc.
- - * Copyright 2011 Linaro Ltd.
- - *
- - * The code contained herein is licensed under the GNU General Public
- - * License. You may obtain a copy of the GNU General Public License
- - * Version 2 or later at the following locations:
- - *
- - * http://www.opensource.org/licenses/gpl-license.html
- - * http://www.gnu.org/copyleft/gpl.html
- - */
- -
- -#include <linux/delay.h>
- -#include <linux/init.h>
- -#include <linux/io.h>
- -#include <linux/irq.h>
- -#include <linux/mfd/syscon.h>
- -#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
- -#include <linux/of.h>
- -#include <linux/of_address.h>
- -#include <linux/regmap.h>
- -#include <linux/suspend.h>
- -#include <asm/cacheflush.h>
- -#include <asm/proc-fns.h>
- -#include <asm/suspend.h>
- -#include <asm/hardware/cache-l2x0.h>
- -
- -#include "common.h"
- -#include "hardware.h"
- -
- -#define CCR 0x0
- -#define BM_CCR_WB_COUNT (0x7 << 16)
- -#define BM_CCR_RBC_BYPASS_COUNT (0x3f << 21)
- -#define BM_CCR_RBC_EN (0x1 << 27)
- -
- -#define CLPCR 0x54
- -#define BP_CLPCR_LPM 0
- -#define BM_CLPCR_LPM (0x3 << 0)
- -#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2)
- -#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
- -#define BM_CLPCR_SBYOS (0x1 << 6)
- -#define BM_CLPCR_DIS_REF_OSC (0x1 << 7)
- -#define BM_CLPCR_VSTBY (0x1 << 8)
- -#define BP_CLPCR_STBY_COUNT 9
- -#define BM_CLPCR_STBY_COUNT (0x3 << 9)
- -#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11)
- -#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16)
- -#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17)
- -#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19)
- -#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21)
- -#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22)
- -#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23)
- -#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24)
- -#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25)
- -#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26)
- -#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27)
- -
- -#define CGPR 0x64
- -#define BM_CGPR_CHICKEN_BIT (0x1 << 17)
- -
- -static void __iomem *ccm_base;
- -
- -void imx6q_set_chicken_bit(void)
- -{
- - u32 val = readl_relaxed(ccm_base + CGPR);
- -
- - val |= BM_CGPR_CHICKEN_BIT;
- - writel_relaxed(val, ccm_base + CGPR);
- -}
- -
- -static void imx6q_enable_rbc(bool enable)
- -{
- - u32 val;
- -
- - /*
- - * need to mask all interrupts in GPC before
- - * operating RBC configurations
- - */
- - imx_gpc_mask_all();
- -
- - /* configure RBC enable bit */
- - val = readl_relaxed(ccm_base + CCR);
- - val &= ~BM_CCR_RBC_EN;
- - val |= enable ? BM_CCR_RBC_EN : 0;
- - writel_relaxed(val, ccm_base + CCR);
- -
- - /* configure RBC count */
- - val = readl_relaxed(ccm_base + CCR);
- - val &= ~BM_CCR_RBC_BYPASS_COUNT;
- - val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0;
- - writel(val, ccm_base + CCR);
- -
- - /*
- - * need to delay at least 2 cycles of CKIL(32K)
- - * due to hardware design requirement, which is
- - * ~61us, here we use 65us for safe
- - */
- - udelay(65);
- -
- - /* restore GPC interrupt mask settings */
- - imx_gpc_restore_all();
- -}
- -
- -static void imx6q_enable_wb(bool enable)
- -{
- - u32 val;
- -
- - /* configure well bias enable bit */
- - val = readl_relaxed(ccm_base + CLPCR);
- - val &= ~BM_CLPCR_WB_PER_AT_LPM;
- - val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0;
- - writel_relaxed(val, ccm_base + CLPCR);
- -
- - /* configure well bias count */
- - val = readl_relaxed(ccm_base + CCR);
- - val &= ~BM_CCR_WB_COUNT;
- - val |= enable ? BM_CCR_WB_COUNT : 0;
- - writel_relaxed(val, ccm_base + CCR);
- -}
- -
- -int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
- -{
- - struct irq_desc *iomuxc_irq_desc;
- - u32 val = readl_relaxed(ccm_base + CLPCR);
- -
- - val &= ~BM_CLPCR_LPM;
- - switch (mode) {
- - case WAIT_CLOCKED:
- - break;
- - case WAIT_UNCLOCKED:
- - val |= 0x1 << BP_CLPCR_LPM;
- - val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
- - break;
- - case STOP_POWER_ON:
- - val |= 0x2 << BP_CLPCR_LPM;
- - break;
- - case WAIT_UNCLOCKED_POWER_OFF:
- - val |= 0x1 << BP_CLPCR_LPM;
- - val &= ~BM_CLPCR_VSTBY;
- - val &= ~BM_CLPCR_SBYOS;
- - break;
- - case STOP_POWER_OFF:
- - val |= 0x2 << BP_CLPCR_LPM;
- - val |= 0x3 << BP_CLPCR_STBY_COUNT;
- - val |= BM_CLPCR_VSTBY;
- - val |= BM_CLPCR_SBYOS;
- - if (cpu_is_imx6sl()) {
- - val |= BM_CLPCR_BYPASS_PMIC_READY;
- - val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
- - } else {
- - val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
- - }
- - break;
- - default:
- - return -EINVAL;
- - }
- -
- - /*
- - * ERR007265: CCM: When improper low-power sequence is used,
- - * the SoC enters low power mode before the ARM core executes WFI.
- - *
- - * Software workaround:
- - * 1) Software should trigger IRQ #32 (IOMUX) to be always pending
- - * by setting IOMUX_GPR1_GINT.
- - * 2) Software should then unmask IRQ #32 in GPC before setting CCM
- - * Low-Power mode.
- - * 3) Software should mask IRQ #32 right after CCM Low-Power mode
- - * is set (set bits 0-1 of CCM_CLPCR).
- - */
- - iomuxc_irq_desc = irq_to_desc(32);
- - imx_gpc_irq_unmask(&iomuxc_irq_desc->irq_data);
- - writel_relaxed(val, ccm_base + CLPCR);
- - imx_gpc_irq_mask(&iomuxc_irq_desc->irq_data);
- -
- - return 0;
- -}
- -
- -static int imx6q_suspend_finish(unsigned long val)
- -{
- - cpu_do_idle();
- - return 0;
- -}
- -
- -static int imx6q_pm_enter(suspend_state_t state)
- -{
- - switch (state) {
- - case PM_SUSPEND_MEM:
- - imx6q_set_lpm(STOP_POWER_OFF);
- - imx6q_enable_wb(true);
- - imx6q_enable_rbc(true);
- - imx_gpc_pre_suspend();
- - imx_anatop_pre_suspend();
- - imx_set_cpu_jump(0, v7_cpu_resume);
- - /* Zzz ... */
- - cpu_suspend(0, imx6q_suspend_finish);
- - if (cpu_is_imx6q() || cpu_is_imx6dl())
- - imx_smp_prepare();
- - imx_anatop_post_resume();
- - imx_gpc_post_resume();
- - imx6q_enable_rbc(false);
- - imx6q_enable_wb(false);
- - imx6q_set_lpm(WAIT_CLOCKED);
- - break;
- - default:
- - return -EINVAL;
- - }
- -
- - return 0;
- -}
- -
- -static const struct platform_suspend_ops imx6q_pm_ops = {
- - .enter = imx6q_pm_enter,
- - .valid = suspend_valid_only_mem,
- -};
- -
- -void __init imx6q_pm_set_ccm_base(void __iomem *base)
- -{
- - ccm_base = base;
- -}
- -
- -void __init imx6q_pm_init(void)
- -{
- - struct regmap *gpr;
- -
- - WARN_ON(!ccm_base);
- -
- - /*
- - * This is for SW workaround step #1 of ERR007265, see comments
- - * in imx6q_set_lpm for details of this errata.
- - * Force IOMUXC irq pending, so that the interrupt to GPC can be
- - * used to deassert dsm_request signal when the signal gets
- - * asserted unexpectedly.
- - */
- - gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
- - if (!IS_ERR(gpr))
- - regmap_update_bits(gpr, IOMUXC_GPR1, IMX6Q_GPR1_GINT,
- - IMX6Q_GPR1_GINT);
- -
- -
- - suspend_set_ops(&imx6q_pm_ops);
- -}
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/suspend-imx6.S linux-3.14.35/arch/arm/mach-imx/suspend-imx6.S
- --- linux-3.14.35.orig/arch/arm/mach-imx/suspend-imx6.S 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/suspend-imx6.S 2015-03-08 14:27:37.433684503 -0500
- @@ -0,0 +1,306 @@
- +/*
- + * Copyright 2014 Freescale Semiconductor, Inc.
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#include <linux/linkage.h>
- +#include <asm/asm-offsets.h>
- +#include <asm/hardware/cache-l2x0.h>
- +#include "hardware.h"
- +
- +/*
- + * ==================== low level suspend ====================
- + *
- + * Better to follow below rules to use ARM registers:
- + * r0: pm_info structure address;
- + * r1 ~ r4: for saving pm_info members;
- + * r5 ~ r10: free registers;
- + * r11: io base address.
- + *
- + * suspend ocram space layout:
- + * ======================== high address ======================
- + * .
- + * .
- + * .
- + * ^
- + * ^
- + * ^
- + * imx6_suspend code
- + * PM_INFO structure(imx6_cpu_pm_info)
- + * ======================== low address =======================
- + */
- +
- +/*
- + * Below offsets are based on struct imx6_cpu_pm_info
- + * which defined in arch/arm/mach-imx/pm-imx6q.c, this
- + * structure contains necessary pm info for low level
- + * suspend related code.
- + */
- +#define PM_INFO_PBASE_OFFSET 0x0
- +#define PM_INFO_RESUME_ADDR_OFFSET 0x4
- +#define PM_INFO_CPU_TYPE_OFFSET 0x8
- +#define PM_INFO_PM_INFO_SIZE_OFFSET 0xC
- +#define PM_INFO_MX6Q_MMDC_P_OFFSET 0x10
- +#define PM_INFO_MX6Q_MMDC_V_OFFSET 0x14
- +#define PM_INFO_MX6Q_SRC_P_OFFSET 0x18
- +#define PM_INFO_MX6Q_SRC_V_OFFSET 0x1C
- +#define PM_INFO_MX6Q_IOMUXC_P_OFFSET 0x20
- +#define PM_INFO_MX6Q_IOMUXC_V_OFFSET 0x24
- +#define PM_INFO_MX6Q_CCM_P_OFFSET 0x28
- +#define PM_INFO_MX6Q_CCM_V_OFFSET 0x2C
- +#define PM_INFO_MX6Q_GPC_P_OFFSET 0x30
- +#define PM_INFO_MX6Q_GPC_V_OFFSET 0x34
- +#define PM_INFO_MX6Q_L2_P_OFFSET 0x38
- +#define PM_INFO_MX6Q_L2_V_OFFSET 0x3C
- +#define PM_INFO_MMDC_IO_NUM_OFFSET 0x40
- +#define PM_INFO_MMDC_IO_VAL_OFFSET 0x44
- +
- +#define MX6Q_SRC_GPR1 0x20
- +#define MX6Q_SRC_GPR2 0x24
- +#define MX6Q_MMDC_MAPSR 0x404
- +#define MX6Q_GPC_IMR1 0x08
- +#define MX6Q_GPC_IMR2 0x0c
- +#define MX6Q_GPC_IMR3 0x10
- +#define MX6Q_GPC_IMR4 0x14
- +#define MX6Q_CCM_CCR 0x0
- +
- + .align 3
- +
- + .macro sync_l2_cache
- +
- + /* sync L2 cache to drain L2's buffers to DRAM. */
- +#ifdef CONFIG_CACHE_L2X0
- + ldr r11, [r0, #PM_INFO_MX6Q_L2_V_OFFSET]
- + mov r6, #0x0
- + str r6, [r11, #L2X0_CACHE_SYNC]
- +1:
- + ldr r6, [r11, #L2X0_CACHE_SYNC]
- + ands r6, r6, #0x1
- + bne 1b
- +#endif
- +
- + .endm
- +
- + .macro resume_mmdc
- +
- + /* restore MMDC IO */
- + cmp r5, #0x0
- + ldreq r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
- + ldrne r11, [r0, #PM_INFO_MX6Q_IOMUXC_P_OFFSET]
- +
- + ldr r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
- + ldr r7, =PM_INFO_MMDC_IO_VAL_OFFSET
- + add r7, r7, r0
- +1:
- + ldr r8, [r7], #0x4
- + ldr r9, [r7], #0x4
- + str r9, [r11, r8]
- + subs r6, r6, #0x1
- + bne 1b
- +
- + cmp r5, #0x0
- + ldreq r11, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
- + ldrne r11, [r0, #PM_INFO_MX6Q_MMDC_P_OFFSET]
- +
- + /* let DDR out of self-refresh */
- + ldr r7, [r11, #MX6Q_MMDC_MAPSR]
- + bic r7, r7, #(1 << 21)
- + str r7, [r11, #MX6Q_MMDC_MAPSR]
- +2:
- + ldr r7, [r11, #MX6Q_MMDC_MAPSR]
- + ands r7, r7, #(1 << 25)
- + bne 2b
- +
- + /* enable DDR auto power saving */
- + ldr r7, [r11, #MX6Q_MMDC_MAPSR]
- + bic r7, r7, #0x1
- + str r7, [r11, #MX6Q_MMDC_MAPSR]
- +
- + .endm
- +
- +ENTRY(imx6_suspend)
- + ldr r1, [r0, #PM_INFO_PBASE_OFFSET]
- + ldr r2, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
- + ldr r3, [r0, #PM_INFO_CPU_TYPE_OFFSET]
- + ldr r4, [r0, #PM_INFO_PM_INFO_SIZE_OFFSET]
- +
- + /*
- + * counting the resume address in iram
- + * to set it in SRC register.
- + */
- + ldr r6, =imx6_suspend
- + ldr r7, =resume
- + sub r7, r7, r6
- + add r8, r1, r4
- + add r9, r8, r7
- +
- + /*
- + * make sure TLB contain the addr we want,
- + * as we will access them after MMDC IO floated.
- + */
- +
- + ldr r11, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
- + ldr r6, [r11, #0x0]
- + ldr r11, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
- + ldr r6, [r11, #0x0]
- + ldr r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
- + ldr r6, [r11, #0x0]
- +
- + /* use r11 to store the IO address */
- + ldr r11, [r0, #PM_INFO_MX6Q_SRC_V_OFFSET]
- + /* store physical resume addr and pm_info address. */
- + str r9, [r11, #MX6Q_SRC_GPR1]
- + str r1, [r11, #MX6Q_SRC_GPR2]
- +
- + /* need to sync L2 cache before DSM. */
- + sync_l2_cache
- +
- + ldr r11, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
- + /*
- + * put DDR explicitly into self-refresh and
- + * disable automatic power savings.
- + */
- + ldr r7, [r11, #MX6Q_MMDC_MAPSR]
- + orr r7, r7, #0x1
- + str r7, [r11, #MX6Q_MMDC_MAPSR]
- +
- + /* make the DDR explicitly enter self-refresh. */
- + ldr r7, [r11, #MX6Q_MMDC_MAPSR]
- + orr r7, r7, #(1 << 21)
- + str r7, [r11, #MX6Q_MMDC_MAPSR]
- +
- +poll_dvfs_set:
- + ldr r7, [r11, #MX6Q_MMDC_MAPSR]
- + ands r7, r7, #(1 << 25)
- + beq poll_dvfs_set
- +
- + ldr r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
- + ldr r6, =0x0
- + ldr r7, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
- + ldr r8, =PM_INFO_MMDC_IO_VAL_OFFSET
- + add r8, r8, r0
- +set_mmdc_io_lpm:
- + ldr r9, [r8], #0x8
- + str r6, [r11, r9]
- + subs r7, r7, #0x1
- + bne set_mmdc_io_lpm
- +
- + /*
- + * mask all GPC interrupts before
- + * enabling the RBC counters to
- + * avoid the counter starting too
- + * early if an interupt is already
- + * pending.
- + */
- + ldr r11, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
- + ldr r6, [r11, #MX6Q_GPC_IMR1]
- + ldr r7, [r11, #MX6Q_GPC_IMR2]
- + ldr r8, [r11, #MX6Q_GPC_IMR3]
- + ldr r9, [r11, #MX6Q_GPC_IMR4]
- +
- + ldr r10, =0xffffffff
- + str r10, [r11, #MX6Q_GPC_IMR1]
- + str r10, [r11, #MX6Q_GPC_IMR2]
- + str r10, [r11, #MX6Q_GPC_IMR3]
- + str r10, [r11, #MX6Q_GPC_IMR4]
- +
- + /*
- + * enable the RBC bypass counter here
- + * to hold off the interrupts. RBC counter
- + * = 32 (1ms), Minimum RBC delay should be
- + * 400us for the analog LDOs to power down.
- + */
- + ldr r11, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
- + ldr r10, [r11, #MX6Q_CCM_CCR]
- + bic r10, r10, #(0x3f << 21)
- + orr r10, r10, #(0x20 << 21)
- + str r10, [r11, #MX6Q_CCM_CCR]
- +
- + /* enable the counter. */
- + ldr r10, [r11, #MX6Q_CCM_CCR]
- + orr r10, r10, #(0x1 << 27)
- + str r10, [r11, #MX6Q_CCM_CCR]
- +
- + /* unmask all the GPC interrupts. */
- + ldr r11, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
- + str r6, [r11, #MX6Q_GPC_IMR1]
- + str r7, [r11, #MX6Q_GPC_IMR2]
- + str r8, [r11, #MX6Q_GPC_IMR3]
- + str r9, [r11, #MX6Q_GPC_IMR4]
- +
- + /*
- + * now delay for a short while (3usec)
- + * ARM is at 1GHz at this point
- + * so a short loop should be enough.
- + * this delay is required to ensure that
- + * the RBC counter can start counting in
- + * case an interrupt is already pending
- + * or in case an interrupt arrives just
- + * as ARM is about to assert DSM_request.
- + */
- + ldr r6, =2000
- +rbc_loop:
- + subs r6, r6, #0x1
- + bne rbc_loop
- +
- + /* Zzz, enter stop mode */
- + wfi
- + nop
- + nop
- + nop
- + nop
- +
- + /*
- + * run to here means there is pending
- + * wakeup source, system should auto
- + * resume, we need to restore MMDC IO first
- + */
- + mov r5, #0x0
- + resume_mmdc
- +
- + /* return to suspend finish */
- + mov pc, lr
- +
- +resume:
- + /* invalidate L1 I-cache first */
- + mov r6, #0x0
- + mcr p15, 0, r6, c7, c5, 0
- + mcr p15, 0, r6, c7, c5, 6
- + /* enable the Icache and branch prediction */
- + mov r6, #0x1800
- + mcr p15, 0, r6, c1, c0, 0
- + isb
- +
- + /* get physical resume address from pm_info. */
- + ldr lr, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
- + /* clear core0's entry and parameter */
- + ldr r11, [r0, #PM_INFO_MX6Q_SRC_P_OFFSET]
- + mov r7, #0x0
- + str r7, [r11, #MX6Q_SRC_GPR1]
- + str r7, [r11, #MX6Q_SRC_GPR2]
- +
- + mov r5, #0x1
- + resume_mmdc
- +
- + mov pc, lr
- +ENDPROC(imx6_suspend)
- +
- +/*
- + * The following code must assume it is running from physical address
- + * where absolute virtual addresses to the data section have to be
- + * turned into relative ones.
- + */
- +
- +ENTRY(v7_cpu_resume)
- + bl v7_invalidate_l1
- +#ifdef CONFIG_CACHE_L2X0
- + bl l2c310_early_resume
- +#endif
- + b cpu_resume
- +ENDPROC(v7_cpu_resume)
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/system.c linux-3.14.35/arch/arm/mach-imx/system.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/system.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/system.c 2015-03-08 14:27:37.433684503 -0500
- @@ -34,6 +34,7 @@
-
- static void __iomem *wdog_base;
- static struct clk *wdog_clk;
- +static u32 wdog_source = 1; /* use WDOG1 default */
-
- /*
- * Reset the system. It is called by machine_restart().
- @@ -47,6 +48,15 @@
-
- if (cpu_is_mx1())
- wcr_enable = (1 << 0);
- + /*
- + * Some i.MX6 boards use WDOG2 to reset external pmic in bypass mode,
- + * so do WDOG2 reset here. Do not set SRS, since we will
- + * trigger external POR later. Use WDOG1 to reset in ldo-enable
- + * mode. You can set it by "fsl,wdog-reset" in dts.
- + */
- + else if (wdog_source == 2 && (cpu_is_imx6q() || cpu_is_imx6dl() ||
- + cpu_is_imx6sl()))
- + wcr_enable = 0x14;
- else
- wcr_enable = (1 << 2);
-
- @@ -90,12 +100,29 @@
-
- void __init mxc_arch_reset_init_dt(void)
- {
- - struct device_node *np;
- + struct device_node *np = NULL;
- +
- + if (cpu_is_imx6q() || cpu_is_imx6dl())
- + np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
- + else if (cpu_is_imx6sl())
- + np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-gpc");
- +
- + if (np)
- + of_property_read_u32(np, "fsl,wdog-reset", &wdog_source);
- + pr_info("Use WDOG%d as reset source\n", wdog_source);
-
- np = of_find_compatible_node(NULL, NULL, "fsl,imx21-wdt");
- wdog_base = of_iomap(np, 0);
- WARN_ON(!wdog_base);
-
- + /* Some i.MX6 boards use WDOG2 to reset board in ldo-bypass mode */
- + if (wdog_source == 2 && (cpu_is_imx6q() || cpu_is_imx6dl() ||
- + cpu_is_imx6sl())) {
- + np = of_find_compatible_node(np, NULL, "fsl,imx21-wdt");
- + wdog_base = of_iomap(np, 0);
- + WARN_ON(!wdog_base);
- + }
- +
- wdog_clk = of_clk_get(np, 0);
- if (IS_ERR(wdog_clk)) {
- pr_warn("%s: failed to get wdog clock\n", __func__);
- @@ -124,7 +151,7 @@
- }
-
- /* Configure the L2 PREFETCH and POWER registers */
- - val = readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL);
- + val = readl_relaxed(l2x0_base + L310_PREFETCH_CTRL);
- val |= 0x70800000;
- /*
- * The L2 cache controller(PL310) version on the i.MX6D/Q is r3p1-50rel0
- @@ -137,14 +164,12 @@
- */
- if (cpu_is_imx6q())
- val &= ~(1 << 30 | 1 << 23);
- - writel_relaxed(val, l2x0_base + L2X0_PREFETCH_CTRL);
- - val = L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN;
- - writel_relaxed(val, l2x0_base + L2X0_POWER_CTRL);
- + writel_relaxed(val, l2x0_base + L310_PREFETCH_CTRL);
-
- iounmap(l2x0_base);
- of_node_put(np);
-
- out:
- - l2x0_of_init(0, ~0UL);
- + l2x0_of_init(0, ~0);
- }
- #endif
- diff -Nur linux-3.14.35.orig/arch/arm/mach-imx/time.c linux-3.14.35/arch/arm/mach-imx/time.c
- --- linux-3.14.35.orig/arch/arm/mach-imx/time.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-imx/time.c 2015-03-08 14:27:37.433684503 -0500
- @@ -60,7 +60,11 @@
- #define V2_TCTL_WAITEN (1 << 3) /* Wait enable mode */
- #define V2_TCTL_CLK_IPG (1 << 6)
- #define V2_TCTL_CLK_PER (2 << 6)
- +#define V2_TCTL_CLK_OSC_DIV8 (5 << 6)
- +#define V2_TCTL_CLK_OSC (7 << 6)
- +#define V2_TCTL_24MEN (1 << 10)
- #define V2_TCTL_FRR (1 << 9)
- +#define V2_TPRER_PRE24M 12
- #define V2_IR 0x0c
- #define V2_TSTAT 0x08
- #define V2_TSTAT_OF1 (1 << 0)
- @@ -277,11 +281,20 @@
-
- void __init mxc_timer_init(void __iomem *base, int irq)
- {
- - uint32_t tctl_val;
- + uint32_t tctl_val, tprer_val;
- struct clk *timer_clk;
- struct clk *timer_ipg_clk;
-
- - timer_clk = clk_get_sys("imx-gpt.0", "per");
- + /*
- + * gpt clk source from 24M OSC on imx6q > TO1.0 and
- + * imx6dl, others from per clk.
- + */
- + if ((cpu_is_imx6q() && imx_get_soc_revision() > IMX_CHIP_REVISION_1_0)
- + || cpu_is_imx6dl())
- + timer_clk = clk_get_sys("imx-gpt.0", "gpt_3m");
- + else
- + timer_clk = clk_get_sys("imx-gpt.0", "per");
- +
- if (IS_ERR(timer_clk)) {
- pr_err("i.MX timer: unable to get clk\n");
- return;
- @@ -302,10 +315,24 @@
- __raw_writel(0, timer_base + MXC_TCTL);
- __raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
-
- - if (timer_is_v2())
- - tctl_val = V2_TCTL_CLK_PER | V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN;
- - else
- + if (timer_is_v2()) {
- + if ((cpu_is_imx6q() && imx_get_soc_revision() >
- + IMX_CHIP_REVISION_1_0) || cpu_is_imx6dl()) {
- + tctl_val = V2_TCTL_CLK_OSC_DIV8 | V2_TCTL_FRR |
- + V2_TCTL_WAITEN | MXC_TCTL_TEN;
- + if (cpu_is_imx6dl()) {
- + /* 24 / 8 = 3 MHz */
- + tprer_val = 7 << V2_TPRER_PRE24M;
- + __raw_writel(tprer_val, timer_base + MXC_TPRER);
- + tctl_val |= V2_TCTL_24MEN;
- + }
- + } else {
- + tctl_val = V2_TCTL_CLK_PER | V2_TCTL_FRR |
- + V2_TCTL_WAITEN | MXC_TCTL_TEN;
- + }
- + } else {
- tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
- + }
-
- __raw_writel(tctl_val, timer_base + MXC_TCTL);
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-nomadik/cpu-8815.c linux-3.14.35/arch/arm/mach-nomadik/cpu-8815.c
- --- linux-3.14.35.orig/arch/arm/mach-nomadik/cpu-8815.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-nomadik/cpu-8815.c 2015-03-08 14:27:37.433684503 -0500
- @@ -147,7 +147,7 @@
- {
- #ifdef CONFIG_CACHE_L2X0
- /* At full speed latency must be >=2, so 0x249 in low bits */
- - l2x0_of_init(0x00730249, 0xfe000fff);
- + l2x0_of_init(0x00700249, 0xfe0fefff);
- #endif
- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
- }
- diff -Nur linux-3.14.35.orig/arch/arm/mach-omap2/common.h linux-3.14.35/arch/arm/mach-omap2/common.h
- --- linux-3.14.35.orig/arch/arm/mach-omap2/common.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-omap2/common.h 2015-03-08 14:27:37.433684503 -0500
- @@ -91,6 +91,7 @@
- extern void omap3_secure_sync32k_timer_init(void);
- extern void omap3_gptimer_timer_init(void);
- extern void omap4_local_timer_init(void);
- +int omap_l2_cache_init(void);
- extern void omap5_realtime_timer_init(void);
-
- void omap2420_init_early(void);
- diff -Nur linux-3.14.35.orig/arch/arm/mach-omap2/io.c linux-3.14.35/arch/arm/mach-omap2/io.c
- --- linux-3.14.35.orig/arch/arm/mach-omap2/io.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-omap2/io.c 2015-03-08 14:27:37.433684503 -0500
- @@ -608,6 +608,7 @@
- am43xx_clockdomains_init();
- am43xx_hwmod_init();
- omap_hwmod_init_postsetup();
- + omap_l2_cache_init();
- omap_clk_soc_init = am43xx_dt_clk_init;
- }
-
- @@ -639,6 +640,7 @@
- omap44xx_clockdomains_init();
- omap44xx_hwmod_init();
- omap_hwmod_init_postsetup();
- + omap_l2_cache_init();
- omap_clk_soc_init = omap4xxx_dt_clk_init;
- }
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-omap2/Kconfig linux-3.14.35/arch/arm/mach-omap2/Kconfig
- --- linux-3.14.35.orig/arch/arm/mach-omap2/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-omap2/Kconfig 2015-03-08 14:27:37.433684503 -0500
- @@ -78,6 +78,7 @@
- select MULTI_IRQ_HANDLER
- select ARM_GIC
- select MACH_OMAP_GENERIC
- + select MIGHT_HAVE_CACHE_L2X0
-
- config SOC_DRA7XX
- bool "TI DRA7XX"
- diff -Nur linux-3.14.35.orig/arch/arm/mach-omap2/omap4-common.c linux-3.14.35/arch/arm/mach-omap2/omap4-common.c
- --- linux-3.14.35.orig/arch/arm/mach-omap2/omap4-common.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-omap2/omap4-common.c 2015-03-08 14:27:37.433684503 -0500
- @@ -166,75 +166,57 @@
- return l2cache_base;
- }
-
- -static void omap4_l2x0_disable(void)
- +static void omap4_l2c310_write_sec(unsigned long val, unsigned reg)
- {
- - outer_flush_all();
- - /* Disable PL310 L2 Cache controller */
- - omap_smc1(0x102, 0x0);
- -}
- + unsigned smc_op;
-
- -static void omap4_l2x0_set_debug(unsigned long val)
- -{
- - /* Program PL310 L2 Cache controller debug register */
- - omap_smc1(0x100, val);
- + switch (reg) {
- + case L2X0_CTRL:
- + smc_op = OMAP4_MON_L2X0_CTRL_INDEX;
- + break;
- +
- + case L2X0_AUX_CTRL:
- + smc_op = OMAP4_MON_L2X0_AUXCTRL_INDEX;
- + break;
- +
- + case L2X0_DEBUG_CTRL:
- + smc_op = OMAP4_MON_L2X0_DBG_CTRL_INDEX;
- + break;
- +
- + case L310_PREFETCH_CTRL:
- + smc_op = OMAP4_MON_L2X0_PREFETCH_INDEX;
- + break;
- +
- + default:
- + WARN_ONCE(1, "OMAP L2C310: ignoring write to reg 0x%x\n", reg);
- + return;
- + }
- +
- + omap_smc1(smc_op, val);
- }
-
- -static int __init omap_l2_cache_init(void)
- +int __init omap_l2_cache_init(void)
- {
- - u32 aux_ctrl = 0;
- -
- - /*
- - * To avoid code running on other OMAPs in
- - * multi-omap builds
- - */
- - if (!cpu_is_omap44xx())
- - return -ENODEV;
- + u32 aux_ctrl;
-
- /* Static mapping, never released */
- l2cache_base = ioremap(OMAP44XX_L2CACHE_BASE, SZ_4K);
- if (WARN_ON(!l2cache_base))
- return -ENOMEM;
-
- - /*
- - * 16-way associativity, parity disabled
- - * Way size - 32KB (es1.0)
- - * Way size - 64KB (es2.0 +)
- - */
- - aux_ctrl = ((1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT) |
- - (0x1 << 25) |
- - (0x1 << L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT) |
- - (0x1 << L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT));
- -
- - if (omap_rev() == OMAP4430_REV_ES1_0) {
- - aux_ctrl |= 0x2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT;
- - } else {
- - aux_ctrl |= ((0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) |
- - (1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
- - (1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
- - (1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
- - (1 << L2X0_AUX_CTRL_EARLY_BRESP_SHIFT));
- - }
- - if (omap_rev() != OMAP4430_REV_ES1_0)
- - omap_smc1(0x109, aux_ctrl);
- -
- - /* Enable PL310 L2 Cache controller */
- - omap_smc1(0x102, 0x1);
- + /* 16-way associativity, parity disabled, way size - 64KB (es2.0 +) */
- + aux_ctrl = L2C_AUX_CTRL_SHARED_OVERRIDE |
- + L310_AUX_CTRL_DATA_PREFETCH |
- + L310_AUX_CTRL_INSTR_PREFETCH;
-
- + outer_cache.write_sec = omap4_l2c310_write_sec;
- if (of_have_populated_dt())
- - l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK);
- + l2x0_of_init(aux_ctrl, 0xcf9fffff);
- else
- - l2x0_init(l2cache_base, aux_ctrl, L2X0_AUX_CTRL_MASK);
- -
- - /*
- - * Override default outer_cache.disable with a OMAP4
- - * specific one
- - */
- - outer_cache.disable = omap4_l2x0_disable;
- - outer_cache.set_debug = omap4_l2x0_set_debug;
- + l2x0_init(l2cache_base, aux_ctrl, 0xcf9fffff);
-
- return 0;
- }
- -omap_early_initcall(omap_l2_cache_init);
- #endif
-
- void __iomem *omap4_get_sar_ram_base(void)
- diff -Nur linux-3.14.35.orig/arch/arm/mach-omap2/omap-mpuss-lowpower.c linux-3.14.35/arch/arm/mach-omap2/omap-mpuss-lowpower.c
- --- linux-3.14.35.orig/arch/arm/mach-omap2/omap-mpuss-lowpower.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-omap2/omap-mpuss-lowpower.c 2015-03-08 14:27:37.433684503 -0500
- @@ -187,19 +187,15 @@
- * in every restore MPUSS OFF path.
- */
- #ifdef CONFIG_CACHE_L2X0
- -static void save_l2x0_context(void)
- +static void __init save_l2x0_context(void)
- {
- - u32 val;
- - void __iomem *l2x0_base = omap4_get_l2cache_base();
- - if (l2x0_base) {
- - val = __raw_readl(l2x0_base + L2X0_AUX_CTRL);
- - __raw_writel(val, sar_base + L2X0_AUXCTRL_OFFSET);
- - val = __raw_readl(l2x0_base + L2X0_PREFETCH_CTRL);
- - __raw_writel(val, sar_base + L2X0_PREFETCH_CTRL_OFFSET);
- - }
- + __raw_writel(l2x0_saved_regs.aux_ctrl,
- + sar_base + L2X0_AUXCTRL_OFFSET);
- + __raw_writel(l2x0_saved_regs.prefetch_ctrl,
- + sar_base + L2X0_PREFETCH_CTRL_OFFSET);
- }
- #else
- -static void save_l2x0_context(void)
- +static void __init save_l2x0_context(void)
- {}
- #endif
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-prima2/l2x0.c linux-3.14.35/arch/arm/mach-prima2/l2x0.c
- --- linux-3.14.35.orig/arch/arm/mach-prima2/l2x0.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-prima2/l2x0.c 2015-03-08 14:27:37.433684503 -0500
- @@ -8,43 +8,10 @@
-
- #include <linux/init.h>
- #include <linux/kernel.h>
- -#include <linux/of.h>
- #include <asm/hardware/cache-l2x0.h>
-
- -struct l2x0_aux
- -{
- - u32 val;
- - u32 mask;
- -};
- -
- -static struct l2x0_aux prima2_l2x0_aux __initconst = {
- - .val = 2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT,
- - .mask = 0,
- -};
- -
- -static struct l2x0_aux marco_l2x0_aux __initconst = {
- - .val = (2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) |
- - (1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT),
- - .mask = L2X0_AUX_CTRL_MASK,
- -};
- -
- -static struct of_device_id sirf_l2x0_ids[] __initconst = {
- - { .compatible = "sirf,prima2-pl310-cache", .data = &prima2_l2x0_aux, },
- - { .compatible = "sirf,marco-pl310-cache", .data = &marco_l2x0_aux, },
- - {},
- -};
- -
- static int __init sirfsoc_l2x0_init(void)
- {
- - struct device_node *np;
- - const struct l2x0_aux *aux;
- -
- - np = of_find_matching_node(NULL, sirf_l2x0_ids);
- - if (np) {
- - aux = of_match_node(sirf_l2x0_ids, np)->data;
- - return l2x0_of_init(aux->val, aux->mask);
- - }
- -
- - return 0;
- + return l2x0_of_init(0, ~0);
- }
- early_initcall(sirfsoc_l2x0_init);
- diff -Nur linux-3.14.35.orig/arch/arm/mach-prima2/pm.c linux-3.14.35/arch/arm/mach-prima2/pm.c
- --- linux-3.14.35.orig/arch/arm/mach-prima2/pm.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-prima2/pm.c 2015-03-08 14:27:37.433684503 -0500
- @@ -71,7 +71,6 @@
- case PM_SUSPEND_MEM:
- sirfsoc_pre_suspend_power_off();
-
- - outer_flush_all();
- outer_disable();
- /* go zzz */
- cpu_suspend(0, sirfsoc_finish_suspend);
- diff -Nur linux-3.14.35.orig/arch/arm/mach-realview/realview_eb.c linux-3.14.35/arch/arm/mach-realview/realview_eb.c
- --- linux-3.14.35.orig/arch/arm/mach-realview/realview_eb.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-realview/realview_eb.c 2015-03-08 14:27:37.433684503 -0500
- @@ -442,8 +442,13 @@
- realview_eb11mp_fixup();
-
- #ifdef CONFIG_CACHE_L2X0
- - /* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
- - * Bits: .... ...0 0111 1001 0000 .... .... .... */
- + /*
- + * The PL220 needs to be manually configured as the hardware
- + * doesn't report the correct sizes.
- + * 1MB (128KB/way), 8-way associativity, event monitor and
- + * parity enabled, ignore share bit, no force write allocate
- + * Bits: .... ...0 0111 1001 0000 .... .... ....
- + */
- l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff);
- #endif
- platform_device_register(&pmu_device);
- diff -Nur linux-3.14.35.orig/arch/arm/mach-realview/realview_pb1176.c linux-3.14.35/arch/arm/mach-realview/realview_pb1176.c
- --- linux-3.14.35.orig/arch/arm/mach-realview/realview_pb1176.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-realview/realview_pb1176.c 2015-03-08 14:27:37.433684503 -0500
- @@ -355,7 +355,13 @@
- int i;
-
- #ifdef CONFIG_CACHE_L2X0
- - /* 128Kb (16Kb/way) 8-way associativity. evmon/parity/share enabled. */
- + /*
- + * The PL220 needs to be manually configured as the hardware
- + * doesn't report the correct sizes.
- + * 128kB (16kB/way), 8-way associativity, event monitor and
- + * parity enabled, ignore share bit, no force write allocate
- + * Bits: .... ...0 0111 0011 0000 .... .... ....
- + */
- l2x0_init(__io_address(REALVIEW_PB1176_L220_BASE), 0x00730000, 0xfe000fff);
- #endif
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-realview/realview_pb11mp.c linux-3.14.35/arch/arm/mach-realview/realview_pb11mp.c
- --- linux-3.14.35.orig/arch/arm/mach-realview/realview_pb11mp.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-realview/realview_pb11mp.c 2015-03-08 14:27:37.433684503 -0500
- @@ -337,8 +337,13 @@
- int i;
-
- #ifdef CONFIG_CACHE_L2X0
- - /* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
- - * Bits: .... ...0 0111 1001 0000 .... .... .... */
- + /*
- + * The PL220 needs to be manually configured as the hardware
- + * doesn't report the correct sizes.
- + * 1MB (128KB/way), 8-way associativity, event monitor and
- + * parity enabled, ignore share bit, no force write allocate
- + * Bits: .... ...0 0111 1001 0000 .... .... ....
- + */
- l2x0_init(__io_address(REALVIEW_TC11MP_L220_BASE), 0x00790000, 0xfe000fff);
- #endif
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-realview/realview_pbx.c linux-3.14.35/arch/arm/mach-realview/realview_pbx.c
- --- linux-3.14.35.orig/arch/arm/mach-realview/realview_pbx.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-realview/realview_pbx.c 2015-03-08 14:27:37.433684503 -0500
- @@ -370,8 +370,8 @@
- __io_address(REALVIEW_PBX_TILE_L220_BASE);
-
- /* set RAM latencies to 1 cycle for eASIC */
- - writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL);
- - writel(0, l2x0_base + L2X0_DATA_LATENCY_CTRL);
- + writel(0, l2x0_base + L310_TAG_LATENCY_CTRL);
- + writel(0, l2x0_base + L310_DATA_LATENCY_CTRL);
-
- /* 16KB way size, 8-way associativity, parity disabled
- * Bits: .. 0 0 0 0 1 00 1 0 1 001 0 000 0 .... .... .... */
- diff -Nur linux-3.14.35.orig/arch/arm/mach-rockchip/rockchip.c linux-3.14.35/arch/arm/mach-rockchip/rockchip.c
- --- linux-3.14.35.orig/arch/arm/mach-rockchip/rockchip.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-rockchip/rockchip.c 2015-03-08 14:27:37.433684503 -0500
- @@ -25,7 +25,7 @@
-
- static void __init rockchip_dt_init(void)
- {
- - l2x0_of_init(0, ~0UL);
- + l2x0_of_init(0, ~0);
- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
- }
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-shmobile/board-armadillo800eva.c linux-3.14.35/arch/arm/mach-shmobile/board-armadillo800eva.c
- --- linux-3.14.35.orig/arch/arm/mach-shmobile/board-armadillo800eva.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-shmobile/board-armadillo800eva.c 2015-03-08 14:27:37.433684503 -0500
- @@ -1270,8 +1270,8 @@
-
-
- #ifdef CONFIG_CACHE_L2X0
- - /* Early BRESP enable, Shared attribute override enable, 32K*8way */
- - l2x0_init(IOMEM(0xf0002000), 0x40440000, 0x82000fff);
- + /* Shared attribute override enable, 32K*8way */
- + l2x0_init(IOMEM(0xf0002000), 0x00400000, 0xc20f0fff);
- #endif
-
- i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices));
- diff -Nur linux-3.14.35.orig/arch/arm/mach-shmobile/board-armadillo800eva-reference.c linux-3.14.35/arch/arm/mach-shmobile/board-armadillo800eva-reference.c
- --- linux-3.14.35.orig/arch/arm/mach-shmobile/board-armadillo800eva-reference.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-shmobile/board-armadillo800eva-reference.c 2015-03-08 14:27:37.433684503 -0500
- @@ -164,8 +164,8 @@
- r8a7740_meram_workaround();
-
- #ifdef CONFIG_CACHE_L2X0
- - /* Early BRESP enable, Shared attribute override enable, 32K*8way */
- - l2x0_init(IOMEM(0xf0002000), 0x40440000, 0x82000fff);
- + /* Shared attribute override enable, 32K*8way */
- + l2x0_init(IOMEM(0xf0002000), 0x00400000, 0xc20f0fff);
- #endif
-
- r8a7740_add_standard_devices_dt();
- diff -Nur linux-3.14.35.orig/arch/arm/mach-shmobile/board-kzm9g.c linux-3.14.35/arch/arm/mach-shmobile/board-kzm9g.c
- --- linux-3.14.35.orig/arch/arm/mach-shmobile/board-kzm9g.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-shmobile/board-kzm9g.c 2015-03-08 14:27:37.433684503 -0500
- @@ -878,8 +878,8 @@
- gpio_request_one(223, GPIOF_IN, NULL); /* IRQ8 */
-
- #ifdef CONFIG_CACHE_L2X0
- - /* Early BRESP enable, Shared attribute override enable, 64K*8way */
- - l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff);
- + /* Shared attribute override enable, 64K*8way */
- + l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff);
- #endif
-
- i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices));
- diff -Nur linux-3.14.35.orig/arch/arm/mach-shmobile/board-kzm9g-reference.c linux-3.14.35/arch/arm/mach-shmobile/board-kzm9g-reference.c
- --- linux-3.14.35.orig/arch/arm/mach-shmobile/board-kzm9g-reference.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-shmobile/board-kzm9g-reference.c 2015-03-08 14:27:37.433684503 -0500
- @@ -36,8 +36,8 @@
- sh73a0_add_standard_devices_dt();
-
- #ifdef CONFIG_CACHE_L2X0
- - /* Early BRESP enable, Shared attribute override enable, 64K*8way */
- - l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff);
- + /* Shared attribute override enable, 64K*8way */
- + l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff);
- #endif
- }
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-shmobile/setup-r8a7778.c linux-3.14.35/arch/arm/mach-shmobile/setup-r8a7778.c
- --- linux-3.14.35.orig/arch/arm/mach-shmobile/setup-r8a7778.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-shmobile/setup-r8a7778.c 2015-03-08 14:27:37.433684503 -0500
- @@ -298,10 +298,10 @@
- void __iomem *base = ioremap_nocache(0xf0100000, 0x1000);
- if (base) {
- /*
- - * Early BRESP enable, Shared attribute override enable, 64K*16way
- + * Shared attribute override enable, 64K*16way
- * don't call iounmap(base)
- */
- - l2x0_init(base, 0x40470000, 0x82000fff);
- + l2x0_init(base, 0x00400000, 0xc20f0fff);
- }
- #endif
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-shmobile/setup-r8a7779.c linux-3.14.35/arch/arm/mach-shmobile/setup-r8a7779.c
- --- linux-3.14.35.orig/arch/arm/mach-shmobile/setup-r8a7779.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-shmobile/setup-r8a7779.c 2015-03-08 14:27:37.433684503 -0500
- @@ -700,8 +700,8 @@
- void __init r8a7779_add_standard_devices(void)
- {
- #ifdef CONFIG_CACHE_L2X0
- - /* Early BRESP enable, Shared attribute override enable, 64K*16way */
- - l2x0_init(IOMEM(0xf0100000), 0x40470000, 0x82000fff);
- + /* Shared attribute override enable, 64K*16way */
- + l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff);
- #endif
- r8a7779_pm_init();
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-socfpga/socfpga.c linux-3.14.35/arch/arm/mach-socfpga/socfpga.c
- --- linux-3.14.35.orig/arch/arm/mach-socfpga/socfpga.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-socfpga/socfpga.c 2015-03-08 14:27:37.437684503 -0500
- @@ -104,7 +104,7 @@
-
- static void __init socfpga_cyclone5_init(void)
- {
- - l2x0_of_init(0, ~0UL);
- + l2x0_of_init(0, ~0);
- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
- socfpga_init_clocks();
- }
- diff -Nur linux-3.14.35.orig/arch/arm/mach-spear/platsmp.c linux-3.14.35/arch/arm/mach-spear/platsmp.c
- --- linux-3.14.35.orig/arch/arm/mach-spear/platsmp.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-spear/platsmp.c 2015-03-08 14:27:37.437684503 -0500
- @@ -20,6 +20,18 @@
- #include <mach/spear.h>
- #include "generic.h"
-
- +/*
- + * Write pen_release in a way that is guaranteed to be visible to all
- + * observers, irrespective of whether they're taking part in coherency
- + * or not. This is necessary for the hotplug code to work reliably.
- + */
- +static void write_pen_release(int val)
- +{
- + pen_release = val;
- + smp_wmb();
- + sync_cache_w(&pen_release);
- +}
- +
- static DEFINE_SPINLOCK(boot_lock);
-
- static void __iomem *scu_base = IOMEM(VA_SCU_BASE);
- @@ -30,8 +42,7 @@
- * let the primary processor know we're out of the
- * pen, then head off into the C entry point
- */
- - pen_release = -1;
- - smp_wmb();
- + write_pen_release(-1);
-
- /*
- * Synchronise with the boot thread.
- @@ -58,9 +69,7 @@
- * Note that "pen_release" is the hardware CPU ID, whereas
- * "cpu" is Linux's internal ID.
- */
- - pen_release = cpu;
- - flush_cache_all();
- - outer_flush_all();
- + write_pen_release(cpu);
-
- timeout = jiffies + (1 * HZ);
- while (time_before(jiffies, timeout)) {
- diff -Nur linux-3.14.35.orig/arch/arm/mach-spear/spear13xx.c linux-3.14.35/arch/arm/mach-spear/spear13xx.c
- --- linux-3.14.35.orig/arch/arm/mach-spear/spear13xx.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-spear/spear13xx.c 2015-03-08 14:27:37.437684503 -0500
- @@ -38,15 +38,15 @@
- if (!IS_ENABLED(CONFIG_CACHE_L2X0))
- return;
-
- - writel_relaxed(0x06, VA_L2CC_BASE + L2X0_PREFETCH_CTRL);
- + writel_relaxed(0x06, VA_L2CC_BASE + L310_PREFETCH_CTRL);
-
- /*
- * Program following latencies in order to make
- * SPEAr1340 work at 600 MHz
- */
- - writel_relaxed(0x221, VA_L2CC_BASE + L2X0_TAG_LATENCY_CTRL);
- - writel_relaxed(0x441, VA_L2CC_BASE + L2X0_DATA_LATENCY_CTRL);
- - l2x0_init(VA_L2CC_BASE, 0x70A60001, 0xfe00ffff);
- + writel_relaxed(0x221, VA_L2CC_BASE + L310_TAG_LATENCY_CTRL);
- + writel_relaxed(0x441, VA_L2CC_BASE + L310_DATA_LATENCY_CTRL);
- + l2x0_init(VA_L2CC_BASE, 0x30a00001, 0xfe0fffff);
- }
-
- /*
- diff -Nur linux-3.14.35.orig/arch/arm/mach-sti/board-dt.c linux-3.14.35/arch/arm/mach-sti/board-dt.c
- --- linux-3.14.35.orig/arch/arm/mach-sti/board-dt.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-sti/board-dt.c 2015-03-08 14:27:37.437684503 -0500
- @@ -16,15 +16,9 @@
-
- void __init stih41x_l2x0_init(void)
- {
- - u32 way_size = 0x4;
- - u32 aux_ctrl;
- - /* may be this can be encoded in macros like BIT*() */
- - aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
- - (0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
- - (0x1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
- - (way_size << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
- -
- - l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK);
- + l2x0_of_init(L2C_AUX_CTRL_SHARED_OVERRIDE |
- + L310_AUX_CTRL_DATA_PREFETCH |
- + L310_AUX_CTRL_INSTR_PREFETCH, 0xc00f0fff);
- }
-
- static void __init stih41x_machine_init(void)
- diff -Nur linux-3.14.35.orig/arch/arm/mach-tegra/pm.h linux-3.14.35/arch/arm/mach-tegra/pm.h
- --- linux-3.14.35.orig/arch/arm/mach-tegra/pm.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-tegra/pm.h 2015-03-08 14:27:37.437684503 -0500
- @@ -35,8 +35,6 @@
- void tegra30_lp1_iram_hook(void);
- void tegra30_sleep_core_init(void);
-
- -extern unsigned long l2x0_saved_regs_addr;
- -
- void tegra_clear_cpu_in_lp2(void);
- bool tegra_set_cpu_in_lp2(void);
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-tegra/reset-handler.S linux-3.14.35/arch/arm/mach-tegra/reset-handler.S
- --- linux-3.14.35.orig/arch/arm/mach-tegra/reset-handler.S 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-tegra/reset-handler.S 2015-03-08 14:27:37.437684503 -0500
- @@ -19,7 +19,6 @@
-
- #include <asm/cache.h>
- #include <asm/asm-offsets.h>
- -#include <asm/hardware/cache-l2x0.h>
-
- #include "flowctrl.h"
- #include "fuse.h"
- @@ -79,8 +78,10 @@
- str r1, [r0]
- #endif
-
- +#ifdef CONFIG_CACHE_L2X0
- /* L2 cache resume & re-enable */
- - l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr
- + bl l2c310_early_resume
- +#endif
- end_ca9_scu_l2_resume:
- mov32 r9, 0xc0f
- cmp r8, r9
- @@ -90,12 +91,6 @@
- ENDPROC(tegra_resume)
- #endif
-
- -#ifdef CONFIG_CACHE_L2X0
- - .globl l2x0_saved_regs_addr
- -l2x0_saved_regs_addr:
- - .long 0
- -#endif
- -
- .align L1_CACHE_SHIFT
- ENTRY(__tegra_cpu_reset_handler_start)
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-tegra/sleep.h linux-3.14.35/arch/arm/mach-tegra/sleep.h
- --- linux-3.14.35.orig/arch/arm/mach-tegra/sleep.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-tegra/sleep.h 2015-03-08 14:27:37.437684503 -0500
- @@ -120,37 +120,6 @@
- mov \tmp1, \tmp1, lsr #8
- .endm
-
- -/* Macro to resume & re-enable L2 cache */
- -#ifndef L2X0_CTRL_EN
- -#define L2X0_CTRL_EN 1
- -#endif
- -
- -#ifdef CONFIG_CACHE_L2X0
- -.macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs
- - W(adr) \tmp1, \phys_l2x0_saved_regs
- - ldr \tmp1, [\tmp1]
- - ldr \tmp2, [\tmp1, #L2X0_R_PHY_BASE]
- - ldr \tmp3, [\tmp2, #L2X0_CTRL]
- - tst \tmp3, #L2X0_CTRL_EN
- - bne exit_l2_resume
- - ldr \tmp3, [\tmp1, #L2X0_R_TAG_LATENCY]
- - str \tmp3, [\tmp2, #L2X0_TAG_LATENCY_CTRL]
- - ldr \tmp3, [\tmp1, #L2X0_R_DATA_LATENCY]
- - str \tmp3, [\tmp2, #L2X0_DATA_LATENCY_CTRL]
- - ldr \tmp3, [\tmp1, #L2X0_R_PREFETCH_CTRL]
- - str \tmp3, [\tmp2, #L2X0_PREFETCH_CTRL]
- - ldr \tmp3, [\tmp1, #L2X0_R_PWR_CTRL]
- - str \tmp3, [\tmp2, #L2X0_POWER_CTRL]
- - ldr \tmp3, [\tmp1, #L2X0_R_AUX_CTRL]
- - str \tmp3, [\tmp2, #L2X0_AUX_CTRL]
- - mov \tmp3, #L2X0_CTRL_EN
- - str \tmp3, [\tmp2, #L2X0_CTRL]
- -exit_l2_resume:
- -.endm
- -#else /* CONFIG_CACHE_L2X0 */
- -.macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs
- -.endm
- -#endif /* CONFIG_CACHE_L2X0 */
- #else
- void tegra_pen_lock(void);
- void tegra_pen_unlock(void);
- diff -Nur linux-3.14.35.orig/arch/arm/mach-tegra/tegra.c linux-3.14.35/arch/arm/mach-tegra/tegra.c
- --- linux-3.14.35.orig/arch/arm/mach-tegra/tegra.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-tegra/tegra.c 2015-03-08 14:27:37.437684503 -0500
- @@ -73,27 +73,7 @@
- static void __init tegra_init_cache(void)
- {
- #ifdef CONFIG_CACHE_L2X0
- - static const struct of_device_id pl310_ids[] __initconst = {
- - { .compatible = "arm,pl310-cache", },
- - {}
- - };
- -
- - struct device_node *np;
- - int ret;
- - void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
- - u32 aux_ctrl, cache_type;
- -
- - np = of_find_matching_node(NULL, pl310_ids);
- - if (!np)
- - return;
- -
- - cache_type = readl(p + L2X0_CACHE_TYPE);
- - aux_ctrl = (cache_type & 0x700) << (17-8);
- - aux_ctrl |= 0x7C400001;
- -
- - ret = l2x0_of_init(aux_ctrl, 0x8200c3fe);
- - if (!ret)
- - l2x0_saved_regs_addr = virt_to_phys(&l2x0_saved_regs);
- + l2x0_of_init(0x3c400001, 0xc20fc3fe);
- #endif
- }
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-ux500/board-mop500-audio.c linux-3.14.35/arch/arm/mach-ux500/board-mop500-audio.c
- --- linux-3.14.35.orig/arch/arm/mach-ux500/board-mop500-audio.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-ux500/board-mop500-audio.c 2015-03-08 14:27:37.437684503 -0500
- @@ -9,7 +9,6 @@
- #include <linux/gpio.h>
- #include <linux/platform_data/dma-ste-dma40.h>
-
- -#include "irqs.h"
- #include <linux/platform_data/asoc-ux500-msp.h>
-
- #include "ste-dma40-db8500.h"
- diff -Nur linux-3.14.35.orig/arch/arm/mach-ux500/cache-l2x0.c linux-3.14.35/arch/arm/mach-ux500/cache-l2x0.c
- --- linux-3.14.35.orig/arch/arm/mach-ux500/cache-l2x0.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-ux500/cache-l2x0.c 2015-03-08 14:27:37.437684503 -0500
- @@ -35,10 +35,16 @@
- return 0;
- }
-
- -static int __init ux500_l2x0_init(void)
- +static void ux500_l2c310_write_sec(unsigned long val, unsigned reg)
- {
- - u32 aux_val = 0x3e000000;
- + /*
- + * We can't write to secure registers as we are in non-secure
- + * mode, until we have some SMI service available.
- + */
- +}
-
- +static int __init ux500_l2x0_init(void)
- +{
- if (cpu_is_u8500_family() || cpu_is_ux540_family())
- l2x0_base = __io_address(U8500_L2CC_BASE);
- else
- @@ -48,28 +54,12 @@
- /* Unlock before init */
- ux500_l2x0_unlock();
-
- - /* DBx540's L2 has 128KB way size */
- - if (cpu_is_ux540_family())
- - /* 128KB way size */
- - aux_val |= (0x4 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
- - else
- - /* 64KB way size */
- - aux_val |= (0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
- + outer_cache.write_sec = ux500_l2c310_write_sec;
-
- - /* 64KB way size, 8 way associativity, force WA */
- if (of_have_populated_dt())
- - l2x0_of_init(aux_val, 0xc0000fff);
- + l2x0_of_init(0, ~0);
- else
- - l2x0_init(l2x0_base, aux_val, 0xc0000fff);
- -
- - /*
- - * We can't disable l2 as we are in non secure mode, currently
- - * this seems be called only during kexec path. So let's
- - * override outer.disable with nasty assignment until we have
- - * some SMI service available.
- - */
- - outer_cache.disable = NULL;
- - outer_cache.set_debug = NULL;
- + l2x0_init(l2x0_base, 0, ~0);
-
- return 0;
- }
- diff -Nur linux-3.14.35.orig/arch/arm/mach-ux500/cpu-db8500.c linux-3.14.35/arch/arm/mach-ux500/cpu-db8500.c
- --- linux-3.14.35.orig/arch/arm/mach-ux500/cpu-db8500.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-ux500/cpu-db8500.c 2015-03-08 14:27:37.437684503 -0500
- @@ -27,7 +27,6 @@
- #include <asm/mach/map.h>
-
- #include "setup.h"
- -#include "irqs.h"
-
- #include "board-mop500-regulators.h"
- #include "board-mop500.h"
- @@ -35,14 +34,11 @@
- #include "id.h"
-
- struct ab8500_platform_data ab8500_platdata = {
- - .irq_base = MOP500_AB8500_IRQ_BASE,
- .regulator = &ab8500_regulator_plat_data,
- };
-
- struct prcmu_pdata db8500_prcmu_pdata = {
- .ab_platdata = &ab8500_platdata,
- - .ab_irq = IRQ_DB8500_AB8500,
- - .irq_base = IRQ_PRCMU_BASE,
- .version_offset = DB8500_PRCMU_FW_VERSION_OFFSET,
- .legacy_offset = DB8500_PRCMU_LEGACY_OFFSET,
- };
- diff -Nur linux-3.14.35.orig/arch/arm/mach-ux500/irqs-board-mop500.h linux-3.14.35/arch/arm/mach-ux500/irqs-board-mop500.h
- --- linux-3.14.35.orig/arch/arm/mach-ux500/irqs-board-mop500.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-ux500/irqs-board-mop500.h 1969-12-31 18:00:00.000000000 -0600
- @@ -1,55 +0,0 @@
- -/*
- - * Copyright (C) ST-Ericsson SA 2010
- - *
- - * Author: Rabin Vincent <rabin.vincent@stericsson.com>
- - * License terms: GNU General Public License (GPL) version 2
- - */
- -
- -#ifndef __MACH_IRQS_BOARD_MOP500_H
- -#define __MACH_IRQS_BOARD_MOP500_H
- -
- -/* Number of AB8500 irqs is taken from header file */
- -#include <linux/mfd/abx500/ab8500.h>
- -
- -#define MOP500_AB8500_IRQ_BASE IRQ_BOARD_START
- -#define MOP500_AB8500_IRQ_END (MOP500_AB8500_IRQ_BASE \
- - + AB8500_MAX_NR_IRQS)
- -
- -/* TC35892 */
- -#define TC35892_NR_INTERNAL_IRQS 8
- -#define TC35892_INT_GPIO(x) (TC35892_NR_INTERNAL_IRQS + (x))
- -#define TC35892_NR_GPIOS 24
- -#define TC35892_NR_IRQS TC35892_INT_GPIO(TC35892_NR_GPIOS)
- -
- -#define MOP500_EGPIO_NR_IRQS TC35892_NR_IRQS
- -
- -#define MOP500_EGPIO_IRQ_BASE MOP500_AB8500_IRQ_END
- -#define MOP500_EGPIO_IRQ_END (MOP500_EGPIO_IRQ_BASE \
- - + MOP500_EGPIO_NR_IRQS)
- -/* STMPE1601 irqs */
- -#define STMPE_NR_INTERNAL_IRQS 9
- -#define STMPE_INT_GPIO(x) (STMPE_NR_INTERNAL_IRQS + (x))
- -#define STMPE_NR_GPIOS 24
- -#define STMPE_NR_IRQS STMPE_INT_GPIO(STMPE_NR_GPIOS)
- -
- -#define MOP500_STMPE1601_IRQBASE MOP500_EGPIO_IRQ_END
- -#define MOP500_STMPE1601_IRQ(x) (MOP500_STMPE1601_IRQBASE + (x))
- -
- -#define MOP500_STMPE1601_IRQ_END \
- - MOP500_STMPE1601_IRQ(STMPE_NR_INTERNAL_IRQS)
- -
- -#define MOP500_NR_IRQS MOP500_STMPE1601_IRQ_END
- -
- -#define MOP500_IRQ_END MOP500_NR_IRQS
- -
- -/*
- - * We may have several boards, but only one will run at a
- - * time, so the one with most IRQs will bump this ahead,
- - * but the IRQ_BOARD_START remains the same for either board.
- - */
- -#if MOP500_IRQ_END > IRQ_BOARD_END
- -#undef IRQ_BOARD_END
- -#define IRQ_BOARD_END MOP500_IRQ_END
- -#endif
- -
- -#endif
- diff -Nur linux-3.14.35.orig/arch/arm/mach-ux500/irqs-db8500.h linux-3.14.35/arch/arm/mach-ux500/irqs-db8500.h
- --- linux-3.14.35.orig/arch/arm/mach-ux500/irqs-db8500.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-ux500/irqs-db8500.h 1969-12-31 18:00:00.000000000 -0600
- @@ -1,125 +0,0 @@
- -/*
- - * Copyright (C) ST-Ericsson SA 2010
- - *
- - * Author: Rabin Vincent <rabin.vincent@stericsson.com>
- - * License terms: GNU General Public License (GPL) version 2
- - */
- -
- -#ifndef __MACH_IRQS_DB8500_H
- -#define __MACH_IRQS_DB8500_H
- -
- -#define IRQ_DB8500_MTU0 (IRQ_SHPI_START + 4)
- -#define IRQ_DB8500_SPI2 (IRQ_SHPI_START + 6)
- -#define IRQ_DB8500_PMU (IRQ_SHPI_START + 7)
- -#define IRQ_DB8500_SPI0 (IRQ_SHPI_START + 8)
- -#define IRQ_DB8500_RTT (IRQ_SHPI_START + 9)
- -#define IRQ_DB8500_PKA (IRQ_SHPI_START + 10)
- -#define IRQ_DB8500_UART0 (IRQ_SHPI_START + 11)
- -#define IRQ_DB8500_I2C3 (IRQ_SHPI_START + 12)
- -#define IRQ_DB8500_L2CC (IRQ_SHPI_START + 13)
- -#define IRQ_DB8500_SSP0 (IRQ_SHPI_START + 14)
- -#define IRQ_DB8500_CRYP1 (IRQ_SHPI_START + 15)
- -#define IRQ_DB8500_MSP1_RX (IRQ_SHPI_START + 16)
- -#define IRQ_DB8500_MTU1 (IRQ_SHPI_START + 17)
- -#define IRQ_DB8500_RTC (IRQ_SHPI_START + 18)
- -#define IRQ_DB8500_UART1 (IRQ_SHPI_START + 19)
- -#define IRQ_DB8500_USB_WAKEUP (IRQ_SHPI_START + 20)
- -#define IRQ_DB8500_I2C0 (IRQ_SHPI_START + 21)
- -#define IRQ_DB8500_I2C1 (IRQ_SHPI_START + 22)
- -#define IRQ_DB8500_USBOTG (IRQ_SHPI_START + 23)
- -#define IRQ_DB8500_DMA_SECURE (IRQ_SHPI_START + 24)
- -#define IRQ_DB8500_DMA (IRQ_SHPI_START + 25)
- -#define IRQ_DB8500_UART2 (IRQ_SHPI_START + 26)
- -#define IRQ_DB8500_ICN_PMU1 (IRQ_SHPI_START + 27)
- -#define IRQ_DB8500_ICN_PMU2 (IRQ_SHPI_START + 28)
- -#define IRQ_DB8500_HSIR_EXCEP (IRQ_SHPI_START + 29)
- -#define IRQ_DB8500_MSP0 (IRQ_SHPI_START + 31)
- -#define IRQ_DB8500_HSIR_CH0_OVRRUN (IRQ_SHPI_START + 32)
- -#define IRQ_DB8500_HSIR_CH1_OVRRUN (IRQ_SHPI_START + 33)
- -#define IRQ_DB8500_HSIR_CH2_OVRRUN (IRQ_SHPI_START + 34)
- -#define IRQ_DB8500_HSIR_CH3_OVRRUN (IRQ_SHPI_START + 35)
- -#define IRQ_DB8500_HSIR_CH4_OVRRUN (IRQ_SHPI_START + 36)
- -#define IRQ_DB8500_HSIR_CH5_OVRRUN (IRQ_SHPI_START + 37)
- -#define IRQ_DB8500_HSIR_CH6_OVRRUN (IRQ_SHPI_START + 38)
- -#define IRQ_DB8500_HSIR_CH7_OVRRUN (IRQ_SHPI_START + 39)
- -#define IRQ_DB8500_AB8500 (IRQ_SHPI_START + 40)
- -#define IRQ_DB8500_SDMMC2 (IRQ_SHPI_START + 41)
- -#define IRQ_DB8500_SIA (IRQ_SHPI_START + 42)
- -#define IRQ_DB8500_SIA2 (IRQ_SHPI_START + 43)
- -#define IRQ_DB8500_SVA (IRQ_SHPI_START + 44)
- -#define IRQ_DB8500_SVA2 (IRQ_SHPI_START + 45)
- -#define IRQ_DB8500_PRCMU0 (IRQ_SHPI_START + 46)
- -#define IRQ_DB8500_PRCMU1 (IRQ_SHPI_START + 47)
- -#define IRQ_DB8500_DISP (IRQ_SHPI_START + 48)
- -#define IRQ_DB8500_SPI3 (IRQ_SHPI_START + 49)
- -#define IRQ_DB8500_SDMMC1 (IRQ_SHPI_START + 50)
- -#define IRQ_DB8500_I2C4 (IRQ_SHPI_START + 51)
- -#define IRQ_DB8500_SSP1 (IRQ_SHPI_START + 52)
- -#define IRQ_DB8500_SKE (IRQ_SHPI_START + 53)
- -#define IRQ_DB8500_KB (IRQ_SHPI_START + 54)
- -#define IRQ_DB8500_I2C2 (IRQ_SHPI_START + 55)
- -#define IRQ_DB8500_B2R2 (IRQ_SHPI_START + 56)
- -#define IRQ_DB8500_CRYP0 (IRQ_SHPI_START + 57)
- -#define IRQ_DB8500_SDMMC3 (IRQ_SHPI_START + 59)
- -#define IRQ_DB8500_SDMMC0 (IRQ_SHPI_START + 60)
- -#define IRQ_DB8500_HSEM (IRQ_SHPI_START + 61)
- -#define IRQ_DB8500_MSP1 (IRQ_SHPI_START + 62)
- -#define IRQ_DB8500_SBAG (IRQ_SHPI_START + 63)
- -#define IRQ_DB8500_SPI1 (IRQ_SHPI_START + 96)
- -#define IRQ_DB8500_SRPTIMER (IRQ_SHPI_START + 97)
- -#define IRQ_DB8500_MSP2 (IRQ_SHPI_START + 98)
- -#define IRQ_DB8500_SDMMC4 (IRQ_SHPI_START + 99)
- -#define IRQ_DB8500_SDMMC5 (IRQ_SHPI_START + 100)
- -#define IRQ_DB8500_HSIRD0 (IRQ_SHPI_START + 104)
- -#define IRQ_DB8500_HSIRD1 (IRQ_SHPI_START + 105)
- -#define IRQ_DB8500_HSITD0 (IRQ_SHPI_START + 106)
- -#define IRQ_DB8500_HSITD1 (IRQ_SHPI_START + 107)
- -#define IRQ_DB8500_CTI0 (IRQ_SHPI_START + 108)
- -#define IRQ_DB8500_CTI1 (IRQ_SHPI_START + 109)
- -#define IRQ_DB8500_ICN_ERR (IRQ_SHPI_START + 110)
- -#define IRQ_DB8500_MALI_PPMMU (IRQ_SHPI_START + 112)
- -#define IRQ_DB8500_MALI_PP (IRQ_SHPI_START + 113)
- -#define IRQ_DB8500_MALI_GPMMU (IRQ_SHPI_START + 114)
- -#define IRQ_DB8500_MALI_GP (IRQ_SHPI_START + 115)
- -#define IRQ_DB8500_MALI (IRQ_SHPI_START + 116)
- -#define IRQ_DB8500_PRCMU_SEM (IRQ_SHPI_START + 118)
- -#define IRQ_DB8500_GPIO0 (IRQ_SHPI_START + 119)
- -#define IRQ_DB8500_GPIO1 (IRQ_SHPI_START + 120)
- -#define IRQ_DB8500_GPIO2 (IRQ_SHPI_START + 121)
- -#define IRQ_DB8500_GPIO3 (IRQ_SHPI_START + 122)
- -#define IRQ_DB8500_GPIO4 (IRQ_SHPI_START + 123)
- -#define IRQ_DB8500_GPIO5 (IRQ_SHPI_START + 124)
- -#define IRQ_DB8500_GPIO6 (IRQ_SHPI_START + 125)
- -#define IRQ_DB8500_GPIO7 (IRQ_SHPI_START + 126)
- -#define IRQ_DB8500_GPIO8 (IRQ_SHPI_START + 127)
- -
- -#define IRQ_CA_WAKE_REQ_ED (IRQ_SHPI_START + 71)
- -#define IRQ_AC_READ_NOTIFICATION_0_ED (IRQ_SHPI_START + 66)
- -#define IRQ_AC_READ_NOTIFICATION_1_ED (IRQ_SHPI_START + 64)
- -#define IRQ_CA_MSG_PEND_NOTIFICATION_0_ED (IRQ_SHPI_START + 67)
- -#define IRQ_CA_MSG_PEND_NOTIFICATION_1_ED (IRQ_SHPI_START + 65)
- -
- -#define IRQ_CA_WAKE_REQ_V1 (IRQ_SHPI_START + 83)
- -#define IRQ_AC_READ_NOTIFICATION_0_V1 (IRQ_SHPI_START + 78)
- -#define IRQ_AC_READ_NOTIFICATION_1_V1 (IRQ_SHPI_START + 76)
- -#define IRQ_CA_MSG_PEND_NOTIFICATION_0_V1 (IRQ_SHPI_START + 79)
- -#define IRQ_CA_MSG_PEND_NOTIFICATION_1_V1 (IRQ_SHPI_START + 77)
- -
- -#ifdef CONFIG_UX500_SOC_DB8500
- -
- -/* Virtual interrupts corresponding to the PRCMU wakeups. */
- -#define IRQ_PRCMU_BASE IRQ_SOC_START
- -#define IRQ_PRCMU_END (IRQ_PRCMU_BASE + 23)
- -
- -/*
- - * We may have several SoCs, but only one will run at a
- - * time, so the one with most IRQs will bump this ahead,
- - * but the IRQ_SOC_START remains the same for either SoC.
- - */
- -#if IRQ_SOC_END < IRQ_PRCMU_END
- -#undef IRQ_SOC_END
- -#define IRQ_SOC_END IRQ_PRCMU_END
- -#endif
- -
- -#endif /* CONFIG_UX500_SOC_DB8500 */
- -#endif
- diff -Nur linux-3.14.35.orig/arch/arm/mach-ux500/irqs.h linux-3.14.35/arch/arm/mach-ux500/irqs.h
- --- linux-3.14.35.orig/arch/arm/mach-ux500/irqs.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-ux500/irqs.h 1969-12-31 18:00:00.000000000 -0600
- @@ -1,49 +0,0 @@
- -/*
- - * Copyright (C) 2008 STMicroelectronics
- - * Copyright (C) 2009 ST-Ericsson.
- - *
- - * 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.
- - */
- -#ifndef ASM_ARCH_IRQS_H
- -#define ASM_ARCH_IRQS_H
- -
- -#define IRQ_LOCALTIMER 29
- -#define IRQ_LOCALWDOG 30
- -
- -/* Shared Peripheral Interrupt (SHPI) */
- -#define IRQ_SHPI_START 32
- -
- -/*
- - * MTU0 preserved for now until plat-nomadik is taught not to use it. Don't
- - * add any other IRQs here, use the irqs-dbx500.h files.
- - */
- -#define IRQ_MTU0 (IRQ_SHPI_START + 4)
- -
- -#define DBX500_NR_INTERNAL_IRQS 166
- -
- -/* After chip-specific IRQ numbers we have the GPIO ones */
- -#define NOMADIK_NR_GPIO 288
- -#define NOMADIK_GPIO_TO_IRQ(gpio) ((gpio) + DBX500_NR_INTERNAL_IRQS)
- -#define NOMADIK_IRQ_TO_GPIO(irq) ((irq) - DBX500_NR_INTERNAL_IRQS)
- -#define IRQ_GPIO_END NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO)
- -
- -#define IRQ_SOC_START IRQ_GPIO_END
- -/* This will be overridden by SoC-specific irq headers */
- -#define IRQ_SOC_END IRQ_SOC_START
- -
- -#include "irqs-db8500.h"
- -
- -#define IRQ_BOARD_START IRQ_SOC_END
- -/* This will be overridden by board-specific irq headers */
- -#define IRQ_BOARD_END IRQ_BOARD_START
- -
- -#ifdef CONFIG_MACH_MOP500
- -#include "irqs-board-mop500.h"
- -#endif
- -
- -#define UX500_NR_IRQS IRQ_BOARD_END
- -
- -#endif /* ASM_ARCH_IRQS_H */
- diff -Nur linux-3.14.35.orig/arch/arm/mach-vexpress/ct-ca9x4.c linux-3.14.35/arch/arm/mach-vexpress/ct-ca9x4.c
- --- linux-3.14.35.orig/arch/arm/mach-vexpress/ct-ca9x4.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-vexpress/ct-ca9x4.c 2015-03-08 14:27:37.437684503 -0500
- @@ -45,6 +45,23 @@
- iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
- }
-
- +static void __init ca9x4_l2_init(void)
- +{
- +#ifdef CONFIG_CACHE_L2X0
- + void __iomem *l2x0_base = ioremap(CT_CA9X4_L2CC, SZ_4K);
- +
- + if (l2x0_base) {
- + /* set RAM latencies to 1 cycle for this core tile. */
- + writel(0, l2x0_base + L310_TAG_LATENCY_CTRL);
- + writel(0, l2x0_base + L310_DATA_LATENCY_CTRL);
- +
- + l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff);
- + } else {
- + pr_err("L2C: unable to map L2 cache controller\n");
- + }
- +#endif
- +}
- +
- #ifdef CONFIG_HAVE_ARM_TWD
- static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, A9_MPCORE_TWD, IRQ_LOCALTIMER);
-
- @@ -63,6 +80,7 @@
- gic_init(0, 29, ioremap(A9_MPCORE_GIC_DIST, SZ_4K),
- ioremap(A9_MPCORE_GIC_CPU, SZ_256));
- ca9x4_twd_init();
- + ca9x4_l2_init();
- }
-
- static int ct_ca9x4_clcd_setup(struct clcd_fb *fb)
- @@ -141,16 +159,6 @@
- {
- int i;
-
- -#ifdef CONFIG_CACHE_L2X0
- - void __iomem *l2x0_base = ioremap(CT_CA9X4_L2CC, SZ_4K);
- -
- - /* set RAM latencies to 1 cycle for this core tile. */
- - writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL);
- - writel(0, l2x0_base + L2X0_DATA_LATENCY_CTRL);
- -
- - l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff);
- -#endif
- -
- for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++)
- amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource);
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-vexpress/dcscb.c linux-3.14.35/arch/arm/mach-vexpress/dcscb.c
- --- linux-3.14.35.orig/arch/arm/mach-vexpress/dcscb.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-vexpress/dcscb.c 2015-03-08 14:27:37.437684503 -0500
- @@ -23,6 +23,7 @@
- #include <asm/cacheflush.h>
- #include <asm/cputype.h>
- #include <asm/cp15.h>
- +#include <asm/psci.h>
-
-
- #define RST_HOLD0 0x0
- @@ -193,6 +194,12 @@
- unsigned int cfg;
- int ret;
-
- + ret = psci_probe();
- + if (!ret) {
- + pr_debug("psci found. Aborting native init\n");
- + return -ENODEV;
- + }
- +
- if (!cci_probed())
- return -ENODEV;
-
- diff -Nur linux-3.14.35.orig/arch/arm/mach-vexpress/Kconfig linux-3.14.35/arch/arm/mach-vexpress/Kconfig
- --- linux-3.14.35.orig/arch/arm/mach-vexpress/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-vexpress/Kconfig 2015-03-08 14:27:37.437684503 -0500
- @@ -55,6 +55,7 @@
-
- config ARCH_VEXPRESS_CA9X4
- bool "Versatile Express Cortex-A9x4 tile"
- + select ARM_ERRATA_643719
-
- config ARCH_VEXPRESS_DCSCB
- bool "Dual Cluster System Control Block (DCSCB) support"
- diff -Nur linux-3.14.35.orig/arch/arm/mach-vexpress/Makefile linux-3.14.35/arch/arm/mach-vexpress/Makefile
- --- linux-3.14.35.orig/arch/arm/mach-vexpress/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-vexpress/Makefile 2015-03-08 14:27:37.437684503 -0500
- @@ -8,8 +8,15 @@
- obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o
- obj-$(CONFIG_ARCH_VEXPRESS_DCSCB) += dcscb.o dcscb_setup.o
- CFLAGS_dcscb.o += -march=armv7-a
- +CFLAGS_REMOVE_dcscb.o = -pg
- obj-$(CONFIG_ARCH_VEXPRESS_SPC) += spc.o
- +CFLAGS_REMOVE_spc.o = -pg
- obj-$(CONFIG_ARCH_VEXPRESS_TC2_PM) += tc2_pm.o
- CFLAGS_tc2_pm.o += -march=armv7-a
- +CFLAGS_REMOVE_tc2_pm.o = -pg
- +ifeq ($(CONFIG_ARCH_VEXPRESS_TC2_PM),y)
- +obj-$(CONFIG_ARM_PSCI) += tc2_pm_psci.o
- +CFLAGS_REMOVE_tc2_pm_psci.o = -pg
- +endif
- obj-$(CONFIG_SMP) += platsmp.o
- obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
- diff -Nur linux-3.14.35.orig/arch/arm/mach-vexpress/spc.c linux-3.14.35/arch/arm/mach-vexpress/spc.c
- --- linux-3.14.35.orig/arch/arm/mach-vexpress/spc.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-vexpress/spc.c 2015-03-08 14:27:37.437684503 -0500
- @@ -392,7 +392,7 @@
- * +--------------------------+
- * | 31 20 | 19 0 |
- * +--------------------------+
- - * | u_volt | freq(kHz) |
- + * | m_volt | freq(kHz) |
- * +--------------------------+
- */
- #define MULT_FACTOR 20
- @@ -414,7 +414,7 @@
- ret = ve_spc_read_sys_cfg(SYSCFG_SCC, off, &data);
- if (!ret) {
- opps->freq = (data & FREQ_MASK) * MULT_FACTOR;
- - opps->u_volt = data >> VOLT_SHIFT;
- + opps->u_volt = (data >> VOLT_SHIFT) * 1000;
- } else {
- break;
- }
- diff -Nur linux-3.14.35.orig/arch/arm/mach-vexpress/tc2_pm.c linux-3.14.35/arch/arm/mach-vexpress/tc2_pm.c
- --- linux-3.14.35.orig/arch/arm/mach-vexpress/tc2_pm.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-vexpress/tc2_pm.c 2015-03-08 14:27:37.437684503 -0500
- @@ -27,6 +27,7 @@
- #include <asm/cacheflush.h>
- #include <asm/cputype.h>
- #include <asm/cp15.h>
- +#include <asm/psci.h>
-
- #include <linux/arm-cci.h>
-
- @@ -329,6 +330,12 @@
- u32 a15_cluster_id, a7_cluster_id, sys_info;
- struct device_node *np;
-
- + ret = psci_probe();
- + if (!ret) {
- + pr_debug("psci found. Aborting native init\n");
- + return -ENODEV;
- + }
- +
- /*
- * The power management-related features are hidden behind
- * SCC registers. We need to extract runtime information like
- diff -Nur linux-3.14.35.orig/arch/arm/mach-vexpress/tc2_pm_psci.c linux-3.14.35/arch/arm/mach-vexpress/tc2_pm_psci.c
- --- linux-3.14.35.orig/arch/arm/mach-vexpress/tc2_pm_psci.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-vexpress/tc2_pm_psci.c 2015-03-08 14:27:37.437684503 -0500
- @@ -0,0 +1,173 @@
- +/*
- + * arch/arm/mach-vexpress/tc2_pm_psci.c - TC2 PSCI support
- + *
- + * Created by: Achin Gupta, December 2012
- + * Copyright: (C) 2012 ARM Limited
- + *
- + * Some portions of this file were originally written by Nicolas Pitre
- + * Copyright: (C) 2012 Linaro Limited
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <linux/init.h>
- +#include <linux/kernel.h>
- +#include <linux/of.h>
- +#include <linux/spinlock.h>
- +#include <linux/errno.h>
- +
- +#include <asm/mcpm.h>
- +#include <asm/proc-fns.h>
- +#include <asm/cacheflush.h>
- +#include <asm/psci.h>
- +#include <asm/atomic.h>
- +#include <asm/cputype.h>
- +#include <asm/cp15.h>
- +
- +#include <mach/motherboard.h>
- +
- +#include <linux/vexpress.h>
- +
- +/*
- + * Platform specific state id understood by the firmware and used to
- + * program the power controller
- + */
- +#define PSCI_POWER_STATE_ID 0
- +
- +#define TC2_CLUSTERS 2
- +#define TC2_MAX_CPUS_PER_CLUSTER 3
- +
- +static atomic_t tc2_pm_use_count[TC2_MAX_CPUS_PER_CLUSTER][TC2_CLUSTERS];
- +
- +static int tc2_pm_psci_power_up(unsigned int cpu, unsigned int cluster)
- +{
- + unsigned int mpidr = (cluster << 8) | cpu;
- + int ret = 0;
- +
- + BUG_ON(!psci_ops.cpu_on);
- +
- + switch (atomic_inc_return(&tc2_pm_use_count[cpu][cluster])) {
- + case 1:
- + /*
- + * This is a request to power up a cpu that linux thinks has
- + * been powered down. Retries are needed if the firmware has
- + * seen the power down request as yet.
- + */
- + do
- + ret = psci_ops.cpu_on(mpidr,
- + virt_to_phys(mcpm_entry_point));
- + while (ret == -EAGAIN);
- +
- + return ret;
- + case 2:
- + /* This power up request has overtaken a power down request */
- + return ret;
- + default:
- + /* Any other value is a bug */
- + BUG();
- + }
- +}
- +
- +static void tc2_pm_psci_power_down(void)
- +{
- + struct psci_power_state power_state;
- + unsigned int mpidr, cpu, cluster;
- +
- + mpidr = read_cpuid_mpidr();
- + cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
- + cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
- +
- + BUG_ON(!psci_ops.cpu_off);
- +
- + switch (atomic_dec_return(&tc2_pm_use_count[cpu][cluster])) {
- + case 1:
- + /*
- + * Overtaken by a power up. Flush caches, exit coherency,
- + * return & fake a reset
- + */
- + set_cr(get_cr() & ~CR_C);
- +
- + flush_cache_louis();
- +
- + asm volatile ("clrex");
- + set_auxcr(get_auxcr() & ~(1 << 6));
- +
- + return;
- + case 0:
- + /* A normal request to possibly power down the cluster */
- + power_state.id = PSCI_POWER_STATE_ID;
- + power_state.type = PSCI_POWER_STATE_TYPE_POWER_DOWN;
- + power_state.affinity_level = PSCI_POWER_STATE_AFFINITY_LEVEL1;
- +
- + psci_ops.cpu_off(power_state);
- +
- + /* On success this function never returns */
- + default:
- + /* Any other value is a bug */
- + BUG();
- + }
- +}
- +
- +static void tc2_pm_psci_suspend(u64 unused)
- +{
- + struct psci_power_state power_state;
- +
- + BUG_ON(!psci_ops.cpu_suspend);
- +
- + /* On TC2 always attempt to power down the cluster */
- + power_state.id = PSCI_POWER_STATE_ID;
- + power_state.type = PSCI_POWER_STATE_TYPE_POWER_DOWN;
- + power_state.affinity_level = PSCI_POWER_STATE_AFFINITY_LEVEL1;
- +
- + psci_ops.cpu_suspend(power_state, virt_to_phys(mcpm_entry_point));
- +
- + /* On success this function never returns */
- + BUG();
- +}
- +
- +static const struct mcpm_platform_ops tc2_pm_power_ops = {
- + .power_up = tc2_pm_psci_power_up,
- + .power_down = tc2_pm_psci_power_down,
- + .suspend = tc2_pm_psci_suspend,
- +};
- +
- +static void __init tc2_pm_usage_count_init(void)
- +{
- + unsigned int mpidr, cpu, cluster;
- +
- + mpidr = read_cpuid_mpidr();
- + cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
- + cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
- +
- + pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
- + BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER);
- +
- + atomic_set(&tc2_pm_use_count[cpu][cluster], 1);
- +}
- +
- +static int __init tc2_pm_psci_init(void)
- +{
- + int ret;
- +
- + ret = psci_probe();
- + if (ret) {
- + pr_debug("psci not found. Aborting psci init\n");
- + return -ENODEV;
- + }
- +
- + if (!of_machine_is_compatible("arm,vexpress,v2p-ca15_a7"))
- + return -ENODEV;
- +
- + tc2_pm_usage_count_init();
- +
- + ret = mcpm_platform_register(&tc2_pm_power_ops);
- + if (!ret)
- + ret = mcpm_sync_init(NULL);
- + if (!ret)
- + pr_info("TC2 power management using PSCI initialized\n");
- + return ret;
- +}
- +
- +early_initcall(tc2_pm_psci_init);
- diff -Nur linux-3.14.35.orig/arch/arm/mach-vexpress/v2m.c linux-3.14.35/arch/arm/mach-vexpress/v2m.c
- --- linux-3.14.35.orig/arch/arm/mach-vexpress/v2m.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-vexpress/v2m.c 2015-03-08 14:27:37.437684503 -0500
- @@ -7,6 +7,7 @@
- #include <linux/io.h>
- #include <linux/smp.h>
- #include <linux/init.h>
- +#include <linux/memblock.h>
- #include <linux/of_address.h>
- #include <linux/of_fdt.h>
- #include <linux/of_irq.h>
- @@ -369,6 +370,31 @@
- .init_machine = v2m_init,
- MACHINE_END
-
- +static void __init v2m_dt_hdlcd_init(void)
- +{
- + struct device_node *node;
- + int len, na, ns;
- + const __be32 *prop;
- + phys_addr_t fb_base, fb_size;
- +
- + node = of_find_compatible_node(NULL, NULL, "arm,hdlcd");
- + if (!node)
- + return;
- +
- + na = of_n_addr_cells(node);
- + ns = of_n_size_cells(node);
- +
- + prop = of_get_property(node, "framebuffer", &len);
- + if (WARN_ON(!prop || len < (na + ns) * sizeof(*prop)))
- + return;
- +
- + fb_base = of_read_number(prop, na);
- + fb_size = of_read_number(prop + na, ns);
- +
- + if (WARN_ON(memblock_remove(fb_base, fb_size)))
- + return;
- +};
- +
- static struct map_desc v2m_rs1_io_desc __initdata = {
- .virtual = V2M_PERIPH,
- .pfn = __phys_to_pfn(0x1c000000),
- @@ -421,6 +447,8 @@
- }
-
- versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), 24000000);
- +
- + v2m_dt_hdlcd_init();
- }
-
- static const struct of_device_id v2m_dt_bus_match[] __initconst = {
- diff -Nur linux-3.14.35.orig/arch/arm/mach-zynq/common.c linux-3.14.35/arch/arm/mach-zynq/common.c
- --- linux-3.14.35.orig/arch/arm/mach-zynq/common.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mach-zynq/common.c 2015-03-08 14:27:37.437684503 -0500
- @@ -67,7 +67,7 @@
- /*
- * 64KB way size, 8-way associativity, parity disabled
- */
- - l2x0_of_init(0x02060000, 0xF0F0FFFF);
- + l2x0_of_init(0x02000000, 0xf0ffffff);
-
- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-
- diff -Nur linux-3.14.35.orig/arch/arm/mm/cache-feroceon-l2.c linux-3.14.35/arch/arm/mm/cache-feroceon-l2.c
- --- linux-3.14.35.orig/arch/arm/mm/cache-feroceon-l2.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mm/cache-feroceon-l2.c 2015-03-08 14:27:37.437684503 -0500
- @@ -343,7 +343,6 @@
- outer_cache.inv_range = feroceon_l2_inv_range;
- outer_cache.clean_range = feroceon_l2_clean_range;
- outer_cache.flush_range = feroceon_l2_flush_range;
- - outer_cache.inv_all = l2_inv_all;
-
- enable_l2();
-
- diff -Nur linux-3.14.35.orig/arch/arm/mm/cache-l2x0.c linux-3.14.35/arch/arm/mm/cache-l2x0.c
- --- linux-3.14.35.orig/arch/arm/mm/cache-l2x0.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mm/cache-l2x0.c 2015-03-08 14:27:37.441684502 -0500
- @@ -16,18 +16,33 @@
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- +#include <linux/cpu.h>
- #include <linux/err.h>
- #include <linux/init.h>
- +#include <linux/smp.h>
- #include <linux/spinlock.h>
- #include <linux/io.h>
- #include <linux/of.h>
- #include <linux/of_address.h>
-
- #include <asm/cacheflush.h>
- +#include <asm/cp15.h>
- +#include <asm/cputype.h>
- #include <asm/hardware/cache-l2x0.h>
- #include "cache-tauros3.h"
- #include "cache-aurora-l2.h"
-
- +struct l2c_init_data {
- + const char *type;
- + unsigned way_size_0;
- + unsigned num_lock;
- + void (*of_parse)(const struct device_node *, u32 *, u32 *);
- + void (*enable)(void __iomem *, u32, unsigned);
- + void (*fixup)(void __iomem *, u32, struct outer_cache_fns *);
- + void (*save)(void __iomem *);
- + struct outer_cache_fns outer_cache;
- +};
- +
- #define CACHE_LINE_SIZE 32
-
- static void __iomem *l2x0_base;
- @@ -36,96 +51,116 @@
- static u32 l2x0_size;
- static unsigned long sync_reg_offset = L2X0_CACHE_SYNC;
-
- -/* Aurora don't have the cache ID register available, so we have to
- - * pass it though the device tree */
- -static u32 cache_id_part_number_from_dt;
- -
- struct l2x0_regs l2x0_saved_regs;
-
- -struct l2x0_of_data {
- - void (*setup)(const struct device_node *, u32 *, u32 *);
- - void (*save)(void);
- - struct outer_cache_fns outer_cache;
- -};
- -
- -static bool of_init = false;
- -
- -static inline void cache_wait_way(void __iomem *reg, unsigned long mask)
- +/*
- + * Common code for all cache controllers.
- + */
- +static inline void l2c_wait_mask(void __iomem *reg, unsigned long mask)
- {
- /* wait for cache operation by line or way to complete */
- while (readl_relaxed(reg) & mask)
- cpu_relax();
- }
-
- -#ifdef CONFIG_CACHE_PL310
- -static inline void cache_wait(void __iomem *reg, unsigned long mask)
- +/*
- + * By default, we write directly to secure registers. Platforms must
- + * override this if they are running non-secure.
- + */
- +static void l2c_write_sec(unsigned long val, void __iomem *base, unsigned reg)
- {
- - /* cache operations by line are atomic on PL310 */
- + if (val == readl_relaxed(base + reg))
- + return;
- + if (outer_cache.write_sec)
- + outer_cache.write_sec(val, reg);
- + else
- + writel_relaxed(val, base + reg);
- }
- -#else
- -#define cache_wait cache_wait_way
- -#endif
-
- -static inline void cache_sync(void)
- +/*
- + * This should only be called when we have a requirement that the
- + * register be written due to a work-around, as platforms running
- + * in non-secure mode may not be able to access this register.
- + */
- +static inline void l2c_set_debug(void __iomem *base, unsigned long val)
- {
- - void __iomem *base = l2x0_base;
- -
- - writel_relaxed(0, base + sync_reg_offset);
- - cache_wait(base + L2X0_CACHE_SYNC, 1);
- + l2c_write_sec(val, base, L2X0_DEBUG_CTRL);
- }
-
- -static inline void l2x0_clean_line(unsigned long addr)
- +static void __l2c_op_way(void __iomem *reg)
- {
- - void __iomem *base = l2x0_base;
- - cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
- - writel_relaxed(addr, base + L2X0_CLEAN_LINE_PA);
- + writel_relaxed(l2x0_way_mask, reg);
- + l2c_wait_mask(reg, l2x0_way_mask);
- }
-
- -static inline void l2x0_inv_line(unsigned long addr)
- +static inline void l2c_unlock(void __iomem *base, unsigned num)
- {
- - void __iomem *base = l2x0_base;
- - cache_wait(base + L2X0_INV_LINE_PA, 1);
- - writel_relaxed(addr, base + L2X0_INV_LINE_PA);
- + unsigned i;
- +
- + for (i = 0; i < num; i++) {
- + writel_relaxed(0, base + L2X0_LOCKDOWN_WAY_D_BASE +
- + i * L2X0_LOCKDOWN_STRIDE);
- + writel_relaxed(0, base + L2X0_LOCKDOWN_WAY_I_BASE +
- + i * L2X0_LOCKDOWN_STRIDE);
- + }
- }
-
- -#if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915)
- -static inline void debug_writel(unsigned long val)
- +/*
- + * Enable the L2 cache controller. This function must only be
- + * called when the cache controller is known to be disabled.
- + */
- +static void l2c_enable(void __iomem *base, u32 aux, unsigned num_lock)
- {
- - if (outer_cache.set_debug)
- - outer_cache.set_debug(val);
- + unsigned long flags;
- +
- + l2c_write_sec(aux, base, L2X0_AUX_CTRL);
- +
- + l2c_unlock(base, num_lock);
- +
- + local_irq_save(flags);
- + __l2c_op_way(base + L2X0_INV_WAY);
- + writel_relaxed(0, base + sync_reg_offset);
- + l2c_wait_mask(base + sync_reg_offset, 1);
- + local_irq_restore(flags);
- +
- + l2c_write_sec(L2X0_CTRL_EN, base, L2X0_CTRL);
- }
-
- -static void pl310_set_debug(unsigned long val)
- +static void l2c_disable(void)
- {
- - writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL);
- + void __iomem *base = l2x0_base;
- +
- + outer_cache.flush_all();
- + l2c_write_sec(0, base, L2X0_CTRL);
- + dsb(st);
- }
- -#else
- -/* Optimised out for non-errata case */
- -static inline void debug_writel(unsigned long val)
- +
- +#ifdef CONFIG_CACHE_PL310
- +static inline void cache_wait(void __iomem *reg, unsigned long mask)
- {
- + /* cache operations by line are atomic on PL310 */
- }
- -
- -#define pl310_set_debug NULL
- +#else
- +#define cache_wait l2c_wait_mask
- #endif
-
- -#ifdef CONFIG_PL310_ERRATA_588369
- -static inline void l2x0_flush_line(unsigned long addr)
- +static inline void cache_sync(void)
- {
- void __iomem *base = l2x0_base;
-
- - /* Clean by PA followed by Invalidate by PA */
- - cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
- - writel_relaxed(addr, base + L2X0_CLEAN_LINE_PA);
- - cache_wait(base + L2X0_INV_LINE_PA, 1);
- - writel_relaxed(addr, base + L2X0_INV_LINE_PA);
- + writel_relaxed(0, base + sync_reg_offset);
- + cache_wait(base + L2X0_CACHE_SYNC, 1);
- }
- -#else
-
- -static inline void l2x0_flush_line(unsigned long addr)
- +#if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915)
- +static inline void debug_writel(unsigned long val)
- +{
- + l2c_set_debug(l2x0_base, val);
- +}
- +#else
- +/* Optimised out for non-errata case */
- +static inline void debug_writel(unsigned long val)
- {
- - void __iomem *base = l2x0_base;
- - cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
- - writel_relaxed(addr, base + L2X0_CLEAN_INV_LINE_PA);
- }
- #endif
-
- @@ -141,8 +176,7 @@
- static void __l2x0_flush_all(void)
- {
- debug_writel(0x03);
- - writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_INV_WAY);
- - cache_wait_way(l2x0_base + L2X0_CLEAN_INV_WAY, l2x0_way_mask);
- + __l2c_op_way(l2x0_base + L2X0_CLEAN_INV_WAY);
- cache_sync();
- debug_writel(0x00);
- }
- @@ -157,274 +191,882 @@
- raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- }
-
- -static void l2x0_clean_all(void)
- +static void l2x0_disable(void)
- {
- unsigned long flags;
-
- - /* clean all ways */
- raw_spin_lock_irqsave(&l2x0_lock, flags);
- - writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_WAY);
- - cache_wait_way(l2x0_base + L2X0_CLEAN_WAY, l2x0_way_mask);
- - cache_sync();
- + __l2x0_flush_all();
- + l2c_write_sec(0, l2x0_base, L2X0_CTRL);
- + dsb(st);
- raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- }
-
- -static void l2x0_inv_all(void)
- +static void l2c_save(void __iomem *base)
- {
- - unsigned long flags;
- + l2x0_saved_regs.aux_ctrl = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
- +}
-
- - /* invalidate all ways */
- - raw_spin_lock_irqsave(&l2x0_lock, flags);
- - /* Invalidating when L2 is enabled is a nono */
- - BUG_ON(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN);
- - writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
- - cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
- - cache_sync();
- - raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- +/*
- + * L2C-210 specific code.
- + *
- + * The L2C-2x0 PA, set/way and sync operations are atomic, but we must
- + * ensure that no background operation is running. The way operations
- + * are all background tasks.
- + *
- + * While a background operation is in progress, any new operation is
- + * ignored (unspecified whether this causes an error.) Thankfully, not
- + * used on SMP.
- + *
- + * Never has a different sync register other than L2X0_CACHE_SYNC, but
- + * we use sync_reg_offset here so we can share some of this with L2C-310.
- + */
- +static void __l2c210_cache_sync(void __iomem *base)
- +{
- + writel_relaxed(0, base + sync_reg_offset);
- }
-
- -static void l2x0_inv_range(unsigned long start, unsigned long end)
- +static void __l2c210_op_pa_range(void __iomem *reg, unsigned long start,
- + unsigned long end)
- +{
- + while (start < end) {
- + writel_relaxed(start, reg);
- + start += CACHE_LINE_SIZE;
- + }
- +}
- +
- +static void l2c210_inv_range(unsigned long start, unsigned long end)
- {
- void __iomem *base = l2x0_base;
- - unsigned long flags;
-
- - raw_spin_lock_irqsave(&l2x0_lock, flags);
- if (start & (CACHE_LINE_SIZE - 1)) {
- start &= ~(CACHE_LINE_SIZE - 1);
- - debug_writel(0x03);
- - l2x0_flush_line(start);
- - debug_writel(0x00);
- + writel_relaxed(start, base + L2X0_CLEAN_INV_LINE_PA);
- start += CACHE_LINE_SIZE;
- }
-
- if (end & (CACHE_LINE_SIZE - 1)) {
- end &= ~(CACHE_LINE_SIZE - 1);
- - debug_writel(0x03);
- - l2x0_flush_line(end);
- - debug_writel(0x00);
- + writel_relaxed(end, base + L2X0_CLEAN_INV_LINE_PA);
- }
-
- + __l2c210_op_pa_range(base + L2X0_INV_LINE_PA, start, end);
- + __l2c210_cache_sync(base);
- +}
- +
- +static void l2c210_clean_range(unsigned long start, unsigned long end)
- +{
- + void __iomem *base = l2x0_base;
- +
- + start &= ~(CACHE_LINE_SIZE - 1);
- + __l2c210_op_pa_range(base + L2X0_CLEAN_LINE_PA, start, end);
- + __l2c210_cache_sync(base);
- +}
- +
- +static void l2c210_flush_range(unsigned long start, unsigned long end)
- +{
- + void __iomem *base = l2x0_base;
- +
- + start &= ~(CACHE_LINE_SIZE - 1);
- + __l2c210_op_pa_range(base + L2X0_CLEAN_INV_LINE_PA, start, end);
- + __l2c210_cache_sync(base);
- +}
- +
- +static void l2c210_flush_all(void)
- +{
- + void __iomem *base = l2x0_base;
- +
- + BUG_ON(!irqs_disabled());
- +
- + __l2c_op_way(base + L2X0_CLEAN_INV_WAY);
- + __l2c210_cache_sync(base);
- +}
- +
- +static void l2c210_sync(void)
- +{
- + __l2c210_cache_sync(l2x0_base);
- +}
- +
- +static void l2c210_resume(void)
- +{
- + void __iomem *base = l2x0_base;
- +
- + if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN))
- + l2c_enable(base, l2x0_saved_regs.aux_ctrl, 1);
- +}
- +
- +static const struct l2c_init_data l2c210_data __initconst = {
- + .type = "L2C-210",
- + .way_size_0 = SZ_8K,
- + .num_lock = 1,
- + .enable = l2c_enable,
- + .save = l2c_save,
- + .outer_cache = {
- + .inv_range = l2c210_inv_range,
- + .clean_range = l2c210_clean_range,
- + .flush_range = l2c210_flush_range,
- + .flush_all = l2c210_flush_all,
- + .disable = l2c_disable,
- + .sync = l2c210_sync,
- + .resume = l2c210_resume,
- + },
- +};
- +
- +/*
- + * L2C-220 specific code.
- + *
- + * All operations are background operations: they have to be waited for.
- + * Conflicting requests generate a slave error (which will cause an
- + * imprecise abort.) Never uses sync_reg_offset, so we hard-code the
- + * sync register here.
- + *
- + * However, we can re-use the l2c210_resume call.
- + */
- +static inline void __l2c220_cache_sync(void __iomem *base)
- +{
- + writel_relaxed(0, base + L2X0_CACHE_SYNC);
- + l2c_wait_mask(base + L2X0_CACHE_SYNC, 1);
- +}
- +
- +static void l2c220_op_way(void __iomem *base, unsigned reg)
- +{
- + unsigned long flags;
- +
- + raw_spin_lock_irqsave(&l2x0_lock, flags);
- + __l2c_op_way(base + reg);
- + __l2c220_cache_sync(base);
- + raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- +}
- +
- +static unsigned long l2c220_op_pa_range(void __iomem *reg, unsigned long start,
- + unsigned long end, unsigned long flags)
- +{
- + raw_spinlock_t *lock = &l2x0_lock;
- +
- while (start < end) {
- unsigned long blk_end = start + min(end - start, 4096UL);
-
- while (start < blk_end) {
- - l2x0_inv_line(start);
- + l2c_wait_mask(reg, 1);
- + writel_relaxed(start, reg);
- start += CACHE_LINE_SIZE;
- }
-
- if (blk_end < end) {
- - raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- - raw_spin_lock_irqsave(&l2x0_lock, flags);
- + raw_spin_unlock_irqrestore(lock, flags);
- + raw_spin_lock_irqsave(lock, flags);
- }
- }
- - cache_wait(base + L2X0_INV_LINE_PA, 1);
- - cache_sync();
- - raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- +
- + return flags;
- }
-
- -static void l2x0_clean_range(unsigned long start, unsigned long end)
- +static void l2c220_inv_range(unsigned long start, unsigned long end)
- {
- void __iomem *base = l2x0_base;
- unsigned long flags;
-
- - if ((end - start) >= l2x0_size) {
- - l2x0_clean_all();
- - return;
- - }
- -
- raw_spin_lock_irqsave(&l2x0_lock, flags);
- - start &= ~(CACHE_LINE_SIZE - 1);
- - while (start < end) {
- - unsigned long blk_end = start + min(end - start, 4096UL);
- -
- - while (start < blk_end) {
- - l2x0_clean_line(start);
- + if ((start | end) & (CACHE_LINE_SIZE - 1)) {
- + if (start & (CACHE_LINE_SIZE - 1)) {
- + start &= ~(CACHE_LINE_SIZE - 1);
- + writel_relaxed(start, base + L2X0_CLEAN_INV_LINE_PA);
- start += CACHE_LINE_SIZE;
- }
-
- - if (blk_end < end) {
- - raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- - raw_spin_lock_irqsave(&l2x0_lock, flags);
- + if (end & (CACHE_LINE_SIZE - 1)) {
- + end &= ~(CACHE_LINE_SIZE - 1);
- + l2c_wait_mask(base + L2X0_CLEAN_INV_LINE_PA, 1);
- + writel_relaxed(end, base + L2X0_CLEAN_INV_LINE_PA);
- }
- }
- - cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
- - cache_sync();
- +
- + flags = l2c220_op_pa_range(base + L2X0_INV_LINE_PA,
- + start, end, flags);
- + l2c_wait_mask(base + L2X0_INV_LINE_PA, 1);
- + __l2c220_cache_sync(base);
- raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- }
-
- -static void l2x0_flush_range(unsigned long start, unsigned long end)
- +static void l2c220_clean_range(unsigned long start, unsigned long end)
- {
- void __iomem *base = l2x0_base;
- unsigned long flags;
-
- + start &= ~(CACHE_LINE_SIZE - 1);
- if ((end - start) >= l2x0_size) {
- - l2x0_flush_all();
- + l2c220_op_way(base, L2X0_CLEAN_WAY);
- return;
- }
-
- raw_spin_lock_irqsave(&l2x0_lock, flags);
- + flags = l2c220_op_pa_range(base + L2X0_CLEAN_LINE_PA,
- + start, end, flags);
- + l2c_wait_mask(base + L2X0_CLEAN_INV_LINE_PA, 1);
- + __l2c220_cache_sync(base);
- + raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- +}
- +
- +static void l2c220_flush_range(unsigned long start, unsigned long end)
- +{
- + void __iomem *base = l2x0_base;
- + unsigned long flags;
- +
- start &= ~(CACHE_LINE_SIZE - 1);
- + if ((end - start) >= l2x0_size) {
- + l2c220_op_way(base, L2X0_CLEAN_INV_WAY);
- + return;
- + }
- +
- + raw_spin_lock_irqsave(&l2x0_lock, flags);
- + flags = l2c220_op_pa_range(base + L2X0_CLEAN_INV_LINE_PA,
- + start, end, flags);
- + l2c_wait_mask(base + L2X0_CLEAN_INV_LINE_PA, 1);
- + __l2c220_cache_sync(base);
- + raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- +}
- +
- +static void l2c220_flush_all(void)
- +{
- + l2c220_op_way(l2x0_base, L2X0_CLEAN_INV_WAY);
- +}
- +
- +static void l2c220_sync(void)
- +{
- + unsigned long flags;
- +
- + raw_spin_lock_irqsave(&l2x0_lock, flags);
- + __l2c220_cache_sync(l2x0_base);
- + raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- +}
- +
- +static void l2c220_enable(void __iomem *base, u32 aux, unsigned num_lock)
- +{
- + /*
- + * Always enable non-secure access to the lockdown registers -
- + * we write to them as part of the L2C enable sequence so they
- + * need to be accessible.
- + */
- + aux |= L220_AUX_CTRL_NS_LOCKDOWN;
- +
- + l2c_enable(base, aux, num_lock);
- +}
- +
- +static const struct l2c_init_data l2c220_data = {
- + .type = "L2C-220",
- + .way_size_0 = SZ_8K,
- + .num_lock = 1,
- + .enable = l2c220_enable,
- + .save = l2c_save,
- + .outer_cache = {
- + .inv_range = l2c220_inv_range,
- + .clean_range = l2c220_clean_range,
- + .flush_range = l2c220_flush_range,
- + .flush_all = l2c220_flush_all,
- + .disable = l2c_disable,
- + .sync = l2c220_sync,
- + .resume = l2c210_resume,
- + },
- +};
- +
- +/*
- + * L2C-310 specific code.
- + *
- + * Very similar to L2C-210, the PA, set/way and sync operations are atomic,
- + * and the way operations are all background tasks. However, issuing an
- + * operation while a background operation is in progress results in a
- + * SLVERR response. We can reuse:
- + *
- + * __l2c210_cache_sync (using sync_reg_offset)
- + * l2c210_sync
- + * l2c210_inv_range (if 588369 is not applicable)
- + * l2c210_clean_range
- + * l2c210_flush_range (if 588369 is not applicable)
- + * l2c210_flush_all (if 727915 is not applicable)
- + *
- + * Errata:
- + * 588369: PL310 R0P0->R1P0, fixed R2P0.
- + * Affects: all clean+invalidate operations
- + * clean and invalidate skips the invalidate step, so we need to issue
- + * separate operations. We also require the above debug workaround
- + * enclosing this code fragment on affected parts. On unaffected parts,
- + * we must not use this workaround without the debug register writes
- + * to avoid exposing a problem similar to 727915.
- + *
- + * 727915: PL310 R2P0->R3P0, fixed R3P1.
- + * Affects: clean+invalidate by way
- + * clean and invalidate by way runs in the background, and a store can
- + * hit the line between the clean operation and invalidate operation,
- + * resulting in the store being lost.
- + *
- + * 752271: PL310 R3P0->R3P1-50REL0, fixed R3P2.
- + * Affects: 8x64-bit (double fill) line fetches
- + * double fill line fetches can fail to cause dirty data to be evicted
- + * from the cache before the new data overwrites the second line.
- + *
- + * 753970: PL310 R3P0, fixed R3P1.
- + * Affects: sync
- + * prevents merging writes after the sync operation, until another L2C
- + * operation is performed (or a number of other conditions.)
- + *
- + * 769419: PL310 R0P0->R3P1, fixed R3P2.
- + * Affects: store buffer
- + * store buffer is not automatically drained.
- + */
- +static void l2c310_inv_range_erratum(unsigned long start, unsigned long end)
- +{
- + void __iomem *base = l2x0_base;
- +
- + if ((start | end) & (CACHE_LINE_SIZE - 1)) {
- + unsigned long flags;
- +
- + /* Erratum 588369 for both clean+invalidate operations */
- + raw_spin_lock_irqsave(&l2x0_lock, flags);
- + l2c_set_debug(base, 0x03);
- +
- + if (start & (CACHE_LINE_SIZE - 1)) {
- + start &= ~(CACHE_LINE_SIZE - 1);
- + writel_relaxed(start, base + L2X0_CLEAN_LINE_PA);
- + writel_relaxed(start, base + L2X0_INV_LINE_PA);
- + start += CACHE_LINE_SIZE;
- + }
- +
- + if (end & (CACHE_LINE_SIZE - 1)) {
- + end &= ~(CACHE_LINE_SIZE - 1);
- + writel_relaxed(end, base + L2X0_CLEAN_LINE_PA);
- + writel_relaxed(end, base + L2X0_INV_LINE_PA);
- + }
- +
- + l2c_set_debug(base, 0x00);
- + raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- + }
- +
- + __l2c210_op_pa_range(base + L2X0_INV_LINE_PA, start, end);
- + __l2c210_cache_sync(base);
- +}
- +
- +static void l2c310_flush_range_erratum(unsigned long start, unsigned long end)
- +{
- + raw_spinlock_t *lock = &l2x0_lock;
- + unsigned long flags;
- + void __iomem *base = l2x0_base;
- +
- + raw_spin_lock_irqsave(lock, flags);
- while (start < end) {
- unsigned long blk_end = start + min(end - start, 4096UL);
-
- - debug_writel(0x03);
- + l2c_set_debug(base, 0x03);
- while (start < blk_end) {
- - l2x0_flush_line(start);
- + writel_relaxed(start, base + L2X0_CLEAN_LINE_PA);
- + writel_relaxed(start, base + L2X0_INV_LINE_PA);
- start += CACHE_LINE_SIZE;
- }
- - debug_writel(0x00);
- + l2c_set_debug(base, 0x00);
-
- if (blk_end < end) {
- - raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- - raw_spin_lock_irqsave(&l2x0_lock, flags);
- + raw_spin_unlock_irqrestore(lock, flags);
- + raw_spin_lock_irqsave(lock, flags);
- }
- }
- - cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
- - cache_sync();
- - raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- + raw_spin_unlock_irqrestore(lock, flags);
- + __l2c210_cache_sync(base);
- }
-
- -static void l2x0_disable(void)
- +static void l2c310_flush_all_erratum(void)
- {
- + void __iomem *base = l2x0_base;
- unsigned long flags;
-
- raw_spin_lock_irqsave(&l2x0_lock, flags);
- - __l2x0_flush_all();
- - writel_relaxed(0, l2x0_base + L2X0_CTRL);
- - dsb(st);
- + l2c_set_debug(base, 0x03);
- + __l2c_op_way(base + L2X0_CLEAN_INV_WAY);
- + l2c_set_debug(base, 0x00);
- + __l2c210_cache_sync(base);
- raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- }
-
- -static void l2x0_unlock(u32 cache_id)
- +static void __init l2c310_save(void __iomem *base)
- {
- - int lockregs;
- - int i;
- + unsigned revision;
-
- - switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
- - case L2X0_CACHE_ID_PART_L310:
- - lockregs = 8;
- - break;
- - case AURORA_CACHE_ID:
- - lockregs = 4;
- + l2c_save(base);
- +
- + l2x0_saved_regs.tag_latency = readl_relaxed(base +
- + L310_TAG_LATENCY_CTRL);
- + l2x0_saved_regs.data_latency = readl_relaxed(base +
- + L310_DATA_LATENCY_CTRL);
- + l2x0_saved_regs.filter_end = readl_relaxed(base +
- + L310_ADDR_FILTER_END);
- + l2x0_saved_regs.filter_start = readl_relaxed(base +
- + L310_ADDR_FILTER_START);
- +
- + revision = readl_relaxed(base + L2X0_CACHE_ID) &
- + L2X0_CACHE_ID_RTL_MASK;
- +
- + /* From r2p0, there is Prefetch offset/control register */
- + if (revision >= L310_CACHE_ID_RTL_R2P0)
- + l2x0_saved_regs.prefetch_ctrl = readl_relaxed(base +
- + L310_PREFETCH_CTRL);
- +
- + /* From r3p0, there is Power control register */
- + if (revision >= L310_CACHE_ID_RTL_R3P0)
- + l2x0_saved_regs.pwr_ctrl = readl_relaxed(base +
- + L310_POWER_CTRL);
- +}
- +
- +static void l2c310_resume(void)
- +{
- + void __iomem *base = l2x0_base;
- +
- + if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)) {
- + unsigned revision;
- +
- + /* restore pl310 setup */
- + writel_relaxed(l2x0_saved_regs.tag_latency,
- + base + L310_TAG_LATENCY_CTRL);
- + writel_relaxed(l2x0_saved_regs.data_latency,
- + base + L310_DATA_LATENCY_CTRL);
- + writel_relaxed(l2x0_saved_regs.filter_end,
- + base + L310_ADDR_FILTER_END);
- + writel_relaxed(l2x0_saved_regs.filter_start,
- + base + L310_ADDR_FILTER_START);
- +
- + revision = readl_relaxed(base + L2X0_CACHE_ID) &
- + L2X0_CACHE_ID_RTL_MASK;
- +
- + if (revision >= L310_CACHE_ID_RTL_R2P0)
- + l2c_write_sec(l2x0_saved_regs.prefetch_ctrl, base,
- + L310_PREFETCH_CTRL);
- + if (revision >= L310_CACHE_ID_RTL_R3P0)
- + l2c_write_sec(l2x0_saved_regs.pwr_ctrl, base,
- + L310_POWER_CTRL);
- +
- + l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8);
- +
- + /* Re-enable full-line-of-zeros for Cortex-A9 */
- + if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_FULL_LINE_ZERO)
- + set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1));
- + }
- +}
- +
- +static int l2c310_cpu_enable_flz(struct notifier_block *nb, unsigned long act, void *data)
- +{
- + switch (act & ~CPU_TASKS_FROZEN) {
- + case CPU_STARTING:
- + set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1));
- break;
- - default:
- - /* L210 and unknown types */
- - lockregs = 1;
- + case CPU_DYING:
- + set_auxcr(get_auxcr() & ~(BIT(3) | BIT(2) | BIT(1)));
- break;
- }
- + return NOTIFY_OK;
- +}
-
- - for (i = 0; i < lockregs; i++) {
- - writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
- - i * L2X0_LOCKDOWN_STRIDE);
- - writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE +
- - i * L2X0_LOCKDOWN_STRIDE);
- +static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock)
- +{
- + unsigned rev = readl_relaxed(base + L2X0_CACHE_ID) & L2X0_CACHE_ID_PART_MASK;
- + bool cortex_a9 = read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9;
- +
- + if (rev >= L310_CACHE_ID_RTL_R2P0) {
- + if (cortex_a9) {
- + aux |= L310_AUX_CTRL_EARLY_BRESP;
- + pr_info("L2C-310 enabling early BRESP for Cortex-A9\n");
- + } else if (aux & L310_AUX_CTRL_EARLY_BRESP) {
- + pr_warn("L2C-310 early BRESP only supported with Cortex-A9\n");
- + aux &= ~L310_AUX_CTRL_EARLY_BRESP;
- + }
- + }
- +
- + if (cortex_a9) {
- + u32 aux_cur = readl_relaxed(base + L2X0_AUX_CTRL);
- + u32 acr = get_auxcr();
- +
- + pr_debug("Cortex-A9 ACR=0x%08x\n", acr);
- +
- + if (acr & BIT(3) && !(aux_cur & L310_AUX_CTRL_FULL_LINE_ZERO))
- + pr_err("L2C-310: full line of zeros enabled in Cortex-A9 but not L2C-310 - invalid\n");
- +
- + if (aux & L310_AUX_CTRL_FULL_LINE_ZERO && !(acr & BIT(3)))
- + pr_err("L2C-310: enabling full line of zeros but not enabled in Cortex-A9\n");
- +
- + if (!(aux & L310_AUX_CTRL_FULL_LINE_ZERO) && !outer_cache.write_sec) {
- + aux |= L310_AUX_CTRL_FULL_LINE_ZERO;
- + pr_info("L2C-310 full line of zeros enabled for Cortex-A9\n");
- + }
- + } else if (aux & (L310_AUX_CTRL_FULL_LINE_ZERO | L310_AUX_CTRL_EARLY_BRESP)) {
- + pr_err("L2C-310: disabling Cortex-A9 specific feature bits\n");
- + aux &= ~(L310_AUX_CTRL_FULL_LINE_ZERO | L310_AUX_CTRL_EARLY_BRESP);
- + }
- +
- + if (aux & (L310_AUX_CTRL_DATA_PREFETCH | L310_AUX_CTRL_INSTR_PREFETCH)) {
- + u32 prefetch = readl_relaxed(base + L310_PREFETCH_CTRL);
- +
- + pr_info("L2C-310 %s%s prefetch enabled, offset %u lines\n",
- + aux & L310_AUX_CTRL_INSTR_PREFETCH ? "I" : "",
- + aux & L310_AUX_CTRL_DATA_PREFETCH ? "D" : "",
- + 1 + (prefetch & L310_PREFETCH_CTRL_OFFSET_MASK));
- + }
- +
- + /* r3p0 or later has power control register */
- + if (rev >= L310_CACHE_ID_RTL_R3P0) {
- + u32 power_ctrl;
- +
- + l2c_write_sec(L310_DYNAMIC_CLK_GATING_EN | L310_STNDBY_MODE_EN,
- + base, L310_POWER_CTRL);
- + power_ctrl = readl_relaxed(base + L310_POWER_CTRL);
- + pr_info("L2C-310 dynamic clock gating %sabled, standby mode %sabled\n",
- + power_ctrl & L310_DYNAMIC_CLK_GATING_EN ? "en" : "dis",
- + power_ctrl & L310_STNDBY_MODE_EN ? "en" : "dis");
- + }
- +
- + /*
- + * Always enable non-secure access to the lockdown registers -
- + * we write to them as part of the L2C enable sequence so they
- + * need to be accessible.
- + */
- + aux |= L310_AUX_CTRL_NS_LOCKDOWN;
- +
- + l2c_enable(base, aux, num_lock);
- +
- + if (aux & L310_AUX_CTRL_FULL_LINE_ZERO) {
- + set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1));
- + cpu_notifier(l2c310_cpu_enable_flz, 0);
- }
- }
-
- -void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
- +static void __init l2c310_fixup(void __iomem *base, u32 cache_id,
- + struct outer_cache_fns *fns)
- {
- - u32 aux;
- - u32 cache_id;
- - u32 way_size = 0;
- - int ways;
- - int way_size_shift = L2X0_WAY_SIZE_SHIFT;
- - const char *type;
- + unsigned revision = cache_id & L2X0_CACHE_ID_RTL_MASK;
- + const char *errata[8];
- + unsigned n = 0;
-
- - l2x0_base = base;
- - if (cache_id_part_number_from_dt)
- - cache_id = cache_id_part_number_from_dt;
- - else
- - cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID);
- - aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
- + if (IS_ENABLED(CONFIG_PL310_ERRATA_588369) &&
- + revision < L310_CACHE_ID_RTL_R2P0 &&
- + /* For bcm compatibility */
- + fns->inv_range == l2c210_inv_range) {
- + fns->inv_range = l2c310_inv_range_erratum;
- + fns->flush_range = l2c310_flush_range_erratum;
- + errata[n++] = "588369";
- + }
- +
- + if (IS_ENABLED(CONFIG_PL310_ERRATA_727915) &&
- + revision >= L310_CACHE_ID_RTL_R2P0 &&
- + revision < L310_CACHE_ID_RTL_R3P1) {
- + fns->flush_all = l2c310_flush_all_erratum;
- + errata[n++] = "727915";
- + }
- +
- + if (revision >= L310_CACHE_ID_RTL_R3P0 &&
- + revision < L310_CACHE_ID_RTL_R3P2) {
- + u32 val = readl_relaxed(base + L310_PREFETCH_CTRL);
- + /* I don't think bit23 is required here... but iMX6 does so */
- + if (val & (BIT(30) | BIT(23))) {
- + val &= ~(BIT(30) | BIT(23));
- + l2c_write_sec(val, base, L310_PREFETCH_CTRL);
- + errata[n++] = "752271";
- + }
- + }
- +
- + if (IS_ENABLED(CONFIG_PL310_ERRATA_753970) &&
- + revision == L310_CACHE_ID_RTL_R3P0) {
- + sync_reg_offset = L2X0_DUMMY_REG;
- + errata[n++] = "753970";
- + }
- +
- + if (IS_ENABLED(CONFIG_PL310_ERRATA_769419))
- + errata[n++] = "769419";
- +
- + if (n) {
- + unsigned i;
- +
- + pr_info("L2C-310 errat%s", n > 1 ? "a" : "um");
- + for (i = 0; i < n; i++)
- + pr_cont(" %s", errata[i]);
- + pr_cont(" enabled\n");
- + }
- +}
- +
- +static void l2c310_disable(void)
- +{
- + /*
- + * If full-line-of-zeros is enabled, we must first disable it in the
- + * Cortex-A9 auxiliary control register before disabling the L2 cache.
- + */
- + if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_FULL_LINE_ZERO)
- + set_auxcr(get_auxcr() & ~(BIT(3) | BIT(2) | BIT(1)));
-
- + l2c_disable();
- +}
- +
- +static const struct l2c_init_data l2c310_init_fns __initconst = {
- + .type = "L2C-310",
- + .way_size_0 = SZ_8K,
- + .num_lock = 8,
- + .enable = l2c310_enable,
- + .fixup = l2c310_fixup,
- + .save = l2c310_save,
- + .outer_cache = {
- + .inv_range = l2c210_inv_range,
- + .clean_range = l2c210_clean_range,
- + .flush_range = l2c210_flush_range,
- + .flush_all = l2c210_flush_all,
- + .disable = l2c310_disable,
- + .sync = l2c210_sync,
- + .resume = l2c310_resume,
- + },
- +};
- +
- +static void __init __l2c_init(const struct l2c_init_data *data,
- + u32 aux_val, u32 aux_mask, u32 cache_id)
- +{
- + struct outer_cache_fns fns;
- + unsigned way_size_bits, ways;
- + u32 aux, old_aux;
- +
- + /*
- + * Sanity check the aux values. aux_mask is the bits we preserve
- + * from reading the hardware register, and aux_val is the bits we
- + * set.
- + */
- + if (aux_val & aux_mask)
- + pr_alert("L2C: platform provided aux values permit register corruption.\n");
- +
- + old_aux = aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
- aux &= aux_mask;
- aux |= aux_val;
-
- + if (old_aux != aux)
- + pr_warn("L2C: DT/platform modifies aux control register: 0x%08x -> 0x%08x\n",
- + old_aux, aux);
- +
- /* Determine the number of ways */
- switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
- case L2X0_CACHE_ID_PART_L310:
- + if ((aux_val | ~aux_mask) & (L2C_AUX_CTRL_WAY_SIZE_MASK | L310_AUX_CTRL_ASSOCIATIVITY_16))
- + pr_warn("L2C: DT/platform tries to modify or specify cache size\n");
- if (aux & (1 << 16))
- ways = 16;
- else
- ways = 8;
- - type = "L310";
- -#ifdef CONFIG_PL310_ERRATA_753970
- - /* Unmapped register. */
- - sync_reg_offset = L2X0_DUMMY_REG;
- -#endif
- - if ((cache_id & L2X0_CACHE_ID_RTL_MASK) <= L2X0_CACHE_ID_RTL_R3P0)
- - outer_cache.set_debug = pl310_set_debug;
- break;
- +
- case L2X0_CACHE_ID_PART_L210:
- + case L2X0_CACHE_ID_PART_L220:
- ways = (aux >> 13) & 0xf;
- - type = "L210";
- break;
-
- case AURORA_CACHE_ID:
- - sync_reg_offset = AURORA_SYNC_REG;
- ways = (aux >> 13) & 0xf;
- ways = 2 << ((ways + 1) >> 2);
- - way_size_shift = AURORA_WAY_SIZE_SHIFT;
- - type = "Aurora";
- break;
- +
- default:
- /* Assume unknown chips have 8 ways */
- ways = 8;
- - type = "L2x0 series";
- break;
- }
-
- l2x0_way_mask = (1 << ways) - 1;
-
- /*
- - * L2 cache Size = Way size * Number of ways
- + * way_size_0 is the size that a way_size value of zero would be
- + * given the calculation: way_size = way_size_0 << way_size_bits.
- + * So, if way_size_bits=0 is reserved, but way_size_bits=1 is 16k,
- + * then way_size_0 would be 8k.
- + *
- + * L2 cache size = number of ways * way size.
- + */
- + way_size_bits = (aux & L2C_AUX_CTRL_WAY_SIZE_MASK) >>
- + L2C_AUX_CTRL_WAY_SIZE_SHIFT;
- + l2x0_size = ways * (data->way_size_0 << way_size_bits);
- +
- + fns = data->outer_cache;
- + fns.write_sec = outer_cache.write_sec;
- + if (data->fixup)
- + data->fixup(l2x0_base, cache_id, &fns);
- +
- + /*
- + * Check if l2x0 controller is already enabled. If we are booting
- + * in non-secure mode accessing the below registers will fault.
- */
- - way_size = (aux & L2X0_AUX_CTRL_WAY_SIZE_MASK) >> 17;
- - way_size = 1 << (way_size + way_size_shift);
- + if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN))
- + data->enable(l2x0_base, aux, data->num_lock);
-
- - l2x0_size = ways * way_size * SZ_1K;
- + outer_cache = fns;
-
- /*
- - * Check if l2x0 controller is already enabled.
- - * If you are booting from non-secure mode
- - * accessing the below registers will fault.
- + * It is strange to save the register state before initialisation,
- + * but hey, this is what the DT implementations decided to do.
- */
- - if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
- - /* Make sure that I&D is not locked down when starting */
- - l2x0_unlock(cache_id);
- + if (data->save)
- + data->save(l2x0_base);
- +
- + /* Re-read it in case some bits are reserved. */
- + aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
- +
- + pr_info("%s cache controller enabled, %d ways, %d kB\n",
- + data->type, ways, l2x0_size >> 10);
- + pr_info("%s: CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n",
- + data->type, cache_id, aux);
- +}
-
- - /* l2x0 controller is disabled */
- - writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL);
- +void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
- +{
- + const struct l2c_init_data *data;
- + u32 cache_id;
-
- - l2x0_inv_all();
- + l2x0_base = base;
-
- - /* enable L2X0 */
- - writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL);
- + cache_id = readl_relaxed(base + L2X0_CACHE_ID);
- +
- + switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
- + default:
- + case L2X0_CACHE_ID_PART_L210:
- + data = &l2c210_data;
- + break;
- +
- + case L2X0_CACHE_ID_PART_L220:
- + data = &l2c220_data;
- + break;
- +
- + case L2X0_CACHE_ID_PART_L310:
- + data = &l2c310_init_fns;
- + break;
- }
-
- - /* Re-read it in case some bits are reserved. */
- - aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
- + __l2c_init(data, aux_val, aux_mask, cache_id);
- +}
- +
- +#ifdef CONFIG_OF
- +static int l2_wt_override;
- +
- +/* Aurora don't have the cache ID register available, so we have to
- + * pass it though the device tree */
- +static u32 cache_id_part_number_from_dt;
- +
- +static void __init l2x0_of_parse(const struct device_node *np,
- + u32 *aux_val, u32 *aux_mask)
- +{
- + u32 data[2] = { 0, 0 };
- + u32 tag = 0;
- + u32 dirty = 0;
- + u32 val = 0, mask = 0;
- +
- + of_property_read_u32(np, "arm,tag-latency", &tag);
- + if (tag) {
- + mask |= L2X0_AUX_CTRL_TAG_LATENCY_MASK;
- + val |= (tag - 1) << L2X0_AUX_CTRL_TAG_LATENCY_SHIFT;
- + }
- +
- + of_property_read_u32_array(np, "arm,data-latency",
- + data, ARRAY_SIZE(data));
- + if (data[0] && data[1]) {
- + mask |= L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK |
- + L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK;
- + val |= ((data[0] - 1) << L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT) |
- + ((data[1] - 1) << L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT);
- + }
- +
- + of_property_read_u32(np, "arm,dirty-latency", &dirty);
- + if (dirty) {
- + mask |= L2X0_AUX_CTRL_DIRTY_LATENCY_MASK;
- + val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT;
- + }
-
- - /* Save the value for resuming. */
- - l2x0_saved_regs.aux_ctrl = aux;
- + *aux_val &= ~mask;
- + *aux_val |= val;
- + *aux_mask &= ~mask;
- +}
- +
- +static const struct l2c_init_data of_l2c210_data __initconst = {
- + .type = "L2C-210",
- + .way_size_0 = SZ_8K,
- + .num_lock = 1,
- + .of_parse = l2x0_of_parse,
- + .enable = l2c_enable,
- + .save = l2c_save,
- + .outer_cache = {
- + .inv_range = l2c210_inv_range,
- + .clean_range = l2c210_clean_range,
- + .flush_range = l2c210_flush_range,
- + .flush_all = l2c210_flush_all,
- + .disable = l2c_disable,
- + .sync = l2c210_sync,
- + .resume = l2c210_resume,
- + },
- +};
- +
- +static const struct l2c_init_data of_l2c220_data __initconst = {
- + .type = "L2C-220",
- + .way_size_0 = SZ_8K,
- + .num_lock = 1,
- + .of_parse = l2x0_of_parse,
- + .enable = l2c220_enable,
- + .save = l2c_save,
- + .outer_cache = {
- + .inv_range = l2c220_inv_range,
- + .clean_range = l2c220_clean_range,
- + .flush_range = l2c220_flush_range,
- + .flush_all = l2c220_flush_all,
- + .disable = l2c_disable,
- + .sync = l2c220_sync,
- + .resume = l2c210_resume,
- + },
- +};
- +
- +static void __init l2c310_of_parse(const struct device_node *np,
- + u32 *aux_val, u32 *aux_mask)
- +{
- + u32 data[3] = { 0, 0, 0 };
- + u32 tag[3] = { 0, 0, 0 };
- + u32 filter[2] = { 0, 0 };
- +
- + of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag));
- + if (tag[0] && tag[1] && tag[2])
- + writel_relaxed(
- + L310_LATENCY_CTRL_RD(tag[0] - 1) |
- + L310_LATENCY_CTRL_WR(tag[1] - 1) |
- + L310_LATENCY_CTRL_SETUP(tag[2] - 1),
- + l2x0_base + L310_TAG_LATENCY_CTRL);
- +
- + of_property_read_u32_array(np, "arm,data-latency",
- + data, ARRAY_SIZE(data));
- + if (data[0] && data[1] && data[2])
- + writel_relaxed(
- + L310_LATENCY_CTRL_RD(data[0] - 1) |
- + L310_LATENCY_CTRL_WR(data[1] - 1) |
- + L310_LATENCY_CTRL_SETUP(data[2] - 1),
- + l2x0_base + L310_DATA_LATENCY_CTRL);
-
- - if (!of_init) {
- - outer_cache.inv_range = l2x0_inv_range;
- - outer_cache.clean_range = l2x0_clean_range;
- - outer_cache.flush_range = l2x0_flush_range;
- - outer_cache.sync = l2x0_cache_sync;
- - outer_cache.flush_all = l2x0_flush_all;
- - outer_cache.inv_all = l2x0_inv_all;
- - outer_cache.disable = l2x0_disable;
- - }
- -
- - pr_info("%s cache controller enabled\n", type);
- - pr_info("l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d kB\n",
- - ways, cache_id, aux, l2x0_size >> 10);
- + of_property_read_u32_array(np, "arm,filter-ranges",
- + filter, ARRAY_SIZE(filter));
- + if (filter[1]) {
- + writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M),
- + l2x0_base + L310_ADDR_FILTER_END);
- + writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L310_ADDR_FILTER_EN,
- + l2x0_base + L310_ADDR_FILTER_START);
- + }
- }
-
- -#ifdef CONFIG_OF
- -static int l2_wt_override;
- +static const struct l2c_init_data of_l2c310_data __initconst = {
- + .type = "L2C-310",
- + .way_size_0 = SZ_8K,
- + .num_lock = 8,
- + .of_parse = l2c310_of_parse,
- + .enable = l2c310_enable,
- + .fixup = l2c310_fixup,
- + .save = l2c310_save,
- + .outer_cache = {
- + .inv_range = l2c210_inv_range,
- + .clean_range = l2c210_clean_range,
- + .flush_range = l2c210_flush_range,
- + .flush_all = l2c210_flush_all,
- + .disable = l2c310_disable,
- + .sync = l2c210_sync,
- + .resume = l2c310_resume,
- + },
- +};
-
- /*
- * Note that the end addresses passed to Linux primitives are
- @@ -524,6 +1166,100 @@
- }
- }
-
- +static void aurora_save(void __iomem *base)
- +{
- + l2x0_saved_regs.ctrl = readl_relaxed(base + L2X0_CTRL);
- + l2x0_saved_regs.aux_ctrl = readl_relaxed(base + L2X0_AUX_CTRL);
- +}
- +
- +static void aurora_resume(void)
- +{
- + void __iomem *base = l2x0_base;
- +
- + if (!(readl(base + L2X0_CTRL) & L2X0_CTRL_EN)) {
- + writel_relaxed(l2x0_saved_regs.aux_ctrl, base + L2X0_AUX_CTRL);
- + writel_relaxed(l2x0_saved_regs.ctrl, base + L2X0_CTRL);
- + }
- +}
- +
- +/*
- + * For Aurora cache in no outer mode, enable via the CP15 coprocessor
- + * broadcasting of cache commands to L2.
- + */
- +static void __init aurora_enable_no_outer(void __iomem *base, u32 aux,
- + unsigned num_lock)
- +{
- + u32 u;
- +
- + asm volatile("mrc p15, 1, %0, c15, c2, 0" : "=r" (u));
- + u |= AURORA_CTRL_FW; /* Set the FW bit */
- + asm volatile("mcr p15, 1, %0, c15, c2, 0" : : "r" (u));
- +
- + isb();
- +
- + l2c_enable(base, aux, num_lock);
- +}
- +
- +static void __init aurora_fixup(void __iomem *base, u32 cache_id,
- + struct outer_cache_fns *fns)
- +{
- + sync_reg_offset = AURORA_SYNC_REG;
- +}
- +
- +static void __init aurora_of_parse(const struct device_node *np,
- + u32 *aux_val, u32 *aux_mask)
- +{
- + u32 val = AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU;
- + u32 mask = AURORA_ACR_REPLACEMENT_MASK;
- +
- + of_property_read_u32(np, "cache-id-part",
- + &cache_id_part_number_from_dt);
- +
- + /* Determine and save the write policy */
- + l2_wt_override = of_property_read_bool(np, "wt-override");
- +
- + if (l2_wt_override) {
- + val |= AURORA_ACR_FORCE_WRITE_THRO_POLICY;
- + mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK;
- + }
- +
- + *aux_val &= ~mask;
- + *aux_val |= val;
- + *aux_mask &= ~mask;
- +}
- +
- +static const struct l2c_init_data of_aurora_with_outer_data __initconst = {
- + .type = "Aurora",
- + .way_size_0 = SZ_4K,
- + .num_lock = 4,
- + .of_parse = aurora_of_parse,
- + .enable = l2c_enable,
- + .fixup = aurora_fixup,
- + .save = aurora_save,
- + .outer_cache = {
- + .inv_range = aurora_inv_range,
- + .clean_range = aurora_clean_range,
- + .flush_range = aurora_flush_range,
- + .flush_all = l2x0_flush_all,
- + .disable = l2x0_disable,
- + .sync = l2x0_cache_sync,
- + .resume = aurora_resume,
- + },
- +};
- +
- +static const struct l2c_init_data of_aurora_no_outer_data __initconst = {
- + .type = "Aurora",
- + .way_size_0 = SZ_4K,
- + .num_lock = 4,
- + .of_parse = aurora_of_parse,
- + .enable = aurora_enable_no_outer,
- + .fixup = aurora_fixup,
- + .save = aurora_save,
- + .outer_cache = {
- + .resume = aurora_resume,
- + },
- +};
- +
- /*
- * For certain Broadcom SoCs, depending on the address range, different offsets
- * need to be added to the address before passing it to L2 for
- @@ -588,16 +1324,16 @@
-
- /* normal case, no cross section between start and end */
- if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) {
- - l2x0_inv_range(new_start, new_end);
- + l2c210_inv_range(new_start, new_end);
- return;
- }
-
- /* They cross sections, so it can only be a cross from section
- * 2 to section 3
- */
- - l2x0_inv_range(new_start,
- + l2c210_inv_range(new_start,
- bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1));
- - l2x0_inv_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR),
- + l2c210_inv_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR),
- new_end);
- }
-
- @@ -610,26 +1346,21 @@
- if (unlikely(end <= start))
- return;
-
- - if ((end - start) >= l2x0_size) {
- - l2x0_clean_all();
- - return;
- - }
- -
- new_start = bcm_l2_phys_addr(start);
- new_end = bcm_l2_phys_addr(end);
-
- /* normal case, no cross section between start and end */
- if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) {
- - l2x0_clean_range(new_start, new_end);
- + l2c210_clean_range(new_start, new_end);
- return;
- }
-
- /* They cross sections, so it can only be a cross from section
- * 2 to section 3
- */
- - l2x0_clean_range(new_start,
- + l2c210_clean_range(new_start,
- bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1));
- - l2x0_clean_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR),
- + l2c210_clean_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR),
- new_end);
- }
-
- @@ -643,7 +1374,7 @@
- return;
-
- if ((end - start) >= l2x0_size) {
- - l2x0_flush_all();
- + outer_cache.flush_all();
- return;
- }
-
- @@ -652,283 +1383,67 @@
-
- /* normal case, no cross section between start and end */
- if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) {
- - l2x0_flush_range(new_start, new_end);
- + l2c210_flush_range(new_start, new_end);
- return;
- }
-
- /* They cross sections, so it can only be a cross from section
- * 2 to section 3
- */
- - l2x0_flush_range(new_start,
- + l2c210_flush_range(new_start,
- bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1));
- - l2x0_flush_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR),
- + l2c210_flush_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR),
- new_end);
- }
-
- -static void __init l2x0_of_setup(const struct device_node *np,
- - u32 *aux_val, u32 *aux_mask)
- -{
- - u32 data[2] = { 0, 0 };
- - u32 tag = 0;
- - u32 dirty = 0;
- - u32 val = 0, mask = 0;
- -
- - of_property_read_u32(np, "arm,tag-latency", &tag);
- - if (tag) {
- - mask |= L2X0_AUX_CTRL_TAG_LATENCY_MASK;
- - val |= (tag - 1) << L2X0_AUX_CTRL_TAG_LATENCY_SHIFT;
- - }
- -
- - of_property_read_u32_array(np, "arm,data-latency",
- - data, ARRAY_SIZE(data));
- - if (data[0] && data[1]) {
- - mask |= L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK |
- - L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK;
- - val |= ((data[0] - 1) << L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT) |
- - ((data[1] - 1) << L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT);
- - }
- -
- - of_property_read_u32(np, "arm,dirty-latency", &dirty);
- - if (dirty) {
- - mask |= L2X0_AUX_CTRL_DIRTY_LATENCY_MASK;
- - val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT;
- - }
- -
- - *aux_val &= ~mask;
- - *aux_val |= val;
- - *aux_mask &= ~mask;
- -}
- -
- -static void __init pl310_of_setup(const struct device_node *np,
- - u32 *aux_val, u32 *aux_mask)
- -{
- - u32 data[3] = { 0, 0, 0 };
- - u32 tag[3] = { 0, 0, 0 };
- - u32 filter[2] = { 0, 0 };
- -
- - of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag));
- - if (tag[0] && tag[1] && tag[2])
- - writel_relaxed(
- - ((tag[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) |
- - ((tag[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) |
- - ((tag[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT),
- - l2x0_base + L2X0_TAG_LATENCY_CTRL);
- -
- - of_property_read_u32_array(np, "arm,data-latency",
- - data, ARRAY_SIZE(data));
- - if (data[0] && data[1] && data[2])
- - writel_relaxed(
- - ((data[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) |
- - ((data[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) |
- - ((data[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT),
- - l2x0_base + L2X0_DATA_LATENCY_CTRL);
- -
- - of_property_read_u32_array(np, "arm,filter-ranges",
- - filter, ARRAY_SIZE(filter));
- - if (filter[1]) {
- - writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M),
- - l2x0_base + L2X0_ADDR_FILTER_END);
- - writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L2X0_ADDR_FILTER_EN,
- - l2x0_base + L2X0_ADDR_FILTER_START);
- - }
- -}
- -
- -static void __init pl310_save(void)
- -{
- - u32 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
- - L2X0_CACHE_ID_RTL_MASK;
- -
- - l2x0_saved_regs.tag_latency = readl_relaxed(l2x0_base +
- - L2X0_TAG_LATENCY_CTRL);
- - l2x0_saved_regs.data_latency = readl_relaxed(l2x0_base +
- - L2X0_DATA_LATENCY_CTRL);
- - l2x0_saved_regs.filter_end = readl_relaxed(l2x0_base +
- - L2X0_ADDR_FILTER_END);
- - l2x0_saved_regs.filter_start = readl_relaxed(l2x0_base +
- - L2X0_ADDR_FILTER_START);
- -
- - if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
- - /*
- - * From r2p0, there is Prefetch offset/control register
- - */
- - l2x0_saved_regs.prefetch_ctrl = readl_relaxed(l2x0_base +
- - L2X0_PREFETCH_CTRL);
- - /*
- - * From r3p0, there is Power control register
- - */
- - if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
- - l2x0_saved_regs.pwr_ctrl = readl_relaxed(l2x0_base +
- - L2X0_POWER_CTRL);
- - }
- -}
- +/* Broadcom L2C-310 start from ARMs R3P2 or later, and require no fixups */
- +static const struct l2c_init_data of_bcm_l2x0_data __initconst = {
- + .type = "BCM-L2C-310",
- + .way_size_0 = SZ_8K,
- + .num_lock = 8,
- + .of_parse = l2c310_of_parse,
- + .enable = l2c310_enable,
- + .save = l2c310_save,
- + .outer_cache = {
- + .inv_range = bcm_inv_range,
- + .clean_range = bcm_clean_range,
- + .flush_range = bcm_flush_range,
- + .flush_all = l2c210_flush_all,
- + .disable = l2c310_disable,
- + .sync = l2c210_sync,
- + .resume = l2c310_resume,
- + },
- +};
-
- -static void aurora_save(void)
- +static void __init tauros3_save(void __iomem *base)
- {
- - l2x0_saved_regs.ctrl = readl_relaxed(l2x0_base + L2X0_CTRL);
- - l2x0_saved_regs.aux_ctrl = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
- -}
- + l2c_save(base);
-
- -static void __init tauros3_save(void)
- -{
- l2x0_saved_regs.aux2_ctrl =
- - readl_relaxed(l2x0_base + TAUROS3_AUX2_CTRL);
- + readl_relaxed(base + TAUROS3_AUX2_CTRL);
- l2x0_saved_regs.prefetch_ctrl =
- - readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL);
- -}
- -
- -static void l2x0_resume(void)
- -{
- - if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
- - /* restore aux ctrl and enable l2 */
- - l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID));
- -
- - writel_relaxed(l2x0_saved_regs.aux_ctrl, l2x0_base +
- - L2X0_AUX_CTRL);
- -
- - l2x0_inv_all();
- -
- - writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL);
- - }
- -}
- -
- -static void pl310_resume(void)
- -{
- - u32 l2x0_revision;
- -
- - if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
- - /* restore pl310 setup */
- - writel_relaxed(l2x0_saved_regs.tag_latency,
- - l2x0_base + L2X0_TAG_LATENCY_CTRL);
- - writel_relaxed(l2x0_saved_regs.data_latency,
- - l2x0_base + L2X0_DATA_LATENCY_CTRL);
- - writel_relaxed(l2x0_saved_regs.filter_end,
- - l2x0_base + L2X0_ADDR_FILTER_END);
- - writel_relaxed(l2x0_saved_regs.filter_start,
- - l2x0_base + L2X0_ADDR_FILTER_START);
- -
- - l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
- - L2X0_CACHE_ID_RTL_MASK;
- -
- - if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
- - writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
- - l2x0_base + L2X0_PREFETCH_CTRL);
- - if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
- - writel_relaxed(l2x0_saved_regs.pwr_ctrl,
- - l2x0_base + L2X0_POWER_CTRL);
- - }
- - }
- -
- - l2x0_resume();
- -}
- -
- -static void aurora_resume(void)
- -{
- - if (!(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
- - writel_relaxed(l2x0_saved_regs.aux_ctrl,
- - l2x0_base + L2X0_AUX_CTRL);
- - writel_relaxed(l2x0_saved_regs.ctrl, l2x0_base + L2X0_CTRL);
- - }
- + readl_relaxed(base + L310_PREFETCH_CTRL);
- }
-
- static void tauros3_resume(void)
- {
- - if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
- + void __iomem *base = l2x0_base;
- +
- + if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)) {
- writel_relaxed(l2x0_saved_regs.aux2_ctrl,
- - l2x0_base + TAUROS3_AUX2_CTRL);
- + base + TAUROS3_AUX2_CTRL);
- writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
- - l2x0_base + L2X0_PREFETCH_CTRL);
- - }
- -
- - l2x0_resume();
- -}
- -
- -static void __init aurora_broadcast_l2_commands(void)
- -{
- - __u32 u;
- - /* Enable Broadcasting of cache commands to L2*/
- - __asm__ __volatile__("mrc p15, 1, %0, c15, c2, 0" : "=r"(u));
- - u |= AURORA_CTRL_FW; /* Set the FW bit */
- - __asm__ __volatile__("mcr p15, 1, %0, c15, c2, 0\n" : : "r"(u));
- - isb();
- -}
- -
- -static void __init aurora_of_setup(const struct device_node *np,
- - u32 *aux_val, u32 *aux_mask)
- -{
- - u32 val = AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU;
- - u32 mask = AURORA_ACR_REPLACEMENT_MASK;
- + base + L310_PREFETCH_CTRL);
-
- - of_property_read_u32(np, "cache-id-part",
- - &cache_id_part_number_from_dt);
- -
- - /* Determine and save the write policy */
- - l2_wt_override = of_property_read_bool(np, "wt-override");
- -
- - if (l2_wt_override) {
- - val |= AURORA_ACR_FORCE_WRITE_THRO_POLICY;
- - mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK;
- + l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8);
- }
- -
- - *aux_val &= ~mask;
- - *aux_val |= val;
- - *aux_mask &= ~mask;
- }
-
- -static const struct l2x0_of_data pl310_data = {
- - .setup = pl310_of_setup,
- - .save = pl310_save,
- - .outer_cache = {
- - .resume = pl310_resume,
- - .inv_range = l2x0_inv_range,
- - .clean_range = l2x0_clean_range,
- - .flush_range = l2x0_flush_range,
- - .sync = l2x0_cache_sync,
- - .flush_all = l2x0_flush_all,
- - .inv_all = l2x0_inv_all,
- - .disable = l2x0_disable,
- - },
- -};
- -
- -static const struct l2x0_of_data l2x0_data = {
- - .setup = l2x0_of_setup,
- - .save = NULL,
- - .outer_cache = {
- - .resume = l2x0_resume,
- - .inv_range = l2x0_inv_range,
- - .clean_range = l2x0_clean_range,
- - .flush_range = l2x0_flush_range,
- - .sync = l2x0_cache_sync,
- - .flush_all = l2x0_flush_all,
- - .inv_all = l2x0_inv_all,
- - .disable = l2x0_disable,
- - },
- -};
- -
- -static const struct l2x0_of_data aurora_with_outer_data = {
- - .setup = aurora_of_setup,
- - .save = aurora_save,
- - .outer_cache = {
- - .resume = aurora_resume,
- - .inv_range = aurora_inv_range,
- - .clean_range = aurora_clean_range,
- - .flush_range = aurora_flush_range,
- - .sync = l2x0_cache_sync,
- - .flush_all = l2x0_flush_all,
- - .inv_all = l2x0_inv_all,
- - .disable = l2x0_disable,
- - },
- -};
- -
- -static const struct l2x0_of_data aurora_no_outer_data = {
- - .setup = aurora_of_setup,
- - .save = aurora_save,
- - .outer_cache = {
- - .resume = aurora_resume,
- - },
- -};
- -
- -static const struct l2x0_of_data tauros3_data = {
- - .setup = NULL,
- +static const struct l2c_init_data of_tauros3_data __initconst = {
- + .type = "Tauros3",
- + .way_size_0 = SZ_8K,
- + .num_lock = 8,
- + .enable = l2c_enable,
- .save = tauros3_save,
- /* Tauros3 broadcasts L1 cache operations to L2 */
- .outer_cache = {
- @@ -936,43 +1451,26 @@
- },
- };
-
- -static const struct l2x0_of_data bcm_l2x0_data = {
- - .setup = pl310_of_setup,
- - .save = pl310_save,
- - .outer_cache = {
- - .resume = pl310_resume,
- - .inv_range = bcm_inv_range,
- - .clean_range = bcm_clean_range,
- - .flush_range = bcm_flush_range,
- - .sync = l2x0_cache_sync,
- - .flush_all = l2x0_flush_all,
- - .inv_all = l2x0_inv_all,
- - .disable = l2x0_disable,
- - },
- -};
- -
- +#define L2C_ID(name, fns) { .compatible = name, .data = (void *)&fns }
- static const struct of_device_id l2x0_ids[] __initconst = {
- - { .compatible = "arm,l210-cache", .data = (void *)&l2x0_data },
- - { .compatible = "arm,l220-cache", .data = (void *)&l2x0_data },
- - { .compatible = "arm,pl310-cache", .data = (void *)&pl310_data },
- - { .compatible = "bcm,bcm11351-a2-pl310-cache", /* deprecated name */
- - .data = (void *)&bcm_l2x0_data},
- - { .compatible = "brcm,bcm11351-a2-pl310-cache",
- - .data = (void *)&bcm_l2x0_data},
- - { .compatible = "marvell,aurora-outer-cache",
- - .data = (void *)&aurora_with_outer_data},
- - { .compatible = "marvell,aurora-system-cache",
- - .data = (void *)&aurora_no_outer_data},
- - { .compatible = "marvell,tauros3-cache",
- - .data = (void *)&tauros3_data },
- + L2C_ID("arm,l210-cache", of_l2c210_data),
- + L2C_ID("arm,l220-cache", of_l2c220_data),
- + L2C_ID("arm,pl310-cache", of_l2c310_data),
- + L2C_ID("brcm,bcm11351-a2-pl310-cache", of_bcm_l2x0_data),
- + L2C_ID("marvell,aurora-outer-cache", of_aurora_with_outer_data),
- + L2C_ID("marvell,aurora-system-cache", of_aurora_no_outer_data),
- + L2C_ID("marvell,tauros3-cache", of_tauros3_data),
- + /* Deprecated IDs */
- + L2C_ID("bcm,bcm11351-a2-pl310-cache", of_bcm_l2x0_data),
- {}
- };
-
- int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
- {
- + const struct l2c_init_data *data;
- struct device_node *np;
- - const struct l2x0_of_data *data;
- struct resource res;
- + u32 cache_id, old_aux;
-
- np = of_find_matching_node(NULL, l2x0_ids);
- if (!np)
- @@ -989,23 +1487,29 @@
-
- data = of_match_node(l2x0_ids, np)->data;
-
- - /* L2 configuration can only be changed if the cache is disabled */
- - if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
- - if (data->setup)
- - data->setup(np, &aux_val, &aux_mask);
- -
- - /* For aurora cache in no outer mode select the
- - * correct mode using the coprocessor*/
- - if (data == &aurora_no_outer_data)
- - aurora_broadcast_l2_commands();
- + old_aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
- + if (old_aux != ((old_aux & aux_mask) | aux_val)) {
- + pr_warn("L2C: platform modifies aux control register: 0x%08x -> 0x%08x\n",
- + old_aux, (old_aux & aux_mask) | aux_val);
- + } else if (aux_mask != ~0U && aux_val != 0) {
- + pr_alert("L2C: platform provided aux values match the hardware, so have no effect. Please remove them.\n");
- }
-
- - if (data->save)
- - data->save();
- + /* All L2 caches are unified, so this property should be specified */
- + if (!of_property_read_bool(np, "cache-unified"))
- + pr_err("L2C: device tree omits to specify unified cache\n");
- +
- + /* L2 configuration can only be changed if the cache is disabled */
- + if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN))
- + if (data->of_parse)
- + data->of_parse(np, &aux_val, &aux_mask);
- +
- + if (cache_id_part_number_from_dt)
- + cache_id = cache_id_part_number_from_dt;
- + else
- + cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID);
-
- - of_init = true;
- - memcpy(&outer_cache, &data->outer_cache, sizeof(outer_cache));
- - l2x0_init(l2x0_base, aux_val, aux_mask);
- + __l2c_init(data, aux_val, aux_mask, cache_id);
-
- return 0;
- }
- diff -Nur linux-3.14.35.orig/arch/arm/mm/dma-mapping.c linux-3.14.35/arch/arm/mm/dma-mapping.c
- --- linux-3.14.35.orig/arch/arm/mm/dma-mapping.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mm/dma-mapping.c 2015-03-08 14:27:37.441684502 -0500
- @@ -26,6 +26,7 @@
- #include <linux/io.h>
- #include <linux/vmalloc.h>
- #include <linux/sizes.h>
- +#include <linux/cma.h>
-
- #include <asm/memory.h>
- #include <asm/highmem.h>
- diff -Nur linux-3.14.35.orig/arch/arm/mm/fault.c linux-3.14.35/arch/arm/mm/fault.c
- --- linux-3.14.35.orig/arch/arm/mm/fault.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mm/fault.c 2015-03-08 14:27:37.441684502 -0500
- @@ -449,8 +449,16 @@
-
- if (pud_none(*pud_k))
- goto bad_area;
- - if (!pud_present(*pud))
- + if (!pud_present(*pud)) {
- set_pud(pud, *pud_k);
- + /*
- + * There is a small window during free_pgtables() where the
- + * user *pud entry is 0 but the TLB has not been invalidated
- + * and we get a level 2 (pmd) translation fault caused by the
- + * intermediate TLB caching of the old level 1 (pud) entry.
- + */
- + flush_tlb_kernel_page(addr);
- + }
-
- pmd = pmd_offset(pud, addr);
- pmd_k = pmd_offset(pud_k, addr);
- @@ -473,8 +481,9 @@
- #endif
- if (pmd_none(pmd_k[index]))
- goto bad_area;
- + if (!pmd_present(pmd[index]))
- + copy_pmd(pmd, pmd_k);
-
- - copy_pmd(pmd, pmd_k);
- return 0;
-
- bad_area:
- diff -Nur linux-3.14.35.orig/arch/arm/mm/init.c linux-3.14.35/arch/arm/mm/init.c
- --- linux-3.14.35.orig/arch/arm/mm/init.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mm/init.c 2015-03-08 14:27:37.441684502 -0500
- @@ -327,7 +327,7 @@
- * reserve memory for DMA contigouos allocations,
- * must come from DMA area inside low memory
- */
- - dma_contiguous_reserve(min(arm_dma_limit, arm_lowmem_limit));
- + dma_contiguous_reserve(arm_dma_limit);
-
- arm_memblock_steal_permitted = false;
- memblock_dump_all();
- diff -Nur linux-3.14.35.orig/arch/arm/mm/Kconfig linux-3.14.35/arch/arm/mm/Kconfig
- --- linux-3.14.35.orig/arch/arm/mm/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mm/Kconfig 2015-03-08 14:27:37.441684502 -0500
- @@ -898,6 +898,57 @@
- This option enables optimisations for the PL310 cache
- controller.
-
- +config PL310_ERRATA_588369
- + bool "PL310 errata: Clean & Invalidate maintenance operations do not invalidate clean lines"
- + depends on CACHE_L2X0
- + help
- + The PL310 L2 cache controller implements three types of Clean &
- + Invalidate maintenance operations: by Physical Address
- + (offset 0x7F0), by Index/Way (0x7F8) and by Way (0x7FC).
- + They are architecturally defined to behave as the execution of a
- + clean operation followed immediately by an invalidate operation,
- + both performing to the same memory location. This functionality
- + is not correctly implemented in PL310 as clean lines are not
- + invalidated as a result of these operations.
- +
- +config PL310_ERRATA_727915
- + bool "PL310 errata: Background Clean & Invalidate by Way operation can cause data corruption"
- + depends on CACHE_L2X0
- + help
- + PL310 implements the Clean & Invalidate by Way L2 cache maintenance
- + operation (offset 0x7FC). This operation runs in background so that
- + PL310 can handle normal accesses while it is in progress. Under very
- + rare circumstances, due to this erratum, write data can be lost when
- + PL310 treats a cacheable write transaction during a Clean &
- + Invalidate by Way operation.
- +
- +config PL310_ERRATA_753970
- + bool "PL310 errata: cache sync operation may be faulty"
- + depends on CACHE_PL310
- + help
- + This option enables the workaround for the 753970 PL310 (r3p0) erratum.
- +
- + Under some condition the effect of cache sync operation on
- + the store buffer still remains when the operation completes.
- + This means that the store buffer is always asked to drain and
- + this prevents it from merging any further writes. The workaround
- + is to replace the normal offset of cache sync operation (0x730)
- + by another offset targeting an unmapped PL310 register 0x740.
- + This has the same effect as the cache sync operation: store buffer
- + drain and waiting for all buffers empty.
- +
- +config PL310_ERRATA_769419
- + bool "PL310 errata: no automatic Store Buffer drain"
- + depends on CACHE_L2X0
- + help
- + On revisions of the PL310 prior to r3p2, the Store Buffer does
- + not automatically drain. This can cause normal, non-cacheable
- + writes to be retained when the memory system is idle, leading
- + to suboptimal I/O performance for drivers using coherent DMA.
- + This option adds a write barrier to the cpu_idle loop so that,
- + on systems with an outer cache, the store buffer is drained
- + explicitly.
- +
- config CACHE_TAUROS2
- bool "Enable the Tauros2 L2 cache controller"
- depends on (ARCH_DOVE || ARCH_MMP || CPU_PJ4)
- diff -Nur linux-3.14.35.orig/arch/arm/mm/l2c-common.c linux-3.14.35/arch/arm/mm/l2c-common.c
- --- linux-3.14.35.orig/arch/arm/mm/l2c-common.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/mm/l2c-common.c 2015-03-08 14:27:37.441684502 -0500
- @@ -0,0 +1,20 @@
- +/*
- + * Copyright (C) 2010 ARM Ltd.
- + * Written by Catalin Marinas <catalin.marinas@arm.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#include <linux/bug.h>
- +#include <linux/smp.h>
- +#include <asm/outercache.h>
- +
- +void outer_disable(void)
- +{
- + WARN_ON(!irqs_disabled());
- + WARN_ON(num_online_cpus() > 1);
- +
- + if (outer_cache.disable)
- + outer_cache.disable();
- +}
- diff -Nur linux-3.14.35.orig/arch/arm/mm/l2c-l2x0-resume.S linux-3.14.35/arch/arm/mm/l2c-l2x0-resume.S
- --- linux-3.14.35.orig/arch/arm/mm/l2c-l2x0-resume.S 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm/mm/l2c-l2x0-resume.S 2015-03-08 14:27:37.441684502 -0500
- @@ -0,0 +1,58 @@
- +/*
- + * L2C-310 early resume code. This can be used by platforms to restore
- + * the settings of their L2 cache controller before restoring the
- + * processor state.
- + *
- + * This code can only be used to if you are running in the secure world.
- + */
- +#include <linux/linkage.h>
- +#include <asm/hardware/cache-l2x0.h>
- +
- + .text
- +
- +ENTRY(l2c310_early_resume)
- + adr r0, 1f
- + ldr r2, [r0]
- + add r0, r2, r0
- +
- + ldmia r0, {r1, r2, r3, r4, r5, r6, r7, r8}
- + @ r1 = phys address of L2C-310 controller
- + @ r2 = aux_ctrl
- + @ r3 = tag_latency
- + @ r4 = data_latency
- + @ r5 = filter_start
- + @ r6 = filter_end
- + @ r7 = prefetch_ctrl
- + @ r8 = pwr_ctrl
- +
- + @ Check that the address has been initialised
- + teq r1, #0
- + moveq pc, lr
- +
- + @ The prefetch and power control registers are revision dependent
- + @ and can be written whether or not the L2 cache is enabled
- + ldr r0, [r1, #L2X0_CACHE_ID]
- + and r0, r0, #L2X0_CACHE_ID_RTL_MASK
- + cmp r0, #L310_CACHE_ID_RTL_R2P0
- + strcs r7, [r1, #L310_PREFETCH_CTRL]
- + cmp r0, #L310_CACHE_ID_RTL_R3P0
- + strcs r8, [r1, #L310_POWER_CTRL]
- +
- + @ Don't setup the L2 cache if it is already enabled
- + ldr r0, [r1, #L2X0_CTRL]
- + tst r0, #L2X0_CTRL_EN
- + movne pc, lr
- +
- + str r3, [r1, #L310_TAG_LATENCY_CTRL]
- + str r4, [r1, #L310_DATA_LATENCY_CTRL]
- + str r6, [r1, #L310_ADDR_FILTER_END]
- + str r5, [r1, #L310_ADDR_FILTER_START]
- +
- + str r2, [r1, #L2X0_AUX_CTRL]
- + mov r9, #L2X0_CTRL_EN
- + str r9, [r1, #L2X0_CTRL]
- + mov pc, lr
- +ENDPROC(l2c310_early_resume)
- +
- + .align
- +1: .long l2x0_saved_regs - .
- diff -Nur linux-3.14.35.orig/arch/arm/mm/Makefile linux-3.14.35/arch/arm/mm/Makefile
- --- linux-3.14.35.orig/arch/arm/mm/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mm/Makefile 2015-03-08 14:27:37.441684502 -0500
- @@ -95,7 +95,8 @@
- AFLAGS_proc-v6.o :=-Wa,-march=armv6
- AFLAGS_proc-v7.o :=-Wa,-march=armv7-a
-
- +obj-$(CONFIG_OUTER_CACHE) += l2c-common.o
- obj-$(CONFIG_CACHE_FEROCEON_L2) += cache-feroceon-l2.o
- -obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
- +obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o l2c-l2x0-resume.o
- obj-$(CONFIG_CACHE_XSC3L2) += cache-xsc3l2.o
- obj-$(CONFIG_CACHE_TAUROS2) += cache-tauros2.o
- diff -Nur linux-3.14.35.orig/arch/arm/mm/proc-v7.S linux-3.14.35/arch/arm/mm/proc-v7.S
- --- linux-3.14.35.orig/arch/arm/mm/proc-v7.S 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm/mm/proc-v7.S 2015-03-08 14:27:37.441684502 -0500
- @@ -334,6 +334,17 @@
- mcrlt p15, 0, r10, c15, c0, 1 @ write diagnostic register
- 1:
- #endif
- +#ifdef CONFIG_ARM_ERRATA_794072
- + mrc p15, 0, r10, c15, c0, 1 @ read diagnostic register
- + orr r10, r10, #1 << 4 @ set bit #4
- + mcr p15, 0, r10, c15, c0, 1 @ write diagnostic register
- +#endif
- +#ifdef CONFIG_ARM_ERRATA_761320
- + cmp r6, #0x40 @ present prior to r4p0
- + mrclt p15, 0, r10, c15, c0, 1 @ read diagnostic register
- + orrlt r10, r10, #1 << 21 @ set bit #21
- + mcrlt p15, 0, r10, c15, c0, 1 @ write diagnostic register
- +#endif
-
- /* Cortex-A15 Errata */
- 3: ldr r10, =0x00000c0f @ Cortex-A15 primary part number
- diff -Nur linux-3.14.35.orig/arch/arm64/boot/dts/apm-mustang.dts linux-3.14.35/arch/arm64/boot/dts/apm-mustang.dts
- --- linux-3.14.35.orig/arch/arm64/boot/dts/apm-mustang.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/boot/dts/apm-mustang.dts 2015-03-08 14:27:37.441684502 -0500
- @@ -24,3 +24,7 @@
- reg = < 0x1 0x00000000 0x0 0x80000000 >; /* Updated by bootloader */
- };
- };
- +
- +&serial0 {
- + status = "ok";
- +};
- diff -Nur linux-3.14.35.orig/arch/arm64/boot/dts/apm-storm.dtsi linux-3.14.35/arch/arm64/boot/dts/apm-storm.dtsi
- --- linux-3.14.35.orig/arch/arm64/boot/dts/apm-storm.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/boot/dts/apm-storm.dtsi 2015-03-08 14:27:37.441684502 -0500
- @@ -176,16 +176,226 @@
- reg-names = "csr-reg";
- clock-output-names = "eth8clk";
- };
- +
- + sataphy1clk: sataphy1clk@1f21c000 {
- + compatible = "apm,xgene-device-clock";
- + #clock-cells = <1>;
- + clocks = <&socplldiv2 0>;
- + reg = <0x0 0x1f21c000 0x0 0x1000>;
- + reg-names = "csr-reg";
- + clock-output-names = "sataphy1clk";
- + status = "disabled";
- + csr-offset = <0x4>;
- + csr-mask = <0x00>;
- + enable-offset = <0x0>;
- + enable-mask = <0x06>;
- + };
- +
- + sataphy2clk: sataphy1clk@1f22c000 {
- + compatible = "apm,xgene-device-clock";
- + #clock-cells = <1>;
- + clocks = <&socplldiv2 0>;
- + reg = <0x0 0x1f22c000 0x0 0x1000>;
- + reg-names = "csr-reg";
- + clock-output-names = "sataphy2clk";
- + status = "ok";
- + csr-offset = <0x4>;
- + csr-mask = <0x3a>;
- + enable-offset = <0x0>;
- + enable-mask = <0x06>;
- + };
- +
- + sataphy3clk: sataphy1clk@1f23c000 {
- + compatible = "apm,xgene-device-clock";
- + #clock-cells = <1>;
- + clocks = <&socplldiv2 0>;
- + reg = <0x0 0x1f23c000 0x0 0x1000>;
- + reg-names = "csr-reg";
- + clock-output-names = "sataphy3clk";
- + status = "ok";
- + csr-offset = <0x4>;
- + csr-mask = <0x3a>;
- + enable-offset = <0x0>;
- + enable-mask = <0x06>;
- + };
- +
- + sata01clk: sata01clk@1f21c000 {
- + compatible = "apm,xgene-device-clock";
- + #clock-cells = <1>;
- + clocks = <&socplldiv2 0>;
- + reg = <0x0 0x1f21c000 0x0 0x1000>;
- + reg-names = "csr-reg";
- + clock-output-names = "sata01clk";
- + csr-offset = <0x4>;
- + csr-mask = <0x05>;
- + enable-offset = <0x0>;
- + enable-mask = <0x39>;
- + };
- +
- + sata23clk: sata23clk@1f22c000 {
- + compatible = "apm,xgene-device-clock";
- + #clock-cells = <1>;
- + clocks = <&socplldiv2 0>;
- + reg = <0x0 0x1f22c000 0x0 0x1000>;
- + reg-names = "csr-reg";
- + clock-output-names = "sata23clk";
- + csr-offset = <0x4>;
- + csr-mask = <0x05>;
- + enable-offset = <0x0>;
- + enable-mask = <0x39>;
- + };
- +
- + sata45clk: sata45clk@1f23c000 {
- + compatible = "apm,xgene-device-clock";
- + #clock-cells = <1>;
- + clocks = <&socplldiv2 0>;
- + reg = <0x0 0x1f23c000 0x0 0x1000>;
- + reg-names = "csr-reg";
- + clock-output-names = "sata45clk";
- + csr-offset = <0x4>;
- + csr-mask = <0x05>;
- + enable-offset = <0x0>;
- + enable-mask = <0x39>;
- + };
- +
- + rtcclk: rtcclk@17000000 {
- + compatible = "apm,xgene-device-clock";
- + #clock-cells = <1>;
- + clocks = <&socplldiv2 0>;
- + reg = <0x0 0x17000000 0x0 0x2000>;
- + reg-names = "csr-reg";
- + csr-offset = <0xc>;
- + csr-mask = <0x2>;
- + enable-offset = <0x10>;
- + enable-mask = <0x2>;
- + clock-output-names = "rtcclk";
- + };
- };
-
- serial0: serial@1c020000 {
- + status = "disabled";
- device_type = "serial";
- - compatible = "ns16550";
- + compatible = "ns16550a";
- reg = <0 0x1c020000 0x0 0x1000>;
- reg-shift = <2>;
- clock-frequency = <10000000>; /* Updated by bootloader */
- interrupt-parent = <&gic>;
- interrupts = <0x0 0x4c 0x4>;
- };
- +
- + serial1: serial@1c021000 {
- + status = "disabled";
- + device_type = "serial";
- + compatible = "ns16550a";
- + reg = <0 0x1c021000 0x0 0x1000>;
- + reg-shift = <2>;
- + clock-frequency = <10000000>; /* Updated by bootloader */
- + interrupt-parent = <&gic>;
- + interrupts = <0x0 0x4d 0x4>;
- + };
- +
- + serial2: serial@1c022000 {
- + status = "disabled";
- + device_type = "serial";
- + compatible = "ns16550a";
- + reg = <0 0x1c022000 0x0 0x1000>;
- + reg-shift = <2>;
- + clock-frequency = <10000000>; /* Updated by bootloader */
- + interrupt-parent = <&gic>;
- + interrupts = <0x0 0x4e 0x4>;
- + };
- +
- + serial3: serial@1c023000 {
- + status = "disabled";
- + device_type = "serial";
- + compatible = "ns16550a";
- + reg = <0 0x1c023000 0x0 0x1000>;
- + reg-shift = <2>;
- + clock-frequency = <10000000>; /* Updated by bootloader */
- + interrupt-parent = <&gic>;
- + interrupts = <0x0 0x4f 0x4>;
- + };
- +
- + phy1: phy@1f21a000 {
- + compatible = "apm,xgene-phy";
- + reg = <0x0 0x1f21a000 0x0 0x100>;
- + #phy-cells = <1>;
- + clocks = <&sataphy1clk 0>;
- + status = "disabled";
- + apm,tx-boost-gain = <30 30 30 30 30 30>;
- + apm,tx-eye-tuning = <2 10 10 2 10 10>;
- + };
- +
- + phy2: phy@1f22a000 {
- + compatible = "apm,xgene-phy";
- + reg = <0x0 0x1f22a000 0x0 0x100>;
- + #phy-cells = <1>;
- + clocks = <&sataphy2clk 0>;
- + status = "ok";
- + apm,tx-boost-gain = <30 30 30 30 30 30>;
- + apm,tx-eye-tuning = <1 10 10 2 10 10>;
- + };
- +
- + phy3: phy@1f23a000 {
- + compatible = "apm,xgene-phy";
- + reg = <0x0 0x1f23a000 0x0 0x100>;
- + #phy-cells = <1>;
- + clocks = <&sataphy3clk 0>;
- + status = "ok";
- + apm,tx-boost-gain = <31 31 31 31 31 31>;
- + apm,tx-eye-tuning = <2 10 10 2 10 10>;
- + };
- +
- + sata1: sata@1a000000 {
- + compatible = "apm,xgene-ahci";
- + reg = <0x0 0x1a000000 0x0 0x1000>,
- + <0x0 0x1f210000 0x0 0x1000>,
- + <0x0 0x1f21d000 0x0 0x1000>,
- + <0x0 0x1f21e000 0x0 0x1000>,
- + <0x0 0x1f217000 0x0 0x1000>;
- + interrupts = <0x0 0x86 0x4>;
- + dma-coherent;
- + status = "disabled";
- + clocks = <&sata01clk 0>;
- + phys = <&phy1 0>;
- + phy-names = "sata-phy";
- + };
- +
- + sata2: sata@1a400000 {
- + compatible = "apm,xgene-ahci";
- + reg = <0x0 0x1a400000 0x0 0x1000>,
- + <0x0 0x1f220000 0x0 0x1000>,
- + <0x0 0x1f22d000 0x0 0x1000>,
- + <0x0 0x1f22e000 0x0 0x1000>,
- + <0x0 0x1f227000 0x0 0x1000>;
- + interrupts = <0x0 0x87 0x4>;
- + dma-coherent;
- + status = "ok";
- + clocks = <&sata23clk 0>;
- + phys = <&phy2 0>;
- + phy-names = "sata-phy";
- + };
- +
- + sata3: sata@1a800000 {
- + compatible = "apm,xgene-ahci";
- + reg = <0x0 0x1a800000 0x0 0x1000>,
- + <0x0 0x1f230000 0x0 0x1000>,
- + <0x0 0x1f23d000 0x0 0x1000>,
- + <0x0 0x1f23e000 0x0 0x1000>;
- + interrupts = <0x0 0x88 0x4>;
- + dma-coherent;
- + status = "ok";
- + clocks = <&sata45clk 0>;
- + phys = <&phy3 0>;
- + phy-names = "sata-phy";
- + };
- +
- + rtc: rtc@10510000 {
- + compatible = "apm,xgene-rtc";
- + reg = <0x0 0x10510000 0x0 0x400>;
- + interrupts = <0x0 0x46 0x4>;
- + #clock-cells = <1>;
- + clocks = <&rtcclk 0>;
- + };
- };
- };
- diff -Nur linux-3.14.35.orig/arch/arm64/boot/dts/clcd-panels.dtsi linux-3.14.35/arch/arm64/boot/dts/clcd-panels.dtsi
- --- linux-3.14.35.orig/arch/arm64/boot/dts/clcd-panels.dtsi 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/boot/dts/clcd-panels.dtsi 2015-03-08 14:27:37.441684502 -0500
- @@ -0,0 +1,52 @@
- +/*
- + * ARM Ltd. Versatile Express
- + *
- + */
- +
- +/ {
- + panels {
- + panel@0 {
- + compatible = "panel";
- + mode = "VGA";
- + refresh = <60>;
- + xres = <640>;
- + yres = <480>;
- + pixclock = <39721>;
- + left_margin = <40>;
- + right_margin = <24>;
- + upper_margin = <32>;
- + lower_margin = <11>;
- + hsync_len = <96>;
- + vsync_len = <2>;
- + sync = <0>;
- + vmode = "FB_VMODE_NONINTERLACED";
- +
- + tim2 = "TIM2_BCD", "TIM2_IPC";
- + cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)";
- + caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888";
- + bpp = <16>;
- + };
- +
- + panel@1 {
- + compatible = "panel";
- + mode = "XVGA";
- + refresh = <60>;
- + xres = <1024>;
- + yres = <768>;
- + pixclock = <15748>;
- + left_margin = <152>;
- + right_margin = <48>;
- + upper_margin = <23>;
- + lower_margin = <3>;
- + hsync_len = <104>;
- + vsync_len = <4>;
- + sync = <0>;
- + vmode = "FB_VMODE_NONINTERLACED";
- +
- + tim2 = "TIM2_BCD", "TIM2_IPC";
- + cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)";
- + caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888";
- + bpp = <16>;
- + };
- + };
- +};
- diff -Nur linux-3.14.35.orig/arch/arm64/boot/dts/fvp-base-gicv2-psci.dts linux-3.14.35/arch/arm64/boot/dts/fvp-base-gicv2-psci.dts
- --- linux-3.14.35.orig/arch/arm64/boot/dts/fvp-base-gicv2-psci.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/boot/dts/fvp-base-gicv2-psci.dts 2015-03-08 14:27:37.441684502 -0500
- @@ -0,0 +1,266 @@
- +/*
- + * Copyright (c) 2013, ARM Limited. All rights reserved.
- + *
- + * Redistribution and use in source and binary forms, with or without
- + * modification, are permitted provided that the following conditions are met:
- + *
- + * Redistributions of source code must retain the above copyright notice, this
- + * list of conditions and the following disclaimer.
- + *
- + * Redistributions in binary form must reproduce the above copyright notice,
- + * this list of conditions and the following disclaimer in the documentation
- + * and/or other materials provided with the distribution.
- + *
- + * Neither the name of ARM nor the names of its contributors may be used
- + * to endorse or promote products derived from this software without specific
- + * prior written permission.
- + *
- + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
- + */
- +
- +/dts-v1/;
- +
- +/memreserve/ 0x80000000 0x00010000;
- +
- +/ {
- +};
- +
- +/ {
- + model = "FVP Base";
- + compatible = "arm,vfp-base", "arm,vexpress";
- + interrupt-parent = <&gic>;
- + #address-cells = <2>;
- + #size-cells = <2>;
- +
- + chosen { };
- +
- + aliases {
- + serial0 = &v2m_serial0;
- + serial1 = &v2m_serial1;
- + serial2 = &v2m_serial2;
- + serial3 = &v2m_serial3;
- + };
- +
- + psci {
- + compatible = "arm,psci";
- + method = "smc";
- + cpu_suspend = <0xc4000001>;
- + cpu_off = <0x84000002>;
- + cpu_on = <0xc4000003>;
- + };
- +
- + cpus {
- + #address-cells = <2>;
- + #size-cells = <0>;
- +
- + big0: cpu@0 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a57", "arm,armv8";
- + reg = <0x0 0x0>;
- + enable-method = "psci";
- + clock-frequency = <1000000>;
- + };
- + big1: cpu@1 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a57", "arm,armv8";
- + reg = <0x0 0x1>;
- + enable-method = "psci";
- + clock-frequency = <1000000>;
- + };
- + big2: cpu@2 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a57", "arm,armv8";
- + reg = <0x0 0x2>;
- + enable-method = "psci";
- + clock-frequency = <1000000>;
- + };
- + big3: cpu@3 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a57", "arm,armv8";
- + reg = <0x0 0x3>;
- + enable-method = "psci";
- + clock-frequency = <1000000>;
- + };
- + little0: cpu@100 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a53", "arm,armv8";
- + reg = <0x0 0x100>;
- + enable-method = "psci";
- + clock-frequency = <1000000>;
- + };
- + little1: cpu@101 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a53", "arm,armv8";
- + reg = <0x0 0x101>;
- + enable-method = "psci";
- + clock-frequency = <1000000>;
- + };
- + little2: cpu@102 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a53", "arm,armv8";
- + reg = <0x0 0x102>;
- + enable-method = "psci";
- + clock-frequency = <1000000>;
- + };
- + little3: cpu@103 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a53", "arm,armv8";
- + reg = <0x0 0x103>;
- + enable-method = "psci";
- + clock-frequency = <1000000>;
- + };
- +
- + cpu-map {
- + cluster0 {
- + core0 {
- + cpu = <&big0>;
- + };
- + core1 {
- + cpu = <&big1>;
- + };
- + core2 {
- + cpu = <&big2>;
- + };
- + core3 {
- + cpu = <&big3>;
- + };
- + };
- + cluster1 {
- + core0 {
- + cpu = <&little0>;
- + };
- + core1 {
- + cpu = <&little1>;
- + };
- + core2 {
- + cpu = <&little2>;
- + };
- + core3 {
- + cpu = <&little3>;
- + };
- + };
- + };
- + };
- +
- + memory@80000000 {
- + device_type = "memory";
- + reg = <0x00000000 0x80000000 0 0x80000000>,
- + <0x00000008 0x80000000 0 0x80000000>;
- + };
- +
- + gic: interrupt-controller@2f000000 {
- + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
- + #interrupt-cells = <3>;
- + #address-cells = <0>;
- + interrupt-controller;
- + reg = <0x0 0x2f000000 0 0x10000>,
- + <0x0 0x2c000000 0 0x2000>,
- + <0x0 0x2c010000 0 0x2000>,
- + <0x0 0x2c02F000 0 0x2000>;
- + interrupts = <1 9 0xf04>;
- + };
- +
- + timer {
- + compatible = "arm,armv8-timer";
- + interrupts = <1 13 0xff01>,
- + <1 14 0xff01>,
- + <1 11 0xff01>,
- + <1 10 0xff01>;
- + clock-frequency = <100000000>;
- + };
- +
- + timer@2a810000 {
- + compatible = "arm,armv7-timer-mem";
- + reg = <0x0 0x2a810000 0x0 0x10000>;
- + clock-frequency = <100000000>;
- + #address-cells = <2>;
- + #size-cells = <2>;
- + ranges;
- + frame@2a820000 {
- + frame-number = <0>;
- + interrupts = <0 25 4>;
- + reg = <0x0 0x2a820000 0x0 0x10000>;
- + };
- + };
- +
- + pmu {
- + compatible = "arm,armv8-pmuv3";
- + interrupts = <0 60 4>,
- + <0 61 4>,
- + <0 62 4>,
- + <0 63 4>;
- + };
- +
- + smb {
- + compatible = "simple-bus";
- +
- + #address-cells = <2>;
- + #size-cells = <1>;
- + ranges = <0 0 0 0x08000000 0x04000000>,
- + <1 0 0 0x14000000 0x04000000>,
- + <2 0 0 0x18000000 0x04000000>,
- + <3 0 0 0x1c000000 0x04000000>,
- + <4 0 0 0x0c000000 0x04000000>,
- + <5 0 0 0x10000000 0x04000000>;
- +
- + #interrupt-cells = <1>;
- + interrupt-map-mask = <0 0 63>;
- + interrupt-map = <0 0 0 &gic 0 0 4>,
- + <0 0 1 &gic 0 1 4>,
- + <0 0 2 &gic 0 2 4>,
- + <0 0 3 &gic 0 3 4>,
- + <0 0 4 &gic 0 4 4>,
- + <0 0 5 &gic 0 5 4>,
- + <0 0 6 &gic 0 6 4>,
- + <0 0 7 &gic 0 7 4>,
- + <0 0 8 &gic 0 8 4>,
- + <0 0 9 &gic 0 9 4>,
- + <0 0 10 &gic 0 10 4>,
- + <0 0 11 &gic 0 11 4>,
- + <0 0 12 &gic 0 12 4>,
- + <0 0 13 &gic 0 13 4>,
- + <0 0 14 &gic 0 14 4>,
- + <0 0 15 &gic 0 15 4>,
- + <0 0 16 &gic 0 16 4>,
- + <0 0 17 &gic 0 17 4>,
- + <0 0 18 &gic 0 18 4>,
- + <0 0 19 &gic 0 19 4>,
- + <0 0 20 &gic 0 20 4>,
- + <0 0 21 &gic 0 21 4>,
- + <0 0 22 &gic 0 22 4>,
- + <0 0 23 &gic 0 23 4>,
- + <0 0 24 &gic 0 24 4>,
- + <0 0 25 &gic 0 25 4>,
- + <0 0 26 &gic 0 26 4>,
- + <0 0 27 &gic 0 27 4>,
- + <0 0 28 &gic 0 28 4>,
- + <0 0 29 &gic 0 29 4>,
- + <0 0 30 &gic 0 30 4>,
- + <0 0 31 &gic 0 31 4>,
- + <0 0 32 &gic 0 32 4>,
- + <0 0 33 &gic 0 33 4>,
- + <0 0 34 &gic 0 34 4>,
- + <0 0 35 &gic 0 35 4>,
- + <0 0 36 &gic 0 36 4>,
- + <0 0 37 &gic 0 37 4>,
- + <0 0 38 &gic 0 38 4>,
- + <0 0 39 &gic 0 39 4>,
- + <0 0 40 &gic 0 40 4>,
- + <0 0 41 &gic 0 41 4>,
- + <0 0 42 &gic 0 42 4>;
- +
- + /include/ "rtsm_ve-motherboard.dtsi"
- + };
- +};
- +
- +/include/ "clcd-panels.dtsi"
- diff -Nur linux-3.14.35.orig/arch/arm64/boot/dts/juno.dts linux-3.14.35/arch/arm64/boot/dts/juno.dts
- --- linux-3.14.35.orig/arch/arm64/boot/dts/juno.dts 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/boot/dts/juno.dts 2015-03-08 14:27:37.441684502 -0500
- @@ -0,0 +1,498 @@
- +/*
- + * ARM Ltd. Juno Plaform
- + *
- + * Fast Models FVP v2 support
- + */
- +
- +/dts-v1/;
- +
- +#include <dt-bindings/interrupt-controller/arm-gic.h>
- +
- +/ {
- + model = "Juno";
- + compatible = "arm,juno", "arm,vexpress";
- + interrupt-parent = <&gic>;
- + #address-cells = <2>;
- + #size-cells = <2>;
- +
- + aliases {
- + serial0 = &soc_uart0;
- + };
- +
- + cpus {
- + #address-cells = <2>;
- + #size-cells = <0>;
- +
- + cpu@100 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a53","arm,armv8";
- + reg = <0x0 0x100>;
- + enable-method = "psci";
- + };
- +
- + cpu@101 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a53","arm,armv8";
- + reg = <0x0 0x101>;
- + enable-method = "psci";
- + };
- +
- + cpu@102 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a53","arm,armv8";
- + reg = <0x0 0x102>;
- + enable-method = "psci";
- + };
- +
- + cpu@103 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a53","arm,armv8";
- + reg = <0x0 0x103>;
- + enable-method = "psci";
- + };
- +
- + cpu@0 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a57","arm,armv8";
- + reg = <0x0 0x0>;
- + enable-method = "psci";
- + };
- +
- + cpu@1 {
- + device_type = "cpu";
- + compatible = "arm,cortex-a57","arm,armv8";
- + reg = <0x0 0x1>;
- + enable-method = "psci";
- + };
- + };
- +
- + memory@80000000 {
- + device_type = "memory";
- + reg = <0x00000000 0x80000000 0x0 0x80000000>,
- + <0x00000008 0x80000000 0x1 0x80000000>;
- + };
- +
- + /* memory@14000000 {
- + device_type = "memory";
- + reg = <0x00000000 0x14000000 0x0 0x02000000>;
- + }; */
- +
- + gic: interrupt-controller@2c001000 {
- + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
- + #interrupt-cells = <3>;
- + #address-cells = <0>;
- + interrupt-controller;
- + reg = <0x0 0x2c010000 0 0x1000>,
- + <0x0 0x2c02f000 0 0x1000>,
- + <0x0 0x2c04f000 0 0x2000>,
- + <0x0 0x2c06f000 0 0x2000>;
- + interrupts = <GIC_PPI 9 0xf04>;
- + };
- +
- + msi0: msi@2c1c0000 {
- + compatible = "arm,gic-msi";
- + reg = <0x0 0x2c1c0000 0 0x10000
- + 0x0 0x2c1d0000 0 0x10000
- + 0x0 0x2c1e0000 0 0x10000
- + 0x0 0x2c1f0000 0 0x10000>;
- + };
- +
- + timer {
- + compatible = "arm,armv8-timer";
- + interrupts = <GIC_PPI 13 0xff01>,
- + <GIC_PPI 14 0xff01>,
- + <GIC_PPI 11 0xff01>,
- + <GIC_PPI 10 0xff01>;
- + };
- +
- + pmu {
- + compatible = "arm,armv8-pmuv3";
- + interrupts = <GIC_SPI 60 4>,
- + <GIC_SPI 61 4>,
- + <GIC_SPI 62 4>,
- + <GIC_SPI 63 4>;
- + };
- +
- + psci {
- + compatible = "arm,psci";
- + method = "smc";
- + cpu_suspend = <0xC4000001>;
- + cpu_off = <0x84000002>;
- + cpu_on = <0xC4000003>;
- + migrate = <0xC4000005>;
- + };
- +
- + pci0: pci@30000000 {
- + compatible = "arm,pcie-xr3";
- + device_type = "pci";
- + reg = <0 0x7ff30000 0 0x1000
- + 0 0x7ff20000 0 0x10000
- + 0 0x40000000 0 0x10000000>;
- + bus-range = <0 255>;
- + #address-cells = <3>;
- + #size-cells = <2>;
- + ranges = <0x01000000 0x0 0x00000000 0x00 0x5ff00000 0x0 0x00100000
- + 0x02000000 0x0 0x00000000 0x40 0x00000000 0x0 0x80000000
- + 0x42000000 0x0 0x80000000 0x40 0x80000000 0x0 0x80000000>;
- + #interrupt-cells = <1>;
- + interrupt-map-mask = <0 0 0 7>;
- + interrupt-map = <0 0 0 1 &gic 0 136 4
- + 0 0 0 2 &gic 0 137 4
- + 0 0 0 3 &gic 0 138 4
- + 0 0 0 4 &gic 0 139 4>;
- + };
- +
- + scpi: scpi@2b1f0000 {
- + compatible = "arm,scpi-mhu";
- + reg = <0x0 0x2b1f0000 0x0 0x10000>, /* MHU registers */
- + <0x0 0x2e000000 0x0 0x10000>; /* Payload area */
- + interrupts = <0 36 4>, /* low priority interrupt */
- + <0 35 4>, /* high priority interrupt */
- + <0 37 4>; /* secure channel interrupt */
- + #clock-cells = <1>;
- + clock-output-names = "a57", "a53", "gpu", "hdlcd0", "hdlcd1";
- + };
- +
- + hdlcd0_osc: scpi_osc@3 {
- + compatible = "arm,scpi-osc";
- + #clock-cells = <0>;
- + clocks = <&scpi 3>;
- + frequency-range = <23000000 210000000>;
- + clock-output-names = "pxlclk0";
- + };
- +
- + hdlcd1_osc: scpi_osc@4 {
- + compatible = "arm,scpi-osc";
- + #clock-cells = <0>;
- + clocks = <&scpi 4>;
- + frequency-range = <23000000 210000000>;
- + clock-output-names = "pxlclk1";
- + };
- +
- + soc_uartclk: refclk72738khz {
- + compatible = "fixed-clock";
- + #clock-cells = <0>;
- + clock-frequency = <7273800>;
- + clock-output-names = "juno:uartclk";
- + };
- +
- + soc_refclk24mhz: clk24mhz {
- + compatible = "fixed-clock";
- + #clock-cells = <0>;
- + clock-frequency = <24000000>;
- + clock-output-names = "juno:clk24mhz";
- + };
- +
- + mb_eth25mhz: clk25mhz {
- + compatible = "fixed-clock";
- + #clock-cells = <0>;
- + clock-frequency = <25000000>;
- + clock-output-names = "ethclk25mhz";
- + };
- +
- + soc_usb48mhz: clk48mhz {
- + compatible = "fixed-clock";
- + #clock-cells = <0>;
- + clock-frequency = <48000000>;
- + clock-output-names = "clk48mhz";
- + };
- +
- + soc_smc50mhz: clk50mhz {
- + compatible = "fixed-clock";
- + #clock-cells = <0>;
- + clock-frequency = <50000000>;
- + clock-output-names = "smc_clk";
- + };
- +
- + soc_refclk100mhz: refclk100mhz {
- + compatible = "fixed-clock";
- + #clock-cells = <0>;
- + clock-frequency = <100000000>;
- + clock-output-names = "apb_pclk";
- + };
- +
- + soc_faxiclk: refclk533mhz {
- + compatible = "fixed-clock";
- + #clock-cells = <0>;
- + clock-frequency = <533000000>;
- + clock-output-names = "faxi_clk";
- + };
- +
- + soc_fixed_3v3: fixedregulator@0 {
- + compatible = "regulator-fixed";
- + regulator-name = "3V3";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + };
- +
- + memory-controller@7ffd0000 {
- + compatible = "arm,pl354", "arm,primecell";
- + reg = <0 0x7ffd0000 0 0x1000>;
- + interrupts = <0 86 4>,
- + <0 87 4>;
- + clocks = <&soc_smc50mhz>;
- + clock-names = "apb_pclk";
- + chip5-memwidth = <16>;
- + };
- +
- + dma0: dma@0x7ff00000 {
- + compatible = "arm,pl330", "arm,primecell";
- + reg = <0x0 0x7ff00000 0 0x1000>;
- + interrupts = <0 95 4>,
- + <0 88 4>,
- + <0 89 4>,
- + <0 90 4>,
- + <0 91 4>,
- + <0 108 4>,
- + <0 109 4>,
- + <0 110 4>,
- + <0 111 4>;
- + #dma-cells = <1>;
- + #dma-channels = <8>;
- + #dma-requests = <32>;
- + clocks = <&soc_faxiclk>;
- + clock-names = "apb_pclk";
- + };
- +
- + soc_uart0: uart@7ff80000 {
- + compatible = "arm,pl011", "arm,primecell";
- + reg = <0x0 0x7ff80000 0x0 0x1000>;
- + interrupts = <0 83 4>;
- + clocks = <&soc_uartclk>, <&soc_refclk100mhz>;
- + clock-names = "uartclk", "apb_pclk";
- + dmas = <&dma0 1
- + &dma0 2>;
- + dma-names = "rx", "tx";
- + };
- +
- + /* this UART is reserved for secure software.
- + soc_uart1: uart@7ff70000 {
- + compatible = "arm,pl011", "arm,primecell";
- + reg = <0x0 0x7ff70000 0x0 0x1000>;
- + interrupts = <0 84 4>;
- + clocks = <&soc_uartclk>, <&soc_refclk100mhz>;
- + clock-names = "uartclk", "apb_pclk";
- + }; */
- +
- + ulpi_phy: phy@0 {
- + compatible = "phy-ulpi-generic";
- + reg = <0x0 0x94 0x0 0x4>;
- + phy-id = <0>;
- + };
- +
- + ehci@7ffc0000 {
- + compatible = "snps,ehci-h20ahb";
- + /* compatible = "arm,h20ahb-ehci"; */
- + reg = <0x0 0x7ffc0000 0x0 0x10000>;
- + interrupts = <0 117 4>;
- + clocks = <&soc_usb48mhz>;
- + clock-names = "otg";
- + phys = <&ulpi_phy>;
- + };
- +
- + ohci@0x7ffb0000 {
- + compatible = "generic-ohci";
- + reg = <0x0 0x7ffb0000 0x0 0x10000>;
- + interrupts = <0 116 4>;
- + clocks = <&soc_usb48mhz>;
- + clock-names = "otg";
- + };
- +
- + i2c@0x7ffa0000 {
- + #address-cells = <1>;
- + #size-cells = <0>;
- + compatible = "snps,designware-i2c";
- + reg = <0x0 0x7ffa0000 0x0 0x1000>;
- + interrupts = <0 104 4>;
- + clock-frequency = <400000>;
- + i2c-sda-hold-time-ns = <500>;
- + clocks = <&soc_smc50mhz>;
- +
- + dvi0: dvi-transmitter@70 {
- + compatible = "nxp,tda998x";
- + reg = <0x70>;
- + };
- +
- + dvi1: dvi-transmitter@71 {
- + compatible = "nxp,tda998x";
- + reg = <0x71>;
- + };
- + };
- +
- + /* mmci@1c050000 {
- + compatible = "arm,pl180", "arm,primecell";
- + reg = <0x0 0x1c050000 0x0 0x1000>;
- + interrupts = <0 73 4>,
- + <0 74 4>;
- + max-frequency = <12000000>;
- + vmmc-supply = <&soc_fixed_3v3>;
- + clocks = <&soc_refclk24mhz>, <&soc_refclk100mhz>;
- + clock-names = "mclk", "apb_pclk";
- + }; */
- +
- + hdlcd@7ff60000 {
- + compatible = "arm,hdlcd";
- + reg = <0 0x7ff60000 0 0x1000>;
- + interrupts = <0 85 4>;
- + clocks = <&hdlcd0_osc>;
- + clock-names = "pxlclk";
- + i2c-slave = <&dvi0>;
- +
- + /* display-timings {
- + native-mode = <&timing0>;
- + timing0: timing@0 {
- + /* 1024 x 768 framebufer, standard VGA timings * /
- + clock-frequency = <65000>;
- + hactive = <1024>;
- + vactive = <768>;
- + hfront-porch = <24>;
- + hback-porch = <160>;
- + hsync-len = <136>;
- + vfront-porch = <3>;
- + vback-porch = <29>;
- + vsync-len = <6>;
- + };
- + }; */
- + };
- +
- + hdlcd@7ff50000 {
- + compatible = "arm,hdlcd";
- + reg = <0 0x7ff50000 0 0x1000>;
- + interrupts = <0 93 4>;
- + clocks = <&hdlcd1_osc>;
- + clock-names = "pxlclk";
- + i2c-slave = <&dvi1>;
- +
- + display-timings {
- + native-mode = <&timing1>;
- + timing1: timing@1 {
- + /* 1024 x 768 framebufer, standard VGA timings */
- + clock-frequency = <65000>;
- + hactive = <1024>;
- + vactive = <768>;
- + hfront-porch = <24>;
- + hback-porch = <160>;
- + hsync-len = <136>;
- + vfront-porch = <3>;
- + vback-porch = <29>;
- + vsync-len = <6>;
- + };
- + };
- + };
- +
- + smb {
- + compatible = "simple-bus";
- + #address-cells = <2>;
- + #size-cells = <1>;
- + ranges = <0 0 0 0x08000000 0x04000000>,
- + <1 0 0 0x14000000 0x04000000>,
- + <2 0 0 0x18000000 0x04000000>,
- + <3 0 0 0x1c000000 0x04000000>,
- + <4 0 0 0x0c000000 0x04000000>,
- + <5 0 0 0x10000000 0x04000000>;
- +
- + #interrupt-cells = <1>;
- + interrupt-map-mask = <0 0 15>;
- + interrupt-map = <0 0 0 &gic 0 68 4>,
- + <0 0 1 &gic 0 69 4>,
- + <0 0 2 &gic 0 70 4>,
- + <0 0 3 &gic 0 160 4>,
- + <0 0 4 &gic 0 161 4>,
- + <0 0 5 &gic 0 162 4>,
- + <0 0 6 &gic 0 163 4>,
- + <0 0 7 &gic 0 164 4>,
- + <0 0 8 &gic 0 165 4>,
- + <0 0 9 &gic 0 166 4>,
- + <0 0 10 &gic 0 167 4>,
- + <0 0 11 &gic 0 168 4>,
- + <0 0 12 &gic 0 169 4>;
- +
- + motherboard {
- + model = "V2M-Juno";
- + arm,hbi = <0x252>;
- + arm,vexpress,site = <0>;
- + arm,v2m-memory-map = "rs1";
- + compatible = "arm,vexpress,v2p-p1", "simple-bus";
- + #address-cells = <2>; /* SMB chipselect number and offset */
- + #size-cells = <1>;
- + #interrupt-cells = <1>;
- + ranges;
- +
- + usb@5,00000000 {
- + compatible = "nxp,usb-isp1763";
- + reg = <5 0x00000000 0x20000>;
- + bus-width = <16>;
- + interrupts = <4>;
- + };
- +
- + ethernet@2,00000000 {
- + compatible = "smsc,lan9118", "smsc,lan9115";
- + reg = <2 0x00000000 0x10000>;
- + interrupts = <3>;
- + phy-mode = "mii";
- + reg-io-width = <4>;
- + smsc,irq-active-high;
- + smsc,irq-push-pull;
- + clocks = <&mb_eth25mhz>;
- + vdd33a-supply = <&soc_fixed_3v3>; /* change this */
- + vddvario-supply = <&soc_fixed_3v3>; /* and this */
- + };
- +
- + iofpga@3,00000000 {
- + compatible = "arm,amba-bus", "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <1>;
- + ranges = <0 3 0 0x200000>;
- +
- + kmi@060000 {
- + compatible = "arm,pl050", "arm,primecell";
- + reg = <0x060000 0x1000>;
- + interrupts = <8>;
- + clocks = <&soc_refclk24mhz>, <&soc_smc50mhz>;
- + clock-names = "KMIREFCLK", "apb_pclk";
- + };
- +
- + kmi@070000 {
- + compatible = "arm,pl050", "arm,primecell";
- + reg = <0x070000 0x1000>;
- + interrupts = <8>;
- + clocks = <&soc_refclk24mhz>, <&soc_smc50mhz>;
- + clock-names = "KMIREFCLK", "apb_pclk";
- + };
- +
- + wdt@0f0000 {
- + compatible = "arm,sp805", "arm,primecell";
- + reg = <0x0f0000 0x10000>;
- + interrupts = <7>;
- + clocks = <&soc_refclk24mhz>, <&soc_smc50mhz>;
- + clock-names = "wdogclk", "apb_pclk";
- + };
- +
- + v2m_timer01: timer@110000 {
- + compatible = "arm,sp804", "arm,primecell";
- + reg = <0x110000 0x10000>;
- + interrupts = <9>;
- + clocks = <&soc_refclk24mhz>, <&soc_smc50mhz>;
- + clock-names = "timclken1", "apb_pclk";
- + };
- +
- + v2m_timer23: timer@120000 {
- + compatible = "arm,sp804", "arm,primecell";
- + reg = <0x120000 0x10000>;
- + interrupts = <9>;
- + clocks = <&soc_refclk24mhz>, <&soc_smc50mhz>;
- + clock-names = "timclken1", "apb_pclk";
- + };
- +
- + rtc@170000 {
- + compatible = "arm,pl031", "arm,primecell";
- + reg = <0x170000 0x10000>;
- + interrupts = <0>;
- + clocks = <&soc_smc50mhz>;
- + clock-names = "apb_pclk";
- + };
- + };
- + };
- + };
- +};
- diff -Nur linux-3.14.35.orig/arch/arm64/boot/dts/Makefile linux-3.14.35/arch/arm64/boot/dts/Makefile
- --- linux-3.14.35.orig/arch/arm64/boot/dts/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/boot/dts/Makefile 2015-03-08 14:27:37.441684502 -0500
- @@ -1,5 +1,7 @@
- -dtb-$(CONFIG_ARCH_VEXPRESS) += rtsm_ve-aemv8a.dtb foundation-v8.dtb
- +dtb-$(CONFIG_ARCH_VEXPRESS) += rtsm_ve-aemv8a.dtb foundation-v8.dtb \
- + fvp-base-gicv2-psci.dtb
- dtb-$(CONFIG_ARCH_XGENE) += apm-mustang.dtb
- +dtb-$(CONFIG_ARCH_VEXPRESS) += juno.dtb
-
- targets += dtbs
- targets += $(dtb-y)
- diff -Nur linux-3.14.35.orig/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts linux-3.14.35/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
- --- linux-3.14.35.orig/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts 2015-03-08 14:27:37.441684502 -0500
- @@ -157,3 +157,5 @@
- /include/ "rtsm_ve-motherboard.dtsi"
- };
- };
- +
- +/include/ "clcd-panels.dtsi"
- diff -Nur linux-3.14.35.orig/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi linux-3.14.35/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi
- --- linux-3.14.35.orig/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi 2015-03-08 14:27:37.441684502 -0500
- @@ -182,6 +182,9 @@
- interrupts = <14>;
- clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>;
- clock-names = "clcdclk", "apb_pclk";
- + mode = "XVGA";
- + use_dma = <0>;
- + framebuffer = <0x18000000 0x00180000>;
- };
-
- virtio_block@0130000 {
- diff -Nur linux-3.14.35.orig/arch/arm64/crypto/aes-ce-ccm-core.S linux-3.14.35/arch/arm64/crypto/aes-ce-ccm-core.S
- --- linux-3.14.35.orig/arch/arm64/crypto/aes-ce-ccm-core.S 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/crypto/aes-ce-ccm-core.S 2015-03-08 14:27:37.441684502 -0500
- @@ -0,0 +1,222 @@
- +/*
- + * aesce-ccm-core.S - AES-CCM transform for ARMv8 with Crypto Extensions
- + *
- + * Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <linux/linkage.h>
- +
- + .text
- + .arch armv8-a+crypto
- +
- + /*
- + * void ce_aes_ccm_auth_data(u8 mac[], u8 const in[], u32 abytes,
- + * u32 *macp, u8 const rk[], u32 rounds);
- + */
- +ENTRY(ce_aes_ccm_auth_data)
- + ldr w8, [x3] /* leftover from prev round? */
- + ld1 {v0.2d}, [x0] /* load mac */
- + cbz w8, 1f
- + sub w8, w8, #16
- + eor v1.16b, v1.16b, v1.16b
- +0: ldrb w7, [x1], #1 /* get 1 byte of input */
- + subs w2, w2, #1
- + add w8, w8, #1
- + ins v1.b[0], w7
- + ext v1.16b, v1.16b, v1.16b, #1 /* rotate in the input bytes */
- + beq 8f /* out of input? */
- + cbnz w8, 0b
- + eor v0.16b, v0.16b, v1.16b
- +1: ld1 {v3.2d}, [x4] /* load first round key */
- + prfm pldl1strm, [x1]
- + cmp w5, #12 /* which key size? */
- + add x6, x4, #16
- + sub w7, w5, #2 /* modified # of rounds */
- + bmi 2f
- + bne 5f
- + mov v5.16b, v3.16b
- + b 4f
- +2: mov v4.16b, v3.16b
- + ld1 {v5.2d}, [x6], #16 /* load 2nd round key */
- +3: aese v0.16b, v4.16b
- + aesmc v0.16b, v0.16b
- +4: ld1 {v3.2d}, [x6], #16 /* load next round key */
- + aese v0.16b, v5.16b
- + aesmc v0.16b, v0.16b
- +5: ld1 {v4.2d}, [x6], #16 /* load next round key */
- + subs w7, w7, #3
- + aese v0.16b, v3.16b
- + aesmc v0.16b, v0.16b
- + ld1 {v5.2d}, [x6], #16 /* load next round key */
- + bpl 3b
- + aese v0.16b, v4.16b
- + subs w2, w2, #16 /* last data? */
- + eor v0.16b, v0.16b, v5.16b /* final round */
- + bmi 6f
- + ld1 {v1.16b}, [x1], #16 /* load next input block */
- + eor v0.16b, v0.16b, v1.16b /* xor with mac */
- + bne 1b
- +6: st1 {v0.2d}, [x0] /* store mac */
- + beq 10f
- + adds w2, w2, #16
- + beq 10f
- + mov w8, w2
- +7: ldrb w7, [x1], #1
- + umov w6, v0.b[0]
- + eor w6, w6, w7
- + strb w6, [x0], #1
- + subs w2, w2, #1
- + beq 10f
- + ext v0.16b, v0.16b, v0.16b, #1 /* rotate out the mac bytes */
- + b 7b
- +8: mov w7, w8
- + add w8, w8, #16
- +9: ext v1.16b, v1.16b, v1.16b, #1
- + adds w7, w7, #1
- + bne 9b
- + eor v0.16b, v0.16b, v1.16b
- + st1 {v0.2d}, [x0]
- +10: str w8, [x3]
- + ret
- +ENDPROC(ce_aes_ccm_auth_data)
- +
- + /*
- + * void ce_aes_ccm_final(u8 mac[], u8 const ctr[], u8 const rk[],
- + * u32 rounds);
- + */
- +ENTRY(ce_aes_ccm_final)
- + ld1 {v3.2d}, [x2], #16 /* load first round key */
- + ld1 {v0.2d}, [x0] /* load mac */
- + cmp w3, #12 /* which key size? */
- + sub w3, w3, #2 /* modified # of rounds */
- + ld1 {v1.2d}, [x1] /* load 1st ctriv */
- + bmi 0f
- + bne 3f
- + mov v5.16b, v3.16b
- + b 2f
- +0: mov v4.16b, v3.16b
- +1: ld1 {v5.2d}, [x2], #16 /* load next round key */
- + aese v0.16b, v4.16b
- + aese v1.16b, v4.16b
- + aesmc v0.16b, v0.16b
- + aesmc v1.16b, v1.16b
- +2: ld1 {v3.2d}, [x2], #16 /* load next round key */
- + aese v0.16b, v5.16b
- + aese v1.16b, v5.16b
- + aesmc v0.16b, v0.16b
- + aesmc v1.16b, v1.16b
- +3: ld1 {v4.2d}, [x2], #16 /* load next round key */
- + subs w3, w3, #3
- + aese v0.16b, v3.16b
- + aese v1.16b, v3.16b
- + aesmc v0.16b, v0.16b
- + aesmc v1.16b, v1.16b
- + bpl 1b
- + aese v0.16b, v4.16b
- + aese v1.16b, v4.16b
- + /* final round key cancels out */
- + eor v0.16b, v0.16b, v1.16b /* en-/decrypt the mac */
- + st1 {v0.2d}, [x0] /* store result */
- + ret
- +ENDPROC(ce_aes_ccm_final)
- +
- + .macro aes_ccm_do_crypt,enc
- + ldr x8, [x6, #8] /* load lower ctr */
- + ld1 {v0.2d}, [x5] /* load mac */
- + rev x8, x8 /* keep swabbed ctr in reg */
- +0: /* outer loop */
- + ld1 {v1.1d}, [x6] /* load upper ctr */
- + prfm pldl1strm, [x1]
- + add x8, x8, #1
- + rev x9, x8
- + cmp w4, #12 /* which key size? */
- + sub w7, w4, #2 /* get modified # of rounds */
- + ins v1.d[1], x9 /* no carry in lower ctr */
- + ld1 {v3.2d}, [x3] /* load first round key */
- + add x10, x3, #16
- + bmi 1f
- + bne 4f
- + mov v5.16b, v3.16b
- + b 3f
- +1: mov v4.16b, v3.16b
- + ld1 {v5.2d}, [x10], #16 /* load 2nd round key */
- +2: /* inner loop: 3 rounds, 2x interleaved */
- + aese v0.16b, v4.16b
- + aese v1.16b, v4.16b
- + aesmc v0.16b, v0.16b
- + aesmc v1.16b, v1.16b
- +3: ld1 {v3.2d}, [x10], #16 /* load next round key */
- + aese v0.16b, v5.16b
- + aese v1.16b, v5.16b
- + aesmc v0.16b, v0.16b
- + aesmc v1.16b, v1.16b
- +4: ld1 {v4.2d}, [x10], #16 /* load next round key */
- + subs w7, w7, #3
- + aese v0.16b, v3.16b
- + aese v1.16b, v3.16b
- + aesmc v0.16b, v0.16b
- + aesmc v1.16b, v1.16b
- + ld1 {v5.2d}, [x10], #16 /* load next round key */
- + bpl 2b
- + aese v0.16b, v4.16b
- + aese v1.16b, v4.16b
- + subs w2, w2, #16
- + bmi 6f /* partial block? */
- + ld1 {v2.16b}, [x1], #16 /* load next input block */
- + .if \enc == 1
- + eor v2.16b, v2.16b, v5.16b /* final round enc+mac */
- + eor v1.16b, v1.16b, v2.16b /* xor with crypted ctr */
- + .else
- + eor v2.16b, v2.16b, v1.16b /* xor with crypted ctr */
- + eor v1.16b, v2.16b, v5.16b /* final round enc */
- + .endif
- + eor v0.16b, v0.16b, v2.16b /* xor mac with pt ^ rk[last] */
- + st1 {v1.16b}, [x0], #16 /* write output block */
- + bne 0b
- + rev x8, x8
- + st1 {v0.2d}, [x5] /* store mac */
- + str x8, [x6, #8] /* store lsb end of ctr (BE) */
- +5: ret
- +
- +6: eor v0.16b, v0.16b, v5.16b /* final round mac */
- + eor v1.16b, v1.16b, v5.16b /* final round enc */
- + st1 {v0.2d}, [x5] /* store mac */
- + add w2, w2, #16 /* process partial tail block */
- +7: ldrb w9, [x1], #1 /* get 1 byte of input */
- + umov w6, v1.b[0] /* get top crypted ctr byte */
- + umov w7, v0.b[0] /* get top mac byte */
- + .if \enc == 1
- + eor w7, w7, w9
- + eor w9, w9, w6
- + .else
- + eor w9, w9, w6
- + eor w7, w7, w9
- + .endif
- + strb w9, [x0], #1 /* store out byte */
- + strb w7, [x5], #1 /* store mac byte */
- + subs w2, w2, #1
- + beq 5b
- + ext v0.16b, v0.16b, v0.16b, #1 /* shift out mac byte */
- + ext v1.16b, v1.16b, v1.16b, #1 /* shift out ctr byte */
- + b 7b
- + .endm
- +
- + /*
- + * void ce_aes_ccm_encrypt(u8 out[], u8 const in[], u32 cbytes,
- + * u8 const rk[], u32 rounds, u8 mac[],
- + * u8 ctr[]);
- + * void ce_aes_ccm_decrypt(u8 out[], u8 const in[], u32 cbytes,
- + * u8 const rk[], u32 rounds, u8 mac[],
- + * u8 ctr[]);
- + */
- +ENTRY(ce_aes_ccm_encrypt)
- + aes_ccm_do_crypt 1
- +ENDPROC(ce_aes_ccm_encrypt)
- +
- +ENTRY(ce_aes_ccm_decrypt)
- + aes_ccm_do_crypt 0
- +ENDPROC(ce_aes_ccm_decrypt)
- diff -Nur linux-3.14.35.orig/arch/arm64/crypto/aes-ce-ccm-glue.c linux-3.14.35/arch/arm64/crypto/aes-ce-ccm-glue.c
- --- linux-3.14.35.orig/arch/arm64/crypto/aes-ce-ccm-glue.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/crypto/aes-ce-ccm-glue.c 2015-03-08 14:27:37.441684502 -0500
- @@ -0,0 +1,297 @@
- +/*
- + * aes-ccm-glue.c - AES-CCM transform for ARMv8 with Crypto Extensions
- + *
- + * Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <asm/neon.h>
- +#include <asm/unaligned.h>
- +#include <crypto/aes.h>
- +#include <crypto/algapi.h>
- +#include <crypto/scatterwalk.h>
- +#include <linux/crypto.h>
- +#include <linux/module.h>
- +
- +static int num_rounds(struct crypto_aes_ctx *ctx)
- +{
- + /*
- + * # of rounds specified by AES:
- + * 128 bit key 10 rounds
- + * 192 bit key 12 rounds
- + * 256 bit key 14 rounds
- + * => n byte key => 6 + (n/4) rounds
- + */
- + return 6 + ctx->key_length / 4;
- +}
- +
- +asmlinkage void ce_aes_ccm_auth_data(u8 mac[], u8 const in[], u32 abytes,
- + u32 *macp, u32 const rk[], u32 rounds);
- +
- +asmlinkage void ce_aes_ccm_encrypt(u8 out[], u8 const in[], u32 cbytes,
- + u32 const rk[], u32 rounds, u8 mac[],
- + u8 ctr[]);
- +
- +asmlinkage void ce_aes_ccm_decrypt(u8 out[], u8 const in[], u32 cbytes,
- + u32 const rk[], u32 rounds, u8 mac[],
- + u8 ctr[]);
- +
- +asmlinkage void ce_aes_ccm_final(u8 mac[], u8 const ctr[], u32 const rk[],
- + u32 rounds);
- +
- +static int ccm_setkey(struct crypto_aead *tfm, const u8 *in_key,
- + unsigned int key_len)
- +{
- + struct crypto_aes_ctx *ctx = crypto_aead_ctx(tfm);
- + int ret;
- +
- + ret = crypto_aes_expand_key(ctx, in_key, key_len);
- + if (!ret)
- + return 0;
- +
- + tfm->base.crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
- + return -EINVAL;
- +}
- +
- +static int ccm_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
- +{
- + if ((authsize & 1) || authsize < 4)
- + return -EINVAL;
- + return 0;
- +}
- +
- +static int ccm_init_mac(struct aead_request *req, u8 maciv[], u32 msglen)
- +{
- + struct crypto_aead *aead = crypto_aead_reqtfm(req);
- + __be32 *n = (__be32 *)&maciv[AES_BLOCK_SIZE - 8];
- + u32 l = req->iv[0] + 1;
- +
- + /* verify that CCM dimension 'L' is set correctly in the IV */
- + if (l < 2 || l > 8)
- + return -EINVAL;
- +
- + /* verify that msglen can in fact be represented in L bytes */
- + if (l < 4 && msglen >> (8 * l))
- + return -EOVERFLOW;
- +
- + /*
- + * Even if the CCM spec allows L values of up to 8, the Linux cryptoapi
- + * uses a u32 type to represent msglen so the top 4 bytes are always 0.
- + */
- + n[0] = 0;
- + n[1] = cpu_to_be32(msglen);
- +
- + memcpy(maciv, req->iv, AES_BLOCK_SIZE - l);
- +
- + /*
- + * Meaning of byte 0 according to CCM spec (RFC 3610/NIST 800-38C)
- + * - bits 0..2 : max # of bytes required to represent msglen, minus 1
- + * (already set by caller)
- + * - bits 3..5 : size of auth tag (1 => 4 bytes, 2 => 6 bytes, etc)
- + * - bit 6 : indicates presence of authenticate-only data
- + */
- + maciv[0] |= (crypto_aead_authsize(aead) - 2) << 2;
- + if (req->assoclen)
- + maciv[0] |= 0x40;
- +
- + memset(&req->iv[AES_BLOCK_SIZE - l], 0, l);
- + return 0;
- +}
- +
- +static void ccm_calculate_auth_mac(struct aead_request *req, u8 mac[])
- +{
- + struct crypto_aead *aead = crypto_aead_reqtfm(req);
- + struct crypto_aes_ctx *ctx = crypto_aead_ctx(aead);
- + struct __packed { __be16 l; __be32 h; u16 len; } ltag;
- + struct scatter_walk walk;
- + u32 len = req->assoclen;
- + u32 macp = 0;
- +
- + /* prepend the AAD with a length tag */
- + if (len < 0xff00) {
- + ltag.l = cpu_to_be16(len);
- + ltag.len = 2;
- + } else {
- + ltag.l = cpu_to_be16(0xfffe);
- + put_unaligned_be32(len, <ag.h);
- + ltag.len = 6;
- + }
- +
- + ce_aes_ccm_auth_data(mac, (u8 *)<ag, ltag.len, &macp, ctx->key_enc,
- + num_rounds(ctx));
- + scatterwalk_start(&walk, req->assoc);
- +
- + do {
- + u32 n = scatterwalk_clamp(&walk, len);
- + u8 *p;
- +
- + if (!n) {
- + scatterwalk_start(&walk, sg_next(walk.sg));
- + n = scatterwalk_clamp(&walk, len);
- + }
- + p = scatterwalk_map(&walk);
- + ce_aes_ccm_auth_data(mac, p, n, &macp, ctx->key_enc,
- + num_rounds(ctx));
- + len -= n;
- +
- + scatterwalk_unmap(p);
- + scatterwalk_advance(&walk, n);
- + scatterwalk_done(&walk, 0, len);
- + } while (len);
- +}
- +
- +static int ccm_encrypt(struct aead_request *req)
- +{
- + struct crypto_aead *aead = crypto_aead_reqtfm(req);
- + struct crypto_aes_ctx *ctx = crypto_aead_ctx(aead);
- + struct blkcipher_desc desc = { .info = req->iv };
- + struct blkcipher_walk walk;
- + u8 __aligned(8) mac[AES_BLOCK_SIZE];
- + u8 buf[AES_BLOCK_SIZE];
- + u32 len = req->cryptlen;
- + int err;
- +
- + err = ccm_init_mac(req, mac, len);
- + if (err)
- + return err;
- +
- + kernel_neon_begin_partial(6);
- +
- + if (req->assoclen)
- + ccm_calculate_auth_mac(req, mac);
- +
- + /* preserve the original iv for the final round */
- + memcpy(buf, req->iv, AES_BLOCK_SIZE);
- +
- + blkcipher_walk_init(&walk, req->dst, req->src, len);
- + err = blkcipher_aead_walk_virt_block(&desc, &walk, aead,
- + AES_BLOCK_SIZE);
- +
- + while (walk.nbytes) {
- + u32 tail = walk.nbytes % AES_BLOCK_SIZE;
- +
- + if (walk.nbytes == len)
- + tail = 0;
- +
- + ce_aes_ccm_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
- + walk.nbytes - tail, ctx->key_enc,
- + num_rounds(ctx), mac, walk.iv);
- +
- + len -= walk.nbytes - tail;
- + err = blkcipher_walk_done(&desc, &walk, tail);
- + }
- + if (!err)
- + ce_aes_ccm_final(mac, buf, ctx->key_enc, num_rounds(ctx));
- +
- + kernel_neon_end();
- +
- + if (err)
- + return err;
- +
- + /* copy authtag to end of dst */
- + scatterwalk_map_and_copy(mac, req->dst, req->cryptlen,
- + crypto_aead_authsize(aead), 1);
- +
- + return 0;
- +}
- +
- +static int ccm_decrypt(struct aead_request *req)
- +{
- + struct crypto_aead *aead = crypto_aead_reqtfm(req);
- + struct crypto_aes_ctx *ctx = crypto_aead_ctx(aead);
- + unsigned int authsize = crypto_aead_authsize(aead);
- + struct blkcipher_desc desc = { .info = req->iv };
- + struct blkcipher_walk walk;
- + u8 __aligned(8) mac[AES_BLOCK_SIZE];
- + u8 buf[AES_BLOCK_SIZE];
- + u32 len = req->cryptlen - authsize;
- + int err;
- +
- + err = ccm_init_mac(req, mac, len);
- + if (err)
- + return err;
- +
- + kernel_neon_begin_partial(6);
- +
- + if (req->assoclen)
- + ccm_calculate_auth_mac(req, mac);
- +
- + /* preserve the original iv for the final round */
- + memcpy(buf, req->iv, AES_BLOCK_SIZE);
- +
- + blkcipher_walk_init(&walk, req->dst, req->src, len);
- + err = blkcipher_aead_walk_virt_block(&desc, &walk, aead,
- + AES_BLOCK_SIZE);
- +
- + while (walk.nbytes) {
- + u32 tail = walk.nbytes % AES_BLOCK_SIZE;
- +
- + if (walk.nbytes == len)
- + tail = 0;
- +
- + ce_aes_ccm_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
- + walk.nbytes - tail, ctx->key_enc,
- + num_rounds(ctx), mac, walk.iv);
- +
- + len -= walk.nbytes - tail;
- + err = blkcipher_walk_done(&desc, &walk, tail);
- + }
- + if (!err)
- + ce_aes_ccm_final(mac, buf, ctx->key_enc, num_rounds(ctx));
- +
- + kernel_neon_end();
- +
- + if (err)
- + return err;
- +
- + /* compare calculated auth tag with the stored one */
- + scatterwalk_map_and_copy(buf, req->src, req->cryptlen - authsize,
- + authsize, 0);
- +
- + if (memcmp(mac, buf, authsize))
- + return -EBADMSG;
- + return 0;
- +}
- +
- +static struct crypto_alg ccm_aes_alg = {
- + .cra_name = "ccm(aes)",
- + .cra_driver_name = "ccm-aes-ce",
- + .cra_priority = 300,
- + .cra_flags = CRYPTO_ALG_TYPE_AEAD,
- + .cra_blocksize = 1,
- + .cra_ctxsize = sizeof(struct crypto_aes_ctx),
- + .cra_alignmask = 7,
- + .cra_type = &crypto_aead_type,
- + .cra_module = THIS_MODULE,
- + .cra_aead = {
- + .ivsize = AES_BLOCK_SIZE,
- + .maxauthsize = AES_BLOCK_SIZE,
- + .setkey = ccm_setkey,
- + .setauthsize = ccm_setauthsize,
- + .encrypt = ccm_encrypt,
- + .decrypt = ccm_decrypt,
- + }
- +};
- +
- +static int __init aes_mod_init(void)
- +{
- + if (!(elf_hwcap & HWCAP_AES))
- + return -ENODEV;
- + return crypto_register_alg(&ccm_aes_alg);
- +}
- +
- +static void __exit aes_mod_exit(void)
- +{
- + crypto_unregister_alg(&ccm_aes_alg);
- +}
- +
- +module_init(aes_mod_init);
- +module_exit(aes_mod_exit);
- +
- +MODULE_DESCRIPTION("Synchronous AES in CCM mode using ARMv8 Crypto Extensions");
- +MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
- +MODULE_LICENSE("GPL v2");
- +MODULE_ALIAS("ccm(aes)");
- diff -Nur linux-3.14.35.orig/arch/arm64/crypto/aes-ce-cipher.c linux-3.14.35/arch/arm64/crypto/aes-ce-cipher.c
- --- linux-3.14.35.orig/arch/arm64/crypto/aes-ce-cipher.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/crypto/aes-ce-cipher.c 2015-03-08 14:27:37.441684502 -0500
- @@ -0,0 +1,155 @@
- +/*
- + * aes-ce-cipher.c - core AES cipher using ARMv8 Crypto Extensions
- + *
- + * Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <asm/neon.h>
- +#include <crypto/aes.h>
- +#include <linux/cpufeature.h>
- +#include <linux/crypto.h>
- +#include <linux/module.h>
- +
- +MODULE_DESCRIPTION("Synchronous AES cipher using ARMv8 Crypto Extensions");
- +MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
- +MODULE_LICENSE("GPL v2");
- +
- +struct aes_block {
- + u8 b[AES_BLOCK_SIZE];
- +};
- +
- +static int num_rounds(struct crypto_aes_ctx *ctx)
- +{
- + /*
- + * # of rounds specified by AES:
- + * 128 bit key 10 rounds
- + * 192 bit key 12 rounds
- + * 256 bit key 14 rounds
- + * => n byte key => 6 + (n/4) rounds
- + */
- + return 6 + ctx->key_length / 4;
- +}
- +
- +static void aes_cipher_encrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
- +{
- + struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
- + struct aes_block *out = (struct aes_block *)dst;
- + struct aes_block const *in = (struct aes_block *)src;
- + void *dummy0;
- + int dummy1;
- +
- + kernel_neon_begin_partial(4);
- +
- + __asm__(" ld1 {v0.16b}, %[in] ;"
- + " ld1 {v1.2d}, [%[key]], #16 ;"
- + " cmp %w[rounds], #10 ;"
- + " bmi 0f ;"
- + " bne 3f ;"
- + " mov v3.16b, v1.16b ;"
- + " b 2f ;"
- + "0: mov v2.16b, v1.16b ;"
- + " ld1 {v3.2d}, [%[key]], #16 ;"
- + "1: aese v0.16b, v2.16b ;"
- + " aesmc v0.16b, v0.16b ;"
- + "2: ld1 {v1.2d}, [%[key]], #16 ;"
- + " aese v0.16b, v3.16b ;"
- + " aesmc v0.16b, v0.16b ;"
- + "3: ld1 {v2.2d}, [%[key]], #16 ;"
- + " subs %w[rounds], %w[rounds], #3 ;"
- + " aese v0.16b, v1.16b ;"
- + " aesmc v0.16b, v0.16b ;"
- + " ld1 {v3.2d}, [%[key]], #16 ;"
- + " bpl 1b ;"
- + " aese v0.16b, v2.16b ;"
- + " eor v0.16b, v0.16b, v3.16b ;"
- + " st1 {v0.16b}, %[out] ;"
- +
- + : [out] "=Q"(*out),
- + [key] "=r"(dummy0),
- + [rounds] "=r"(dummy1)
- + : [in] "Q"(*in),
- + "1"(ctx->key_enc),
- + "2"(num_rounds(ctx) - 2)
- + : "cc");
- +
- + kernel_neon_end();
- +}
- +
- +static void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
- +{
- + struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
- + struct aes_block *out = (struct aes_block *)dst;
- + struct aes_block const *in = (struct aes_block *)src;
- + void *dummy0;
- + int dummy1;
- +
- + kernel_neon_begin_partial(4);
- +
- + __asm__(" ld1 {v0.16b}, %[in] ;"
- + " ld1 {v1.2d}, [%[key]], #16 ;"
- + " cmp %w[rounds], #10 ;"
- + " bmi 0f ;"
- + " bne 3f ;"
- + " mov v3.16b, v1.16b ;"
- + " b 2f ;"
- + "0: mov v2.16b, v1.16b ;"
- + " ld1 {v3.2d}, [%[key]], #16 ;"
- + "1: aesd v0.16b, v2.16b ;"
- + " aesimc v0.16b, v0.16b ;"
- + "2: ld1 {v1.2d}, [%[key]], #16 ;"
- + " aesd v0.16b, v3.16b ;"
- + " aesimc v0.16b, v0.16b ;"
- + "3: ld1 {v2.2d}, [%[key]], #16 ;"
- + " subs %w[rounds], %w[rounds], #3 ;"
- + " aesd v0.16b, v1.16b ;"
- + " aesimc v0.16b, v0.16b ;"
- + " ld1 {v3.2d}, [%[key]], #16 ;"
- + " bpl 1b ;"
- + " aesd v0.16b, v2.16b ;"
- + " eor v0.16b, v0.16b, v3.16b ;"
- + " st1 {v0.16b}, %[out] ;"
- +
- + : [out] "=Q"(*out),
- + [key] "=r"(dummy0),
- + [rounds] "=r"(dummy1)
- + : [in] "Q"(*in),
- + "1"(ctx->key_dec),
- + "2"(num_rounds(ctx) - 2)
- + : "cc");
- +
- + kernel_neon_end();
- +}
- +
- +static struct crypto_alg aes_alg = {
- + .cra_name = "aes",
- + .cra_driver_name = "aes-ce",
- + .cra_priority = 300,
- + .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
- + .cra_blocksize = AES_BLOCK_SIZE,
- + .cra_ctxsize = sizeof(struct crypto_aes_ctx),
- + .cra_module = THIS_MODULE,
- + .cra_cipher = {
- + .cia_min_keysize = AES_MIN_KEY_SIZE,
- + .cia_max_keysize = AES_MAX_KEY_SIZE,
- + .cia_setkey = crypto_aes_set_key,
- + .cia_encrypt = aes_cipher_encrypt,
- + .cia_decrypt = aes_cipher_decrypt
- + }
- +};
- +
- +static int __init aes_mod_init(void)
- +{
- + return crypto_register_alg(&aes_alg);
- +}
- +
- +static void __exit aes_mod_exit(void)
- +{
- + crypto_unregister_alg(&aes_alg);
- +}
- +
- +module_cpu_feature_match(AES, aes_mod_init);
- +module_exit(aes_mod_exit);
- diff -Nur linux-3.14.35.orig/arch/arm64/crypto/aes-ce.S linux-3.14.35/arch/arm64/crypto/aes-ce.S
- --- linux-3.14.35.orig/arch/arm64/crypto/aes-ce.S 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/crypto/aes-ce.S 2015-03-08 14:27:37.445684502 -0500
- @@ -0,0 +1,133 @@
- +/*
- + * linux/arch/arm64/crypto/aes-ce.S - AES cipher for ARMv8 with
- + * Crypto Extensions
- + *
- + * Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <linux/linkage.h>
- +
- +#define AES_ENTRY(func) ENTRY(ce_ ## func)
- +#define AES_ENDPROC(func) ENDPROC(ce_ ## func)
- +
- + .arch armv8-a+crypto
- +
- + /* preload all round keys */
- + .macro load_round_keys, rounds, rk
- + cmp \rounds, #12
- + blo 2222f /* 128 bits */
- + beq 1111f /* 192 bits */
- + ld1 {v17.16b-v18.16b}, [\rk], #32
- +1111: ld1 {v19.16b-v20.16b}, [\rk], #32
- +2222: ld1 {v21.16b-v24.16b}, [\rk], #64
- + ld1 {v25.16b-v28.16b}, [\rk], #64
- + ld1 {v29.16b-v31.16b}, [\rk]
- + .endm
- +
- + /* prepare for encryption with key in rk[] */
- + .macro enc_prepare, rounds, rk, ignore
- + load_round_keys \rounds, \rk
- + .endm
- +
- + /* prepare for encryption (again) but with new key in rk[] */
- + .macro enc_switch_key, rounds, rk, ignore
- + load_round_keys \rounds, \rk
- + .endm
- +
- + /* prepare for decryption with key in rk[] */
- + .macro dec_prepare, rounds, rk, ignore
- + load_round_keys \rounds, \rk
- + .endm
- +
- + .macro do_enc_Nx, de, mc, k, i0, i1, i2, i3
- + aes\de \i0\().16b, \k\().16b
- + .ifnb \i1
- + aes\de \i1\().16b, \k\().16b
- + .ifnb \i3
- + aes\de \i2\().16b, \k\().16b
- + aes\de \i3\().16b, \k\().16b
- + .endif
- + .endif
- + aes\mc \i0\().16b, \i0\().16b
- + .ifnb \i1
- + aes\mc \i1\().16b, \i1\().16b
- + .ifnb \i3
- + aes\mc \i2\().16b, \i2\().16b
- + aes\mc \i3\().16b, \i3\().16b
- + .endif
- + .endif
- + .endm
- +
- + /* up to 4 interleaved encryption rounds with the same round key */
- + .macro round_Nx, enc, k, i0, i1, i2, i3
- + .ifc \enc, e
- + do_enc_Nx e, mc, \k, \i0, \i1, \i2, \i3
- + .else
- + do_enc_Nx d, imc, \k, \i0, \i1, \i2, \i3
- + .endif
- + .endm
- +
- + /* up to 4 interleaved final rounds */
- + .macro fin_round_Nx, de, k, k2, i0, i1, i2, i3
- + aes\de \i0\().16b, \k\().16b
- + .ifnb \i1
- + aes\de \i1\().16b, \k\().16b
- + .ifnb \i3
- + aes\de \i2\().16b, \k\().16b
- + aes\de \i3\().16b, \k\().16b
- + .endif
- + .endif
- + eor \i0\().16b, \i0\().16b, \k2\().16b
- + .ifnb \i1
- + eor \i1\().16b, \i1\().16b, \k2\().16b
- + .ifnb \i3
- + eor \i2\().16b, \i2\().16b, \k2\().16b
- + eor \i3\().16b, \i3\().16b, \k2\().16b
- + .endif
- + .endif
- + .endm
- +
- + /* up to 4 interleaved blocks */
- + .macro do_block_Nx, enc, rounds, i0, i1, i2, i3
- + cmp \rounds, #12
- + blo 2222f /* 128 bits */
- + beq 1111f /* 192 bits */
- + round_Nx \enc, v17, \i0, \i1, \i2, \i3
- + round_Nx \enc, v18, \i0, \i1, \i2, \i3
- +1111: round_Nx \enc, v19, \i0, \i1, \i2, \i3
- + round_Nx \enc, v20, \i0, \i1, \i2, \i3
- +2222: .irp key, v21, v22, v23, v24, v25, v26, v27, v28, v29
- + round_Nx \enc, \key, \i0, \i1, \i2, \i3
- + .endr
- + fin_round_Nx \enc, v30, v31, \i0, \i1, \i2, \i3
- + .endm
- +
- + .macro encrypt_block, in, rounds, t0, t1, t2
- + do_block_Nx e, \rounds, \in
- + .endm
- +
- + .macro encrypt_block2x, i0, i1, rounds, t0, t1, t2
- + do_block_Nx e, \rounds, \i0, \i1
- + .endm
- +
- + .macro encrypt_block4x, i0, i1, i2, i3, rounds, t0, t1, t2
- + do_block_Nx e, \rounds, \i0, \i1, \i2, \i3
- + .endm
- +
- + .macro decrypt_block, in, rounds, t0, t1, t2
- + do_block_Nx d, \rounds, \in
- + .endm
- +
- + .macro decrypt_block2x, i0, i1, rounds, t0, t1, t2
- + do_block_Nx d, \rounds, \i0, \i1
- + .endm
- +
- + .macro decrypt_block4x, i0, i1, i2, i3, rounds, t0, t1, t2
- + do_block_Nx d, \rounds, \i0, \i1, \i2, \i3
- + .endm
- +
- +#include "aes-modes.S"
- diff -Nur linux-3.14.35.orig/arch/arm64/crypto/aes-glue.c linux-3.14.35/arch/arm64/crypto/aes-glue.c
- --- linux-3.14.35.orig/arch/arm64/crypto/aes-glue.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/crypto/aes-glue.c 2015-03-08 14:27:37.445684502 -0500
- @@ -0,0 +1,446 @@
- +/*
- + * linux/arch/arm64/crypto/aes-glue.c - wrapper code for ARMv8 AES
- + *
- + * Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <asm/neon.h>
- +#include <asm/hwcap.h>
- +#include <crypto/aes.h>
- +#include <crypto/ablk_helper.h>
- +#include <crypto/algapi.h>
- +#include <linux/module.h>
- +#include <linux/cpufeature.h>
- +
- +#ifdef USE_V8_CRYPTO_EXTENSIONS
- +#define MODE "ce"
- +#define PRIO 300
- +#define aes_ecb_encrypt ce_aes_ecb_encrypt
- +#define aes_ecb_decrypt ce_aes_ecb_decrypt
- +#define aes_cbc_encrypt ce_aes_cbc_encrypt
- +#define aes_cbc_decrypt ce_aes_cbc_decrypt
- +#define aes_ctr_encrypt ce_aes_ctr_encrypt
- +#define aes_xts_encrypt ce_aes_xts_encrypt
- +#define aes_xts_decrypt ce_aes_xts_decrypt
- +MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS using ARMv8 Crypto Extensions");
- +#else
- +#define MODE "neon"
- +#define PRIO 200
- +#define aes_ecb_encrypt neon_aes_ecb_encrypt
- +#define aes_ecb_decrypt neon_aes_ecb_decrypt
- +#define aes_cbc_encrypt neon_aes_cbc_encrypt
- +#define aes_cbc_decrypt neon_aes_cbc_decrypt
- +#define aes_ctr_encrypt neon_aes_ctr_encrypt
- +#define aes_xts_encrypt neon_aes_xts_encrypt
- +#define aes_xts_decrypt neon_aes_xts_decrypt
- +MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS using ARMv8 NEON");
- +MODULE_ALIAS("ecb(aes)");
- +MODULE_ALIAS("cbc(aes)");
- +MODULE_ALIAS("ctr(aes)");
- +MODULE_ALIAS("xts(aes)");
- +#endif
- +
- +MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
- +MODULE_LICENSE("GPL v2");
- +
- +/* defined in aes-modes.S */
- +asmlinkage void aes_ecb_encrypt(u8 out[], u8 const in[], u8 const rk[],
- + int rounds, int blocks, int first);
- +asmlinkage void aes_ecb_decrypt(u8 out[], u8 const in[], u8 const rk[],
- + int rounds, int blocks, int first);
- +
- +asmlinkage void aes_cbc_encrypt(u8 out[], u8 const in[], u8 const rk[],
- + int rounds, int blocks, u8 iv[], int first);
- +asmlinkage void aes_cbc_decrypt(u8 out[], u8 const in[], u8 const rk[],
- + int rounds, int blocks, u8 iv[], int first);
- +
- +asmlinkage void aes_ctr_encrypt(u8 out[], u8 const in[], u8 const rk[],
- + int rounds, int blocks, u8 ctr[], int first);
- +
- +asmlinkage void aes_xts_encrypt(u8 out[], u8 const in[], u8 const rk1[],
- + int rounds, int blocks, u8 const rk2[], u8 iv[],
- + int first);
- +asmlinkage void aes_xts_decrypt(u8 out[], u8 const in[], u8 const rk1[],
- + int rounds, int blocks, u8 const rk2[], u8 iv[],
- + int first);
- +
- +struct crypto_aes_xts_ctx {
- + struct crypto_aes_ctx key1;
- + struct crypto_aes_ctx __aligned(8) key2;
- +};
- +
- +static int xts_set_key(struct crypto_tfm *tfm, const u8 *in_key,
- + unsigned int key_len)
- +{
- + struct crypto_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm);
- + int ret;
- +
- + ret = crypto_aes_expand_key(&ctx->key1, in_key, key_len / 2);
- + if (!ret)
- + ret = crypto_aes_expand_key(&ctx->key2, &in_key[key_len / 2],
- + key_len / 2);
- + if (!ret)
- + return 0;
- +
- + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
- + return -EINVAL;
- +}
- +
- +static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
- + struct scatterlist *src, unsigned int nbytes)
- +{
- + struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
- + int err, first, rounds = 6 + ctx->key_length / 4;
- + struct blkcipher_walk walk;
- + unsigned int blocks;
- +
- + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
- + blkcipher_walk_init(&walk, dst, src, nbytes);
- + err = blkcipher_walk_virt(desc, &walk);
- +
- + kernel_neon_begin();
- + for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) {
- + aes_ecb_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
- + (u8 *)ctx->key_enc, rounds, blocks, first);
- + err = blkcipher_walk_done(desc, &walk, 0);
- + }
- + kernel_neon_end();
- + return err;
- +}
- +
- +static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
- + struct scatterlist *src, unsigned int nbytes)
- +{
- + struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
- + int err, first, rounds = 6 + ctx->key_length / 4;
- + struct blkcipher_walk walk;
- + unsigned int blocks;
- +
- + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
- + blkcipher_walk_init(&walk, dst, src, nbytes);
- + err = blkcipher_walk_virt(desc, &walk);
- +
- + kernel_neon_begin();
- + for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) {
- + aes_ecb_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
- + (u8 *)ctx->key_dec, rounds, blocks, first);
- + err = blkcipher_walk_done(desc, &walk, 0);
- + }
- + kernel_neon_end();
- + return err;
- +}
- +
- +static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
- + struct scatterlist *src, unsigned int nbytes)
- +{
- + struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
- + int err, first, rounds = 6 + ctx->key_length / 4;
- + struct blkcipher_walk walk;
- + unsigned int blocks;
- +
- + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
- + blkcipher_walk_init(&walk, dst, src, nbytes);
- + err = blkcipher_walk_virt(desc, &walk);
- +
- + kernel_neon_begin();
- + for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) {
- + aes_cbc_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
- + (u8 *)ctx->key_enc, rounds, blocks, walk.iv,
- + first);
- + err = blkcipher_walk_done(desc, &walk, 0);
- + }
- + kernel_neon_end();
- + return err;
- +}
- +
- +static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
- + struct scatterlist *src, unsigned int nbytes)
- +{
- + struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
- + int err, first, rounds = 6 + ctx->key_length / 4;
- + struct blkcipher_walk walk;
- + unsigned int blocks;
- +
- + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
- + blkcipher_walk_init(&walk, dst, src, nbytes);
- + err = blkcipher_walk_virt(desc, &walk);
- +
- + kernel_neon_begin();
- + for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) {
- + aes_cbc_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
- + (u8 *)ctx->key_dec, rounds, blocks, walk.iv,
- + first);
- + err = blkcipher_walk_done(desc, &walk, 0);
- + }
- + kernel_neon_end();
- + return err;
- +}
- +
- +static int ctr_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
- + struct scatterlist *src, unsigned int nbytes)
- +{
- + struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
- + int err, first, rounds = 6 + ctx->key_length / 4;
- + struct blkcipher_walk walk;
- + int blocks;
- +
- + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
- + blkcipher_walk_init(&walk, dst, src, nbytes);
- + err = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE);
- +
- + first = 1;
- + kernel_neon_begin();
- + while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
- + aes_ctr_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
- + (u8 *)ctx->key_enc, rounds, blocks, walk.iv,
- + first);
- + first = 0;
- + nbytes -= blocks * AES_BLOCK_SIZE;
- + if (nbytes && nbytes == walk.nbytes % AES_BLOCK_SIZE)
- + break;
- + err = blkcipher_walk_done(desc, &walk,
- + walk.nbytes % AES_BLOCK_SIZE);
- + }
- + if (nbytes) {
- + u8 *tdst = walk.dst.virt.addr + blocks * AES_BLOCK_SIZE;
- + u8 *tsrc = walk.src.virt.addr + blocks * AES_BLOCK_SIZE;
- + u8 __aligned(8) tail[AES_BLOCK_SIZE];
- +
- + /*
- + * Minimum alignment is 8 bytes, so if nbytes is <= 8, we need
- + * to tell aes_ctr_encrypt() to only read half a block.
- + */
- + blocks = (nbytes <= 8) ? -1 : 1;
- +
- + aes_ctr_encrypt(tail, tsrc, (u8 *)ctx->key_enc, rounds,
- + blocks, walk.iv, first);
- + memcpy(tdst, tail, nbytes);
- + err = blkcipher_walk_done(desc, &walk, 0);
- + }
- + kernel_neon_end();
- +
- + return err;
- +}
- +
- +static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
- + struct scatterlist *src, unsigned int nbytes)
- +{
- + struct crypto_aes_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
- + int err, first, rounds = 6 + ctx->key1.key_length / 4;
- + struct blkcipher_walk walk;
- + unsigned int blocks;
- +
- + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
- + blkcipher_walk_init(&walk, dst, src, nbytes);
- + err = blkcipher_walk_virt(desc, &walk);
- +
- + kernel_neon_begin();
- + for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) {
- + aes_xts_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
- + (u8 *)ctx->key1.key_enc, rounds, blocks,
- + (u8 *)ctx->key2.key_enc, walk.iv, first);
- + err = blkcipher_walk_done(desc, &walk, 0);
- + }
- + kernel_neon_end();
- +
- + return err;
- +}
- +
- +static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
- + struct scatterlist *src, unsigned int nbytes)
- +{
- + struct crypto_aes_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
- + int err, first, rounds = 6 + ctx->key1.key_length / 4;
- + struct blkcipher_walk walk;
- + unsigned int blocks;
- +
- + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
- + blkcipher_walk_init(&walk, dst, src, nbytes);
- + err = blkcipher_walk_virt(desc, &walk);
- +
- + kernel_neon_begin();
- + for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) {
- + aes_xts_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
- + (u8 *)ctx->key1.key_dec, rounds, blocks,
- + (u8 *)ctx->key2.key_enc, walk.iv, first);
- + err = blkcipher_walk_done(desc, &walk, 0);
- + }
- + kernel_neon_end();
- +
- + return err;
- +}
- +
- +static struct crypto_alg aes_algs[] = { {
- + .cra_name = "__ecb-aes-" MODE,
- + .cra_driver_name = "__driver-ecb-aes-" MODE,
- + .cra_priority = 0,
- + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
- + .cra_blocksize = AES_BLOCK_SIZE,
- + .cra_ctxsize = sizeof(struct crypto_aes_ctx),
- + .cra_alignmask = 7,
- + .cra_type = &crypto_blkcipher_type,
- + .cra_module = THIS_MODULE,
- + .cra_blkcipher = {
- + .min_keysize = AES_MIN_KEY_SIZE,
- + .max_keysize = AES_MAX_KEY_SIZE,
- + .ivsize = AES_BLOCK_SIZE,
- + .setkey = crypto_aes_set_key,
- + .encrypt = ecb_encrypt,
- + .decrypt = ecb_decrypt,
- + },
- +}, {
- + .cra_name = "__cbc-aes-" MODE,
- + .cra_driver_name = "__driver-cbc-aes-" MODE,
- + .cra_priority = 0,
- + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
- + .cra_blocksize = AES_BLOCK_SIZE,
- + .cra_ctxsize = sizeof(struct crypto_aes_ctx),
- + .cra_alignmask = 7,
- + .cra_type = &crypto_blkcipher_type,
- + .cra_module = THIS_MODULE,
- + .cra_blkcipher = {
- + .min_keysize = AES_MIN_KEY_SIZE,
- + .max_keysize = AES_MAX_KEY_SIZE,
- + .ivsize = AES_BLOCK_SIZE,
- + .setkey = crypto_aes_set_key,
- + .encrypt = cbc_encrypt,
- + .decrypt = cbc_decrypt,
- + },
- +}, {
- + .cra_name = "__ctr-aes-" MODE,
- + .cra_driver_name = "__driver-ctr-aes-" MODE,
- + .cra_priority = 0,
- + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
- + .cra_blocksize = 1,
- + .cra_ctxsize = sizeof(struct crypto_aes_ctx),
- + .cra_alignmask = 7,
- + .cra_type = &crypto_blkcipher_type,
- + .cra_module = THIS_MODULE,
- + .cra_blkcipher = {
- + .min_keysize = AES_MIN_KEY_SIZE,
- + .max_keysize = AES_MAX_KEY_SIZE,
- + .ivsize = AES_BLOCK_SIZE,
- + .setkey = crypto_aes_set_key,
- + .encrypt = ctr_encrypt,
- + .decrypt = ctr_encrypt,
- + },
- +}, {
- + .cra_name = "__xts-aes-" MODE,
- + .cra_driver_name = "__driver-xts-aes-" MODE,
- + .cra_priority = 0,
- + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
- + .cra_blocksize = AES_BLOCK_SIZE,
- + .cra_ctxsize = sizeof(struct crypto_aes_xts_ctx),
- + .cra_alignmask = 7,
- + .cra_type = &crypto_blkcipher_type,
- + .cra_module = THIS_MODULE,
- + .cra_blkcipher = {
- + .min_keysize = 2 * AES_MIN_KEY_SIZE,
- + .max_keysize = 2 * AES_MAX_KEY_SIZE,
- + .ivsize = AES_BLOCK_SIZE,
- + .setkey = xts_set_key,
- + .encrypt = xts_encrypt,
- + .decrypt = xts_decrypt,
- + },
- +}, {
- + .cra_name = "ecb(aes)",
- + .cra_driver_name = "ecb-aes-" MODE,
- + .cra_priority = PRIO,
- + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
- + .cra_blocksize = AES_BLOCK_SIZE,
- + .cra_ctxsize = sizeof(struct async_helper_ctx),
- + .cra_alignmask = 7,
- + .cra_type = &crypto_ablkcipher_type,
- + .cra_module = THIS_MODULE,
- + .cra_init = ablk_init,
- + .cra_exit = ablk_exit,
- + .cra_ablkcipher = {
- + .min_keysize = AES_MIN_KEY_SIZE,
- + .max_keysize = AES_MAX_KEY_SIZE,
- + .ivsize = AES_BLOCK_SIZE,
- + .setkey = ablk_set_key,
- + .encrypt = ablk_encrypt,
- + .decrypt = ablk_decrypt,
- + }
- +}, {
- + .cra_name = "cbc(aes)",
- + .cra_driver_name = "cbc-aes-" MODE,
- + .cra_priority = PRIO,
- + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
- + .cra_blocksize = AES_BLOCK_SIZE,
- + .cra_ctxsize = sizeof(struct async_helper_ctx),
- + .cra_alignmask = 7,
- + .cra_type = &crypto_ablkcipher_type,
- + .cra_module = THIS_MODULE,
- + .cra_init = ablk_init,
- + .cra_exit = ablk_exit,
- + .cra_ablkcipher = {
- + .min_keysize = AES_MIN_KEY_SIZE,
- + .max_keysize = AES_MAX_KEY_SIZE,
- + .ivsize = AES_BLOCK_SIZE,
- + .setkey = ablk_set_key,
- + .encrypt = ablk_encrypt,
- + .decrypt = ablk_decrypt,
- + }
- +}, {
- + .cra_name = "ctr(aes)",
- + .cra_driver_name = "ctr-aes-" MODE,
- + .cra_priority = PRIO,
- + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
- + .cra_blocksize = 1,
- + .cra_ctxsize = sizeof(struct async_helper_ctx),
- + .cra_alignmask = 7,
- + .cra_type = &crypto_ablkcipher_type,
- + .cra_module = THIS_MODULE,
- + .cra_init = ablk_init,
- + .cra_exit = ablk_exit,
- + .cra_ablkcipher = {
- + .min_keysize = AES_MIN_KEY_SIZE,
- + .max_keysize = AES_MAX_KEY_SIZE,
- + .ivsize = AES_BLOCK_SIZE,
- + .setkey = ablk_set_key,
- + .encrypt = ablk_encrypt,
- + .decrypt = ablk_decrypt,
- + }
- +}, {
- + .cra_name = "xts(aes)",
- + .cra_driver_name = "xts-aes-" MODE,
- + .cra_priority = PRIO,
- + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
- + .cra_blocksize = AES_BLOCK_SIZE,
- + .cra_ctxsize = sizeof(struct async_helper_ctx),
- + .cra_alignmask = 7,
- + .cra_type = &crypto_ablkcipher_type,
- + .cra_module = THIS_MODULE,
- + .cra_init = ablk_init,
- + .cra_exit = ablk_exit,
- + .cra_ablkcipher = {
- + .min_keysize = 2 * AES_MIN_KEY_SIZE,
- + .max_keysize = 2 * AES_MAX_KEY_SIZE,
- + .ivsize = AES_BLOCK_SIZE,
- + .setkey = ablk_set_key,
- + .encrypt = ablk_encrypt,
- + .decrypt = ablk_decrypt,
- + }
- +} };
- +
- +static int __init aes_init(void)
- +{
- + return crypto_register_algs(aes_algs, ARRAY_SIZE(aes_algs));
- +}
- +
- +static void __exit aes_exit(void)
- +{
- + crypto_unregister_algs(aes_algs, ARRAY_SIZE(aes_algs));
- +}
- +
- +#ifdef USE_V8_CRYPTO_EXTENSIONS
- +module_cpu_feature_match(AES, aes_init);
- +#else
- +module_init(aes_init);
- +#endif
- +module_exit(aes_exit);
- diff -Nur linux-3.14.35.orig/arch/arm64/crypto/aes-modes.S linux-3.14.35/arch/arm64/crypto/aes-modes.S
- --- linux-3.14.35.orig/arch/arm64/crypto/aes-modes.S 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/crypto/aes-modes.S 2015-03-08 14:27:37.445684502 -0500
- @@ -0,0 +1,532 @@
- +/*
- + * linux/arch/arm64/crypto/aes-modes.S - chaining mode wrappers for AES
- + *
- + * Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +/* included by aes-ce.S and aes-neon.S */
- +
- + .text
- + .align 4
- +
- +/*
- + * There are several ways to instantiate this code:
- + * - no interleave, all inline
- + * - 2-way interleave, 2x calls out of line (-DINTERLEAVE=2)
- + * - 2-way interleave, all inline (-DINTERLEAVE=2 -DINTERLEAVE_INLINE)
- + * - 4-way interleave, 4x calls out of line (-DINTERLEAVE=4)
- + * - 4-way interleave, all inline (-DINTERLEAVE=4 -DINTERLEAVE_INLINE)
- + *
- + * Macros imported by this code:
- + * - enc_prepare - setup NEON registers for encryption
- + * - dec_prepare - setup NEON registers for decryption
- + * - enc_switch_key - change to new key after having prepared for encryption
- + * - encrypt_block - encrypt a single block
- + * - decrypt block - decrypt a single block
- + * - encrypt_block2x - encrypt 2 blocks in parallel (if INTERLEAVE == 2)
- + * - decrypt_block2x - decrypt 2 blocks in parallel (if INTERLEAVE == 2)
- + * - encrypt_block4x - encrypt 4 blocks in parallel (if INTERLEAVE == 4)
- + * - decrypt_block4x - decrypt 4 blocks in parallel (if INTERLEAVE == 4)
- + */
- +
- +#if defined(INTERLEAVE) && !defined(INTERLEAVE_INLINE)
- +#define FRAME_PUSH stp x29, x30, [sp,#-16]! ; mov x29, sp
- +#define FRAME_POP ldp x29, x30, [sp],#16
- +
- +#if INTERLEAVE == 2
- +
- +aes_encrypt_block2x:
- + encrypt_block2x v0, v1, w3, x2, x6, w7
- + ret
- +ENDPROC(aes_encrypt_block2x)
- +
- +aes_decrypt_block2x:
- + decrypt_block2x v0, v1, w3, x2, x6, w7
- + ret
- +ENDPROC(aes_decrypt_block2x)
- +
- +#elif INTERLEAVE == 4
- +
- +aes_encrypt_block4x:
- + encrypt_block4x v0, v1, v2, v3, w3, x2, x6, w7
- + ret
- +ENDPROC(aes_encrypt_block4x)
- +
- +aes_decrypt_block4x:
- + decrypt_block4x v0, v1, v2, v3, w3, x2, x6, w7
- + ret
- +ENDPROC(aes_decrypt_block4x)
- +
- +#else
- +#error INTERLEAVE should equal 2 or 4
- +#endif
- +
- + .macro do_encrypt_block2x
- + bl aes_encrypt_block2x
- + .endm
- +
- + .macro do_decrypt_block2x
- + bl aes_decrypt_block2x
- + .endm
- +
- + .macro do_encrypt_block4x
- + bl aes_encrypt_block4x
- + .endm
- +
- + .macro do_decrypt_block4x
- + bl aes_decrypt_block4x
- + .endm
- +
- +#else
- +#define FRAME_PUSH
- +#define FRAME_POP
- +
- + .macro do_encrypt_block2x
- + encrypt_block2x v0, v1, w3, x2, x6, w7
- + .endm
- +
- + .macro do_decrypt_block2x
- + decrypt_block2x v0, v1, w3, x2, x6, w7
- + .endm
- +
- + .macro do_encrypt_block4x
- + encrypt_block4x v0, v1, v2, v3, w3, x2, x6, w7
- + .endm
- +
- + .macro do_decrypt_block4x
- + decrypt_block4x v0, v1, v2, v3, w3, x2, x6, w7
- + .endm
- +
- +#endif
- +
- + /*
- + * aes_ecb_encrypt(u8 out[], u8 const in[], u8 const rk[], int rounds,
- + * int blocks, int first)
- + * aes_ecb_decrypt(u8 out[], u8 const in[], u8 const rk[], int rounds,
- + * int blocks, int first)
- + */
- +
- +AES_ENTRY(aes_ecb_encrypt)
- + FRAME_PUSH
- + cbz w5, .LecbencloopNx
- +
- + enc_prepare w3, x2, x5
- +
- +.LecbencloopNx:
- +#if INTERLEAVE >= 2
- + subs w4, w4, #INTERLEAVE
- + bmi .Lecbenc1x
- +#if INTERLEAVE == 2
- + ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 pt blocks */
- + do_encrypt_block2x
- + st1 {v0.16b-v1.16b}, [x0], #32
- +#else
- + ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 pt blocks */
- + do_encrypt_block4x
- + st1 {v0.16b-v3.16b}, [x0], #64
- +#endif
- + b .LecbencloopNx
- +.Lecbenc1x:
- + adds w4, w4, #INTERLEAVE
- + beq .Lecbencout
- +#endif
- +.Lecbencloop:
- + ld1 {v0.16b}, [x1], #16 /* get next pt block */
- + encrypt_block v0, w3, x2, x5, w6
- + st1 {v0.16b}, [x0], #16
- + subs w4, w4, #1
- + bne .Lecbencloop
- +.Lecbencout:
- + FRAME_POP
- + ret
- +AES_ENDPROC(aes_ecb_encrypt)
- +
- +
- +AES_ENTRY(aes_ecb_decrypt)
- + FRAME_PUSH
- + cbz w5, .LecbdecloopNx
- +
- + dec_prepare w3, x2, x5
- +
- +.LecbdecloopNx:
- +#if INTERLEAVE >= 2
- + subs w4, w4, #INTERLEAVE
- + bmi .Lecbdec1x
- +#if INTERLEAVE == 2
- + ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 ct blocks */
- + do_decrypt_block2x
- + st1 {v0.16b-v1.16b}, [x0], #32
- +#else
- + ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 ct blocks */
- + do_decrypt_block4x
- + st1 {v0.16b-v3.16b}, [x0], #64
- +#endif
- + b .LecbdecloopNx
- +.Lecbdec1x:
- + adds w4, w4, #INTERLEAVE
- + beq .Lecbdecout
- +#endif
- +.Lecbdecloop:
- + ld1 {v0.16b}, [x1], #16 /* get next ct block */
- + decrypt_block v0, w3, x2, x5, w6
- + st1 {v0.16b}, [x0], #16
- + subs w4, w4, #1
- + bne .Lecbdecloop
- +.Lecbdecout:
- + FRAME_POP
- + ret
- +AES_ENDPROC(aes_ecb_decrypt)
- +
- +
- + /*
- + * aes_cbc_encrypt(u8 out[], u8 const in[], u8 const rk[], int rounds,
- + * int blocks, u8 iv[], int first)
- + * aes_cbc_decrypt(u8 out[], u8 const in[], u8 const rk[], int rounds,
- + * int blocks, u8 iv[], int first)
- + */
- +
- +AES_ENTRY(aes_cbc_encrypt)
- + cbz w6, .Lcbcencloop
- +
- + ld1 {v0.16b}, [x5] /* get iv */
- + enc_prepare w3, x2, x5
- +
- +.Lcbcencloop:
- + ld1 {v1.16b}, [x1], #16 /* get next pt block */
- + eor v0.16b, v0.16b, v1.16b /* ..and xor with iv */
- + encrypt_block v0, w3, x2, x5, w6
- + st1 {v0.16b}, [x0], #16
- + subs w4, w4, #1
- + bne .Lcbcencloop
- + ret
- +AES_ENDPROC(aes_cbc_encrypt)
- +
- +
- +AES_ENTRY(aes_cbc_decrypt)
- + FRAME_PUSH
- + cbz w6, .LcbcdecloopNx
- +
- + ld1 {v7.16b}, [x5] /* get iv */
- + dec_prepare w3, x2, x5
- +
- +.LcbcdecloopNx:
- +#if INTERLEAVE >= 2
- + subs w4, w4, #INTERLEAVE
- + bmi .Lcbcdec1x
- +#if INTERLEAVE == 2
- + ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 ct blocks */
- + mov v2.16b, v0.16b
- + mov v3.16b, v1.16b
- + do_decrypt_block2x
- + eor v0.16b, v0.16b, v7.16b
- + eor v1.16b, v1.16b, v2.16b
- + mov v7.16b, v3.16b
- + st1 {v0.16b-v1.16b}, [x0], #32
- +#else
- + ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 ct blocks */
- + mov v4.16b, v0.16b
- + mov v5.16b, v1.16b
- + mov v6.16b, v2.16b
- + do_decrypt_block4x
- + sub x1, x1, #16
- + eor v0.16b, v0.16b, v7.16b
- + eor v1.16b, v1.16b, v4.16b
- + ld1 {v7.16b}, [x1], #16 /* reload 1 ct block */
- + eor v2.16b, v2.16b, v5.16b
- + eor v3.16b, v3.16b, v6.16b
- + st1 {v0.16b-v3.16b}, [x0], #64
- +#endif
- + b .LcbcdecloopNx
- +.Lcbcdec1x:
- + adds w4, w4, #INTERLEAVE
- + beq .Lcbcdecout
- +#endif
- +.Lcbcdecloop:
- + ld1 {v1.16b}, [x1], #16 /* get next ct block */
- + mov v0.16b, v1.16b /* ...and copy to v0 */
- + decrypt_block v0, w3, x2, x5, w6
- + eor v0.16b, v0.16b, v7.16b /* xor with iv => pt */
- + mov v7.16b, v1.16b /* ct is next iv */
- + st1 {v0.16b}, [x0], #16
- + subs w4, w4, #1
- + bne .Lcbcdecloop
- +.Lcbcdecout:
- + FRAME_POP
- + ret
- +AES_ENDPROC(aes_cbc_decrypt)
- +
- +
- + /*
- + * aes_ctr_encrypt(u8 out[], u8 const in[], u8 const rk[], int rounds,
- + * int blocks, u8 ctr[], int first)
- + */
- +
- +AES_ENTRY(aes_ctr_encrypt)
- + FRAME_PUSH
- + cbnz w6, .Lctrfirst /* 1st time around? */
- + umov x5, v4.d[1] /* keep swabbed ctr in reg */
- + rev x5, x5
- +#if INTERLEAVE >= 2
- + cmn w5, w4 /* 32 bit overflow? */
- + bcs .Lctrinc
- + add x5, x5, #1 /* increment BE ctr */
- + b .LctrincNx
- +#else
- + b .Lctrinc
- +#endif
- +.Lctrfirst:
- + enc_prepare w3, x2, x6
- + ld1 {v4.16b}, [x5]
- + umov x5, v4.d[1] /* keep swabbed ctr in reg */
- + rev x5, x5
- +#if INTERLEAVE >= 2
- + cmn w5, w4 /* 32 bit overflow? */
- + bcs .Lctrloop
- +.LctrloopNx:
- + subs w4, w4, #INTERLEAVE
- + bmi .Lctr1x
- +#if INTERLEAVE == 2
- + mov v0.8b, v4.8b
- + mov v1.8b, v4.8b
- + rev x7, x5
- + add x5, x5, #1
- + ins v0.d[1], x7
- + rev x7, x5
- + add x5, x5, #1
- + ins v1.d[1], x7
- + ld1 {v2.16b-v3.16b}, [x1], #32 /* get 2 input blocks */
- + do_encrypt_block2x
- + eor v0.16b, v0.16b, v2.16b
- + eor v1.16b, v1.16b, v3.16b
- + st1 {v0.16b-v1.16b}, [x0], #32
- +#else
- + ldr q8, =0x30000000200000001 /* addends 1,2,3[,0] */
- + dup v7.4s, w5
- + mov v0.16b, v4.16b
- + add v7.4s, v7.4s, v8.4s
- + mov v1.16b, v4.16b
- + rev32 v8.16b, v7.16b
- + mov v2.16b, v4.16b
- + mov v3.16b, v4.16b
- + mov v1.s[3], v8.s[0]
- + mov v2.s[3], v8.s[1]
- + mov v3.s[3], v8.s[2]
- + ld1 {v5.16b-v7.16b}, [x1], #48 /* get 3 input blocks */
- + do_encrypt_block4x
- + eor v0.16b, v5.16b, v0.16b
- + ld1 {v5.16b}, [x1], #16 /* get 1 input block */
- + eor v1.16b, v6.16b, v1.16b
- + eor v2.16b, v7.16b, v2.16b
- + eor v3.16b, v5.16b, v3.16b
- + st1 {v0.16b-v3.16b}, [x0], #64
- + add x5, x5, #INTERLEAVE
- +#endif
- + cbz w4, .LctroutNx
- +.LctrincNx:
- + rev x7, x5
- + ins v4.d[1], x7
- + b .LctrloopNx
- +.LctroutNx:
- + sub x5, x5, #1
- + rev x7, x5
- + ins v4.d[1], x7
- + b .Lctrout
- +.Lctr1x:
- + adds w4, w4, #INTERLEAVE
- + beq .Lctrout
- +#endif
- +.Lctrloop:
- + mov v0.16b, v4.16b
- + encrypt_block v0, w3, x2, x6, w7
- + subs w4, w4, #1
- + bmi .Lctrhalfblock /* blocks < 0 means 1/2 block */
- + ld1 {v3.16b}, [x1], #16
- + eor v3.16b, v0.16b, v3.16b
- + st1 {v3.16b}, [x0], #16
- + beq .Lctrout
- +.Lctrinc:
- + adds x5, x5, #1 /* increment BE ctr */
- + rev x7, x5
- + ins v4.d[1], x7
- + bcc .Lctrloop /* no overflow? */
- + umov x7, v4.d[0] /* load upper word of ctr */
- + rev x7, x7 /* ... to handle the carry */
- + add x7, x7, #1
- + rev x7, x7
- + ins v4.d[0], x7
- + b .Lctrloop
- +.Lctrhalfblock:
- + ld1 {v3.8b}, [x1]
- + eor v3.8b, v0.8b, v3.8b
- + st1 {v3.8b}, [x0]
- +.Lctrout:
- + FRAME_POP
- + ret
- +AES_ENDPROC(aes_ctr_encrypt)
- + .ltorg
- +
- +
- + /*
- + * aes_xts_decrypt(u8 out[], u8 const in[], u8 const rk1[], int rounds,
- + * int blocks, u8 const rk2[], u8 iv[], int first)
- + * aes_xts_decrypt(u8 out[], u8 const in[], u8 const rk1[], int rounds,
- + * int blocks, u8 const rk2[], u8 iv[], int first)
- + */
- +
- + .macro next_tweak, out, in, const, tmp
- + sshr \tmp\().2d, \in\().2d, #63
- + and \tmp\().16b, \tmp\().16b, \const\().16b
- + add \out\().2d, \in\().2d, \in\().2d
- + ext \tmp\().16b, \tmp\().16b, \tmp\().16b, #8
- + eor \out\().16b, \out\().16b, \tmp\().16b
- + .endm
- +
- +.Lxts_mul_x:
- + .word 1, 0, 0x87, 0
- +
- +AES_ENTRY(aes_xts_encrypt)
- + FRAME_PUSH
- + cbz w7, .LxtsencloopNx
- +
- + ld1 {v4.16b}, [x6]
- + enc_prepare w3, x5, x6
- + encrypt_block v4, w3, x5, x6, w7 /* first tweak */
- + enc_switch_key w3, x2, x6
- + ldr q7, .Lxts_mul_x
- + b .LxtsencNx
- +
- +.LxtsencloopNx:
- + ldr q7, .Lxts_mul_x
- + next_tweak v4, v4, v7, v8
- +.LxtsencNx:
- +#if INTERLEAVE >= 2
- + subs w4, w4, #INTERLEAVE
- + bmi .Lxtsenc1x
- +#if INTERLEAVE == 2
- + ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 pt blocks */
- + next_tweak v5, v4, v7, v8
- + eor v0.16b, v0.16b, v4.16b
- + eor v1.16b, v1.16b, v5.16b
- + do_encrypt_block2x
- + eor v0.16b, v0.16b, v4.16b
- + eor v1.16b, v1.16b, v5.16b
- + st1 {v0.16b-v1.16b}, [x0], #32
- + cbz w4, .LxtsencoutNx
- + next_tweak v4, v5, v7, v8
- + b .LxtsencNx
- +.LxtsencoutNx:
- + mov v4.16b, v5.16b
- + b .Lxtsencout
- +#else
- + ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 pt blocks */
- + next_tweak v5, v4, v7, v8
- + eor v0.16b, v0.16b, v4.16b
- + next_tweak v6, v5, v7, v8
- + eor v1.16b, v1.16b, v5.16b
- + eor v2.16b, v2.16b, v6.16b
- + next_tweak v7, v6, v7, v8
- + eor v3.16b, v3.16b, v7.16b
- + do_encrypt_block4x
- + eor v3.16b, v3.16b, v7.16b
- + eor v0.16b, v0.16b, v4.16b
- + eor v1.16b, v1.16b, v5.16b
- + eor v2.16b, v2.16b, v6.16b
- + st1 {v0.16b-v3.16b}, [x0], #64
- + mov v4.16b, v7.16b
- + cbz w4, .Lxtsencout
- + b .LxtsencloopNx
- +#endif
- +.Lxtsenc1x:
- + adds w4, w4, #INTERLEAVE
- + beq .Lxtsencout
- +#endif
- +.Lxtsencloop:
- + ld1 {v1.16b}, [x1], #16
- + eor v0.16b, v1.16b, v4.16b
- + encrypt_block v0, w3, x2, x6, w7
- + eor v0.16b, v0.16b, v4.16b
- + st1 {v0.16b}, [x0], #16
- + subs w4, w4, #1
- + beq .Lxtsencout
- + next_tweak v4, v4, v7, v8
- + b .Lxtsencloop
- +.Lxtsencout:
- + FRAME_POP
- + ret
- +AES_ENDPROC(aes_xts_encrypt)
- +
- +
- +AES_ENTRY(aes_xts_decrypt)
- + FRAME_PUSH
- + cbz w7, .LxtsdecloopNx
- +
- + ld1 {v4.16b}, [x6]
- + enc_prepare w3, x5, x6
- + encrypt_block v4, w3, x5, x6, w7 /* first tweak */
- + dec_prepare w3, x2, x6
- + ldr q7, .Lxts_mul_x
- + b .LxtsdecNx
- +
- +.LxtsdecloopNx:
- + ldr q7, .Lxts_mul_x
- + next_tweak v4, v4, v7, v8
- +.LxtsdecNx:
- +#if INTERLEAVE >= 2
- + subs w4, w4, #INTERLEAVE
- + bmi .Lxtsdec1x
- +#if INTERLEAVE == 2
- + ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 ct blocks */
- + next_tweak v5, v4, v7, v8
- + eor v0.16b, v0.16b, v4.16b
- + eor v1.16b, v1.16b, v5.16b
- + do_decrypt_block2x
- + eor v0.16b, v0.16b, v4.16b
- + eor v1.16b, v1.16b, v5.16b
- + st1 {v0.16b-v1.16b}, [x0], #32
- + cbz w4, .LxtsdecoutNx
- + next_tweak v4, v5, v7, v8
- + b .LxtsdecNx
- +.LxtsdecoutNx:
- + mov v4.16b, v5.16b
- + b .Lxtsdecout
- +#else
- + ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 ct blocks */
- + next_tweak v5, v4, v7, v8
- + eor v0.16b, v0.16b, v4.16b
- + next_tweak v6, v5, v7, v8
- + eor v1.16b, v1.16b, v5.16b
- + eor v2.16b, v2.16b, v6.16b
- + next_tweak v7, v6, v7, v8
- + eor v3.16b, v3.16b, v7.16b
- + do_decrypt_block4x
- + eor v3.16b, v3.16b, v7.16b
- + eor v0.16b, v0.16b, v4.16b
- + eor v1.16b, v1.16b, v5.16b
- + eor v2.16b, v2.16b, v6.16b
- + st1 {v0.16b-v3.16b}, [x0], #64
- + mov v4.16b, v7.16b
- + cbz w4, .Lxtsdecout
- + b .LxtsdecloopNx
- +#endif
- +.Lxtsdec1x:
- + adds w4, w4, #INTERLEAVE
- + beq .Lxtsdecout
- +#endif
- +.Lxtsdecloop:
- + ld1 {v1.16b}, [x1], #16
- + eor v0.16b, v1.16b, v4.16b
- + decrypt_block v0, w3, x2, x6, w7
- + eor v0.16b, v0.16b, v4.16b
- + st1 {v0.16b}, [x0], #16
- + subs w4, w4, #1
- + beq .Lxtsdecout
- + next_tweak v4, v4, v7, v8
- + b .Lxtsdecloop
- +.Lxtsdecout:
- + FRAME_POP
- + ret
- +AES_ENDPROC(aes_xts_decrypt)
- diff -Nur linux-3.14.35.orig/arch/arm64/crypto/aes-neon.S linux-3.14.35/arch/arm64/crypto/aes-neon.S
- --- linux-3.14.35.orig/arch/arm64/crypto/aes-neon.S 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/crypto/aes-neon.S 2015-03-08 14:27:37.445684502 -0500
- @@ -0,0 +1,382 @@
- +/*
- + * linux/arch/arm64/crypto/aes-neon.S - AES cipher for ARMv8 NEON
- + *
- + * Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <linux/linkage.h>
- +
- +#define AES_ENTRY(func) ENTRY(neon_ ## func)
- +#define AES_ENDPROC(func) ENDPROC(neon_ ## func)
- +
- + /* multiply by polynomial 'x' in GF(2^8) */
- + .macro mul_by_x, out, in, temp, const
- + sshr \temp, \in, #7
- + add \out, \in, \in
- + and \temp, \temp, \const
- + eor \out, \out, \temp
- + .endm
- +
- + /* preload the entire Sbox */
- + .macro prepare, sbox, shiftrows, temp
- + adr \temp, \sbox
- + movi v12.16b, #0x40
- + ldr q13, \shiftrows
- + movi v14.16b, #0x1b
- + ld1 {v16.16b-v19.16b}, [\temp], #64
- + ld1 {v20.16b-v23.16b}, [\temp], #64
- + ld1 {v24.16b-v27.16b}, [\temp], #64
- + ld1 {v28.16b-v31.16b}, [\temp]
- + .endm
- +
- + /* do preload for encryption */
- + .macro enc_prepare, ignore0, ignore1, temp
- + prepare .LForward_Sbox, .LForward_ShiftRows, \temp
- + .endm
- +
- + .macro enc_switch_key, ignore0, ignore1, temp
- + /* do nothing */
- + .endm
- +
- + /* do preload for decryption */
- + .macro dec_prepare, ignore0, ignore1, temp
- + prepare .LReverse_Sbox, .LReverse_ShiftRows, \temp
- + .endm
- +
- + /* apply SubBytes transformation using the the preloaded Sbox */
- + .macro sub_bytes, in
- + sub v9.16b, \in\().16b, v12.16b
- + tbl \in\().16b, {v16.16b-v19.16b}, \in\().16b
- + sub v10.16b, v9.16b, v12.16b
- + tbx \in\().16b, {v20.16b-v23.16b}, v9.16b
- + sub v11.16b, v10.16b, v12.16b
- + tbx \in\().16b, {v24.16b-v27.16b}, v10.16b
- + tbx \in\().16b, {v28.16b-v31.16b}, v11.16b
- + .endm
- +
- + /* apply MixColumns transformation */
- + .macro mix_columns, in
- + mul_by_x v10.16b, \in\().16b, v9.16b, v14.16b
- + rev32 v8.8h, \in\().8h
- + eor \in\().16b, v10.16b, \in\().16b
- + shl v9.4s, v8.4s, #24
- + shl v11.4s, \in\().4s, #24
- + sri v9.4s, v8.4s, #8
- + sri v11.4s, \in\().4s, #8
- + eor v9.16b, v9.16b, v8.16b
- + eor v10.16b, v10.16b, v9.16b
- + eor \in\().16b, v10.16b, v11.16b
- + .endm
- +
- + /* Inverse MixColumns: pre-multiply by { 5, 0, 4, 0 } */
- + .macro inv_mix_columns, in
- + mul_by_x v11.16b, \in\().16b, v10.16b, v14.16b
- + mul_by_x v11.16b, v11.16b, v10.16b, v14.16b
- + eor \in\().16b, \in\().16b, v11.16b
- + rev32 v11.8h, v11.8h
- + eor \in\().16b, \in\().16b, v11.16b
- + mix_columns \in
- + .endm
- +
- + .macro do_block, enc, in, rounds, rk, rkp, i
- + ld1 {v15.16b}, [\rk]
- + add \rkp, \rk, #16
- + mov \i, \rounds
- +1111: eor \in\().16b, \in\().16b, v15.16b /* ^round key */
- + tbl \in\().16b, {\in\().16b}, v13.16b /* ShiftRows */
- + sub_bytes \in
- + ld1 {v15.16b}, [\rkp], #16
- + subs \i, \i, #1
- + beq 2222f
- + .if \enc == 1
- + mix_columns \in
- + .else
- + inv_mix_columns \in
- + .endif
- + b 1111b
- +2222: eor \in\().16b, \in\().16b, v15.16b /* ^round key */
- + .endm
- +
- + .macro encrypt_block, in, rounds, rk, rkp, i
- + do_block 1, \in, \rounds, \rk, \rkp, \i
- + .endm
- +
- + .macro decrypt_block, in, rounds, rk, rkp, i
- + do_block 0, \in, \rounds, \rk, \rkp, \i
- + .endm
- +
- + /*
- + * Interleaved versions: functionally equivalent to the
- + * ones above, but applied to 2 or 4 AES states in parallel.
- + */
- +
- + .macro sub_bytes_2x, in0, in1
- + sub v8.16b, \in0\().16b, v12.16b
- + sub v9.16b, \in1\().16b, v12.16b
- + tbl \in0\().16b, {v16.16b-v19.16b}, \in0\().16b
- + tbl \in1\().16b, {v16.16b-v19.16b}, \in1\().16b
- + sub v10.16b, v8.16b, v12.16b
- + sub v11.16b, v9.16b, v12.16b
- + tbx \in0\().16b, {v20.16b-v23.16b}, v8.16b
- + tbx \in1\().16b, {v20.16b-v23.16b}, v9.16b
- + sub v8.16b, v10.16b, v12.16b
- + sub v9.16b, v11.16b, v12.16b
- + tbx \in0\().16b, {v24.16b-v27.16b}, v10.16b
- + tbx \in1\().16b, {v24.16b-v27.16b}, v11.16b
- + tbx \in0\().16b, {v28.16b-v31.16b}, v8.16b
- + tbx \in1\().16b, {v28.16b-v31.16b}, v9.16b
- + .endm
- +
- + .macro sub_bytes_4x, in0, in1, in2, in3
- + sub v8.16b, \in0\().16b, v12.16b
- + tbl \in0\().16b, {v16.16b-v19.16b}, \in0\().16b
- + sub v9.16b, \in1\().16b, v12.16b
- + tbl \in1\().16b, {v16.16b-v19.16b}, \in1\().16b
- + sub v10.16b, \in2\().16b, v12.16b
- + tbl \in2\().16b, {v16.16b-v19.16b}, \in2\().16b
- + sub v11.16b, \in3\().16b, v12.16b
- + tbl \in3\().16b, {v16.16b-v19.16b}, \in3\().16b
- + tbx \in0\().16b, {v20.16b-v23.16b}, v8.16b
- + tbx \in1\().16b, {v20.16b-v23.16b}, v9.16b
- + sub v8.16b, v8.16b, v12.16b
- + tbx \in2\().16b, {v20.16b-v23.16b}, v10.16b
- + sub v9.16b, v9.16b, v12.16b
- + tbx \in3\().16b, {v20.16b-v23.16b}, v11.16b
- + sub v10.16b, v10.16b, v12.16b
- + tbx \in0\().16b, {v24.16b-v27.16b}, v8.16b
- + sub v11.16b, v11.16b, v12.16b
- + tbx \in1\().16b, {v24.16b-v27.16b}, v9.16b
- + sub v8.16b, v8.16b, v12.16b
- + tbx \in2\().16b, {v24.16b-v27.16b}, v10.16b
- + sub v9.16b, v9.16b, v12.16b
- + tbx \in3\().16b, {v24.16b-v27.16b}, v11.16b
- + sub v10.16b, v10.16b, v12.16b
- + tbx \in0\().16b, {v28.16b-v31.16b}, v8.16b
- + sub v11.16b, v11.16b, v12.16b
- + tbx \in1\().16b, {v28.16b-v31.16b}, v9.16b
- + tbx \in2\().16b, {v28.16b-v31.16b}, v10.16b
- + tbx \in3\().16b, {v28.16b-v31.16b}, v11.16b
- + .endm
- +
- + .macro mul_by_x_2x, out0, out1, in0, in1, tmp0, tmp1, const
- + sshr \tmp0\().16b, \in0\().16b, #7
- + add \out0\().16b, \in0\().16b, \in0\().16b
- + sshr \tmp1\().16b, \in1\().16b, #7
- + and \tmp0\().16b, \tmp0\().16b, \const\().16b
- + add \out1\().16b, \in1\().16b, \in1\().16b
- + and \tmp1\().16b, \tmp1\().16b, \const\().16b
- + eor \out0\().16b, \out0\().16b, \tmp0\().16b
- + eor \out1\().16b, \out1\().16b, \tmp1\().16b
- + .endm
- +
- + .macro mix_columns_2x, in0, in1
- + mul_by_x_2x v8, v9, \in0, \in1, v10, v11, v14
- + rev32 v10.8h, \in0\().8h
- + rev32 v11.8h, \in1\().8h
- + eor \in0\().16b, v8.16b, \in0\().16b
- + eor \in1\().16b, v9.16b, \in1\().16b
- + shl v12.4s, v10.4s, #24
- + shl v13.4s, v11.4s, #24
- + eor v8.16b, v8.16b, v10.16b
- + sri v12.4s, v10.4s, #8
- + shl v10.4s, \in0\().4s, #24
- + eor v9.16b, v9.16b, v11.16b
- + sri v13.4s, v11.4s, #8
- + shl v11.4s, \in1\().4s, #24
- + sri v10.4s, \in0\().4s, #8
- + eor \in0\().16b, v8.16b, v12.16b
- + sri v11.4s, \in1\().4s, #8
- + eor \in1\().16b, v9.16b, v13.16b
- + eor \in0\().16b, v10.16b, \in0\().16b
- + eor \in1\().16b, v11.16b, \in1\().16b
- + .endm
- +
- + .macro inv_mix_cols_2x, in0, in1
- + mul_by_x_2x v8, v9, \in0, \in1, v10, v11, v14
- + mul_by_x_2x v8, v9, v8, v9, v10, v11, v14
- + eor \in0\().16b, \in0\().16b, v8.16b
- + eor \in1\().16b, \in1\().16b, v9.16b
- + rev32 v8.8h, v8.8h
- + rev32 v9.8h, v9.8h
- + eor \in0\().16b, \in0\().16b, v8.16b
- + eor \in1\().16b, \in1\().16b, v9.16b
- + mix_columns_2x \in0, \in1
- + .endm
- +
- + .macro inv_mix_cols_4x, in0, in1, in2, in3
- + mul_by_x_2x v8, v9, \in0, \in1, v10, v11, v14
- + mul_by_x_2x v10, v11, \in2, \in3, v12, v13, v14
- + mul_by_x_2x v8, v9, v8, v9, v12, v13, v14
- + mul_by_x_2x v10, v11, v10, v11, v12, v13, v14
- + eor \in0\().16b, \in0\().16b, v8.16b
- + eor \in1\().16b, \in1\().16b, v9.16b
- + eor \in2\().16b, \in2\().16b, v10.16b
- + eor \in3\().16b, \in3\().16b, v11.16b
- + rev32 v8.8h, v8.8h
- + rev32 v9.8h, v9.8h
- + rev32 v10.8h, v10.8h
- + rev32 v11.8h, v11.8h
- + eor \in0\().16b, \in0\().16b, v8.16b
- + eor \in1\().16b, \in1\().16b, v9.16b
- + eor \in2\().16b, \in2\().16b, v10.16b
- + eor \in3\().16b, \in3\().16b, v11.16b
- + mix_columns_2x \in0, \in1
- + mix_columns_2x \in2, \in3
- + .endm
- +
- + .macro do_block_2x, enc, in0, in1 rounds, rk, rkp, i
- + ld1 {v15.16b}, [\rk]
- + add \rkp, \rk, #16
- + mov \i, \rounds
- +1111: eor \in0\().16b, \in0\().16b, v15.16b /* ^round key */
- + eor \in1\().16b, \in1\().16b, v15.16b /* ^round key */
- + sub_bytes_2x \in0, \in1
- + tbl \in0\().16b, {\in0\().16b}, v13.16b /* ShiftRows */
- + tbl \in1\().16b, {\in1\().16b}, v13.16b /* ShiftRows */
- + ld1 {v15.16b}, [\rkp], #16
- + subs \i, \i, #1
- + beq 2222f
- + .if \enc == 1
- + mix_columns_2x \in0, \in1
- + ldr q13, .LForward_ShiftRows
- + .else
- + inv_mix_cols_2x \in0, \in1
- + ldr q13, .LReverse_ShiftRows
- + .endif
- + movi v12.16b, #0x40
- + b 1111b
- +2222: eor \in0\().16b, \in0\().16b, v15.16b /* ^round key */
- + eor \in1\().16b, \in1\().16b, v15.16b /* ^round key */
- + .endm
- +
- + .macro do_block_4x, enc, in0, in1, in2, in3, rounds, rk, rkp, i
- + ld1 {v15.16b}, [\rk]
- + add \rkp, \rk, #16
- + mov \i, \rounds
- +1111: eor \in0\().16b, \in0\().16b, v15.16b /* ^round key */
- + eor \in1\().16b, \in1\().16b, v15.16b /* ^round key */
- + eor \in2\().16b, \in2\().16b, v15.16b /* ^round key */
- + eor \in3\().16b, \in3\().16b, v15.16b /* ^round key */
- + sub_bytes_4x \in0, \in1, \in2, \in3
- + tbl \in0\().16b, {\in0\().16b}, v13.16b /* ShiftRows */
- + tbl \in1\().16b, {\in1\().16b}, v13.16b /* ShiftRows */
- + tbl \in2\().16b, {\in2\().16b}, v13.16b /* ShiftRows */
- + tbl \in3\().16b, {\in3\().16b}, v13.16b /* ShiftRows */
- + ld1 {v15.16b}, [\rkp], #16
- + subs \i, \i, #1
- + beq 2222f
- + .if \enc == 1
- + mix_columns_2x \in0, \in1
- + mix_columns_2x \in2, \in3
- + ldr q13, .LForward_ShiftRows
- + .else
- + inv_mix_cols_4x \in0, \in1, \in2, \in3
- + ldr q13, .LReverse_ShiftRows
- + .endif
- + movi v12.16b, #0x40
- + b 1111b
- +2222: eor \in0\().16b, \in0\().16b, v15.16b /* ^round key */
- + eor \in1\().16b, \in1\().16b, v15.16b /* ^round key */
- + eor \in2\().16b, \in2\().16b, v15.16b /* ^round key */
- + eor \in3\().16b, \in3\().16b, v15.16b /* ^round key */
- + .endm
- +
- + .macro encrypt_block2x, in0, in1, rounds, rk, rkp, i
- + do_block_2x 1, \in0, \in1, \rounds, \rk, \rkp, \i
- + .endm
- +
- + .macro decrypt_block2x, in0, in1, rounds, rk, rkp, i
- + do_block_2x 0, \in0, \in1, \rounds, \rk, \rkp, \i
- + .endm
- +
- + .macro encrypt_block4x, in0, in1, in2, in3, rounds, rk, rkp, i
- + do_block_4x 1, \in0, \in1, \in2, \in3, \rounds, \rk, \rkp, \i
- + .endm
- +
- + .macro decrypt_block4x, in0, in1, in2, in3, rounds, rk, rkp, i
- + do_block_4x 0, \in0, \in1, \in2, \in3, \rounds, \rk, \rkp, \i
- + .endm
- +
- +#include "aes-modes.S"
- +
- + .text
- + .align 4
- +.LForward_ShiftRows:
- + .byte 0x0, 0x5, 0xa, 0xf, 0x4, 0x9, 0xe, 0x3
- + .byte 0x8, 0xd, 0x2, 0x7, 0xc, 0x1, 0x6, 0xb
- +
- +.LReverse_ShiftRows:
- + .byte 0x0, 0xd, 0xa, 0x7, 0x4, 0x1, 0xe, 0xb
- + .byte 0x8, 0x5, 0x2, 0xf, 0xc, 0x9, 0x6, 0x3
- +
- +.LForward_Sbox:
- + .byte 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5
- + .byte 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76
- + .byte 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0
- + .byte 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0
- + .byte 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc
- + .byte 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15
- + .byte 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a
- + .byte 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75
- + .byte 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0
- + .byte 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84
- + .byte 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b
- + .byte 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf
- + .byte 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85
- + .byte 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8
- + .byte 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5
- + .byte 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2
- + .byte 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17
- + .byte 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73
- + .byte 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88
- + .byte 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb
- + .byte 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c
- + .byte 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79
- + .byte 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9
- + .byte 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08
- + .byte 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6
- + .byte 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a
- + .byte 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e
- + .byte 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e
- + .byte 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94
- + .byte 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf
- + .byte 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68
- + .byte 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
- +
- +.LReverse_Sbox:
- + .byte 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38
- + .byte 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb
- + .byte 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87
- + .byte 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb
- + .byte 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d
- + .byte 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e
- + .byte 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2
- + .byte 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25
- + .byte 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16
- + .byte 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92
- + .byte 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda
- + .byte 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84
- + .byte 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a
- + .byte 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06
- + .byte 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02
- + .byte 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b
- + .byte 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea
- + .byte 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73
- + .byte 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85
- + .byte 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e
- + .byte 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89
- + .byte 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b
- + .byte 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20
- + .byte 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4
- + .byte 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31
- + .byte 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f
- + .byte 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d
- + .byte 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef
- + .byte 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0
- + .byte 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61
- + .byte 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26
- + .byte 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
- diff -Nur linux-3.14.35.orig/arch/arm64/crypto/ghash-ce-core.S linux-3.14.35/arch/arm64/crypto/ghash-ce-core.S
- --- linux-3.14.35.orig/arch/arm64/crypto/ghash-ce-core.S 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/crypto/ghash-ce-core.S 2015-03-08 14:27:37.445684502 -0500
- @@ -0,0 +1,79 @@
- +/*
- + * Accelerated GHASH implementation with ARMv8 PMULL instructions.
- + *
- + * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify it
- + * under the terms of the GNU General Public License version 2 as published
- + * by the Free Software Foundation.
- + */
- +
- +#include <linux/linkage.h>
- +#include <asm/assembler.h>
- +
- + SHASH .req v0
- + SHASH2 .req v1
- + T1 .req v2
- + T2 .req v3
- + MASK .req v4
- + XL .req v5
- + XM .req v6
- + XH .req v7
- + IN1 .req v7
- +
- + .text
- + .arch armv8-a+crypto
- +
- + /*
- + * void pmull_ghash_update(int blocks, u64 dg[], const char *src,
- + * struct ghash_key const *k, const char *head)
- + */
- +ENTRY(pmull_ghash_update)
- + ld1 {SHASH.16b}, [x3]
- + ld1 {XL.16b}, [x1]
- + movi MASK.16b, #0xe1
- + ext SHASH2.16b, SHASH.16b, SHASH.16b, #8
- + shl MASK.2d, MASK.2d, #57
- + eor SHASH2.16b, SHASH2.16b, SHASH.16b
- +
- + /* do the head block first, if supplied */
- + cbz x4, 0f
- + ld1 {T1.2d}, [x4]
- + b 1f
- +
- +0: ld1 {T1.2d}, [x2], #16
- + sub w0, w0, #1
- +
- +1: /* multiply XL by SHASH in GF(2^128) */
- +CPU_LE( rev64 T1.16b, T1.16b )
- +
- + ext T2.16b, XL.16b, XL.16b, #8
- + ext IN1.16b, T1.16b, T1.16b, #8
- + eor T1.16b, T1.16b, T2.16b
- + eor XL.16b, XL.16b, IN1.16b
- +
- + pmull2 XH.1q, SHASH.2d, XL.2d // a1 * b1
- + eor T1.16b, T1.16b, XL.16b
- + pmull XL.1q, SHASH.1d, XL.1d // a0 * b0
- + pmull XM.1q, SHASH2.1d, T1.1d // (a1 + a0)(b1 + b0)
- +
- + ext T1.16b, XL.16b, XH.16b, #8
- + eor T2.16b, XL.16b, XH.16b
- + eor XM.16b, XM.16b, T1.16b
- + eor XM.16b, XM.16b, T2.16b
- + pmull T2.1q, XL.1d, MASK.1d
- +
- + mov XH.d[0], XM.d[1]
- + mov XM.d[1], XL.d[0]
- +
- + eor XL.16b, XM.16b, T2.16b
- + ext T2.16b, XL.16b, XL.16b, #8
- + pmull XL.1q, XL.1d, MASK.1d
- + eor T2.16b, T2.16b, XH.16b
- + eor XL.16b, XL.16b, T2.16b
- +
- + cbnz w0, 0b
- +
- + st1 {XL.16b}, [x1]
- + ret
- +ENDPROC(pmull_ghash_update)
- diff -Nur linux-3.14.35.orig/arch/arm64/crypto/ghash-ce-glue.c linux-3.14.35/arch/arm64/crypto/ghash-ce-glue.c
- --- linux-3.14.35.orig/arch/arm64/crypto/ghash-ce-glue.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/crypto/ghash-ce-glue.c 2015-03-08 14:27:37.445684502 -0500
- @@ -0,0 +1,156 @@
- +/*
- + * Accelerated GHASH implementation with ARMv8 PMULL instructions.
- + *
- + * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify it
- + * under the terms of the GNU General Public License version 2 as published
- + * by the Free Software Foundation.
- + */
- +
- +#include <asm/neon.h>
- +#include <asm/unaligned.h>
- +#include <crypto/internal/hash.h>
- +#include <linux/cpufeature.h>
- +#include <linux/crypto.h>
- +#include <linux/module.h>
- +
- +MODULE_DESCRIPTION("GHASH secure hash using ARMv8 Crypto Extensions");
- +MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
- +MODULE_LICENSE("GPL v2");
- +
- +#define GHASH_BLOCK_SIZE 16
- +#define GHASH_DIGEST_SIZE 16
- +
- +struct ghash_key {
- + u64 a;
- + u64 b;
- +};
- +
- +struct ghash_desc_ctx {
- + u64 digest[GHASH_DIGEST_SIZE/sizeof(u64)];
- + u8 buf[GHASH_BLOCK_SIZE];
- + u32 count;
- +};
- +
- +asmlinkage void pmull_ghash_update(int blocks, u64 dg[], const char *src,
- + struct ghash_key const *k, const char *head);
- +
- +static int ghash_init(struct shash_desc *desc)
- +{
- + struct ghash_desc_ctx *ctx = shash_desc_ctx(desc);
- +
- + *ctx = (struct ghash_desc_ctx){};
- + return 0;
- +}
- +
- +static int ghash_update(struct shash_desc *desc, const u8 *src,
- + unsigned int len)
- +{
- + struct ghash_desc_ctx *ctx = shash_desc_ctx(desc);
- + unsigned int partial = ctx->count % GHASH_BLOCK_SIZE;
- +
- + ctx->count += len;
- +
- + if ((partial + len) >= GHASH_BLOCK_SIZE) {
- + struct ghash_key *key = crypto_shash_ctx(desc->tfm);
- + int blocks;
- +
- + if (partial) {
- + int p = GHASH_BLOCK_SIZE - partial;
- +
- + memcpy(ctx->buf + partial, src, p);
- + src += p;
- + len -= p;
- + }
- +
- + blocks = len / GHASH_BLOCK_SIZE;
- + len %= GHASH_BLOCK_SIZE;
- +
- + kernel_neon_begin_partial(8);
- + pmull_ghash_update(blocks, ctx->digest, src, key,
- + partial ? ctx->buf : NULL);
- + kernel_neon_end();
- + src += blocks * GHASH_BLOCK_SIZE;
- + partial = 0;
- + }
- + if (len)
- + memcpy(ctx->buf + partial, src, len);
- + return 0;
- +}
- +
- +static int ghash_final(struct shash_desc *desc, u8 *dst)
- +{
- + struct ghash_desc_ctx *ctx = shash_desc_ctx(desc);
- + unsigned int partial = ctx->count % GHASH_BLOCK_SIZE;
- +
- + if (partial) {
- + struct ghash_key *key = crypto_shash_ctx(desc->tfm);
- +
- + memset(ctx->buf + partial, 0, GHASH_BLOCK_SIZE - partial);
- +
- + kernel_neon_begin_partial(8);
- + pmull_ghash_update(1, ctx->digest, ctx->buf, key, NULL);
- + kernel_neon_end();
- + }
- + put_unaligned_be64(ctx->digest[1], dst);
- + put_unaligned_be64(ctx->digest[0], dst + 8);
- +
- + *ctx = (struct ghash_desc_ctx){};
- + return 0;
- +}
- +
- +static int ghash_setkey(struct crypto_shash *tfm,
- + const u8 *inkey, unsigned int keylen)
- +{
- + struct ghash_key *key = crypto_shash_ctx(tfm);
- + u64 a, b;
- +
- + if (keylen != GHASH_BLOCK_SIZE) {
- + crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
- + return -EINVAL;
- + }
- +
- + /* perform multiplication by 'x' in GF(2^128) */
- + b = get_unaligned_be64(inkey);
- + a = get_unaligned_be64(inkey + 8);
- +
- + key->a = (a << 1) | (b >> 63);
- + key->b = (b << 1) | (a >> 63);
- +
- + if (b >> 63)
- + key->b ^= 0xc200000000000000UL;
- +
- + return 0;
- +}
- +
- +static struct shash_alg ghash_alg = {
- + .digestsize = GHASH_DIGEST_SIZE,
- + .init = ghash_init,
- + .update = ghash_update,
- + .final = ghash_final,
- + .setkey = ghash_setkey,
- + .descsize = sizeof(struct ghash_desc_ctx),
- + .base = {
- + .cra_name = "ghash",
- + .cra_driver_name = "ghash-ce",
- + .cra_priority = 200,
- + .cra_flags = CRYPTO_ALG_TYPE_SHASH,
- + .cra_blocksize = GHASH_BLOCK_SIZE,
- + .cra_ctxsize = sizeof(struct ghash_key),
- + .cra_module = THIS_MODULE,
- + },
- +};
- +
- +static int __init ghash_ce_mod_init(void)
- +{
- + return crypto_register_shash(&ghash_alg);
- +}
- +
- +static void __exit ghash_ce_mod_exit(void)
- +{
- + crypto_unregister_shash(&ghash_alg);
- +}
- +
- +module_cpu_feature_match(PMULL, ghash_ce_mod_init);
- +module_exit(ghash_ce_mod_exit);
- diff -Nur linux-3.14.35.orig/arch/arm64/crypto/Kconfig linux-3.14.35/arch/arm64/crypto/Kconfig
- --- linux-3.14.35.orig/arch/arm64/crypto/Kconfig 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/crypto/Kconfig 2015-03-08 14:27:37.445684502 -0500
- @@ -0,0 +1,53 @@
- +
- +menuconfig ARM64_CRYPTO
- + bool "ARM64 Accelerated Cryptographic Algorithms"
- + depends on ARM64
- + help
- + Say Y here to choose from a selection of cryptographic algorithms
- + implemented using ARM64 specific CPU features or instructions.
- +
- +if ARM64_CRYPTO
- +
- +config CRYPTO_SHA1_ARM64_CE
- + tristate "SHA-1 digest algorithm (ARMv8 Crypto Extensions)"
- + depends on ARM64 && KERNEL_MODE_NEON
- + select CRYPTO_HASH
- +
- +config CRYPTO_SHA2_ARM64_CE
- + tristate "SHA-224/SHA-256 digest algorithm (ARMv8 Crypto Extensions)"
- + depends on ARM64 && KERNEL_MODE_NEON
- + select CRYPTO_HASH
- +
- +config CRYPTO_GHASH_ARM64_CE
- + tristate "GHASH (for GCM chaining mode) using ARMv8 Crypto Extensions"
- + depends on ARM64 && KERNEL_MODE_NEON
- + select CRYPTO_HASH
- +
- +config CRYPTO_AES_ARM64_CE
- + tristate "AES core cipher using ARMv8 Crypto Extensions"
- + depends on ARM64 && KERNEL_MODE_NEON
- + select CRYPTO_ALGAPI
- + select CRYPTO_AES
- +
- +config CRYPTO_AES_ARM64_CE_CCM
- + tristate "AES in CCM mode using ARMv8 Crypto Extensions"
- + depends on ARM64 && KERNEL_MODE_NEON
- + select CRYPTO_ALGAPI
- + select CRYPTO_AES
- + select CRYPTO_AEAD
- +
- +config CRYPTO_AES_ARM64_CE_BLK
- + tristate "AES in ECB/CBC/CTR/XTS modes using ARMv8 Crypto Extensions"
- + depends on ARM64 && KERNEL_MODE_NEON
- + select CRYPTO_BLKCIPHER
- + select CRYPTO_AES
- + select CRYPTO_ABLK_HELPER
- +
- +config CRYPTO_AES_ARM64_NEON_BLK
- + tristate "AES in ECB/CBC/CTR/XTS modes using NEON instructions"
- + depends on ARM64 && KERNEL_MODE_NEON
- + select CRYPTO_BLKCIPHER
- + select CRYPTO_AES
- + select CRYPTO_ABLK_HELPER
- +
- +endif
- diff -Nur linux-3.14.35.orig/arch/arm64/crypto/Makefile linux-3.14.35/arch/arm64/crypto/Makefile
- --- linux-3.14.35.orig/arch/arm64/crypto/Makefile 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/crypto/Makefile 2015-03-08 14:27:37.445684502 -0500
- @@ -0,0 +1,38 @@
- +#
- +# linux/arch/arm64/crypto/Makefile
- +#
- +# Copyright (C) 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
- +#
- +# This program is free software; you can redistribute it and/or modify
- +# it under the terms of the GNU General Public License version 2 as
- +# published by the Free Software Foundation.
- +#
- +
- +obj-$(CONFIG_CRYPTO_SHA1_ARM64_CE) += sha1-ce.o
- +sha1-ce-y := sha1-ce-glue.o sha1-ce-core.o
- +
- +obj-$(CONFIG_CRYPTO_SHA2_ARM64_CE) += sha2-ce.o
- +sha2-ce-y := sha2-ce-glue.o sha2-ce-core.o
- +
- +obj-$(CONFIG_CRYPTO_GHASH_ARM64_CE) += ghash-ce.o
- +ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o
- +
- +obj-$(CONFIG_CRYPTO_AES_ARM64_CE) += aes-ce-cipher.o
- +CFLAGS_aes-ce-cipher.o += -march=armv8-a+crypto
- +
- +obj-$(CONFIG_CRYPTO_AES_ARM64_CE_CCM) += aes-ce-ccm.o
- +aes-ce-ccm-y := aes-ce-ccm-glue.o aes-ce-ccm-core.o
- +
- +obj-$(CONFIG_CRYPTO_AES_ARM64_CE_BLK) += aes-ce-blk.o
- +aes-ce-blk-y := aes-glue-ce.o aes-ce.o
- +
- +obj-$(CONFIG_CRYPTO_AES_ARM64_NEON_BLK) += aes-neon-blk.o
- +aes-neon-blk-y := aes-glue-neon.o aes-neon.o
- +
- +AFLAGS_aes-ce.o := -DINTERLEAVE=2 -DINTERLEAVE_INLINE
- +AFLAGS_aes-neon.o := -DINTERLEAVE=4
- +
- +CFLAGS_aes-glue-ce.o := -DUSE_V8_CRYPTO_EXTENSIONS
- +
- +$(obj)/aes-glue-%.o: $(src)/aes-glue.c FORCE
- + $(call if_changed_dep,cc_o_c)
- diff -Nur linux-3.14.35.orig/arch/arm64/crypto/sha1-ce-core.S linux-3.14.35/arch/arm64/crypto/sha1-ce-core.S
- --- linux-3.14.35.orig/arch/arm64/crypto/sha1-ce-core.S 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/crypto/sha1-ce-core.S 2015-03-08 14:27:37.445684502 -0500
- @@ -0,0 +1,153 @@
- +/*
- + * sha1-ce-core.S - SHA-1 secure hash using ARMv8 Crypto Extensions
- + *
- + * Copyright (C) 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <linux/linkage.h>
- +#include <asm/assembler.h>
- +
- + .text
- + .arch armv8-a+crypto
- +
- + k0 .req v0
- + k1 .req v1
- + k2 .req v2
- + k3 .req v3
- +
- + t0 .req v4
- + t1 .req v5
- +
- + dga .req q6
- + dgav .req v6
- + dgb .req s7
- + dgbv .req v7
- +
- + dg0q .req q12
- + dg0s .req s12
- + dg0v .req v12
- + dg1s .req s13
- + dg1v .req v13
- + dg2s .req s14
- +
- + .macro add_only, op, ev, rc, s0, dg1
- + .ifc \ev, ev
- + add t1.4s, v\s0\().4s, \rc\().4s
- + sha1h dg2s, dg0s
- + .ifnb \dg1
- + sha1\op dg0q, \dg1, t0.4s
- + .else
- + sha1\op dg0q, dg1s, t0.4s
- + .endif
- + .else
- + .ifnb \s0
- + add t0.4s, v\s0\().4s, \rc\().4s
- + .endif
- + sha1h dg1s, dg0s
- + sha1\op dg0q, dg2s, t1.4s
- + .endif
- + .endm
- +
- + .macro add_update, op, ev, rc, s0, s1, s2, s3, dg1
- + sha1su0 v\s0\().4s, v\s1\().4s, v\s2\().4s
- + add_only \op, \ev, \rc, \s1, \dg1
- + sha1su1 v\s0\().4s, v\s3\().4s
- + .endm
- +
- + /*
- + * The SHA1 round constants
- + */
- + .align 4
- +.Lsha1_rcon:
- + .word 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6
- +
- + /*
- + * void sha1_ce_transform(int blocks, u8 const *src, u32 *state,
- + * u8 *head, long bytes)
- + */
- +ENTRY(sha1_ce_transform)
- + /* load round constants */
- + adr x6, .Lsha1_rcon
- + ld1r {k0.4s}, [x6], #4
- + ld1r {k1.4s}, [x6], #4
- + ld1r {k2.4s}, [x6], #4
- + ld1r {k3.4s}, [x6]
- +
- + /* load state */
- + ldr dga, [x2]
- + ldr dgb, [x2, #16]
- +
- + /* load partial state (if supplied) */
- + cbz x3, 0f
- + ld1 {v8.4s-v11.4s}, [x3]
- + b 1f
- +
- + /* load input */
- +0: ld1 {v8.4s-v11.4s}, [x1], #64
- + sub w0, w0, #1
- +
- +1:
- +CPU_LE( rev32 v8.16b, v8.16b )
- +CPU_LE( rev32 v9.16b, v9.16b )
- +CPU_LE( rev32 v10.16b, v10.16b )
- +CPU_LE( rev32 v11.16b, v11.16b )
- +
- +2: add t0.4s, v8.4s, k0.4s
- + mov dg0v.16b, dgav.16b
- +
- + add_update c, ev, k0, 8, 9, 10, 11, dgb
- + add_update c, od, k0, 9, 10, 11, 8
- + add_update c, ev, k0, 10, 11, 8, 9
- + add_update c, od, k0, 11, 8, 9, 10
- + add_update c, ev, k1, 8, 9, 10, 11
- +
- + add_update p, od, k1, 9, 10, 11, 8
- + add_update p, ev, k1, 10, 11, 8, 9
- + add_update p, od, k1, 11, 8, 9, 10
- + add_update p, ev, k1, 8, 9, 10, 11
- + add_update p, od, k2, 9, 10, 11, 8
- +
- + add_update m, ev, k2, 10, 11, 8, 9
- + add_update m, od, k2, 11, 8, 9, 10
- + add_update m, ev, k2, 8, 9, 10, 11
- + add_update m, od, k2, 9, 10, 11, 8
- + add_update m, ev, k3, 10, 11, 8, 9
- +
- + add_update p, od, k3, 11, 8, 9, 10
- + add_only p, ev, k3, 9
- + add_only p, od, k3, 10
- + add_only p, ev, k3, 11
- + add_only p, od
- +
- + /* update state */
- + add dgbv.2s, dgbv.2s, dg1v.2s
- + add dgav.4s, dgav.4s, dg0v.4s
- +
- + cbnz w0, 0b
- +
- + /*
- + * Final block: add padding and total bit count.
- + * Skip if we have no total byte count in x4. In that case, the input
- + * size was not a round multiple of the block size, and the padding is
- + * handled by the C code.
- + */
- + cbz x4, 3f
- + movi v9.2d, #0
- + mov x8, #0x80000000
- + movi v10.2d, #0
- + ror x7, x4, #29 // ror(lsl(x4, 3), 32)
- + fmov d8, x8
- + mov x4, #0
- + mov v11.d[0], xzr
- + mov v11.d[1], x7
- + b 2b
- +
- + /* store new state */
- +3: str dga, [x2]
- + str dgb, [x2, #16]
- + ret
- +ENDPROC(sha1_ce_transform)
- diff -Nur linux-3.14.35.orig/arch/arm64/crypto/sha1-ce-glue.c linux-3.14.35/arch/arm64/crypto/sha1-ce-glue.c
- --- linux-3.14.35.orig/arch/arm64/crypto/sha1-ce-glue.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/crypto/sha1-ce-glue.c 2015-03-08 14:27:37.445684502 -0500
- @@ -0,0 +1,174 @@
- +/*
- + * sha1-ce-glue.c - SHA-1 secure hash using ARMv8 Crypto Extensions
- + *
- + * Copyright (C) 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <asm/neon.h>
- +#include <asm/unaligned.h>
- +#include <crypto/internal/hash.h>
- +#include <crypto/sha.h>
- +#include <linux/cpufeature.h>
- +#include <linux/crypto.h>
- +#include <linux/module.h>
- +
- +MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions");
- +MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
- +MODULE_LICENSE("GPL v2");
- +
- +asmlinkage void sha1_ce_transform(int blocks, u8 const *src, u32 *state,
- + u8 *head, long bytes);
- +
- +static int sha1_init(struct shash_desc *desc)
- +{
- + struct sha1_state *sctx = shash_desc_ctx(desc);
- +
- + *sctx = (struct sha1_state){
- + .state = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 },
- + };
- + return 0;
- +}
- +
- +static int sha1_update(struct shash_desc *desc, const u8 *data,
- + unsigned int len)
- +{
- + struct sha1_state *sctx = shash_desc_ctx(desc);
- + unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
- +
- + sctx->count += len;
- +
- + if ((partial + len) >= SHA1_BLOCK_SIZE) {
- + int blocks;
- +
- + if (partial) {
- + int p = SHA1_BLOCK_SIZE - partial;
- +
- + memcpy(sctx->buffer + partial, data, p);
- + data += p;
- + len -= p;
- + }
- +
- + blocks = len / SHA1_BLOCK_SIZE;
- + len %= SHA1_BLOCK_SIZE;
- +
- + kernel_neon_begin_partial(16);
- + sha1_ce_transform(blocks, data, sctx->state,
- + partial ? sctx->buffer : NULL, 0);
- + kernel_neon_end();
- +
- + data += blocks * SHA1_BLOCK_SIZE;
- + partial = 0;
- + }
- + if (len)
- + memcpy(sctx->buffer + partial, data, len);
- + return 0;
- +}
- +
- +static int sha1_final(struct shash_desc *desc, u8 *out)
- +{
- + static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, };
- +
- + struct sha1_state *sctx = shash_desc_ctx(desc);
- + __be64 bits = cpu_to_be64(sctx->count << 3);
- + __be32 *dst = (__be32 *)out;
- + int i;
- +
- + u32 padlen = SHA1_BLOCK_SIZE
- + - ((sctx->count + sizeof(bits)) % SHA1_BLOCK_SIZE);
- +
- + sha1_update(desc, padding, padlen);
- + sha1_update(desc, (const u8 *)&bits, sizeof(bits));
- +
- + for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++)
- + put_unaligned_be32(sctx->state[i], dst++);
- +
- + *sctx = (struct sha1_state){};
- + return 0;
- +}
- +
- +static int sha1_finup(struct shash_desc *desc, const u8 *data,
- + unsigned int len, u8 *out)
- +{
- + struct sha1_state *sctx = shash_desc_ctx(desc);
- + __be32 *dst = (__be32 *)out;
- + int blocks;
- + int i;
- +
- + if (sctx->count || !len || (len % SHA1_BLOCK_SIZE)) {
- + sha1_update(desc, data, len);
- + return sha1_final(desc, out);
- + }
- +
- + /*
- + * Use a fast path if the input is a multiple of 64 bytes. In
- + * this case, there is no need to copy data around, and we can
- + * perform the entire digest calculation in a single invocation
- + * of sha1_ce_transform()
- + */
- + blocks = len / SHA1_BLOCK_SIZE;
- +
- + kernel_neon_begin_partial(16);
- + sha1_ce_transform(blocks, data, sctx->state, NULL, len);
- + kernel_neon_end();
- +
- + for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++)
- + put_unaligned_be32(sctx->state[i], dst++);
- +
- + *sctx = (struct sha1_state){};
- + return 0;
- +}
- +
- +static int sha1_export(struct shash_desc *desc, void *out)
- +{
- + struct sha1_state *sctx = shash_desc_ctx(desc);
- + struct sha1_state *dst = out;
- +
- + *dst = *sctx;
- + return 0;
- +}
- +
- +static int sha1_import(struct shash_desc *desc, const void *in)
- +{
- + struct sha1_state *sctx = shash_desc_ctx(desc);
- + struct sha1_state const *src = in;
- +
- + *sctx = *src;
- + return 0;
- +}
- +
- +static struct shash_alg alg = {
- + .init = sha1_init,
- + .update = sha1_update,
- + .final = sha1_final,
- + .finup = sha1_finup,
- + .export = sha1_export,
- + .import = sha1_import,
- + .descsize = sizeof(struct sha1_state),
- + .digestsize = SHA1_DIGEST_SIZE,
- + .statesize = sizeof(struct sha1_state),
- + .base = {
- + .cra_name = "sha1",
- + .cra_driver_name = "sha1-ce",
- + .cra_priority = 200,
- + .cra_flags = CRYPTO_ALG_TYPE_SHASH,
- + .cra_blocksize = SHA1_BLOCK_SIZE,
- + .cra_module = THIS_MODULE,
- + }
- +};
- +
- +static int __init sha1_ce_mod_init(void)
- +{
- + return crypto_register_shash(&alg);
- +}
- +
- +static void __exit sha1_ce_mod_fini(void)
- +{
- + crypto_unregister_shash(&alg);
- +}
- +
- +module_cpu_feature_match(SHA1, sha1_ce_mod_init);
- +module_exit(sha1_ce_mod_fini);
- diff -Nur linux-3.14.35.orig/arch/arm64/crypto/sha2-ce-core.S linux-3.14.35/arch/arm64/crypto/sha2-ce-core.S
- --- linux-3.14.35.orig/arch/arm64/crypto/sha2-ce-core.S 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/crypto/sha2-ce-core.S 2015-03-08 14:27:37.445684502 -0500
- @@ -0,0 +1,156 @@
- +/*
- + * sha2-ce-core.S - core SHA-224/SHA-256 transform using v8 Crypto Extensions
- + *
- + * Copyright (C) 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <linux/linkage.h>
- +#include <asm/assembler.h>
- +
- + .text
- + .arch armv8-a+crypto
- +
- + dga .req q20
- + dgav .req v20
- + dgb .req q21
- + dgbv .req v21
- +
- + t0 .req v22
- + t1 .req v23
- +
- + dg0q .req q24
- + dg0v .req v24
- + dg1q .req q25
- + dg1v .req v25
- + dg2q .req q26
- + dg2v .req v26
- +
- + .macro add_only, ev, rc, s0
- + mov dg2v.16b, dg0v.16b
- + .ifeq \ev
- + add t1.4s, v\s0\().4s, \rc\().4s
- + sha256h dg0q, dg1q, t0.4s
- + sha256h2 dg1q, dg2q, t0.4s
- + .else
- + .ifnb \s0
- + add t0.4s, v\s0\().4s, \rc\().4s
- + .endif
- + sha256h dg0q, dg1q, t1.4s
- + sha256h2 dg1q, dg2q, t1.4s
- + .endif
- + .endm
- +
- + .macro add_update, ev, rc, s0, s1, s2, s3
- + sha256su0 v\s0\().4s, v\s1\().4s
- + add_only \ev, \rc, \s1
- + sha256su1 v\s0\().4s, v\s2\().4s, v\s3\().4s
- + .endm
- +
- + /*
- + * The SHA-256 round constants
- + */
- + .align 4
- +.Lsha2_rcon:
- + .word 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5
- + .word 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5
- + .word 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3
- + .word 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174
- + .word 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc
- + .word 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da
- + .word 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7
- + .word 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967
- + .word 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13
- + .word 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85
- + .word 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3
- + .word 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070
- + .word 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5
- + .word 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3
- + .word 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208
- + .word 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
- +
- + /*
- + * void sha2_ce_transform(int blocks, u8 const *src, u32 *state,
- + * u8 *head, long bytes)
- + */
- +ENTRY(sha2_ce_transform)
- + /* load round constants */
- + adr x8, .Lsha2_rcon
- + ld1 { v0.4s- v3.4s}, [x8], #64
- + ld1 { v4.4s- v7.4s}, [x8], #64
- + ld1 { v8.4s-v11.4s}, [x8], #64
- + ld1 {v12.4s-v15.4s}, [x8]
- +
- + /* load state */
- + ldp dga, dgb, [x2]
- +
- + /* load partial input (if supplied) */
- + cbz x3, 0f
- + ld1 {v16.4s-v19.4s}, [x3]
- + b 1f
- +
- + /* load input */
- +0: ld1 {v16.4s-v19.4s}, [x1], #64
- + sub w0, w0, #1
- +
- +1:
- +CPU_LE( rev32 v16.16b, v16.16b )
- +CPU_LE( rev32 v17.16b, v17.16b )
- +CPU_LE( rev32 v18.16b, v18.16b )
- +CPU_LE( rev32 v19.16b, v19.16b )
- +
- +2: add t0.4s, v16.4s, v0.4s
- + mov dg0v.16b, dgav.16b
- + mov dg1v.16b, dgbv.16b
- +
- + add_update 0, v1, 16, 17, 18, 19
- + add_update 1, v2, 17, 18, 19, 16
- + add_update 0, v3, 18, 19, 16, 17
- + add_update 1, v4, 19, 16, 17, 18
- +
- + add_update 0, v5, 16, 17, 18, 19
- + add_update 1, v6, 17, 18, 19, 16
- + add_update 0, v7, 18, 19, 16, 17
- + add_update 1, v8, 19, 16, 17, 18
- +
- + add_update 0, v9, 16, 17, 18, 19
- + add_update 1, v10, 17, 18, 19, 16
- + add_update 0, v11, 18, 19, 16, 17
- + add_update 1, v12, 19, 16, 17, 18
- +
- + add_only 0, v13, 17
- + add_only 1, v14, 18
- + add_only 0, v15, 19
- + add_only 1
- +
- + /* update state */
- + add dgav.4s, dgav.4s, dg0v.4s
- + add dgbv.4s, dgbv.4s, dg1v.4s
- +
- + /* handled all input blocks? */
- + cbnz w0, 0b
- +
- + /*
- + * Final block: add padding and total bit count.
- + * Skip if we have no total byte count in x4. In that case, the input
- + * size was not a round multiple of the block size, and the padding is
- + * handled by the C code.
- + */
- + cbz x4, 3f
- + movi v17.2d, #0
- + mov x8, #0x80000000
- + movi v18.2d, #0
- + ror x7, x4, #29 // ror(lsl(x4, 3), 32)
- + fmov d16, x8
- + mov x4, #0
- + mov v19.d[0], xzr
- + mov v19.d[1], x7
- + b 2b
- +
- + /* store new state */
- +3: stp dga, dgb, [x2]
- + ret
- +ENDPROC(sha2_ce_transform)
- diff -Nur linux-3.14.35.orig/arch/arm64/crypto/sha2-ce-glue.c linux-3.14.35/arch/arm64/crypto/sha2-ce-glue.c
- --- linux-3.14.35.orig/arch/arm64/crypto/sha2-ce-glue.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/crypto/sha2-ce-glue.c 2015-03-08 14:27:37.445684502 -0500
- @@ -0,0 +1,255 @@
- +/*
- + * sha2-ce-glue.c - SHA-224/SHA-256 using ARMv8 Crypto Extensions
- + *
- + * Copyright (C) 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <asm/neon.h>
- +#include <asm/unaligned.h>
- +#include <crypto/internal/hash.h>
- +#include <crypto/sha.h>
- +#include <linux/cpufeature.h>
- +#include <linux/crypto.h>
- +#include <linux/module.h>
- +
- +MODULE_DESCRIPTION("SHA-224/SHA-256 secure hash using ARMv8 Crypto Extensions");
- +MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
- +MODULE_LICENSE("GPL v2");
- +
- +asmlinkage int sha2_ce_transform(int blocks, u8 const *src, u32 *state,
- + u8 *head, long bytes);
- +
- +static int sha224_init(struct shash_desc *desc)
- +{
- + struct sha256_state *sctx = shash_desc_ctx(desc);
- +
- + *sctx = (struct sha256_state){
- + .state = {
- + SHA224_H0, SHA224_H1, SHA224_H2, SHA224_H3,
- + SHA224_H4, SHA224_H5, SHA224_H6, SHA224_H7,
- + }
- + };
- + return 0;
- +}
- +
- +static int sha256_init(struct shash_desc *desc)
- +{
- + struct sha256_state *sctx = shash_desc_ctx(desc);
- +
- + *sctx = (struct sha256_state){
- + .state = {
- + SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3,
- + SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7,
- + }
- + };
- + return 0;
- +}
- +
- +static int sha2_update(struct shash_desc *desc, const u8 *data,
- + unsigned int len)
- +{
- + struct sha256_state *sctx = shash_desc_ctx(desc);
- + unsigned int partial = sctx->count % SHA256_BLOCK_SIZE;
- +
- + sctx->count += len;
- +
- + if ((partial + len) >= SHA256_BLOCK_SIZE) {
- + int blocks;
- +
- + if (partial) {
- + int p = SHA256_BLOCK_SIZE - partial;
- +
- + memcpy(sctx->buf + partial, data, p);
- + data += p;
- + len -= p;
- + }
- +
- + blocks = len / SHA256_BLOCK_SIZE;
- + len %= SHA256_BLOCK_SIZE;
- +
- + kernel_neon_begin_partial(28);
- + sha2_ce_transform(blocks, data, sctx->state,
- + partial ? sctx->buf : NULL, 0);
- + kernel_neon_end();
- +
- + data += blocks * SHA256_BLOCK_SIZE;
- + partial = 0;
- + }
- + if (len)
- + memcpy(sctx->buf + partial, data, len);
- + return 0;
- +}
- +
- +static void sha2_final(struct shash_desc *desc)
- +{
- + static const u8 padding[SHA256_BLOCK_SIZE] = { 0x80, };
- +
- + struct sha256_state *sctx = shash_desc_ctx(desc);
- + __be64 bits = cpu_to_be64(sctx->count << 3);
- + u32 padlen = SHA256_BLOCK_SIZE
- + - ((sctx->count + sizeof(bits)) % SHA256_BLOCK_SIZE);
- +
- + sha2_update(desc, padding, padlen);
- + sha2_update(desc, (const u8 *)&bits, sizeof(bits));
- +}
- +
- +static int sha224_final(struct shash_desc *desc, u8 *out)
- +{
- + struct sha256_state *sctx = shash_desc_ctx(desc);
- + __be32 *dst = (__be32 *)out;
- + int i;
- +
- + sha2_final(desc);
- +
- + for (i = 0; i < SHA224_DIGEST_SIZE / sizeof(__be32); i++)
- + put_unaligned_be32(sctx->state[i], dst++);
- +
- + *sctx = (struct sha256_state){};
- + return 0;
- +}
- +
- +static int sha256_final(struct shash_desc *desc, u8 *out)
- +{
- + struct sha256_state *sctx = shash_desc_ctx(desc);
- + __be32 *dst = (__be32 *)out;
- + int i;
- +
- + sha2_final(desc);
- +
- + for (i = 0; i < SHA256_DIGEST_SIZE / sizeof(__be32); i++)
- + put_unaligned_be32(sctx->state[i], dst++);
- +
- + *sctx = (struct sha256_state){};
- + return 0;
- +}
- +
- +static void sha2_finup(struct shash_desc *desc, const u8 *data,
- + unsigned int len)
- +{
- + struct sha256_state *sctx = shash_desc_ctx(desc);
- + int blocks;
- +
- + if (sctx->count || !len || (len % SHA256_BLOCK_SIZE)) {
- + sha2_update(desc, data, len);
- + sha2_final(desc);
- + return;
- + }
- +
- + /*
- + * Use a fast path if the input is a multiple of 64 bytes. In
- + * this case, there is no need to copy data around, and we can
- + * perform the entire digest calculation in a single invocation
- + * of sha2_ce_transform()
- + */
- + blocks = len / SHA256_BLOCK_SIZE;
- +
- + kernel_neon_begin_partial(28);
- + sha2_ce_transform(blocks, data, sctx->state, NULL, len);
- + kernel_neon_end();
- + data += blocks * SHA256_BLOCK_SIZE;
- +}
- +
- +static int sha224_finup(struct shash_desc *desc, const u8 *data,
- + unsigned int len, u8 *out)
- +{
- + struct sha256_state *sctx = shash_desc_ctx(desc);
- + __be32 *dst = (__be32 *)out;
- + int i;
- +
- + sha2_finup(desc, data, len);
- +
- + for (i = 0; i < SHA224_DIGEST_SIZE / sizeof(__be32); i++)
- + put_unaligned_be32(sctx->state[i], dst++);
- +
- + *sctx = (struct sha256_state){};
- + return 0;
- +}
- +
- +static int sha256_finup(struct shash_desc *desc, const u8 *data,
- + unsigned int len, u8 *out)
- +{
- + struct sha256_state *sctx = shash_desc_ctx(desc);
- + __be32 *dst = (__be32 *)out;
- + int i;
- +
- + sha2_finup(desc, data, len);
- +
- + for (i = 0; i < SHA256_DIGEST_SIZE / sizeof(__be32); i++)
- + put_unaligned_be32(sctx->state[i], dst++);
- +
- + *sctx = (struct sha256_state){};
- + return 0;
- +}
- +
- +static int sha2_export(struct shash_desc *desc, void *out)
- +{
- + struct sha256_state *sctx = shash_desc_ctx(desc);
- + struct sha256_state *dst = out;
- +
- + *dst = *sctx;
- + return 0;
- +}
- +
- +static int sha2_import(struct shash_desc *desc, const void *in)
- +{
- + struct sha256_state *sctx = shash_desc_ctx(desc);
- + struct sha256_state const *src = in;
- +
- + *sctx = *src;
- + return 0;
- +}
- +
- +static struct shash_alg algs[] = { {
- + .init = sha224_init,
- + .update = sha2_update,
- + .final = sha224_final,
- + .finup = sha224_finup,
- + .export = sha2_export,
- + .import = sha2_import,
- + .descsize = sizeof(struct sha256_state),
- + .digestsize = SHA224_DIGEST_SIZE,
- + .statesize = sizeof(struct sha256_state),
- + .base = {
- + .cra_name = "sha224",
- + .cra_driver_name = "sha224-ce",
- + .cra_priority = 200,
- + .cra_flags = CRYPTO_ALG_TYPE_SHASH,
- + .cra_blocksize = SHA256_BLOCK_SIZE,
- + .cra_module = THIS_MODULE,
- + }
- +}, {
- + .init = sha256_init,
- + .update = sha2_update,
- + .final = sha256_final,
- + .finup = sha256_finup,
- + .export = sha2_export,
- + .import = sha2_import,
- + .descsize = sizeof(struct sha256_state),
- + .digestsize = SHA256_DIGEST_SIZE,
- + .statesize = sizeof(struct sha256_state),
- + .base = {
- + .cra_name = "sha256",
- + .cra_driver_name = "sha256-ce",
- + .cra_priority = 200,
- + .cra_flags = CRYPTO_ALG_TYPE_SHASH,
- + .cra_blocksize = SHA256_BLOCK_SIZE,
- + .cra_module = THIS_MODULE,
- + }
- +} };
- +
- +static int __init sha2_ce_mod_init(void)
- +{
- + return crypto_register_shashes(algs, ARRAY_SIZE(algs));
- +}
- +
- +static void __exit sha2_ce_mod_fini(void)
- +{
- + crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
- +}
- +
- +module_cpu_feature_match(SHA2, sha2_ce_mod_init);
- +module_exit(sha2_ce_mod_fini);
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/bL_switcher.h linux-3.14.35/arch/arm64/include/asm/bL_switcher.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/bL_switcher.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/bL_switcher.h 2015-03-08 14:27:37.445684502 -0500
- @@ -0,0 +1,54 @@
- +/*
- + * Based on the stubs for the ARM implementation which is:
- + *
- + * Created by: Nicolas Pitre, April 2012
- + * Copyright: (C) 2012-2013 Linaro Limited
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#ifndef ASM_BL_SWITCHER_H
- +#define ASM_BL_SWITCHER_H
- +
- +#include <linux/notifier.h>
- +#include <linux/types.h>
- +
- +typedef void (*bL_switch_completion_handler)(void *cookie);
- +
- +static inline int bL_switch_request(unsigned int cpu,
- + unsigned int new_cluster_id)
- +{
- + return -ENOTSUPP;
- +}
- +
- +/*
- + * Register here to be notified about runtime enabling/disabling of
- + * the switcher.
- + *
- + * The notifier chain is called with the switcher activation lock held:
- + * the switcher will not be enabled or disabled during callbacks.
- + * Callbacks must not call bL_switcher_{get,put}_enabled().
- + */
- +#define BL_NOTIFY_PRE_ENABLE 0
- +#define BL_NOTIFY_POST_ENABLE 1
- +#define BL_NOTIFY_PRE_DISABLE 2
- +#define BL_NOTIFY_POST_DISABLE 3
- +
- +static inline int bL_switcher_register_notifier(struct notifier_block *nb)
- +{
- + return 0;
- +}
- +
- +static inline int bL_switcher_unregister_notifier(struct notifier_block *nb)
- +{
- + return 0;
- +}
- +
- +static inline bool bL_switcher_get_enabled(void) { return false; }
- +static inline void bL_switcher_put_enabled(void) { }
- +static inline int bL_switcher_trace_trigger(void) { return 0; }
- +static inline int bL_switcher_get_logical_index(u32 mpidr) { return -EUNATCH; }
- +
- +#endif
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/cacheflush.h linux-3.14.35/arch/arm64/include/asm/cacheflush.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/cacheflush.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/cacheflush.h 2015-03-08 14:27:37.445684502 -0500
- @@ -85,6 +85,13 @@
- }
-
- /*
- + * Cache maintenance functions used by the DMA API. No to be used directly.
- + */
- +extern void __dma_map_area(const void *, size_t, int);
- +extern void __dma_unmap_area(const void *, size_t, int);
- +extern void __dma_flush_range(const void *, const void *);
- +
- +/*
- * Copy user data from/to a page which is mapped into a different
- * processes address space. Really, we want to allow our "user
- * space" model to handle this.
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/compat.h linux-3.14.35/arch/arm64/include/asm/compat.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/compat.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/compat.h 2015-03-08 14:27:37.445684502 -0500
- @@ -228,7 +228,7 @@
- return (u32)(unsigned long)uptr;
- }
-
- -#define compat_user_stack_pointer() (current_pt_regs()->compat_sp)
- +#define compat_user_stack_pointer() (user_stack_pointer(current_pt_regs()))
-
- static inline void __user *arch_compat_alloc_user_space(long len)
- {
- @@ -305,11 +305,6 @@
-
- #else /* !CONFIG_COMPAT */
-
- -static inline int is_compat_task(void)
- -{
- - return 0;
- -}
- -
- static inline int is_compat_thread(struct thread_info *thread)
- {
- return 0;
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/cpufeature.h linux-3.14.35/arch/arm64/include/asm/cpufeature.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/cpufeature.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/cpufeature.h 2015-03-08 14:27:37.445684502 -0500
- @@ -0,0 +1,29 @@
- +/*
- + * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#ifndef __ASM_CPUFEATURE_H
- +#define __ASM_CPUFEATURE_H
- +
- +#include <asm/hwcap.h>
- +
- +/*
- + * In the arm64 world (as in the ARM world), elf_hwcap is used both internally
- + * in the kernel and for user space to keep track of which optional features
- + * are supported by the current system. So let's map feature 'x' to HWCAP_x.
- + * Note that HWCAP_x constants are bit fields so we need to take the log.
- + */
- +
- +#define MAX_CPU_FEATURES (8 * sizeof(elf_hwcap))
- +#define cpu_feature(x) ilog2(HWCAP_ ## x)
- +
- +static inline bool cpu_have_feature(unsigned int num)
- +{
- + return elf_hwcap & (1UL << num);
- +}
- +
- +#endif
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/debug-monitors.h linux-3.14.35/arch/arm64/include/asm/debug-monitors.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/debug-monitors.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/debug-monitors.h 2015-03-08 14:27:37.445684502 -0500
- @@ -26,6 +26,53 @@
- #define DBG_ESR_EVT_HWWP 0x2
- #define DBG_ESR_EVT_BRK 0x6
-
- +/*
- + * Break point instruction encoding
- + */
- +#define BREAK_INSTR_SIZE 4
- +
- +/*
- + * ESR values expected for dynamic and compile time BRK instruction
- + */
- +#define DBG_ESR_VAL_BRK(x) (0xf2000000 | ((x) & 0xfffff))
- +
- +/*
- + * #imm16 values used for BRK instruction generation
- + * Allowed values for kgbd are 0x400 - 0x7ff
- + * 0x400: for dynamic BRK instruction
- + * 0x401: for compile time BRK instruction
- + */
- +#define KGDB_DYN_DGB_BRK_IMM 0x400
- +#define KDBG_COMPILED_DBG_BRK_IMM 0x401
- +
- +/*
- + * BRK instruction encoding
- + * The #imm16 value should be placed at bits[20:5] within BRK ins
- + */
- +#define AARCH64_BREAK_MON 0xd4200000
- +
- +/*
- + * Extract byte from BRK instruction
- + */
- +#define KGDB_DYN_DGB_BRK_INS_BYTE(x) \
- + ((((AARCH64_BREAK_MON) & 0xffe0001f) >> (x * 8)) & 0xff)
- +
- +/*
- + * Extract byte from BRK #imm16
- + */
- +#define KGBD_DYN_DGB_BRK_IMM_BYTE(x) \
- + (((((KGDB_DYN_DGB_BRK_IMM) & 0xffff) << 5) >> (x * 8)) & 0xff)
- +
- +#define KGDB_DYN_DGB_BRK_BYTE(x) \
- + (KGDB_DYN_DGB_BRK_INS_BYTE(x) | KGBD_DYN_DGB_BRK_IMM_BYTE(x))
- +
- +#define KGDB_DYN_BRK_INS_BYTE0 KGDB_DYN_DGB_BRK_BYTE(0)
- +#define KGDB_DYN_BRK_INS_BYTE1 KGDB_DYN_DGB_BRK_BYTE(1)
- +#define KGDB_DYN_BRK_INS_BYTE2 KGDB_DYN_DGB_BRK_BYTE(2)
- +#define KGDB_DYN_BRK_INS_BYTE3 KGDB_DYN_DGB_BRK_BYTE(3)
- +
- +#define CACHE_FLUSH_IS_SAFE 1
- +
- enum debug_el {
- DBG_ACTIVE_EL0 = 0,
- DBG_ACTIVE_EL1,
- @@ -43,23 +90,6 @@
- #ifndef __ASSEMBLY__
- struct task_struct;
-
- -#define local_dbg_save(flags) \
- - do { \
- - typecheck(unsigned long, flags); \
- - asm volatile( \
- - "mrs %0, daif // local_dbg_save\n" \
- - "msr daifset, #8" \
- - : "=r" (flags) : : "memory"); \
- - } while (0)
- -
- -#define local_dbg_restore(flags) \
- - do { \
- - typecheck(unsigned long, flags); \
- - asm volatile( \
- - "msr daif, %0 // local_dbg_restore\n" \
- - : : "r" (flags) : "memory"); \
- - } while (0)
- -
- #define DBG_ARCH_ID_RESERVED 0 /* In case of ptrace ABI updates. */
-
- #define DBG_HOOK_HANDLED 0
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/dma-mapping.h linux-3.14.35/arch/arm64/include/asm/dma-mapping.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/dma-mapping.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/dma-mapping.h 2015-03-08 14:27:37.445684502 -0500
- @@ -28,6 +28,8 @@
-
- #define DMA_ERROR_CODE (~(dma_addr_t)0)
- extern struct dma_map_ops *dma_ops;
- +extern struct dma_map_ops coherent_swiotlb_dma_ops;
- +extern struct dma_map_ops noncoherent_swiotlb_dma_ops;
-
- static inline struct dma_map_ops *__generic_dma_ops(struct device *dev)
- {
- @@ -45,6 +47,11 @@
- return __generic_dma_ops(dev);
- }
-
- +static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
- +{
- + dev->archdata.dma_ops = ops;
- +}
- +
- #include <asm-generic/dma-mapping-common.h>
-
- static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/ftrace.h linux-3.14.35/arch/arm64/include/asm/ftrace.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/ftrace.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/ftrace.h 2015-03-08 14:27:37.445684502 -0500
- @@ -0,0 +1,59 @@
- +/*
- + * arch/arm64/include/asm/ftrace.h
- + *
- + * Copyright (C) 2013 Linaro Limited
- + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#ifndef __ASM_FTRACE_H
- +#define __ASM_FTRACE_H
- +
- +#include <asm/insn.h>
- +
- +#define MCOUNT_ADDR ((unsigned long)_mcount)
- +#define MCOUNT_INSN_SIZE AARCH64_INSN_SIZE
- +
- +#ifndef __ASSEMBLY__
- +#include <linux/compat.h>
- +
- +extern void _mcount(unsigned long);
- +extern void *return_address(unsigned int);
- +
- +struct dyn_arch_ftrace {
- + /* No extra data needed for arm64 */
- +};
- +
- +extern unsigned long ftrace_graph_call;
- +
- +static inline unsigned long ftrace_call_adjust(unsigned long addr)
- +{
- + /*
- + * addr is the address of the mcount call instruction.
- + * recordmcount does the necessary offset calculation.
- + */
- + return addr;
- +}
- +
- +#define ftrace_return_address(n) return_address(n)
- +
- +/*
- + * Because AArch32 mode does not share the same syscall table with AArch64,
- + * tracing compat syscalls may result in reporting bogus syscalls or even
- + * hang-up, so just do not trace them.
- + * See kernel/trace/trace_syscalls.c
- + *
- + * x86 code says:
- + * If the user realy wants these, then they should use the
- + * raw syscall tracepoints with filtering.
- + */
- +#define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS
- +static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
- +{
- + return is_compat_task();
- +}
- +#endif /* ifndef __ASSEMBLY__ */
- +
- +#endif /* __ASM_FTRACE_H */
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/hwcap.h linux-3.14.35/arch/arm64/include/asm/hwcap.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/hwcap.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/hwcap.h 2015-03-08 14:27:37.445684502 -0500
- @@ -33,6 +33,12 @@
- #define COMPAT_HWCAP_LPAE (1 << 20)
- #define COMPAT_HWCAP_EVTSTRM (1 << 21)
-
- +#define COMPAT_HWCAP2_AES (1 << 0)
- +#define COMPAT_HWCAP2_PMULL (1 << 1)
- +#define COMPAT_HWCAP2_SHA1 (1 << 2)
- +#define COMPAT_HWCAP2_SHA2 (1 << 3)
- +#define COMPAT_HWCAP2_CRC32 (1 << 4)
- +
- #ifndef __ASSEMBLY__
- /*
- * This yields a mask that user programs can use to figure out what
- @@ -42,7 +48,8 @@
-
- #ifdef CONFIG_COMPAT
- #define COMPAT_ELF_HWCAP (compat_elf_hwcap)
- -extern unsigned int compat_elf_hwcap;
- +#define COMPAT_ELF_HWCAP2 (compat_elf_hwcap2)
- +extern unsigned int compat_elf_hwcap, compat_elf_hwcap2;
- #endif
-
- extern unsigned long elf_hwcap;
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/insn.h linux-3.14.35/arch/arm64/include/asm/insn.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/insn.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/insn.h 2015-03-08 14:27:37.445684502 -0500
- @@ -16,11 +16,14 @@
- */
- #ifndef __ASM_INSN_H
- #define __ASM_INSN_H
- +
- #include <linux/types.h>
-
- /* A64 instructions are always 32 bits. */
- #define AARCH64_INSN_SIZE 4
-
- +#ifndef __ASSEMBLY__
- +
- /*
- * ARM Architecture Reference Manual for ARMv8 Profile-A, Issue A.a
- * Section C3.1 "A64 instruction index by encoding":
- @@ -105,4 +108,6 @@
- int aarch64_insn_patch_text_sync(void *addrs[], u32 insns[], int cnt);
- int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt);
-
- +#endif /* __ASSEMBLY__ */
- +
- #endif /* __ASM_INSN_H */
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/irqflags.h linux-3.14.35/arch/arm64/include/asm/irqflags.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/irqflags.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/irqflags.h 2015-03-08 14:27:37.445684502 -0500
- @@ -90,5 +90,28 @@
- return flags & PSR_I_BIT;
- }
-
- +/*
- + * save and restore debug state
- + */
- +#define local_dbg_save(flags) \
- + do { \
- + typecheck(unsigned long, flags); \
- + asm volatile( \
- + "mrs %0, daif // local_dbg_save\n" \
- + "msr daifset, #8" \
- + : "=r" (flags) : : "memory"); \
- + } while (0)
- +
- +#define local_dbg_restore(flags) \
- + do { \
- + typecheck(unsigned long, flags); \
- + asm volatile( \
- + "msr daif, %0 // local_dbg_restore\n" \
- + : : "r" (flags) : "memory"); \
- + } while (0)
- +
- +#define local_dbg_enable() asm("msr daifclr, #8" : : : "memory")
- +#define local_dbg_disable() asm("msr daifset, #8" : : : "memory")
- +
- #endif
- #endif
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/Kbuild linux-3.14.35/arch/arm64/include/asm/Kbuild
- --- linux-3.14.35.orig/arch/arm64/include/asm/Kbuild 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/Kbuild 2015-03-08 14:27:37.445684502 -0500
- @@ -35,6 +35,7 @@
- generic-y += sembuf.h
- generic-y += serial.h
- generic-y += shmbuf.h
- +generic-y += simd.h
- generic-y += sizes.h
- generic-y += socket.h
- generic-y += sockios.h
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/kgdb.h linux-3.14.35/arch/arm64/include/asm/kgdb.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/kgdb.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/kgdb.h 2015-03-08 14:27:37.445684502 -0500
- @@ -0,0 +1,84 @@
- +/*
- + * AArch64 KGDB support
- + *
- + * Based on arch/arm/include/kgdb.h
- + *
- + * Copyright (C) 2013 Cavium Inc.
- + * Author: Vijaya Kumar K <vijaya.kumar@caviumnetworks.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program. If not, see <http://www.gnu.org/licenses/>.
- + */
- +
- +#ifndef __ARM_KGDB_H
- +#define __ARM_KGDB_H
- +
- +#include <linux/ptrace.h>
- +#include <asm/debug-monitors.h>
- +
- +#ifndef __ASSEMBLY__
- +
- +static inline void arch_kgdb_breakpoint(void)
- +{
- + asm ("brk %0" : : "I" (KDBG_COMPILED_DBG_BRK_IMM));
- +}
- +
- +extern void kgdb_handle_bus_error(void);
- +extern int kgdb_fault_expected;
- +
- +#endif /* !__ASSEMBLY__ */
- +
- +/*
- + * gdb is expecting the following registers layout.
- + *
- + * General purpose regs:
- + * r0-r30: 64 bit
- + * sp,pc : 64 bit
- + * pstate : 64 bit
- + * Total: 34
- + * FPU regs:
- + * f0-f31: 128 bit
- + * Total: 32
- + * Extra regs
- + * fpsr & fpcr: 32 bit
- + * Total: 2
- + *
- + */
- +
- +#define _GP_REGS 34
- +#define _FP_REGS 32
- +#define _EXTRA_REGS 2
- +/*
- + * general purpose registers size in bytes.
- + * pstate is only 4 bytes. subtract 4 bytes
- + */
- +#define GP_REG_BYTES (_GP_REGS * 8)
- +#define DBG_MAX_REG_NUM (_GP_REGS + _FP_REGS + _EXTRA_REGS)
- +
- +/*
- + * Size of I/O buffer for gdb packet.
- + * considering to hold all register contents, size is set
- + */
- +
- +#define BUFMAX 2048
- +
- +/*
- + * Number of bytes required for gdb_regs buffer.
- + * _GP_REGS: 8 bytes, _FP_REGS: 16 bytes and _EXTRA_REGS: 4 bytes each
- + * GDB fails to connect for size beyond this with error
- + * "'g' packet reply is too long"
- + */
- +
- +#define NUMREGBYTES ((_GP_REGS * 8) + (_FP_REGS * 16) + \
- + (_EXTRA_REGS * 4))
- +
- +#endif /* __ASM_KGDB_H */
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/page.h linux-3.14.35/arch/arm64/include/asm/page.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/page.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/page.h 2015-03-08 14:27:37.445684502 -0500
- @@ -31,6 +31,15 @@
- /* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */
- #define __HAVE_ARCH_GATE_AREA 1
-
- +/*
- + * The idmap and swapper page tables need some space reserved in the kernel
- + * image. The idmap only requires a pgd and a next level table to (section) map
- + * the kernel, while the swapper also maps the FDT and requires an additional
- + * table to map an early UART. See __create_page_tables for more information.
- + */
- +#define SWAPPER_DIR_SIZE (3 * PAGE_SIZE)
- +#define IDMAP_DIR_SIZE (2 * PAGE_SIZE)
- +
- #ifndef __ASSEMBLY__
-
- #ifdef CONFIG_ARM64_64K_PAGES
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/pgtable.h linux-3.14.35/arch/arm64/include/asm/pgtable.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/pgtable.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/pgtable.h 2015-03-08 14:27:37.445684502 -0500
- @@ -227,36 +227,36 @@
-
- #define __HAVE_ARCH_PTE_SPECIAL
-
- -/*
- - * Software PMD bits for THP
- - */
- +static inline pte_t pmd_pte(pmd_t pmd)
- +{
- + return __pte(pmd_val(pmd));
- +}
-
- -#define PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55)
- -#define PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 57)
- +static inline pmd_t pte_pmd(pte_t pte)
- +{
- + return __pmd(pte_val(pte));
- +}
-
- /*
- * THP definitions.
- */
- -#define pmd_young(pmd) (pmd_val(pmd) & PMD_SECT_AF)
- -
- -#define __HAVE_ARCH_PMD_WRITE
- -#define pmd_write(pmd) (!(pmd_val(pmd) & PMD_SECT_RDONLY))
-
- #ifdef CONFIG_TRANSPARENT_HUGEPAGE
- #define pmd_trans_huge(pmd) (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT))
- -#define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING)
- +#define pmd_trans_splitting(pmd) pte_special(pmd_pte(pmd))
- #endif
-
- -#define PMD_BIT_FUNC(fn,op) \
- -static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
- +#define pmd_young(pmd) pte_young(pmd_pte(pmd))
- +#define pmd_wrprotect(pmd) pte_pmd(pte_wrprotect(pmd_pte(pmd)))
- +#define pmd_mksplitting(pmd) pte_pmd(pte_mkspecial(pmd_pte(pmd)))
- +#define pmd_mkold(pmd) pte_pmd(pte_mkold(pmd_pte(pmd)))
- +#define pmd_mkwrite(pmd) pte_pmd(pte_mkwrite(pmd_pte(pmd)))
- +#define pmd_mkdirty(pmd) pte_pmd(pte_mkdirty(pmd_pte(pmd)))
- +#define pmd_mkyoung(pmd) pte_pmd(pte_mkyoung(pmd_pte(pmd)))
- +#define pmd_mknotpresent(pmd) (__pmd(pmd_val(pmd) &= ~PMD_TYPE_MASK))
-
- -PMD_BIT_FUNC(wrprotect, |= PMD_SECT_RDONLY);
- -PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF);
- -PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING);
- -PMD_BIT_FUNC(mkwrite, &= ~PMD_SECT_RDONLY);
- -PMD_BIT_FUNC(mkdirty, |= PMD_SECT_DIRTY);
- -PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF);
- -PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK);
- +#define __HAVE_ARCH_PMD_WRITE
- +#define pmd_write(pmd) pte_write(pmd_pte(pmd))
-
- #define pmd_mkhuge(pmd) (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))
-
- @@ -266,16 +266,7 @@
-
- #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
-
- -static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
- -{
- - const pmdval_t mask = PMD_SECT_USER | PMD_SECT_PXN | PMD_SECT_UXN |
- - PMD_SECT_RDONLY | PMD_SECT_PROT_NONE |
- - PMD_SECT_VALID;
- - pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask);
- - return pmd;
- -}
- -
- -#define set_pmd_at(mm, addr, pmdp, pmd) set_pmd(pmdp, pmd)
- +#define set_pmd_at(mm, addr, pmdp, pmd) set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd))
-
- static inline int has_transparent_hugepage(void)
- {
- @@ -383,12 +374,14 @@
- return pte;
- }
-
- +static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
- +{
- + return pte_pmd(pte_modify(pmd_pte(pmd), newprot));
- +}
- +
- extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
- extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
-
- -#define SWAPPER_DIR_SIZE (3 * PAGE_SIZE)
- -#define IDMAP_DIR_SIZE (2 * PAGE_SIZE)
- -
- /*
- * Encode and decode a swap entry:
- * bits 0-1: present (must be zero)
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/ptrace.h linux-3.14.35/arch/arm64/include/asm/ptrace.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/ptrace.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/ptrace.h 2015-03-08 14:27:37.445684502 -0500
- @@ -68,6 +68,7 @@
-
- /* Architecturally defined mapping between AArch32 and AArch64 registers */
- #define compat_usr(x) regs[(x)]
- +#define compat_fp regs[11]
- #define compat_sp regs[13]
- #define compat_lr regs[14]
- #define compat_sp_hyp regs[15]
- @@ -132,7 +133,12 @@
- (!((regs)->pstate & PSR_F_BIT))
-
- #define user_stack_pointer(regs) \
- - ((regs)->sp)
- + (!compat_user_mode(regs)) ? ((regs)->sp) : ((regs)->compat_sp)
- +
- +static inline unsigned long regs_return_value(struct pt_regs *regs)
- +{
- + return regs->regs[0];
- +}
-
- /*
- * Are the current registers suitable for user mode? (used to maintain
- @@ -164,7 +170,7 @@
- return 0;
- }
-
- -#define instruction_pointer(regs) (regs)->pc
- +#define instruction_pointer(regs) ((unsigned long)(regs)->pc)
-
- #ifdef CONFIG_SMP
- extern unsigned long profile_pc(struct pt_regs *regs);
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/syscall.h linux-3.14.35/arch/arm64/include/asm/syscall.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/syscall.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/syscall.h 2015-03-08 14:27:37.445684502 -0500
- @@ -18,6 +18,7 @@
-
- #include <linux/err.h>
-
- +extern const void *sys_call_table[];
-
- static inline int syscall_get_nr(struct task_struct *task,
- struct pt_regs *regs)
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/thread_info.h linux-3.14.35/arch/arm64/include/asm/thread_info.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/thread_info.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/thread_info.h 2015-03-08 14:27:37.449684502 -0500
- @@ -91,6 +91,9 @@
- /*
- * thread information flags:
- * TIF_SYSCALL_TRACE - syscall trace active
- + * TIF_SYSCALL_TRACEPOINT - syscall tracepoint for ftrace
- + * TIF_SYSCALL_AUDIT - syscall auditing
- + * TIF_SECOMP - syscall secure computing
- * TIF_SIGPENDING - signal pending
- * TIF_NEED_RESCHED - rescheduling necessary
- * TIF_NOTIFY_RESUME - callback before returning to user
- @@ -101,6 +104,9 @@
- #define TIF_NEED_RESCHED 1
- #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
- #define TIF_SYSCALL_TRACE 8
- +#define TIF_SYSCALL_AUDIT 9
- +#define TIF_SYSCALL_TRACEPOINT 10
- +#define TIF_SECCOMP 11
- #define TIF_POLLING_NRFLAG 16
- #define TIF_MEMDIE 18 /* is terminating due to OOM killer */
- #define TIF_FREEZE 19
- @@ -112,10 +118,17 @@
- #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
- #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
- #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
- +#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
- +#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
- +#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
- +#define _TIF_SECCOMP (1 << TIF_SECCOMP)
- #define _TIF_32BIT (1 << TIF_32BIT)
-
- #define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
- _TIF_NOTIFY_RESUME)
-
- +#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
- + _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP)
- +
- #endif /* __KERNEL__ */
- #endif /* __ASM_THREAD_INFO_H */
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/topology.h linux-3.14.35/arch/arm64/include/asm/topology.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/topology.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/topology.h 2015-03-08 14:27:37.449684502 -0500
- @@ -0,0 +1,70 @@
- +#ifndef __ASM_TOPOLOGY_H
- +#define __ASM_TOPOLOGY_H
- +
- +#ifdef CONFIG_SMP
- +
- +#include <linux/cpumask.h>
- +
- +struct cpu_topology {
- + int thread_id;
- + int core_id;
- + int cluster_id;
- + cpumask_t thread_sibling;
- + cpumask_t core_sibling;
- +};
- +
- +extern struct cpu_topology cpu_topology[NR_CPUS];
- +
- +#define topology_physical_package_id(cpu) (cpu_topology[cpu].cluster_id)
- +#define topology_core_id(cpu) (cpu_topology[cpu].core_id)
- +#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling)
- +#define topology_thread_cpumask(cpu) (&cpu_topology[cpu].thread_sibling)
- +
- +#define mc_capable() (cpu_topology[0].cluster_id != -1)
- +#define smt_capable() (cpu_topology[0].thread_id != -1)
- +
- +void init_cpu_topology(void);
- +void store_cpu_topology(unsigned int cpuid);
- +const struct cpumask *cpu_coregroup_mask(int cpu);
- +
- +#ifdef CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE
- +/* Common values for CPUs */
- +#ifndef SD_CPU_INIT
- +#define SD_CPU_INIT (struct sched_domain) { \
- + .min_interval = 1, \
- + .max_interval = 4, \
- + .busy_factor = 64, \
- + .imbalance_pct = 125, \
- + .cache_nice_tries = 1, \
- + .busy_idx = 2, \
- + .idle_idx = 1, \
- + .newidle_idx = 0, \
- + .wake_idx = 0, \
- + .forkexec_idx = 0, \
- + \
- + .flags = 0*SD_LOAD_BALANCE \
- + | 1*SD_BALANCE_NEWIDLE \
- + | 1*SD_BALANCE_EXEC \
- + | 1*SD_BALANCE_FORK \
- + | 0*SD_BALANCE_WAKE \
- + | 1*SD_WAKE_AFFINE \
- + | 0*SD_SHARE_CPUPOWER \
- + | 0*SD_SHARE_PKG_RESOURCES \
- + | 0*SD_SERIALIZE \
- + , \
- + .last_balance = jiffies, \
- + .balance_interval = 1, \
- +}
- +#endif
- +#endif /* CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE */
- +
- +#else
- +
- +static inline void init_cpu_topology(void) { }
- +static inline void store_cpu_topology(unsigned int cpuid) { }
- +
- +#endif
- +
- +#include <asm-generic/topology.h>
- +
- +#endif /* _ASM_ARM_TOPOLOGY_H */
- diff -Nur linux-3.14.35.orig/arch/arm64/include/asm/unistd.h linux-3.14.35/arch/arm64/include/asm/unistd.h
- --- linux-3.14.35.orig/arch/arm64/include/asm/unistd.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/asm/unistd.h 2015-03-08 14:27:37.449684502 -0500
- @@ -28,3 +28,5 @@
- #endif
- #define __ARCH_WANT_SYS_CLONE
- #include <uapi/asm/unistd.h>
- +
- +#define NR_syscalls (__NR_syscalls)
- diff -Nur linux-3.14.35.orig/arch/arm64/include/uapi/asm/Kbuild linux-3.14.35/arch/arm64/include/uapi/asm/Kbuild
- --- linux-3.14.35.orig/arch/arm64/include/uapi/asm/Kbuild 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/uapi/asm/Kbuild 2015-03-08 14:27:37.449684502 -0500
- @@ -9,6 +9,7 @@
- header-y += fcntl.h
- header-y += hwcap.h
- header-y += kvm_para.h
- +header-y += perf_regs.h
- header-y += param.h
- header-y += ptrace.h
- header-y += setup.h
- diff -Nur linux-3.14.35.orig/arch/arm64/include/uapi/asm/perf_regs.h linux-3.14.35/arch/arm64/include/uapi/asm/perf_regs.h
- --- linux-3.14.35.orig/arch/arm64/include/uapi/asm/perf_regs.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/include/uapi/asm/perf_regs.h 2015-03-08 14:27:37.449684502 -0500
- @@ -0,0 +1,40 @@
- +#ifndef _ASM_ARM64_PERF_REGS_H
- +#define _ASM_ARM64_PERF_REGS_H
- +
- +enum perf_event_arm_regs {
- + PERF_REG_ARM64_X0,
- + PERF_REG_ARM64_X1,
- + PERF_REG_ARM64_X2,
- + PERF_REG_ARM64_X3,
- + PERF_REG_ARM64_X4,
- + PERF_REG_ARM64_X5,
- + PERF_REG_ARM64_X6,
- + PERF_REG_ARM64_X7,
- + PERF_REG_ARM64_X8,
- + PERF_REG_ARM64_X9,
- + PERF_REG_ARM64_X10,
- + PERF_REG_ARM64_X11,
- + PERF_REG_ARM64_X12,
- + PERF_REG_ARM64_X13,
- + PERF_REG_ARM64_X14,
- + PERF_REG_ARM64_X15,
- + PERF_REG_ARM64_X16,
- + PERF_REG_ARM64_X17,
- + PERF_REG_ARM64_X18,
- + PERF_REG_ARM64_X19,
- + PERF_REG_ARM64_X20,
- + PERF_REG_ARM64_X21,
- + PERF_REG_ARM64_X22,
- + PERF_REG_ARM64_X23,
- + PERF_REG_ARM64_X24,
- + PERF_REG_ARM64_X25,
- + PERF_REG_ARM64_X26,
- + PERF_REG_ARM64_X27,
- + PERF_REG_ARM64_X28,
- + PERF_REG_ARM64_X29,
- + PERF_REG_ARM64_LR,
- + PERF_REG_ARM64_SP,
- + PERF_REG_ARM64_PC,
- + PERF_REG_ARM64_MAX,
- +};
- +#endif /* _ASM_ARM64_PERF_REGS_H */
- diff -Nur linux-3.14.35.orig/arch/arm64/Kconfig linux-3.14.35/arch/arm64/Kconfig
- --- linux-3.14.35.orig/arch/arm64/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/Kconfig 2015-03-08 14:27:37.449684502 -0500
- @@ -4,6 +4,7 @@
- select ARCH_USE_CMPXCHG_LOCKREF
- select ARCH_SUPPORTS_ATOMIC_RMW
- select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
- + select ARCH_HAS_OPP
- select ARCH_WANT_OPTIONAL_GPIOLIB
- select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
- select ARCH_WANT_FRAME_POINTERS
- @@ -17,6 +18,7 @@
- select DCACHE_WORD_ACCESS
- select GENERIC_CLOCKEVENTS
- select GENERIC_CLOCKEVENTS_BROADCAST if SMP
- + select GENERIC_CPU_AUTOPROBE
- select GENERIC_IOMAP
- select GENERIC_IRQ_PROBE
- select GENERIC_IRQ_SHOW
- @@ -27,18 +29,27 @@
- select GENERIC_TIME_VSYSCALL
- select HARDIRQS_SW_RESEND
- select HAVE_ARCH_JUMP_LABEL
- + select HAVE_ARCH_KGDB
- select HAVE_ARCH_TRACEHOOK
- + select HAVE_C_RECORDMCOUNT
- select HAVE_DEBUG_BUGVERBOSE
- select HAVE_DEBUG_KMEMLEAK
- select HAVE_DMA_API_DEBUG
- select HAVE_DMA_ATTRS
- select HAVE_DMA_CONTIGUOUS
- select HAVE_EFFICIENT_UNALIGNED_ACCESS
- + select HAVE_DYNAMIC_FTRACE
- + select HAVE_FTRACE_MCOUNT_RECORD
- + select HAVE_FUNCTION_TRACER
- + select HAVE_FUNCTION_GRAPH_TRACER
- select HAVE_GENERIC_DMA_COHERENT
- select HAVE_HW_BREAKPOINT if PERF_EVENTS
- select HAVE_MEMBLOCK
- select HAVE_PATA_PLATFORM
- select HAVE_PERF_EVENTS
- + select HAVE_PERF_REGS
- + select HAVE_PERF_USER_STACK_DUMP
- + select HAVE_SYSCALL_TRACEPOINTS
- select IRQ_DOMAIN
- select MODULES_USE_ELF_RELA
- select NO_BOOTMEM
- @@ -86,7 +97,7 @@
- config GENERIC_CALIBRATE_DELAY
- def_bool y
-
- -config ZONE_DMA32
- +config ZONE_DMA
- def_bool y
-
- config ARCH_DMA_ADDR_T_64BIT
- @@ -165,6 +176,134 @@
-
- If you don't know what to do here, say N.
-
- +config SCHED_MC
- + bool "Multi-core scheduler support"
- + depends on SMP
- + help
- + Multi-core scheduler support improves the CPU scheduler's decision
- + making when dealing with multi-core CPU chips at a cost of slightly
- + increased overhead in some places. If unsure say N here.
- +
- +config SCHED_SMT
- + bool "SMT scheduler support"
- + depends on SMP
- + help
- + Improves the CPU scheduler's decision making when dealing with
- + MultiThreading at a cost of slightly increased overhead in some
- + places. If unsure say N here.
- +
- +config SCHED_MC
- + bool "Multi-core scheduler support"
- + depends on ARM_CPU_TOPOLOGY
- + help
- + Multi-core scheduler support improves the CPU scheduler's decision
- + making when dealing with multi-core CPU chips at a cost of slightly
- + increased overhead in some places. If unsure say N here.
- +
- +config SCHED_SMT
- + bool "SMT scheduler support"
- + depends on ARM_CPU_TOPOLOGY
- + help
- + Improves the CPU scheduler's decision making when dealing with
- + MultiThreading at a cost of slightly increased overhead in some
- + places. If unsure say N here.
- +
- +config DISABLE_CPU_SCHED_DOMAIN_BALANCE
- + bool "(EXPERIMENTAL) Disable CPU level scheduler load-balancing"
- + help
- + Disables scheduler load-balancing at CPU sched domain level.
- +
- +config SCHED_HMP
- + bool "(EXPERIMENTAL) Heterogenous multiprocessor scheduling"
- + depends on DISABLE_CPU_SCHED_DOMAIN_BALANCE && SCHED_MC && FAIR_GROUP_SCHED && !SCHED_AUTOGROUP
- + help
- + Experimental scheduler optimizations for heterogeneous platforms.
- + Attempts to introspectively select task affinity to optimize power
- + and performance. Basic support for multiple (>2) cpu types is in place,
- + but it has only been tested with two types of cpus.
- + There is currently no support for migration of task groups, hence
- + !SCHED_AUTOGROUP. Furthermore, normal load-balancing must be disabled
- + between cpus of different type (DISABLE_CPU_SCHED_DOMAIN_BALANCE).
- +
- +config SCHED_HMP_PRIO_FILTER
- + bool "(EXPERIMENTAL) Filter HMP migrations by task priority"
- + depends on SCHED_HMP
- + help
- + Enables task priority based HMP migration filter. Any task with
- + a NICE value above the threshold will always be on low-power cpus
- + with less compute capacity.
- +
- +config SCHED_HMP_PRIO_FILTER_VAL
- + int "NICE priority threshold"
- + default 5
- + depends on SCHED_HMP_PRIO_FILTER
- +
- +config HMP_FAST_CPU_MASK
- + string "HMP scheduler fast CPU mask"
- + depends on SCHED_HMP
- + help
- + Leave empty to use device tree information.
- + Specify the cpuids of the fast CPUs in the system as a list string,
- + e.g. cpuid 0+1 should be specified as 0-1.
- +
- +config HMP_SLOW_CPU_MASK
- + string "HMP scheduler slow CPU mask"
- + depends on SCHED_HMP
- + help
- + Leave empty to use device tree information.
- + Specify the cpuids of the slow CPUs in the system as a list string,
- + e.g. cpuid 0+1 should be specified as 0-1.
- +
- +config HMP_VARIABLE_SCALE
- + bool "Allows changing the load tracking scale through sysfs"
- + depends on SCHED_HMP
- + help
- + When turned on, this option exports the thresholds and load average
- + period value for the load tracking patches through sysfs.
- + The values can be modified to change the rate of load accumulation
- + and the thresholds used for HMP migration.
- + The load_avg_period_ms is the time in ms to reach a load average of
- + 0.5 for an idle task of 0 load average ratio that start a busy loop.
- + The up_threshold and down_threshold is the value to go to a faster
- + CPU or to go back to a slower cpu.
- + The {up,down}_threshold are devided by 1024 before being compared
- + to the load average.
- + For examples, with load_avg_period_ms = 128 and up_threshold = 512,
- + a running task with a load of 0 will be migrated to a bigger CPU after
- + 128ms, because after 128ms its load_avg_ratio is 0.5 and the real
- + up_threshold is 0.5.
- + This patch has the same behavior as changing the Y of the load
- + average computation to
- + (1002/1024)^(LOAD_AVG_PERIOD/load_avg_period_ms)
- + but it remove intermadiate overflows in computation.
- +
- +config HMP_FREQUENCY_INVARIANT_SCALE
- + bool "(EXPERIMENTAL) Frequency-Invariant Tracked Load for HMP"
- + depends on HMP_VARIABLE_SCALE && CPU_FREQ
- + help
- + Scales the current load contribution in line with the frequency
- + of the CPU that the task was executed on.
- + In this version, we use a simple linear scale derived from the
- + maximum frequency reported by CPUFreq.
- + Restricting tracked load to be scaled by the CPU's frequency
- + represents the consumption of possible compute capacity
- + (rather than consumption of actual instantaneous capacity as
- + normal) and allows the HMP migration's simple threshold
- + migration strategy to interact more predictably with CPUFreq's
- + asynchronous compute capacity changes.
- +
- +config SCHED_HMP_LITTLE_PACKING
- + bool "Small task packing for HMP"
- + depends on SCHED_HMP
- + default n
- + help
- + Allows the HMP Scheduler to pack small tasks into CPUs in the
- + smallest HMP domain.
- + Controlled by two sysfs files in sys/kernel/hmp.
- + packing_enable: 1 to enable, 0 to disable packing. Default 1.
- + packing_limit: runqueue load ratio where a RQ is considered
- + to be full. Default is NICE_0_LOAD * 9/8.
- +
- config NR_CPUS
- int "Maximum number of CPUs (2-32)"
- range 2 32
- @@ -317,5 +456,8 @@
- source "security/Kconfig"
-
- source "crypto/Kconfig"
- +if CRYPTO
- +source "arch/arm64/crypto/Kconfig"
- +endif
-
- source "lib/Kconfig"
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/arm64ksyms.c linux-3.14.35/arch/arm64/kernel/arm64ksyms.c
- --- linux-3.14.35.orig/arch/arm64/kernel/arm64ksyms.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/arm64ksyms.c 2015-03-08 14:27:37.449684502 -0500
- @@ -56,3 +56,7 @@
- EXPORT_SYMBOL(test_and_clear_bit);
- EXPORT_SYMBOL(change_bit);
- EXPORT_SYMBOL(test_and_change_bit);
- +
- +#ifdef CONFIG_FUNCTION_TRACER
- +EXPORT_SYMBOL(_mcount);
- +#endif
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/debug-monitors.c linux-3.14.35/arch/arm64/kernel/debug-monitors.c
- --- linux-3.14.35.orig/arch/arm64/kernel/debug-monitors.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/debug-monitors.c 2015-03-08 14:27:37.449684502 -0500
- @@ -138,6 +138,7 @@
- {
- asm volatile("msr oslar_el1, %0" : : "r" (0));
- isb();
- + local_dbg_enable();
- }
-
- static int os_lock_notify(struct notifier_block *self,
- @@ -314,9 +315,6 @@
- if (call_break_hook(regs, esr) == DBG_HOOK_HANDLED)
- return 0;
-
- - pr_warn("unexpected brk exception at %lx, esr=0x%x\n",
- - (long)instruction_pointer(regs), esr);
- -
- if (!user_mode(regs))
- return -EFAULT;
-
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/entry-ftrace.S linux-3.14.35/arch/arm64/kernel/entry-ftrace.S
- --- linux-3.14.35.orig/arch/arm64/kernel/entry-ftrace.S 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/entry-ftrace.S 2015-03-08 14:27:37.449684502 -0500
- @@ -0,0 +1,218 @@
- +/*
- + * arch/arm64/kernel/entry-ftrace.S
- + *
- + * Copyright (C) 2013 Linaro Limited
- + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <linux/linkage.h>
- +#include <asm/ftrace.h>
- +#include <asm/insn.h>
- +
- +/*
- + * Gcc with -pg will put the following code in the beginning of each function:
- + * mov x0, x30
- + * bl _mcount
- + * [function's body ...]
- + * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
- + * ftrace is enabled.
- + *
- + * Please note that x0 as an argument will not be used here because we can
- + * get lr(x30) of instrumented function at any time by winding up call stack
- + * as long as the kernel is compiled without -fomit-frame-pointer.
- + * (or CONFIG_FRAME_POINTER, this is forced on arm64)
- + *
- + * stack layout after mcount_enter in _mcount():
- + *
- + * current sp/fp => 0:+-----+
- + * in _mcount() | x29 | -> instrumented function's fp
- + * +-----+
- + * | x30 | -> _mcount()'s lr (= instrumented function's pc)
- + * old sp => +16:+-----+
- + * when instrumented | |
- + * function calls | ... |
- + * _mcount() | |
- + * | |
- + * instrumented => +xx:+-----+
- + * function's fp | x29 | -> parent's fp
- + * +-----+
- + * | x30 | -> instrumented function's lr (= parent's pc)
- + * +-----+
- + * | ... |
- + */
- +
- + .macro mcount_enter
- + stp x29, x30, [sp, #-16]!
- + mov x29, sp
- + .endm
- +
- + .macro mcount_exit
- + ldp x29, x30, [sp], #16
- + ret
- + .endm
- +
- + .macro mcount_adjust_addr rd, rn
- + sub \rd, \rn, #AARCH64_INSN_SIZE
- + .endm
- +
- + /* for instrumented function's parent */
- + .macro mcount_get_parent_fp reg
- + ldr \reg, [x29]
- + ldr \reg, [\reg]
- + .endm
- +
- + /* for instrumented function */
- + .macro mcount_get_pc0 reg
- + mcount_adjust_addr \reg, x30
- + .endm
- +
- + .macro mcount_get_pc reg
- + ldr \reg, [x29, #8]
- + mcount_adjust_addr \reg, \reg
- + .endm
- +
- + .macro mcount_get_lr reg
- + ldr \reg, [x29]
- + ldr \reg, [\reg, #8]
- + mcount_adjust_addr \reg, \reg
- + .endm
- +
- + .macro mcount_get_lr_addr reg
- + ldr \reg, [x29]
- + add \reg, \reg, #8
- + .endm
- +
- +#ifndef CONFIG_DYNAMIC_FTRACE
- +/*
- + * void _mcount(unsigned long return_address)
- + * @return_address: return address to instrumented function
- + *
- + * This function makes calls, if enabled, to:
- + * - tracer function to probe instrumented function's entry,
- + * - ftrace_graph_caller to set up an exit hook
- + */
- +ENTRY(_mcount)
- +#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
- + ldr x0, =ftrace_trace_stop
- + ldr x0, [x0] // if ftrace_trace_stop
- + ret // return;
- +#endif
- + mcount_enter
- +
- + ldr x0, =ftrace_trace_function
- + ldr x2, [x0]
- + adr x0, ftrace_stub
- + cmp x0, x2 // if (ftrace_trace_function
- + b.eq skip_ftrace_call // != ftrace_stub) {
- +
- + mcount_get_pc x0 // function's pc
- + mcount_get_lr x1 // function's lr (= parent's pc)
- + blr x2 // (*ftrace_trace_function)(pc, lr);
- +
- +#ifndef CONFIG_FUNCTION_GRAPH_TRACER
- +skip_ftrace_call: // return;
- + mcount_exit // }
- +#else
- + mcount_exit // return;
- + // }
- +skip_ftrace_call:
- + ldr x1, =ftrace_graph_return
- + ldr x2, [x1] // if ((ftrace_graph_return
- + cmp x0, x2 // != ftrace_stub)
- + b.ne ftrace_graph_caller
- +
- + ldr x1, =ftrace_graph_entry // || (ftrace_graph_entry
- + ldr x2, [x1] // != ftrace_graph_entry_stub))
- + ldr x0, =ftrace_graph_entry_stub
- + cmp x0, x2
- + b.ne ftrace_graph_caller // ftrace_graph_caller();
- +
- + mcount_exit
- +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
- +ENDPROC(_mcount)
- +
- +#else /* CONFIG_DYNAMIC_FTRACE */
- +/*
- + * _mcount() is used to build the kernel with -pg option, but all the branch
- + * instructions to _mcount() are replaced to NOP initially at kernel start up,
- + * and later on, NOP to branch to ftrace_caller() when enabled or branch to
- + * NOP when disabled per-function base.
- + */
- +ENTRY(_mcount)
- + ret
- +ENDPROC(_mcount)
- +
- +/*
- + * void ftrace_caller(unsigned long return_address)
- + * @return_address: return address to instrumented function
- + *
- + * This function is a counterpart of _mcount() in 'static' ftrace, and
- + * makes calls to:
- + * - tracer function to probe instrumented function's entry,
- + * - ftrace_graph_caller to set up an exit hook
- + */
- +ENTRY(ftrace_caller)
- + mcount_enter
- +
- + mcount_get_pc0 x0 // function's pc
- + mcount_get_lr x1 // function's lr
- +
- + .global ftrace_call
- +ftrace_call: // tracer(pc, lr);
- + nop // This will be replaced with "bl xxx"
- + // where xxx can be any kind of tracer.
- +
- +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- + .global ftrace_graph_call
- +ftrace_graph_call: // ftrace_graph_caller();
- + nop // If enabled, this will be replaced
- + // "b ftrace_graph_caller"
- +#endif
- +
- + mcount_exit
- +ENDPROC(ftrace_caller)
- +#endif /* CONFIG_DYNAMIC_FTRACE */
- +
- +ENTRY(ftrace_stub)
- + ret
- +ENDPROC(ftrace_stub)
- +
- +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- +/*
- + * void ftrace_graph_caller(void)
- + *
- + * Called from _mcount() or ftrace_caller() when function_graph tracer is
- + * selected.
- + * This function w/ prepare_ftrace_return() fakes link register's value on
- + * the call stack in order to intercept instrumented function's return path
- + * and run return_to_handler() later on its exit.
- + */
- +ENTRY(ftrace_graph_caller)
- + mcount_get_lr_addr x0 // pointer to function's saved lr
- + mcount_get_pc x1 // function's pc
- + mcount_get_parent_fp x2 // parent's fp
- + bl prepare_ftrace_return // prepare_ftrace_return(&lr, pc, fp)
- +
- + mcount_exit
- +ENDPROC(ftrace_graph_caller)
- +
- +/*
- + * void return_to_handler(void)
- + *
- + * Run ftrace_return_to_handler() before going back to parent.
- + * @fp is checked against the value passed by ftrace_graph_caller()
- + * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
- + */
- +ENTRY(return_to_handler)
- + str x0, [sp, #-16]!
- + mov x0, x29 // parent's fp
- + bl ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
- + mov x30, x0 // restore the original return address
- + ldr x0, [sp], #16
- + ret
- +END(return_to_handler)
- +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/entry.S linux-3.14.35/arch/arm64/kernel/entry.S
- --- linux-3.14.35.orig/arch/arm64/kernel/entry.S 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/entry.S 2015-03-08 14:27:37.449684502 -0500
- @@ -630,8 +630,9 @@
- enable_irq
-
- get_thread_info tsk
- - ldr x16, [tsk, #TI_FLAGS] // check for syscall tracing
- - tbnz x16, #TIF_SYSCALL_TRACE, __sys_trace // are we tracing syscalls?
- + ldr x16, [tsk, #TI_FLAGS] // check for syscall hooks
- + tst x16, #_TIF_SYSCALL_WORK
- + b.ne __sys_trace
- adr lr, ret_fast_syscall // return address
- cmp scno, sc_nr // check upper syscall limit
- b.hs ni_sys
- @@ -647,9 +648,8 @@
- * switches, and waiting for our parent to respond.
- */
- __sys_trace:
- - mov x1, sp
- - mov w0, #0 // trace entry
- - bl syscall_trace
- + mov x0, sp
- + bl syscall_trace_enter
- adr lr, __sys_trace_return // return address
- uxtw scno, w0 // syscall number (possibly new)
- mov x1, sp // pointer to regs
- @@ -664,9 +664,8 @@
-
- __sys_trace_return:
- str x0, [sp] // save returned x0
- - mov x1, sp
- - mov w0, #1 // trace exit
- - bl syscall_trace
- + mov x0, sp
- + bl syscall_trace_exit
- b ret_to_user
-
- /*
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/ftrace.c linux-3.14.35/arch/arm64/kernel/ftrace.c
- --- linux-3.14.35.orig/arch/arm64/kernel/ftrace.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/ftrace.c 2015-03-08 14:27:37.449684502 -0500
- @@ -0,0 +1,177 @@
- +/*
- + * arch/arm64/kernel/ftrace.c
- + *
- + * Copyright (C) 2013 Linaro Limited
- + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <linux/ftrace.h>
- +#include <linux/swab.h>
- +#include <linux/uaccess.h>
- +
- +#include <asm/cacheflush.h>
- +#include <asm/ftrace.h>
- +#include <asm/insn.h>
- +
- +#ifdef CONFIG_DYNAMIC_FTRACE
- +/*
- + * Replace a single instruction, which may be a branch or NOP.
- + * If @validate == true, a replaced instruction is checked against 'old'.
- + */
- +static int ftrace_modify_code(unsigned long pc, u32 old, u32 new,
- + bool validate)
- +{
- + u32 replaced;
- +
- + /*
- + * Note:
- + * Due to modules and __init, code can disappear and change,
- + * we need to protect against faulting as well as code changing.
- + * We do this by aarch64_insn_*() which use the probe_kernel_*().
- + *
- + * No lock is held here because all the modifications are run
- + * through stop_machine().
- + */
- + if (validate) {
- + if (aarch64_insn_read((void *)pc, &replaced))
- + return -EFAULT;
- +
- + if (replaced != old)
- + return -EINVAL;
- + }
- + if (aarch64_insn_patch_text_nosync((void *)pc, new))
- + return -EPERM;
- +
- + return 0;
- +}
- +
- +/*
- + * Replace tracer function in ftrace_caller()
- + */
- +int ftrace_update_ftrace_func(ftrace_func_t func)
- +{
- + unsigned long pc;
- + u32 new;
- +
- + pc = (unsigned long)&ftrace_call;
- + new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
- +
- + return ftrace_modify_code(pc, 0, new, false);
- +}
- +
- +/*
- + * Turn on the call to ftrace_caller() in instrumented function
- + */
- +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
- +{
- + unsigned long pc = rec->ip;
- + u32 old, new;
- +
- + old = aarch64_insn_gen_nop();
- + new = aarch64_insn_gen_branch_imm(pc, addr, true);
- +
- + return ftrace_modify_code(pc, old, new, true);
- +}
- +
- +/*
- + * Turn off the call to ftrace_caller() in instrumented function
- + */
- +int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
- + unsigned long addr)
- +{
- + unsigned long pc = rec->ip;
- + u32 old, new;
- +
- + old = aarch64_insn_gen_branch_imm(pc, addr, true);
- + new = aarch64_insn_gen_nop();
- +
- + return ftrace_modify_code(pc, old, new, true);
- +}
- +
- +int __init ftrace_dyn_arch_init(void *data)
- +{
- + *(unsigned long *)data = 0;
- + return 0;
- +}
- +#endif /* CONFIG_DYNAMIC_FTRACE */
- +
- +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- +/*
- + * function_graph tracer expects ftrace_return_to_handler() to be called
- + * on the way back to parent. For this purpose, this function is called
- + * in _mcount() or ftrace_caller() to replace return address (*parent) on
- + * the call stack to return_to_handler.
- + *
- + * Note that @frame_pointer is used only for sanity check later.
- + */
- +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
- + unsigned long frame_pointer)
- +{
- + unsigned long return_hooker = (unsigned long)&return_to_handler;
- + unsigned long old;
- + struct ftrace_graph_ent trace;
- + int err;
- +
- + if (unlikely(atomic_read(¤t->tracing_graph_pause)))
- + return;
- +
- + /*
- + * Note:
- + * No protection against faulting at *parent, which may be seen
- + * on other archs. It's unlikely on AArch64.
- + */
- + old = *parent;
- + *parent = return_hooker;
- +
- + trace.func = self_addr;
- + trace.depth = current->curr_ret_stack + 1;
- +
- + /* Only trace if the calling function expects to */
- + if (!ftrace_graph_entry(&trace)) {
- + *parent = old;
- + return;
- + }
- +
- + err = ftrace_push_return_trace(old, self_addr, &trace.depth,
- + frame_pointer);
- + if (err == -EBUSY) {
- + *parent = old;
- + return;
- + }
- +}
- +
- +#ifdef CONFIG_DYNAMIC_FTRACE
- +/*
- + * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
- + * depending on @enable.
- + */
- +static int ftrace_modify_graph_caller(bool enable)
- +{
- + unsigned long pc = (unsigned long)&ftrace_graph_call;
- + u32 branch, nop;
- +
- + branch = aarch64_insn_gen_branch_imm(pc,
- + (unsigned long)ftrace_graph_caller, false);
- + nop = aarch64_insn_gen_nop();
- +
- + if (enable)
- + return ftrace_modify_code(pc, nop, branch, true);
- + else
- + return ftrace_modify_code(pc, branch, nop, true);
- +}
- +
- +int ftrace_enable_ftrace_graph_caller(void)
- +{
- + return ftrace_modify_graph_caller(true);
- +}
- +
- +int ftrace_disable_ftrace_graph_caller(void)
- +{
- + return ftrace_modify_graph_caller(false);
- +}
- +#endif /* CONFIG_DYNAMIC_FTRACE */
- +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/head.S linux-3.14.35/arch/arm64/kernel/head.S
- --- linux-3.14.35.orig/arch/arm64/kernel/head.S 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/head.S 2015-03-08 14:27:37.449684502 -0500
- @@ -26,6 +26,7 @@
- #include <asm/assembler.h>
- #include <asm/ptrace.h>
- #include <asm/asm-offsets.h>
- +#include <asm/cache.h>
- #include <asm/cputype.h>
- #include <asm/memory.h>
- #include <asm/thread_info.h>
- @@ -34,29 +35,17 @@
- #include <asm/page.h>
- #include <asm/virt.h>
-
- -/*
- - * swapper_pg_dir is the virtual address of the initial page table. We place
- - * the page tables 3 * PAGE_SIZE below KERNEL_RAM_VADDR. The idmap_pg_dir has
- - * 2 pages and is placed below swapper_pg_dir.
- - */
- #define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET)
-
- #if (KERNEL_RAM_VADDR & 0xfffff) != 0x80000
- #error KERNEL_RAM_VADDR must start at 0xXXX80000
- #endif
-
- -#define SWAPPER_DIR_SIZE (3 * PAGE_SIZE)
- -#define IDMAP_DIR_SIZE (2 * PAGE_SIZE)
- -
- - .globl swapper_pg_dir
- - .equ swapper_pg_dir, KERNEL_RAM_VADDR - SWAPPER_DIR_SIZE
- -
- - .globl idmap_pg_dir
- - .equ idmap_pg_dir, swapper_pg_dir - IDMAP_DIR_SIZE
- -
- - .macro pgtbl, ttb0, ttb1, phys
- - add \ttb1, \phys, #TEXT_OFFSET - SWAPPER_DIR_SIZE
- - sub \ttb0, \ttb1, #IDMAP_DIR_SIZE
- + .macro pgtbl, ttb0, ttb1, virt_to_phys
- + ldr \ttb1, =swapper_pg_dir
- + ldr \ttb0, =idmap_pg_dir
- + add \ttb1, \ttb1, \virt_to_phys
- + add \ttb0, \ttb0, \virt_to_phys
- .endm
-
- #ifdef CONFIG_ARM64_64K_PAGES
- @@ -229,7 +218,11 @@
- cmp w20, #BOOT_CPU_MODE_EL2
- b.ne 1f
- add x1, x1, #4
- -1: str w20, [x1] // This CPU has booted in EL1
- +1: dc cvac, x1 // Clean potentially dirty cache line
- + dsb sy
- + str w20, [x1] // This CPU has booted in EL1
- + dc civac, x1 // Clean&invalidate potentially stale cache line
- + dsb sy
- ret
- ENDPROC(set_cpu_boot_mode_flag)
-
- @@ -240,8 +233,9 @@
- * This is not in .bss, because we set it sufficiently early that the boot-time
- * zeroing of .bss would clobber it.
- */
- - .pushsection .data
- + .pushsection .data..cacheline_aligned
- ENTRY(__boot_cpu_mode)
- + .align L1_CACHE_SHIFT
- .long BOOT_CPU_MODE_EL2
- .long 0
- .popsection
- @@ -298,7 +292,7 @@
- mov x23, x0 // x23=current cpu_table
- cbz x23, __error_p // invalid processor (x23=0)?
-
- - pgtbl x25, x26, x24 // x25=TTBR0, x26=TTBR1
- + pgtbl x25, x26, x28 // x25=TTBR0, x26=TTBR1
- ldr x12, [x23, #CPU_INFO_SETUP]
- add x12, x12, x28 // __virt_to_phys
- blr x12 // initialise processor
- @@ -340,8 +334,13 @@
- * x27 = *virtual* address to jump to upon completion
- *
- * other registers depend on the function called upon completion
- + *
- + * We align the entire function to the smallest power of two larger than it to
- + * ensure it fits within a single block map entry. Otherwise were PHYS_OFFSET
- + * close to the end of a 512MB or 1GB block we might require an additional
- + * table to map the entire function.
- */
- - .align 6
- + .align 4
- __turn_mmu_on:
- msr sctlr_el1, x0
- isb
- @@ -384,26 +383,18 @@
- * Preserves: tbl, flags
- * Corrupts: phys, start, end, pstate
- */
- - .macro create_block_map, tbl, flags, phys, start, end, idmap=0
- + .macro create_block_map, tbl, flags, phys, start, end
- lsr \phys, \phys, #BLOCK_SHIFT
- - .if \idmap
- - and \start, \phys, #PTRS_PER_PTE - 1 // table index
- - .else
- lsr \start, \start, #BLOCK_SHIFT
- and \start, \start, #PTRS_PER_PTE - 1 // table index
- - .endif
- orr \phys, \flags, \phys, lsl #BLOCK_SHIFT // table entry
- - .ifnc \start,\end
- lsr \end, \end, #BLOCK_SHIFT
- and \end, \end, #PTRS_PER_PTE - 1 // table end index
- - .endif
- 9999: str \phys, [\tbl, \start, lsl #3] // store the entry
- - .ifnc \start,\end
- add \start, \start, #1 // next entry
- add \phys, \phys, #BLOCK_SIZE // next block
- cmp \start, \end
- b.ls 9999b
- - .endif
- .endm
-
- /*
- @@ -415,7 +406,16 @@
- * - UART mapping if CONFIG_EARLY_PRINTK is enabled (TTBR1)
- */
- __create_page_tables:
- - pgtbl x25, x26, x24 // idmap_pg_dir and swapper_pg_dir addresses
- + pgtbl x25, x26, x28 // idmap_pg_dir and swapper_pg_dir addresses
- + mov x27, lr
- +
- + /*
- + * Invalidate the idmap and swapper page tables to avoid potential
- + * dirty cache lines being evicted.
- + */
- + mov x0, x25
- + add x1, x26, #SWAPPER_DIR_SIZE
- + bl __inval_cache_range
-
- /*
- * Clear the idmap and swapper page tables.
- @@ -435,9 +435,13 @@
- * Create the identity mapping.
- */
- add x0, x25, #PAGE_SIZE // section table address
- - adr x3, __turn_mmu_on // virtual/physical address
- + ldr x3, =KERNEL_START
- + add x3, x3, x28 // __pa(KERNEL_START)
- create_pgd_entry x25, x0, x3, x5, x6
- - create_block_map x0, x7, x3, x5, x5, idmap=1
- + ldr x6, =KERNEL_END
- + mov x5, x3 // __pa(KERNEL_START)
- + add x6, x6, x28 // __pa(KERNEL_END)
- + create_block_map x0, x7, x3, x5, x6
-
- /*
- * Map the kernel image (starting with PHYS_OFFSET).
- @@ -445,7 +449,7 @@
- add x0, x26, #PAGE_SIZE // section table address
- mov x5, #PAGE_OFFSET
- create_pgd_entry x26, x0, x5, x3, x6
- - ldr x6, =KERNEL_END - 1
- + ldr x6, =KERNEL_END
- mov x3, x24 // phys offset
- create_block_map x0, x7, x3, x5, x6
-
- @@ -474,6 +478,17 @@
- add x0, x26, #2 * PAGE_SIZE // section table address
- create_pgd_entry x26, x0, x5, x6, x7
- #endif
- +
- + /*
- + * Since the page tables have been populated with non-cacheable
- + * accesses (MMU disabled), invalidate the idmap and swapper page
- + * tables again to remove any speculatively loaded cache lines.
- + */
- + mov x0, x25
- + add x1, x26, #SWAPPER_DIR_SIZE
- + bl __inval_cache_range
- +
- + mov lr, x27
- ret
- ENDPROC(__create_page_tables)
- .ltorg
- @@ -483,7 +498,7 @@
- __switch_data:
- .quad __mmap_switched
- .quad __bss_start // x6
- - .quad _end // x7
- + .quad __bss_stop // x7
- .quad processor_id // x4
- .quad __fdt_pointer // x5
- .quad memstart_addr // x6
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/hw_breakpoint.c linux-3.14.35/arch/arm64/kernel/hw_breakpoint.c
- --- linux-3.14.35.orig/arch/arm64/kernel/hw_breakpoint.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/hw_breakpoint.c 2015-03-08 14:27:37.449684502 -0500
- @@ -20,6 +20,7 @@
-
- #define pr_fmt(fmt) "hw-breakpoint: " fmt
-
- +#include <linux/compat.h>
- #include <linux/cpu_pm.h>
- #include <linux/errno.h>
- #include <linux/hw_breakpoint.h>
- @@ -27,7 +28,6 @@
- #include <linux/ptrace.h>
- #include <linux/smp.h>
-
- -#include <asm/compat.h>
- #include <asm/current.h>
- #include <asm/debug-monitors.h>
- #include <asm/hw_breakpoint.h>
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/kgdb.c linux-3.14.35/arch/arm64/kernel/kgdb.c
- --- linux-3.14.35.orig/arch/arm64/kernel/kgdb.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/kgdb.c 2015-03-08 14:27:37.449684502 -0500
- @@ -0,0 +1,336 @@
- +/*
- + * AArch64 KGDB support
- + *
- + * Based on arch/arm/kernel/kgdb.c
- + *
- + * Copyright (C) 2013 Cavium Inc.
- + * Author: Vijaya Kumar K <vijaya.kumar@caviumnetworks.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program. If not, see <http://www.gnu.org/licenses/>.
- + */
- +
- +#include <linux/irq.h>
- +#include <linux/kdebug.h>
- +#include <linux/kgdb.h>
- +#include <asm/traps.h>
- +
- +struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
- + { "x0", 8, offsetof(struct pt_regs, regs[0])},
- + { "x1", 8, offsetof(struct pt_regs, regs[1])},
- + { "x2", 8, offsetof(struct pt_regs, regs[2])},
- + { "x3", 8, offsetof(struct pt_regs, regs[3])},
- + { "x4", 8, offsetof(struct pt_regs, regs[4])},
- + { "x5", 8, offsetof(struct pt_regs, regs[5])},
- + { "x6", 8, offsetof(struct pt_regs, regs[6])},
- + { "x7", 8, offsetof(struct pt_regs, regs[7])},
- + { "x8", 8, offsetof(struct pt_regs, regs[8])},
- + { "x9", 8, offsetof(struct pt_regs, regs[9])},
- + { "x10", 8, offsetof(struct pt_regs, regs[10])},
- + { "x11", 8, offsetof(struct pt_regs, regs[11])},
- + { "x12", 8, offsetof(struct pt_regs, regs[12])},
- + { "x13", 8, offsetof(struct pt_regs, regs[13])},
- + { "x14", 8, offsetof(struct pt_regs, regs[14])},
- + { "x15", 8, offsetof(struct pt_regs, regs[15])},
- + { "x16", 8, offsetof(struct pt_regs, regs[16])},
- + { "x17", 8, offsetof(struct pt_regs, regs[17])},
- + { "x18", 8, offsetof(struct pt_regs, regs[18])},
- + { "x19", 8, offsetof(struct pt_regs, regs[19])},
- + { "x20", 8, offsetof(struct pt_regs, regs[20])},
- + { "x21", 8, offsetof(struct pt_regs, regs[21])},
- + { "x22", 8, offsetof(struct pt_regs, regs[22])},
- + { "x23", 8, offsetof(struct pt_regs, regs[23])},
- + { "x24", 8, offsetof(struct pt_regs, regs[24])},
- + { "x25", 8, offsetof(struct pt_regs, regs[25])},
- + { "x26", 8, offsetof(struct pt_regs, regs[26])},
- + { "x27", 8, offsetof(struct pt_regs, regs[27])},
- + { "x28", 8, offsetof(struct pt_regs, regs[28])},
- + { "x29", 8, offsetof(struct pt_regs, regs[29])},
- + { "x30", 8, offsetof(struct pt_regs, regs[30])},
- + { "sp", 8, offsetof(struct pt_regs, sp)},
- + { "pc", 8, offsetof(struct pt_regs, pc)},
- + { "pstate", 8, offsetof(struct pt_regs, pstate)},
- + { "v0", 16, -1 },
- + { "v1", 16, -1 },
- + { "v2", 16, -1 },
- + { "v3", 16, -1 },
- + { "v4", 16, -1 },
- + { "v5", 16, -1 },
- + { "v6", 16, -1 },
- + { "v7", 16, -1 },
- + { "v8", 16, -1 },
- + { "v9", 16, -1 },
- + { "v10", 16, -1 },
- + { "v11", 16, -1 },
- + { "v12", 16, -1 },
- + { "v13", 16, -1 },
- + { "v14", 16, -1 },
- + { "v15", 16, -1 },
- + { "v16", 16, -1 },
- + { "v17", 16, -1 },
- + { "v18", 16, -1 },
- + { "v19", 16, -1 },
- + { "v20", 16, -1 },
- + { "v21", 16, -1 },
- + { "v22", 16, -1 },
- + { "v23", 16, -1 },
- + { "v24", 16, -1 },
- + { "v25", 16, -1 },
- + { "v26", 16, -1 },
- + { "v27", 16, -1 },
- + { "v28", 16, -1 },
- + { "v29", 16, -1 },
- + { "v30", 16, -1 },
- + { "v31", 16, -1 },
- + { "fpsr", 4, -1 },
- + { "fpcr", 4, -1 },
- +};
- +
- +char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
- +{
- + if (regno >= DBG_MAX_REG_NUM || regno < 0)
- + return NULL;
- +
- + if (dbg_reg_def[regno].offset != -1)
- + memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
- + dbg_reg_def[regno].size);
- + else
- + memset(mem, 0, dbg_reg_def[regno].size);
- + return dbg_reg_def[regno].name;
- +}
- +
- +int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
- +{
- + if (regno >= DBG_MAX_REG_NUM || regno < 0)
- + return -EINVAL;
- +
- + if (dbg_reg_def[regno].offset != -1)
- + memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
- + dbg_reg_def[regno].size);
- + return 0;
- +}
- +
- +void
- +sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
- +{
- + struct pt_regs *thread_regs;
- +
- + /* Initialize to zero */
- + memset((char *)gdb_regs, 0, NUMREGBYTES);
- + thread_regs = task_pt_regs(task);
- + memcpy((void *)gdb_regs, (void *)thread_regs->regs, GP_REG_BYTES);
- +}
- +
- +void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
- +{
- + regs->pc = pc;
- +}
- +
- +static int compiled_break;
- +
- +static void kgdb_arch_update_addr(struct pt_regs *regs,
- + char *remcom_in_buffer)
- +{
- + unsigned long addr;
- + char *ptr;
- +
- + ptr = &remcom_in_buffer[1];
- + if (kgdb_hex2long(&ptr, &addr))
- + kgdb_arch_set_pc(regs, addr);
- + else if (compiled_break == 1)
- + kgdb_arch_set_pc(regs, regs->pc + 4);
- +
- + compiled_break = 0;
- +}
- +
- +int kgdb_arch_handle_exception(int exception_vector, int signo,
- + int err_code, char *remcom_in_buffer,
- + char *remcom_out_buffer,
- + struct pt_regs *linux_regs)
- +{
- + int err;
- +
- + switch (remcom_in_buffer[0]) {
- + case 'D':
- + case 'k':
- + /*
- + * Packet D (Detach), k (kill). No special handling
- + * is required here. Handle same as c packet.
- + */
- + case 'c':
- + /*
- + * Packet c (Continue) to continue executing.
- + * Set pc to required address.
- + * Try to read optional parameter and set pc.
- + * If this was a compiled breakpoint, we need to move
- + * to the next instruction else we will just breakpoint
- + * over and over again.
- + */
- + kgdb_arch_update_addr(linux_regs, remcom_in_buffer);
- + atomic_set(&kgdb_cpu_doing_single_step, -1);
- + kgdb_single_step = 0;
- +
- + /*
- + * Received continue command, disable single step
- + */
- + if (kernel_active_single_step())
- + kernel_disable_single_step();
- +
- + err = 0;
- + break;
- + case 's':
- + /*
- + * Update step address value with address passed
- + * with step packet.
- + * On debug exception return PC is copied to ELR
- + * So just update PC.
- + * If no step address is passed, resume from the address
- + * pointed by PC. Do not update PC
- + */
- + kgdb_arch_update_addr(linux_regs, remcom_in_buffer);
- + atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id());
- + kgdb_single_step = 1;
- +
- + /*
- + * Enable single step handling
- + */
- + if (!kernel_active_single_step())
- + kernel_enable_single_step(linux_regs);
- + err = 0;
- + break;
- + default:
- + err = -1;
- + }
- + return err;
- +}
- +
- +static int kgdb_brk_fn(struct pt_regs *regs, unsigned int esr)
- +{
- + kgdb_handle_exception(1, SIGTRAP, 0, regs);
- + return 0;
- +}
- +
- +static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int esr)
- +{
- + compiled_break = 1;
- + kgdb_handle_exception(1, SIGTRAP, 0, regs);
- +
- + return 0;
- +}
- +
- +static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr)
- +{
- + kgdb_handle_exception(1, SIGTRAP, 0, regs);
- + return 0;
- +}
- +
- +static struct break_hook kgdb_brkpt_hook = {
- + .esr_mask = 0xffffffff,
- + .esr_val = DBG_ESR_VAL_BRK(KGDB_DYN_DGB_BRK_IMM),
- + .fn = kgdb_brk_fn
- +};
- +
- +static struct break_hook kgdb_compiled_brkpt_hook = {
- + .esr_mask = 0xffffffff,
- + .esr_val = DBG_ESR_VAL_BRK(KDBG_COMPILED_DBG_BRK_IMM),
- + .fn = kgdb_compiled_brk_fn
- +};
- +
- +static struct step_hook kgdb_step_hook = {
- + .fn = kgdb_step_brk_fn
- +};
- +
- +static void kgdb_call_nmi_hook(void *ignored)
- +{
- + kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());
- +}
- +
- +void kgdb_roundup_cpus(unsigned long flags)
- +{
- + local_irq_enable();
- + smp_call_function(kgdb_call_nmi_hook, NULL, 0);
- + local_irq_disable();
- +}
- +
- +static int __kgdb_notify(struct die_args *args, unsigned long cmd)
- +{
- + struct pt_regs *regs = args->regs;
- +
- + if (kgdb_handle_exception(1, args->signr, cmd, regs))
- + return NOTIFY_DONE;
- + return NOTIFY_STOP;
- +}
- +
- +static int
- +kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
- +{
- + unsigned long flags;
- + int ret;
- +
- + local_irq_save(flags);
- + ret = __kgdb_notify(ptr, cmd);
- + local_irq_restore(flags);
- +
- + return ret;
- +}
- +
- +static struct notifier_block kgdb_notifier = {
- + .notifier_call = kgdb_notify,
- + /*
- + * Want to be lowest priority
- + */
- + .priority = -INT_MAX,
- +};
- +
- +/*
- + * kgdb_arch_init - Perform any architecture specific initalization.
- + * This function will handle the initalization of any architecture
- + * specific callbacks.
- + */
- +int kgdb_arch_init(void)
- +{
- + int ret = register_die_notifier(&kgdb_notifier);
- +
- + if (ret != 0)
- + return ret;
- +
- + register_break_hook(&kgdb_brkpt_hook);
- + register_break_hook(&kgdb_compiled_brkpt_hook);
- + register_step_hook(&kgdb_step_hook);
- + return 0;
- +}
- +
- +/*
- + * kgdb_arch_exit - Perform any architecture specific uninitalization.
- + * This function will handle the uninitalization of any architecture
- + * specific callbacks, for dynamic registration and unregistration.
- + */
- +void kgdb_arch_exit(void)
- +{
- + unregister_break_hook(&kgdb_brkpt_hook);
- + unregister_break_hook(&kgdb_compiled_brkpt_hook);
- + unregister_step_hook(&kgdb_step_hook);
- + unregister_die_notifier(&kgdb_notifier);
- +}
- +
- +/*
- + * ARM instructions are always in LE.
- + * Break instruction is encoded in LE format
- + */
- +struct kgdb_arch arch_kgdb_ops = {
- + .gdb_bpt_instr = {
- + KGDB_DYN_BRK_INS_BYTE0,
- + KGDB_DYN_BRK_INS_BYTE1,
- + KGDB_DYN_BRK_INS_BYTE2,
- + KGDB_DYN_BRK_INS_BYTE3,
- + }
- +};
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/Makefile linux-3.14.35/arch/arm64/kernel/Makefile
- --- linux-3.14.35.orig/arch/arm64/kernel/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/Makefile 2015-03-08 14:27:37.449684502 -0500
- @@ -5,21 +5,29 @@
- CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET)
- AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
-
- +CFLAGS_REMOVE_ftrace.o = -pg
- +CFLAGS_REMOVE_insn.o = -pg
- +CFLAGS_REMOVE_return_address.o = -pg
- +
- # Object file lists.
- arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \
- entry-fpsimd.o process.o ptrace.o setup.o signal.o \
- sys.o stacktrace.o time.o traps.o io.o vdso.o \
- - hyp-stub.o psci.o cpu_ops.o insn.o
- + hyp-stub.o psci.o cpu_ops.o insn.o return_address.o
-
- arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \
- sys_compat.o
- +arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
- arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
- +arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o topology.o
- arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o
- +arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o
- arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
- -arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o
- +arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
- arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
- arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o
- arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o
- +arm64-obj-$(CONFIG_KGDB) += kgdb.o
-
- obj-y += $(arm64-obj-y) vdso/
- obj-m += $(arm64-obj-m)
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/perf_event.c linux-3.14.35/arch/arm64/kernel/perf_event.c
- --- linux-3.14.35.orig/arch/arm64/kernel/perf_event.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/perf_event.c 2015-03-08 14:27:37.449684502 -0500
- @@ -1348,8 +1348,8 @@
- * Callchain handling code.
- */
- struct frame_tail {
- - struct frame_tail __user *fp;
- - unsigned long lr;
- + struct frame_tail __user *fp;
- + unsigned long lr;
- } __attribute__((packed));
-
- /*
- @@ -1386,22 +1386,84 @@
- return buftail.fp;
- }
-
- +#ifdef CONFIG_COMPAT
- +/*
- + * The registers we're interested in are at the end of the variable
- + * length saved register structure. The fp points at the end of this
- + * structure so the address of this struct is:
- + * (struct compat_frame_tail *)(xxx->fp)-1
- + *
- + * This code has been adapted from the ARM OProfile support.
- + */
- +struct compat_frame_tail {
- + compat_uptr_t fp; /* a (struct compat_frame_tail *) in compat mode */
- + u32 sp;
- + u32 lr;
- +} __attribute__((packed));
- +
- +static struct compat_frame_tail __user *
- +compat_user_backtrace(struct compat_frame_tail __user *tail,
- + struct perf_callchain_entry *entry)
- +{
- + struct compat_frame_tail buftail;
- + unsigned long err;
- +
- + /* Also check accessibility of one struct frame_tail beyond */
- + if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
- + return NULL;
- +
- + pagefault_disable();
- + err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail));
- + pagefault_enable();
- +
- + if (err)
- + return NULL;
- +
- + perf_callchain_store(entry, buftail.lr);
- +
- + /*
- + * Frame pointers should strictly progress back up the stack
- + * (towards higher addresses).
- + */
- + if (tail + 1 >= (struct compat_frame_tail __user *)
- + compat_ptr(buftail.fp))
- + return NULL;
- +
- + return (struct compat_frame_tail __user *)compat_ptr(buftail.fp) - 1;
- +}
- +#endif /* CONFIG_COMPAT */
- +
- void perf_callchain_user(struct perf_callchain_entry *entry,
- struct pt_regs *regs)
- {
- - struct frame_tail __user *tail;
- -
- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
- /* We don't support guest os callchain now */
- return;
- }
-
- perf_callchain_store(entry, regs->pc);
- - tail = (struct frame_tail __user *)regs->regs[29];
-
- - while (entry->nr < PERF_MAX_STACK_DEPTH &&
- - tail && !((unsigned long)tail & 0xf))
- - tail = user_backtrace(tail, entry);
- + if (!compat_user_mode(regs)) {
- + /* AARCH64 mode */
- + struct frame_tail __user *tail;
- +
- + tail = (struct frame_tail __user *)regs->regs[29];
- +
- + while (entry->nr < PERF_MAX_STACK_DEPTH &&
- + tail && !((unsigned long)tail & 0xf))
- + tail = user_backtrace(tail, entry);
- + } else {
- +#ifdef CONFIG_COMPAT
- + /* AARCH32 compat mode */
- + struct compat_frame_tail __user *tail;
- +
- + tail = (struct compat_frame_tail __user *)regs->compat_fp - 1;
- +
- + while ((entry->nr < PERF_MAX_STACK_DEPTH) &&
- + tail && !((unsigned long)tail & 0x3))
- + tail = compat_user_backtrace(tail, entry);
- +#endif
- + }
- }
-
- /*
- @@ -1429,6 +1491,7 @@
- frame.fp = regs->regs[29];
- frame.sp = regs->sp;
- frame.pc = regs->pc;
- +
- walk_stackframe(&frame, callchain_trace, entry);
- }
-
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/perf_regs.c linux-3.14.35/arch/arm64/kernel/perf_regs.c
- --- linux-3.14.35.orig/arch/arm64/kernel/perf_regs.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/perf_regs.c 2015-03-08 14:27:37.449684502 -0500
- @@ -0,0 +1,46 @@
- +#include <linux/errno.h>
- +#include <linux/kernel.h>
- +#include <linux/perf_event.h>
- +#include <linux/bug.h>
- +
- +#include <asm/compat.h>
- +#include <asm/perf_regs.h>
- +#include <asm/ptrace.h>
- +
- +u64 perf_reg_value(struct pt_regs *regs, int idx)
- +{
- + if (WARN_ON_ONCE((u32)idx >= PERF_REG_ARM64_MAX))
- + return 0;
- +
- + /*
- + * Compat (i.e. 32 bit) mode:
- + * - PC has been set in the pt_regs struct in kernel_entry,
- + * - Handle SP and LR here.
- + */
- + if (compat_user_mode(regs)) {
- + if ((u32)idx == PERF_REG_ARM64_SP)
- + return regs->compat_sp;
- + if ((u32)idx == PERF_REG_ARM64_LR)
- + return regs->compat_lr;
- + }
- +
- + return regs->regs[idx];
- +}
- +
- +#define REG_RESERVED (~((1ULL << PERF_REG_ARM64_MAX) - 1))
- +
- +int perf_reg_validate(u64 mask)
- +{
- + if (!mask || mask & REG_RESERVED)
- + return -EINVAL;
- +
- + return 0;
- +}
- +
- +u64 perf_reg_abi(struct task_struct *task)
- +{
- + if (is_compat_thread(task_thread_info(task)))
- + return PERF_SAMPLE_REGS_ABI_32;
- + else
- + return PERF_SAMPLE_REGS_ABI_64;
- +}
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/process.c linux-3.14.35/arch/arm64/kernel/process.c
- --- linux-3.14.35.orig/arch/arm64/kernel/process.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/process.c 2015-03-08 14:27:37.449684502 -0500
- @@ -20,6 +20,7 @@
-
- #include <stdarg.h>
-
- +#include <linux/compat.h>
- #include <linux/export.h>
- #include <linux/sched.h>
- #include <linux/kernel.h>
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/ptrace.c linux-3.14.35/arch/arm64/kernel/ptrace.c
- --- linux-3.14.35.orig/arch/arm64/kernel/ptrace.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/ptrace.c 2015-03-08 14:27:37.449684502 -0500
- @@ -19,6 +19,7 @@
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
- +#include <linux/compat.h>
- #include <linux/kernel.h>
- #include <linux/sched.h>
- #include <linux/mm.h>
- @@ -41,6 +42,9 @@
- #include <asm/traps.h>
- #include <asm/system_misc.h>
-
- +#define CREATE_TRACE_POINTS
- +#include <trace/events/syscalls.h>
- +
- /*
- * TODO: does not yet catch signals sent when the child dies.
- * in exit.c or in signal.c.
- @@ -1073,35 +1077,49 @@
- return ptrace_request(child, request, addr, data);
- }
-
- -asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
- +enum ptrace_syscall_dir {
- + PTRACE_SYSCALL_ENTER = 0,
- + PTRACE_SYSCALL_EXIT,
- +};
- +
- +static void tracehook_report_syscall(struct pt_regs *regs,
- + enum ptrace_syscall_dir dir)
- {
- + int regno;
- unsigned long saved_reg;
-
- - if (!test_thread_flag(TIF_SYSCALL_TRACE))
- - return regs->syscallno;
- -
- - if (is_compat_task()) {
- - /* AArch32 uses ip (r12) for scratch */
- - saved_reg = regs->regs[12];
- - regs->regs[12] = dir;
- - } else {
- - /*
- - * Save X7. X7 is used to denote syscall entry/exit:
- - * X7 = 0 -> entry, = 1 -> exit
- - */
- - saved_reg = regs->regs[7];
- - regs->regs[7] = dir;
- - }
- + /*
- + * A scratch register (ip(r12) on AArch32, x7 on AArch64) is
- + * used to denote syscall entry/exit:
- + */
- + regno = (is_compat_task() ? 12 : 7);
- + saved_reg = regs->regs[regno];
- + regs->regs[regno] = dir;
-
- - if (dir)
- + if (dir == PTRACE_SYSCALL_EXIT)
- tracehook_report_syscall_exit(regs, 0);
- else if (tracehook_report_syscall_entry(regs))
- regs->syscallno = ~0UL;
-
- - if (is_compat_task())
- - regs->regs[12] = saved_reg;
- - else
- - regs->regs[7] = saved_reg;
- + regs->regs[regno] = saved_reg;
- +}
- +
- +asmlinkage int syscall_trace_enter(struct pt_regs *regs)
- +{
- + if (test_thread_flag(TIF_SYSCALL_TRACE))
- + tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
- +
- + if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
- + trace_sys_enter(regs, regs->syscallno);
-
- return regs->syscallno;
- }
- +
- +asmlinkage void syscall_trace_exit(struct pt_regs *regs)
- +{
- + if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
- + trace_sys_exit(regs, regs_return_value(regs));
- +
- + if (test_thread_flag(TIF_SYSCALL_TRACE))
- + tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
- +}
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/return_address.c linux-3.14.35/arch/arm64/kernel/return_address.c
- --- linux-3.14.35.orig/arch/arm64/kernel/return_address.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/return_address.c 2015-03-08 14:27:37.449684502 -0500
- @@ -0,0 +1,55 @@
- +/*
- + * arch/arm64/kernel/return_address.c
- + *
- + * Copyright (C) 2013 Linaro Limited
- + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <linux/export.h>
- +#include <linux/ftrace.h>
- +
- +#include <asm/stacktrace.h>
- +
- +struct return_address_data {
- + unsigned int level;
- + void *addr;
- +};
- +
- +static int save_return_addr(struct stackframe *frame, void *d)
- +{
- + struct return_address_data *data = d;
- +
- + if (!data->level) {
- + data->addr = (void *)frame->pc;
- + return 1;
- + } else {
- + --data->level;
- + return 0;
- + }
- +}
- +
- +void *return_address(unsigned int level)
- +{
- + struct return_address_data data;
- + struct stackframe frame;
- + register unsigned long current_sp asm ("sp");
- +
- + data.level = level + 2;
- + data.addr = NULL;
- +
- + frame.fp = (unsigned long)__builtin_frame_address(0);
- + frame.sp = current_sp;
- + frame.pc = (unsigned long)return_address; /* dummy */
- +
- + walk_stackframe(&frame, save_return_addr, &data);
- +
- + if (!data.level)
- + return data.addr;
- + else
- + return NULL;
- +}
- +EXPORT_SYMBOL_GPL(return_address);
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/setup.c linux-3.14.35/arch/arm64/kernel/setup.c
- --- linux-3.14.35.orig/arch/arm64/kernel/setup.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/setup.c 2015-03-08 14:27:37.449684502 -0500
- @@ -71,6 +71,7 @@
- COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV|\
- COMPAT_HWCAP_LPAE)
- unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT;
- +unsigned int compat_elf_hwcap2 __read_mostly;
- #endif
-
- static const char *cpu_name;
- @@ -258,6 +259,38 @@
- block = (features >> 16) & 0xf;
- if (block && !(block & 0x8))
- elf_hwcap |= HWCAP_CRC32;
- +
- +#ifdef CONFIG_COMPAT
- + /*
- + * ID_ISAR5_EL1 carries similar information as above, but pertaining to
- + * the Aarch32 32-bit execution state.
- + */
- + features = read_cpuid(ID_ISAR5_EL1);
- + block = (features >> 4) & 0xf;
- + if (!(block & 0x8)) {
- + switch (block) {
- + default:
- + case 2:
- + compat_elf_hwcap2 |= COMPAT_HWCAP2_PMULL;
- + case 1:
- + compat_elf_hwcap2 |= COMPAT_HWCAP2_AES;
- + case 0:
- + break;
- + }
- + }
- +
- + block = (features >> 8) & 0xf;
- + if (block && !(block & 0x8))
- + compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA1;
- +
- + block = (features >> 12) & 0xf;
- + if (block && !(block & 0x8))
- + compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA2;
- +
- + block = (features >> 16) & 0xf;
- + if (block && !(block & 0x8))
- + compat_elf_hwcap2 |= COMPAT_HWCAP2_CRC32;
- +#endif
- }
-
- static void __init setup_machine_fdt(phys_addr_t dt_phys)
- @@ -374,7 +407,7 @@
- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
- return 0;
- }
- -arch_initcall(arm64_device_init);
- +arch_initcall_sync(arm64_device_init);
-
- static int __init topology_init(void)
- {
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/signal.c linux-3.14.35/arch/arm64/kernel/signal.c
- --- linux-3.14.35.orig/arch/arm64/kernel/signal.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/signal.c 2015-03-08 14:27:37.449684502 -0500
- @@ -17,6 +17,7 @@
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
- +#include <linux/compat.h>
- #include <linux/errno.h>
- #include <linux/signal.h>
- #include <linux/personality.h>
- @@ -25,7 +26,6 @@
- #include <linux/tracehook.h>
- #include <linux/ratelimit.h>
-
- -#include <asm/compat.h>
- #include <asm/debug-monitors.h>
- #include <asm/elf.h>
- #include <asm/cacheflush.h>
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/smp.c linux-3.14.35/arch/arm64/kernel/smp.c
- --- linux-3.14.35.orig/arch/arm64/kernel/smp.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/smp.c 2015-03-08 14:27:37.449684502 -0500
- @@ -114,6 +114,11 @@
- return ret;
- }
-
- +static void smp_store_cpu_info(unsigned int cpuid)
- +{
- + store_cpu_topology(cpuid);
- +}
- +
- /*
- * This is the secondary CPU boot entry. We're using this CPUs
- * idle thread stack, but a set of temporary page tables.
- @@ -157,6 +162,8 @@
- */
- notify_cpu_starting(cpu);
-
- + smp_store_cpu_info(cpu);
- +
- /*
- * OK, now it's safe to let the boot CPU continue. Wait for
- * the CPU migration code to notice that the CPU is online
- @@ -395,6 +402,10 @@
- int err;
- unsigned int cpu, ncores = num_possible_cpus();
-
- + init_cpu_topology();
- +
- + smp_store_cpu_info(smp_processor_id());
- +
- /*
- * are we trying to boot more cores than exist?
- */
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/stacktrace.c linux-3.14.35/arch/arm64/kernel/stacktrace.c
- --- linux-3.14.35.orig/arch/arm64/kernel/stacktrace.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/stacktrace.c 2015-03-08 14:27:37.453684502 -0500
- @@ -35,7 +35,7 @@
- * ldp x29, x30, [sp]
- * add sp, sp, #0x10
- */
- -int unwind_frame(struct stackframe *frame)
- +int notrace unwind_frame(struct stackframe *frame)
- {
- unsigned long high, low;
- unsigned long fp = frame->fp;
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/topology.c linux-3.14.35/arch/arm64/kernel/topology.c
- --- linux-3.14.35.orig/arch/arm64/kernel/topology.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/topology.c 2015-03-08 14:27:37.453684502 -0500
- @@ -0,0 +1,558 @@
- +/*
- + * arch/arm64/kernel/topology.c
- + *
- + * Copyright (C) 2011,2013,2014 Linaro Limited.
- + *
- + * Based on the arm32 version written by Vincent Guittot in turn based on
- + * arch/sh/kernel/topology.c
- + *
- + * This file is subject to the terms and conditions of the GNU General Public
- + * License. See the file "COPYING" in the main directory of this archive
- + * for more details.
- + */
- +
- +#include <linux/cpu.h>
- +#include <linux/cpumask.h>
- +#include <linux/init.h>
- +#include <linux/percpu.h>
- +#include <linux/node.h>
- +#include <linux/nodemask.h>
- +#include <linux/of.h>
- +#include <linux/sched.h>
- +#include <linux/slab.h>
- +
- +#include <asm/topology.h>
- +
- +/*
- + * cpu power table
- + * This per cpu data structure describes the relative capacity of each core.
- + * On a heteregenous system, cores don't have the same computation capacity
- + * and we reflect that difference in the cpu_power field so the scheduler can
- + * take this difference into account during load balance. A per cpu structure
- + * is preferred because each CPU updates its own cpu_power field during the
- + * load balance except for idle cores. One idle core is selected to run the
- + * rebalance_domains for all idle cores and the cpu_power can be updated
- + * during this sequence.
- + */
- +static DEFINE_PER_CPU(unsigned long, cpu_scale);
- +
- +unsigned long arch_scale_freq_power(struct sched_domain *sd, int cpu)
- +{
- + return per_cpu(cpu_scale, cpu);
- +}
- +
- +static void set_power_scale(unsigned int cpu, unsigned long power)
- +{
- + per_cpu(cpu_scale, cpu) = power;
- +}
- +
- +static int __init get_cpu_for_node(struct device_node *node)
- +{
- + struct device_node *cpu_node;
- + int cpu;
- +
- + cpu_node = of_parse_phandle(node, "cpu", 0);
- + if (!cpu_node)
- + return -1;
- +
- + for_each_possible_cpu(cpu) {
- + if (of_get_cpu_node(cpu, NULL) == cpu_node) {
- + of_node_put(cpu_node);
- + return cpu;
- + }
- + }
- +
- + pr_crit("Unable to find CPU node for %s\n", cpu_node->full_name);
- +
- + of_node_put(cpu_node);
- + return -1;
- +}
- +
- +static int __init parse_core(struct device_node *core, int cluster_id,
- + int core_id)
- +{
- + char name[10];
- + bool leaf = true;
- + int i = 0;
- + int cpu;
- + struct device_node *t;
- +
- + do {
- + snprintf(name, sizeof(name), "thread%d", i);
- + t = of_get_child_by_name(core, name);
- + if (t) {
- + leaf = false;
- + cpu = get_cpu_for_node(t);
- + if (cpu >= 0) {
- + cpu_topology[cpu].cluster_id = cluster_id;
- + cpu_topology[cpu].core_id = core_id;
- + cpu_topology[cpu].thread_id = i;
- + } else {
- + pr_err("%s: Can't get CPU for thread\n",
- + t->full_name);
- + of_node_put(t);
- + return -EINVAL;
- + }
- + of_node_put(t);
- + }
- + i++;
- + } while (t);
- +
- + cpu = get_cpu_for_node(core);
- + if (cpu >= 0) {
- + if (!leaf) {
- + pr_err("%s: Core has both threads and CPU\n",
- + core->full_name);
- + return -EINVAL;
- + }
- +
- + cpu_topology[cpu].cluster_id = cluster_id;
- + cpu_topology[cpu].core_id = core_id;
- + } else if (leaf) {
- + pr_err("%s: Can't get CPU for leaf core\n", core->full_name);
- + return -EINVAL;
- + }
- +
- + return 0;
- +}
- +
- +static int __init parse_cluster(struct device_node *cluster, int depth)
- +{
- + char name[10];
- + bool leaf = true;
- + bool has_cores = false;
- + struct device_node *c;
- + static int cluster_id __initdata;
- + int core_id = 0;
- + int i, ret;
- +
- + /*
- + * First check for child clusters; we currently ignore any
- + * information about the nesting of clusters and present the
- + * scheduler with a flat list of them.
- + */
- + i = 0;
- + do {
- + snprintf(name, sizeof(name), "cluster%d", i);
- + c = of_get_child_by_name(cluster, name);
- + if (c) {
- + leaf = false;
- + ret = parse_cluster(c, depth + 1);
- + of_node_put(c);
- + if (ret != 0)
- + return ret;
- + }
- + i++;
- + } while (c);
- +
- + /* Now check for cores */
- + i = 0;
- + do {
- + snprintf(name, sizeof(name), "core%d", i);
- + c = of_get_child_by_name(cluster, name);
- + if (c) {
- + has_cores = true;
- +
- + if (depth == 0) {
- + pr_err("%s: cpu-map children should be clusters\n",
- + c->full_name);
- + of_node_put(c);
- + return -EINVAL;
- + }
- +
- + if (leaf) {
- + ret = parse_core(c, cluster_id, core_id++);
- + } else {
- + pr_err("%s: Non-leaf cluster with core %s\n",
- + cluster->full_name, name);
- + ret = -EINVAL;
- + }
- +
- + of_node_put(c);
- + if (ret != 0)
- + return ret;
- + }
- + i++;
- + } while (c);
- +
- + if (leaf && !has_cores)
- + pr_warn("%s: empty cluster\n", cluster->full_name);
- +
- + if (leaf)
- + cluster_id++;
- +
- + return 0;
- +}
- +
- +struct cpu_efficiency {
- + const char *compatible;
- + unsigned long efficiency;
- +};
- +
- +/*
- + * Table of relative efficiency of each processors
- + * The efficiency value must fit in 20bit and the final
- + * cpu_scale value must be in the range
- + * 0 < cpu_scale < 3*SCHED_POWER_SCALE/2
- + * in order to return at most 1 when DIV_ROUND_CLOSEST
- + * is used to compute the capacity of a CPU.
- + * Processors that are not defined in the table,
- + * use the default SCHED_POWER_SCALE value for cpu_scale.
- + */
- +static const struct cpu_efficiency table_efficiency[] = {
- + { "arm,cortex-a57", 3891 },
- + { "arm,cortex-a53", 2048 },
- + { NULL, },
- +};
- +
- +static unsigned long *__cpu_capacity;
- +#define cpu_capacity(cpu) __cpu_capacity[cpu]
- +
- +static unsigned long middle_capacity = 1;
- +
- +/*
- + * Iterate all CPUs' descriptor in DT and compute the efficiency
- + * (as per table_efficiency). Also calculate a middle efficiency
- + * as close as possible to (max{eff_i} - min{eff_i}) / 2
- + * This is later used to scale the cpu_power field such that an
- + * 'average' CPU is of middle power. Also see the comments near
- + * table_efficiency[] and update_cpu_power().
- + */
- +static int __init parse_dt_topology(void)
- +{
- + struct device_node *cn, *map;
- + int ret = 0;
- + int cpu;
- +
- + cn = of_find_node_by_path("/cpus");
- + if (!cn) {
- + pr_err("No CPU information found in DT\n");
- + return 0;
- + }
- +
- + /*
- + * When topology is provided cpu-map is essentially a root
- + * cluster with restricted subnodes.
- + */
- + map = of_get_child_by_name(cn, "cpu-map");
- + if (!map)
- + goto out;
- +
- + ret = parse_cluster(map, 0);
- + if (ret != 0)
- + goto out_map;
- +
- + /*
- + * Check that all cores are in the topology; the SMP code will
- + * only mark cores described in the DT as possible.
- + */
- + for_each_possible_cpu(cpu) {
- + if (cpu_topology[cpu].cluster_id == -1) {
- + pr_err("CPU%d: No topology information specified\n",
- + cpu);
- + ret = -EINVAL;
- + }
- + }
- +
- +out_map:
- + of_node_put(map);
- +out:
- + of_node_put(cn);
- + return ret;
- +}
- +
- +static void __init parse_dt_cpu_power(void)
- +{
- + const struct cpu_efficiency *cpu_eff;
- + struct device_node *cn;
- + unsigned long min_capacity = ULONG_MAX;
- + unsigned long max_capacity = 0;
- + unsigned long capacity = 0;
- + int cpu;
- +
- + __cpu_capacity = kcalloc(nr_cpu_ids, sizeof(*__cpu_capacity),
- + GFP_NOWAIT);
- +
- + for_each_possible_cpu(cpu) {
- + const u32 *rate;
- + int len;
- +
- + /* Too early to use cpu->of_node */
- + cn = of_get_cpu_node(cpu, NULL);
- + if (!cn) {
- + pr_err("Missing device node for CPU %d\n", cpu);
- + continue;
- + }
- +
- + for (cpu_eff = table_efficiency; cpu_eff->compatible; cpu_eff++)
- + if (of_device_is_compatible(cn, cpu_eff->compatible))
- + break;
- +
- + if (cpu_eff->compatible == NULL) {
- + pr_warn("%s: Unknown CPU type\n", cn->full_name);
- + continue;
- + }
- +
- + rate = of_get_property(cn, "clock-frequency", &len);
- + if (!rate || len != 4) {
- + pr_err("%s: Missing clock-frequency property\n",
- + cn->full_name);
- + continue;
- + }
- +
- + capacity = ((be32_to_cpup(rate)) >> 20) * cpu_eff->efficiency;
- +
- + /* Save min capacity of the system */
- + if (capacity < min_capacity)
- + min_capacity = capacity;
- +
- + /* Save max capacity of the system */
- + if (capacity > max_capacity)
- + max_capacity = capacity;
- +
- + cpu_capacity(cpu) = capacity;
- + }
- +
- + /* If min and max capacities are equal we bypass the update of the
- + * cpu_scale because all CPUs have the same capacity. Otherwise, we
- + * compute a middle_capacity factor that will ensure that the capacity
- + * of an 'average' CPU of the system will be as close as possible to
- + * SCHED_POWER_SCALE, which is the default value, but with the
- + * constraint explained near table_efficiency[].
- + */
- + if (min_capacity == max_capacity)
- + return;
- + else if (4 * max_capacity < (3 * (max_capacity + min_capacity)))
- + middle_capacity = (min_capacity + max_capacity)
- + >> (SCHED_POWER_SHIFT+1);
- + else
- + middle_capacity = ((max_capacity / 3)
- + >> (SCHED_POWER_SHIFT-1)) + 1;
- +}
- +
- +/*
- + * Look for a customed capacity of a CPU in the cpu_topo_data table during the
- + * boot. The update of all CPUs is in O(n^2) for heteregeneous system but the
- + * function returns directly for SMP system.
- + */
- +static void update_cpu_power(unsigned int cpu)
- +{
- + if (!cpu_capacity(cpu))
- + return;
- +
- + set_power_scale(cpu, cpu_capacity(cpu) / middle_capacity);
- +
- + pr_info("CPU%u: update cpu_power %lu\n",
- + cpu, arch_scale_freq_power(NULL, cpu));
- +}
- +
- +/*
- + * cpu topology table
- + */
- +struct cpu_topology cpu_topology[NR_CPUS];
- +EXPORT_SYMBOL_GPL(cpu_topology);
- +
- +const struct cpumask *cpu_coregroup_mask(int cpu)
- +{
- + return &cpu_topology[cpu].core_sibling;
- +}
- +
- +static void update_siblings_masks(unsigned int cpuid)
- +{
- + struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
- + int cpu;
- +
- + if (cpuid_topo->cluster_id == -1) {
- + /*
- + * DT does not contain topology information for this cpu.
- + */
- + pr_debug("CPU%u: No topology information configured\n", cpuid);
- + return;
- + }
- +
- + /* update core and thread sibling masks */
- + for_each_possible_cpu(cpu) {
- + cpu_topo = &cpu_topology[cpu];
- +
- + if (cpuid_topo->cluster_id != cpu_topo->cluster_id)
- + continue;
- +
- + cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
- + if (cpu != cpuid)
- + cpumask_set_cpu(cpu, &cpuid_topo->core_sibling);
- +
- + if (cpuid_topo->core_id != cpu_topo->core_id)
- + continue;
- +
- + cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling);
- + if (cpu != cpuid)
- + cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling);
- + }
- +}
- +
- +void store_cpu_topology(unsigned int cpuid)
- +{
- + update_siblings_masks(cpuid);
- + update_cpu_power(cpuid);
- +}
- +
- +#ifdef CONFIG_SCHED_HMP
- +
- +/*
- + * Retrieve logical cpu index corresponding to a given MPIDR[23:0]
- + * - mpidr: MPIDR[23:0] to be used for the look-up
- + *
- + * Returns the cpu logical index or -EINVAL on look-up error
- + */
- +static inline int get_logical_index(u32 mpidr)
- +{
- + int cpu;
- + for (cpu = 0; cpu < nr_cpu_ids; cpu++)
- + if (cpu_logical_map(cpu) == mpidr)
- + return cpu;
- + return -EINVAL;
- +}
- +
- +static const char * const little_cores[] = {
- + "arm,cortex-a53",
- + NULL,
- +};
- +
- +static bool is_little_cpu(struct device_node *cn)
- +{
- + const char * const *lc;
- + for (lc = little_cores; *lc; lc++)
- + if (of_device_is_compatible(cn, *lc))
- + return true;
- + return false;
- +}
- +
- +void __init arch_get_fast_and_slow_cpus(struct cpumask *fast,
- + struct cpumask *slow)
- +{
- + struct device_node *cn = NULL;
- + int cpu;
- +
- + cpumask_clear(fast);
- + cpumask_clear(slow);
- +
- + /*
- + * Use the config options if they are given. This helps testing
- + * HMP scheduling on systems without a big.LITTLE architecture.
- + */
- + if (strlen(CONFIG_HMP_FAST_CPU_MASK) && strlen(CONFIG_HMP_SLOW_CPU_MASK)) {
- + if (cpulist_parse(CONFIG_HMP_FAST_CPU_MASK, fast))
- + WARN(1, "Failed to parse HMP fast cpu mask!\n");
- + if (cpulist_parse(CONFIG_HMP_SLOW_CPU_MASK, slow))
- + WARN(1, "Failed to parse HMP slow cpu mask!\n");
- + return;
- + }
- +
- + /*
- + * Else, parse device tree for little cores.
- + */
- + while ((cn = of_find_node_by_type(cn, "cpu"))) {
- +
- + const u32 *mpidr;
- + int len;
- +
- + mpidr = of_get_property(cn, "reg", &len);
- + if (!mpidr || len != 8) {
- + pr_err("%s missing reg property\n", cn->full_name);
- + continue;
- + }
- +
- + cpu = get_logical_index(be32_to_cpup(mpidr+1));
- + if (cpu == -EINVAL) {
- + pr_err("couldn't get logical index for mpidr %x\n",
- + be32_to_cpup(mpidr+1));
- + break;
- + }
- +
- + if (is_little_cpu(cn))
- + cpumask_set_cpu(cpu, slow);
- + else
- + cpumask_set_cpu(cpu, fast);
- + }
- +
- + if (!cpumask_empty(fast) && !cpumask_empty(slow))
- + return;
- +
- + /*
- + * We didn't find both big and little cores so let's call all cores
- + * fast as this will keep the system running, with all cores being
- + * treated equal.
- + */
- + cpumask_setall(fast);
- + cpumask_clear(slow);
- +}
- +
- +struct cpumask hmp_slow_cpu_mask;
- +
- +void __init arch_get_hmp_domains(struct list_head *hmp_domains_list)
- +{
- + struct cpumask hmp_fast_cpu_mask;
- + struct hmp_domain *domain;
- +
- + arch_get_fast_and_slow_cpus(&hmp_fast_cpu_mask, &hmp_slow_cpu_mask);
- +
- + /*
- + * Initialize hmp_domains
- + * Must be ordered with respect to compute capacity.
- + * Fastest domain at head of list.
- + */
- + if(!cpumask_empty(&hmp_slow_cpu_mask)) {
- + domain = (struct hmp_domain *)
- + kmalloc(sizeof(struct hmp_domain), GFP_KERNEL);
- + cpumask_copy(&domain->possible_cpus, &hmp_slow_cpu_mask);
- + cpumask_and(&domain->cpus, cpu_online_mask, &domain->possible_cpus);
- + list_add(&domain->hmp_domains, hmp_domains_list);
- + }
- + domain = (struct hmp_domain *)
- + kmalloc(sizeof(struct hmp_domain), GFP_KERNEL);
- + cpumask_copy(&domain->possible_cpus, &hmp_fast_cpu_mask);
- + cpumask_and(&domain->cpus, cpu_online_mask, &domain->possible_cpus);
- + list_add(&domain->hmp_domains, hmp_domains_list);
- +}
- +#endif /* CONFIG_SCHED_HMP */
- +
- +static void __init reset_cpu_topology(void)
- +{
- + unsigned int cpu;
- +
- + for_each_possible_cpu(cpu) {
- + struct cpu_topology *cpu_topo = &cpu_topology[cpu];
- +
- + cpu_topo->thread_id = -1;
- + cpu_topo->core_id = 0;
- + cpu_topo->cluster_id = -1;
- +
- + cpumask_clear(&cpu_topo->core_sibling);
- + cpumask_set_cpu(cpu, &cpu_topo->core_sibling);
- + cpumask_clear(&cpu_topo->thread_sibling);
- + cpumask_set_cpu(cpu, &cpu_topo->thread_sibling);
- + }
- +}
- +
- +static void __init reset_cpu_power(void)
- +{
- + unsigned int cpu;
- +
- + for_each_possible_cpu(cpu)
- + set_power_scale(cpu, SCHED_POWER_SCALE);
- +}
- +
- +void __init init_cpu_topology(void)
- +{
- + reset_cpu_topology();
- +
- + /*
- + * Discard anything that was parsed if we hit an error so we
- + * don't use partial information.
- + */
- + if (parse_dt_topology())
- + reset_cpu_topology();
- +
- + reset_cpu_power();
- + parse_dt_cpu_power();
- +}
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/vdso/Makefile linux-3.14.35/arch/arm64/kernel/vdso/Makefile
- --- linux-3.14.35.orig/arch/arm64/kernel/vdso/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/vdso/Makefile 2015-03-08 14:27:37.453684502 -0500
- @@ -47,9 +47,9 @@
- $(call if_changed_dep,vdsoas)
-
- # Actual build commands
- -quiet_cmd_vdsold = VDSOL $@
- +quiet_cmd_vdsold = VDSOL $@
- cmd_vdsold = $(CC) $(c_flags) -Wl,-n -Wl,-T $^ -o $@
- -quiet_cmd_vdsoas = VDSOA $@
- +quiet_cmd_vdsoas = VDSOA $@
- cmd_vdsoas = $(CC) $(a_flags) -c -o $@ $<
-
- # Install commands for the unstripped file
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/vdso.c linux-3.14.35/arch/arm64/kernel/vdso.c
- --- linux-3.14.35.orig/arch/arm64/kernel/vdso.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/vdso.c 2015-03-08 14:27:37.453684502 -0500
- @@ -156,11 +156,12 @@
- int uses_interp)
- {
- struct mm_struct *mm = current->mm;
- - unsigned long vdso_base, vdso_mapping_len;
- + unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
- int ret;
-
- + vdso_text_len = vdso_pages << PAGE_SHIFT;
- /* Be sure to map the data page */
- - vdso_mapping_len = (vdso_pages + 1) << PAGE_SHIFT;
- + vdso_mapping_len = vdso_text_len + PAGE_SIZE;
-
- down_write(&mm->mmap_sem);
- vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0);
- @@ -170,35 +171,52 @@
- }
- mm->context.vdso = (void *)vdso_base;
-
- - ret = install_special_mapping(mm, vdso_base, vdso_mapping_len,
- + ret = install_special_mapping(mm, vdso_base, vdso_text_len,
- VM_READ|VM_EXEC|
- VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
- vdso_pagelist);
- - if (ret) {
- - mm->context.vdso = NULL;
- + if (ret)
- + goto up_fail;
- +
- + vdso_base += vdso_text_len;
- + ret = install_special_mapping(mm, vdso_base, PAGE_SIZE,
- + VM_READ|VM_MAYREAD,
- + vdso_pagelist + vdso_pages);
- + if (ret)
- goto up_fail;
- - }
-
- -up_fail:
- up_write(&mm->mmap_sem);
- + return 0;
-
- +up_fail:
- + mm->context.vdso = NULL;
- + up_write(&mm->mmap_sem);
- return ret;
- }
-
- const char *arch_vma_name(struct vm_area_struct *vma)
- {
- + unsigned long vdso_text;
- +
- + if (!vma->vm_mm)
- + return NULL;
- +
- + vdso_text = (unsigned long)vma->vm_mm->context.vdso;
- +
- /*
- * We can re-use the vdso pointer in mm_context_t for identifying
- * the vectors page for compat applications. The vDSO will always
- * sit above TASK_UNMAPPED_BASE and so we don't need to worry about
- * it conflicting with the vectors base.
- */
- - if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) {
- + if (vma->vm_start == vdso_text) {
- #ifdef CONFIG_COMPAT
- if (vma->vm_start == AARCH32_VECTORS_BASE)
- return "[vectors]";
- #endif
- return "[vdso]";
- + } else if (vma->vm_start == (vdso_text + (vdso_pages << PAGE_SHIFT))) {
- + return "[vvar]";
- }
-
- return NULL;
- diff -Nur linux-3.14.35.orig/arch/arm64/kernel/vmlinux.lds.S linux-3.14.35/arch/arm64/kernel/vmlinux.lds.S
- --- linux-3.14.35.orig/arch/arm64/kernel/vmlinux.lds.S 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/kernel/vmlinux.lds.S 2015-03-08 14:27:37.453684502 -0500
- @@ -104,6 +104,13 @@
- _edata = .;
-
- BSS_SECTION(0, 0, 0)
- +
- + . = ALIGN(PAGE_SIZE);
- + idmap_pg_dir = .;
- + . += IDMAP_DIR_SIZE;
- + swapper_pg_dir = .;
- + . += SWAPPER_DIR_SIZE;
- +
- _end = .;
-
- STABS_DEBUG
- diff -Nur linux-3.14.35.orig/arch/arm64/Makefile linux-3.14.35/arch/arm64/Makefile
- --- linux-3.14.35.orig/arch/arm64/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/Makefile 2015-03-08 14:27:37.453684502 -0500
- @@ -45,6 +45,7 @@
- core-y += arch/arm64/kernel/ arch/arm64/mm/
- core-$(CONFIG_KVM) += arch/arm64/kvm/
- core-$(CONFIG_XEN) += arch/arm64/xen/
- +core-$(CONFIG_CRYPTO) += arch/arm64/crypto/
- libs-y := arch/arm64/lib/ $(libs-y)
- libs-y += $(LIBGCC)
-
- diff -Nur linux-3.14.35.orig/arch/arm64/mm/cache.S linux-3.14.35/arch/arm64/mm/cache.S
- --- linux-3.14.35.orig/arch/arm64/mm/cache.S 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/mm/cache.S 2015-03-08 14:27:37.453684502 -0500
- @@ -30,7 +30,7 @@
- *
- * Corrupted registers: x0-x7, x9-x11
- */
- -ENTRY(__flush_dcache_all)
- +__flush_dcache_all:
- dsb sy // ensure ordering with previous memory accesses
- mrs x0, clidr_el1 // read clidr
- and x3, x0, #0x7000000 // extract loc from clidr
- @@ -166,3 +166,97 @@
- dsb sy
- ret
- ENDPROC(__flush_dcache_area)
- +
- +/*
- + * __inval_cache_range(start, end)
- + * - start - start address of region
- + * - end - end address of region
- + */
- +ENTRY(__inval_cache_range)
- + /* FALLTHROUGH */
- +
- +/*
- + * __dma_inv_range(start, end)
- + * - start - virtual start address of region
- + * - end - virtual end address of region
- + */
- +__dma_inv_range:
- + dcache_line_size x2, x3
- + sub x3, x2, #1
- + tst x1, x3 // end cache line aligned?
- + bic x1, x1, x3
- + b.eq 1f
- + dc civac, x1 // clean & invalidate D / U line
- +1: tst x0, x3 // start cache line aligned?
- + bic x0, x0, x3
- + b.eq 2f
- + dc civac, x0 // clean & invalidate D / U line
- + b 3f
- +2: dc ivac, x0 // invalidate D / U line
- +3: add x0, x0, x2
- + cmp x0, x1
- + b.lo 2b
- + dsb sy
- + ret
- +ENDPROC(__inval_cache_range)
- +ENDPROC(__dma_inv_range)
- +
- +/*
- + * __dma_clean_range(start, end)
- + * - start - virtual start address of region
- + * - end - virtual end address of region
- + */
- +__dma_clean_range:
- + dcache_line_size x2, x3
- + sub x3, x2, #1
- + bic x0, x0, x3
- +1: dc cvac, x0 // clean D / U line
- + add x0, x0, x2
- + cmp x0, x1
- + b.lo 1b
- + dsb sy
- + ret
- +ENDPROC(__dma_clean_range)
- +
- +/*
- + * __dma_flush_range(start, end)
- + * - start - virtual start address of region
- + * - end - virtual end address of region
- + */
- +ENTRY(__dma_flush_range)
- + dcache_line_size x2, x3
- + sub x3, x2, #1
- + bic x0, x0, x3
- +1: dc civac, x0 // clean & invalidate D / U line
- + add x0, x0, x2
- + cmp x0, x1
- + b.lo 1b
- + dsb sy
- + ret
- +ENDPROC(__dma_flush_range)
- +
- +/*
- + * __dma_map_area(start, size, dir)
- + * - start - kernel virtual start address
- + * - size - size of region
- + * - dir - DMA direction
- + */
- +ENTRY(__dma_map_area)
- + add x1, x1, x0
- + cmp w2, #DMA_FROM_DEVICE
- + b.eq __dma_inv_range
- + b __dma_clean_range
- +ENDPROC(__dma_map_area)
- +
- +/*
- + * __dma_unmap_area(start, size, dir)
- + * - start - kernel virtual start address
- + * - size - size of region
- + * - dir - DMA direction
- + */
- +ENTRY(__dma_unmap_area)
- + add x1, x1, x0
- + cmp w2, #DMA_TO_DEVICE
- + b.ne __dma_inv_range
- + ret
- +ENDPROC(__dma_unmap_area)
- diff -Nur linux-3.14.35.orig/arch/arm64/mm/copypage.c linux-3.14.35/arch/arm64/mm/copypage.c
- --- linux-3.14.35.orig/arch/arm64/mm/copypage.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/mm/copypage.c 2015-03-08 14:27:37.453684502 -0500
- @@ -27,8 +27,10 @@
- copy_page(kto, kfrom);
- __flush_dcache_area(kto, PAGE_SIZE);
- }
- +EXPORT_SYMBOL_GPL(__cpu_copy_user_page);
-
- void __cpu_clear_user_page(void *kaddr, unsigned long vaddr)
- {
- clear_page(kaddr);
- }
- +EXPORT_SYMBOL_GPL(__cpu_clear_user_page);
- diff -Nur linux-3.14.35.orig/arch/arm64/mm/dma-mapping.c linux-3.14.35/arch/arm64/mm/dma-mapping.c
- --- linux-3.14.35.orig/arch/arm64/mm/dma-mapping.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/mm/dma-mapping.c 2015-03-08 14:27:37.457684502 -0500
- @@ -22,26 +22,39 @@
- #include <linux/slab.h>
- #include <linux/dma-mapping.h>
- #include <linux/dma-contiguous.h>
- +#include <linux/of.h>
- +#include <linux/platform_device.h>
- #include <linux/vmalloc.h>
- #include <linux/swiotlb.h>
- +#include <linux/amba/bus.h>
-
- #include <asm/cacheflush.h>
-
- struct dma_map_ops *dma_ops;
- EXPORT_SYMBOL(dma_ops);
-
- -static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
- - dma_addr_t *dma_handle, gfp_t flags,
- - struct dma_attrs *attrs)
- +static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot,
- + bool coherent)
- +{
- + if (dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs))
- + return pgprot_writecombine(prot);
- + else if (!coherent)
- + return pgprot_dmacoherent(prot);
- + return prot;
- +}
- +
- +static void *__dma_alloc_coherent(struct device *dev, size_t size,
- + dma_addr_t *dma_handle, gfp_t flags,
- + struct dma_attrs *attrs)
- {
- if (dev == NULL) {
- WARN_ONCE(1, "Use an actual device structure for DMA allocation\n");
- return NULL;
- }
-
- - if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
- + if (IS_ENABLED(CONFIG_ZONE_DMA) &&
- dev->coherent_dma_mask <= DMA_BIT_MASK(32))
- - flags |= GFP_DMA32;
- + flags |= GFP_DMA;
- if (IS_ENABLED(CONFIG_DMA_CMA)) {
- struct page *page;
-
- @@ -58,9 +71,9 @@
- }
- }
-
- -static void arm64_swiotlb_free_coherent(struct device *dev, size_t size,
- - void *vaddr, dma_addr_t dma_handle,
- - struct dma_attrs *attrs)
- +static void __dma_free_coherent(struct device *dev, size_t size,
- + void *vaddr, dma_addr_t dma_handle,
- + struct dma_attrs *attrs)
- {
- if (dev == NULL) {
- WARN_ONCE(1, "Use an actual device structure for DMA allocation\n");
- @@ -78,9 +91,212 @@
- }
- }
-
- -static struct dma_map_ops arm64_swiotlb_dma_ops = {
- - .alloc = arm64_swiotlb_alloc_coherent,
- - .free = arm64_swiotlb_free_coherent,
- +static void *__dma_alloc_noncoherent(struct device *dev, size_t size,
- + dma_addr_t *dma_handle, gfp_t flags,
- + struct dma_attrs *attrs)
- +{
- + struct page *page, **map;
- + void *ptr, *coherent_ptr;
- + int order, i;
- +
- + size = PAGE_ALIGN(size);
- + order = get_order(size);
- +
- + ptr = __dma_alloc_coherent(dev, size, dma_handle, flags, attrs);
- + if (!ptr)
- + goto no_mem;
- + map = kmalloc(sizeof(struct page *) << order, flags & ~GFP_DMA);
- + if (!map)
- + goto no_map;
- +
- + /* remove any dirty cache lines on the kernel alias */
- + __dma_flush_range(ptr, ptr + size);
- +
- + /* create a coherent mapping */
- + page = virt_to_page(ptr);
- + for (i = 0; i < (size >> PAGE_SHIFT); i++)
- + map[i] = page + i;
- + coherent_ptr = vmap(map, size >> PAGE_SHIFT, VM_MAP,
- + __get_dma_pgprot(attrs, pgprot_default, false));
- + kfree(map);
- + if (!coherent_ptr)
- + goto no_map;
- +
- + return coherent_ptr;
- +
- +no_map:
- + __dma_free_coherent(dev, size, ptr, *dma_handle, attrs);
- +no_mem:
- + *dma_handle = ~0;
- + return NULL;
- +}
- +
- +static void __dma_free_noncoherent(struct device *dev, size_t size,
- + void *vaddr, dma_addr_t dma_handle,
- + struct dma_attrs *attrs)
- +{
- + void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle));
- +
- + vunmap(vaddr);
- + __dma_free_coherent(dev, size, swiotlb_addr, dma_handle, attrs);
- +}
- +
- +static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
- + unsigned long offset, size_t size,
- + enum dma_data_direction dir,
- + struct dma_attrs *attrs)
- +{
- + dma_addr_t dev_addr;
- +
- + dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs);
- + __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
- +
- + return dev_addr;
- +}
- +
- +
- +static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr,
- + size_t size, enum dma_data_direction dir,
- + struct dma_attrs *attrs)
- +{
- + __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
- + swiotlb_unmap_page(dev, dev_addr, size, dir, attrs);
- +}
- +
- +static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
- + int nelems, enum dma_data_direction dir,
- + struct dma_attrs *attrs)
- +{
- + struct scatterlist *sg;
- + int i, ret;
- +
- + ret = swiotlb_map_sg_attrs(dev, sgl, nelems, dir, attrs);
- + for_each_sg(sgl, sg, ret, i)
- + __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
- + sg->length, dir);
- +
- + return ret;
- +}
- +
- +static void __swiotlb_unmap_sg_attrs(struct device *dev,
- + struct scatterlist *sgl, int nelems,
- + enum dma_data_direction dir,
- + struct dma_attrs *attrs)
- +{
- + struct scatterlist *sg;
- + int i;
- +
- + for_each_sg(sgl, sg, nelems, i)
- + __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
- + sg->length, dir);
- + swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs);
- +}
- +
- +static void __swiotlb_sync_single_for_cpu(struct device *dev,
- + dma_addr_t dev_addr, size_t size,
- + enum dma_data_direction dir)
- +{
- + __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
- + swiotlb_sync_single_for_cpu(dev, dev_addr, size, dir);
- +}
- +
- +static void __swiotlb_sync_single_for_device(struct device *dev,
- + dma_addr_t dev_addr, size_t size,
- + enum dma_data_direction dir)
- +{
- + swiotlb_sync_single_for_device(dev, dev_addr, size, dir);
- + __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
- +}
- +
- +static void __swiotlb_sync_sg_for_cpu(struct device *dev,
- + struct scatterlist *sgl, int nelems,
- + enum dma_data_direction dir)
- +{
- + struct scatterlist *sg;
- + int i;
- +
- + for_each_sg(sgl, sg, nelems, i)
- + __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
- + sg->length, dir);
- + swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir);
- +}
- +
- +static void __swiotlb_sync_sg_for_device(struct device *dev,
- + struct scatterlist *sgl, int nelems,
- + enum dma_data_direction dir)
- +{
- + struct scatterlist *sg;
- + int i;
- +
- + swiotlb_sync_sg_for_device(dev, sgl, nelems, dir);
- + for_each_sg(sgl, sg, nelems, i)
- + __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
- + sg->length, dir);
- +}
- +
- +/* vma->vm_page_prot must be set appropriately before calling this function */
- +static int __dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
- + void *cpu_addr, dma_addr_t dma_addr, size_t size)
- +{
- + int ret = -ENXIO;
- + unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >>
- + PAGE_SHIFT;
- + unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
- + unsigned long pfn = dma_to_phys(dev, dma_addr) >> PAGE_SHIFT;
- + unsigned long off = vma->vm_pgoff;
- +
- + if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
- + return ret;
- +
- + if (off < nr_pages && nr_vma_pages <= (nr_pages - off)) {
- + ret = remap_pfn_range(vma, vma->vm_start,
- + pfn + off,
- + vma->vm_end - vma->vm_start,
- + vma->vm_page_prot);
- + }
- +
- + return ret;
- +}
- +
- +static int __swiotlb_mmap_noncoherent(struct device *dev,
- + struct vm_area_struct *vma,
- + void *cpu_addr, dma_addr_t dma_addr, size_t size,
- + struct dma_attrs *attrs)
- +{
- + vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot, false);
- + return __dma_common_mmap(dev, vma, cpu_addr, dma_addr, size);
- +}
- +
- +static int __swiotlb_mmap_coherent(struct device *dev,
- + struct vm_area_struct *vma,
- + void *cpu_addr, dma_addr_t dma_addr, size_t size,
- + struct dma_attrs *attrs)
- +{
- + /* Just use whatever page_prot attributes were specified */
- + return __dma_common_mmap(dev, vma, cpu_addr, dma_addr, size);
- +}
- +
- +struct dma_map_ops noncoherent_swiotlb_dma_ops = {
- + .alloc = __dma_alloc_noncoherent,
- + .free = __dma_free_noncoherent,
- + .mmap = __swiotlb_mmap_noncoherent,
- + .map_page = __swiotlb_map_page,
- + .unmap_page = __swiotlb_unmap_page,
- + .map_sg = __swiotlb_map_sg_attrs,
- + .unmap_sg = __swiotlb_unmap_sg_attrs,
- + .sync_single_for_cpu = __swiotlb_sync_single_for_cpu,
- + .sync_single_for_device = __swiotlb_sync_single_for_device,
- + .sync_sg_for_cpu = __swiotlb_sync_sg_for_cpu,
- + .sync_sg_for_device = __swiotlb_sync_sg_for_device,
- + .dma_supported = swiotlb_dma_supported,
- + .mapping_error = swiotlb_dma_mapping_error,
- +};
- +EXPORT_SYMBOL(noncoherent_swiotlb_dma_ops);
- +
- +struct dma_map_ops coherent_swiotlb_dma_ops = {
- + .alloc = __dma_alloc_coherent,
- + .free = __dma_free_coherent,
- + .mmap = __swiotlb_mmap_coherent,
- .map_page = swiotlb_map_page,
- .unmap_page = swiotlb_unmap_page,
- .map_sg = swiotlb_map_sg_attrs,
- @@ -92,12 +308,47 @@
- .dma_supported = swiotlb_dma_supported,
- .mapping_error = swiotlb_dma_mapping_error,
- };
- +EXPORT_SYMBOL(coherent_swiotlb_dma_ops);
-
- -void __init arm64_swiotlb_init(void)
- +static int dma_bus_notifier(struct notifier_block *nb,
- + unsigned long event, void *_dev)
- {
- - dma_ops = &arm64_swiotlb_dma_ops;
- - swiotlb_init(1);
- + struct device *dev = _dev;
- +
- + if (event != BUS_NOTIFY_ADD_DEVICE)
- + return NOTIFY_DONE;
- +
- + if (of_property_read_bool(dev->of_node, "dma-coherent"))
- + set_dma_ops(dev, &coherent_swiotlb_dma_ops);
- +
- + return NOTIFY_OK;
- +}
- +
- +static struct notifier_block platform_bus_nb = {
- + .notifier_call = dma_bus_notifier,
- +};
- +
- +static struct notifier_block amba_bus_nb = {
- + .notifier_call = dma_bus_notifier,
- +};
- +
- +extern int swiotlb_late_init_with_default_size(size_t default_size);
- +
- +static int __init swiotlb_late_init(void)
- +{
- + size_t swiotlb_size = min(SZ_64M, MAX_ORDER_NR_PAGES << PAGE_SHIFT);
- +
- + /*
- + * These must be registered before of_platform_populate().
- + */
- + bus_register_notifier(&platform_bus_type, &platform_bus_nb);
- + bus_register_notifier(&amba_bustype, &amba_bus_nb);
- +
- + dma_ops = &noncoherent_swiotlb_dma_ops;
- +
- + return swiotlb_late_init_with_default_size(swiotlb_size);
- }
- +arch_initcall(swiotlb_late_init);
-
- #define PREALLOC_DMA_DEBUG_ENTRIES 4096
-
- diff -Nur linux-3.14.35.orig/arch/arm64/mm/init.c linux-3.14.35/arch/arm64/mm/init.c
- --- linux-3.14.35.orig/arch/arm64/mm/init.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/mm/init.c 2015-03-08 14:27:37.457684502 -0500
- @@ -30,6 +30,7 @@
- #include <linux/memblock.h>
- #include <linux/sort.h>
- #include <linux/of_fdt.h>
- +#include <linux/dma-mapping.h>
- #include <linux/dma-contiguous.h>
-
- #include <asm/sections.h>
- @@ -59,22 +60,22 @@
- early_param("initrd", early_initrd);
- #endif
-
- -#define MAX_DMA32_PFN ((4UL * 1024 * 1024 * 1024) >> PAGE_SHIFT)
- -
- static void __init zone_sizes_init(unsigned long min, unsigned long max)
- {
- struct memblock_region *reg;
- unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
- - unsigned long max_dma32 = min;
- + unsigned long max_dma = min;
-
- memset(zone_size, 0, sizeof(zone_size));
-
- -#ifdef CONFIG_ZONE_DMA32
- /* 4GB maximum for 32-bit only capable devices */
- - max_dma32 = max(min, min(max, MAX_DMA32_PFN));
- - zone_size[ZONE_DMA32] = max_dma32 - min;
- -#endif
- - zone_size[ZONE_NORMAL] = max - max_dma32;
- + if (IS_ENABLED(CONFIG_ZONE_DMA)) {
- + unsigned long max_dma_phys =
- + (unsigned long)dma_to_phys(NULL, DMA_BIT_MASK(32) + 1);
- + max_dma = max(min, min(max, max_dma_phys >> PAGE_SHIFT));
- + zone_size[ZONE_DMA] = max_dma - min;
- + }
- + zone_size[ZONE_NORMAL] = max - max_dma;
-
- memcpy(zhole_size, zone_size, sizeof(zhole_size));
-
- @@ -84,15 +85,15 @@
-
- if (start >= max)
- continue;
- -#ifdef CONFIG_ZONE_DMA32
- - if (start < max_dma32) {
- - unsigned long dma_end = min(end, max_dma32);
- - zhole_size[ZONE_DMA32] -= dma_end - start;
- +
- + if (IS_ENABLED(CONFIG_ZONE_DMA) && start < max_dma) {
- + unsigned long dma_end = min(end, max_dma);
- + zhole_size[ZONE_DMA] -= dma_end - start;
- }
- -#endif
- - if (end > max_dma32) {
- +
- + if (end > max_dma) {
- unsigned long normal_end = min(end, max);
- - unsigned long normal_start = max(start, max_dma32);
- + unsigned long normal_start = max(start, max_dma);
- zhole_size[ZONE_NORMAL] -= normal_end - normal_start;
- }
- }
- @@ -127,20 +128,16 @@
- {
- u64 *reserve_map, base, size;
-
- - /* Register the kernel text, kernel data and initrd with memblock */
- + /*
- + * Register the kernel text, kernel data, initrd, and initial
- + * pagetables with memblock.
- + */
- memblock_reserve(__pa(_text), _end - _text);
- #ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- memblock_reserve(__virt_to_phys(initrd_start), initrd_end - initrd_start);
- #endif
-
- - /*
- - * Reserve the page tables. These are already in use,
- - * and can only be in node 0.
- - */
- - memblock_reserve(__pa(swapper_pg_dir), SWAPPER_DIR_SIZE);
- - memblock_reserve(__pa(idmap_pg_dir), IDMAP_DIR_SIZE);
- -
- /* Reserve the dtb region */
- memblock_reserve(virt_to_phys(initial_boot_params),
- be32_to_cpu(initial_boot_params->totalsize));
- @@ -261,8 +258,6 @@
- */
- void __init mem_init(void)
- {
- - arm64_swiotlb_init();
- -
- max_mapnr = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map;
-
- #ifndef CONFIG_SPARSEMEM_VMEMMAP
- diff -Nur linux-3.14.35.orig/arch/arm64/mm/proc.S linux-3.14.35/arch/arm64/mm/proc.S
- --- linux-3.14.35.orig/arch/arm64/mm/proc.S 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/arm64/mm/proc.S 2015-03-08 14:27:37.457684502 -0500
- @@ -173,12 +173,6 @@
- * value of the SCTLR_EL1 register.
- */
- ENTRY(__cpu_setup)
- - /*
- - * Preserve the link register across the function call.
- - */
- - mov x28, lr
- - bl __flush_dcache_all
- - mov lr, x28
- ic iallu // I+BTB cache invalidate
- tlbi vmalle1is // invalidate I + D TLBs
- dsb sy
- diff -Nur linux-3.14.35.orig/arch/avr32/kernel/cpu.c linux-3.14.35/arch/avr32/kernel/cpu.c
- --- linux-3.14.35.orig/arch/avr32/kernel/cpu.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/avr32/kernel/cpu.c 2015-03-08 14:27:37.457684502 -0500
- @@ -39,10 +39,12 @@
- size_t count)
- {
- unsigned long val;
- - char *endp;
- + int ret;
-
- - val = simple_strtoul(buf, &endp, 0);
- - if (endp == buf || val > 0x3f)
- + ret = kstrtoul(buf, 0, &val);
- + if (ret)
- + return ret;
- + if (val > 0x3f)
- return -EINVAL;
- val = (val << 12) | (sysreg_read(PCCR) & 0xfffc0fff);
- sysreg_write(PCCR, val);
- @@ -61,11 +63,11 @@
- const char *buf, size_t count)
- {
- unsigned long val;
- - char *endp;
- + int ret;
-
- - val = simple_strtoul(buf, &endp, 0);
- - if (endp == buf)
- - return -EINVAL;
- + ret = kstrtoul(buf, 0, &val);
- + if (ret)
- + return ret;
- sysreg_write(PCNT0, val);
-
- return count;
- @@ -84,10 +86,12 @@
- size_t count)
- {
- unsigned long val;
- - char *endp;
- + int ret;
-
- - val = simple_strtoul(buf, &endp, 0);
- - if (endp == buf || val > 0x3f)
- + ret = kstrtoul(buf, 0, &val);
- + if (ret)
- + return ret;
- + if (val > 0x3f)
- return -EINVAL;
- val = (val << 18) | (sysreg_read(PCCR) & 0xff03ffff);
- sysreg_write(PCCR, val);
- @@ -106,11 +110,11 @@
- size_t count)
- {
- unsigned long val;
- - char *endp;
- + int ret;
-
- - val = simple_strtoul(buf, &endp, 0);
- - if (endp == buf)
- - return -EINVAL;
- + ret = kstrtoul(buf, 0, &val);
- + if (ret)
- + return ret;
- sysreg_write(PCNT1, val);
-
- return count;
- @@ -129,11 +133,11 @@
- size_t count)
- {
- unsigned long val;
- - char *endp;
- + int ret;
-
- - val = simple_strtoul(buf, &endp, 0);
- - if (endp == buf)
- - return -EINVAL;
- + ret = kstrtoul(buf, 0, &val);
- + if (ret)
- + return ret;
- sysreg_write(PCCNT, val);
-
- return count;
- @@ -152,11 +156,11 @@
- size_t count)
- {
- unsigned long pccr, val;
- - char *endp;
- + int ret;
-
- - val = simple_strtoul(buf, &endp, 0);
- - if (endp == buf)
- - return -EINVAL;
- + ret = kstrtoul(buf, 0, &val);
- + if (ret)
- + return ret;
- if (val)
- val = 1;
-
- diff -Nur linux-3.14.35.orig/arch/blackfin/include/asm/ftrace.h linux-3.14.35/arch/blackfin/include/asm/ftrace.h
- --- linux-3.14.35.orig/arch/blackfin/include/asm/ftrace.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/blackfin/include/asm/ftrace.h 2015-03-08 14:27:37.457684502 -0500
- @@ -66,16 +66,7 @@
-
- #endif /* CONFIG_FRAME_POINTER */
-
- -#define HAVE_ARCH_CALLER_ADDR
- -
- -/* inline function or macro may lead to unexpected result */
- -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
- -#define CALLER_ADDR1 ((unsigned long)return_address(1))
- -#define CALLER_ADDR2 ((unsigned long)return_address(2))
- -#define CALLER_ADDR3 ((unsigned long)return_address(3))
- -#define CALLER_ADDR4 ((unsigned long)return_address(4))
- -#define CALLER_ADDR5 ((unsigned long)return_address(5))
- -#define CALLER_ADDR6 ((unsigned long)return_address(6))
- +#define ftrace_return_address(n) return_address(n)
-
- #endif /* __ASSEMBLY__ */
-
- diff -Nur linux-3.14.35.orig/arch/hexagon/include/asm/elf.h linux-3.14.35/arch/hexagon/include/asm/elf.h
- --- linux-3.14.35.orig/arch/hexagon/include/asm/elf.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/hexagon/include/asm/elf.h 2015-03-08 14:27:37.457684502 -0500
- @@ -1,7 +1,7 @@
- /*
- * ELF definitions for the Hexagon architecture
- *
- - * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
- + * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- diff -Nur linux-3.14.35.orig/arch/parisc/include/asm/ftrace.h linux-3.14.35/arch/parisc/include/asm/ftrace.h
- --- linux-3.14.35.orig/arch/parisc/include/asm/ftrace.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/parisc/include/asm/ftrace.h 2015-03-08 14:27:37.457684502 -0500
- @@ -24,15 +24,7 @@
-
- extern unsigned long return_address(unsigned int);
-
- -#define HAVE_ARCH_CALLER_ADDR
- -
- -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
- -#define CALLER_ADDR1 return_address(1)
- -#define CALLER_ADDR2 return_address(2)
- -#define CALLER_ADDR3 return_address(3)
- -#define CALLER_ADDR4 return_address(4)
- -#define CALLER_ADDR5 return_address(5)
- -#define CALLER_ADDR6 return_address(6)
- +#define ftrace_return_address(n) return_address(n)
-
- #endif /* __ASSEMBLY__ */
-
- diff -Nur linux-3.14.35.orig/arch/s390/include/asm/cio.h linux-3.14.35/arch/s390/include/asm/cio.h
- --- linux-3.14.35.orig/arch/s390/include/asm/cio.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/s390/include/asm/cio.h 2015-03-08 14:27:37.457684502 -0500
- @@ -199,7 +199,7 @@
- /**
- * struct irb - interruption response block
- * @scsw: subchannel status word
- - * @esw: extened status word
- + * @esw: extended status word
- * @ecw: extended control word
- *
- * The irb that is handed to the device driver when an interrupt occurs. For
- diff -Nur linux-3.14.35.orig/arch/sh/include/asm/ftrace.h linux-3.14.35/arch/sh/include/asm/ftrace.h
- --- linux-3.14.35.orig/arch/sh/include/asm/ftrace.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/sh/include/asm/ftrace.h 2015-03-08 14:27:37.457684502 -0500
- @@ -40,15 +40,7 @@
- /* arch/sh/kernel/return_address.c */
- extern void *return_address(unsigned int);
-
- -#define HAVE_ARCH_CALLER_ADDR
- -
- -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
- -#define CALLER_ADDR1 ((unsigned long)return_address(1))
- -#define CALLER_ADDR2 ((unsigned long)return_address(2))
- -#define CALLER_ADDR3 ((unsigned long)return_address(3))
- -#define CALLER_ADDR4 ((unsigned long)return_address(4))
- -#define CALLER_ADDR5 ((unsigned long)return_address(5))
- -#define CALLER_ADDR6 ((unsigned long)return_address(6))
- +#define ftrace_return_address(n) return_address(n)
-
- #endif /* __ASSEMBLY__ */
-
- diff -Nur linux-3.14.35.orig/arch/x86/kernel/setup.c linux-3.14.35/arch/x86/kernel/setup.c
- --- linux-3.14.35.orig/arch/x86/kernel/setup.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/arch/x86/kernel/setup.c 2015-03-08 14:27:37.457684502 -0500
- @@ -1120,7 +1120,7 @@
- setup_real_mode();
-
- memblock_set_current_limit(get_max_mapped());
- - dma_contiguous_reserve(0);
- + dma_contiguous_reserve(max_pfn_mapped << PAGE_SHIFT);
-
- /*
- * NOTE: On x86-32, only from this point on, fixmaps are ready for use.
- diff -Nur linux-3.14.35.orig/block/bfq-cgroup.c linux-3.14.35/block/bfq-cgroup.c
- --- linux-3.14.35.orig/block/bfq-cgroup.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/block/bfq-cgroup.c 2015-03-08 14:27:37.457684502 -0500
- @@ -0,0 +1,932 @@
- +/*
- + * BFQ: CGROUPS support.
- + *
- + * Based on ideas and code from CFQ:
- + * Copyright (C) 2003 Jens Axboe <axboe@kernel.dk>
- + *
- + * Copyright (C) 2008 Fabio Checconi <fabio@gandalf.sssup.it>
- + * Paolo Valente <paolo.valente@unimore.it>
- + *
- + * Copyright (C) 2010 Paolo Valente <paolo.valente@unimore.it>
- + *
- + * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ
- + * file.
- + */
- +
- +#ifdef CONFIG_CGROUP_BFQIO
- +
- +static DEFINE_MUTEX(bfqio_mutex);
- +
- +static bool bfqio_is_removed(struct bfqio_cgroup *bgrp)
- +{
- + return bgrp ? !bgrp->online : false;
- +}
- +
- +static struct bfqio_cgroup bfqio_root_cgroup = {
- + .weight = BFQ_DEFAULT_GRP_WEIGHT,
- + .ioprio = BFQ_DEFAULT_GRP_IOPRIO,
- + .ioprio_class = BFQ_DEFAULT_GRP_CLASS,
- +};
- +
- +static inline void bfq_init_entity(struct bfq_entity *entity,
- + struct bfq_group *bfqg)
- +{
- + entity->weight = entity->new_weight;
- + entity->orig_weight = entity->new_weight;
- + entity->ioprio = entity->new_ioprio;
- + entity->ioprio_class = entity->new_ioprio_class;
- + entity->parent = bfqg->my_entity;
- + entity->sched_data = &bfqg->sched_data;
- +}
- +
- +static struct bfqio_cgroup *css_to_bfqio(struct cgroup_subsys_state *css)
- +{
- + return css ? container_of(css, struct bfqio_cgroup, css) : NULL;
- +}
- +
- +/*
- + * Search the bfq_group for bfqd into the hash table (by now only a list)
- + * of bgrp. Must be called under rcu_read_lock().
- + */
- +static struct bfq_group *bfqio_lookup_group(struct bfqio_cgroup *bgrp,
- + struct bfq_data *bfqd)
- +{
- + struct bfq_group *bfqg;
- + void *key;
- +
- + hlist_for_each_entry_rcu(bfqg, &bgrp->group_data, group_node) {
- + key = rcu_dereference(bfqg->bfqd);
- + if (key == bfqd)
- + return bfqg;
- + }
- +
- + return NULL;
- +}
- +
- +static inline void bfq_group_init_entity(struct bfqio_cgroup *bgrp,
- + struct bfq_group *bfqg)
- +{
- + struct bfq_entity *entity = &bfqg->entity;
- +
- + /*
- + * If the weight of the entity has never been set via the sysfs
- + * interface, then bgrp->weight == 0. In this case we initialize
- + * the weight from the current ioprio value. Otherwise, the group
- + * weight, if set, has priority over the ioprio value.
- + */
- + if (bgrp->weight == 0) {
- + entity->new_weight = bfq_ioprio_to_weight(bgrp->ioprio);
- + entity->new_ioprio = bgrp->ioprio;
- + } else {
- + entity->new_weight = bgrp->weight;
- + entity->new_ioprio = bfq_weight_to_ioprio(bgrp->weight);
- + }
- + entity->orig_weight = entity->weight = entity->new_weight;
- + entity->ioprio = entity->new_ioprio;
- + entity->ioprio_class = entity->new_ioprio_class = bgrp->ioprio_class;
- + entity->my_sched_data = &bfqg->sched_data;
- + bfqg->active_entities = 0;
- +}
- +
- +static inline void bfq_group_set_parent(struct bfq_group *bfqg,
- + struct bfq_group *parent)
- +{
- + struct bfq_entity *entity;
- +
- + BUG_ON(parent == NULL);
- + BUG_ON(bfqg == NULL);
- +
- + entity = &bfqg->entity;
- + entity->parent = parent->my_entity;
- + entity->sched_data = &parent->sched_data;
- +}
- +
- +/**
- + * bfq_group_chain_alloc - allocate a chain of groups.
- + * @bfqd: queue descriptor.
- + * @css: the leaf cgroup_subsys_state this chain starts from.
- + *
- + * Allocate a chain of groups starting from the one belonging to
- + * @cgroup up to the root cgroup. Stop if a cgroup on the chain
- + * to the root has already an allocated group on @bfqd.
- + */
- +static struct bfq_group *bfq_group_chain_alloc(struct bfq_data *bfqd,
- + struct cgroup_subsys_state *css)
- +{
- + struct bfqio_cgroup *bgrp;
- + struct bfq_group *bfqg, *prev = NULL, *leaf = NULL;
- +
- + for (; css != NULL; css = css->parent) {
- + bgrp = css_to_bfqio(css);
- +
- + bfqg = bfqio_lookup_group(bgrp, bfqd);
- + if (bfqg != NULL) {
- + /*
- + * All the cgroups in the path from there to the
- + * root must have a bfq_group for bfqd, so we don't
- + * need any more allocations.
- + */
- + break;
- + }
- +
- + bfqg = kzalloc(sizeof(*bfqg), GFP_ATOMIC);
- + if (bfqg == NULL)
- + goto cleanup;
- +
- + bfq_group_init_entity(bgrp, bfqg);
- + bfqg->my_entity = &bfqg->entity;
- +
- + if (leaf == NULL) {
- + leaf = bfqg;
- + prev = leaf;
- + } else {
- + bfq_group_set_parent(prev, bfqg);
- + /*
- + * Build a list of allocated nodes using the bfqd
- + * filed, that is still unused and will be
- + * initialized only after the node will be
- + * connected.
- + */
- + prev->bfqd = bfqg;
- + prev = bfqg;
- + }
- + }
- +
- + return leaf;
- +
- +cleanup:
- + while (leaf != NULL) {
- + prev = leaf;
- + leaf = leaf->bfqd;
- + kfree(prev);
- + }
- +
- + return NULL;
- +}
- +
- +/**
- + * bfq_group_chain_link - link an allocated group chain to a cgroup
- + * hierarchy.
- + * @bfqd: the queue descriptor.
- + * @css: the leaf cgroup_subsys_state to start from.
- + * @leaf: the leaf group (to be associated to @cgroup).
- + *
- + * Try to link a chain of groups to a cgroup hierarchy, connecting the
- + * nodes bottom-up, so we can be sure that when we find a cgroup in the
- + * hierarchy that already as a group associated to @bfqd all the nodes
- + * in the path to the root cgroup have one too.
- + *
- + * On locking: the queue lock protects the hierarchy (there is a hierarchy
- + * per device) while the bfqio_cgroup lock protects the list of groups
- + * belonging to the same cgroup.
- + */
- +static void bfq_group_chain_link(struct bfq_data *bfqd,
- + struct cgroup_subsys_state *css,
- + struct bfq_group *leaf)
- +{
- + struct bfqio_cgroup *bgrp;
- + struct bfq_group *bfqg, *next, *prev = NULL;
- + unsigned long flags;
- +
- + assert_spin_locked(bfqd->queue->queue_lock);
- +
- + for (; css != NULL && leaf != NULL; css = css->parent) {
- + bgrp = css_to_bfqio(css);
- + next = leaf->bfqd;
- +
- + bfqg = bfqio_lookup_group(bgrp, bfqd);
- + BUG_ON(bfqg != NULL);
- +
- + spin_lock_irqsave(&bgrp->lock, flags);
- +
- + rcu_assign_pointer(leaf->bfqd, bfqd);
- + hlist_add_head_rcu(&leaf->group_node, &bgrp->group_data);
- + hlist_add_head(&leaf->bfqd_node, &bfqd->group_list);
- +
- + spin_unlock_irqrestore(&bgrp->lock, flags);
- +
- + prev = leaf;
- + leaf = next;
- + }
- +
- + BUG_ON(css == NULL && leaf != NULL);
- + if (css != NULL && prev != NULL) {
- + bgrp = css_to_bfqio(css);
- + bfqg = bfqio_lookup_group(bgrp, bfqd);
- + bfq_group_set_parent(prev, bfqg);
- + }
- +}
- +
- +/**
- + * bfq_find_alloc_group - return the group associated to @bfqd in @cgroup.
- + * @bfqd: queue descriptor.
- + * @cgroup: cgroup being searched for.
- + *
- + * Return a group associated to @bfqd in @cgroup, allocating one if
- + * necessary. When a group is returned all the cgroups in the path
- + * to the root have a group associated to @bfqd.
- + *
- + * If the allocation fails, return the root group: this breaks guarantees
- + * but is a safe fallback. If this loss becomes a problem it can be
- + * mitigated using the equivalent weight (given by the product of the
- + * weights of the groups in the path from @group to the root) in the
- + * root scheduler.
- + *
- + * We allocate all the missing nodes in the path from the leaf cgroup
- + * to the root and we connect the nodes only after all the allocations
- + * have been successful.
- + */
- +static struct bfq_group *bfq_find_alloc_group(struct bfq_data *bfqd,
- + struct cgroup_subsys_state *css)
- +{
- + struct bfqio_cgroup *bgrp = css_to_bfqio(css);
- + struct bfq_group *bfqg;
- +
- + bfqg = bfqio_lookup_group(bgrp, bfqd);
- + if (bfqg != NULL)
- + return bfqg;
- +
- + bfqg = bfq_group_chain_alloc(bfqd, css);
- + if (bfqg != NULL)
- + bfq_group_chain_link(bfqd, css, bfqg);
- + else
- + bfqg = bfqd->root_group;
- +
- + return bfqg;
- +}
- +
- +/**
- + * bfq_bfqq_move - migrate @bfqq to @bfqg.
- + * @bfqd: queue descriptor.
- + * @bfqq: the queue to move.
- + * @entity: @bfqq's entity.
- + * @bfqg: the group to move to.
- + *
- + * Move @bfqq to @bfqg, deactivating it from its old group and reactivating
- + * it on the new one. Avoid putting the entity on the old group idle tree.
- + *
- + * Must be called under the queue lock; the cgroup owning @bfqg must
- + * not disappear (by now this just means that we are called under
- + * rcu_read_lock()).
- + */
- +static void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
- + struct bfq_entity *entity, struct bfq_group *bfqg)
- +{
- + int busy, resume;
- +
- + busy = bfq_bfqq_busy(bfqq);
- + resume = !RB_EMPTY_ROOT(&bfqq->sort_list);
- +
- + BUG_ON(resume && !entity->on_st);
- + BUG_ON(busy && !resume && entity->on_st &&
- + bfqq != bfqd->in_service_queue);
- +
- + if (busy) {
- + BUG_ON(atomic_read(&bfqq->ref) < 2);
- +
- + if (!resume)
- + bfq_del_bfqq_busy(bfqd, bfqq, 0);
- + else
- + bfq_deactivate_bfqq(bfqd, bfqq, 0);
- + } else if (entity->on_st)
- + bfq_put_idle_entity(bfq_entity_service_tree(entity), entity);
- +
- + /*
- + * Here we use a reference to bfqg. We don't need a refcounter
- + * as the cgroup reference will not be dropped, so that its
- + * destroy() callback will not be invoked.
- + */
- + entity->parent = bfqg->my_entity;
- + entity->sched_data = &bfqg->sched_data;
- +
- + if (busy && resume)
- + bfq_activate_bfqq(bfqd, bfqq);
- +
- + if (bfqd->in_service_queue == NULL && !bfqd->rq_in_driver)
- + bfq_schedule_dispatch(bfqd);
- +}
- +
- +/**
- + * __bfq_bic_change_cgroup - move @bic to @cgroup.
- + * @bfqd: the queue descriptor.
- + * @bic: the bic to move.
- + * @cgroup: the cgroup to move to.
- + *
- + * Move bic to cgroup, assuming that bfqd->queue is locked; the caller
- + * has to make sure that the reference to cgroup is valid across the call.
- + *
- + * NOTE: an alternative approach might have been to store the current
- + * cgroup in bfqq and getting a reference to it, reducing the lookup
- + * time here, at the price of slightly more complex code.
- + */
- +static struct bfq_group *__bfq_bic_change_cgroup(struct bfq_data *bfqd,
- + struct bfq_io_cq *bic,
- + struct cgroup_subsys_state *css)
- +{
- + struct bfq_queue *async_bfqq = bic_to_bfqq(bic, 0);
- + struct bfq_queue *sync_bfqq = bic_to_bfqq(bic, 1);
- + struct bfq_entity *entity;
- + struct bfq_group *bfqg;
- + struct bfqio_cgroup *bgrp;
- +
- + bgrp = css_to_bfqio(css);
- +
- + bfqg = bfq_find_alloc_group(bfqd, css);
- + if (async_bfqq != NULL) {
- + entity = &async_bfqq->entity;
- +
- + if (entity->sched_data != &bfqg->sched_data) {
- + bic_set_bfqq(bic, NULL, 0);
- + bfq_log_bfqq(bfqd, async_bfqq,
- + "bic_change_group: %p %d",
- + async_bfqq, atomic_read(&async_bfqq->ref));
- + bfq_put_queue(async_bfqq);
- + }
- + }
- +
- + if (sync_bfqq != NULL) {
- + entity = &sync_bfqq->entity;
- + if (entity->sched_data != &bfqg->sched_data)
- + bfq_bfqq_move(bfqd, sync_bfqq, entity, bfqg);
- + }
- +
- + return bfqg;
- +}
- +
- +/**
- + * bfq_bic_change_cgroup - move @bic to @cgroup.
- + * @bic: the bic being migrated.
- + * @cgroup: the destination cgroup.
- + *
- + * When the task owning @bic is moved to @cgroup, @bic is immediately
- + * moved into its new parent group.
- + */
- +static void bfq_bic_change_cgroup(struct bfq_io_cq *bic,
- + struct cgroup_subsys_state *css)
- +{
- + struct bfq_data *bfqd;
- + unsigned long uninitialized_var(flags);
- +
- + bfqd = bfq_get_bfqd_locked(&(bic->icq.q->elevator->elevator_data),
- + &flags);
- + if (bfqd != NULL) {
- + __bfq_bic_change_cgroup(bfqd, bic, css);
- + bfq_put_bfqd_unlock(bfqd, &flags);
- + }
- +}
- +
- +/**
- + * bfq_bic_update_cgroup - update the cgroup of @bic.
- + * @bic: the @bic to update.
- + *
- + * Make sure that @bic is enqueued in the cgroup of the current task.
- + * We need this in addition to moving bics during the cgroup attach
- + * phase because the task owning @bic could be at its first disk
- + * access or we may end up in the root cgroup as the result of a
- + * memory allocation failure and here we try to move to the right
- + * group.
- + *
- + * Must be called under the queue lock. It is safe to use the returned
- + * value even after the rcu_read_unlock() as the migration/destruction
- + * paths act under the queue lock too. IOW it is impossible to race with
- + * group migration/destruction and end up with an invalid group as:
- + * a) here cgroup has not yet been destroyed, nor its destroy callback
- + * has started execution, as current holds a reference to it,
- + * b) if it is destroyed after rcu_read_unlock() [after current is
- + * migrated to a different cgroup] its attach() callback will have
- + * taken care of remove all the references to the old cgroup data.
- + */
- +static struct bfq_group *bfq_bic_update_cgroup(struct bfq_io_cq *bic)
- +{
- + struct bfq_data *bfqd = bic_to_bfqd(bic);
- + struct bfq_group *bfqg;
- + struct cgroup_subsys_state *css;
- +
- + BUG_ON(bfqd == NULL);
- +
- + rcu_read_lock();
- + css = task_css(current, bfqio_subsys_id);
- + bfqg = __bfq_bic_change_cgroup(bfqd, bic, css);
- + rcu_read_unlock();
- +
- + return bfqg;
- +}
- +
- +/**
- + * bfq_flush_idle_tree - deactivate any entity on the idle tree of @st.
- + * @st: the service tree being flushed.
- + */
- +static inline void bfq_flush_idle_tree(struct bfq_service_tree *st)
- +{
- + struct bfq_entity *entity = st->first_idle;
- +
- + for (; entity != NULL; entity = st->first_idle)
- + __bfq_deactivate_entity(entity, 0);
- +}
- +
- +/**
- + * bfq_reparent_leaf_entity - move leaf entity to the root_group.
- + * @bfqd: the device data structure with the root group.
- + * @entity: the entity to move.
- + */
- +static inline void bfq_reparent_leaf_entity(struct bfq_data *bfqd,
- + struct bfq_entity *entity)
- +{
- + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
- +
- + BUG_ON(bfqq == NULL);
- + bfq_bfqq_move(bfqd, bfqq, entity, bfqd->root_group);
- + return;
- +}
- +
- +/**
- + * bfq_reparent_active_entities - move to the root group all active
- + * entities.
- + * @bfqd: the device data structure with the root group.
- + * @bfqg: the group to move from.
- + * @st: the service tree with the entities.
- + *
- + * Needs queue_lock to be taken and reference to be valid over the call.
- + */
- +static inline void bfq_reparent_active_entities(struct bfq_data *bfqd,
- + struct bfq_group *bfqg,
- + struct bfq_service_tree *st)
- +{
- + struct rb_root *active = &st->active;
- + struct bfq_entity *entity = NULL;
- +
- + if (!RB_EMPTY_ROOT(&st->active))
- + entity = bfq_entity_of(rb_first(active));
- +
- + for (; entity != NULL; entity = bfq_entity_of(rb_first(active)))
- + bfq_reparent_leaf_entity(bfqd, entity);
- +
- + if (bfqg->sched_data.in_service_entity != NULL)
- + bfq_reparent_leaf_entity(bfqd,
- + bfqg->sched_data.in_service_entity);
- +
- + return;
- +}
- +
- +/**
- + * bfq_destroy_group - destroy @bfqg.
- + * @bgrp: the bfqio_cgroup containing @bfqg.
- + * @bfqg: the group being destroyed.
- + *
- + * Destroy @bfqg, making sure that it is not referenced from its parent.
- + */
- +static void bfq_destroy_group(struct bfqio_cgroup *bgrp, struct bfq_group *bfqg)
- +{
- + struct bfq_data *bfqd;
- + struct bfq_service_tree *st;
- + struct bfq_entity *entity = bfqg->my_entity;
- + unsigned long uninitialized_var(flags);
- + int i;
- +
- + hlist_del(&bfqg->group_node);
- +
- + /*
- + * Empty all service_trees belonging to this group before
- + * deactivating the group itself.
- + */
- + for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) {
- + st = bfqg->sched_data.service_tree + i;
- +
- + /*
- + * The idle tree may still contain bfq_queues belonging
- + * to exited task because they never migrated to a different
- + * cgroup from the one being destroyed now. No one else
- + * can access them so it's safe to act without any lock.
- + */
- + bfq_flush_idle_tree(st);
- +
- + /*
- + * It may happen that some queues are still active
- + * (busy) upon group destruction (if the corresponding
- + * processes have been forced to terminate). We move
- + * all the leaf entities corresponding to these queues
- + * to the root_group.
- + * Also, it may happen that the group has an entity
- + * in service, which is disconnected from the active
- + * tree: it must be moved, too.
- + * There is no need to put the sync queues, as the
- + * scheduler has taken no reference.
- + */
- + bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags);
- + if (bfqd != NULL) {
- + bfq_reparent_active_entities(bfqd, bfqg, st);
- + bfq_put_bfqd_unlock(bfqd, &flags);
- + }
- + BUG_ON(!RB_EMPTY_ROOT(&st->active));
- + BUG_ON(!RB_EMPTY_ROOT(&st->idle));
- + }
- + BUG_ON(bfqg->sched_data.next_in_service != NULL);
- + BUG_ON(bfqg->sched_data.in_service_entity != NULL);
- +
- + /*
- + * We may race with device destruction, take extra care when
- + * dereferencing bfqg->bfqd.
- + */
- + bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags);
- + if (bfqd != NULL) {
- + hlist_del(&bfqg->bfqd_node);
- + __bfq_deactivate_entity(entity, 0);
- + bfq_put_async_queues(bfqd, bfqg);
- + bfq_put_bfqd_unlock(bfqd, &flags);
- + }
- + BUG_ON(entity->tree != NULL);
- +
- + /*
- + * No need to defer the kfree() to the end of the RCU grace
- + * period: we are called from the destroy() callback of our
- + * cgroup, so we can be sure that no one is a) still using
- + * this cgroup or b) doing lookups in it.
- + */
- + kfree(bfqg);
- +}
- +
- +static void bfq_end_wr_async(struct bfq_data *bfqd)
- +{
- + struct hlist_node *tmp;
- + struct bfq_group *bfqg;
- +
- + hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node)
- + bfq_end_wr_async_queues(bfqd, bfqg);
- + bfq_end_wr_async_queues(bfqd, bfqd->root_group);
- +}
- +
- +/**
- + * bfq_disconnect_groups - disconnect @bfqd from all its groups.
- + * @bfqd: the device descriptor being exited.
- + *
- + * When the device exits we just make sure that no lookup can return
- + * the now unused group structures. They will be deallocated on cgroup
- + * destruction.
- + */
- +static void bfq_disconnect_groups(struct bfq_data *bfqd)
- +{
- + struct hlist_node *tmp;
- + struct bfq_group *bfqg;
- +
- + bfq_log(bfqd, "disconnect_groups beginning");
- + hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node) {
- + hlist_del(&bfqg->bfqd_node);
- +
- + __bfq_deactivate_entity(bfqg->my_entity, 0);
- +
- + /*
- + * Don't remove from the group hash, just set an
- + * invalid key. No lookups can race with the
- + * assignment as bfqd is being destroyed; this
- + * implies also that new elements cannot be added
- + * to the list.
- + */
- + rcu_assign_pointer(bfqg->bfqd, NULL);
- +
- + bfq_log(bfqd, "disconnect_groups: put async for group %p",
- + bfqg);
- + bfq_put_async_queues(bfqd, bfqg);
- + }
- +}
- +
- +static inline void bfq_free_root_group(struct bfq_data *bfqd)
- +{
- + struct bfqio_cgroup *bgrp = &bfqio_root_cgroup;
- + struct bfq_group *bfqg = bfqd->root_group;
- +
- + bfq_put_async_queues(bfqd, bfqg);
- +
- + spin_lock_irq(&bgrp->lock);
- + hlist_del_rcu(&bfqg->group_node);
- + spin_unlock_irq(&bgrp->lock);
- +
- + /*
- + * No need to synchronize_rcu() here: since the device is gone
- + * there cannot be any read-side access to its root_group.
- + */
- + kfree(bfqg);
- +}
- +
- +static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node)
- +{
- + struct bfq_group *bfqg;
- + struct bfqio_cgroup *bgrp;
- + int i;
- +
- + bfqg = kzalloc_node(sizeof(*bfqg), GFP_KERNEL, node);
- + if (bfqg == NULL)
- + return NULL;
- +
- + bfqg->entity.parent = NULL;
- + for (i = 0; i < BFQ_IOPRIO_CLASSES; i++)
- + bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT;
- +
- + bgrp = &bfqio_root_cgroup;
- + spin_lock_irq(&bgrp->lock);
- + rcu_assign_pointer(bfqg->bfqd, bfqd);
- + hlist_add_head_rcu(&bfqg->group_node, &bgrp->group_data);
- + spin_unlock_irq(&bgrp->lock);
- +
- + return bfqg;
- +}
- +
- +#define SHOW_FUNCTION(__VAR) \
- +static u64 bfqio_cgroup_##__VAR##_read(struct cgroup_subsys_state *css, \
- + struct cftype *cftype) \
- +{ \
- + struct bfqio_cgroup *bgrp = css_to_bfqio(css); \
- + u64 ret = -ENODEV; \
- + \
- + mutex_lock(&bfqio_mutex); \
- + if (bfqio_is_removed(bgrp)) \
- + goto out_unlock; \
- + \
- + spin_lock_irq(&bgrp->lock); \
- + ret = bgrp->__VAR; \
- + spin_unlock_irq(&bgrp->lock); \
- + \
- +out_unlock: \
- + mutex_unlock(&bfqio_mutex); \
- + return ret; \
- +}
- +
- +SHOW_FUNCTION(weight);
- +SHOW_FUNCTION(ioprio);
- +SHOW_FUNCTION(ioprio_class);
- +#undef SHOW_FUNCTION
- +
- +#define STORE_FUNCTION(__VAR, __MIN, __MAX) \
- +static int bfqio_cgroup_##__VAR##_write(struct cgroup_subsys_state *css,\
- + struct cftype *cftype, \
- + u64 val) \
- +{ \
- + struct bfqio_cgroup *bgrp = css_to_bfqio(css); \
- + struct bfq_group *bfqg; \
- + int ret = -EINVAL; \
- + \
- + if (val < (__MIN) || val > (__MAX)) \
- + return ret; \
- + \
- + ret = -ENODEV; \
- + mutex_lock(&bfqio_mutex); \
- + if (bfqio_is_removed(bgrp)) \
- + goto out_unlock; \
- + ret = 0; \
- + \
- + spin_lock_irq(&bgrp->lock); \
- + bgrp->__VAR = (unsigned short)val; \
- + hlist_for_each_entry(bfqg, &bgrp->group_data, group_node) { \
- + /* \
- + * Setting the ioprio_changed flag of the entity \
- + * to 1 with new_##__VAR == ##__VAR would re-set \
- + * the value of the weight to its ioprio mapping. \
- + * Set the flag only if necessary. \
- + */ \
- + if ((unsigned short)val != bfqg->entity.new_##__VAR) { \
- + bfqg->entity.new_##__VAR = (unsigned short)val; \
- + /* \
- + * Make sure that the above new value has been \
- + * stored in bfqg->entity.new_##__VAR before \
- + * setting the ioprio_changed flag. In fact, \
- + * this flag may be read asynchronously (in \
- + * critical sections protected by a different \
- + * lock than that held here), and finding this \
- + * flag set may cause the execution of the code \
- + * for updating parameters whose value may \
- + * depend also on bfqg->entity.new_##__VAR (in \
- + * __bfq_entity_update_weight_prio). \
- + * This barrier makes sure that the new value \
- + * of bfqg->entity.new_##__VAR is correctly \
- + * seen in that code. \
- + */ \
- + smp_wmb(); \
- + bfqg->entity.ioprio_changed = 1; \
- + } \
- + } \
- + spin_unlock_irq(&bgrp->lock); \
- + \
- +out_unlock: \
- + mutex_unlock(&bfqio_mutex); \
- + return ret; \
- +}
- +
- +STORE_FUNCTION(weight, BFQ_MIN_WEIGHT, BFQ_MAX_WEIGHT);
- +STORE_FUNCTION(ioprio, 0, IOPRIO_BE_NR - 1);
- +STORE_FUNCTION(ioprio_class, IOPRIO_CLASS_RT, IOPRIO_CLASS_IDLE);
- +#undef STORE_FUNCTION
- +
- +static struct cftype bfqio_files[] = {
- + {
- + .name = "weight",
- + .read_u64 = bfqio_cgroup_weight_read,
- + .write_u64 = bfqio_cgroup_weight_write,
- + },
- + {
- + .name = "ioprio",
- + .read_u64 = bfqio_cgroup_ioprio_read,
- + .write_u64 = bfqio_cgroup_ioprio_write,
- + },
- + {
- + .name = "ioprio_class",
- + .read_u64 = bfqio_cgroup_ioprio_class_read,
- + .write_u64 = bfqio_cgroup_ioprio_class_write,
- + },
- + { }, /* terminate */
- +};
- +
- +static struct cgroup_subsys_state *bfqio_create(struct cgroup_subsys_state
- + *parent_css)
- +{
- + struct bfqio_cgroup *bgrp;
- +
- + if (parent_css != NULL) {
- + bgrp = kzalloc(sizeof(*bgrp), GFP_KERNEL);
- + if (bgrp == NULL)
- + return ERR_PTR(-ENOMEM);
- + } else
- + bgrp = &bfqio_root_cgroup;
- +
- + spin_lock_init(&bgrp->lock);
- + INIT_HLIST_HEAD(&bgrp->group_data);
- + bgrp->ioprio = BFQ_DEFAULT_GRP_IOPRIO;
- + bgrp->ioprio_class = BFQ_DEFAULT_GRP_CLASS;
- +
- + return &bgrp->css;
- +}
- +
- +/*
- + * We cannot support shared io contexts, as we have no means to support
- + * two tasks with the same ioc in two different groups without major rework
- + * of the main bic/bfqq data structures. By now we allow a task to change
- + * its cgroup only if it's the only owner of its ioc; the drawback of this
- + * behavior is that a group containing a task that forked using CLONE_IO
- + * will not be destroyed until the tasks sharing the ioc die.
- + */
- +static int bfqio_can_attach(struct cgroup_subsys_state *css,
- + struct cgroup_taskset *tset)
- +{
- + struct task_struct *task;
- + struct io_context *ioc;
- + int ret = 0;
- +
- + cgroup_taskset_for_each(task, css, tset) {
- + /*
- + * task_lock() is needed to avoid races with
- + * exit_io_context()
- + */
- + task_lock(task);
- + ioc = task->io_context;
- + if (ioc != NULL && atomic_read(&ioc->nr_tasks) > 1)
- + /*
- + * ioc == NULL means that the task is either too
- + * young or exiting: if it has still no ioc the
- + * ioc can't be shared, if the task is exiting the
- + * attach will fail anyway, no matter what we
- + * return here.
- + */
- + ret = -EINVAL;
- + task_unlock(task);
- + if (ret)
- + break;
- + }
- +
- + return ret;
- +}
- +
- +static void bfqio_attach(struct cgroup_subsys_state *css,
- + struct cgroup_taskset *tset)
- +{
- + struct task_struct *task;
- + struct io_context *ioc;
- + struct io_cq *icq;
- +
- + /*
- + * IMPORTANT NOTE: The move of more than one process at a time to a
- + * new group has not yet been tested.
- + */
- + cgroup_taskset_for_each(task, css, tset) {
- + ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE);
- + if (ioc) {
- + /*
- + * Handle cgroup change here.
- + */
- + rcu_read_lock();
- + hlist_for_each_entry_rcu(icq, &ioc->icq_list, ioc_node)
- + if (!strncmp(
- + icq->q->elevator->type->elevator_name,
- + "bfq", ELV_NAME_MAX))
- + bfq_bic_change_cgroup(icq_to_bic(icq),
- + css);
- + rcu_read_unlock();
- + put_io_context(ioc);
- + }
- + }
- +}
- +
- +static void bfqio_destroy(struct cgroup_subsys_state *css)
- +{
- + struct bfqio_cgroup *bgrp = css_to_bfqio(css);
- + struct hlist_node *tmp;
- + struct bfq_group *bfqg;
- +
- + /*
- + * Since we are destroying the cgroup, there are no more tasks
- + * referencing it, and all the RCU grace periods that may have
- + * referenced it are ended (as the destruction of the parent
- + * cgroup is RCU-safe); bgrp->group_data will not be accessed by
- + * anything else and we don't need any synchronization.
- + */
- + hlist_for_each_entry_safe(bfqg, tmp, &bgrp->group_data, group_node)
- + bfq_destroy_group(bgrp, bfqg);
- +
- + BUG_ON(!hlist_empty(&bgrp->group_data));
- +
- + kfree(bgrp);
- +}
- +
- +static int bfqio_css_online(struct cgroup_subsys_state *css)
- +{
- + struct bfqio_cgroup *bgrp = css_to_bfqio(css);
- +
- + mutex_lock(&bfqio_mutex);
- + bgrp->online = true;
- + mutex_unlock(&bfqio_mutex);
- +
- + return 0;
- +}
- +
- +static void bfqio_css_offline(struct cgroup_subsys_state *css)
- +{
- + struct bfqio_cgroup *bgrp = css_to_bfqio(css);
- +
- + mutex_lock(&bfqio_mutex);
- + bgrp->online = false;
- + mutex_unlock(&bfqio_mutex);
- +}
- +
- +struct cgroup_subsys bfqio_subsys = {
- + .name = "bfqio",
- + .css_alloc = bfqio_create,
- + .css_online = bfqio_css_online,
- + .css_offline = bfqio_css_offline,
- + .can_attach = bfqio_can_attach,
- + .attach = bfqio_attach,
- + .css_free = bfqio_destroy,
- + .subsys_id = bfqio_subsys_id,
- + .base_cftypes = bfqio_files,
- +};
- +#else
- +static inline void bfq_init_entity(struct bfq_entity *entity,
- + struct bfq_group *bfqg)
- +{
- + entity->weight = entity->new_weight;
- + entity->orig_weight = entity->new_weight;
- + entity->ioprio = entity->new_ioprio;
- + entity->ioprio_class = entity->new_ioprio_class;
- + entity->sched_data = &bfqg->sched_data;
- +}
- +
- +static inline struct bfq_group *
- +bfq_bic_update_cgroup(struct bfq_io_cq *bic)
- +{
- + struct bfq_data *bfqd = bic_to_bfqd(bic);
- + return bfqd->root_group;
- +}
- +
- +static inline void bfq_bfqq_move(struct bfq_data *bfqd,
- + struct bfq_queue *bfqq,
- + struct bfq_entity *entity,
- + struct bfq_group *bfqg)
- +{
- +}
- +
- +static void bfq_end_wr_async(struct bfq_data *bfqd)
- +{
- + bfq_end_wr_async_queues(bfqd, bfqd->root_group);
- +}
- +
- +static inline void bfq_disconnect_groups(struct bfq_data *bfqd)
- +{
- + bfq_put_async_queues(bfqd, bfqd->root_group);
- +}
- +
- +static inline void bfq_free_root_group(struct bfq_data *bfqd)
- +{
- + kfree(bfqd->root_group);
- +}
- +
- +static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node)
- +{
- + struct bfq_group *bfqg;
- + int i;
- +
- + bfqg = kmalloc_node(sizeof(*bfqg), GFP_KERNEL | __GFP_ZERO, node);
- + if (bfqg == NULL)
- + return NULL;
- +
- + for (i = 0; i < BFQ_IOPRIO_CLASSES; i++)
- + bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT;
- +
- + return bfqg;
- +}
- +#endif
- diff -Nur linux-3.14.35.orig/block/bfq.h linux-3.14.35/block/bfq.h
- --- linux-3.14.35.orig/block/bfq.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/block/bfq.h 2015-03-08 14:27:37.457684502 -0500
- @@ -0,0 +1,770 @@
- +/*
- + * BFQ-v7r5 for 3.14.0: data structures and common functions prototypes.
- + *
- + * Based on ideas and code from CFQ:
- + * Copyright (C) 2003 Jens Axboe <axboe@kernel.dk>
- + *
- + * Copyright (C) 2008 Fabio Checconi <fabio@gandalf.sssup.it>
- + * Paolo Valente <paolo.valente@unimore.it>
- + *
- + * Copyright (C) 2010 Paolo Valente <paolo.valente@unimore.it>
- + */
- +
- +#ifndef _BFQ_H
- +#define _BFQ_H
- +
- +#include <linux/blktrace_api.h>
- +#include <linux/hrtimer.h>
- +#include <linux/ioprio.h>
- +#include <linux/rbtree.h>
- +
- +#define BFQ_IOPRIO_CLASSES 3
- +#define BFQ_CL_IDLE_TIMEOUT (HZ/5)
- +
- +#define BFQ_MIN_WEIGHT 1
- +#define BFQ_MAX_WEIGHT 1000
- +
- +#define BFQ_DEFAULT_GRP_WEIGHT 10
- +#define BFQ_DEFAULT_GRP_IOPRIO 0
- +#define BFQ_DEFAULT_GRP_CLASS IOPRIO_CLASS_BE
- +
- +struct bfq_entity;
- +
- +/**
- + * struct bfq_service_tree - per ioprio_class service tree.
- + * @active: tree for active entities (i.e., those backlogged).
- + * @idle: tree for idle entities (i.e., those not backlogged, with V <= F_i).
- + * @first_idle: idle entity with minimum F_i.
- + * @last_idle: idle entity with maximum F_i.
- + * @vtime: scheduler virtual time.
- + * @wsum: scheduler weight sum; active and idle entities contribute to it.
- + *
- + * Each service tree represents a B-WF2Q+ scheduler on its own. Each
- + * ioprio_class has its own independent scheduler, and so its own
- + * bfq_service_tree. All the fields are protected by the queue lock
- + * of the containing bfqd.
- + */
- +struct bfq_service_tree {
- + struct rb_root active;
- + struct rb_root idle;
- +
- + struct bfq_entity *first_idle;
- + struct bfq_entity *last_idle;
- +
- + u64 vtime;
- + unsigned long wsum;
- +};
- +
- +/**
- + * struct bfq_sched_data - multi-class scheduler.
- + * @in_service_entity: entity in service.
- + * @next_in_service: head-of-the-line entity in the scheduler.
- + * @service_tree: array of service trees, one per ioprio_class.
- + *
- + * bfq_sched_data is the basic scheduler queue. It supports three
- + * ioprio_classes, and can be used either as a toplevel queue or as
- + * an intermediate queue on a hierarchical setup.
- + * @next_in_service points to the active entity of the sched_data
- + * service trees that will be scheduled next.
- + *
- + * The supported ioprio_classes are the same as in CFQ, in descending
- + * priority order, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE.
- + * Requests from higher priority queues are served before all the
- + * requests from lower priority queues; among requests of the same
- + * queue requests are served according to B-WF2Q+.
- + * All the fields are protected by the queue lock of the containing bfqd.
- + */
- +struct bfq_sched_data {
- + struct bfq_entity *in_service_entity;
- + struct bfq_entity *next_in_service;
- + struct bfq_service_tree service_tree[BFQ_IOPRIO_CLASSES];
- +};
- +
- +/**
- + * struct bfq_weight_counter - counter of the number of all active entities
- + * with a given weight.
- + * @weight: weight of the entities that this counter refers to.
- + * @num_active: number of active entities with this weight.
- + * @weights_node: weights tree member (see bfq_data's @queue_weights_tree
- + * and @group_weights_tree).
- + */
- +struct bfq_weight_counter {
- + short int weight;
- + unsigned int num_active;
- + struct rb_node weights_node;
- +};
- +
- +/**
- + * struct bfq_entity - schedulable entity.
- + * @rb_node: service_tree member.
- + * @weight_counter: pointer to the weight counter associated with this entity.
- + * @on_st: flag, true if the entity is on a tree (either the active or
- + * the idle one of its service_tree).
- + * @finish: B-WF2Q+ finish timestamp (aka F_i).
- + * @start: B-WF2Q+ start timestamp (aka S_i).
- + * @tree: tree the entity is enqueued into; %NULL if not on a tree.
- + * @min_start: minimum start time of the (active) subtree rooted at
- + * this entity; used for O(log N) lookups into active trees.
- + * @service: service received during the last round of service.
- + * @budget: budget used to calculate F_i; F_i = S_i + @budget / @weight.
- + * @weight: weight of the queue
- + * @parent: parent entity, for hierarchical scheduling.
- + * @my_sched_data: for non-leaf nodes in the cgroup hierarchy, the
- + * associated scheduler queue, %NULL on leaf nodes.
- + * @sched_data: the scheduler queue this entity belongs to.
- + * @ioprio: the ioprio in use.
- + * @new_weight: when a weight change is requested, the new weight value.
- + * @orig_weight: original weight, used to implement weight boosting
- + * @new_ioprio: when an ioprio change is requested, the new ioprio value.
- + * @ioprio_class: the ioprio_class in use.
- + * @new_ioprio_class: when an ioprio_class change is requested, the new
- + * ioprio_class value.
- + * @ioprio_changed: flag, true when the user requested a weight, ioprio or
- + * ioprio_class change.
- + *
- + * A bfq_entity is used to represent either a bfq_queue (leaf node in the
- + * cgroup hierarchy) or a bfq_group into the upper level scheduler. Each
- + * entity belongs to the sched_data of the parent group in the cgroup
- + * hierarchy. Non-leaf entities have also their own sched_data, stored
- + * in @my_sched_data.
- + *
- + * Each entity stores independently its priority values; this would
- + * allow different weights on different devices, but this
- + * functionality is not exported to userspace by now. Priorities and
- + * weights are updated lazily, first storing the new values into the
- + * new_* fields, then setting the @ioprio_changed flag. As soon as
- + * there is a transition in the entity state that allows the priority
- + * update to take place the effective and the requested priority
- + * values are synchronized.
- + *
- + * Unless cgroups are used, the weight value is calculated from the
- + * ioprio to export the same interface as CFQ. When dealing with
- + * ``well-behaved'' queues (i.e., queues that do not spend too much
- + * time to consume their budget and have true sequential behavior, and
- + * when there are no external factors breaking anticipation) the
- + * relative weights at each level of the cgroups hierarchy should be
- + * guaranteed. All the fields are protected by the queue lock of the
- + * containing bfqd.
- + */
- +struct bfq_entity {
- + struct rb_node rb_node;
- + struct bfq_weight_counter *weight_counter;
- +
- + int on_st;
- +
- + u64 finish;
- + u64 start;
- +
- + struct rb_root *tree;
- +
- + u64 min_start;
- +
- + unsigned long service, budget;
- + unsigned short weight, new_weight;
- + unsigned short orig_weight;
- +
- + struct bfq_entity *parent;
- +
- + struct bfq_sched_data *my_sched_data;
- + struct bfq_sched_data *sched_data;
- +
- + unsigned short ioprio, new_ioprio;
- + unsigned short ioprio_class, new_ioprio_class;
- +
- + int ioprio_changed;
- +};
- +
- +struct bfq_group;
- +
- +/**
- + * struct bfq_queue - leaf schedulable entity.
- + * @ref: reference counter.
- + * @bfqd: parent bfq_data.
- + * @new_bfqq: shared bfq_queue if queue is cooperating with
- + * one or more other queues.
- + * @pos_node: request-position tree member (see bfq_data's @rq_pos_tree).
- + * @pos_root: request-position tree root (see bfq_data's @rq_pos_tree).
- + * @sort_list: sorted list of pending requests.
- + * @next_rq: if fifo isn't expired, next request to serve.
- + * @queued: nr of requests queued in @sort_list.
- + * @allocated: currently allocated requests.
- + * @meta_pending: pending metadata requests.
- + * @fifo: fifo list of requests in sort_list.
- + * @entity: entity representing this queue in the scheduler.
- + * @max_budget: maximum budget allowed from the feedback mechanism.
- + * @budget_timeout: budget expiration (in jiffies).
- + * @dispatched: number of requests on the dispatch list or inside driver.
- + * @flags: status flags.
- + * @bfqq_list: node for active/idle bfqq list inside our bfqd.
- + * @seek_samples: number of seeks sampled
- + * @seek_total: sum of the distances of the seeks sampled
- + * @seek_mean: mean seek distance
- + * @last_request_pos: position of the last request enqueued
- + * @requests_within_timer: number of consecutive pairs of request completion
- + * and arrival, such that the queue becomes idle
- + * after the completion, but the next request arrives
- + * within an idle time slice; used only if the queue's
- + * IO_bound has been cleared.
- + * @pid: pid of the process owning the queue, used for logging purposes.
- + * @last_wr_start_finish: start time of the current weight-raising period if
- + * the @bfq-queue is being weight-raised, otherwise
- + * finish time of the last weight-raising period
- + * @wr_cur_max_time: current max raising time for this queue
- + * @soft_rt_next_start: minimum time instant such that, only if a new
- + * request is enqueued after this time instant in an
- + * idle @bfq_queue with no outstanding requests, then
- + * the task associated with the queue it is deemed as
- + * soft real-time (see the comments to the function
- + * bfq_bfqq_softrt_next_start())
- + * @last_idle_bklogged: time of the last transition of the @bfq_queue from
- + * idle to backlogged
- + * @service_from_backlogged: cumulative service received from the @bfq_queue
- + * since the last transition from idle to
- + * backlogged
- + * @bic: pointer to the bfq_io_cq owning the bfq_queue, set to %NULL if the
- + * queue is shared
- + *
- + * A bfq_queue is a leaf request queue; it can be associated with an
- + * io_context or more, if it is async or shared between cooperating
- + * processes. @cgroup holds a reference to the cgroup, to be sure that it
- + * does not disappear while a bfqq still references it (mostly to avoid
- + * races between request issuing and task migration followed by cgroup
- + * destruction).
- + * All the fields are protected by the queue lock of the containing bfqd.
- + */
- +struct bfq_queue {
- + atomic_t ref;
- + struct bfq_data *bfqd;
- +
- + /* fields for cooperating queues handling */
- + struct bfq_queue *new_bfqq;
- + struct rb_node pos_node;
- + struct rb_root *pos_root;
- +
- + struct rb_root sort_list;
- + struct request *next_rq;
- + int queued[2];
- + int allocated[2];
- + int meta_pending;
- + struct list_head fifo;
- +
- + struct bfq_entity entity;
- +
- + unsigned long max_budget;
- + unsigned long budget_timeout;
- +
- + int dispatched;
- +
- + unsigned int flags;
- +
- + struct list_head bfqq_list;
- +
- + unsigned int seek_samples;
- + u64 seek_total;
- + sector_t seek_mean;
- + sector_t last_request_pos;
- +
- + unsigned int requests_within_timer;
- +
- + pid_t pid;
- + struct bfq_io_cq *bic;
- +
- + /* weight-raising fields */
- + unsigned long wr_cur_max_time;
- + unsigned long soft_rt_next_start;
- + unsigned long last_wr_start_finish;
- + unsigned int wr_coeff;
- + unsigned long last_idle_bklogged;
- + unsigned long service_from_backlogged;
- +};
- +
- +/**
- + * struct bfq_ttime - per process thinktime stats.
- + * @ttime_total: total process thinktime
- + * @ttime_samples: number of thinktime samples
- + * @ttime_mean: average process thinktime
- + */
- +struct bfq_ttime {
- + unsigned long last_end_request;
- +
- + unsigned long ttime_total;
- + unsigned long ttime_samples;
- + unsigned long ttime_mean;
- +};
- +
- +/**
- + * struct bfq_io_cq - per (request_queue, io_context) structure.
- + * @icq: associated io_cq structure
- + * @bfqq: array of two process queues, the sync and the async
- + * @ttime: associated @bfq_ttime struct
- + * @wr_time_left: snapshot of the time left before weight raising ends
- + * for the sync queue associated to this process; this
- + * snapshot is taken to remember this value while the weight
- + * raising is suspended because the queue is merged with a
- + * shared queue, and is used to set @raising_cur_max_time
- + * when the queue is split from the shared queue and its
- + * weight is raised again
- + * @saved_idle_window: same purpose as the previous field for the idle
- + * window
- + * @saved_IO_bound: same purpose as the previous two fields for the I/O
- + * bound classification of a queue
- + * @cooperations: counter of consecutive successful queue merges underwent
- + * by any of the process' @bfq_queues
- + * @failed_cooperations: counter of consecutive failed queue merges of any
- + * of the process' @bfq_queues
- + */
- +struct bfq_io_cq {
- + struct io_cq icq; /* must be the first member */
- + struct bfq_queue *bfqq[2];
- + struct bfq_ttime ttime;
- + int ioprio;
- +
- + unsigned int wr_time_left;
- + unsigned int saved_idle_window;
- + unsigned int saved_IO_bound;
- +
- + unsigned int cooperations;
- + unsigned int failed_cooperations;
- +};
- +
- +enum bfq_device_speed {
- + BFQ_BFQD_FAST,
- + BFQ_BFQD_SLOW,
- +};
- +
- +/**
- + * struct bfq_data - per device data structure.
- + * @queue: request queue for the managed device.
- + * @root_group: root bfq_group for the device.
- + * @rq_pos_tree: rbtree sorted by next_request position, used when
- + * determining if two or more queues have interleaving
- + * requests (see bfq_close_cooperator()).
- + * @active_numerous_groups: number of bfq_groups containing more than one
- + * active @bfq_entity.
- + * @queue_weights_tree: rbtree of weight counters of @bfq_queues, sorted by
- + * weight. Used to keep track of whether all @bfq_queues
- + * have the same weight. The tree contains one counter
- + * for each distinct weight associated to some active
- + * and not weight-raised @bfq_queue (see the comments to
- + * the functions bfq_weights_tree_[add|remove] for
- + * further details).
- + * @group_weights_tree: rbtree of non-queue @bfq_entity weight counters, sorted
- + * by weight. Used to keep track of whether all
- + * @bfq_groups have the same weight. The tree contains
- + * one counter for each distinct weight associated to
- + * some active @bfq_group (see the comments to the
- + * functions bfq_weights_tree_[add|remove] for further
- + * details).
- + * @busy_queues: number of bfq_queues containing requests (including the
- + * queue in service, even if it is idling).
- + * @busy_in_flight_queues: number of @bfq_queues containing pending or
- + * in-flight requests, plus the @bfq_queue in
- + * service, even if idle but waiting for the
- + * possible arrival of its next sync request. This
- + * field is updated only if the device is rotational,
- + * but used only if the device is also NCQ-capable.
- + * The reason why the field is updated also for non-
- + * NCQ-capable rotational devices is related to the
- + * fact that the value of @hw_tag may be set also
- + * later than when busy_in_flight_queues may need to
- + * be incremented for the first time(s). Taking also
- + * this possibility into account, to avoid unbalanced
- + * increments/decrements, would imply more overhead
- + * than just updating busy_in_flight_queues
- + * regardless of the value of @hw_tag.
- + * @const_seeky_busy_in_flight_queues: number of constantly-seeky @bfq_queues
- + * (that is, seeky queues that expired
- + * for budget timeout at least once)
- + * containing pending or in-flight
- + * requests, including the in-service
- + * @bfq_queue if constantly seeky. This
- + * field is updated only if the device
- + * is rotational, but used only if the
- + * device is also NCQ-capable (see the
- + * comments to @busy_in_flight_queues).
- + * @wr_busy_queues: number of weight-raised busy @bfq_queues.
- + * @queued: number of queued requests.
- + * @rq_in_driver: number of requests dispatched and waiting for completion.
- + * @sync_flight: number of sync requests in the driver.
- + * @max_rq_in_driver: max number of reqs in driver in the last
- + * @hw_tag_samples completed requests.
- + * @hw_tag_samples: nr of samples used to calculate hw_tag.
- + * @hw_tag: flag set to one if the driver is showing a queueing behavior.
- + * @budgets_assigned: number of budgets assigned.
- + * @idle_slice_timer: timer set when idling for the next sequential request
- + * from the queue in service.
- + * @unplug_work: delayed work to restart dispatching on the request queue.
- + * @in_service_queue: bfq_queue in service.
- + * @in_service_bic: bfq_io_cq (bic) associated with the @in_service_queue.
- + * @last_position: on-disk position of the last served request.
- + * @last_budget_start: beginning of the last budget.
- + * @last_idling_start: beginning of the last idle slice.
- + * @peak_rate: peak transfer rate observed for a budget.
- + * @peak_rate_samples: number of samples used to calculate @peak_rate.
- + * @bfq_max_budget: maximum budget allotted to a bfq_queue before
- + * rescheduling.
- + * @group_list: list of all the bfq_groups active on the device.
- + * @active_list: list of all the bfq_queues active on the device.
- + * @idle_list: list of all the bfq_queues idle on the device.
- + * @bfq_quantum: max number of requests dispatched per dispatch round.
- + * @bfq_fifo_expire: timeout for async/sync requests; when it expires
- + * requests are served in fifo order.
- + * @bfq_back_penalty: weight of backward seeks wrt forward ones.
- + * @bfq_back_max: maximum allowed backward seek.
- + * @bfq_slice_idle: maximum idling time.
- + * @bfq_user_max_budget: user-configured max budget value
- + * (0 for auto-tuning).
- + * @bfq_max_budget_async_rq: maximum budget (in nr of requests) allotted to
- + * async queues.
- + * @bfq_timeout: timeout for bfq_queues to consume their budget; used to
- + * to prevent seeky queues to impose long latencies to well
- + * behaved ones (this also implies that seeky queues cannot
- + * receive guarantees in the service domain; after a timeout
- + * they are charged for the whole allocated budget, to try
- + * to preserve a behavior reasonably fair among them, but
- + * without service-domain guarantees).
- + * @bfq_coop_thresh: number of queue merges after which a @bfq_queue is
- + * no more granted any weight-raising.
- + * @bfq_failed_cooperations: number of consecutive failed cooperation
- + * chances after which weight-raising is restored
- + * to a queue subject to more than bfq_coop_thresh
- + * queue merges.
- + * @bfq_requests_within_timer: number of consecutive requests that must be
- + * issued within the idle time slice to set
- + * again idling to a queue which was marked as
- + * non-I/O-bound (see the definition of the
- + * IO_bound flag for further details).
- + * @bfq_wr_coeff: Maximum factor by which the weight of a weight-raised
- + * queue is multiplied
- + * @bfq_wr_max_time: maximum duration of a weight-raising period (jiffies)
- + * @bfq_wr_rt_max_time: maximum duration for soft real-time processes
- + * @bfq_wr_min_idle_time: minimum idle period after which weight-raising
- + * may be reactivated for a queue (in jiffies)
- + * @bfq_wr_min_inter_arr_async: minimum period between request arrivals
- + * after which weight-raising may be
- + * reactivated for an already busy queue
- + * (in jiffies)
- + * @bfq_wr_max_softrt_rate: max service-rate for a soft real-time queue,
- + * sectors per seconds
- + * @RT_prod: cached value of the product R*T used for computing the maximum
- + * duration of the weight raising automatically
- + * @device_speed: device-speed class for the low-latency heuristic
- + * @oom_bfqq: fallback dummy bfqq for extreme OOM conditions
- + *
- + * All the fields are protected by the @queue lock.
- + */
- +struct bfq_data {
- + struct request_queue *queue;
- +
- + struct bfq_group *root_group;
- + struct rb_root rq_pos_tree;
- +
- +#ifdef CONFIG_CGROUP_BFQIO
- + int active_numerous_groups;
- +#endif
- +
- + struct rb_root queue_weights_tree;
- + struct rb_root group_weights_tree;
- +
- + int busy_queues;
- + int busy_in_flight_queues;
- + int const_seeky_busy_in_flight_queues;
- + int wr_busy_queues;
- + int queued;
- + int rq_in_driver;
- + int sync_flight;
- +
- + int max_rq_in_driver;
- + int hw_tag_samples;
- + int hw_tag;
- +
- + int budgets_assigned;
- +
- + struct timer_list idle_slice_timer;
- + struct work_struct unplug_work;
- +
- + struct bfq_queue *in_service_queue;
- + struct bfq_io_cq *in_service_bic;
- +
- + sector_t last_position;
- +
- + ktime_t last_budget_start;
- + ktime_t last_idling_start;
- + int peak_rate_samples;
- + u64 peak_rate;
- + unsigned long bfq_max_budget;
- +
- + struct hlist_head group_list;
- + struct list_head active_list;
- + struct list_head idle_list;
- +
- + unsigned int bfq_quantum;
- + unsigned int bfq_fifo_expire[2];
- + unsigned int bfq_back_penalty;
- + unsigned int bfq_back_max;
- + unsigned int bfq_slice_idle;
- + u64 bfq_class_idle_last_service;
- +
- + unsigned int bfq_user_max_budget;
- + unsigned int bfq_max_budget_async_rq;
- + unsigned int bfq_timeout[2];
- +
- + unsigned int bfq_coop_thresh;
- + unsigned int bfq_failed_cooperations;
- + unsigned int bfq_requests_within_timer;
- +
- + bool low_latency;
- +
- + /* parameters of the low_latency heuristics */
- + unsigned int bfq_wr_coeff;
- + unsigned int bfq_wr_max_time;
- + unsigned int bfq_wr_rt_max_time;
- + unsigned int bfq_wr_min_idle_time;
- + unsigned long bfq_wr_min_inter_arr_async;
- + unsigned int bfq_wr_max_softrt_rate;
- + u64 RT_prod;
- + enum bfq_device_speed device_speed;
- +
- + struct bfq_queue oom_bfqq;
- +};
- +
- +enum bfqq_state_flags {
- + BFQ_BFQQ_FLAG_busy = 0, /* has requests or is in service */
- + BFQ_BFQQ_FLAG_wait_request, /* waiting for a request */
- + BFQ_BFQQ_FLAG_must_alloc, /* must be allowed rq alloc */
- + BFQ_BFQQ_FLAG_fifo_expire, /* FIFO checked in this slice */
- + BFQ_BFQQ_FLAG_idle_window, /* slice idling enabled */
- + BFQ_BFQQ_FLAG_prio_changed, /* task priority has changed */
- + BFQ_BFQQ_FLAG_sync, /* synchronous queue */
- + BFQ_BFQQ_FLAG_budget_new, /* no completion with this budget */
- + BFQ_BFQQ_FLAG_IO_bound, /*
- + * bfqq has timed-out at least once
- + * having consumed at most 2/10 of
- + * its budget
- + */
- + BFQ_BFQQ_FLAG_constantly_seeky, /*
- + * bfqq has proved to be slow and
- + * seeky until budget timeout
- + */
- + BFQ_BFQQ_FLAG_softrt_update, /*
- + * may need softrt-next-start
- + * update
- + */
- + BFQ_BFQQ_FLAG_coop, /* bfqq is shared */
- + BFQ_BFQQ_FLAG_split_coop, /* shared bfqq will be split */
- + BFQ_BFQQ_FLAG_just_split, /* queue has just been split */
- +};
- +
- +#define BFQ_BFQQ_FNS(name) \
- +static inline void bfq_mark_bfqq_##name(struct bfq_queue *bfqq) \
- +{ \
- + (bfqq)->flags |= (1 << BFQ_BFQQ_FLAG_##name); \
- +} \
- +static inline void bfq_clear_bfqq_##name(struct bfq_queue *bfqq) \
- +{ \
- + (bfqq)->flags &= ~(1 << BFQ_BFQQ_FLAG_##name); \
- +} \
- +static inline int bfq_bfqq_##name(const struct bfq_queue *bfqq) \
- +{ \
- + return ((bfqq)->flags & (1 << BFQ_BFQQ_FLAG_##name)) != 0; \
- +}
- +
- +BFQ_BFQQ_FNS(busy);
- +BFQ_BFQQ_FNS(wait_request);
- +BFQ_BFQQ_FNS(must_alloc);
- +BFQ_BFQQ_FNS(fifo_expire);
- +BFQ_BFQQ_FNS(idle_window);
- +BFQ_BFQQ_FNS(prio_changed);
- +BFQ_BFQQ_FNS(sync);
- +BFQ_BFQQ_FNS(budget_new);
- +BFQ_BFQQ_FNS(IO_bound);
- +BFQ_BFQQ_FNS(constantly_seeky);
- +BFQ_BFQQ_FNS(coop);
- +BFQ_BFQQ_FNS(split_coop);
- +BFQ_BFQQ_FNS(just_split);
- +BFQ_BFQQ_FNS(softrt_update);
- +#undef BFQ_BFQQ_FNS
- +
- +/* Logging facilities. */
- +#define bfq_log_bfqq(bfqd, bfqq, fmt, args...) \
- + blk_add_trace_msg((bfqd)->queue, "bfq%d " fmt, (bfqq)->pid, ##args)
- +
- +#define bfq_log(bfqd, fmt, args...) \
- + blk_add_trace_msg((bfqd)->queue, "bfq " fmt, ##args)
- +
- +/* Expiration reasons. */
- +enum bfqq_expiration {
- + BFQ_BFQQ_TOO_IDLE = 0, /*
- + * queue has been idling for
- + * too long
- + */
- + BFQ_BFQQ_BUDGET_TIMEOUT, /* budget took too long to be used */
- + BFQ_BFQQ_BUDGET_EXHAUSTED, /* budget consumed */
- + BFQ_BFQQ_NO_MORE_REQUESTS, /* the queue has no more requests */
- +};
- +
- +#ifdef CONFIG_CGROUP_BFQIO
- +/**
- + * struct bfq_group - per (device, cgroup) data structure.
- + * @entity: schedulable entity to insert into the parent group sched_data.
- + * @sched_data: own sched_data, to contain child entities (they may be
- + * both bfq_queues and bfq_groups).
- + * @group_node: node to be inserted into the bfqio_cgroup->group_data
- + * list of the containing cgroup's bfqio_cgroup.
- + * @bfqd_node: node to be inserted into the @bfqd->group_list list
- + * of the groups active on the same device; used for cleanup.
- + * @bfqd: the bfq_data for the device this group acts upon.
- + * @async_bfqq: array of async queues for all the tasks belonging to
- + * the group, one queue per ioprio value per ioprio_class,
- + * except for the idle class that has only one queue.
- + * @async_idle_bfqq: async queue for the idle class (ioprio is ignored).
- + * @my_entity: pointer to @entity, %NULL for the toplevel group; used
- + * to avoid too many special cases during group creation/
- + * migration.
- + * @active_entities: number of active entities belonging to the group;
- + * unused for the root group. Used to know whether there
- + * are groups with more than one active @bfq_entity
- + * (see the comments to the function
- + * bfq_bfqq_must_not_expire()).
- + *
- + * Each (device, cgroup) pair has its own bfq_group, i.e., for each cgroup
- + * there is a set of bfq_groups, each one collecting the lower-level
- + * entities belonging to the group that are acting on the same device.
- + *
- + * Locking works as follows:
- + * o @group_node is protected by the bfqio_cgroup lock, and is accessed
- + * via RCU from its readers.
- + * o @bfqd is protected by the queue lock, RCU is used to access it
- + * from the readers.
- + * o All the other fields are protected by the @bfqd queue lock.
- + */
- +struct bfq_group {
- + struct bfq_entity entity;
- + struct bfq_sched_data sched_data;
- +
- + struct hlist_node group_node;
- + struct hlist_node bfqd_node;
- +
- + void *bfqd;
- +
- + struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR];
- + struct bfq_queue *async_idle_bfqq;
- +
- + struct bfq_entity *my_entity;
- +
- + int active_entities;
- +};
- +
- +/**
- + * struct bfqio_cgroup - bfq cgroup data structure.
- + * @css: subsystem state for bfq in the containing cgroup.
- + * @online: flag marked when the subsystem is inserted.
- + * @weight: cgroup weight.
- + * @ioprio: cgroup ioprio.
- + * @ioprio_class: cgroup ioprio_class.
- + * @lock: spinlock that protects @ioprio, @ioprio_class and @group_data.
- + * @group_data: list containing the bfq_group belonging to this cgroup.
- + *
- + * @group_data is accessed using RCU, with @lock protecting the updates,
- + * @ioprio and @ioprio_class are protected by @lock.
- + */
- +struct bfqio_cgroup {
- + struct cgroup_subsys_state css;
- + bool online;
- +
- + unsigned short weight, ioprio, ioprio_class;
- +
- + spinlock_t lock;
- + struct hlist_head group_data;
- +};
- +#else
- +struct bfq_group {
- + struct bfq_sched_data sched_data;
- +
- + struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR];
- + struct bfq_queue *async_idle_bfqq;
- +};
- +#endif
- +
- +static inline struct bfq_service_tree *
- +bfq_entity_service_tree(struct bfq_entity *entity)
- +{
- + struct bfq_sched_data *sched_data = entity->sched_data;
- + unsigned int idx = entity->ioprio_class - 1;
- +
- + BUG_ON(idx >= BFQ_IOPRIO_CLASSES);
- + BUG_ON(sched_data == NULL);
- +
- + return sched_data->service_tree + idx;
- +}
- +
- +static inline struct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic,
- + int is_sync)
- +{
- + return bic->bfqq[!!is_sync];
- +}
- +
- +static inline void bic_set_bfqq(struct bfq_io_cq *bic,
- + struct bfq_queue *bfqq, int is_sync)
- +{
- + bic->bfqq[!!is_sync] = bfqq;
- +}
- +
- +static inline struct bfq_data *bic_to_bfqd(struct bfq_io_cq *bic)
- +{
- + return bic->icq.q->elevator->elevator_data;
- +}
- +
- +/**
- + * bfq_get_bfqd_locked - get a lock to a bfqd using a RCU protected pointer.
- + * @ptr: a pointer to a bfqd.
- + * @flags: storage for the flags to be saved.
- + *
- + * This function allows bfqg->bfqd to be protected by the
- + * queue lock of the bfqd they reference; the pointer is dereferenced
- + * under RCU, so the storage for bfqd is assured to be safe as long
- + * as the RCU read side critical section does not end. After the
- + * bfqd->queue->queue_lock is taken the pointer is rechecked, to be
- + * sure that no other writer accessed it. If we raced with a writer,
- + * the function returns NULL, with the queue unlocked, otherwise it
- + * returns the dereferenced pointer, with the queue locked.
- + */
- +static inline struct bfq_data *bfq_get_bfqd_locked(void **ptr,
- + unsigned long *flags)
- +{
- + struct bfq_data *bfqd;
- +
- + rcu_read_lock();
- + bfqd = rcu_dereference(*(struct bfq_data **)ptr);
- +
- + if (bfqd != NULL) {
- + spin_lock_irqsave(bfqd->queue->queue_lock, *flags);
- + if (*ptr == bfqd)
- + goto out;
- + spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags);
- + }
- +
- + bfqd = NULL;
- +out:
- + rcu_read_unlock();
- + return bfqd;
- +}
- +
- +static inline void bfq_put_bfqd_unlock(struct bfq_data *bfqd,
- + unsigned long *flags)
- +{
- + spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags);
- +}
- +
- +static void bfq_changed_ioprio(struct bfq_io_cq *bic);
- +static void bfq_put_queue(struct bfq_queue *bfqq);
- +static void bfq_dispatch_insert(struct request_queue *q, struct request *rq);
- +static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd,
- + struct bfq_group *bfqg, int is_sync,
- + struct bfq_io_cq *bic, gfp_t gfp_mask);
- +static void bfq_end_wr_async_queues(struct bfq_data *bfqd,
- + struct bfq_group *bfqg);
- +static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg);
- +static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq);
- +
- +#endif /* _BFQ_H */
- diff -Nur linux-3.14.35.orig/block/bfq-ioc.c linux-3.14.35/block/bfq-ioc.c
- --- linux-3.14.35.orig/block/bfq-ioc.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/block/bfq-ioc.c 2015-03-08 14:27:37.457684502 -0500
- @@ -0,0 +1,36 @@
- +/*
- + * BFQ: I/O context handling.
- + *
- + * Based on ideas and code from CFQ:
- + * Copyright (C) 2003 Jens Axboe <axboe@kernel.dk>
- + *
- + * Copyright (C) 2008 Fabio Checconi <fabio@gandalf.sssup.it>
- + * Paolo Valente <paolo.valente@unimore.it>
- + *
- + * Copyright (C) 2010 Paolo Valente <paolo.valente@unimore.it>
- + */
- +
- +/**
- + * icq_to_bic - convert iocontext queue structure to bfq_io_cq.
- + * @icq: the iocontext queue.
- + */
- +static inline struct bfq_io_cq *icq_to_bic(struct io_cq *icq)
- +{
- + /* bic->icq is the first member, %NULL will convert to %NULL */
- + return container_of(icq, struct bfq_io_cq, icq);
- +}
- +
- +/**
- + * bfq_bic_lookup - search into @ioc a bic associated to @bfqd.
- + * @bfqd: the lookup key.
- + * @ioc: the io_context of the process doing I/O.
- + *
- + * Queue lock must be held.
- + */
- +static inline struct bfq_io_cq *bfq_bic_lookup(struct bfq_data *bfqd,
- + struct io_context *ioc)
- +{
- + if (ioc)
- + return icq_to_bic(ioc_lookup_icq(ioc, bfqd->queue));
- + return NULL;
- +}
- diff -Nur linux-3.14.35.orig/block/bfq-iosched.c linux-3.14.35/block/bfq-iosched.c
- --- linux-3.14.35.orig/block/bfq-iosched.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/block/bfq-iosched.c 2015-03-08 14:27:37.461684502 -0500
- @@ -0,0 +1,3919 @@
- +/*
- + * Budget Fair Queueing (BFQ) disk scheduler.
- + *
- + * Based on ideas and code from CFQ:
- + * Copyright (C) 2003 Jens Axboe <axboe@kernel.dk>
- + *
- + * Copyright (C) 2008 Fabio Checconi <fabio@gandalf.sssup.it>
- + * Paolo Valente <paolo.valente@unimore.it>
- + *
- + * Copyright (C) 2010 Paolo Valente <paolo.valente@unimore.it>
- + *
- + * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ
- + * file.
- + *
- + * BFQ is a proportional-share storage-I/O scheduling algorithm based on
- + * the slice-by-slice service scheme of CFQ. But BFQ assigns budgets,
- + * measured in number of sectors, to processes instead of time slices. The
- + * device is not granted to the in-service process for a given time slice,
- + * but until it has exhausted its assigned budget. This change from the time
- + * to the service domain allows BFQ to distribute the device throughput
- + * among processes as desired, without any distortion due to ZBR, workload
- + * fluctuations or other factors. BFQ uses an ad hoc internal scheduler,
- + * called B-WF2Q+, to schedule processes according to their budgets. More
- + * precisely, BFQ schedules queues associated to processes. Thanks to the
- + * accurate policy of B-WF2Q+, BFQ can afford to assign high budgets to
- + * I/O-bound processes issuing sequential requests (to boost the
- + * throughput), and yet guarantee a low latency to interactive and soft
- + * real-time applications.
- + *
- + * BFQ is described in [1], where also a reference to the initial, more
- + * theoretical paper on BFQ can be found. The interested reader can find
- + * in the latter paper full details on the main algorithm, as well as
- + * formulas of the guarantees and formal proofs of all the properties.
- + * With respect to the version of BFQ presented in these papers, this
- + * implementation adds a few more heuristics, such as the one that
- + * guarantees a low latency to soft real-time applications, and a
- + * hierarchical extension based on H-WF2Q+.
- + *
- + * B-WF2Q+ is based on WF2Q+, that is described in [2], together with
- + * H-WF2Q+, while the augmented tree used to implement B-WF2Q+ with O(log N)
- + * complexity derives from the one introduced with EEVDF in [3].
- + *
- + * [1] P. Valente and M. Andreolini, ``Improving Application Responsiveness
- + * with the BFQ Disk I/O Scheduler'',
- + * Proceedings of the 5th Annual International Systems and Storage
- + * Conference (SYSTOR '12), June 2012.
- + *
- + * http://algogroup.unimo.it/people/paolo/disk_sched/bf1-v1-suite-results.pdf
- + *
- + * [2] Jon C.R. Bennett and H. Zhang, ``Hierarchical Packet Fair Queueing
- + * Algorithms,'' IEEE/ACM Transactions on Networking, 5(5):675-689,
- + * Oct 1997.
- + *
- + * http://www.cs.cmu.edu/~hzhang/papers/TON-97-Oct.ps.gz
- + *
- + * [3] I. Stoica and H. Abdel-Wahab, ``Earliest Eligible Virtual Deadline
- + * First: A Flexible and Accurate Mechanism for Proportional Share
- + * Resource Allocation,'' technical report.
- + *
- + * http://www.cs.berkeley.edu/~istoica/papers/eevdf-tr-95.pdf
- + */
- +#include <linux/module.h>
- +#include <linux/slab.h>
- +#include <linux/blkdev.h>
- +#include <linux/cgroup.h>
- +#include <linux/elevator.h>
- +#include <linux/jiffies.h>
- +#include <linux/rbtree.h>
- +#include <linux/ioprio.h>
- +#include "bfq.h"
- +#include "blk.h"
- +
- +/* Max number of dispatches in one round of service. */
- +static const int bfq_quantum = 4;
- +
- +/* Expiration time of sync (0) and async (1) requests, in jiffies. */
- +static const int bfq_fifo_expire[2] = { HZ / 4, HZ / 8 };
- +
- +/* Maximum backwards seek, in KiB. */
- +static const int bfq_back_max = 16 * 1024;
- +
- +/* Penalty of a backwards seek, in number of sectors. */
- +static const int bfq_back_penalty = 2;
- +
- +/* Idling period duration, in jiffies. */
- +static int bfq_slice_idle = HZ / 125;
- +
- +/* Default maximum budget values, in sectors and number of requests. */
- +static const int bfq_default_max_budget = 16 * 1024;
- +static const int bfq_max_budget_async_rq = 4;
- +
- +/*
- + * Async to sync throughput distribution is controlled as follows:
- + * when an async request is served, the entity is charged the number
- + * of sectors of the request, multiplied by the factor below
- + */
- +static const int bfq_async_charge_factor = 10;
- +
- +/* Default timeout values, in jiffies, approximating CFQ defaults. */
- +static const int bfq_timeout_sync = HZ / 8;
- +static int bfq_timeout_async = HZ / 25;
- +
- +struct kmem_cache *bfq_pool;
- +
- +/* Below this threshold (in ms), we consider thinktime immediate. */
- +#define BFQ_MIN_TT 2
- +
- +/* hw_tag detection: parallel requests threshold and min samples needed. */
- +#define BFQ_HW_QUEUE_THRESHOLD 4
- +#define BFQ_HW_QUEUE_SAMPLES 32
- +
- +#define BFQQ_SEEK_THR (sector_t)(8 * 1024)
- +#define BFQQ_SEEKY(bfqq) ((bfqq)->seek_mean > BFQQ_SEEK_THR)
- +
- +/* Min samples used for peak rate estimation (for autotuning). */
- +#define BFQ_PEAK_RATE_SAMPLES 32
- +
- +/* Shift used for peak rate fixed precision calculations. */
- +#define BFQ_RATE_SHIFT 16
- +
- +/*
- + * By default, BFQ computes the duration of the weight raising for
- + * interactive applications automatically, using the following formula:
- + * duration = (R / r) * T, where r is the peak rate of the device, and
- + * R and T are two reference parameters.
- + * In particular, R is the peak rate of the reference device (see below),
- + * and T is a reference time: given the systems that are likely to be
- + * installed on the reference device according to its speed class, T is
- + * about the maximum time needed, under BFQ and while reading two files in
- + * parallel, to load typical large applications on these systems.
- + * In practice, the slower/faster the device at hand is, the more/less it
- + * takes to load applications with respect to the reference device.
- + * Accordingly, the longer/shorter BFQ grants weight raising to interactive
- + * applications.
- + *
- + * BFQ uses four different reference pairs (R, T), depending on:
- + * . whether the device is rotational or non-rotational;
- + * . whether the device is slow, such as old or portable HDDs, as well as
- + * SD cards, or fast, such as newer HDDs and SSDs.
- + *
- + * The device's speed class is dynamically (re)detected in
- + * bfq_update_peak_rate() every time the estimated peak rate is updated.
- + *
- + * In the following definitions, R_slow[0]/R_fast[0] and T_slow[0]/T_fast[0]
- + * are the reference values for a slow/fast rotational device, whereas
- + * R_slow[1]/R_fast[1] and T_slow[1]/T_fast[1] are the reference values for
- + * a slow/fast non-rotational device. Finally, device_speed_thresh are the
- + * thresholds used to switch between speed classes.
- + * Both the reference peak rates and the thresholds are measured in
- + * sectors/usec, left-shifted by BFQ_RATE_SHIFT.
- + */
- +static int R_slow[2] = {1536, 10752};
- +static int R_fast[2] = {17415, 34791};
- +/*
- + * To improve readability, a conversion function is used to initialize the
- + * following arrays, which entails that they can be initialized only in a
- + * function.
- + */
- +static int T_slow[2];
- +static int T_fast[2];
- +static int device_speed_thresh[2];
- +
- +#define BFQ_SERVICE_TREE_INIT ((struct bfq_service_tree) \
- + { RB_ROOT, RB_ROOT, NULL, NULL, 0, 0 })
- +
- +#define RQ_BIC(rq) ((struct bfq_io_cq *) (rq)->elv.priv[0])
- +#define RQ_BFQQ(rq) ((rq)->elv.priv[1])
- +
- +static inline void bfq_schedule_dispatch(struct bfq_data *bfqd);
- +
- +#include "bfq-ioc.c"
- +#include "bfq-sched.c"
- +#include "bfq-cgroup.c"
- +
- +#define bfq_class_idle(bfqq) ((bfqq)->entity.ioprio_class ==\
- + IOPRIO_CLASS_IDLE)
- +#define bfq_class_rt(bfqq) ((bfqq)->entity.ioprio_class ==\
- + IOPRIO_CLASS_RT)
- +
- +#define bfq_sample_valid(samples) ((samples) > 80)
- +
- +/*
- + * We regard a request as SYNC, if either it's a read or has the SYNC bit
- + * set (in which case it could also be a direct WRITE).
- + */
- +static inline int bfq_bio_sync(struct bio *bio)
- +{
- + if (bio_data_dir(bio) == READ || (bio->bi_rw & REQ_SYNC))
- + return 1;
- +
- + return 0;
- +}
- +
- +/*
- + * Scheduler run of queue, if there are requests pending and no one in the
- + * driver that will restart queueing.
- + */
- +static inline void bfq_schedule_dispatch(struct bfq_data *bfqd)
- +{
- + if (bfqd->queued != 0) {
- + bfq_log(bfqd, "schedule dispatch");
- + kblockd_schedule_work(bfqd->queue, &bfqd->unplug_work);
- + }
- +}
- +
- +/*
- + * Lifted from AS - choose which of rq1 and rq2 that is best served now.
- + * We choose the request that is closesr to the head right now. Distance
- + * behind the head is penalized and only allowed to a certain extent.
- + */
- +static struct request *bfq_choose_req(struct bfq_data *bfqd,
- + struct request *rq1,
- + struct request *rq2,
- + sector_t last)
- +{
- + sector_t s1, s2, d1 = 0, d2 = 0;
- + unsigned long back_max;
- +#define BFQ_RQ1_WRAP 0x01 /* request 1 wraps */
- +#define BFQ_RQ2_WRAP 0x02 /* request 2 wraps */
- + unsigned wrap = 0; /* bit mask: requests behind the disk head? */
- +
- + if (rq1 == NULL || rq1 == rq2)
- + return rq2;
- + if (rq2 == NULL)
- + return rq1;
- +
- + if (rq_is_sync(rq1) && !rq_is_sync(rq2))
- + return rq1;
- + else if (rq_is_sync(rq2) && !rq_is_sync(rq1))
- + return rq2;
- + if ((rq1->cmd_flags & REQ_META) && !(rq2->cmd_flags & REQ_META))
- + return rq1;
- + else if ((rq2->cmd_flags & REQ_META) && !(rq1->cmd_flags & REQ_META))
- + return rq2;
- +
- + s1 = blk_rq_pos(rq1);
- + s2 = blk_rq_pos(rq2);
- +
- + /*
- + * By definition, 1KiB is 2 sectors.
- + */
- + back_max = bfqd->bfq_back_max * 2;
- +
- + /*
- + * Strict one way elevator _except_ in the case where we allow
- + * short backward seeks which are biased as twice the cost of a
- + * similar forward seek.
- + */
- + if (s1 >= last)
- + d1 = s1 - last;
- + else if (s1 + back_max >= last)
- + d1 = (last - s1) * bfqd->bfq_back_penalty;
- + else
- + wrap |= BFQ_RQ1_WRAP;
- +
- + if (s2 >= last)
- + d2 = s2 - last;
- + else if (s2 + back_max >= last)
- + d2 = (last - s2) * bfqd->bfq_back_penalty;
- + else
- + wrap |= BFQ_RQ2_WRAP;
- +
- + /* Found required data */
- +
- + /*
- + * By doing switch() on the bit mask "wrap" we avoid having to
- + * check two variables for all permutations: --> faster!
- + */
- + switch (wrap) {
- + case 0: /* common case for CFQ: rq1 and rq2 not wrapped */
- + if (d1 < d2)
- + return rq1;
- + else if (d2 < d1)
- + return rq2;
- + else {
- + if (s1 >= s2)
- + return rq1;
- + else
- + return rq2;
- + }
- +
- + case BFQ_RQ2_WRAP:
- + return rq1;
- + case BFQ_RQ1_WRAP:
- + return rq2;
- + case (BFQ_RQ1_WRAP|BFQ_RQ2_WRAP): /* both rqs wrapped */
- + default:
- + /*
- + * Since both rqs are wrapped,
- + * start with the one that's further behind head
- + * (--> only *one* back seek required),
- + * since back seek takes more time than forward.
- + */
- + if (s1 <= s2)
- + return rq1;
- + else
- + return rq2;
- + }
- +}
- +
- +static struct bfq_queue *
- +bfq_rq_pos_tree_lookup(struct bfq_data *bfqd, struct rb_root *root,
- + sector_t sector, struct rb_node **ret_parent,
- + struct rb_node ***rb_link)
- +{
- + struct rb_node **p, *parent;
- + struct bfq_queue *bfqq = NULL;
- +
- + parent = NULL;
- + p = &root->rb_node;
- + while (*p) {
- + struct rb_node **n;
- +
- + parent = *p;
- + bfqq = rb_entry(parent, struct bfq_queue, pos_node);
- +
- + /*
- + * Sort strictly based on sector. Smallest to the left,
- + * largest to the right.
- + */
- + if (sector > blk_rq_pos(bfqq->next_rq))
- + n = &(*p)->rb_right;
- + else if (sector < blk_rq_pos(bfqq->next_rq))
- + n = &(*p)->rb_left;
- + else
- + break;
- + p = n;
- + bfqq = NULL;
- + }
- +
- + *ret_parent = parent;
- + if (rb_link)
- + *rb_link = p;
- +
- + bfq_log(bfqd, "rq_pos_tree_lookup %llu: returning %d",
- + (long long unsigned)sector,
- + bfqq != NULL ? bfqq->pid : 0);
- +
- + return bfqq;
- +}
- +
- +static void bfq_rq_pos_tree_add(struct bfq_data *bfqd, struct bfq_queue *bfqq)
- +{
- + struct rb_node **p, *parent;
- + struct bfq_queue *__bfqq;
- +
- + if (bfqq->pos_root != NULL) {
- + rb_erase(&bfqq->pos_node, bfqq->pos_root);
- + bfqq->pos_root = NULL;
- + }
- +
- + if (bfq_class_idle(bfqq))
- + return;
- + if (!bfqq->next_rq)
- + return;
- +
- + bfqq->pos_root = &bfqd->rq_pos_tree;
- + __bfqq = bfq_rq_pos_tree_lookup(bfqd, bfqq->pos_root,
- + blk_rq_pos(bfqq->next_rq), &parent, &p);
- + if (__bfqq == NULL) {
- + rb_link_node(&bfqq->pos_node, parent, p);
- + rb_insert_color(&bfqq->pos_node, bfqq->pos_root);
- + } else
- + bfqq->pos_root = NULL;
- +}
- +
- +/*
- + * Tell whether there are active queues or groups with differentiated weights.
- + */
- +static inline bool bfq_differentiated_weights(struct bfq_data *bfqd)
- +{
- + BUG_ON(!bfqd->hw_tag);
- + /*
- + * For weights to differ, at least one of the trees must contain
- + * at least two nodes.
- + */
- + return (!RB_EMPTY_ROOT(&bfqd->queue_weights_tree) &&
- + (bfqd->queue_weights_tree.rb_node->rb_left ||
- + bfqd->queue_weights_tree.rb_node->rb_right)
- +#ifdef CONFIG_CGROUP_BFQIO
- + ) ||
- + (!RB_EMPTY_ROOT(&bfqd->group_weights_tree) &&
- + (bfqd->group_weights_tree.rb_node->rb_left ||
- + bfqd->group_weights_tree.rb_node->rb_right)
- +#endif
- + );
- +}
- +
- +/*
- + * If the weight-counter tree passed as input contains no counter for
- + * the weight of the input entity, then add that counter; otherwise just
- + * increment the existing counter.
- + *
- + * Note that weight-counter trees contain few nodes in mostly symmetric
- + * scenarios. For example, if all queues have the same weight, then the
- + * weight-counter tree for the queues may contain at most one node.
- + * This holds even if low_latency is on, because weight-raised queues
- + * are not inserted in the tree.
- + * In most scenarios, the rate at which nodes are created/destroyed
- + * should be low too.
- + */
- +static void bfq_weights_tree_add(struct bfq_data *bfqd,
- + struct bfq_entity *entity,
- + struct rb_root *root)
- +{
- + struct rb_node **new = &(root->rb_node), *parent = NULL;
- +
- + /*
- + * Do not insert if:
- + * - the device does not support queueing;
- + * - the entity is already associated with a counter, which happens if:
- + * 1) the entity is associated with a queue, 2) a request arrival
- + * has caused the queue to become both non-weight-raised, and hence
- + * change its weight, and backlogged; in this respect, each
- + * of the two events causes an invocation of this function,
- + * 3) this is the invocation of this function caused by the second
- + * event. This second invocation is actually useless, and we handle
- + * this fact by exiting immediately. More efficient or clearer
- + * solutions might possibly be adopted.
- + */
- + if (!bfqd->hw_tag || entity->weight_counter)
- + return;
- +
- + while (*new) {
- + struct bfq_weight_counter *__counter = container_of(*new,
- + struct bfq_weight_counter,
- + weights_node);
- + parent = *new;
- +
- + if (entity->weight == __counter->weight) {
- + entity->weight_counter = __counter;
- + goto inc_counter;
- + }
- + if (entity->weight < __counter->weight)
- + new = &((*new)->rb_left);
- + else
- + new = &((*new)->rb_right);
- + }
- +
- + entity->weight_counter = kzalloc(sizeof(struct bfq_weight_counter),
- + GFP_ATOMIC);
- + entity->weight_counter->weight = entity->weight;
- + rb_link_node(&entity->weight_counter->weights_node, parent, new);
- + rb_insert_color(&entity->weight_counter->weights_node, root);
- +
- +inc_counter:
- + entity->weight_counter->num_active++;
- +}
- +
- +/*
- + * Decrement the weight counter associated with the entity, and, if the
- + * counter reaches 0, remove the counter from the tree.
- + * See the comments to the function bfq_weights_tree_add() for considerations
- + * about overhead.
- + */
- +static void bfq_weights_tree_remove(struct bfq_data *bfqd,
- + struct bfq_entity *entity,
- + struct rb_root *root)
- +{
- + /*
- + * Check whether the entity is actually associated with a counter.
- + * In fact, the device may not be considered NCQ-capable for a while,
- + * which implies that no insertion in the weight trees is performed,
- + * after which the device may start to be deemed NCQ-capable, and hence
- + * this function may start to be invoked. This may cause the function
- + * to be invoked for entities that are not associated with any counter.
- + */
- + if (!entity->weight_counter)
- + return;
- +
- + BUG_ON(RB_EMPTY_ROOT(root));
- + BUG_ON(entity->weight_counter->weight != entity->weight);
- +
- + BUG_ON(!entity->weight_counter->num_active);
- + entity->weight_counter->num_active--;
- + if (entity->weight_counter->num_active > 0)
- + goto reset_entity_pointer;
- +
- + rb_erase(&entity->weight_counter->weights_node, root);
- + kfree(entity->weight_counter);
- +
- +reset_entity_pointer:
- + entity->weight_counter = NULL;
- +}
- +
- +static struct request *bfq_find_next_rq(struct bfq_data *bfqd,
- + struct bfq_queue *bfqq,
- + struct request *last)
- +{
- + struct rb_node *rbnext = rb_next(&last->rb_node);
- + struct rb_node *rbprev = rb_prev(&last->rb_node);
- + struct request *next = NULL, *prev = NULL;
- +
- + BUG_ON(RB_EMPTY_NODE(&last->rb_node));
- +
- + if (rbprev != NULL)
- + prev = rb_entry_rq(rbprev);
- +
- + if (rbnext != NULL)
- + next = rb_entry_rq(rbnext);
- + else {
- + rbnext = rb_first(&bfqq->sort_list);
- + if (rbnext && rbnext != &last->rb_node)
- + next = rb_entry_rq(rbnext);
- + }
- +
- + return bfq_choose_req(bfqd, next, prev, blk_rq_pos(last));
- +}
- +
- +/* see the definition of bfq_async_charge_factor for details */
- +static inline unsigned long bfq_serv_to_charge(struct request *rq,
- + struct bfq_queue *bfqq)
- +{
- + return blk_rq_sectors(rq) *
- + (1 + ((!bfq_bfqq_sync(bfqq)) * (bfqq->wr_coeff == 1) *
- + bfq_async_charge_factor));
- +}
- +
- +/**
- + * bfq_updated_next_req - update the queue after a new next_rq selection.
- + * @bfqd: the device data the queue belongs to.
- + * @bfqq: the queue to update.
- + *
- + * If the first request of a queue changes we make sure that the queue
- + * has enough budget to serve at least its first request (if the
- + * request has grown). We do this because if the queue has not enough
- + * budget for its first request, it has to go through two dispatch
- + * rounds to actually get it dispatched.
- + */
- +static void bfq_updated_next_req(struct bfq_data *bfqd,
- + struct bfq_queue *bfqq)
- +{
- + struct bfq_entity *entity = &bfqq->entity;
- + struct bfq_service_tree *st = bfq_entity_service_tree(entity);
- + struct request *next_rq = bfqq->next_rq;
- + unsigned long new_budget;
- +
- + if (next_rq == NULL)
- + return;
- +
- + if (bfqq == bfqd->in_service_queue)
- + /*
- + * In order not to break guarantees, budgets cannot be
- + * changed after an entity has been selected.
- + */
- + return;
- +
- + BUG_ON(entity->tree != &st->active);
- + BUG_ON(entity == entity->sched_data->in_service_entity);
- +
- + new_budget = max_t(unsigned long, bfqq->max_budget,
- + bfq_serv_to_charge(next_rq, bfqq));
- + if (entity->budget != new_budget) {
- + entity->budget = new_budget;
- + bfq_log_bfqq(bfqd, bfqq, "updated next rq: new budget %lu",
- + new_budget);
- + bfq_activate_bfqq(bfqd, bfqq);
- + }
- +}
- +
- +static inline unsigned int bfq_wr_duration(struct bfq_data *bfqd)
- +{
- + u64 dur;
- +
- + if (bfqd->bfq_wr_max_time > 0)
- + return bfqd->bfq_wr_max_time;
- +
- + dur = bfqd->RT_prod;
- + do_div(dur, bfqd->peak_rate);
- +
- + return dur;
- +}
- +
- +static inline unsigned
- +bfq_bfqq_cooperations(struct bfq_queue *bfqq)
- +{
- + return bfqq->bic ? bfqq->bic->cooperations : 0;
- +}
- +
- +static inline void
- +bfq_bfqq_resume_state(struct bfq_queue *bfqq, struct bfq_io_cq *bic)
- +{
- + if (bic->saved_idle_window)
- + bfq_mark_bfqq_idle_window(bfqq);
- + else
- + bfq_clear_bfqq_idle_window(bfqq);
- + if (bic->saved_IO_bound)
- + bfq_mark_bfqq_IO_bound(bfqq);
- + else
- + bfq_clear_bfqq_IO_bound(bfqq);
- + if (bic->wr_time_left && bfqq->bfqd->low_latency &&
- + bic->cooperations < bfqq->bfqd->bfq_coop_thresh) {
- + /*
- + * Start a weight raising period with the duration given by
- + * the raising_time_left snapshot.
- + */
- + if (bfq_bfqq_busy(bfqq))
- + bfqq->bfqd->wr_busy_queues++;
- + bfqq->wr_coeff = bfqq->bfqd->bfq_wr_coeff;
- + bfqq->wr_cur_max_time = bic->wr_time_left;
- + bfqq->last_wr_start_finish = jiffies;
- + bfqq->entity.ioprio_changed = 1;
- + }
- + /*
- + * Clear wr_time_left to prevent bfq_bfqq_save_state() from
- + * getting confused about the queue's need of a weight-raising
- + * period.
- + */
- + bic->wr_time_left = 0;
- +}
- +
- +/*
- + * Must be called with the queue_lock held.
- + */
- +static int bfqq_process_refs(struct bfq_queue *bfqq)
- +{
- + int process_refs, io_refs;
- +
- + io_refs = bfqq->allocated[READ] + bfqq->allocated[WRITE];
- + process_refs = atomic_read(&bfqq->ref) - io_refs - bfqq->entity.on_st;
- + BUG_ON(process_refs < 0);
- + return process_refs;
- +}
- +
- +static void bfq_add_request(struct request *rq)
- +{
- + struct bfq_queue *bfqq = RQ_BFQQ(rq);
- + struct bfq_entity *entity = &bfqq->entity;
- + struct bfq_data *bfqd = bfqq->bfqd;
- + struct request *next_rq, *prev;
- + unsigned long old_wr_coeff = bfqq->wr_coeff;
- + int idle_for_long_time = 0;
- +
- + bfq_log_bfqq(bfqd, bfqq, "add_request %d", rq_is_sync(rq));
- + bfqq->queued[rq_is_sync(rq)]++;
- + bfqd->queued++;
- +
- + elv_rb_add(&bfqq->sort_list, rq);
- +
- + /*
- + * Check if this request is a better next-serve candidate.
- + */
- + prev = bfqq->next_rq;
- + next_rq = bfq_choose_req(bfqd, bfqq->next_rq, rq, bfqd->last_position);
- + BUG_ON(next_rq == NULL);
- + bfqq->next_rq = next_rq;
- +
- + /*
- + * Adjust priority tree position, if next_rq changes.
- + */
- + if (prev != bfqq->next_rq)
- + bfq_rq_pos_tree_add(bfqd, bfqq);
- +
- + if (!bfq_bfqq_busy(bfqq)) {
- + int soft_rt = bfqd->bfq_wr_max_softrt_rate > 0 &&
- + bfq_bfqq_cooperations(bfqq) < bfqd->bfq_coop_thresh &&
- + time_is_before_jiffies(bfqq->soft_rt_next_start);
- + idle_for_long_time = bfq_bfqq_cooperations(bfqq) <
- + bfqd->bfq_coop_thresh &&
- + time_is_before_jiffies(
- + bfqq->budget_timeout +
- + bfqd->bfq_wr_min_idle_time);
- + entity->budget = max_t(unsigned long, bfqq->max_budget,
- + bfq_serv_to_charge(next_rq, bfqq));
- +
- + if (!bfq_bfqq_IO_bound(bfqq)) {
- + if (time_before(jiffies,
- + RQ_BIC(rq)->ttime.last_end_request +
- + bfqd->bfq_slice_idle)) {
- + bfqq->requests_within_timer++;
- + if (bfqq->requests_within_timer >=
- + bfqd->bfq_requests_within_timer)
- + bfq_mark_bfqq_IO_bound(bfqq);
- + } else
- + bfqq->requests_within_timer = 0;
- + }
- +
- + if (!bfqd->low_latency)
- + goto add_bfqq_busy;
- +
- + if (bfq_bfqq_just_split(bfqq))
- + goto set_ioprio_changed;
- +
- + /*
- + * If the queue:
- + * - is not being boosted,
- + * - has been idle for enough time,
- + * - is not a sync queue or is linked to a bfq_io_cq (it is
- + * shared "for its nature" or it is not shared and its
- + * requests have not been redirected to a shared queue)
- + * start a weight-raising period.
- + */
- + if (old_wr_coeff == 1 && (idle_for_long_time || soft_rt) &&
- + (!bfq_bfqq_sync(bfqq) || bfqq->bic != NULL)) {
- + bfqq->wr_coeff = bfqd->bfq_wr_coeff;
- + if (idle_for_long_time)
- + bfqq->wr_cur_max_time = bfq_wr_duration(bfqd);
- + else
- + bfqq->wr_cur_max_time =
- + bfqd->bfq_wr_rt_max_time;
- + bfq_log_bfqq(bfqd, bfqq,
- + "wrais starting at %lu, rais_max_time %u",
- + jiffies,
- + jiffies_to_msecs(bfqq->wr_cur_max_time));
- + } else if (old_wr_coeff > 1) {
- + if (idle_for_long_time)
- + bfqq->wr_cur_max_time = bfq_wr_duration(bfqd);
- + else if (bfq_bfqq_cooperations(bfqq) >=
- + bfqd->bfq_coop_thresh ||
- + (bfqq->wr_cur_max_time ==
- + bfqd->bfq_wr_rt_max_time &&
- + !soft_rt)) {
- + bfqq->wr_coeff = 1;
- + bfq_log_bfqq(bfqd, bfqq,
- + "wrais ending at %lu, rais_max_time %u",
- + jiffies,
- + jiffies_to_msecs(bfqq->
- + wr_cur_max_time));
- + } else if (time_before(
- + bfqq->last_wr_start_finish +
- + bfqq->wr_cur_max_time,
- + jiffies +
- + bfqd->bfq_wr_rt_max_time) &&
- + soft_rt) {
- + /*
- + *
- + * The remaining weight-raising time is lower
- + * than bfqd->bfq_wr_rt_max_time, which means
- + * that the application is enjoying weight
- + * raising either because deemed soft-rt in
- + * the near past, or because deemed interactive
- + * a long ago.
- + * In both cases, resetting now the current
- + * remaining weight-raising time for the
- + * application to the weight-raising duration
- + * for soft rt applications would not cause any
- + * latency increase for the application (as the
- + * new duration would be higher than the
- + * remaining time).
- + *
- + * In addition, the application is now meeting
- + * the requirements for being deemed soft rt.
- + * In the end we can correctly and safely
- + * (re)charge the weight-raising duration for
- + * the application with the weight-raising
- + * duration for soft rt applications.
- + *
- + * In particular, doing this recharge now, i.e.,
- + * before the weight-raising period for the
- + * application finishes, reduces the probability
- + * of the following negative scenario:
- + * 1) the weight of a soft rt application is
- + * raised at startup (as for any newly
- + * created application),
- + * 2) since the application is not interactive,
- + * at a certain time weight-raising is
- + * stopped for the application,
- + * 3) at that time the application happens to
- + * still have pending requests, and hence
- + * is destined to not have a chance to be
- + * deemed soft rt before these requests are
- + * completed (see the comments to the
- + * function bfq_bfqq_softrt_next_start()
- + * for details on soft rt detection),
- + * 4) these pending requests experience a high
- + * latency because the application is not
- + * weight-raised while they are pending.
- + */
- + bfqq->last_wr_start_finish = jiffies;
- + bfqq->wr_cur_max_time =
- + bfqd->bfq_wr_rt_max_time;
- + }
- + }
- +set_ioprio_changed:
- + if (old_wr_coeff != bfqq->wr_coeff)
- + entity->ioprio_changed = 1;
- +add_bfqq_busy:
- + bfqq->last_idle_bklogged = jiffies;
- + bfqq->service_from_backlogged = 0;
- + bfq_clear_bfqq_softrt_update(bfqq);
- + bfq_add_bfqq_busy(bfqd, bfqq);
- + } else {
- + if (bfqd->low_latency && old_wr_coeff == 1 && !rq_is_sync(rq) &&
- + time_is_before_jiffies(
- + bfqq->last_wr_start_finish +
- + bfqd->bfq_wr_min_inter_arr_async)) {
- + bfqq->wr_coeff = bfqd->bfq_wr_coeff;
- + bfqq->wr_cur_max_time = bfq_wr_duration(bfqd);
- +
- + bfqd->wr_busy_queues++;
- + entity->ioprio_changed = 1;
- + bfq_log_bfqq(bfqd, bfqq,
- + "non-idle wrais starting at %lu, rais_max_time %u",
- + jiffies,
- + jiffies_to_msecs(bfqq->wr_cur_max_time));
- + }
- + if (prev != bfqq->next_rq)
- + bfq_updated_next_req(bfqd, bfqq);
- + }
- +
- + if (bfqd->low_latency &&
- + (old_wr_coeff == 1 || bfqq->wr_coeff == 1 ||
- + idle_for_long_time))
- + bfqq->last_wr_start_finish = jiffies;
- +}
- +
- +static struct request *bfq_find_rq_fmerge(struct bfq_data *bfqd,
- + struct bio *bio)
- +{
- + struct task_struct *tsk = current;
- + struct bfq_io_cq *bic;
- + struct bfq_queue *bfqq;
- +
- + bic = bfq_bic_lookup(bfqd, tsk->io_context);
- + if (bic == NULL)
- + return NULL;
- +
- + bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio));
- + if (bfqq != NULL)
- + return elv_rb_find(&bfqq->sort_list, bio_end_sector(bio));
- +
- + return NULL;
- +}
- +
- +static void bfq_activate_request(struct request_queue *q, struct request *rq)
- +{
- + struct bfq_data *bfqd = q->elevator->elevator_data;
- +
- + bfqd->rq_in_driver++;
- + bfqd->last_position = blk_rq_pos(rq) + blk_rq_sectors(rq);
- + bfq_log(bfqd, "activate_request: new bfqd->last_position %llu",
- + (long long unsigned)bfqd->last_position);
- +}
- +
- +static inline void bfq_deactivate_request(struct request_queue *q,
- + struct request *rq)
- +{
- + struct bfq_data *bfqd = q->elevator->elevator_data;
- +
- + BUG_ON(bfqd->rq_in_driver == 0);
- + bfqd->rq_in_driver--;
- +}
- +
- +static void bfq_remove_request(struct request *rq)
- +{
- + struct bfq_queue *bfqq = RQ_BFQQ(rq);
- + struct bfq_data *bfqd = bfqq->bfqd;
- + const int sync = rq_is_sync(rq);
- +
- + if (bfqq->next_rq == rq) {
- + bfqq->next_rq = bfq_find_next_rq(bfqd, bfqq, rq);
- + bfq_updated_next_req(bfqd, bfqq);
- + }
- +
- + list_del_init(&rq->queuelist);
- + BUG_ON(bfqq->queued[sync] == 0);
- + bfqq->queued[sync]--;
- + bfqd->queued--;
- + elv_rb_del(&bfqq->sort_list, rq);
- +
- + if (RB_EMPTY_ROOT(&bfqq->sort_list)) {
- + if (bfq_bfqq_busy(bfqq) && bfqq != bfqd->in_service_queue)
- + bfq_del_bfqq_busy(bfqd, bfqq, 1);
- + /*
- + * Remove queue from request-position tree as it is empty.
- + */
- + if (bfqq->pos_root != NULL) {
- + rb_erase(&bfqq->pos_node, bfqq->pos_root);
- + bfqq->pos_root = NULL;
- + }
- + }
- +
- + if (rq->cmd_flags & REQ_META) {
- + BUG_ON(bfqq->meta_pending == 0);
- + bfqq->meta_pending--;
- + }
- +}
- +
- +static int bfq_merge(struct request_queue *q, struct request **req,
- + struct bio *bio)
- +{
- + struct bfq_data *bfqd = q->elevator->elevator_data;
- + struct request *__rq;
- +
- + __rq = bfq_find_rq_fmerge(bfqd, bio);
- + if (__rq != NULL && elv_rq_merge_ok(__rq, bio)) {
- + *req = __rq;
- + return ELEVATOR_FRONT_MERGE;
- + }
- +
- + return ELEVATOR_NO_MERGE;
- +}
- +
- +static void bfq_merged_request(struct request_queue *q, struct request *req,
- + int type)
- +{
- + if (type == ELEVATOR_FRONT_MERGE &&
- + rb_prev(&req->rb_node) &&
- + blk_rq_pos(req) <
- + blk_rq_pos(container_of(rb_prev(&req->rb_node),
- + struct request, rb_node))) {
- + struct bfq_queue *bfqq = RQ_BFQQ(req);
- + struct bfq_data *bfqd = bfqq->bfqd;
- + struct request *prev, *next_rq;
- +
- + /* Reposition request in its sort_list */
- + elv_rb_del(&bfqq->sort_list, req);
- + elv_rb_add(&bfqq->sort_list, req);
- + /* Choose next request to be served for bfqq */
- + prev = bfqq->next_rq;
- + next_rq = bfq_choose_req(bfqd, bfqq->next_rq, req,
- + bfqd->last_position);
- + BUG_ON(next_rq == NULL);
- + bfqq->next_rq = next_rq;
- + /*
- + * If next_rq changes, update both the queue's budget to
- + * fit the new request and the queue's position in its
- + * rq_pos_tree.
- + */
- + if (prev != bfqq->next_rq) {
- + bfq_updated_next_req(bfqd, bfqq);
- + bfq_rq_pos_tree_add(bfqd, bfqq);
- + }
- + }
- +}
- +
- +static void bfq_merged_requests(struct request_queue *q, struct request *rq,
- + struct request *next)
- +{
- + struct bfq_queue *bfqq = RQ_BFQQ(rq);
- +
- + /*
- + * Reposition in fifo if next is older than rq.
- + */
- + if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) &&
- + time_before(rq_fifo_time(next), rq_fifo_time(rq))) {
- + list_move(&rq->queuelist, &next->queuelist);
- + rq_set_fifo_time(rq, rq_fifo_time(next));
- + }
- +
- + if (bfqq->next_rq == next)
- + bfqq->next_rq = rq;
- +
- + bfq_remove_request(next);
- +}
- +
- +/* Must be called with bfqq != NULL */
- +static inline void bfq_bfqq_end_wr(struct bfq_queue *bfqq)
- +{
- + BUG_ON(bfqq == NULL);
- + if (bfq_bfqq_busy(bfqq))
- + bfqq->bfqd->wr_busy_queues--;
- + bfqq->wr_coeff = 1;
- + bfqq->wr_cur_max_time = 0;
- + /* Trigger a weight change on the next activation of the queue */
- + bfqq->entity.ioprio_changed = 1;
- +}
- +
- +static void bfq_end_wr_async_queues(struct bfq_data *bfqd,
- + struct bfq_group *bfqg)
- +{
- + int i, j;
- +
- + for (i = 0; i < 2; i++)
- + for (j = 0; j < IOPRIO_BE_NR; j++)
- + if (bfqg->async_bfqq[i][j] != NULL)
- + bfq_bfqq_end_wr(bfqg->async_bfqq[i][j]);
- + if (bfqg->async_idle_bfqq != NULL)
- + bfq_bfqq_end_wr(bfqg->async_idle_bfqq);
- +}
- +
- +static void bfq_end_wr(struct bfq_data *bfqd)
- +{
- + struct bfq_queue *bfqq;
- +
- + spin_lock_irq(bfqd->queue->queue_lock);
- +
- + list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list)
- + bfq_bfqq_end_wr(bfqq);
- + list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list)
- + bfq_bfqq_end_wr(bfqq);
- + bfq_end_wr_async(bfqd);
- +
- + spin_unlock_irq(bfqd->queue->queue_lock);
- +}
- +
- +static inline sector_t bfq_io_struct_pos(void *io_struct, bool request)
- +{
- + if (request)
- + return blk_rq_pos(io_struct);
- + else
- + return ((struct bio *)io_struct)->bi_iter.bi_sector;
- +}
- +
- +static inline sector_t bfq_dist_from(sector_t pos1,
- + sector_t pos2)
- +{
- + if (pos1 >= pos2)
- + return pos1 - pos2;
- + else
- + return pos2 - pos1;
- +}
- +
- +static inline int bfq_rq_close_to_sector(void *io_struct, bool request,
- + sector_t sector)
- +{
- + return bfq_dist_from(bfq_io_struct_pos(io_struct, request), sector) <=
- + BFQQ_SEEK_THR;
- +}
- +
- +static struct bfq_queue *bfqq_close(struct bfq_data *bfqd, sector_t sector)
- +{
- + struct rb_root *root = &bfqd->rq_pos_tree;
- + struct rb_node *parent, *node;
- + struct bfq_queue *__bfqq;
- +
- + if (RB_EMPTY_ROOT(root))
- + return NULL;
- +
- + /*
- + * First, if we find a request starting at the end of the last
- + * request, choose it.
- + */
- + __bfqq = bfq_rq_pos_tree_lookup(bfqd, root, sector, &parent, NULL);
- + if (__bfqq != NULL)
- + return __bfqq;
- +
- + /*
- + * If the exact sector wasn't found, the parent of the NULL leaf
- + * will contain the closest sector (rq_pos_tree sorted by
- + * next_request position).
- + */
- + __bfqq = rb_entry(parent, struct bfq_queue, pos_node);
- + if (bfq_rq_close_to_sector(__bfqq->next_rq, true, sector))
- + return __bfqq;
- +
- + if (blk_rq_pos(__bfqq->next_rq) < sector)
- + node = rb_next(&__bfqq->pos_node);
- + else
- + node = rb_prev(&__bfqq->pos_node);
- + if (node == NULL)
- + return NULL;
- +
- + __bfqq = rb_entry(node, struct bfq_queue, pos_node);
- + if (bfq_rq_close_to_sector(__bfqq->next_rq, true, sector))
- + return __bfqq;
- +
- + return NULL;
- +}
- +
- +/*
- + * bfqd - obvious
- + * cur_bfqq - passed in so that we don't decide that the current queue
- + * is closely cooperating with itself
- + * sector - used as a reference point to search for a close queue
- + */
- +static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd,
- + struct bfq_queue *cur_bfqq,
- + sector_t sector)
- +{
- + struct bfq_queue *bfqq;
- +
- + if (bfq_class_idle(cur_bfqq))
- + return NULL;
- + if (!bfq_bfqq_sync(cur_bfqq))
- + return NULL;
- + if (BFQQ_SEEKY(cur_bfqq))
- + return NULL;
- +
- + /* If device has only one backlogged bfq_queue, don't search. */
- + if (bfqd->busy_queues == 1)
- + return NULL;
- +
- + /*
- + * We should notice if some of the queues are cooperating, e.g.
- + * working closely on the same area of the disk. In that case,
- + * we can group them together and don't waste time idling.
- + */
- + bfqq = bfqq_close(bfqd, sector);
- + if (bfqq == NULL || bfqq == cur_bfqq)
- + return NULL;
- +
- + /*
- + * Do not merge queues from different bfq_groups.
- + */
- + if (bfqq->entity.parent != cur_bfqq->entity.parent)
- + return NULL;
- +
- + /*
- + * It only makes sense to merge sync queues.
- + */
- + if (!bfq_bfqq_sync(bfqq))
- + return NULL;
- + if (BFQQ_SEEKY(bfqq))
- + return NULL;
- +
- + /*
- + * Do not merge queues of different priority classes.
- + */
- + if (bfq_class_rt(bfqq) != bfq_class_rt(cur_bfqq))
- + return NULL;
- +
- + return bfqq;
- +}
- +
- +static struct bfq_queue *
- +bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq)
- +{
- + int process_refs, new_process_refs;
- + struct bfq_queue *__bfqq;
- +
- + /*
- + * If there are no process references on the new_bfqq, then it is
- + * unsafe to follow the ->new_bfqq chain as other bfqq's in the chain
- + * may have dropped their last reference (not just their last process
- + * reference).
- + */
- + if (!bfqq_process_refs(new_bfqq))
- + return NULL;
- +
- + /* Avoid a circular list and skip interim queue merges. */
- + while ((__bfqq = new_bfqq->new_bfqq)) {
- + if (__bfqq == bfqq)
- + return NULL;
- + new_bfqq = __bfqq;
- + }
- +
- + process_refs = bfqq_process_refs(bfqq);
- + new_process_refs = bfqq_process_refs(new_bfqq);
- + /*
- + * If the process for the bfqq has gone away, there is no
- + * sense in merging the queues.
- + */
- + if (process_refs == 0 || new_process_refs == 0)
- + return NULL;
- +
- + bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d",
- + new_bfqq->pid);
- +
- + /*
- + * Merging is just a redirection: the requests of the process
- + * owning one of the two queues are redirected to the other queue.
- + * The latter queue, in its turn, is set as shared if this is the
- + * first time that the requests of some process are redirected to
- + * it.
- + *
- + * We redirect bfqq to new_bfqq and not the opposite, because we
- + * are in the context of the process owning bfqq, hence we have
- + * the io_cq of this process. So we can immediately configure this
- + * io_cq to redirect the requests of the process to new_bfqq.
- + *
- + * NOTE, even if new_bfqq coincides with the in-service queue, the
- + * io_cq of new_bfqq is not available, because, if the in-service
- + * queue is shared, bfqd->in_service_bic may not point to the
- + * io_cq of the in-service queue.
- + * Redirecting the requests of the process owning bfqq to the
- + * currently in-service queue is in any case the best option, as
- + * we feed the in-service queue with new requests close to the
- + * last request served and, by doing so, hopefully increase the
- + * throughput.
- + */
- + bfqq->new_bfqq = new_bfqq;
- + atomic_add(process_refs, &new_bfqq->ref);
- + return new_bfqq;
- +}
- +
- +/*
- + * Attempt to schedule a merge of bfqq with the currently in-service queue
- + * or with a close queue among the scheduled queues.
- + * Return NULL if no merge was scheduled, a pointer to the shared bfq_queue
- + * structure otherwise.
- + */
- +static struct bfq_queue *
- +bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
- + void *io_struct, bool request)
- +{
- + struct bfq_queue *in_service_bfqq, *new_bfqq;
- +
- + if (bfqq->new_bfqq)
- + return bfqq->new_bfqq;
- +
- + if (!io_struct)
- + return NULL;
- +
- + in_service_bfqq = bfqd->in_service_queue;
- +
- + if (in_service_bfqq == NULL || in_service_bfqq == bfqq ||
- + !bfqd->in_service_bic)
- + goto check_scheduled;
- +
- + if (bfq_class_idle(in_service_bfqq) || bfq_class_idle(bfqq))
- + goto check_scheduled;
- +
- + if (bfq_class_rt(in_service_bfqq) != bfq_class_rt(bfqq))
- + goto check_scheduled;
- +
- + if (in_service_bfqq->entity.parent != bfqq->entity.parent)
- + goto check_scheduled;
- +
- + if (bfq_rq_close_to_sector(io_struct, request, bfqd->last_position) &&
- + bfq_bfqq_sync(in_service_bfqq) && bfq_bfqq_sync(bfqq)) {
- + new_bfqq = bfq_setup_merge(bfqq, in_service_bfqq);
- + if (new_bfqq != NULL)
- + return new_bfqq; /* Merge with in-service queue */
- + }
- +
- + /*
- + * Check whether there is a cooperator among currently scheduled
- + * queues. The only thing we need is that the bio/request is not
- + * NULL, as we need it to establish whether a cooperator exists.
- + */
- +check_scheduled:
- + new_bfqq = bfq_close_cooperator(bfqd, bfqq,
- + bfq_io_struct_pos(io_struct, request));
- + if (new_bfqq)
- + return bfq_setup_merge(bfqq, new_bfqq);
- +
- + return NULL;
- +}
- +
- +static inline void
- +bfq_bfqq_save_state(struct bfq_queue *bfqq)
- +{
- + /*
- + * If bfqq->bic == NULL, the queue is already shared or its requests
- + * have already been redirected to a shared queue; both idle window
- + * and weight raising state have already been saved. Do nothing.
- + */
- + if (bfqq->bic == NULL)
- + return;
- + if (bfqq->bic->wr_time_left)
- + /*
- + * This is the queue of a just-started process, and would
- + * deserve weight raising: we set wr_time_left to the full
- + * weight-raising duration to trigger weight-raising when
- + * and if the queue is split and the first request of the
- + * queue is enqueued.
- + */
- + bfqq->bic->wr_time_left = bfq_wr_duration(bfqq->bfqd);
- + else if (bfqq->wr_coeff > 1) {
- + unsigned long wr_duration =
- + jiffies - bfqq->last_wr_start_finish;
- + /*
- + * It may happen that a queue's weight raising period lasts
- + * longer than its wr_cur_max_time, as weight raising is
- + * handled only when a request is enqueued or dispatched (it
- + * does not use any timer). If the weight raising period is
- + * about to end, don't save it.
- + */
- + if (bfqq->wr_cur_max_time <= wr_duration)
- + bfqq->bic->wr_time_left = 0;
- + else
- + bfqq->bic->wr_time_left =
- + bfqq->wr_cur_max_time - wr_duration;
- + /*
- + * The bfq_queue is becoming shared or the requests of the
- + * process owning the queue are being redirected to a shared
- + * queue. Stop the weight raising period of the queue, as in
- + * both cases it should not be owned by an interactive or
- + * soft real-time application.
- + */
- + bfq_bfqq_end_wr(bfqq);
- + } else
- + bfqq->bic->wr_time_left = 0;
- + bfqq->bic->saved_idle_window = bfq_bfqq_idle_window(bfqq);
- + bfqq->bic->saved_IO_bound = bfq_bfqq_IO_bound(bfqq);
- + bfqq->bic->cooperations++;
- + bfqq->bic->failed_cooperations = 0;
- +}
- +
- +static inline void
- +bfq_get_bic_reference(struct bfq_queue *bfqq)
- +{
- + /*
- + * If bfqq->bic has a non-NULL value, the bic to which it belongs
- + * is about to begin using a shared bfq_queue.
- + */
- + if (bfqq->bic)
- + atomic_long_inc(&bfqq->bic->icq.ioc->refcount);
- +}
- +
- +static void
- +bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic,
- + struct bfq_queue *bfqq, struct bfq_queue *new_bfqq)
- +{
- + bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu",
- + (long unsigned)new_bfqq->pid);
- + /* Save weight raising and idle window of the merged queues */
- + bfq_bfqq_save_state(bfqq);
- + bfq_bfqq_save_state(new_bfqq);
- + if (bfq_bfqq_IO_bound(bfqq))
- + bfq_mark_bfqq_IO_bound(new_bfqq);
- + bfq_clear_bfqq_IO_bound(bfqq);
- + /*
- + * Grab a reference to the bic, to prevent it from being destroyed
- + * before being possibly touched by a bfq_split_bfqq().
- + */
- + bfq_get_bic_reference(bfqq);
- + bfq_get_bic_reference(new_bfqq);
- + /*
- + * Merge queues (that is, let bic redirect its requests to new_bfqq)
- + */
- + bic_set_bfqq(bic, new_bfqq, 1);
- + bfq_mark_bfqq_coop(new_bfqq);
- + /*
- + * new_bfqq now belongs to at least two bics (it is a shared queue):
- + * set new_bfqq->bic to NULL. bfqq either:
- + * - does not belong to any bic any more, and hence bfqq->bic must
- + * be set to NULL, or
- + * - is a queue whose owning bics have already been redirected to a
- + * different queue, hence the queue is destined to not belong to
- + * any bic soon and bfqq->bic is already NULL (therefore the next
- + * assignment causes no harm).
- + */
- + new_bfqq->bic = NULL;
- + bfqq->bic = NULL;
- + bfq_put_queue(bfqq);
- +}
- +
- +static inline void bfq_bfqq_increase_failed_cooperations(struct bfq_queue *bfqq)
- +{
- + struct bfq_io_cq *bic = bfqq->bic;
- + struct bfq_data *bfqd = bfqq->bfqd;
- +
- + if (bic && bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh) {
- + bic->failed_cooperations++;
- + if (bic->failed_cooperations >= bfqd->bfq_failed_cooperations)
- + bic->cooperations = 0;
- + }
- +}
- +
- +static int bfq_allow_merge(struct request_queue *q, struct request *rq,
- + struct bio *bio)
- +{
- + struct bfq_data *bfqd = q->elevator->elevator_data;
- + struct bfq_io_cq *bic;
- + struct bfq_queue *bfqq, *new_bfqq;
- +
- + /*
- + * Disallow merge of a sync bio into an async request.
- + */
- + if (bfq_bio_sync(bio) && !rq_is_sync(rq))
- + return 0;
- +
- + /*
- + * Lookup the bfqq that this bio will be queued with. Allow
- + * merge only if rq is queued there.
- + * Queue lock is held here.
- + */
- + bic = bfq_bic_lookup(bfqd, current->io_context);
- + if (bic == NULL)
- + return 0;
- +
- + bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio));
- + /*
- + * We take advantage of this function to perform an early merge
- + * of the queues of possible cooperating processes.
- + */
- + if (bfqq != NULL) {
- + new_bfqq = bfq_setup_cooperator(bfqd, bfqq, bio, false);
- + if (new_bfqq != NULL) {
- + bfq_merge_bfqqs(bfqd, bic, bfqq, new_bfqq);
- + /*
- + * If we get here, the bio will be queued in the
- + * shared queue, i.e., new_bfqq, so use new_bfqq
- + * to decide whether bio and rq can be merged.
- + */
- + bfqq = new_bfqq;
- + } else
- + bfq_bfqq_increase_failed_cooperations(bfqq);
- + }
- +
- + return bfqq == RQ_BFQQ(rq);
- +}
- +
- +static void __bfq_set_in_service_queue(struct bfq_data *bfqd,
- + struct bfq_queue *bfqq)
- +{
- + if (bfqq != NULL) {
- + bfq_mark_bfqq_must_alloc(bfqq);
- + bfq_mark_bfqq_budget_new(bfqq);
- + bfq_clear_bfqq_fifo_expire(bfqq);
- +
- + bfqd->budgets_assigned = (bfqd->budgets_assigned*7 + 256) / 8;
- +
- + bfq_log_bfqq(bfqd, bfqq,
- + "set_in_service_queue, cur-budget = %lu",
- + bfqq->entity.budget);
- + }
- +
- + bfqd->in_service_queue = bfqq;
- +}
- +
- +/*
- + * Get and set a new queue for service.
- + */
- +static struct bfq_queue *bfq_set_in_service_queue(struct bfq_data *bfqd)
- +{
- + struct bfq_queue *bfqq = bfq_get_next_queue(bfqd);
- +
- + __bfq_set_in_service_queue(bfqd, bfqq);
- + return bfqq;
- +}
- +
- +/*
- + * If enough samples have been computed, return the current max budget
- + * stored in bfqd, which is dynamically updated according to the
- + * estimated disk peak rate; otherwise return the default max budget
- + */
- +static inline unsigned long bfq_max_budget(struct bfq_data *bfqd)
- +{
- + if (bfqd->budgets_assigned < 194)
- + return bfq_default_max_budget;
- + else
- + return bfqd->bfq_max_budget;
- +}
- +
- +/*
- + * Return min budget, which is a fraction of the current or default
- + * max budget (trying with 1/32)
- + */
- +static inline unsigned long bfq_min_budget(struct bfq_data *bfqd)
- +{
- + if (bfqd->budgets_assigned < 194)
- + return bfq_default_max_budget / 32;
- + else
- + return bfqd->bfq_max_budget / 32;
- +}
- +
- +static void bfq_arm_slice_timer(struct bfq_data *bfqd)
- +{
- + struct bfq_queue *bfqq = bfqd->in_service_queue;
- + struct bfq_io_cq *bic;
- + unsigned long sl;
- +
- + BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list));
- +
- + /* Processes have exited, don't wait. */
- + bic = bfqd->in_service_bic;
- + if (bic == NULL || atomic_read(&bic->icq.ioc->active_ref) == 0)
- + return;
- +
- + bfq_mark_bfqq_wait_request(bfqq);
- +
- + /*
- + * We don't want to idle for seeks, but we do want to allow
- + * fair distribution of slice time for a process doing back-to-back
- + * seeks. So allow a little bit of time for him to submit a new rq.
- + *
- + * To prevent processes with (partly) seeky workloads from
- + * being too ill-treated, grant them a small fraction of the
- + * assigned budget before reducing the waiting time to
- + * BFQ_MIN_TT. This happened to help reduce latency.
- + */
- + sl = bfqd->bfq_slice_idle;
- + /*
- + * Unless the queue is being weight-raised, grant only minimum idle
- + * time if the queue either has been seeky for long enough or has
- + * already proved to be constantly seeky.
- + */
- + if (bfq_sample_valid(bfqq->seek_samples) &&
- + ((BFQQ_SEEKY(bfqq) && bfqq->entity.service >
- + bfq_max_budget(bfqq->bfqd) / 8) ||
- + bfq_bfqq_constantly_seeky(bfqq)) && bfqq->wr_coeff == 1)
- + sl = min(sl, msecs_to_jiffies(BFQ_MIN_TT));
- + else if (bfqq->wr_coeff > 1)
- + sl = sl * 3;
- + bfqd->last_idling_start = ktime_get();
- + mod_timer(&bfqd->idle_slice_timer, jiffies + sl);
- + bfq_log(bfqd, "arm idle: %u/%u ms",
- + jiffies_to_msecs(sl), jiffies_to_msecs(bfqd->bfq_slice_idle));
- +}
- +
- +/*
- + * Set the maximum time for the in-service queue to consume its
- + * budget. This prevents seeky processes from lowering the disk
- + * throughput (always guaranteed with a time slice scheme as in CFQ).
- + */
- +static void bfq_set_budget_timeout(struct bfq_data *bfqd)
- +{
- + struct bfq_queue *bfqq = bfqd->in_service_queue;
- + unsigned int timeout_coeff;
- + if (bfqq->wr_cur_max_time == bfqd->bfq_wr_rt_max_time)
- + timeout_coeff = 1;
- + else
- + timeout_coeff = bfqq->entity.weight / bfqq->entity.orig_weight;
- +
- + bfqd->last_budget_start = ktime_get();
- +
- + bfq_clear_bfqq_budget_new(bfqq);
- + bfqq->budget_timeout = jiffies +
- + bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] * timeout_coeff;
- +
- + bfq_log_bfqq(bfqd, bfqq, "set budget_timeout %u",
- + jiffies_to_msecs(bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] *
- + timeout_coeff));
- +}
- +
- +/*
- + * Move request from internal lists to the request queue dispatch list.
- + */
- +static void bfq_dispatch_insert(struct request_queue *q, struct request *rq)
- +{
- + struct bfq_data *bfqd = q->elevator->elevator_data;
- + struct bfq_queue *bfqq = RQ_BFQQ(rq);
- +
- + /*
- + * For consistency, the next instruction should have been executed
- + * after removing the request from the queue and dispatching it.
- + * We execute instead this instruction before bfq_remove_request()
- + * (and hence introduce a temporary inconsistency), for efficiency.
- + * In fact, in a forced_dispatch, this prevents two counters related
- + * to bfqq->dispatched to risk to be uselessly decremented if bfqq
- + * is not in service, and then to be incremented again after
- + * incrementing bfqq->dispatched.
- + */
- + bfqq->dispatched++;
- + bfq_remove_request(rq);
- + elv_dispatch_sort(q, rq);
- +
- + if (bfq_bfqq_sync(bfqq))
- + bfqd->sync_flight++;
- +}
- +
- +/*
- + * Return expired entry, or NULL to just start from scratch in rbtree.
- + */
- +static struct request *bfq_check_fifo(struct bfq_queue *bfqq)
- +{
- + struct request *rq = NULL;
- +
- + if (bfq_bfqq_fifo_expire(bfqq))
- + return NULL;
- +
- + bfq_mark_bfqq_fifo_expire(bfqq);
- +
- + if (list_empty(&bfqq->fifo))
- + return NULL;
- +
- + rq = rq_entry_fifo(bfqq->fifo.next);
- +
- + if (time_before(jiffies, rq_fifo_time(rq)))
- + return NULL;
- +
- + return rq;
- +}
- +
- +static inline unsigned long bfq_bfqq_budget_left(struct bfq_queue *bfqq)
- +{
- + struct bfq_entity *entity = &bfqq->entity;
- + return entity->budget - entity->service;
- +}
- +
- +static void __bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq)
- +{
- + BUG_ON(bfqq != bfqd->in_service_queue);
- +
- + __bfq_bfqd_reset_in_service(bfqd);
- +
- + /*
- + * If this bfqq is shared between multiple processes, check
- + * to make sure that those processes are still issuing I/Os
- + * within the mean seek distance. If not, it may be time to
- + * break the queues apart again.
- + */
- + if (bfq_bfqq_coop(bfqq) && BFQQ_SEEKY(bfqq))
- + bfq_mark_bfqq_split_coop(bfqq);
- +
- + if (RB_EMPTY_ROOT(&bfqq->sort_list)) {
- + /*
- + * Overloading budget_timeout field to store the time
- + * at which the queue remains with no backlog; used by
- + * the weight-raising mechanism.
- + */
- + bfqq->budget_timeout = jiffies;
- + bfq_del_bfqq_busy(bfqd, bfqq, 1);
- + } else {
- + bfq_activate_bfqq(bfqd, bfqq);
- + /*
- + * Resort priority tree of potential close cooperators.
- + */
- + bfq_rq_pos_tree_add(bfqd, bfqq);
- + }
- +}
- +
- +/**
- + * __bfq_bfqq_recalc_budget - try to adapt the budget to the @bfqq behavior.
- + * @bfqd: device data.
- + * @bfqq: queue to update.
- + * @reason: reason for expiration.
- + *
- + * Handle the feedback on @bfqq budget. See the body for detailed
- + * comments.
- + */
- +static void __bfq_bfqq_recalc_budget(struct bfq_data *bfqd,
- + struct bfq_queue *bfqq,
- + enum bfqq_expiration reason)
- +{
- + struct request *next_rq;
- + unsigned long budget, min_budget;
- +
- + budget = bfqq->max_budget;
- + min_budget = bfq_min_budget(bfqd);
- +
- + BUG_ON(bfqq != bfqd->in_service_queue);
- +
- + bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last budg %lu, budg left %lu",
- + bfqq->entity.budget, bfq_bfqq_budget_left(bfqq));
- + bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last max_budg %lu, min budg %lu",
- + budget, bfq_min_budget(bfqd));
- + bfq_log_bfqq(bfqd, bfqq, "recalc_budg: sync %d, seeky %d",
- + bfq_bfqq_sync(bfqq), BFQQ_SEEKY(bfqd->in_service_queue));
- +
- + if (bfq_bfqq_sync(bfqq)) {
- + switch (reason) {
- + /*
- + * Caveat: in all the following cases we trade latency
- + * for throughput.
- + */
- + case BFQ_BFQQ_TOO_IDLE:
- + /*
- + * This is the only case where we may reduce
- + * the budget: if there is no request of the
- + * process still waiting for completion, then
- + * we assume (tentatively) that the timer has
- + * expired because the batch of requests of
- + * the process could have been served with a
- + * smaller budget. Hence, betting that
- + * process will behave in the same way when it
- + * becomes backlogged again, we reduce its
- + * next budget. As long as we guess right,
- + * this budget cut reduces the latency
- + * experienced by the process.
- + *
- + * However, if there are still outstanding
- + * requests, then the process may have not yet
- + * issued its next request just because it is
- + * still waiting for the completion of some of
- + * the still outstanding ones. So in this
- + * subcase we do not reduce its budget, on the
- + * contrary we increase it to possibly boost
- + * the throughput, as discussed in the
- + * comments to the BUDGET_TIMEOUT case.
- + */
- + if (bfqq->dispatched > 0) /* still outstanding reqs */
- + budget = min(budget * 2, bfqd->bfq_max_budget);
- + else {
- + if (budget > 5 * min_budget)
- + budget -= 4 * min_budget;
- + else
- + budget = min_budget;
- + }
- + break;
- + case BFQ_BFQQ_BUDGET_TIMEOUT:
- + /*
- + * We double the budget here because: 1) it
- + * gives the chance to boost the throughput if
- + * this is not a seeky process (which may have
- + * bumped into this timeout because of, e.g.,
- + * ZBR), 2) together with charge_full_budget
- + * it helps give seeky processes higher
- + * timestamps, and hence be served less
- + * frequently.
- + */
- + budget = min(budget * 2, bfqd->bfq_max_budget);
- + break;
- + case BFQ_BFQQ_BUDGET_EXHAUSTED:
- + /*
- + * The process still has backlog, and did not
- + * let either the budget timeout or the disk
- + * idling timeout expire. Hence it is not
- + * seeky, has a short thinktime and may be
- + * happy with a higher budget too. So
- + * definitely increase the budget of this good
- + * candidate to boost the disk throughput.
- + */
- + budget = min(budget * 4, bfqd->bfq_max_budget);
- + break;
- + case BFQ_BFQQ_NO_MORE_REQUESTS:
- + /*
- + * Leave the budget unchanged.
- + */
- + default:
- + return;
- + }
- + } else /* async queue */
- + /* async queues get always the maximum possible budget
- + * (their ability to dispatch is limited by
- + * @bfqd->bfq_max_budget_async_rq).
- + */
- + budget = bfqd->bfq_max_budget;
- +
- + bfqq->max_budget = budget;
- +
- + if (bfqd->budgets_assigned >= 194 && bfqd->bfq_user_max_budget == 0 &&
- + bfqq->max_budget > bfqd->bfq_max_budget)
- + bfqq->max_budget = bfqd->bfq_max_budget;
- +
- + /*
- + * Make sure that we have enough budget for the next request.
- + * Since the finish time of the bfqq must be kept in sync with
- + * the budget, be sure to call __bfq_bfqq_expire() after the
- + * update.
- + */
- + next_rq = bfqq->next_rq;
- + if (next_rq != NULL)
- + bfqq->entity.budget = max_t(unsigned long, bfqq->max_budget,
- + bfq_serv_to_charge(next_rq, bfqq));
- + else
- + bfqq->entity.budget = bfqq->max_budget;
- +
- + bfq_log_bfqq(bfqd, bfqq, "head sect: %u, new budget %lu",
- + next_rq != NULL ? blk_rq_sectors(next_rq) : 0,
- + bfqq->entity.budget);
- +}
- +
- +static unsigned long bfq_calc_max_budget(u64 peak_rate, u64 timeout)
- +{
- + unsigned long max_budget;
- +
- + /*
- + * The max_budget calculated when autotuning is equal to the
- + * amount of sectors transfered in timeout_sync at the
- + * estimated peak rate.
- + */
- + max_budget = (unsigned long)(peak_rate * 1000 *
- + timeout >> BFQ_RATE_SHIFT);
- +
- + return max_budget;
- +}
- +
- +/*
- + * In addition to updating the peak rate, checks whether the process
- + * is "slow", and returns 1 if so. This slow flag is used, in addition
- + * to the budget timeout, to reduce the amount of service provided to
- + * seeky processes, and hence reduce their chances to lower the
- + * throughput. See the code for more details.
- + */
- +static int bfq_update_peak_rate(struct bfq_data *bfqd, struct bfq_queue *bfqq,
- + int compensate, enum bfqq_expiration reason)
- +{
- + u64 bw, usecs, expected, timeout;
- + ktime_t delta;
- + int update = 0;
- +
- + if (!bfq_bfqq_sync(bfqq) || bfq_bfqq_budget_new(bfqq))
- + return 0;
- +
- + if (compensate)
- + delta = bfqd->last_idling_start;
- + else
- + delta = ktime_get();
- + delta = ktime_sub(delta, bfqd->last_budget_start);
- + usecs = ktime_to_us(delta);
- +
- + /* Don't trust short/unrealistic values. */
- + if (usecs < 100 || usecs >= LONG_MAX)
- + return 0;
- +
- + /*
- + * Calculate the bandwidth for the last slice. We use a 64 bit
- + * value to store the peak rate, in sectors per usec in fixed
- + * point math. We do so to have enough precision in the estimate
- + * and to avoid overflows.
- + */
- + bw = (u64)bfqq->entity.service << BFQ_RATE_SHIFT;
- + do_div(bw, (unsigned long)usecs);
- +
- + timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]);
- +
- + /*
- + * Use only long (> 20ms) intervals to filter out spikes for
- + * the peak rate estimation.
- + */
- + if (usecs > 20000) {
- + if (bw > bfqd->peak_rate ||
- + (!BFQQ_SEEKY(bfqq) &&
- + reason == BFQ_BFQQ_BUDGET_TIMEOUT)) {
- + bfq_log(bfqd, "measured bw =%llu", bw);
- + /*
- + * To smooth oscillations use a low-pass filter with
- + * alpha=7/8, i.e.,
- + * new_rate = (7/8) * old_rate + (1/8) * bw
- + */
- + do_div(bw, 8);
- + if (bw == 0)
- + return 0;
- + bfqd->peak_rate *= 7;
- + do_div(bfqd->peak_rate, 8);
- + bfqd->peak_rate += bw;
- + update = 1;
- + bfq_log(bfqd, "new peak_rate=%llu", bfqd->peak_rate);
- + }
- +
- + update |= bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES - 1;
- +
- + if (bfqd->peak_rate_samples < BFQ_PEAK_RATE_SAMPLES)
- + bfqd->peak_rate_samples++;
- +
- + if (bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES &&
- + update) {
- + int dev_type = blk_queue_nonrot(bfqd->queue);
- + if (bfqd->bfq_user_max_budget == 0) {
- + bfqd->bfq_max_budget =
- + bfq_calc_max_budget(bfqd->peak_rate,
- + timeout);
- + bfq_log(bfqd, "new max_budget=%lu",
- + bfqd->bfq_max_budget);
- + }
- + if (bfqd->device_speed == BFQ_BFQD_FAST &&
- + bfqd->peak_rate < device_speed_thresh[dev_type]) {
- + bfqd->device_speed = BFQ_BFQD_SLOW;
- + bfqd->RT_prod = R_slow[dev_type] *
- + T_slow[dev_type];
- + } else if (bfqd->device_speed == BFQ_BFQD_SLOW &&
- + bfqd->peak_rate > device_speed_thresh[dev_type]) {
- + bfqd->device_speed = BFQ_BFQD_FAST;
- + bfqd->RT_prod = R_fast[dev_type] *
- + T_fast[dev_type];
- + }
- + }
- + }
- +
- + /*
- + * If the process has been served for a too short time
- + * interval to let its possible sequential accesses prevail on
- + * the initial seek time needed to move the disk head on the
- + * first sector it requested, then give the process a chance
- + * and for the moment return false.
- + */
- + if (bfqq->entity.budget <= bfq_max_budget(bfqd) / 8)
- + return 0;
- +
- + /*
- + * A process is considered ``slow'' (i.e., seeky, so that we
- + * cannot treat it fairly in the service domain, as it would
- + * slow down too much the other processes) if, when a slice
- + * ends for whatever reason, it has received service at a
- + * rate that would not be high enough to complete the budget
- + * before the budget timeout expiration.
- + */
- + expected = bw * 1000 * timeout >> BFQ_RATE_SHIFT;
- +
- + /*
- + * Caveat: processes doing IO in the slower disk zones will
- + * tend to be slow(er) even if not seeky. And the estimated
- + * peak rate will actually be an average over the disk
- + * surface. Hence, to not be too harsh with unlucky processes,
- + * we keep a budget/3 margin of safety before declaring a
- + * process slow.
- + */
- + return expected > (4 * bfqq->entity.budget) / 3;
- +}
- +
- +/*
- + * To be deemed as soft real-time, an application must meet two
- + * requirements. First, the application must not require an average
- + * bandwidth higher than the approximate bandwidth required to playback or
- + * record a compressed high-definition video.
- + * The next function is invoked on the completion of the last request of a
- + * batch, to compute the next-start time instant, soft_rt_next_start, such
- + * that, if the next request of the application does not arrive before
- + * soft_rt_next_start, then the above requirement on the bandwidth is met.
- + *
- + * The second requirement is that the request pattern of the application is
- + * isochronous, i.e., that, after issuing a request or a batch of requests,
- + * the application stops issuing new requests until all its pending requests
- + * have been completed. After that, the application may issue a new batch,
- + * and so on.
- + * For this reason the next function is invoked to compute
- + * soft_rt_next_start only for applications that meet this requirement,
- + * whereas soft_rt_next_start is set to infinity for applications that do
- + * not.
- + *
- + * Unfortunately, even a greedy application may happen to behave in an
- + * isochronous way if the CPU load is high. In fact, the application may
- + * stop issuing requests while the CPUs are busy serving other processes,
- + * then restart, then stop again for a while, and so on. In addition, if
- + * the disk achieves a low enough throughput with the request pattern
- + * issued by the application (e.g., because the request pattern is random
- + * and/or the device is slow), then the application may meet the above
- + * bandwidth requirement too. To prevent such a greedy application to be
- + * deemed as soft real-time, a further rule is used in the computation of
- + * soft_rt_next_start: soft_rt_next_start must be higher than the current
- + * time plus the maximum time for which the arrival of a request is waited
- + * for when a sync queue becomes idle, namely bfqd->bfq_slice_idle.
- + * This filters out greedy applications, as the latter issue instead their
- + * next request as soon as possible after the last one has been completed
- + * (in contrast, when a batch of requests is completed, a soft real-time
- + * application spends some time processing data).
- + *
- + * Unfortunately, the last filter may easily generate false positives if
- + * only bfqd->bfq_slice_idle is used as a reference time interval and one
- + * or both the following cases occur:
- + * 1) HZ is so low that the duration of a jiffy is comparable to or higher
- + * than bfqd->bfq_slice_idle. This happens, e.g., on slow devices with
- + * HZ=100.
- + * 2) jiffies, instead of increasing at a constant rate, may stop increasing
- + * for a while, then suddenly 'jump' by several units to recover the lost
- + * increments. This seems to happen, e.g., inside virtual machines.
- + * To address this issue, we do not use as a reference time interval just
- + * bfqd->bfq_slice_idle, but bfqd->bfq_slice_idle plus a few jiffies. In
- + * particular we add the minimum number of jiffies for which the filter
- + * seems to be quite precise also in embedded systems and KVM/QEMU virtual
- + * machines.
- + */
- +static inline unsigned long bfq_bfqq_softrt_next_start(struct bfq_data *bfqd,
- + struct bfq_queue *bfqq)
- +{
- + return max(bfqq->last_idle_bklogged +
- + HZ * bfqq->service_from_backlogged /
- + bfqd->bfq_wr_max_softrt_rate,
- + jiffies + bfqq->bfqd->bfq_slice_idle + 4);
- +}
- +
- +/*
- + * Return the largest-possible time instant such that, for as long as possible,
- + * the current time will be lower than this time instant according to the macro
- + * time_is_before_jiffies().
- + */
- +static inline unsigned long bfq_infinity_from_now(unsigned long now)
- +{
- + return now + ULONG_MAX / 2;
- +}
- +
- +/**
- + * bfq_bfqq_expire - expire a queue.
- + * @bfqd: device owning the queue.
- + * @bfqq: the queue to expire.
- + * @compensate: if true, compensate for the time spent idling.
- + * @reason: the reason causing the expiration.
- + *
- + *
- + * If the process associated to the queue is slow (i.e., seeky), or in
- + * case of budget timeout, or, finally, if it is async, we
- + * artificially charge it an entire budget (independently of the
- + * actual service it received). As a consequence, the queue will get
- + * higher timestamps than the correct ones upon reactivation, and
- + * hence it will be rescheduled as if it had received more service
- + * than what it actually received. In the end, this class of processes
- + * will receive less service in proportion to how slowly they consume
- + * their budgets (and hence how seriously they tend to lower the
- + * throughput).
- + *
- + * In contrast, when a queue expires because it has been idling for
- + * too much or because it exhausted its budget, we do not touch the
- + * amount of service it has received. Hence when the queue will be
- + * reactivated and its timestamps updated, the latter will be in sync
- + * with the actual service received by the queue until expiration.
- + *
- + * Charging a full budget to the first type of queues and the exact
- + * service to the others has the effect of using the WF2Q+ policy to
- + * schedule the former on a timeslice basis, without violating the
- + * service domain guarantees of the latter.
- + */
- +static void bfq_bfqq_expire(struct bfq_data *bfqd,
- + struct bfq_queue *bfqq,
- + int compensate,
- + enum bfqq_expiration reason)
- +{
- + int slow;
- + BUG_ON(bfqq != bfqd->in_service_queue);
- +
- + /* Update disk peak rate for autotuning and check whether the
- + * process is slow (see bfq_update_peak_rate).
- + */
- + slow = bfq_update_peak_rate(bfqd, bfqq, compensate, reason);
- +
- + /*
- + * As above explained, 'punish' slow (i.e., seeky), timed-out
- + * and async queues, to favor sequential sync workloads.
- + *
- + * Processes doing I/O in the slower disk zones will tend to be
- + * slow(er) even if not seeky. Hence, since the estimated peak
- + * rate is actually an average over the disk surface, these
- + * processes may timeout just for bad luck. To avoid punishing
- + * them we do not charge a full budget to a process that
- + * succeeded in consuming at least 2/3 of its budget.
- + */
- + if (slow || (reason == BFQ_BFQQ_BUDGET_TIMEOUT &&
- + bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3))
- + bfq_bfqq_charge_full_budget(bfqq);
- +
- + bfqq->service_from_backlogged += bfqq->entity.service;
- +
- + if (BFQQ_SEEKY(bfqq) && reason == BFQ_BFQQ_BUDGET_TIMEOUT &&
- + !bfq_bfqq_constantly_seeky(bfqq)) {
- + bfq_mark_bfqq_constantly_seeky(bfqq);
- + if (!blk_queue_nonrot(bfqd->queue))
- + bfqd->const_seeky_busy_in_flight_queues++;
- + }
- +
- + if (reason == BFQ_BFQQ_TOO_IDLE &&
- + bfqq->entity.service <= 2 * bfqq->entity.budget / 10 )
- + bfq_clear_bfqq_IO_bound(bfqq);
- +
- + if (bfqd->low_latency && bfqq->wr_coeff == 1)
- + bfqq->last_wr_start_finish = jiffies;
- +
- + if (bfqd->low_latency && bfqd->bfq_wr_max_softrt_rate > 0 &&
- + RB_EMPTY_ROOT(&bfqq->sort_list)) {
- + /*
- + * If we get here, and there are no outstanding requests,
- + * then the request pattern is isochronous (see the comments
- + * to the function bfq_bfqq_softrt_next_start()). Hence we
- + * can compute soft_rt_next_start. If, instead, the queue
- + * still has outstanding requests, then we have to wait
- + * for the completion of all the outstanding requests to
- + * discover whether the request pattern is actually
- + * isochronous.
- + */
- + if (bfqq->dispatched == 0)
- + bfqq->soft_rt_next_start =
- + bfq_bfqq_softrt_next_start(bfqd, bfqq);
- + else {
- + /*
- + * The application is still waiting for the
- + * completion of one or more requests:
- + * prevent it from possibly being incorrectly
- + * deemed as soft real-time by setting its
- + * soft_rt_next_start to infinity. In fact,
- + * without this assignment, the application
- + * would be incorrectly deemed as soft
- + * real-time if:
- + * 1) it issued a new request before the
- + * completion of all its in-flight
- + * requests, and
- + * 2) at that time, its soft_rt_next_start
- + * happened to be in the past.
- + */
- + bfqq->soft_rt_next_start =
- + bfq_infinity_from_now(jiffies);
- + /*
- + * Schedule an update of soft_rt_next_start to when
- + * the task may be discovered to be isochronous.
- + */
- + bfq_mark_bfqq_softrt_update(bfqq);
- + }
- + }
- +
- + bfq_log_bfqq(bfqd, bfqq,
- + "expire (%d, slow %d, num_disp %d, idle_win %d)", reason,
- + slow, bfqq->dispatched, bfq_bfqq_idle_window(bfqq));
- +
- + /*
- + * Increase, decrease or leave budget unchanged according to
- + * reason.
- + */
- + __bfq_bfqq_recalc_budget(bfqd, bfqq, reason);
- + __bfq_bfqq_expire(bfqd, bfqq);
- +}
- +
- +/*
- + * Budget timeout is not implemented through a dedicated timer, but
- + * just checked on request arrivals and completions, as well as on
- + * idle timer expirations.
- + */
- +static int bfq_bfqq_budget_timeout(struct bfq_queue *bfqq)
- +{
- + if (bfq_bfqq_budget_new(bfqq) ||
- + time_before(jiffies, bfqq->budget_timeout))
- + return 0;
- + return 1;
- +}
- +
- +/*
- + * If we expire a queue that is waiting for the arrival of a new
- + * request, we may prevent the fictitious timestamp back-shifting that
- + * allows the guarantees of the queue to be preserved (see [1] for
- + * this tricky aspect). Hence we return true only if this condition
- + * does not hold, or if the queue is slow enough to deserve only to be
- + * kicked off for preserving a high throughput.
- +*/
- +static inline int bfq_may_expire_for_budg_timeout(struct bfq_queue *bfqq)
- +{
- + bfq_log_bfqq(bfqq->bfqd, bfqq,
- + "may_budget_timeout: wait_request %d left %d timeout %d",
- + bfq_bfqq_wait_request(bfqq),
- + bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3,
- + bfq_bfqq_budget_timeout(bfqq));
- +
- + return (!bfq_bfqq_wait_request(bfqq) ||
- + bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3)
- + &&
- + bfq_bfqq_budget_timeout(bfqq);
- +}
- +
- +/*
- + * Device idling is allowed only for the queues for which this function
- + * returns true. For this reason, the return value of this function plays a
- + * critical role for both throughput boosting and service guarantees. The
- + * return value is computed through a logical expression. In this rather
- + * long comment, we try to briefly describe all the details and motivations
- + * behind the components of this logical expression.
- + *
- + * First, the expression may be true only for sync queues. Besides, if
- + * bfqq is also being weight-raised, then the expression always evaluates
- + * to true, as device idling is instrumental for preserving low-latency
- + * guarantees (see [1]). Otherwise, the expression evaluates to true only
- + * if bfqq has a non-null idle window and at least one of the following
- + * two conditions holds. The first condition is that the device is not
- + * performing NCQ, because idling the device most certainly boosts the
- + * throughput if this condition holds and bfqq has been granted a non-null
- + * idle window. The second compound condition is made of the logical AND of
- + * two components.
- + *
- + * The first component is true only if there is no weight-raised busy
- + * queue. This guarantees that the device is not idled for a sync non-
- + * weight-raised queue when there are busy weight-raised queues. The former
- + * is then expired immediately if empty. Combined with the timestamping
- + * rules of BFQ (see [1] for details), this causes sync non-weight-raised
- + * queues to get a lower number of requests served, and hence to ask for a
- + * lower number of requests from the request pool, before the busy weight-
- + * raised queues get served again.
- + *
- + * This is beneficial for the processes associated with weight-raised
- + * queues, when the request pool is saturated (e.g., in the presence of
- + * write hogs). In fact, if the processes associated with the other queues
- + * ask for requests at a lower rate, then weight-raised processes have a
- + * higher probability to get a request from the pool immediately (or at
- + * least soon) when they need one. Hence they have a higher probability to
- + * actually get a fraction of the disk throughput proportional to their
- + * high weight. This is especially true with NCQ-capable drives, which
- + * enqueue several requests in advance and further reorder internally-
- + * queued requests.
- + *
- + * In the end, mistreating non-weight-raised queues when there are busy
- + * weight-raised queues seems to mitigate starvation problems in the
- + * presence of heavy write workloads and NCQ, and hence to guarantee a
- + * higher application and system responsiveness in these hostile scenarios.
- + *
- + * If the first component of the compound condition is instead true, i.e.,
- + * there is no weight-raised busy queue, then the second component of the
- + * compound condition takes into account service-guarantee and throughput
- + * issues related to NCQ (recall that the compound condition is evaluated
- + * only if the device is detected as supporting NCQ).
- + *
- + * As for service guarantees, allowing the drive to enqueue more than one
- + * request at a time, and hence delegating de facto final scheduling
- + * decisions to the drive's internal scheduler, causes loss of control on
- + * the actual request service order. In this respect, when the drive is
- + * allowed to enqueue more than one request at a time, the service
- + * distribution enforced by the drive's internal scheduler is likely to
- + * coincide with the desired device-throughput distribution only in the
- + * following, perfectly symmetric, scenario:
- + * 1) all active queues have the same weight,
- + * 2) all active groups at the same level in the groups tree have the same
- + * weight,
- + * 3) all active groups at the same level in the groups tree have the same
- + * number of children.
- + *
- + * Even in such a scenario, sequential I/O may still receive a preferential
- + * treatment, but this is not likely to be a big issue with flash-based
- + * devices, because of their non-dramatic loss of throughput with random
- + * I/O. Things do differ with HDDs, for which additional care is taken, as
- + * explained after completing the discussion for flash-based devices.
- + *
- + * Unfortunately, keeping the necessary state for evaluating exactly the
- + * above symmetry conditions would be quite complex and time-consuming.
- + * Therefore BFQ evaluates instead the following stronger sub-conditions,
- + * for which it is much easier to maintain the needed state:
- + * 1) all active queues have the same weight,
- + * 2) all active groups have the same weight,
- + * 3) all active groups have at most one active child each.
- + * In particular, the last two conditions are always true if hierarchical
- + * support and the cgroups interface are not enabled, hence no state needs
- + * to be maintained in this case.
- + *
- + * According to the above considerations, the second component of the
- + * compound condition evaluates to true if any of the above symmetry
- + * sub-condition does not hold, or the device is not flash-based. Therefore,
- + * if also the first component is true, then idling is allowed for a sync
- + * queue. These are the only sub-conditions considered if the device is
- + * flash-based, as, for such a device, it is sensible to force idling only
- + * for service-guarantee issues. In fact, as for throughput, idling
- + * NCQ-capable flash-based devices would not boost the throughput even
- + * with sequential I/O; rather it would lower the throughput in proportion
- + * to how fast the device is. In the end, (only) if all the three
- + * sub-conditions hold and the device is flash-based, the compound
- + * condition evaluates to false and therefore no idling is performed.
- + *
- + * As already said, things change with a rotational device, where idling
- + * boosts the throughput with sequential I/O (even with NCQ). Hence, for
- + * such a device the second component of the compound condition evaluates
- + * to true also if the following additional sub-condition does not hold:
- + * the queue is constantly seeky. Unfortunately, this different behavior
- + * with respect to flash-based devices causes an additional asymmetry: if
- + * some sync queues enjoy idling and some other sync queues do not, then
- + * the latter get a low share of the device throughput, simply because the
- + * former get many requests served after being set as in service, whereas
- + * the latter do not. As a consequence, to guarantee the desired throughput
- + * distribution, on HDDs the compound expression evaluates to true (and
- + * hence device idling is performed) also if the following last symmetry
- + * condition does not hold: no other queue is benefiting from idling. Also
- + * this last condition is actually replaced with a simpler-to-maintain and
- + * stronger condition: there is no busy queue which is not constantly seeky
- + * (and hence may also benefit from idling).
- + *
- + * To sum up, when all the required symmetry and throughput-boosting
- + * sub-conditions hold, the second component of the compound condition
- + * evaluates to false, and hence no idling is performed. This helps to
- + * keep the drives' internal queues full on NCQ-capable devices, and hence
- + * to boost the throughput, without causing 'almost' any loss of service
- + * guarantees. The 'almost' follows from the fact that, if the internal
- + * queue of one such device is filled while all the sub-conditions hold,
- + * but at some point in time some sub-condition stops to hold, then it may
- + * become impossible to let requests be served in the new desired order
- + * until all the requests already queued in the device have been served.
- + */
- +static inline bool bfq_bfqq_must_not_expire(struct bfq_queue *bfqq)
- +{
- + struct bfq_data *bfqd = bfqq->bfqd;
- +#ifdef CONFIG_CGROUP_BFQIO
- +#define symmetric_scenario (!bfqd->active_numerous_groups && \
- + !bfq_differentiated_weights(bfqd))
- +#else
- +#define symmetric_scenario (!bfq_differentiated_weights(bfqd))
- +#endif
- +#define cond_for_seeky_on_ncq_hdd (bfq_bfqq_constantly_seeky(bfqq) && \
- + bfqd->busy_in_flight_queues == \
- + bfqd->const_seeky_busy_in_flight_queues)
- +/*
- + * Condition for expiring a non-weight-raised queue (and hence not idling
- + * the device).
- + */
- +#define cond_for_expiring_non_wr (bfqd->hw_tag && \
- + (bfqd->wr_busy_queues > 0 || \
- + (symmetric_scenario && \
- + (blk_queue_nonrot(bfqd->queue) || \
- + cond_for_seeky_on_ncq_hdd))))
- +
- + return bfq_bfqq_sync(bfqq) &&
- + (bfq_bfqq_IO_bound(bfqq) || bfqq->wr_coeff > 1) &&
- + (bfqq->wr_coeff > 1 ||
- + (bfq_bfqq_idle_window(bfqq) &&
- + !cond_for_expiring_non_wr)
- + );
- +}
- +
- +/*
- + * If the in-service queue is empty but sync, and the function
- + * bfq_bfqq_must_not_expire returns true, then:
- + * 1) the queue must remain in service and cannot be expired, and
- + * 2) the disk must be idled to wait for the possible arrival of a new
- + * request for the queue.
- + * See the comments to the function bfq_bfqq_must_not_expire for the reasons
- + * why performing device idling is the best choice to boost the throughput
- + * and preserve service guarantees when bfq_bfqq_must_not_expire itself
- + * returns true.
- + */
- +static inline bool bfq_bfqq_must_idle(struct bfq_queue *bfqq)
- +{
- + struct bfq_data *bfqd = bfqq->bfqd;
- +
- + return RB_EMPTY_ROOT(&bfqq->sort_list) && bfqd->bfq_slice_idle != 0 &&
- + bfq_bfqq_must_not_expire(bfqq);
- +}
- +
- +/*
- + * Select a queue for service. If we have a current queue in service,
- + * check whether to continue servicing it, or retrieve and set a new one.
- + */
- +static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd)
- +{
- + struct bfq_queue *bfqq;
- + struct request *next_rq;
- + enum bfqq_expiration reason = BFQ_BFQQ_BUDGET_TIMEOUT;
- +
- + bfqq = bfqd->in_service_queue;
- + if (bfqq == NULL)
- + goto new_queue;
- +
- + bfq_log_bfqq(bfqd, bfqq, "select_queue: already in-service queue");
- +
- + if (bfq_may_expire_for_budg_timeout(bfqq) &&
- + !timer_pending(&bfqd->idle_slice_timer) &&
- + !bfq_bfqq_must_idle(bfqq))
- + goto expire;
- +
- + next_rq = bfqq->next_rq;
- + /*
- + * If bfqq has requests queued and it has enough budget left to
- + * serve them, keep the queue, otherwise expire it.
- + */
- + if (next_rq != NULL) {
- + if (bfq_serv_to_charge(next_rq, bfqq) >
- + bfq_bfqq_budget_left(bfqq)) {
- + reason = BFQ_BFQQ_BUDGET_EXHAUSTED;
- + goto expire;
- + } else {
- + /*
- + * The idle timer may be pending because we may
- + * not disable disk idling even when a new request
- + * arrives.
- + */
- + if (timer_pending(&bfqd->idle_slice_timer)) {
- + /*
- + * If we get here: 1) at least a new request
- + * has arrived but we have not disabled the
- + * timer because the request was too small,
- + * 2) then the block layer has unplugged
- + * the device, causing the dispatch to be
- + * invoked.
- + *
- + * Since the device is unplugged, now the
- + * requests are probably large enough to
- + * provide a reasonable throughput.
- + * So we disable idling.
- + */
- + bfq_clear_bfqq_wait_request(bfqq);
- + del_timer(&bfqd->idle_slice_timer);
- + }
- + goto keep_queue;
- + }
- + }
- +
- + /*
- + * No requests pending. If the in-service queue still has requests
- + * in flight (possibly waiting for a completion) or is idling for a
- + * new request, then keep it.
- + */
- + if (timer_pending(&bfqd->idle_slice_timer) ||
- + (bfqq->dispatched != 0 && bfq_bfqq_must_not_expire(bfqq))) {
- + bfqq = NULL;
- + goto keep_queue;
- + }
- +
- + reason = BFQ_BFQQ_NO_MORE_REQUESTS;
- +expire:
- + bfq_bfqq_expire(bfqd, bfqq, 0, reason);
- +new_queue:
- + bfqq = bfq_set_in_service_queue(bfqd);
- + bfq_log(bfqd, "select_queue: new queue %d returned",
- + bfqq != NULL ? bfqq->pid : 0);
- +keep_queue:
- + return bfqq;
- +}
- +
- +static void bfq_update_wr_data(struct bfq_data *bfqd, struct bfq_queue *bfqq)
- +{
- + struct bfq_entity *entity = &bfqq->entity;
- + if (bfqq->wr_coeff > 1) { /* queue is being weight-raised */
- + bfq_log_bfqq(bfqd, bfqq,
- + "raising period dur %u/%u msec, old coeff %u, w %d(%d)",
- + jiffies_to_msecs(jiffies - bfqq->last_wr_start_finish),
- + jiffies_to_msecs(bfqq->wr_cur_max_time),
- + bfqq->wr_coeff,
- + bfqq->entity.weight, bfqq->entity.orig_weight);
- +
- + BUG_ON(bfqq != bfqd->in_service_queue && entity->weight !=
- + entity->orig_weight * bfqq->wr_coeff);
- + if (entity->ioprio_changed)
- + bfq_log_bfqq(bfqd, bfqq, "WARN: pending prio change");
- +
- + /*
- + * If too much time has elapsed from the beginning
- + * of this weight-raising period, or the queue has
- + * exceeded the acceptable number of cooperations,
- + * stop it.
- + */
- + if (bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh ||
- + time_is_before_jiffies(bfqq->last_wr_start_finish +
- + bfqq->wr_cur_max_time)) {
- + bfqq->last_wr_start_finish = jiffies;
- + bfq_log_bfqq(bfqd, bfqq,
- + "wrais ending at %lu, rais_max_time %u",
- + bfqq->last_wr_start_finish,
- + jiffies_to_msecs(bfqq->wr_cur_max_time));
- + bfq_bfqq_end_wr(bfqq);
- + }
- + }
- + /* Update weight both if it must be raised and if it must be lowered */
- + if ((entity->weight > entity->orig_weight) != (bfqq->wr_coeff > 1))
- + __bfq_entity_update_weight_prio(
- + bfq_entity_service_tree(entity),
- + entity);
- +}
- +
- +/*
- + * Dispatch one request from bfqq, moving it to the request queue
- + * dispatch list.
- + */
- +static int bfq_dispatch_request(struct bfq_data *bfqd,
- + struct bfq_queue *bfqq)
- +{
- + int dispatched = 0;
- + struct request *rq;
- + unsigned long service_to_charge;
- +
- + BUG_ON(RB_EMPTY_ROOT(&bfqq->sort_list));
- +
- + /* Follow expired path, else get first next available. */
- + rq = bfq_check_fifo(bfqq);
- + if (rq == NULL)
- + rq = bfqq->next_rq;
- + service_to_charge = bfq_serv_to_charge(rq, bfqq);
- +
- + if (service_to_charge > bfq_bfqq_budget_left(bfqq)) {
- + /*
- + * This may happen if the next rq is chosen in fifo order
- + * instead of sector order. The budget is properly
- + * dimensioned to be always sufficient to serve the next
- + * request only if it is chosen in sector order. The reason
- + * is that it would be quite inefficient and little useful
- + * to always make sure that the budget is large enough to
- + * serve even the possible next rq in fifo order.
- + * In fact, requests are seldom served in fifo order.
- + *
- + * Expire the queue for budget exhaustion, and make sure
- + * that the next act_budget is enough to serve the next
- + * request, even if it comes from the fifo expired path.
- + */
- + bfqq->next_rq = rq;
- + /*
- + * Since this dispatch is failed, make sure that
- + * a new one will be performed
- + */
- + if (!bfqd->rq_in_driver)
- + bfq_schedule_dispatch(bfqd);
- + goto expire;
- + }
- +
- + /* Finally, insert request into driver dispatch list. */
- + bfq_bfqq_served(bfqq, service_to_charge);
- + bfq_dispatch_insert(bfqd->queue, rq);
- +
- + bfq_update_wr_data(bfqd, bfqq);
- +
- + bfq_log_bfqq(bfqd, bfqq,
- + "dispatched %u sec req (%llu), budg left %lu",
- + blk_rq_sectors(rq),
- + (long long unsigned)blk_rq_pos(rq),
- + bfq_bfqq_budget_left(bfqq));
- +
- + dispatched++;
- +
- + if (bfqd->in_service_bic == NULL) {
- + atomic_long_inc(&RQ_BIC(rq)->icq.ioc->refcount);
- + bfqd->in_service_bic = RQ_BIC(rq);
- + }
- +
- + if (bfqd->busy_queues > 1 && ((!bfq_bfqq_sync(bfqq) &&
- + dispatched >= bfqd->bfq_max_budget_async_rq) ||
- + bfq_class_idle(bfqq)))
- + goto expire;
- +
- + return dispatched;
- +
- +expire:
- + bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_EXHAUSTED);
- + return dispatched;
- +}
- +
- +static int __bfq_forced_dispatch_bfqq(struct bfq_queue *bfqq)
- +{
- + int dispatched = 0;
- +
- + while (bfqq->next_rq != NULL) {
- + bfq_dispatch_insert(bfqq->bfqd->queue, bfqq->next_rq);
- + dispatched++;
- + }
- +
- + BUG_ON(!list_empty(&bfqq->fifo));
- + return dispatched;
- +}
- +
- +/*
- + * Drain our current requests.
- + * Used for barriers and when switching io schedulers on-the-fly.
- + */
- +static int bfq_forced_dispatch(struct bfq_data *bfqd)
- +{
- + struct bfq_queue *bfqq, *n;
- + struct bfq_service_tree *st;
- + int dispatched = 0;
- +
- + bfqq = bfqd->in_service_queue;
- + if (bfqq != NULL)
- + __bfq_bfqq_expire(bfqd, bfqq);
- +
- + /*
- + * Loop through classes, and be careful to leave the scheduler
- + * in a consistent state, as feedback mechanisms and vtime
- + * updates cannot be disabled during the process.
- + */
- + list_for_each_entry_safe(bfqq, n, &bfqd->active_list, bfqq_list) {
- + st = bfq_entity_service_tree(&bfqq->entity);
- +
- + dispatched += __bfq_forced_dispatch_bfqq(bfqq);
- + bfqq->max_budget = bfq_max_budget(bfqd);
- +
- + bfq_forget_idle(st);
- + }
- +
- + BUG_ON(bfqd->busy_queues != 0);
- +
- + return dispatched;
- +}
- +
- +static int bfq_dispatch_requests(struct request_queue *q, int force)
- +{
- + struct bfq_data *bfqd = q->elevator->elevator_data;
- + struct bfq_queue *bfqq;
- + int max_dispatch;
- +
- + bfq_log(bfqd, "dispatch requests: %d busy queues", bfqd->busy_queues);
- + if (bfqd->busy_queues == 0)
- + return 0;
- +
- + if (unlikely(force))
- + return bfq_forced_dispatch(bfqd);
- +
- + bfqq = bfq_select_queue(bfqd);
- + if (bfqq == NULL)
- + return 0;
- +
- + max_dispatch = bfqd->bfq_quantum;
- + if (bfq_class_idle(bfqq))
- + max_dispatch = 1;
- +
- + if (!bfq_bfqq_sync(bfqq))
- + max_dispatch = bfqd->bfq_max_budget_async_rq;
- +
- + if (bfqq->dispatched >= max_dispatch) {
- + if (bfqd->busy_queues > 1)
- + return 0;
- + if (bfqq->dispatched >= 4 * max_dispatch)
- + return 0;
- + }
- +
- + if (bfqd->sync_flight != 0 && !bfq_bfqq_sync(bfqq))
- + return 0;
- +
- + bfq_clear_bfqq_wait_request(bfqq);
- + BUG_ON(timer_pending(&bfqd->idle_slice_timer));
- +
- + if (!bfq_dispatch_request(bfqd, bfqq))
- + return 0;
- +
- + bfq_log_bfqq(bfqd, bfqq, "dispatched one request of %d (max_disp %d)",
- + bfqq->pid, max_dispatch);
- +
- + return 1;
- +}
- +
- +/*
- + * Task holds one reference to the queue, dropped when task exits. Each rq
- + * in-flight on this queue also holds a reference, dropped when rq is freed.
- + *
- + * Queue lock must be held here.
- + */
- +static void bfq_put_queue(struct bfq_queue *bfqq)
- +{
- + struct bfq_data *bfqd = bfqq->bfqd;
- +
- + BUG_ON(atomic_read(&bfqq->ref) <= 0);
- +
- + bfq_log_bfqq(bfqd, bfqq, "put_queue: %p %d", bfqq,
- + atomic_read(&bfqq->ref));
- + if (!atomic_dec_and_test(&bfqq->ref))
- + return;
- +
- + BUG_ON(rb_first(&bfqq->sort_list) != NULL);
- + BUG_ON(bfqq->allocated[READ] + bfqq->allocated[WRITE] != 0);
- + BUG_ON(bfqq->entity.tree != NULL);
- + BUG_ON(bfq_bfqq_busy(bfqq));
- + BUG_ON(bfqd->in_service_queue == bfqq);
- +
- + bfq_log_bfqq(bfqd, bfqq, "put_queue: %p freed", bfqq);
- +
- + kmem_cache_free(bfq_pool, bfqq);
- +}
- +
- +static void bfq_put_cooperator(struct bfq_queue *bfqq)
- +{
- + struct bfq_queue *__bfqq, *next;
- +
- + /*
- + * If this queue was scheduled to merge with another queue, be
- + * sure to drop the reference taken on that queue (and others in
- + * the merge chain). See bfq_setup_merge and bfq_merge_bfqqs.
- + */
- + __bfqq = bfqq->new_bfqq;
- + while (__bfqq) {
- + if (__bfqq == bfqq)
- + break;
- + next = __bfqq->new_bfqq;
- + bfq_put_queue(__bfqq);
- + __bfqq = next;
- + }
- +}
- +
- +static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
- +{
- + if (bfqq == bfqd->in_service_queue) {
- + __bfq_bfqq_expire(bfqd, bfqq);
- + bfq_schedule_dispatch(bfqd);
- + }
- +
- + bfq_log_bfqq(bfqd, bfqq, "exit_bfqq: %p, %d", bfqq,
- + atomic_read(&bfqq->ref));
- +
- + bfq_put_cooperator(bfqq);
- +
- + bfq_put_queue(bfqq);
- +}
- +
- +static inline void bfq_init_icq(struct io_cq *icq)
- +{
- + struct bfq_io_cq *bic = icq_to_bic(icq);
- +
- + bic->ttime.last_end_request = jiffies;
- + /*
- + * A newly created bic indicates that the process has just
- + * started doing I/O, and is probably mapping into memory its
- + * executable and libraries: it definitely needs weight raising.
- + * There is however the possibility that the process performs,
- + * for a while, I/O close to some other process. EQM intercepts
- + * this behavior and may merge the queue corresponding to the
- + * process with some other queue, BEFORE the weight of the queue
- + * is raised. Merged queues are not weight-raised (they are assumed
- + * to belong to processes that benefit only from high throughput).
- + * If the merge is basically the consequence of an accident, then
- + * the queue will be split soon and will get back its old weight.
- + * It is then important to write down somewhere that this queue
- + * does need weight raising, even if it did not make it to get its
- + * weight raised before being merged. To this purpose, we overload
- + * the field raising_time_left and assign 1 to it, to mark the queue
- + * as needing weight raising.
- + */
- + bic->wr_time_left = 1;
- +}
- +
- +static void bfq_exit_icq(struct io_cq *icq)
- +{
- + struct bfq_io_cq *bic = icq_to_bic(icq);
- + struct bfq_data *bfqd = bic_to_bfqd(bic);
- +
- + if (bic->bfqq[BLK_RW_ASYNC]) {
- + bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_ASYNC]);
- + bic->bfqq[BLK_RW_ASYNC] = NULL;
- + }
- +
- + if (bic->bfqq[BLK_RW_SYNC]) {
- + /*
- + * If the bic is using a shared queue, put the reference
- + * taken on the io_context when the bic started using a
- + * shared bfq_queue.
- + */
- + if (bfq_bfqq_coop(bic->bfqq[BLK_RW_SYNC]))
- + put_io_context(icq->ioc);
- + bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_SYNC]);
- + bic->bfqq[BLK_RW_SYNC] = NULL;
- + }
- +}
- +
- +/*
- + * Update the entity prio values; note that the new values will not
- + * be used until the next (re)activation.
- + */
- +static void bfq_init_prio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic)
- +{
- + struct task_struct *tsk = current;
- + int ioprio_class;
- +
- + if (!bfq_bfqq_prio_changed(bfqq))
- + return;
- +
- + ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio);
- + switch (ioprio_class) {
- + default:
- + dev_err(bfqq->bfqd->queue->backing_dev_info.dev,
- + "bfq: bad prio %x\n", ioprio_class);
- + case IOPRIO_CLASS_NONE:
- + /*
- + * No prio set, inherit CPU scheduling settings.
- + */
- + bfqq->entity.new_ioprio = task_nice_ioprio(tsk);
- + bfqq->entity.new_ioprio_class = task_nice_ioclass(tsk);
- + break;
- + case IOPRIO_CLASS_RT:
- + bfqq->entity.new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio);
- + bfqq->entity.new_ioprio_class = IOPRIO_CLASS_RT;
- + break;
- + case IOPRIO_CLASS_BE:
- + bfqq->entity.new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio);
- + bfqq->entity.new_ioprio_class = IOPRIO_CLASS_BE;
- + break;
- + case IOPRIO_CLASS_IDLE:
- + bfqq->entity.new_ioprio_class = IOPRIO_CLASS_IDLE;
- + bfqq->entity.new_ioprio = 7;
- + bfq_clear_bfqq_idle_window(bfqq);
- + break;
- + }
- +
- + bfqq->entity.ioprio_changed = 1;
- +
- + bfq_clear_bfqq_prio_changed(bfqq);
- +}
- +
- +static void bfq_changed_ioprio(struct bfq_io_cq *bic)
- +{
- + struct bfq_data *bfqd;
- + struct bfq_queue *bfqq, *new_bfqq;
- + struct bfq_group *bfqg;
- + unsigned long uninitialized_var(flags);
- + int ioprio = bic->icq.ioc->ioprio;
- +
- + bfqd = bfq_get_bfqd_locked(&(bic->icq.q->elevator->elevator_data),
- + &flags);
- + /*
- + * This condition may trigger on a newly created bic, be sure to
- + * drop the lock before returning.
- + */
- + if (unlikely(bfqd == NULL) || likely(bic->ioprio == ioprio))
- + goto out;
- +
- + bfqq = bic->bfqq[BLK_RW_ASYNC];
- + if (bfqq != NULL) {
- + bfqg = container_of(bfqq->entity.sched_data, struct bfq_group,
- + sched_data);
- + new_bfqq = bfq_get_queue(bfqd, bfqg, BLK_RW_ASYNC, bic,
- + GFP_ATOMIC);
- + if (new_bfqq != NULL) {
- + bic->bfqq[BLK_RW_ASYNC] = new_bfqq;
- + bfq_log_bfqq(bfqd, bfqq,
- + "changed_ioprio: bfqq %p %d",
- + bfqq, atomic_read(&bfqq->ref));
- + bfq_put_queue(bfqq);
- + }
- + }
- +
- + bfqq = bic->bfqq[BLK_RW_SYNC];
- + if (bfqq != NULL)
- + bfq_mark_bfqq_prio_changed(bfqq);
- +
- + bic->ioprio = ioprio;
- +
- +out:
- + bfq_put_bfqd_unlock(bfqd, &flags);
- +}
- +
- +static void bfq_init_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq,
- + pid_t pid, int is_sync)
- +{
- + RB_CLEAR_NODE(&bfqq->entity.rb_node);
- + INIT_LIST_HEAD(&bfqq->fifo);
- +
- + atomic_set(&bfqq->ref, 0);
- + bfqq->bfqd = bfqd;
- +
- + bfq_mark_bfqq_prio_changed(bfqq);
- +
- + if (is_sync) {
- + if (!bfq_class_idle(bfqq))
- + bfq_mark_bfqq_idle_window(bfqq);
- + bfq_mark_bfqq_sync(bfqq);
- + }
- + bfq_mark_bfqq_IO_bound(bfqq);
- +
- + /* Tentative initial value to trade off between thr and lat */
- + bfqq->max_budget = (2 * bfq_max_budget(bfqd)) / 3;
- + bfqq->pid = pid;
- +
- + bfqq->wr_coeff = 1;
- + bfqq->last_wr_start_finish = 0;
- + /*
- + * Set to the value for which bfqq will not be deemed as
- + * soft rt when it becomes backlogged.
- + */
- + bfqq->soft_rt_next_start = bfq_infinity_from_now(jiffies);
- +}
- +
- +static struct bfq_queue *bfq_find_alloc_queue(struct bfq_data *bfqd,
- + struct bfq_group *bfqg,
- + int is_sync,
- + struct bfq_io_cq *bic,
- + gfp_t gfp_mask)
- +{
- + struct bfq_queue *bfqq, *new_bfqq = NULL;
- +
- +retry:
- + /* bic always exists here */
- + bfqq = bic_to_bfqq(bic, is_sync);
- +
- + /*
- + * Always try a new alloc if we fall back to the OOM bfqq
- + * originally, since it should just be a temporary situation.
- + */
- + if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) {
- + bfqq = NULL;
- + if (new_bfqq != NULL) {
- + bfqq = new_bfqq;
- + new_bfqq = NULL;
- + } else if (gfp_mask & __GFP_WAIT) {
- + spin_unlock_irq(bfqd->queue->queue_lock);
- + new_bfqq = kmem_cache_alloc_node(bfq_pool,
- + gfp_mask | __GFP_ZERO,
- + bfqd->queue->node);
- + spin_lock_irq(bfqd->queue->queue_lock);
- + if (new_bfqq != NULL)
- + goto retry;
- + } else {
- + bfqq = kmem_cache_alloc_node(bfq_pool,
- + gfp_mask | __GFP_ZERO,
- + bfqd->queue->node);
- + }
- +
- + if (bfqq != NULL) {
- + bfq_init_bfqq(bfqd, bfqq, current->pid, is_sync);
- + bfq_log_bfqq(bfqd, bfqq, "allocated");
- + } else {
- + bfqq = &bfqd->oom_bfqq;
- + bfq_log_bfqq(bfqd, bfqq, "using oom bfqq");
- + }
- +
- + bfq_init_prio_data(bfqq, bic);
- + bfq_init_entity(&bfqq->entity, bfqg);
- + }
- +
- + if (new_bfqq != NULL)
- + kmem_cache_free(bfq_pool, new_bfqq);
- +
- + return bfqq;
- +}
- +
- +static struct bfq_queue **bfq_async_queue_prio(struct bfq_data *bfqd,
- + struct bfq_group *bfqg,
- + int ioprio_class, int ioprio)
- +{
- + switch (ioprio_class) {
- + case IOPRIO_CLASS_RT:
- + return &bfqg->async_bfqq[0][ioprio];
- + case IOPRIO_CLASS_NONE:
- + ioprio = IOPRIO_NORM;
- + /* fall through */
- + case IOPRIO_CLASS_BE:
- + return &bfqg->async_bfqq[1][ioprio];
- + case IOPRIO_CLASS_IDLE:
- + return &bfqg->async_idle_bfqq;
- + default:
- + BUG();
- + }
- +}
- +
- +static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd,
- + struct bfq_group *bfqg, int is_sync,
- + struct bfq_io_cq *bic, gfp_t gfp_mask)
- +{
- + const int ioprio = IOPRIO_PRIO_DATA(bic->ioprio);
- + const int ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio);
- + struct bfq_queue **async_bfqq = NULL;
- + struct bfq_queue *bfqq = NULL;
- +
- + if (!is_sync) {
- + async_bfqq = bfq_async_queue_prio(bfqd, bfqg, ioprio_class,
- + ioprio);
- + bfqq = *async_bfqq;
- + }
- +
- + if (bfqq == NULL)
- + bfqq = bfq_find_alloc_queue(bfqd, bfqg, is_sync, bic, gfp_mask);
- +
- + /*
- + * Pin the queue now that it's allocated, scheduler exit will
- + * prune it.
- + */
- + if (!is_sync && *async_bfqq == NULL) {
- + atomic_inc(&bfqq->ref);
- + bfq_log_bfqq(bfqd, bfqq, "get_queue, bfqq not in async: %p, %d",
- + bfqq, atomic_read(&bfqq->ref));
- + *async_bfqq = bfqq;
- + }
- +
- + atomic_inc(&bfqq->ref);
- + bfq_log_bfqq(bfqd, bfqq, "get_queue, at end: %p, %d", bfqq,
- + atomic_read(&bfqq->ref));
- + return bfqq;
- +}
- +
- +static void bfq_update_io_thinktime(struct bfq_data *bfqd,
- + struct bfq_io_cq *bic)
- +{
- + unsigned long elapsed = jiffies - bic->ttime.last_end_request;
- + unsigned long ttime = min(elapsed, 2UL * bfqd->bfq_slice_idle);
- +
- + bic->ttime.ttime_samples = (7*bic->ttime.ttime_samples + 256) / 8;
- + bic->ttime.ttime_total = (7*bic->ttime.ttime_total + 256*ttime) / 8;
- + bic->ttime.ttime_mean = (bic->ttime.ttime_total + 128) /
- + bic->ttime.ttime_samples;
- +}
- +
- +static void bfq_update_io_seektime(struct bfq_data *bfqd,
- + struct bfq_queue *bfqq,
- + struct request *rq)
- +{
- + sector_t sdist;
- + u64 total;
- +
- + if (bfqq->last_request_pos < blk_rq_pos(rq))
- + sdist = blk_rq_pos(rq) - bfqq->last_request_pos;
- + else
- + sdist = bfqq->last_request_pos - blk_rq_pos(rq);
- +
- + /*
- + * Don't allow the seek distance to get too large from the
- + * odd fragment, pagein, etc.
- + */
- + if (bfqq->seek_samples == 0) /* first request, not really a seek */
- + sdist = 0;
- + else if (bfqq->seek_samples <= 60) /* second & third seek */
- + sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*1024);
- + else
- + sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*64);
- +
- + bfqq->seek_samples = (7*bfqq->seek_samples + 256) / 8;
- + bfqq->seek_total = (7*bfqq->seek_total + (u64)256*sdist) / 8;
- + total = bfqq->seek_total + (bfqq->seek_samples/2);
- + do_div(total, bfqq->seek_samples);
- + bfqq->seek_mean = (sector_t)total;
- +
- + bfq_log_bfqq(bfqd, bfqq, "dist=%llu mean=%llu", (u64)sdist,
- + (u64)bfqq->seek_mean);
- +}
- +
- +/*
- + * Disable idle window if the process thinks too long or seeks so much that
- + * it doesn't matter.
- + */
- +static void bfq_update_idle_window(struct bfq_data *bfqd,
- + struct bfq_queue *bfqq,
- + struct bfq_io_cq *bic)
- +{
- + int enable_idle;
- +
- + /* Don't idle for async or idle io prio class. */
- + if (!bfq_bfqq_sync(bfqq) || bfq_class_idle(bfqq))
- + return;
- +
- + /* Idle window just restored, statistics are meaningless. */
- + if (bfq_bfqq_just_split(bfqq))
- + return;
- +
- + enable_idle = bfq_bfqq_idle_window(bfqq);
- +
- + if (atomic_read(&bic->icq.ioc->active_ref) == 0 ||
- + bfqd->bfq_slice_idle == 0 ||
- + (bfqd->hw_tag && BFQQ_SEEKY(bfqq) &&
- + bfqq->wr_coeff == 1))
- + enable_idle = 0;
- + else if (bfq_sample_valid(bic->ttime.ttime_samples)) {
- + if (bic->ttime.ttime_mean > bfqd->bfq_slice_idle &&
- + bfqq->wr_coeff == 1)
- + enable_idle = 0;
- + else
- + enable_idle = 1;
- + }
- + bfq_log_bfqq(bfqd, bfqq, "update_idle_window: enable_idle %d",
- + enable_idle);
- +
- + if (enable_idle)
- + bfq_mark_bfqq_idle_window(bfqq);
- + else
- + bfq_clear_bfqq_idle_window(bfqq);
- +}
- +
- +/*
- + * Called when a new fs request (rq) is added to bfqq. Check if there's
- + * something we should do about it.
- + */
- +static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq,
- + struct request *rq)
- +{
- + struct bfq_io_cq *bic = RQ_BIC(rq);
- +
- + if (rq->cmd_flags & REQ_META)
- + bfqq->meta_pending++;
- +
- + bfq_update_io_thinktime(bfqd, bic);
- + bfq_update_io_seektime(bfqd, bfqq, rq);
- + if (!BFQQ_SEEKY(bfqq) && bfq_bfqq_constantly_seeky(bfqq)) {
- + bfq_clear_bfqq_constantly_seeky(bfqq);
- + if (!blk_queue_nonrot(bfqd->queue)) {
- + BUG_ON(!bfqd->const_seeky_busy_in_flight_queues);
- + bfqd->const_seeky_busy_in_flight_queues--;
- + }
- + }
- + if (bfqq->entity.service > bfq_max_budget(bfqd) / 8 ||
- + !BFQQ_SEEKY(bfqq))
- + bfq_update_idle_window(bfqd, bfqq, bic);
- + bfq_clear_bfqq_just_split(bfqq);
- +
- + bfq_log_bfqq(bfqd, bfqq,
- + "rq_enqueued: idle_window=%d (seeky %d, mean %llu)",
- + bfq_bfqq_idle_window(bfqq), BFQQ_SEEKY(bfqq),
- + (long long unsigned)bfqq->seek_mean);
- +
- + bfqq->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq);
- +
- + if (bfqq == bfqd->in_service_queue && bfq_bfqq_wait_request(bfqq)) {
- + int small_req = bfqq->queued[rq_is_sync(rq)] == 1 &&
- + blk_rq_sectors(rq) < 32;
- + int budget_timeout = bfq_bfqq_budget_timeout(bfqq);
- +
- + /*
- + * There is just this request queued: if the request
- + * is small and the queue is not to be expired, then
- + * just exit.
- + *
- + * In this way, if the disk is being idled to wait for
- + * a new request from the in-service queue, we avoid
- + * unplugging the device and committing the disk to serve
- + * just a small request. On the contrary, we wait for
- + * the block layer to decide when to unplug the device:
- + * hopefully, new requests will be merged to this one
- + * quickly, then the device will be unplugged and
- + * larger requests will be dispatched.
- + */
- + if (small_req && !budget_timeout)
- + return;
- +
- + /*
- + * A large enough request arrived, or the queue is to
- + * be expired: in both cases disk idling is to be
- + * stopped, so clear wait_request flag and reset
- + * timer.
- + */
- + bfq_clear_bfqq_wait_request(bfqq);
- + del_timer(&bfqd->idle_slice_timer);
- +
- + /*
- + * The queue is not empty, because a new request just
- + * arrived. Hence we can safely expire the queue, in
- + * case of budget timeout, without risking that the
- + * timestamps of the queue are not updated correctly.
- + * See [1] for more details.
- + */
- + if (budget_timeout)
- + bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_TIMEOUT);
- +
- + /*
- + * Let the request rip immediately, or let a new queue be
- + * selected if bfqq has just been expired.
- + */
- + __blk_run_queue(bfqd->queue);
- + }
- +}
- +
- +static void bfq_insert_request(struct request_queue *q, struct request *rq)
- +{
- + struct bfq_data *bfqd = q->elevator->elevator_data;
- + struct bfq_queue *bfqq = RQ_BFQQ(rq), *new_bfqq;
- +
- + assert_spin_locked(bfqd->queue->queue_lock);
- +
- + /*
- + * An unplug may trigger a requeue of a request from the device
- + * driver: make sure we are in process context while trying to
- + * merge two bfq_queues.
- + */
- + if (!in_interrupt()) {
- + new_bfqq = bfq_setup_cooperator(bfqd, bfqq, rq, true);
- + if (new_bfqq != NULL) {
- + if (bic_to_bfqq(RQ_BIC(rq), 1) != bfqq)
- + new_bfqq = bic_to_bfqq(RQ_BIC(rq), 1);
- + /*
- + * Release the request's reference to the old bfqq
- + * and make sure one is taken to the shared queue.
- + */
- + new_bfqq->allocated[rq_data_dir(rq)]++;
- + bfqq->allocated[rq_data_dir(rq)]--;
- + atomic_inc(&new_bfqq->ref);
- + bfq_put_queue(bfqq);
- + if (bic_to_bfqq(RQ_BIC(rq), 1) == bfqq)
- + bfq_merge_bfqqs(bfqd, RQ_BIC(rq),
- + bfqq, new_bfqq);
- + rq->elv.priv[1] = new_bfqq;
- + bfqq = new_bfqq;
- + } else
- + bfq_bfqq_increase_failed_cooperations(bfqq);
- + }
- +
- + bfq_init_prio_data(bfqq, RQ_BIC(rq));
- +
- + bfq_add_request(rq);
- +
- + /*
- + * Here a newly-created bfq_queue has already started a weight-raising
- + * period: clear raising_time_left to prevent bfq_bfqq_save_state()
- + * from assigning it a full weight-raising period. See the detailed
- + * comments about this field in bfq_init_icq().
- + */
- + if (bfqq->bic != NULL)
- + bfqq->bic->wr_time_left = 0;
- + rq_set_fifo_time(rq, jiffies + bfqd->bfq_fifo_expire[rq_is_sync(rq)]);
- + list_add_tail(&rq->queuelist, &bfqq->fifo);
- +
- + bfq_rq_enqueued(bfqd, bfqq, rq);
- +}
- +
- +static void bfq_update_hw_tag(struct bfq_data *bfqd)
- +{
- + bfqd->max_rq_in_driver = max(bfqd->max_rq_in_driver,
- + bfqd->rq_in_driver);
- +
- + if (bfqd->hw_tag == 1)
- + return;
- +
- + /*
- + * This sample is valid if the number of outstanding requests
- + * is large enough to allow a queueing behavior. Note that the
- + * sum is not exact, as it's not taking into account deactivated
- + * requests.
- + */
- + if (bfqd->rq_in_driver + bfqd->queued < BFQ_HW_QUEUE_THRESHOLD)
- + return;
- +
- + if (bfqd->hw_tag_samples++ < BFQ_HW_QUEUE_SAMPLES)
- + return;
- +
- + bfqd->hw_tag = bfqd->max_rq_in_driver > BFQ_HW_QUEUE_THRESHOLD;
- + bfqd->max_rq_in_driver = 0;
- + bfqd->hw_tag_samples = 0;
- +}
- +
- +static void bfq_completed_request(struct request_queue *q, struct request *rq)
- +{
- + struct bfq_queue *bfqq = RQ_BFQQ(rq);
- + struct bfq_data *bfqd = bfqq->bfqd;
- + bool sync = bfq_bfqq_sync(bfqq);
- +
- + bfq_log_bfqq(bfqd, bfqq, "completed one req with %u sects left (%d)",
- + blk_rq_sectors(rq), sync);
- +
- + bfq_update_hw_tag(bfqd);
- +
- + BUG_ON(!bfqd->rq_in_driver);
- + BUG_ON(!bfqq->dispatched);
- + bfqd->rq_in_driver--;
- + bfqq->dispatched--;
- +
- + if (!bfqq->dispatched && !bfq_bfqq_busy(bfqq)) {
- + bfq_weights_tree_remove(bfqd, &bfqq->entity,
- + &bfqd->queue_weights_tree);
- + if (!blk_queue_nonrot(bfqd->queue)) {
- + BUG_ON(!bfqd->busy_in_flight_queues);
- + bfqd->busy_in_flight_queues--;
- + if (bfq_bfqq_constantly_seeky(bfqq)) {
- + BUG_ON(!bfqd->
- + const_seeky_busy_in_flight_queues);
- + bfqd->const_seeky_busy_in_flight_queues--;
- + }
- + }
- + }
- +
- + if (sync) {
- + bfqd->sync_flight--;
- + RQ_BIC(rq)->ttime.last_end_request = jiffies;
- + }
- +
- + /*
- + * If we are waiting to discover whether the request pattern of the
- + * task associated with the queue is actually isochronous, and
- + * both requisites for this condition to hold are satisfied, then
- + * compute soft_rt_next_start (see the comments to the function
- + * bfq_bfqq_softrt_next_start()).
- + */
- + if (bfq_bfqq_softrt_update(bfqq) && bfqq->dispatched == 0 &&
- + RB_EMPTY_ROOT(&bfqq->sort_list))
- + bfqq->soft_rt_next_start =
- + bfq_bfqq_softrt_next_start(bfqd, bfqq);
- +
- + /*
- + * If this is the in-service queue, check if it needs to be expired,
- + * or if we want to idle in case it has no pending requests.
- + */
- + if (bfqd->in_service_queue == bfqq) {
- + if (bfq_bfqq_budget_new(bfqq))
- + bfq_set_budget_timeout(bfqd);
- +
- + if (bfq_bfqq_must_idle(bfqq)) {
- + bfq_arm_slice_timer(bfqd);
- + goto out;
- + } else if (bfq_may_expire_for_budg_timeout(bfqq))
- + bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_TIMEOUT);
- + else if (RB_EMPTY_ROOT(&bfqq->sort_list) &&
- + (bfqq->dispatched == 0 ||
- + !bfq_bfqq_must_not_expire(bfqq)))
- + bfq_bfqq_expire(bfqd, bfqq, 0,
- + BFQ_BFQQ_NO_MORE_REQUESTS);
- + }
- +
- + if (!bfqd->rq_in_driver)
- + bfq_schedule_dispatch(bfqd);
- +
- +out:
- + return;
- +}
- +
- +static inline int __bfq_may_queue(struct bfq_queue *bfqq)
- +{
- + if (bfq_bfqq_wait_request(bfqq) && bfq_bfqq_must_alloc(bfqq)) {
- + bfq_clear_bfqq_must_alloc(bfqq);
- + return ELV_MQUEUE_MUST;
- + }
- +
- + return ELV_MQUEUE_MAY;
- +}
- +
- +static int bfq_may_queue(struct request_queue *q, int rw)
- +{
- + struct bfq_data *bfqd = q->elevator->elevator_data;
- + struct task_struct *tsk = current;
- + struct bfq_io_cq *bic;
- + struct bfq_queue *bfqq;
- +
- + /*
- + * Don't force setup of a queue from here, as a call to may_queue
- + * does not necessarily imply that a request actually will be
- + * queued. So just lookup a possibly existing queue, or return
- + * 'may queue' if that fails.
- + */
- + bic = bfq_bic_lookup(bfqd, tsk->io_context);
- + if (bic == NULL)
- + return ELV_MQUEUE_MAY;
- +
- + bfqq = bic_to_bfqq(bic, rw_is_sync(rw));
- + if (bfqq != NULL) {
- + bfq_init_prio_data(bfqq, bic);
- +
- + return __bfq_may_queue(bfqq);
- + }
- +
- + return ELV_MQUEUE_MAY;
- +}
- +
- +/*
- + * Queue lock held here.
- + */
- +static void bfq_put_request(struct request *rq)
- +{
- + struct bfq_queue *bfqq = RQ_BFQQ(rq);
- +
- + if (bfqq != NULL) {
- + const int rw = rq_data_dir(rq);
- +
- + BUG_ON(!bfqq->allocated[rw]);
- + bfqq->allocated[rw]--;
- +
- + rq->elv.priv[0] = NULL;
- + rq->elv.priv[1] = NULL;
- +
- + bfq_log_bfqq(bfqq->bfqd, bfqq, "put_request %p, %d",
- + bfqq, atomic_read(&bfqq->ref));
- + bfq_put_queue(bfqq);
- + }
- +}
- +
- +/*
- + * Returns NULL if a new bfqq should be allocated, or the old bfqq if this
- + * was the last process referring to said bfqq.
- + */
- +static struct bfq_queue *
- +bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq)
- +{
- + bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue");
- +
- + put_io_context(bic->icq.ioc);
- +
- + if (bfqq_process_refs(bfqq) == 1) {
- + bfqq->pid = current->pid;
- + bfq_clear_bfqq_coop(bfqq);
- + bfq_clear_bfqq_split_coop(bfqq);
- + return bfqq;
- + }
- +
- + bic_set_bfqq(bic, NULL, 1);
- +
- + bfq_put_cooperator(bfqq);
- +
- + bfq_put_queue(bfqq);
- + return NULL;
- +}
- +
- +/*
- + * Allocate bfq data structures associated with this request.
- + */
- +static int bfq_set_request(struct request_queue *q, struct request *rq,
- + struct bio *bio, gfp_t gfp_mask)
- +{
- + struct bfq_data *bfqd = q->elevator->elevator_data;
- + struct bfq_io_cq *bic = icq_to_bic(rq->elv.icq);
- + const int rw = rq_data_dir(rq);
- + const int is_sync = rq_is_sync(rq);
- + struct bfq_queue *bfqq;
- + struct bfq_group *bfqg;
- + unsigned long flags;
- + bool split = false;
- +
- + might_sleep_if(gfp_mask & __GFP_WAIT);
- +
- + bfq_changed_ioprio(bic);
- +
- + spin_lock_irqsave(q->queue_lock, flags);
- +
- + if (bic == NULL)
- + goto queue_fail;
- +
- + bfqg = bfq_bic_update_cgroup(bic);
- +
- +new_queue:
- + bfqq = bic_to_bfqq(bic, is_sync);
- + if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) {
- + bfqq = bfq_get_queue(bfqd, bfqg, is_sync, bic, gfp_mask);
- + bic_set_bfqq(bic, bfqq, is_sync);
- + } else {
- + /* If the queue was seeky for too long, break it apart. */
- + if (bfq_bfqq_coop(bfqq) && bfq_bfqq_split_coop(bfqq)) {
- + bfq_log_bfqq(bfqd, bfqq, "breaking apart bfqq");
- + bfqq = bfq_split_bfqq(bic, bfqq);
- + split = true;
- + if (!bfqq)
- + goto new_queue;
- + }
- + }
- +
- + bfqq->allocated[rw]++;
- + atomic_inc(&bfqq->ref);
- + bfq_log_bfqq(bfqd, bfqq, "set_request: bfqq %p, %d", bfqq,
- + atomic_read(&bfqq->ref));
- +
- + rq->elv.priv[0] = bic;
- + rq->elv.priv[1] = bfqq;
- +
- + /*
- + * If a bfq_queue has only one process reference, it is owned
- + * by only one bfq_io_cq: we can set the bic field of the
- + * bfq_queue to the address of that structure. Also, if the
- + * queue has just been split, mark a flag so that the
- + * information is available to the other scheduler hooks.
- + */
- + if (bfqq_process_refs(bfqq) == 1) {
- + bfqq->bic = bic;
- + if (split) {
- + bfq_mark_bfqq_just_split(bfqq);
- + /*
- + * If the queue has just been split from a shared
- + * queue, restore the idle window and the possible
- + * weight raising period.
- + */
- + bfq_bfqq_resume_state(bfqq, bic);
- + }
- + }
- +
- + spin_unlock_irqrestore(q->queue_lock, flags);
- +
- + return 0;
- +
- +queue_fail:
- + bfq_schedule_dispatch(bfqd);
- + spin_unlock_irqrestore(q->queue_lock, flags);
- +
- + return 1;
- +}
- +
- +static void bfq_kick_queue(struct work_struct *work)
- +{
- + struct bfq_data *bfqd =
- + container_of(work, struct bfq_data, unplug_work);
- + struct request_queue *q = bfqd->queue;
- +
- + spin_lock_irq(q->queue_lock);
- + __blk_run_queue(q);
- + spin_unlock_irq(q->queue_lock);
- +}
- +
- +/*
- + * Handler of the expiration of the timer running if the in-service queue
- + * is idling inside its time slice.
- + */
- +static void bfq_idle_slice_timer(unsigned long data)
- +{
- + struct bfq_data *bfqd = (struct bfq_data *)data;
- + struct bfq_queue *bfqq;
- + unsigned long flags;
- + enum bfqq_expiration reason;
- +
- + spin_lock_irqsave(bfqd->queue->queue_lock, flags);
- +
- + bfqq = bfqd->in_service_queue;
- + /*
- + * Theoretical race here: the in-service queue can be NULL or
- + * different from the queue that was idling if the timer handler
- + * spins on the queue_lock and a new request arrives for the
- + * current queue and there is a full dispatch cycle that changes
- + * the in-service queue. This can hardly happen, but in the worst
- + * case we just expire a queue too early.
- + */
- + if (bfqq != NULL) {
- + bfq_log_bfqq(bfqd, bfqq, "slice_timer expired");
- + if (bfq_bfqq_budget_timeout(bfqq))
- + /*
- + * Also here the queue can be safely expired
- + * for budget timeout without wasting
- + * guarantees
- + */
- + reason = BFQ_BFQQ_BUDGET_TIMEOUT;
- + else if (bfqq->queued[0] == 0 && bfqq->queued[1] == 0)
- + /*
- + * The queue may not be empty upon timer expiration,
- + * because we may not disable the timer when the
- + * first request of the in-service queue arrives
- + * during disk idling.
- + */
- + reason = BFQ_BFQQ_TOO_IDLE;
- + else
- + goto schedule_dispatch;
- +
- + bfq_bfqq_expire(bfqd, bfqq, 1, reason);
- + }
- +
- +schedule_dispatch:
- + bfq_schedule_dispatch(bfqd);
- +
- + spin_unlock_irqrestore(bfqd->queue->queue_lock, flags);
- +}
- +
- +static void bfq_shutdown_timer_wq(struct bfq_data *bfqd)
- +{
- + del_timer_sync(&bfqd->idle_slice_timer);
- + cancel_work_sync(&bfqd->unplug_work);
- +}
- +
- +static inline void __bfq_put_async_bfqq(struct bfq_data *bfqd,
- + struct bfq_queue **bfqq_ptr)
- +{
- + struct bfq_group *root_group = bfqd->root_group;
- + struct bfq_queue *bfqq = *bfqq_ptr;
- +
- + bfq_log(bfqd, "put_async_bfqq: %p", bfqq);
- + if (bfqq != NULL) {
- + bfq_bfqq_move(bfqd, bfqq, &bfqq->entity, root_group);
- + bfq_log_bfqq(bfqd, bfqq, "put_async_bfqq: putting %p, %d",
- + bfqq, atomic_read(&bfqq->ref));
- + bfq_put_queue(bfqq);
- + *bfqq_ptr = NULL;
- + }
- +}
- +
- +/*
- + * Release all the bfqg references to its async queues. If we are
- + * deallocating the group these queues may still contain requests, so
- + * we reparent them to the root cgroup (i.e., the only one that will
- + * exist for sure until all the requests on a device are gone).
- + */
- +static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg)
- +{
- + int i, j;
- +
- + for (i = 0; i < 2; i++)
- + for (j = 0; j < IOPRIO_BE_NR; j++)
- + __bfq_put_async_bfqq(bfqd, &bfqg->async_bfqq[i][j]);
- +
- + __bfq_put_async_bfqq(bfqd, &bfqg->async_idle_bfqq);
- +}
- +
- +static void bfq_exit_queue(struct elevator_queue *e)
- +{
- + struct bfq_data *bfqd = e->elevator_data;
- + struct request_queue *q = bfqd->queue;
- + struct bfq_queue *bfqq, *n;
- +
- + bfq_shutdown_timer_wq(bfqd);
- +
- + spin_lock_irq(q->queue_lock);
- +
- + BUG_ON(bfqd->in_service_queue != NULL);
- + list_for_each_entry_safe(bfqq, n, &bfqd->idle_list, bfqq_list)
- + bfq_deactivate_bfqq(bfqd, bfqq, 0);
- +
- + bfq_disconnect_groups(bfqd);
- + spin_unlock_irq(q->queue_lock);
- +
- + bfq_shutdown_timer_wq(bfqd);
- +
- + synchronize_rcu();
- +
- + BUG_ON(timer_pending(&bfqd->idle_slice_timer));
- +
- + bfq_free_root_group(bfqd);
- + kfree(bfqd);
- +}
- +
- +static int bfq_init_queue(struct request_queue *q, struct elevator_type *e)
- +{
- + struct bfq_group *bfqg;
- + struct bfq_data *bfqd;
- + struct elevator_queue *eq;
- +
- + eq = elevator_alloc(q, e);
- + if (eq == NULL)
- + return -ENOMEM;
- +
- + bfqd = kzalloc_node(sizeof(*bfqd), GFP_KERNEL, q->node);
- + if (bfqd == NULL) {
- + kobject_put(&eq->kobj);
- + return -ENOMEM;
- + }
- + eq->elevator_data = bfqd;
- +
- + /*
- + * Our fallback bfqq if bfq_find_alloc_queue() runs into OOM issues.
- + * Grab a permanent reference to it, so that the normal code flow
- + * will not attempt to free it.
- + */
- + bfq_init_bfqq(bfqd, &bfqd->oom_bfqq, 1, 0);
- + atomic_inc(&bfqd->oom_bfqq.ref);
- +
- + bfqd->queue = q;
- +
- + spin_lock_irq(q->queue_lock);
- + q->elevator = eq;
- + spin_unlock_irq(q->queue_lock);
- +
- + bfqg = bfq_alloc_root_group(bfqd, q->node);
- + if (bfqg == NULL) {
- + kfree(bfqd);
- + kobject_put(&eq->kobj);
- + return -ENOMEM;
- + }
- +
- + bfqd->root_group = bfqg;
- +#ifdef CONFIG_CGROUP_BFQIO
- + bfqd->active_numerous_groups = 0;
- +#endif
- +
- + init_timer(&bfqd->idle_slice_timer);
- + bfqd->idle_slice_timer.function = bfq_idle_slice_timer;
- + bfqd->idle_slice_timer.data = (unsigned long)bfqd;
- +
- + bfqd->rq_pos_tree = RB_ROOT;
- + bfqd->queue_weights_tree = RB_ROOT;
- + bfqd->group_weights_tree = RB_ROOT;
- +
- + INIT_WORK(&bfqd->unplug_work, bfq_kick_queue);
- +
- + INIT_LIST_HEAD(&bfqd->active_list);
- + INIT_LIST_HEAD(&bfqd->idle_list);
- +
- + bfqd->hw_tag = -1;
- +
- + bfqd->bfq_max_budget = bfq_default_max_budget;
- +
- + bfqd->bfq_quantum = bfq_quantum;
- + bfqd->bfq_fifo_expire[0] = bfq_fifo_expire[0];
- + bfqd->bfq_fifo_expire[1] = bfq_fifo_expire[1];
- + bfqd->bfq_back_max = bfq_back_max;
- + bfqd->bfq_back_penalty = bfq_back_penalty;
- + bfqd->bfq_slice_idle = bfq_slice_idle;
- + bfqd->bfq_class_idle_last_service = 0;
- + bfqd->bfq_max_budget_async_rq = bfq_max_budget_async_rq;
- + bfqd->bfq_timeout[BLK_RW_ASYNC] = bfq_timeout_async;
- + bfqd->bfq_timeout[BLK_RW_SYNC] = bfq_timeout_sync;
- +
- + bfqd->bfq_coop_thresh = 2;
- + bfqd->bfq_failed_cooperations = 7000;
- + bfqd->bfq_requests_within_timer = 120;
- +
- + bfqd->low_latency = true;
- +
- + bfqd->bfq_wr_coeff = 20;
- + bfqd->bfq_wr_rt_max_time = msecs_to_jiffies(300);
- + bfqd->bfq_wr_max_time = 0;
- + bfqd->bfq_wr_min_idle_time = msecs_to_jiffies(2000);
- + bfqd->bfq_wr_min_inter_arr_async = msecs_to_jiffies(500);
- + bfqd->bfq_wr_max_softrt_rate = 7000; /*
- + * Approximate rate required
- + * to playback or record a
- + * high-definition compressed
- + * video.
- + */
- + bfqd->wr_busy_queues = 0;
- + bfqd->busy_in_flight_queues = 0;
- + bfqd->const_seeky_busy_in_flight_queues = 0;
- +
- + /*
- + * Begin by assuming, optimistically, that the device peak rate is
- + * equal to the highest reference rate.
- + */
- + bfqd->RT_prod = R_fast[blk_queue_nonrot(bfqd->queue)] *
- + T_fast[blk_queue_nonrot(bfqd->queue)];
- + bfqd->peak_rate = R_fast[blk_queue_nonrot(bfqd->queue)];
- + bfqd->device_speed = BFQ_BFQD_FAST;
- +
- + return 0;
- +}
- +
- +static void bfq_slab_kill(void)
- +{
- + if (bfq_pool != NULL)
- + kmem_cache_destroy(bfq_pool);
- +}
- +
- +static int __init bfq_slab_setup(void)
- +{
- + bfq_pool = KMEM_CACHE(bfq_queue, 0);
- + if (bfq_pool == NULL)
- + return -ENOMEM;
- + return 0;
- +}
- +
- +static ssize_t bfq_var_show(unsigned int var, char *page)
- +{
- + return sprintf(page, "%d\n", var);
- +}
- +
- +static ssize_t bfq_var_store(unsigned long *var, const char *page,
- + size_t count)
- +{
- + unsigned long new_val;
- + int ret = kstrtoul(page, 10, &new_val);
- +
- + if (ret == 0)
- + *var = new_val;
- +
- + return count;
- +}
- +
- +static ssize_t bfq_wr_max_time_show(struct elevator_queue *e, char *page)
- +{
- + struct bfq_data *bfqd = e->elevator_data;
- + return sprintf(page, "%d\n", bfqd->bfq_wr_max_time > 0 ?
- + jiffies_to_msecs(bfqd->bfq_wr_max_time) :
- + jiffies_to_msecs(bfq_wr_duration(bfqd)));
- +}
- +
- +static ssize_t bfq_weights_show(struct elevator_queue *e, char *page)
- +{
- + struct bfq_queue *bfqq;
- + struct bfq_data *bfqd = e->elevator_data;
- + ssize_t num_char = 0;
- +
- + num_char += sprintf(page + num_char, "Tot reqs queued %d\n\n",
- + bfqd->queued);
- +
- + spin_lock_irq(bfqd->queue->queue_lock);
- +
- + num_char += sprintf(page + num_char, "Active:\n");
- + list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list) {
- + num_char += sprintf(page + num_char,
- + "pid%d: weight %hu, nr_queued %d %d, dur %d/%u\n",
- + bfqq->pid,
- + bfqq->entity.weight,
- + bfqq->queued[0],
- + bfqq->queued[1],
- + jiffies_to_msecs(jiffies - bfqq->last_wr_start_finish),
- + jiffies_to_msecs(bfqq->wr_cur_max_time));
- + }
- +
- + num_char += sprintf(page + num_char, "Idle:\n");
- + list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list) {
- + num_char += sprintf(page + num_char,
- + "pid%d: weight %hu, dur %d/%u\n",
- + bfqq->pid,
- + bfqq->entity.weight,
- + jiffies_to_msecs(jiffies -
- + bfqq->last_wr_start_finish),
- + jiffies_to_msecs(bfqq->wr_cur_max_time));
- + }
- +
- + spin_unlock_irq(bfqd->queue->queue_lock);
- +
- + return num_char;
- +}
- +
- +#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \
- +static ssize_t __FUNC(struct elevator_queue *e, char *page) \
- +{ \
- + struct bfq_data *bfqd = e->elevator_data; \
- + unsigned int __data = __VAR; \
- + if (__CONV) \
- + __data = jiffies_to_msecs(__data); \
- + return bfq_var_show(__data, (page)); \
- +}
- +SHOW_FUNCTION(bfq_quantum_show, bfqd->bfq_quantum, 0);
- +SHOW_FUNCTION(bfq_fifo_expire_sync_show, bfqd->bfq_fifo_expire[1], 1);
- +SHOW_FUNCTION(bfq_fifo_expire_async_show, bfqd->bfq_fifo_expire[0], 1);
- +SHOW_FUNCTION(bfq_back_seek_max_show, bfqd->bfq_back_max, 0);
- +SHOW_FUNCTION(bfq_back_seek_penalty_show, bfqd->bfq_back_penalty, 0);
- +SHOW_FUNCTION(bfq_slice_idle_show, bfqd->bfq_slice_idle, 1);
- +SHOW_FUNCTION(bfq_max_budget_show, bfqd->bfq_user_max_budget, 0);
- +SHOW_FUNCTION(bfq_max_budget_async_rq_show,
- + bfqd->bfq_max_budget_async_rq, 0);
- +SHOW_FUNCTION(bfq_timeout_sync_show, bfqd->bfq_timeout[BLK_RW_SYNC], 1);
- +SHOW_FUNCTION(bfq_timeout_async_show, bfqd->bfq_timeout[BLK_RW_ASYNC], 1);
- +SHOW_FUNCTION(bfq_low_latency_show, bfqd->low_latency, 0);
- +SHOW_FUNCTION(bfq_wr_coeff_show, bfqd->bfq_wr_coeff, 0);
- +SHOW_FUNCTION(bfq_wr_rt_max_time_show, bfqd->bfq_wr_rt_max_time, 1);
- +SHOW_FUNCTION(bfq_wr_min_idle_time_show, bfqd->bfq_wr_min_idle_time, 1);
- +SHOW_FUNCTION(bfq_wr_min_inter_arr_async_show, bfqd->bfq_wr_min_inter_arr_async,
- + 1);
- +SHOW_FUNCTION(bfq_wr_max_softrt_rate_show, bfqd->bfq_wr_max_softrt_rate, 0);
- +#undef SHOW_FUNCTION
- +
- +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \
- +static ssize_t \
- +__FUNC(struct elevator_queue *e, const char *page, size_t count) \
- +{ \
- + struct bfq_data *bfqd = e->elevator_data; \
- + unsigned long uninitialized_var(__data); \
- + int ret = bfq_var_store(&__data, (page), count); \
- + if (__data < (MIN)) \
- + __data = (MIN); \
- + else if (__data > (MAX)) \
- + __data = (MAX); \
- + if (__CONV) \
- + *(__PTR) = msecs_to_jiffies(__data); \
- + else \
- + *(__PTR) = __data; \
- + return ret; \
- +}
- +STORE_FUNCTION(bfq_quantum_store, &bfqd->bfq_quantum, 1, INT_MAX, 0);
- +STORE_FUNCTION(bfq_fifo_expire_sync_store, &bfqd->bfq_fifo_expire[1], 1,
- + INT_MAX, 1);
- +STORE_FUNCTION(bfq_fifo_expire_async_store, &bfqd->bfq_fifo_expire[0], 1,
- + INT_MAX, 1);
- +STORE_FUNCTION(bfq_back_seek_max_store, &bfqd->bfq_back_max, 0, INT_MAX, 0);
- +STORE_FUNCTION(bfq_back_seek_penalty_store, &bfqd->bfq_back_penalty, 1,
- + INT_MAX, 0);
- +STORE_FUNCTION(bfq_slice_idle_store, &bfqd->bfq_slice_idle, 0, INT_MAX, 1);
- +STORE_FUNCTION(bfq_max_budget_async_rq_store, &bfqd->bfq_max_budget_async_rq,
- + 1, INT_MAX, 0);
- +STORE_FUNCTION(bfq_timeout_async_store, &bfqd->bfq_timeout[BLK_RW_ASYNC], 0,
- + INT_MAX, 1);
- +STORE_FUNCTION(bfq_wr_coeff_store, &bfqd->bfq_wr_coeff, 1, INT_MAX, 0);
- +STORE_FUNCTION(bfq_wr_max_time_store, &bfqd->bfq_wr_max_time, 0, INT_MAX, 1);
- +STORE_FUNCTION(bfq_wr_rt_max_time_store, &bfqd->bfq_wr_rt_max_time, 0, INT_MAX,
- + 1);
- +STORE_FUNCTION(bfq_wr_min_idle_time_store, &bfqd->bfq_wr_min_idle_time, 0,
- + INT_MAX, 1);
- +STORE_FUNCTION(bfq_wr_min_inter_arr_async_store,
- + &bfqd->bfq_wr_min_inter_arr_async, 0, INT_MAX, 1);
- +STORE_FUNCTION(bfq_wr_max_softrt_rate_store, &bfqd->bfq_wr_max_softrt_rate, 0,
- + INT_MAX, 0);
- +#undef STORE_FUNCTION
- +
- +/* do nothing for the moment */
- +static ssize_t bfq_weights_store(struct elevator_queue *e,
- + const char *page, size_t count)
- +{
- + return count;
- +}
- +
- +static inline unsigned long bfq_estimated_max_budget(struct bfq_data *bfqd)
- +{
- + u64 timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]);
- +
- + if (bfqd->peak_rate_samples >= BFQ_PEAK_RATE_SAMPLES)
- + return bfq_calc_max_budget(bfqd->peak_rate, timeout);
- + else
- + return bfq_default_max_budget;
- +}
- +
- +static ssize_t bfq_max_budget_store(struct elevator_queue *e,
- + const char *page, size_t count)
- +{
- + struct bfq_data *bfqd = e->elevator_data;
- + unsigned long uninitialized_var(__data);
- + int ret = bfq_var_store(&__data, (page), count);
- +
- + if (__data == 0)
- + bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd);
- + else {
- + if (__data > INT_MAX)
- + __data = INT_MAX;
- + bfqd->bfq_max_budget = __data;
- + }
- +
- + bfqd->bfq_user_max_budget = __data;
- +
- + return ret;
- +}
- +
- +static ssize_t bfq_timeout_sync_store(struct elevator_queue *e,
- + const char *page, size_t count)
- +{
- + struct bfq_data *bfqd = e->elevator_data;
- + unsigned long uninitialized_var(__data);
- + int ret = bfq_var_store(&__data, (page), count);
- +
- + if (__data < 1)
- + __data = 1;
- + else if (__data > INT_MAX)
- + __data = INT_MAX;
- +
- + bfqd->bfq_timeout[BLK_RW_SYNC] = msecs_to_jiffies(__data);
- + if (bfqd->bfq_user_max_budget == 0)
- + bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd);
- +
- + return ret;
- +}
- +
- +static ssize_t bfq_low_latency_store(struct elevator_queue *e,
- + const char *page, size_t count)
- +{
- + struct bfq_data *bfqd = e->elevator_data;
- + unsigned long uninitialized_var(__data);
- + int ret = bfq_var_store(&__data, (page), count);
- +
- + if (__data > 1)
- + __data = 1;
- + if (__data == 0 && bfqd->low_latency != 0)
- + bfq_end_wr(bfqd);
- + bfqd->low_latency = __data;
- +
- + return ret;
- +}
- +
- +#define BFQ_ATTR(name) \
- + __ATTR(name, S_IRUGO|S_IWUSR, bfq_##name##_show, bfq_##name##_store)
- +
- +static struct elv_fs_entry bfq_attrs[] = {
- + BFQ_ATTR(quantum),
- + BFQ_ATTR(fifo_expire_sync),
- + BFQ_ATTR(fifo_expire_async),
- + BFQ_ATTR(back_seek_max),
- + BFQ_ATTR(back_seek_penalty),
- + BFQ_ATTR(slice_idle),
- + BFQ_ATTR(max_budget),
- + BFQ_ATTR(max_budget_async_rq),
- + BFQ_ATTR(timeout_sync),
- + BFQ_ATTR(timeout_async),
- + BFQ_ATTR(low_latency),
- + BFQ_ATTR(wr_coeff),
- + BFQ_ATTR(wr_max_time),
- + BFQ_ATTR(wr_rt_max_time),
- + BFQ_ATTR(wr_min_idle_time),
- + BFQ_ATTR(wr_min_inter_arr_async),
- + BFQ_ATTR(wr_max_softrt_rate),
- + BFQ_ATTR(weights),
- + __ATTR_NULL
- +};
- +
- +static struct elevator_type iosched_bfq = {
- + .ops = {
- + .elevator_merge_fn = bfq_merge,
- + .elevator_merged_fn = bfq_merged_request,
- + .elevator_merge_req_fn = bfq_merged_requests,
- + .elevator_allow_merge_fn = bfq_allow_merge,
- + .elevator_dispatch_fn = bfq_dispatch_requests,
- + .elevator_add_req_fn = bfq_insert_request,
- + .elevator_activate_req_fn = bfq_activate_request,
- + .elevator_deactivate_req_fn = bfq_deactivate_request,
- + .elevator_completed_req_fn = bfq_completed_request,
- + .elevator_former_req_fn = elv_rb_former_request,
- + .elevator_latter_req_fn = elv_rb_latter_request,
- + .elevator_init_icq_fn = bfq_init_icq,
- + .elevator_exit_icq_fn = bfq_exit_icq,
- + .elevator_set_req_fn = bfq_set_request,
- + .elevator_put_req_fn = bfq_put_request,
- + .elevator_may_queue_fn = bfq_may_queue,
- + .elevator_init_fn = bfq_init_queue,
- + .elevator_exit_fn = bfq_exit_queue,
- + },
- + .icq_size = sizeof(struct bfq_io_cq),
- + .icq_align = __alignof__(struct bfq_io_cq),
- + .elevator_attrs = bfq_attrs,
- + .elevator_name = "bfq",
- + .elevator_owner = THIS_MODULE,
- +};
- +
- +static int __init bfq_init(void)
- +{
- + /*
- + * Can be 0 on HZ < 1000 setups.
- + */
- + if (bfq_slice_idle == 0)
- + bfq_slice_idle = 1;
- +
- + if (bfq_timeout_async == 0)
- + bfq_timeout_async = 1;
- +
- + if (bfq_slab_setup())
- + return -ENOMEM;
- +
- + /*
- + * Times to load large popular applications for the typical systems
- + * installed on the reference devices (see the comments before the
- + * definitions of the two arrays).
- + */
- + T_slow[0] = msecs_to_jiffies(2600);
- + T_slow[1] = msecs_to_jiffies(1000);
- + T_fast[0] = msecs_to_jiffies(5500);
- + T_fast[1] = msecs_to_jiffies(2000);
- +
- + /*
- + * Thresholds that determine the switch between speed classes (see
- + * the comments before the definition of the array).
- + */
- + device_speed_thresh[0] = (R_fast[0] + R_slow[0]) / 2;
- + device_speed_thresh[1] = (R_fast[1] + R_slow[1]) / 2;
- +
- + elv_register(&iosched_bfq);
- + pr_info("BFQ I/O-scheduler version: v7r5");
- +
- + return 0;
- +}
- +
- +static void __exit bfq_exit(void)
- +{
- + elv_unregister(&iosched_bfq);
- + bfq_slab_kill();
- +}
- +
- +module_init(bfq_init);
- +module_exit(bfq_exit);
- +
- +MODULE_AUTHOR("Fabio Checconi, Paolo Valente");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/block/bfq-sched.c linux-3.14.35/block/bfq-sched.c
- --- linux-3.14.35.orig/block/bfq-sched.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/block/bfq-sched.c 2015-03-08 14:27:37.461684502 -0500
- @@ -0,0 +1,1179 @@
- +/*
- + * BFQ: Hierarchical B-WF2Q+ scheduler.
- + *
- + * Based on ideas and code from CFQ:
- + * Copyright (C) 2003 Jens Axboe <axboe@kernel.dk>
- + *
- + * Copyright (C) 2008 Fabio Checconi <fabio@gandalf.sssup.it>
- + * Paolo Valente <paolo.valente@unimore.it>
- + *
- + * Copyright (C) 2010 Paolo Valente <paolo.valente@unimore.it>
- + */
- +
- +#ifdef CONFIG_CGROUP_BFQIO
- +#define for_each_entity(entity) \
- + for (; entity != NULL; entity = entity->parent)
- +
- +#define for_each_entity_safe(entity, parent) \
- + for (; entity && ({ parent = entity->parent; 1; }); entity = parent)
- +
- +static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd,
- + int extract,
- + struct bfq_data *bfqd);
- +
- +static inline void bfq_update_budget(struct bfq_entity *next_in_service)
- +{
- + struct bfq_entity *bfqg_entity;
- + struct bfq_group *bfqg;
- + struct bfq_sched_data *group_sd;
- +
- + BUG_ON(next_in_service == NULL);
- +
- + group_sd = next_in_service->sched_data;
- +
- + bfqg = container_of(group_sd, struct bfq_group, sched_data);
- + /*
- + * bfq_group's my_entity field is not NULL only if the group
- + * is not the root group. We must not touch the root entity
- + * as it must never become an in-service entity.
- + */
- + bfqg_entity = bfqg->my_entity;
- + if (bfqg_entity != NULL)
- + bfqg_entity->budget = next_in_service->budget;
- +}
- +
- +static int bfq_update_next_in_service(struct bfq_sched_data *sd)
- +{
- + struct bfq_entity *next_in_service;
- +
- + if (sd->in_service_entity != NULL)
- + /* will update/requeue at the end of service */
- + return 0;
- +
- + /*
- + * NOTE: this can be improved in many ways, such as returning
- + * 1 (and thus propagating upwards the update) only when the
- + * budget changes, or caching the bfqq that will be scheduled
- + * next from this subtree. By now we worry more about
- + * correctness than about performance...
- + */
- + next_in_service = bfq_lookup_next_entity(sd, 0, NULL);
- + sd->next_in_service = next_in_service;
- +
- + if (next_in_service != NULL)
- + bfq_update_budget(next_in_service);
- +
- + return 1;
- +}
- +
- +static inline void bfq_check_next_in_service(struct bfq_sched_data *sd,
- + struct bfq_entity *entity)
- +{
- + BUG_ON(sd->next_in_service != entity);
- +}
- +#else
- +#define for_each_entity(entity) \
- + for (; entity != NULL; entity = NULL)
- +
- +#define for_each_entity_safe(entity, parent) \
- + for (parent = NULL; entity != NULL; entity = parent)
- +
- +static inline int bfq_update_next_in_service(struct bfq_sched_data *sd)
- +{
- + return 0;
- +}
- +
- +static inline void bfq_check_next_in_service(struct bfq_sched_data *sd,
- + struct bfq_entity *entity)
- +{
- +}
- +
- +static inline void bfq_update_budget(struct bfq_entity *next_in_service)
- +{
- +}
- +#endif
- +
- +/*
- + * Shift for timestamp calculations. This actually limits the maximum
- + * service allowed in one timestamp delta (small shift values increase it),
- + * the maximum total weight that can be used for the queues in the system
- + * (big shift values increase it), and the period of virtual time
- + * wraparounds.
- + */
- +#define WFQ_SERVICE_SHIFT 22
- +
- +/**
- + * bfq_gt - compare two timestamps.
- + * @a: first ts.
- + * @b: second ts.
- + *
- + * Return @a > @b, dealing with wrapping correctly.
- + */
- +static inline int bfq_gt(u64 a, u64 b)
- +{
- + return (s64)(a - b) > 0;
- +}
- +
- +static inline struct bfq_queue *bfq_entity_to_bfqq(struct bfq_entity *entity)
- +{
- + struct bfq_queue *bfqq = NULL;
- +
- + BUG_ON(entity == NULL);
- +
- + if (entity->my_sched_data == NULL)
- + bfqq = container_of(entity, struct bfq_queue, entity);
- +
- + return bfqq;
- +}
- +
- +
- +/**
- + * bfq_delta - map service into the virtual time domain.
- + * @service: amount of service.
- + * @weight: scale factor (weight of an entity or weight sum).
- + */
- +static inline u64 bfq_delta(unsigned long service,
- + unsigned long weight)
- +{
- + u64 d = (u64)service << WFQ_SERVICE_SHIFT;
- +
- + do_div(d, weight);
- + return d;
- +}
- +
- +/**
- + * bfq_calc_finish - assign the finish time to an entity.
- + * @entity: the entity to act upon.
- + * @service: the service to be charged to the entity.
- + */
- +static inline void bfq_calc_finish(struct bfq_entity *entity,
- + unsigned long service)
- +{
- + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
- +
- + BUG_ON(entity->weight == 0);
- +
- + entity->finish = entity->start +
- + bfq_delta(service, entity->weight);
- +
- + if (bfqq != NULL) {
- + bfq_log_bfqq(bfqq->bfqd, bfqq,
- + "calc_finish: serv %lu, w %d",
- + service, entity->weight);
- + bfq_log_bfqq(bfqq->bfqd, bfqq,
- + "calc_finish: start %llu, finish %llu, delta %llu",
- + entity->start, entity->finish,
- + bfq_delta(service, entity->weight));
- + }
- +}
- +
- +/**
- + * bfq_entity_of - get an entity from a node.
- + * @node: the node field of the entity.
- + *
- + * Convert a node pointer to the relative entity. This is used only
- + * to simplify the logic of some functions and not as the generic
- + * conversion mechanism because, e.g., in the tree walking functions,
- + * the check for a %NULL value would be redundant.
- + */
- +static inline struct bfq_entity *bfq_entity_of(struct rb_node *node)
- +{
- + struct bfq_entity *entity = NULL;
- +
- + if (node != NULL)
- + entity = rb_entry(node, struct bfq_entity, rb_node);
- +
- + return entity;
- +}
- +
- +/**
- + * bfq_extract - remove an entity from a tree.
- + * @root: the tree root.
- + * @entity: the entity to remove.
- + */
- +static inline void bfq_extract(struct rb_root *root,
- + struct bfq_entity *entity)
- +{
- + BUG_ON(entity->tree != root);
- +
- + entity->tree = NULL;
- + rb_erase(&entity->rb_node, root);
- +}
- +
- +/**
- + * bfq_idle_extract - extract an entity from the idle tree.
- + * @st: the service tree of the owning @entity.
- + * @entity: the entity being removed.
- + */
- +static void bfq_idle_extract(struct bfq_service_tree *st,
- + struct bfq_entity *entity)
- +{
- + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
- + struct rb_node *next;
- +
- + BUG_ON(entity->tree != &st->idle);
- +
- + if (entity == st->first_idle) {
- + next = rb_next(&entity->rb_node);
- + st->first_idle = bfq_entity_of(next);
- + }
- +
- + if (entity == st->last_idle) {
- + next = rb_prev(&entity->rb_node);
- + st->last_idle = bfq_entity_of(next);
- + }
- +
- + bfq_extract(&st->idle, entity);
- +
- + if (bfqq != NULL)
- + list_del(&bfqq->bfqq_list);
- +}
- +
- +/**
- + * bfq_insert - generic tree insertion.
- + * @root: tree root.
- + * @entity: entity to insert.
- + *
- + * This is used for the idle and the active tree, since they are both
- + * ordered by finish time.
- + */
- +static void bfq_insert(struct rb_root *root, struct bfq_entity *entity)
- +{
- + struct bfq_entity *entry;
- + struct rb_node **node = &root->rb_node;
- + struct rb_node *parent = NULL;
- +
- + BUG_ON(entity->tree != NULL);
- +
- + while (*node != NULL) {
- + parent = *node;
- + entry = rb_entry(parent, struct bfq_entity, rb_node);
- +
- + if (bfq_gt(entry->finish, entity->finish))
- + node = &parent->rb_left;
- + else
- + node = &parent->rb_right;
- + }
- +
- + rb_link_node(&entity->rb_node, parent, node);
- + rb_insert_color(&entity->rb_node, root);
- +
- + entity->tree = root;
- +}
- +
- +/**
- + * bfq_update_min - update the min_start field of a entity.
- + * @entity: the entity to update.
- + * @node: one of its children.
- + *
- + * This function is called when @entity may store an invalid value for
- + * min_start due to updates to the active tree. The function assumes
- + * that the subtree rooted at @node (which may be its left or its right
- + * child) has a valid min_start value.
- + */
- +static inline void bfq_update_min(struct bfq_entity *entity,
- + struct rb_node *node)
- +{
- + struct bfq_entity *child;
- +
- + if (node != NULL) {
- + child = rb_entry(node, struct bfq_entity, rb_node);
- + if (bfq_gt(entity->min_start, child->min_start))
- + entity->min_start = child->min_start;
- + }
- +}
- +
- +/**
- + * bfq_update_active_node - recalculate min_start.
- + * @node: the node to update.
- + *
- + * @node may have changed position or one of its children may have moved,
- + * this function updates its min_start value. The left and right subtrees
- + * are assumed to hold a correct min_start value.
- + */
- +static inline void bfq_update_active_node(struct rb_node *node)
- +{
- + struct bfq_entity *entity = rb_entry(node, struct bfq_entity, rb_node);
- +
- + entity->min_start = entity->start;
- + bfq_update_min(entity, node->rb_right);
- + bfq_update_min(entity, node->rb_left);
- +}
- +
- +/**
- + * bfq_update_active_tree - update min_start for the whole active tree.
- + * @node: the starting node.
- + *
- + * @node must be the deepest modified node after an update. This function
- + * updates its min_start using the values held by its children, assuming
- + * that they did not change, and then updates all the nodes that may have
- + * changed in the path to the root. The only nodes that may have changed
- + * are the ones in the path or their siblings.
- + */
- +static void bfq_update_active_tree(struct rb_node *node)
- +{
- + struct rb_node *parent;
- +
- +up:
- + bfq_update_active_node(node);
- +
- + parent = rb_parent(node);
- + if (parent == NULL)
- + return;
- +
- + if (node == parent->rb_left && parent->rb_right != NULL)
- + bfq_update_active_node(parent->rb_right);
- + else if (parent->rb_left != NULL)
- + bfq_update_active_node(parent->rb_left);
- +
- + node = parent;
- + goto up;
- +}
- +
- +static void bfq_weights_tree_add(struct bfq_data *bfqd,
- + struct bfq_entity *entity,
- + struct rb_root *root);
- +
- +static void bfq_weights_tree_remove(struct bfq_data *bfqd,
- + struct bfq_entity *entity,
- + struct rb_root *root);
- +
- +
- +/**
- + * bfq_active_insert - insert an entity in the active tree of its
- + * group/device.
- + * @st: the service tree of the entity.
- + * @entity: the entity being inserted.
- + *
- + * The active tree is ordered by finish time, but an extra key is kept
- + * per each node, containing the minimum value for the start times of
- + * its children (and the node itself), so it's possible to search for
- + * the eligible node with the lowest finish time in logarithmic time.
- + */
- +static void bfq_active_insert(struct bfq_service_tree *st,
- + struct bfq_entity *entity)
- +{
- + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
- + struct rb_node *node = &entity->rb_node;
- +#ifdef CONFIG_CGROUP_BFQIO
- + struct bfq_sched_data *sd = NULL;
- + struct bfq_group *bfqg = NULL;
- + struct bfq_data *bfqd = NULL;
- +#endif
- +
- + bfq_insert(&st->active, entity);
- +
- + if (node->rb_left != NULL)
- + node = node->rb_left;
- + else if (node->rb_right != NULL)
- + node = node->rb_right;
- +
- + bfq_update_active_tree(node);
- +
- +#ifdef CONFIG_CGROUP_BFQIO
- + sd = entity->sched_data;
- + bfqg = container_of(sd, struct bfq_group, sched_data);
- + BUG_ON(!bfqg);
- + bfqd = (struct bfq_data *)bfqg->bfqd;
- +#endif
- + if (bfqq != NULL)
- + list_add(&bfqq->bfqq_list, &bfqq->bfqd->active_list);
- +#ifdef CONFIG_CGROUP_BFQIO
- + else { /* bfq_group */
- + BUG_ON(!bfqd);
- + bfq_weights_tree_add(bfqd, entity, &bfqd->group_weights_tree);
- + }
- + if (bfqg != bfqd->root_group) {
- + BUG_ON(!bfqg);
- + BUG_ON(!bfqd);
- + bfqg->active_entities++;
- + if (bfqg->active_entities == 2)
- + bfqd->active_numerous_groups++;
- + }
- +#endif
- +}
- +
- +/**
- + * bfq_ioprio_to_weight - calc a weight from an ioprio.
- + * @ioprio: the ioprio value to convert.
- + */
- +static inline unsigned short bfq_ioprio_to_weight(int ioprio)
- +{
- + BUG_ON(ioprio < 0 || ioprio >= IOPRIO_BE_NR);
- + return IOPRIO_BE_NR - ioprio;
- +}
- +
- +/**
- + * bfq_weight_to_ioprio - calc an ioprio from a weight.
- + * @weight: the weight value to convert.
- + *
- + * To preserve as mush as possible the old only-ioprio user interface,
- + * 0 is used as an escape ioprio value for weights (numerically) equal or
- + * larger than IOPRIO_BE_NR
- + */
- +static inline unsigned short bfq_weight_to_ioprio(int weight)
- +{
- + BUG_ON(weight < BFQ_MIN_WEIGHT || weight > BFQ_MAX_WEIGHT);
- + return IOPRIO_BE_NR - weight < 0 ? 0 : IOPRIO_BE_NR - weight;
- +}
- +
- +static inline void bfq_get_entity(struct bfq_entity *entity)
- +{
- + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
- +
- + if (bfqq != NULL) {
- + atomic_inc(&bfqq->ref);
- + bfq_log_bfqq(bfqq->bfqd, bfqq, "get_entity: %p %d",
- + bfqq, atomic_read(&bfqq->ref));
- + }
- +}
- +
- +/**
- + * bfq_find_deepest - find the deepest node that an extraction can modify.
- + * @node: the node being removed.
- + *
- + * Do the first step of an extraction in an rb tree, looking for the
- + * node that will replace @node, and returning the deepest node that
- + * the following modifications to the tree can touch. If @node is the
- + * last node in the tree return %NULL.
- + */
- +static struct rb_node *bfq_find_deepest(struct rb_node *node)
- +{
- + struct rb_node *deepest;
- +
- + if (node->rb_right == NULL && node->rb_left == NULL)
- + deepest = rb_parent(node);
- + else if (node->rb_right == NULL)
- + deepest = node->rb_left;
- + else if (node->rb_left == NULL)
- + deepest = node->rb_right;
- + else {
- + deepest = rb_next(node);
- + if (deepest->rb_right != NULL)
- + deepest = deepest->rb_right;
- + else if (rb_parent(deepest) != node)
- + deepest = rb_parent(deepest);
- + }
- +
- + return deepest;
- +}
- +
- +/**
- + * bfq_active_extract - remove an entity from the active tree.
- + * @st: the service_tree containing the tree.
- + * @entity: the entity being removed.
- + */
- +static void bfq_active_extract(struct bfq_service_tree *st,
- + struct bfq_entity *entity)
- +{
- + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
- + struct rb_node *node;
- +#ifdef CONFIG_CGROUP_BFQIO
- + struct bfq_sched_data *sd = NULL;
- + struct bfq_group *bfqg = NULL;
- + struct bfq_data *bfqd = NULL;
- +#endif
- +
- + node = bfq_find_deepest(&entity->rb_node);
- + bfq_extract(&st->active, entity);
- +
- + if (node != NULL)
- + bfq_update_active_tree(node);
- +
- +#ifdef CONFIG_CGROUP_BFQIO
- + sd = entity->sched_data;
- + bfqg = container_of(sd, struct bfq_group, sched_data);
- + BUG_ON(!bfqg);
- + bfqd = (struct bfq_data *)bfqg->bfqd;
- +#endif
- + if (bfqq != NULL)
- + list_del(&bfqq->bfqq_list);
- +#ifdef CONFIG_CGROUP_BFQIO
- + else { /* bfq_group */
- + BUG_ON(!bfqd);
- + bfq_weights_tree_remove(bfqd, entity,
- + &bfqd->group_weights_tree);
- + }
- + if (bfqg != bfqd->root_group) {
- + BUG_ON(!bfqg);
- + BUG_ON(!bfqd);
- + BUG_ON(!bfqg->active_entities);
- + bfqg->active_entities--;
- + if (bfqg->active_entities == 1) {
- + BUG_ON(!bfqd->active_numerous_groups);
- + bfqd->active_numerous_groups--;
- + }
- + }
- +#endif
- +}
- +
- +/**
- + * bfq_idle_insert - insert an entity into the idle tree.
- + * @st: the service tree containing the tree.
- + * @entity: the entity to insert.
- + */
- +static void bfq_idle_insert(struct bfq_service_tree *st,
- + struct bfq_entity *entity)
- +{
- + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
- + struct bfq_entity *first_idle = st->first_idle;
- + struct bfq_entity *last_idle = st->last_idle;
- +
- + if (first_idle == NULL || bfq_gt(first_idle->finish, entity->finish))
- + st->first_idle = entity;
- + if (last_idle == NULL || bfq_gt(entity->finish, last_idle->finish))
- + st->last_idle = entity;
- +
- + bfq_insert(&st->idle, entity);
- +
- + if (bfqq != NULL)
- + list_add(&bfqq->bfqq_list, &bfqq->bfqd->idle_list);
- +}
- +
- +/**
- + * bfq_forget_entity - remove an entity from the wfq trees.
- + * @st: the service tree.
- + * @entity: the entity being removed.
- + *
- + * Update the device status and forget everything about @entity, putting
- + * the device reference to it, if it is a queue. Entities belonging to
- + * groups are not refcounted.
- + */
- +static void bfq_forget_entity(struct bfq_service_tree *st,
- + struct bfq_entity *entity)
- +{
- + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
- + struct bfq_sched_data *sd;
- +
- + BUG_ON(!entity->on_st);
- +
- + entity->on_st = 0;
- + st->wsum -= entity->weight;
- + if (bfqq != NULL) {
- + sd = entity->sched_data;
- + bfq_log_bfqq(bfqq->bfqd, bfqq, "forget_entity: %p %d",
- + bfqq, atomic_read(&bfqq->ref));
- + bfq_put_queue(bfqq);
- + }
- +}
- +
- +/**
- + * bfq_put_idle_entity - release the idle tree ref of an entity.
- + * @st: service tree for the entity.
- + * @entity: the entity being released.
- + */
- +static void bfq_put_idle_entity(struct bfq_service_tree *st,
- + struct bfq_entity *entity)
- +{
- + bfq_idle_extract(st, entity);
- + bfq_forget_entity(st, entity);
- +}
- +
- +/**
- + * bfq_forget_idle - update the idle tree if necessary.
- + * @st: the service tree to act upon.
- + *
- + * To preserve the global O(log N) complexity we only remove one entry here;
- + * as the idle tree will not grow indefinitely this can be done safely.
- + */
- +static void bfq_forget_idle(struct bfq_service_tree *st)
- +{
- + struct bfq_entity *first_idle = st->first_idle;
- + struct bfq_entity *last_idle = st->last_idle;
- +
- + if (RB_EMPTY_ROOT(&st->active) && last_idle != NULL &&
- + !bfq_gt(last_idle->finish, st->vtime)) {
- + /*
- + * Forget the whole idle tree, increasing the vtime past
- + * the last finish time of idle entities.
- + */
- + st->vtime = last_idle->finish;
- + }
- +
- + if (first_idle != NULL && !bfq_gt(first_idle->finish, st->vtime))
- + bfq_put_idle_entity(st, first_idle);
- +}
- +
- +static struct bfq_service_tree *
- +__bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
- + struct bfq_entity *entity)
- +{
- + struct bfq_service_tree *new_st = old_st;
- +
- + if (entity->ioprio_changed) {
- + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
- + unsigned short prev_weight, new_weight;
- + struct bfq_data *bfqd = NULL;
- + struct rb_root *root;
- +#ifdef CONFIG_CGROUP_BFQIO
- + struct bfq_sched_data *sd;
- + struct bfq_group *bfqg;
- +#endif
- +
- + if (bfqq != NULL)
- + bfqd = bfqq->bfqd;
- +#ifdef CONFIG_CGROUP_BFQIO
- + else {
- + sd = entity->my_sched_data;
- + bfqg = container_of(sd, struct bfq_group, sched_data);
- + BUG_ON(!bfqg);
- + bfqd = (struct bfq_data *)bfqg->bfqd;
- + BUG_ON(!bfqd);
- + }
- +#endif
- +
- + BUG_ON(old_st->wsum < entity->weight);
- + old_st->wsum -= entity->weight;
- +
- + if (entity->new_weight != entity->orig_weight) {
- + entity->orig_weight = entity->new_weight;
- + entity->ioprio =
- + bfq_weight_to_ioprio(entity->orig_weight);
- + } else if (entity->new_ioprio != entity->ioprio) {
- + entity->ioprio = entity->new_ioprio;
- + entity->orig_weight =
- + bfq_ioprio_to_weight(entity->ioprio);
- + } else
- + entity->new_weight = entity->orig_weight =
- + bfq_ioprio_to_weight(entity->ioprio);
- +
- + entity->ioprio_class = entity->new_ioprio_class;
- + entity->ioprio_changed = 0;
- +
- + /*
- + * NOTE: here we may be changing the weight too early,
- + * this will cause unfairness. The correct approach
- + * would have required additional complexity to defer
- + * weight changes to the proper time instants (i.e.,
- + * when entity->finish <= old_st->vtime).
- + */
- + new_st = bfq_entity_service_tree(entity);
- +
- + prev_weight = entity->weight;
- + new_weight = entity->orig_weight *
- + (bfqq != NULL ? bfqq->wr_coeff : 1);
- + /*
- + * If the weight of the entity changes, remove the entity
- + * from its old weight counter (if there is a counter
- + * associated with the entity), and add it to the counter
- + * associated with its new weight.
- + */
- + if (prev_weight != new_weight) {
- + root = bfqq ? &bfqd->queue_weights_tree :
- + &bfqd->group_weights_tree;
- + bfq_weights_tree_remove(bfqd, entity, root);
- + }
- + entity->weight = new_weight;
- + /*
- + * Add the entity to its weights tree only if it is
- + * not associated with a weight-raised queue.
- + */
- + if (prev_weight != new_weight &&
- + (bfqq ? bfqq->wr_coeff == 1 : 1))
- + /* If we get here, root has been initialized. */
- + bfq_weights_tree_add(bfqd, entity, root);
- +
- + new_st->wsum += entity->weight;
- +
- + if (new_st != old_st)
- + entity->start = new_st->vtime;
- + }
- +
- + return new_st;
- +}
- +
- +/**
- + * bfq_bfqq_served - update the scheduler status after selection for
- + * service.
- + * @bfqq: the queue being served.
- + * @served: bytes to transfer.
- + *
- + * NOTE: this can be optimized, as the timestamps of upper level entities
- + * are synchronized every time a new bfqq is selected for service. By now,
- + * we keep it to better check consistency.
- + */
- +static void bfq_bfqq_served(struct bfq_queue *bfqq, unsigned long served)
- +{
- + struct bfq_entity *entity = &bfqq->entity;
- + struct bfq_service_tree *st;
- +
- + for_each_entity(entity) {
- + st = bfq_entity_service_tree(entity);
- +
- + entity->service += served;
- + BUG_ON(entity->service > entity->budget);
- + BUG_ON(st->wsum == 0);
- +
- + st->vtime += bfq_delta(served, st->wsum);
- + bfq_forget_idle(st);
- + }
- + bfq_log_bfqq(bfqq->bfqd, bfqq, "bfqq_served %lu secs", served);
- +}
- +
- +/**
- + * bfq_bfqq_charge_full_budget - set the service to the entity budget.
- + * @bfqq: the queue that needs a service update.
- + *
- + * When it's not possible to be fair in the service domain, because
- + * a queue is not consuming its budget fast enough (the meaning of
- + * fast depends on the timeout parameter), we charge it a full
- + * budget. In this way we should obtain a sort of time-domain
- + * fairness among all the seeky/slow queues.
- + */
- +static inline void bfq_bfqq_charge_full_budget(struct bfq_queue *bfqq)
- +{
- + struct bfq_entity *entity = &bfqq->entity;
- +
- + bfq_log_bfqq(bfqq->bfqd, bfqq, "charge_full_budget");
- +
- + bfq_bfqq_served(bfqq, entity->budget - entity->service);
- +}
- +
- +/**
- + * __bfq_activate_entity - activate an entity.
- + * @entity: the entity being activated.
- + *
- + * Called whenever an entity is activated, i.e., it is not active and one
- + * of its children receives a new request, or has to be reactivated due to
- + * budget exhaustion. It uses the current budget of the entity (and the
- + * service received if @entity is active) of the queue to calculate its
- + * timestamps.
- + */
- +static void __bfq_activate_entity(struct bfq_entity *entity)
- +{
- + struct bfq_sched_data *sd = entity->sched_data;
- + struct bfq_service_tree *st = bfq_entity_service_tree(entity);
- +
- + if (entity == sd->in_service_entity) {
- + BUG_ON(entity->tree != NULL);
- + /*
- + * If we are requeueing the current entity we have
- + * to take care of not charging to it service it has
- + * not received.
- + */
- + bfq_calc_finish(entity, entity->service);
- + entity->start = entity->finish;
- + sd->in_service_entity = NULL;
- + } else if (entity->tree == &st->active) {
- + /*
- + * Requeueing an entity due to a change of some
- + * next_in_service entity below it. We reuse the
- + * old start time.
- + */
- + bfq_active_extract(st, entity);
- + } else if (entity->tree == &st->idle) {
- + /*
- + * Must be on the idle tree, bfq_idle_extract() will
- + * check for that.
- + */
- + bfq_idle_extract(st, entity);
- + entity->start = bfq_gt(st->vtime, entity->finish) ?
- + st->vtime : entity->finish;
- + } else {
- + /*
- + * The finish time of the entity may be invalid, and
- + * it is in the past for sure, otherwise the queue
- + * would have been on the idle tree.
- + */
- + entity->start = st->vtime;
- + st->wsum += entity->weight;
- + bfq_get_entity(entity);
- +
- + BUG_ON(entity->on_st);
- + entity->on_st = 1;
- + }
- +
- + st = __bfq_entity_update_weight_prio(st, entity);
- + bfq_calc_finish(entity, entity->budget);
- + bfq_active_insert(st, entity);
- +}
- +
- +/**
- + * bfq_activate_entity - activate an entity and its ancestors if necessary.
- + * @entity: the entity to activate.
- + *
- + * Activate @entity and all the entities on the path from it to the root.
- + */
- +static void bfq_activate_entity(struct bfq_entity *entity)
- +{
- + struct bfq_sched_data *sd;
- +
- + for_each_entity(entity) {
- + __bfq_activate_entity(entity);
- +
- + sd = entity->sched_data;
- + if (!bfq_update_next_in_service(sd))
- + /*
- + * No need to propagate the activation to the
- + * upper entities, as they will be updated when
- + * the in-service entity is rescheduled.
- + */
- + break;
- + }
- +}
- +
- +/**
- + * __bfq_deactivate_entity - deactivate an entity from its service tree.
- + * @entity: the entity to deactivate.
- + * @requeue: if false, the entity will not be put into the idle tree.
- + *
- + * Deactivate an entity, independently from its previous state. If the
- + * entity was not on a service tree just return, otherwise if it is on
- + * any scheduler tree, extract it from that tree, and if necessary
- + * and if the caller did not specify @requeue, put it on the idle tree.
- + *
- + * Return %1 if the caller should update the entity hierarchy, i.e.,
- + * if the entity was in service or if it was the next_in_service for
- + * its sched_data; return %0 otherwise.
- + */
- +static int __bfq_deactivate_entity(struct bfq_entity *entity, int requeue)
- +{
- + struct bfq_sched_data *sd = entity->sched_data;
- + struct bfq_service_tree *st = bfq_entity_service_tree(entity);
- + int was_in_service = entity == sd->in_service_entity;
- + int ret = 0;
- +
- + if (!entity->on_st)
- + return 0;
- +
- + BUG_ON(was_in_service && entity->tree != NULL);
- +
- + if (was_in_service) {
- + bfq_calc_finish(entity, entity->service);
- + sd->in_service_entity = NULL;
- + } else if (entity->tree == &st->active)
- + bfq_active_extract(st, entity);
- + else if (entity->tree == &st->idle)
- + bfq_idle_extract(st, entity);
- + else if (entity->tree != NULL)
- + BUG();
- +
- + if (was_in_service || sd->next_in_service == entity)
- + ret = bfq_update_next_in_service(sd);
- +
- + if (!requeue || !bfq_gt(entity->finish, st->vtime))
- + bfq_forget_entity(st, entity);
- + else
- + bfq_idle_insert(st, entity);
- +
- + BUG_ON(sd->in_service_entity == entity);
- + BUG_ON(sd->next_in_service == entity);
- +
- + return ret;
- +}
- +
- +/**
- + * bfq_deactivate_entity - deactivate an entity.
- + * @entity: the entity to deactivate.
- + * @requeue: true if the entity can be put on the idle tree
- + */
- +static void bfq_deactivate_entity(struct bfq_entity *entity, int requeue)
- +{
- + struct bfq_sched_data *sd;
- + struct bfq_entity *parent;
- +
- + for_each_entity_safe(entity, parent) {
- + sd = entity->sched_data;
- +
- + if (!__bfq_deactivate_entity(entity, requeue))
- + /*
- + * The parent entity is still backlogged, and
- + * we don't need to update it as it is still
- + * in service.
- + */
- + break;
- +
- + if (sd->next_in_service != NULL)
- + /*
- + * The parent entity is still backlogged and
- + * the budgets on the path towards the root
- + * need to be updated.
- + */
- + goto update;
- +
- + /*
- + * If we reach there the parent is no more backlogged and
- + * we want to propagate the dequeue upwards.
- + */
- + requeue = 1;
- + }
- +
- + return;
- +
- +update:
- + entity = parent;
- + for_each_entity(entity) {
- + __bfq_activate_entity(entity);
- +
- + sd = entity->sched_data;
- + if (!bfq_update_next_in_service(sd))
- + break;
- + }
- +}
- +
- +/**
- + * bfq_update_vtime - update vtime if necessary.
- + * @st: the service tree to act upon.
- + *
- + * If necessary update the service tree vtime to have at least one
- + * eligible entity, skipping to its start time. Assumes that the
- + * active tree of the device is not empty.
- + *
- + * NOTE: this hierarchical implementation updates vtimes quite often,
- + * we may end up with reactivated processes getting timestamps after a
- + * vtime skip done because we needed a ->first_active entity on some
- + * intermediate node.
- + */
- +static void bfq_update_vtime(struct bfq_service_tree *st)
- +{
- + struct bfq_entity *entry;
- + struct rb_node *node = st->active.rb_node;
- +
- + entry = rb_entry(node, struct bfq_entity, rb_node);
- + if (bfq_gt(entry->min_start, st->vtime)) {
- + st->vtime = entry->min_start;
- + bfq_forget_idle(st);
- + }
- +}
- +
- +/**
- + * bfq_first_active_entity - find the eligible entity with
- + * the smallest finish time
- + * @st: the service tree to select from.
- + *
- + * This function searches the first schedulable entity, starting from the
- + * root of the tree and going on the left every time on this side there is
- + * a subtree with at least one eligible (start >= vtime) entity. The path on
- + * the right is followed only if a) the left subtree contains no eligible
- + * entities and b) no eligible entity has been found yet.
- + */
- +static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st)
- +{
- + struct bfq_entity *entry, *first = NULL;
- + struct rb_node *node = st->active.rb_node;
- +
- + while (node != NULL) {
- + entry = rb_entry(node, struct bfq_entity, rb_node);
- +left:
- + if (!bfq_gt(entry->start, st->vtime))
- + first = entry;
- +
- + BUG_ON(bfq_gt(entry->min_start, st->vtime));
- +
- + if (node->rb_left != NULL) {
- + entry = rb_entry(node->rb_left,
- + struct bfq_entity, rb_node);
- + if (!bfq_gt(entry->min_start, st->vtime)) {
- + node = node->rb_left;
- + goto left;
- + }
- + }
- + if (first != NULL)
- + break;
- + node = node->rb_right;
- + }
- +
- + BUG_ON(first == NULL && !RB_EMPTY_ROOT(&st->active));
- + return first;
- +}
- +
- +/**
- + * __bfq_lookup_next_entity - return the first eligible entity in @st.
- + * @st: the service tree.
- + *
- + * Update the virtual time in @st and return the first eligible entity
- + * it contains.
- + */
- +static struct bfq_entity *__bfq_lookup_next_entity(struct bfq_service_tree *st,
- + bool force)
- +{
- + struct bfq_entity *entity, *new_next_in_service = NULL;
- +
- + if (RB_EMPTY_ROOT(&st->active))
- + return NULL;
- +
- + bfq_update_vtime(st);
- + entity = bfq_first_active_entity(st);
- + BUG_ON(bfq_gt(entity->start, st->vtime));
- +
- + /*
- + * If the chosen entity does not match with the sched_data's
- + * next_in_service and we are forcedly serving the IDLE priority
- + * class tree, bubble up budget update.
- + */
- + if (unlikely(force && entity != entity->sched_data->next_in_service)) {
- + new_next_in_service = entity;
- + for_each_entity(new_next_in_service)
- + bfq_update_budget(new_next_in_service);
- + }
- +
- + return entity;
- +}
- +
- +/**
- + * bfq_lookup_next_entity - return the first eligible entity in @sd.
- + * @sd: the sched_data.
- + * @extract: if true the returned entity will be also extracted from @sd.
- + *
- + * NOTE: since we cache the next_in_service entity at each level of the
- + * hierarchy, the complexity of the lookup can be decreased with
- + * absolutely no effort just returning the cached next_in_service value;
- + * we prefer to do full lookups to test the consistency of * the data
- + * structures.
- + */
- +static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd,
- + int extract,
- + struct bfq_data *bfqd)
- +{
- + struct bfq_service_tree *st = sd->service_tree;
- + struct bfq_entity *entity;
- + int i = 0;
- +
- + BUG_ON(sd->in_service_entity != NULL);
- +
- + if (bfqd != NULL &&
- + jiffies - bfqd->bfq_class_idle_last_service > BFQ_CL_IDLE_TIMEOUT) {
- + entity = __bfq_lookup_next_entity(st + BFQ_IOPRIO_CLASSES - 1,
- + true);
- + if (entity != NULL) {
- + i = BFQ_IOPRIO_CLASSES - 1;
- + bfqd->bfq_class_idle_last_service = jiffies;
- + sd->next_in_service = entity;
- + }
- + }
- + for (; i < BFQ_IOPRIO_CLASSES; i++) {
- + entity = __bfq_lookup_next_entity(st + i, false);
- + if (entity != NULL) {
- + if (extract) {
- + bfq_check_next_in_service(sd, entity);
- + bfq_active_extract(st + i, entity);
- + sd->in_service_entity = entity;
- + sd->next_in_service = NULL;
- + }
- + break;
- + }
- + }
- +
- + return entity;
- +}
- +
- +/*
- + * Get next queue for service.
- + */
- +static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd)
- +{
- + struct bfq_entity *entity = NULL;
- + struct bfq_sched_data *sd;
- + struct bfq_queue *bfqq;
- +
- + BUG_ON(bfqd->in_service_queue != NULL);
- +
- + if (bfqd->busy_queues == 0)
- + return NULL;
- +
- + sd = &bfqd->root_group->sched_data;
- + for (; sd != NULL; sd = entity->my_sched_data) {
- + entity = bfq_lookup_next_entity(sd, 1, bfqd);
- + BUG_ON(entity == NULL);
- + entity->service = 0;
- + }
- +
- + bfqq = bfq_entity_to_bfqq(entity);
- + BUG_ON(bfqq == NULL);
- +
- + return bfqq;
- +}
- +
- +static void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd)
- +{
- + if (bfqd->in_service_bic != NULL) {
- + put_io_context(bfqd->in_service_bic->icq.ioc);
- + bfqd->in_service_bic = NULL;
- + }
- +
- + bfqd->in_service_queue = NULL;
- + del_timer(&bfqd->idle_slice_timer);
- +}
- +
- +static void bfq_deactivate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq,
- + int requeue)
- +{
- + struct bfq_entity *entity = &bfqq->entity;
- +
- + if (bfqq == bfqd->in_service_queue)
- + __bfq_bfqd_reset_in_service(bfqd);
- +
- + bfq_deactivate_entity(entity, requeue);
- +}
- +
- +static void bfq_activate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
- +{
- + struct bfq_entity *entity = &bfqq->entity;
- +
- + bfq_activate_entity(entity);
- +}
- +
- +/*
- + * Called when the bfqq no longer has requests pending, remove it from
- + * the service tree.
- + */
- +static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq,
- + int requeue)
- +{
- + BUG_ON(!bfq_bfqq_busy(bfqq));
- + BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list));
- +
- + bfq_log_bfqq(bfqd, bfqq, "del from busy");
- +
- + bfq_clear_bfqq_busy(bfqq);
- +
- + BUG_ON(bfqd->busy_queues == 0);
- + bfqd->busy_queues--;
- +
- + if (!bfqq->dispatched) {
- + bfq_weights_tree_remove(bfqd, &bfqq->entity,
- + &bfqd->queue_weights_tree);
- + if (!blk_queue_nonrot(bfqd->queue)) {
- + BUG_ON(!bfqd->busy_in_flight_queues);
- + bfqd->busy_in_flight_queues--;
- + if (bfq_bfqq_constantly_seeky(bfqq)) {
- + BUG_ON(!bfqd->
- + const_seeky_busy_in_flight_queues);
- + bfqd->const_seeky_busy_in_flight_queues--;
- + }
- + }
- + }
- + if (bfqq->wr_coeff > 1)
- + bfqd->wr_busy_queues--;
- +
- + bfq_deactivate_bfqq(bfqd, bfqq, requeue);
- +}
- +
- +/*
- + * Called when an inactive queue receives a new request.
- + */
- +static void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq)
- +{
- + BUG_ON(bfq_bfqq_busy(bfqq));
- + BUG_ON(bfqq == bfqd->in_service_queue);
- +
- + bfq_log_bfqq(bfqd, bfqq, "add to busy");
- +
- + bfq_activate_bfqq(bfqd, bfqq);
- +
- + bfq_mark_bfqq_busy(bfqq);
- + bfqd->busy_queues++;
- +
- + if (!bfqq->dispatched) {
- + if (bfqq->wr_coeff == 1)
- + bfq_weights_tree_add(bfqd, &bfqq->entity,
- + &bfqd->queue_weights_tree);
- + if (!blk_queue_nonrot(bfqd->queue)) {
- + bfqd->busy_in_flight_queues++;
- + if (bfq_bfqq_constantly_seeky(bfqq))
- + bfqd->const_seeky_busy_in_flight_queues++;
- + }
- + }
- + if (bfqq->wr_coeff > 1)
- + bfqd->wr_busy_queues++;
- +}
- diff -Nur linux-3.14.35.orig/block/blk-core.c linux-3.14.35/block/blk-core.c
- --- linux-3.14.35.orig/block/blk-core.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/block/blk-core.c 2015-03-08 14:27:37.461684502 -0500
- @@ -1928,7 +1928,7 @@
- * in some cases below, so export this function.
- * Request stacking drivers like request-based dm may change the queue
- * limits while requests are in the queue (e.g. dm's table swapping).
- - * Such request stacking drivers should check those requests agaist
- + * Such request stacking drivers should check those requests against
- * the new queue limits again when they dispatch those requests,
- * although such checkings are also done against the old queue limits
- * when submitting requests.
- diff -Nur linux-3.14.35.orig/block/blk-map.c linux-3.14.35/block/blk-map.c
- --- linux-3.14.35.orig/block/blk-map.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/block/blk-map.c 2015-03-08 14:27:37.461684502 -0500
- @@ -285,7 +285,7 @@
- *
- * Description:
- * Data will be mapped directly if possible. Otherwise a bounce
- - * buffer is used. Can be called multple times to append multple
- + * buffer is used. Can be called multiple times to append multiple
- * buffers.
- */
- int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
- diff -Nur linux-3.14.35.orig/block/Kconfig.iosched linux-3.14.35/block/Kconfig.iosched
- --- linux-3.14.35.orig/block/Kconfig.iosched 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/block/Kconfig.iosched 2015-03-08 14:27:37.461684502 -0500
- @@ -39,6 +39,27 @@
- ---help---
- Enable group IO scheduling in CFQ.
-
- +config IOSCHED_BFQ
- + tristate "BFQ I/O scheduler"
- + default n
- + ---help---
- + The BFQ I/O scheduler tries to distribute bandwidth among
- + all processes according to their weights.
- + It aims at distributing the bandwidth as desired, independently of
- + the disk parameters and with any workload. It also tries to
- + guarantee low latency to interactive and soft real-time
- + applications. If compiled built-in (saying Y here), BFQ can
- + be configured to support hierarchical scheduling.
- +
- +config CGROUP_BFQIO
- + bool "BFQ hierarchical scheduling support"
- + depends on CGROUPS && IOSCHED_BFQ=y
- + default n
- + ---help---
- + Enable hierarchical scheduling in BFQ, using the cgroups
- + filesystem interface. The name of the subsystem will be
- + bfqio.
- +
- choice
- prompt "Default I/O scheduler"
- default DEFAULT_CFQ
- @@ -52,6 +73,16 @@
- config DEFAULT_CFQ
- bool "CFQ" if IOSCHED_CFQ=y
-
- + config DEFAULT_BFQ
- + bool "BFQ" if IOSCHED_BFQ=y
- + help
- + Selects BFQ as the default I/O scheduler which will be
- + used by default for all block devices.
- + The BFQ I/O scheduler aims at distributing the bandwidth
- + as desired, independently of the disk parameters and with
- + any workload. It also tries to guarantee low latency to
- + interactive and soft real-time applications.
- +
- config DEFAULT_NOOP
- bool "No-op"
-
- @@ -61,6 +92,7 @@
- string
- default "deadline" if DEFAULT_DEADLINE
- default "cfq" if DEFAULT_CFQ
- + default "bfq" if DEFAULT_BFQ
- default "noop" if DEFAULT_NOOP
-
- endmenu
- diff -Nur linux-3.14.35.orig/block/Makefile linux-3.14.35/block/Makefile
- --- linux-3.14.35.orig/block/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/block/Makefile 2015-03-08 14:27:37.461684502 -0500
- @@ -16,6 +16,7 @@
- obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o
- obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o
- obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o
- +obj-$(CONFIG_IOSCHED_BFQ) += bfq-iosched.o
-
- obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o
- obj-$(CONFIG_BLK_DEV_INTEGRITY) += blk-integrity.o
- diff -Nur linux-3.14.35.orig/crypto/blkcipher.c linux-3.14.35/crypto/blkcipher.c
- --- linux-3.14.35.orig/crypto/blkcipher.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/crypto/blkcipher.c 2015-03-08 14:27:37.461684502 -0500
- @@ -70,14 +70,12 @@
- return max(start, end_page);
- }
-
- -static inline unsigned int blkcipher_done_slow(struct crypto_blkcipher *tfm,
- - struct blkcipher_walk *walk,
- +static inline unsigned int blkcipher_done_slow(struct blkcipher_walk *walk,
- unsigned int bsize)
- {
- u8 *addr;
- - unsigned int alignmask = crypto_blkcipher_alignmask(tfm);
-
- - addr = (u8 *)ALIGN((unsigned long)walk->buffer, alignmask + 1);
- + addr = (u8 *)ALIGN((unsigned long)walk->buffer, walk->alignmask + 1);
- addr = blkcipher_get_spot(addr, bsize);
- scatterwalk_copychunks(addr, &walk->out, bsize, 1);
- return bsize;
- @@ -105,7 +103,6 @@
- int blkcipher_walk_done(struct blkcipher_desc *desc,
- struct blkcipher_walk *walk, int err)
- {
- - struct crypto_blkcipher *tfm = desc->tfm;
- unsigned int nbytes = 0;
-
- if (likely(err >= 0)) {
- @@ -117,7 +114,7 @@
- err = -EINVAL;
- goto err;
- } else
- - n = blkcipher_done_slow(tfm, walk, n);
- + n = blkcipher_done_slow(walk, n);
-
- nbytes = walk->total - n;
- err = 0;
- @@ -136,7 +133,7 @@
- }
-
- if (walk->iv != desc->info)
- - memcpy(desc->info, walk->iv, crypto_blkcipher_ivsize(tfm));
- + memcpy(desc->info, walk->iv, walk->ivsize);
- if (walk->buffer != walk->page)
- kfree(walk->buffer);
- if (walk->page)
- @@ -226,22 +223,20 @@
- static int blkcipher_walk_next(struct blkcipher_desc *desc,
- struct blkcipher_walk *walk)
- {
- - struct crypto_blkcipher *tfm = desc->tfm;
- - unsigned int alignmask = crypto_blkcipher_alignmask(tfm);
- unsigned int bsize;
- unsigned int n;
- int err;
-
- n = walk->total;
- - if (unlikely(n < crypto_blkcipher_blocksize(tfm))) {
- + if (unlikely(n < walk->cipher_blocksize)) {
- desc->flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
- return blkcipher_walk_done(desc, walk, -EINVAL);
- }
-
- walk->flags &= ~(BLKCIPHER_WALK_SLOW | BLKCIPHER_WALK_COPY |
- BLKCIPHER_WALK_DIFF);
- - if (!scatterwalk_aligned(&walk->in, alignmask) ||
- - !scatterwalk_aligned(&walk->out, alignmask)) {
- + if (!scatterwalk_aligned(&walk->in, walk->alignmask) ||
- + !scatterwalk_aligned(&walk->out, walk->alignmask)) {
- walk->flags |= BLKCIPHER_WALK_COPY;
- if (!walk->page) {
- walk->page = (void *)__get_free_page(GFP_ATOMIC);
- @@ -250,12 +245,12 @@
- }
- }
-
- - bsize = min(walk->blocksize, n);
- + bsize = min(walk->walk_blocksize, n);
- n = scatterwalk_clamp(&walk->in, n);
- n = scatterwalk_clamp(&walk->out, n);
-
- if (unlikely(n < bsize)) {
- - err = blkcipher_next_slow(desc, walk, bsize, alignmask);
- + err = blkcipher_next_slow(desc, walk, bsize, walk->alignmask);
- goto set_phys_lowmem;
- }
-
- @@ -277,28 +272,26 @@
- return err;
- }
-
- -static inline int blkcipher_copy_iv(struct blkcipher_walk *walk,
- - struct crypto_blkcipher *tfm,
- - unsigned int alignmask)
- -{
- - unsigned bs = walk->blocksize;
- - unsigned int ivsize = crypto_blkcipher_ivsize(tfm);
- - unsigned aligned_bs = ALIGN(bs, alignmask + 1);
- - unsigned int size = aligned_bs * 2 + ivsize + max(aligned_bs, ivsize) -
- - (alignmask + 1);
- +static inline int blkcipher_copy_iv(struct blkcipher_walk *walk)
- +{
- + unsigned bs = walk->walk_blocksize;
- + unsigned aligned_bs = ALIGN(bs, walk->alignmask + 1);
- + unsigned int size = aligned_bs * 2 +
- + walk->ivsize + max(aligned_bs, walk->ivsize) -
- + (walk->alignmask + 1);
- u8 *iv;
-
- - size += alignmask & ~(crypto_tfm_ctx_alignment() - 1);
- + size += walk->alignmask & ~(crypto_tfm_ctx_alignment() - 1);
- walk->buffer = kmalloc(size, GFP_ATOMIC);
- if (!walk->buffer)
- return -ENOMEM;
-
- - iv = (u8 *)ALIGN((unsigned long)walk->buffer, alignmask + 1);
- + iv = (u8 *)ALIGN((unsigned long)walk->buffer, walk->alignmask + 1);
- iv = blkcipher_get_spot(iv, bs) + aligned_bs;
- iv = blkcipher_get_spot(iv, bs) + aligned_bs;
- - iv = blkcipher_get_spot(iv, ivsize);
- + iv = blkcipher_get_spot(iv, walk->ivsize);
-
- - walk->iv = memcpy(iv, walk->iv, ivsize);
- + walk->iv = memcpy(iv, walk->iv, walk->ivsize);
- return 0;
- }
-
- @@ -306,7 +299,10 @@
- struct blkcipher_walk *walk)
- {
- walk->flags &= ~BLKCIPHER_WALK_PHYS;
- - walk->blocksize = crypto_blkcipher_blocksize(desc->tfm);
- + walk->walk_blocksize = crypto_blkcipher_blocksize(desc->tfm);
- + walk->cipher_blocksize = walk->walk_blocksize;
- + walk->ivsize = crypto_blkcipher_ivsize(desc->tfm);
- + walk->alignmask = crypto_blkcipher_alignmask(desc->tfm);
- return blkcipher_walk_first(desc, walk);
- }
- EXPORT_SYMBOL_GPL(blkcipher_walk_virt);
- @@ -315,7 +311,10 @@
- struct blkcipher_walk *walk)
- {
- walk->flags |= BLKCIPHER_WALK_PHYS;
- - walk->blocksize = crypto_blkcipher_blocksize(desc->tfm);
- + walk->walk_blocksize = crypto_blkcipher_blocksize(desc->tfm);
- + walk->cipher_blocksize = walk->walk_blocksize;
- + walk->ivsize = crypto_blkcipher_ivsize(desc->tfm);
- + walk->alignmask = crypto_blkcipher_alignmask(desc->tfm);
- return blkcipher_walk_first(desc, walk);
- }
- EXPORT_SYMBOL_GPL(blkcipher_walk_phys);
- @@ -323,9 +322,6 @@
- static int blkcipher_walk_first(struct blkcipher_desc *desc,
- struct blkcipher_walk *walk)
- {
- - struct crypto_blkcipher *tfm = desc->tfm;
- - unsigned int alignmask = crypto_blkcipher_alignmask(tfm);
- -
- if (WARN_ON_ONCE(in_irq()))
- return -EDEADLK;
-
- @@ -335,8 +331,8 @@
-
- walk->buffer = NULL;
- walk->iv = desc->info;
- - if (unlikely(((unsigned long)walk->iv & alignmask))) {
- - int err = blkcipher_copy_iv(walk, tfm, alignmask);
- + if (unlikely(((unsigned long)walk->iv & walk->alignmask))) {
- + int err = blkcipher_copy_iv(walk);
- if (err)
- return err;
- }
- @@ -353,11 +349,28 @@
- unsigned int blocksize)
- {
- walk->flags &= ~BLKCIPHER_WALK_PHYS;
- - walk->blocksize = blocksize;
- + walk->walk_blocksize = blocksize;
- + walk->cipher_blocksize = crypto_blkcipher_blocksize(desc->tfm);
- + walk->ivsize = crypto_blkcipher_ivsize(desc->tfm);
- + walk->alignmask = crypto_blkcipher_alignmask(desc->tfm);
- return blkcipher_walk_first(desc, walk);
- }
- EXPORT_SYMBOL_GPL(blkcipher_walk_virt_block);
-
- +int blkcipher_aead_walk_virt_block(struct blkcipher_desc *desc,
- + struct blkcipher_walk *walk,
- + struct crypto_aead *tfm,
- + unsigned int blocksize)
- +{
- + walk->flags &= ~BLKCIPHER_WALK_PHYS;
- + walk->walk_blocksize = blocksize;
- + walk->cipher_blocksize = crypto_aead_blocksize(tfm);
- + walk->ivsize = crypto_aead_ivsize(tfm);
- + walk->alignmask = crypto_aead_alignmask(tfm);
- + return blkcipher_walk_first(desc, walk);
- +}
- +EXPORT_SYMBOL_GPL(blkcipher_aead_walk_virt_block);
- +
- static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key,
- unsigned int keylen)
- {
- diff -Nur linux-3.14.35.orig/crypto/tcrypt.c linux-3.14.35/crypto/tcrypt.c
- --- linux-3.14.35.orig/crypto/tcrypt.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/crypto/tcrypt.c 2015-03-08 14:27:37.461684502 -0500
- @@ -33,6 +33,7 @@
- #include <linux/jiffies.h>
- #include <linux/timex.h>
- #include <linux/interrupt.h>
- +#include <linux/sched.h>
- #include "tcrypt.h"
- #include "internal.h"
-
- @@ -447,6 +448,7 @@
- goto out;
- }
-
- + schedule();
- printk("test %u (%d bit key, %d byte blocks): ", i,
- *keysize * 8, *b_size);
-
- @@ -713,6 +715,7 @@
- if (speed[i].klen)
- crypto_hash_setkey(tfm, tvmem[0], speed[i].klen);
-
- + schedule();
- printk(KERN_INFO "test%3u "
- "(%5u byte blocks,%5u bytes per update,%4u updates): ",
- i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen);
- @@ -953,6 +956,7 @@
- break;
- }
-
- + schedule();
- pr_info("test%3u "
- "(%5u byte blocks,%5u bytes per update,%4u updates): ",
- i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen);
- @@ -1118,6 +1122,7 @@
- goto out_free_req;
- }
-
- + schedule();
- pr_info("test %u (%d bit key, %d byte blocks): ", i,
- *keysize * 8, *b_size);
-
- @@ -1199,6 +1204,7 @@
- printk("alg %s ", *name);
- printk(crypto_has_alg(*name, 0, 0) ?
- "found\n" : "not found\n");
- + schedule();
- name++;
- }
- }
- diff -Nur linux-3.14.35.orig/Documentation/ABI/testing/sysfs-class-net-statistics linux-3.14.35/Documentation/ABI/testing/sysfs-class-net-statistics
- --- linux-3.14.35.orig/Documentation/ABI/testing/sysfs-class-net-statistics 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/Documentation/ABI/testing/sysfs-class-net-statistics 2015-03-08 14:27:37.461684502 -0500
- @@ -0,0 +1,201 @@
- +What: /sys/class/<iface>/statistics/collisions
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of collisions seen by this network device.
- + This value might not be relevant with all MAC layers.
- +
- +What: /sys/class/<iface>/statistics/multicast
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of multicast packets received by this
- + network device.
- +
- +What: /sys/class/<iface>/statistics/rx_bytes
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of bytes received by this network device.
- + See the network driver for the exact meaning of when this
- + value is incremented.
- +
- +What: /sys/class/<iface>/statistics/rx_compressed
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of compressed packets received by this
- + network device. This value might only be relevant for interfaces
- + that support packet compression (e.g: PPP).
- +
- +What: /sys/class/<iface>/statistics/rx_crc_errors
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of packets received with a CRC (FCS) error
- + by this network device. Note that the specific meaning might
- + depend on the MAC layer used by the interface.
- +
- +What: /sys/class/<iface>/statistics/rx_dropped
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of packets received by the network device
- + but dropped, that are not forwarded to the upper layers for
- + packet processing. See the network driver for the exact
- + meaning of this value.
- +
- +What: /sys/class/<iface>/statistics/rx_fifo_errors
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of receive FIFO errors seen by this
- + network device. See the network driver for the exact
- + meaning of this value.
- +
- +What: /sys/class/<iface>/statistics/rx_frame_errors
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of received frames with error, such as
- + alignment errors. Note that the specific meaning depends on
- + on the MAC layer protocol used. See the network driver for
- + the exact meaning of this value.
- +
- +What: /sys/class/<iface>/statistics/rx_length_errors
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of received error packet with a length
- + error, oversized or undersized. See the network driver for the
- + exact meaning of this value.
- +
- +What: /sys/class/<iface>/statistics/rx_missed_errors
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of received packets that have been missed
- + due to lack of capacity in the receive side. See the network
- + driver for the exact meaning of this value.
- +
- +What: /sys/class/<iface>/statistics/rx_over_errors
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of received packets that are oversized
- + compared to what the network device is configured to accept
- + (e.g: larger than MTU). See the network driver for the exact
- + meaning of this value.
- +
- +What: /sys/class/<iface>/statistics/rx_packets
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the total number of good packets received by this
- + network device.
- +
- +What: /sys/class/<iface>/statistics/tx_aborted_errors
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of packets that have been aborted
- + during transmission by a network device (e.g: because of
- + a medium collision). See the network driver for the exact
- + meaning of this value.
- +
- +What: /sys/class/<iface>/statistics/tx_bytes
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of bytes transmitted by a network
- + device. See the network driver for the exact meaning of this
- + value, in particular whether this accounts for all successfully
- + transmitted packets or all packets that have been queued for
- + transmission.
- +
- +What: /sys/class/<iface>/statistics/tx_carrier_errors
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of packets that could not be transmitted
- + because of carrier errors (e.g: physical link down). See the
- + network driver for the exact meaning of this value.
- +
- +What: /sys/class/<iface>/statistics/tx_compressed
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of transmitted compressed packets. Note
- + this might only be relevant for devices that support
- + compression (e.g: PPP).
- +
- +What: /sys/class/<iface>/statistics/tx_dropped
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of packets dropped during transmission.
- + See the driver for the exact reasons as to why the packets were
- + dropped.
- +
- +What: /sys/class/<iface>/statistics/tx_errors
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of packets in error during transmission by
- + a network device. See the driver for the exact reasons as to
- + why the packets were dropped.
- +
- +What: /sys/class/<iface>/statistics/tx_fifo_errors
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of packets having caused a transmit
- + FIFO error. See the driver for the exact reasons as to why the
- + packets were dropped.
- +
- +What: /sys/class/<iface>/statistics/tx_heartbeat_errors
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of packets transmitted that have been
- + reported as heartbeat errors. See the driver for the exact
- + reasons as to why the packets were dropped.
- +
- +What: /sys/class/<iface>/statistics/tx_packets
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of packets transmitted by a network
- + device. See the driver for whether this reports the number of all
- + attempted or successful transmissions.
- +
- +What: /sys/class/<iface>/statistics/tx_window_errors
- +Date: April 2005
- +KernelVersion: 2.6.12
- +Contact: netdev@vger.kernel.org
- +Description:
- + Indicates the number of packets not successfully transmitted
- + due to a window collision. The specific meaning depends on the
- + MAC layer used. On Ethernet this is usually used to report
- + late collisions errors.
- diff -Nur linux-3.14.35.orig/Documentation/arm64/booting.txt linux-3.14.35/Documentation/arm64/booting.txt
- --- linux-3.14.35.orig/Documentation/arm64/booting.txt 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/Documentation/arm64/booting.txt 2015-03-08 14:27:37.461684502 -0500
- @@ -111,8 +111,14 @@
- - Caches, MMUs
- The MMU must be off.
- Instruction cache may be on or off.
- - Data cache must be off and invalidated.
- - External caches (if present) must be configured and disabled.
- + The address range corresponding to the loaded kernel image must be
- + cleaned to the PoC. In the presence of a system cache or other
- + coherent masters with caches enabled, this will typically require
- + cache maintenance by VA rather than set/way operations.
- + System caches which respect the architected cache maintenance by VA
- + operations must be configured and may be enabled.
- + System caches which do not respect architected cache maintenance by VA
- + operations (not recommended) must be configured and disabled.
-
- - Architected timers
- CNTFRQ must be programmed with the timer frequency and CNTVOFF must
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/arm/imx/busfreq-imx6.txt linux-3.14.35/Documentation/devicetree/bindings/arm/imx/busfreq-imx6.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/arm/imx/busfreq-imx6.txt 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/arm/imx/busfreq-imx6.txt 2015-03-08 14:27:37.461684502 -0500
- @@ -0,0 +1,64 @@
- +Freescale Busfreq driver
- +
- +It is a generic driver that manages the frequency of the DDR, AHB and AXI buses in the iMX6x architecture.
- +It works for both SMP and UP systems and for both DDR3 and LPDDR2 memory types.
- +
- +Required properties are listed below:
- +- compatible: should be "fsl,imx6_busfreq"
- +- clocks: Lists the various clocks used by the busfreq driver
- +- interrupts - Lists the interrupts used by the busfreq driver. This is needed only for SMP architecutre.
- +- fsl,max_ddr_freq - The max ddr freq for this chip
- +
- +Examples:
- +For SOC imx6q.dtsi:
- + busfreq { /* BUSFREQ */
- + compatible = "fsl,imx6_busfreq";
- + clocks = <&clks 171>, <&clks 6>, <&clks 11>, <&clks 104>, <&clks 172>, <&clks 58>,
- + <&clks 18>, <&clks 60>, <&clks 20>, <&clks 3>;
- + clock-names = "pll2_bus", "pll2_pfd2_396m", "pll2_198m", "arm", "pll3_usb_otg", "periph",
- + "periph_pre", "periph_clk2", "periph_clk2_sel", "osc";
- + interrupts = <0 107 0x04>, <0 112 0x4>, <0 113 0x4>, <0 114 0x4>;
- + interrupt-names = "irq_busfreq_0", "irq_busfreq_1", "irq_busfreq_2", "irq_busfreq_3";
- + fsl,max_ddr_freq = <528000000>;
- + };
- +
- +The Freescale Busfreq driver supports the following setpoints for the DDR freq:
- +enum bus_freq_mode {
- + BUS_FREQ_HIGH, -> The max freq the SOC supports
- + BUS_FREQ_MED, -> Medium setpoint (ex 400MHz for DDR3 when the max is 528MHz)
- + BUS_FREQ_AUDIO, -> Audio playback freq (50MHz)
- + BUS_FREQ_LOW, -> Low power IDLE freq (24MHz)
- +};
- +
- +Currently the Freescale Busfreq driver implementation requires drivers to call the following APIs:
- +1. request_bus_freq(enum bus_freq_mode):
- + The driver is requesting the system and ddr freq to be set to the requested value. The driver should call this
- + API before it even enables its clocks.
- +
- +2. release_bus_freq(enum bus_freq_mode):
- + The driver no longer needs the system and ddr freq at the required value. The driver should call this API after
- + its work is done and it has disabled its clocks.
- +
- +Examples:
- +In the IPU driver, the requesting and releasing of the required bus frequency is tied into the runtime PM implementation:
- +
- +int ipu_runtime_suspend(struct device *dev)
- +{
- + release_bus_freq(BUS_FREQ_HIGH);
- + dev_dbg(dev, "ipu busfreq high release.\n");
- +
- + return 0;
- +}
- +
- +int ipu_runtime_resume(struct device *dev)
- +{
- + request_bus_freq(BUS_FREQ_HIGH);
- + dev_dbg(dev, "ipu busfreq high requst.\n");
- +
- + return 0;
- +}
- +
- +static const struct dev_pm_ops ipu_pm_ops = {
- + SET_RUNTIME_PM_OPS(ipu_runtime_suspend, ipu_runtime_resume, NULL)
- + SET_SYSTEM_SLEEP_PM_OPS(ipu_suspend, ipu_resume)
- +};
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/arm/imx/gpc.txt linux-3.14.35/Documentation/devicetree/bindings/arm/imx/gpc.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/arm/imx/gpc.txt 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/arm/imx/gpc.txt 2015-03-08 14:27:37.461684502 -0500
- @@ -0,0 +1,20 @@
- +Freescale imx GPC bindings
- +
- +Optional properties:
- +- fsl,cpu_pupscr_sw2iso: for powering up CPU, number of 32K clock cycle PGC will wait before negating isolation signal.
- +- fsl,cpu_pupscr_sw: for powering up CPU, number of 32K clock cycle PGC will wait before asserting isolation signal.
- +- fsl,cpu_pdnscr_iso2sw: for powering down CPU, number of ipg clock cycle PGC will wait before negating isolation signal.
- +- fsl,cpu_pdnscr_iso: for powering down CPU, number of ipg clock cycle PGC will wait before asserting isolation signal.
- +
- +These properties are for adjusting the GPC PGC CPU power up/down setting, if there is no such property in dts, then default
- +value in GPC PGC registers will be used.
- +
- +
- +Example:
- +
- + &gpc {
- + fsl,cpu_pupscr_sw2iso = <0xf>;
- + fsl,cpu_pupscr_sw = <0xf>;
- + fsl,cpu_pdnscr_iso2sw = <0x1>;
- + fsl,cpu_pdnscr_iso = <0x1>;
- + };
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/arm/pmu.txt linux-3.14.35/Documentation/devicetree/bindings/arm/pmu.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/arm/pmu.txt 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/arm/pmu.txt 2015-03-08 14:27:37.461684502 -0500
- @@ -17,6 +17,9 @@
- "arm,arm1176-pmu"
- "arm,arm1136-pmu"
- - interrupts : 1 combined interrupt or 1 per core.
- +- cluster : a phandle to the cluster to which it belongs
- + If there are more than one cluster with same CPU type
- + then there should be separate PMU nodes per cluster.
-
- Example:
-
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/ata/ahci-platform.txt linux-3.14.35/Documentation/devicetree/bindings/ata/ahci-platform.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/ata/ahci-platform.txt 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/ata/ahci-platform.txt 2015-03-08 14:27:37.461684502 -0500
- @@ -4,12 +4,19 @@
- Each SATA controller should have its own node.
-
- Required properties:
- -- compatible : compatible list, contains "snps,spear-ahci"
- +- compatible : compatible list, contains "snps,spear-ahci",
- + "fsl,imx53-ahci" or "fsl,imx6q-ahci"
- - interrupts : <interrupt mapping for SATA IRQ>
- - reg : <registers mapping>
-
- Optional properties:
- - dma-coherent : Present if dma operations are coherent
- +- clocks : a list of phandle + clock specifier pairs
- +- target-supply : regulator for SATA target power
- +
- +"fsl,imx53-ahci", "fsl,imx6q-ahci" required properties:
- +- clocks : must contain the sata, sata_ref and ahb clocks
- +- clock-names : must contain "ahb" for the ahb clock
-
- Example:
- sata@ffe08000 {
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/clock/imx6q-clock.txt linux-3.14.35/Documentation/devicetree/bindings/clock/imx6q-clock.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/clock/imx6q-clock.txt 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/clock/imx6q-clock.txt 2015-03-08 14:27:37.465684502 -0500
- @@ -89,8 +89,6 @@
- gpu3d_shader 74
- ipu1_podf 75
- ipu2_podf 76
- - ldb_di0_podf 77
- - ldb_di1_podf 78
- ipu1_di0_pre 79
- ipu1_di1_pre 80
- ipu2_di0_pre 81
- @@ -220,6 +218,20 @@
- lvds2_sel 205
- lvds1_gate 206
- lvds2_gate 207
- + gpt_3m 208
- + video_27m 209
- + ldb_di0_div_7 210
- + ldb_di1_div_7 211
- + ldb_di0_div_sel 212
- + ldb_di1_div_sel 213
- + caam_mem 214
- + caam_aclk 215
- + caam_ipg 216
- + epit1 217
- + epit2 218
- + tzasc2 219
- + lvds1_in 220
- + lvds1_out 221
-
- Examples:
-
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt linux-3.14.35/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt 2015-03-08 14:27:37.465684502 -0500
- @@ -47,6 +47,7 @@
- 20 ASRC
- 21 ESAI
- 22 SSI Dual FIFO (needs firmware ver >= 2)
- + 23 HDMI Audio
-
- The third cell specifies the transfer priority as below.
-
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/fb/fsl_ipuv3_fb.txt linux-3.14.35/Documentation/devicetree/bindings/fb/fsl_ipuv3_fb.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/fb/fsl_ipuv3_fb.txt 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/fb/fsl_ipuv3_fb.txt 2015-03-08 14:27:37.465684502 -0500
- @@ -0,0 +1,146 @@
- +* FSL IPUv3 Display/FB
- +
- +The FSL IPUv3 is Image Processing Unit version 3, a part of video and graphics
- +subsystem in an application processor. The goal of the IPU is to provide
- +comprehensive support for the flow of data from an image sensor or/and to a
- +display device.
- +
- +Two IPU units are on the imx6q SOC while only one IPU unit on the imx6dl SOC.
- +Each IPU unit has two display interfaces.
- +
- +For LDB/LVDS panel, there are two LVDS channels(LVDS0 and LVDS1) which can
- +transfer video data, these two channels can be used as
- +split/dual/single/separate mode.
- +-split mode means display data from DI0 or DI1 will send to both channels
- + LVDS0+LVDS1.
- +-dual mode means display data from DI0 or DI1 will be duplicated on LVDS0
- + and LVDS1, it said, LVDS0 and LVDS1 has the same content.
- +-single mode means only work for DI0/DI1->LVDS0 or DI0/DI1->LVDS1.
- +-separate mode means you can make DI0/DI1->LVDS0 and DI0/DI1->LVDS1 work
- + at the same time.
- + "ldb=spl0/1" -- split mode on DI0/1
- + "ldb=dul0/1" -- dual mode on DI0/1
- + "ldb=sin0/1" -- single mode on LVDS0/1
- + "ldb=sep0/1" -- separate mode begin from LVDS0/1
- +
- +Required properties for IPU:
- +- bypass_reset :Bypass reset to avoid display channel being.
- + stopped by probe since it may start to work in bootloader: 0 or 1.
- +- compatible : should be "fsl,imx6q-ipu".
- +- reg : the register address range.
- +- interrupts : the error and sync interrupts request.
- +- clocks : the clock sources that it depends on.
- +- clock-names: the related clock names.
- +- resets : IPU reset specifier. See reset.txt and fsl,imx-src.txt in
- + Documentation/devicetree/bindings/reset/ for details.
- +
- +Required properties for fb:
- +- compatible : should be "fsl,mxc_sdc_fb".
- +- disp_dev : display device: "ldb", "lcd", "hdmi", "mipi_dsi".
- +- mode_str : video mode string: "LDB-XGA" or "LDB-1080P60" for ldb,
- + "CLAA-WVGA" for lcd, "TRULY-WVGA" for TRULY mipi_dsi lcd panel,
- + "1920x1080M@60" for hdmi.
- +- default_bpp : default bits per pixel: 8/16/24/32
- +- int_clk : use internal clock as pixel clock: 0 or 1
- +- late_init : to avoid display channel being re-initialized
- + as we've probably setup the channel in bootloader: 0 or 1
- +- interface_pix_fmt : display interface pixel format as below:
- + RGB666 IPU_PIX_FMT_RGB666
- + RGB565 IPU_PIX_FMT_RGB565
- + RGB24 IPU_PIX_FMT_RGB24
- + BGR24 IPU_PIX_FMT_BGR24
- + GBR24 IPU_PIX_FMT_GBR24
- + YUV444 IPU_PIX_FMT_YUV444
- + LVDS666 IPU_PIX_FMT_LVDS666
- + YUYV IPU_PIX_FMT_YUYV
- + UYVY IPU_PIX_FMT_UYVY
- + YVYV IPU_PIX_FMT_YVYU
- + VYUY IPU_PIX_FMT_VYUY
- +
- +Required properties for display:
- +- compatible : should be "fsl,lcd" for lcd panel, "fsl,imx6q-ldb" for ldb
- +- reg : the register address range if necessary to have.
- +- interrupts : the error and sync interrupts if necessary to have.
- +- clocks : the clock sources that it depends on if necessary to have.
- +- clock-names: the related clock names if necessary to have.
- +- ipu_id : ipu id for the first display device: 0 or 1
- +- disp_id : display interface id for the first display interface: 0 or 1
- +- default_ifmt : save as above display interface pixel format for lcd
- +- pinctrl-names : should be "default"
- +- pinctrl-0 : should be pinctrl_ipu1_1 or pinctrl_ipu2_1, which depends on the
- + IPU connected.
- +- sec_ipu_id : secondary ipu id for the second display device(ldb only): 0 or 1
- +- sec_disp_id : secondary display interface id for the second display
- + device(ldb only): 0 or 1
- +- ext_ref : reference resistor select for ldb only: 0 or 1
- +- mode : ldb mode as below:
- + spl0 LDB_SPL_DI0
- + spl1 LDB_SPL_DI1
- + dul0 LDB_DUL_DI0
- + dul1 LDB_DUL_DI1
- + sin0 LDB_SIN0
- + sin1 LDB_SIN1
- + sep0 LDB_SEP0
- + sep1 LDB_SEP1
- +- gpr : the mux controller for the display engine's display interfaces and the display encoder
- + (only valid for mipi dsi now).
- +- disp-power-on-supply : the regulator to control display panel's power.
- + (only valid for mipi dsi now).
- +- resets : the gpio pin to reset the display device(only valid for mipi display panel now).
- +- lcd_panel : the video mode name for the display device(only valid for mipi display panel now).
- +- dev_id : the display engine's identity within the system, which intends to replace ipu_id
- + (only valid for mipi dsi now).
- +
- +Example for IPU:
- + ipu1: ipu@02400000 {
- + compatible = "fsl,imx6q-ipu";
- + reg = <0x02400000 0x400000>;
- + interrupts = <0 6 0x4 0 5 0x4>;
- + clocks = <&clks 130>, <&clks 131>, <&clks 132>,
- + <&clks 39>, <&clks 40>,
- + <&clks 135>, <&clks 136>;
- + clock-names = "bus", "di0", "di1",
- + "di0_sel", "di1_sel",
- + "ldb_di0", "ldb_di1";
- + resets = <&src 2>;
- + bypass_reset = <0>;
- + };
- +
- +Example for fb:
- + fb0 {
- + compatible = "fsl,mxc_sdc_fb";
- + disp_dev = "ldb";
- + interface_pix_fmt = "RGB666";
- + mode_str ="LDB-XGA";
- + default_bpp = <16>;
- + int_clk = <0>;
- + late_init = <0>;
- + status = "okay";
- + };
- +
- +Example for ldb display:
- + ldb@020e0000 {
- + ipu_id = <1>;
- + disp_id = <0>;
- + ext_ref = <1>;
- + mode = "sep0";
- + sec_ipu_id = <1>;
- + sec_disp_id = <1>;
- + status = "okay";
- + };
- +
- +Example for mipi dsi display:
- + mipi_dsi: mipi@021e0000 {
- + compatible = "fsl,imx6q-mipi-dsi";
- + reg = <0x021e0000 0x4000>;
- + interrupts = <0 102 0x04>;
- + gpr = <&gpr>;
- + clocks = <&clks 138>, <&clks 204>;
- + clock-names = "mipi_pllref_clk", "mipi_cfg_clk";
- + dev_id = <0>;
- + disp_id = <0>;
- + lcd_panel = "TRULY-WVGA";
- + disp-power-on-supply = <®_mipi_dsi_pwr_on>
- + resets = <&mipi_dsi_reset>;
- + status = "okay";
- + };
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/leds/leds-pwm.txt linux-3.14.35/Documentation/devicetree/bindings/leds/leds-pwm.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/leds/leds-pwm.txt 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/leds/leds-pwm.txt 2015-03-08 14:27:37.465684502 -0500
- @@ -13,6 +13,8 @@
- For the pwms and pwm-names property please refer to:
- Documentation/devicetree/bindings/pwm/pwm.txt
- - max-brightness : Maximum brightness possible for the LED
- +- active-low : (optional) For PWMs where the LED is wired to supply
- + rather than ground.
- - label : (optional)
- see Documentation/devicetree/bindings/leds/common.txt
- - linux,default-trigger : (optional)
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/mailbox/mailbox.txt linux-3.14.35/Documentation/devicetree/bindings/mailbox/mailbox.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/mailbox/mailbox.txt 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/mailbox/mailbox.txt 2015-03-08 14:27:37.465684502 -0500
- @@ -0,0 +1,33 @@
- +* Generic Mailbox Controller and client driver bindings
- +
- +Generic binding to provide a way for Mailbox controller drivers to
- +assign appropriate mailbox channel to client drivers.
- +
- +* Mailbox Controller
- +
- +Required property:
- +- #mbox-cells: Must be at least 1. Number of cells in a mailbox
- + specifier.
- +
- +Example:
- + mailbox: mailbox {
- + ...
- + #mbox-cells = <1>;
- + };
- +
- +
- +* Mailbox Client
- +
- +Required property:
- +- mbox: List of phandle and mailbox channel specifier.
- +
- +- mbox-names: List of identifier strings for each mailbox channel
- + required by the client.
- +
- +Example:
- + pwr_cntrl: power {
- + ...
- + mbox-names = "pwr-ctrl", "rpc";
- + mbox = <&mailbox 0
- + &mailbox 1>;
- + };
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/mlb/mlb150.txt linux-3.14.35/Documentation/devicetree/bindings/mlb/mlb150.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/mlb/mlb150.txt 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/mlb/mlb150.txt 2015-03-08 14:27:37.465684502 -0500
- @@ -0,0 +1,22 @@
- +* Freescale Media Local Bus Host Controller (MLB) for i.MX6Q/DL
- +
- +The Media Local Bus Host Controller on Freescale i.MX family
- +provides an interface for MOST network.
- +
- +Required properties:
- +- compatible : Should be "fsl,<chip>-mlb150"
- +- reg : Should contain mlb registers location and length
- +- interrupts : Should contain mlb interrupt
- +- clocks: Should contain the mlb clock sources
- +- clock-names: Should be the names of mlb clock sources
- +- iram : phandle pointing to the SRAM device node
- +
- +Examples:
- +mlb@0218c000 {
- + compatible = "fsl,imx6q-mlb150";
- + reg = <0x0218c000 0x4000>;
- + interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>;
- + clocks = <&clks 139>, <&clks 175>;
- + clock-names = "mlb", "pll8_mlb";
- + iram = <&ocram>;
- +};
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/mmc/mmc.txt linux-3.14.35/Documentation/devicetree/bindings/mmc/mmc.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/mmc/mmc.txt 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/mmc/mmc.txt 2015-03-08 14:27:37.465684502 -0500
- @@ -5,6 +5,8 @@
- Interpreted by the OF core:
- - reg: Registers location and length.
- - interrupts: Interrupts used by the MMC controller.
- +- clocks: Clocks needed for the host controller, if any.
- +- clock-names: Goes with clocks above.
-
- Card detection:
- If no property below is supplied, host native card detect is used.
- @@ -30,6 +32,15 @@
- - cap-sdio-irq: enable SDIO IRQ signalling on this interface
- - full-pwr-cycle: full power cycle of the card is supported
-
- +Card power and reset control:
- +The following properties can be specified for cases where the MMC
- +peripheral needs additional reset, regulator and clock lines. It is for
- +example common for WiFi/BT adapters to have these separate from the main
- +MMC bus:
- + - card-reset-gpios: Specify GPIOs for card reset (reset active low)
- + - card-external-vcc-supply: Regulator to drive (independent) card VCC
- + - clock with name "card_ext_clock": External clock provided to the card
- +
- *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
- polarity properties, we have to fix the meaning of the "normal" and "inverted"
- line levels. We choose to follow the SDHCI standard, which specifies both those
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt linux-3.14.35/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt 2015-03-08 14:27:37.477684502 -0500
- @@ -71,6 +71,13 @@
- name for integer state ID 0, list entry 1 for state ID 1, and
- so on.
-
- +pinctrl-assert-gpios:
- + List of phandles, each pointing at a GPIO which is used by some
- + board design to steer pins between two peripherals on the board.
- + It plays like a board level pin multiplexer to choose different
- + functions for given pins by pulling up/down the GPIOs. See
- + bindings/gpio/gpio.txt for details of how to specify GPIO.
- +
- For example:
-
- /* For a client device requiring named states */
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/reset/gpio-reset.txt linux-3.14.35/Documentation/devicetree/bindings/reset/gpio-reset.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/reset/gpio-reset.txt 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/reset/gpio-reset.txt 2015-03-08 14:27:37.477684502 -0500
- @@ -0,0 +1,35 @@
- +GPIO reset controller
- +=====================
- +
- +A GPIO reset controller controls a single GPIO that is connected to the reset
- +pin of a peripheral IC. Please also refer to reset.txt in this directory for
- +common reset controller binding usage.
- +
- +Required properties:
- +- compatible: Should be "gpio-reset"
- +- reset-gpios: A gpio used as reset line. The gpio specifier for this property
- + depends on the gpio controller that provides the gpio.
- +- #reset-cells: 0, see below
- +
- +Optional properties:
- +- reset-delay-us: delay in microseconds. The gpio reset line will be asserted for
- + this duration to reset.
- +- initially-in-reset: boolean. If not set, the initial state should be a
- + deasserted reset line. If this property exists, the
- + reset line should be kept in reset.
- +
- +example:
- +
- +sii902x_reset: gpio-reset {
- + compatible = "gpio-reset";
- + reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
- + reset-delay-us = <10000>;
- + initially-in-reset;
- + #reset-cells = <0>;
- +};
- +
- +/* Device with nRESET pin connected to GPIO5_0 */
- +sii902x@39 {
- + /* ... */
- + resets = <&sii902x_reset>; /* active-low GPIO5_0, 10 ms delay */
- +};
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/sound/cs42888.txt linux-3.14.35/Documentation/devicetree/bindings/sound/cs42888.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/sound/cs42888.txt 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/sound/cs42888.txt 2015-03-08 14:27:37.489684502 -0500
- @@ -0,0 +1,29 @@
- +CS42888 audio CODEC
- +
- +This device supports I2C only.
- +
- +Required properties:
- +
- + - compatible: "cirrus,cs42888"
- + - reg: the I2C address of the device.
- + - clocks: Phandle to the clock node.
- + - clock-names: Contains name for each entry in clocks.
- + "codec_osc" : the external oscillator.
- + "esai" : the hckt clock from esai.
- + - <name>-supply: Phandle to the regulator <name>.
- +
- +Note: cs42888 needs a regulators node and a clocks node.
- +
- +Example:
- +In this case, the clock is external oscillator.
- +
- +codec: cs42888@48 {
- + compatible = "cirrus,cs42888";
- + reg = <0x048>;
- + clocks = <&codec_osc 0>;
- + clock-names = "codec_osc";
- + VA-supply = <®_audio>;
- + VD-supply = <®_audio>;
- + VLS-supply = <®_audio>;
- + VLC-supply = <®_audio>;
- +};
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/sound/fsl-asrc-p2p.txt linux-3.14.35/Documentation/devicetree/bindings/sound/fsl-asrc-p2p.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/sound/fsl-asrc-p2p.txt 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/sound/fsl-asrc-p2p.txt 2015-03-08 14:27:37.489684502 -0500
- @@ -0,0 +1,23 @@
- +* Freescale Asynchronous Sample Rate Converter (ASRC)
- +
- +This document is for asrc p2p node. p2p is one of asrc mode. asrc p2p depend on
- +MXC_ASRC.
- +
- +Required properties:
- + - compatible: Should be "fsl,<chip>-asrc-p2p".
- + - fsl,output-rate: the output rate of asrc p2p. which can be <32000> to <192000>,
- + - fsl,output-width: the output width of asrc p2p. which can be <16>, <24>.
- + - fsl,asrc-dma-rx-events: The rx dma event of the asrc, <a b c> corresponding
- + to 3 pair of asrc.
- + - fsl,asrc-dma-tx-events: The tx dma event of the esai, <a b c> corresponding
- + to 3 pair of asrc.
- +
- +Example:
- +asrc_p2p: asrc_p2p {
- + compatible = "fsl,imx6q-asrc-p2p";
- + fsl,output-rate = <48000>;
- + fsl,output-width = <16>;
- + fsl,asrc-dma-rx-events = <17 18 19>;
- + fsl,asrc-dma-tx-events = <20 21 22>;
- + status = "okay";
- +};
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/sound/imx-audio-cs42888.txt linux-3.14.35/Documentation/devicetree/bindings/sound/imx-audio-cs42888.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/sound/imx-audio-cs42888.txt 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/sound/imx-audio-cs42888.txt 2015-03-08 14:27:37.489684502 -0500
- @@ -0,0 +1,25 @@
- +Freescale i.MX audio complex with CS42888 codec
- +
- +Required properties:
- +- compatible : "fsl,imx-audio-cs42888"
- +- model : The user-visible name of this sound complex
- +- esai-controller : The phandle of the i.MX SSI controller
- +- audio-codec : The phandle of the CS42888 audio codec
- +
- +Optional properties:
- +- asrc-controller : The phandle of the i.MX ASRC controller
- +- audio-routing : A list of the connections between audio components.
- + Each entry is a pair of strings, the first being the connection's sink,
- + the second being the connection's source. Valid names could be power
- + supplies, CS42888 pins, and the jacks on the board:
- +
- +Example:
- +
- +sound {
- + compatible = "fsl,imx6q-sabresd-wm8962",
- + "fsl,imx-audio-wm8962";
- + model = "cs42888-audio";
- + esai-controller = <&esai>;
- + asrc-controller = <&asrc_p2p>;
- + audio-codec = <&codec>;
- +};
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt linux-3.14.35/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt 2015-03-08 14:27:37.489684502 -0500
- @@ -24,6 +24,12 @@
- Note: The AUDMUX port numbering should start at 1, which is consistent with
- hardware manual.
-
- +Optional properties:
- +- hp-det-gpios : The gpio pin to detect plug in/out event that happens to
- + Headphone jack.
- +- mic-det-gpios: The gpio pin to detect plug in/out event that happens to
- + Microphone jack.
- +
- Example:
-
- sound {
- @@ -43,4 +49,6 @@
- "DMICDAT", "DMIC";
- mux-int-port = <2>;
- mux-ext-port = <3>;
- + hp-det-gpios = <&gpio7 8 1>;
- + mic-det-gpios = <&gpio1 9 1>;
- };
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/sound/wm8962.txt linux-3.14.35/Documentation/devicetree/bindings/sound/wm8962.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/sound/wm8962.txt 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/sound/wm8962.txt 2015-03-08 14:27:37.493684502 -0500
- @@ -13,6 +13,14 @@
- of R51 (Class D Control 2) gets set, indicating that the speaker is
- in mono mode.
-
- + - amic-mono: This is a boolean property. If present, indicating that the
- + analog micphone is hardware mono input, the driver would enable monomix
- + for it.
- +
- + - dmic-mono: This is a boolean property. If present, indicating that the
- + digital micphone is hardware mono input, the driver would enable monomix
- + for it.
- +
- - mic-cfg : Default register value for R48 (Additional Control 4).
- If absent, the default should be the register default.
-
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/usb/mxs-phy.txt linux-3.14.35/Documentation/devicetree/bindings/usb/mxs-phy.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/usb/mxs-phy.txt 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/usb/mxs-phy.txt 2015-03-08 14:27:37.493684502 -0500
- @@ -1,13 +1,16 @@
- * Freescale MXS USB Phy Device
-
- Required properties:
- -- compatible: Should be "fsl,imx23-usbphy"
- +- compatible: "fsl,imx23-usbphy" for imx23 and imx28, "fsl,imx6q-usbphy"
- +for imx6dq and imx6dl, "fsl,imx6sl-usbphy" for imx6sl
- - reg: Should contain registers location and length
- - interrupts: Should contain phy interrupt
- +- fsl,anatop: phandle for anatop register, it is only for imx6 SoC series
-
- Example:
- usbphy1: usbphy@020c9000 {
- compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
- reg = <0x020c9000 0x1000>;
- interrupts = <0 44 0x04>;
- + fsl,anatop = <&anatop>;
- };
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/video/fsl,csi-v4l2-capture.txt linux-3.14.35/Documentation/devicetree/bindings/video/fsl,csi-v4l2-capture.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/video/fsl,csi-v4l2-capture.txt 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/video/fsl,csi-v4l2-capture.txt 2015-03-08 14:27:37.493684502 -0500
- @@ -0,0 +1,61 @@
- +* Freescale CMOS Sensor Interface (CSI) V4L2 Capture
- +
- +Required properties for CSI
- +- compatible: "fsl,<soc>-csi". Supported chip includes imx6sl
- +- reg: Address and length of the register set for CSI
- +- interrupts: Should contain CSI interrupts
- +
- +Required properties for v4l2_capture
- +- compatible: should be "fsl,<soc>-csi-v4l2", supported socs include imx6sl
- +
- +Required properties for sensor
- +- compatible: "<vendor>,<sensor>"
- + please check the supported sensor in the Supported Sensor fields.
- +- reg: sensor I2C slave address
- +- pinctrl-names: should be "default" for parallel sensor
- +- pinctrl-0: should depend on the connection between sensor and i.MX
- + connection between sensor and i.MX could be only legacy parallel on i.MX6SL
- +- clocks: should be the clock source provided to sensor.
- +- clock-names: should be "csi_mclk"
- +- AVDD-supply: set according to the board.
- +- DVDD-supply: set according to the board.
- +- pwn-gpios: set according to the board.
- +- rst-gpios: set according to the board.
- +- csi_id: csi id for v4l2 capture device
- + should be 0 for i.MX6SL
- +- mclk: should the value of mclk clock send out the sensor. unit is Hz.
- +- mclk_source: should be 0 for i.MX6SL
- +
- +Supported Sensor
- +- ovti, ov5640
- +
- +Example for CSI:
- + csi: csi@020e4000 {
- + compatible = "fsl,imx6sl-csi";
- + reg = <0x020e4000 0x4000>;
- + interrupts = <0 7 0x04>;
- + status = "disabled";
- + };
- +
- +Examples for v4l2_capture:
- + csi_v4l2_cap {
- + compatible = "fsl,imx6q-v4l2-capture";
- + status = "okay";
- + };
- +
- +Examples for sensors:
- + ov564x: ov564x@3c {
- + compatible = "ovti,ov564x";
- + reg = <0x3c>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_csi_0>;
- + clocks = <&clks IMX6SL_CLK_CSI>;
- + clock-names = "csi_mclk";
- + AVDD-supply = <&vgen6_reg>; /* 2.8v */
- + DVDD-supply = <&vgen2_reg>; /* 1.5v*/
- + pwn-gpios = <&gpio1 25 1>;
- + rst-gpios = <&gpio1 26 0>;
- + csi_id = <0>;
- + mclk = <24000000>;
- + mclk_source = <0>;
- + };
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/video/fsl,mipi-csi2.txt linux-3.14.35/Documentation/devicetree/bindings/video/fsl,mipi-csi2.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/video/fsl,mipi-csi2.txt 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/video/fsl,mipi-csi2.txt 2015-03-08 14:27:37.493684502 -0500
- @@ -0,0 +1,42 @@
- +* Freescale MIPI CSI2 Controller for i.MX6DQ/i.MX6SDL
- +
- +Required properties for mipi csi2 controller:
- +- compatible: should be "fsl,imx6q-mipi-csi2"
- +- reg: <base addr, range> contains mipi csi2 register base address and range
- +- interrupts: <type num flag> where type is a interrupt type, num is the
- + interrupt number and flag is a field that level/trigger information for
- + the interrupt.
- +- clocks: the clock sources that mipi csi2 depends on.
- +- clock-names: the name is related to the clock source one by one.
- +- status: should be set to "disable".
- +
- +Required properties for mipi csi2 on specified board:
- +- ipu_id: ipu id which mipi csi2 connected to.
- + should be 0 or 1 for i.MX6DQ; should be 0 for i.MX6SDL
- +- csi_id: csi id which mipi csi2 connected to.
- + should be 0 or 1 for i.MX6DQ/i.MX6SDL
- +- v_channel: virtual channel which send to MIPI CSI2 controller
- + should keep consistent with the input MIPI signal.
- +- lanes: data lanes of input MIPI signal. The maximum data lanes is 4.
- + should keep consistent with the input MIPI signal.
- +- status: should be set to "okay".
- +
- +Examples:
- +for SOC imx6qdl.dtsi:
- + mipi_csi@021dc000 {
- + compatible = "fsl,imx6q-mipi-csi2";
- + reg = <0x021dc000 0x4000>;
- + interrupts = <0 100 0x04>, <0 101 0x04>;
- + clocks = <&clks 138>, <&clks 53>, <&clks 204>;
- + clock-names = "dphy_clk", "pixel_clk", "cfg_clk";
- + status = "disabled";
- + };
- +
- +for board imx6qdl-sabresd.dtsi:
- + mipi_csi@021dc000 {
- + status = "okay";
- + ipu_id = <0>;
- + csi_id = <1>;
- + v_channel = <0>;
- + lanes = <2>;
- + };
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/video/fsl,pxp.txt linux-3.14.35/Documentation/devicetree/bindings/video/fsl,pxp.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/video/fsl,pxp.txt 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/video/fsl,pxp.txt 2015-03-08 14:27:37.493684502 -0500
- @@ -0,0 +1,30 @@
- +* Freescale PxP Controller for i.MX6DL, i.MX6SL
- +
- +Required properties for PxP controller:
- +- compatible: should be "fsl,<soc>-pxp-dma"
- +- reg: <base addr, range> contains pxp register base address and range
- +- interrupts: <type num flag> where type is an interrupt type, num is the
- + interrupt number and flag is a field that level/trigger information for
- + the interrupt.
- +- clocks: the clock sources that pxp depends on.
- +- clock-names: the name is related to the clock source
- +
- +Required properties for pxp on specified board:
- +- status: should be set to "okay" if want to use PxP
- +
- +Examples:
- +for SOC imx6dl.dtsi:
- + pxp@020f0000 {
- + compatible = "fsl,imx6dl-pxp-dma";
- + reg = <0x020f0000 0x4000>;
- + interrupts = <0 98 0x04>;
- + clocks = <&clks 133>;
- + clock-names = "pxp-axi";
- + status = "disabled";
- + };
- +
- +
- +for board imx6dl-sabresd.dts:
- + &pxp {
- + status = "okay";
- + };
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/video/fsl,v4l2-capture.txt linux-3.14.35/Documentation/devicetree/bindings/video/fsl,v4l2-capture.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/video/fsl,v4l2-capture.txt 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/video/fsl,v4l2-capture.txt 2015-03-08 14:27:37.493684502 -0500
- @@ -0,0 +1,102 @@
- +* Freescale V4L2 Capture for i.MX6DQ/i.MX6SDL
- +
- +Required board properties for IPUv3 capture:
- +- clocks: should include the clock provided by i.MX6 to sensor
- +- clock-names: sensor clock's name should be "ipux_csiy"
- + x should be 1 or 2 for i.MX6DQ; should be 1 for i.MX6SDL
- + y is 0 or 1 for i.MX6DQ/i.MX6SDL
- +Note: other detailed information for IPUv3, please refer to
- +Documentation/devicetree/bindings/fb/fsl_ipuv3_fb.txt
- +
- +Required properties for v4l2_capture
- +- compatible: should be "fsl,imx6q-v4l2-capture"
- +- ipu_id: ipu id for v4l2 capture device
- + should be 0 or 1 for i.MX6DQ; should be 0 for i.MX6SDL
- +- csi_id: csi id for v4l2 capture device
- + should be 0 or 1 for i.MX6DQ/i.MX6SDL
- +- mclk_source: should be 0 or 1. two mclk sources at most now
- +- status: should be set to "okay" to enable this device
- +
- +Required properties for sensor
- +- compatible: "<vendor>,<sensor>"
- + please check the supported sensor in the Supported Sensor fields.
- +- reg: sensor I2C slave address
- +- pinctrl-names: should be "default" for parallel sensor
- +- pinctrl-0: should depend on the connection between sensor and i.MX
- + connection between sensor and i.MX could be MIPI-CSI2 or legacy parallel
- +- clocks: should be the clock source provided to sensor.
- +- clock-names: should be "csi_mclk"
- +- DOVDD-supply: set according to the board.
- +- AVDD-supply: set according to the board.
- +- DVDD-supply: set according to the board.
- +- pwn-gpios: set according to the board.
- +- rst-gpios: set according to the board.
- +- csi_id: csi id for v4l2 capture device
- + should be 0 or 1 for i.MX6DQ/i.MX6SDL.
- +- mclk: should the value of mclk clock send out the sensor. unit is Hz.
- +- mclk_source: should be 0 or 1 and should be the same as the setting in
- + v4l2_capture.
- +- cvbs: 1 for CVBS input, 0 YPbPr input. This property is only needed for
- + adv7180 tv decoder.
- +
- +Supported Sensor
- +- ov5640
- +- ov5642
- +- ov5640_mipi
- +- adv7180
- +
- +
- +Example for IPUv3 including capture settings on imx6q-sabresd.dts:
- + ipu1: ipu@02400000 { /* IPU1 */
- + compatible = "fsl,imx6q-ipuv3";
- + reg = <0x02400000 0x400000>;
- + interrupts = <0 5 0x04>, < 0 6 0x04>;
- + clocks = <&clks 130>, <&clks 131>, <&clks 132>, <&clks 39>, <&clks 40>, <&clks 169>;
- + clock-names = "ipu1", "ipu1_di0", "ipu1_di1", "ipu1_di0_sel", "ipu1_di1_sel", "ipu1_csi0";
- + status = "disabled";
- + };
- +
- +Examples for v4l2_capture:
- + v4l2_cap {
- + compatible = "fsl,imx6q-v4l2-capture";
- + ipu_id = <0>;
- + csi_id = <0>;
- + mclk_source = <0>;
- + status = "okay";
- + };
- +
- +Examples for sensors:
- + ov5642: ov5642@3c {
- + compatible = "ovti,ov5642";
- + reg = <0x3c>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_ipu1_2>;
- + clocks = <&clks 201>;
- + clock-names = "csi_mclk";
- + DOVDD-supply = <&vgen4_reg>; /* 1.8v */
- + AVDD-supply = <&vgen3_reg>; /* 2.8v, on rev C board is VGEN3 */
- + DVDD-supply = <&vgen2_reg>; /* 1.5v*/
- + pwn-gpios = <&gpio1 16 1>; /* active low: SD1_DAT0 */
- + rst-gpios = <&gpio1 17 0>; /* active high: SD1_DAT1 */
- + csi_id = <0>;
- + mclk = <24000000>;
- + mclk_source = <0>;
- + };
- +
- + adv7180: adv7180@21 {
- + compatible = "adv,adv7180";
- + reg = <0x21>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_ipu1_3>;
- + clocks = <&clks 201>;
- + clock-names = "csi_mclk";
- + DOVDD-supply = <®_3p3v>; /* 3.3v, enabled via 2.8 VGEN6 */
- + AVDD-supply = <®_3p3v>; /* 1.8v */
- + DVDD-supply = <®_3p3v>; /* 1.8v */
- + PVDD-supply = <®_3p3v>; /* 1.8v */
- + pwn-gpios = <&max7310_b 2 0>;
- + csi_id = <0>;
- + mclk = <24000000>;
- + mclk_source = <0>;
- + cvbs = <1>;
- + };
- diff -Nur linux-3.14.35.orig/Documentation/devicetree/bindings/video/mxc_hdmi_video.txt linux-3.14.35/Documentation/devicetree/bindings/video/mxc_hdmi_video.txt
- --- linux-3.14.35.orig/Documentation/devicetree/bindings/video/mxc_hdmi_video.txt 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/Documentation/devicetree/bindings/video/mxc_hdmi_video.txt 2015-03-08 14:27:37.493684502 -0500
- @@ -0,0 +1,20 @@
- +Device-Tree bindings for hdmi video driver
- +
- +Required properties:
- +- compatible: value should be "fsl,imx6q-hdmi-video".
- +- fsl,hdcp: define the property in dts, hdmi driver will initalize for hdcp,
- + otherwise hdcp function will not supported.
- +- fsl,phy_reg_vlev: hdmi phy register,Voltage Level Control Register offset 0x0e,
- + adjust hdmi phy signal voltage level.
- +- fsl,phy_reg_cksymtx: hdmi phy register, clock symbol and transmitter control
- + register offset 0x09, adjust hdmi signal pre-emphasis.
- +
- +Example:
- +
- + hdmi_video {
- + compatible = "fsl,imx6q-hdmi-video";
- + fsl,hdcp;
- + fsl,phy_reg_vlev = <0x0294>;
- + fsl,phy_reg_cksymtx = <0x800d>;
- + };
- +
- diff -Nur linux-3.14.35.orig/Documentation/filesystems/hfsplus.txt linux-3.14.35/Documentation/filesystems/hfsplus.txt
- --- linux-3.14.35.orig/Documentation/filesystems/hfsplus.txt 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/Documentation/filesystems/hfsplus.txt 2015-03-08 14:27:37.493684502 -0500
- @@ -56,4 +56,4 @@
-
- kernel source: <file:fs/hfsplus>
-
- -Apple Technote 1150 http://developer.apple.com/technotes/tn/tn1150.html
- +Apple Technote 1150 https://developer.apple.com/legacy/library/technotes/tn/tn1150.html
- diff -Nur linux-3.14.35.orig/Documentation/kernel-parameters.txt linux-3.14.35/Documentation/kernel-parameters.txt
- --- linux-3.14.35.orig/Documentation/kernel-parameters.txt 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/Documentation/kernel-parameters.txt 2015-03-08 14:27:37.497684502 -0500
- @@ -603,8 +603,11 @@
- Also note the kernel might malfunction if you disable
- some critical bits.
-
- - cma=nn[MG] [ARM,KNL]
- - Sets the size of kernel global memory area for contiguous
- + cma=nn[MG]@[start[MG][-end[MG]]]
- + [ARM,X86,KNL]
- + Sets the size of kernel global memory area for
- + contiguous memory allocations and optionally the
- + placement constraint by the physical address range of
- memory allocations. For more information, see
- include/linux/dma-contiguous.h
-
- diff -Nur linux-3.14.35.orig/Documentation/networking/gianfar.txt linux-3.14.35/Documentation/networking/gianfar.txt
- --- linux-3.14.35.orig/Documentation/networking/gianfar.txt 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/Documentation/networking/gianfar.txt 2015-03-08 14:27:37.497684502 -0500
- @@ -1,38 +1,8 @@
- The Gianfar Ethernet Driver
- -Sysfs File description
-
- Author: Andy Fleming <afleming@freescale.com>
- Updated: 2005-07-28
-
- -SYSFS
- -
- -Several of the features of the gianfar driver are controlled
- -through sysfs files. These are:
- -
- -bd_stash:
- -To stash RX Buffer Descriptors in the L2, echo 'on' or '1' to
- -bd_stash, echo 'off' or '0' to disable
- -
- -rx_stash_len:
- -To stash the first n bytes of the packet in L2, echo the number
- -of bytes to buf_stash_len. echo 0 to disable.
- -
- -WARNING: You could really screw these up if you set them too low or high!
- -fifo_threshold:
- -To change the number of bytes the controller needs in the
- -fifo before it starts transmission, echo the number of bytes to
- -fifo_thresh. Range should be 0-511.
- -
- -fifo_starve:
- -When the FIFO has less than this many bytes during a transmit, it
- -enters starve mode, and increases the priority of TX memory
- -transactions. To change, echo the number of bytes to
- -fifo_starve. Range should be 0-511.
- -
- -fifo_starve_off:
- -Once in starve mode, the FIFO remains there until it has this
- -many bytes. To change, echo the number of bytes to
- -fifo_starve_off. Range should be 0-511.
-
- CHECKSUM OFFLOADING
-
- diff -Nur linux-3.14.35.orig/drivers/ata/acard-ahci.c linux-3.14.35/drivers/ata/acard-ahci.c
- --- linux-3.14.35.orig/drivers/ata/acard-ahci.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/acard-ahci.c 2015-03-08 14:27:37.497684502 -0500
- @@ -36,7 +36,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/ahci.c linux-3.14.35/drivers/ata/ahci.c
- --- linux-3.14.35.orig/drivers/ata/ahci.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/ahci.c 2015-03-08 14:27:37.501684502 -0500
- @@ -35,7 +35,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- @@ -610,6 +609,7 @@
- unsigned long deadline)
- {
- struct ata_port *ap = link->ap;
- + struct ahci_host_priv *hpriv = ap->host->private_data;
- bool online;
- int rc;
-
- @@ -620,7 +620,7 @@
- rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
- deadline, &online, NULL);
-
- - ahci_start_engine(ap);
- + hpriv->start_engine(ap);
-
- DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
-
- @@ -635,6 +635,7 @@
- {
- struct ata_port *ap = link->ap;
- struct ahci_port_priv *pp = ap->private_data;
- + struct ahci_host_priv *hpriv = ap->host->private_data;
- u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
- struct ata_taskfile tf;
- bool online;
- @@ -650,7 +651,7 @@
- rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
- deadline, &online, NULL);
-
- - ahci_start_engine(ap);
- + hpriv->start_engine(ap);
-
- /* The pseudo configuration device on SIMG4726 attached to
- * ASUS P5W-DH Deluxe doesn't send signature FIS after
- @@ -1146,6 +1147,17 @@
- return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
- }
-
- +static bool ahci_broken_devslp(struct pci_dev *pdev)
- +{
- + /* device with broken DEVSLP but still showing SDS capability */
- + static const struct pci_device_id ids[] = {
- + { PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */
- + {}
- + };
- +
- + return pci_match_id(ids, pdev);
- +}
- +
- #ifdef CONFIG_ATA_ACPI
- static void ahci_gtf_filter_workaround(struct ata_host *host)
- {
- @@ -1397,6 +1409,10 @@
-
- hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
-
- + /* must set flag prior to save config in order to take effect */
- + if (ahci_broken_devslp(pdev))
- + hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
- +
- /* save initial config */
- ahci_pci_save_initial_config(pdev, hpriv);
-
- diff -Nur linux-3.14.35.orig/drivers/ata/ahci.h linux-3.14.35/drivers/ata/ahci.h
- --- linux-3.14.35.orig/drivers/ata/ahci.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/ahci.h 2015-03-08 14:27:37.501684502 -0500
- @@ -37,6 +37,8 @@
-
- #include <linux/clk.h>
- #include <linux/libata.h>
- +#include <linux/phy/phy.h>
- +#include <linux/regulator/consumer.h>
-
- /* Enclosure Management Control */
- #define EM_CTRL_MSG_TYPE 0x000f0000
- @@ -51,6 +53,7 @@
-
- enum {
- AHCI_MAX_PORTS = 32,
- + AHCI_MAX_CLKS = 3,
- AHCI_MAX_SG = 168, /* hardware max is 64K */
- AHCI_DMA_BOUNDARY = 0xffffffff,
- AHCI_MAX_CMDS = 32,
- @@ -233,6 +236,8 @@
- port start (wait until
- error-handling stage) */
- AHCI_HFLAG_MULTI_MSI = (1 << 16), /* multiple PCI MSIs */
- + AHCI_HFLAG_NO_DEVSLP = (1 << 17), /* no device sleep */
- + AHCI_HFLAG_NO_FBS = (1 << 18), /* no FBS */
-
- /* ap->flags bits */
-
- @@ -322,8 +327,17 @@
- u32 em_loc; /* enclosure management location */
- u32 em_buf_sz; /* EM buffer size in byte */
- u32 em_msg_type; /* EM message type */
- - struct clk *clk; /* Only for platforms supporting clk */
- + bool got_runtime_pm; /* Did we do pm_runtime_get? */
- + struct clk *clks[AHCI_MAX_CLKS]; /* Optional */
- + struct regulator *target_pwr; /* Optional */
- + struct phy *phy; /* If platform uses phy */
- void *plat_data; /* Other platform data */
- + /*
- + * Optional ahci_start_engine override, if not set this gets set to the
- + * default ahci_start_engine during ahci_save_initial_config, this can
- + * be overridden anytime before the host is activated.
- + */
- + void (*start_engine)(struct ata_port *ap);
- };
-
- extern int ahci_ignore_sss;
- diff -Nur linux-3.14.35.orig/drivers/ata/ahci_imx.c linux-3.14.35/drivers/ata/ahci_imx.c
- --- linux-3.14.35.orig/drivers/ata/ahci_imx.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/ahci_imx.c 2015-03-08 14:27:37.505684502 -0500
- @@ -26,12 +26,29 @@
- #include <linux/mfd/syscon.h>
- #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
- #include <linux/libata.h>
- +#include <linux/busfreq-imx6.h>
- #include "ahci.h"
-
- enum {
- - PORT_PHY_CTL = 0x178, /* Port0 PHY Control */
- - PORT_PHY_CTL_PDDQ_LOC = 0x100000, /* PORT_PHY_CTL bits */
- - HOST_TIMER1MS = 0xe0, /* Timer 1-ms */
- + /* Timer 1-ms Register */
- + IMX_TIMER1MS = 0x00e0,
- + /* Port0 PHY Control Register */
- + IMX_P0PHYCR = 0x0178,
- + IMX_P0PHYCR_TEST_PDDQ = 1 << 20,
- + IMX_P0PHYCR_CR_READ = 1 << 19,
- + IMX_P0PHYCR_CR_WRITE = 1 << 18,
- + IMX_P0PHYCR_CR_CAP_DATA = 1 << 17,
- + IMX_P0PHYCR_CR_CAP_ADDR = 1 << 16,
- + /* Port0 PHY Status Register */
- + IMX_P0PHYSR = 0x017c,
- + IMX_P0PHYSR_CR_ACK = 1 << 18,
- + IMX_P0PHYSR_CR_DATA_OUT = 0xffff << 0,
- + /* Lane0 Output Status Register */
- + IMX_LANE0_OUT_STAT = 0x2003,
- + IMX_LANE0_OUT_STAT_RX_PLL_STATE = 1 << 1,
- + /* Clock Reset Register */
- + IMX_CLOCK_RESET = 0x7f3f,
- + IMX_CLOCK_RESET_RESET = 1 << 0,
- };
-
- enum ahci_imx_type {
- @@ -42,62 +59,230 @@
- struct imx_ahci_priv {
- struct platform_device *ahci_pdev;
- enum ahci_imx_type type;
- -
- - /* i.MX53 clock */
- - struct clk *sata_gate_clk;
- - /* Common clock */
- - struct clk *sata_ref_clk;
- struct clk *ahb_clk;
- -
- struct regmap *gpr;
- bool no_device;
- bool first_time;
- + u32 phy_params;
- };
-
- static int ahci_imx_hotplug;
- module_param_named(hotplug, ahci_imx_hotplug, int, 0644);
- MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)");
-
- -static int imx_sata_clock_enable(struct device *dev)
- +static void ahci_imx_host_stop(struct ata_host *host);
- +
- +static int imx_phy_crbit_assert(void __iomem *mmio, u32 bit, bool assert)
- +{
- + int timeout = 10;
- + u32 crval;
- + u32 srval;
- +
- + /* Assert or deassert the bit */
- + crval = readl(mmio + IMX_P0PHYCR);
- + if (assert)
- + crval |= bit;
- + else
- + crval &= ~bit;
- + writel(crval, mmio + IMX_P0PHYCR);
- +
- + /* Wait for the cr_ack signal */
- + do {
- + srval = readl(mmio + IMX_P0PHYSR);
- + if ((assert ? srval : ~srval) & IMX_P0PHYSR_CR_ACK)
- + break;
- + usleep_range(100, 200);
- + } while (--timeout);
- +
- + return timeout ? 0 : -ETIMEDOUT;
- +}
- +
- +static int imx_phy_reg_addressing(u16 addr, void __iomem *mmio)
- {
- - struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
- + u32 crval = addr;
- int ret;
-
- - if (imxpriv->type == AHCI_IMX53) {
- - ret = clk_prepare_enable(imxpriv->sata_gate_clk);
- - if (ret < 0) {
- - dev_err(dev, "prepare-enable sata_gate clock err:%d\n",
- - ret);
- - return ret;
- - }
- + /* Supply the address on cr_data_in */
- + writel(crval, mmio + IMX_P0PHYCR);
- +
- + /* Assert the cr_cap_addr signal */
- + ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_ADDR, true);
- + if (ret)
- + return ret;
- +
- + /* Deassert cr_cap_addr */
- + ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_ADDR, false);
- + if (ret)
- + return ret;
- +
- + return 0;
- +}
- +
- +static int imx_phy_reg_write(u16 val, void __iomem *mmio)
- +{
- + u32 crval = val;
- + int ret;
- +
- + /* Supply the data on cr_data_in */
- + writel(crval, mmio + IMX_P0PHYCR);
- +
- + /* Assert the cr_cap_data signal */
- + ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_DATA, true);
- + if (ret)
- + return ret;
- +
- + /* Deassert cr_cap_data */
- + ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_DATA, false);
- + if (ret)
- + return ret;
- +
- + if (val & IMX_CLOCK_RESET_RESET) {
- + /*
- + * In case we're resetting the phy, it's unable to acknowledge,
- + * so we return immediately here.
- + */
- + crval |= IMX_P0PHYCR_CR_WRITE;
- + writel(crval, mmio + IMX_P0PHYCR);
- + goto out;
- }
-
- - ret = clk_prepare_enable(imxpriv->sata_ref_clk);
- - if (ret < 0) {
- - dev_err(dev, "prepare-enable sata_ref clock err:%d\n",
- - ret);
- - goto clk_err;
- + /* Assert the cr_write signal */
- + ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_WRITE, true);
- + if (ret)
- + return ret;
- +
- + /* Deassert cr_write */
- + ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_WRITE, false);
- + if (ret)
- + return ret;
- +
- +out:
- + return 0;
- +}
- +
- +static int imx_phy_reg_read(u16 *val, void __iomem *mmio)
- +{
- + int ret;
- +
- + /* Assert the cr_read signal */
- + ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_READ, true);
- + if (ret)
- + return ret;
- +
- + /* Capture the data from cr_data_out[] */
- + *val = readl(mmio + IMX_P0PHYSR) & IMX_P0PHYSR_CR_DATA_OUT;
- +
- + /* Deassert cr_read */
- + ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_READ, false);
- + if (ret)
- + return ret;
- +
- + return 0;
- +}
- +
- +static int imx_sata_phy_reset(struct ahci_host_priv *hpriv)
- +{
- + void __iomem *mmio = hpriv->mmio;
- + int timeout = 10;
- + u16 val;
- + int ret;
- +
- + /* Reset SATA PHY by setting RESET bit of PHY register CLOCK_RESET */
- + ret = imx_phy_reg_addressing(IMX_CLOCK_RESET, mmio);
- + if (ret)
- + return ret;
- + ret = imx_phy_reg_write(IMX_CLOCK_RESET_RESET, mmio);
- + if (ret)
- + return ret;
- +
- + /* Wait for PHY RX_PLL to be stable */
- + do {
- + usleep_range(100, 200);
- + ret = imx_phy_reg_addressing(IMX_LANE0_OUT_STAT, mmio);
- + if (ret)
- + return ret;
- + ret = imx_phy_reg_read(&val, mmio);
- + if (ret)
- + return ret;
- + if (val & IMX_LANE0_OUT_STAT_RX_PLL_STATE)
- + break;
- + } while (--timeout);
- +
- + return timeout ? 0 : -ETIMEDOUT;
- +}
- +
- +static int imx_sata_enable(struct ahci_host_priv *hpriv)
- +{
- + struct imx_ahci_priv *imxpriv = hpriv->plat_data;
- + struct device *dev = &imxpriv->ahci_pdev->dev;
- + int ret;
- +
- + if (imxpriv->no_device)
- + return 0;
- +
- + if (hpriv->target_pwr) {
- + ret = regulator_enable(hpriv->target_pwr);
- + if (ret)
- + return ret;
- }
-
- + request_bus_freq(BUS_FREQ_HIGH);
- +
- + ret = ahci_platform_enable_clks(hpriv);
- + if (ret < 0)
- + goto disable_regulator;
- +
- if (imxpriv->type == AHCI_IMX6Q) {
- + /*
- + * set PHY Paremeters, two steps to configure the GPR13,
- + * one write for rest of parameters, mask of first write
- + * is 0x07ffffff, and the other one write for setting
- + * the mpll_clk_en.
- + */
- + regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
- + IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK |
- + IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK |
- + IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK |
- + IMX6Q_GPR13_SATA_SPD_MODE_MASK |
- + IMX6Q_GPR13_SATA_MPLL_SS_EN |
- + IMX6Q_GPR13_SATA_TX_ATTEN_MASK |
- + IMX6Q_GPR13_SATA_TX_BOOST_MASK |
- + IMX6Q_GPR13_SATA_TX_LVL_MASK |
- + IMX6Q_GPR13_SATA_MPLL_CLK_EN |
- + IMX6Q_GPR13_SATA_TX_EDGE_RATE,
- + imxpriv->phy_params);
- regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
- IMX6Q_GPR13_SATA_MPLL_CLK_EN,
- IMX6Q_GPR13_SATA_MPLL_CLK_EN);
- +
- + usleep_range(100, 200);
- +
- + ret = imx_sata_phy_reset(hpriv);
- + if (ret) {
- + dev_err(dev, "failed to reset phy: %d\n", ret);
- + goto disable_regulator;
- + }
- }
-
- usleep_range(1000, 2000);
-
- return 0;
-
- -clk_err:
- - if (imxpriv->type == AHCI_IMX53)
- - clk_disable_unprepare(imxpriv->sata_gate_clk);
- +disable_regulator:
- + release_bus_freq(BUS_FREQ_HIGH);
- +
- + if (hpriv->target_pwr)
- + regulator_disable(hpriv->target_pwr);
- +
- return ret;
- }
-
- -static void imx_sata_clock_disable(struct device *dev)
- +static void imx_sata_disable(struct ahci_host_priv *hpriv)
- {
- - struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
- + struct imx_ahci_priv *imxpriv = hpriv->plat_data;
- +
- + if (imxpriv->no_device)
- + return;
-
- if (imxpriv->type == AHCI_IMX6Q) {
- regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
- @@ -105,10 +290,12 @@
- !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
- }
-
- - clk_disable_unprepare(imxpriv->sata_ref_clk);
- + ahci_platform_disable_clks(hpriv);
-
- - if (imxpriv->type == AHCI_IMX53)
- - clk_disable_unprepare(imxpriv->sata_gate_clk);
- + release_bus_freq(BUS_FREQ_HIGH);
- +
- + if (hpriv->target_pwr)
- + regulator_disable(hpriv->target_pwr);
- }
-
- static void ahci_imx_error_handler(struct ata_port *ap)
- @@ -118,7 +305,7 @@
- struct ata_host *host = dev_get_drvdata(ap->dev);
- struct ahci_host_priv *hpriv = host->private_data;
- void __iomem *mmio = hpriv->mmio;
- - struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent);
- + struct imx_ahci_priv *imxpriv = hpriv->plat_data;
-
- ahci_error_handler(ap);
-
- @@ -134,17 +321,23 @@
- * without full reset once the pddq mode is enabled making it
- * impossible to use as part of libata LPM.
- */
- - reg_val = readl(mmio + PORT_PHY_CTL);
- - writel(reg_val | PORT_PHY_CTL_PDDQ_LOC, mmio + PORT_PHY_CTL);
- - imx_sata_clock_disable(ap->dev);
- + reg_val = readl(mmio + IMX_P0PHYCR);
- + writel(reg_val | IMX_P0PHYCR_TEST_PDDQ, mmio + IMX_P0PHYCR);
- + imx_sata_disable(hpriv);
- imxpriv->no_device = true;
- +
- + dev_info(ap->dev, "no device found, disabling link.\n");
- + dev_info(ap->dev, "pass " MODULE_PARAM_PREFIX
- + ".hotplug=1 to enable hotplug\n");
- }
-
- static int ahci_imx_softreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline)
- {
- struct ata_port *ap = link->ap;
- - struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent);
- + struct ata_host *host = dev_get_drvdata(ap->dev);
- + struct ahci_host_priv *hpriv = host->private_data;
- + struct imx_ahci_priv *imxpriv = hpriv->plat_data;
- int ret = -EIO;
-
- if (imxpriv->type == AHCI_IMX53)
- @@ -156,7 +349,8 @@
- }
-
- static struct ata_port_operations ahci_imx_ops = {
- - .inherits = &ahci_platform_ops,
- + .inherits = &ahci_ops,
- + .host_stop = ahci_imx_host_stop,
- .error_handler = ahci_imx_error_handler,
- .softreset = ahci_imx_softreset,
- };
- @@ -168,234 +362,306 @@
- .port_ops = &ahci_imx_ops,
- };
-
- -static int imx_sata_init(struct device *dev, void __iomem *mmio)
- -{
- - int ret = 0;
- - unsigned int reg_val;
- - struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
- -
- - ret = imx_sata_clock_enable(dev);
- - if (ret < 0)
- - return ret;
- +static const struct of_device_id imx_ahci_of_match[] = {
- + { .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 },
- + { .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q },
- + {},
- +};
- +MODULE_DEVICE_TABLE(of, imx_ahci_of_match);
-
- - /*
- - * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL,
- - * and IP vendor specific register HOST_TIMER1MS.
- - * Configure CAP_SSS (support stagered spin up).
- - * Implement the port0.
- - * Get the ahb clock rate, and configure the TIMER1MS register.
- - */
- - reg_val = readl(mmio + HOST_CAP);
- - if (!(reg_val & HOST_CAP_SSS)) {
- - reg_val |= HOST_CAP_SSS;
- - writel(reg_val, mmio + HOST_CAP);
- - }
- - reg_val = readl(mmio + HOST_PORTS_IMPL);
- - if (!(reg_val & 0x1)) {
- - reg_val |= 0x1;
- - writel(reg_val, mmio + HOST_PORTS_IMPL);
- - }
- +struct reg_value {
- + u32 of_value;
- + u32 reg_value;
- +};
-
- - reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
- - writel(reg_val, mmio + HOST_TIMER1MS);
- +struct reg_property {
- + const char *name;
- + const struct reg_value *values;
- + size_t num_values;
- + u32 def_value;
- + u32 set_value;
- +};
-
- - return 0;
- -}
- +static const struct reg_value gpr13_tx_level[] = {
- + { 937, IMX6Q_GPR13_SATA_TX_LVL_0_937_V },
- + { 947, IMX6Q_GPR13_SATA_TX_LVL_0_947_V },
- + { 957, IMX6Q_GPR13_SATA_TX_LVL_0_957_V },
- + { 966, IMX6Q_GPR13_SATA_TX_LVL_0_966_V },
- + { 976, IMX6Q_GPR13_SATA_TX_LVL_0_976_V },
- + { 986, IMX6Q_GPR13_SATA_TX_LVL_0_986_V },
- + { 996, IMX6Q_GPR13_SATA_TX_LVL_0_996_V },
- + { 1005, IMX6Q_GPR13_SATA_TX_LVL_1_005_V },
- + { 1015, IMX6Q_GPR13_SATA_TX_LVL_1_015_V },
- + { 1025, IMX6Q_GPR13_SATA_TX_LVL_1_025_V },
- + { 1035, IMX6Q_GPR13_SATA_TX_LVL_1_035_V },
- + { 1045, IMX6Q_GPR13_SATA_TX_LVL_1_045_V },
- + { 1054, IMX6Q_GPR13_SATA_TX_LVL_1_054_V },
- + { 1064, IMX6Q_GPR13_SATA_TX_LVL_1_064_V },
- + { 1074, IMX6Q_GPR13_SATA_TX_LVL_1_074_V },
- + { 1084, IMX6Q_GPR13_SATA_TX_LVL_1_084_V },
- + { 1094, IMX6Q_GPR13_SATA_TX_LVL_1_094_V },
- + { 1104, IMX6Q_GPR13_SATA_TX_LVL_1_104_V },
- + { 1113, IMX6Q_GPR13_SATA_TX_LVL_1_113_V },
- + { 1123, IMX6Q_GPR13_SATA_TX_LVL_1_123_V },
- + { 1133, IMX6Q_GPR13_SATA_TX_LVL_1_133_V },
- + { 1143, IMX6Q_GPR13_SATA_TX_LVL_1_143_V },
- + { 1152, IMX6Q_GPR13_SATA_TX_LVL_1_152_V },
- + { 1162, IMX6Q_GPR13_SATA_TX_LVL_1_162_V },
- + { 1172, IMX6Q_GPR13_SATA_TX_LVL_1_172_V },
- + { 1182, IMX6Q_GPR13_SATA_TX_LVL_1_182_V },
- + { 1191, IMX6Q_GPR13_SATA_TX_LVL_1_191_V },
- + { 1201, IMX6Q_GPR13_SATA_TX_LVL_1_201_V },
- + { 1211, IMX6Q_GPR13_SATA_TX_LVL_1_211_V },
- + { 1221, IMX6Q_GPR13_SATA_TX_LVL_1_221_V },
- + { 1230, IMX6Q_GPR13_SATA_TX_LVL_1_230_V },
- + { 1240, IMX6Q_GPR13_SATA_TX_LVL_1_240_V }
- +};
-
- -static void imx_sata_exit(struct device *dev)
- -{
- - imx_sata_clock_disable(dev);
- -}
- +static const struct reg_value gpr13_tx_boost[] = {
- + { 0, IMX6Q_GPR13_SATA_TX_BOOST_0_00_DB },
- + { 370, IMX6Q_GPR13_SATA_TX_BOOST_0_37_DB },
- + { 740, IMX6Q_GPR13_SATA_TX_BOOST_0_74_DB },
- + { 1110, IMX6Q_GPR13_SATA_TX_BOOST_1_11_DB },
- + { 1480, IMX6Q_GPR13_SATA_TX_BOOST_1_48_DB },
- + { 1850, IMX6Q_GPR13_SATA_TX_BOOST_1_85_DB },
- + { 2220, IMX6Q_GPR13_SATA_TX_BOOST_2_22_DB },
- + { 2590, IMX6Q_GPR13_SATA_TX_BOOST_2_59_DB },
- + { 2960, IMX6Q_GPR13_SATA_TX_BOOST_2_96_DB },
- + { 3330, IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB },
- + { 3700, IMX6Q_GPR13_SATA_TX_BOOST_3_70_DB },
- + { 4070, IMX6Q_GPR13_SATA_TX_BOOST_4_07_DB },
- + { 4440, IMX6Q_GPR13_SATA_TX_BOOST_4_44_DB },
- + { 4810, IMX6Q_GPR13_SATA_TX_BOOST_4_81_DB },
- + { 5280, IMX6Q_GPR13_SATA_TX_BOOST_5_28_DB },
- + { 5750, IMX6Q_GPR13_SATA_TX_BOOST_5_75_DB }
- +};
-
- -static int imx_ahci_suspend(struct device *dev)
- -{
- - struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
- +static const struct reg_value gpr13_tx_atten[] = {
- + { 8, IMX6Q_GPR13_SATA_TX_ATTEN_8_16 },
- + { 9, IMX6Q_GPR13_SATA_TX_ATTEN_9_16 },
- + { 10, IMX6Q_GPR13_SATA_TX_ATTEN_10_16 },
- + { 12, IMX6Q_GPR13_SATA_TX_ATTEN_12_16 },
- + { 14, IMX6Q_GPR13_SATA_TX_ATTEN_14_16 },
- + { 16, IMX6Q_GPR13_SATA_TX_ATTEN_16_16 },
- +};
-
- - /*
- - * If no_device is set, The CLKs had been gated off in the
- - * initialization so don't do it again here.
- - */
- - if (!imxpriv->no_device)
- - imx_sata_clock_disable(dev);
- +static const struct reg_value gpr13_rx_eq[] = {
- + { 500, IMX6Q_GPR13_SATA_RX_EQ_VAL_0_5_DB },
- + { 1000, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_0_DB },
- + { 1500, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_5_DB },
- + { 2000, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_0_DB },
- + { 2500, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_5_DB },
- + { 3000, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB },
- + { 3500, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_5_DB },
- + { 4000, IMX6Q_GPR13_SATA_RX_EQ_VAL_4_0_DB },
- +};
-
- - return 0;
- -}
- +static const struct reg_property gpr13_props[] = {
- + {
- + .name = "fsl,transmit-level-mV",
- + .values = gpr13_tx_level,
- + .num_values = ARRAY_SIZE(gpr13_tx_level),
- + .def_value = IMX6Q_GPR13_SATA_TX_LVL_1_025_V,
- + }, {
- + .name = "fsl,transmit-boost-mdB",
- + .values = gpr13_tx_boost,
- + .num_values = ARRAY_SIZE(gpr13_tx_boost),
- + .def_value = IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB,
- + }, {
- + .name = "fsl,transmit-atten-16ths",
- + .values = gpr13_tx_atten,
- + .num_values = ARRAY_SIZE(gpr13_tx_atten),
- + .def_value = IMX6Q_GPR13_SATA_TX_ATTEN_9_16,
- + }, {
- + .name = "fsl,receive-eq-mdB",
- + .values = gpr13_rx_eq,
- + .num_values = ARRAY_SIZE(gpr13_rx_eq),
- + .def_value = IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB,
- + }, {
- + .name = "fsl,no-spread-spectrum",
- + .def_value = IMX6Q_GPR13_SATA_MPLL_SS_EN,
- + .set_value = 0,
- + },
- +};
-
- -static int imx_ahci_resume(struct device *dev)
- +static u32 imx_ahci_parse_props(struct device *dev,
- + const struct reg_property *prop, size_t num)
- {
- - struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
- - int ret = 0;
- -
- - if (!imxpriv->no_device)
- - ret = imx_sata_clock_enable(dev);
- + struct device_node *np = dev->of_node;
- + u32 reg_value = 0;
- + int i, j;
- +
- + for (i = 0; i < num; i++, prop++) {
- + u32 of_val;
- +
- + if (prop->num_values == 0) {
- + if (of_property_read_bool(np, prop->name))
- + reg_value |= prop->set_value;
- + else
- + reg_value |= prop->def_value;
- + continue;
- + }
-
- - return ret;
- -}
- + if (of_property_read_u32(np, prop->name, &of_val)) {
- + dev_info(dev, "%s not specified, using %08x\n",
- + prop->name, prop->def_value);
- + reg_value |= prop->def_value;
- + continue;
- + }
-
- -static struct ahci_platform_data imx_sata_pdata = {
- - .init = imx_sata_init,
- - .exit = imx_sata_exit,
- - .ata_port_info = &ahci_imx_port_info,
- - .suspend = imx_ahci_suspend,
- - .resume = imx_ahci_resume,
- + for (j = 0; j < prop->num_values; j++) {
- + if (prop->values[j].of_value == of_val) {
- + dev_info(dev, "%s value %u, using %08x\n",
- + prop->name, of_val, prop->values[j].reg_value);
- + reg_value |= prop->values[j].reg_value;
- + break;
- + }
- + }
-
- -};
- + if (j == prop->num_values) {
- + dev_err(dev, "DT property %s is not a valid value\n",
- + prop->name);
- + reg_value |= prop->def_value;
- + }
- + }
-
- -static const struct of_device_id imx_ahci_of_match[] = {
- - { .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 },
- - { .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q },
- - {},
- -};
- -MODULE_DEVICE_TABLE(of, imx_ahci_of_match);
- + return reg_value;
- +}
-
- static int imx_ahci_probe(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
- - struct resource *mem, *irq, res[2];
- const struct of_device_id *of_id;
- - enum ahci_imx_type type;
- - const struct ahci_platform_data *pdata = NULL;
- + struct ahci_host_priv *hpriv;
- struct imx_ahci_priv *imxpriv;
- - struct device *ahci_dev;
- - struct platform_device *ahci_pdev;
- + unsigned int reg_val;
- int ret;
-
- of_id = of_match_device(imx_ahci_of_match, dev);
- if (!of_id)
- return -EINVAL;
-
- - type = (enum ahci_imx_type)of_id->data;
- - pdata = &imx_sata_pdata;
- -
- imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL);
- - if (!imxpriv) {
- - dev_err(dev, "can't alloc ahci_host_priv\n");
- + if (!imxpriv)
- return -ENOMEM;
- - }
- -
- - ahci_pdev = platform_device_alloc("ahci", -1);
- - if (!ahci_pdev)
- - return -ENODEV;
- -
- - ahci_dev = &ahci_pdev->dev;
- - ahci_dev->parent = dev;
-
- + imxpriv->ahci_pdev = pdev;
- imxpriv->no_device = false;
- imxpriv->first_time = true;
- - imxpriv->type = type;
- -
- + imxpriv->type = (enum ahci_imx_type)of_id->data;
- imxpriv->ahb_clk = devm_clk_get(dev, "ahb");
- if (IS_ERR(imxpriv->ahb_clk)) {
- dev_err(dev, "can't get ahb clock.\n");
- - ret = PTR_ERR(imxpriv->ahb_clk);
- - goto err_out;
- - }
- -
- - if (type == AHCI_IMX53) {
- - imxpriv->sata_gate_clk = devm_clk_get(dev, "sata_gate");
- - if (IS_ERR(imxpriv->sata_gate_clk)) {
- - dev_err(dev, "can't get sata_gate clock.\n");
- - ret = PTR_ERR(imxpriv->sata_gate_clk);
- - goto err_out;
- - }
- - }
- -
- - imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref");
- - if (IS_ERR(imxpriv->sata_ref_clk)) {
- - dev_err(dev, "can't get sata_ref clock.\n");
- - ret = PTR_ERR(imxpriv->sata_ref_clk);
- - goto err_out;
- + return PTR_ERR(imxpriv->ahb_clk);
- }
-
- - imxpriv->ahci_pdev = ahci_pdev;
- - platform_set_drvdata(pdev, imxpriv);
- -
- - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- - irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- - if (!mem || !irq) {
- - dev_err(dev, "no mmio/irq resource\n");
- - ret = -ENOMEM;
- - goto err_out;
- - }
- -
- - res[0] = *mem;
- - res[1] = *irq;
- -
- - ahci_dev->coherent_dma_mask = DMA_BIT_MASK(32);
- - ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask;
- - ahci_dev->of_node = dev->of_node;
- + if (imxpriv->type == AHCI_IMX6Q) {
- + u32 reg_value;
-
- - if (type == AHCI_IMX6Q) {
- imxpriv->gpr = syscon_regmap_lookup_by_compatible(
- "fsl,imx6q-iomuxc-gpr");
- if (IS_ERR(imxpriv->gpr)) {
- dev_err(dev,
- "failed to find fsl,imx6q-iomux-gpr regmap\n");
- - ret = PTR_ERR(imxpriv->gpr);
- - goto err_out;
- + return PTR_ERR(imxpriv->gpr);
- }
-
- - /*
- - * Set PHY Paremeters, two steps to configure the GPR13,
- - * one write for rest of parameters, mask of first write
- - * is 0x07fffffe, and the other one write for setting
- - * the mpll_clk_en happens in imx_sata_clock_enable().
- - */
- - regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
- - IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK |
- - IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK |
- - IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK |
- - IMX6Q_GPR13_SATA_SPD_MODE_MASK |
- - IMX6Q_GPR13_SATA_MPLL_SS_EN |
- - IMX6Q_GPR13_SATA_TX_ATTEN_MASK |
- - IMX6Q_GPR13_SATA_TX_BOOST_MASK |
- - IMX6Q_GPR13_SATA_TX_LVL_MASK |
- - IMX6Q_GPR13_SATA_MPLL_CLK_EN |
- - IMX6Q_GPR13_SATA_TX_EDGE_RATE,
- - IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB |
- + reg_value = imx_ahci_parse_props(dev, gpr13_props,
- + ARRAY_SIZE(gpr13_props));
- +
- + imxpriv->phy_params =
- IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
- IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
- IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
- - IMX6Q_GPR13_SATA_MPLL_SS_EN |
- - IMX6Q_GPR13_SATA_TX_ATTEN_9_16 |
- - IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB |
- - IMX6Q_GPR13_SATA_TX_LVL_1_025_V);
- + reg_value;
- }
-
- - ret = platform_device_add_resources(ahci_pdev, res, 2);
- + hpriv = ahci_platform_get_resources(pdev);
- + if (IS_ERR(hpriv))
- + return PTR_ERR(hpriv);
- +
- + hpriv->plat_data = imxpriv;
- +
- + ret = imx_sata_enable(hpriv);
- if (ret)
- - goto err_out;
- + return ret;
-
- - ret = platform_device_add_data(ahci_pdev, pdata, sizeof(*pdata));
- + /*
- + * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL,
- + * and IP vendor specific register IMX_TIMER1MS.
- + * Configure CAP_SSS (support stagered spin up).
- + * Implement the port0.
- + * Get the ahb clock rate, and configure the TIMER1MS register.
- + */
- + reg_val = readl(hpriv->mmio + HOST_CAP);
- + if (!(reg_val & HOST_CAP_SSS)) {
- + reg_val |= HOST_CAP_SSS;
- + writel(reg_val, hpriv->mmio + HOST_CAP);
- + }
- + reg_val = readl(hpriv->mmio + HOST_PORTS_IMPL);
- + if (!(reg_val & 0x1)) {
- + reg_val |= 0x1;
- + writel(reg_val, hpriv->mmio + HOST_PORTS_IMPL);
- + }
- +
- + reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
- + writel(reg_val, hpriv->mmio + IMX_TIMER1MS);
- +
- + ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info,
- + 0, 0, 0);
- if (ret)
- - goto err_out;
- + imx_sata_disable(hpriv);
- +
- + return ret;
- +}
-
- - ret = platform_device_add(ahci_pdev);
- - if (ret) {
- -err_out:
- - platform_device_put(ahci_pdev);
- +static void ahci_imx_host_stop(struct ata_host *host)
- +{
- + struct ahci_host_priv *hpriv = host->private_data;
- +
- + imx_sata_disable(hpriv);
- +}
- +
- +#ifdef CONFIG_PM_SLEEP
- +static int imx_ahci_suspend(struct device *dev)
- +{
- + struct ata_host *host = dev_get_drvdata(dev);
- + struct ahci_host_priv *hpriv = host->private_data;
- + int ret;
- +
- + ret = ahci_platform_suspend_host(dev);
- + if (ret)
- return ret;
- - }
- +
- + imx_sata_disable(hpriv);
-
- return 0;
- }
-
- -static int imx_ahci_remove(struct platform_device *pdev)
- +static int imx_ahci_resume(struct device *dev)
- {
- - struct imx_ahci_priv *imxpriv = platform_get_drvdata(pdev);
- - struct platform_device *ahci_pdev = imxpriv->ahci_pdev;
- + struct ata_host *host = dev_get_drvdata(dev);
- + struct ahci_host_priv *hpriv = host->private_data;
- + int ret;
-
- - platform_device_unregister(ahci_pdev);
- - return 0;
- + ret = imx_sata_enable(hpriv);
- + if (ret)
- + return ret;
- +
- + return ahci_platform_resume_host(dev);
- }
- +#endif
- +
- +static SIMPLE_DEV_PM_OPS(ahci_imx_pm_ops, imx_ahci_suspend, imx_ahci_resume);
-
- static struct platform_driver imx_ahci_driver = {
- .probe = imx_ahci_probe,
- - .remove = imx_ahci_remove,
- + .remove = ata_platform_remove_one,
- .driver = {
- .name = "ahci-imx",
- .owner = THIS_MODULE,
- .of_match_table = imx_ahci_of_match,
- + .pm = &ahci_imx_pm_ops,
- },
- };
- module_platform_driver(imx_ahci_driver);
- diff -Nur linux-3.14.35.orig/drivers/ata/ahci_platform.c linux-3.14.35/drivers/ata/ahci_platform.c
- --- linux-3.14.35.orig/drivers/ata/ahci_platform.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/ahci_platform.c 2015-03-08 14:27:37.505684502 -0500
- @@ -12,135 +12,36 @@
- * any later version.
- */
-
- -#include <linux/clk.h>
- #include <linux/kernel.h>
- -#include <linux/gfp.h>
- #include <linux/module.h>
- #include <linux/pm.h>
- -#include <linux/init.h>
- -#include <linux/interrupt.h>
- #include <linux/device.h>
- #include <linux/platform_device.h>
- #include <linux/libata.h>
- #include <linux/ahci_platform.h>
- #include "ahci.h"
-
- -static void ahci_host_stop(struct ata_host *host);
- -
- -enum ahci_type {
- - AHCI, /* standard platform ahci */
- - IMX53_AHCI, /* ahci on i.mx53 */
- - STRICT_AHCI, /* delayed DMA engine start */
- -};
- -
- -static struct platform_device_id ahci_devtype[] = {
- - {
- - .name = "ahci",
- - .driver_data = AHCI,
- - }, {
- - .name = "imx53-ahci",
- - .driver_data = IMX53_AHCI,
- - }, {
- - .name = "strict-ahci",
- - .driver_data = STRICT_AHCI,
- - }, {
- - /* sentinel */
- - }
- -};
- -MODULE_DEVICE_TABLE(platform, ahci_devtype);
- -
- -struct ata_port_operations ahci_platform_ops = {
- - .inherits = &ahci_ops,
- - .host_stop = ahci_host_stop,
- -};
- -EXPORT_SYMBOL_GPL(ahci_platform_ops);
- -
- -static struct ata_port_operations ahci_platform_retry_srst_ops = {
- - .inherits = &ahci_pmp_retry_srst_ops,
- - .host_stop = ahci_host_stop,
- -};
- -
- -static const struct ata_port_info ahci_port_info[] = {
- - /* by features */
- - [AHCI] = {
- - .flags = AHCI_FLAG_COMMON,
- - .pio_mask = ATA_PIO4,
- - .udma_mask = ATA_UDMA6,
- - .port_ops = &ahci_platform_ops,
- - },
- - [IMX53_AHCI] = {
- - .flags = AHCI_FLAG_COMMON,
- - .pio_mask = ATA_PIO4,
- - .udma_mask = ATA_UDMA6,
- - .port_ops = &ahci_platform_retry_srst_ops,
- - },
- - [STRICT_AHCI] = {
- - AHCI_HFLAGS (AHCI_HFLAG_DELAY_ENGINE),
- - .flags = AHCI_FLAG_COMMON,
- - .pio_mask = ATA_PIO4,
- - .udma_mask = ATA_UDMA6,
- - .port_ops = &ahci_platform_ops,
- - },
- -};
- -
- -static struct scsi_host_template ahci_platform_sht = {
- - AHCI_SHT("ahci_platform"),
- +static const struct ata_port_info ahci_port_info = {
- + .flags = AHCI_FLAG_COMMON,
- + .pio_mask = ATA_PIO4,
- + .udma_mask = ATA_UDMA6,
- + .port_ops = &ahci_platform_ops,
- };
-
- static int ahci_probe(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
- struct ahci_platform_data *pdata = dev_get_platdata(dev);
- - const struct platform_device_id *id = platform_get_device_id(pdev);
- - struct ata_port_info pi = ahci_port_info[id ? id->driver_data : 0];
- - const struct ata_port_info *ppi[] = { &pi, NULL };
- struct ahci_host_priv *hpriv;
- - struct ata_host *host;
- - struct resource *mem;
- - int irq;
- - int n_ports;
- - int i;
- int rc;
-
- - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- - if (!mem) {
- - dev_err(dev, "no mmio space\n");
- - return -EINVAL;
- - }
- -
- - irq = platform_get_irq(pdev, 0);
- - if (irq <= 0) {
- - dev_err(dev, "no irq\n");
- - return -EINVAL;
- - }
- -
- - if (pdata && pdata->ata_port_info)
- - pi = *pdata->ata_port_info;
- -
- - hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
- - if (!hpriv) {
- - dev_err(dev, "can't alloc ahci_host_priv\n");
- - return -ENOMEM;
- - }
- -
- - hpriv->flags |= (unsigned long)pi.private_data;
- + hpriv = ahci_platform_get_resources(pdev);
- + if (IS_ERR(hpriv))
- + return PTR_ERR(hpriv);
-
- - hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem));
- - if (!hpriv->mmio) {
- - dev_err(dev, "can't map %pR\n", mem);
- - return -ENOMEM;
- - }
- -
- - hpriv->clk = clk_get(dev, NULL);
- - if (IS_ERR(hpriv->clk)) {
- - dev_err(dev, "can't get clock\n");
- - } else {
- - rc = clk_prepare_enable(hpriv->clk);
- - if (rc) {
- - dev_err(dev, "clock prepare enable failed");
- - goto free_clk;
- - }
- - }
- + rc = ahci_platform_enable_resources(hpriv);
- + if (rc)
- + return rc;
-
- /*
- * Some platforms might need to prepare for mmio region access,
- @@ -151,69 +52,10 @@
- if (pdata && pdata->init) {
- rc = pdata->init(dev, hpriv->mmio);
- if (rc)
- - goto disable_unprepare_clk;
- - }
- -
- - ahci_save_initial_config(dev, hpriv,
- - pdata ? pdata->force_port_map : 0,
- - pdata ? pdata->mask_port_map : 0);
- -
- - /* prepare host */
- - if (hpriv->cap & HOST_CAP_NCQ)
- - pi.flags |= ATA_FLAG_NCQ;
- -
- - if (hpriv->cap & HOST_CAP_PMP)
- - pi.flags |= ATA_FLAG_PMP;
- -
- - ahci_set_em_messages(hpriv, &pi);
- -
- - /* CAP.NP sometimes indicate the index of the last enabled
- - * port, at other times, that of the last possible port, so
- - * determining the maximum port number requires looking at
- - * both CAP.NP and port_map.
- - */
- - n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
- -
- - host = ata_host_alloc_pinfo(dev, ppi, n_ports);
- - if (!host) {
- - rc = -ENOMEM;
- - goto pdata_exit;
- + goto disable_resources;
- }
-
- - host->private_data = hpriv;
- -
- - if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
- - host->flags |= ATA_HOST_PARALLEL_SCAN;
- - else
- - dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
- -
- - if (pi.flags & ATA_FLAG_EM)
- - ahci_reset_em(host);
- -
- - for (i = 0; i < host->n_ports; i++) {
- - struct ata_port *ap = host->ports[i];
- -
- - ata_port_desc(ap, "mmio %pR", mem);
- - ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
- -
- - /* set enclosure management message type */
- - if (ap->flags & ATA_FLAG_EM)
- - ap->em_message_type = hpriv->em_msg_type;
- -
- - /* disabled/not-implemented port */
- - if (!(hpriv->port_map & (1 << i)))
- - ap->ops = &ata_dummy_port_ops;
- - }
- -
- - rc = ahci_reset_controller(host);
- - if (rc)
- - goto pdata_exit;
- -
- - ahci_init_controller(host);
- - ahci_print_info(host, "platform");
- -
- - rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
- - &ahci_platform_sht);
- + rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info, 0, 0, 0);
- if (rc)
- goto pdata_exit;
-
- @@ -221,115 +63,19 @@
- pdata_exit:
- if (pdata && pdata->exit)
- pdata->exit(dev);
- -disable_unprepare_clk:
- - if (!IS_ERR(hpriv->clk))
- - clk_disable_unprepare(hpriv->clk);
- -free_clk:
- - if (!IS_ERR(hpriv->clk))
- - clk_put(hpriv->clk);
- - return rc;
- -}
- -
- -static void ahci_host_stop(struct ata_host *host)
- -{
- - struct device *dev = host->dev;
- - struct ahci_platform_data *pdata = dev_get_platdata(dev);
- - struct ahci_host_priv *hpriv = host->private_data;
- -
- - if (pdata && pdata->exit)
- - pdata->exit(dev);
- -
- - if (!IS_ERR(hpriv->clk)) {
- - clk_disable_unprepare(hpriv->clk);
- - clk_put(hpriv->clk);
- - }
- -}
- -
- -#ifdef CONFIG_PM_SLEEP
- -static int ahci_suspend(struct device *dev)
- -{
- - struct ahci_platform_data *pdata = dev_get_platdata(dev);
- - struct ata_host *host = dev_get_drvdata(dev);
- - struct ahci_host_priv *hpriv = host->private_data;
- - void __iomem *mmio = hpriv->mmio;
- - u32 ctl;
- - int rc;
- -
- - if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
- - dev_err(dev, "firmware update required for suspend/resume\n");
- - return -EIO;
- - }
- -
- - /*
- - * AHCI spec rev1.1 section 8.3.3:
- - * Software must disable interrupts prior to requesting a
- - * transition of the HBA to D3 state.
- - */
- - ctl = readl(mmio + HOST_CTL);
- - ctl &= ~HOST_IRQ_EN;
- - writel(ctl, mmio + HOST_CTL);
- - readl(mmio + HOST_CTL); /* flush */
- -
- - rc = ata_host_suspend(host, PMSG_SUSPEND);
- - if (rc)
- - return rc;
- -
- - if (pdata && pdata->suspend)
- - return pdata->suspend(dev);
- -
- - if (!IS_ERR(hpriv->clk))
- - clk_disable_unprepare(hpriv->clk);
- -
- - return 0;
- -}
- -
- -static int ahci_resume(struct device *dev)
- -{
- - struct ahci_platform_data *pdata = dev_get_platdata(dev);
- - struct ata_host *host = dev_get_drvdata(dev);
- - struct ahci_host_priv *hpriv = host->private_data;
- - int rc;
- -
- - if (!IS_ERR(hpriv->clk)) {
- - rc = clk_prepare_enable(hpriv->clk);
- - if (rc) {
- - dev_err(dev, "clock prepare enable failed");
- - return rc;
- - }
- - }
- -
- - if (pdata && pdata->resume) {
- - rc = pdata->resume(dev);
- - if (rc)
- - goto disable_unprepare_clk;
- - }
- -
- - if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
- - rc = ahci_reset_controller(host);
- - if (rc)
- - goto disable_unprepare_clk;
- -
- - ahci_init_controller(host);
- - }
- -
- - ata_host_resume(host);
- -
- - return 0;
- -
- -disable_unprepare_clk:
- - if (!IS_ERR(hpriv->clk))
- - clk_disable_unprepare(hpriv->clk);
- -
- +disable_resources:
- + ahci_platform_disable_resources(hpriv);
- return rc;
- }
- -#endif
-
- -static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume);
- +static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
- + ahci_platform_resume);
-
- static const struct of_device_id ahci_of_match[] = {
- { .compatible = "snps,spear-ahci", },
- { .compatible = "snps,exynos5440-ahci", },
- { .compatible = "ibm,476gtr-ahci", },
- + { .compatible = "snps,dwc-ahci", },
- {},
- };
- MODULE_DEVICE_TABLE(of, ahci_of_match);
- @@ -343,7 +89,6 @@
- .of_match_table = ahci_of_match,
- .pm = &ahci_pm_ops,
- },
- - .id_table = ahci_devtype,
- };
- module_platform_driver(ahci_driver);
-
- diff -Nur linux-3.14.35.orig/drivers/ata/ata_generic.c linux-3.14.35/drivers/ata/ata_generic.c
- --- linux-3.14.35.orig/drivers/ata/ata_generic.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/ata_generic.c 2015-03-08 14:27:37.505684502 -0500
- @@ -19,7 +19,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/Kconfig linux-3.14.35/drivers/ata/Kconfig
- --- linux-3.14.35.orig/drivers/ata/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/Kconfig 2015-03-08 14:27:37.505684502 -0500
- @@ -99,7 +99,7 @@
-
- config AHCI_IMX
- tristate "Freescale i.MX AHCI SATA support"
- - depends on SATA_AHCI_PLATFORM && MFD_SYSCON
- + depends on MFD_SYSCON
- help
- This option enables support for the Freescale i.MX SoC's
- onboard AHCI SATA.
- diff -Nur linux-3.14.35.orig/drivers/ata/libahci.c linux-3.14.35/drivers/ata/libahci.c
- --- linux-3.14.35.orig/drivers/ata/libahci.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/libahci.c 2015-03-08 14:27:37.509684502 -0500
- @@ -35,7 +35,6 @@
- #include <linux/kernel.h>
- #include <linux/gfp.h>
- #include <linux/module.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- @@ -394,6 +393,9 @@
- *
- * If inconsistent, config values are fixed up by this function.
- *
- + * If it is not set already this function sets hpriv->start_engine to
- + * ahci_start_engine.
- + *
- * LOCKING:
- * None.
- */
- @@ -450,11 +452,23 @@
- cap &= ~HOST_CAP_SNTF;
- }
-
- + if ((cap2 & HOST_CAP2_SDS) && (hpriv->flags & AHCI_HFLAG_NO_DEVSLP)) {
- + dev_info(dev,
- + "controller can't do DEVSLP, turning off\n");
- + cap2 &= ~HOST_CAP2_SDS;
- + cap2 &= ~HOST_CAP2_SADM;
- + }
- +
- if (!(cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_YES_FBS)) {
- dev_info(dev, "controller can do FBS, turning on CAP_FBS\n");
- cap |= HOST_CAP_FBS;
- }
-
- + if ((cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_NO_FBS)) {
- + dev_info(dev, "controller can't do FBS, turning off CAP_FBS\n");
- + cap &= ~HOST_CAP_FBS;
- + }
- +
- if (force_port_map && port_map != force_port_map) {
- dev_info(dev, "forcing port_map 0x%x -> 0x%x\n",
- port_map, force_port_map);
- @@ -500,6 +514,9 @@
- hpriv->cap = cap;
- hpriv->cap2 = cap2;
- hpriv->port_map = port_map;
- +
- + if (!hpriv->start_engine)
- + hpriv->start_engine = ahci_start_engine;
- }
- EXPORT_SYMBOL_GPL(ahci_save_initial_config);
-
- @@ -766,7 +783,7 @@
-
- /* enable DMA */
- if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE))
- - ahci_start_engine(ap);
- + hpriv->start_engine(ap);
-
- /* turn on LEDs */
- if (ap->flags & ATA_FLAG_EM) {
- @@ -1234,7 +1251,7 @@
-
- /* restart engine */
- out_restart:
- - ahci_start_engine(ap);
- + hpriv->start_engine(ap);
- return rc;
- }
- EXPORT_SYMBOL_GPL(ahci_kick_engine);
- @@ -1426,6 +1443,7 @@
- const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
- struct ata_port *ap = link->ap;
- struct ahci_port_priv *pp = ap->private_data;
- + struct ahci_host_priv *hpriv = ap->host->private_data;
- u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
- struct ata_taskfile tf;
- bool online;
- @@ -1443,7 +1461,7 @@
- rc = sata_link_hardreset(link, timing, deadline, &online,
- ahci_check_ready);
-
- - ahci_start_engine(ap);
- + hpriv->start_engine(ap);
-
- if (online)
- *class = ahci_dev_classify(ap);
- @@ -2007,10 +2025,12 @@
-
- void ahci_error_handler(struct ata_port *ap)
- {
- + struct ahci_host_priv *hpriv = ap->host->private_data;
- +
- if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
- /* restart engine */
- ahci_stop_engine(ap);
- - ahci_start_engine(ap);
- + hpriv->start_engine(ap);
- }
-
- sata_pmp_error_handler(ap);
- @@ -2031,6 +2051,7 @@
-
- static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
- {
- + struct ahci_host_priv *hpriv = ap->host->private_data;
- void __iomem *port_mmio = ahci_port_base(ap);
- struct ata_device *dev = ap->link.device;
- u32 devslp, dm, dito, mdat, deto;
- @@ -2094,7 +2115,7 @@
- PORT_DEVSLP_ADSE);
- writel(devslp, port_mmio + PORT_DEVSLP);
-
- - ahci_start_engine(ap);
- + hpriv->start_engine(ap);
-
- /* enable device sleep feature for the drive */
- err_mask = ata_dev_set_feature(dev,
- @@ -2106,6 +2127,7 @@
-
- static void ahci_enable_fbs(struct ata_port *ap)
- {
- + struct ahci_host_priv *hpriv = ap->host->private_data;
- struct ahci_port_priv *pp = ap->private_data;
- void __iomem *port_mmio = ahci_port_base(ap);
- u32 fbs;
- @@ -2134,11 +2156,12 @@
- } else
- dev_err(ap->host->dev, "Failed to enable FBS\n");
-
- - ahci_start_engine(ap);
- + hpriv->start_engine(ap);
- }
-
- static void ahci_disable_fbs(struct ata_port *ap)
- {
- + struct ahci_host_priv *hpriv = ap->host->private_data;
- struct ahci_port_priv *pp = ap->private_data;
- void __iomem *port_mmio = ahci_port_base(ap);
- u32 fbs;
- @@ -2166,7 +2189,7 @@
- pp->fbs_enabled = false;
- }
-
- - ahci_start_engine(ap);
- + hpriv->start_engine(ap);
- }
-
- static void ahci_pmp_attach(struct ata_port *ap)
- diff -Nur linux-3.14.35.orig/drivers/ata/libahci_platform.c linux-3.14.35/drivers/ata/libahci_platform.c
- --- linux-3.14.35.orig/drivers/ata/libahci_platform.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/ata/libahci_platform.c 2015-03-08 14:27:37.509684502 -0500
- @@ -0,0 +1,544 @@
- +/*
- + * AHCI SATA platform library
- + *
- + * Copyright 2004-2005 Red Hat, Inc.
- + * Jeff Garzik <jgarzik@pobox.com>
- + * Copyright 2010 MontaVista Software, LLC.
- + * Anton Vorontsov <avorontsov@ru.mvista.com>
- + *
- + * 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, or (at your option)
- + * any later version.
- + */
- +
- +#include <linux/clk.h>
- +#include <linux/kernel.h>
- +#include <linux/gfp.h>
- +#include <linux/module.h>
- +#include <linux/pm.h>
- +#include <linux/interrupt.h>
- +#include <linux/device.h>
- +#include <linux/platform_device.h>
- +#include <linux/libata.h>
- +#include <linux/ahci_platform.h>
- +#include <linux/phy/phy.h>
- +#include <linux/pm_runtime.h>
- +#include "ahci.h"
- +
- +static void ahci_host_stop(struct ata_host *host);
- +
- +struct ata_port_operations ahci_platform_ops = {
- + .inherits = &ahci_ops,
- + .host_stop = ahci_host_stop,
- +};
- +EXPORT_SYMBOL_GPL(ahci_platform_ops);
- +
- +static struct scsi_host_template ahci_platform_sht = {
- + AHCI_SHT("ahci_platform"),
- +};
- +
- +/**
- + * ahci_platform_enable_clks - Enable platform clocks
- + * @hpriv: host private area to store config values
- + *
- + * This function enables all the clks found in hpriv->clks, starting at
- + * index 0. If any clk fails to enable it disables all the clks already
- + * enabled in reverse order, and then returns an error.
- + *
- + * RETURNS:
- + * 0 on success otherwise a negative error code
- + */
- +int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
- +{
- + int c, rc;
- +
- + for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
- + rc = clk_prepare_enable(hpriv->clks[c]);
- + if (rc)
- + goto disable_unprepare_clk;
- + }
- + return 0;
- +
- +disable_unprepare_clk:
- + while (--c >= 0)
- + clk_disable_unprepare(hpriv->clks[c]);
- + return rc;
- +}
- +EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
- +
- +/**
- + * ahci_platform_disable_clks - Disable platform clocks
- + * @hpriv: host private area to store config values
- + *
- + * This function disables all the clks found in hpriv->clks, in reverse
- + * order of ahci_platform_enable_clks (starting at the end of the array).
- + */
- +void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
- +{
- + int c;
- +
- + for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
- + if (hpriv->clks[c])
- + clk_disable_unprepare(hpriv->clks[c]);
- +}
- +EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
- +
- +/**
- + * ahci_platform_enable_resources - Enable platform resources
- + * @hpriv: host private area to store config values
- + *
- + * This function enables all ahci_platform managed resources in the
- + * following order:
- + * 1) Regulator
- + * 2) Clocks (through ahci_platform_enable_clks)
- + * 3) Phy
- + *
- + * If resource enabling fails at any point the previous enabled resources
- + * are disabled in reverse order.
- + *
- + * RETURNS:
- + * 0 on success otherwise a negative error code
- + */
- +int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
- +{
- + int rc;
- +
- + if (hpriv->target_pwr) {
- + rc = regulator_enable(hpriv->target_pwr);
- + if (rc)
- + return rc;
- + }
- +
- + rc = ahci_platform_enable_clks(hpriv);
- + if (rc)
- + goto disable_regulator;
- +
- + if (hpriv->phy) {
- + rc = phy_init(hpriv->phy);
- + if (rc)
- + goto disable_clks;
- +
- + rc = phy_power_on(hpriv->phy);
- + if (rc) {
- + phy_exit(hpriv->phy);
- + goto disable_clks;
- + }
- + }
- +
- + return 0;
- +
- +disable_clks:
- + ahci_platform_disable_clks(hpriv);
- +
- +disable_regulator:
- + if (hpriv->target_pwr)
- + regulator_disable(hpriv->target_pwr);
- + return rc;
- +}
- +EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
- +
- +/**
- + * ahci_platform_disable_resources - Disable platform resources
- + * @hpriv: host private area to store config values
- + *
- + * This function disables all ahci_platform managed resources in the
- + * following order:
- + * 1) Phy
- + * 2) Clocks (through ahci_platform_disable_clks)
- + * 3) Regulator
- + */
- +void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
- +{
- + if (hpriv->phy) {
- + phy_power_off(hpriv->phy);
- + phy_exit(hpriv->phy);
- + }
- +
- + ahci_platform_disable_clks(hpriv);
- +
- + if (hpriv->target_pwr)
- + regulator_disable(hpriv->target_pwr);
- +}
- +EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
- +
- +static void ahci_platform_put_resources(struct device *dev, void *res)
- +{
- + struct ahci_host_priv *hpriv = res;
- + int c;
- +
- + if (hpriv->got_runtime_pm) {
- + pm_runtime_put_sync(dev);
- + pm_runtime_disable(dev);
- + }
- +
- + for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
- + clk_put(hpriv->clks[c]);
- +}
- +
- +/**
- + * ahci_platform_get_resources - Get platform resources
- + * @pdev: platform device to get resources for
- + *
- + * This function allocates an ahci_host_priv struct, and gets the following
- + * resources, storing a reference to them inside the returned struct:
- + *
- + * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
- + * 2) regulator for controlling the targets power (optional)
- + * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
- + * or for non devicetree enabled platforms a single clock
- + * 4) phy (optional)
- + *
- + * RETURNS:
- + * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
- + */
- +struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
- +{
- + struct device *dev = &pdev->dev;
- + struct ahci_host_priv *hpriv;
- + struct clk *clk;
- + int i, rc = -ENOMEM;
- +
- + if (!devres_open_group(dev, NULL, GFP_KERNEL))
- + return ERR_PTR(-ENOMEM);
- +
- + hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
- + GFP_KERNEL);
- + if (!hpriv)
- + goto err_out;
- +
- + devres_add(dev, hpriv);
- +
- + hpriv->mmio = devm_ioremap_resource(dev,
- + platform_get_resource(pdev, IORESOURCE_MEM, 0));
- + if (IS_ERR(hpriv->mmio)) {
- + dev_err(dev, "no mmio space\n");
- + rc = PTR_ERR(hpriv->mmio);
- + goto err_out;
- + }
- +
- + hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
- + if (IS_ERR(hpriv->target_pwr)) {
- + rc = PTR_ERR(hpriv->target_pwr);
- + if (rc == -EPROBE_DEFER)
- + goto err_out;
- + hpriv->target_pwr = NULL;
- + }
- +
- + for (i = 0; i < AHCI_MAX_CLKS; i++) {
- + /*
- + * For now we must use clk_get(dev, NULL) for the first clock,
- + * because some platforms (da850, spear13xx) are not yet
- + * converted to use devicetree for clocks. For new platforms
- + * this is equivalent to of_clk_get(dev->of_node, 0).
- + */
- + if (i == 0)
- + clk = clk_get(dev, NULL);
- + else
- + clk = of_clk_get(dev->of_node, i);
- +
- + if (IS_ERR(clk)) {
- + rc = PTR_ERR(clk);
- + if (rc == -EPROBE_DEFER)
- + goto err_out;
- + break;
- + }
- + hpriv->clks[i] = clk;
- + }
- +
- + hpriv->phy = devm_phy_get(dev, "sata-phy");
- + if (IS_ERR(hpriv->phy)) {
- + rc = PTR_ERR(hpriv->phy);
- + switch (rc) {
- + case -ENODEV:
- + case -ENOSYS:
- + /* continue normally */
- + hpriv->phy = NULL;
- + break;
- +
- + case -EPROBE_DEFER:
- + goto err_out;
- +
- + default:
- + dev_err(dev, "couldn't get sata-phy\n");
- + goto err_out;
- + }
- + }
- +
- + pm_runtime_enable(dev);
- + pm_runtime_get_sync(dev);
- + hpriv->got_runtime_pm = true;
- +
- + devres_remove_group(dev, NULL);
- + return hpriv;
- +
- +err_out:
- + devres_release_group(dev, NULL);
- + return ERR_PTR(rc);
- +}
- +EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
- +
- +/**
- + * ahci_platform_init_host - Bring up an ahci-platform host
- + * @pdev: platform device pointer for the host
- + * @hpriv: ahci-host private data for the host
- + * @pi_template: template for the ata_port_info to use
- + * @host_flags: ahci host flags used in ahci_host_priv
- + * @force_port_map: param passed to ahci_save_initial_config
- + * @mask_port_map: param passed to ahci_save_initial_config
- + *
- + * This function does all the usual steps needed to bring up an
- + * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
- + * must be initialized / enabled before calling this.
- + *
- + * RETURNS:
- + * 0 on success otherwise a negative error code
- + */
- +int ahci_platform_init_host(struct platform_device *pdev,
- + struct ahci_host_priv *hpriv,
- + const struct ata_port_info *pi_template,
- + unsigned long host_flags,
- + unsigned int force_port_map,
- + unsigned int mask_port_map)
- +{
- + struct device *dev = &pdev->dev;
- + struct ata_port_info pi = *pi_template;
- + const struct ata_port_info *ppi[] = { &pi, NULL };
- + struct ata_host *host;
- + int i, irq, n_ports, rc;
- +
- + irq = platform_get_irq(pdev, 0);
- + if (irq <= 0) {
- + dev_err(dev, "no irq\n");
- + return -EINVAL;
- + }
- +
- + /* prepare host */
- + pi.private_data = (void *)host_flags;
- + hpriv->flags |= host_flags;
- +
- + ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
- +
- + if (hpriv->cap & HOST_CAP_NCQ)
- + pi.flags |= ATA_FLAG_NCQ;
- +
- + if (hpriv->cap & HOST_CAP_PMP)
- + pi.flags |= ATA_FLAG_PMP;
- +
- + ahci_set_em_messages(hpriv, &pi);
- +
- + /* CAP.NP sometimes indicate the index of the last enabled
- + * port, at other times, that of the last possible port, so
- + * determining the maximum port number requires looking at
- + * both CAP.NP and port_map.
- + */
- + n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
- +
- + host = ata_host_alloc_pinfo(dev, ppi, n_ports);
- + if (!host)
- + return -ENOMEM;
- +
- + host->private_data = hpriv;
- +
- + if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
- + host->flags |= ATA_HOST_PARALLEL_SCAN;
- + else
- + dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
- +
- + if (pi.flags & ATA_FLAG_EM)
- + ahci_reset_em(host);
- +
- + for (i = 0; i < host->n_ports; i++) {
- + struct ata_port *ap = host->ports[i];
- +
- + ata_port_desc(ap, "mmio %pR",
- + platform_get_resource(pdev, IORESOURCE_MEM, 0));
- + ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
- +
- + /* set enclosure management message type */
- + if (ap->flags & ATA_FLAG_EM)
- + ap->em_message_type = hpriv->em_msg_type;
- +
- + /* disabled/not-implemented port */
- + if (!(hpriv->port_map & (1 << i)))
- + ap->ops = &ata_dummy_port_ops;
- + }
- +
- + rc = ahci_reset_controller(host);
- + if (rc)
- + return rc;
- +
- + ahci_init_controller(host);
- + ahci_print_info(host, "platform");
- +
- + return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
- + &ahci_platform_sht);
- +}
- +EXPORT_SYMBOL_GPL(ahci_platform_init_host);
- +
- +static void ahci_host_stop(struct ata_host *host)
- +{
- + struct device *dev = host->dev;
- + struct ahci_platform_data *pdata = dev_get_platdata(dev);
- + struct ahci_host_priv *hpriv = host->private_data;
- +
- + if (pdata && pdata->exit)
- + pdata->exit(dev);
- +
- + ahci_platform_disable_resources(hpriv);
- +}
- +
- +#ifdef CONFIG_PM_SLEEP
- +/**
- + * ahci_platform_suspend_host - Suspend an ahci-platform host
- + * @dev: device pointer for the host
- + *
- + * This function does all the usual steps needed to suspend an
- + * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
- + * must be disabled after calling this.
- + *
- + * RETURNS:
- + * 0 on success otherwise a negative error code
- + */
- +int ahci_platform_suspend_host(struct device *dev)
- +{
- + struct ata_host *host = dev_get_drvdata(dev);
- + struct ahci_host_priv *hpriv = host->private_data;
- + void __iomem *mmio = hpriv->mmio;
- + u32 ctl;
- +
- + if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
- + dev_err(dev, "firmware update required for suspend/resume\n");
- + return -EIO;
- + }
- +
- + /*
- + * AHCI spec rev1.1 section 8.3.3:
- + * Software must disable interrupts prior to requesting a
- + * transition of the HBA to D3 state.
- + */
- + ctl = readl(mmio + HOST_CTL);
- + ctl &= ~HOST_IRQ_EN;
- + writel(ctl, mmio + HOST_CTL);
- + readl(mmio + HOST_CTL); /* flush */
- +
- + return ata_host_suspend(host, PMSG_SUSPEND);
- +}
- +EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
- +
- +/**
- + * ahci_platform_resume_host - Resume an ahci-platform host
- + * @dev: device pointer for the host
- + *
- + * This function does all the usual steps needed to resume an ahci-platform
- + * host, note any necessary resources (ie clks, phy, etc.) must be
- + * initialized / enabled before calling this.
- + *
- + * RETURNS:
- + * 0 on success otherwise a negative error code
- + */
- +int ahci_platform_resume_host(struct device *dev)
- +{
- + struct ata_host *host = dev_get_drvdata(dev);
- + int rc;
- +
- + if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
- + rc = ahci_reset_controller(host);
- + if (rc)
- + return rc;
- +
- + ahci_init_controller(host);
- + }
- +
- + ata_host_resume(host);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
- +
- +/**
- + * ahci_platform_suspend - Suspend an ahci-platform device
- + * @dev: the platform device to suspend
- + *
- + * This function suspends the host associated with the device, followed by
- + * disabling all the resources of the device.
- + *
- + * RETURNS:
- + * 0 on success otherwise a negative error code
- + */
- +int ahci_platform_suspend(struct device *dev)
- +{
- + struct ahci_platform_data *pdata = dev_get_platdata(dev);
- + struct ata_host *host = dev_get_drvdata(dev);
- + struct ahci_host_priv *hpriv = host->private_data;
- + int rc;
- +
- + rc = ahci_platform_suspend_host(dev);
- + if (rc)
- + return rc;
- +
- + if (pdata && pdata->suspend) {
- + rc = pdata->suspend(dev);
- + if (rc)
- + goto resume_host;
- + }
- +
- + ahci_platform_disable_resources(hpriv);
- +
- + return 0;
- +
- +resume_host:
- + ahci_platform_resume_host(dev);
- + return rc;
- +}
- +EXPORT_SYMBOL_GPL(ahci_platform_suspend);
- +
- +/**
- + * ahci_platform_resume - Resume an ahci-platform device
- + * @dev: the platform device to resume
- + *
- + * This function enables all the resources of the device followed by
- + * resuming the host associated with the device.
- + *
- + * RETURNS:
- + * 0 on success otherwise a negative error code
- + */
- +int ahci_platform_resume(struct device *dev)
- +{
- + struct ahci_platform_data *pdata = dev_get_platdata(dev);
- + struct ata_host *host = dev_get_drvdata(dev);
- + struct ahci_host_priv *hpriv = host->private_data;
- + int rc;
- +
- + rc = ahci_platform_enable_resources(hpriv);
- + if (rc)
- + return rc;
- +
- + if (pdata && pdata->resume) {
- + rc = pdata->resume(dev);
- + if (rc)
- + goto disable_resources;
- + }
- +
- + rc = ahci_platform_resume_host(dev);
- + if (rc)
- + goto disable_resources;
- +
- + /* We resumed so update PM runtime state */
- + pm_runtime_disable(dev);
- + pm_runtime_set_active(dev);
- + pm_runtime_enable(dev);
- +
- + return 0;
- +
- +disable_resources:
- + ahci_platform_disable_resources(hpriv);
- +
- + return rc;
- +}
- +EXPORT_SYMBOL_GPL(ahci_platform_resume);
- +#endif
- +
- +MODULE_DESCRIPTION("AHCI SATA platform library");
- +MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/ata/libata-core.c linux-3.14.35/drivers/ata/libata-core.c
- --- linux-3.14.35.orig/drivers/ata/libata-core.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/libata-core.c 2015-03-08 14:27:37.513684502 -0500
- @@ -1524,7 +1524,7 @@
- * @dev: Device to which the command is sent
- * @tf: Taskfile registers for the command and the result
- * @cdb: CDB for packet command
- - * @dma_dir: Data tranfer direction of the command
- + * @dma_dir: Data transfer direction of the command
- * @sgl: sg list for the data buffer of the command
- * @n_elem: Number of sg entries
- * @timeout: Timeout in msecs (0 for default)
- @@ -1712,7 +1712,7 @@
- * @dev: Device to which the command is sent
- * @tf: Taskfile registers for the command and the result
- * @cdb: CDB for packet command
- - * @dma_dir: Data tranfer direction of the command
- + * @dma_dir: Data transfer direction of the command
- * @buf: Data buffer of the command
- * @buflen: Length of data buffer
- * @timeout: Timeout in msecs (0 for default)
- diff -Nur linux-3.14.35.orig/drivers/ata/Makefile linux-3.14.35/drivers/ata/Makefile
- --- linux-3.14.35.orig/drivers/ata/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/Makefile 2015-03-08 14:27:37.513684502 -0500
- @@ -4,13 +4,13 @@
- # non-SFF interface
- obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o
- obj-$(CONFIG_SATA_ACARD_AHCI) += acard-ahci.o libahci.o
- -obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o
- +obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o libahci_platform.o
- obj-$(CONFIG_SATA_FSL) += sata_fsl.o
- obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o
- obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
- obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o
- obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o
- -obj-$(CONFIG_AHCI_IMX) += ahci_imx.o
- +obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o
-
- # SFF w/ custom DMA
- obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_acpi.c linux-3.14.35/drivers/ata/pata_acpi.c
- --- linux-3.14.35.orig/drivers/ata/pata_acpi.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_acpi.c 2015-03-08 14:27:37.513684502 -0500
- @@ -7,7 +7,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_amd.c linux-3.14.35/drivers/ata/pata_amd.c
- --- linux-3.14.35.orig/drivers/ata/pata_amd.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_amd.c 2015-03-08 14:27:37.513684502 -0500
- @@ -17,7 +17,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_artop.c linux-3.14.35/drivers/ata/pata_artop.c
- --- linux-3.14.35.orig/drivers/ata/pata_artop.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_artop.c 2015-03-08 14:27:37.513684502 -0500
- @@ -19,7 +19,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_at91.c linux-3.14.35/drivers/ata/pata_at91.c
- --- linux-3.14.35.orig/drivers/ata/pata_at91.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_at91.c 2015-03-08 14:27:37.513684502 -0500
- @@ -18,7 +18,6 @@
-
- #include <linux/kernel.h>
- #include <linux/module.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/gfp.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_atiixp.c linux-3.14.35/drivers/ata/pata_atiixp.c
- --- linux-3.14.35.orig/drivers/ata/pata_atiixp.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_atiixp.c 2015-03-08 14:27:37.513684502 -0500
- @@ -15,7 +15,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_atp867x.c linux-3.14.35/drivers/ata/pata_atp867x.c
- --- linux-3.14.35.orig/drivers/ata/pata_atp867x.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_atp867x.c 2015-03-08 14:27:37.513684502 -0500
- @@ -29,7 +29,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_cmd640.c linux-3.14.35/drivers/ata/pata_cmd640.c
- --- linux-3.14.35.orig/drivers/ata/pata_cmd640.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_cmd640.c 2015-03-08 14:27:37.513684502 -0500
- @@ -15,7 +15,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/gfp.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_cmd64x.c linux-3.14.35/drivers/ata/pata_cmd64x.c
- --- linux-3.14.35.orig/drivers/ata/pata_cmd64x.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_cmd64x.c 2015-03-08 14:27:37.513684502 -0500
- @@ -26,7 +26,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_cs5520.c linux-3.14.35/drivers/ata/pata_cs5520.c
- --- linux-3.14.35.orig/drivers/ata/pata_cs5520.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_cs5520.c 2015-03-08 14:27:37.513684502 -0500
- @@ -34,7 +34,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_cs5530.c linux-3.14.35/drivers/ata/pata_cs5530.c
- --- linux-3.14.35.orig/drivers/ata/pata_cs5530.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_cs5530.c 2015-03-08 14:27:37.513684502 -0500
- @@ -26,7 +26,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_cs5535.c linux-3.14.35/drivers/ata/pata_cs5535.c
- --- linux-3.14.35.orig/drivers/ata/pata_cs5535.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_cs5535.c 2015-03-08 14:27:37.513684502 -0500
- @@ -31,7 +31,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_cs5536.c linux-3.14.35/drivers/ata/pata_cs5536.c
- --- linux-3.14.35.orig/drivers/ata/pata_cs5536.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_cs5536.c 2015-03-08 14:27:37.513684502 -0500
- @@ -33,7 +33,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/libata.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_cypress.c linux-3.14.35/drivers/ata/pata_cypress.c
- --- linux-3.14.35.orig/drivers/ata/pata_cypress.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_cypress.c 2015-03-08 14:27:37.513684502 -0500
- @@ -11,7 +11,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_efar.c linux-3.14.35/drivers/ata/pata_efar.c
- --- linux-3.14.35.orig/drivers/ata/pata_efar.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_efar.c 2015-03-08 14:27:37.513684502 -0500
- @@ -14,7 +14,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_ep93xx.c linux-3.14.35/drivers/ata/pata_ep93xx.c
- --- linux-3.14.35.orig/drivers/ata/pata_ep93xx.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_ep93xx.c 2015-03-08 14:27:37.513684502 -0500
- @@ -34,7 +34,6 @@
- #include <linux/err.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <scsi/scsi_host.h>
- #include <linux/ata.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_hpt366.c linux-3.14.35/drivers/ata/pata_hpt366.c
- --- linux-3.14.35.orig/drivers/ata/pata_hpt366.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_hpt366.c 2015-03-08 14:27:37.513684502 -0500
- @@ -19,7 +19,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_hpt37x.c linux-3.14.35/drivers/ata/pata_hpt37x.c
- --- linux-3.14.35.orig/drivers/ata/pata_hpt37x.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_hpt37x.c 2015-03-08 14:27:37.517684502 -0500
- @@ -19,7 +19,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_hpt3x2n.c linux-3.14.35/drivers/ata/pata_hpt3x2n.c
- --- linux-3.14.35.orig/drivers/ata/pata_hpt3x2n.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_hpt3x2n.c 2015-03-08 14:27:37.517684502 -0500
- @@ -20,7 +20,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_hpt3x3.c linux-3.14.35/drivers/ata/pata_hpt3x3.c
- --- linux-3.14.35.orig/drivers/ata/pata_hpt3x3.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_hpt3x3.c 2015-03-08 14:27:37.517684502 -0500
- @@ -16,7 +16,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_imx.c linux-3.14.35/drivers/ata/pata_imx.c
- --- linux-3.14.35.orig/drivers/ata/pata_imx.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_imx.c 2015-03-08 14:27:37.517684502 -0500
- @@ -15,7 +15,6 @@
- */
- #include <linux/kernel.h>
- #include <linux/module.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <scsi/scsi_host.h>
- #include <linux/ata.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_it8213.c linux-3.14.35/drivers/ata/pata_it8213.c
- --- linux-3.14.35.orig/drivers/ata/pata_it8213.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_it8213.c 2015-03-08 14:27:37.517684502 -0500
- @@ -10,7 +10,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_it821x.c linux-3.14.35/drivers/ata/pata_it821x.c
- --- linux-3.14.35.orig/drivers/ata/pata_it821x.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_it821x.c 2015-03-08 14:27:37.517684502 -0500
- @@ -72,7 +72,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/slab.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_jmicron.c linux-3.14.35/drivers/ata/pata_jmicron.c
- --- linux-3.14.35.orig/drivers/ata/pata_jmicron.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_jmicron.c 2015-03-08 14:27:37.517684502 -0500
- @@ -10,7 +10,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_marvell.c linux-3.14.35/drivers/ata/pata_marvell.c
- --- linux-3.14.35.orig/drivers/ata/pata_marvell.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_marvell.c 2015-03-08 14:27:37.517684502 -0500
- @@ -11,7 +11,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_mpiix.c linux-3.14.35/drivers/ata/pata_mpiix.c
- --- linux-3.14.35.orig/drivers/ata/pata_mpiix.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_mpiix.c 2015-03-08 14:27:37.517684502 -0500
- @@ -28,7 +28,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_netcell.c linux-3.14.35/drivers/ata/pata_netcell.c
- --- linux-3.14.35.orig/drivers/ata/pata_netcell.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_netcell.c 2015-03-08 14:27:37.517684502 -0500
- @@ -7,7 +7,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_ninja32.c linux-3.14.35/drivers/ata/pata_ninja32.c
- --- linux-3.14.35.orig/drivers/ata/pata_ninja32.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_ninja32.c 2015-03-08 14:27:37.517684502 -0500
- @@ -37,7 +37,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_ns87410.c linux-3.14.35/drivers/ata/pata_ns87410.c
- --- linux-3.14.35.orig/drivers/ata/pata_ns87410.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_ns87410.c 2015-03-08 14:27:37.517684502 -0500
- @@ -20,7 +20,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_ns87415.c linux-3.14.35/drivers/ata/pata_ns87415.c
- --- linux-3.14.35.orig/drivers/ata/pata_ns87415.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_ns87415.c 2015-03-08 14:27:37.517684502 -0500
- @@ -25,7 +25,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_oldpiix.c linux-3.14.35/drivers/ata/pata_oldpiix.c
- --- linux-3.14.35.orig/drivers/ata/pata_oldpiix.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_oldpiix.c 2015-03-08 14:27:37.517684502 -0500
- @@ -16,7 +16,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_opti.c linux-3.14.35/drivers/ata/pata_opti.c
- --- linux-3.14.35.orig/drivers/ata/pata_opti.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_opti.c 2015-03-08 14:27:37.517684502 -0500
- @@ -26,7 +26,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_optidma.c linux-3.14.35/drivers/ata/pata_optidma.c
- --- linux-3.14.35.orig/drivers/ata/pata_optidma.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_optidma.c 2015-03-08 14:27:37.517684502 -0500
- @@ -25,7 +25,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_pcmcia.c linux-3.14.35/drivers/ata/pata_pcmcia.c
- --- linux-3.14.35.orig/drivers/ata/pata_pcmcia.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_pcmcia.c 2015-03-08 14:27:37.517684502 -0500
- @@ -26,7 +26,6 @@
-
- #include <linux/kernel.h>
- #include <linux/module.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/slab.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_pdc2027x.c linux-3.14.35/drivers/ata/pata_pdc2027x.c
- --- linux-3.14.35.orig/drivers/ata/pata_pdc2027x.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_pdc2027x.c 2015-03-08 14:27:37.517684502 -0500
- @@ -25,7 +25,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_pdc202xx_old.c linux-3.14.35/drivers/ata/pata_pdc202xx_old.c
- --- linux-3.14.35.orig/drivers/ata/pata_pdc202xx_old.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_pdc202xx_old.c 2015-03-08 14:27:37.517684502 -0500
- @@ -15,7 +15,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_piccolo.c linux-3.14.35/drivers/ata/pata_piccolo.c
- --- linux-3.14.35.orig/drivers/ata/pata_piccolo.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_piccolo.c 2015-03-08 14:27:37.517684502 -0500
- @@ -18,7 +18,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_platform.c linux-3.14.35/drivers/ata/pata_platform.c
- --- linux-3.14.35.orig/drivers/ata/pata_platform.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_platform.c 2015-03-08 14:27:37.517684502 -0500
- @@ -13,7 +13,6 @@
- */
- #include <linux/kernel.h>
- #include <linux/module.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <scsi/scsi_host.h>
- #include <linux/ata.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_pxa.c linux-3.14.35/drivers/ata/pata_pxa.c
- --- linux-3.14.35.orig/drivers/ata/pata_pxa.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_pxa.c 2015-03-08 14:27:37.517684502 -0500
- @@ -20,7 +20,6 @@
-
- #include <linux/kernel.h>
- #include <linux/module.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/ata.h>
- #include <linux/libata.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_radisys.c linux-3.14.35/drivers/ata/pata_radisys.c
- --- linux-3.14.35.orig/drivers/ata/pata_radisys.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_radisys.c 2015-03-08 14:27:37.521684501 -0500
- @@ -15,7 +15,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_rdc.c linux-3.14.35/drivers/ata/pata_rdc.c
- --- linux-3.14.35.orig/drivers/ata/pata_rdc.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_rdc.c 2015-03-08 14:27:37.521684501 -0500
- @@ -24,7 +24,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_rz1000.c linux-3.14.35/drivers/ata/pata_rz1000.c
- --- linux-3.14.35.orig/drivers/ata/pata_rz1000.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_rz1000.c 2015-03-08 14:27:37.521684501 -0500
- @@ -14,7 +14,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_sc1200.c linux-3.14.35/drivers/ata/pata_sc1200.c
- --- linux-3.14.35.orig/drivers/ata/pata_sc1200.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_sc1200.c 2015-03-08 14:27:37.521684501 -0500
- @@ -32,7 +32,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_scc.c linux-3.14.35/drivers/ata/pata_scc.c
- --- linux-3.14.35.orig/drivers/ata/pata_scc.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_scc.c 2015-03-08 14:27:37.521684501 -0500
- @@ -35,7 +35,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_sch.c linux-3.14.35/drivers/ata/pata_sch.c
- --- linux-3.14.35.orig/drivers/ata/pata_sch.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_sch.c 2015-03-08 14:27:37.521684501 -0500
- @@ -27,7 +27,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_serverworks.c linux-3.14.35/drivers/ata/pata_serverworks.c
- --- linux-3.14.35.orig/drivers/ata/pata_serverworks.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_serverworks.c 2015-03-08 14:27:37.521684501 -0500
- @@ -34,7 +34,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_sil680.c linux-3.14.35/drivers/ata/pata_sil680.c
- --- linux-3.14.35.orig/drivers/ata/pata_sil680.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_sil680.c 2015-03-08 14:27:37.521684501 -0500
- @@ -25,7 +25,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_sis.c linux-3.14.35/drivers/ata/pata_sis.c
- --- linux-3.14.35.orig/drivers/ata/pata_sis.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_sis.c 2015-03-08 14:27:37.521684501 -0500
- @@ -26,7 +26,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_sl82c105.c linux-3.14.35/drivers/ata/pata_sl82c105.c
- --- linux-3.14.35.orig/drivers/ata/pata_sl82c105.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_sl82c105.c 2015-03-08 14:27:37.521684501 -0500
- @@ -19,7 +19,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_triflex.c linux-3.14.35/drivers/ata/pata_triflex.c
- --- linux-3.14.35.orig/drivers/ata/pata_triflex.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_triflex.c 2015-03-08 14:27:37.521684501 -0500
- @@ -36,7 +36,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <scsi/scsi_host.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pata_via.c linux-3.14.35/drivers/ata/pata_via.c
- --- linux-3.14.35.orig/drivers/ata/pata_via.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pata_via.c 2015-03-08 14:27:37.521684501 -0500
- @@ -55,7 +55,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/gfp.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/pdc_adma.c linux-3.14.35/drivers/ata/pdc_adma.c
- --- linux-3.14.35.orig/drivers/ata/pdc_adma.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/pdc_adma.c 2015-03-08 14:27:37.521684501 -0500
- @@ -36,7 +36,6 @@
- #include <linux/module.h>
- #include <linux/gfp.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/sata_dwc_460ex.c linux-3.14.35/drivers/ata/sata_dwc_460ex.c
- --- linux-3.14.35.orig/drivers/ata/sata_dwc_460ex.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/sata_dwc_460ex.c 2015-03-08 14:27:37.521684501 -0500
- @@ -29,7 +29,6 @@
-
- #include <linux/kernel.h>
- #include <linux/module.h>
- -#include <linux/init.h>
- #include <linux/device.h>
- #include <linux/of_address.h>
- #include <linux/of_irq.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/sata_highbank.c linux-3.14.35/drivers/ata/sata_highbank.c
- --- linux-3.14.35.orig/drivers/ata/sata_highbank.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/sata_highbank.c 2015-03-08 14:27:37.521684501 -0500
- @@ -19,7 +19,6 @@
- #include <linux/kernel.h>
- #include <linux/gfp.h>
- #include <linux/module.h>
- -#include <linux/init.h>
- #include <linux/types.h>
- #include <linux/err.h>
- #include <linux/io.h>
- @@ -403,6 +402,7 @@
- static const unsigned long timing[] = { 5, 100, 500};
- struct ata_port *ap = link->ap;
- struct ahci_port_priv *pp = ap->private_data;
- + struct ahci_host_priv *hpriv = ap->host->private_data;
- u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
- struct ata_taskfile tf;
- bool online;
- @@ -431,7 +431,7 @@
- break;
- } while (!online && retry--);
-
- - ahci_start_engine(ap);
- + hpriv->start_engine(ap);
-
- if (online)
- *class = ahci_dev_classify(ap);
- diff -Nur linux-3.14.35.orig/drivers/ata/sata_nv.c linux-3.14.35/drivers/ata/sata_nv.c
- --- linux-3.14.35.orig/drivers/ata/sata_nv.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/sata_nv.c 2015-03-08 14:27:37.521684501 -0500
- @@ -40,7 +40,6 @@
- #include <linux/module.h>
- #include <linux/gfp.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/sata_promise.c linux-3.14.35/drivers/ata/sata_promise.c
- --- linux-3.14.35.orig/drivers/ata/sata_promise.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/sata_promise.c 2015-03-08 14:27:37.521684501 -0500
- @@ -35,7 +35,6 @@
- #include <linux/module.h>
- #include <linux/gfp.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/sata_qstor.c linux-3.14.35/drivers/ata/sata_qstor.c
- --- linux-3.14.35.orig/drivers/ata/sata_qstor.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/sata_qstor.c 2015-03-08 14:27:37.525684501 -0500
- @@ -31,7 +31,6 @@
- #include <linux/module.h>
- #include <linux/gfp.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/sata_sil.c linux-3.14.35/drivers/ata/sata_sil.c
- --- linux-3.14.35.orig/drivers/ata/sata_sil.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/sata_sil.c 2015-03-08 14:27:37.525684501 -0500
- @@ -37,7 +37,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/sata_sis.c linux-3.14.35/drivers/ata/sata_sis.c
- --- linux-3.14.35.orig/drivers/ata/sata_sis.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/sata_sis.c 2015-03-08 14:27:37.525684501 -0500
- @@ -33,7 +33,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/sata_svw.c linux-3.14.35/drivers/ata/sata_svw.c
- --- linux-3.14.35.orig/drivers/ata/sata_svw.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/sata_svw.c 2015-03-08 14:27:37.525684501 -0500
- @@ -39,7 +39,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/sata_sx4.c linux-3.14.35/drivers/ata/sata_sx4.c
- --- linux-3.14.35.orig/drivers/ata/sata_sx4.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/sata_sx4.c 2015-03-08 14:27:37.525684501 -0500
- @@ -82,7 +82,6 @@
- #include <linux/module.h>
- #include <linux/pci.h>
- #include <linux/slab.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/sata_uli.c linux-3.14.35/drivers/ata/sata_uli.c
- --- linux-3.14.35.orig/drivers/ata/sata_uli.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/sata_uli.c 2015-03-08 14:27:37.525684501 -0500
- @@ -28,7 +28,6 @@
- #include <linux/module.h>
- #include <linux/gfp.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/sata_via.c linux-3.14.35/drivers/ata/sata_via.c
- --- linux-3.14.35.orig/drivers/ata/sata_via.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/sata_via.c 2015-03-08 14:27:37.525684501 -0500
- @@ -36,7 +36,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- diff -Nur linux-3.14.35.orig/drivers/ata/sata_vsc.c linux-3.14.35/drivers/ata/sata_vsc.c
- --- linux-3.14.35.orig/drivers/ata/sata_vsc.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ata/sata_vsc.c 2015-03-08 14:27:37.525684501 -0500
- @@ -37,7 +37,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- -#include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- diff -Nur linux-3.14.35.orig/drivers/base/bus.c linux-3.14.35/drivers/base/bus.c
- --- linux-3.14.35.orig/drivers/base/bus.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/base/bus.c 2015-03-08 14:27:37.525684501 -0500
- @@ -1220,7 +1220,7 @@
- * with the name of the subsystem. The root device can carry subsystem-
- * wide attributes. All registered devices are below this single root
- * device and are named after the subsystem with a simple enumeration
- - * number appended. The registered devices are not explicitely named;
- + * number appended. The registered devices are not explicitly named;
- * only 'id' in the device needs to be set.
- *
- * Do not use this interface for anything new, it exists for compatibility
- diff -Nur linux-3.14.35.orig/drivers/base/cpu.c linux-3.14.35/drivers/base/cpu.c
- --- linux-3.14.35.orig/drivers/base/cpu.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/base/cpu.c 2015-03-08 14:27:37.525684501 -0500
- @@ -15,6 +15,7 @@
- #include <linux/percpu.h>
- #include <linux/acpi.h>
- #include <linux/of.h>
- +#include <linux/cpufeature.h>
-
- #include "base.h"
-
- @@ -286,6 +287,45 @@
- */
- }
-
- +#ifdef CONFIG_HAVE_CPU_AUTOPROBE
- +#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
- +static ssize_t print_cpu_modalias(struct device *dev,
- + struct device_attribute *attr,
- + char *buf)
- +{
- + ssize_t n;
- + u32 i;
- +
- + n = sprintf(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:",
- + CPU_FEATURE_TYPEVAL);
- +
- + for (i = 0; i < MAX_CPU_FEATURES; i++)
- + if (cpu_have_feature(i)) {
- + if (PAGE_SIZE < n + sizeof(",XXXX\n")) {
- + WARN(1, "CPU features overflow page\n");
- + break;
- + }
- + n += sprintf(&buf[n], ",%04X", i);
- + }
- + buf[n++] = '\n';
- + return n;
- +}
- +#else
- +#define print_cpu_modalias arch_print_cpu_modalias
- +#endif
- +
- +static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
- +{
- + char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
- + if (buf) {
- + print_cpu_modalias(NULL, NULL, buf);
- + add_uevent_var(env, "MODALIAS=%s", buf);
- + kfree(buf);
- + }
- + return 0;
- +}
- +#endif
- +
- /*
- * register_cpu - Setup a sysfs device for a CPU.
- * @cpu - cpu->hotpluggable field set to 1 will generate a control file in
- @@ -306,8 +346,8 @@
- cpu->dev.offline_disabled = !cpu->hotpluggable;
- cpu->dev.offline = !cpu_online(num);
- cpu->dev.of_node = of_get_cpu_node(num, NULL);
- -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
- - cpu->dev.bus->uevent = arch_cpu_uevent;
- +#ifdef CONFIG_HAVE_CPU_AUTOPROBE
- + cpu->dev.bus->uevent = cpu_uevent;
- #endif
- cpu->dev.groups = common_cpu_attr_groups;
- if (cpu->hotpluggable)
- @@ -330,8 +370,8 @@
- }
- EXPORT_SYMBOL_GPL(get_cpu_device);
-
- -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
- -static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL);
- +#ifdef CONFIG_HAVE_CPU_AUTOPROBE
- +static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL);
- #endif
-
- static struct attribute *cpu_root_attrs[] = {
- @@ -344,7 +384,7 @@
- &cpu_attrs[2].attr.attr,
- &dev_attr_kernel_max.attr,
- &dev_attr_offline.attr,
- -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
- +#ifdef CONFIG_HAVE_CPU_AUTOPROBE
- &dev_attr_modalias.attr,
- #endif
- NULL
- diff -Nur linux-3.14.35.orig/drivers/base/dma-buf.c linux-3.14.35/drivers/base/dma-buf.c
- --- linux-3.14.35.orig/drivers/base/dma-buf.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/base/dma-buf.c 2015-03-08 14:27:37.525684501 -0500
- @@ -251,9 +251,8 @@
- * @dmabuf: [in] buffer to attach device to.
- * @dev: [in] device to be attached.
- *
- - * Returns struct dma_buf_attachment * for this attachment; may return negative
- - * error codes.
- - *
- + * Returns struct dma_buf_attachment * for this attachment; returns ERR_PTR on
- + * error.
- */
- struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
- struct device *dev)
- @@ -319,9 +318,8 @@
- * @attach: [in] attachment whose scatterlist is to be returned
- * @direction: [in] direction of DMA transfer
- *
- - * Returns sg_table containing the scatterlist to be returned; may return NULL
- - * or ERR_PTR.
- - *
- + * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR
- + * on error.
- */
- struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
- enum dma_data_direction direction)
- @@ -334,6 +332,8 @@
- return ERR_PTR(-EINVAL);
-
- sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
- + if (!sg_table)
- + sg_table = ERR_PTR(-ENOMEM);
-
- return sg_table;
- }
- @@ -544,6 +544,8 @@
- * These calls are optional in drivers. The intended use for them
- * is for mapping objects linear in kernel space for high use objects.
- * Please attempt to use kmap/kunmap before thinking about these interfaces.
- + *
- + * Returns NULL on error.
- */
- void *dma_buf_vmap(struct dma_buf *dmabuf)
- {
- @@ -566,7 +568,9 @@
- BUG_ON(dmabuf->vmap_ptr);
-
- ptr = dmabuf->ops->vmap(dmabuf);
- - if (IS_ERR_OR_NULL(ptr))
- + if (WARN_ON_ONCE(IS_ERR(ptr)))
- + ptr = NULL;
- + if (!ptr)
- goto out_unlock;
-
- dmabuf->vmap_ptr = ptr;
- diff -Nur linux-3.14.35.orig/drivers/base/dma-contiguous.c linux-3.14.35/drivers/base/dma-contiguous.c
- --- linux-3.14.35.orig/drivers/base/dma-contiguous.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/base/dma-contiguous.c 2015-03-08 14:27:37.525684501 -0500
- @@ -24,22 +24,9 @@
-
- #include <linux/memblock.h>
- #include <linux/err.h>
- -#include <linux/mm.h>
- -#include <linux/mutex.h>
- -#include <linux/page-isolation.h>
- #include <linux/sizes.h>
- -#include <linux/slab.h>
- -#include <linux/swap.h>
- -#include <linux/mm_types.h>
- #include <linux/dma-contiguous.h>
- -
- -struct cma {
- - unsigned long base_pfn;
- - unsigned long count;
- - unsigned long *bitmap;
- -};
- -
- -struct cma *dma_contiguous_default_area;
- +#include <linux/cma.h>
-
- #ifdef CONFIG_CMA_SIZE_MBYTES
- #define CMA_SIZE_MBYTES CONFIG_CMA_SIZE_MBYTES
- @@ -47,6 +34,8 @@
- #define CMA_SIZE_MBYTES 0
- #endif
-
- +struct cma *dma_contiguous_default_area;
- +
- /*
- * Default global CMA area size can be defined in kernel's .config.
- * This is useful mainly for distro maintainers to create a kernel
- @@ -59,11 +48,22 @@
- */
- static const phys_addr_t size_bytes = CMA_SIZE_MBYTES * SZ_1M;
- static phys_addr_t size_cmdline = -1;
- +static phys_addr_t base_cmdline;
- +static phys_addr_t limit_cmdline;
-
- static int __init early_cma(char *p)
- {
- pr_debug("%s(%s)\n", __func__, p);
- size_cmdline = memparse(p, &p);
- + if (*p != '@')
- + return 0;
- + base_cmdline = memparse(p + 1, &p);
- + if (*p != '-') {
- + limit_cmdline = base_cmdline + size_cmdline;
- + return 0;
- + }
- + limit_cmdline = memparse(p + 1, &p);
- +
- return 0;
- }
- early_param("cma", early_cma);
- @@ -107,11 +107,18 @@
- void __init dma_contiguous_reserve(phys_addr_t limit)
- {
- phys_addr_t selected_size = 0;
- + phys_addr_t selected_base = 0;
- + phys_addr_t selected_limit = limit;
- + bool fixed = false;
-
- pr_debug("%s(limit %08lx)\n", __func__, (unsigned long)limit);
-
- if (size_cmdline != -1) {
- selected_size = size_cmdline;
- + selected_base = base_cmdline;
- + selected_limit = min_not_zero(limit_cmdline, limit);
- + if (base_cmdline + size_cmdline == limit_cmdline)
- + fixed = true;
- } else {
- #ifdef CONFIG_CMA_SIZE_SEL_MBYTES
- selected_size = size_bytes;
- @@ -128,68 +135,12 @@
- pr_debug("%s: reserving %ld MiB for global area\n", __func__,
- (unsigned long)selected_size / SZ_1M);
-
- - dma_contiguous_reserve_area(selected_size, 0, limit,
- - &dma_contiguous_default_area);
- - }
- -};
- -
- -static DEFINE_MUTEX(cma_mutex);
- -
- -static int __init cma_activate_area(struct cma *cma)
- -{
- - int bitmap_size = BITS_TO_LONGS(cma->count) * sizeof(long);
- - unsigned long base_pfn = cma->base_pfn, pfn = base_pfn;
- - unsigned i = cma->count >> pageblock_order;
- - struct zone *zone;
- -
- - cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
- -
- - if (!cma->bitmap)
- - return -ENOMEM;
- -
- - WARN_ON_ONCE(!pfn_valid(pfn));
- - zone = page_zone(pfn_to_page(pfn));
- -
- - do {
- - unsigned j;
- - base_pfn = pfn;
- - for (j = pageblock_nr_pages; j; --j, pfn++) {
- - WARN_ON_ONCE(!pfn_valid(pfn));
- - /*
- - * alloc_contig_range requires the pfn range
- - * specified to be in the same zone. Make this
- - * simple by forcing the entire CMA resv range
- - * to be in the same zone.
- - */
- - if (page_zone(pfn_to_page(pfn)) != zone)
- - goto err;
- - }
- - init_cma_reserved_pageblock(pfn_to_page(base_pfn));
- - } while (--i);
- -
- - return 0;
- -
- -err:
- - kfree(cma->bitmap);
- - return -EINVAL;
- -}
- -
- -static struct cma cma_areas[MAX_CMA_AREAS];
- -static unsigned cma_area_count;
- -
- -static int __init cma_init_reserved_areas(void)
- -{
- - int i;
- -
- - for (i = 0; i < cma_area_count; i++) {
- - int ret = cma_activate_area(&cma_areas[i]);
- - if (ret)
- - return ret;
- + dma_contiguous_reserve_area(selected_size, selected_base,
- + selected_limit,
- + &dma_contiguous_default_area,
- + fixed);
- }
- -
- - return 0;
- }
- -core_initcall(cma_init_reserved_areas);
-
- /**
- * dma_contiguous_reserve_area() - reserve custom contiguous area
- @@ -197,78 +148,32 @@
- * @base: Base address of the reserved area optional, use 0 for any
- * @limit: End address of the reserved memory (optional, 0 for any).
- * @res_cma: Pointer to store the created cma region.
- + * @fixed: hint about where to place the reserved area
- *
- * This function reserves memory from early allocator. It should be
- * called by arch specific code once the early allocator (memblock or bootmem)
- * has been activated and all other subsystems have already allocated/reserved
- * memory. This function allows to create custom reserved areas for specific
- * devices.
- + *
- + * If @fixed is true, reserve contiguous area at exactly @base. If false,
- + * reserve in range from @base to @limit.
- */
- int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
- - phys_addr_t limit, struct cma **res_cma)
- + phys_addr_t limit, struct cma **res_cma,
- + bool fixed)
- {
- - struct cma *cma = &cma_areas[cma_area_count];
- - phys_addr_t alignment;
- - int ret = 0;
- -
- - pr_debug("%s(size %lx, base %08lx, limit %08lx)\n", __func__,
- - (unsigned long)size, (unsigned long)base,
- - (unsigned long)limit);
- -
- - /* Sanity checks */
- - if (cma_area_count == ARRAY_SIZE(cma_areas)) {
- - pr_err("Not enough slots for CMA reserved regions!\n");
- - return -ENOSPC;
- - }
- -
- - if (!size)
- - return -EINVAL;
- -
- - /* Sanitise input arguments */
- - alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
- - base = ALIGN(base, alignment);
- - size = ALIGN(size, alignment);
- - limit &= ~(alignment - 1);
- -
- - /* Reserve memory */
- - if (base) {
- - if (memblock_is_region_reserved(base, size) ||
- - memblock_reserve(base, size) < 0) {
- - ret = -EBUSY;
- - goto err;
- - }
- - } else {
- - /*
- - * Use __memblock_alloc_base() since
- - * memblock_alloc_base() panic()s.
- - */
- - phys_addr_t addr = __memblock_alloc_base(size, alignment, limit);
- - if (!addr) {
- - ret = -ENOMEM;
- - goto err;
- - } else {
- - base = addr;
- - }
- - }
- -
- - /*
- - * Each reserved area must be initialised later, when more kernel
- - * subsystems (like slab allocator) are available.
- - */
- - cma->base_pfn = PFN_DOWN(base);
- - cma->count = size >> PAGE_SHIFT;
- - *res_cma = cma;
- - cma_area_count++;
- + int ret;
-
- - pr_info("CMA: reserved %ld MiB at %08lx\n", (unsigned long)size / SZ_1M,
- - (unsigned long)base);
- + ret = cma_declare_contiguous(base, size, limit, 0, 0, fixed, res_cma);
- + if (ret)
- + return ret;
-
- /* Architecture specific contiguous memory fixup. */
- - dma_contiguous_early_fixup(base, size);
- + dma_contiguous_early_fixup(cma_get_base(*res_cma),
- + cma_get_size(*res_cma));
- +
- return 0;
- -err:
- - pr_err("CMA: failed to reserve %ld MiB\n", (unsigned long)size / SZ_1M);
- - return ret;
- }
-
- /**
- @@ -279,57 +184,16 @@
- *
- * This function allocates memory buffer for specified device. It uses
- * device specific contiguous memory area if available or the default
- - * global one. Requires architecture specific get_dev_cma_area() helper
- + * global one. Requires architecture specific dev_get_cma_area() helper
- * function.
- */
- struct page *dma_alloc_from_contiguous(struct device *dev, int count,
- unsigned int align)
- {
- - unsigned long mask, pfn, pageno, start = 0;
- - struct cma *cma = dev_get_cma_area(dev);
- - struct page *page = NULL;
- - int ret;
- -
- - if (!cma || !cma->count)
- - return NULL;
- -
- if (align > CONFIG_CMA_ALIGNMENT)
- align = CONFIG_CMA_ALIGNMENT;
-
- - pr_debug("%s(cma %p, count %d, align %d)\n", __func__, (void *)cma,
- - count, align);
- -
- - if (!count)
- - return NULL;
- -
- - mask = (1 << align) - 1;
- -
- - mutex_lock(&cma_mutex);
- -
- - for (;;) {
- - pageno = bitmap_find_next_zero_area(cma->bitmap, cma->count,
- - start, count, mask);
- - if (pageno >= cma->count)
- - break;
- -
- - pfn = cma->base_pfn + pageno;
- - ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA);
- - if (ret == 0) {
- - bitmap_set(cma->bitmap, pageno, count);
- - page = pfn_to_page(pfn);
- - break;
- - } else if (ret != -EBUSY) {
- - break;
- - }
- - pr_debug("%s(): memory range at %p is busy, retrying\n",
- - __func__, pfn_to_page(pfn));
- - /* try again with a bit different memory target */
- - start = pageno + mask + 1;
- - }
- -
- - mutex_unlock(&cma_mutex);
- - pr_debug("%s(): returned %p\n", __func__, page);
- - return page;
- + return cma_alloc(dev_get_cma_area(dev), count, align);
- }
-
- /**
- @@ -345,25 +209,5 @@
- bool dma_release_from_contiguous(struct device *dev, struct page *pages,
- int count)
- {
- - struct cma *cma = dev_get_cma_area(dev);
- - unsigned long pfn;
- -
- - if (!cma || !pages)
- - return false;
- -
- - pr_debug("%s(page %p)\n", __func__, (void *)pages);
- -
- - pfn = page_to_pfn(pages);
- -
- - if (pfn < cma->base_pfn || pfn >= cma->base_pfn + cma->count)
- - return false;
- -
- - VM_BUG_ON(pfn + count > cma->base_pfn + cma->count);
- -
- - mutex_lock(&cma_mutex);
- - bitmap_clear(cma->bitmap, pfn - cma->base_pfn, count);
- - free_contig_range(pfn, count);
- - mutex_unlock(&cma_mutex);
- -
- - return true;
- + return cma_release(dev_get_cma_area(dev), pages, count);
- }
- diff -Nur linux-3.14.35.orig/drivers/base/Kconfig linux-3.14.35/drivers/base/Kconfig
- --- linux-3.14.35.orig/drivers/base/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/base/Kconfig 2015-03-08 14:27:37.525684501 -0500
- @@ -185,6 +185,14 @@
- bool
- default n
-
- +config HAVE_CPU_AUTOPROBE
- + def_bool ARCH_HAS_CPU_AUTOPROBE
- +
- +config GENERIC_CPU_AUTOPROBE
- + bool
- + depends on !ARCH_HAS_CPU_AUTOPROBE
- + select HAVE_CPU_AUTOPROBE
- +
- config SOC_BUS
- bool
-
- @@ -266,16 +274,6 @@
-
- If unsure, leave the default value "8".
-
- -config CMA_AREAS
- - int "Maximum count of the CMA device-private areas"
- - default 7
- - help
- - CMA allows to create CMA areas for particular devices. This parameter
- - sets the maximum number of such device private CMA areas in the
- - system.
- -
- - If unsure, leave the default value "7".
- -
- endif
-
- endmenu
- diff -Nur linux-3.14.35.orig/drivers/bus/arm-cci.c linux-3.14.35/drivers/bus/arm-cci.c
- --- linux-3.14.35.orig/drivers/bus/arm-cci.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/bus/arm-cci.c 2015-03-08 14:27:37.525684501 -0500
- @@ -26,6 +26,7 @@
-
- #include <asm/cacheflush.h>
- #include <asm/irq_regs.h>
- +#include <asm/psci.h>
- #include <asm/pmu.h>
- #include <asm/smp_plat.h>
-
- @@ -544,6 +545,7 @@
-
- cci_pmu->plat_device = pdev;
- cci_pmu->num_events = pmu_get_max_counters();
- + cpumask_setall(&cci_pmu->valid_cpus);
-
- return armpmu_register(cci_pmu, -1);
- }
- @@ -969,6 +971,11 @@
- const char *match_str;
- bool is_ace;
-
- + if (psci_probe() == 0) {
- + pr_debug("psci found. Aborting cci probe\n");
- + return -ENODEV;
- + }
- +
- np = of_find_matching_node(NULL, arm_cci_matches);
- if (!np)
- return -ENODEV;
- diff -Nur linux-3.14.35.orig/drivers/char/fsl_otp.c linux-3.14.35/drivers/char/fsl_otp.c
- --- linux-3.14.35.orig/drivers/char/fsl_otp.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/char/fsl_otp.c 2015-03-08 14:27:37.525684501 -0500
- @@ -0,0 +1,299 @@
- +/*
- + * Freescale On-Chip OTP driver
- + *
- + * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + */
- +
- +#include <linux/clk.h>
- +#include <linux/delay.h>
- +#include <linux/err.h>
- +#include <linux/init.h>
- +#include <linux/io.h>
- +#include <linux/kobject.h>
- +#include <linux/module.h>
- +#include <linux/mutex.h>
- +#include <linux/of.h>
- +#include <linux/platform_device.h>
- +#include <linux/slab.h>
- +#include <linux/sysfs.h>
- +
- +#define HW_OCOTP_CTRL 0x00000000
- +#define HW_OCOTP_CTRL_SET 0x00000004
- +#define BP_OCOTP_CTRL_WR_UNLOCK 16
- +#define BM_OCOTP_CTRL_WR_UNLOCK 0xFFFF0000
- +#define BM_OCOTP_CTRL_RELOAD_SHADOWS 0x00000400
- +#define BM_OCOTP_CTRL_ERROR 0x00000200
- +#define BM_OCOTP_CTRL_BUSY 0x00000100
- +#define BP_OCOTP_CTRL_ADDR 0
- +#define BM_OCOTP_CTRL_ADDR 0x0000007F
- +
- +#define HW_OCOTP_TIMING 0x00000010
- +#define BP_OCOTP_TIMING_STROBE_READ 16
- +#define BM_OCOTP_TIMING_STROBE_READ 0x003F0000
- +#define BP_OCOTP_TIMING_RELAX 12
- +#define BM_OCOTP_TIMING_RELAX 0x0000F000
- +#define BP_OCOTP_TIMING_STROBE_PROG 0
- +#define BM_OCOTP_TIMING_STROBE_PROG 0x00000FFF
- +
- +#define HW_OCOTP_DATA 0x00000020
- +
- +#define HW_OCOTP_CUST_N(n) (0x00000400 + (n) * 0x10)
- +#define BF(value, field) (((value) << BP_##field) & BM_##field)
- +
- +#define DEF_RELAX 20 /* > 16.5ns */
- +
- +#define BANK(a, b, c, d, e, f, g, h) { \
- + "HW_OCOTP_"#a, "HW_OCOTP_"#b, "HW_OCOTP_"#c, "HW_OCOTP_"#d, \
- + "HW_OCOTP_"#e, "HW_OCOTP_"#f, "HW_OCOTP_"#g, "HW_OCOTP_"#h, \
- +}
- +
- +static const char *imx6q_otp_desc[16][8] = {
- + BANK(LOCK, CFG0, CFG1, CFG2, CFG3, CFG4, CFG5, CFG6),
- + BANK(MEM0, MEM1, MEM2, MEM3, MEM4, ANA0, ANA1, ANA2),
- + BANK(OTPMK0, OTPMK1, OTPMK2, OTPMK3, OTPMK4, OTPMK5, OTPMK6, OTPMK7),
- + BANK(SRK0, SRK1, SRK2, SRK3, SRK4, SRK5, SRK6, SRK7),
- + BANK(RESP0, HSJC_RESP1, MAC0, MAC1, HDCP_KSV0, HDCP_KSV1, GP1, GP2),
- + BANK(DTCP_KEY0, DTCP_KEY1, DTCP_KEY2, DTCP_KEY3, DTCP_KEY4, MISC_CONF, FIELD_RETURN, SRK_REVOKE),
- + BANK(HDCP_KEY0, HDCP_KEY1, HDCP_KEY2, HDCP_KEY3, HDCP_KEY4, HDCP_KEY5, HDCP_KEY6, HDCP_KEY7),
- + BANK(HDCP_KEY8, HDCP_KEY9, HDCP_KEY10, HDCP_KEY11, HDCP_KEY12, HDCP_KEY13, HDCP_KEY14, HDCP_KEY15),
- + BANK(HDCP_KEY16, HDCP_KEY17, HDCP_KEY18, HDCP_KEY19, HDCP_KEY20, HDCP_KEY21, HDCP_KEY22, HDCP_KEY23),
- + BANK(HDCP_KEY24, HDCP_KEY25, HDCP_KEY26, HDCP_KEY27, HDCP_KEY28, HDCP_KEY29, HDCP_KEY30, HDCP_KEY31),
- + BANK(HDCP_KEY32, HDCP_KEY33, HDCP_KEY34, HDCP_KEY35, HDCP_KEY36, HDCP_KEY37, HDCP_KEY38, HDCP_KEY39),
- + BANK(HDCP_KEY40, HDCP_KEY41, HDCP_KEY42, HDCP_KEY43, HDCP_KEY44, HDCP_KEY45, HDCP_KEY46, HDCP_KEY47),
- + BANK(HDCP_KEY48, HDCP_KEY49, HDCP_KEY50, HDCP_KEY51, HDCP_KEY52, HDCP_KEY53, HDCP_KEY54, HDCP_KEY55),
- + BANK(HDCP_KEY56, HDCP_KEY57, HDCP_KEY58, HDCP_KEY59, HDCP_KEY60, HDCP_KEY61, HDCP_KEY62, HDCP_KEY63),
- + BANK(HDCP_KEY64, HDCP_KEY65, HDCP_KEY66, HDCP_KEY67, HDCP_KEY68, HDCP_KEY69, HDCP_KEY70, HDCP_KEY71),
- + BANK(CRC0, CRC1, CRC2, CRC3, CRC4, CRC5, CRC6, CRC7),
- +};
- +
- +static DEFINE_MUTEX(otp_mutex);
- +static void __iomem *otp_base;
- +static struct clk *otp_clk;
- +struct kobject *otp_kobj;
- +struct kobj_attribute *otp_kattr;
- +struct attribute_group *otp_attr_group;
- +
- +static void set_otp_timing(void)
- +{
- + unsigned long clk_rate = 0;
- + unsigned long strobe_read, relex, strobe_prog;
- + u32 timing = 0;
- +
- + clk_rate = clk_get_rate(otp_clk);
- +
- + /* do optimization for too many zeros */
- + relex = clk_rate / (1000000000 / DEF_RELAX) - 1;
- + strobe_prog = clk_rate / (1000000000 / 10000) + 2 * (DEF_RELAX + 1) - 1;
- + strobe_read = clk_rate / (1000000000 / 40) + 2 * (DEF_RELAX + 1) - 1;
- +
- + timing = BF(relex, OCOTP_TIMING_RELAX);
- + timing |= BF(strobe_read, OCOTP_TIMING_STROBE_READ);
- + timing |= BF(strobe_prog, OCOTP_TIMING_STROBE_PROG);
- +
- + __raw_writel(timing, otp_base + HW_OCOTP_TIMING);
- +}
- +
- +static int otp_wait_busy(u32 flags)
- +{
- + int count;
- + u32 c;
- +
- + for (count = 10000; count >= 0; count--) {
- + c = __raw_readl(otp_base + HW_OCOTP_CTRL);
- + if (!(c & (BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR | flags)))
- + break;
- + cpu_relax();
- + }
- +
- + if (count < 0)
- + return -ETIMEDOUT;
- +
- + return 0;
- +}
- +
- +static ssize_t fsl_otp_show(struct kobject *kobj, struct kobj_attribute *attr,
- + char *buf)
- +{
- + unsigned int index = attr - otp_kattr;
- + u32 value = 0;
- + int ret;
- +
- + ret = clk_prepare_enable(otp_clk);
- + if (ret)
- + return 0;
- +
- + mutex_lock(&otp_mutex);
- +
- + set_otp_timing();
- + ret = otp_wait_busy(0);
- + if (ret)
- + goto out;
- +
- + value = __raw_readl(otp_base + HW_OCOTP_CUST_N(index));
- +
- +out:
- + mutex_unlock(&otp_mutex);
- + clk_disable_unprepare(otp_clk);
- + return ret ? 0 : sprintf(buf, "0x%x\n", value);
- +}
- +
- +static int otp_write_bits(int addr, u32 data, u32 magic)
- +{
- + u32 c; /* for control register */
- +
- + /* init the control register */
- + c = __raw_readl(otp_base + HW_OCOTP_CTRL);
- + c &= ~BM_OCOTP_CTRL_ADDR;
- + c |= BF(addr, OCOTP_CTRL_ADDR);
- + c |= BF(magic, OCOTP_CTRL_WR_UNLOCK);
- + __raw_writel(c, otp_base + HW_OCOTP_CTRL);
- +
- + /* init the data register */
- + __raw_writel(data, otp_base + HW_OCOTP_DATA);
- + otp_wait_busy(0);
- +
- + mdelay(2); /* Write Postamble */
- +
- + return 0;
- +}
- +
- +static ssize_t fsl_otp_store(struct kobject *kobj, struct kobj_attribute *attr,
- + const char *buf, size_t count)
- +{
- + unsigned int index = attr - otp_kattr;
- + u32 value;
- + int ret;
- +
- + sscanf(buf, "0x%x", &value);
- +
- + ret = clk_prepare_enable(otp_clk);
- + if (ret)
- + return 0;
- +
- + mutex_lock(&otp_mutex);
- +
- + set_otp_timing();
- + ret = otp_wait_busy(0);
- + if (ret)
- + goto out;
- +
- + otp_write_bits(index, value, 0x3e77);
- +
- + /* Reload all the shadow registers */
- + __raw_writel(BM_OCOTP_CTRL_RELOAD_SHADOWS,
- + otp_base + HW_OCOTP_CTRL_SET);
- + udelay(1);
- + otp_wait_busy(BM_OCOTP_CTRL_RELOAD_SHADOWS);
- +
- +out:
- + mutex_unlock(&otp_mutex);
- + clk_disable_unprepare(otp_clk);
- + return ret ? 0 : count;
- +}
- +
- +static int fsl_otp_probe(struct platform_device *pdev)
- +{
- + struct resource *res;
- + struct attribute **attrs;
- + const char **desc;
- + int i, num;
- + int ret;
- +
- + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- + otp_base = devm_ioremap_resource(&pdev->dev, res);
- + if (IS_ERR(otp_base)) {
- + ret = PTR_ERR(otp_base);
- + dev_err(&pdev->dev, "failed to ioremap resource: %d\n", ret);
- + return ret;
- + }
- +
- + otp_clk = devm_clk_get(&pdev->dev, NULL);
- + if (IS_ERR(otp_clk)) {
- + ret = PTR_ERR(otp_clk);
- + dev_err(&pdev->dev, "failed to get clock: %d\n", ret);
- + return ret;
- + }
- +
- + desc = (const char **) imx6q_otp_desc;
- + num = sizeof(imx6q_otp_desc) / sizeof(void *);
- +
- + /* The last one is NULL, which is used to detect the end */
- + attrs = devm_kzalloc(&pdev->dev, (num + 1) * sizeof(*attrs),
- + GFP_KERNEL);
- + otp_kattr = devm_kzalloc(&pdev->dev, num * sizeof(*otp_kattr),
- + GFP_KERNEL);
- + otp_attr_group = devm_kzalloc(&pdev->dev, sizeof(*otp_attr_group),
- + GFP_KERNEL);
- + if (!attrs || !otp_kattr || !otp_attr_group)
- + return -ENOMEM;
- +
- + for (i = 0; i < num; i++) {
- + sysfs_attr_init(&otp_kattr[i].attr);
- + otp_kattr[i].attr.name = desc[i];
- + otp_kattr[i].attr.mode = 0600;
- + otp_kattr[i].show = fsl_otp_show;
- + otp_kattr[i].store = fsl_otp_store;
- + attrs[i] = &otp_kattr[i].attr;
- + }
- + otp_attr_group->attrs = attrs;
- +
- + otp_kobj = kobject_create_and_add("fsl_otp", NULL);
- + if (!otp_kobj) {
- + dev_err(&pdev->dev, "failed to add kobject\n");
- + return -ENOMEM;
- + }
- +
- + ret = sysfs_create_group(otp_kobj, otp_attr_group);
- + if (ret) {
- + dev_err(&pdev->dev, "failed to create sysfs group: %d\n", ret);
- + kobject_put(otp_kobj);
- + return ret;
- + }
- +
- + mutex_init(&otp_mutex);
- +
- + return 0;
- +}
- +
- +static int fsl_otp_remove(struct platform_device *pdev)
- +{
- + sysfs_remove_group(otp_kobj, otp_attr_group);
- + kobject_put(otp_kobj);
- +
- + return 0;
- +}
- +
- +static const struct of_device_id fsl_otp_dt_ids[] = {
- + { .compatible = "fsl,imx6q-ocotp", },
- + { /* sentinel */ }
- +};
- +MODULE_DEVICE_TABLE(of, fsl_otp_dt_ids);
- +
- +static struct platform_driver fsl_otp_driver = {
- + .driver = {
- + .name = "imx-ocotp",
- + .owner = THIS_MODULE,
- + .of_match_table = fsl_otp_dt_ids,
- + },
- + .probe = fsl_otp_probe,
- + .remove = fsl_otp_remove,
- +};
- +module_platform_driver(fsl_otp_driver);
- +
- +MODULE_LICENSE("GPL");
- +MODULE_AUTHOR("Huang Shijie <b32955@freescale.com>");
- +MODULE_DESCRIPTION("Freescale i.MX OCOTP driver");
- diff -Nur linux-3.14.35.orig/drivers/char/Kconfig linux-3.14.35/drivers/char/Kconfig
- --- linux-3.14.35.orig/drivers/char/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/char/Kconfig 2015-03-08 14:27:37.525684501 -0500
- @@ -82,6 +82,21 @@
-
- If unsure, say N.
-
- +config FSL_OTP
- + tristate "Freescale On-Chip OTP Memory Support"
- + depends on HAS_IOMEM && OF
- + help
- + If you say Y here, you will get support for a character device
- + interface into the One Time Programmable memory pages that are
- + stored on the some Freescale i.MX processors. This will not get
- + you access to the secure memory pages however. You will need to
- + write your own secure code and reader for that.
- +
- + To compile this driver as a module, choose M here: the module
- + will be called fsl_otp.
- +
- + If unsure, it is safe to say Y.
- +
- config PRINTER
- tristate "Parallel printer support"
- depends on PARPORT
- diff -Nur linux-3.14.35.orig/drivers/char/Makefile linux-3.14.35/drivers/char/Makefile
- --- linux-3.14.35.orig/drivers/char/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/char/Makefile 2015-03-08 14:27:37.525684501 -0500
- @@ -16,6 +16,7 @@
- obj-$(CONFIG_IBM_BSR) += bsr.o
- obj-$(CONFIG_SGI_MBCS) += mbcs.o
- obj-$(CONFIG_BFIN_OTP) += bfin-otp.o
- +obj-$(CONFIG_FSL_OTP) += fsl_otp.o
-
- obj-$(CONFIG_PRINTER) += lp.o
-
- diff -Nur linux-3.14.35.orig/drivers/clk/clk.c linux-3.14.35/drivers/clk/clk.c
- --- linux-3.14.35.orig/drivers/clk/clk.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/clk/clk.c 2015-03-08 14:27:37.529684502 -0500
- @@ -1707,6 +1707,7 @@
- */
- int clk_set_parent(struct clk *clk, struct clk *parent)
- {
- + struct clk *child;
- int ret = 0;
- int p_index = 0;
- unsigned long p_rate = 0;
- @@ -1733,6 +1734,18 @@
- goto out;
- }
-
- + /* check two consecutive basic mux clocks */
- + if (clk->flags & CLK_IS_BASIC_MUX) {
- + hlist_for_each_entry(child, &clk->children, child_node) {
- + if (child->flags & CLK_IS_BASIC_MUX) {
- + pr_err("%s: failed to switch parent of %s due to child mux %s\n",
- + __func__, clk->name, child->name);
- + ret = -EBUSY;
- + goto out;
- + }
- + }
- + }
- +
- /* try finding the new parent index */
- if (parent) {
- p_index = clk_fetch_parent_index(clk, parent);
- diff -Nur linux-3.14.35.orig/drivers/clk/clk-mux.c linux-3.14.35/drivers/clk/clk-mux.c
- --- linux-3.14.35.orig/drivers/clk/clk-mux.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/clk/clk-mux.c 2015-03-08 14:27:37.529684502 -0500
- @@ -143,7 +143,7 @@
- init.ops = &clk_mux_ro_ops;
- else
- init.ops = &clk_mux_ops;
- - init.flags = flags | CLK_IS_BASIC;
- + init.flags = flags | CLK_IS_BASIC | CLK_IS_BASIC_MUX;
- init.parent_names = parent_names;
- init.num_parents = num_parents;
-
- diff -Nur linux-3.14.35.orig/drivers/cpufreq/cpufreq_interactive.c linux-3.14.35/drivers/cpufreq/cpufreq_interactive.c
- --- linux-3.14.35.orig/drivers/cpufreq/cpufreq_interactive.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/cpufreq/cpufreq_interactive.c 2015-03-08 14:27:37.529684502 -0500
- @@ -0,0 +1,1349 @@
- +/*
- + * drivers/cpufreq/cpufreq_interactive.c
- + *
- + * Copyright (C) 2010 Google, Inc.
- + *
- + * This software is licensed under the terms of the GNU General Public
- + * License version 2, as published by the Free Software Foundation, and
- + * may be copied, distributed, and modified under those terms.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * Author: Mike Chan (mike@android.com)
- + *
- + */
- +
- +#include <linux/cpu.h>
- +#include <linux/cpumask.h>
- +#include <linux/cpufreq.h>
- +#include <linux/module.h>
- +#include <linux/moduleparam.h>
- +#include <linux/rwsem.h>
- +#include <linux/sched.h>
- +#include <linux/sched/rt.h>
- +#include <linux/tick.h>
- +#include <linux/time.h>
- +#include <linux/timer.h>
- +#include <linux/workqueue.h>
- +#include <linux/kthread.h>
- +#include <linux/slab.h>
- +
- +#define CREATE_TRACE_POINTS
- +#include <trace/events/cpufreq_interactive.h>
- +
- +struct cpufreq_interactive_cpuinfo {
- + struct timer_list cpu_timer;
- + struct timer_list cpu_slack_timer;
- + spinlock_t load_lock; /* protects the next 4 fields */
- + u64 time_in_idle;
- + u64 time_in_idle_timestamp;
- + u64 cputime_speedadj;
- + u64 cputime_speedadj_timestamp;
- + struct cpufreq_policy *policy;
- + struct cpufreq_frequency_table *freq_table;
- + unsigned int target_freq;
- + unsigned int floor_freq;
- + u64 floor_validate_time;
- + u64 hispeed_validate_time;
- + struct rw_semaphore enable_sem;
- + int governor_enabled;
- +};
- +
- +static DEFINE_PER_CPU(struct cpufreq_interactive_cpuinfo, cpuinfo);
- +
- +/* realtime thread handles frequency scaling */
- +static struct task_struct *speedchange_task;
- +static cpumask_t speedchange_cpumask;
- +static spinlock_t speedchange_cpumask_lock;
- +static struct mutex gov_lock;
- +
- +/* Target load. Lower values result in higher CPU speeds. */
- +#define DEFAULT_TARGET_LOAD 90
- +static unsigned int default_target_loads[] = {DEFAULT_TARGET_LOAD};
- +
- +#define DEFAULT_TIMER_RATE (20 * USEC_PER_MSEC)
- +#define DEFAULT_ABOVE_HISPEED_DELAY DEFAULT_TIMER_RATE
- +static unsigned int default_above_hispeed_delay[] = {
- + DEFAULT_ABOVE_HISPEED_DELAY };
- +
- +struct cpufreq_interactive_tunables {
- + int usage_count;
- + /* Hi speed to bump to from lo speed when load burst (default max) */
- + unsigned int hispeed_freq;
- + /* Go to hi speed when CPU load at or above this value. */
- +#define DEFAULT_GO_HISPEED_LOAD 99
- + unsigned long go_hispeed_load;
- + /* Target load. Lower values result in higher CPU speeds. */
- + spinlock_t target_loads_lock;
- + unsigned int *target_loads;
- + int ntarget_loads;
- + /*
- + * The minimum amount of time to spend at a frequency before we can ramp
- + * down.
- + */
- +#define DEFAULT_MIN_SAMPLE_TIME (80 * USEC_PER_MSEC)
- + unsigned long min_sample_time;
- + /*
- + * The sample rate of the timer used to increase frequency
- + */
- + unsigned long timer_rate;
- + /*
- + * Wait this long before raising speed above hispeed, by default a
- + * single timer interval.
- + */
- + spinlock_t above_hispeed_delay_lock;
- + unsigned int *above_hispeed_delay;
- + int nabove_hispeed_delay;
- + /* Non-zero means indefinite speed boost active */
- + int boost_val;
- + /* Duration of a boot pulse in usecs */
- + int boostpulse_duration_val;
- + /* End time of boost pulse in ktime converted to usecs */
- + u64 boostpulse_endtime;
- + /*
- + * Max additional time to wait in idle, beyond timer_rate, at speeds
- + * above minimum before wakeup to reduce speed, or -1 if unnecessary.
- + */
- +#define DEFAULT_TIMER_SLACK (4 * DEFAULT_TIMER_RATE)
- + int timer_slack_val;
- + bool io_is_busy;
- +};
- +
- +/* For cases where we have single governor instance for system */
- +struct cpufreq_interactive_tunables *common_tunables;
- +
- +static struct attribute_group *get_sysfs_attr(void);
- +
- +static void cpufreq_interactive_timer_resched(
- + struct cpufreq_interactive_cpuinfo *pcpu)
- +{
- + struct cpufreq_interactive_tunables *tunables =
- + pcpu->policy->governor_data;
- + unsigned long expires;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&pcpu->load_lock, flags);
- + pcpu->time_in_idle =
- + get_cpu_idle_time(smp_processor_id(),
- + &pcpu->time_in_idle_timestamp,
- + tunables->io_is_busy);
- + pcpu->cputime_speedadj = 0;
- + pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp;
- + expires = jiffies + usecs_to_jiffies(tunables->timer_rate);
- + mod_timer_pinned(&pcpu->cpu_timer, expires);
- +
- + if (tunables->timer_slack_val >= 0 &&
- + pcpu->target_freq > pcpu->policy->min) {
- + expires += usecs_to_jiffies(tunables->timer_slack_val);
- + mod_timer_pinned(&pcpu->cpu_slack_timer, expires);
- + }
- +
- + spin_unlock_irqrestore(&pcpu->load_lock, flags);
- +}
- +
- +/* The caller shall take enable_sem write semaphore to avoid any timer race.
- + * The cpu_timer and cpu_slack_timer must be deactivated when calling this
- + * function.
- + */
- +static void cpufreq_interactive_timer_start(
- + struct cpufreq_interactive_tunables *tunables, int cpu)
- +{
- + struct cpufreq_interactive_cpuinfo *pcpu = &per_cpu(cpuinfo, cpu);
- + unsigned long expires = jiffies +
- + usecs_to_jiffies(tunables->timer_rate);
- + unsigned long flags;
- +
- + pcpu->cpu_timer.expires = expires;
- + add_timer_on(&pcpu->cpu_timer, cpu);
- + if (tunables->timer_slack_val >= 0 &&
- + pcpu->target_freq > pcpu->policy->min) {
- + expires += usecs_to_jiffies(tunables->timer_slack_val);
- + pcpu->cpu_slack_timer.expires = expires;
- + add_timer_on(&pcpu->cpu_slack_timer, cpu);
- + }
- +
- + spin_lock_irqsave(&pcpu->load_lock, flags);
- + pcpu->time_in_idle =
- + get_cpu_idle_time(cpu, &pcpu->time_in_idle_timestamp,
- + tunables->io_is_busy);
- + pcpu->cputime_speedadj = 0;
- + pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp;
- + spin_unlock_irqrestore(&pcpu->load_lock, flags);
- +}
- +
- +static unsigned int freq_to_above_hispeed_delay(
- + struct cpufreq_interactive_tunables *tunables,
- + unsigned int freq)
- +{
- + int i;
- + unsigned int ret;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&tunables->above_hispeed_delay_lock, flags);
- +
- + for (i = 0; i < tunables->nabove_hispeed_delay - 1 &&
- + freq >= tunables->above_hispeed_delay[i+1]; i += 2)
- + ;
- +
- + ret = tunables->above_hispeed_delay[i];
- + spin_unlock_irqrestore(&tunables->above_hispeed_delay_lock, flags);
- + return ret;
- +}
- +
- +static unsigned int freq_to_targetload(
- + struct cpufreq_interactive_tunables *tunables, unsigned int freq)
- +{
- + int i;
- + unsigned int ret;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&tunables->target_loads_lock, flags);
- +
- + for (i = 0; i < tunables->ntarget_loads - 1 &&
- + freq >= tunables->target_loads[i+1]; i += 2)
- + ;
- +
- + ret = tunables->target_loads[i];
- + spin_unlock_irqrestore(&tunables->target_loads_lock, flags);
- + return ret;
- +}
- +
- +/*
- + * If increasing frequencies never map to a lower target load then
- + * choose_freq() will find the minimum frequency that does not exceed its
- + * target load given the current load.
- + */
- +static unsigned int choose_freq(struct cpufreq_interactive_cpuinfo *pcpu,
- + unsigned int loadadjfreq)
- +{
- + unsigned int freq = pcpu->policy->cur;
- + unsigned int prevfreq, freqmin, freqmax;
- + unsigned int tl;
- + int index;
- +
- + freqmin = 0;
- + freqmax = UINT_MAX;
- +
- + do {
- + prevfreq = freq;
- + tl = freq_to_targetload(pcpu->policy->governor_data, freq);
- +
- + /*
- + * Find the lowest frequency where the computed load is less
- + * than or equal to the target load.
- + */
- +
- + if (cpufreq_frequency_table_target(
- + pcpu->policy, pcpu->freq_table, loadadjfreq / tl,
- + CPUFREQ_RELATION_L, &index))
- + break;
- + freq = pcpu->freq_table[index].frequency;
- +
- + if (freq > prevfreq) {
- + /* The previous frequency is too low. */
- + freqmin = prevfreq;
- +
- + if (freq >= freqmax) {
- + /*
- + * Find the highest frequency that is less
- + * than freqmax.
- + */
- + if (cpufreq_frequency_table_target(
- + pcpu->policy, pcpu->freq_table,
- + freqmax - 1, CPUFREQ_RELATION_H,
- + &index))
- + break;
- + freq = pcpu->freq_table[index].frequency;
- +
- + if (freq == freqmin) {
- + /*
- + * The first frequency below freqmax
- + * has already been found to be too
- + * low. freqmax is the lowest speed
- + * we found that is fast enough.
- + */
- + freq = freqmax;
- + break;
- + }
- + }
- + } else if (freq < prevfreq) {
- + /* The previous frequency is high enough. */
- + freqmax = prevfreq;
- +
- + if (freq <= freqmin) {
- + /*
- + * Find the lowest frequency that is higher
- + * than freqmin.
- + */
- + if (cpufreq_frequency_table_target(
- + pcpu->policy, pcpu->freq_table,
- + freqmin + 1, CPUFREQ_RELATION_L,
- + &index))
- + break;
- + freq = pcpu->freq_table[index].frequency;
- +
- + /*
- + * If freqmax is the first frequency above
- + * freqmin then we have already found that
- + * this speed is fast enough.
- + */
- + if (freq == freqmax)
- + break;
- + }
- + }
- +
- + /* If same frequency chosen as previous then done. */
- + } while (freq != prevfreq);
- +
- + return freq;
- +}
- +
- +static u64 update_load(int cpu)
- +{
- + struct cpufreq_interactive_cpuinfo *pcpu = &per_cpu(cpuinfo, cpu);
- + struct cpufreq_interactive_tunables *tunables =
- + pcpu->policy->governor_data;
- + u64 now;
- + u64 now_idle;
- + unsigned int delta_idle;
- + unsigned int delta_time;
- + u64 active_time;
- +
- + now_idle = get_cpu_idle_time(cpu, &now, tunables->io_is_busy);
- + delta_idle = (unsigned int)(now_idle - pcpu->time_in_idle);
- + delta_time = (unsigned int)(now - pcpu->time_in_idle_timestamp);
- +
- + if (delta_time <= delta_idle)
- + active_time = 0;
- + else
- + active_time = delta_time - delta_idle;
- +
- + pcpu->cputime_speedadj += active_time * pcpu->policy->cur;
- +
- + pcpu->time_in_idle = now_idle;
- + pcpu->time_in_idle_timestamp = now;
- + return now;
- +}
- +
- +static void cpufreq_interactive_timer(unsigned long data)
- +{
- + u64 now;
- + unsigned int delta_time;
- + u64 cputime_speedadj;
- + int cpu_load;
- + struct cpufreq_interactive_cpuinfo *pcpu =
- + &per_cpu(cpuinfo, data);
- + struct cpufreq_interactive_tunables *tunables =
- + pcpu->policy->governor_data;
- + unsigned int new_freq;
- + unsigned int loadadjfreq;
- + unsigned int index;
- + unsigned long flags;
- + bool boosted;
- +
- + if (!down_read_trylock(&pcpu->enable_sem))
- + return;
- + if (!pcpu->governor_enabled)
- + goto exit;
- +
- + spin_lock_irqsave(&pcpu->load_lock, flags);
- + now = update_load(data);
- + delta_time = (unsigned int)(now - pcpu->cputime_speedadj_timestamp);
- + cputime_speedadj = pcpu->cputime_speedadj;
- + spin_unlock_irqrestore(&pcpu->load_lock, flags);
- +
- + if (WARN_ON_ONCE(!delta_time))
- + goto rearm;
- +
- + do_div(cputime_speedadj, delta_time);
- + loadadjfreq = (unsigned int)cputime_speedadj * 100;
- + cpu_load = loadadjfreq / pcpu->target_freq;
- + boosted = tunables->boost_val || now < tunables->boostpulse_endtime;
- +
- + if (cpu_load >= tunables->go_hispeed_load || boosted) {
- + if (pcpu->target_freq < tunables->hispeed_freq) {
- + new_freq = tunables->hispeed_freq;
- + } else {
- + new_freq = choose_freq(pcpu, loadadjfreq);
- +
- + if (new_freq < tunables->hispeed_freq)
- + new_freq = tunables->hispeed_freq;
- + }
- + } else {
- + new_freq = choose_freq(pcpu, loadadjfreq);
- + }
- +
- + if (pcpu->target_freq >= tunables->hispeed_freq &&
- + new_freq > pcpu->target_freq &&
- + now - pcpu->hispeed_validate_time <
- + freq_to_above_hispeed_delay(tunables, pcpu->target_freq)) {
- + trace_cpufreq_interactive_notyet(
- + data, cpu_load, pcpu->target_freq,
- + pcpu->policy->cur, new_freq);
- + goto rearm;
- + }
- +
- + pcpu->hispeed_validate_time = now;
- +
- + if (cpufreq_frequency_table_target(pcpu->policy, pcpu->freq_table,
- + new_freq, CPUFREQ_RELATION_L,
- + &index))
- + goto rearm;
- +
- + new_freq = pcpu->freq_table[index].frequency;
- +
- + /*
- + * Do not scale below floor_freq unless we have been at or above the
- + * floor frequency for the minimum sample time since last validated.
- + */
- + if (new_freq < pcpu->floor_freq) {
- + if (now - pcpu->floor_validate_time <
- + tunables->min_sample_time) {
- + trace_cpufreq_interactive_notyet(
- + data, cpu_load, pcpu->target_freq,
- + pcpu->policy->cur, new_freq);
- + goto rearm;
- + }
- + }
- +
- + /*
- + * Update the timestamp for checking whether speed has been held at
- + * or above the selected frequency for a minimum of min_sample_time,
- + * if not boosted to hispeed_freq. If boosted to hispeed_freq then we
- + * allow the speed to drop as soon as the boostpulse duration expires
- + * (or the indefinite boost is turned off).
- + */
- +
- + if (!boosted || new_freq > tunables->hispeed_freq) {
- + pcpu->floor_freq = new_freq;
- + pcpu->floor_validate_time = now;
- + }
- +
- + if (pcpu->target_freq == new_freq) {
- + trace_cpufreq_interactive_already(
- + data, cpu_load, pcpu->target_freq,
- + pcpu->policy->cur, new_freq);
- + goto rearm_if_notmax;
- + }
- +
- + trace_cpufreq_interactive_target(data, cpu_load, pcpu->target_freq,
- + pcpu->policy->cur, new_freq);
- +
- + pcpu->target_freq = new_freq;
- + spin_lock_irqsave(&speedchange_cpumask_lock, flags);
- + cpumask_set_cpu(data, &speedchange_cpumask);
- + spin_unlock_irqrestore(&speedchange_cpumask_lock, flags);
- + wake_up_process(speedchange_task);
- +
- +rearm_if_notmax:
- + /*
- + * Already set max speed and don't see a need to change that,
- + * wait until next idle to re-evaluate, don't need timer.
- + */
- + if (pcpu->target_freq == pcpu->policy->max)
- + goto exit;
- +
- +rearm:
- + if (!timer_pending(&pcpu->cpu_timer))
- + cpufreq_interactive_timer_resched(pcpu);
- +
- +exit:
- + up_read(&pcpu->enable_sem);
- + return;
- +}
- +
- +static void cpufreq_interactive_idle_start(void)
- +{
- + struct cpufreq_interactive_cpuinfo *pcpu =
- + &per_cpu(cpuinfo, smp_processor_id());
- + int pending;
- +
- + if (!down_read_trylock(&pcpu->enable_sem))
- + return;
- + if (!pcpu->governor_enabled) {
- + up_read(&pcpu->enable_sem);
- + return;
- + }
- +
- + pending = timer_pending(&pcpu->cpu_timer);
- +
- + if (pcpu->target_freq != pcpu->policy->min) {
- + /*
- + * Entering idle while not at lowest speed. On some
- + * platforms this can hold the other CPU(s) at that speed
- + * even though the CPU is idle. Set a timer to re-evaluate
- + * speed so this idle CPU doesn't hold the other CPUs above
- + * min indefinitely. This should probably be a quirk of
- + * the CPUFreq driver.
- + */
- + if (!pending)
- + cpufreq_interactive_timer_resched(pcpu);
- + }
- +
- + up_read(&pcpu->enable_sem);
- +}
- +
- +static void cpufreq_interactive_idle_end(void)
- +{
- + struct cpufreq_interactive_cpuinfo *pcpu =
- + &per_cpu(cpuinfo, smp_processor_id());
- +
- + if (!down_read_trylock(&pcpu->enable_sem))
- + return;
- + if (!pcpu->governor_enabled) {
- + up_read(&pcpu->enable_sem);
- + return;
- + }
- +
- + /* Arm the timer for 1-2 ticks later if not already. */
- + if (!timer_pending(&pcpu->cpu_timer)) {
- + cpufreq_interactive_timer_resched(pcpu);
- + } else if (time_after_eq(jiffies, pcpu->cpu_timer.expires)) {
- + del_timer(&pcpu->cpu_timer);
- + del_timer(&pcpu->cpu_slack_timer);
- + cpufreq_interactive_timer(smp_processor_id());
- + }
- +
- + up_read(&pcpu->enable_sem);
- +}
- +
- +static int cpufreq_interactive_speedchange_task(void *data)
- +{
- + unsigned int cpu;
- + cpumask_t tmp_mask;
- + unsigned long flags;
- + struct cpufreq_interactive_cpuinfo *pcpu;
- +
- + while (1) {
- + set_current_state(TASK_INTERRUPTIBLE);
- + spin_lock_irqsave(&speedchange_cpumask_lock, flags);
- +
- + if (cpumask_empty(&speedchange_cpumask)) {
- + spin_unlock_irqrestore(&speedchange_cpumask_lock,
- + flags);
- + schedule();
- +
- + if (kthread_should_stop())
- + break;
- +
- + spin_lock_irqsave(&speedchange_cpumask_lock, flags);
- + }
- +
- + set_current_state(TASK_RUNNING);
- + tmp_mask = speedchange_cpumask;
- + cpumask_clear(&speedchange_cpumask);
- + spin_unlock_irqrestore(&speedchange_cpumask_lock, flags);
- +
- + for_each_cpu(cpu, &tmp_mask) {
- + unsigned int j;
- + unsigned int max_freq = 0;
- +
- + pcpu = &per_cpu(cpuinfo, cpu);
- + if (!down_read_trylock(&pcpu->enable_sem))
- + continue;
- + if (!pcpu->governor_enabled) {
- + up_read(&pcpu->enable_sem);
- + continue;
- + }
- +
- + for_each_cpu(j, pcpu->policy->cpus) {
- + struct cpufreq_interactive_cpuinfo *pjcpu =
- + &per_cpu(cpuinfo, j);
- +
- + if (pjcpu->target_freq > max_freq)
- + max_freq = pjcpu->target_freq;
- + }
- +
- + if (max_freq != pcpu->policy->cur)
- + __cpufreq_driver_target(pcpu->policy,
- + max_freq,
- + CPUFREQ_RELATION_H);
- + trace_cpufreq_interactive_setspeed(cpu,
- + pcpu->target_freq,
- + pcpu->policy->cur);
- +
- + up_read(&pcpu->enable_sem);
- + }
- + }
- +
- + return 0;
- +}
- +
- +static void cpufreq_interactive_boost(void)
- +{
- + int i;
- + int anyboost = 0;
- + unsigned long flags;
- + struct cpufreq_interactive_cpuinfo *pcpu;
- + struct cpufreq_interactive_tunables *tunables;
- +
- + spin_lock_irqsave(&speedchange_cpumask_lock, flags);
- +
- + for_each_online_cpu(i) {
- + pcpu = &per_cpu(cpuinfo, i);
- + tunables = pcpu->policy->governor_data;
- +
- + if (pcpu->target_freq < tunables->hispeed_freq) {
- + pcpu->target_freq = tunables->hispeed_freq;
- + cpumask_set_cpu(i, &speedchange_cpumask);
- + pcpu->hispeed_validate_time =
- + ktime_to_us(ktime_get());
- + anyboost = 1;
- + }
- +
- + /*
- + * Set floor freq and (re)start timer for when last
- + * validated.
- + */
- +
- + pcpu->floor_freq = tunables->hispeed_freq;
- + pcpu->floor_validate_time = ktime_to_us(ktime_get());
- + }
- +
- + spin_unlock_irqrestore(&speedchange_cpumask_lock, flags);
- +
- + if (anyboost)
- + wake_up_process(speedchange_task);
- +}
- +
- +static int cpufreq_interactive_notifier(
- + struct notifier_block *nb, unsigned long val, void *data)
- +{
- + struct cpufreq_freqs *freq = data;
- + struct cpufreq_interactive_cpuinfo *pcpu;
- + int cpu;
- + unsigned long flags;
- +
- + if (val == CPUFREQ_POSTCHANGE) {
- + pcpu = &per_cpu(cpuinfo, freq->cpu);
- + if (!down_read_trylock(&pcpu->enable_sem))
- + return 0;
- + if (!pcpu->governor_enabled) {
- + up_read(&pcpu->enable_sem);
- + return 0;
- + }
- +
- + for_each_cpu(cpu, pcpu->policy->cpus) {
- + struct cpufreq_interactive_cpuinfo *pjcpu =
- + &per_cpu(cpuinfo, cpu);
- + if (cpu != freq->cpu) {
- + if (!down_read_trylock(&pjcpu->enable_sem))
- + continue;
- + if (!pjcpu->governor_enabled) {
- + up_read(&pjcpu->enable_sem);
- + continue;
- + }
- + }
- + spin_lock_irqsave(&pjcpu->load_lock, flags);
- + update_load(cpu);
- + spin_unlock_irqrestore(&pjcpu->load_lock, flags);
- + if (cpu != freq->cpu)
- + up_read(&pjcpu->enable_sem);
- + }
- +
- + up_read(&pcpu->enable_sem);
- + }
- + return 0;
- +}
- +
- +static struct notifier_block cpufreq_notifier_block = {
- + .notifier_call = cpufreq_interactive_notifier,
- +};
- +
- +static unsigned int *get_tokenized_data(const char *buf, int *num_tokens)
- +{
- + const char *cp;
- + int i;
- + int ntokens = 1;
- + unsigned int *tokenized_data;
- + int err = -EINVAL;
- +
- + cp = buf;
- + while ((cp = strpbrk(cp + 1, " :")))
- + ntokens++;
- +
- + if (!(ntokens & 0x1))
- + goto err;
- +
- + tokenized_data = kmalloc(ntokens * sizeof(unsigned int), GFP_KERNEL);
- + if (!tokenized_data) {
- + err = -ENOMEM;
- + goto err;
- + }
- +
- + cp = buf;
- + i = 0;
- + while (i < ntokens) {
- + if (sscanf(cp, "%u", &tokenized_data[i++]) != 1)
- + goto err_kfree;
- +
- + cp = strpbrk(cp, " :");
- + if (!cp)
- + break;
- + cp++;
- + }
- +
- + if (i != ntokens)
- + goto err_kfree;
- +
- + *num_tokens = ntokens;
- + return tokenized_data;
- +
- +err_kfree:
- + kfree(tokenized_data);
- +err:
- + return ERR_PTR(err);
- +}
- +
- +static ssize_t show_target_loads(
- + struct cpufreq_interactive_tunables *tunables,
- + char *buf)
- +{
- + int i;
- + ssize_t ret = 0;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&tunables->target_loads_lock, flags);
- +
- + for (i = 0; i < tunables->ntarget_loads; i++)
- + ret += sprintf(buf + ret, "%u%s", tunables->target_loads[i],
- + i & 0x1 ? ":" : " ");
- +
- + sprintf(buf + ret - 1, "\n");
- + spin_unlock_irqrestore(&tunables->target_loads_lock, flags);
- + return ret;
- +}
- +
- +static ssize_t store_target_loads(
- + struct cpufreq_interactive_tunables *tunables,
- + const char *buf, size_t count)
- +{
- + int ntokens;
- + unsigned int *new_target_loads = NULL;
- + unsigned long flags;
- +
- + new_target_loads = get_tokenized_data(buf, &ntokens);
- + if (IS_ERR(new_target_loads))
- + return PTR_RET(new_target_loads);
- +
- + spin_lock_irqsave(&tunables->target_loads_lock, flags);
- + if (tunables->target_loads != default_target_loads)
- + kfree(tunables->target_loads);
- + tunables->target_loads = new_target_loads;
- + tunables->ntarget_loads = ntokens;
- + spin_unlock_irqrestore(&tunables->target_loads_lock, flags);
- + return count;
- +}
- +
- +static ssize_t show_above_hispeed_delay(
- + struct cpufreq_interactive_tunables *tunables, char *buf)
- +{
- + int i;
- + ssize_t ret = 0;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&tunables->above_hispeed_delay_lock, flags);
- +
- + for (i = 0; i < tunables->nabove_hispeed_delay; i++)
- + ret += sprintf(buf + ret, "%u%s",
- + tunables->above_hispeed_delay[i],
- + i & 0x1 ? ":" : " ");
- +
- + sprintf(buf + ret - 1, "\n");
- + spin_unlock_irqrestore(&tunables->above_hispeed_delay_lock, flags);
- + return ret;
- +}
- +
- +static ssize_t store_above_hispeed_delay(
- + struct cpufreq_interactive_tunables *tunables,
- + const char *buf, size_t count)
- +{
- + int ntokens;
- + unsigned int *new_above_hispeed_delay = NULL;
- + unsigned long flags;
- +
- + new_above_hispeed_delay = get_tokenized_data(buf, &ntokens);
- + if (IS_ERR(new_above_hispeed_delay))
- + return PTR_RET(new_above_hispeed_delay);
- +
- + spin_lock_irqsave(&tunables->above_hispeed_delay_lock, flags);
- + if (tunables->above_hispeed_delay != default_above_hispeed_delay)
- + kfree(tunables->above_hispeed_delay);
- + tunables->above_hispeed_delay = new_above_hispeed_delay;
- + tunables->nabove_hispeed_delay = ntokens;
- + spin_unlock_irqrestore(&tunables->above_hispeed_delay_lock, flags);
- + return count;
- +
- +}
- +
- +static ssize_t show_hispeed_freq(struct cpufreq_interactive_tunables *tunables,
- + char *buf)
- +{
- + return sprintf(buf, "%u\n", tunables->hispeed_freq);
- +}
- +
- +static ssize_t store_hispeed_freq(struct cpufreq_interactive_tunables *tunables,
- + const char *buf, size_t count)
- +{
- + int ret;
- + long unsigned int val;
- +
- + ret = strict_strtoul(buf, 0, &val);
- + if (ret < 0)
- + return ret;
- + tunables->hispeed_freq = val;
- + return count;
- +}
- +
- +static ssize_t show_go_hispeed_load(struct cpufreq_interactive_tunables
- + *tunables, char *buf)
- +{
- + return sprintf(buf, "%lu\n", tunables->go_hispeed_load);
- +}
- +
- +static ssize_t store_go_hispeed_load(struct cpufreq_interactive_tunables
- + *tunables, const char *buf, size_t count)
- +{
- + int ret;
- + unsigned long val;
- +
- + ret = strict_strtoul(buf, 0, &val);
- + if (ret < 0)
- + return ret;
- + tunables->go_hispeed_load = val;
- + return count;
- +}
- +
- +static ssize_t show_min_sample_time(struct cpufreq_interactive_tunables
- + *tunables, char *buf)
- +{
- + return sprintf(buf, "%lu\n", tunables->min_sample_time);
- +}
- +
- +static ssize_t store_min_sample_time(struct cpufreq_interactive_tunables
- + *tunables, const char *buf, size_t count)
- +{
- + int ret;
- + unsigned long val;
- +
- + ret = strict_strtoul(buf, 0, &val);
- + if (ret < 0)
- + return ret;
- + tunables->min_sample_time = val;
- + return count;
- +}
- +
- +static ssize_t show_timer_rate(struct cpufreq_interactive_tunables *tunables,
- + char *buf)
- +{
- + return sprintf(buf, "%lu\n", tunables->timer_rate);
- +}
- +
- +static ssize_t store_timer_rate(struct cpufreq_interactive_tunables *tunables,
- + const char *buf, size_t count)
- +{
- + int ret;
- + unsigned long val;
- +
- + ret = strict_strtoul(buf, 0, &val);
- + if (ret < 0)
- + return ret;
- + tunables->timer_rate = val;
- + return count;
- +}
- +
- +static ssize_t show_timer_slack(struct cpufreq_interactive_tunables *tunables,
- + char *buf)
- +{
- + return sprintf(buf, "%d\n", tunables->timer_slack_val);
- +}
- +
- +static ssize_t store_timer_slack(struct cpufreq_interactive_tunables *tunables,
- + const char *buf, size_t count)
- +{
- + int ret;
- + unsigned long val;
- +
- + ret = kstrtol(buf, 10, &val);
- + if (ret < 0)
- + return ret;
- +
- + tunables->timer_slack_val = val;
- + return count;
- +}
- +
- +static ssize_t show_boost(struct cpufreq_interactive_tunables *tunables,
- + char *buf)
- +{
- + return sprintf(buf, "%d\n", tunables->boost_val);
- +}
- +
- +static ssize_t store_boost(struct cpufreq_interactive_tunables *tunables,
- + const char *buf, size_t count)
- +{
- + int ret;
- + unsigned long val;
- +
- + ret = kstrtoul(buf, 0, &val);
- + if (ret < 0)
- + return ret;
- +
- + tunables->boost_val = val;
- +
- + if (tunables->boost_val) {
- + trace_cpufreq_interactive_boost("on");
- + cpufreq_interactive_boost();
- + } else {
- + trace_cpufreq_interactive_unboost("off");
- + }
- +
- + return count;
- +}
- +
- +static ssize_t store_boostpulse(struct cpufreq_interactive_tunables *tunables,
- + const char *buf, size_t count)
- +{
- + int ret;
- + unsigned long val;
- +
- + ret = kstrtoul(buf, 0, &val);
- + if (ret < 0)
- + return ret;
- +
- + tunables->boostpulse_endtime = ktime_to_us(ktime_get()) +
- + tunables->boostpulse_duration_val;
- + trace_cpufreq_interactive_boost("pulse");
- + cpufreq_interactive_boost();
- + return count;
- +}
- +
- +static ssize_t show_boostpulse_duration(struct cpufreq_interactive_tunables
- + *tunables, char *buf)
- +{
- + return sprintf(buf, "%d\n", tunables->boostpulse_duration_val);
- +}
- +
- +static ssize_t store_boostpulse_duration(struct cpufreq_interactive_tunables
- + *tunables, const char *buf, size_t count)
- +{
- + int ret;
- + unsigned long val;
- +
- + ret = kstrtoul(buf, 0, &val);
- + if (ret < 0)
- + return ret;
- +
- + tunables->boostpulse_duration_val = val;
- + return count;
- +}
- +
- +static ssize_t show_io_is_busy(struct cpufreq_interactive_tunables *tunables,
- + char *buf)
- +{
- + return sprintf(buf, "%u\n", tunables->io_is_busy);
- +}
- +
- +static ssize_t store_io_is_busy(struct cpufreq_interactive_tunables *tunables,
- + const char *buf, size_t count)
- +{
- + int ret;
- + unsigned long val;
- +
- + ret = kstrtoul(buf, 0, &val);
- + if (ret < 0)
- + return ret;
- + tunables->io_is_busy = val;
- + return count;
- +}
- +
- +/*
- + * Create show/store routines
- + * - sys: One governor instance for complete SYSTEM
- + * - pol: One governor instance per struct cpufreq_policy
- + */
- +#define show_gov_pol_sys(file_name) \
- +static ssize_t show_##file_name##_gov_sys \
- +(struct kobject *kobj, struct attribute *attr, char *buf) \
- +{ \
- + return show_##file_name(common_tunables, buf); \
- +} \
- + \
- +static ssize_t show_##file_name##_gov_pol \
- +(struct cpufreq_policy *policy, char *buf) \
- +{ \
- + return show_##file_name(policy->governor_data, buf); \
- +}
- +
- +#define store_gov_pol_sys(file_name) \
- +static ssize_t store_##file_name##_gov_sys \
- +(struct kobject *kobj, struct attribute *attr, const char *buf, \
- + size_t count) \
- +{ \
- + return store_##file_name(common_tunables, buf, count); \
- +} \
- + \
- +static ssize_t store_##file_name##_gov_pol \
- +(struct cpufreq_policy *policy, const char *buf, size_t count) \
- +{ \
- + return store_##file_name(policy->governor_data, buf, count); \
- +}
- +
- +#define show_store_gov_pol_sys(file_name) \
- +show_gov_pol_sys(file_name); \
- +store_gov_pol_sys(file_name)
- +
- +show_store_gov_pol_sys(target_loads);
- +show_store_gov_pol_sys(above_hispeed_delay);
- +show_store_gov_pol_sys(hispeed_freq);
- +show_store_gov_pol_sys(go_hispeed_load);
- +show_store_gov_pol_sys(min_sample_time);
- +show_store_gov_pol_sys(timer_rate);
- +show_store_gov_pol_sys(timer_slack);
- +show_store_gov_pol_sys(boost);
- +store_gov_pol_sys(boostpulse);
- +show_store_gov_pol_sys(boostpulse_duration);
- +show_store_gov_pol_sys(io_is_busy);
- +
- +#define gov_sys_attr_rw(_name) \
- +static struct global_attr _name##_gov_sys = \
- +__ATTR(_name, 0644, show_##_name##_gov_sys, store_##_name##_gov_sys)
- +
- +#define gov_pol_attr_rw(_name) \
- +static struct freq_attr _name##_gov_pol = \
- +__ATTR(_name, 0644, show_##_name##_gov_pol, store_##_name##_gov_pol)
- +
- +#define gov_sys_pol_attr_rw(_name) \
- + gov_sys_attr_rw(_name); \
- + gov_pol_attr_rw(_name)
- +
- +gov_sys_pol_attr_rw(target_loads);
- +gov_sys_pol_attr_rw(above_hispeed_delay);
- +gov_sys_pol_attr_rw(hispeed_freq);
- +gov_sys_pol_attr_rw(go_hispeed_load);
- +gov_sys_pol_attr_rw(min_sample_time);
- +gov_sys_pol_attr_rw(timer_rate);
- +gov_sys_pol_attr_rw(timer_slack);
- +gov_sys_pol_attr_rw(boost);
- +gov_sys_pol_attr_rw(boostpulse_duration);
- +gov_sys_pol_attr_rw(io_is_busy);
- +
- +static struct global_attr boostpulse_gov_sys =
- + __ATTR(boostpulse, 0200, NULL, store_boostpulse_gov_sys);
- +
- +static struct freq_attr boostpulse_gov_pol =
- + __ATTR(boostpulse, 0200, NULL, store_boostpulse_gov_pol);
- +
- +/* One Governor instance for entire system */
- +static struct attribute *interactive_attributes_gov_sys[] = {
- + &target_loads_gov_sys.attr,
- + &above_hispeed_delay_gov_sys.attr,
- + &hispeed_freq_gov_sys.attr,
- + &go_hispeed_load_gov_sys.attr,
- + &min_sample_time_gov_sys.attr,
- + &timer_rate_gov_sys.attr,
- + &timer_slack_gov_sys.attr,
- + &boost_gov_sys.attr,
- + &boostpulse_gov_sys.attr,
- + &boostpulse_duration_gov_sys.attr,
- + &io_is_busy_gov_sys.attr,
- + NULL,
- +};
- +
- +static struct attribute_group interactive_attr_group_gov_sys = {
- + .attrs = interactive_attributes_gov_sys,
- + .name = "interactive",
- +};
- +
- +/* Per policy governor instance */
- +static struct attribute *interactive_attributes_gov_pol[] = {
- + &target_loads_gov_pol.attr,
- + &above_hispeed_delay_gov_pol.attr,
- + &hispeed_freq_gov_pol.attr,
- + &go_hispeed_load_gov_pol.attr,
- + &min_sample_time_gov_pol.attr,
- + &timer_rate_gov_pol.attr,
- + &timer_slack_gov_pol.attr,
- + &boost_gov_pol.attr,
- + &boostpulse_gov_pol.attr,
- + &boostpulse_duration_gov_pol.attr,
- + &io_is_busy_gov_pol.attr,
- + NULL,
- +};
- +
- +static struct attribute_group interactive_attr_group_gov_pol = {
- + .attrs = interactive_attributes_gov_pol,
- + .name = "interactive",
- +};
- +
- +static struct attribute_group *get_sysfs_attr(void)
- +{
- + if (have_governor_per_policy())
- + return &interactive_attr_group_gov_pol;
- + else
- + return &interactive_attr_group_gov_sys;
- +}
- +
- +static int cpufreq_interactive_idle_notifier(struct notifier_block *nb,
- + unsigned long val,
- + void *data)
- +{
- + switch (val) {
- + case IDLE_START:
- + cpufreq_interactive_idle_start();
- + break;
- + case IDLE_END:
- + cpufreq_interactive_idle_end();
- + break;
- + }
- +
- + return 0;
- +}
- +
- +static struct notifier_block cpufreq_interactive_idle_nb = {
- + .notifier_call = cpufreq_interactive_idle_notifier,
- +};
- +
- +static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
- + unsigned int event)
- +{
- + int rc;
- + unsigned int j;
- + struct cpufreq_interactive_cpuinfo *pcpu;
- + struct cpufreq_frequency_table *freq_table;
- + struct cpufreq_interactive_tunables *tunables;
- +
- + if (have_governor_per_policy())
- + tunables = policy->governor_data;
- + else
- + tunables = common_tunables;
- +
- + WARN_ON(!tunables && (event != CPUFREQ_GOV_POLICY_INIT));
- +
- + switch (event) {
- + case CPUFREQ_GOV_POLICY_INIT:
- + if (have_governor_per_policy()) {
- + WARN_ON(tunables);
- + } else if (tunables) {
- + tunables->usage_count++;
- + policy->governor_data = tunables;
- + return 0;
- + }
- +
- + tunables = kzalloc(sizeof(*tunables), GFP_KERNEL);
- + if (!tunables) {
- + pr_err("%s: POLICY_INIT: kzalloc failed\n", __func__);
- + return -ENOMEM;
- + }
- +
- + tunables->usage_count = 1;
- + tunables->above_hispeed_delay = default_above_hispeed_delay;
- + tunables->nabove_hispeed_delay =
- + ARRAY_SIZE(default_above_hispeed_delay);
- + tunables->go_hispeed_load = DEFAULT_GO_HISPEED_LOAD;
- + tunables->target_loads = default_target_loads;
- + tunables->ntarget_loads = ARRAY_SIZE(default_target_loads);
- + tunables->min_sample_time = DEFAULT_MIN_SAMPLE_TIME;
- + tunables->timer_rate = DEFAULT_TIMER_RATE;
- + tunables->boostpulse_duration_val = DEFAULT_MIN_SAMPLE_TIME;
- + tunables->timer_slack_val = DEFAULT_TIMER_SLACK;
- +
- + spin_lock_init(&tunables->target_loads_lock);
- + spin_lock_init(&tunables->above_hispeed_delay_lock);
- +
- + policy->governor_data = tunables;
- + if (!have_governor_per_policy()) {
- + common_tunables = tunables;
- + WARN_ON(cpufreq_get_global_kobject());
- + }
- +
- + rc = sysfs_create_group(get_governor_parent_kobj(policy),
- + get_sysfs_attr());
- + if (rc) {
- + kfree(tunables);
- + policy->governor_data = NULL;
- + if (!have_governor_per_policy())
- + common_tunables = NULL;
- + return rc;
- + }
- +
- + if (!policy->governor->initialized) {
- + idle_notifier_register(&cpufreq_interactive_idle_nb);
- + cpufreq_register_notifier(&cpufreq_notifier_block,
- + CPUFREQ_TRANSITION_NOTIFIER);
- + }
- +
- + break;
- +
- + case CPUFREQ_GOV_POLICY_EXIT:
- + if (!--tunables->usage_count) {
- + sysfs_remove_group(get_governor_parent_kobj(policy),
- + get_sysfs_attr());
- +
- + if (!have_governor_per_policy())
- + cpufreq_put_global_kobject();
- +
- + if (policy->governor->initialized == 1) {
- + cpufreq_unregister_notifier(&cpufreq_notifier_block,
- + CPUFREQ_TRANSITION_NOTIFIER);
- + idle_notifier_unregister(&cpufreq_interactive_idle_nb);
- + }
- +
- + kfree(tunables);
- + common_tunables = NULL;
- + }
- +
- + policy->governor_data = NULL;
- + break;
- +
- + case CPUFREQ_GOV_START:
- + mutex_lock(&gov_lock);
- +
- + freq_table = cpufreq_frequency_get_table(policy->cpu);
- + if (!tunables->hispeed_freq)
- + tunables->hispeed_freq = policy->max;
- +
- + for_each_cpu(j, policy->cpus) {
- + pcpu = &per_cpu(cpuinfo, j);
- + pcpu->policy = policy;
- + pcpu->target_freq = policy->cur;
- + pcpu->freq_table = freq_table;
- + pcpu->floor_freq = pcpu->target_freq;
- + pcpu->floor_validate_time =
- + ktime_to_us(ktime_get());
- + pcpu->hispeed_validate_time =
- + pcpu->floor_validate_time;
- + down_write(&pcpu->enable_sem);
- + del_timer_sync(&pcpu->cpu_timer);
- + del_timer_sync(&pcpu->cpu_slack_timer);
- + cpufreq_interactive_timer_start(tunables, j);
- + pcpu->governor_enabled = 1;
- + up_write(&pcpu->enable_sem);
- + }
- +
- + mutex_unlock(&gov_lock);
- + break;
- +
- + case CPUFREQ_GOV_STOP:
- + mutex_lock(&gov_lock);
- + for_each_cpu(j, policy->cpus) {
- + pcpu = &per_cpu(cpuinfo, j);
- + down_write(&pcpu->enable_sem);
- + pcpu->governor_enabled = 0;
- + del_timer_sync(&pcpu->cpu_timer);
- + del_timer_sync(&pcpu->cpu_slack_timer);
- + up_write(&pcpu->enable_sem);
- + }
- +
- + mutex_unlock(&gov_lock);
- + break;
- +
- + case CPUFREQ_GOV_LIMITS:
- + if (policy->max < policy->cur)
- + __cpufreq_driver_target(policy,
- + policy->max, CPUFREQ_RELATION_H);
- + else if (policy->min > policy->cur)
- + __cpufreq_driver_target(policy,
- + policy->min, CPUFREQ_RELATION_L);
- + for_each_cpu(j, policy->cpus) {
- + pcpu = &per_cpu(cpuinfo, j);
- +
- + /* hold write semaphore to avoid race */
- + down_write(&pcpu->enable_sem);
- + if (pcpu->governor_enabled == 0) {
- + up_write(&pcpu->enable_sem);
- + continue;
- + }
- +
- + /* update target_freq firstly */
- + if (policy->max < pcpu->target_freq)
- + pcpu->target_freq = policy->max;
- + else if (policy->min > pcpu->target_freq)
- + pcpu->target_freq = policy->min;
- +
- + /* Reschedule timer.
- + * Delete the timers, else the timer callback may
- + * return without re-arm the timer when failed
- + * acquire the semaphore. This race may cause timer
- + * stopped unexpectedly.
- + */
- + del_timer_sync(&pcpu->cpu_timer);
- + del_timer_sync(&pcpu->cpu_slack_timer);
- + cpufreq_interactive_timer_start(tunables, j);
- + up_write(&pcpu->enable_sem);
- + }
- + break;
- + }
- + return 0;
- +}
- +
- +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE
- +static
- +#endif
- +struct cpufreq_governor cpufreq_gov_interactive = {
- + .name = "interactive",
- + .governor = cpufreq_governor_interactive,
- + .max_transition_latency = 10000000,
- + .owner = THIS_MODULE,
- +};
- +
- +static void cpufreq_interactive_nop_timer(unsigned long data)
- +{
- +}
- +
- +static int __init cpufreq_interactive_init(void)
- +{
- + unsigned int i;
- + struct cpufreq_interactive_cpuinfo *pcpu;
- + struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
- +
- + /* Initalize per-cpu timers */
- + for_each_possible_cpu(i) {
- + pcpu = &per_cpu(cpuinfo, i);
- + init_timer_deferrable(&pcpu->cpu_timer);
- + pcpu->cpu_timer.function = cpufreq_interactive_timer;
- + pcpu->cpu_timer.data = i;
- + init_timer(&pcpu->cpu_slack_timer);
- + pcpu->cpu_slack_timer.function = cpufreq_interactive_nop_timer;
- + spin_lock_init(&pcpu->load_lock);
- + init_rwsem(&pcpu->enable_sem);
- + }
- +
- + spin_lock_init(&speedchange_cpumask_lock);
- + mutex_init(&gov_lock);
- + speedchange_task =
- + kthread_create(cpufreq_interactive_speedchange_task, NULL,
- + "cfinteractive");
- + if (IS_ERR(speedchange_task))
- + return PTR_ERR(speedchange_task);
- +
- + sched_setscheduler_nocheck(speedchange_task, SCHED_FIFO, ¶m);
- + get_task_struct(speedchange_task);
- +
- + /* NB: wake up so the thread does not look hung to the freezer */
- + wake_up_process(speedchange_task);
- +
- + return cpufreq_register_governor(&cpufreq_gov_interactive);
- +}
- +
- +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE
- +fs_initcall(cpufreq_interactive_init);
- +#else
- +module_init(cpufreq_interactive_init);
- +#endif
- +
- +static void __exit cpufreq_interactive_exit(void)
- +{
- + cpufreq_unregister_governor(&cpufreq_gov_interactive);
- + kthread_stop(speedchange_task);
- + put_task_struct(speedchange_task);
- +}
- +
- +module_exit(cpufreq_interactive_exit);
- +
- +MODULE_AUTHOR("Mike Chan <mike@android.com>");
- +MODULE_DESCRIPTION("'cpufreq_interactive' - A cpufreq governor for "
- + "Latency sensitive workloads");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/cpufreq/highbank-cpufreq.c linux-3.14.35/drivers/cpufreq/highbank-cpufreq.c
- --- linux-3.14.35.orig/drivers/cpufreq/highbank-cpufreq.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/cpufreq/highbank-cpufreq.c 2015-03-08 14:27:37.529684502 -0500
- @@ -19,7 +19,7 @@
- #include <linux/cpu.h>
- #include <linux/err.h>
- #include <linux/of.h>
- -#include <linux/mailbox.h>
- +#include <linux/pl320-ipc.h>
- #include <linux/platform_device.h>
-
- #define HB_CPUFREQ_CHANGE_NOTE 0x80000001
- diff -Nur linux-3.14.35.orig/drivers/cpufreq/imx6-cpufreq.c linux-3.14.35/drivers/cpufreq/imx6-cpufreq.c
- --- linux-3.14.35.orig/drivers/cpufreq/imx6-cpufreq.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/cpufreq/imx6-cpufreq.c 2015-03-08 14:27:37.529684502 -0500
- @@ -0,0 +1,393 @@
- +/*
- + * Copyright (C) 2013 Freescale Semiconductor, Inc.
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <linux/busfreq-imx6.h>
- +#include <linux/clk.h>
- +#include <linux/cpu.h>
- +#include <linux/cpufreq.h>
- +#include <linux/delay.h>
- +#include <linux/err.h>
- +#include <linux/module.h>
- +#include <linux/of.h>
- +#include <linux/pm_opp.h>
- +#include <linux/platform_device.h>
- +#include <linux/regulator/consumer.h>
- +#include <linux/suspend.h>
- +
- +#define PU_SOC_VOLTAGE_NORMAL 1250000
- +#define PU_SOC_VOLTAGE_HIGH 1275000
- +#define FREQ_1P2_GHZ 1200000000
- +
- +static struct regulator *arm_reg;
- +static struct regulator *pu_reg;
- +static struct regulator *soc_reg;
- +
- +static struct clk *arm_clk;
- +static struct clk *pll1_sys_clk;
- +static struct clk *pll1_sw_clk;
- +static struct clk *step_clk;
- +static struct clk *pll2_pfd2_396m_clk;
- +
- +static struct device *cpu_dev;
- +static struct cpufreq_frequency_table *freq_table;
- +static unsigned int transition_latency;
- +static struct mutex set_cpufreq_lock;
- +
- +static u32 *imx6_soc_volt;
- +static u32 soc_opp_count;
- +
- +static int imx6_set_target(struct cpufreq_policy *policy, unsigned int index)
- +{
- + struct dev_pm_opp *opp;
- + unsigned long freq_hz, volt, volt_old;
- + unsigned int old_freq, new_freq;
- + int ret;
- +
- + mutex_lock(&set_cpufreq_lock);
- +
- + new_freq = freq_table[index].frequency;
- + freq_hz = new_freq * 1000;
- + old_freq = clk_get_rate(arm_clk) / 1000;
- +
- + rcu_read_lock();
- + opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
- + if (IS_ERR(opp)) {
- + rcu_read_unlock();
- + dev_err(cpu_dev, "failed to find OPP for %ld\n", freq_hz);
- + ret = PTR_ERR(opp);
- + goto unlock;
- + }
- +
- + volt = dev_pm_opp_get_voltage(opp);
- + rcu_read_unlock();
- + volt_old = regulator_get_voltage(arm_reg);
- +
- + dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n",
- + old_freq / 1000, volt_old / 1000,
- + new_freq / 1000, volt / 1000);
- +
- + /*
- + * CPU freq is increasing, so need to ensure
- + * that bus frequency is increased too.
- + */
- + if (old_freq == freq_table[0].frequency)
- + request_bus_freq(BUS_FREQ_HIGH);
- +
- + /* scaling up? scale voltage before frequency */
- + if (new_freq > old_freq) {
- + if (regulator_is_enabled(pu_reg)) {
- + ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
- + if (ret) {
- + dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret);
- + goto unlock;
- + }
- + }
- + ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0);
- + if (ret) {
- + dev_err(cpu_dev, "failed to scale vddsoc up: %d\n", ret);
- + goto unlock;
- + }
- + ret = regulator_set_voltage_tol(arm_reg, volt, 0);
- + if (ret) {
- + dev_err(cpu_dev,
- + "failed to scale vddarm up: %d\n", ret);
- + goto unlock;
- + }
- + }
- +
- + /*
- + * The setpoints are selected per PLL/PDF frequencies, so we need to
- + * reprogram PLL for frequency scaling. The procedure of reprogramming
- + * PLL1 is as below.
- + *
- + * - Enable pll2_pfd2_396m_clk and reparent pll1_sw_clk to it
- + * - Reprogram pll1_sys_clk and reparent pll1_sw_clk back to it
- + * - Disable pll2_pfd2_396m_clk
- + */
- + clk_set_parent(step_clk, pll2_pfd2_396m_clk);
- + clk_set_parent(pll1_sw_clk, step_clk);
- + if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) {
- + clk_set_rate(pll1_sys_clk, new_freq * 1000);
- + clk_set_parent(pll1_sw_clk, pll1_sys_clk);
- + }
- +
- + /* Ensure the arm clock divider is what we expect */
- + ret = clk_set_rate(arm_clk, new_freq * 1000);
- + if (ret) {
- + dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
- + regulator_set_voltage_tol(arm_reg, volt_old, 0);
- + goto unlock;
- + }
- +
- + /* scaling down? scale voltage after frequency */
- + if (new_freq < old_freq) {
- + ret = regulator_set_voltage_tol(arm_reg, volt, 0);
- + if (ret) {
- + dev_warn(cpu_dev,
- + "failed to scale vddarm down: %d\n", ret);
- + ret = 0;
- + }
- + ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0);
- + if (ret) {
- + dev_warn(cpu_dev, "failed to scale vddsoc down: %d\n", ret);
- + ret = 0;
- + }
- + if (regulator_is_enabled(pu_reg)) {
- + ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
- + if (ret) {
- + dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret);
- + ret = 0;
- + }
- + }
- + }
- +
- + if (policy->cur == freq_table[0].frequency)
- + release_bus_freq(BUS_FREQ_HIGH);
- +
- +unlock:
- + mutex_unlock(&set_cpufreq_lock);
- + return ret;
- +}
- +
- +static int imx6_cpufreq_init(struct cpufreq_policy *policy)
- +{
- + policy->clk = arm_clk;
- +
- + if (policy->cur > freq_table[0].frequency)
- + request_bus_freq(BUS_FREQ_HIGH);
- +
- + return cpufreq_generic_init(policy, freq_table, transition_latency);
- +}
- +
- +static struct cpufreq_driver imx6_cpufreq_driver = {
- + .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK,
- + .verify = cpufreq_generic_frequency_table_verify,
- + .target_index = imx6_set_target,
- + .get = cpufreq_generic_get,
- + .init = imx6_cpufreq_init,
- + .exit = cpufreq_generic_exit,
- + .name = "imx6-cpufreq",
- + .attr = cpufreq_generic_attr,
- +};
- +
- +static int imx6_cpufreq_pm_notify(struct notifier_block *nb,
- + unsigned long event, void *dummy)
- +{
- + struct cpufreq_policy *data = cpufreq_cpu_get(0);
- + static u32 cpufreq_policy_min_pre_suspend;
- +
- + /*
- + * During suspend/resume, When cpufreq driver try to increase
- + * voltage/freq, it needs to control I2C/SPI to communicate
- + * with external PMIC to adjust voltage, but these I2C/SPI
- + * devices may be already suspended, to avoid such scenario,
- + * we just increase cpufreq to highest setpoint before suspend.
- + */
- + switch (event) {
- + case PM_SUSPEND_PREPARE:
- + cpufreq_policy_min_pre_suspend = data->user_policy.min;
- + data->user_policy.min = data->user_policy.max;
- + break;
- + case PM_POST_SUSPEND:
- + data->user_policy.min = cpufreq_policy_min_pre_suspend;
- + break;
- + default:
- + break;
- + }
- +
- + cpufreq_update_policy(0);
- +
- + return NOTIFY_OK;
- +}
- +
- +static struct notifier_block imx6_cpufreq_pm_notifier = {
- + .notifier_call = imx6_cpufreq_pm_notify,
- +};
- +
- +static int imx6_cpufreq_probe(struct platform_device *pdev)
- +{
- + struct device_node *np;
- + struct dev_pm_opp *opp;
- + unsigned long min_volt, max_volt;
- + int num, ret;
- + const struct property *prop;
- + const __be32 *val;
- + u32 nr, i, j;
- +
- + cpu_dev = get_cpu_device(0);
- + if (!cpu_dev) {
- + pr_err("failed to get cpu0 device\n");
- + return -ENODEV;
- + }
- +
- + np = of_node_get(cpu_dev->of_node);
- + if (!np) {
- + dev_err(cpu_dev, "failed to find cpu0 node\n");
- + return -ENOENT;
- + }
- +
- + arm_clk = devm_clk_get(cpu_dev, "arm");
- + pll1_sys_clk = devm_clk_get(cpu_dev, "pll1_sys");
- + pll1_sw_clk = devm_clk_get(cpu_dev, "pll1_sw");
- + step_clk = devm_clk_get(cpu_dev, "step");
- + pll2_pfd2_396m_clk = devm_clk_get(cpu_dev, "pll2_pfd2_396m");
- + if (IS_ERR(arm_clk) || IS_ERR(pll1_sys_clk) || IS_ERR(pll1_sw_clk) ||
- + IS_ERR(step_clk) || IS_ERR(pll2_pfd2_396m_clk)) {
- + dev_err(cpu_dev, "failed to get clocks\n");
- + ret = -ENOENT;
- + goto put_node;
- + }
- +
- + arm_reg = devm_regulator_get(cpu_dev, "arm");
- + pu_reg = devm_regulator_get(cpu_dev, "pu");
- + soc_reg = devm_regulator_get(cpu_dev, "soc");
- + if (IS_ERR(arm_reg) || IS_ERR(pu_reg) || IS_ERR(soc_reg)) {
- + dev_err(cpu_dev, "failed to get regulators\n");
- + ret = -ENOENT;
- + goto put_node;
- + }
- +
- + /*
- + * We expect an OPP table supplied by platform.
- + * Just, incase the platform did not supply the OPP
- + * table, it will try to get it.
- + */
- + num = dev_pm_opp_get_opp_count(cpu_dev);
- + if (num < 0) {
- + ret = of_init_opp_table(cpu_dev);
- + if (ret < 0) {
- + dev_err(cpu_dev, "failed to init OPP table: %d\n", ret);
- + goto put_node;
- + }
- +
- + num = dev_pm_opp_get_opp_count(cpu_dev);
- + if (num < 0) {
- + ret = num;
- + dev_err(cpu_dev, "no OPP table is found: %d\n", ret);
- + goto put_node;
- + }
- + }
- +
- + ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
- + if (ret) {
- + dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
- + goto put_node;
- + }
- +
- + /* Make imx6_soc_volt array's size same as arm opp number */
- + imx6_soc_volt = devm_kzalloc(cpu_dev, sizeof(*imx6_soc_volt) * num, GFP_KERNEL);
- + if (imx6_soc_volt == NULL) {
- + ret = -ENOMEM;
- + goto free_freq_table;
- + }
- +
- + prop = of_find_property(np, "fsl,soc-operating-points", NULL);
- + if (!prop || !prop->value)
- + goto soc_opp_out;
- +
- + /*
- + * Each OPP is a set of tuples consisting of frequency and
- + * voltage like <freq-kHz vol-uV>.
- + */
- + nr = prop->length / sizeof(u32);
- + if (nr % 2 || (nr / 2) < num)
- + goto soc_opp_out;
- +
- + for (j = 0; j < num; j++) {
- + val = prop->value;
- + for (i = 0; i < nr / 2; i++) {
- + unsigned long freq = be32_to_cpup(val++);
- + unsigned long volt = be32_to_cpup(val++);
- + if (freq_table[j].frequency == freq) {
- + imx6_soc_volt[soc_opp_count++] = volt;
- + break;
- + }
- + }
- + }
- +
- +soc_opp_out:
- + /* use fixed soc opp volt if no valid soc opp info found in dtb */
- + if (soc_opp_count != num) {
- + dev_warn(cpu_dev, "can NOT find valid fsl,soc-operating-points property in dtb, use default value!\n");
- + for (j = 0; j < num; j++)
- + imx6_soc_volt[j] = PU_SOC_VOLTAGE_NORMAL;
- + if (freq_table[num - 1].frequency * 1000 == FREQ_1P2_GHZ)
- + imx6_soc_volt[num - 1] = PU_SOC_VOLTAGE_HIGH;
- + }
- +
- + if (of_property_read_u32(np, "clock-latency", &transition_latency))
- + transition_latency = CPUFREQ_ETERNAL;
- +
- + /*
- + * Calculate the ramp time for max voltage change in the
- + * VDDSOC and VDDPU regulators.
- + */
- + ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
- + if (ret > 0)
- + transition_latency += ret * 1000;
- + ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
- + if (ret > 0)
- + transition_latency += ret * 1000;
- +
- + /*
- + * OPP is maintained in order of increasing frequency, and
- + * freq_table initialised from OPP is therefore sorted in the
- + * same order.
- + */
- + rcu_read_lock();
- + opp = dev_pm_opp_find_freq_exact(cpu_dev,
- + freq_table[0].frequency * 1000, true);
- + min_volt = dev_pm_opp_get_voltage(opp);
- + opp = dev_pm_opp_find_freq_exact(cpu_dev,
- + freq_table[--num].frequency * 1000, true);
- + max_volt = dev_pm_opp_get_voltage(opp);
- + rcu_read_unlock();
- + ret = regulator_set_voltage_time(arm_reg, min_volt, max_volt);
- + if (ret > 0)
- + transition_latency += ret * 1000;
- +
- + mutex_init(&set_cpufreq_lock);
- + register_pm_notifier(&imx6_cpufreq_pm_notifier);
- +
- + ret = cpufreq_register_driver(&imx6_cpufreq_driver);
- + if (ret) {
- + dev_err(cpu_dev, "failed register driver: %d\n", ret);
- + goto free_freq_table;
- + }
- +
- + of_node_put(np);
- + return 0;
- +
- +free_freq_table:
- + dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
- +put_node:
- + of_node_put(np);
- + return ret;
- +}
- +
- +static int imx6_cpufreq_remove(struct platform_device *pdev)
- +{
- + cpufreq_unregister_driver(&imx6_cpufreq_driver);
- + dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
- +
- + return 0;
- +}
- +
- +static struct platform_driver imx6_cpufreq_platdrv = {
- + .driver = {
- + .name = "imx6-cpufreq",
- + .owner = THIS_MODULE,
- + },
- + .probe = imx6_cpufreq_probe,
- + .remove = imx6_cpufreq_remove,
- +};
- +module_platform_driver(imx6_cpufreq_platdrv);
- +
- +MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
- +MODULE_DESCRIPTION("Freescale i.MX6Q cpufreq driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/cpufreq/imx6q-cpufreq.c linux-3.14.35/drivers/cpufreq/imx6q-cpufreq.c
- --- linux-3.14.35.orig/drivers/cpufreq/imx6q-cpufreq.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/cpufreq/imx6q-cpufreq.c 1969-12-31 18:00:00.000000000 -0600
- @@ -1,330 +0,0 @@
- -/*
- - * Copyright (C) 2013 Freescale Semiconductor, Inc.
- - *
- - * This program is free software; you can redistribute it and/or modify
- - * it under the terms of the GNU General Public License version 2 as
- - * published by the Free Software Foundation.
- - */
- -
- -#include <linux/clk.h>
- -#include <linux/cpu.h>
- -#include <linux/cpufreq.h>
- -#include <linux/delay.h>
- -#include <linux/err.h>
- -#include <linux/module.h>
- -#include <linux/of.h>
- -#include <linux/pm_opp.h>
- -#include <linux/platform_device.h>
- -#include <linux/regulator/consumer.h>
- -
- -#define PU_SOC_VOLTAGE_NORMAL 1250000
- -#define PU_SOC_VOLTAGE_HIGH 1275000
- -#define FREQ_1P2_GHZ 1200000000
- -
- -static struct regulator *arm_reg;
- -static struct regulator *pu_reg;
- -static struct regulator *soc_reg;
- -
- -static struct clk *arm_clk;
- -static struct clk *pll1_sys_clk;
- -static struct clk *pll1_sw_clk;
- -static struct clk *step_clk;
- -static struct clk *pll2_pfd2_396m_clk;
- -
- -static struct device *cpu_dev;
- -static struct cpufreq_frequency_table *freq_table;
- -static unsigned int transition_latency;
- -
- -static u32 *imx6_soc_volt;
- -static u32 soc_opp_count;
- -
- -static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
- -{
- - struct dev_pm_opp *opp;
- - unsigned long freq_hz, volt, volt_old;
- - unsigned int old_freq, new_freq;
- - int ret;
- -
- - new_freq = freq_table[index].frequency;
- - freq_hz = new_freq * 1000;
- - old_freq = clk_get_rate(arm_clk) / 1000;
- -
- - rcu_read_lock();
- - opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
- - if (IS_ERR(opp)) {
- - rcu_read_unlock();
- - dev_err(cpu_dev, "failed to find OPP for %ld\n", freq_hz);
- - return PTR_ERR(opp);
- - }
- -
- - volt = dev_pm_opp_get_voltage(opp);
- - rcu_read_unlock();
- - volt_old = regulator_get_voltage(arm_reg);
- -
- - dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n",
- - old_freq / 1000, volt_old / 1000,
- - new_freq / 1000, volt / 1000);
- -
- - /* scaling up? scale voltage before frequency */
- - if (new_freq > old_freq) {
- - ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
- - if (ret) {
- - dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret);
- - return ret;
- - }
- - ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0);
- - if (ret) {
- - dev_err(cpu_dev, "failed to scale vddsoc up: %d\n", ret);
- - return ret;
- - }
- - ret = regulator_set_voltage_tol(arm_reg, volt, 0);
- - if (ret) {
- - dev_err(cpu_dev,
- - "failed to scale vddarm up: %d\n", ret);
- - return ret;
- - }
- - }
- -
- - /*
- - * The setpoints are selected per PLL/PDF frequencies, so we need to
- - * reprogram PLL for frequency scaling. The procedure of reprogramming
- - * PLL1 is as below.
- - *
- - * - Enable pll2_pfd2_396m_clk and reparent pll1_sw_clk to it
- - * - Reprogram pll1_sys_clk and reparent pll1_sw_clk back to it
- - * - Disable pll2_pfd2_396m_clk
- - */
- - clk_set_parent(step_clk, pll2_pfd2_396m_clk);
- - clk_set_parent(pll1_sw_clk, step_clk);
- - if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) {
- - clk_set_rate(pll1_sys_clk, new_freq * 1000);
- - clk_set_parent(pll1_sw_clk, pll1_sys_clk);
- - }
- -
- - /* Ensure the arm clock divider is what we expect */
- - ret = clk_set_rate(arm_clk, new_freq * 1000);
- - if (ret) {
- - dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
- - regulator_set_voltage_tol(arm_reg, volt_old, 0);
- - return ret;
- - }
- -
- - /* scaling down? scale voltage after frequency */
- - if (new_freq < old_freq) {
- - ret = regulator_set_voltage_tol(arm_reg, volt, 0);
- - if (ret) {
- - dev_warn(cpu_dev,
- - "failed to scale vddarm down: %d\n", ret);
- - ret = 0;
- - }
- - ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0);
- - if (ret) {
- - dev_warn(cpu_dev, "failed to scale vddsoc down: %d\n", ret);
- - ret = 0;
- - }
- - ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
- - if (ret) {
- - dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret);
- - ret = 0;
- - }
- - }
- -
- - return 0;
- -}
- -
- -static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
- -{
- - policy->clk = arm_clk;
- - return cpufreq_generic_init(policy, freq_table, transition_latency);
- -}
- -
- -static struct cpufreq_driver imx6q_cpufreq_driver = {
- - .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK,
- - .verify = cpufreq_generic_frequency_table_verify,
- - .target_index = imx6q_set_target,
- - .get = cpufreq_generic_get,
- - .init = imx6q_cpufreq_init,
- - .exit = cpufreq_generic_exit,
- - .name = "imx6q-cpufreq",
- - .attr = cpufreq_generic_attr,
- -};
- -
- -static int imx6q_cpufreq_probe(struct platform_device *pdev)
- -{
- - struct device_node *np;
- - struct dev_pm_opp *opp;
- - unsigned long min_volt, max_volt;
- - int num, ret;
- - const struct property *prop;
- - const __be32 *val;
- - u32 nr, i, j;
- -
- - cpu_dev = get_cpu_device(0);
- - if (!cpu_dev) {
- - pr_err("failed to get cpu0 device\n");
- - return -ENODEV;
- - }
- -
- - np = of_node_get(cpu_dev->of_node);
- - if (!np) {
- - dev_err(cpu_dev, "failed to find cpu0 node\n");
- - return -ENOENT;
- - }
- -
- - arm_clk = devm_clk_get(cpu_dev, "arm");
- - pll1_sys_clk = devm_clk_get(cpu_dev, "pll1_sys");
- - pll1_sw_clk = devm_clk_get(cpu_dev, "pll1_sw");
- - step_clk = devm_clk_get(cpu_dev, "step");
- - pll2_pfd2_396m_clk = devm_clk_get(cpu_dev, "pll2_pfd2_396m");
- - if (IS_ERR(arm_clk) || IS_ERR(pll1_sys_clk) || IS_ERR(pll1_sw_clk) ||
- - IS_ERR(step_clk) || IS_ERR(pll2_pfd2_396m_clk)) {
- - dev_err(cpu_dev, "failed to get clocks\n");
- - ret = -ENOENT;
- - goto put_node;
- - }
- -
- - arm_reg = devm_regulator_get(cpu_dev, "arm");
- - pu_reg = devm_regulator_get(cpu_dev, "pu");
- - soc_reg = devm_regulator_get(cpu_dev, "soc");
- - if (IS_ERR(arm_reg) || IS_ERR(pu_reg) || IS_ERR(soc_reg)) {
- - dev_err(cpu_dev, "failed to get regulators\n");
- - ret = -ENOENT;
- - goto put_node;
- - }
- -
- - /*
- - * We expect an OPP table supplied by platform.
- - * Just, incase the platform did not supply the OPP
- - * table, it will try to get it.
- - */
- - num = dev_pm_opp_get_opp_count(cpu_dev);
- - if (num < 0) {
- - ret = of_init_opp_table(cpu_dev);
- - if (ret < 0) {
- - dev_err(cpu_dev, "failed to init OPP table: %d\n", ret);
- - goto put_node;
- - }
- -
- - num = dev_pm_opp_get_opp_count(cpu_dev);
- - if (num < 0) {
- - ret = num;
- - dev_err(cpu_dev, "no OPP table is found: %d\n", ret);
- - goto put_node;
- - }
- - }
- -
- - ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
- - if (ret) {
- - dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
- - goto put_node;
- - }
- -
- - /* Make imx6_soc_volt array's size same as arm opp number */
- - imx6_soc_volt = devm_kzalloc(cpu_dev, sizeof(*imx6_soc_volt) * num, GFP_KERNEL);
- - if (imx6_soc_volt == NULL) {
- - ret = -ENOMEM;
- - goto free_freq_table;
- - }
- -
- - prop = of_find_property(np, "fsl,soc-operating-points", NULL);
- - if (!prop || !prop->value)
- - goto soc_opp_out;
- -
- - /*
- - * Each OPP is a set of tuples consisting of frequency and
- - * voltage like <freq-kHz vol-uV>.
- - */
- - nr = prop->length / sizeof(u32);
- - if (nr % 2 || (nr / 2) < num)
- - goto soc_opp_out;
- -
- - for (j = 0; j < num; j++) {
- - val = prop->value;
- - for (i = 0; i < nr / 2; i++) {
- - unsigned long freq = be32_to_cpup(val++);
- - unsigned long volt = be32_to_cpup(val++);
- - if (freq_table[j].frequency == freq) {
- - imx6_soc_volt[soc_opp_count++] = volt;
- - break;
- - }
- - }
- - }
- -
- -soc_opp_out:
- - /* use fixed soc opp volt if no valid soc opp info found in dtb */
- - if (soc_opp_count != num) {
- - dev_warn(cpu_dev, "can NOT find valid fsl,soc-operating-points property in dtb, use default value!\n");
- - for (j = 0; j < num; j++)
- - imx6_soc_volt[j] = PU_SOC_VOLTAGE_NORMAL;
- - if (freq_table[num - 1].frequency * 1000 == FREQ_1P2_GHZ)
- - imx6_soc_volt[num - 1] = PU_SOC_VOLTAGE_HIGH;
- - }
- -
- - if (of_property_read_u32(np, "clock-latency", &transition_latency))
- - transition_latency = CPUFREQ_ETERNAL;
- -
- - /*
- - * Calculate the ramp time for max voltage change in the
- - * VDDSOC and VDDPU regulators.
- - */
- - ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
- - if (ret > 0)
- - transition_latency += ret * 1000;
- - ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
- - if (ret > 0)
- - transition_latency += ret * 1000;
- -
- - /*
- - * OPP is maintained in order of increasing frequency, and
- - * freq_table initialised from OPP is therefore sorted in the
- - * same order.
- - */
- - rcu_read_lock();
- - opp = dev_pm_opp_find_freq_exact(cpu_dev,
- - freq_table[0].frequency * 1000, true);
- - min_volt = dev_pm_opp_get_voltage(opp);
- - opp = dev_pm_opp_find_freq_exact(cpu_dev,
- - freq_table[--num].frequency * 1000, true);
- - max_volt = dev_pm_opp_get_voltage(opp);
- - rcu_read_unlock();
- - ret = regulator_set_voltage_time(arm_reg, min_volt, max_volt);
- - if (ret > 0)
- - transition_latency += ret * 1000;
- -
- - ret = cpufreq_register_driver(&imx6q_cpufreq_driver);
- - if (ret) {
- - dev_err(cpu_dev, "failed register driver: %d\n", ret);
- - goto free_freq_table;
- - }
- -
- - of_node_put(np);
- - return 0;
- -
- -free_freq_table:
- - dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
- -put_node:
- - of_node_put(np);
- - return ret;
- -}
- -
- -static int imx6q_cpufreq_remove(struct platform_device *pdev)
- -{
- - cpufreq_unregister_driver(&imx6q_cpufreq_driver);
- - dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
- -
- - return 0;
- -}
- -
- -static struct platform_driver imx6q_cpufreq_platdrv = {
- - .driver = {
- - .name = "imx6q-cpufreq",
- - .owner = THIS_MODULE,
- - },
- - .probe = imx6q_cpufreq_probe,
- - .remove = imx6q_cpufreq_remove,
- -};
- -module_platform_driver(imx6q_cpufreq_platdrv);
- -
- -MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
- -MODULE_DESCRIPTION("Freescale i.MX6Q cpufreq driver");
- -MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/cpufreq/Kconfig linux-3.14.35/drivers/cpufreq/Kconfig
- --- linux-3.14.35.orig/drivers/cpufreq/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/cpufreq/Kconfig 2015-03-08 14:27:37.541684501 -0500
- @@ -91,6 +91,15 @@
- governor. If unsure have a look at the help section of the
- driver. Fallback governor will be the performance governor.
-
- +config CPU_FREQ_DEFAULT_GOV_INTERACTIVE
- + bool "interactive"
- + select CPU_FREQ_GOV_INTERACTIVE
- + help
- + Use the CPUFreq governor 'interactive' as default. This allows
- + you to get a full dynamic cpu frequency capable system by simply
- + loading your cpufreq low-level hardware driver, using the
- + 'interactive' governor for latency-sensitive workloads.
- +
- config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
- bool "conservative"
- select CPU_FREQ_GOV_CONSERVATIVE
- @@ -157,6 +166,24 @@
-
- For details, take a look at linux/Documentation/cpu-freq.
-
- + If in doubt, say N.
- +
- +config CPU_FREQ_GOV_INTERACTIVE
- + tristate "'interactive' cpufreq policy governor"
- + default n
- + help
- + 'interactive' - This driver adds a dynamic cpufreq policy governor
- + designed for latency-sensitive workloads.
- +
- + This governor attempts to reduce the latency of clock
- + increases so that the system is more responsive to
- + interactive workloads.
- +
- + To compile this driver as a module, choose M here: the
- + module will be called cpufreq_interactive.
- +
- + For details, take a look at linux/Documentation/cpu-freq.
- +
- If in doubt, say N.
-
- config CPU_FREQ_GOV_CONSERVATIVE
- diff -Nur linux-3.14.35.orig/drivers/cpufreq/Kconfig.arm linux-3.14.35/drivers/cpufreq/Kconfig.arm
- --- linux-3.14.35.orig/drivers/cpufreq/Kconfig.arm 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/cpufreq/Kconfig.arm 2015-03-08 14:27:37.541684501 -0500
- @@ -4,7 +4,8 @@
-
- config ARM_BIG_LITTLE_CPUFREQ
- tristate "Generic ARM big LITTLE CPUfreq driver"
- - depends on ARM && BIG_LITTLE && ARM_CPU_TOPOLOGY && HAVE_CLK
- + depends on (BIG_LITTLE && ARM_CPU_TOPOLOGY) || (ARM64 && SMP)
- + depends on HAVE_CLK
- select PM_OPP
- help
- This enables the Generic CPUfreq driver for ARM big.LITTLE platforms.
- @@ -95,7 +96,7 @@
-
- If in doubt, say N.
-
- -config ARM_IMX6Q_CPUFREQ
- +config ARM_IMX6_CPUFREQ
- tristate "Freescale i.MX6 cpufreq support"
- depends on ARCH_MXC
- depends on REGULATOR_ANATOP
- diff -Nur linux-3.14.35.orig/drivers/cpufreq/Makefile linux-3.14.35/drivers/cpufreq/Makefile
- --- linux-3.14.35.orig/drivers/cpufreq/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/cpufreq/Makefile 2015-03-08 14:27:37.541684501 -0500
- @@ -8,6 +8,7 @@
- obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o
- obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o
- obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o
- +obj-$(CONFIG_CPU_FREQ_GOV_INTERACTIVE) += cpufreq_interactive.o
- obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o
- obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o
-
- @@ -55,7 +56,7 @@
- obj-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o
- obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o
- obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o
- -obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
- +obj-$(CONFIG_ARM_IMX6_CPUFREQ) += imx6-cpufreq.o
- obj-$(CONFIG_ARM_INTEGRATOR) += integrator-cpufreq.o
- obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o
- obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o
- diff -Nur linux-3.14.35.orig/drivers/crypto/caam/secvio.c linux-3.14.35/drivers/crypto/caam/secvio.c
- --- linux-3.14.35.orig/drivers/crypto/caam/secvio.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/crypto/caam/secvio.c 2015-03-08 14:27:37.541684501 -0500
- @@ -0,0 +1,335 @@
- +
- +/*
- + * CAAM/SEC 4.x Security Violation Handler
- + * Copyright (C) 2013 Freescale Semiconductor, Inc., All Rights Reserved
- + */
- +
- +#include "compat.h"
- +#include "intern.h"
- +#include "secvio.h"
- +#include "regs.h"
- +
- +/*
- + * These names are associated with each violation handler.
- + * The source names were taken from MX6, and are based on recommendations
- + * for most common SoCs.
- + */
- +static const u8 *violation_src_name[] = {
- + "CAAM Security Violation",
- + "JTAG Alarm",
- + "Watchdog",
- + "(reserved)",
- + "External Boot",
- + "Tamper Detect",
- +};
- +
- +/* Top-level security violation interrupt */
- +static irqreturn_t caam_secvio_interrupt(int irq, void *snvsdev)
- +{
- + struct device *dev = snvsdev;
- + struct caam_drv_private_secvio *svpriv = dev_get_drvdata(dev);
- + u32 irqstate;
- +
- + /* Check the HP secvio status register */
- + irqstate = rd_reg32(&svpriv->svregs->hp.secvio_status) |
- + HP_SECVIOST_SECVIOMASK;
- +
- + if (!irqstate)
- + return IRQ_NONE;
- +
- + /* Mask out one or more causes for deferred service */
- + clrbits32(&svpriv->svregs->hp.secvio_int_ctl, irqstate);
- +
- + /* Now ACK causes */
- + setbits32(&svpriv->svregs->hp.secvio_status, irqstate);
- +
- + /* And run deferred service */
- + preempt_disable();
- + tasklet_schedule(&svpriv->irqtask[smp_processor_id()]);
- + preempt_enable();
- +
- + return IRQ_HANDLED;
- +}
- +
- +/* Deferred service handler. Tasklet arg is simply the SNVS dev */
- +static void caam_secvio_dispatch(unsigned long indev)
- +{
- + struct device *dev = (struct device *)indev;
- + struct caam_drv_private_secvio *svpriv = dev_get_drvdata(dev);
- + unsigned long flags, cause;
- + int i;
- +
- +
- + /*
- + * Capture the interrupt cause, using masked interrupts as
- + * identification. This only works if all are enabled; if
- + * this changes in the future, a "cause queue" will have to
- + * be built
- + */
- + cause = rd_reg32(&svpriv->svregs->hp.secvio_int_ctl) &
- + (HP_SECVIO_INTEN_SRC5 | HP_SECVIO_INTEN_SRC4 |
- + HP_SECVIO_INTEN_SRC3 | HP_SECVIO_INTEN_SRC2 |
- + HP_SECVIO_INTEN_SRC1 | HP_SECVIO_INTEN_SRC0);
- +
- + /* Look through causes, call each handler if exists */
- + for (i = 0; i < MAX_SECVIO_SOURCES; i++)
- + if (cause & (1 << i)) {
- + spin_lock_irqsave(&svpriv->svlock, flags);
- + svpriv->intsrc[i].handler(dev, i,
- + svpriv->intsrc[i].ext);
- + spin_unlock_irqrestore(&svpriv->svlock, flags);
- + };
- +
- + /* Re-enable now-serviced interrupts */
- + setbits32(&svpriv->svregs->hp.secvio_int_ctl, cause);
- +}
- +
- +/*
- + * Default cause handler, used in lieu of an application-defined handler.
- + * All it does at this time is print a console message. It could force a halt.
- + */
- +static void caam_secvio_default(struct device *dev, u32 cause, void *ext)
- +{
- + struct caam_drv_private_secvio *svpriv = dev_get_drvdata(dev);
- +
- + dev_err(dev, "Unhandled Security Violation Interrupt %d = %s\n",
- + cause, svpriv->intsrc[cause].intname);
- +}
- +
- +/*
- + * Install an application-defined handler for a specified cause
- + * Arguments:
- + * - dev points to SNVS-owning device
- + * - cause interrupt source cause
- + * - handler application-defined handler, gets called with dev
- + * source cause, and locally-defined handler argument
- + * - cause_description points to a string to override the default cause
- + * name, this can be used as an alternate for error
- + * messages and such. If left NULL, the default
- + * description string is used.
- + * - ext pointer to any extra data needed by the handler.
- + */
- +int caam_secvio_install_handler(struct device *dev, enum secvio_cause cause,
- + void (*handler)(struct device *dev, u32 cause,
- + void *ext),
- + u8 *cause_description, void *ext)
- +{
- + unsigned long flags;
- + struct caam_drv_private_secvio *svpriv;
- +
- + svpriv = dev_get_drvdata(dev);
- +
- + if ((handler == NULL) || (cause > SECVIO_CAUSE_SOURCE_5))
- + return -EINVAL;
- +
- + spin_lock_irqsave(&svpriv->svlock, flags);
- + svpriv->intsrc[cause].handler = handler;
- + if (cause_description != NULL)
- + svpriv->intsrc[cause].intname = cause_description;
- + if (ext != NULL)
- + svpriv->intsrc[cause].ext = ext;
- + spin_unlock_irqrestore(&svpriv->svlock, flags);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(caam_secvio_install_handler);
- +
- +/*
- + * Remove an application-defined handler for a specified cause (and, by
- + * implication, restore the "default".
- + * Arguments:
- + * - dev points to SNVS-owning device
- + * - cause interrupt source cause
- + */
- +int caam_secvio_remove_handler(struct device *dev, enum secvio_cause cause)
- +{
- + unsigned long flags;
- + struct caam_drv_private_secvio *svpriv;
- +
- + svpriv = dev_get_drvdata(dev);
- +
- + if (cause > SECVIO_CAUSE_SOURCE_5)
- + return -EINVAL;
- +
- + spin_lock_irqsave(&svpriv->svlock, flags);
- + svpriv->intsrc[cause].intname = violation_src_name[cause];
- + svpriv->intsrc[cause].handler = caam_secvio_default;
- + svpriv->intsrc[cause].ext = NULL;
- + spin_unlock_irqrestore(&svpriv->svlock, flags);
- + return 0;
- +}
- +EXPORT_SYMBOL(caam_secvio_remove_handler);
- +
- +int caam_secvio_startup(struct platform_device *pdev)
- +{
- + struct device *ctrldev, *svdev;
- + struct caam_drv_private *ctrlpriv;
- + struct caam_drv_private_secvio *svpriv;
- + struct platform_device *svpdev;
- + struct device_node *np;
- + const void *prop;
- + int i, error, secvio_inten_src;
- +
- + ctrldev = &pdev->dev;
- + ctrlpriv = dev_get_drvdata(ctrldev);
- + /*
- + * Set up the private block for secure memory
- + * Only one instance is possible
- + */
- + svpriv = kzalloc(sizeof(struct caam_drv_private_secvio), GFP_KERNEL);
- + if (svpriv == NULL) {
- + dev_err(ctrldev, "can't alloc private mem for secvio\n");
- + return -ENOMEM;
- + }
- + svpriv->parentdev = ctrldev;
- +
- + /* Create the security violation dev */
- +#ifdef CONFIG_OF
- +
- + np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-caam-secvio");
- + if (!np)
- + return -ENODEV;
- +
- + ctrlpriv->secvio_irq = of_irq_to_resource(np, 0, NULL);
- +
- + prop = of_get_property(np, "secvio_src", NULL);
- + if (prop)
- + secvio_inten_src = of_read_ulong(prop, 1);
- + else
- + secvio_inten_src = HP_SECVIO_INTEN_ALL;
- +
- + printk(KERN_ERR "secvio_inten_src = %x\n", secvio_inten_src);
- +
- + svpdev = of_platform_device_create(np, NULL, ctrldev);
- + if (!svpdev)
- + return -ENODEV;
- +
- +#else
- + svpdev = platform_device_register_data(ctrldev, "caam_secvio", 0,
- + svpriv,
- + sizeof(struct caam_drv_private_secvio));
- +
- + secvio_inten_src = HP_SECVIO_INTEN_ALL;
- +#endif
- + if (svpdev == NULL) {
- + kfree(svpriv);
- + return -EINVAL;
- + }
- + svdev = &svpdev->dev;
- + dev_set_drvdata(svdev, svpriv);
- + ctrlpriv->secviodev = svdev;
- + svpriv->svregs = ctrlpriv->snvs;
- +
- + /*
- + * Now we have all the dev data set up. Init interrupt
- + * source descriptions
- + */
- + for (i = 0; i < MAX_SECVIO_SOURCES; i++) {
- + svpriv->intsrc[i].intname = violation_src_name[i];
- + svpriv->intsrc[i].handler = caam_secvio_default;
- + }
- +
- + /* Connect main handler */
- + for_each_possible_cpu(i)
- + tasklet_init(&svpriv->irqtask[i], caam_secvio_dispatch,
- + (unsigned long)svdev);
- +
- + error = request_irq(ctrlpriv->secvio_irq, caam_secvio_interrupt,
- + IRQF_SHARED, "caam_secvio", svdev);
- + if (error) {
- + dev_err(svdev, "can't connect secvio interrupt\n");
- + irq_dispose_mapping(ctrlpriv->secvio_irq);
- + ctrlpriv->secvio_irq = 0;
- + return -EINVAL;
- + }
- +
- + /* Enable all sources */
- + wr_reg32(&svpriv->svregs->hp.secvio_int_ctl, secvio_inten_src);
- +
- + dev_info(svdev, "security violation service handlers armed\n");
- +
- + return 0;
- +}
- +
- +void caam_secvio_shutdown(struct platform_device *pdev)
- +{
- + struct device *ctrldev, *svdev;
- + struct caam_drv_private *priv;
- + struct caam_drv_private_secvio *svpriv;
- + int i;
- +
- + ctrldev = &pdev->dev;
- + priv = dev_get_drvdata(ctrldev);
- + svdev = priv->secviodev;
- + svpriv = dev_get_drvdata(svdev);
- +
- + /* Shut off all sources */
- +
- + wr_reg32(&svpriv->svregs->hp.secvio_int_ctl, 0);
- +
- + /* Remove tasklets and release interrupt */
- + for_each_possible_cpu(i)
- + tasklet_kill(&svpriv->irqtask[i]);
- +
- + free_irq(priv->secvio_irq, svdev);
- +
- + kfree(svpriv);
- +}
- +
- +
- +#ifdef CONFIG_OF
- +static void __exit caam_secvio_exit(void)
- +{
- + struct device_node *dev_node;
- + struct platform_device *pdev;
- +
- + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
- + if (!dev_node) {
- + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
- + if (!dev_node)
- + return;
- + }
- +
- + pdev = of_find_device_by_node(dev_node);
- + if (!pdev)
- + return;
- +
- + of_node_get(dev_node);
- +
- + caam_secvio_shutdown(pdev);
- +
- +}
- +
- +static int __init caam_secvio_init(void)
- +{
- + struct device_node *dev_node;
- + struct platform_device *pdev;
- +
- + /*
- + * Do of_find_compatible_node() then of_find_device_by_node()
- + * once a functional device tree is available
- + */
- + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
- + if (!dev_node) {
- + dev_node = of_find_compatible_node(NULL, NULL,
- + "arm,imx6-caam-secvio");
- + if (!dev_node)
- + return -ENODEV;
- + }
- +
- + pdev = of_find_device_by_node(dev_node);
- + if (!pdev)
- + return -ENODEV;
- +
- + of_node_put(dev_node);
- +
- + return caam_secvio_startup(pdev);
- +}
- +
- +module_init(caam_secvio_init);
- +module_exit(caam_secvio_exit);
- +
- +MODULE_LICENSE("Dual BSD/GPL");
- +MODULE_DESCRIPTION("FSL CAAM/SNVS Security Violation Handler");
- +MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD");
- +#endif
- diff -Nur linux-3.14.35.orig/drivers/crypto/caam/secvio.h linux-3.14.35/drivers/crypto/caam/secvio.h
- --- linux-3.14.35.orig/drivers/crypto/caam/secvio.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/crypto/caam/secvio.h 2015-03-08 14:27:37.541684501 -0500
- @@ -0,0 +1,64 @@
- +
- +/*
- + * CAAM Security Violation Handler
- + * Copyright (C) 2013 Freescale Semiconductor, Inc., All Rights Reserved
- + */
- +
- +#ifndef SECVIO_H
- +#define SECVIO_H
- +
- +#include "snvsregs.h"
- +
- +
- +/*
- + * Defines the published interfaces to install/remove application-specified
- + * handlers for catching violations
- + */
- +
- +#define MAX_SECVIO_SOURCES 6
- +
- +/* these are the untranslated causes */
- +enum secvio_cause {
- + SECVIO_CAUSE_SOURCE_0,
- + SECVIO_CAUSE_SOURCE_1,
- + SECVIO_CAUSE_SOURCE_2,
- + SECVIO_CAUSE_SOURCE_3,
- + SECVIO_CAUSE_SOURCE_4,
- + SECVIO_CAUSE_SOURCE_5
- +};
- +
- +/* These are common "recommended" cause definitions for most devices */
- +#define SECVIO_CAUSE_CAAM_VIOLATION SECVIO_CAUSE_SOURCE_0
- +#define SECVIO_CAUSE JTAG_ALARM SECVIO_CAUSE_SOURCE_1
- +#define SECVIO_CAUSE_WATCHDOG SECVIO_CAUSE_SOURCE_2
- +#define SECVIO_CAUSE_EXTERNAL_BOOT SECVIO_CAUSE_SOURCE_4
- +#define SECVIO_CAUSE_TAMPER_DETECT SECVIO_CAUSE_SOURCE_5
- +
- +int caam_secvio_install_handler(struct device *dev, enum secvio_cause cause,
- + void (*handler)(struct device *dev, u32 cause,
- + void *ext),
- + u8 *cause_description, void *ext);
- +int caam_secvio_remove_handler(struct device *dev, enum secvio_cause cause);
- +
- +/*
- + * Private data definitions for the secvio "driver"
- + */
- +
- +struct secvio_int_src {
- + const u8 *intname; /* Points to a descriptive name for source */
- + void *ext; /* Extended data to pass to the handler */
- + void (*handler)(struct device *dev, u32 cause, void *ext);
- +};
- +
- +struct caam_drv_private_secvio {
- + struct device *parentdev; /* points back to the controller */
- + spinlock_t svlock ____cacheline_aligned;
- + struct tasklet_struct irqtask[NR_CPUS];
- + struct snvs_full __iomem *svregs; /* both HP and LP domains */
- +
- + /* Registered handlers for each violation */
- + struct secvio_int_src intsrc[MAX_SECVIO_SOURCES];
- +
- +};
- +
- +#endif /* SECVIO_H */
- diff -Nur linux-3.14.35.orig/drivers/crypto/caam/sm.h linux-3.14.35/drivers/crypto/caam/sm.h
- --- linux-3.14.35.orig/drivers/crypto/caam/sm.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/crypto/caam/sm.h 2015-03-08 14:27:37.545684501 -0500
- @@ -0,0 +1,88 @@
- +
- +/*
- + * CAAM Secure Memory/Keywrap API Definitions
- + * Copyright (C) 2008-2013 Freescale Semiconductor, Inc.
- + */
- +
- +#ifndef SM_H
- +#define SM_H
- +
- +
- +/* Storage access permissions */
- +#define SM_PERM_READ 0x01
- +#define SM_PERM_WRITE 0x02
- +#define SM_PERM_BLOB 0x03
- +
- +
- +/* Keystore maintenance functions */
- +void sm_init_keystore(struct device *dev);
- +u32 sm_detect_keystore_units(struct device *dev);
- +int sm_establish_keystore(struct device *dev, u32 unit);
- +void sm_release_keystore(struct device *dev, u32 unit);
- +void caam_sm_shutdown(struct platform_device *pdev);
- +int caam_sm_example_init(struct platform_device *pdev);
- +
- +/* Keystore accessor functions */
- +extern int sm_keystore_slot_alloc(struct device *dev, u32 unit, u32 size,
- + u32 *slot);
- +extern int sm_keystore_slot_dealloc(struct device *dev, u32 unit, u32 slot);
- +extern int sm_keystore_slot_load(struct device *dev, u32 unit, u32 slot,
- + const u8 *key_data, u32 key_length);
- +extern int sm_keystore_slot_read(struct device *dev, u32 unit, u32 slot,
- + u32 key_length, u8 *key_data);
- +extern int sm_keystore_slot_encapsulate(struct device *dev, u32 unit,
- + u32 inslot, u32 outslot, u16 secretlen,
- + u8 *keymod, u16 keymodlen);
- +extern int sm_keystore_slot_decapsulate(struct device *dev, u32 unit,
- + u32 inslot, u32 outslot, u16 secretlen,
- + u8 *keymod, u16 keymodlen);
- +
- +/* Data structure to hold per-slot information */
- +struct keystore_data_slot_info {
- + u8 allocated; /* Track slot assignments */
- + u32 key_length; /* Size of the key */
- +};
- +
- +/* Data structure to hold keystore information */
- +struct keystore_data {
- + void *base_address; /* Base of the Secure Partition */
- + u32 slot_count; /* Number of slots in the keystore */
- + struct keystore_data_slot_info *slot; /* Per-slot information */
- +};
- +
- +/* store the detected attributes of a secure memory page */
- +struct sm_page_descriptor {
- + u16 phys_pagenum; /* may be discontiguous */
- + u16 own_part; /* Owning partition */
- + void *pg_base; /* Calculated virtual address */
- + struct keystore_data *ksdata;
- +};
- +
- +struct caam_drv_private_sm {
- + struct device *parentdev; /* this ends up as the controller */
- + struct device *smringdev; /* ring that owns this instance */
- + spinlock_t kslock ____cacheline_aligned;
- +
- + /* Default parameters for geometry */
- + u32 max_pages; /* maximum pages this instance can support */
- + u32 top_partition; /* highest partition number in this instance */
- + u32 top_page; /* highest page number in this instance */
- + u32 page_size; /* page size */
- + u32 slot_size; /* selected size of each storage block */
- +
- + /* Partition/Page Allocation Map */
- + u32 localpages; /* Number of pages we can access */
- + struct sm_page_descriptor *pagedesc; /* Allocated per-page */
- +
- + /* Installed handlers for keystore access */
- + int (*data_init)(struct device *dev, u32 unit);
- + void (*data_cleanup)(struct device *dev, u32 unit);
- + int (*slot_alloc)(struct device *dev, u32 unit, u32 size, u32 *slot);
- + int (*slot_dealloc)(struct device *dev, u32 unit, u32 slot);
- + void *(*slot_get_address)(struct device *dev, u32 unit, u32 handle);
- + u32 (*slot_get_base)(struct device *dev, u32 unit, u32 handle);
- + u32 (*slot_get_offset)(struct device *dev, u32 unit, u32 handle);
- + u32 (*slot_get_slot_size)(struct device *dev, u32 unit, u32 handle);
- +};
- +
- +#endif /* SM_H */
- diff -Nur linux-3.14.35.orig/drivers/crypto/caam/sm_store.c linux-3.14.35/drivers/crypto/caam/sm_store.c
- --- linux-3.14.35.orig/drivers/crypto/caam/sm_store.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/crypto/caam/sm_store.c 2015-03-08 14:27:37.545684501 -0500
- @@ -0,0 +1,896 @@
- +
- +/*
- + * CAAM Secure Memory Storage Interface
- + * Copyright (C) 2008-2013 Freescale Semiconductor, Inc.
- + *
- + * Loosely based on the SHW Keystore API for SCC/SCC2
- + * Experimental implementation and NOT intended for upstream use. Expect
- + * this interface to be amended significantly in the future once it becomes
- + * integrated into live applications.
- + *
- + * Known issues:
- + *
- + * - Executes one instance of an secure memory "driver". This is tied to the
- + * fact that job rings can't run as standalone instances in the present
- + * configuration.
- + *
- + * - It does not expose a userspace interface. The value of a userspace
- + * interface for access to secrets is a point for further architectural
- + * discussion.
- + *
- + * - Partition/permission management is not part of this interface. It
- + * depends on some level of "knowledge" agreed upon between bootloader,
- + * provisioning applications, and OS-hosted software (which uses this
- + * driver).
- + *
- + * - No means of identifying the location or purpose of secrets managed by
- + * this interface exists; "slot location" and format of a given secret
- + * needs to be agreed upon between bootloader, provisioner, and OS-hosted
- + * application.
- + */
- +
- +#include "compat.h"
- +#include "regs.h"
- +#include "jr.h"
- +#include "desc.h"
- +#include "intern.h"
- +#include "error.h"
- +#include "sm.h"
- +
- +#ifdef SM_DEBUG_CONT
- +void sm_show_page(struct device *dev, struct sm_page_descriptor *pgdesc)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- + u32 i, *smdata;
- +
- + dev_info(dev, "physical page %d content at 0x%08x\n",
- + pgdesc->phys_pagenum, pgdesc->pg_base);
- + smdata = pgdesc->pg_base;
- + for (i = 0; i < (smpriv->page_size / sizeof(u32)); i += 4)
- + dev_info(dev, "[0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n",
- + (u32)&smdata[i], smdata[i], smdata[i+1], smdata[i+2],
- + smdata[i+3]);
- +}
- +#endif
- +
- +/*
- + * Construct a secure memory blob encapsulation job descriptor
- + *
- + * - desc pointer to hold new (to be allocated) pointer to the generated
- + * descriptor for later use. Calling thread can kfree the
- + * descriptor after execution.
- + * - keymod Physical pointer to key modifier (contiguous piece).
- + * - keymodsz Size of key modifier in bytes (should normally be 8).
- + * - secretbuf Physical pointer (within an accessible secure memory page)
- + * of the secret to be encapsulated.
- + * - outbuf Physical pointer (within an accessible secure memory page)
- + * of the encapsulated output. This will be larger than the
- + * input secret because of the added encapsulation data.
- + * - secretsz Size of input secret, in bytes.
- + * - auth If nonzero, use AES-CCM for encapsulation, else use ECB
- + *
- + * Note: this uses 32-bit pointers at present
- + */
- +#define INITIAL_DESCSZ 16 /* size of tmp buffer for descriptor const. */
- +static int blob_encap_desc(u32 **desc, dma_addr_t keymod, u16 keymodsz,
- + dma_addr_t secretbuf, dma_addr_t outbuf,
- + u16 secretsz, bool auth)
- +{
- + u32 *tdesc, tmpdesc[INITIAL_DESCSZ];
- + u16 dsize, idx;
- +
- + memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32));
- + idx = 1;
- +
- + /* Load key modifier */
- + tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY |
- + ((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK) |
- + (keymodsz & LDST_LEN_MASK);
- +
- + tmpdesc[idx++] = (u32)keymod;
- +
- + /* Encapsulate to secure memory */
- + tmpdesc[idx++] = CMD_SEQ_IN_PTR | secretsz;
- + tmpdesc[idx++] = (u32)secretbuf;
- +
- + /* Add space for BKEK and MAC tag */
- + tmpdesc[idx++] = CMD_SEQ_IN_PTR | (secretsz + (32 + 16));
- +
- + tmpdesc[idx++] = (u32)outbuf;
- + tmpdesc[idx] = CMD_OPERATION | OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB |
- + OP_PCL_BLOB_PTXT_SECMEM;
- + if (auth)
- + tmpdesc[idx] |= OP_PCL_BLOB_EKT;
- +
- + idx++;
- + tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK);
- + dsize = idx * sizeof(u32);
- +
- + tdesc = kmalloc(dsize, GFP_KERNEL | GFP_DMA);
- + if (tdesc == NULL)
- + return 0;
- +
- + memcpy(tdesc, tmpdesc, dsize);
- + *desc = tdesc;
- + return dsize;
- +}
- +
- +/*
- + * Construct a secure memory blob decapsulation job descriptor
- + *
- + * - desc pointer to hold new (to be allocated) pointer to the generated
- + * descriptor for later use. Calling thread can kfree the
- + * descriptor after execution.
- + * - keymod Physical pointer to key modifier (contiguous piece).
- + * - keymodsz Size of key modifier in bytes (should normally be 16).
- + * - blobbuf Physical pointer (within an accessible secure memory page)
- + * of the blob to be decapsulated.
- + * - outbuf Physical pointer (within an accessible secure memory page)
- + * of the decapsulated output.
- + * - secretsz Size of input blob, in bytes.
- + * - auth If nonzero, assume AES-CCM for decapsulation, else use ECB
- + *
- + * Note: this uses 32-bit pointers at present
- + */
- +static int blob_decap_desc(u32 **desc, dma_addr_t keymod, u16 keymodsz,
- + dma_addr_t blobbuf, dma_addr_t outbuf,
- + u16 blobsz, bool auth)
- +{
- + u32 *tdesc, tmpdesc[INITIAL_DESCSZ];
- + u16 dsize, idx;
- +
- + memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32));
- + idx = 1;
- +
- + /* Load key modifier */
- + tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY |
- + ((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK) |
- + (keymodsz & LDST_LEN_MASK);
- +
- + tmpdesc[idx++] = (u32)keymod;
- +
- + /* Compensate BKEK + MAC tag */
- + tmpdesc[idx++] = CMD_SEQ_IN_PTR | (blobsz + 32 + 16);
- +
- + tmpdesc[idx++] = (u32)blobbuf;
- + tmpdesc[idx++] = CMD_SEQ_OUT_PTR | blobsz;
- + tmpdesc[idx++] = (u32)outbuf;
- +
- + /* Decapsulate from secure memory partition to black blob */
- + tmpdesc[idx] = CMD_OPERATION | OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB |
- + OP_PCL_BLOB_PTXT_SECMEM | OP_PCL_BLOB_BLACK;
- + if (auth)
- + tmpdesc[idx] |= OP_PCL_BLOB_EKT;
- +
- + idx++;
- + tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK);
- + dsize = idx * sizeof(u32);
- +
- + tdesc = kmalloc(dsize, GFP_KERNEL | GFP_DMA);
- + if (tdesc == NULL)
- + return 0;
- +
- + memcpy(tdesc, tmpdesc, dsize);
- + *desc = tdesc;
- + return dsize;
- +}
- +
- +/*
- + * Pseudo-synchronous ring access functions for carrying out key
- + * encapsulation and decapsulation
- + */
- +
- +struct sm_key_job_result {
- + int error;
- + struct completion completion;
- +};
- +
- +void sm_key_job_done(struct device *dev, u32 *desc, u32 err, void *context)
- +{
- + struct sm_key_job_result *res = context;
- +
- + res->error = err; /* save off the error for postprocessing */
- + complete(&res->completion); /* mark us complete */
- +}
- +
- +static int sm_key_job(struct device *ksdev, u32 *jobdesc)
- +{
- + struct sm_key_job_result testres;
- + struct caam_drv_private_sm *kspriv;
- + int rtn = 0;
- +
- + kspriv = dev_get_drvdata(ksdev);
- +
- + init_completion(&testres.completion);
- +
- + rtn = caam_jr_enqueue(kspriv->smringdev, jobdesc, sm_key_job_done,
- + &testres);
- + if (!rtn) {
- + wait_for_completion_interruptible(&testres.completion);
- + rtn = testres.error;
- + }
- + return rtn;
- +}
- +
- +/*
- + * Following section establishes the default methods for keystore access
- + * They are NOT intended for use external to this module
- + *
- + * In the present version, these are the only means for the higher-level
- + * interface to deal with the mechanics of accessing the phyiscal keystore
- + */
- +
- +
- +int slot_alloc(struct device *dev, u32 unit, u32 size, u32 *slot)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- + struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata;
- + u32 i;
- +#ifdef SM_DEBUG
- + dev_info(dev, "slot_alloc(): requesting slot for %d bytes\n", size);
- +#endif
- +
- + if (size > smpriv->slot_size)
- + return -EKEYREJECTED;
- +
- + for (i = 0; i < ksdata->slot_count; i++) {
- + if (ksdata->slot[i].allocated == 0) {
- + ksdata->slot[i].allocated = 1;
- + (*slot) = i;
- +#ifdef SM_DEBUG
- + dev_info(dev, "slot_alloc(): new slot %d allocated\n",
- + *slot);
- +#endif
- + return 0;
- + }
- + }
- +
- + return -ENOSPC;
- +}
- +EXPORT_SYMBOL(slot_alloc);
- +
- +int slot_dealloc(struct device *dev, u32 unit, u32 slot)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- + struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata;
- + u8 __iomem *slotdata;
- +
- +#ifdef SM_DEBUG
- + dev_info(dev, "slot_dealloc(): releasing slot %d\n", slot);
- +#endif
- + if (slot >= ksdata->slot_count)
- + return -EINVAL;
- + slotdata = ksdata->base_address + slot * smpriv->slot_size;
- +
- + if (ksdata->slot[slot].allocated == 1) {
- + /* Forcibly overwrite the data from the keystore */
- + memset(ksdata->base_address + slot * smpriv->slot_size, 0,
- + smpriv->slot_size);
- +
- + ksdata->slot[slot].allocated = 0;
- +#ifdef SM_DEBUG
- + dev_info(dev, "slot_dealloc(): slot %d released\n", slot);
- +#endif
- + return 0;
- + }
- +
- + return -EINVAL;
- +}
- +EXPORT_SYMBOL(slot_dealloc);
- +
- +void *slot_get_address(struct device *dev, u32 unit, u32 slot)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- + struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata;
- +
- + if (slot >= ksdata->slot_count)
- + return NULL;
- +
- +#ifdef SM_DEBUG
- + dev_info(dev, "slot_get_address(): slot %d is 0x%08x\n", slot,
- + (u32)ksdata->base_address + slot * smpriv->slot_size);
- +#endif
- +
- + return ksdata->base_address + slot * smpriv->slot_size;
- +}
- +
- +u32 slot_get_base(struct device *dev, u32 unit, u32 slot)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- + struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata;
- +
- + /*
- + * There could potentially be more than one secure partition object
- + * associated with this keystore. For now, there is just one.
- + */
- +
- + (void)slot;
- +
- +#ifdef SM_DEBUG
- + dev_info(dev, "slot_get_base(): slot %d = 0x%08x\n",
- + slot, (u32)ksdata->base_address);
- +#endif
- +
- + return (u32)(ksdata->base_address);
- +}
- +
- +u32 slot_get_offset(struct device *dev, u32 unit, u32 slot)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- + struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata;
- +
- + if (slot >= ksdata->slot_count)
- + return -EINVAL;
- +
- +#ifdef SM_DEBUG
- + dev_info(dev, "slot_get_offset(): slot %d = %d\n", slot,
- + slot * smpriv->slot_size);
- +#endif
- +
- + return slot * smpriv->slot_size;
- +}
- +
- +u32 slot_get_slot_size(struct device *dev, u32 unit, u32 slot)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- +
- +
- +#ifdef SM_DEBUG
- + dev_info(dev, "slot_get_slot_size(): slot %d = %d\n", slot,
- + smpriv->slot_size);
- +#endif
- + /* All slots are the same size in the default implementation */
- + return smpriv->slot_size;
- +}
- +
- +
- +
- +int kso_init_data(struct device *dev, u32 unit)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- + int retval = -EINVAL;
- + struct keystore_data *keystore_data = NULL;
- + u32 slot_count;
- + u32 keystore_data_size;
- +
- + /*
- + * Calculate the required size of the keystore data structure, based
- + * on the number of keys that can fit in the partition.
- + */
- + slot_count = smpriv->page_size / smpriv->slot_size;
- +#ifdef SM_DEBUG
- + dev_info(dev, "kso_init_data: %d slots initializing\n", slot_count);
- +#endif
- +
- + keystore_data_size = sizeof(struct keystore_data) +
- + slot_count *
- + sizeof(struct keystore_data_slot_info);
- +
- + keystore_data = kzalloc(keystore_data_size, GFP_KERNEL);
- +
- + if (keystore_data == NULL) {
- + retval = -ENOSPC;
- + goto out;
- + }
- +
- +#ifdef SM_DEBUG
- + dev_info(dev, "kso_init_data: keystore data size = %d\n",
- + keystore_data_size);
- +#endif
- +
- + /*
- + * Place the slot information structure directly after the keystore data
- + * structure.
- + */
- + keystore_data->slot = (struct keystore_data_slot_info *)
- + (keystore_data + 1);
- + keystore_data->slot_count = slot_count;
- +
- + smpriv->pagedesc[unit].ksdata = keystore_data;
- + smpriv->pagedesc[unit].ksdata->base_address =
- + smpriv->pagedesc[unit].pg_base;
- +
- + retval = 0;
- +
- +out:
- + if (retval != 0)
- + if (keystore_data != NULL)
- + kfree(keystore_data);
- +
- +
- + return retval;
- +}
- +
- +void kso_cleanup_data(struct device *dev, u32 unit)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- + struct keystore_data *keystore_data = NULL;
- +
- + if (smpriv->pagedesc[unit].ksdata != NULL)
- + keystore_data = smpriv->pagedesc[unit].ksdata;
- +
- + /* Release the allocated keystore management data */
- + kfree(smpriv->pagedesc[unit].ksdata);
- +
- + return;
- +}
- +
- +
- +
- +/*
- + * Keystore management section
- + */
- +
- +void sm_init_keystore(struct device *dev)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- +
- + smpriv->data_init = kso_init_data;
- + smpriv->data_cleanup = kso_cleanup_data;
- + smpriv->slot_alloc = slot_alloc;
- + smpriv->slot_dealloc = slot_dealloc;
- + smpriv->slot_get_address = slot_get_address;
- + smpriv->slot_get_base = slot_get_base;
- + smpriv->slot_get_offset = slot_get_offset;
- + smpriv->slot_get_slot_size = slot_get_slot_size;
- +#ifdef SM_DEBUG
- + dev_info(dev, "sm_init_keystore(): handlers installed\n");
- +#endif
- +}
- +EXPORT_SYMBOL(sm_init_keystore);
- +
- +/* Return available pages/units */
- +u32 sm_detect_keystore_units(struct device *dev)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- +
- + return smpriv->localpages;
- +}
- +EXPORT_SYMBOL(sm_detect_keystore_units);
- +
- +/*
- + * Do any keystore specific initializations
- + */
- +int sm_establish_keystore(struct device *dev, u32 unit)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- +
- +#ifdef SM_DEBUG
- + dev_info(dev, "sm_establish_keystore(): unit %d initializing\n", unit);
- +#endif
- +
- + if (smpriv->data_init == NULL)
- + return -EINVAL;
- +
- + /* Call the data_init function for any user setup */
- + return smpriv->data_init(dev, unit);
- +}
- +EXPORT_SYMBOL(sm_establish_keystore);
- +
- +void sm_release_keystore(struct device *dev, u32 unit)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- +
- +#ifdef SM_DEBUG
- + dev_info(dev, "sm_establish_keystore(): unit %d releasing\n", unit);
- +#endif
- + if ((smpriv != NULL) && (smpriv->data_cleanup != NULL))
- + smpriv->data_cleanup(dev, unit);
- +
- + return;
- +}
- +EXPORT_SYMBOL(sm_release_keystore);
- +
- +/*
- + * Subsequent interfacce (sm_keystore_*) forms the accessor interfacce to
- + * the keystore
- + */
- +int sm_keystore_slot_alloc(struct device *dev, u32 unit, u32 size, u32 *slot)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- + int retval = -EINVAL;
- +
- + spin_lock(&smpriv->kslock);
- +
- + if ((smpriv->slot_alloc == NULL) ||
- + (smpriv->pagedesc[unit].ksdata == NULL))
- + goto out;
- +
- + retval = smpriv->slot_alloc(dev, unit, size, slot);
- +
- +out:
- + spin_unlock(&smpriv->kslock);
- + return retval;
- +}
- +EXPORT_SYMBOL(sm_keystore_slot_alloc);
- +
- +int sm_keystore_slot_dealloc(struct device *dev, u32 unit, u32 slot)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- + int retval = -EINVAL;
- +
- + spin_lock(&smpriv->kslock);
- +
- + if ((smpriv->slot_alloc == NULL) ||
- + (smpriv->pagedesc[unit].ksdata == NULL))
- + goto out;
- +
- + retval = smpriv->slot_dealloc(dev, unit, slot);
- +out:
- + spin_unlock(&smpriv->kslock);
- + return retval;
- +}
- +EXPORT_SYMBOL(sm_keystore_slot_dealloc);
- +
- +int sm_keystore_slot_load(struct device *dev, u32 unit, u32 slot,
- + const u8 *key_data, u32 key_length)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- + int retval = -EINVAL;
- + u32 slot_size;
- + u32 i;
- + u8 __iomem *slot_location;
- +
- + spin_lock(&smpriv->kslock);
- +
- + slot_size = smpriv->slot_get_slot_size(dev, unit, slot);
- +
- + if (key_length > slot_size) {
- + retval = -EFBIG;
- + goto out;
- + }
- +
- + slot_location = smpriv->slot_get_address(dev, unit, slot);
- +
- + for (i = 0; i < key_length; i++)
- + slot_location[i] = key_data[i];
- +
- + retval = 0;
- +
- +out:
- + spin_unlock(&smpriv->kslock);
- + return retval;
- +}
- +EXPORT_SYMBOL(sm_keystore_slot_load);
- +
- +int sm_keystore_slot_read(struct device *dev, u32 unit, u32 slot,
- + u32 key_length, u8 *key_data)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- + int retval = -EINVAL;
- + u8 __iomem *slot_addr;
- + u32 slot_size;
- +
- + spin_lock(&smpriv->kslock);
- +
- + slot_addr = smpriv->slot_get_address(dev, unit, slot);
- + slot_size = smpriv->slot_get_slot_size(dev, unit, slot);
- +
- + if (key_length > slot_size) {
- + retval = -EKEYREJECTED;
- + goto out;
- + }
- +
- + memcpy(key_data, slot_addr, key_length);
- + retval = 0;
- +
- +out:
- + spin_unlock(&smpriv->kslock);
- + return retval;
- +}
- +EXPORT_SYMBOL(sm_keystore_slot_read);
- +
- +int sm_keystore_slot_encapsulate(struct device *dev, u32 unit, u32 inslot,
- + u32 outslot, u16 secretlen, u8 *keymod,
- + u16 keymodlen)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- + int retval = 0;
- + u32 slot_length, dsize, jstat;
- + u32 __iomem *encapdesc = NULL;
- + u8 __iomem *lkeymod, *inpslotaddr, *outslotaddr;
- + dma_addr_t keymod_dma;
- +
- + /* Ensure that the full blob will fit in the key slot */
- + slot_length = smpriv->slot_get_slot_size(dev, unit, outslot);
- + if ((secretlen + 48) > slot_length)
- + goto out;
- +
- + /* Get the base addresses of both keystore slots */
- + inpslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, inslot);
- + outslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, outslot);
- +
- + /* Build the key modifier */
- + lkeymod = kmalloc(keymodlen, GFP_KERNEL | GFP_DMA);
- + memcpy(lkeymod, keymod, keymodlen);
- + keymod_dma = dma_map_single(dev, lkeymod, keymodlen, DMA_TO_DEVICE);
- + dma_sync_single_for_device(dev, keymod_dma, keymodlen, DMA_TO_DEVICE);
- +
- + /* Build the encapsulation job descriptor */
- + dsize = blob_encap_desc(&encapdesc, keymod_dma, keymodlen,
- + __pa(inpslotaddr), __pa(outslotaddr),
- + secretlen, 0);
- + if (!dsize) {
- + dev_err(dev, "can't alloc an encap descriptor\n");
- + retval = -ENOMEM;
- + goto out;
- + }
- + jstat = sm_key_job(dev, encapdesc);
- +
- + dma_unmap_single(dev, keymod_dma, keymodlen, DMA_TO_DEVICE);
- + kfree(encapdesc);
- +
- +out:
- + return retval;
- +
- +}
- +EXPORT_SYMBOL(sm_keystore_slot_encapsulate);
- +
- +int sm_keystore_slot_decapsulate(struct device *dev, u32 unit, u32 inslot,
- + u32 outslot, u16 secretlen, u8 *keymod,
- + u16 keymodlen)
- +{
- + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
- + int retval = 0;
- + u32 slot_length, dsize, jstat;
- + u32 __iomem *decapdesc = NULL;
- + u8 __iomem *lkeymod, *inpslotaddr, *outslotaddr;
- + dma_addr_t keymod_dma;
- +
- + /* Ensure that the decap data will fit in the key slot */
- + slot_length = smpriv->slot_get_slot_size(dev, unit, outslot);
- + if (secretlen > slot_length)
- + goto out;
- +
- + /* Get the base addresses of both keystore slots */
- + inpslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, inslot);
- + outslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, outslot);
- +
- + /* Build the key modifier */
- + lkeymod = kmalloc(keymodlen, GFP_KERNEL | GFP_DMA);
- + memcpy(lkeymod, keymod, keymodlen);
- + keymod_dma = dma_map_single(dev, lkeymod, keymodlen, DMA_TO_DEVICE);
- + dma_sync_single_for_device(dev, keymod_dma, keymodlen, DMA_TO_DEVICE);
- +
- + /* Build the decapsulation job descriptor */
- + dsize = blob_decap_desc(&decapdesc, keymod_dma, keymodlen,
- + __pa(inpslotaddr), __pa(outslotaddr),
- + secretlen, 0);
- + if (!dsize) {
- + dev_err(dev, "can't alloc a decap descriptor\n");
- + retval = -ENOMEM;
- + goto out;
- + }
- + jstat = sm_key_job(dev, decapdesc);
- +
- + dma_unmap_single(dev, keymod_dma, keymodlen, DMA_TO_DEVICE);
- + kfree(decapdesc);
- +
- +out:
- + return retval;
- +
- +}
- +EXPORT_SYMBOL(sm_keystore_slot_decapsulate);
- +
- +
- +/*
- + * Initialization/shutdown subsystem
- + * Assumes statically-invoked startup/shutdown from the controller driver
- + * for the present time, to be reworked when a device tree becomes
- + * available. This code will not modularize in present form.
- + *
- + * Also, simply uses ring 0 for execution at the present
- + */
- +
- +int caam_sm_startup(struct platform_device *pdev)
- +{
- + struct device *ctrldev, *smdev;
- + struct caam_drv_private *ctrlpriv;
- + struct caam_drv_private_sm *smpriv;
- + struct caam_drv_private_jr *jrpriv; /* need this for reg page */
- + struct platform_device *sm_pdev;
- + struct sm_page_descriptor *lpagedesc;
- + u32 page, pgstat, lpagect, detectedpage;
- +
- + struct device_node *np;
- + ctrldev = &pdev->dev;
- + ctrlpriv = dev_get_drvdata(ctrldev);
- +
- + /*
- + * Set up the private block for secure memory
- + * Only one instance is possible
- + */
- + smpriv = kzalloc(sizeof(struct caam_drv_private_sm), GFP_KERNEL);
- + if (smpriv == NULL) {
- + dev_err(ctrldev, "can't alloc private mem for secure memory\n");
- + return -ENOMEM;
- + }
- + smpriv->parentdev = ctrldev; /* copy of parent dev is handy */
- +
- + /* Create the dev */
- +#ifdef CONFIG_OF
- + np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-caam-sm");
- + sm_pdev = of_platform_device_create(np, "caam_sm", ctrldev);
- +#else
- + sm_pdev = platform_device_register_data(ctrldev, "caam_sm", 0,
- + smpriv,
- + sizeof(struct caam_drv_private_sm));
- +#endif
- + if (sm_pdev == NULL) {
- + kfree(smpriv);
- + return -EINVAL;
- + }
- + smdev = &sm_pdev->dev;
- + dev_set_drvdata(smdev, smpriv);
- + ctrlpriv->smdev = smdev;
- +
- + /*
- + * Collect configuration limit data for reference
- + * This batch comes from the partition data/vid registers in perfmon
- + */
- + smpriv->max_pages = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart)
- + & SMPART_MAX_NUMPG_MASK) >>
- + SMPART_MAX_NUMPG_SHIFT) + 1;
- + smpriv->top_partition = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart)
- + & SMPART_MAX_PNUM_MASK) >>
- + SMPART_MAX_PNUM_SHIFT) + 1;
- + smpriv->top_page = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart)
- + & SMPART_MAX_PG_MASK) >> SMPART_MAX_PG_SHIFT) + 1;
- + smpriv->page_size = 1024 << ((rd_reg32(&ctrlpriv->ctrl->perfmon.smvid)
- + & SMVID_PG_SIZE_MASK) >> SMVID_PG_SIZE_SHIFT);
- + smpriv->slot_size = 1 << CONFIG_CRYPTO_DEV_FSL_CAAM_SM_SLOTSIZE;
- +
- +#ifdef SM_DEBUG
- + dev_info(smdev, "max pages = %d, top partition = %d\n",
- + smpriv->max_pages, smpriv->top_partition);
- + dev_info(smdev, "top page = %d, page size = %d (total = %d)\n",
- + smpriv->top_page, smpriv->page_size,
- + smpriv->top_page * smpriv->page_size);
- + dev_info(smdev, "selected slot size = %d\n", smpriv->slot_size);
- +#endif
- +
- + /*
- + * Now probe for partitions/pages to which we have access. Note that
- + * these have likely been set up by a bootloader or platform
- + * provisioning application, so we have to assume that we "inherit"
- + * a configuration and work within the constraints of what it might be.
- + *
- + * Assume use of the zeroth ring in the present iteration (until
- + * we can divorce the controller and ring drivers, and then assign
- + * an SM instance to any ring instance).
- + */
- + smpriv->smringdev = ctrlpriv->jrdev[0];
- + jrpriv = dev_get_drvdata(smpriv->smringdev);
- + lpagect = 0;
- + lpagedesc = kzalloc(sizeof(struct sm_page_descriptor)
- + * smpriv->max_pages, GFP_KERNEL);
- + if (lpagedesc == NULL) {
- + kfree(smpriv);
- + return -ENOMEM;
- + }
- +
- + for (page = 0; page < smpriv->max_pages; page++) {
- + wr_reg32(&jrpriv->rregs->sm_cmd,
- + ((page << SMC_PAGE_SHIFT) & SMC_PAGE_MASK) |
- + (SMC_CMD_PAGE_INQUIRY & SMC_CMD_MASK));
- + pgstat = rd_reg32(&jrpriv->rregs->sm_status);
- + if (((pgstat & SMCS_PGWON_MASK) >> SMCS_PGOWN_SHIFT)
- + == SMCS_PGOWN_OWNED) { /* our page? */
- + lpagedesc[page].phys_pagenum =
- + (pgstat & SMCS_PAGE_MASK) >> SMCS_PAGE_SHIFT;
- + lpagedesc[page].own_part =
- + (pgstat & SMCS_PART_SHIFT) >> SMCS_PART_MASK;
- + lpagedesc[page].pg_base = ctrlpriv->sm_base +
- + ((smpriv->page_size * page) / sizeof(u32));
- + lpagect++;
- +#ifdef SM_DEBUG
- + dev_info(smdev,
- + "physical page %d, owning partition = %d\n",
- + lpagedesc[page].phys_pagenum,
- + lpagedesc[page].own_part);
- +#endif
- + }
- + }
- +
- + smpriv->pagedesc = kzalloc(sizeof(struct sm_page_descriptor) * lpagect,
- + GFP_KERNEL);
- + if (smpriv->pagedesc == NULL) {
- + kfree(lpagedesc);
- + kfree(smpriv);
- + return -ENOMEM;
- + }
- + smpriv->localpages = lpagect;
- +
- + detectedpage = 0;
- + for (page = 0; page < smpriv->max_pages; page++) {
- + if (lpagedesc[page].pg_base != NULL) { /* e.g. live entry */
- + memcpy(&smpriv->pagedesc[detectedpage],
- + &lpagedesc[page],
- + sizeof(struct sm_page_descriptor));
- +#ifdef SM_DEBUG_CONT
- + sm_show_page(smdev, &smpriv->pagedesc[detectedpage]);
- +#endif
- + detectedpage++;
- + }
- + }
- +
- + kfree(lpagedesc);
- +
- + sm_init_keystore(smdev);
- +
- + return 0;
- +}
- +
- +void caam_sm_shutdown(struct platform_device *pdev)
- +{
- + struct device *ctrldev, *smdev;
- + struct caam_drv_private *priv;
- + struct caam_drv_private_sm *smpriv;
- +
- + ctrldev = &pdev->dev;
- + priv = dev_get_drvdata(ctrldev);
- + smdev = priv->smdev;
- + smpriv = dev_get_drvdata(smdev);
- +
- + kfree(smpriv->pagedesc);
- + kfree(smpriv);
- +}
- +EXPORT_SYMBOL(caam_sm_shutdown);
- +#ifdef CONFIG_OF
- +static void __exit caam_sm_exit(void)
- +{
- + struct device_node *dev_node;
- + struct platform_device *pdev;
- +
- + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
- + if (!dev_node) {
- + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
- + if (!dev_node)
- + return;
- + }
- +
- + pdev = of_find_device_by_node(dev_node);
- + if (!pdev)
- + return;
- +
- + of_node_put(dev_node);
- +
- + caam_sm_shutdown(pdev);
- +
- + return;
- +}
- +
- +static int __init caam_sm_init(void)
- +{
- + struct device_node *dev_node;
- + struct platform_device *pdev;
- +
- + /*
- + * Do of_find_compatible_node() then of_find_device_by_node()
- + * once a functional device tree is available
- + */
- + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
- + if (!dev_node) {
- + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
- + if (!dev_node)
- + return -ENODEV;
- + }
- +
- + pdev = of_find_device_by_node(dev_node);
- + if (!pdev)
- + return -ENODEV;
- +
- + of_node_get(dev_node);
- +
- + caam_sm_startup(pdev);
- +
- + return 0;
- +}
- +
- +module_init(caam_sm_init);
- +module_exit(caam_sm_exit);
- +
- +MODULE_LICENSE("Dual BSD/GPL");
- +MODULE_DESCRIPTION("FSL CAAM Secure Memory / Keystore");
- +MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD");
- +#endif
- diff -Nur linux-3.14.35.orig/drivers/crypto/caam/sm_test.c linux-3.14.35/drivers/crypto/caam/sm_test.c
- --- linux-3.14.35.orig/drivers/crypto/caam/sm_test.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/crypto/caam/sm_test.c 2015-03-08 14:27:37.545684501 -0500
- @@ -0,0 +1,844 @@
- +/*
- + * Secure Memory / Keystore Exemplification Module
- + * Copyright (C) 2013 Freescale Semiconductor, Inc. All Rights Reserved
- + *
- + * Serves as a functional example, and as a self-contained unit test for
- + * the functionality contained in sm_store.c.
- + *
- + * The example function, caam_sm_example_init(), runs a thread that:
- + *
- + * - initializes a set of fixed keys
- + * - stores one copy in clear buffers
- + * - stores them again in secure memory
- + * - extracts stored keys back out for use
- + * - intializes 3 data buffers for a test:
- + * (1) containing cleartext
- + * (2) to hold ciphertext encrypted with an extracted black key
- + * (3) to hold extracted cleartext decrypted with an equivalent clear key
- + *
- + * The function then builds simple job descriptors that reference the key
- + * material and buffers as initialized, and executes an encryption job
- + * with a black key, and a decryption job using a the same key held in the
- + * clear. The output of the decryption job is compared to the original
- + * cleartext; if they don't compare correctly, one can assume a key problem
- + * exists, where the function will exit with an error.
- + *
- + * This module can use a substantial amount of refactoring, which may occur
- + * after the API gets some mileage. Furthermore, expect this module to
- + * eventually disappear once the API is integrated into "real" software.
- + */
- +
- +#include "compat.h"
- +#include "intern.h"
- +#include "desc.h"
- +#include "error.h"
- +#include "jr.h"
- +#include "sm.h"
- +
- +static u8 skeymod[] = {
- + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
- + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
- +};
- +static u8 symkey[] = {
- + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
- +};
- +
- +static u8 symdata[] = {
- + 0x00, 0x01, 0x02, 0x03, 0x04, 0x0f, 0x06, 0x07,
- + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
- + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
- + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
- + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
- + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
- + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
- + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
- + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
- + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
- + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
- + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
- + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
- + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
- + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
- + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
- + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
- + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
- + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
- + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
- + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
- + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
- + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
- + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
- + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
- + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
- + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
- + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
- + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
- +};
- +
- +static int mk_job_desc(u32 *desc, dma_addr_t key, u16 keysz, dma_addr_t indata,
- + dma_addr_t outdata, u16 sz, u32 cipherdir, u32 keymode)
- +{
- + desc[1] = CMD_KEY | CLASS_1 | (keysz & KEY_LENGTH_MASK) | keymode;
- + desc[2] = (u32)key;
- + desc[3] = CMD_OPERATION | OP_TYPE_CLASS1_ALG | OP_ALG_AAI_ECB |
- + cipherdir;
- + desc[4] = CMD_FIFO_LOAD | FIFOLD_CLASS_CLASS1 |
- + FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1 | sz;
- + desc[5] = (u32)indata;
- + desc[6] = CMD_FIFO_STORE | FIFOST_TYPE_MESSAGE_DATA | sz;
- + desc[7] = (u32)outdata;
- +
- + desc[0] = CMD_DESC_HDR | HDR_ONE | (8 & HDR_DESCLEN_MASK);
- + return 8 * sizeof(u32);
- +}
- +
- +struct exec_test_result {
- + int error;
- + struct completion completion;
- +};
- +
- +void exec_test_done(struct device *dev, u32 *desc, u32 err, void *context)
- +{
- + struct exec_test_result *res = context;
- +
- + if (err) {
- + char tmp[CAAM_ERROR_STR_MAX];
- + dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
- + }
- +
- + res->error = err;
- + complete(&res->completion);
- +}
- +
- +static int exec_test_job(struct device *ksdev, u32 *jobdesc)
- +{
- + struct exec_test_result testres;
- + struct caam_drv_private_sm *kspriv;
- + int rtn = 0;
- +
- + kspriv = dev_get_drvdata(ksdev);
- +
- + init_completion(&testres.completion);
- +
- + rtn = caam_jr_enqueue(kspriv->smringdev, jobdesc, exec_test_done,
- + &testres);
- + if (!rtn) {
- + wait_for_completion_interruptible(&testres.completion);
- + rtn = testres.error;
- + }
- + return rtn;
- +}
- +
- +
- +int caam_sm_example_init(struct platform_device *pdev)
- +{
- + struct device *ctrldev, *ksdev;
- + struct caam_drv_private *ctrlpriv;
- + struct caam_drv_private_sm *kspriv;
- + u32 unit, units, jdescsz;
- + int stat, jstat, rtnval = 0;
- + u8 __iomem *syminp, *symint, *symout = NULL;
- + dma_addr_t syminp_dma, symint_dma, symout_dma;
- + u8 __iomem *black_key_des, *black_key_aes128;
- + u8 __iomem *black_key_aes256;
- + dma_addr_t black_key_des_dma, black_key_aes128_dma;
- + dma_addr_t black_key_aes256_dma;
- + u8 __iomem *clear_key_des, *clear_key_aes128, *clear_key_aes256;
- + dma_addr_t clear_key_des_dma, clear_key_aes128_dma;
- + dma_addr_t clear_key_aes256_dma;
- + u32 __iomem *jdesc;
- + u32 keyslot_des, keyslot_aes128, keyslot_aes256 = 0;
- +
- + jdesc = NULL;
- + black_key_des = black_key_aes128 = black_key_aes256 = NULL;
- + clear_key_des = clear_key_aes128 = clear_key_aes256 = NULL;
- +
- + /* We can lose this cruft once we can get a pdev by name */
- + ctrldev = &pdev->dev;
- + ctrlpriv = dev_get_drvdata(ctrldev);
- + ksdev = ctrlpriv->smdev;
- + kspriv = dev_get_drvdata(ksdev);
- + if (kspriv == NULL)
- + return -ENODEV;
- +
- + /* Now that we have the dev for the single SM instance, connect */
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "caam_sm_test_init() running\n");
- +#endif
- + /* Probe to see what keystores are available to us */
- + units = sm_detect_keystore_units(ksdev);
- + if (!units)
- + dev_err(ksdev, "caam_sm_test: no keystore units available\n");
- +
- + /*
- + * MX6 bootloader stores some stuff in unit 0, so let's
- + * use 1 or above
- + */
- + if (units < 2) {
- + dev_err(ksdev, "caam_sm_test: insufficient keystore units\n");
- + return -ENODEV;
- + }
- + unit = 1;
- +
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "caam_sm_test: %d keystore units available\n", units);
- +#endif
- +
- + /* Initialize/Establish Keystore */
- + sm_establish_keystore(ksdev, unit); /* Initalize store in #1 */
- +
- + /*
- + * Top of main test thread
- + */
- +
- + /* Allocate test data blocks (input, intermediate, output) */
- + syminp = kmalloc(256, GFP_KERNEL | GFP_DMA);
- + symint = kmalloc(256, GFP_KERNEL | GFP_DMA);
- + symout = kmalloc(256, GFP_KERNEL | GFP_DMA);
- + if ((syminp == NULL) || (symint == NULL) || (symout == NULL)) {
- + rtnval = -ENOMEM;
- + dev_err(ksdev, "caam_sm_test: can't get test data buffers\n");
- + goto freemem;
- + }
- +
- + /* Allocate storage for 3 black keys: encapsulated 8, 16, 32 */
- + black_key_des = kmalloc(16, GFP_KERNEL | GFP_DMA); /* padded to 16... */
- + black_key_aes128 = kmalloc(16, GFP_KERNEL | GFP_DMA);
- + black_key_aes256 = kmalloc(16, GFP_KERNEL | GFP_DMA);
- + if ((black_key_des == NULL) || (black_key_aes128 == NULL) ||
- + (black_key_aes256 == NULL)) {
- + rtnval = -ENOMEM;
- + dev_err(ksdev, "caam_sm_test: can't black key buffers\n");
- + goto freemem;
- + }
- +
- + clear_key_des = kmalloc(8, GFP_KERNEL | GFP_DMA);
- + clear_key_aes128 = kmalloc(16, GFP_KERNEL | GFP_DMA);
- + clear_key_aes256 = kmalloc(32, GFP_KERNEL | GFP_DMA);
- + if ((clear_key_des == NULL) || (clear_key_aes128 == NULL) ||
- + (clear_key_aes256 == NULL)) {
- + rtnval = -ENOMEM;
- + dev_err(ksdev, "caam_sm_test: can't get clear key buffers\n");
- + goto freemem;
- + }
- +
- + /* Allocate storage for job descriptor */
- + jdesc = kmalloc(8 * sizeof(u32), GFP_KERNEL | GFP_DMA);
- + if (jdesc == NULL) {
- + rtnval = -ENOMEM;
- + dev_err(ksdev, "caam_sm_test: can't get descriptor buffers\n");
- + goto freemem;
- + }
- +
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "caam_sm_test: all buffers allocated\n");
- +#endif
- +
- + /* Load up input data block, clear outputs */
- + memcpy(syminp, symdata, 256);
- + memset(symint, 0, 256);
- + memset(symout, 0, 256);
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + syminp[0], syminp[1], syminp[2], syminp[3],
- + syminp[4], syminp[5], syminp[6], syminp[7]);
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symint[0], symint[1], symint[2], symint[3],
- + symint[4], symint[5], symint[6], symint[7]);
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symout[0], symout[1], symout[2], symout[3],
- + symout[4], symout[5], symout[6], symout[7]);
- +
- + dev_info(ksdev, "caam_sm_test: data buffers initialized\n");
- +#endif
- +
- + /* Load up clear keys */
- + memcpy(clear_key_des, symkey, 8);
- + memcpy(clear_key_aes128, symkey, 16);
- + memcpy(clear_key_aes256, symkey, 32);
- +
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "caam_sm_test: all clear keys loaded\n");
- +#endif
- +
- + /*
- + * Place clear keys in keystore.
- + * All the interesting stuff happens here.
- + */
- + /* 8 bit DES key */
- + stat = sm_keystore_slot_alloc(ksdev, unit, 8, &keyslot_des);
- + if (stat)
- + goto freemem;
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "caam_sm_test: 8 byte key slot in %d\n", keyslot_des);
- +#endif
- + stat = sm_keystore_slot_load(ksdev, unit, keyslot_des, clear_key_des,
- + 8);
- + if (stat) {
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "caam_sm_test: can't load 8 byte key in %d\n",
- + keyslot_des);
- +#endif
- + sm_keystore_slot_dealloc(ksdev, unit, keyslot_des);
- + goto freemem;
- + }
- +
- + /* 16 bit AES key */
- + stat = sm_keystore_slot_alloc(ksdev, unit, 16, &keyslot_aes128);
- + if (stat) {
- + sm_keystore_slot_dealloc(ksdev, unit, keyslot_des);
- + goto freemem;
- + }
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "caam_sm_test: 16 byte key slot in %d\n",
- + keyslot_aes128);
- +#endif
- + stat = sm_keystore_slot_load(ksdev, unit, keyslot_aes128,
- + clear_key_aes128, 16);
- + if (stat) {
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "caam_sm_test: can't load 16 byte key in %d\n",
- + keyslot_aes128);
- +#endif
- + sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128);
- + sm_keystore_slot_dealloc(ksdev, unit, keyslot_des);
- + goto freemem;
- + }
- +
- + /* 32 bit AES key */
- + stat = sm_keystore_slot_alloc(ksdev, unit, 32, &keyslot_aes256);
- + if (stat) {
- + sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128);
- + sm_keystore_slot_dealloc(ksdev, unit, keyslot_des);
- + goto freemem;
- + }
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "caam_sm_test: 32 byte key slot in %d\n",
- + keyslot_aes256);
- +#endif
- + stat = sm_keystore_slot_load(ksdev, unit, keyslot_aes256,
- + clear_key_aes256, 32);
- + if (stat) {
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "caam_sm_test: can't load 32 byte key in %d\n",
- + keyslot_aes128);
- +#endif
- + sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes256);
- + sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128);
- + sm_keystore_slot_dealloc(ksdev, unit, keyslot_des);
- + goto freemem;
- + }
- +
- + /* Encapsulate all keys as SM blobs */
- + stat = sm_keystore_slot_encapsulate(ksdev, unit, keyslot_des,
- + keyslot_des, 8, skeymod, 8);
- + if (stat) {
- + dev_info(ksdev, "caam_sm_test: can't encapsulate DES key\n");
- + goto freekeys;
- + }
- +
- + stat = sm_keystore_slot_encapsulate(ksdev, unit, keyslot_aes128,
- + keyslot_aes128, 16, skeymod, 8);
- + if (stat) {
- + dev_info(ksdev, "caam_sm_test: can't encapsulate AES128 key\n");
- + goto freekeys;
- + }
- +
- + stat = sm_keystore_slot_encapsulate(ksdev, unit, keyslot_aes256,
- + keyslot_aes256, 32, skeymod, 8);
- + if (stat) {
- + dev_info(ksdev, "caam_sm_test: can't encapsulate AES256 key\n");
- + goto freekeys;
- + }
- +
- + /* Now decapsulate as black key blobs */
- + stat = sm_keystore_slot_decapsulate(ksdev, unit, keyslot_des,
- + keyslot_des, 8, skeymod, 8);
- + if (stat) {
- + dev_info(ksdev, "caam_sm_test: can't decapsulate DES key\n");
- + goto freekeys;
- + }
- +
- + stat = sm_keystore_slot_decapsulate(ksdev, unit, keyslot_aes128,
- + keyslot_aes128, 16, skeymod, 8);
- + if (stat) {
- + dev_info(ksdev, "caam_sm_test: can't decapsulate AES128 key\n");
- + goto freekeys;
- + }
- +
- + stat = sm_keystore_slot_decapsulate(ksdev, unit, keyslot_aes256,
- + keyslot_aes256, 32, skeymod, 8);
- + if (stat) {
- + dev_info(ksdev, "caam_sm_test: can't decapsulate AES128 key\n");
- + goto freekeys;
- + }
- +
- + /* Extract 8/16/32 byte black keys */
- + sm_keystore_slot_read(ksdev, unit, keyslot_des, 8, black_key_des);
- + sm_keystore_slot_read(ksdev, unit, keyslot_aes128, 16,
- + black_key_aes128);
- + sm_keystore_slot_read(ksdev, unit, keyslot_aes256, 32,
- + black_key_aes256);
- +
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "caam_sm_test: all black keys extracted\n");
- +#endif
- +
- + /* DES encrypt using 8 byte black key */
- + black_key_des_dma = dma_map_single(ksdev, black_key_des, 8,
- + DMA_TO_DEVICE);
- + dma_sync_single_for_device(ksdev, black_key_des_dma, 8, DMA_TO_DEVICE);
- + syminp_dma = dma_map_single(ksdev, syminp, 256, DMA_TO_DEVICE);
- + dma_sync_single_for_device(ksdev, syminp_dma, 256, DMA_TO_DEVICE);
- + symint_dma = dma_map_single(ksdev, symint, 256, DMA_FROM_DEVICE);
- +
- + jdescsz = mk_job_desc(jdesc, black_key_des_dma, 8, syminp_dma,
- + symint_dma, 256,
- + OP_ALG_ENCRYPT | OP_ALG_ALGSEL_DES, 0);
- +
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "jobdesc:\n");
- + dev_info(ksdev, "0x%08x\n", jdesc[0]);
- + dev_info(ksdev, "0x%08x\n", jdesc[1]);
- + dev_info(ksdev, "0x%08x\n", jdesc[2]);
- + dev_info(ksdev, "0x%08x\n", jdesc[3]);
- + dev_info(ksdev, "0x%08x\n", jdesc[4]);
- + dev_info(ksdev, "0x%08x\n", jdesc[5]);
- + dev_info(ksdev, "0x%08x\n", jdesc[6]);
- + dev_info(ksdev, "0x%08x\n", jdesc[7]);
- +#endif
- +
- + jstat = exec_test_job(ksdev, jdesc);
- +
- + dma_sync_single_for_cpu(ksdev, symint_dma, 256, DMA_FROM_DEVICE);
- + dma_unmap_single(ksdev, symint_dma, 256, DMA_FROM_DEVICE);
- + dma_unmap_single(ksdev, syminp_dma, 256, DMA_TO_DEVICE);
- + dma_unmap_single(ksdev, black_key_des_dma, 8, DMA_TO_DEVICE);
- +
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "input block:\n");
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + syminp[0], syminp[1], syminp[2], syminp[3],
- + syminp[4], syminp[5], syminp[6], syminp[7]);
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + syminp[8], syminp[9], syminp[10], syminp[11],
- + syminp[12], syminp[13], syminp[14], syminp[15]);
- + dev_info(ksdev, "intermediate block:\n");
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symint[0], symint[1], symint[2], symint[3],
- + symint[4], symint[5], symint[6], symint[7]);
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symint[8], symint[9], symint[10], symint[11],
- + symint[12], symint[13], symint[14], symint[15]);
- + dev_info(ksdev, "caam_sm_test: encrypt cycle with 8 byte key\n");
- +#endif
- +
- + /* DES decrypt using 8 byte clear key */
- + clear_key_des_dma = dma_map_single(ksdev, clear_key_des, 8,
- + DMA_TO_DEVICE);
- + dma_sync_single_for_device(ksdev, clear_key_des_dma, 8, DMA_TO_DEVICE);
- + symint_dma = dma_map_single(ksdev, symint, 256, DMA_TO_DEVICE);
- + dma_sync_single_for_device(ksdev, symint_dma, 256, DMA_TO_DEVICE);
- + symout_dma = dma_map_single(ksdev, symout, 256, DMA_FROM_DEVICE);
- +
- + jdescsz = mk_job_desc(jdesc, clear_key_des_dma, 8, symint_dma,
- + symout_dma, 256,
- + OP_ALG_DECRYPT | OP_ALG_ALGSEL_DES, 0);
- +
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "jobdesc:\n");
- + dev_info(ksdev, "0x%08x\n", jdesc[0]);
- + dev_info(ksdev, "0x%08x\n", jdesc[1]);
- + dev_info(ksdev, "0x%08x\n", jdesc[2]);
- + dev_info(ksdev, "0x%08x\n", jdesc[3]);
- + dev_info(ksdev, "0x%08x\n", jdesc[4]);
- + dev_info(ksdev, "0x%08x\n", jdesc[5]);
- + dev_info(ksdev, "0x%08x\n", jdesc[6]);
- + dev_info(ksdev, "0x%08x\n", jdesc[7]);
- +#endif
- +
- + jstat = exec_test_job(ksdev, jdesc);
- +
- + dma_sync_single_for_cpu(ksdev, symout_dma, 256, DMA_FROM_DEVICE);
- + dma_unmap_single(ksdev, symout_dma, 256, DMA_FROM_DEVICE);
- + dma_unmap_single(ksdev, symint_dma, 256, DMA_TO_DEVICE);
- + dma_unmap_single(ksdev, clear_key_des_dma, 8, DMA_TO_DEVICE);
- +
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "intermediate block:\n");
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symint[0], symint[1], symint[2], symint[3],
- + symint[4], symint[5], symint[6], symint[7]);
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symint[8], symint[9], symint[10], symint[11],
- + symint[12], symint[13], symint[14], symint[15]);
- + dev_info(ksdev, "decrypted block:\n");
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symout[0], symout[1], symout[2], symout[3],
- + symout[4], symout[5], symout[6], symout[7]);
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symout[8], symout[9], symout[10], symout[11],
- + symout[12], symout[13], symout[14], symout[15]);
- + dev_info(ksdev, "caam_sm_test: decrypt cycle with 8 byte key\n");
- +#endif
- +
- + /* Check result */
- + if (memcmp(symout, syminp, 256)) {
- + dev_info(ksdev, "caam_sm_test: 8-byte key test mismatch\n");
- + rtnval = -1;
- + goto freekeys;
- + } else
- + dev_info(ksdev, "caam_sm_test: 8-byte key test match OK\n");
- +
- + /* AES-128 encrypt using 16 byte black key */
- + black_key_aes128_dma = dma_map_single(ksdev, black_key_aes128, 16,
- + DMA_TO_DEVICE);
- + dma_sync_single_for_device(ksdev, black_key_aes128_dma, 16,
- + DMA_TO_DEVICE);
- + syminp_dma = dma_map_single(ksdev, syminp, 256, DMA_TO_DEVICE);
- + dma_sync_single_for_device(ksdev, syminp_dma, 256, DMA_TO_DEVICE);
- + symint_dma = dma_map_single(ksdev, symint, 256, DMA_FROM_DEVICE);
- +
- + jdescsz = mk_job_desc(jdesc, black_key_aes128_dma, 16, syminp_dma,
- + symint_dma, 256,
- + OP_ALG_ENCRYPT | OP_ALG_ALGSEL_AES, 0);
- +
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "jobdesc:\n");
- + dev_info(ksdev, "0x%08x\n", jdesc[0]);
- + dev_info(ksdev, "0x%08x\n", jdesc[1]);
- + dev_info(ksdev, "0x%08x\n", jdesc[2]);
- + dev_info(ksdev, "0x%08x\n", jdesc[3]);
- + dev_info(ksdev, "0x%08x\n", jdesc[4]);
- + dev_info(ksdev, "0x%08x\n", jdesc[5]);
- + dev_info(ksdev, "0x%08x\n", jdesc[6]);
- + dev_info(ksdev, "0x%08x\n", jdesc[7]);
- +#endif
- +
- + jstat = exec_test_job(ksdev, jdesc);
- +
- + dma_sync_single_for_cpu(ksdev, symint_dma, 256, DMA_FROM_DEVICE);
- + dma_unmap_single(ksdev, symint_dma, 256, DMA_FROM_DEVICE);
- + dma_unmap_single(ksdev, syminp_dma, 256, DMA_TO_DEVICE);
- + dma_unmap_single(ksdev, black_key_aes128_dma, 16, DMA_TO_DEVICE);
- +
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "input block:\n");
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + syminp[0], syminp[1], syminp[2], syminp[3],
- + syminp[4], syminp[5], syminp[6], syminp[7]);
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + syminp[8], syminp[9], syminp[10], syminp[11],
- + syminp[12], syminp[13], syminp[14], syminp[15]);
- + dev_info(ksdev, "intermediate block:\n");
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symint[0], symint[1], symint[2], symint[3],
- + symint[4], symint[5], symint[6], symint[7]);
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symint[8], symint[9], symint[10], symint[11],
- + symint[12], symint[13], symint[14], symint[15]);
- + dev_info(ksdev, "caam_sm_test: encrypt cycle with 16 byte key\n");
- +#endif
- +
- + /* AES-128 decrypt using 16 byte clear key */
- + clear_key_aes128_dma = dma_map_single(ksdev, clear_key_aes128, 16,
- + DMA_TO_DEVICE);
- + dma_sync_single_for_device(ksdev, clear_key_aes128_dma, 16,
- + DMA_TO_DEVICE);
- + symint_dma = dma_map_single(ksdev, symint, 256, DMA_TO_DEVICE);
- + dma_sync_single_for_device(ksdev, symint_dma, 256, DMA_TO_DEVICE);
- + symout_dma = dma_map_single(ksdev, symout, 256, DMA_FROM_DEVICE);
- +
- + jdescsz = mk_job_desc(jdesc, clear_key_aes128_dma, 16, symint_dma,
- + symout_dma, 256,
- + OP_ALG_DECRYPT | OP_ALG_ALGSEL_AES, 0);
- +
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "jobdesc:\n");
- + dev_info(ksdev, "0x%08x\n", jdesc[0]);
- + dev_info(ksdev, "0x%08x\n", jdesc[1]);
- + dev_info(ksdev, "0x%08x\n", jdesc[2]);
- + dev_info(ksdev, "0x%08x\n", jdesc[3]);
- + dev_info(ksdev, "0x%08x\n", jdesc[4]);
- + dev_info(ksdev, "0x%08x\n", jdesc[5]);
- + dev_info(ksdev, "0x%08x\n", jdesc[6]);
- + dev_info(ksdev, "0x%08x\n", jdesc[7]);
- +#endif
- + jstat = exec_test_job(ksdev, jdesc);
- +
- + dma_sync_single_for_cpu(ksdev, symout_dma, 256, DMA_FROM_DEVICE);
- + dma_unmap_single(ksdev, symout_dma, 256, DMA_FROM_DEVICE);
- + dma_unmap_single(ksdev, symint_dma, 256, DMA_TO_DEVICE);
- + dma_unmap_single(ksdev, clear_key_aes128_dma, 16, DMA_TO_DEVICE);
- +
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "intermediate block:\n");
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symint[0], symint[1], symint[2], symint[3],
- + symint[4], symint[5], symint[6], symint[7]);
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symint[8], symint[9], symint[10], symint[11],
- + symint[12], symint[13], symint[14], symint[15]);
- + dev_info(ksdev, "decrypted block:\n");
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symout[0], symout[1], symout[2], symout[3],
- + symout[4], symout[5], symout[6], symout[7]);
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symout[8], symout[9], symout[10], symout[11],
- + symout[12], symout[13], symout[14], symout[15]);
- + dev_info(ksdev, "caam_sm_test: decrypt cycle with 16 byte key\n");
- +#endif
- +
- + /* Check result */
- + if (memcmp(symout, syminp, 256)) {
- + dev_info(ksdev, "caam_sm_test: 16-byte key test mismatch\n");
- + rtnval = -1;
- + goto freekeys;
- + } else
- + dev_info(ksdev, "caam_sm_test: 16-byte key test match OK\n");
- +
- + /* AES-256 encrypt using 32 byte black key */
- + black_key_aes256_dma = dma_map_single(ksdev, black_key_aes256, 32,
- + DMA_TO_DEVICE);
- + dma_sync_single_for_device(ksdev, black_key_aes256_dma, 32,
- + DMA_TO_DEVICE);
- + syminp_dma = dma_map_single(ksdev, syminp, 256, DMA_TO_DEVICE);
- + dma_sync_single_for_device(ksdev, syminp_dma, 256, DMA_TO_DEVICE);
- + symint_dma = dma_map_single(ksdev, symint, 256, DMA_FROM_DEVICE);
- +
- + jdescsz = mk_job_desc(jdesc, black_key_aes256_dma, 32, syminp_dma,
- + symint_dma, 256,
- + OP_ALG_ENCRYPT | OP_ALG_ALGSEL_AES, 0);
- +
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "jobdesc:\n");
- + dev_info(ksdev, "0x%08x\n", jdesc[0]);
- + dev_info(ksdev, "0x%08x\n", jdesc[1]);
- + dev_info(ksdev, "0x%08x\n", jdesc[2]);
- + dev_info(ksdev, "0x%08x\n", jdesc[3]);
- + dev_info(ksdev, "0x%08x\n", jdesc[4]);
- + dev_info(ksdev, "0x%08x\n", jdesc[5]);
- + dev_info(ksdev, "0x%08x\n", jdesc[6]);
- + dev_info(ksdev, "0x%08x\n", jdesc[7]);
- +#endif
- +
- + jstat = exec_test_job(ksdev, jdesc);
- +
- + dma_sync_single_for_cpu(ksdev, symint_dma, 256, DMA_FROM_DEVICE);
- + dma_unmap_single(ksdev, symint_dma, 256, DMA_FROM_DEVICE);
- + dma_unmap_single(ksdev, syminp_dma, 256, DMA_TO_DEVICE);
- + dma_unmap_single(ksdev, black_key_aes256_dma, 32, DMA_TO_DEVICE);
- +
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "input block:\n");
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + syminp[0], syminp[1], syminp[2], syminp[3],
- + syminp[4], syminp[5], syminp[6], syminp[7]);
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + syminp[8], syminp[9], syminp[10], syminp[11],
- + syminp[12], syminp[13], syminp[14], syminp[15]);
- + dev_info(ksdev, "intermediate block:\n");
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symint[0], symint[1], symint[2], symint[3],
- + symint[4], symint[5], symint[6], symint[7]);
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symint[8], symint[9], symint[10], symint[11],
- + symint[12], symint[13], symint[14], symint[15]);
- + dev_info(ksdev, "caam_sm_test: encrypt cycle with 32 byte key\n");
- +#endif
- +
- + /* AES-256 decrypt using 32-byte black key */
- + clear_key_aes256_dma = dma_map_single(ksdev, clear_key_aes256, 32,
- + DMA_TO_DEVICE);
- + dma_sync_single_for_device(ksdev, clear_key_aes256_dma, 32,
- + DMA_TO_DEVICE);
- + symint_dma = dma_map_single(ksdev, symint, 256, DMA_TO_DEVICE);
- + dma_sync_single_for_device(ksdev, symint_dma, 256, DMA_TO_DEVICE);
- + symout_dma = dma_map_single(ksdev, symout, 256, DMA_FROM_DEVICE);
- +
- + jdescsz = mk_job_desc(jdesc, clear_key_aes256_dma, 32, symint_dma,
- + symout_dma, 256,
- + OP_ALG_DECRYPT | OP_ALG_ALGSEL_AES, 0);
- +
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "jobdesc:\n");
- + dev_info(ksdev, "0x%08x\n", jdesc[0]);
- + dev_info(ksdev, "0x%08x\n", jdesc[1]);
- + dev_info(ksdev, "0x%08x\n", jdesc[2]);
- + dev_info(ksdev, "0x%08x\n", jdesc[3]);
- + dev_info(ksdev, "0x%08x\n", jdesc[4]);
- + dev_info(ksdev, "0x%08x\n", jdesc[5]);
- + dev_info(ksdev, "0x%08x\n", jdesc[6]);
- + dev_info(ksdev, "0x%08x\n", jdesc[7]);
- +#endif
- +
- + jstat = exec_test_job(ksdev, jdesc);
- +
- + dma_sync_single_for_cpu(ksdev, symout_dma, 256, DMA_FROM_DEVICE);
- + dma_unmap_single(ksdev, symout_dma, 256, DMA_FROM_DEVICE);
- + dma_unmap_single(ksdev, symint_dma, 256, DMA_TO_DEVICE);
- + dma_unmap_single(ksdev, clear_key_aes256_dma, 32, DMA_TO_DEVICE);
- +
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "intermediate block:\n");
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symint[0], symint[1], symint[2], symint[3],
- + symint[4], symint[5], symint[6], symint[7]);
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symint[8], symint[9], symint[10], symint[11],
- + symint[12], symint[13], symint[14], symint[15]);
- + dev_info(ksdev, "decrypted block:\n");
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symout[0], symout[1], symout[2], symout[3],
- + symout[4], symout[5], symout[6], symout[7]);
- + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \
- + "0x%02x 0x%02x 0x%02x 0x%02x\n",
- + symout[8], symout[9], symout[10], symout[11],
- + symout[12], symout[13], symout[14], symout[15]);
- + dev_info(ksdev, "caam_sm_test: decrypt cycle with 32 byte key\n");
- +#endif
- +
- + /* Check result */
- + if (memcmp(symout, syminp, 256)) {
- + dev_info(ksdev, "caam_sm_test: 32-byte key test mismatch\n");
- + rtnval = -1;
- + goto freekeys;
- + } else
- + dev_info(ksdev, "caam_sm_test: 32-byte key test match OK\n");
- +
- +
- + /* Remove 8/16/32 byte keys from keystore */
- +freekeys:
- + stat = sm_keystore_slot_dealloc(ksdev, unit, keyslot_des);
- + if (stat)
- + dev_info(ksdev, "caam_sm_test: can't release slot %d\n",
- + keyslot_des);
- +
- + stat = sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128);
- + if (stat)
- + dev_info(ksdev, "caam_sm_test: can't release slot %d\n",
- + keyslot_aes128);
- +
- + stat = sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes256);
- + if (stat)
- + dev_info(ksdev, "caam_sm_test: can't release slot %d\n",
- + keyslot_aes256);
- +
- +
- + /* Free resources */
- +freemem:
- +#ifdef SM_TEST_DETAIL
- + dev_info(ksdev, "caam_sm_test: cleaning up\n");
- +#endif
- + kfree(syminp);
- + kfree(symint);
- + kfree(symout);
- + kfree(clear_key_des);
- + kfree(clear_key_aes128);
- + kfree(clear_key_aes256);
- + kfree(black_key_des);
- + kfree(black_key_aes128);
- + kfree(black_key_aes256);
- + kfree(jdesc);
- +
- + /* Disconnect from keystore and leave */
- + sm_release_keystore(ksdev, unit);
- +
- + return rtnval;
- +}
- +EXPORT_SYMBOL(caam_sm_example_init);
- +
- +void caam_sm_example_shutdown(void)
- +{
- + /* unused in present version */
- + struct device_node *dev_node;
- + struct platform_device *pdev;
- +
- + /*
- + * Do of_find_compatible_node() then of_find_device_by_node()
- + * once a functional device tree is available
- + */
- + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
- + if (!dev_node) {
- + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
- + if (!dev_node)
- + return;
- + }
- +
- + pdev = of_find_device_by_node(dev_node);
- + if (!pdev)
- + return;
- +
- + of_node_get(dev_node);
- +
- +}
- +
- +static int __init caam_sm_test_init(void)
- +{
- + struct device_node *dev_node;
- + struct platform_device *pdev;
- +
- + /*
- + * Do of_find_compatible_node() then of_find_device_by_node()
- + * once a functional device tree is available
- + */
- + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
- + if (!dev_node) {
- + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
- + if (!dev_node)
- + return -ENODEV;
- + }
- +
- + pdev = of_find_device_by_node(dev_node);
- + if (!pdev)
- + return -ENODEV;
- +
- + of_node_put(dev_node);
- +
- + caam_sm_example_init(pdev);
- +
- + return 0;
- +}
- +
- +
- +/* Module-based initialization needs to wait for dev tree */
- +#ifdef CONFIG_OF
- +module_init(caam_sm_test_init);
- +module_exit(caam_sm_example_shutdown);
- +
- +MODULE_LICENSE("Dual BSD/GPL");
- +MODULE_DESCRIPTION("FSL CAAM Keystore Usage Example");
- +MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD");
- +#endif
- diff -Nur linux-3.14.35.orig/drivers/crypto/caam/snvsregs.h linux-3.14.35/drivers/crypto/caam/snvsregs.h
- --- linux-3.14.35.orig/drivers/crypto/caam/snvsregs.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/crypto/caam/snvsregs.h 2015-03-08 14:27:37.545684501 -0500
- @@ -0,0 +1,237 @@
- +/*
- + * SNVS hardware register-level view
- + *
- + * Copyright (C) 2013 Freescale Semiconductor, Inc., All Rights Reserved
- + */
- +
- +#ifndef SNVSREGS_H
- +#define SNVSREGS_H
- +
- +#include <linux/types.h>
- +#include <linux/io.h>
- +
- +/*
- + * SNVS High Power Domain
- + * Includes security violations, HA counter, RTC, alarm
- + */
- +struct snvs_hp {
- + u32 lock;
- + u32 cmd;
- + u32 ctl;
- + u32 secvio_int_en; /* Security Violation Interrupt Enable */
- + u32 secvio_int_ctl; /* Security Violation Interrupt Control */
- + u32 status;
- + u32 secvio_status; /* Security Violation Status */
- + u32 ha_counteriv; /* High Assurance Counter IV */
- + u32 ha_counter; /* High Assurance Counter */
- + u32 rtc_msb; /* Real Time Clock/Counter MSB */
- + u32 rtc_lsb; /* Real Time Counter LSB */
- + u32 time_alarm_msb; /* Time Alarm MSB */
- + u32 time_alarm_lsb; /* Time Alarm LSB */
- +};
- +
- +#define HP_LOCK_HAC_LCK 0x00040000
- +#define HP_LOCK_HPSICR_LCK 0x00020000
- +#define HP_LOCK_HPSVCR_LCK 0x00010000
- +#define HP_LOCK_MKEYSEL_LCK 0x00000200
- +#define HP_LOCK_TAMPCFG_LCK 0x00000100
- +#define HP_LOCK_TAMPFLT_LCK 0x00000080
- +#define HP_LOCK_SECVIO_LCK 0x00000040
- +#define HP_LOCK_GENP_LCK 0x00000020
- +#define HP_LOCK_MONOCTR_LCK 0x00000010
- +#define HP_LOCK_CALIB_LCK 0x00000008
- +#define HP_LOCK_SRTC_LCK 0x00000004
- +#define HP_LOCK_ZMK_RD_LCK 0x00000002
- +#define HP_LOCK_ZMK_WT_LCK 0x00000001
- +
- +#define HP_CMD_NONPRIV_AXS 0x80000000
- +#define HP_CMD_HAC_STOP 0x00080000
- +#define HP_CMD_HAC_CLEAR 0x00040000
- +#define HP_CMD_HAC_LOAD 0x00020000
- +#define HP_CMD_HAC_CFG_EN 0x00010000
- +#define HP_CMD_SNVS_MSTR_KEY 0x00002000
- +#define HP_CMD_PROG_ZMK 0x00001000
- +#define HP_CMD_SW_LPSV 0x00000400
- +#define HP_CMD_SW_FSV 0x00000200
- +#define HP_CMD_SW_SV 0x00000100
- +#define HP_CMD_LP_SWR_DIS 0x00000020
- +#define HP_CMD_LP_SWR 0x00000010
- +#define HP_CMD_SSM_SFNS_DIS 0x00000004
- +#define HP_CMD_SSM_ST_DIS 0x00000002
- +#define HP_CMD_SMM_ST 0x00000001
- +
- +#define HP_CTL_TIME_SYNC 0x00010000
- +#define HP_CTL_CAL_VAL_SHIFT 10
- +#define HP_CTL_CAL_VAL_MASK (0x1f << HP_CTL_CALIB_SHIFT)
- +#define HP_CTL_CALIB_EN 0x00000100
- +#define HP_CTL_PI_FREQ_SHIFT 4
- +#define HP_CTL_PI_FREQ_MASK (0xf << HP_CTL_PI_FREQ_SHIFT)
- +#define HP_CTL_PI_EN 0x00000008
- +#define HP_CTL_TIMEALARM_EN 0x00000002
- +#define HP_CTL_RTC_EN 0x00000001
- +
- +#define HP_SECVIO_INTEN_EN 0x10000000
- +#define HP_SECVIO_INTEN_SRC5 0x00000020
- +#define HP_SECVIO_INTEN_SRC4 0x00000010
- +#define HP_SECVIO_INTEN_SRC3 0x00000008
- +#define HP_SECVIO_INTEN_SRC2 0x00000004
- +#define HP_SECVIO_INTEN_SRC1 0x00000002
- +#define HP_SECVIO_INTEN_SRC0 0x00000001
- +#define HP_SECVIO_INTEN_ALL 0x8000003f
- +
- +#define HP_SECVIO_ICTL_CFG_SHIFT 30
- +#define HP_SECVIO_ICTL_CFG_MASK (0x3 << HP_SECVIO_ICTL_CFG_SHIFT)
- +#define HP_SECVIO_ICTL_CFG5_SHIFT 5
- +#define HP_SECVIO_ICTL_CFG5_MASK (0x3 << HP_SECVIO_ICTL_CFG5_SHIFT)
- +#define HP_SECVIO_ICTL_CFG_DISABLE 0
- +#define HP_SECVIO_ICTL_CFG_NONFATAL 1
- +#define HP_SECVIO_ICTL_CFG_FATAL 2
- +#define HP_SECVIO_ICTL_CFG4_FATAL 0x00000010
- +#define HP_SECVIO_ICTL_CFG3_FATAL 0x00000008
- +#define HP_SECVIO_ICTL_CFG2_FATAL 0x00000004
- +#define HP_SECVIO_ICTL_CFG1_FATAL 0x00000002
- +#define HP_SECVIO_ICTL_CFG0_FATAL 0x00000001
- +
- +#define HP_STATUS_ZMK_ZERO 0x80000000
- +#define HP_STATUS_OTPMK_ZERO 0x08000000
- +#define HP_STATUS_OTPMK_SYN_SHIFT 16
- +#define HP_STATUS_OTPMK_SYN_MASK (0x1ff << HP_STATUS_OTPMK_SYN_SHIFT)
- +#define HP_STATUS_SSM_ST_SHIFT 8
- +#define HP_STATUS_SSM_ST_MASK (0xf << HP_STATUS_SSM_ST_SHIFT)
- +#define HP_STATUS_SSM_ST_INIT 0
- +#define HP_STATUS_SSM_ST_HARDFAIL 1
- +#define HP_STATUS_SSM_ST_SOFTFAIL 3
- +#define HP_STATUS_SSM_ST_INITINT 8
- +#define HP_STATUS_SSM_ST_CHECK 9
- +#define HP_STATUS_SSM_ST_NONSECURE 11
- +#define HP_STATUS_SSM_ST_TRUSTED 13
- +#define HP_STATUS_SSM_ST_SECURE 15
- +
- +#define HP_SECVIOST_ZMK_ECC_FAIL 0x08000000 /* write to clear */
- +#define HP_SECVIOST_ZMK_SYN_SHIFT 16
- +#define HP_SECVIOST_ZMK_SYN_MASK (0x1ff << HP_SECVIOST_ZMK_SYN_SHIFT)
- +#define HP_SECVIOST_SECVIO5 0x00000020
- +#define HP_SECVIOST_SECVIO4 0x00000010
- +#define HP_SECVIOST_SECVIO3 0x00000008
- +#define HP_SECVIOST_SECVIO2 0x00000004
- +#define HP_SECVIOST_SECVIO1 0x00000002
- +#define HP_SECVIOST_SECVIO0 0x00000001
- +#define HP_SECVIOST_SECVIOMASK 0x0000003f
- +
- +/*
- + * SNVS Low Power Domain
- + * Includes glitch detector, SRTC, alarm, monotonic counter, ZMK
- + */
- +struct snvs_lp {
- + u32 lock;
- + u32 ctl;
- + u32 mstr_key_ctl; /* Master Key Control */
- + u32 secvio_ctl; /* Security Violation Control */
- + u32 tamper_filt_cfg; /* Tamper Glitch Filters Configuration */
- + u32 tamper_det_cfg; /* Tamper Detectors Configuration */
- + u32 status;
- + u32 srtc_msb; /* Secure Real Time Clock/Counter MSB */
- + u32 srtc_lsb; /* Secure Real Time Clock/Counter LSB */
- + u32 time_alarm; /* Time Alarm */
- + u32 smc_msb; /* Secure Monotonic Counter MSB */
- + u32 smc_lsb; /* Secure Monotonic Counter LSB */
- + u32 pwr_glitch_det; /* Power Glitch Detector */
- + u32 gen_purpose;
- + u32 zmk[8]; /* Zeroizable Master Key */
- +};
- +
- +#define LP_LOCK_MKEYSEL_LCK 0x00000200
- +#define LP_LOCK_TAMPDET_LCK 0x00000100
- +#define LP_LOCK_TAMPFLT_LCK 0x00000080
- +#define LP_LOCK_SECVIO_LCK 0x00000040
- +#define LP_LOCK_GENP_LCK 0x00000020
- +#define LP_LOCK_MONOCTR_LCK 0x00000010
- +#define LP_LOCK_CALIB_LCK 0x00000008
- +#define LP_LOCK_SRTC_LCK 0x00000004
- +#define LP_LOCK_ZMK_RD_LCK 0x00000002
- +#define LP_LOCK_ZMK_WT_LCK 0x00000001
- +
- +#define LP_CTL_CAL_VAL_SHIFT 10
- +#define LP_CTL_CAL_VAL_MASK (0x1f << LP_CTL_CAL_VAL_SHIFT)
- +#define LP_CTL_CALIB_EN 0x00000100
- +#define LP_CTL_SRTC_INVAL_EN 0x00000010
- +#define LP_CTL_WAKE_INT_EN 0x00000008
- +#define LP_CTL_MONOCTR_EN 0x00000004
- +#define LP_CTL_TIMEALARM_EN 0x00000002
- +#define LP_CTL_SRTC_EN 0x00000001
- +
- +#define LP_MKEYCTL_ZMKECC_SHIFT 8
- +#define LP_MKEYCTL_ZMKECC_MASK (0xff << LP_MKEYCTL_ZMKECC_SHIFT)
- +#define LP_MKEYCTL_ZMKECC_EN 0x00000010
- +#define LP_MKEYCTL_ZMKECC_VAL 0x00000008
- +#define LP_MKEYCTL_ZMKECC_PROG 0x00000004
- +#define LP_MKEYCTL_MKSEL_SHIFT 0
- +#define LP_MKEYCTL_MKSEL_MASK (3 << LP_MKEYCTL_MKSEL_SHIFT)
- +#define LP_MKEYCTL_MK_OTP 0
- +#define LP_MKEYCTL_MK_ZMK 2
- +#define LP_MKEYCTL_MK_COMB 3
- +
- +#define LP_SECVIO_CTL_SRC5 0x20
- +#define LP_SECVIO_CTL_SRC4 0x10
- +#define LP_SECVIO_CTL_SRC3 0x08
- +#define LP_SECVIO_CTL_SRC2 0x04
- +#define LP_SECVIO_CTL_SRC1 0x02
- +#define LP_SECVIO_CTL_SRC0 0x01
- +
- +#define LP_TAMPFILT_EXT2_EN 0x80000000
- +#define LP_TAMPFILT_EXT2_SHIFT 24
- +#define LP_TAMPFILT_EXT2_MASK (0x1f << LP_TAMPFILT_EXT2_SHIFT)
- +#define LP_TAMPFILT_EXT1_EN 0x00800000
- +#define LP_TAMPFILT_EXT1_SHIFT 16
- +#define LP_TAMPFILT_EXT1_MASK (0x1f << LP_TAMPFILT_EXT1_SHIFT)
- +#define LP_TAMPFILT_WM_EN 0x00000080
- +#define LP_TAMPFILT_WM_SHIFT 0
- +#define LP_TAMPFILT_WM_MASK (0x1f << LP_TAMPFILT_WM_SHIFT)
- +
- +#define LP_TAMPDET_OSC_BPS 0x10000000
- +#define LP_TAMPDET_VRC_SHIFT 24
- +#define LP_TAMPDET_VRC_MASK (3 << LP_TAMPFILT_VRC_SHIFT)
- +#define LP_TAMPDET_HTDC_SHIFT 20
- +#define LP_TAMPDET_HTDC_MASK (3 << LP_TAMPFILT_HTDC_SHIFT)
- +#define LP_TAMPDET_LTDC_SHIFT 16
- +#define LP_TAMPDET_LTDC_MASK (3 << LP_TAMPFILT_LTDC_SHIFT)
- +#define LP_TAMPDET_POR_OBS 0x00008000
- +#define LP_TAMPDET_PFD_OBS 0x00004000
- +#define LP_TAMPDET_ET2_EN 0x00000400
- +#define LP_TAMPDET_ET1_EN 0x00000200
- +#define LP_TAMPDET_WMT2_EN 0x00000100
- +#define LP_TAMPDET_WMT1_EN 0x00000080
- +#define LP_TAMPDET_VT_EN 0x00000040
- +#define LP_TAMPDET_TT_EN 0x00000020
- +#define LP_TAMPDET_CT_EN 0x00000010
- +#define LP_TAMPDET_MCR_EN 0x00000004
- +#define LP_TAMPDET_SRTCR_EN 0x00000002
- +
- +#define LP_STATUS_SECURE
- +#define LP_STATUS_NONSECURE
- +#define LP_STATUS_SCANEXIT 0x00100000 /* all write 1 clear here on */
- +#define LP_STATUS_EXT_SECVIO 0x00010000
- +#define LP_STATUS_ET2 0x00000400
- +#define LP_STATUS_ET1 0x00000200
- +#define LP_STATUS_WMT2 0x00000100
- +#define LP_STATUS_WMT1 0x00000080
- +#define LP_STATUS_VTD 0x00000040
- +#define LP_STATUS_TTD 0x00000020
- +#define LP_STATUS_CTD 0x00000010
- +#define LP_STATUS_PGD 0x00000008
- +#define LP_STATUS_MCR 0x00000004
- +#define LP_STATUS_SRTCR 0x00000002
- +#define LP_STATUS_LPTA 0x00000001
- +
- +/* Full SNVS register page, including version/options */
- +struct snvs_full {
- + struct snvs_hp hp;
- + struct snvs_lp lp;
- + u32 rsvd[731]; /* deadspace 0x08c-0xbf7 */
- +
- + /* Version / Revision / Option ID space - end of register page */
- + u32 vid; /* 0xbf8 HP Version ID (VID 1) */
- + u32 opt_rev; /* 0xbfc HP Options / Revision (VID 2) */
- +};
- +
- +#endif /* SNVSREGS_H */
- diff -Nur linux-3.14.35.orig/drivers/dma/imx-sdma.c linux-3.14.35/drivers/dma/imx-sdma.c
- --- linux-3.14.35.orig/drivers/dma/imx-sdma.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/dma/imx-sdma.c 2015-03-08 14:27:37.545684501 -0500
- @@ -29,6 +29,7 @@
- #include <linux/semaphore.h>
- #include <linux/spinlock.h>
- #include <linux/device.h>
- +#include <linux/genalloc.h>
- #include <linux/dma-mapping.h>
- #include <linux/firmware.h>
- #include <linux/slab.h>
- @@ -232,6 +233,14 @@
-
- struct sdma_engine;
-
- +enum sdma_mode {
- + SDMA_MODE_INVALID = 0,
- + SDMA_MODE_LOOP,
- + SDMA_MODE_NORMAL,
- + SDMA_MODE_P2P,
- + SDMA_MODE_NO_BD,
- +};
- +
- /**
- * struct sdma_channel - housekeeping for a SDMA channel
- *
- @@ -244,6 +253,7 @@
- * @word_size peripheral access size
- * @buf_tail ID of the buffer that was processed
- * @num_bd max NUM_BD. number of descriptors currently handling
- + * @bd_iram flag indicating the memory location of buffer descriptor
- */
- struct sdma_channel {
- struct sdma_engine *sdma;
- @@ -255,14 +265,19 @@
- enum dma_slave_buswidth word_size;
- unsigned int buf_tail;
- unsigned int num_bd;
- + unsigned int period_len;
- struct sdma_buffer_descriptor *bd;
- dma_addr_t bd_phys;
- + bool bd_iram;
- unsigned int pc_from_device, pc_to_device;
- - unsigned long flags;
- - dma_addr_t per_address;
- + unsigned int device_to_device;
- + unsigned int other_script;
- + enum sdma_mode mode;
- + dma_addr_t per_address, per_address2;
- unsigned long event_mask[2];
- unsigned long watermark_level;
- u32 shp_addr, per_addr;
- + u32 data_addr1, data_addr2;
- struct dma_chan chan;
- spinlock_t lock;
- struct dma_async_tx_descriptor desc;
- @@ -272,8 +287,6 @@
- struct tasklet_struct tasklet;
- };
-
- -#define IMX_DMA_SG_LOOP BIT(0)
- -
- #define MAX_DMA_CHANNELS 32
- #define MXC_SDMA_DEFAULT_PRIORITY 1
- #define MXC_SDMA_MIN_PRIORITY 1
- @@ -325,6 +338,7 @@
- spinlock_t channel_0_lock;
- u32 script_number;
- struct sdma_script_start_addrs *script_addrs;
- + struct gen_pool *iram_pool;
- const struct sdma_driver_data *drvdata;
- };
-
- @@ -540,12 +554,14 @@
- dma_addr_t buf_phys;
- int ret;
- unsigned long flags;
- + bool use_iram = true;
-
- - buf_virt = dma_alloc_coherent(NULL,
- - size,
- - &buf_phys, GFP_KERNEL);
- + buf_virt = gen_pool_dma_alloc(sdma->iram_pool, size, &buf_phys);
- if (!buf_virt) {
- - return -ENOMEM;
- + use_iram = false;
- + buf_virt = dma_alloc_coherent(NULL, size, &buf_phys, GFP_KERNEL);
- + if (!buf_virt)
- + return -ENOMEM;
- }
-
- spin_lock_irqsave(&sdma->channel_0_lock, flags);
- @@ -562,7 +578,10 @@
-
- spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
-
- - dma_free_coherent(NULL, size, buf_virt, buf_phys);
- + if (use_iram)
- + gen_pool_free(sdma->iram_pool, (unsigned long)buf_virt, size);
- + else
- + dma_free_coherent(NULL, size, buf_virt, buf_phys);
-
- return ret;
- }
- @@ -593,6 +612,12 @@
-
- static void sdma_handle_channel_loop(struct sdma_channel *sdmac)
- {
- + if (sdmac->desc.callback)
- + sdmac->desc.callback(sdmac->desc.callback_param);
- +}
- +
- +static void sdma_update_channel_loop(struct sdma_channel *sdmac)
- +{
- struct sdma_buffer_descriptor *bd;
-
- /*
- @@ -607,15 +632,10 @@
-
- if (bd->mode.status & BD_RROR)
- sdmac->status = DMA_ERROR;
- - else
- - sdmac->status = DMA_IN_PROGRESS;
-
- bd->mode.status |= BD_DONE;
- sdmac->buf_tail++;
- sdmac->buf_tail %= sdmac->num_bd;
- -
- - if (sdmac->desc.callback)
- - sdmac->desc.callback(sdmac->desc.callback_param);
- }
- }
-
- @@ -647,14 +667,31 @@
- sdmac->desc.callback(sdmac->desc.callback_param);
- }
-
- +static void sdma_handle_other_intr(struct sdma_channel *sdmac)
- +{
- + if (sdmac->desc.callback)
- + sdmac->desc.callback(sdmac->desc.callback_param);
- +}
- +
- static void sdma_tasklet(unsigned long data)
- {
- struct sdma_channel *sdmac = (struct sdma_channel *) data;
- + struct sdma_engine *sdma = sdmac->sdma;
-
- - if (sdmac->flags & IMX_DMA_SG_LOOP)
- + switch (sdmac->mode) {
- + case SDMA_MODE_LOOP:
- sdma_handle_channel_loop(sdmac);
- - else
- + break;
- + case SDMA_MODE_NORMAL:
- mxc_sdma_handle_channel_normal(sdmac);
- + break;
- + case SDMA_MODE_NO_BD:
- + sdma_handle_other_intr(sdmac);
- + break;
- + default:
- + dev_err(sdma->dev, "invalid SDMA MODE!\n");
- + break;
- + }
- }
-
- static irqreturn_t sdma_int_handler(int irq, void *dev_id)
- @@ -671,6 +708,9 @@
- int channel = fls(stat) - 1;
- struct sdma_channel *sdmac = &sdma->channel[channel];
-
- + if (sdmac->mode & SDMA_MODE_LOOP)
- + sdma_update_channel_loop(sdmac);
- +
- tasklet_schedule(&sdmac->tasklet);
-
- __clear_bit(channel, &stat);
- @@ -692,9 +732,12 @@
- * two peripherals or memory-to-memory transfers
- */
- int per_2_per = 0, emi_2_emi = 0;
- + int other = 0;
-
- sdmac->pc_from_device = 0;
- sdmac->pc_to_device = 0;
- + sdmac->device_to_device = 0;
- + sdmac->other_script = 0;
-
- switch (peripheral_type) {
- case IMX_DMATYPE_MEMORY:
- @@ -740,8 +783,8 @@
- emi_2_per = sdma->script_addrs->mcu_2_shp_addr;
- break;
- case IMX_DMATYPE_ASRC:
- - per_2_emi = sdma->script_addrs->asrc_2_mcu_addr;
- - emi_2_per = sdma->script_addrs->asrc_2_mcu_addr;
- + per_2_emi = sdma->script_addrs->shp_2_mcu_addr;
- + emi_2_per = sdma->script_addrs->mcu_2_shp_addr;
- per_2_per = sdma->script_addrs->per_2_per_addr;
- break;
- case IMX_DMATYPE_MSHC:
- @@ -758,12 +801,17 @@
- case IMX_DMATYPE_IPU_MEMORY:
- emi_2_per = sdma->script_addrs->ext_mem_2_ipu_addr;
- break;
- + case IMX_DMATYPE_HDMI:
- + other = sdma->script_addrs->hdmi_dma_addr;
- + break;
- default:
- break;
- }
-
- sdmac->pc_from_device = per_2_emi;
- sdmac->pc_to_device = emi_2_per;
- + sdmac->device_to_device = per_2_per;
- + sdmac->other_script = other;
- }
-
- static int sdma_load_context(struct sdma_channel *sdmac)
- @@ -776,11 +824,14 @@
- int ret;
- unsigned long flags;
-
- - if (sdmac->direction == DMA_DEV_TO_MEM) {
- + if (sdmac->direction == DMA_DEV_TO_MEM)
- load_address = sdmac->pc_from_device;
- - } else {
- + else if (sdmac->direction == DMA_DEV_TO_DEV)
- + load_address = sdmac->device_to_device;
- + else if (sdmac->direction == DMA_MEM_TO_DEV)
- load_address = sdmac->pc_to_device;
- - }
- + else
- + load_address = sdmac->other_script;
-
- if (load_address < 0)
- return load_address;
- @@ -800,11 +851,16 @@
- /* Send by context the event mask,base address for peripheral
- * and watermark level
- */
- - context->gReg[0] = sdmac->event_mask[1];
- - context->gReg[1] = sdmac->event_mask[0];
- - context->gReg[2] = sdmac->per_addr;
- - context->gReg[6] = sdmac->shp_addr;
- - context->gReg[7] = sdmac->watermark_level;
- + if (sdmac->peripheral_type == IMX_DMATYPE_HDMI) {
- + context->gReg[4] = sdmac->data_addr1;
- + context->gReg[6] = sdmac->data_addr2;
- + } else {
- + context->gReg[0] = sdmac->event_mask[1];
- + context->gReg[1] = sdmac->event_mask[0];
- + context->gReg[2] = sdmac->per_addr;
- + context->gReg[6] = sdmac->shp_addr;
- + context->gReg[7] = sdmac->watermark_level;
- + }
-
- bd0->mode.command = C0_SETDM;
- bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
- @@ -829,6 +885,7 @@
-
- static int sdma_config_channel(struct sdma_channel *sdmac)
- {
- + struct imx_dma_data *data = sdmac->chan.private;
- int ret;
-
- sdma_disable_channel(sdmac);
- @@ -837,12 +894,19 @@
- sdmac->event_mask[1] = 0;
- sdmac->shp_addr = 0;
- sdmac->per_addr = 0;
- + sdmac->data_addr1 = 0;
- + sdmac->data_addr2 = 0;
-
- if (sdmac->event_id0) {
- if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events)
- return -EINVAL;
- sdma_event_enable(sdmac, sdmac->event_id0);
- }
- + if (sdmac->event_id1) {
- + if (sdmac->event_id1 >= sdmac->sdma->drvdata->num_events)
- + return -EINVAL;
- + sdma_event_enable(sdmac, sdmac->event_id1);
- + }
-
- switch (sdmac->peripheral_type) {
- case IMX_DMATYPE_DSP:
- @@ -862,19 +926,75 @@
- (sdmac->peripheral_type != IMX_DMATYPE_DSP)) {
- /* Handle multiple event channels differently */
- if (sdmac->event_id1) {
- - sdmac->event_mask[1] = BIT(sdmac->event_id1 % 32);
- - if (sdmac->event_id1 > 31)
- - __set_bit(31, &sdmac->watermark_level);
- - sdmac->event_mask[0] = BIT(sdmac->event_id0 % 32);
- - if (sdmac->event_id0 > 31)
- - __set_bit(30, &sdmac->watermark_level);
- + if (sdmac->event_id0 > 31) {
- + sdmac->event_mask[0] |= 0;
- + __set_bit(28, &sdmac->watermark_level);
- + sdmac->event_mask[1] |=
- + BIT(sdmac->event_id0 % 32);
- + } else {
- + sdmac->event_mask[1] |= 0;
- + sdmac->event_mask[0] |=
- + BIT(sdmac->event_id0 % 32);
- + }
- + if (sdmac->event_id1 > 31) {
- + sdmac->event_mask[0] |= 0;
- + __set_bit(29, &sdmac->watermark_level);
- + sdmac->event_mask[1] |=
- + BIT(sdmac->event_id1 % 32);
- + } else {
- + sdmac->event_mask[1] |= 0;
- + sdmac->event_mask[0] |=
- + BIT(sdmac->event_id1 % 32);
- + }
- + /* BIT 11:
- + * 1 : Source on SPBA
- + * 0 : Source on AIPS
- + */
- + __set_bit(11, &sdmac->watermark_level);
- + /* BIT 12:
- + * 1 : Destination on SPBA
- + * 0 : Destination on AIPS
- + */
- + __set_bit(12, &sdmac->watermark_level);
- + __set_bit(31, &sdmac->watermark_level);
- + /* BIT 31:
- + * 1 : Amount of samples to be transferred is
- + * unknown and script will keep on transferring
- + * samples as long as both events are detected
- + * and script must be manually stopped by the
- + * application.
- + * 0 : The amount of samples to be is equal to
- + * the count field of mode word
- + * */
- + __set_bit(25, &sdmac->watermark_level);
- + __clear_bit(24, &sdmac->watermark_level);
- } else {
- - __set_bit(sdmac->event_id0, sdmac->event_mask);
- + if (sdmac->event_id0 > 31) {
- + sdmac->event_mask[0] = 0;
- + sdmac->event_mask[1] |=
- + BIT(sdmac->event_id0 % 32);
- + } else {
- + sdmac->event_mask[0] |=
- + BIT(sdmac->event_id0 % 32);
- + sdmac->event_mask[1] = 0;
- + }
- }
- /* Watermark Level */
- sdmac->watermark_level |= sdmac->watermark_level;
- /* Address */
- - sdmac->shp_addr = sdmac->per_address;
- + if (sdmac->direction == DMA_DEV_TO_DEV) {
- + sdmac->shp_addr = sdmac->per_address2;
- + sdmac->per_addr = sdmac->per_address;
- + } else if (sdmac->direction == DMA_TRANS_NONE) {
- + if (sdmac->peripheral_type != IMX_DMATYPE_HDMI ||
- + !data->data_addr1 || !data->data_addr2)
- + return -EINVAL;
- + sdmac->data_addr1 = *(u32 *)data->data_addr1;
- + sdmac->data_addr2 = *(u32 *)data->data_addr2;
- + sdmac->watermark_level = 0;
- + } else {
- + sdmac->shp_addr = sdmac->per_address;
- + }
- } else {
- sdmac->watermark_level = 0; /* FIXME: M3_BASE_ADDRESS */
- }
- @@ -906,10 +1026,15 @@
- int channel = sdmac->channel;
- int ret = -EBUSY;
-
- - sdmac->bd = dma_alloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys, GFP_KERNEL);
- + sdmac->bd_iram = true;
- + sdmac->bd = gen_pool_dma_alloc(sdma->iram_pool, PAGE_SIZE, &sdmac->bd_phys);
- if (!sdmac->bd) {
- - ret = -ENOMEM;
- - goto out;
- + sdmac->bd_iram = false;
- + sdmac->bd = dma_alloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys, GFP_KERNEL);
- + if (!sdmac->bd) {
- + ret = -ENOMEM;
- + goto out;
- + }
- }
-
- memset(sdmac->bd, 0, PAGE_SIZE);
- @@ -967,7 +1092,8 @@
- }
-
- sdmac->peripheral_type = data->peripheral_type;
- - sdmac->event_id0 = data->dma_request;
- + sdmac->event_id0 = data->dma_request0;
- + sdmac->event_id1 = data->dma_request1;
-
- clk_enable(sdmac->sdma->clk_ipg);
- clk_enable(sdmac->sdma->clk_ahb);
- @@ -985,6 +1111,9 @@
- /* txd.flags will be overwritten in prep funcs */
- sdmac->desc.flags = DMA_CTRL_ACK;
-
- + /* Set SDMA channel mode to unvalid to avoid misconfig */
- + sdmac->mode = SDMA_MODE_INVALID;
- +
- return 0;
- }
-
- @@ -1005,7 +1134,10 @@
-
- sdma_set_channel_priority(sdmac, 0);
-
- - dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys);
- + if (sdmac->bd_iram)
- + gen_pool_free(sdma->iram_pool, (unsigned long)sdmac->bd, PAGE_SIZE);
- + else
- + dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys);
-
- clk_disable(sdma->clk_ipg);
- clk_disable(sdma->clk_ahb);
- @@ -1026,7 +1158,7 @@
- return NULL;
- sdmac->status = DMA_IN_PROGRESS;
-
- - sdmac->flags = 0;
- + sdmac->mode = SDMA_MODE_NORMAL;
-
- sdmac->buf_tail = 0;
-
- @@ -1119,9 +1251,9 @@
- {
- struct sdma_channel *sdmac = to_sdma_chan(chan);
- struct sdma_engine *sdma = sdmac->sdma;
- - int num_periods = buf_len / period_len;
- int channel = sdmac->channel;
- int ret, i = 0, buf = 0;
- + int num_periods;
-
- dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel);
-
- @@ -1131,13 +1263,35 @@
- sdmac->status = DMA_IN_PROGRESS;
-
- sdmac->buf_tail = 0;
- + sdmac->period_len = period_len;
-
- - sdmac->flags |= IMX_DMA_SG_LOOP;
- sdmac->direction = direction;
- +
- + switch (sdmac->direction) {
- + case DMA_DEV_TO_DEV:
- + sdmac->mode = SDMA_MODE_P2P;
- + break;
- + case DMA_TRANS_NONE:
- + sdmac->mode = SDMA_MODE_NO_BD;
- + break;
- + case DMA_MEM_TO_DEV:
- + case DMA_DEV_TO_MEM:
- + sdmac->mode = SDMA_MODE_LOOP;
- + break;
- + default:
- + dev_err(sdma->dev, "invalid SDMA direction %d\n", direction);
- + return NULL;
- + }
- +
- ret = sdma_load_context(sdmac);
- if (ret)
- goto err_out;
-
- + if (period_len)
- + num_periods = buf_len / period_len;
- + else
- + return &sdmac->desc;
- +
- if (num_periods > NUM_BD) {
- dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n",
- channel, num_periods, NUM_BD);
- @@ -1202,18 +1356,31 @@
- sdma_disable_channel(sdmac);
- return 0;
- case DMA_SLAVE_CONFIG:
- - if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) {
- + if (dmaengine_cfg->direction == DMA_DEV_TO_DEV) {
- + sdmac->per_address = dmaengine_cfg->src_addr;
- + sdmac->per_address2 = dmaengine_cfg->dst_addr;
- + sdmac->watermark_level = 0;
- + sdmac->watermark_level |=
- + dmaengine_cfg->src_maxburst;
- + sdmac->watermark_level |=
- + dmaengine_cfg->dst_maxburst << 16;
- + sdmac->word_size = dmaengine_cfg->dst_addr_width;
- + } else if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) {
- sdmac->per_address = dmaengine_cfg->src_addr;
- sdmac->watermark_level = dmaengine_cfg->src_maxburst *
- dmaengine_cfg->src_addr_width;
- sdmac->word_size = dmaengine_cfg->src_addr_width;
- - } else {
- + } else if (dmaengine_cfg->direction == DMA_MEM_TO_DEV) {
- sdmac->per_address = dmaengine_cfg->dst_addr;
- sdmac->watermark_level = dmaengine_cfg->dst_maxburst *
- dmaengine_cfg->dst_addr_width;
- sdmac->word_size = dmaengine_cfg->dst_addr_width;
- }
- sdmac->direction = dmaengine_cfg->direction;
- + if (dmaengine_cfg->dma_request0)
- + sdmac->event_id0 = dmaengine_cfg->dma_request0;
- + if (dmaengine_cfg->dma_request1)
- + sdmac->event_id1 = dmaengine_cfg->dma_request1;
- return sdma_config_channel(sdmac);
- default:
- return -ENOSYS;
- @@ -1227,9 +1394,15 @@
- struct dma_tx_state *txstate)
- {
- struct sdma_channel *sdmac = to_sdma_chan(chan);
- + u32 residue;
- +
- + if (sdmac->mode & SDMA_MODE_LOOP)
- + residue = (sdmac->num_bd - sdmac->buf_tail) * sdmac->period_len;
- + else
- + residue = sdmac->chn_count - sdmac->chn_real_count;
-
- dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie,
- - sdmac->chn_count - sdmac->chn_real_count);
- + residue);
-
- return sdmac->status;
- }
- @@ -1285,7 +1458,10 @@
- goto err_firmware;
- switch (header->version_major) {
- case 1:
- - sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1;
- + if (header->version_minor > 0)
- + sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2;
- + else
- + sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1;
- break;
- case 2:
- sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2;
- @@ -1331,7 +1507,7 @@
-
- static int __init sdma_init(struct sdma_engine *sdma)
- {
- - int i, ret;
- + int i, ret, ccbsize;
- dma_addr_t ccb_phys;
-
- clk_enable(sdma->clk_ipg);
- @@ -1340,14 +1516,17 @@
- /* Be sure SDMA has not started yet */
- writel_relaxed(0, sdma->regs + SDMA_H_C0PTR);
-
- - sdma->channel_control = dma_alloc_coherent(NULL,
- - MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control) +
- - sizeof(struct sdma_context_data),
- - &ccb_phys, GFP_KERNEL);
- + ccbsize = MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control)
- + + sizeof(struct sdma_context_data);
-
- + sdma->channel_control = gen_pool_dma_alloc(sdma->iram_pool, ccbsize, &ccb_phys);
- if (!sdma->channel_control) {
- - ret = -ENOMEM;
- - goto err_dma_alloc;
- + sdma->channel_control = dma_alloc_coherent(NULL, ccbsize,
- + &ccb_phys, GFP_KERNEL);
- + if (!sdma->channel_control) {
- + ret = -ENOMEM;
- + goto err_dma_alloc;
- + }
- }
-
- sdma->context = (void *)sdma->channel_control +
- @@ -1422,9 +1601,10 @@
- if (dma_spec->args_count != 3)
- return NULL;
-
- - data.dma_request = dma_spec->args[0];
- + data.dma_request0 = dma_spec->args[0];
- data.peripheral_type = dma_spec->args[1];
- data.priority = dma_spec->args[2];
- + data.dma_request1 = 0;
-
- return dma_request_channel(mask, sdma_filter_fn, &data);
- }
- @@ -1542,6 +1722,11 @@
- &sdma->dma_device.channels);
- }
-
- + if (np)
- + sdma->iram_pool = of_get_named_gen_pool(np, "iram", 0);
- + if (!sdma->iram_pool)
- + dev_warn(&pdev->dev, "no iram assigned, using external mem\n");
- +
- ret = sdma_init(sdma);
- if (ret)
- goto err_init;
- diff -Nur linux-3.14.35.orig/drivers/dma/Kconfig linux-3.14.35/drivers/dma/Kconfig
- --- linux-3.14.35.orig/drivers/dma/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/dma/Kconfig 2015-03-08 14:27:37.545684501 -0500
- @@ -137,6 +137,19 @@
- To avoid bloating the irq_desc[] array we allocate a sufficient
- number of IRQ slots and map them dynamically to specific sources.
-
- +config MXC_PXP_V2
- + bool "MXC PxP V2 support"
- + depends on ARM
- + select DMA_ENGINE
- + help
- + Support the PxP (Pixel Pipeline) on i.MX6 DualLite and i.MX6 SoloLite.
- + If unsure, select N.
- +
- +config MXC_PXP_CLIENT_DEVICE
- + bool "MXC PxP Client Device"
- + default y
- + depends on MXC_PXP_V2
- +
- config TXX9_DMAC
- tristate "Toshiba TXx9 SoC DMA support"
- depends on MACH_TX49XX || MACH_TX39XX
- diff -Nur linux-3.14.35.orig/drivers/dma/Makefile linux-3.14.35/drivers/dma/Makefile
- --- linux-3.14.35.orig/drivers/dma/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/dma/Makefile 2015-03-08 14:27:37.545684501 -0500
- @@ -18,6 +18,7 @@
- obj-$(CONFIG_DW_DMAC_CORE) += dw/
- obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
- obj-$(CONFIG_MX3_IPU) += ipu/
- +obj-$(CONFIG_MXC_PXP_V2) += pxp/
- obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o
- obj-$(CONFIG_SH_DMAE_BASE) += sh/
- obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o
- diff -Nur linux-3.14.35.orig/drivers/dma/pxp/Makefile linux-3.14.35/drivers/dma/pxp/Makefile
- --- linux-3.14.35.orig/drivers/dma/pxp/Makefile 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/dma/pxp/Makefile 2015-03-08 14:27:37.545684501 -0500
- @@ -0,0 +1,2 @@
- +obj-$(CONFIG_MXC_PXP_V2) += pxp_dma_v2.o
- +obj-$(CONFIG_MXC_PXP_CLIENT_DEVICE) += pxp_device.o
- diff -Nur linux-3.14.35.orig/drivers/dma/pxp/pxp_device.c linux-3.14.35/drivers/dma/pxp/pxp_device.c
- --- linux-3.14.35.orig/drivers/dma/pxp/pxp_device.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/dma/pxp/pxp_device.c 2015-03-08 14:27:37.545684501 -0500
- @@ -0,0 +1,765 @@
- +/*
- + * Copyright (C) 2010-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + */
- +#include <linux/interrupt.h>
- +#include <linux/miscdevice.h>
- +#include <linux/platform_device.h>
- +#include <linux/fs.h>
- +#include <linux/slab.h>
- +#include <linux/uaccess.h>
- +#include <linux/delay.h>
- +#include <linux/dmaengine.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/sched.h>
- +#include <linux/module.h>
- +#include <linux/pxp_device.h>
- +#include <linux/atomic.h>
- +#include <linux/platform_data/dma-imx.h>
- +
- +#define BUFFER_HASH_ORDER 4
- +
- +static struct pxp_buffer_hash bufhash;
- +static struct pxp_irq_info irq_info[NR_PXP_VIRT_CHANNEL];
- +
- +static int pxp_ht_create(struct pxp_buffer_hash *hash, int order)
- +{
- + unsigned long i;
- + unsigned long table_size;
- +
- + table_size = 1U << order;
- +
- + hash->order = order;
- + hash->hash_table = kmalloc(sizeof(*hash->hash_table) * table_size, GFP_KERNEL);
- +
- + if (!hash->hash_table) {
- + pr_err("%s: Out of memory for hash table\n", __func__);
- + return -ENOMEM;
- + }
- +
- + for (i = 0; i < table_size; i++)
- + INIT_HLIST_HEAD(&hash->hash_table[i]);
- +
- + return 0;
- +}
- +
- +static int pxp_ht_insert_item(struct pxp_buffer_hash *hash,
- + struct pxp_buf_obj *new)
- +{
- + unsigned long hashkey;
- + struct hlist_head *h_list;
- +
- + hashkey = hash_long(new->offset >> PAGE_SHIFT, hash->order);
- + h_list = &hash->hash_table[hashkey];
- +
- + spin_lock(&hash->hash_lock);
- + hlist_add_head_rcu(&new->item, h_list);
- + spin_unlock(&hash->hash_lock);
- +
- + return 0;
- +}
- +
- +static int pxp_ht_remove_item(struct pxp_buffer_hash *hash,
- + struct pxp_buf_obj *obj)
- +{
- + spin_lock(&hash->hash_lock);
- + hlist_del_init_rcu(&obj->item);
- + spin_unlock(&hash->hash_lock);
- + return 0;
- +}
- +
- +static struct hlist_node *pxp_ht_find_key(struct pxp_buffer_hash *hash,
- + unsigned long key)
- +{
- + struct pxp_buf_obj *entry;
- + struct hlist_head *h_list;
- + unsigned long hashkey;
- +
- + hashkey = hash_long(key, hash->order);
- + h_list = &hash->hash_table[hashkey];
- +
- + hlist_for_each_entry_rcu(entry, h_list, item) {
- + if (entry->offset >> PAGE_SHIFT == key)
- + return &entry->item;
- + }
- +
- + return NULL;
- +}
- +
- +static void pxp_ht_destroy(struct pxp_buffer_hash *hash)
- +{
- + kfree(hash->hash_table);
- + hash->hash_table = NULL;
- +}
- +
- +static int pxp_buffer_handle_create(struct pxp_file *file_priv,
- + struct pxp_buf_obj *obj,
- + uint32_t *handlep)
- +{
- + int ret;
- +
- + idr_preload(GFP_KERNEL);
- + spin_lock(&file_priv->buffer_lock);
- +
- + ret = idr_alloc(&file_priv->buffer_idr, obj, 1, 0, GFP_NOWAIT);
- +
- + spin_unlock(&file_priv->buffer_lock);
- + idr_preload_end();
- +
- + if (ret < 0)
- + return ret;
- +
- + *handlep = ret;
- +
- + return 0;
- +}
- +
- +static struct pxp_buf_obj *
- +pxp_buffer_object_lookup(struct pxp_file *file_priv,
- + uint32_t handle)
- +{
- + struct pxp_buf_obj *obj;
- +
- + spin_lock(&file_priv->buffer_lock);
- +
- + obj = idr_find(&file_priv->buffer_idr, handle);
- + if (!obj) {
- + spin_unlock(&file_priv->buffer_lock);
- + return NULL;
- + }
- +
- + spin_unlock(&file_priv->buffer_lock);
- +
- + return obj;
- +}
- +
- +static int pxp_buffer_handle_delete(struct pxp_file *file_priv,
- + uint32_t handle)
- +{
- + struct pxp_buf_obj *obj;
- +
- + spin_lock(&file_priv->buffer_lock);
- +
- + obj = idr_find(&file_priv->buffer_idr, handle);
- + if (!obj) {
- + spin_unlock(&file_priv->buffer_lock);
- + return -EINVAL;
- + }
- +
- + idr_remove(&file_priv->buffer_idr, handle);
- + spin_unlock(&file_priv->buffer_lock);
- +
- + return 0;
- +}
- +
- +static int pxp_channel_handle_create(struct pxp_file *file_priv,
- + struct pxp_chan_obj *obj,
- + uint32_t *handlep)
- +{
- + int ret;
- +
- + idr_preload(GFP_KERNEL);
- + spin_lock(&file_priv->channel_lock);
- +
- + ret = idr_alloc(&file_priv->channel_idr, obj, 0, 0, GFP_NOWAIT);
- +
- + spin_unlock(&file_priv->channel_lock);
- + idr_preload_end();
- +
- + if (ret < 0)
- + return ret;
- +
- + *handlep = ret;
- +
- + return 0;
- +}
- +
- +static struct pxp_chan_obj *
- +pxp_channel_object_lookup(struct pxp_file *file_priv,
- + uint32_t handle)
- +{
- + struct pxp_chan_obj *obj;
- +
- + spin_lock(&file_priv->channel_lock);
- +
- + obj = idr_find(&file_priv->channel_idr, handle);
- + if (!obj) {
- + spin_unlock(&file_priv->channel_lock);
- + return NULL;
- + }
- +
- + spin_unlock(&file_priv->channel_lock);
- +
- + return obj;
- +}
- +
- +static int pxp_channel_handle_delete(struct pxp_file *file_priv,
- + uint32_t handle)
- +{
- + struct pxp_chan_obj *obj;
- +
- + spin_lock(&file_priv->channel_lock);
- +
- + obj = idr_find(&file_priv->channel_idr, handle);
- + if (!obj) {
- + spin_unlock(&file_priv->channel_lock);
- + return -EINVAL;
- + }
- +
- + idr_remove(&file_priv->channel_idr, handle);
- + spin_unlock(&file_priv->channel_lock);
- +
- + return 0;
- +}
- +
- +static int pxp_alloc_dma_buffer(struct pxp_buf_obj *obj)
- +{
- + obj->virtual = dma_alloc_coherent(NULL, PAGE_ALIGN(obj->size),
- + (dma_addr_t *) (&obj->offset),
- + GFP_DMA | GFP_KERNEL);
- + pr_debug("[ALLOC] mem alloc phys_addr = 0x%lx\n", obj->offset);
- +
- + if (obj->virtual == NULL) {
- + printk(KERN_ERR "Physical memory allocation error!\n");
- + return -1;
- + }
- +
- + return 0;
- +}
- +
- +static void pxp_free_dma_buffer(struct pxp_buf_obj *obj)
- +{
- + if (obj->virtual != NULL) {
- + dma_free_coherent(0, PAGE_ALIGN(obj->size),
- + obj->virtual, (dma_addr_t)obj->offset);
- + }
- +}
- +
- +static int
- +pxp_buffer_object_free(int id, void *ptr, void *data)
- +{
- + struct pxp_file *file_priv = data;
- + struct pxp_buf_obj *obj = ptr;
- + int ret;
- +
- + ret = pxp_buffer_handle_delete(file_priv, obj->handle);
- + if (ret < 0)
- + return ret;
- +
- + pxp_ht_remove_item(&bufhash, obj);
- + pxp_free_dma_buffer(obj);
- + kfree(obj);
- +
- + return 0;
- +}
- +
- +static int
- +pxp_channel_object_free(int id, void *ptr, void *data)
- +{
- + struct pxp_file *file_priv = data;
- + struct pxp_chan_obj *obj = ptr;
- + int chan_id;
- +
- + chan_id = obj->chan->chan_id;
- + wait_event(irq_info[chan_id].waitq,
- + atomic_read(&irq_info[chan_id].irq_pending) == 0);
- +
- + pxp_channel_handle_delete(file_priv, obj->handle);
- + dma_release_channel(obj->chan);
- + kfree(obj);
- +
- + return 0;
- +}
- +
- +static void pxp_free_buffers(struct pxp_file *file_priv)
- +{
- + idr_for_each(&file_priv->buffer_idr,
- + &pxp_buffer_object_free, file_priv);
- + idr_destroy(&file_priv->buffer_idr);
- +}
- +
- +static void pxp_free_channels(struct pxp_file *file_priv)
- +{
- + idr_for_each(&file_priv->channel_idr,
- + &pxp_channel_object_free, file_priv);
- + idr_destroy(&file_priv->channel_idr);
- +}
- +
- +/* Callback function triggered after PxP receives an EOF interrupt */
- +static void pxp_dma_done(void *arg)
- +{
- + struct pxp_tx_desc *tx_desc = to_tx_desc(arg);
- + struct dma_chan *chan = tx_desc->txd.chan;
- + struct pxp_channel *pxp_chan = to_pxp_channel(chan);
- + int chan_id = pxp_chan->dma_chan.chan_id;
- +
- + pr_debug("DMA Done ISR, chan_id %d\n", chan_id);
- +
- + atomic_dec(&irq_info[chan_id].irq_pending);
- + irq_info[chan_id].hist_status = tx_desc->hist_status;
- +
- + wake_up(&(irq_info[chan_id].waitq));
- +}
- +
- +static int pxp_ioc_config_chan(struct pxp_file *priv, unsigned long arg)
- +{
- + struct scatterlist sg[3];
- + struct pxp_tx_desc *desc;
- + struct dma_async_tx_descriptor *txd;
- + struct pxp_config_data pxp_conf;
- + dma_cookie_t cookie;
- + int handle, chan_id;
- + int i, length, ret;
- + struct dma_chan *chan;
- + struct pxp_chan_obj *obj;
- +
- + ret = copy_from_user(&pxp_conf,
- + (struct pxp_config_data *)arg,
- + sizeof(struct pxp_config_data));
- + if (ret)
- + return -EFAULT;
- +
- + handle = pxp_conf.handle;
- + obj = pxp_channel_object_lookup(priv, handle);
- + if (!obj)
- + return -EINVAL;
- + chan = obj->chan;
- + chan_id = chan->chan_id;
- +
- + sg_init_table(sg, 3);
- +
- + txd = chan->device->device_prep_slave_sg(chan,
- + sg, 3,
- + DMA_TO_DEVICE,
- + DMA_PREP_INTERRUPT,
- + NULL);
- + if (!txd) {
- + pr_err("Error preparing a DMA transaction descriptor.\n");
- + return -EIO;
- + }
- +
- + txd->callback_param = txd;
- + txd->callback = pxp_dma_done;
- +
- + desc = to_tx_desc(txd);
- +
- + length = desc->len;
- + for (i = 0; i < length; i++) {
- + if (i == 0) { /* S0 */
- + memcpy(&desc->proc_data,
- + &pxp_conf.proc_data,
- + sizeof(struct pxp_proc_data));
- + memcpy(&desc->layer_param.s0_param,
- + &pxp_conf.s0_param,
- + sizeof(struct pxp_layer_param));
- + } else if (i == 1) { /* Output */
- + memcpy(&desc->layer_param.out_param,
- + &pxp_conf.out_param,
- + sizeof(struct pxp_layer_param));
- + } else {
- + /* OverLay */
- + memcpy(&desc->layer_param.ol_param,
- + &pxp_conf.ol_param,
- + sizeof(struct pxp_layer_param));
- + }
- +
- + desc = desc->next;
- + }
- +
- + cookie = txd->tx_submit(txd);
- + if (cookie < 0) {
- + pr_err("Error tx_submit\n");
- + return -EIO;
- + }
- +
- + atomic_inc(&irq_info[chan_id].irq_pending);
- +
- + return 0;
- +}
- +
- +static int pxp_device_open(struct inode *inode, struct file *filp)
- +{
- + struct pxp_file *priv;
- +
- + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- +
- + if (!priv)
- + return -ENOMEM;
- +
- + filp->private_data = priv;
- + priv->filp = filp;
- +
- + idr_init(&priv->buffer_idr);
- + spin_lock_init(&priv->buffer_lock);
- +
- + idr_init(&priv->channel_idr);
- + spin_lock_init(&priv->channel_lock);
- +
- + return 0;
- +}
- +
- +static int pxp_device_release(struct inode *inode, struct file *filp)
- +{
- + struct pxp_file *priv = filp->private_data;
- +
- + if (priv) {
- + pxp_free_channels(priv);
- + pxp_free_buffers(priv);
- + kfree(priv);
- + filp->private_data = NULL;
- + }
- +
- + return 0;
- +}
- +
- +static int pxp_device_mmap(struct file *file, struct vm_area_struct *vma)
- +{
- + int request_size;
- + struct hlist_node *node;
- + struct pxp_buf_obj *obj;
- +
- + request_size = vma->vm_end - vma->vm_start;
- +
- + pr_debug("start=0x%x, pgoff=0x%x, size=0x%x\n",
- + (unsigned int)(vma->vm_start), (unsigned int)(vma->vm_pgoff),
- + request_size);
- +
- + node = pxp_ht_find_key(&bufhash, vma->vm_pgoff);
- + if (!node)
- + return -EINVAL;
- +
- + obj = list_entry(node, struct pxp_buf_obj, item);
- + if (obj->offset + (obj->size >> PAGE_SHIFT) <
- + (vma->vm_pgoff + vma_pages(vma)))
- + return -ENOMEM;
- +
- + switch (obj->mem_type) {
- + case MEMORY_TYPE_UNCACHED:
- + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- + break;
- + case MEMORY_TYPE_WC:
- + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- + break;
- + case MEMORY_TYPE_CACHED:
- + break;
- + default:
- + pr_err("%s: invalid memory type!\n", __func__);
- + return -EINVAL;
- + }
- +
- + return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- + request_size, vma->vm_page_prot) ? -EAGAIN : 0;
- +}
- +
- +static bool chan_filter(struct dma_chan *chan, void *arg)
- +{
- + if (imx_dma_is_pxp(chan))
- + return true;
- + else
- + return false;
- +}
- +
- +static long pxp_device_ioctl(struct file *filp,
- + unsigned int cmd, unsigned long arg)
- +{
- + int ret = 0;
- + struct pxp_file *file_priv = filp->private_data;
- +
- + switch (cmd) {
- + case PXP_IOC_GET_CHAN:
- + {
- + int ret;
- + struct dma_chan *chan = NULL;
- + dma_cap_mask_t mask;
- + struct pxp_chan_obj *obj = NULL;
- +
- + pr_debug("drv: PXP_IOC_GET_CHAN Line %d\n", __LINE__);
- +
- + dma_cap_zero(mask);
- + dma_cap_set(DMA_SLAVE, mask);
- + dma_cap_set(DMA_PRIVATE, mask);
- +
- + chan = dma_request_channel(mask, chan_filter, NULL);
- + if (!chan) {
- + pr_err("Unsccessfully received channel!\n");
- + return -EBUSY;
- + }
- +
- + pr_debug("Successfully received channel."
- + "chan_id %d\n", chan->chan_id);
- +
- + obj = kzalloc(sizeof(*obj), GFP_KERNEL);
- + if (!obj) {
- + dma_release_channel(chan);
- + return -ENOMEM;
- + }
- + obj->chan = chan;
- +
- + ret = pxp_channel_handle_create(file_priv, obj,
- + &obj->handle);
- + if (ret) {
- + dma_release_channel(chan);
- + kfree(obj);
- + return ret;
- + }
- +
- + init_waitqueue_head(&(irq_info[chan->chan_id].waitq));
- + if (put_user(obj->handle, (u32 __user *) arg)) {
- + pxp_channel_handle_delete(file_priv, obj->handle);
- + dma_release_channel(chan);
- + kfree(obj);
- + return -EFAULT;
- + }
- +
- + break;
- + }
- + case PXP_IOC_PUT_CHAN:
- + {
- + int handle;
- + struct pxp_chan_obj *obj;
- +
- + if (get_user(handle, (u32 __user *) arg))
- + return -EFAULT;
- +
- + pr_debug("%d release handle %d\n", __LINE__, handle);
- +
- + obj = pxp_channel_object_lookup(file_priv, handle);
- + if (!obj)
- + return -EINVAL;
- +
- + pxp_channel_handle_delete(file_priv, obj->handle);
- + dma_release_channel(obj->chan);
- + kfree(obj);
- +
- + break;
- + }
- + case PXP_IOC_CONFIG_CHAN:
- + {
- + int ret;
- +
- + ret = pxp_ioc_config_chan(file_priv, arg);
- + if (ret)
- + return ret;
- +
- + break;
- + }
- + case PXP_IOC_START_CHAN:
- + {
- + int handle;
- + struct pxp_chan_obj *obj = NULL;
- +
- + if (get_user(handle, (u32 __user *) arg))
- + return -EFAULT;
- +
- + obj = pxp_channel_object_lookup(file_priv, handle);
- + if (!obj)
- + return -EINVAL;
- +
- + dma_async_issue_pending(obj->chan);
- +
- + break;
- + }
- + case PXP_IOC_GET_PHYMEM:
- + {
- + struct pxp_mem_desc buffer;
- + struct pxp_buf_obj *obj;
- +
- + ret = copy_from_user(&buffer,
- + (struct pxp_mem_desc *)arg,
- + sizeof(struct pxp_mem_desc));
- + if (ret)
- + return -EFAULT;
- +
- + pr_debug("[ALLOC] mem alloc size = 0x%x\n",
- + buffer.size);
- +
- + obj = kzalloc(sizeof(*obj), GFP_KERNEL);
- + if (!obj)
- + return -ENOMEM;
- + obj->size = buffer.size;
- + obj->mem_type = buffer.mtype;
- +
- + ret = pxp_alloc_dma_buffer(obj);
- + if (ret == -1) {
- + printk(KERN_ERR
- + "Physical memory allocation error!\n");
- + kfree(obj);
- + return ret;
- + }
- +
- + ret = pxp_buffer_handle_create(file_priv, obj, &obj->handle);
- + if (ret) {
- + pxp_free_dma_buffer(obj);
- + kfree(obj);
- + return ret;
- + }
- + buffer.handle = obj->handle;
- + buffer.phys_addr = obj->offset;
- +
- + ret = copy_to_user((void __user *)arg, &buffer,
- + sizeof(struct pxp_mem_desc));
- + if (ret) {
- + pxp_buffer_handle_delete(file_priv, buffer.handle);
- + pxp_free_dma_buffer(obj);
- + kfree(obj);
- + return -EFAULT;
- + }
- +
- + pxp_ht_insert_item(&bufhash, obj);
- +
- + break;
- + }
- + case PXP_IOC_PUT_PHYMEM:
- + {
- + struct pxp_mem_desc pxp_mem;
- + struct pxp_buf_obj *obj;
- +
- + ret = copy_from_user(&pxp_mem,
- + (struct pxp_mem_desc *)arg,
- + sizeof(struct pxp_mem_desc));
- + if (ret)
- + return -EACCES;
- +
- + obj = pxp_buffer_object_lookup(file_priv, pxp_mem.handle);
- + if (!obj)
- + return -EINVAL;
- +
- + ret = pxp_buffer_handle_delete(file_priv, obj->handle);
- + if (ret)
- + return ret;
- +
- + pxp_ht_remove_item(&bufhash, obj);
- + pxp_free_dma_buffer(obj);
- + kfree(obj);
- +
- + break;
- + }
- + case PXP_IOC_FLUSH_PHYMEM:
- + {
- + int ret;
- + struct pxp_mem_flush flush;
- + struct pxp_buf_obj *obj;
- +
- + ret = copy_from_user(&flush,
- + (struct pxp_mem_flush *)arg,
- + sizeof(struct pxp_mem_flush));
- + if (ret)
- + return -EACCES;
- +
- + obj = pxp_buffer_object_lookup(file_priv, flush.handle);
- + if (!obj)
- + return -EINVAL;
- +
- + switch (flush.type) {
- + case CACHE_CLEAN:
- + dma_sync_single_for_device(NULL, obj->offset,
- + obj->size, DMA_TO_DEVICE);
- + break;
- + case CACHE_INVALIDATE:
- + dma_sync_single_for_device(NULL, obj->offset,
- + obj->size, DMA_FROM_DEVICE);
- + break;
- + case CACHE_FLUSH:
- + dma_sync_single_for_device(NULL, obj->offset,
- + obj->size, DMA_TO_DEVICE);
- + dma_sync_single_for_device(NULL, obj->offset,
- + obj->size, DMA_FROM_DEVICE);
- + break;
- + default:
- + pr_err("%s: invalid cache flush type\n", __func__);
- + return -EINVAL;
- + }
- +
- + break;
- + }
- + case PXP_IOC_WAIT4CMPLT:
- + {
- + struct pxp_chan_handle chan_handle;
- + int ret, chan_id, handle;
- + struct pxp_chan_obj *obj = NULL;
- +
- + ret = copy_from_user(&chan_handle,
- + (struct pxp_chan_handle *)arg,
- + sizeof(struct pxp_chan_handle));
- + if (ret)
- + return -EFAULT;
- +
- + handle = chan_handle.handle;
- + obj = pxp_channel_object_lookup(file_priv, handle);
- + if (!obj)
- + return -EINVAL;
- + chan_id = obj->chan->chan_id;
- +
- + ret = wait_event_interruptible
- + (irq_info[chan_id].waitq,
- + (atomic_read(&irq_info[chan_id].irq_pending) == 0));
- + if (ret < 0) {
- + printk(KERN_WARNING
- + "WAIT4CMPLT: signal received.\n");
- + return -ERESTARTSYS;
- + }
- +
- + chan_handle.hist_status = irq_info[chan_id].hist_status;
- + ret = copy_to_user((struct pxp_chan_handle *)arg,
- + &chan_handle,
- + sizeof(struct pxp_chan_handle));
- + if (ret)
- + return -EFAULT;
- + break;
- + }
- + default:
- + break;
- + }
- +
- + return 0;
- +}
- +
- +static const struct file_operations pxp_device_fops = {
- + .open = pxp_device_open,
- + .release = pxp_device_release,
- + .unlocked_ioctl = pxp_device_ioctl,
- + .mmap = pxp_device_mmap,
- +};
- +
- +static struct miscdevice pxp_device_miscdev = {
- + .minor = MISC_DYNAMIC_MINOR,
- + .name = "pxp_device",
- + .fops = &pxp_device_fops,
- +};
- +
- +int register_pxp_device(void)
- +{
- + int ret;
- +
- + ret = misc_register(&pxp_device_miscdev);
- + if (ret)
- + return ret;
- +
- + ret = pxp_ht_create(&bufhash, BUFFER_HASH_ORDER);
- + if (ret)
- + return ret;
- + spin_lock_init(&(bufhash.hash_lock));
- +
- + pr_debug("PxP_Device registered Successfully\n");
- + return 0;
- +}
- +
- +void unregister_pxp_device(void)
- +{
- + pxp_ht_destroy(&bufhash);
- + misc_deregister(&pxp_device_miscdev);
- +}
- diff -Nur linux-3.14.35.orig/drivers/dma/pxp/pxp_dma_v2.c linux-3.14.35/drivers/dma/pxp/pxp_dma_v2.c
- --- linux-3.14.35.orig/drivers/dma/pxp/pxp_dma_v2.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/dma/pxp/pxp_dma_v2.c 2015-03-08 14:27:37.545684501 -0500
- @@ -0,0 +1,1854 @@
- +/*
- + * Copyright (C) 2010-2013 Freescale Semiconductor, 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + */
- +/*
- + * Based on STMP378X PxP driver
- + * Copyright 2008-2009 Embedded Alley Solutions, Inc All Rights Reserved.
- + */
- +
- +#include <linux/dma-mapping.h>
- +#include <linux/init.h>
- +#include <linux/interrupt.h>
- +#include <linux/io.h>
- +#include <linux/kernel.h>
- +#include <linux/module.h>
- +#include <linux/mutex.h>
- +#include <linux/platform_device.h>
- +#include <linux/slab.h>
- +#include <linux/vmalloc.h>
- +#include <linux/dmaengine.h>
- +#include <linux/pxp_dma.h>
- +#include <linux/timer.h>
- +#include <linux/clk.h>
- +#include <linux/workqueue.h>
- +#include <linux/sched.h>
- +#include <linux/of.h>
- +#include <linux/kthread.h>
- +
- +#include "regs-pxp_v2.h"
- +
- +#define PXP_DOWNSCALE_THRESHOLD 0x4000
- +
- +static LIST_HEAD(head);
- +static int timeout_in_ms = 600;
- +static unsigned int block_size;
- +static struct kmem_cache *tx_desc_cache;
- +
- +struct pxp_dma {
- + struct dma_device dma;
- +};
- +
- +struct pxps {
- + struct platform_device *pdev;
- + struct clk *clk;
- + void __iomem *base;
- + int irq; /* PXP IRQ to the CPU */
- +
- + spinlock_t lock;
- + struct mutex clk_mutex;
- + int clk_stat;
- +#define CLK_STAT_OFF 0
- +#define CLK_STAT_ON 1
- + int pxp_ongoing;
- + int lut_state;
- +
- + struct device *dev;
- + struct pxp_dma pxp_dma;
- + struct pxp_channel channel[NR_PXP_VIRT_CHANNEL];
- + struct work_struct work;
- +
- + /* describes most recent processing configuration */
- + struct pxp_config_data pxp_conf_state;
- +
- + /* to turn clock off when pxp is inactive */
- + struct timer_list clk_timer;
- +
- + /* for pxp config dispatch asynchronously*/
- + struct task_struct *dispatch;
- + wait_queue_head_t thread_waitq;
- + struct completion complete;
- +};
- +
- +#define to_pxp_dma(d) container_of(d, struct pxp_dma, dma)
- +#define to_tx_desc(tx) container_of(tx, struct pxp_tx_desc, txd)
- +#define to_pxp_channel(d) container_of(d, struct pxp_channel, dma_chan)
- +#define to_pxp(id) container_of(id, struct pxps, pxp_dma)
- +
- +#define PXP_DEF_BUFS 2
- +#define PXP_MIN_PIX 8
- +
- +static uint32_t pxp_s0_formats[] = {
- + PXP_PIX_FMT_RGB32,
- + PXP_PIX_FMT_RGB565,
- + PXP_PIX_FMT_RGB555,
- + PXP_PIX_FMT_YUV420P,
- + PXP_PIX_FMT_YUV422P,
- +};
- +
- +/*
- + * PXP common functions
- + */
- +static void dump_pxp_reg(struct pxps *pxp)
- +{
- + dev_dbg(pxp->dev, "PXP_CTRL 0x%x",
- + __raw_readl(pxp->base + HW_PXP_CTRL));
- + dev_dbg(pxp->dev, "PXP_STAT 0x%x",
- + __raw_readl(pxp->base + HW_PXP_STAT));
- + dev_dbg(pxp->dev, "PXP_OUT_CTRL 0x%x",
- + __raw_readl(pxp->base + HW_PXP_OUT_CTRL));
- + dev_dbg(pxp->dev, "PXP_OUT_BUF 0x%x",
- + __raw_readl(pxp->base + HW_PXP_OUT_BUF));
- + dev_dbg(pxp->dev, "PXP_OUT_BUF2 0x%x",
- + __raw_readl(pxp->base + HW_PXP_OUT_BUF2));
- + dev_dbg(pxp->dev, "PXP_OUT_PITCH 0x%x",
- + __raw_readl(pxp->base + HW_PXP_OUT_PITCH));
- + dev_dbg(pxp->dev, "PXP_OUT_LRC 0x%x",
- + __raw_readl(pxp->base + HW_PXP_OUT_LRC));
- + dev_dbg(pxp->dev, "PXP_OUT_PS_ULC 0x%x",
- + __raw_readl(pxp->base + HW_PXP_OUT_PS_ULC));
- + dev_dbg(pxp->dev, "PXP_OUT_PS_LRC 0x%x",
- + __raw_readl(pxp->base + HW_PXP_OUT_PS_LRC));
- + dev_dbg(pxp->dev, "PXP_OUT_AS_ULC 0x%x",
- + __raw_readl(pxp->base + HW_PXP_OUT_AS_ULC));
- + dev_dbg(pxp->dev, "PXP_OUT_AS_LRC 0x%x",
- + __raw_readl(pxp->base + HW_PXP_OUT_AS_LRC));
- + dev_dbg(pxp->dev, "PXP_PS_CTRL 0x%x",
- + __raw_readl(pxp->base + HW_PXP_PS_CTRL));
- + dev_dbg(pxp->dev, "PXP_PS_BUF 0x%x",
- + __raw_readl(pxp->base + HW_PXP_PS_BUF));
- + dev_dbg(pxp->dev, "PXP_PS_UBUF 0x%x",
- + __raw_readl(pxp->base + HW_PXP_PS_UBUF));
- + dev_dbg(pxp->dev, "PXP_PS_VBUF 0x%x",
- + __raw_readl(pxp->base + HW_PXP_PS_VBUF));
- + dev_dbg(pxp->dev, "PXP_PS_PITCH 0x%x",
- + __raw_readl(pxp->base + HW_PXP_PS_PITCH));
- + dev_dbg(pxp->dev, "PXP_PS_BACKGROUND 0x%x",
- + __raw_readl(pxp->base + HW_PXP_PS_BACKGROUND));
- + dev_dbg(pxp->dev, "PXP_PS_SCALE 0x%x",
- + __raw_readl(pxp->base + HW_PXP_PS_SCALE));
- + dev_dbg(pxp->dev, "PXP_PS_OFFSET 0x%x",
- + __raw_readl(pxp->base + HW_PXP_PS_OFFSET));
- + dev_dbg(pxp->dev, "PXP_PS_CLRKEYLOW 0x%x",
- + __raw_readl(pxp->base + HW_PXP_PS_CLRKEYLOW));
- + dev_dbg(pxp->dev, "PXP_PS_CLRKEYHIGH 0x%x",
- + __raw_readl(pxp->base + HW_PXP_PS_CLRKEYHIGH));
- + dev_dbg(pxp->dev, "PXP_AS_CTRL 0x%x",
- + __raw_readl(pxp->base + HW_PXP_AS_CTRL));
- + dev_dbg(pxp->dev, "PXP_AS_BUF 0x%x",
- + __raw_readl(pxp->base + HW_PXP_AS_BUF));
- + dev_dbg(pxp->dev, "PXP_AS_PITCH 0x%x",
- + __raw_readl(pxp->base + HW_PXP_AS_PITCH));
- + dev_dbg(pxp->dev, "PXP_AS_CLRKEYLOW 0x%x",
- + __raw_readl(pxp->base + HW_PXP_AS_CLRKEYLOW));
- + dev_dbg(pxp->dev, "PXP_AS_CLRKEYHIGH 0x%x",
- + __raw_readl(pxp->base + HW_PXP_AS_CLRKEYHIGH));
- + dev_dbg(pxp->dev, "PXP_CSC1_COEF0 0x%x",
- + __raw_readl(pxp->base + HW_PXP_CSC1_COEF0));
- + dev_dbg(pxp->dev, "PXP_CSC1_COEF1 0x%x",
- + __raw_readl(pxp->base + HW_PXP_CSC1_COEF1));
- + dev_dbg(pxp->dev, "PXP_CSC1_COEF2 0x%x",
- + __raw_readl(pxp->base + HW_PXP_CSC1_COEF2));
- + dev_dbg(pxp->dev, "PXP_CSC2_CTRL 0x%x",
- + __raw_readl(pxp->base + HW_PXP_CSC2_CTRL));
- + dev_dbg(pxp->dev, "PXP_CSC2_COEF0 0x%x",
- + __raw_readl(pxp->base + HW_PXP_CSC2_COEF0));
- + dev_dbg(pxp->dev, "PXP_CSC2_COEF1 0x%x",
- + __raw_readl(pxp->base + HW_PXP_CSC2_COEF1));
- + dev_dbg(pxp->dev, "PXP_CSC2_COEF2 0x%x",
- + __raw_readl(pxp->base + HW_PXP_CSC2_COEF2));
- + dev_dbg(pxp->dev, "PXP_CSC2_COEF3 0x%x",
- + __raw_readl(pxp->base + HW_PXP_CSC2_COEF3));
- + dev_dbg(pxp->dev, "PXP_CSC2_COEF4 0x%x",
- + __raw_readl(pxp->base + HW_PXP_CSC2_COEF4));
- + dev_dbg(pxp->dev, "PXP_CSC2_COEF5 0x%x",
- + __raw_readl(pxp->base + HW_PXP_CSC2_COEF5));
- + dev_dbg(pxp->dev, "PXP_LUT_CTRL 0x%x",
- + __raw_readl(pxp->base + HW_PXP_LUT_CTRL));
- + dev_dbg(pxp->dev, "PXP_LUT_ADDR 0x%x",
- + __raw_readl(pxp->base + HW_PXP_LUT_ADDR));
- + dev_dbg(pxp->dev, "PXP_LUT_DATA 0x%x",
- + __raw_readl(pxp->base + HW_PXP_LUT_DATA));
- + dev_dbg(pxp->dev, "PXP_LUT_EXTMEM 0x%x",
- + __raw_readl(pxp->base + HW_PXP_LUT_EXTMEM));
- + dev_dbg(pxp->dev, "PXP_CFA 0x%x",
- + __raw_readl(pxp->base + HW_PXP_CFA));
- + dev_dbg(pxp->dev, "PXP_HIST_CTRL 0x%x",
- + __raw_readl(pxp->base + HW_PXP_HIST_CTRL));
- + dev_dbg(pxp->dev, "PXP_HIST2_PARAM 0x%x",
- + __raw_readl(pxp->base + HW_PXP_HIST2_PARAM));
- + dev_dbg(pxp->dev, "PXP_HIST4_PARAM 0x%x",
- + __raw_readl(pxp->base + HW_PXP_HIST4_PARAM));
- + dev_dbg(pxp->dev, "PXP_HIST8_PARAM0 0x%x",
- + __raw_readl(pxp->base + HW_PXP_HIST8_PARAM0));
- + dev_dbg(pxp->dev, "PXP_HIST8_PARAM1 0x%x",
- + __raw_readl(pxp->base + HW_PXP_HIST8_PARAM1));
- + dev_dbg(pxp->dev, "PXP_HIST16_PARAM0 0x%x",
- + __raw_readl(pxp->base + HW_PXP_HIST16_PARAM0));
- + dev_dbg(pxp->dev, "PXP_HIST16_PARAM1 0x%x",
- + __raw_readl(pxp->base + HW_PXP_HIST16_PARAM1));
- + dev_dbg(pxp->dev, "PXP_HIST16_PARAM2 0x%x",
- + __raw_readl(pxp->base + HW_PXP_HIST16_PARAM2));
- + dev_dbg(pxp->dev, "PXP_HIST16_PARAM3 0x%x",
- + __raw_readl(pxp->base + HW_PXP_HIST16_PARAM3));
- + dev_dbg(pxp->dev, "PXP_POWER 0x%x",
- + __raw_readl(pxp->base + HW_PXP_POWER));
- + dev_dbg(pxp->dev, "PXP_NEXT 0x%x",
- + __raw_readl(pxp->base + HW_PXP_NEXT));
- + dev_dbg(pxp->dev, "PXP_DEBUGCTRL 0x%x",
- + __raw_readl(pxp->base + HW_PXP_DEBUGCTRL));
- + dev_dbg(pxp->dev, "PXP_DEBUG 0x%x",
- + __raw_readl(pxp->base + HW_PXP_DEBUG));
- + dev_dbg(pxp->dev, "PXP_VERSION 0x%x",
- + __raw_readl(pxp->base + HW_PXP_VERSION));
- +}
- +
- +static bool is_yuv(u32 pix_fmt)
- +{
- + if ((pix_fmt == PXP_PIX_FMT_YUYV) |
- + (pix_fmt == PXP_PIX_FMT_UYVY) |
- + (pix_fmt == PXP_PIX_FMT_YVYU) |
- + (pix_fmt == PXP_PIX_FMT_VYUY) |
- + (pix_fmt == PXP_PIX_FMT_Y41P) |
- + (pix_fmt == PXP_PIX_FMT_YUV444) |
- + (pix_fmt == PXP_PIX_FMT_NV12) |
- + (pix_fmt == PXP_PIX_FMT_NV16) |
- + (pix_fmt == PXP_PIX_FMT_NV61) |
- + (pix_fmt == PXP_PIX_FMT_GREY) |
- + (pix_fmt == PXP_PIX_FMT_GY04) |
- + (pix_fmt == PXP_PIX_FMT_YVU410P) |
- + (pix_fmt == PXP_PIX_FMT_YUV410P) |
- + (pix_fmt == PXP_PIX_FMT_YVU420P) |
- + (pix_fmt == PXP_PIX_FMT_YUV420P) |
- + (pix_fmt == PXP_PIX_FMT_YUV420P2) |
- + (pix_fmt == PXP_PIX_FMT_YVU422P) |
- + (pix_fmt == PXP_PIX_FMT_YUV422P)) {
- + return true;
- + } else {
- + return false;
- + }
- +}
- +
- +static void pxp_set_ctrl(struct pxps *pxp)
- +{
- + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
- + struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
- + u32 ctrl;
- + u32 fmt_ctrl;
- + int need_swap = 0; /* to support YUYV and YVYU formats */
- +
- + /* Configure S0 input format */
- + switch (pxp_conf->s0_param.pixel_fmt) {
- + case PXP_PIX_FMT_RGB32:
- + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB888;
- + break;
- + case PXP_PIX_FMT_RGB565:
- + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB565;
- + break;
- + case PXP_PIX_FMT_RGB555:
- + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB555;
- + break;
- + case PXP_PIX_FMT_YUV420P:
- + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420;
- + break;
- + case PXP_PIX_FMT_YVU420P:
- + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420;
- + break;
- + case PXP_PIX_FMT_GREY:
- + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y8;
- + break;
- + case PXP_PIX_FMT_GY04:
- + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y4;
- + break;
- + case PXP_PIX_FMT_YUV422P:
- + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV422;
- + break;
- + case PXP_PIX_FMT_UYVY:
- + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
- + break;
- + case PXP_PIX_FMT_YUYV:
- + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
- + need_swap = 1;
- + break;
- + case PXP_PIX_FMT_VYUY:
- + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
- + break;
- + case PXP_PIX_FMT_YVYU:
- + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
- + need_swap = 1;
- + break;
- + case PXP_PIX_FMT_NV12:
- + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P420;
- + break;
- + case PXP_PIX_FMT_NV21:
- + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P420;
- + break;
- + case PXP_PIX_FMT_NV16:
- + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P422;
- + break;
- + case PXP_PIX_FMT_NV61:
- + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P422;
- + break;
- + default:
- + fmt_ctrl = 0;
- + }
- +
- + ctrl = BF_PXP_PS_CTRL_FORMAT(fmt_ctrl) | BF_PXP_PS_CTRL_SWAP(need_swap);
- + __raw_writel(ctrl, pxp->base + HW_PXP_PS_CTRL_SET);
- +
- + /* Configure output format based on out_channel format */
- + switch (pxp_conf->out_param.pixel_fmt) {
- + case PXP_PIX_FMT_RGB32:
- + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888;
- + break;
- + case PXP_PIX_FMT_BGRA32:
- + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__ARGB8888;
- + break;
- + case PXP_PIX_FMT_RGB24:
- + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888P;
- + break;
- + case PXP_PIX_FMT_RGB565:
- + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB565;
- + break;
- + case PXP_PIX_FMT_RGB555:
- + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB555;
- + break;
- + case PXP_PIX_FMT_GREY:
- + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y8;
- + break;
- + case PXP_PIX_FMT_GY04:
- + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y4;
- + break;
- + case PXP_PIX_FMT_UYVY:
- + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__UYVY1P422;
- + break;
- + case PXP_PIX_FMT_VYUY:
- + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__VYUY1P422;
- + break;
- + case PXP_PIX_FMT_NV12:
- + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P420;
- + break;
- + case PXP_PIX_FMT_NV21:
- + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P420;
- + break;
- + case PXP_PIX_FMT_NV16:
- + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P422;
- + break;
- + case PXP_PIX_FMT_NV61:
- + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P422;
- + break;
- + default:
- + fmt_ctrl = 0;
- + }
- +
- + ctrl = BF_PXP_OUT_CTRL_FORMAT(fmt_ctrl);
- + __raw_writel(ctrl, pxp->base + HW_PXP_OUT_CTRL);
- +
- + ctrl = 0;
- + if (proc_data->scaling)
- + ;
- + if (proc_data->vflip)
- + ctrl |= BM_PXP_CTRL_VFLIP;
- + if (proc_data->hflip)
- + ctrl |= BM_PXP_CTRL_HFLIP;
- + if (proc_data->rotate) {
- + ctrl |= BF_PXP_CTRL_ROTATE(proc_data->rotate / 90);
- + if (proc_data->rot_pos)
- + ctrl |= BM_PXP_CTRL_ROT_POS;
- + }
- +
- + /* In default, the block size is set to 8x8
- + * But block size can be set to 16x16 due to
- + * blocksize variable modification
- + */
- + ctrl |= block_size << 23;
- +
- + __raw_writel(ctrl, pxp->base + HW_PXP_CTRL);
- +}
- +
- +static int pxp_start(struct pxps *pxp)
- +{
- + __raw_writel(BM_PXP_CTRL_IRQ_ENABLE, pxp->base + HW_PXP_CTRL_SET);
- + __raw_writel(BM_PXP_CTRL_ENABLE, pxp->base + HW_PXP_CTRL_SET);
- + dump_pxp_reg(pxp);
- +
- + return 0;
- +}
- +
- +static void pxp_set_outbuf(struct pxps *pxp)
- +{
- + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
- + struct pxp_layer_param *out_params = &pxp_conf->out_param;
- +
- + __raw_writel(out_params->paddr, pxp->base + HW_PXP_OUT_BUF);
- +
- + __raw_writel(BF_PXP_OUT_LRC_X(out_params->width - 1) |
- + BF_PXP_OUT_LRC_Y(out_params->height - 1),
- + pxp->base + HW_PXP_OUT_LRC);
- +
- + if (out_params->pixel_fmt == PXP_PIX_FMT_RGB24) {
- + __raw_writel(out_params->stride * 3,
- + pxp->base + HW_PXP_OUT_PITCH);
- + } else if (out_params->pixel_fmt == PXP_PIX_FMT_BGRA32 ||
- + out_params->pixel_fmt == PXP_PIX_FMT_RGB32) {
- + __raw_writel(out_params->stride << 2,
- + pxp->base + HW_PXP_OUT_PITCH);
- + } else if (out_params->pixel_fmt == PXP_PIX_FMT_RGB565) {
- + __raw_writel(out_params->stride << 1,
- + pxp->base + HW_PXP_OUT_PITCH);
- + } else if (out_params->pixel_fmt == PXP_PIX_FMT_UYVY ||
- + (out_params->pixel_fmt == PXP_PIX_FMT_VYUY)) {
- + __raw_writel(out_params->stride << 1,
- + pxp->base + HW_PXP_OUT_PITCH);
- + } else if (out_params->pixel_fmt == PXP_PIX_FMT_GREY ||
- + out_params->pixel_fmt == PXP_PIX_FMT_NV12 ||
- + out_params->pixel_fmt == PXP_PIX_FMT_NV21 ||
- + out_params->pixel_fmt == PXP_PIX_FMT_NV16 ||
- + out_params->pixel_fmt == PXP_PIX_FMT_NV61) {
- + __raw_writel(out_params->stride,
- + pxp->base + HW_PXP_OUT_PITCH);
- + } else if (out_params->pixel_fmt == PXP_PIX_FMT_GY04) {
- + __raw_writel(out_params->stride >> 1,
- + pxp->base + HW_PXP_OUT_PITCH);
- + } else {
- + __raw_writel(0, pxp->base + HW_PXP_OUT_PITCH);
- + }
- +
- + /* set global alpha if necessary */
- + if (out_params->global_alpha_enable) {
- + __raw_writel(out_params->global_alpha << 24,
- + pxp->base + HW_PXP_OUT_CTRL_SET);
- + __raw_writel(BM_PXP_OUT_CTRL_ALPHA_OUTPUT,
- + pxp->base + HW_PXP_OUT_CTRL_SET);
- + }
- +}
- +
- +static void pxp_set_s0colorkey(struct pxps *pxp)
- +{
- + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
- + struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
- +
- + /* Low and high are set equal. V4L does not allow a chromakey range */
- + if (s0_params->color_key_enable == 0 || s0_params->color_key == -1) {
- + /* disable color key */
- + __raw_writel(0xFFFFFF, pxp->base + HW_PXP_PS_CLRKEYLOW);
- + __raw_writel(0, pxp->base + HW_PXP_PS_CLRKEYHIGH);
- + } else {
- + __raw_writel(s0_params->color_key,
- + pxp->base + HW_PXP_PS_CLRKEYLOW);
- + __raw_writel(s0_params->color_key,
- + pxp->base + HW_PXP_PS_CLRKEYHIGH);
- + }
- +}
- +
- +static void pxp_set_olcolorkey(int layer_no, struct pxps *pxp)
- +{
- + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
- + struct pxp_layer_param *ol_params = &pxp_conf->ol_param[layer_no];
- +
- + /* Low and high are set equal. V4L does not allow a chromakey range */
- + if (ol_params->color_key_enable != 0 && ol_params->color_key != -1) {
- + __raw_writel(ol_params->color_key,
- + pxp->base + HW_PXP_AS_CLRKEYLOW);
- + __raw_writel(ol_params->color_key,
- + pxp->base + HW_PXP_AS_CLRKEYHIGH);
- + } else {
- + /* disable color key */
- + __raw_writel(0xFFFFFF, pxp->base + HW_PXP_AS_CLRKEYLOW);
- + __raw_writel(0, pxp->base + HW_PXP_AS_CLRKEYHIGH);
- + }
- +}
- +
- +static void pxp_set_oln(int layer_no, struct pxps *pxp)
- +{
- + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
- + struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no];
- + dma_addr_t phys_addr = olparams_data->paddr;
- + u32 pitch = olparams_data->stride ? olparams_data->stride :
- + olparams_data->width;
- +
- + __raw_writel(phys_addr, pxp->base + HW_PXP_AS_BUF);
- +
- + /* Fixme */
- + if (olparams_data->width == 0 && olparams_data->height == 0) {
- + __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_AS_ULC);
- + __raw_writel(0x0, pxp->base + HW_PXP_OUT_AS_LRC);
- + } else {
- + __raw_writel(0x0, pxp->base + HW_PXP_OUT_AS_ULC);
- + if (pxp_conf->proc_data.rotate == 90 ||
- + pxp_conf->proc_data.rotate == 270) {
- + if (pxp_conf->proc_data.rot_pos == 1) {
- + __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->height - 1) |
- + BF_PXP_OUT_AS_LRC_Y(olparams_data->width - 1),
- + pxp->base + HW_PXP_OUT_AS_LRC);
- + } else {
- + __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->width - 1) |
- + BF_PXP_OUT_AS_LRC_Y(olparams_data->height - 1),
- + pxp->base + HW_PXP_OUT_AS_LRC);
- + }
- + } else {
- + __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->width - 1) |
- + BF_PXP_OUT_AS_LRC_Y(olparams_data->height - 1),
- + pxp->base + HW_PXP_OUT_AS_LRC);
- + }
- + }
- +
- + if ((olparams_data->pixel_fmt == PXP_PIX_FMT_BGRA32) |
- + (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB32)) {
- + __raw_writel(pitch << 2,
- + pxp->base + HW_PXP_AS_PITCH);
- + } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB565) {
- + __raw_writel(pitch << 1,
- + pxp->base + HW_PXP_AS_PITCH);
- + } else {
- + __raw_writel(0, pxp->base + HW_PXP_AS_PITCH);
- + }
- +}
- +
- +static void pxp_set_olparam(int layer_no, struct pxps *pxp)
- +{
- + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
- + struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no];
- + u32 olparam;
- +
- + olparam = BF_PXP_AS_CTRL_ALPHA(olparams_data->global_alpha);
- + if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB32) {
- + olparam |=
- + BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB888);
- + } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_BGRA32) {
- + olparam |=
- + BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__ARGB8888);
- + if (!olparams_data->combine_enable) {
- + olparam |=
- + BF_PXP_AS_CTRL_ALPHA_CTRL
- + (BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs);
- + olparam |= 0x3 << 16;
- + }
- + } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB565) {
- + olparam |=
- + BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB565);
- + }
- + if (olparams_data->global_alpha_enable) {
- + if (olparams_data->global_override) {
- + olparam |=
- + BF_PXP_AS_CTRL_ALPHA_CTRL
- + (BV_PXP_AS_CTRL_ALPHA_CTRL__Override);
- + } else {
- + olparam |=
- + BF_PXP_AS_CTRL_ALPHA_CTRL
- + (BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply);
- + }
- + if (olparams_data->alpha_invert)
- + olparam |= BM_PXP_AS_CTRL_ALPHA_INVERT;
- + }
- + if (olparams_data->color_key_enable)
- + olparam |= BM_PXP_AS_CTRL_ENABLE_COLORKEY;
- +
- + __raw_writel(olparam, pxp->base + HW_PXP_AS_CTRL);
- +}
- +
- +static void pxp_set_s0param(struct pxps *pxp)
- +{
- + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
- + struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
- + u32 s0param;
- +
- + /* contains the coordinate for the PS in the OUTPUT buffer. */
- + if ((pxp_conf->s0_param).width == 0 &&
- + (pxp_conf->s0_param).height == 0) {
- + __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_PS_ULC);
- + __raw_writel(0x0, pxp->base + HW_PXP_OUT_PS_LRC);
- + } else {
- + s0param = BF_PXP_OUT_PS_ULC_X(proc_data->drect.left);
- + s0param |= BF_PXP_OUT_PS_ULC_Y(proc_data->drect.top);
- + __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_ULC);
- + s0param = BF_PXP_OUT_PS_LRC_X(proc_data->drect.left +
- + proc_data->drect.width - 1);
- + s0param |= BF_PXP_OUT_PS_LRC_Y(proc_data->drect.top +
- + proc_data->drect.height - 1);
- + __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_LRC);
- + }
- +}
- +
- +/* crop behavior is re-designed in h/w. */
- +static void pxp_set_s0crop(struct pxps *pxp)
- +{
- + /*
- + * place-holder, it's implemented in other functions in this driver.
- + * Refer to "Clipping source images" section in RM for detail.
- + */
- +}
- +
- +static int pxp_set_scaling(struct pxps *pxp)
- +{
- + int ret = 0;
- + u32 xscale, yscale, s0scale;
- + u32 decx, decy, xdec = 0, ydec = 0;
- + struct pxp_proc_data *proc_data = &pxp->pxp_conf_state.proc_data;
- +
- + if (((proc_data->srect.width == proc_data->drect.width) &&
- + (proc_data->srect.height == proc_data->drect.height)) ||
- + ((proc_data->srect.width == 0) && (proc_data->srect.height == 0))) {
- + proc_data->scaling = 0;
- + __raw_writel(0x10001000, pxp->base + HW_PXP_PS_SCALE);
- + __raw_writel(0, pxp->base + HW_PXP_PS_CTRL);
- + goto out;
- + }
- +
- + proc_data->scaling = 1;
- + decx = proc_data->srect.width / proc_data->drect.width;
- + decy = proc_data->srect.height / proc_data->drect.height;
- + if (decx > 0) {
- + if (decx >= 2 && decx < 4) {
- + decx = 2;
- + xdec = 1;
- + } else if (decx >= 4 && decx < 8) {
- + decx = 4;
- + xdec = 2;
- + } else if (decx >= 8) {
- + decx = 8;
- + xdec = 3;
- + }
- + xscale = proc_data->srect.width * 0x1000 /
- + (proc_data->drect.width * decx);
- + } else
- + xscale = proc_data->srect.width * 0x1000 /
- + proc_data->drect.width;
- + if (decy > 0) {
- + if (decy >= 2 && decy < 4) {
- + decy = 2;
- + ydec = 1;
- + } else if (decy >= 4 && decy < 8) {
- + decy = 4;
- + ydec = 2;
- + } else if (decy >= 8) {
- + decy = 8;
- + ydec = 3;
- + }
- + yscale = proc_data->srect.height * 0x1000 /
- + (proc_data->drect.height * decy);
- + } else
- + yscale = proc_data->srect.height * 0x1000 /
- + proc_data->drect.height;
- +
- + __raw_writel((xdec << 10) | (ydec << 8), pxp->base + HW_PXP_PS_CTRL);
- +
- + if (xscale > PXP_DOWNSCALE_THRESHOLD)
- + xscale = PXP_DOWNSCALE_THRESHOLD;
- + if (yscale > PXP_DOWNSCALE_THRESHOLD)
- + yscale = PXP_DOWNSCALE_THRESHOLD;
- + s0scale = BF_PXP_PS_SCALE_YSCALE(yscale) |
- + BF_PXP_PS_SCALE_XSCALE(xscale);
- + __raw_writel(s0scale, pxp->base + HW_PXP_PS_SCALE);
- +
- +out:
- + pxp_set_ctrl(pxp);
- +
- + return ret;
- +}
- +
- +static void pxp_set_bg(struct pxps *pxp)
- +{
- + __raw_writel(pxp->pxp_conf_state.proc_data.bgcolor,
- + pxp->base + HW_PXP_PS_BACKGROUND);
- +}
- +
- +static void pxp_set_lut(struct pxps *pxp)
- +{
- + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
- + int lut_op = pxp_conf->proc_data.lut_transform;
- + u32 reg_val;
- + int i;
- + bool use_cmap = (lut_op & PXP_LUT_USE_CMAP) ? true : false;
- + u8 *cmap = pxp_conf->proc_data.lut_map;
- + u32 entry_src;
- + u32 pix_val;
- + u8 entry[4];
- +
- + /*
- + * If LUT already configured as needed, return...
- + * Unless CMAP is needed and it has been updated.
- + */
- + if ((pxp->lut_state == lut_op) &&
- + !(use_cmap && pxp_conf->proc_data.lut_map_updated))
- + return;
- +
- + if (lut_op == PXP_LUT_NONE) {
- + __raw_writel(BM_PXP_LUT_CTRL_BYPASS,
- + pxp->base + HW_PXP_LUT_CTRL);
- + } else if (((lut_op & PXP_LUT_INVERT) != 0)
- + && ((lut_op & PXP_LUT_BLACK_WHITE) != 0)) {
- + /* Fill out LUT table with inverted monochromized values */
- +
- + /* clear bypass bit, set lookup mode & out mode */
- + __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
- + (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
- + BF_PXP_LUT_CTRL_OUT_MODE
- + (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
- + pxp->base + HW_PXP_LUT_CTRL);
- +
- + /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
- + __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
- +
- + /* LUT address pointer auto-increments after each data write */
- + for (pix_val = 0; pix_val < 256; pix_val += 4) {
- + for (i = 0; i < 4; i++) {
- + entry_src = use_cmap ?
- + cmap[pix_val + i] : pix_val + i;
- + entry[i] = (entry_src < 0x80) ? 0xFF : 0x00;
- + }
- + reg_val = (entry[3] << 24) | (entry[2] << 16) |
- + (entry[1] << 8) | entry[0];
- + __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
- + }
- + } else if ((lut_op & PXP_LUT_INVERT) != 0) {
- + /* Fill out LUT table with 8-bit inverted values */
- +
- + /* clear bypass bit, set lookup mode & out mode */
- + __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
- + (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
- + BF_PXP_LUT_CTRL_OUT_MODE
- + (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
- + pxp->base + HW_PXP_LUT_CTRL);
- +
- + /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
- + __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
- +
- + /* LUT address pointer auto-increments after each data write */
- + for (pix_val = 0; pix_val < 256; pix_val += 4) {
- + for (i = 0; i < 4; i++) {
- + entry_src = use_cmap ?
- + cmap[pix_val + i] : pix_val + i;
- + entry[i] = ~entry_src & 0xFF;
- + }
- + reg_val = (entry[3] << 24) | (entry[2] << 16) |
- + (entry[1] << 8) | entry[0];
- + __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
- + }
- + } else if ((lut_op & PXP_LUT_BLACK_WHITE) != 0) {
- + /* Fill out LUT table with 8-bit monochromized values */
- +
- + /* clear bypass bit, set lookup mode & out mode */
- + __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
- + (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
- + BF_PXP_LUT_CTRL_OUT_MODE
- + (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
- + pxp->base + HW_PXP_LUT_CTRL);
- +
- + /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
- + __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
- +
- + /* LUT address pointer auto-increments after each data write */
- + for (pix_val = 0; pix_val < 256; pix_val += 4) {
- + for (i = 0; i < 4; i++) {
- + entry_src = use_cmap ?
- + cmap[pix_val + i] : pix_val + i;
- + entry[i] = (entry_src < 0x80) ? 0x00 : 0xFF;
- + }
- + reg_val = (entry[3] << 24) | (entry[2] << 16) |
- + (entry[1] << 8) | entry[0];
- + __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
- + }
- + } else if (use_cmap) {
- + /* Fill out LUT table using colormap values */
- +
- + /* clear bypass bit, set lookup mode & out mode */
- + __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
- + (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
- + BF_PXP_LUT_CTRL_OUT_MODE
- + (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
- + pxp->base + HW_PXP_LUT_CTRL);
- +
- + /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
- + __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
- +
- + /* LUT address pointer auto-increments after each data write */
- + for (pix_val = 0; pix_val < 256; pix_val += 4) {
- + for (i = 0; i < 4; i++)
- + entry[i] = cmap[pix_val + i];
- + reg_val = (entry[3] << 24) | (entry[2] << 16) |
- + (entry[1] << 8) | entry[0];
- + __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
- + }
- + }
- +
- + pxp->lut_state = lut_op;
- +}
- +
- +static void pxp_set_csc(struct pxps *pxp)
- +{
- + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
- + struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
- + struct pxp_layer_param *ol_params = &pxp_conf->ol_param[0];
- + struct pxp_layer_param *out_params = &pxp_conf->out_param;
- +
- + bool input_is_YUV = is_yuv(s0_params->pixel_fmt);
- + bool output_is_YUV = is_yuv(out_params->pixel_fmt);
- +
- + if (input_is_YUV && output_is_YUV) {
- + /*
- + * Input = YUV, Output = YUV
- + * No CSC unless we need to do combining
- + */
- + if (ol_params->combine_enable) {
- + /* Must convert to RGB for combining with RGB overlay */
- +
- + /* CSC1 - YUV->RGB */
- + __raw_writel(0x04030000, pxp->base + HW_PXP_CSC1_COEF0);
- + __raw_writel(0x01230208, pxp->base + HW_PXP_CSC1_COEF1);
- + __raw_writel(0x076b079c, pxp->base + HW_PXP_CSC1_COEF2);
- +
- + /* CSC2 - RGB->YUV */
- + __raw_writel(0x4, pxp->base + HW_PXP_CSC2_CTRL);
- + __raw_writel(0x0096004D, pxp->base + HW_PXP_CSC2_COEF0);
- + __raw_writel(0x05DA001D, pxp->base + HW_PXP_CSC2_COEF1);
- + __raw_writel(0x007005B6, pxp->base + HW_PXP_CSC2_COEF2);
- + __raw_writel(0x057C009E, pxp->base + HW_PXP_CSC2_COEF3);
- + __raw_writel(0x000005E6, pxp->base + HW_PXP_CSC2_COEF4);
- + __raw_writel(0x00000000, pxp->base + HW_PXP_CSC2_COEF5);
- + } else {
- + /* Input & Output both YUV, so bypass both CSCs */
- +
- + /* CSC1 - Bypass */
- + __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
- +
- + /* CSC2 - Bypass */
- + __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
- + }
- + } else if (input_is_YUV && !output_is_YUV) {
- + /*
- + * Input = YUV, Output = RGB
- + * Use CSC1 to convert to RGB
- + */
- +
- + /* CSC1 - YUV->RGB */
- + __raw_writel(0x84ab01f0, pxp->base + HW_PXP_CSC1_COEF0);
- + __raw_writel(0x01980204, pxp->base + HW_PXP_CSC1_COEF1);
- + __raw_writel(0x0730079c, pxp->base + HW_PXP_CSC1_COEF2);
- +
- + /* CSC2 - Bypass */
- + __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
- + } else if (!input_is_YUV && output_is_YUV) {
- + /*
- + * Input = RGB, Output = YUV
- + * Use CSC2 to convert to YUV
- + */
- +
- + /* CSC1 - Bypass */
- + __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
- +
- + /* CSC2 - RGB->YUV */
- + __raw_writel(0x4, pxp->base + HW_PXP_CSC2_CTRL);
- + __raw_writel(0x0096004D, pxp->base + HW_PXP_CSC2_COEF0);
- + __raw_writel(0x05DA001D, pxp->base + HW_PXP_CSC2_COEF1);
- + __raw_writel(0x007005B6, pxp->base + HW_PXP_CSC2_COEF2);
- + __raw_writel(0x057C009E, pxp->base + HW_PXP_CSC2_COEF3);
- + __raw_writel(0x000005E6, pxp->base + HW_PXP_CSC2_COEF4);
- + __raw_writel(0x00000000, pxp->base + HW_PXP_CSC2_COEF5);
- + } else {
- + /*
- + * Input = RGB, Output = RGB
- + * Input & Output both RGB, so bypass both CSCs
- + */
- +
- + /* CSC1 - Bypass */
- + __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
- +
- + /* CSC2 - Bypass */
- + __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
- + }
- +
- + /* YCrCb colorspace */
- + /* Not sure when we use this...no YCrCb formats are defined for PxP */
- + /*
- + __raw_writel(0x84ab01f0, HW_PXP_CSCCOEFF0_ADDR);
- + __raw_writel(0x01230204, HW_PXP_CSCCOEFF1_ADDR);
- + __raw_writel(0x0730079c, HW_PXP_CSCCOEFF2_ADDR);
- + */
- +
- +}
- +
- +static void pxp_set_s0buf(struct pxps *pxp)
- +{
- + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
- + struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
- + struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
- + dma_addr_t Y, U, V;
- + dma_addr_t Y1, U1, V1;
- + u32 offset, bpp = 1;
- + u32 pitch = s0_params->stride ? s0_params->stride :
- + s0_params->width;
- +
- + Y = s0_params->paddr;
- +
- + if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB565)
- + bpp = 2;
- + else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB32)
- + bpp = 4;
- + offset = (proc_data->srect.top * s0_params->width +
- + proc_data->srect.left) * bpp;
- + /* clipping or cropping */
- + Y1 = Y + offset;
- + __raw_writel(Y1, pxp->base + HW_PXP_PS_BUF);
- + if ((s0_params->pixel_fmt == PXP_PIX_FMT_YUV420P) ||
- + (s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P) ||
- + (s0_params->pixel_fmt == PXP_PIX_FMT_GREY) ||
- + (s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P)) {
- + /* Set to 1 if YUV format is 4:2:2 rather than 4:2:0 */
- + int s = 2;
- + if (s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P)
- + s = 1;
- +
- + offset = proc_data->srect.top * s0_params->width / 4 +
- + proc_data->srect.left / 2;
- + U = Y + (s0_params->width * s0_params->height);
- + U1 = U + offset;
- + V = U + ((s0_params->width * s0_params->height) >> s);
- + V1 = V + offset;
- + if (s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P) {
- + __raw_writel(V1, pxp->base + HW_PXP_PS_UBUF);
- + __raw_writel(U1, pxp->base + HW_PXP_PS_VBUF);
- + } else {
- + __raw_writel(U1, pxp->base + HW_PXP_PS_UBUF);
- + __raw_writel(V1, pxp->base + HW_PXP_PS_VBUF);
- + }
- + } else if ((s0_params->pixel_fmt == PXP_PIX_FMT_NV12) ||
- + (s0_params->pixel_fmt == PXP_PIX_FMT_NV21) ||
- + (s0_params->pixel_fmt == PXP_PIX_FMT_NV16) ||
- + (s0_params->pixel_fmt == PXP_PIX_FMT_NV61)) {
- + int s = 2;
- + if ((s0_params->pixel_fmt == PXP_PIX_FMT_NV16) ||
- + (s0_params->pixel_fmt == PXP_PIX_FMT_NV61))
- + s = 1;
- +
- + offset = (proc_data->srect.top * s0_params->width +
- + proc_data->srect.left) / s;
- + U = Y + (s0_params->width * s0_params->height);
- + U1 = U + offset;
- +
- + __raw_writel(U1, pxp->base + HW_PXP_PS_UBUF);
- + }
- +
- + /* TODO: only support RGB565, Y8, Y4, YUV420 */
- + if (s0_params->pixel_fmt == PXP_PIX_FMT_GREY ||
- + s0_params->pixel_fmt == PXP_PIX_FMT_YUV420P ||
- + s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P ||
- + s0_params->pixel_fmt == PXP_PIX_FMT_NV12 ||
- + s0_params->pixel_fmt == PXP_PIX_FMT_NV21 ||
- + s0_params->pixel_fmt == PXP_PIX_FMT_NV16 ||
- + s0_params->pixel_fmt == PXP_PIX_FMT_NV61 ||
- + s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P) {
- + __raw_writel(pitch, pxp->base + HW_PXP_PS_PITCH);
- + }
- + else if (s0_params->pixel_fmt == PXP_PIX_FMT_GY04)
- + __raw_writel(pitch >> 1,
- + pxp->base + HW_PXP_PS_PITCH);
- + else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB32)
- + __raw_writel(pitch << 2,
- + pxp->base + HW_PXP_PS_PITCH);
- + else if (s0_params->pixel_fmt == PXP_PIX_FMT_UYVY ||
- + s0_params->pixel_fmt == PXP_PIX_FMT_YUYV ||
- + s0_params->pixel_fmt == PXP_PIX_FMT_VYUY ||
- + s0_params->pixel_fmt == PXP_PIX_FMT_YVYU)
- + __raw_writel(pitch << 1,
- + pxp->base + HW_PXP_PS_PITCH);
- + else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB565)
- + __raw_writel(pitch << 1,
- + pxp->base + HW_PXP_PS_PITCH);
- + else
- + __raw_writel(0, pxp->base + HW_PXP_PS_PITCH);
- +}
- +
- +/**
- + * pxp_config() - configure PxP for a processing task
- + * @pxps: PXP context.
- + * @pxp_chan: PXP channel.
- + * @return: 0 on success or negative error code on failure.
- + */
- +static int pxp_config(struct pxps *pxp, struct pxp_channel *pxp_chan)
- +{
- + struct pxp_config_data *pxp_conf_data = &pxp->pxp_conf_state;
- + int ol_nr;
- + int i;
- +
- + /* Configure PxP regs */
- + pxp_set_ctrl(pxp);
- + pxp_set_s0param(pxp);
- + pxp_set_s0crop(pxp);
- + pxp_set_scaling(pxp);
- + ol_nr = pxp_conf_data->layer_nr - 2;
- + while (ol_nr > 0) {
- + i = pxp_conf_data->layer_nr - 2 - ol_nr;
- + pxp_set_oln(i, pxp);
- + pxp_set_olparam(i, pxp);
- + /* only the color key in higher overlay will take effect. */
- + pxp_set_olcolorkey(i, pxp);
- + ol_nr--;
- + }
- + pxp_set_s0colorkey(pxp);
- + pxp_set_csc(pxp);
- + pxp_set_bg(pxp);
- + pxp_set_lut(pxp);
- +
- + pxp_set_s0buf(pxp);
- + pxp_set_outbuf(pxp);
- +
- + return 0;
- +}
- +
- +static void pxp_clk_enable(struct pxps *pxp)
- +{
- + mutex_lock(&pxp->clk_mutex);
- +
- + if (pxp->clk_stat == CLK_STAT_ON) {
- + mutex_unlock(&pxp->clk_mutex);
- + return;
- + }
- +
- + clk_prepare_enable(pxp->clk);
- + pxp->clk_stat = CLK_STAT_ON;
- +
- + mutex_unlock(&pxp->clk_mutex);
- +}
- +
- +static void pxp_clk_disable(struct pxps *pxp)
- +{
- + unsigned long flags;
- +
- + mutex_lock(&pxp->clk_mutex);
- +
- + if (pxp->clk_stat == CLK_STAT_OFF) {
- + mutex_unlock(&pxp->clk_mutex);
- + return;
- + }
- +
- + spin_lock_irqsave(&pxp->lock, flags);
- + if ((pxp->pxp_ongoing == 0) && list_empty(&head)) {
- + spin_unlock_irqrestore(&pxp->lock, flags);
- + clk_disable_unprepare(pxp->clk);
- + pxp->clk_stat = CLK_STAT_OFF;
- + } else
- + spin_unlock_irqrestore(&pxp->lock, flags);
- +
- + mutex_unlock(&pxp->clk_mutex);
- +}
- +
- +static inline void clkoff_callback(struct work_struct *w)
- +{
- + struct pxps *pxp = container_of(w, struct pxps, work);
- +
- + pxp_clk_disable(pxp);
- +}
- +
- +static void pxp_clkoff_timer(unsigned long arg)
- +{
- + struct pxps *pxp = (struct pxps *)arg;
- +
- + if ((pxp->pxp_ongoing == 0) && list_empty(&head))
- + schedule_work(&pxp->work);
- + else
- + mod_timer(&pxp->clk_timer,
- + jiffies + msecs_to_jiffies(timeout_in_ms));
- +}
- +
- +static struct pxp_tx_desc *pxpdma_first_queued(struct pxp_channel *pxp_chan)
- +{
- + return list_entry(pxp_chan->queue.next, struct pxp_tx_desc, list);
- +}
- +
- +/* called with pxp_chan->lock held */
- +static void __pxpdma_dostart(struct pxp_channel *pxp_chan)
- +{
- + struct pxp_dma *pxp_dma = to_pxp_dma(pxp_chan->dma_chan.device);
- + struct pxps *pxp = to_pxp(pxp_dma);
- + struct pxp_tx_desc *desc;
- + struct pxp_tx_desc *child;
- + int i = 0;
- +
- + /* S0 */
- + desc = list_first_entry(&head, struct pxp_tx_desc, list);
- + memcpy(&pxp->pxp_conf_state.s0_param,
- + &desc->layer_param.s0_param, sizeof(struct pxp_layer_param));
- + memcpy(&pxp->pxp_conf_state.proc_data,
- + &desc->proc_data, sizeof(struct pxp_proc_data));
- +
- + /* Save PxP configuration */
- + list_for_each_entry(child, &desc->tx_list, list) {
- + if (i == 0) { /* Output */
- + memcpy(&pxp->pxp_conf_state.out_param,
- + &child->layer_param.out_param,
- + sizeof(struct pxp_layer_param));
- + } else { /* Overlay */
- + memcpy(&pxp->pxp_conf_state.ol_param[i - 1],
- + &child->layer_param.ol_param,
- + sizeof(struct pxp_layer_param));
- + }
- +
- + i++;
- + }
- + pr_debug("%s:%d S0 w/h %d/%d paddr %08x\n", __func__, __LINE__,
- + pxp->pxp_conf_state.s0_param.width,
- + pxp->pxp_conf_state.s0_param.height,
- + pxp->pxp_conf_state.s0_param.paddr);
- + pr_debug("%s:%d OUT w/h %d/%d paddr %08x\n", __func__, __LINE__,
- + pxp->pxp_conf_state.out_param.width,
- + pxp->pxp_conf_state.out_param.height,
- + pxp->pxp_conf_state.out_param.paddr);
- +}
- +
- +static void pxpdma_dostart_work(struct pxps *pxp)
- +{
- + struct pxp_channel *pxp_chan = NULL;
- + unsigned long flags;
- + struct pxp_tx_desc *desc = NULL;
- +
- + spin_lock_irqsave(&pxp->lock, flags);
- +
- + desc = list_entry(head.next, struct pxp_tx_desc, list);
- + pxp_chan = to_pxp_channel(desc->txd.chan);
- +
- + __pxpdma_dostart(pxp_chan);
- +
- + /* Configure PxP */
- + pxp_config(pxp, pxp_chan);
- +
- + pxp_start(pxp);
- +
- + spin_unlock_irqrestore(&pxp->lock, flags);
- +}
- +
- +static void pxpdma_dequeue(struct pxp_channel *pxp_chan, struct pxps *pxp)
- +{
- + unsigned long flags;
- + struct pxp_tx_desc *desc = NULL;
- +
- + do {
- + desc = pxpdma_first_queued(pxp_chan);
- + spin_lock_irqsave(&pxp->lock, flags);
- + list_move_tail(&desc->list, &head);
- + spin_unlock_irqrestore(&pxp->lock, flags);
- + } while (!list_empty(&pxp_chan->queue));
- +}
- +
- +static dma_cookie_t pxp_tx_submit(struct dma_async_tx_descriptor *tx)
- +{
- + struct pxp_tx_desc *desc = to_tx_desc(tx);
- + struct pxp_channel *pxp_chan = to_pxp_channel(tx->chan);
- + dma_cookie_t cookie;
- +
- + dev_dbg(&pxp_chan->dma_chan.dev->device, "received TX\n");
- +
- + /* pxp_chan->lock can be taken under ichan->lock, but not v.v. */
- + spin_lock(&pxp_chan->lock);
- +
- + cookie = pxp_chan->dma_chan.cookie;
- +
- + if (++cookie < 0)
- + cookie = 1;
- +
- + /* from dmaengine.h: "last cookie value returned to client" */
- + pxp_chan->dma_chan.cookie = cookie;
- + tx->cookie = cookie;
- +
- + /* Here we add the tx descriptor to our PxP task queue. */
- + list_add_tail(&desc->list, &pxp_chan->queue);
- +
- + spin_unlock(&pxp_chan->lock);
- +
- + dev_dbg(&pxp_chan->dma_chan.dev->device, "done TX\n");
- +
- + return cookie;
- +}
- +
- +/**
- + * pxp_init_channel() - initialize a PXP channel.
- + * @pxp_dma: PXP DMA context.
- + * @pchan: pointer to the channel object.
- + * @return 0 on success or negative error code on failure.
- + */
- +static int pxp_init_channel(struct pxp_dma *pxp_dma,
- + struct pxp_channel *pxp_chan)
- +{
- + int ret = 0;
- +
- + /*
- + * We are using _virtual_ channel here.
- + * Each channel contains all parameters of corresponding layers
- + * for one transaction; each layer is represented as one descriptor
- + * (i.e., pxp_tx_desc) here.
- + */
- +
- + INIT_LIST_HEAD(&pxp_chan->queue);
- +
- + return ret;
- +}
- +
- +static irqreturn_t pxp_irq(int irq, void *dev_id)
- +{
- + struct pxps *pxp = dev_id;
- + struct pxp_channel *pxp_chan;
- + struct pxp_tx_desc *desc;
- + struct pxp_tx_desc *child, *_child;
- + dma_async_tx_callback callback;
- + void *callback_param;
- + unsigned long flags;
- + u32 hist_status;
- +
- + dump_pxp_reg(pxp);
- +
- + hist_status =
- + __raw_readl(pxp->base + HW_PXP_HIST_CTRL) & BM_PXP_HIST_CTRL_STATUS;
- +
- + __raw_writel(BM_PXP_STAT_IRQ, pxp->base + HW_PXP_STAT_CLR);
- +
- + spin_lock_irqsave(&pxp->lock, flags);
- +
- + if (list_empty(&head)) {
- + pxp->pxp_ongoing = 0;
- + spin_unlock_irqrestore(&pxp->lock, flags);
- + return IRQ_NONE;
- + }
- +
- + /* Get descriptor and call callback */
- + desc = list_entry(head.next, struct pxp_tx_desc, list);
- + pxp_chan = to_pxp_channel(desc->txd.chan);
- +
- + pxp_chan->completed = desc->txd.cookie;
- +
- + callback = desc->txd.callback;
- + callback_param = desc->txd.callback_param;
- +
- + /* Send histogram status back to caller */
- + desc->hist_status = hist_status;
- +
- + if ((desc->txd.flags & DMA_PREP_INTERRUPT) && callback)
- + callback(callback_param);
- +
- + pxp_chan->status = PXP_CHANNEL_INITIALIZED;
- +
- + list_for_each_entry_safe(child, _child, &desc->tx_list, list) {
- + list_del_init(&child->list);
- + kmem_cache_free(tx_desc_cache, (void *)child);
- + }
- + list_del_init(&desc->list);
- + kmem_cache_free(tx_desc_cache, (void *)desc);
- +
- + complete(&pxp->complete);
- + pxp->pxp_ongoing = 0;
- + mod_timer(&pxp->clk_timer, jiffies + msecs_to_jiffies(timeout_in_ms));
- +
- + spin_unlock_irqrestore(&pxp->lock, flags);
- +
- + return IRQ_HANDLED;
- +}
- +
- +/* allocate/free dma tx descriptor dynamically*/
- +static struct pxp_tx_desc *pxpdma_desc_alloc(struct pxp_channel *pxp_chan)
- +{
- + struct pxp_tx_desc *desc = NULL;
- + struct dma_async_tx_descriptor *txd = NULL;
- +
- + desc = kmem_cache_alloc(tx_desc_cache, GFP_KERNEL | __GFP_ZERO);
- + if (desc == NULL)
- + return NULL;
- +
- + INIT_LIST_HEAD(&desc->list);
- + INIT_LIST_HEAD(&desc->tx_list);
- + txd = &desc->txd;
- + dma_async_tx_descriptor_init(txd, &pxp_chan->dma_chan);
- + txd->tx_submit = pxp_tx_submit;
- +
- + return desc;
- +}
- +
- +/* Allocate and initialise a transfer descriptor. */
- +static struct dma_async_tx_descriptor *pxp_prep_slave_sg(struct dma_chan *chan,
- + struct scatterlist
- + *sgl,
- + unsigned int sg_len,
- + enum
- + dma_transfer_direction
- + direction,
- + unsigned long tx_flags,
- + void *context)
- +{
- + struct pxp_channel *pxp_chan = to_pxp_channel(chan);
- + struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
- + struct pxps *pxp = to_pxp(pxp_dma);
- + struct pxp_tx_desc *desc = NULL;
- + struct pxp_tx_desc *first = NULL, *prev = NULL;
- + struct scatterlist *sg;
- + dma_addr_t phys_addr;
- + int i;
- +
- + if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) {
- + dev_err(chan->device->dev, "Invalid DMA direction %d!\n",
- + direction);
- + return NULL;
- + }
- +
- + if (unlikely(sg_len < 2))
- + return NULL;
- +
- + for_each_sg(sgl, sg, sg_len, i) {
- + desc = pxpdma_desc_alloc(pxp_chan);
- + if (!desc) {
- + dev_err(chan->device->dev, "no enough memory to allocate tx descriptor\n");
- + return NULL;
- + }
- +
- + phys_addr = sg_dma_address(sg);
- +
- + if (!first) {
- + first = desc;
- +
- + desc->layer_param.s0_param.paddr = phys_addr;
- + } else {
- + list_add_tail(&desc->list, &first->tx_list);
- + prev->next = desc;
- + desc->next = NULL;
- +
- + if (i == 1)
- + desc->layer_param.out_param.paddr = phys_addr;
- + else
- + desc->layer_param.ol_param.paddr = phys_addr;
- + }
- +
- + prev = desc;
- + }
- +
- + pxp->pxp_conf_state.layer_nr = sg_len;
- + first->txd.flags = tx_flags;
- + first->len = sg_len;
- + pr_debug("%s:%d first %p, first->len %d, flags %08x\n",
- + __func__, __LINE__, first, first->len, first->txd.flags);
- +
- + return &first->txd;
- +}
- +
- +static void pxp_issue_pending(struct dma_chan *chan)
- +{
- + struct pxp_channel *pxp_chan = to_pxp_channel(chan);
- + struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
- + struct pxps *pxp = to_pxp(pxp_dma);
- +
- + spin_lock(&pxp_chan->lock);
- +
- + if (list_empty(&pxp_chan->queue)) {
- + spin_unlock(&pxp_chan->lock);
- + return;
- + }
- +
- + pxpdma_dequeue(pxp_chan, pxp);
- + pxp_chan->status = PXP_CHANNEL_READY;
- +
- + spin_unlock(&pxp_chan->lock);
- +
- + pxp_clk_enable(pxp);
- + wake_up_interruptible(&pxp->thread_waitq);
- +}
- +
- +static void __pxp_terminate_all(struct dma_chan *chan)
- +{
- + struct pxp_channel *pxp_chan = to_pxp_channel(chan);
- +
- + pxp_chan->status = PXP_CHANNEL_INITIALIZED;
- +}
- +
- +static int pxp_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
- + unsigned long arg)
- +{
- + struct pxp_channel *pxp_chan = to_pxp_channel(chan);
- +
- + /* Only supports DMA_TERMINATE_ALL */
- + if (cmd != DMA_TERMINATE_ALL)
- + return -ENXIO;
- +
- + spin_lock(&pxp_chan->lock);
- + __pxp_terminate_all(chan);
- + spin_unlock(&pxp_chan->lock);
- +
- + return 0;
- +}
- +
- +static int pxp_alloc_chan_resources(struct dma_chan *chan)
- +{
- + struct pxp_channel *pxp_chan = to_pxp_channel(chan);
- + struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
- + int ret;
- +
- + /* dmaengine.c now guarantees to only offer free channels */
- + BUG_ON(chan->client_count > 1);
- + WARN_ON(pxp_chan->status != PXP_CHANNEL_FREE);
- +
- + chan->cookie = 1;
- + pxp_chan->completed = -ENXIO;
- +
- + pr_debug("%s dma_chan.chan_id %d\n", __func__, chan->chan_id);
- + ret = pxp_init_channel(pxp_dma, pxp_chan);
- + if (ret < 0)
- + goto err_chan;
- +
- + pxp_chan->status = PXP_CHANNEL_INITIALIZED;
- +
- + dev_dbg(&chan->dev->device, "Found channel 0x%x, irq %d\n",
- + chan->chan_id, pxp_chan->eof_irq);
- +
- + return ret;
- +
- +err_chan:
- + return ret;
- +}
- +
- +static void pxp_free_chan_resources(struct dma_chan *chan)
- +{
- + struct pxp_channel *pxp_chan = to_pxp_channel(chan);
- +
- + spin_lock(&pxp_chan->lock);
- +
- + __pxp_terminate_all(chan);
- +
- + pxp_chan->status = PXP_CHANNEL_FREE;
- +
- + spin_unlock(&pxp_chan->lock);
- +}
- +
- +static enum dma_status pxp_tx_status(struct dma_chan *chan,
- + dma_cookie_t cookie,
- + struct dma_tx_state *txstate)
- +{
- + struct pxp_channel *pxp_chan = to_pxp_channel(chan);
- +
- + if (cookie != chan->cookie)
- + return DMA_ERROR;
- +
- + if (txstate) {
- + txstate->last = pxp_chan->completed;
- + txstate->used = chan->cookie;
- + txstate->residue = 0;
- + }
- + return DMA_COMPLETE;
- +}
- +
- +static int pxp_hw_init(struct pxps *pxp)
- +{
- + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
- + struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
- + u32 reg_val;
- +
- + /* Pull PxP out of reset */
- + __raw_writel(0, pxp->base + HW_PXP_CTRL);
- +
- + /* Config defaults */
- +
- + /* Initialize non-channel-specific PxP parameters */
- + proc_data->drect.left = proc_data->srect.left = 0;
- + proc_data->drect.top = proc_data->srect.top = 0;
- + proc_data->drect.width = proc_data->srect.width = 0;
- + proc_data->drect.height = proc_data->srect.height = 0;
- + proc_data->scaling = 0;
- + proc_data->hflip = 0;
- + proc_data->vflip = 0;
- + proc_data->rotate = 0;
- + proc_data->bgcolor = 0;
- +
- + /* Initialize S0 channel parameters */
- + pxp_conf->s0_param.pixel_fmt = pxp_s0_formats[0];
- + pxp_conf->s0_param.width = 0;
- + pxp_conf->s0_param.height = 0;
- + pxp_conf->s0_param.color_key = -1;
- + pxp_conf->s0_param.color_key_enable = false;
- +
- + /* Initialize OL channel parameters */
- + pxp_conf->ol_param[0].combine_enable = false;
- + pxp_conf->ol_param[0].width = 0;
- + pxp_conf->ol_param[0].height = 0;
- + pxp_conf->ol_param[0].pixel_fmt = PXP_PIX_FMT_RGB565;
- + pxp_conf->ol_param[0].color_key_enable = false;
- + pxp_conf->ol_param[0].color_key = -1;
- + pxp_conf->ol_param[0].global_alpha_enable = false;
- + pxp_conf->ol_param[0].global_alpha = 0;
- + pxp_conf->ol_param[0].local_alpha_enable = false;
- +
- + /* Initialize Output channel parameters */
- + pxp_conf->out_param.width = 0;
- + pxp_conf->out_param.height = 0;
- + pxp_conf->out_param.pixel_fmt = PXP_PIX_FMT_RGB565;
- +
- + proc_data->overlay_state = 0;
- +
- + /* Write default h/w config */
- + pxp_set_ctrl(pxp);
- + pxp_set_s0param(pxp);
- + pxp_set_s0crop(pxp);
- + /*
- + * simply program the ULC to a higher value than the LRC
- + * to avoid any AS pixels to show up in the output buffer.
- + */
- + __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_OUT_AS_ULC);
- + pxp_set_olparam(0, pxp);
- + pxp_set_olcolorkey(0, pxp);
- +
- + pxp_set_s0colorkey(pxp);
- + pxp_set_csc(pxp);
- + pxp_set_bg(pxp);
- + pxp_set_lut(pxp);
- +
- + /* One-time histogram configuration */
- + reg_val =
- + BF_PXP_HIST_CTRL_PANEL_MODE(BV_PXP_HIST_CTRL_PANEL_MODE__GRAY16);
- + __raw_writel(reg_val, pxp->base + HW_PXP_HIST_CTRL);
- +
- + reg_val = BF_PXP_HIST2_PARAM_VALUE0(0x00) |
- + BF_PXP_HIST2_PARAM_VALUE1(0x00F);
- + __raw_writel(reg_val, pxp->base + HW_PXP_HIST2_PARAM);
- +
- + reg_val = BF_PXP_HIST4_PARAM_VALUE0(0x00) |
- + BF_PXP_HIST4_PARAM_VALUE1(0x05) |
- + BF_PXP_HIST4_PARAM_VALUE2(0x0A) | BF_PXP_HIST4_PARAM_VALUE3(0x0F);
- + __raw_writel(reg_val, pxp->base + HW_PXP_HIST4_PARAM);
- +
- + reg_val = BF_PXP_HIST8_PARAM0_VALUE0(0x00) |
- + BF_PXP_HIST8_PARAM0_VALUE1(0x02) |
- + BF_PXP_HIST8_PARAM0_VALUE2(0x04) | BF_PXP_HIST8_PARAM0_VALUE3(0x06);
- + __raw_writel(reg_val, pxp->base + HW_PXP_HIST8_PARAM0);
- + reg_val = BF_PXP_HIST8_PARAM1_VALUE4(0x09) |
- + BF_PXP_HIST8_PARAM1_VALUE5(0x0B) |
- + BF_PXP_HIST8_PARAM1_VALUE6(0x0D) | BF_PXP_HIST8_PARAM1_VALUE7(0x0F);
- + __raw_writel(reg_val, pxp->base + HW_PXP_HIST8_PARAM1);
- +
- + reg_val = BF_PXP_HIST16_PARAM0_VALUE0(0x00) |
- + BF_PXP_HIST16_PARAM0_VALUE1(0x01) |
- + BF_PXP_HIST16_PARAM0_VALUE2(0x02) |
- + BF_PXP_HIST16_PARAM0_VALUE3(0x03);
- + __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM0);
- + reg_val = BF_PXP_HIST16_PARAM1_VALUE4(0x04) |
- + BF_PXP_HIST16_PARAM1_VALUE5(0x05) |
- + BF_PXP_HIST16_PARAM1_VALUE6(0x06) |
- + BF_PXP_HIST16_PARAM1_VALUE7(0x07);
- + __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM1);
- + reg_val = BF_PXP_HIST16_PARAM2_VALUE8(0x08) |
- + BF_PXP_HIST16_PARAM2_VALUE9(0x09) |
- + BF_PXP_HIST16_PARAM2_VALUE10(0x0A) |
- + BF_PXP_HIST16_PARAM2_VALUE11(0x0B);
- + __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM2);
- + reg_val = BF_PXP_HIST16_PARAM3_VALUE12(0x0C) |
- + BF_PXP_HIST16_PARAM3_VALUE13(0x0D) |
- + BF_PXP_HIST16_PARAM3_VALUE14(0x0E) |
- + BF_PXP_HIST16_PARAM3_VALUE15(0x0F);
- + __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM3);
- +
- + return 0;
- +}
- +
- +static int pxp_dma_init(struct pxps *pxp)
- +{
- + struct pxp_dma *pxp_dma = &pxp->pxp_dma;
- + struct dma_device *dma = &pxp_dma->dma;
- + int i;
- +
- + dma_cap_set(DMA_SLAVE, dma->cap_mask);
- + dma_cap_set(DMA_PRIVATE, dma->cap_mask);
- +
- + /* Compulsory common fields */
- + dma->dev = pxp->dev;
- + dma->device_alloc_chan_resources = pxp_alloc_chan_resources;
- + dma->device_free_chan_resources = pxp_free_chan_resources;
- + dma->device_tx_status = pxp_tx_status;
- + dma->device_issue_pending = pxp_issue_pending;
- +
- + /* Compulsory for DMA_SLAVE fields */
- + dma->device_prep_slave_sg = pxp_prep_slave_sg;
- + dma->device_control = pxp_control;
- +
- + /* Initialize PxP Channels */
- + INIT_LIST_HEAD(&dma->channels);
- + for (i = 0; i < NR_PXP_VIRT_CHANNEL; i++) {
- + struct pxp_channel *pxp_chan = pxp->channel + i;
- + struct dma_chan *dma_chan = &pxp_chan->dma_chan;
- +
- + spin_lock_init(&pxp_chan->lock);
- +
- + /* Only one EOF IRQ for PxP, shared by all channels */
- + pxp_chan->eof_irq = pxp->irq;
- + pxp_chan->status = PXP_CHANNEL_FREE;
- + pxp_chan->completed = -ENXIO;
- + snprintf(pxp_chan->eof_name, sizeof(pxp_chan->eof_name),
- + "PXP EOF %d", i);
- +
- + dma_chan->device = &pxp_dma->dma;
- + dma_chan->cookie = 1;
- + dma_chan->chan_id = i;
- + list_add_tail(&dma_chan->device_node, &dma->channels);
- + }
- +
- + return dma_async_device_register(&pxp_dma->dma);
- +}
- +
- +static ssize_t clk_off_timeout_show(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + return sprintf(buf, "%d\n", timeout_in_ms);
- +}
- +
- +static ssize_t clk_off_timeout_store(struct device *dev,
- + struct device_attribute *attr,
- + const char *buf, size_t count)
- +{
- + int val;
- + if (sscanf(buf, "%d", &val) > 0) {
- + timeout_in_ms = val;
- + return count;
- + }
- + return -EINVAL;
- +}
- +
- +static DEVICE_ATTR(clk_off_timeout, 0644, clk_off_timeout_show,
- + clk_off_timeout_store);
- +
- +static ssize_t block_size_show(struct device *dev,
- + struct device_attribute *attr,
- + char *buf)
- +{
- + return sprintf(buf, "%d\n", block_size);
- +}
- +
- +static ssize_t block_size_store(struct device *dev,
- + struct device_attribute *attr,
- + const char *buf, size_t count)
- +{
- + char **last = NULL;
- +
- + block_size = simple_strtoul(buf, last, 0);
- + if (block_size > 1)
- + block_size = 1;
- +
- + return count;
- +}
- +static DEVICE_ATTR(block_size, S_IWUSR | S_IRUGO,
- + block_size_show, block_size_store);
- +
- +static const struct of_device_id imx_pxpdma_dt_ids[] = {
- + { .compatible = "fsl,imx6dl-pxp-dma", },
- + { /* sentinel */ }
- +};
- +MODULE_DEVICE_TABLE(of, imx_pxpdma_dt_ids);
- +
- +static int has_pending_task(struct pxps *pxp, struct pxp_channel *task)
- +{
- + int found;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&pxp->lock, flags);
- + found = !list_empty(&head);
- + spin_unlock_irqrestore(&pxp->lock, flags);
- +
- + return found;
- +}
- +
- +static int pxp_dispatch_thread(void *argv)
- +{
- + struct pxps *pxp = (struct pxps *)argv;
- + struct pxp_channel *pending = NULL;
- + unsigned long flags;
- +
- + while (!kthread_should_stop()) {
- + int ret;
- + ret = wait_event_interruptible(pxp->thread_waitq,
- + has_pending_task(pxp, pending));
- + if (signal_pending(current))
- + continue;
- +
- + if (kthread_should_stop())
- + break;
- +
- + spin_lock_irqsave(&pxp->lock, flags);
- + pxp->pxp_ongoing = 1;
- + spin_unlock_irqrestore(&pxp->lock, flags);
- + init_completion(&pxp->complete);
- + pxpdma_dostart_work(pxp);
- + ret = wait_for_completion_timeout(&pxp->complete, 2 * HZ);
- + if (ret == 0) {
- + printk(KERN_EMERG "%s: task is timeout\n\n", __func__);
- + break;
- + }
- + }
- +
- + return 0;
- +}
- +
- +static int pxp_probe(struct platform_device *pdev)
- +{
- + struct pxps *pxp;
- + struct resource *res;
- + int irq;
- + int err = 0;
- +
- + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- + irq = platform_get_irq(pdev, 0);
- + if (!res || irq < 0) {
- + err = -ENODEV;
- + goto exit;
- + }
- +
- + pxp = devm_kzalloc(&pdev->dev, sizeof(*pxp), GFP_KERNEL);
- + if (!pxp) {
- + dev_err(&pdev->dev, "failed to allocate control object\n");
- + err = -ENOMEM;
- + goto exit;
- + }
- +
- + pxp->dev = &pdev->dev;
- +
- + platform_set_drvdata(pdev, pxp);
- + pxp->irq = irq;
- +
- + pxp->pxp_ongoing = 0;
- + pxp->lut_state = 0;
- +
- + spin_lock_init(&pxp->lock);
- + mutex_init(&pxp->clk_mutex);
- +
- + pxp->base = devm_request_and_ioremap(&pdev->dev, res);
- + if (pxp->base == NULL) {
- + dev_err(&pdev->dev, "Couldn't ioremap regs\n");
- + err = -ENODEV;
- + goto exit;
- + }
- +
- + pxp->pdev = pdev;
- +
- + pxp->clk = devm_clk_get(&pdev->dev, "pxp-axi");
- + clk_prepare_enable(pxp->clk);
- +
- + err = pxp_hw_init(pxp);
- + clk_disable_unprepare(pxp->clk);
- + if (err) {
- + dev_err(&pdev->dev, "failed to initialize hardware\n");
- + goto exit;
- + }
- +
- + err = devm_request_irq(&pdev->dev, pxp->irq, pxp_irq, 0,
- + "pxp-dmaengine", pxp);
- + if (err)
- + goto exit;
- + /* Initialize DMA engine */
- + err = pxp_dma_init(pxp);
- + if (err < 0)
- + goto exit;
- +
- + if (device_create_file(&pdev->dev, &dev_attr_clk_off_timeout)) {
- + dev_err(&pdev->dev,
- + "Unable to create file from clk_off_timeout\n");
- + goto exit;
- + }
- +
- + device_create_file(&pdev->dev, &dev_attr_block_size);
- + dump_pxp_reg(pxp);
- +
- + INIT_WORK(&pxp->work, clkoff_callback);
- + init_timer(&pxp->clk_timer);
- + pxp->clk_timer.function = pxp_clkoff_timer;
- + pxp->clk_timer.data = (unsigned long)pxp;
- +
- + /* allocate a kernel thread to dispatch pxp conf */
- + pxp->dispatch = kthread_run(pxp_dispatch_thread, pxp, "pxp_dispatch");
- + if (IS_ERR(pxp->dispatch)) {
- + err = PTR_ERR(pxp->dispatch);
- + goto exit;
- + }
- + init_waitqueue_head(&pxp->thread_waitq);
- + tx_desc_cache = kmem_cache_create("tx_desc", sizeof(struct pxp_tx_desc),
- + 0, SLAB_HWCACHE_ALIGN, NULL);
- + if (!tx_desc_cache) {
- + err = -ENOMEM;
- + goto exit;
- + }
- +
- + register_pxp_device();
- +
- +exit:
- + if (err)
- + dev_err(&pdev->dev, "Exiting (unsuccessfully) pxp_probe()\n");
- + return err;
- +}
- +
- +static int pxp_remove(struct platform_device *pdev)
- +{
- + struct pxps *pxp = platform_get_drvdata(pdev);
- +
- + unregister_pxp_device();
- + kmem_cache_destroy(tx_desc_cache);
- + kthread_stop(pxp->dispatch);
- + cancel_work_sync(&pxp->work);
- + del_timer_sync(&pxp->clk_timer);
- + clk_disable_unprepare(pxp->clk);
- + device_remove_file(&pdev->dev, &dev_attr_clk_off_timeout);
- + device_remove_file(&pdev->dev, &dev_attr_block_size);
- + dma_async_device_unregister(&(pxp->pxp_dma.dma));
- +
- + return 0;
- +}
- +
- +#ifdef CONFIG_PM
- +static int pxp_suspend(struct platform_device *pdev, pm_message_t state)
- +{
- + struct pxps *pxp = platform_get_drvdata(pdev);
- +
- + pxp_clk_enable(pxp);
- + while (__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_ENABLE)
- + ;
- +
- + __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL);
- + pxp_clk_disable(pxp);
- +
- + return 0;
- +}
- +
- +static int pxp_resume(struct platform_device *pdev)
- +{
- + struct pxps *pxp = platform_get_drvdata(pdev);
- +
- + pxp_clk_enable(pxp);
- + /* Pull PxP out of reset */
- + __raw_writel(0, pxp->base + HW_PXP_CTRL);
- + pxp_clk_disable(pxp);
- +
- + return 0;
- +}
- +#else
- +#define pxp_suspend NULL
- +#define pxp_resume NULL
- +#endif
- +
- +static struct platform_driver pxp_driver = {
- + .driver = {
- + .name = "imx-pxp",
- + .of_match_table = of_match_ptr(imx_pxpdma_dt_ids),
- + },
- + .probe = pxp_probe,
- + .remove = pxp_remove,
- + .suspend = pxp_suspend,
- + .resume = pxp_resume,
- +};
- +
- +module_platform_driver(pxp_driver);
- +
- +
- +MODULE_DESCRIPTION("i.MX PxP driver");
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/dma/pxp/regs-pxp_v2.h linux-3.14.35/drivers/dma/pxp/regs-pxp_v2.h
- --- linux-3.14.35.orig/drivers/dma/pxp/regs-pxp_v2.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/dma/pxp/regs-pxp_v2.h 2015-03-08 14:27:37.549684501 -0500
- @@ -0,0 +1,1152 @@
- +/*
- + * Freescale PXP Register Definitions
- + *
- + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + * This file is created by xml file. Don't Edit it.
- + *
- + * Xml Revision: 1.29
- + * Template revision: 1.3
- + */
- +
- +#ifndef __ARCH_ARM___PXP_H
- +#define __ARCH_ARM___PXP_H
- +
- +#define HW_PXP_CTRL (0x00000000)
- +#define HW_PXP_CTRL_SET (0x00000004)
- +#define HW_PXP_CTRL_CLR (0x00000008)
- +#define HW_PXP_CTRL_TOG (0x0000000c)
- +
- +#define BM_PXP_CTRL_SFTRST 0x80000000
- +#define BM_PXP_CTRL_CLKGATE 0x40000000
- +#define BM_PXP_CTRL_RSVD4 0x20000000
- +#define BM_PXP_CTRL_EN_REPEAT 0x10000000
- +#define BP_PXP_CTRL_RSVD3 26
- +#define BM_PXP_CTRL_RSVD3 0x0C000000
- +#define BF_PXP_CTRL_RSVD3(v) \
- + (((v) << 26) & BM_PXP_CTRL_RSVD3)
- +#define BP_PXP_CTRL_INTERLACED_INPUT 24
- +#define BM_PXP_CTRL_INTERLACED_INPUT 0x03000000
- +#define BF_PXP_CTRL_INTERLACED_INPUT(v) \
- + (((v) << 24) & BM_PXP_CTRL_INTERLACED_INPUT)
- +#define BV_PXP_CTRL_INTERLACED_INPUT__PROGRESSIVE 0x0
- +#define BV_PXP_CTRL_INTERLACED_INPUT__FIELD0 0x2
- +#define BV_PXP_CTRL_INTERLACED_INPUT__FIELD1 0x3
- +#define BM_PXP_CTRL_BLOCK_SIZE 0x00800000
- +#define BV_PXP_CTRL_BLOCK_SIZE__8X8 0x0
- +#define BV_PXP_CTRL_BLOCK_SIZE__16X16 0x1
- +#define BM_PXP_CTRL_ROT_POS 0x00400000
- +#define BM_PXP_CTRL_IN_PLACE 0x00200000
- +#define BP_PXP_CTRL_RSVD1 12
- +#define BM_PXP_CTRL_RSVD1 0x001FF000
- +#define BF_PXP_CTRL_RSVD1(v) \
- + (((v) << 12) & BM_PXP_CTRL_RSVD1)
- +#define BM_PXP_CTRL_VFLIP 0x00000800
- +#define BM_PXP_CTRL_HFLIP 0x00000400
- +#define BP_PXP_CTRL_ROTATE 8
- +#define BM_PXP_CTRL_ROTATE 0x00000300
- +#define BF_PXP_CTRL_ROTATE(v) \
- + (((v) << 8) & BM_PXP_CTRL_ROTATE)
- +#define BV_PXP_CTRL_ROTATE__ROT_0 0x0
- +#define BV_PXP_CTRL_ROTATE__ROT_90 0x1
- +#define BV_PXP_CTRL_ROTATE__ROT_180 0x2
- +#define BV_PXP_CTRL_ROTATE__ROT_270 0x3
- +#define BP_PXP_CTRL_RSVD0 5
- +#define BM_PXP_CTRL_RSVD0 0x000000E0
- +#define BF_PXP_CTRL_RSVD0(v) \
- + (((v) << 5) & BM_PXP_CTRL_RSVD0)
- +#define BM_PXP_CTRL_ENABLE_LCD_HANDSHAKE 0x00000010
- +#define BM_PXP_CTRL_LUT_DMA_IRQ_ENABLE 0x00000008
- +#define BM_PXP_CTRL_NEXT_IRQ_ENABLE 0x00000004
- +#define BM_PXP_CTRL_IRQ_ENABLE 0x00000002
- +#define BM_PXP_CTRL_ENABLE 0x00000001
- +
- +#define HW_PXP_STAT (0x00000010)
- +#define HW_PXP_STAT_SET (0x00000014)
- +#define HW_PXP_STAT_CLR (0x00000018)
- +#define HW_PXP_STAT_TOG (0x0000001c)
- +
- +#define BP_PXP_STAT_BLOCKX 24
- +#define BM_PXP_STAT_BLOCKX 0xFF000000
- +#define BF_PXP_STAT_BLOCKX(v) \
- + (((v) << 24) & BM_PXP_STAT_BLOCKX)
- +#define BP_PXP_STAT_BLOCKY 16
- +#define BM_PXP_STAT_BLOCKY 0x00FF0000
- +#define BF_PXP_STAT_BLOCKY(v) \
- + (((v) << 16) & BM_PXP_STAT_BLOCKY)
- +#define BP_PXP_STAT_RSVD2 9
- +#define BM_PXP_STAT_RSVD2 0x0000FE00
- +#define BF_PXP_STAT_RSVD2(v) \
- + (((v) << 9) & BM_PXP_STAT_RSVD2)
- +#define BM_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ 0x00000100
- +#define BP_PXP_STAT_AXI_ERROR_ID 4
- +#define BM_PXP_STAT_AXI_ERROR_ID 0x000000F0
- +#define BF_PXP_STAT_AXI_ERROR_ID(v) \
- + (((v) << 4) & BM_PXP_STAT_AXI_ERROR_ID)
- +#define BM_PXP_STAT_NEXT_IRQ 0x00000008
- +#define BM_PXP_STAT_AXI_READ_ERROR 0x00000004
- +#define BM_PXP_STAT_AXI_WRITE_ERROR 0x00000002
- +#define BM_PXP_STAT_IRQ 0x00000001
- +
- +#define HW_PXP_OUT_CTRL (0x00000020)
- +#define HW_PXP_OUT_CTRL_SET (0x00000024)
- +#define HW_PXP_OUT_CTRL_CLR (0x00000028)
- +#define HW_PXP_OUT_CTRL_TOG (0x0000002c)
- +
- +#define BP_PXP_OUT_CTRL_ALPHA 24
- +#define BM_PXP_OUT_CTRL_ALPHA 0xFF000000
- +#define BF_PXP_OUT_CTRL_ALPHA(v) \
- + (((v) << 24) & BM_PXP_OUT_CTRL_ALPHA)
- +#define BM_PXP_OUT_CTRL_ALPHA_OUTPUT 0x00800000
- +#define BP_PXP_OUT_CTRL_RSVD1 10
- +#define BM_PXP_OUT_CTRL_RSVD1 0x007FFC00
- +#define BF_PXP_OUT_CTRL_RSVD1(v) \
- + (((v) << 10) & BM_PXP_OUT_CTRL_RSVD1)
- +#define BP_PXP_OUT_CTRL_INTERLACED_OUTPUT 8
- +#define BM_PXP_OUT_CTRL_INTERLACED_OUTPUT 0x00000300
- +#define BF_PXP_OUT_CTRL_INTERLACED_OUTPUT(v) \
- + (((v) << 8) & BM_PXP_OUT_CTRL_INTERLACED_OUTPUT)
- +#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__PROGRESSIVE 0x0
- +#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD0 0x1
- +#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD1 0x2
- +#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__INTERLACED 0x3
- +#define BP_PXP_OUT_CTRL_RSVD0 5
- +#define BM_PXP_OUT_CTRL_RSVD0 0x000000E0
- +#define BF_PXP_OUT_CTRL_RSVD0(v) \
- + (((v) << 5) & BM_PXP_OUT_CTRL_RSVD0)
- +#define BP_PXP_OUT_CTRL_FORMAT 0
- +#define BM_PXP_OUT_CTRL_FORMAT 0x0000001F
- +#define BF_PXP_OUT_CTRL_FORMAT(v) \
- + (((v) << 0) & BM_PXP_OUT_CTRL_FORMAT)
- +#define BV_PXP_OUT_CTRL_FORMAT__ARGB8888 0x0
- +#define BV_PXP_OUT_CTRL_FORMAT__RGB888 0x4
- +#define BV_PXP_OUT_CTRL_FORMAT__RGB888P 0x5
- +#define BV_PXP_OUT_CTRL_FORMAT__ARGB1555 0x8
- +#define BV_PXP_OUT_CTRL_FORMAT__ARGB4444 0x9
- +#define BV_PXP_OUT_CTRL_FORMAT__RGB555 0xC
- +#define BV_PXP_OUT_CTRL_FORMAT__RGB444 0xD
- +#define BV_PXP_OUT_CTRL_FORMAT__RGB565 0xE
- +#define BV_PXP_OUT_CTRL_FORMAT__YUV1P444 0x10
- +#define BV_PXP_OUT_CTRL_FORMAT__UYVY1P422 0x12
- +#define BV_PXP_OUT_CTRL_FORMAT__VYUY1P422 0x13
- +#define BV_PXP_OUT_CTRL_FORMAT__Y8 0x14
- +#define BV_PXP_OUT_CTRL_FORMAT__Y4 0x15
- +#define BV_PXP_OUT_CTRL_FORMAT__YUV2P422 0x18
- +#define BV_PXP_OUT_CTRL_FORMAT__YUV2P420 0x19
- +#define BV_PXP_OUT_CTRL_FORMAT__YVU2P422 0x1A
- +#define BV_PXP_OUT_CTRL_FORMAT__YVU2P420 0x1B
- +
- +#define HW_PXP_OUT_BUF (0x00000030)
- +
- +#define BP_PXP_OUT_BUF_ADDR 0
- +#define BM_PXP_OUT_BUF_ADDR 0xFFFFFFFF
- +#define BF_PXP_OUT_BUF_ADDR(v) (v)
- +
- +#define HW_PXP_OUT_BUF2 (0x00000040)
- +
- +#define BP_PXP_OUT_BUF2_ADDR 0
- +#define BM_PXP_OUT_BUF2_ADDR 0xFFFFFFFF
- +#define BF_PXP_OUT_BUF2_ADDR(v) (v)
- +
- +#define HW_PXP_OUT_PITCH (0x00000050)
- +
- +#define BP_PXP_OUT_PITCH_RSVD 16
- +#define BM_PXP_OUT_PITCH_RSVD 0xFFFF0000
- +#define BF_PXP_OUT_PITCH_RSVD(v) \
- + (((v) << 16) & BM_PXP_OUT_PITCH_RSVD)
- +#define BP_PXP_OUT_PITCH_PITCH 0
- +#define BM_PXP_OUT_PITCH_PITCH 0x0000FFFF
- +#define BF_PXP_OUT_PITCH_PITCH(v) \
- + (((v) << 0) & BM_PXP_OUT_PITCH_PITCH)
- +
- +#define HW_PXP_OUT_LRC (0x00000060)
- +
- +#define BP_PXP_OUT_LRC_RSVD1 30
- +#define BM_PXP_OUT_LRC_RSVD1 0xC0000000
- +#define BF_PXP_OUT_LRC_RSVD1(v) \
- + (((v) << 30) & BM_PXP_OUT_LRC_RSVD1)
- +#define BP_PXP_OUT_LRC_X 16
- +#define BM_PXP_OUT_LRC_X 0x3FFF0000
- +#define BF_PXP_OUT_LRC_X(v) \
- + (((v) << 16) & BM_PXP_OUT_LRC_X)
- +#define BP_PXP_OUT_LRC_RSVD0 14
- +#define BM_PXP_OUT_LRC_RSVD0 0x0000C000
- +#define BF_PXP_OUT_LRC_RSVD0(v) \
- + (((v) << 14) & BM_PXP_OUT_LRC_RSVD0)
- +#define BP_PXP_OUT_LRC_Y 0
- +#define BM_PXP_OUT_LRC_Y 0x00003FFF
- +#define BF_PXP_OUT_LRC_Y(v) \
- + (((v) << 0) & BM_PXP_OUT_LRC_Y)
- +
- +#define HW_PXP_OUT_PS_ULC (0x00000070)
- +
- +#define BP_PXP_OUT_PS_ULC_RSVD1 30
- +#define BM_PXP_OUT_PS_ULC_RSVD1 0xC0000000
- +#define BF_PXP_OUT_PS_ULC_RSVD1(v) \
- + (((v) << 30) & BM_PXP_OUT_PS_ULC_RSVD1)
- +#define BP_PXP_OUT_PS_ULC_X 16
- +#define BM_PXP_OUT_PS_ULC_X 0x3FFF0000
- +#define BF_PXP_OUT_PS_ULC_X(v) \
- + (((v) << 16) & BM_PXP_OUT_PS_ULC_X)
- +#define BP_PXP_OUT_PS_ULC_RSVD0 14
- +#define BM_PXP_OUT_PS_ULC_RSVD0 0x0000C000
- +#define BF_PXP_OUT_PS_ULC_RSVD0(v) \
- + (((v) << 14) & BM_PXP_OUT_PS_ULC_RSVD0)
- +#define BP_PXP_OUT_PS_ULC_Y 0
- +#define BM_PXP_OUT_PS_ULC_Y 0x00003FFF
- +#define BF_PXP_OUT_PS_ULC_Y(v) \
- + (((v) << 0) & BM_PXP_OUT_PS_ULC_Y)
- +
- +#define HW_PXP_OUT_PS_LRC (0x00000080)
- +
- +#define BP_PXP_OUT_PS_LRC_RSVD1 30
- +#define BM_PXP_OUT_PS_LRC_RSVD1 0xC0000000
- +#define BF_PXP_OUT_PS_LRC_RSVD1(v) \
- + (((v) << 30) & BM_PXP_OUT_PS_LRC_RSVD1)
- +#define BP_PXP_OUT_PS_LRC_X 16
- +#define BM_PXP_OUT_PS_LRC_X 0x3FFF0000
- +#define BF_PXP_OUT_PS_LRC_X(v) \
- + (((v) << 16) & BM_PXP_OUT_PS_LRC_X)
- +#define BP_PXP_OUT_PS_LRC_RSVD0 14
- +#define BM_PXP_OUT_PS_LRC_RSVD0 0x0000C000
- +#define BF_PXP_OUT_PS_LRC_RSVD0(v) \
- + (((v) << 14) & BM_PXP_OUT_PS_LRC_RSVD0)
- +#define BP_PXP_OUT_PS_LRC_Y 0
- +#define BM_PXP_OUT_PS_LRC_Y 0x00003FFF
- +#define BF_PXP_OUT_PS_LRC_Y(v) \
- + (((v) << 0) & BM_PXP_OUT_PS_LRC_Y)
- +
- +#define HW_PXP_OUT_AS_ULC (0x00000090)
- +
- +#define BP_PXP_OUT_AS_ULC_RSVD1 30
- +#define BM_PXP_OUT_AS_ULC_RSVD1 0xC0000000
- +#define BF_PXP_OUT_AS_ULC_RSVD1(v) \
- + (((v) << 30) & BM_PXP_OUT_AS_ULC_RSVD1)
- +#define BP_PXP_OUT_AS_ULC_X 16
- +#define BM_PXP_OUT_AS_ULC_X 0x3FFF0000
- +#define BF_PXP_OUT_AS_ULC_X(v) \
- + (((v) << 16) & BM_PXP_OUT_AS_ULC_X)
- +#define BP_PXP_OUT_AS_ULC_RSVD0 14
- +#define BM_PXP_OUT_AS_ULC_RSVD0 0x0000C000
- +#define BF_PXP_OUT_AS_ULC_RSVD0(v) \
- + (((v) << 14) & BM_PXP_OUT_AS_ULC_RSVD0)
- +#define BP_PXP_OUT_AS_ULC_Y 0
- +#define BM_PXP_OUT_AS_ULC_Y 0x00003FFF
- +#define BF_PXP_OUT_AS_ULC_Y(v) \
- + (((v) << 0) & BM_PXP_OUT_AS_ULC_Y)
- +
- +#define HW_PXP_OUT_AS_LRC (0x000000a0)
- +
- +#define BP_PXP_OUT_AS_LRC_RSVD1 30
- +#define BM_PXP_OUT_AS_LRC_RSVD1 0xC0000000
- +#define BF_PXP_OUT_AS_LRC_RSVD1(v) \
- + (((v) << 30) & BM_PXP_OUT_AS_LRC_RSVD1)
- +#define BP_PXP_OUT_AS_LRC_X 16
- +#define BM_PXP_OUT_AS_LRC_X 0x3FFF0000
- +#define BF_PXP_OUT_AS_LRC_X(v) \
- + (((v) << 16) & BM_PXP_OUT_AS_LRC_X)
- +#define BP_PXP_OUT_AS_LRC_RSVD0 14
- +#define BM_PXP_OUT_AS_LRC_RSVD0 0x0000C000
- +#define BF_PXP_OUT_AS_LRC_RSVD0(v) \
- + (((v) << 14) & BM_PXP_OUT_AS_LRC_RSVD0)
- +#define BP_PXP_OUT_AS_LRC_Y 0
- +#define BM_PXP_OUT_AS_LRC_Y 0x00003FFF
- +#define BF_PXP_OUT_AS_LRC_Y(v) \
- + (((v) << 0) & BM_PXP_OUT_AS_LRC_Y)
- +
- +#define HW_PXP_PS_CTRL (0x000000b0)
- +#define HW_PXP_PS_CTRL_SET (0x000000b4)
- +#define HW_PXP_PS_CTRL_CLR (0x000000b8)
- +#define HW_PXP_PS_CTRL_TOG (0x000000bc)
- +
- +#define BP_PXP_PS_CTRL_RSVD1 12
- +#define BM_PXP_PS_CTRL_RSVD1 0xFFFFF000
- +#define BF_PXP_PS_CTRL_RSVD1(v) \
- + (((v) << 12) & BM_PXP_PS_CTRL_RSVD1)
- +#define BP_PXP_PS_CTRL_DECX 10
- +#define BM_PXP_PS_CTRL_DECX 0x00000C00
- +#define BF_PXP_PS_CTRL_DECX(v) \
- + (((v) << 10) & BM_PXP_PS_CTRL_DECX)
- +#define BV_PXP_PS_CTRL_DECX__DISABLE 0x0
- +#define BV_PXP_PS_CTRL_DECX__DECX2 0x1
- +#define BV_PXP_PS_CTRL_DECX__DECX4 0x2
- +#define BV_PXP_PS_CTRL_DECX__DECX8 0x3
- +#define BP_PXP_PS_CTRL_DECY 8
- +#define BM_PXP_PS_CTRL_DECY 0x00000300
- +#define BF_PXP_PS_CTRL_DECY(v) \
- + (((v) << 8) & BM_PXP_PS_CTRL_DECY)
- +#define BV_PXP_PS_CTRL_DECY__DISABLE 0x0
- +#define BV_PXP_PS_CTRL_DECY__DECY2 0x1
- +#define BV_PXP_PS_CTRL_DECY__DECY4 0x2
- +#define BV_PXP_PS_CTRL_DECY__DECY8 0x3
- +#define BP_PXP_PS_CTRL_SWAP 5
- +#define BM_PXP_PS_CTRL_SWAP 0x000000E0
- +#define BF_PXP_PS_CTRL_SWAP(v) \
- + (((v) << 5) & BM_PXP_PS_CTRL_SWAP)
- +#define BP_PXP_PS_CTRL_FORMAT 0
- +#define BM_PXP_PS_CTRL_FORMAT 0x0000001F
- +#define BF_PXP_PS_CTRL_FORMAT(v) \
- + (((v) << 0) & BM_PXP_PS_CTRL_FORMAT)
- +#define BV_PXP_PS_CTRL_FORMAT__RGB888 0x4
- +#define BV_PXP_PS_CTRL_FORMAT__RGB555 0xC
- +#define BV_PXP_PS_CTRL_FORMAT__RGB444 0xD
- +#define BV_PXP_PS_CTRL_FORMAT__RGB565 0xE
- +#define BV_PXP_PS_CTRL_FORMAT__YUV1P444 0x10
- +#define BV_PXP_PS_CTRL_FORMAT__UYVY1P422 0x12
- +#define BV_PXP_PS_CTRL_FORMAT__VYUY1P422 0x13
- +#define BV_PXP_PS_CTRL_FORMAT__Y8 0x14
- +#define BV_PXP_PS_CTRL_FORMAT__Y4 0x15
- +#define BV_PXP_PS_CTRL_FORMAT__YUV2P422 0x18
- +#define BV_PXP_PS_CTRL_FORMAT__YUV2P420 0x19
- +#define BV_PXP_PS_CTRL_FORMAT__YVU2P422 0x1A
- +#define BV_PXP_PS_CTRL_FORMAT__YVU2P420 0x1B
- +#define BV_PXP_PS_CTRL_FORMAT__YUV422 0x1E
- +#define BV_PXP_PS_CTRL_FORMAT__YUV420 0x1F
- +
- +#define HW_PXP_PS_BUF (0x000000c0)
- +
- +#define BP_PXP_PS_BUF_ADDR 0
- +#define BM_PXP_PS_BUF_ADDR 0xFFFFFFFF
- +#define BF_PXP_PS_BUF_ADDR(v) (v)
- +
- +#define HW_PXP_PS_UBUF (0x000000d0)
- +
- +#define BP_PXP_PS_UBUF_ADDR 0
- +#define BM_PXP_PS_UBUF_ADDR 0xFFFFFFFF
- +#define BF_PXP_PS_UBUF_ADDR(v) (v)
- +
- +#define HW_PXP_PS_VBUF (0x000000e0)
- +
- +#define BP_PXP_PS_VBUF_ADDR 0
- +#define BM_PXP_PS_VBUF_ADDR 0xFFFFFFFF
- +#define BF_PXP_PS_VBUF_ADDR(v) (v)
- +
- +#define HW_PXP_PS_PITCH (0x000000f0)
- +
- +#define BP_PXP_PS_PITCH_RSVD 16
- +#define BM_PXP_PS_PITCH_RSVD 0xFFFF0000
- +#define BF_PXP_PS_PITCH_RSVD(v) \
- + (((v) << 16) & BM_PXP_PS_PITCH_RSVD)
- +#define BP_PXP_PS_PITCH_PITCH 0
- +#define BM_PXP_PS_PITCH_PITCH 0x0000FFFF
- +#define BF_PXP_PS_PITCH_PITCH(v) \
- + (((v) << 0) & BM_PXP_PS_PITCH_PITCH)
- +
- +#define HW_PXP_PS_BACKGROUND (0x00000100)
- +
- +#define BP_PXP_PS_BACKGROUND_RSVD 24
- +#define BM_PXP_PS_BACKGROUND_RSVD 0xFF000000
- +#define BF_PXP_PS_BACKGROUND_RSVD(v) \
- + (((v) << 24) & BM_PXP_PS_BACKGROUND_RSVD)
- +#define BP_PXP_PS_BACKGROUND_COLOR 0
- +#define BM_PXP_PS_BACKGROUND_COLOR 0x00FFFFFF
- +#define BF_PXP_PS_BACKGROUND_COLOR(v) \
- + (((v) << 0) & BM_PXP_PS_BACKGROUND_COLOR)
- +
- +#define HW_PXP_PS_SCALE (0x00000110)
- +
- +#define BM_PXP_PS_SCALE_RSVD2 0x80000000
- +#define BP_PXP_PS_SCALE_YSCALE 16
- +#define BM_PXP_PS_SCALE_YSCALE 0x7FFF0000
- +#define BF_PXP_PS_SCALE_YSCALE(v) \
- + (((v) << 16) & BM_PXP_PS_SCALE_YSCALE)
- +#define BM_PXP_PS_SCALE_RSVD1 0x00008000
- +#define BP_PXP_PS_SCALE_XSCALE 0
- +#define BM_PXP_PS_SCALE_XSCALE 0x00007FFF
- +#define BF_PXP_PS_SCALE_XSCALE(v) \
- + (((v) << 0) & BM_PXP_PS_SCALE_XSCALE)
- +
- +#define HW_PXP_PS_OFFSET (0x00000120)
- +
- +#define BP_PXP_PS_OFFSET_RSVD2 28
- +#define BM_PXP_PS_OFFSET_RSVD2 0xF0000000
- +#define BF_PXP_PS_OFFSET_RSVD2(v) \
- + (((v) << 28) & BM_PXP_PS_OFFSET_RSVD2)
- +#define BP_PXP_PS_OFFSET_YOFFSET 16
- +#define BM_PXP_PS_OFFSET_YOFFSET 0x0FFF0000
- +#define BF_PXP_PS_OFFSET_YOFFSET(v) \
- + (((v) << 16) & BM_PXP_PS_OFFSET_YOFFSET)
- +#define BP_PXP_PS_OFFSET_RSVD1 12
- +#define BM_PXP_PS_OFFSET_RSVD1 0x0000F000
- +#define BF_PXP_PS_OFFSET_RSVD1(v) \
- + (((v) << 12) & BM_PXP_PS_OFFSET_RSVD1)
- +#define BP_PXP_PS_OFFSET_XOFFSET 0
- +#define BM_PXP_PS_OFFSET_XOFFSET 0x00000FFF
- +#define BF_PXP_PS_OFFSET_XOFFSET(v) \
- + (((v) << 0) & BM_PXP_PS_OFFSET_XOFFSET)
- +
- +#define HW_PXP_PS_CLRKEYLOW (0x00000130)
- +
- +#define BP_PXP_PS_CLRKEYLOW_RSVD1 24
- +#define BM_PXP_PS_CLRKEYLOW_RSVD1 0xFF000000
- +#define BF_PXP_PS_CLRKEYLOW_RSVD1(v) \
- + (((v) << 24) & BM_PXP_PS_CLRKEYLOW_RSVD1)
- +#define BP_PXP_PS_CLRKEYLOW_PIXEL 0
- +#define BM_PXP_PS_CLRKEYLOW_PIXEL 0x00FFFFFF
- +#define BF_PXP_PS_CLRKEYLOW_PIXEL(v) \
- + (((v) << 0) & BM_PXP_PS_CLRKEYLOW_PIXEL)
- +
- +#define HW_PXP_PS_CLRKEYHIGH (0x00000140)
- +
- +#define BP_PXP_PS_CLRKEYHIGH_RSVD1 24
- +#define BM_PXP_PS_CLRKEYHIGH_RSVD1 0xFF000000
- +#define BF_PXP_PS_CLRKEYHIGH_RSVD1(v) \
- + (((v) << 24) & BM_PXP_PS_CLRKEYHIGH_RSVD1)
- +#define BP_PXP_PS_CLRKEYHIGH_PIXEL 0
- +#define BM_PXP_PS_CLRKEYHIGH_PIXEL 0x00FFFFFF
- +#define BF_PXP_PS_CLRKEYHIGH_PIXEL(v) \
- + (((v) << 0) & BM_PXP_PS_CLRKEYHIGH_PIXEL)
- +
- +#define HW_PXP_AS_CTRL (0x00000150)
- +
- +#define BP_PXP_AS_CTRL_RSVD1 21
- +#define BM_PXP_AS_CTRL_RSVD1 0xFFE00000
- +#define BF_PXP_AS_CTRL_RSVD1(v) \
- + (((v) << 21) & BM_PXP_AS_CTRL_RSVD1)
- +#define BM_PXP_AS_CTRL_ALPHA_INVERT 0x00100000
- +#define BP_PXP_AS_CTRL_ROP 16
- +#define BM_PXP_AS_CTRL_ROP 0x000F0000
- +#define BF_PXP_AS_CTRL_ROP(v) \
- + (((v) << 16) & BM_PXP_AS_CTRL_ROP)
- +#define BV_PXP_AS_CTRL_ROP__MASKAS 0x0
- +#define BV_PXP_AS_CTRL_ROP__MASKNOTAS 0x1
- +#define BV_PXP_AS_CTRL_ROP__MASKASNOT 0x2
- +#define BV_PXP_AS_CTRL_ROP__MERGEAS 0x3
- +#define BV_PXP_AS_CTRL_ROP__MERGENOTAS 0x4
- +#define BV_PXP_AS_CTRL_ROP__MERGEASNOT 0x5
- +#define BV_PXP_AS_CTRL_ROP__NOTCOPYAS 0x6
- +#define BV_PXP_AS_CTRL_ROP__NOT 0x7
- +#define BV_PXP_AS_CTRL_ROP__NOTMASKAS 0x8
- +#define BV_PXP_AS_CTRL_ROP__NOTMERGEAS 0x9
- +#define BV_PXP_AS_CTRL_ROP__XORAS 0xA
- +#define BV_PXP_AS_CTRL_ROP__NOTXORAS 0xB
- +#define BP_PXP_AS_CTRL_ALPHA 8
- +#define BM_PXP_AS_CTRL_ALPHA 0x0000FF00
- +#define BF_PXP_AS_CTRL_ALPHA(v) \
- + (((v) << 8) & BM_PXP_AS_CTRL_ALPHA)
- +#define BP_PXP_AS_CTRL_FORMAT 4
- +#define BM_PXP_AS_CTRL_FORMAT 0x000000F0
- +#define BF_PXP_AS_CTRL_FORMAT(v) \
- + (((v) << 4) & BM_PXP_AS_CTRL_FORMAT)
- +#define BV_PXP_AS_CTRL_FORMAT__ARGB8888 0x0
- +#define BV_PXP_AS_CTRL_FORMAT__RGB888 0x4
- +#define BV_PXP_AS_CTRL_FORMAT__ARGB1555 0x8
- +#define BV_PXP_AS_CTRL_FORMAT__ARGB4444 0x9
- +#define BV_PXP_AS_CTRL_FORMAT__RGB555 0xC
- +#define BV_PXP_AS_CTRL_FORMAT__RGB444 0xD
- +#define BV_PXP_AS_CTRL_FORMAT__RGB565 0xE
- +#define BM_PXP_AS_CTRL_ENABLE_COLORKEY 0x00000008
- +#define BP_PXP_AS_CTRL_ALPHA_CTRL 1
- +#define BM_PXP_AS_CTRL_ALPHA_CTRL 0x00000006
- +#define BF_PXP_AS_CTRL_ALPHA_CTRL(v) \
- + (((v) << 1) & BM_PXP_AS_CTRL_ALPHA_CTRL)
- +#define BV_PXP_AS_CTRL_ALPHA_CTRL__Embedded 0x0
- +#define BV_PXP_AS_CTRL_ALPHA_CTRL__Override 0x1
- +#define BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply 0x2
- +#define BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs 0x3
- +#define BM_PXP_AS_CTRL_RSVD0 0x00000001
- +
- +#define HW_PXP_AS_BUF (0x00000160)
- +
- +#define BP_PXP_AS_BUF_ADDR 0
- +#define BM_PXP_AS_BUF_ADDR 0xFFFFFFFF
- +#define BF_PXP_AS_BUF_ADDR(v) (v)
- +
- +#define HW_PXP_AS_PITCH (0x00000170)
- +
- +#define BP_PXP_AS_PITCH_RSVD 16
- +#define BM_PXP_AS_PITCH_RSVD 0xFFFF0000
- +#define BF_PXP_AS_PITCH_RSVD(v) \
- + (((v) << 16) & BM_PXP_AS_PITCH_RSVD)
- +#define BP_PXP_AS_PITCH_PITCH 0
- +#define BM_PXP_AS_PITCH_PITCH 0x0000FFFF
- +#define BF_PXP_AS_PITCH_PITCH(v) \
- + (((v) << 0) & BM_PXP_AS_PITCH_PITCH)
- +
- +#define HW_PXP_AS_CLRKEYLOW (0x00000180)
- +
- +#define BP_PXP_AS_CLRKEYLOW_RSVD1 24
- +#define BM_PXP_AS_CLRKEYLOW_RSVD1 0xFF000000
- +#define BF_PXP_AS_CLRKEYLOW_RSVD1(v) \
- + (((v) << 24) & BM_PXP_AS_CLRKEYLOW_RSVD1)
- +#define BP_PXP_AS_CLRKEYLOW_PIXEL 0
- +#define BM_PXP_AS_CLRKEYLOW_PIXEL 0x00FFFFFF
- +#define BF_PXP_AS_CLRKEYLOW_PIXEL(v) \
- + (((v) << 0) & BM_PXP_AS_CLRKEYLOW_PIXEL)
- +
- +#define HW_PXP_AS_CLRKEYHIGH (0x00000190)
- +
- +#define BP_PXP_AS_CLRKEYHIGH_RSVD1 24
- +#define BM_PXP_AS_CLRKEYHIGH_RSVD1 0xFF000000
- +#define BF_PXP_AS_CLRKEYHIGH_RSVD1(v) \
- + (((v) << 24) & BM_PXP_AS_CLRKEYHIGH_RSVD1)
- +#define BP_PXP_AS_CLRKEYHIGH_PIXEL 0
- +#define BM_PXP_AS_CLRKEYHIGH_PIXEL 0x00FFFFFF
- +#define BF_PXP_AS_CLRKEYHIGH_PIXEL(v) \
- + (((v) << 0) & BM_PXP_AS_CLRKEYHIGH_PIXEL)
- +
- +#define HW_PXP_CSC1_COEF0 (0x000001a0)
- +
- +#define BM_PXP_CSC1_COEF0_YCBCR_MODE 0x80000000
- +#define BM_PXP_CSC1_COEF0_BYPASS 0x40000000
- +#define BM_PXP_CSC1_COEF0_RSVD1 0x20000000
- +#define BP_PXP_CSC1_COEF0_C0 18
- +#define BM_PXP_CSC1_COEF0_C0 0x1FFC0000
- +#define BF_PXP_CSC1_COEF0_C0(v) \
- + (((v) << 18) & BM_PXP_CSC1_COEF0_C0)
- +#define BP_PXP_CSC1_COEF0_UV_OFFSET 9
- +#define BM_PXP_CSC1_COEF0_UV_OFFSET 0x0003FE00
- +#define BF_PXP_CSC1_COEF0_UV_OFFSET(v) \
- + (((v) << 9) & BM_PXP_CSC1_COEF0_UV_OFFSET)
- +#define BP_PXP_CSC1_COEF0_Y_OFFSET 0
- +#define BM_PXP_CSC1_COEF0_Y_OFFSET 0x000001FF
- +#define BF_PXP_CSC1_COEF0_Y_OFFSET(v) \
- + (((v) << 0) & BM_PXP_CSC1_COEF0_Y_OFFSET)
- +
- +#define HW_PXP_CSC1_COEF1 (0x000001b0)
- +
- +#define BP_PXP_CSC1_COEF1_RSVD1 27
- +#define BM_PXP_CSC1_COEF1_RSVD1 0xF8000000
- +#define BF_PXP_CSC1_COEF1_RSVD1(v) \
- + (((v) << 27) & BM_PXP_CSC1_COEF1_RSVD1)
- +#define BP_PXP_CSC1_COEF1_C1 16
- +#define BM_PXP_CSC1_COEF1_C1 0x07FF0000
- +#define BF_PXP_CSC1_COEF1_C1(v) \
- + (((v) << 16) & BM_PXP_CSC1_COEF1_C1)
- +#define BP_PXP_CSC1_COEF1_RSVD0 11
- +#define BM_PXP_CSC1_COEF1_RSVD0 0x0000F800
- +#define BF_PXP_CSC1_COEF1_RSVD0(v) \
- + (((v) << 11) & BM_PXP_CSC1_COEF1_RSVD0)
- +#define BP_PXP_CSC1_COEF1_C4 0
- +#define BM_PXP_CSC1_COEF1_C4 0x000007FF
- +#define BF_PXP_CSC1_COEF1_C4(v) \
- + (((v) << 0) & BM_PXP_CSC1_COEF1_C4)
- +
- +#define HW_PXP_CSC1_COEF2 (0x000001c0)
- +
- +#define BP_PXP_CSC1_COEF2_RSVD1 27
- +#define BM_PXP_CSC1_COEF2_RSVD1 0xF8000000
- +#define BF_PXP_CSC1_COEF2_RSVD1(v) \
- + (((v) << 27) & BM_PXP_CSC1_COEF2_RSVD1)
- +#define BP_PXP_CSC1_COEF2_C2 16
- +#define BM_PXP_CSC1_COEF2_C2 0x07FF0000
- +#define BF_PXP_CSC1_COEF2_C2(v) \
- + (((v) << 16) & BM_PXP_CSC1_COEF2_C2)
- +#define BP_PXP_CSC1_COEF2_RSVD0 11
- +#define BM_PXP_CSC1_COEF2_RSVD0 0x0000F800
- +#define BF_PXP_CSC1_COEF2_RSVD0(v) \
- + (((v) << 11) & BM_PXP_CSC1_COEF2_RSVD0)
- +#define BP_PXP_CSC1_COEF2_C3 0
- +#define BM_PXP_CSC1_COEF2_C3 0x000007FF
- +#define BF_PXP_CSC1_COEF2_C3(v) \
- + (((v) << 0) & BM_PXP_CSC1_COEF2_C3)
- +
- +#define HW_PXP_CSC2_CTRL (0x000001d0)
- +
- +#define BP_PXP_CSC2_CTRL_RSVD 3
- +#define BM_PXP_CSC2_CTRL_RSVD 0xFFFFFFF8
- +#define BF_PXP_CSC2_CTRL_RSVD(v) \
- + (((v) << 3) & BM_PXP_CSC2_CTRL_RSVD)
- +#define BP_PXP_CSC2_CTRL_CSC_MODE 1
- +#define BM_PXP_CSC2_CTRL_CSC_MODE 0x00000006
- +#define BF_PXP_CSC2_CTRL_CSC_MODE(v) \
- + (((v) << 1) & BM_PXP_CSC2_CTRL_CSC_MODE)
- +#define BV_PXP_CSC2_CTRL_CSC_MODE__YUV2RGB 0x0
- +#define BV_PXP_CSC2_CTRL_CSC_MODE__YCbCr2RGB 0x1
- +#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YUV 0x2
- +#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YCbCr 0x3
- +#define BM_PXP_CSC2_CTRL_BYPASS 0x00000001
- +
- +#define HW_PXP_CSC2_COEF0 (0x000001e0)
- +
- +#define BP_PXP_CSC2_COEF0_RSVD1 27
- +#define BM_PXP_CSC2_COEF0_RSVD1 0xF8000000
- +#define BF_PXP_CSC2_COEF0_RSVD1(v) \
- + (((v) << 27) & BM_PXP_CSC2_COEF0_RSVD1)
- +#define BP_PXP_CSC2_COEF0_A2 16
- +#define BM_PXP_CSC2_COEF0_A2 0x07FF0000
- +#define BF_PXP_CSC2_COEF0_A2(v) \
- + (((v) << 16) & BM_PXP_CSC2_COEF0_A2)
- +#define BP_PXP_CSC2_COEF0_RSVD0 11
- +#define BM_PXP_CSC2_COEF0_RSVD0 0x0000F800
- +#define BF_PXP_CSC2_COEF0_RSVD0(v) \
- + (((v) << 11) & BM_PXP_CSC2_COEF0_RSVD0)
- +#define BP_PXP_CSC2_COEF0_A1 0
- +#define BM_PXP_CSC2_COEF0_A1 0x000007FF
- +#define BF_PXP_CSC2_COEF0_A1(v) \
- + (((v) << 0) & BM_PXP_CSC2_COEF0_A1)
- +
- +#define HW_PXP_CSC2_COEF1 (0x000001f0)
- +
- +#define BP_PXP_CSC2_COEF1_RSVD1 27
- +#define BM_PXP_CSC2_COEF1_RSVD1 0xF8000000
- +#define BF_PXP_CSC2_COEF1_RSVD1(v) \
- + (((v) << 27) & BM_PXP_CSC2_COEF1_RSVD1)
- +#define BP_PXP_CSC2_COEF1_B1 16
- +#define BM_PXP_CSC2_COEF1_B1 0x07FF0000
- +#define BF_PXP_CSC2_COEF1_B1(v) \
- + (((v) << 16) & BM_PXP_CSC2_COEF1_B1)
- +#define BP_PXP_CSC2_COEF1_RSVD0 11
- +#define BM_PXP_CSC2_COEF1_RSVD0 0x0000F800
- +#define BF_PXP_CSC2_COEF1_RSVD0(v) \
- + (((v) << 11) & BM_PXP_CSC2_COEF1_RSVD0)
- +#define BP_PXP_CSC2_COEF1_A3 0
- +#define BM_PXP_CSC2_COEF1_A3 0x000007FF
- +#define BF_PXP_CSC2_COEF1_A3(v) \
- + (((v) << 0) & BM_PXP_CSC2_COEF1_A3)
- +
- +#define HW_PXP_CSC2_COEF2 (0x00000200)
- +
- +#define BP_PXP_CSC2_COEF2_RSVD1 27
- +#define BM_PXP_CSC2_COEF2_RSVD1 0xF8000000
- +#define BF_PXP_CSC2_COEF2_RSVD1(v) \
- + (((v) << 27) & BM_PXP_CSC2_COEF2_RSVD1)
- +#define BP_PXP_CSC2_COEF2_B3 16
- +#define BM_PXP_CSC2_COEF2_B3 0x07FF0000
- +#define BF_PXP_CSC2_COEF2_B3(v) \
- + (((v) << 16) & BM_PXP_CSC2_COEF2_B3)
- +#define BP_PXP_CSC2_COEF2_RSVD0 11
- +#define BM_PXP_CSC2_COEF2_RSVD0 0x0000F800
- +#define BF_PXP_CSC2_COEF2_RSVD0(v) \
- + (((v) << 11) & BM_PXP_CSC2_COEF2_RSVD0)
- +#define BP_PXP_CSC2_COEF2_B2 0
- +#define BM_PXP_CSC2_COEF2_B2 0x000007FF
- +#define BF_PXP_CSC2_COEF2_B2(v) \
- + (((v) << 0) & BM_PXP_CSC2_COEF2_B2)
- +
- +#define HW_PXP_CSC2_COEF3 (0x00000210)
- +
- +#define BP_PXP_CSC2_COEF3_RSVD1 27
- +#define BM_PXP_CSC2_COEF3_RSVD1 0xF8000000
- +#define BF_PXP_CSC2_COEF3_RSVD1(v) \
- + (((v) << 27) & BM_PXP_CSC2_COEF3_RSVD1)
- +#define BP_PXP_CSC2_COEF3_C2 16
- +#define BM_PXP_CSC2_COEF3_C2 0x07FF0000
- +#define BF_PXP_CSC2_COEF3_C2(v) \
- + (((v) << 16) & BM_PXP_CSC2_COEF3_C2)
- +#define BP_PXP_CSC2_COEF3_RSVD0 11
- +#define BM_PXP_CSC2_COEF3_RSVD0 0x0000F800
- +#define BF_PXP_CSC2_COEF3_RSVD0(v) \
- + (((v) << 11) & BM_PXP_CSC2_COEF3_RSVD0)
- +#define BP_PXP_CSC2_COEF3_C1 0
- +#define BM_PXP_CSC2_COEF3_C1 0x000007FF
- +#define BF_PXP_CSC2_COEF3_C1(v) \
- + (((v) << 0) & BM_PXP_CSC2_COEF3_C1)
- +
- +#define HW_PXP_CSC2_COEF4 (0x00000220)
- +
- +#define BP_PXP_CSC2_COEF4_RSVD1 25
- +#define BM_PXP_CSC2_COEF4_RSVD1 0xFE000000
- +#define BF_PXP_CSC2_COEF4_RSVD1(v) \
- + (((v) << 25) & BM_PXP_CSC2_COEF4_RSVD1)
- +#define BP_PXP_CSC2_COEF4_D1 16
- +#define BM_PXP_CSC2_COEF4_D1 0x01FF0000
- +#define BF_PXP_CSC2_COEF4_D1(v) \
- + (((v) << 16) & BM_PXP_CSC2_COEF4_D1)
- +#define BP_PXP_CSC2_COEF4_RSVD0 11
- +#define BM_PXP_CSC2_COEF4_RSVD0 0x0000F800
- +#define BF_PXP_CSC2_COEF4_RSVD0(v) \
- + (((v) << 11) & BM_PXP_CSC2_COEF4_RSVD0)
- +#define BP_PXP_CSC2_COEF4_C3 0
- +#define BM_PXP_CSC2_COEF4_C3 0x000007FF
- +#define BF_PXP_CSC2_COEF4_C3(v) \
- + (((v) << 0) & BM_PXP_CSC2_COEF4_C3)
- +
- +#define HW_PXP_CSC2_COEF5 (0x00000230)
- +
- +#define BP_PXP_CSC2_COEF5_RSVD1 25
- +#define BM_PXP_CSC2_COEF5_RSVD1 0xFE000000
- +#define BF_PXP_CSC2_COEF5_RSVD1(v) \
- + (((v) << 25) & BM_PXP_CSC2_COEF5_RSVD1)
- +#define BP_PXP_CSC2_COEF5_D3 16
- +#define BM_PXP_CSC2_COEF5_D3 0x01FF0000
- +#define BF_PXP_CSC2_COEF5_D3(v) \
- + (((v) << 16) & BM_PXP_CSC2_COEF5_D3)
- +#define BP_PXP_CSC2_COEF5_RSVD0 9
- +#define BM_PXP_CSC2_COEF5_RSVD0 0x0000FE00
- +#define BF_PXP_CSC2_COEF5_RSVD0(v) \
- + (((v) << 9) & BM_PXP_CSC2_COEF5_RSVD0)
- +#define BP_PXP_CSC2_COEF5_D2 0
- +#define BM_PXP_CSC2_COEF5_D2 0x000001FF
- +#define BF_PXP_CSC2_COEF5_D2(v) \
- + (((v) << 0) & BM_PXP_CSC2_COEF5_D2)
- +
- +#define HW_PXP_LUT_CTRL (0x00000240)
- +
- +#define BM_PXP_LUT_CTRL_BYPASS 0x80000000
- +#define BP_PXP_LUT_CTRL_RSVD3 26
- +#define BM_PXP_LUT_CTRL_RSVD3 0x7C000000
- +#define BF_PXP_LUT_CTRL_RSVD3(v) \
- + (((v) << 26) & BM_PXP_LUT_CTRL_RSVD3)
- +#define BP_PXP_LUT_CTRL_LOOKUP_MODE 24
- +#define BM_PXP_LUT_CTRL_LOOKUP_MODE 0x03000000
- +#define BF_PXP_LUT_CTRL_LOOKUP_MODE(v) \
- + (((v) << 24) & BM_PXP_LUT_CTRL_LOOKUP_MODE)
- +#define BV_PXP_LUT_CTRL_LOOKUP_MODE__CACHE_RGB565 0x0
- +#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8 0x1
- +#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB444 0x2
- +#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB454 0x3
- +#define BP_PXP_LUT_CTRL_RSVD2 18
- +#define BM_PXP_LUT_CTRL_RSVD2 0x00FC0000
- +#define BF_PXP_LUT_CTRL_RSVD2(v) \
- + (((v) << 18) & BM_PXP_LUT_CTRL_RSVD2)
- +#define BP_PXP_LUT_CTRL_OUT_MODE 16
- +#define BM_PXP_LUT_CTRL_OUT_MODE 0x00030000
- +#define BF_PXP_LUT_CTRL_OUT_MODE(v) \
- + (((v) << 16) & BM_PXP_LUT_CTRL_OUT_MODE)
- +#define BV_PXP_LUT_CTRL_OUT_MODE__RESERVED 0x0
- +#define BV_PXP_LUT_CTRL_OUT_MODE__Y8 0x1
- +#define BV_PXP_LUT_CTRL_OUT_MODE__RGBW4444CFA 0x2
- +#define BV_PXP_LUT_CTRL_OUT_MODE__RGB888 0x3
- +#define BP_PXP_LUT_CTRL_RSVD1 11
- +#define BM_PXP_LUT_CTRL_RSVD1 0x0000F800
- +#define BF_PXP_LUT_CTRL_RSVD1(v) \
- + (((v) << 11) & BM_PXP_LUT_CTRL_RSVD1)
- +#define BM_PXP_LUT_CTRL_SEL_8KB 0x00000400
- +#define BM_PXP_LUT_CTRL_LRU_UPD 0x00000200
- +#define BM_PXP_LUT_CTRL_INVALID 0x00000100
- +#define BP_PXP_LUT_CTRL_RSVD0 1
- +#define BM_PXP_LUT_CTRL_RSVD0 0x000000FE
- +#define BF_PXP_LUT_CTRL_RSVD0(v) \
- + (((v) << 1) & BM_PXP_LUT_CTRL_RSVD0)
- +#define BM_PXP_LUT_CTRL_DMA_START 0x00000001
- +
- +#define HW_PXP_LUT_ADDR (0x00000250)
- +
- +#define BM_PXP_LUT_ADDR_RSVD2 0x80000000
- +#define BP_PXP_LUT_ADDR_NUM_BYTES 16
- +#define BM_PXP_LUT_ADDR_NUM_BYTES 0x7FFF0000
- +#define BF_PXP_LUT_ADDR_NUM_BYTES(v) \
- + (((v) << 16) & BM_PXP_LUT_ADDR_NUM_BYTES)
- +#define BP_PXP_LUT_ADDR_RSVD1 14
- +#define BM_PXP_LUT_ADDR_RSVD1 0x0000C000
- +#define BF_PXP_LUT_ADDR_RSVD1(v) \
- + (((v) << 14) & BM_PXP_LUT_ADDR_RSVD1)
- +#define BP_PXP_LUT_ADDR_ADDR 0
- +#define BM_PXP_LUT_ADDR_ADDR 0x00003FFF
- +#define BF_PXP_LUT_ADDR_ADDR(v) \
- + (((v) << 0) & BM_PXP_LUT_ADDR_ADDR)
- +
- +#define HW_PXP_LUT_DATA (0x00000260)
- +
- +#define BP_PXP_LUT_DATA_DATA 0
- +#define BM_PXP_LUT_DATA_DATA 0xFFFFFFFF
- +#define BF_PXP_LUT_DATA_DATA(v) (v)
- +
- +#define HW_PXP_LUT_EXTMEM (0x00000270)
- +
- +#define BP_PXP_LUT_EXTMEM_ADDR 0
- +#define BM_PXP_LUT_EXTMEM_ADDR 0xFFFFFFFF
- +#define BF_PXP_LUT_EXTMEM_ADDR(v) (v)
- +
- +#define HW_PXP_CFA (0x00000280)
- +
- +#define BP_PXP_CFA_DATA 0
- +#define BM_PXP_CFA_DATA 0xFFFFFFFF
- +#define BF_PXP_CFA_DATA(v) (v)
- +
- +#define HW_PXP_HIST_CTRL (0x00000290)
- +
- +#define BP_PXP_HIST_CTRL_RSVD 6
- +#define BM_PXP_HIST_CTRL_RSVD 0xFFFFFFC0
- +#define BF_PXP_HIST_CTRL_RSVD(v) \
- + (((v) << 6) & BM_PXP_HIST_CTRL_RSVD)
- +#define BP_PXP_HIST_CTRL_PANEL_MODE 4
- +#define BM_PXP_HIST_CTRL_PANEL_MODE 0x00000030
- +#define BF_PXP_HIST_CTRL_PANEL_MODE(v) \
- + (((v) << 4) & BM_PXP_HIST_CTRL_PANEL_MODE)
- +#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY4 0x0
- +#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY8 0x1
- +#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY16 0x2
- +#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY32 0x3
- +#define BP_PXP_HIST_CTRL_STATUS 0
- +#define BM_PXP_HIST_CTRL_STATUS 0x0000000F
- +#define BF_PXP_HIST_CTRL_STATUS(v) \
- + (((v) << 0) & BM_PXP_HIST_CTRL_STATUS)
- +
- +#define HW_PXP_HIST2_PARAM (0x000002a0)
- +
- +#define BP_PXP_HIST2_PARAM_RSVD 16
- +#define BM_PXP_HIST2_PARAM_RSVD 0xFFFF0000
- +#define BF_PXP_HIST2_PARAM_RSVD(v) \
- + (((v) << 16) & BM_PXP_HIST2_PARAM_RSVD)
- +#define BP_PXP_HIST2_PARAM_RSVD1 13
- +#define BM_PXP_HIST2_PARAM_RSVD1 0x0000E000
- +#define BF_PXP_HIST2_PARAM_RSVD1(v) \
- + (((v) << 13) & BM_PXP_HIST2_PARAM_RSVD1)
- +#define BP_PXP_HIST2_PARAM_VALUE1 8
- +#define BM_PXP_HIST2_PARAM_VALUE1 0x00001F00
- +#define BF_PXP_HIST2_PARAM_VALUE1(v) \
- + (((v) << 8) & BM_PXP_HIST2_PARAM_VALUE1)
- +#define BP_PXP_HIST2_PARAM_RSVD0 5
- +#define BM_PXP_HIST2_PARAM_RSVD0 0x000000E0
- +#define BF_PXP_HIST2_PARAM_RSVD0(v) \
- + (((v) << 5) & BM_PXP_HIST2_PARAM_RSVD0)
- +#define BP_PXP_HIST2_PARAM_VALUE0 0
- +#define BM_PXP_HIST2_PARAM_VALUE0 0x0000001F
- +#define BF_PXP_HIST2_PARAM_VALUE0(v) \
- + (((v) << 0) & BM_PXP_HIST2_PARAM_VALUE0)
- +
- +#define HW_PXP_HIST4_PARAM (0x000002b0)
- +
- +#define BP_PXP_HIST4_PARAM_RSVD3 29
- +#define BM_PXP_HIST4_PARAM_RSVD3 0xE0000000
- +#define BF_PXP_HIST4_PARAM_RSVD3(v) \
- + (((v) << 29) & BM_PXP_HIST4_PARAM_RSVD3)
- +#define BP_PXP_HIST4_PARAM_VALUE3 24
- +#define BM_PXP_HIST4_PARAM_VALUE3 0x1F000000
- +#define BF_PXP_HIST4_PARAM_VALUE3(v) \
- + (((v) << 24) & BM_PXP_HIST4_PARAM_VALUE3)
- +#define BP_PXP_HIST4_PARAM_RSVD2 21
- +#define BM_PXP_HIST4_PARAM_RSVD2 0x00E00000
- +#define BF_PXP_HIST4_PARAM_RSVD2(v) \
- + (((v) << 21) & BM_PXP_HIST4_PARAM_RSVD2)
- +#define BP_PXP_HIST4_PARAM_VALUE2 16
- +#define BM_PXP_HIST4_PARAM_VALUE2 0x001F0000
- +#define BF_PXP_HIST4_PARAM_VALUE2(v) \
- + (((v) << 16) & BM_PXP_HIST4_PARAM_VALUE2)
- +#define BP_PXP_HIST4_PARAM_RSVD1 13
- +#define BM_PXP_HIST4_PARAM_RSVD1 0x0000E000
- +#define BF_PXP_HIST4_PARAM_RSVD1(v) \
- + (((v) << 13) & BM_PXP_HIST4_PARAM_RSVD1)
- +#define BP_PXP_HIST4_PARAM_VALUE1 8
- +#define BM_PXP_HIST4_PARAM_VALUE1 0x00001F00
- +#define BF_PXP_HIST4_PARAM_VALUE1(v) \
- + (((v) << 8) & BM_PXP_HIST4_PARAM_VALUE1)
- +#define BP_PXP_HIST4_PARAM_RSVD0 5
- +#define BM_PXP_HIST4_PARAM_RSVD0 0x000000E0
- +#define BF_PXP_HIST4_PARAM_RSVD0(v) \
- + (((v) << 5) & BM_PXP_HIST4_PARAM_RSVD0)
- +#define BP_PXP_HIST4_PARAM_VALUE0 0
- +#define BM_PXP_HIST4_PARAM_VALUE0 0x0000001F
- +#define BF_PXP_HIST4_PARAM_VALUE0(v) \
- + (((v) << 0) & BM_PXP_HIST4_PARAM_VALUE0)
- +
- +#define HW_PXP_HIST8_PARAM0 (0x000002c0)
- +
- +#define BP_PXP_HIST8_PARAM0_RSVD3 29
- +#define BM_PXP_HIST8_PARAM0_RSVD3 0xE0000000
- +#define BF_PXP_HIST8_PARAM0_RSVD3(v) \
- + (((v) << 29) & BM_PXP_HIST8_PARAM0_RSVD3)
- +#define BP_PXP_HIST8_PARAM0_VALUE3 24
- +#define BM_PXP_HIST8_PARAM0_VALUE3 0x1F000000
- +#define BF_PXP_HIST8_PARAM0_VALUE3(v) \
- + (((v) << 24) & BM_PXP_HIST8_PARAM0_VALUE3)
- +#define BP_PXP_HIST8_PARAM0_RSVD2 21
- +#define BM_PXP_HIST8_PARAM0_RSVD2 0x00E00000
- +#define BF_PXP_HIST8_PARAM0_RSVD2(v) \
- + (((v) << 21) & BM_PXP_HIST8_PARAM0_RSVD2)
- +#define BP_PXP_HIST8_PARAM0_VALUE2 16
- +#define BM_PXP_HIST8_PARAM0_VALUE2 0x001F0000
- +#define BF_PXP_HIST8_PARAM0_VALUE2(v) \
- + (((v) << 16) & BM_PXP_HIST8_PARAM0_VALUE2)
- +#define BP_PXP_HIST8_PARAM0_RSVD1 13
- +#define BM_PXP_HIST8_PARAM0_RSVD1 0x0000E000
- +#define BF_PXP_HIST8_PARAM0_RSVD1(v) \
- + (((v) << 13) & BM_PXP_HIST8_PARAM0_RSVD1)
- +#define BP_PXP_HIST8_PARAM0_VALUE1 8
- +#define BM_PXP_HIST8_PARAM0_VALUE1 0x00001F00
- +#define BF_PXP_HIST8_PARAM0_VALUE1(v) \
- + (((v) << 8) & BM_PXP_HIST8_PARAM0_VALUE1)
- +#define BP_PXP_HIST8_PARAM0_RSVD0 5
- +#define BM_PXP_HIST8_PARAM0_RSVD0 0x000000E0
- +#define BF_PXP_HIST8_PARAM0_RSVD0(v) \
- + (((v) << 5) & BM_PXP_HIST8_PARAM0_RSVD0)
- +#define BP_PXP_HIST8_PARAM0_VALUE0 0
- +#define BM_PXP_HIST8_PARAM0_VALUE0 0x0000001F
- +#define BF_PXP_HIST8_PARAM0_VALUE0(v) \
- + (((v) << 0) & BM_PXP_HIST8_PARAM0_VALUE0)
- +
- +#define HW_PXP_HIST8_PARAM1 (0x000002d0)
- +
- +#define BP_PXP_HIST8_PARAM1_RSVD7 29
- +#define BM_PXP_HIST8_PARAM1_RSVD7 0xE0000000
- +#define BF_PXP_HIST8_PARAM1_RSVD7(v) \
- + (((v) << 29) & BM_PXP_HIST8_PARAM1_RSVD7)
- +#define BP_PXP_HIST8_PARAM1_VALUE7 24
- +#define BM_PXP_HIST8_PARAM1_VALUE7 0x1F000000
- +#define BF_PXP_HIST8_PARAM1_VALUE7(v) \
- + (((v) << 24) & BM_PXP_HIST8_PARAM1_VALUE7)
- +#define BP_PXP_HIST8_PARAM1_RSVD6 21
- +#define BM_PXP_HIST8_PARAM1_RSVD6 0x00E00000
- +#define BF_PXP_HIST8_PARAM1_RSVD6(v) \
- + (((v) << 21) & BM_PXP_HIST8_PARAM1_RSVD6)
- +#define BP_PXP_HIST8_PARAM1_VALUE6 16
- +#define BM_PXP_HIST8_PARAM1_VALUE6 0x001F0000
- +#define BF_PXP_HIST8_PARAM1_VALUE6(v) \
- + (((v) << 16) & BM_PXP_HIST8_PARAM1_VALUE6)
- +#define BP_PXP_HIST8_PARAM1_RSVD5 13
- +#define BM_PXP_HIST8_PARAM1_RSVD5 0x0000E000
- +#define BF_PXP_HIST8_PARAM1_RSVD5(v) \
- + (((v) << 13) & BM_PXP_HIST8_PARAM1_RSVD5)
- +#define BP_PXP_HIST8_PARAM1_VALUE5 8
- +#define BM_PXP_HIST8_PARAM1_VALUE5 0x00001F00
- +#define BF_PXP_HIST8_PARAM1_VALUE5(v) \
- + (((v) << 8) & BM_PXP_HIST8_PARAM1_VALUE5)
- +#define BP_PXP_HIST8_PARAM1_RSVD4 5
- +#define BM_PXP_HIST8_PARAM1_RSVD4 0x000000E0
- +#define BF_PXP_HIST8_PARAM1_RSVD4(v) \
- + (((v) << 5) & BM_PXP_HIST8_PARAM1_RSVD4)
- +#define BP_PXP_HIST8_PARAM1_VALUE4 0
- +#define BM_PXP_HIST8_PARAM1_VALUE4 0x0000001F
- +#define BF_PXP_HIST8_PARAM1_VALUE4(v) \
- + (((v) << 0) & BM_PXP_HIST8_PARAM1_VALUE4)
- +
- +#define HW_PXP_HIST16_PARAM0 (0x000002e0)
- +
- +#define BP_PXP_HIST16_PARAM0_RSVD3 29
- +#define BM_PXP_HIST16_PARAM0_RSVD3 0xE0000000
- +#define BF_PXP_HIST16_PARAM0_RSVD3(v) \
- + (((v) << 29) & BM_PXP_HIST16_PARAM0_RSVD3)
- +#define BP_PXP_HIST16_PARAM0_VALUE3 24
- +#define BM_PXP_HIST16_PARAM0_VALUE3 0x1F000000
- +#define BF_PXP_HIST16_PARAM0_VALUE3(v) \
- + (((v) << 24) & BM_PXP_HIST16_PARAM0_VALUE3)
- +#define BP_PXP_HIST16_PARAM0_RSVD2 21
- +#define BM_PXP_HIST16_PARAM0_RSVD2 0x00E00000
- +#define BF_PXP_HIST16_PARAM0_RSVD2(v) \
- + (((v) << 21) & BM_PXP_HIST16_PARAM0_RSVD2)
- +#define BP_PXP_HIST16_PARAM0_VALUE2 16
- +#define BM_PXP_HIST16_PARAM0_VALUE2 0x001F0000
- +#define BF_PXP_HIST16_PARAM0_VALUE2(v) \
- + (((v) << 16) & BM_PXP_HIST16_PARAM0_VALUE2)
- +#define BP_PXP_HIST16_PARAM0_RSVD1 13
- +#define BM_PXP_HIST16_PARAM0_RSVD1 0x0000E000
- +#define BF_PXP_HIST16_PARAM0_RSVD1(v) \
- + (((v) << 13) & BM_PXP_HIST16_PARAM0_RSVD1)
- +#define BP_PXP_HIST16_PARAM0_VALUE1 8
- +#define BM_PXP_HIST16_PARAM0_VALUE1 0x00001F00
- +#define BF_PXP_HIST16_PARAM0_VALUE1(v) \
- + (((v) << 8) & BM_PXP_HIST16_PARAM0_VALUE1)
- +#define BP_PXP_HIST16_PARAM0_RSVD0 5
- +#define BM_PXP_HIST16_PARAM0_RSVD0 0x000000E0
- +#define BF_PXP_HIST16_PARAM0_RSVD0(v) \
- + (((v) << 5) & BM_PXP_HIST16_PARAM0_RSVD0)
- +#define BP_PXP_HIST16_PARAM0_VALUE0 0
- +#define BM_PXP_HIST16_PARAM0_VALUE0 0x0000001F
- +#define BF_PXP_HIST16_PARAM0_VALUE0(v) \
- + (((v) << 0) & BM_PXP_HIST16_PARAM0_VALUE0)
- +
- +#define HW_PXP_HIST16_PARAM1 (0x000002f0)
- +
- +#define BP_PXP_HIST16_PARAM1_RSVD7 29
- +#define BM_PXP_HIST16_PARAM1_RSVD7 0xE0000000
- +#define BF_PXP_HIST16_PARAM1_RSVD7(v) \
- + (((v) << 29) & BM_PXP_HIST16_PARAM1_RSVD7)
- +#define BP_PXP_HIST16_PARAM1_VALUE7 24
- +#define BM_PXP_HIST16_PARAM1_VALUE7 0x1F000000
- +#define BF_PXP_HIST16_PARAM1_VALUE7(v) \
- + (((v) << 24) & BM_PXP_HIST16_PARAM1_VALUE7)
- +#define BP_PXP_HIST16_PARAM1_RSVD6 21
- +#define BM_PXP_HIST16_PARAM1_RSVD6 0x00E00000
- +#define BF_PXP_HIST16_PARAM1_RSVD6(v) \
- + (((v) << 21) & BM_PXP_HIST16_PARAM1_RSVD6)
- +#define BP_PXP_HIST16_PARAM1_VALUE6 16
- +#define BM_PXP_HIST16_PARAM1_VALUE6 0x001F0000
- +#define BF_PXP_HIST16_PARAM1_VALUE6(v) \
- + (((v) << 16) & BM_PXP_HIST16_PARAM1_VALUE6)
- +#define BP_PXP_HIST16_PARAM1_RSVD5 13
- +#define BM_PXP_HIST16_PARAM1_RSVD5 0x0000E000
- +#define BF_PXP_HIST16_PARAM1_RSVD5(v) \
- + (((v) << 13) & BM_PXP_HIST16_PARAM1_RSVD5)
- +#define BP_PXP_HIST16_PARAM1_VALUE5 8
- +#define BM_PXP_HIST16_PARAM1_VALUE5 0x00001F00
- +#define BF_PXP_HIST16_PARAM1_VALUE5(v) \
- + (((v) << 8) & BM_PXP_HIST16_PARAM1_VALUE5)
- +#define BP_PXP_HIST16_PARAM1_RSVD4 5
- +#define BM_PXP_HIST16_PARAM1_RSVD4 0x000000E0
- +#define BF_PXP_HIST16_PARAM1_RSVD4(v) \
- + (((v) << 5) & BM_PXP_HIST16_PARAM1_RSVD4)
- +#define BP_PXP_HIST16_PARAM1_VALUE4 0
- +#define BM_PXP_HIST16_PARAM1_VALUE4 0x0000001F
- +#define BF_PXP_HIST16_PARAM1_VALUE4(v) \
- + (((v) << 0) & BM_PXP_HIST16_PARAM1_VALUE4)
- +
- +#define HW_PXP_HIST16_PARAM2 (0x00000300)
- +
- +#define BP_PXP_HIST16_PARAM2_RSVD11 29
- +#define BM_PXP_HIST16_PARAM2_RSVD11 0xE0000000
- +#define BF_PXP_HIST16_PARAM2_RSVD11(v) \
- + (((v) << 29) & BM_PXP_HIST16_PARAM2_RSVD11)
- +#define BP_PXP_HIST16_PARAM2_VALUE11 24
- +#define BM_PXP_HIST16_PARAM2_VALUE11 0x1F000000
- +#define BF_PXP_HIST16_PARAM2_VALUE11(v) \
- + (((v) << 24) & BM_PXP_HIST16_PARAM2_VALUE11)
- +#define BP_PXP_HIST16_PARAM2_RSVD10 21
- +#define BM_PXP_HIST16_PARAM2_RSVD10 0x00E00000
- +#define BF_PXP_HIST16_PARAM2_RSVD10(v) \
- + (((v) << 21) & BM_PXP_HIST16_PARAM2_RSVD10)
- +#define BP_PXP_HIST16_PARAM2_VALUE10 16
- +#define BM_PXP_HIST16_PARAM2_VALUE10 0x001F0000
- +#define BF_PXP_HIST16_PARAM2_VALUE10(v) \
- + (((v) << 16) & BM_PXP_HIST16_PARAM2_VALUE10)
- +#define BP_PXP_HIST16_PARAM2_RSVD9 13
- +#define BM_PXP_HIST16_PARAM2_RSVD9 0x0000E000
- +#define BF_PXP_HIST16_PARAM2_RSVD9(v) \
- + (((v) << 13) & BM_PXP_HIST16_PARAM2_RSVD9)
- +#define BP_PXP_HIST16_PARAM2_VALUE9 8
- +#define BM_PXP_HIST16_PARAM2_VALUE9 0x00001F00
- +#define BF_PXP_HIST16_PARAM2_VALUE9(v) \
- + (((v) << 8) & BM_PXP_HIST16_PARAM2_VALUE9)
- +#define BP_PXP_HIST16_PARAM2_RSVD8 5
- +#define BM_PXP_HIST16_PARAM2_RSVD8 0x000000E0
- +#define BF_PXP_HIST16_PARAM2_RSVD8(v) \
- + (((v) << 5) & BM_PXP_HIST16_PARAM2_RSVD8)
- +#define BP_PXP_HIST16_PARAM2_VALUE8 0
- +#define BM_PXP_HIST16_PARAM2_VALUE8 0x0000001F
- +#define BF_PXP_HIST16_PARAM2_VALUE8(v) \
- + (((v) << 0) & BM_PXP_HIST16_PARAM2_VALUE8)
- +
- +#define HW_PXP_HIST16_PARAM3 (0x00000310)
- +
- +#define BP_PXP_HIST16_PARAM3_RSVD15 29
- +#define BM_PXP_HIST16_PARAM3_RSVD15 0xE0000000
- +#define BF_PXP_HIST16_PARAM3_RSVD15(v) \
- + (((v) << 29) & BM_PXP_HIST16_PARAM3_RSVD15)
- +#define BP_PXP_HIST16_PARAM3_VALUE15 24
- +#define BM_PXP_HIST16_PARAM3_VALUE15 0x1F000000
- +#define BF_PXP_HIST16_PARAM3_VALUE15(v) \
- + (((v) << 24) & BM_PXP_HIST16_PARAM3_VALUE15)
- +#define BP_PXP_HIST16_PARAM3_RSVD14 21
- +#define BM_PXP_HIST16_PARAM3_RSVD14 0x00E00000
- +#define BF_PXP_HIST16_PARAM3_RSVD14(v) \
- + (((v) << 21) & BM_PXP_HIST16_PARAM3_RSVD14)
- +#define BP_PXP_HIST16_PARAM3_VALUE14 16
- +#define BM_PXP_HIST16_PARAM3_VALUE14 0x001F0000
- +#define BF_PXP_HIST16_PARAM3_VALUE14(v) \
- + (((v) << 16) & BM_PXP_HIST16_PARAM3_VALUE14)
- +#define BP_PXP_HIST16_PARAM3_RSVD13 13
- +#define BM_PXP_HIST16_PARAM3_RSVD13 0x0000E000
- +#define BF_PXP_HIST16_PARAM3_RSVD13(v) \
- + (((v) << 13) & BM_PXP_HIST16_PARAM3_RSVD13)
- +#define BP_PXP_HIST16_PARAM3_VALUE13 8
- +#define BM_PXP_HIST16_PARAM3_VALUE13 0x00001F00
- +#define BF_PXP_HIST16_PARAM3_VALUE13(v) \
- + (((v) << 8) & BM_PXP_HIST16_PARAM3_VALUE13)
- +#define BP_PXP_HIST16_PARAM3_RSVD12 5
- +#define BM_PXP_HIST16_PARAM3_RSVD12 0x000000E0
- +#define BF_PXP_HIST16_PARAM3_RSVD12(v) \
- + (((v) << 5) & BM_PXP_HIST16_PARAM3_RSVD12)
- +#define BP_PXP_HIST16_PARAM3_VALUE12 0
- +#define BM_PXP_HIST16_PARAM3_VALUE12 0x0000001F
- +#define BF_PXP_HIST16_PARAM3_VALUE12(v) \
- + (((v) << 0) & BM_PXP_HIST16_PARAM3_VALUE12)
- +
- +#define HW_PXP_POWER (0x00000320)
- +
- +#define BP_PXP_POWER_CTRL 12
- +#define BM_PXP_POWER_CTRL 0xFFFFF000
- +#define BF_PXP_POWER_CTRL(v) \
- + (((v) << 12) & BM_PXP_POWER_CTRL)
- +#define BP_PXP_POWER_ROT_MEM_LP_STATE 9
- +#define BM_PXP_POWER_ROT_MEM_LP_STATE 0x00000E00
- +#define BF_PXP_POWER_ROT_MEM_LP_STATE(v) \
- + (((v) << 9) & BM_PXP_POWER_ROT_MEM_LP_STATE)
- +#define BV_PXP_POWER_ROT_MEM_LP_STATE__NONE 0x0
- +#define BV_PXP_POWER_ROT_MEM_LP_STATE__LS 0x1
- +#define BV_PXP_POWER_ROT_MEM_LP_STATE__DS 0x2
- +#define BV_PXP_POWER_ROT_MEM_LP_STATE__SD 0x4
- +#define BP_PXP_POWER_LUT_LP_STATE_WAY1_BANKN 6
- +#define BM_PXP_POWER_LUT_LP_STATE_WAY1_BANKN 0x000001C0
- +#define BF_PXP_POWER_LUT_LP_STATE_WAY1_BANKN(v) \
- + (((v) << 6) & BM_PXP_POWER_LUT_LP_STATE_WAY1_BANKN)
- +#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__NONE 0x0
- +#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__LS 0x1
- +#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__DS 0x2
- +#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__SD 0x4
- +#define BP_PXP_POWER_LUT_LP_STATE_WAY0_BANKN 3
- +#define BM_PXP_POWER_LUT_LP_STATE_WAY0_BANKN 0x00000038
- +#define BF_PXP_POWER_LUT_LP_STATE_WAY0_BANKN(v) \
- + (((v) << 3) & BM_PXP_POWER_LUT_LP_STATE_WAY0_BANKN)
- +#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__NONE 0x0
- +#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__LS 0x1
- +#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__DS 0x2
- +#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__SD 0x4
- +#define BP_PXP_POWER_LUT_LP_STATE_WAY0_BANK0 0
- +#define BM_PXP_POWER_LUT_LP_STATE_WAY0_BANK0 0x00000007
- +#define BF_PXP_POWER_LUT_LP_STATE_WAY0_BANK0(v) \
- + (((v) << 0) & BM_PXP_POWER_LUT_LP_STATE_WAY0_BANK0)
- +#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__NONE 0x0
- +#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__LS 0x1
- +#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__DS 0x2
- +#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__SD 0x4
- +
- +#define HW_PXP_NEXT (0x00000400)
- +
- +#define BP_PXP_NEXT_POINTER 2
- +#define BM_PXP_NEXT_POINTER 0xFFFFFFFC
- +#define BF_PXP_NEXT_POINTER(v) \
- + (((v) << 2) & BM_PXP_NEXT_POINTER)
- +#define BM_PXP_NEXT_RSVD 0x00000002
- +#define BM_PXP_NEXT_ENABLED 0x00000001
- +
- +#define HW_PXP_DEBUGCTRL (0x00000410)
- +
- +#define BP_PXP_DEBUGCTRL_RSVD 12
- +#define BM_PXP_DEBUGCTRL_RSVD 0xFFFFF000
- +#define BF_PXP_DEBUGCTRL_RSVD(v) \
- + (((v) << 12) & BM_PXP_DEBUGCTRL_RSVD)
- +#define BP_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 8
- +#define BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 0x00000F00
- +#define BF_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT(v) \
- + (((v) << 8) & BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT)
- +#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__NONE 0x0
- +#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MISS_CNT 0x1
- +#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__HIT_CNT 0x2
- +#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__LAT_CNT 0x4
- +#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MAX_LAT 0x8
- +#define BP_PXP_DEBUGCTRL_SELECT 0
- +#define BM_PXP_DEBUGCTRL_SELECT 0x000000FF
- +#define BF_PXP_DEBUGCTRL_SELECT(v) \
- + (((v) << 0) & BM_PXP_DEBUGCTRL_SELECT)
- +#define BV_PXP_DEBUGCTRL_SELECT__NONE 0x0
- +#define BV_PXP_DEBUGCTRL_SELECT__CTRL 0x1
- +#define BV_PXP_DEBUGCTRL_SELECT__PSBUF 0x2
- +#define BV_PXP_DEBUGCTRL_SELECT__PSBAX 0x3
- +#define BV_PXP_DEBUGCTRL_SELECT__PSBAY 0x4
- +#define BV_PXP_DEBUGCTRL_SELECT__ASBUF 0x5
- +#define BV_PXP_DEBUGCTRL_SELECT__ROTATION 0x6
- +#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF0 0x7
- +#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF1 0x8
- +#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF2 0x9
- +#define BV_PXP_DEBUGCTRL_SELECT__LUT_STAT 0x10
- +#define BV_PXP_DEBUGCTRL_SELECT__LUT_MISS 0x11
- +#define BV_PXP_DEBUGCTRL_SELECT__LUT_HIT 0x12
- +#define BV_PXP_DEBUGCTRL_SELECT__LUT_LAT 0x13
- +#define BV_PXP_DEBUGCTRL_SELECT__LUT_MAX_LAT 0x14
- +
- +#define HW_PXP_DEBUG (0x00000420)
- +
- +#define BP_PXP_DEBUG_DATA 0
- +#define BM_PXP_DEBUG_DATA 0xFFFFFFFF
- +#define BF_PXP_DEBUG_DATA(v) (v)
- +
- +#define HW_PXP_VERSION (0x00000430)
- +
- +#define BP_PXP_VERSION_MAJOR 24
- +#define BM_PXP_VERSION_MAJOR 0xFF000000
- +#define BF_PXP_VERSION_MAJOR(v) \
- + (((v) << 24) & BM_PXP_VERSION_MAJOR)
- +#define BP_PXP_VERSION_MINOR 16
- +#define BM_PXP_VERSION_MINOR 0x00FF0000
- +#define BF_PXP_VERSION_MINOR(v) \
- + (((v) << 16) & BM_PXP_VERSION_MINOR)
- +#define BP_PXP_VERSION_STEP 0
- +#define BM_PXP_VERSION_STEP 0x0000FFFF
- +#define BF_PXP_VERSION_STEP(v) \
- + (((v) << 0) & BM_PXP_VERSION_STEP)
- +#endif /* __ARCH_ARM___PXP_H */
- diff -Nur linux-3.14.35.orig/drivers/gpio/gpio-pca953x.c linux-3.14.35/drivers/gpio/gpio-pca953x.c
- --- linux-3.14.35.orig/drivers/gpio/gpio-pca953x.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/gpio/gpio-pca953x.c 2015-03-08 14:27:37.549684501 -0500
- @@ -19,6 +19,7 @@
- #include <linux/irqdomain.h>
- #include <linux/i2c.h>
- #include <linux/platform_data/pca953x.h>
- +#include <linux/reset.h>
- #include <linux/slab.h>
- #ifdef CONFIG_OF_GPIO
- #include <linux/of_platform.h>
- @@ -741,6 +742,10 @@
-
- mutex_init(&chip->i2c_lock);
-
- + ret = device_reset(&client->dev);
- + if (ret == -ENODEV)
- + return -EPROBE_DEFER;
- +
- /* initialize cached registers from their original values.
- * we can't share this chip with another i2c master.
- */
- diff -Nur linux-3.14.35.orig/drivers/gpu/drm/drm_crtc_helper.c linux-3.14.35/drivers/gpu/drm/drm_crtc_helper.c
- --- linux-3.14.35.orig/drivers/gpu/drm/drm_crtc_helper.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/gpu/drm/drm_crtc_helper.c 2015-03-08 14:27:37.549684501 -0500
- @@ -564,7 +564,7 @@
- * Caller must hold mode config lock.
- *
- * Setup a new configuration, provided by the upper layers (either an ioctl call
- - * from userspace or internally e.g. from the fbdev suppport code) in @set, and
- + * from userspace or internally e.g. from the fbdev support code) in @set, and
- * enable it. This is the main helper functions for drivers that implement
- * kernel mode setting with the crtc helper functions and the assorted
- * ->prepare(), ->modeset() and ->commit() helper callbacks.
- diff -Nur linux-3.14.35.orig/drivers/gpu/drm/drm_prime.c linux-3.14.35/drivers/gpu/drm/drm_prime.c
- --- linux-3.14.35.orig/drivers/gpu/drm/drm_prime.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/gpu/drm/drm_prime.c 2015-03-08 14:27:37.553684501 -0500
- @@ -471,7 +471,7 @@
- get_dma_buf(dma_buf);
-
- sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
- - if (IS_ERR_OR_NULL(sgt)) {
- + if (IS_ERR(sgt)) {
- ret = PTR_ERR(sgt);
- goto fail_detach;
- }
- diff -Nur linux-3.14.35.orig/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c linux-3.14.35/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
- --- linux-3.14.35.orig/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c 2015-03-08 14:27:37.553684501 -0500
- @@ -224,7 +224,7 @@
- get_dma_buf(dma_buf);
-
- sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
- - if (IS_ERR_OR_NULL(sgt)) {
- + if (IS_ERR(sgt)) {
- ret = PTR_ERR(sgt);
- goto err_buf_detach;
- }
- diff -Nur linux-3.14.35.orig/drivers/gpu/drm/Kconfig linux-3.14.35/drivers/gpu/drm/Kconfig
- --- linux-3.14.35.orig/drivers/gpu/drm/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/gpu/drm/Kconfig 2015-03-08 14:27:37.553684501 -0500
- @@ -166,6 +166,13 @@
- Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
- chipset. If M is selected the module will be called savage.
-
- +config DRM_VIVANTE
- + tristate "Vivante GCCore"
- + depends on DRM
- + help
- + Choose this option if you have a Vivante graphics card.
- + If M is selected, the module will be called vivante.
- +
- source "drivers/gpu/drm/exynos/Kconfig"
-
- source "drivers/gpu/drm/vmwgfx/Kconfig"
- diff -Nur linux-3.14.35.orig/drivers/gpu/drm/Makefile linux-3.14.35/drivers/gpu/drm/Makefile
- --- linux-3.14.35.orig/drivers/gpu/drm/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/gpu/drm/Makefile 2015-03-08 14:27:37.553684501 -0500
- @@ -1,3 +1,24 @@
- +##############################################################################
- +#
- +# Copyright (C) 2005 - 2013 by Vivante Corp.
- +#
- +# 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 program is distributed in the hope that it will be useful,
- +# but WITHOUT ANY WARRANTY; without even the implied warranty of
- +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +# GNU General Public License for more details.
- +#
- +# 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.
- +#
- +##############################################################################
- +
- +
- #
- # Makefile for the drm device driver. This driver provides support for the
- # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
- @@ -35,6 +56,7 @@
- obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o
- obj-$(CONFIG_DRM_USB) += drm_usb.o
- obj-$(CONFIG_DRM_TTM) += ttm/
- +obj-$(CONFIG_DRM_VIVANTE) += vivante/
- obj-$(CONFIG_DRM_TDFX) += tdfx/
- obj-$(CONFIG_DRM_R128) += r128/
- obj-$(CONFIG_DRM_RADEON)+= radeon/
- diff -Nur linux-3.14.35.orig/drivers/gpu/drm/vivante/Makefile linux-3.14.35/drivers/gpu/drm/vivante/Makefile
- --- linux-3.14.35.orig/drivers/gpu/drm/vivante/Makefile 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/gpu/drm/vivante/Makefile 2015-03-08 14:27:37.553684501 -0500
- @@ -0,0 +1,29 @@
- +##############################################################################
- +#
- +# Copyright (C) 2005 - 2013 by Vivante Corp.
- +#
- +# 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 program is distributed in the hope that it will be useful,
- +# but WITHOUT ANY WARRANTY; without even the implied warranty of
- +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +# GNU General Public License for more details.
- +#
- +# 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.
- +#
- +##############################################################################
- +
- +
- +#
- +# Makefile for the drm device driver. This driver provides support for the
- +# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
- +
- +ccflags-y := -Iinclude/drm
- +vivante-y := vivante_drv.o
- +
- +obj-$(CONFIG_DRM_VIVANTE) += vivante.o
- diff -Nur linux-3.14.35.orig/drivers/gpu/drm/vivante/vivante_drv.c linux-3.14.35/drivers/gpu/drm/vivante/vivante_drv.c
- --- linux-3.14.35.orig/drivers/gpu/drm/vivante/vivante_drv.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/gpu/drm/vivante/vivante_drv.c 2015-03-08 14:27:37.553684501 -0500
- @@ -0,0 +1,108 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +/* vivante_drv.c -- vivante driver -*- linux-c -*-
- + *
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice (including the next
- + * paragraph) shall be included in all copies or substantial portions of the
- + * Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- + * DEALINGS IN THE SOFTWARE.
- + *
- + * Authors:
- + * Rickard E. (Rik) Faith <faith@valinux.com>
- + * Daryll Strauss <daryll@valinux.com>
- + * Gareth Hughes <gareth@valinux.com>
- + */
- +
- +#include <linux/version.h>
- +#include <linux/module.h>
- +
- +#include "drmP.h"
- +#include "vivante_drv.h"
- +
- +#include "drm_pciids.h"
- +
- +static char platformdevicename[] = "Vivante GCCore";
- +static struct platform_device *pplatformdev;
- +
- +static const struct file_operations viv_driver_fops = {
- + .owner = THIS_MODULE,
- + .open = drm_open,
- + .release = drm_release,
- + .unlocked_ioctl = drm_ioctl,
- + .mmap = drm_mmap,
- + .poll = drm_poll,
- + .llseek = noop_llseek,
- +};
- +
- +static struct drm_driver driver = {
- + .fops = &viv_driver_fops,
- + .name = DRIVER_NAME,
- + .desc = DRIVER_DESC,
- + .date = DRIVER_DATE,
- + .major = DRIVER_MAJOR,
- + .minor = DRIVER_MINOR,
- + .patchlevel = DRIVER_PATCHLEVEL,
- +};
- +
- +static int __init vivante_init(void)
- +{
- + int retcode;
- +
- + pplatformdev = platform_device_register_simple(platformdevicename,
- + -1, NULL, 0);
- + if (pplatformdev == NULL)
- + printk(KERN_ERR"Platform device is null\n");
- +
- + retcode = drm_platform_init(&driver, pplatformdev);
- +
- + return retcode;
- +}
- +
- +static void __exit vivante_exit(void)
- +{
- + if (pplatformdev) {
- + platform_device_unregister(pplatformdev);
- + pplatformdev = NULL;
- + }
- +}
- +
- +module_init(vivante_init);
- +module_exit(vivante_exit);
- +
- +MODULE_AUTHOR(DRIVER_AUTHOR);
- +MODULE_DESCRIPTION(DRIVER_DESC);
- +MODULE_LICENSE("GPL and additional rights");
- diff -Nur linux-3.14.35.orig/drivers/gpu/drm/vivante/vivante_drv.h linux-3.14.35/drivers/gpu/drm/vivante/vivante_drv.h
- --- linux-3.14.35.orig/drivers/gpu/drm/vivante/vivante_drv.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/gpu/drm/vivante/vivante_drv.h 2015-03-08 14:27:37.553684501 -0500
- @@ -0,0 +1,66 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +/* vivante_drv.h -- Vivante DRM template customization -*- linux-c -*-
- + * Created: Wed Feb 14 12:32:32 2012 by John Zhao
- + */
- +/*
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a
- + * copy of this software and associated documentation files (the "Software"),
- + * to deal in the Software without restriction, including without limitation
- + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- + * and/or sell copies of the Software, and to permit persons to whom the
- + * Software is furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice (including the next
- + * paragraph) shall be included in all copies or substantial portions of the
- + * Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- + * OTHER DEALINGS IN THE SOFTWARE.
- + *
- + * Authors:
- + * Gareth Hughes <gareth@valinux.com>
- + */
- +
- +#ifndef __VIVANTE_DRV_H__
- +#define __VIVANTE_DRV_H__
- +
- +/* General customization:
- + */
- +
- +#define DRIVER_AUTHOR "Vivante Inc."
- +
- +#define DRIVER_NAME "vivante"
- +#define DRIVER_DESC "Vivante GCCore"
- +#define DRIVER_DATE "20120216"
- +
- +#define DRIVER_MAJOR 1
- +#define DRIVER_MINOR 0
- +#define DRIVER_PATCHLEVEL 0
- +
- +#endif
- diff -Nur linux-3.14.35.orig/drivers/hwmon/Kconfig linux-3.14.35/drivers/hwmon/Kconfig
- --- linux-3.14.35.orig/drivers/hwmon/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/hwmon/Kconfig 2015-03-08 14:27:37.557684501 -0500
- @@ -1584,4 +1584,19 @@
-
- endif # ACPI
-
- +config SENSORS_MAG3110
- + tristate "Freescale MAG3110 e-compass sensor"
- + depends on I2C && SYSFS
- + help
- + If you say yes here you get support for the Freescale MAG3110
- + e-compass sensor.
- + This driver can also be built as a module. If so, the module
- + will be called mag3110.
- +
- +config MXC_MMA8451
- + tristate "MMA8451 device driver"
- + depends on I2C
- + depends on INPUT_POLLDEV
- + default y
- +
- endif # HWMON
- diff -Nur linux-3.14.35.orig/drivers/hwmon/mag3110.c linux-3.14.35/drivers/hwmon/mag3110.c
- --- linux-3.14.35.orig/drivers/hwmon/mag3110.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/hwmon/mag3110.c 2015-03-08 14:27:37.557684501 -0500
- @@ -0,0 +1,611 @@
- +/*
- + *
- + * Copyright (C) 2011-2013 Freescale Semiconductor, 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/slab.h>
- +#include <linux/interrupt.h>
- +#include <linux/delay.h>
- +#include <linux/i2c.h>
- +#include <linux/irq.h>
- +#include <linux/platform_device.h>
- +#include <linux/input-polldev.h>
- +#include <linux/hwmon.h>
- +#include <linux/input.h>
- +#include <linux/wait.h>
- +#include <linux/workqueue.h>
- +#include <linux/of.h>
- +#include <linux/regulator/consumer.h>
- +
- +#define MAG3110_DRV_NAME "mag3110"
- +#define MAG3110_ID 0xC4
- +#define MAG3110_XYZ_DATA_LEN 6
- +#define MAG3110_STATUS_ZYXDR 0x08
- +
- +#define MAG3110_AC_MASK (0x01)
- +#define MAG3110_AC_OFFSET 0
- +#define MAG3110_DR_MODE_MASK (0x7 << 5)
- +#define MAG3110_DR_MODE_OFFSET 5
- +#define MAG3110_IRQ_USED 0
- +
- +#define POLL_INTERVAL_MAX 500
- +#define POLL_INTERVAL 100
- +#define INT_TIMEOUT 1000
- +#define DEFAULT_POSITION 2
- +/* register enum for mag3110 registers */
- +enum {
- + MAG3110_DR_STATUS = 0x00,
- + MAG3110_OUT_X_MSB,
- + MAG3110_OUT_X_LSB,
- + MAG3110_OUT_Y_MSB,
- + MAG3110_OUT_Y_LSB,
- + MAG3110_OUT_Z_MSB,
- + MAG3110_OUT_Z_LSB,
- + MAG3110_WHO_AM_I,
- +
- + MAG3110_OFF_X_MSB,
- + MAG3110_OFF_X_LSB,
- + MAG3110_OFF_Y_MSB,
- + MAG3110_OFF_Y_LSB,
- + MAG3110_OFF_Z_MSB,
- + MAG3110_OFF_Z_LSB,
- +
- + MAG3110_DIE_TEMP,
- +
- + MAG3110_CTRL_REG1 = 0x10,
- + MAG3110_CTRL_REG2,
- +};
- +enum {
- + MAG_STANDBY,
- + MAG_ACTIVED
- +};
- +struct mag3110_data {
- + struct i2c_client *client;
- + struct input_polled_dev *poll_dev;
- + struct device *hwmon_dev;
- + wait_queue_head_t waitq;
- + bool data_ready;
- + u8 ctl_reg1;
- + int active;
- + int position;
- +};
- +static short MAGHAL[8][3][3] = {
- + { {0, 1, 0}, {-1, 0, 0}, {0, 0, 1} },
- + { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} },
- + { {0, -1, 0}, {1, 0, 0}, {0, 0, 1} },
- + { {-1, 0, 0}, {0, -1, 0}, {0, 0, 1} },
- +
- + { {0, 1, 0}, {1, 0, 0}, {0, 0, -1} },
- + { {1, 0, 0}, {0, -1, 0}, {0, 0, -1} },
- + { {0, -1, 0}, {-1, 0, 0}, {0, 0, -1} },
- + { {-1, 0, 0}, {0, 1, 0}, {0, 0, -1} },
- +};
- +
- +static struct mag3110_data *mag3110_pdata;
- +/*!
- + * This function do one mag3110 register read.
- + */
- +static DEFINE_MUTEX(mag3110_lock);
- +static int mag3110_adjust_position(short *x, short *y, short *z)
- +{
- + short rawdata[3], data[3];
- + int i, j;
- + int position = mag3110_pdata->position;
- + if (position < 0 || position > 7)
- + position = 0;
- + rawdata[0] = *x;
- + rawdata[1] = *y;
- + rawdata[2] = *z;
- + for (i = 0; i < 3; i++) {
- + data[i] = 0;
- + for (j = 0; j < 3; j++)
- + data[i] += rawdata[j] * MAGHAL[position][i][j];
- + }
- + *x = data[0];
- + *y = data[1];
- + *z = data[2];
- + return 0;
- +}
- +
- +static int mag3110_read_reg(struct i2c_client *client, u8 reg)
- +{
- + return i2c_smbus_read_byte_data(client, reg);
- +}
- +
- +/*!
- + * This function do one mag3110 register write.
- + */
- +static int mag3110_write_reg(struct i2c_client *client, u8 reg, char value)
- +{
- + int ret;
- +
- + ret = i2c_smbus_write_byte_data(client, reg, value);
- + if (ret < 0)
- + dev_err(&client->dev, "i2c write failed\n");
- + return ret;
- +}
- +
- +/*!
- + * This function do multiple mag3110 registers read.
- + */
- +static int mag3110_read_block_data(struct i2c_client *client, u8 reg,
- + int count, u8 *addr)
- +{
- + if (i2c_smbus_read_i2c_block_data(client, reg, count, addr) < count) {
- + dev_err(&client->dev, "i2c block read failed\n");
- + return -1;
- + }
- +
- + return count;
- +}
- +
- +/*
- + * Initialization function
- + */
- +static int mag3110_init_client(struct i2c_client *client)
- +{
- + int val, ret;
- +
- + /* enable automatic resets */
- + val = 0x80;
- + ret = mag3110_write_reg(client, MAG3110_CTRL_REG2, val);
- +
- + /* set default data rate to 10HZ */
- + val = mag3110_read_reg(client, MAG3110_CTRL_REG1);
- + val |= (0x0 << MAG3110_DR_MODE_OFFSET);
- + ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, val);
- +
- + return ret;
- +}
- +
- +/***************************************************************
- +*
- +* read sensor data from mag3110
- +*
- +***************************************************************/
- +static int mag3110_read_data(short *x, short *y, short *z)
- +{
- + struct mag3110_data *data;
- + int retry = 3;
- + u8 tmp_data[MAG3110_XYZ_DATA_LEN];
- + int result;
- + if (!mag3110_pdata || mag3110_pdata->active == MAG_STANDBY)
- + return -EINVAL;
- +
- + data = mag3110_pdata;
- +#if MAG3110_IRQ_USED
- + if (!wait_event_interruptible_timeout
- + (data->waitq, data->data_ready != 0,
- + msecs_to_jiffies(INT_TIMEOUT))) {
- + dev_dbg(&data->client->dev, "interrupt not received\n");
- + return -ETIME;
- + }
- +#else
- + do {
- + msleep(1);
- + result = i2c_smbus_read_byte_data(data->client,
- + MAG3110_DR_STATUS);
- + retry--;
- + } while (!(result & MAG3110_STATUS_ZYXDR) && retry > 0);
- + /* Clear data_ready flag after data is read out */
- + if (retry == 0)
- + return -EINVAL;
- +#endif
- +
- + data->data_ready = 0;
- +
- + if (mag3110_read_block_data(data->client,
- + MAG3110_OUT_X_MSB, MAG3110_XYZ_DATA_LEN,
- + tmp_data) < 0)
- + return -1;
- +
- + *x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1];
- + *y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3];
- + *z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5];
- +
- + return 0;
- +}
- +
- +static void report_abs(void)
- +{
- + struct input_dev *idev;
- + short x, y, z;
- +
- + mutex_lock(&mag3110_lock);
- + if (mag3110_read_data(&x, &y, &z) != 0)
- + goto out;
- + mag3110_adjust_position(&x, &y, &z);
- + idev = mag3110_pdata->poll_dev->input;
- + input_report_abs(idev, ABS_X, x);
- + input_report_abs(idev, ABS_Y, y);
- + input_report_abs(idev, ABS_Z, z);
- + input_sync(idev);
- +out:
- + mutex_unlock(&mag3110_lock);
- +}
- +
- +static void mag3110_dev_poll(struct input_polled_dev *dev)
- +{
- + report_abs();
- +}
- +
- +#if MAG3110_IRQ_USED
- +static irqreturn_t mag3110_irq_handler(int irq, void *dev_id)
- +{
- + mag3110_pdata->data_ready = 1;
- + wake_up_interruptible(&mag3110_pdata->waitq);
- +
- + return IRQ_HANDLED;
- +}
- +#endif
- +static ssize_t mag3110_enable_show(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + struct i2c_client *client;
- + int val;
- + mutex_lock(&mag3110_lock);
- + client = mag3110_pdata->client;
- + val = mag3110_read_reg(client, MAG3110_CTRL_REG1) & MAG3110_AC_MASK;
- +
- + mutex_unlock(&mag3110_lock);
- + return sprintf(buf, "%d\n", val);
- +}
- +
- +static ssize_t mag3110_enable_store(struct device *dev,
- + struct device_attribute *attr,
- + const char *buf, size_t count)
- +{
- + struct i2c_client *client;
- + int reg, ret;
- + long enable;
- + u8 tmp_data[MAG3110_XYZ_DATA_LEN];
- +
- + ret = strict_strtol(buf, 10, &enable);
- + if (ret) {
- + dev_err(dev, "string to long error\n");
- + return ret;
- + }
- +
- + mutex_lock(&mag3110_lock);
- + client = mag3110_pdata->client;
- + reg = mag3110_read_reg(client, MAG3110_CTRL_REG1);
- + if (enable && mag3110_pdata->active == MAG_STANDBY) {
- + reg |= MAG3110_AC_MASK;
- + ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg);
- + if (!ret)
- + mag3110_pdata->active = MAG_ACTIVED;
- + } else if (!enable && mag3110_pdata->active == MAG_ACTIVED) {
- + reg &= ~MAG3110_AC_MASK;
- + ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg);
- + if (!ret)
- + mag3110_pdata->active = MAG_STANDBY;
- + }
- +
- + if (mag3110_pdata->active == MAG_ACTIVED) {
- + msleep(100);
- + /* Read out MSB data to clear interrupt flag automatically */
- + mag3110_read_block_data(client, MAG3110_OUT_X_MSB,
- + MAG3110_XYZ_DATA_LEN, tmp_data);
- + }
- + mutex_unlock(&mag3110_lock);
- + return count;
- +}
- +
- +static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
- + mag3110_enable_show, mag3110_enable_store);
- +
- +static ssize_t mag3110_dr_mode_show(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + struct i2c_client *client;
- + int val;
- +
- + client = mag3110_pdata->client;
- + val = (mag3110_read_reg(client, MAG3110_CTRL_REG1)
- + & MAG3110_DR_MODE_MASK) >> MAG3110_DR_MODE_OFFSET;
- +
- + return sprintf(buf, "%d\n", val);
- +}
- +
- +static ssize_t mag3110_dr_mode_store(struct device *dev,
- + struct device_attribute *attr,
- + const char *buf, size_t count)
- +{
- + struct i2c_client *client;
- + int reg, ret;
- + unsigned long val;
- +
- + /* This must be done when mag3110 is disabled */
- + if ((strict_strtoul(buf, 10, &val) < 0) || (val > 7))
- + return -EINVAL;
- +
- + client = mag3110_pdata->client;
- + reg = mag3110_read_reg(client, MAG3110_CTRL_REG1) &
- + ~MAG3110_DR_MODE_MASK;
- + reg |= (val << MAG3110_DR_MODE_OFFSET);
- + /* MAG3110_CTRL_REG1 bit 5-7: data rate mode */
- + ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg);
- + if (ret < 0)
- + return ret;
- +
- + return count;
- +}
- +
- +static DEVICE_ATTR(dr_mode, S_IWUSR | S_IRUGO,
- + mag3110_dr_mode_show, mag3110_dr_mode_store);
- +
- +static ssize_t mag3110_position_show(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + int val;
- + mutex_lock(&mag3110_lock);
- + val = mag3110_pdata->position;
- + mutex_unlock(&mag3110_lock);
- + return sprintf(buf, "%d\n", val);
- +}
- +
- +static ssize_t mag3110_position_store(struct device *dev,
- + struct device_attribute *attr,
- + const char *buf, size_t count)
- +{
- + long position;
- + int ret;
- + ret = strict_strtol(buf, 10, &position);
- + if (ret) {
- + dev_err(dev, "string to long error\n");
- + return ret;
- + }
- +
- + mutex_lock(&mag3110_lock);
- + mag3110_pdata->position = (int)position;
- + mutex_unlock(&mag3110_lock);
- + return count;
- +}
- +
- +static DEVICE_ATTR(position, S_IWUSR | S_IRUGO,
- + mag3110_position_show, mag3110_position_store);
- +
- +static struct attribute *mag3110_attributes[] = {
- + &dev_attr_enable.attr,
- + &dev_attr_dr_mode.attr,
- + &dev_attr_position.attr,
- + NULL
- +};
- +
- +static const struct attribute_group mag3110_attr_group = {
- + .attrs = mag3110_attributes,
- +};
- +
- +static int mag3110_probe(struct i2c_client *client,
- + const struct i2c_device_id *id)
- +{
- + struct i2c_adapter *adapter;
- + struct input_dev *idev;
- + struct mag3110_data *data;
- + int ret = 0;
- + struct regulator *vdd, *vdd_io;
- + u32 pos = 0;
- + struct device_node *of_node = client->dev.of_node;
- + vdd = NULL;
- + vdd_io = NULL;
- +
- + vdd = devm_regulator_get(&client->dev, "vdd");
- + if (!IS_ERR(vdd)) {
- + ret = regulator_enable(vdd);
- + if (ret) {
- + dev_err(&client->dev, "vdd set voltage error\n");
- + return ret;
- + }
- + }
- +
- + vdd_io = devm_regulator_get(&client->dev, "vddio");
- + if (!IS_ERR(vdd_io)) {
- + ret = regulator_enable(vdd_io);
- + if (ret) {
- + dev_err(&client->dev, "vddio set voltage error\n");
- + return ret;
- + }
- + }
- +
- + adapter = to_i2c_adapter(client->dev.parent);
- + if (!i2c_check_functionality(adapter,
- + I2C_FUNC_SMBUS_BYTE |
- + I2C_FUNC_SMBUS_BYTE_DATA |
- + I2C_FUNC_SMBUS_I2C_BLOCK))
- + return -EIO;
- +
- + dev_info(&client->dev, "check mag3110 chip ID\n");
- + ret = mag3110_read_reg(client, MAG3110_WHO_AM_I);
- +
- + if (MAG3110_ID != ret) {
- + dev_err(&client->dev,
- + "read chip ID 0x%x is not equal to 0x%x!\n", ret,
- + MAG3110_ID);
- + return -EINVAL;
- + }
- + data = kzalloc(sizeof(struct mag3110_data), GFP_KERNEL);
- + if (!data)
- + return -ENOMEM;
- + data->client = client;
- + i2c_set_clientdata(client, data);
- + /* Init queue */
- + init_waitqueue_head(&data->waitq);
- +
- + data->hwmon_dev = hwmon_device_register(&client->dev);
- + if (IS_ERR(data->hwmon_dev)) {
- + dev_err(&client->dev, "hwmon register failed!\n");
- + ret = PTR_ERR(data->hwmon_dev);
- + goto error_rm_dev_sysfs;
- + }
- +
- + /*input poll device register */
- + data->poll_dev = input_allocate_polled_device();
- + if (!data->poll_dev) {
- + dev_err(&client->dev, "alloc poll device failed!\n");
- + ret = -ENOMEM;
- + goto error_rm_hwmon_dev;
- + }
- + data->poll_dev->poll = mag3110_dev_poll;
- + data->poll_dev->poll_interval = POLL_INTERVAL;
- + data->poll_dev->poll_interval_max = POLL_INTERVAL_MAX;
- + idev = data->poll_dev->input;
- + idev->name = MAG3110_DRV_NAME;
- + idev->id.bustype = BUS_I2C;
- + idev->evbit[0] = BIT_MASK(EV_ABS);
- + input_set_abs_params(idev, ABS_X, -15000, 15000, 0, 0);
- + input_set_abs_params(idev, ABS_Y, -15000, 15000, 0, 0);
- + input_set_abs_params(idev, ABS_Z, -15000, 15000, 0, 0);
- + ret = input_register_polled_device(data->poll_dev);
- + if (ret) {
- + dev_err(&client->dev, "register poll device failed!\n");
- + goto error_free_poll_dev;
- + }
- +
- + /*create device group in sysfs as user interface */
- + ret = sysfs_create_group(&idev->dev.kobj, &mag3110_attr_group);
- + if (ret) {
- + dev_err(&client->dev, "create device file failed!\n");
- + ret = -EINVAL;
- + goto error_rm_poll_dev;
- + }
- + /* set irq type to edge rising */
- +#if MAG3110_IRQ_USED
- + ret = request_irq(client->irq, mag3110_irq_handler,
- + IRQF_TRIGGER_RISING, client->dev.driver->name, idev);
- + if (ret < 0) {
- + dev_err(&client->dev, "failed to register irq %d!\n",
- + client->irq);
- + goto error_rm_dev_sysfs;
- + }
- +#endif
- + /* Initialize mag3110 chip */
- + mag3110_init_client(client);
- + mag3110_pdata = data;
- + mag3110_pdata->active = MAG_STANDBY;
- + ret = of_property_read_u32(of_node, "position", &pos);
- + if (ret)
- + pos = DEFAULT_POSITION;
- + mag3110_pdata->position = (int)pos;
- + dev_info(&client->dev, "mag3110 is probed\n");
- + return 0;
- +error_rm_dev_sysfs:
- + sysfs_remove_group(&client->dev.kobj, &mag3110_attr_group);
- +error_rm_poll_dev:
- + input_unregister_polled_device(data->poll_dev);
- +error_free_poll_dev:
- + input_free_polled_device(data->poll_dev);
- +error_rm_hwmon_dev:
- + hwmon_device_unregister(data->hwmon_dev);
- +
- + kfree(data);
- + mag3110_pdata = NULL;
- +
- + return ret;
- +}
- +
- +static int mag3110_remove(struct i2c_client *client)
- +{
- + struct mag3110_data *data;
- + int ret;
- +
- + data = i2c_get_clientdata(client);
- +
- + data->ctl_reg1 = mag3110_read_reg(client, MAG3110_CTRL_REG1);
- + ret = mag3110_write_reg(client, MAG3110_CTRL_REG1,
- + data->ctl_reg1 & ~MAG3110_AC_MASK);
- +
- + free_irq(client->irq, data);
- + input_unregister_polled_device(data->poll_dev);
- + input_free_polled_device(data->poll_dev);
- + hwmon_device_unregister(data->hwmon_dev);
- + sysfs_remove_group(&client->dev.kobj, &mag3110_attr_group);
- + kfree(data);
- + mag3110_pdata = NULL;
- +
- + return ret;
- +}
- +
- +#ifdef CONFIG_PM
- +static int mag3110_suspend(struct i2c_client *client, pm_message_t mesg)
- +{
- + int ret = 0;
- + struct mag3110_data *data = i2c_get_clientdata(client);
- + if (data->active == MAG_ACTIVED) {
- + data->ctl_reg1 = mag3110_read_reg(client, MAG3110_CTRL_REG1);
- + ret = mag3110_write_reg(client, MAG3110_CTRL_REG1,
- + data->ctl_reg1 & ~MAG3110_AC_MASK);
- + }
- + return ret;
- +}
- +
- +static int mag3110_resume(struct i2c_client *client)
- +{
- + int ret = 0;
- + u8 tmp_data[MAG3110_XYZ_DATA_LEN];
- + struct mag3110_data *data = i2c_get_clientdata(client);
- + if (data->active == MAG_ACTIVED) {
- + ret = mag3110_write_reg(client, MAG3110_CTRL_REG1,
- + data->ctl_reg1);
- +
- + if (data->ctl_reg1 & MAG3110_AC_MASK) {
- + /* Read out MSB data to clear interrupt
- + flag automatically */
- + mag3110_read_block_data(client, MAG3110_OUT_X_MSB,
- + MAG3110_XYZ_DATA_LEN, tmp_data);
- + }
- + }
- + return ret;
- +}
- +
- +#else
- +#define mag3110_suspend NULL
- +#define mag3110_resume NULL
- +#endif /* CONFIG_PM */
- +
- +static const struct i2c_device_id mag3110_id[] = {
- + {MAG3110_DRV_NAME, 0},
- + {}
- +};
- +
- +MODULE_DEVICE_TABLE(i2c, mag3110_id);
- +static struct i2c_driver mag3110_driver = {
- + .driver = {.name = MAG3110_DRV_NAME,
- + .owner = THIS_MODULE,},
- + .suspend = mag3110_suspend,
- + .resume = mag3110_resume,
- + .probe = mag3110_probe,
- + .remove = mag3110_remove,
- + .id_table = mag3110_id,
- +};
- +
- +static int __init mag3110_init(void)
- +{
- + return i2c_add_driver(&mag3110_driver);
- +}
- +
- +static void __exit mag3110_exit(void)
- +{
- + i2c_del_driver(&mag3110_driver);
- +}
- +
- +module_init(mag3110_init);
- +module_exit(mag3110_exit);
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("Freescale mag3110 3-axis magnetometer driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/hwmon/Makefile linux-3.14.35/drivers/hwmon/Makefile
- --- linux-3.14.35.orig/drivers/hwmon/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/hwmon/Makefile 2015-03-08 14:27:37.557684501 -0500
- @@ -142,6 +142,8 @@
- obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o
- obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o
- obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o
- +obj-$(CONFIG_SENSORS_MAG3110) += mag3110.o
- +obj-$(CONFIG_MXC_MMA8451) += mxc_mma8451.o
-
- obj-$(CONFIG_PMBUS) += pmbus/
-
- diff -Nur linux-3.14.35.orig/drivers/hwmon/mxc_mma8451.c linux-3.14.35/drivers/hwmon/mxc_mma8451.c
- --- linux-3.14.35.orig/drivers/hwmon/mxc_mma8451.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/hwmon/mxc_mma8451.c 2015-03-08 14:27:37.557684501 -0500
- @@ -0,0 +1,598 @@
- +/*
- + * mma8451.c - Linux kernel modules for 3-Axis Orientation/Motion
- + * Detection Sensor
- + *
- + * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/init.h>
- +#include <linux/slab.h>
- +#include <linux/i2c.h>
- +#include <linux/pm.h>
- +#include <linux/mutex.h>
- +#include <linux/delay.h>
- +#include <linux/interrupt.h>
- +#include <linux/irq.h>
- +#include <linux/hwmon-sysfs.h>
- +#include <linux/err.h>
- +#include <linux/hwmon.h>
- +#include <linux/input-polldev.h>
- +#include <linux/of.h>
- +#include <linux/regulator/consumer.h>
- +
- +#define MMA8451_I2C_ADDR 0x1C
- +#define MMA8451_ID 0x1A
- +#define MMA8452_ID 0x2A
- +#define MMA8453_ID 0x3A
- +
- +#define POLL_INTERVAL_MIN 1
- +#define POLL_INTERVAL_MAX 500
- +#define POLL_INTERVAL 100 /* msecs */
- +#define INPUT_FUZZ 32
- +#define INPUT_FLAT 32
- +#define MODE_CHANGE_DELAY_MS 100
- +
- +#define MMA8451_STATUS_ZYXDR 0x08
- +#define MMA8451_BUF_SIZE 7
- +#define DEFAULT_POSITION 0
- +
- +/* register enum for mma8451 registers */
- +enum {
- + MMA8451_STATUS = 0x00,
- + MMA8451_OUT_X_MSB,
- + MMA8451_OUT_X_LSB,
- + MMA8451_OUT_Y_MSB,
- + MMA8451_OUT_Y_LSB,
- + MMA8451_OUT_Z_MSB,
- + MMA8451_OUT_Z_LSB,
- +
- + MMA8451_F_SETUP = 0x09,
- + MMA8451_TRIG_CFG,
- + MMA8451_SYSMOD,
- + MMA8451_INT_SOURCE,
- + MMA8451_WHO_AM_I,
- + MMA8451_XYZ_DATA_CFG,
- + MMA8451_HP_FILTER_CUTOFF,
- +
- + MMA8451_PL_STATUS,
- + MMA8451_PL_CFG,
- + MMA8451_PL_COUNT,
- + MMA8451_PL_BF_ZCOMP,
- + MMA8451_P_L_THS_REG,
- +
- + MMA8451_FF_MT_CFG,
- + MMA8451_FF_MT_SRC,
- + MMA8451_FF_MT_THS,
- + MMA8451_FF_MT_COUNT,
- +
- + MMA8451_TRANSIENT_CFG = 0x1D,
- + MMA8451_TRANSIENT_SRC,
- + MMA8451_TRANSIENT_THS,
- + MMA8451_TRANSIENT_COUNT,
- +
- + MMA8451_PULSE_CFG,
- + MMA8451_PULSE_SRC,
- + MMA8451_PULSE_THSX,
- + MMA8451_PULSE_THSY,
- + MMA8451_PULSE_THSZ,
- + MMA8451_PULSE_TMLT,
- + MMA8451_PULSE_LTCY,
- + MMA8451_PULSE_WIND,
- +
- + MMA8451_ASLP_COUNT,
- + MMA8451_CTRL_REG1,
- + MMA8451_CTRL_REG2,
- + MMA8451_CTRL_REG3,
- + MMA8451_CTRL_REG4,
- + MMA8451_CTRL_REG5,
- +
- + MMA8451_OFF_X,
- + MMA8451_OFF_Y,
- + MMA8451_OFF_Z,
- +
- + MMA8451_REG_END,
- +};
- +
- +/* The sensitivity is represented in counts/g. In 2g mode the
- +sensitivity is 1024 counts/g. In 4g mode the sensitivity is 512
- +counts/g and in 8g mode the sensitivity is 256 counts/g.
- + */
- +enum {
- + MODE_2G = 0,
- + MODE_4G,
- + MODE_8G,
- +};
- +
- +enum {
- + MMA_STANDBY = 0,
- + MMA_ACTIVED,
- +};
- +
- +/* mma8451 status */
- +struct mma8451_status {
- + u8 mode;
- + u8 ctl_reg1;
- + int active;
- + int position;
- +};
- +
- +static struct mma8451_status mma_status;
- +static struct input_polled_dev *mma8451_idev;
- +static struct device *hwmon_dev;
- +static struct i2c_client *mma8451_i2c_client;
- +
- +static int senstive_mode = MODE_2G;
- +static int ACCHAL[8][3][3] = {
- + { {0, -1, 0}, {1, 0, 0}, {0, 0, 1} },
- + { {-1, 0, 0}, {0, -1, 0}, {0, 0, 1} },
- + { {0, 1, 0}, {-1, 0, 0}, {0, 0, 1} },
- + { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} },
- +
- + { {0, -1, 0}, {-1, 0, 0}, {0, 0, -1} },
- + { {-1, 0, 0}, {0, 1, 0}, {0, 0, -1} },
- + { {0, 1, 0}, {1, 0, 0}, {0, 0, -1} },
- + { {1, 0, 0}, {0, -1, 0}, {0, 0, -1} },
- +};
- +
- +static DEFINE_MUTEX(mma8451_lock);
- +static int mma8451_adjust_position(short *x, short *y, short *z)
- +{
- + short rawdata[3], data[3];
- + int i, j;
- + int position = mma_status.position;
- + if (position < 0 || position > 7)
- + position = 0;
- + rawdata[0] = *x;
- + rawdata[1] = *y;
- + rawdata[2] = *z;
- + for (i = 0; i < 3; i++) {
- + data[i] = 0;
- + for (j = 0; j < 3; j++)
- + data[i] += rawdata[j] * ACCHAL[position][i][j];
- + }
- + *x = data[0];
- + *y = data[1];
- + *z = data[2];
- + return 0;
- +}
- +
- +static int mma8451_change_mode(struct i2c_client *client, int mode)
- +{
- + int result;
- +
- + mma_status.ctl_reg1 = 0;
- + result = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, 0);
- + if (result < 0)
- + goto out;
- + mma_status.active = MMA_STANDBY;
- +
- + result = i2c_smbus_write_byte_data(client, MMA8451_XYZ_DATA_CFG,
- + mode);
- + if (result < 0)
- + goto out;
- + mdelay(MODE_CHANGE_DELAY_MS);
- + mma_status.mode = mode;
- +
- + return 0;
- +out:
- + dev_err(&client->dev, "error when init mma8451:(%d)", result);
- + return result;
- +}
- +
- +static int mma8451_read_data(short *x, short *y, short *z)
- +{
- + u8 tmp_data[MMA8451_BUF_SIZE];
- + int ret;
- +
- + ret = i2c_smbus_read_i2c_block_data(mma8451_i2c_client,
- + MMA8451_OUT_X_MSB, 7, tmp_data);
- + if (ret < MMA8451_BUF_SIZE) {
- + dev_err(&mma8451_i2c_client->dev, "i2c block read failed\n");
- + return -EIO;
- + }
- +
- + *x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1];
- + *y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3];
- + *z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5];
- + return 0;
- +}
- +
- +static void report_abs(void)
- +{
- + short x, y, z;
- + int result;
- + int retry = 3;
- +
- + mutex_lock(&mma8451_lock);
- + if (mma_status.active == MMA_STANDBY)
- + goto out;
- + /* wait for the data ready */
- + do {
- + result = i2c_smbus_read_byte_data(mma8451_i2c_client,
- + MMA8451_STATUS);
- + retry--;
- + msleep(1);
- + } while (!(result & MMA8451_STATUS_ZYXDR) && retry > 0);
- + if (retry == 0)
- + goto out;
- + if (mma8451_read_data(&x, &y, &z) != 0)
- + goto out;
- + mma8451_adjust_position(&x, &y, &z);
- + input_report_abs(mma8451_idev->input, ABS_X, x);
- + input_report_abs(mma8451_idev->input, ABS_Y, y);
- + input_report_abs(mma8451_idev->input, ABS_Z, z);
- + input_sync(mma8451_idev->input);
- +out:
- + mutex_unlock(&mma8451_lock);
- +}
- +
- +static void mma8451_dev_poll(struct input_polled_dev *dev)
- +{
- + report_abs();
- +}
- +
- +static ssize_t mma8451_enable_show(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + struct i2c_client *client;
- + u8 val;
- + int enable;
- +
- + mutex_lock(&mma8451_lock);
- + client = mma8451_i2c_client;
- + val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1);
- + if ((val & 0x01) && mma_status.active == MMA_ACTIVED)
- + enable = 1;
- + else
- + enable = 0;
- + mutex_unlock(&mma8451_lock);
- + return sprintf(buf, "%d\n", enable);
- +}
- +
- +static ssize_t mma8451_enable_store(struct device *dev,
- + struct device_attribute *attr,
- + const char *buf, size_t count)
- +{
- + struct i2c_client *client;
- + int ret;
- + unsigned long enable;
- + u8 val = 0;
- +
- + ret = strict_strtoul(buf, 10, &enable);
- + if (ret) {
- + dev_err(dev, "string transform error\n");
- + return ret;
- + }
- +
- + mutex_lock(&mma8451_lock);
- + client = mma8451_i2c_client;
- + enable = (enable > 0) ? 1 : 0;
- + if (enable && mma_status.active == MMA_STANDBY) {
- + val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1);
- + ret =
- + i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
- + val | 0x01);
- + if (!ret)
- + mma_status.active = MMA_ACTIVED;
- +
- + } else if (enable == 0 && mma_status.active == MMA_ACTIVED) {
- + val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1);
- + ret =
- + i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
- + val & 0xFE);
- + if (!ret)
- + mma_status.active = MMA_STANDBY;
- +
- + }
- + mutex_unlock(&mma8451_lock);
- + return count;
- +}
- +
- +static ssize_t mma8451_position_show(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + int position = 0;
- + mutex_lock(&mma8451_lock);
- + position = mma_status.position;
- + mutex_unlock(&mma8451_lock);
- + return sprintf(buf, "%d\n", position);
- +}
- +
- +static ssize_t mma8451_position_store(struct device *dev,
- + struct device_attribute *attr,
- + const char *buf, size_t count)
- +{
- + unsigned long position;
- + int ret;
- + ret = strict_strtoul(buf, 10, &position);
- + if (ret) {
- + dev_err(dev, "string transform error\n");
- + return ret;
- + }
- +
- + mutex_lock(&mma8451_lock);
- + mma_status.position = (int)position;
- + mutex_unlock(&mma8451_lock);
- + return count;
- +}
- +
- +static ssize_t mma8451_scalemode_show(struct device *dev,
- + struct device_attribute *attr,
- + char *buf)
- +{
- + int mode = 0;
- + mutex_lock(&mma8451_lock);
- + mode = (int)mma_status.mode;
- + mutex_unlock(&mma8451_lock);
- +
- + return sprintf(buf, "%d\n", mode);
- +}
- +
- +static ssize_t mma8451_scalemode_store(struct device *dev,
- + struct device_attribute *attr,
- + const char *buf, size_t count)
- +{
- + unsigned long mode;
- + int ret, active_save;
- + struct i2c_client *client = mma8451_i2c_client;
- +
- + ret = strict_strtoul(buf, 10, &mode);
- + if (ret) {
- + dev_err(dev, "string transform error\n");
- + goto out;
- + }
- +
- + if (mode > MODE_8G) {
- + dev_warn(dev, "not supported mode\n");
- + ret = count;
- + goto out;
- + }
- +
- + mutex_lock(&mma8451_lock);
- + if (mode == mma_status.mode) {
- + ret = count;
- + goto out_unlock;
- + }
- +
- + active_save = mma_status.active;
- + ret = mma8451_change_mode(client, mode);
- + if (ret)
- + goto out_unlock;
- +
- + if (active_save == MMA_ACTIVED) {
- + ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, 1);
- +
- + if (ret)
- + goto out_unlock;
- + mma_status.active = active_save;
- + }
- +
- +out_unlock:
- + mutex_unlock(&mma8451_lock);
- +out:
- + return ret;
- +}
- +
- +static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
- + mma8451_enable_show, mma8451_enable_store);
- +static DEVICE_ATTR(position, S_IWUSR | S_IRUGO,
- + mma8451_position_show, mma8451_position_store);
- +static DEVICE_ATTR(scalemode, S_IWUSR | S_IRUGO,
- + mma8451_scalemode_show, mma8451_scalemode_store);
- +
- +static struct attribute *mma8451_attributes[] = {
- + &dev_attr_enable.attr,
- + &dev_attr_position.attr,
- + &dev_attr_scalemode.attr,
- + NULL
- +};
- +
- +static const struct attribute_group mma8451_attr_group = {
- + .attrs = mma8451_attributes,
- +};
- +
- +static int mma8451_probe(struct i2c_client *client,
- + const struct i2c_device_id *id)
- +{
- + int result, client_id;
- + struct input_dev *idev;
- + struct i2c_adapter *adapter;
- + u32 pos;
- + struct device_node *of_node = client->dev.of_node;
- + struct regulator *vdd, *vdd_io;
- +
- + mma8451_i2c_client = client;
- +
- + vdd = devm_regulator_get(&client->dev, "vdd");
- + if (!IS_ERR(vdd)) {
- + result = regulator_enable(vdd);
- + if (result) {
- + dev_err(&client->dev, "vdd set voltage error\n");
- + return result;
- + }
- + }
- +
- + vdd_io = devm_regulator_get(&client->dev, "vddio");
- + if (!IS_ERR(vdd_io)) {
- + result = regulator_enable(vdd_io);
- + if (result) {
- + dev_err(&client->dev, "vddio set voltage error\n");
- + return result;
- + }
- + }
- +
- + adapter = to_i2c_adapter(client->dev.parent);
- + result = i2c_check_functionality(adapter,
- + I2C_FUNC_SMBUS_BYTE |
- + I2C_FUNC_SMBUS_BYTE_DATA);
- + if (!result)
- + goto err_out;
- +
- + client_id = i2c_smbus_read_byte_data(client, MMA8451_WHO_AM_I);
- + if (client_id != MMA8451_ID && client_id != MMA8452_ID
- + && client_id != MMA8453_ID) {
- + dev_err(&client->dev,
- + "read chip ID 0x%x is not equal to 0x%x or 0x%x!\n",
- + result, MMA8451_ID, MMA8452_ID);
- + result = -EINVAL;
- + goto err_out;
- + }
- +
- + /* Initialize the MMA8451 chip */
- + result = mma8451_change_mode(client, senstive_mode);
- + if (result) {
- + dev_err(&client->dev,
- + "error when init mma8451 chip:(%d)\n", result);
- + goto err_out;
- + }
- +
- + hwmon_dev = hwmon_device_register(&client->dev);
- + if (!hwmon_dev) {
- + result = -ENOMEM;
- + dev_err(&client->dev, "error when register hwmon device\n");
- + goto err_out;
- + }
- +
- + mma8451_idev = input_allocate_polled_device();
- + if (!mma8451_idev) {
- + result = -ENOMEM;
- + dev_err(&client->dev, "alloc poll device failed!\n");
- + goto err_alloc_poll_device;
- + }
- + mma8451_idev->poll = mma8451_dev_poll;
- + mma8451_idev->poll_interval = POLL_INTERVAL;
- + mma8451_idev->poll_interval_min = POLL_INTERVAL_MIN;
- + mma8451_idev->poll_interval_max = POLL_INTERVAL_MAX;
- + idev = mma8451_idev->input;
- + idev->name = "mma845x";
- + idev->id.bustype = BUS_I2C;
- + idev->evbit[0] = BIT_MASK(EV_ABS);
- +
- + input_set_abs_params(idev, ABS_X, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);
- + input_set_abs_params(idev, ABS_Y, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);
- + input_set_abs_params(idev, ABS_Z, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);
- +
- + result = input_register_polled_device(mma8451_idev);
- + if (result) {
- + dev_err(&client->dev, "register poll device failed!\n");
- + goto err_register_polled_device;
- + }
- + result = sysfs_create_group(&idev->dev.kobj, &mma8451_attr_group);
- + if (result) {
- + dev_err(&client->dev, "create device file failed!\n");
- + result = -EINVAL;
- + goto err_register_polled_device;
- + }
- +
- + result = of_property_read_u32(of_node, "position", &pos);
- + if (result)
- + pos = DEFAULT_POSITION;
- + mma_status.position = (int)pos;
- +
- + return 0;
- +err_register_polled_device:
- + input_free_polled_device(mma8451_idev);
- +err_alloc_poll_device:
- + hwmon_device_unregister(&client->dev);
- +err_out:
- + return result;
- +}
- +
- +static int mma8451_stop_chip(struct i2c_client *client)
- +{
- + int ret = 0;
- + if (mma_status.active == MMA_ACTIVED) {
- + mma_status.ctl_reg1 = i2c_smbus_read_byte_data(client,
- + MMA8451_CTRL_REG1);
- + ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
- + mma_status.ctl_reg1 & 0xFE);
- + }
- + return ret;
- +}
- +
- +static int mma8451_remove(struct i2c_client *client)
- +{
- + int ret;
- + ret = mma8451_stop_chip(client);
- + hwmon_device_unregister(hwmon_dev);
- +
- + return ret;
- +}
- +
- +#ifdef CONFIG_PM_SLEEP
- +static int mma8451_suspend(struct device *dev)
- +{
- + struct i2c_client *client = to_i2c_client(dev);
- +
- + return mma8451_stop_chip(client);
- +}
- +
- +static int mma8451_resume(struct device *dev)
- +{
- + int ret = 0;
- + struct i2c_client *client = to_i2c_client(dev);
- + if (mma_status.active == MMA_ACTIVED)
- + ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
- + mma_status.ctl_reg1);
- + return ret;
- +
- +}
- +#endif
- +
- +static const struct i2c_device_id mma8451_id[] = {
- + {"mma8451", 0},
- +};
- +
- +MODULE_DEVICE_TABLE(i2c, mma8451_id);
- +
- +static SIMPLE_DEV_PM_OPS(mma8451_pm_ops, mma8451_suspend, mma8451_resume);
- +static struct i2c_driver mma8451_driver = {
- + .driver = {
- + .name = "mma8451",
- + .owner = THIS_MODULE,
- + .pm = &mma8451_pm_ops,
- + },
- + .probe = mma8451_probe,
- + .remove = mma8451_remove,
- + .id_table = mma8451_id,
- +};
- +
- +static int __init mma8451_init(void)
- +{
- + /* register driver */
- + int res;
- +
- + res = i2c_add_driver(&mma8451_driver);
- + if (res < 0) {
- + printk(KERN_INFO "add mma8451 i2c driver failed\n");
- + return -ENODEV;
- + }
- + return res;
- +}
- +
- +static void __exit mma8451_exit(void)
- +{
- + i2c_del_driver(&mma8451_driver);
- +}
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("MMA8451 3-Axis Orientation/Motion Detection Sensor driver");
- +MODULE_LICENSE("GPL");
- +
- +module_init(mma8451_init);
- +module_exit(mma8451_exit);
- diff -Nur linux-3.14.35.orig/drivers/i2c/busses/i2c-imx.c linux-3.14.35/drivers/i2c/busses/i2c-imx.c
- --- linux-3.14.35.orig/drivers/i2c/busses/i2c-imx.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/i2c/busses/i2c-imx.c 2015-03-08 14:27:37.561684501 -0500
- @@ -184,6 +184,9 @@
- int stopped;
- unsigned int ifdr; /* IMX_I2C_IFDR */
- const struct imx_i2c_hwdata *hwdata;
- +
- + unsigned int cur_clk;
- + unsigned int bitrate;
- };
-
- static const struct imx_i2c_hwdata imx1_i2c_hwdata = {
- @@ -305,6 +308,51 @@
- return 0;
- }
-
- +static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx)
- +{
- + struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div;
- + unsigned ndivs = i2c_imx->hwdata->ndivs;
- + unsigned int i2c_clk_rate;
- + unsigned int div;
- + int i;
- +
- + /* Divider value calculation */
- + i2c_clk_rate = clk_get_rate(i2c_imx->clk);
- + if (i2c_imx->cur_clk == i2c_clk_rate)
- + return;
- + else
- + i2c_imx->cur_clk = i2c_clk_rate;
- +
- + div = (i2c_clk_rate + i2c_imx->bitrate - 1) / i2c_imx->bitrate;
- + if (div < i2c_clk_div[0].div)
- + i = 0;
- + else if (div > i2c_clk_div[ndivs - 1].div)
- + i = ndivs - 1;
- + else
- + for (i = 0; i2c_clk_div[i].div < div; i++)
- + ;
- +
- + /* Store divider value */
- + i2c_imx->ifdr = imx_i2c_clk_div[i].val;
- +
- + /*
- + * There dummy delay is calculated.
- + * It should be about one I2C clock period long.
- + * This delay is used in I2C bus disable function
- + * to fix chip hardware bug.
- + */
- + i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div
- + + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2);
- +
- + /* dev_dbg() can't be used, because adapter is not yet registered */
- +#ifdef CONFIG_I2C_DEBUG_BUS
- + dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n",
- + __func__, i2c_clk_rate, div);
- + dev_dbg(&i2c_imx->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n",
- + __func__, i2c_clk_div[i].val, i2c_clk_div[i].div);
- +#endif
- +}
- +
- static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
- {
- unsigned int temp = 0;
- @@ -312,6 +360,7 @@
-
- dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
-
- + i2c_imx_set_clk(i2c_imx);
- result = clk_prepare_enable(i2c_imx->clk);
- if (result)
- return result;
- @@ -367,45 +416,6 @@
- clk_disable_unprepare(i2c_imx->clk);
- }
-
- -static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
- - unsigned int rate)
- -{
- - struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div;
- - unsigned int i2c_clk_rate;
- - unsigned int div;
- - int i;
- -
- - /* Divider value calculation */
- - i2c_clk_rate = clk_get_rate(i2c_imx->clk);
- - div = (i2c_clk_rate + rate - 1) / rate;
- - if (div < i2c_clk_div[0].div)
- - i = 0;
- - else if (div > i2c_clk_div[i2c_imx->hwdata->ndivs - 1].div)
- - i = i2c_imx->hwdata->ndivs - 1;
- - else
- - for (i = 0; i2c_clk_div[i].div < div; i++);
- -
- - /* Store divider value */
- - i2c_imx->ifdr = i2c_clk_div[i].val;
- -
- - /*
- - * There dummy delay is calculated.
- - * It should be about one I2C clock period long.
- - * This delay is used in I2C bus disable function
- - * to fix chip hardware bug.
- - */
- - i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div
- - + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2);
- -
- - /* dev_dbg() can't be used, because adapter is not yet registered */
- -#ifdef CONFIG_I2C_DEBUG_BUS
- - dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n",
- - __func__, i2c_clk_rate, div);
- - dev_dbg(&i2c_imx->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n",
- - __func__, i2c_clk_div[i].val, i2c_clk_div[i].div);
- -#endif
- -}
- -
- static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
- {
- struct imx_i2c_struct *i2c_imx = dev_id;
- @@ -600,7 +610,6 @@
- struct imxi2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
- void __iomem *base;
- int irq, ret;
- - u32 bitrate;
-
- dev_dbg(&pdev->dev, "<%s>\n", __func__);
-
- @@ -664,12 +673,12 @@
- i2c_set_adapdata(&i2c_imx->adapter, i2c_imx);
-
- /* Set up clock divider */
- - bitrate = IMX_I2C_BIT_RATE;
- + i2c_imx->bitrate = IMX_I2C_BIT_RATE;
- ret = of_property_read_u32(pdev->dev.of_node,
- - "clock-frequency", &bitrate);
- + "clock-frequency", &i2c_imx->bitrate);
- if (ret < 0 && pdata && pdata->bitrate)
- - bitrate = pdata->bitrate;
- - i2c_imx_set_clk(i2c_imx, bitrate);
- + i2c_imx->bitrate = pdata->bitrate;
- + i2c_imx_set_clk(i2c_imx);
-
- /* Set up chip registers to defaults */
- imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
- diff -Nur linux-3.14.35.orig/drivers/input/keyboard/gpio_keys.c linux-3.14.35/drivers/input/keyboard/gpio_keys.c
- --- linux-3.14.35.orig/drivers/input/keyboard/gpio_keys.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/input/keyboard/gpio_keys.c 2015-03-08 14:27:37.561684501 -0500
- @@ -3,6 +3,7 @@
- *
- * Copyright 2005 Phil Blundell
- * Copyright 2010, 2011 David Jander <david@protonic.nl>
- + * Copyright (C) 2013 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- @@ -473,6 +474,8 @@
-
- isr = gpio_keys_gpio_isr;
- irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
- + if (bdata->button->wakeup)
- + irqflags |= IRQF_NO_SUSPEND;
-
- } else {
- if (!button->irq) {
- diff -Nur linux-3.14.35.orig/drivers/input/keyboard/imx_keypad.c linux-3.14.35/drivers/input/keyboard/imx_keypad.c
- --- linux-3.14.35.orig/drivers/input/keyboard/imx_keypad.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/input/keyboard/imx_keypad.c 2015-03-08 14:27:37.561684501 -0500
- @@ -1,6 +1,7 @@
- /*
- * Driver for the IMX keypad port.
- * Copyright (C) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
- + * Copyright (C) 2013 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- @@ -548,6 +549,8 @@
-
- if (device_may_wakeup(&pdev->dev))
- enable_irq_wake(kbd->irq);
- + else
- + pinctrl_pm_select_sleep_state(dev);
-
- return 0;
- }
- @@ -561,6 +564,8 @@
-
- if (device_may_wakeup(&pdev->dev))
- disable_irq_wake(kbd->irq);
- + else
- + pinctrl_pm_select_default_state(dev);
-
- mutex_lock(&input_dev->mutex);
-
- diff -Nur linux-3.14.35.orig/drivers/input/misc/mma8450.c linux-3.14.35/drivers/input/misc/mma8450.c
- --- linux-3.14.35.orig/drivers/input/misc/mma8450.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/input/misc/mma8450.c 2015-03-08 14:27:37.573684501 -0500
- @@ -1,7 +1,7 @@
- /*
- * Driver for Freescale's 3-Axis Accelerometer MMA8450
- *
- - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * 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
- @@ -25,6 +25,7 @@
- #include <linux/i2c.h>
- #include <linux/input-polldev.h>
- #include <linux/of_device.h>
- +#include <linux/mutex.h>
-
- #define MMA8450_DRV_NAME "mma8450"
-
- @@ -51,11 +52,22 @@
-
- #define MMA8450_CTRL_REG1 0x38
- #define MMA8450_CTRL_REG2 0x39
- +#define MMA8450_ID 0xC6
- +#define MMA8450_WHO_AM_I 0x0F
- +
- +enum {
- + MODE_STANDBY = 0,
- + MODE_2G,
- + MODE_4G,
- + MODE_8G,
- +};
-
- /* mma8450 status */
- struct mma8450 {
- struct i2c_client *client;
- struct input_polled_dev *idev;
- + struct mutex mma8450_lock;
- + u8 mode;
- };
-
- static int mma8450_read(struct mma8450 *m, unsigned off)
- @@ -112,16 +124,19 @@
- int ret;
- u8 buf[6];
-
- - ret = mma8450_read(m, MMA8450_STATUS);
- - if (ret < 0)
- - return;
- + mutex_lock(&m->mma8450_lock);
-
- - if (!(ret & MMA8450_STATUS_ZXYDR))
- + ret = mma8450_read(m, MMA8450_STATUS);
- + if (ret < 0 || !(ret & MMA8450_STATUS_ZXYDR)) {
- + mutex_unlock(&m->mma8450_lock);
- return;
- + }
-
- ret = mma8450_read_block(m, MMA8450_OUT_X_LSB, buf, sizeof(buf));
- - if (ret < 0)
- + if (ret < 0) {
- + mutex_unlock(&m->mma8450_lock);
- return;
- + }
-
- x = ((int)(s8)buf[1] << 4) | (buf[0] & 0xf);
- y = ((int)(s8)buf[3] << 4) | (buf[2] & 0xf);
- @@ -131,10 +146,12 @@
- input_report_abs(dev->input, ABS_Y, y);
- input_report_abs(dev->input, ABS_Z, z);
- input_sync(dev->input);
- +
- + mutex_unlock(&m->mma8450_lock);
- }
-
- /* Initialize the MMA8450 chip */
- -static void mma8450_open(struct input_polled_dev *dev)
- +static s32 mma8450_open(struct input_polled_dev *dev)
- {
- struct mma8450 *m = dev->private;
- int err;
- @@ -142,18 +159,20 @@
- /* enable all events from X/Y/Z, no FIFO */
- err = mma8450_write(m, MMA8450_XYZ_DATA_CFG, 0x07);
- if (err)
- - return;
- + return err;
-
- /*
- * Sleep mode poll rate - 50Hz
- * System output data rate - 400Hz
- - * Full scale selection - Active, +/- 2G
- + * Standby mode
- */
- - err = mma8450_write(m, MMA8450_CTRL_REG1, 0x01);
- - if (err < 0)
- - return;
- -
- + err = mma8450_write(m, MMA8450_CTRL_REG1, MODE_STANDBY);
- + if (err)
- + return err;
- + m->mode = MODE_STANDBY;
- msleep(MODE_CHANGE_DELAY_MS);
- +
- + return 0;
- }
-
- static void mma8450_close(struct input_polled_dev *dev)
- @@ -164,6 +183,76 @@
- mma8450_write(m, MMA8450_CTRL_REG2, 0x01);
- }
-
- +static ssize_t mma8450_scalemode_show(struct device *dev,
- + struct device_attribute *attr,
- + char *buf)
- +{
- + int mode = 0;
- + struct mma8450 *m;
- + struct i2c_client *client = to_i2c_client(dev);
- +
- + m = i2c_get_clientdata(client);
- +
- + mutex_lock(&m->mma8450_lock);
- + mode = (int)m->mode;
- + mutex_unlock(&m->mma8450_lock);
- +
- + return sprintf(buf, "%d\n", mode);
- +}
- +
- +static ssize_t mma8450_scalemode_store(struct device *dev,
- + struct device_attribute *attr,
- + const char *buf, size_t count)
- +{
- + unsigned long mode;
- + int ret;
- + struct mma8450 *m = NULL;
- + struct i2c_client *client = to_i2c_client(dev);
- +
- + ret = strict_strtoul(buf, 10, &mode);
- + if (ret) {
- + dev_err(dev, "string transform error\n");
- + return ret;
- + }
- +
- + if (mode > MODE_8G) {
- + dev_warn(dev, "not supported mode %d\n", (int)mode);
- + return count;
- + }
- +
- + m = i2c_get_clientdata(client);
- +
- + mutex_lock(&m->mma8450_lock);
- + if (mode == m->mode) {
- + mutex_unlock(&m->mma8450_lock);
- + return count;
- + }
- +
- + ret = mma8450_write(m, MMA8450_CTRL_REG1, mode);
- + if (ret < 0) {
- + mutex_unlock(&m->mma8450_lock);
- + return ret;
- + }
- +
- + msleep(MODE_CHANGE_DELAY_MS);
- + m->mode = (u8)mode;
- + mutex_unlock(&m->mma8450_lock);
- +
- + return count;
- +}
- +
- +static DEVICE_ATTR(scalemode, S_IWUSR | S_IRUGO,
- + mma8450_scalemode_show, mma8450_scalemode_store);
- +
- +static struct attribute *mma8450_attributes[] = {
- + &dev_attr_scalemode.attr,
- + NULL
- +};
- +
- +static const struct attribute_group mma8450_attr_group = {
- + .attrs = mma8450_attributes,
- +};
- +
- /*
- * I2C init/probing/exit functions
- */
- @@ -172,7 +261,25 @@
- {
- struct input_polled_dev *idev;
- struct mma8450 *m;
- - int err;
- + int err, client_id;
- + struct i2c_adapter *adapter = NULL;
- +
- + adapter = to_i2c_adapter(c->dev.parent);
- + err = i2c_check_functionality(adapter,
- + I2C_FUNC_SMBUS_BYTE |
- + I2C_FUNC_SMBUS_BYTE_DATA);
- + if (!err)
- + goto err_out;
- +
- + client_id = i2c_smbus_read_byte_data(c, MMA8450_WHO_AM_I);
- +
- + if (MMA8450_ID != client_id) {
- + dev_err(&c->dev,
- + "read chip ID 0x%x is not equal to 0x%x!\n", client_id,
- + MMA8450_ID);
- + err = -EINVAL;
- + goto err_out;
- + }
-
- m = kzalloc(sizeof(struct mma8450), GFP_KERNEL);
- idev = input_allocate_polled_device();
- @@ -183,6 +290,7 @@
-
- m->client = c;
- m->idev = idev;
- + i2c_set_clientdata(c, m);
-
- idev->private = m;
- idev->input->name = MMA8450_DRV_NAME;
- @@ -190,8 +298,6 @@
- idev->poll = mma8450_poll;
- idev->poll_interval = POLL_INTERVAL;
- idev->poll_interval_max = POLL_INTERVAL_MAX;
- - idev->open = mma8450_open;
- - idev->close = mma8450_close;
-
- __set_bit(EV_ABS, idev->input->evbit);
- input_set_abs_params(idev->input, ABS_X, -2048, 2047, 32, 32);
- @@ -206,11 +312,32 @@
-
- i2c_set_clientdata(c, m);
-
- + mutex_init(&m->mma8450_lock);
- +
- + err = mma8450_open(idev);
- + if (err) {
- + dev_err(&c->dev, "failed to initialize mma8450\n");
- + goto err_unreg_dev;
- + }
- +
- + err = sysfs_create_group(&c->dev.kobj, &mma8450_attr_group);
- + if (err) {
- + dev_err(&c->dev, "create device file failed!\n");
- + err = -EINVAL;
- + goto err_close;
- + }
- +
- return 0;
-
- +err_close:
- + mma8450_close(idev);
- +err_unreg_dev:
- + mutex_destroy(&m->mma8450_lock);
- + input_unregister_polled_device(idev);
- err_free_mem:
- input_free_polled_device(idev);
- kfree(m);
- +err_out:
- return err;
- }
-
- @@ -219,6 +346,9 @@
- struct mma8450 *m = i2c_get_clientdata(c);
- struct input_polled_dev *idev = m->idev;
-
- + sysfs_remove_group(&c->dev.kobj, &mma8450_attr_group);
- + mma8450_close(idev);
- + mutex_destroy(&m->mma8450_lock);
- input_unregister_polled_device(idev);
- input_free_polled_device(idev);
- kfree(m);
- diff -Nur linux-3.14.35.orig/drivers/input/sparse-keymap.c linux-3.14.35/drivers/input/sparse-keymap.c
- --- linux-3.14.35.orig/drivers/input/sparse-keymap.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/input/sparse-keymap.c 2015-03-08 14:27:37.573684501 -0500
- @@ -236,7 +236,7 @@
- * in an input device that was set up by sparse_keymap_setup().
- * NOTE: It is safe to cal this function while input device is
- * still registered (however the drivers should care not to try to
- - * use freed keymap and thus have to shut off interrups/polling
- + * use freed keymap and thus have to shut off interrupts/polling
- * before freeing the keymap).
- */
- void sparse_keymap_free(struct input_dev *dev)
- diff -Nur linux-3.14.35.orig/drivers/Kconfig linux-3.14.35/drivers/Kconfig
- --- linux-3.14.35.orig/drivers/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/Kconfig 2015-03-08 14:27:37.573684501 -0500
- @@ -96,6 +96,8 @@
-
- source "drivers/memstick/Kconfig"
-
- +source "drivers/mxc/Kconfig"
- +
- source "drivers/leds/Kconfig"
-
- source "drivers/accessibility/Kconfig"
- diff -Nur linux-3.14.35.orig/drivers/leds/leds-gpio.c linux-3.14.35/drivers/leds/leds-gpio.c
- --- linux-3.14.35.orig/drivers/leds/leds-gpio.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/leds/leds-gpio.c 2015-03-08 14:27:37.573684501 -0500
- @@ -3,7 +3,7 @@
- *
- * Copyright (C) 2007 8D Technologies inc.
- * Raphael Assenat <raph@8d.com>
- - * Copyright (C) 2008 Freescale Semiconductor, Inc.
- + * Copyright (C) 2008, 2014 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- @@ -203,6 +203,8 @@
- else
- led.default_state = LEDS_GPIO_DEFSTATE_OFF;
- }
- + if (of_get_property(child, "retain-state-suspended", NULL))
- + led.retain_state_suspended = 1;
-
- ret = create_gpio_led(&led, &priv->leds[priv->num_leds++],
- &pdev->dev, NULL);
- diff -Nur linux-3.14.35.orig/drivers/leds/leds-pwm.c linux-3.14.35/drivers/leds/leds-pwm.c
- --- linux-3.14.35.orig/drivers/leds/leds-pwm.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/leds/leds-pwm.c 2015-03-08 14:27:37.577684501 -0500
- @@ -70,6 +70,10 @@
-
- duty *= brightness;
- do_div(duty, max);
- +
- + if (led_dat->active_low)
- + duty = led_dat->period - duty;
- +
- led_dat->duty = duty;
-
- if (led_dat->can_sleep)
- @@ -93,55 +97,75 @@
- }
- }
-
- -static int led_pwm_create_of(struct platform_device *pdev,
- - struct led_pwm_priv *priv)
- +static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
- + struct led_pwm *led, struct device_node *child)
- {
- - struct device_node *child;
- + struct led_pwm_data *led_data = &priv->leds[priv->num_leds];
- int ret;
-
- - for_each_child_of_node(pdev->dev.of_node, child) {
- - struct led_pwm_data *led_dat = &priv->leds[priv->num_leds];
- + led_data->active_low = led->active_low;
- + led_data->period = led->pwm_period_ns;
- + led_data->cdev.name = led->name;
- + led_data->cdev.default_trigger = led->default_trigger;
- + led_data->cdev.brightness_set = led_pwm_set;
- + led_data->cdev.brightness = LED_OFF;
- + led_data->cdev.max_brightness = led->max_brightness;
- + led_data->cdev.flags = LED_CORE_SUSPENDRESUME;
- +
- + if (child)
- + led_data->pwm = devm_of_pwm_get(dev, child, NULL);
- + else
- + led_data->pwm = devm_pwm_get(dev, led->name);
- + if (IS_ERR(led_data->pwm)) {
- + ret = PTR_ERR(led_data->pwm);
- + dev_err(dev, "unable to request PWM for %s: %d\n",
- + led->name, ret);
- + return ret;
- + }
-
- - led_dat->cdev.name = of_get_property(child, "label",
- - NULL) ? : child->name;
- + if (child)
- + led_data->period = pwm_get_period(led_data->pwm);
-
- - led_dat->pwm = devm_of_pwm_get(&pdev->dev, child, NULL);
- - if (IS_ERR(led_dat->pwm)) {
- - dev_err(&pdev->dev, "unable to request PWM for %s\n",
- - led_dat->cdev.name);
- - ret = PTR_ERR(led_dat->pwm);
- - goto err;
- - }
- - /* Get the period from PWM core when n*/
- - led_dat->period = pwm_get_period(led_dat->pwm);
- + led_data->can_sleep = pwm_can_sleep(led_data->pwm);
- + if (led_data->can_sleep)
- + INIT_WORK(&led_data->work, led_pwm_work);
-
- - led_dat->cdev.default_trigger = of_get_property(child,
- + ret = led_classdev_register(dev, &led_data->cdev);
- + if (ret == 0) {
- + priv->num_leds++;
- + } else {
- + dev_err(dev, "failed to register PWM led for %s: %d\n",
- + led->name, ret);
- + }
- +
- + return ret;
- +}
- +
- +static int led_pwm_create_of(struct device *dev, struct led_pwm_priv *priv)
- +{
- + struct device_node *child;
- + struct led_pwm led;
- + int ret = 0;
- +
- + memset(&led, 0, sizeof(led));
- +
- + for_each_child_of_node(dev->of_node, child) {
- + led.name = of_get_property(child, "label", NULL) ? :
- + child->name;
- +
- + led.default_trigger = of_get_property(child,
- "linux,default-trigger", NULL);
- + led.active_low = of_property_read_bool(child, "active-low");
- of_property_read_u32(child, "max-brightness",
- - &led_dat->cdev.max_brightness);
- + &led.max_brightness);
-
- - led_dat->cdev.brightness_set = led_pwm_set;
- - led_dat->cdev.brightness = LED_OFF;
- - led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
- -
- - led_dat->can_sleep = pwm_can_sleep(led_dat->pwm);
- - if (led_dat->can_sleep)
- - INIT_WORK(&led_dat->work, led_pwm_work);
- -
- - ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
- - if (ret < 0) {
- - dev_err(&pdev->dev, "failed to register for %s\n",
- - led_dat->cdev.name);
- + ret = led_pwm_add(dev, priv, &led, child);
- + if (ret) {
- of_node_put(child);
- - goto err;
- + break;
- }
- - priv->num_leds++;
- }
-
- - return 0;
- -err:
- - led_pwm_cleanup(priv);
- -
- return ret;
- }
-
- @@ -167,51 +191,23 @@
-
- if (pdata) {
- for (i = 0; i < count; i++) {
- - struct led_pwm *cur_led = &pdata->leds[i];
- - struct led_pwm_data *led_dat = &priv->leds[i];
- -
- - led_dat->pwm = devm_pwm_get(&pdev->dev, cur_led->name);
- - if (IS_ERR(led_dat->pwm)) {
- - ret = PTR_ERR(led_dat->pwm);
- - dev_err(&pdev->dev,
- - "unable to request PWM for %s\n",
- - cur_led->name);
- - goto err;
- - }
- -
- - led_dat->cdev.name = cur_led->name;
- - led_dat->cdev.default_trigger = cur_led->default_trigger;
- - led_dat->active_low = cur_led->active_low;
- - led_dat->period = cur_led->pwm_period_ns;
- - led_dat->cdev.brightness_set = led_pwm_set;
- - led_dat->cdev.brightness = LED_OFF;
- - led_dat->cdev.max_brightness = cur_led->max_brightness;
- - led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
- -
- - led_dat->can_sleep = pwm_can_sleep(led_dat->pwm);
- - if (led_dat->can_sleep)
- - INIT_WORK(&led_dat->work, led_pwm_work);
- -
- - ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
- - if (ret < 0)
- - goto err;
- + ret = led_pwm_add(&pdev->dev, priv, &pdata->leds[i],
- + NULL);
- + if (ret)
- + break;
- }
- - priv->num_leds = count;
- } else {
- - ret = led_pwm_create_of(pdev, priv);
- - if (ret)
- - return ret;
- + ret = led_pwm_create_of(&pdev->dev, priv);
- + }
- +
- + if (ret) {
- + led_pwm_cleanup(priv);
- + return ret;
- }
-
- platform_set_drvdata(pdev, priv);
-
- return 0;
- -
- -err:
- - priv->num_leds = i;
- - led_pwm_cleanup(priv);
- -
- - return ret;
- }
-
- static int led_pwm_remove(struct platform_device *pdev)
- diff -Nur linux-3.14.35.orig/drivers/mailbox/mailbox.c linux-3.14.35/drivers/mailbox/mailbox.c
- --- linux-3.14.35.orig/drivers/mailbox/mailbox.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mailbox/mailbox.c 2015-03-08 14:27:37.577684501 -0500
- @@ -0,0 +1,488 @@
- +/*
- + * Mailbox: Common code for Mailbox controllers and users
- + *
- + * Copyright (C) 2014 Linaro Ltd.
- + * Author: Jassi Brar <jassisinghbrar@gmail.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <linux/interrupt.h>
- +#include <linux/spinlock.h>
- +#include <linux/mutex.h>
- +#include <linux/delay.h>
- +#include <linux/slab.h>
- +#include <linux/err.h>
- +#include <linux/module.h>
- +#include <linux/device.h>
- +#include <linux/mailbox_client.h>
- +#include <linux/mailbox_controller.h>
- +
- +#define TXDONE_BY_IRQ (1 << 0) /* controller has remote RTR irq */
- +#define TXDONE_BY_POLL (1 << 1) /* controller can read status of last TX */
- +#define TXDONE_BY_ACK (1 << 2) /* S/W ACK recevied by Client ticks the TX */
- +
- +static LIST_HEAD(mbox_cons);
- +static DEFINE_MUTEX(con_mutex);
- +
- +static int _add_to_rbuf(struct mbox_chan *chan, void *mssg)
- +{
- + int idx;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&chan->lock, flags);
- +
- + /* See if there is any space left */
- + if (chan->msg_count == MBOX_TX_QUEUE_LEN) {
- + spin_unlock_irqrestore(&chan->lock, flags);
- + return -ENOMEM;
- + }
- +
- + idx = chan->msg_free;
- + chan->msg_data[idx] = mssg;
- + chan->msg_count++;
- +
- + if (idx == MBOX_TX_QUEUE_LEN - 1)
- + chan->msg_free = 0;
- + else
- + chan->msg_free++;
- +
- + spin_unlock_irqrestore(&chan->lock, flags);
- +
- + return idx;
- +}
- +
- +static void _msg_submit(struct mbox_chan *chan)
- +{
- + unsigned count, idx;
- + unsigned long flags;
- + void *data;
- + int err;
- +
- + spin_lock_irqsave(&chan->lock, flags);
- +
- + if (!chan->msg_count || chan->active_req) {
- + spin_unlock_irqrestore(&chan->lock, flags);
- + return;
- + }
- +
- + count = chan->msg_count;
- + idx = chan->msg_free;
- + if (idx >= count)
- + idx -= count;
- + else
- + idx += MBOX_TX_QUEUE_LEN - count;
- +
- + data = chan->msg_data[idx];
- +
- + /* Try to submit a message to the MBOX controller */
- + err = chan->mbox->ops->send_data(chan, data);
- + if (!err) {
- + chan->active_req = data;
- + chan->msg_count--;
- + }
- +
- + spin_unlock_irqrestore(&chan->lock, flags);
- +}
- +
- +static void tx_tick(struct mbox_chan *chan, int r)
- +{
- + unsigned long flags;
- + void *mssg;
- +
- + spin_lock_irqsave(&chan->lock, flags);
- + mssg = chan->active_req;
- + chan->active_req = NULL;
- + spin_unlock_irqrestore(&chan->lock, flags);
- +
- + /* Submit next message */
- + _msg_submit(chan);
- +
- + /* Notify the client */
- + if (chan->cl->tx_block)
- + complete(&chan->tx_complete);
- + else if (mssg && chan->cl->tx_done)
- + chan->cl->tx_done(chan->cl, mssg, r);
- +}
- +
- +static void poll_txdone(unsigned long data)
- +{
- + struct mbox_controller *mbox = (struct mbox_controller *)data;
- + bool txdone, resched = false;
- + int i;
- +
- + for (i = 0; i < mbox->num_chans; i++) {
- + struct mbox_chan *chan = &mbox->chans[i];
- +
- + if (chan->active_req && chan->cl) {
- + resched = true;
- + txdone = chan->mbox->ops->last_tx_done(chan);
- + if (txdone)
- + tx_tick(chan, 0);
- + }
- + }
- +
- + if (resched)
- + mod_timer(&mbox->poll,
- + jiffies + msecs_to_jiffies(mbox->period));
- +}
- +
- +/**
- + * mbox_chan_received_data - A way for controller driver to push data
- + * received from remote to the upper layer.
- + * @chan: Pointer to the mailbox channel on which RX happened.
- + * @data: Client specific message typecasted as void *
- + *
- + * After startup and before shutdown any data received on the chan
- + * is passed on to the API via atomic mbox_chan_received_data().
- + * The controller should ACK the RX only after this call returns.
- + */
- +void mbox_chan_received_data(struct mbox_chan *chan, void *mssg)
- +{
- + /* No buffering the received data */
- + if (chan->cl->rx_callback)
- + chan->cl->rx_callback(chan->cl, mssg);
- +}
- +EXPORT_SYMBOL_GPL(mbox_chan_received_data);
- +
- +/**
- + * mbox_chan_txdone - A way for controller driver to notify the
- + * framework that the last TX has completed.
- + * @chan: Pointer to the mailbox chan on which TX happened.
- + * @r: Status of last TX - OK or ERROR
- + *
- + * The controller that has IRQ for TX ACK calls this atomic API
- + * to tick the TX state machine. It works only if txdone_irq
- + * is set by the controller.
- + */
- +void mbox_chan_txdone(struct mbox_chan *chan, int r)
- +{
- + if (unlikely(!(chan->txdone_method & TXDONE_BY_IRQ))) {
- + pr_err("Controller can't run the TX ticker\n");
- + return;
- + }
- +
- + tx_tick(chan, r);
- +}
- +EXPORT_SYMBOL_GPL(mbox_chan_txdone);
- +
- +/**
- + * mbox_client_txdone - The way for a client to run the TX state machine.
- + * @chan: Mailbox channel assigned to this client.
- + * @r: Success status of last transmission.
- + *
- + * The client/protocol had received some 'ACK' packet and it notifies
- + * the API that the last packet was sent successfully. This only works
- + * if the controller can't sense TX-Done.
- + */
- +void mbox_client_txdone(struct mbox_chan *chan, int r)
- +{
- + if (unlikely(!(chan->txdone_method & TXDONE_BY_ACK))) {
- + pr_err("Client can't run the TX ticker\n");
- + return;
- + }
- +
- + tx_tick(chan, r);
- +}
- +EXPORT_SYMBOL_GPL(mbox_client_txdone);
- +
- +/**
- + * mbox_client_peek_data - A way for client driver to pull data
- + * received from remote by the controller.
- + * @chan: Mailbox channel assigned to this client.
- + *
- + * A poke to controller driver for any received data.
- + * The data is actually passed onto client via the
- + * mbox_chan_received_data()
- + * The call can be made from atomic context, so the controller's
- + * implementation of peek_data() must not sleep.
- + *
- + * Return: True, if controller has, and is going to push after this,
- + * some data.
- + * False, if controller doesn't have any data to be read.
- + */
- +bool mbox_client_peek_data(struct mbox_chan *chan)
- +{
- + if (chan->mbox->ops->peek_data)
- + return chan->mbox->ops->peek_data(chan);
- +
- + return false;
- +}
- +EXPORT_SYMBOL_GPL(mbox_client_peek_data);
- +
- +/**
- + * mbox_send_message - For client to submit a message to be
- + * sent to the remote.
- + * @chan: Mailbox channel assigned to this client.
- + * @mssg: Client specific message typecasted.
- + *
- + * For client to submit data to the controller destined for a remote
- + * processor. If the client had set 'tx_block', the call will return
- + * either when the remote receives the data or when 'tx_tout' millisecs
- + * run out.
- + * In non-blocking mode, the requests are buffered by the API and a
- + * non-negative token is returned for each queued request. If the request
- + * is not queued, a negative token is returned. Upon failure or successful
- + * TX, the API calls 'tx_done' from atomic context, from which the client
- + * could submit yet another request.
- + * In blocking mode, 'tx_done' is not called, effectively making the
- + * queue length 1.
- + * The pointer to message should be preserved until it is sent
- + * over the chan, i.e, tx_done() is made.
- + * This function could be called from atomic context as it simply
- + * queues the data and returns a token against the request.
- + *
- + * Return: Non-negative integer for successful submission (non-blocking mode)
- + * or transmission over chan (blocking mode).
- + * Negative value denotes failure.
- + */
- +int mbox_send_message(struct mbox_chan *chan, void *mssg)
- +{
- + int t;
- +
- + if (!chan || !chan->cl)
- + return -EINVAL;
- +
- + t = _add_to_rbuf(chan, mssg);
- + if (t < 0) {
- + pr_err("Try increasing MBOX_TX_QUEUE_LEN\n");
- + return t;
- + }
- +
- + _msg_submit(chan);
- +
- + reinit_completion(&chan->tx_complete);
- +
- + if (chan->txdone_method == TXDONE_BY_POLL)
- + poll_txdone((unsigned long)chan->mbox);
- +
- + if (chan->cl->tx_block && chan->active_req) {
- + unsigned long wait;
- + int ret;
- +
- + if (!chan->cl->tx_tout) /* wait for ever */
- + wait = msecs_to_jiffies(3600000);
- + else
- + wait = msecs_to_jiffies(chan->cl->tx_tout);
- +
- + ret = wait_for_completion_timeout(&chan->tx_complete, wait);
- + if (ret == 0) {
- + t = -EIO;
- + tx_tick(chan, -EIO);
- + }
- + }
- +
- + return t;
- +}
- +EXPORT_SYMBOL_GPL(mbox_send_message);
- +
- +/**
- + * mbox_request_channel - Request a mailbox channel.
- + * @cl: Identity of the client requesting the channel.
- + *
- + * The Client specifies its requirements and capabilities while asking for
- + * a mailbox channel. It can't be called from atomic context.
- + * The channel is exclusively allocated and can't be used by another
- + * client before the owner calls mbox_free_channel.
- + * After assignment, any packet received on this channel will be
- + * handed over to the client via the 'rx_callback'.
- + * The framework holds reference to the client, so the mbox_client
- + * structure shouldn't be modified until the mbox_free_channel returns.
- + *
- + * Return: Pointer to the channel assigned to the client if successful.
- + * ERR_PTR for request failure.
- + */
- +struct mbox_chan *mbox_request_channel(struct mbox_client *cl)
- +{
- + struct device *dev = cl->dev;
- + struct mbox_controller *mbox;
- + struct of_phandle_args spec;
- + struct mbox_chan *chan;
- + unsigned long flags;
- + int count, i, ret;
- +
- + if (!dev || !dev->of_node) {
- + pr_err("%s: No owner device node\n", __func__);
- + return ERR_PTR(-ENODEV);
- + }
- +
- + count = of_property_count_strings(dev->of_node, "mbox-names");
- + if (count < 0) {
- + pr_err("%s: mbox-names property of node '%s' missing\n",
- + __func__, dev->of_node->full_name);
- + return ERR_PTR(-ENODEV);
- + }
- +
- + mutex_lock(&con_mutex);
- +
- + ret = -ENODEV;
- + for (i = 0; i < count; i++) {
- + const char *s;
- +
- + if (of_property_read_string_index(dev->of_node,
- + "mbox-names", i, &s))
- + continue;
- +
- + if (strcmp(cl->chan_name, s))
- + continue;
- +
- + if (of_parse_phandle_with_args(dev->of_node,
- + "mbox", "#mbox-cells", i, &spec))
- + continue;
- +
- + chan = NULL;
- + list_for_each_entry(mbox, &mbox_cons, node)
- + if (mbox->dev->of_node == spec.np) {
- + chan = mbox->of_xlate(mbox, &spec);
- + break;
- + }
- +
- + of_node_put(spec.np);
- +
- + if (!chan)
- + continue;
- +
- + ret = -EBUSY;
- + if (!chan->cl && try_module_get(mbox->dev->driver->owner))
- + break;
- + }
- +
- + if (i == count) {
- + mutex_unlock(&con_mutex);
- + return ERR_PTR(ret);
- + }
- +
- + spin_lock_irqsave(&chan->lock, flags);
- + chan->msg_free = 0;
- + chan->msg_count = 0;
- + chan->active_req = NULL;
- + chan->cl = cl;
- + init_completion(&chan->tx_complete);
- +
- + if (chan->txdone_method == TXDONE_BY_POLL
- + && cl->knows_txdone)
- + chan->txdone_method |= TXDONE_BY_ACK;
- + spin_unlock_irqrestore(&chan->lock, flags);
- +
- + ret = chan->mbox->ops->startup(chan);
- + if (ret) {
- + pr_err("Unable to startup the chan (%d)\n", ret);
- + mbox_free_channel(chan);
- + chan = ERR_PTR(ret);
- + }
- +
- + mutex_unlock(&con_mutex);
- + return chan;
- +}
- +EXPORT_SYMBOL_GPL(mbox_request_channel);
- +
- +/**
- + * mbox_free_channel - The client relinquishes control of a mailbox
- + * channel by this call.
- + * @chan: The mailbox channel to be freed.
- + */
- +void mbox_free_channel(struct mbox_chan *chan)
- +{
- + unsigned long flags;
- +
- + if (!chan || !chan->cl)
- + return;
- +
- + chan->mbox->ops->shutdown(chan);
- +
- + /* The queued TX requests are simply aborted, no callbacks are made */
- + spin_lock_irqsave(&chan->lock, flags);
- + chan->cl = NULL;
- + chan->active_req = NULL;
- + if (chan->txdone_method == (TXDONE_BY_POLL | TXDONE_BY_ACK))
- + chan->txdone_method = TXDONE_BY_POLL;
- +
- + module_put(chan->mbox->dev->driver->owner);
- + spin_unlock_irqrestore(&chan->lock, flags);
- +}
- +EXPORT_SYMBOL_GPL(mbox_free_channel);
- +
- +static struct mbox_chan *
- +of_mbox_index_xlate(struct mbox_controller *mbox,
- + const struct of_phandle_args *sp)
- +{
- + int ind = sp->args[0];
- +
- + if (ind >= mbox->num_chans)
- + return NULL;
- +
- + return &mbox->chans[ind];
- +}
- +
- +/**
- + * mbox_controller_register - Register the mailbox controller
- + * @mbox: Pointer to the mailbox controller.
- + *
- + * The controller driver registers its communication chans
- + */
- +int mbox_controller_register(struct mbox_controller *mbox)
- +{
- + int i, txdone;
- +
- + /* Sanity check */
- + if (!mbox || !mbox->dev || !mbox->ops || !mbox->num_chans)
- + return -EINVAL;
- +
- + if (mbox->txdone_irq)
- + txdone = TXDONE_BY_IRQ;
- + else if (mbox->txdone_poll)
- + txdone = TXDONE_BY_POLL;
- + else /* It has to be ACK then */
- + txdone = TXDONE_BY_ACK;
- +
- + if (txdone == TXDONE_BY_POLL) {
- + mbox->poll.function = &poll_txdone;
- + mbox->poll.data = (unsigned long)mbox;
- + init_timer(&mbox->poll);
- + }
- +
- + for (i = 0; i < mbox->num_chans; i++) {
- + struct mbox_chan *chan = &mbox->chans[i];
- + chan->cl = NULL;
- + chan->mbox = mbox;
- + chan->txdone_method = txdone;
- + spin_lock_init(&chan->lock);
- + }
- +
- + if (!mbox->of_xlate)
- + mbox->of_xlate = of_mbox_index_xlate;
- +
- + mutex_lock(&con_mutex);
- + list_add_tail(&mbox->node, &mbox_cons);
- + mutex_unlock(&con_mutex);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL_GPL(mbox_controller_register);
- +
- +/**
- + * mbox_controller_unregister - UnRegister the mailbox controller
- + * @mbox: Pointer to the mailbox controller.
- + */
- +void mbox_controller_unregister(struct mbox_controller *mbox)
- +{
- + int i;
- +
- + if (!mbox)
- + return;
- +
- + mutex_lock(&con_mutex);
- +
- + list_del(&mbox->node);
- +
- + for (i = 0; i < mbox->num_chans; i++)
- + mbox_free_channel(&mbox->chans[i]);
- +
- + if (mbox->txdone_poll)
- + del_timer_sync(&mbox->poll);
- +
- + mutex_unlock(&con_mutex);
- +}
- +EXPORT_SYMBOL_GPL(mbox_controller_unregister);
- diff -Nur linux-3.14.35.orig/drivers/mailbox/Makefile linux-3.14.35/drivers/mailbox/Makefile
- --- linux-3.14.35.orig/drivers/mailbox/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mailbox/Makefile 2015-03-08 14:27:37.577684501 -0500
- @@ -1,3 +1,7 @@
- +# Generic MAILBOX API
- +
- +obj-$(CONFIG_MAILBOX) += mailbox.o
- +
- obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o
-
- obj-$(CONFIG_OMAP_MBOX) += omap-mailbox.o
- diff -Nur linux-3.14.35.orig/drivers/mailbox/pl320-ipc.c linux-3.14.35/drivers/mailbox/pl320-ipc.c
- --- linux-3.14.35.orig/drivers/mailbox/pl320-ipc.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mailbox/pl320-ipc.c 2015-03-08 14:27:37.577684501 -0500
- @@ -26,7 +26,7 @@
- #include <linux/device.h>
- #include <linux/amba/bus.h>
-
- -#include <linux/mailbox.h>
- +#include <linux/pl320-ipc.h>
-
- #define IPCMxSOURCE(m) ((m) * 0x40)
- #define IPCMxDSET(m) (((m) * 0x40) + 0x004)
- diff -Nur linux-3.14.35.orig/drivers/Makefile linux-3.14.35/drivers/Makefile
- --- linux-3.14.35.orig/drivers/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/Makefile 2015-03-08 14:27:37.577684501 -0500
- @@ -111,6 +111,7 @@
- obj-$(CONFIG_CPU_FREQ) += cpufreq/
- obj-$(CONFIG_CPU_IDLE) += cpuidle/
- obj-y += mmc/
- +obj-$(CONFIG_ARCH_MXC) += mxc/
- obj-$(CONFIG_MEMSTICK) += memstick/
- obj-y += leds/
- obj-$(CONFIG_INFINIBAND) += infiniband/
- diff -Nur linux-3.14.35.orig/drivers/media/platform/Kconfig linux-3.14.35/drivers/media/platform/Kconfig
- --- linux-3.14.35.orig/drivers/media/platform/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/Kconfig 2015-03-08 14:27:37.577684501 -0500
- @@ -115,6 +115,21 @@
- To compile this driver as a module, choose M here: the module
- will be called s3c-camif.
-
- +config VIDEO_MXC_OUTPUT
- + tristate "MXC Video For Linux Video Output"
- + depends on VIDEO_DEV && ARCH_MXC && FB_MXC
- + select VIDEOBUF_DMA_CONTIG
- + ---help---
- + This is the video4linux2 output driver based on MXC module.
- +
- +config VIDEO_MXC_CAPTURE
- + tristate "MXC Video For Linux Video Capture"
- + depends on VIDEO_V4L2 && VIDEO_V4L2_INT_DEVICE
- + ---help---
- + This is the video4linux2 capture driver based on i.MX video-in module.
- +
- +source "drivers/media/platform/mxc/capture/Kconfig"
- +source "drivers/media/platform/mxc/output/Kconfig"
- source "drivers/media/platform/soc_camera/Kconfig"
- source "drivers/media/platform/exynos4-is/Kconfig"
- source "drivers/media/platform/s5p-tv/Kconfig"
- diff -Nur linux-3.14.35.orig/drivers/media/platform/Makefile linux-3.14.35/drivers/media/platform/Makefile
- --- linux-3.14.35.orig/drivers/media/platform/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/Makefile 2015-03-08 14:27:37.581684501 -0500
- @@ -51,4 +51,7 @@
-
- obj-$(CONFIG_ARCH_OMAP) += omap/
-
- +obj-$(CONFIG_VIDEO_MXC_CAPTURE) += mxc/capture/
- +obj-$(CONFIG_VIDEO_MXC_OUTPUT) += mxc/output/
- +
- ccflags-y += -I$(srctree)/drivers/media/i2c
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/adv7180.c linux-3.14.35/drivers/media/platform/mxc/capture/adv7180.c
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/adv7180.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/adv7180.c 2015-03-08 14:27:37.581684501 -0500
- @@ -0,0 +1,1344 @@
- +/*
- + * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file adv7180.c
- + *
- + * @brief Analog Device ADV7180 video decoder functions
- + *
- + * @ingroup Camera
- + */
- +
- +#include <linux/clk.h>
- +#include <linux/delay.h>
- +#include <linux/device.h>
- +#include <linux/i2c.h>
- +#include <linux/init.h>
- +#include <linux/module.h>
- +#include <linux/of_device.h>
- +#include <linux/of_gpio.h>
- +#include <linux/pinctrl/consumer.h>
- +#include <linux/regulator/consumer.h>
- +#include <media/v4l2-chip-ident.h>
- +#include <media/v4l2-int-device.h>
- +#include "mxc_v4l2_capture.h"
- +
- +#define ADV7180_VOLTAGE_ANALOG 1800000
- +#define ADV7180_VOLTAGE_DIGITAL_CORE 1800000
- +#define ADV7180_VOLTAGE_DIGITAL_IO 3300000
- +#define ADV7180_VOLTAGE_PLL 1800000
- +
- +static struct regulator *dvddio_regulator;
- +static struct regulator *dvdd_regulator;
- +static struct regulator *avdd_regulator;
- +static struct regulator *pvdd_regulator;
- +static int pwn_gpio;
- +
- +static int adv7180_probe(struct i2c_client *adapter,
- + const struct i2c_device_id *id);
- +static int adv7180_detach(struct i2c_client *client);
- +
- +static const struct i2c_device_id adv7180_id[] = {
- + {"adv7180", 0},
- + {},
- +};
- +
- +MODULE_DEVICE_TABLE(i2c, adv7180_id);
- +
- +static struct i2c_driver adv7180_i2c_driver = {
- + .driver = {
- + .owner = THIS_MODULE,
- + .name = "adv7180",
- + },
- + .probe = adv7180_probe,
- + .remove = adv7180_detach,
- + .id_table = adv7180_id,
- +};
- +
- +/*!
- + * Maintains the information on the current state of the sensor.
- + */
- +struct sensor {
- + struct sensor_data sen;
- + v4l2_std_id std_id;
- +} adv7180_data;
- +
- +
- +/*! List of input video formats supported. The video formats is corresponding
- + * with v4l2 id in video_fmt_t
- + */
- +typedef enum {
- + ADV7180_NTSC = 0, /*!< Locked on (M) NTSC video signal. */
- + ADV7180_PAL, /*!< (B, G, H, I, N)PAL video signal. */
- + ADV7180_NOT_LOCKED, /*!< Not locked on a signal. */
- +} video_fmt_idx;
- +
- +/*! Number of video standards supported (including 'not locked' signal). */
- +#define ADV7180_STD_MAX (ADV7180_PAL + 1)
- +
- +/*! Video format structure. */
- +typedef struct {
- + int v4l2_id; /*!< Video for linux ID. */
- + char name[16]; /*!< Name (e.g., "NTSC", "PAL", etc.) */
- + u16 raw_width; /*!< Raw width. */
- + u16 raw_height; /*!< Raw height. */
- + u16 active_width; /*!< Active width. */
- + u16 active_height; /*!< Active height. */
- +} video_fmt_t;
- +
- +/*! Description of video formats supported.
- + *
- + * PAL: raw=720x625, active=720x576.
- + * NTSC: raw=720x525, active=720x480.
- + */
- +static video_fmt_t video_fmts[] = {
- + { /*! NTSC */
- + .v4l2_id = V4L2_STD_NTSC,
- + .name = "NTSC",
- + .raw_width = 720, /* SENS_FRM_WIDTH */
- + .raw_height = 525, /* SENS_FRM_HEIGHT */
- + .active_width = 720, /* ACT_FRM_WIDTH plus 1 */
- + .active_height = 480, /* ACT_FRM_WIDTH plus 1 */
- + },
- + { /*! (B, G, H, I, N) PAL */
- + .v4l2_id = V4L2_STD_PAL,
- + .name = "PAL",
- + .raw_width = 720,
- + .raw_height = 625,
- + .active_width = 720,
- + .active_height = 576,
- + },
- + { /*! Unlocked standard */
- + .v4l2_id = V4L2_STD_ALL,
- + .name = "Autodetect",
- + .raw_width = 720,
- + .raw_height = 625,
- + .active_width = 720,
- + .active_height = 576,
- + },
- +};
- +
- +/*!* Standard index of ADV7180. */
- +static video_fmt_idx video_idx = ADV7180_PAL;
- +
- +/*! @brief This mutex is used to provide mutual exclusion.
- + *
- + * Create a mutex that can be used to provide mutually exclusive
- + * read/write access to the globally accessible data structures
- + * and variables that were defined above.
- + */
- +static DEFINE_MUTEX(mutex);
- +
- +#define IF_NAME "adv7180"
- +#define ADV7180_INPUT_CTL 0x00 /* Input Control */
- +#define ADV7180_STATUS_1 0x10 /* Status #1 */
- +#define ADV7180_BRIGHTNESS 0x0a /* Brightness */
- +#define ADV7180_IDENT 0x11 /* IDENT */
- +#define ADV7180_VSYNC_FIELD_CTL_1 0x31 /* VSYNC Field Control #1 */
- +#define ADV7180_MANUAL_WIN_CTL 0x3d /* Manual Window Control */
- +#define ADV7180_SD_SATURATION_CB 0xe3 /* SD Saturation Cb */
- +#define ADV7180_SD_SATURATION_CR 0xe4 /* SD Saturation Cr */
- +#define ADV7180_PWR_MNG 0x0f /* Power Management */
- +
- +/* supported controls */
- +/* This hasn't been fully implemented yet.
- + * This is how it should work, though. */
- +static struct v4l2_queryctrl adv7180_qctrl[] = {
- + {
- + .id = V4L2_CID_BRIGHTNESS,
- + .type = V4L2_CTRL_TYPE_INTEGER,
- + .name = "Brightness",
- + .minimum = 0, /* check this value */
- + .maximum = 255, /* check this value */
- + .step = 1, /* check this value */
- + .default_value = 127, /* check this value */
- + .flags = 0,
- + }, {
- + .id = V4L2_CID_SATURATION,
- + .type = V4L2_CTRL_TYPE_INTEGER,
- + .name = "Saturation",
- + .minimum = 0, /* check this value */
- + .maximum = 255, /* check this value */
- + .step = 0x1, /* check this value */
- + .default_value = 127, /* check this value */
- + .flags = 0,
- + }
- +};
- +
- +static inline void adv7180_power_down(int enable)
- +{
- + gpio_set_value_cansleep(pwn_gpio, !enable);
- + msleep(2);
- +}
- +
- +static int adv7180_regulator_enable(struct device *dev)
- +{
- + int ret = 0;
- +
- + dvddio_regulator = devm_regulator_get(dev, "DOVDD");
- +
- + if (!IS_ERR(dvddio_regulator)) {
- + regulator_set_voltage(dvddio_regulator,
- + ADV7180_VOLTAGE_DIGITAL_IO,
- + ADV7180_VOLTAGE_DIGITAL_IO);
- + ret = regulator_enable(dvddio_regulator);
- + if (ret) {
- + dev_err(dev, "set io voltage failed\n");
- + return ret;
- + } else {
- + dev_dbg(dev, "set io voltage ok\n");
- + }
- + } else {
- + dev_warn(dev, "cannot get io voltage\n");
- + }
- +
- + dvdd_regulator = devm_regulator_get(dev, "DVDD");
- + if (!IS_ERR(dvdd_regulator)) {
- + regulator_set_voltage(dvdd_regulator,
- + ADV7180_VOLTAGE_DIGITAL_CORE,
- + ADV7180_VOLTAGE_DIGITAL_CORE);
- + ret = regulator_enable(dvdd_regulator);
- + if (ret) {
- + dev_err(dev, "set core voltage failed\n");
- + return ret;
- + } else {
- + dev_dbg(dev, "set core voltage ok\n");
- + }
- + } else {
- + dev_warn(dev, "cannot get core voltage\n");
- + }
- +
- + avdd_regulator = devm_regulator_get(dev, "AVDD");
- + if (!IS_ERR(avdd_regulator)) {
- + regulator_set_voltage(avdd_regulator,
- + ADV7180_VOLTAGE_ANALOG,
- + ADV7180_VOLTAGE_ANALOG);
- + ret = regulator_enable(avdd_regulator);
- + if (ret) {
- + dev_err(dev, "set analog voltage failed\n");
- + return ret;
- + } else {
- + dev_dbg(dev, "set analog voltage ok\n");
- + }
- + } else {
- + dev_warn(dev, "cannot get analog voltage\n");
- + }
- +
- + pvdd_regulator = devm_regulator_get(dev, "PVDD");
- + if (!IS_ERR(pvdd_regulator)) {
- + regulator_set_voltage(pvdd_regulator,
- + ADV7180_VOLTAGE_PLL,
- + ADV7180_VOLTAGE_PLL);
- + ret = regulator_enable(pvdd_regulator);
- + if (ret) {
- + dev_err(dev, "set pll voltage failed\n");
- + return ret;
- + } else {
- + dev_dbg(dev, "set pll voltage ok\n");
- + }
- + } else {
- + dev_warn(dev, "cannot get pll voltage\n");
- + }
- +
- + return ret;
- +}
- +
- +
- +/***********************************************************************
- + * I2C transfert.
- + ***********************************************************************/
- +
- +/*! Read one register from a ADV7180 i2c slave device.
- + *
- + * @param *reg register in the device we wish to access.
- + *
- + * @return 0 if success, an error code otherwise.
- + */
- +static inline int adv7180_read(u8 reg)
- +{
- + int val;
- +
- + val = i2c_smbus_read_byte_data(adv7180_data.sen.i2c_client, reg);
- + if (val < 0) {
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + "%s:read reg error: reg=%2x\n", __func__, reg);
- + return -1;
- + }
- + return val;
- +}
- +
- +/*! Write one register of a ADV7180 i2c slave device.
- + *
- + * @param *reg register in the device we wish to access.
- + *
- + * @return 0 if success, an error code otherwise.
- + */
- +static int adv7180_write_reg(u8 reg, u8 val)
- +{
- + s32 ret;
- +
- + ret = i2c_smbus_write_byte_data(adv7180_data.sen.i2c_client, reg, val);
- + if (ret < 0) {
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + "%s:write reg error:reg=%2x,val=%2x\n", __func__,
- + reg, val);
- + return -1;
- + }
- + return 0;
- +}
- +
- +/***********************************************************************
- + * mxc_v4l2_capture interface.
- + ***********************************************************************/
- +
- +/*!
- + * Return attributes of current video standard.
- + * Since this device autodetects the current standard, this function also
- + * sets the values that need to be changed if the standard changes.
- + * There is no set std equivalent function.
- + *
- + * @return None.
- + */
- +static void adv7180_get_std(v4l2_std_id *std)
- +{
- + int tmp;
- + int idx;
- +
- + dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180_get_std\n");
- +
- + /* Read the AD_RESULT to get the detect output video standard */
- + tmp = adv7180_read(ADV7180_STATUS_1) & 0x70;
- +
- + mutex_lock(&mutex);
- + if (tmp == 0x40) {
- + /* PAL */
- + *std = V4L2_STD_PAL;
- + idx = ADV7180_PAL;
- + } else if (tmp == 0) {
- + /*NTSC*/
- + *std = V4L2_STD_NTSC;
- + idx = ADV7180_NTSC;
- + } else {
- + *std = V4L2_STD_ALL;
- + idx = ADV7180_NOT_LOCKED;
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + "Got invalid video standard!\n");
- + }
- + mutex_unlock(&mutex);
- +
- + /* This assumes autodetect which this device uses. */
- + if (*std != adv7180_data.std_id) {
- + video_idx = idx;
- + adv7180_data.std_id = *std;
- + adv7180_data.sen.pix.width = video_fmts[video_idx].raw_width;
- + adv7180_data.sen.pix.height = video_fmts[video_idx].raw_height;
- + }
- +}
- +
- +/***********************************************************************
- + * IOCTL Functions from v4l2_int_ioctl_desc.
- + ***********************************************************************/
- +
- +/*!
- + * ioctl_g_ifparm - V4L2 sensor interface handler for vidioc_int_g_ifparm_num
- + * s: pointer to standard V4L2 device structure
- + * p: pointer to standard V4L2 vidioc_int_g_ifparm_num ioctl structure
- + *
- + * Gets slave interface parameters.
- + * Calculates the required xclk value to support the requested
- + * clock parameters in p. This value is returned in the p
- + * parameter.
- + *
- + * vidioc_int_g_ifparm returns platform-specific information about the
- + * interface settings used by the sensor.
- + *
- + * Called on open.
- + */
- +static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
- +{
- + dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_g_ifparm\n");
- +
- + if (s == NULL) {
- + pr_err(" ERROR!! no slave device set!\n");
- + return -1;
- + }
- +
- + /* Initialize structure to 0s then set any non-0 values. */
- + memset(p, 0, sizeof(*p));
- + p->if_type = V4L2_IF_TYPE_BT656; /* This is the only possibility. */
- + p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
- + p->u.bt656.nobt_hs_inv = 1;
- + p->u.bt656.bt_sync_correct = 1;
- +
- + /* ADV7180 has a dedicated clock so no clock settings needed. */
- +
- + return 0;
- +}
- +
- +/*!
- + * Sets the camera power.
- + *
- + * s pointer to the camera device
- + * on if 1, power is to be turned on. 0 means power is to be turned off
- + *
- + * ioctl_s_power - V4L2 sensor interface handler for vidioc_int_s_power_num
- + * @s: pointer to standard V4L2 device structure
- + * @on: power state to which device is to be set
- + *
- + * Sets devices power state to requrested state, if possible.
- + * This is called on open, close, suspend and resume.
- + */
- +static int ioctl_s_power(struct v4l2_int_device *s, int on)
- +{
- + struct sensor *sensor = s->priv;
- +
- + dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_s_power\n");
- +
- + if (on && !sensor->sen.on) {
- + if (adv7180_write_reg(ADV7180_PWR_MNG, 0x04) != 0)
- + return -EIO;
- +
- + /*
- + * FIXME:Additional 400ms to wait the chip to be stable?
- + * This is a workaround for preview scrolling issue.
- + */
- + msleep(400);
- + } else if (!on && sensor->sen.on) {
- + if (adv7180_write_reg(ADV7180_PWR_MNG, 0x24) != 0)
- + return -EIO;
- + }
- +
- + sensor->sen.on = on;
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
- + *
- + * Returns the sensor's video CAPTURE parameters.
- + */
- +static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
- +{
- + struct sensor *sensor = s->priv;
- + struct v4l2_captureparm *cparm = &a->parm.capture;
- +
- + dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_g_parm\n");
- +
- + switch (a->type) {
- + /* These are all the possible cases. */
- + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- + pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
- + memset(a, 0, sizeof(*a));
- + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- + cparm->capability = sensor->sen.streamcap.capability;
- + cparm->timeperframe = sensor->sen.streamcap.timeperframe;
- + cparm->capturemode = sensor->sen.streamcap.capturemode;
- + break;
- +
- + case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- + case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- + case V4L2_BUF_TYPE_VBI_CAPTURE:
- + case V4L2_BUF_TYPE_VBI_OUTPUT:
- + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- + break;
- +
- + default:
- + pr_debug("ioctl_g_parm:type is unknown %d\n", a->type);
- + break;
- + }
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
- + *
- + * Configures the sensor to use the input parameters, if possible. If
- + * not possible, reverts to the old parameters and returns the
- + * appropriate error code.
- + *
- + * This driver cannot change these settings.
- + */
- +static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
- +{
- + dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_s_parm\n");
- +
- + switch (a->type) {
- + /* These are all the possible cases. */
- + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- + case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- + case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- + case V4L2_BUF_TYPE_VBI_CAPTURE:
- + case V4L2_BUF_TYPE_VBI_OUTPUT:
- + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- + break;
- +
- + default:
- + pr_debug(" type is unknown - %d\n", a->type);
- + break;
- + }
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
- + * @s: pointer to standard V4L2 device structure
- + * @f: pointer to standard V4L2 v4l2_format structure
- + *
- + * Returns the sensor's current pixel format in the v4l2_format
- + * parameter.
- + */
- +static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
- +{
- + struct sensor *sensor = s->priv;
- +
- + dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_g_fmt_cap\n");
- +
- + switch (f->type) {
- + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- + pr_debug(" Returning size of %dx%d\n",
- + sensor->sen.pix.width, sensor->sen.pix.height);
- + f->fmt.pix = sensor->sen.pix;
- + break;
- +
- + case V4L2_BUF_TYPE_PRIVATE: {
- + v4l2_std_id std;
- + adv7180_get_std(&std);
- + f->fmt.pix.pixelformat = (u32)std;
- + }
- + break;
- +
- + default:
- + f->fmt.pix = sensor->sen.pix;
- + break;
- + }
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_queryctrl - V4L2 sensor interface handler for VIDIOC_QUERYCTRL ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @qc: standard V4L2 VIDIOC_QUERYCTRL ioctl structure
- + *
- + * If the requested control is supported, returns the control information
- + * from the video_control[] array. Otherwise, returns -EINVAL if the
- + * control is not supported.
- + */
- +static int ioctl_queryctrl(struct v4l2_int_device *s,
- + struct v4l2_queryctrl *qc)
- +{
- + int i;
- +
- + dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_queryctrl\n");
- +
- + for (i = 0; i < ARRAY_SIZE(adv7180_qctrl); i++)
- + if (qc->id && qc->id == adv7180_qctrl[i].id) {
- + memcpy(qc, &(adv7180_qctrl[i]),
- + sizeof(*qc));
- + return 0;
- + }
- +
- + return -EINVAL;
- +}
- +
- +/*!
- + * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
- + *
- + * If the requested control is supported, returns the control's current
- + * value from the video_control[] array. Otherwise, returns -EINVAL
- + * if the control is not supported.
- + */
- +static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
- +{
- + int ret = 0;
- + int sat = 0;
- +
- + dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_g_ctrl\n");
- +
- + switch (vc->id) {
- + case V4L2_CID_BRIGHTNESS:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_BRIGHTNESS\n");
- + adv7180_data.sen.brightness = adv7180_read(ADV7180_BRIGHTNESS);
- + vc->value = adv7180_data.sen.brightness;
- + break;
- + case V4L2_CID_CONTRAST:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_CONTRAST\n");
- + vc->value = adv7180_data.sen.contrast;
- + break;
- + case V4L2_CID_SATURATION:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_SATURATION\n");
- + sat = adv7180_read(ADV7180_SD_SATURATION_CB);
- + adv7180_data.sen.saturation = sat;
- + vc->value = adv7180_data.sen.saturation;
- + break;
- + case V4L2_CID_HUE:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_HUE\n");
- + vc->value = adv7180_data.sen.hue;
- + break;
- + case V4L2_CID_AUTO_WHITE_BALANCE:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_AUTO_WHITE_BALANCE\n");
- + break;
- + case V4L2_CID_DO_WHITE_BALANCE:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_DO_WHITE_BALANCE\n");
- + break;
- + case V4L2_CID_RED_BALANCE:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_RED_BALANCE\n");
- + vc->value = adv7180_data.sen.red;
- + break;
- + case V4L2_CID_BLUE_BALANCE:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_BLUE_BALANCE\n");
- + vc->value = adv7180_data.sen.blue;
- + break;
- + case V4L2_CID_GAMMA:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_GAMMA\n");
- + break;
- + case V4L2_CID_EXPOSURE:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_EXPOSURE\n");
- + vc->value = adv7180_data.sen.ae_mode;
- + break;
- + case V4L2_CID_AUTOGAIN:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_AUTOGAIN\n");
- + break;
- + case V4L2_CID_GAIN:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_GAIN\n");
- + break;
- + case V4L2_CID_HFLIP:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_HFLIP\n");
- + break;
- + case V4L2_CID_VFLIP:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_VFLIP\n");
- + break;
- + default:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " Default case\n");
- + vc->value = 0;
- + ret = -EPERM;
- + break;
- + }
- +
- + return ret;
- +}
- +
- +/*!
- + * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
- + *
- + * If the requested control is supported, sets the control's current
- + * value in HW (and updates the video_control[] array). Otherwise,
- + * returns -EINVAL if the control is not supported.
- + */
- +static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
- +{
- + int retval = 0;
- + u8 tmp;
- +
- + dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_s_ctrl\n");
- +
- + switch (vc->id) {
- + case V4L2_CID_BRIGHTNESS:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_BRIGHTNESS\n");
- + tmp = vc->value;
- + adv7180_write_reg(ADV7180_BRIGHTNESS, tmp);
- + adv7180_data.sen.brightness = vc->value;
- + break;
- + case V4L2_CID_CONTRAST:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_CONTRAST\n");
- + break;
- + case V4L2_CID_SATURATION:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_SATURATION\n");
- + tmp = vc->value;
- + adv7180_write_reg(ADV7180_SD_SATURATION_CB, tmp);
- + adv7180_write_reg(ADV7180_SD_SATURATION_CR, tmp);
- + adv7180_data.sen.saturation = vc->value;
- + break;
- + case V4L2_CID_HUE:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_HUE\n");
- + break;
- + case V4L2_CID_AUTO_WHITE_BALANCE:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_AUTO_WHITE_BALANCE\n");
- + break;
- + case V4L2_CID_DO_WHITE_BALANCE:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_DO_WHITE_BALANCE\n");
- + break;
- + case V4L2_CID_RED_BALANCE:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_RED_BALANCE\n");
- + break;
- + case V4L2_CID_BLUE_BALANCE:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_BLUE_BALANCE\n");
- + break;
- + case V4L2_CID_GAMMA:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_GAMMA\n");
- + break;
- + case V4L2_CID_EXPOSURE:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_EXPOSURE\n");
- + break;
- + case V4L2_CID_AUTOGAIN:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_AUTOGAIN\n");
- + break;
- + case V4L2_CID_GAIN:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_GAIN\n");
- + break;
- + case V4L2_CID_HFLIP:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_HFLIP\n");
- + break;
- + case V4L2_CID_VFLIP:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " V4L2_CID_VFLIP\n");
- + break;
- + default:
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + " Default case\n");
- + retval = -EPERM;
- + break;
- + }
- +
- + return retval;
- +}
- +
- +/*!
- + * ioctl_enum_framesizes - V4L2 sensor interface handler for
- + * VIDIOC_ENUM_FRAMESIZES ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
- + *
- + * Return 0 if successful, otherwise -EINVAL.
- + */
- +static int ioctl_enum_framesizes(struct v4l2_int_device *s,
- + struct v4l2_frmsizeenum *fsize)
- +{
- + if (fsize->index >= 1)
- + return -EINVAL;
- +
- + fsize->discrete.width = video_fmts[video_idx].active_width;
- + fsize->discrete.height = video_fmts[video_idx].active_height;
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_g_chip_ident - V4L2 sensor interface handler for
- + * VIDIOC_DBG_G_CHIP_IDENT ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @id: pointer to int
- + *
- + * Return 0.
- + */
- +static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
- +{
- + ((struct v4l2_dbg_chip_ident *)id)->match.type =
- + V4L2_CHIP_MATCH_I2C_DRIVER;
- + strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name,
- + "adv7180_decoder");
- + ((struct v4l2_dbg_chip_ident *)id)->ident = V4L2_IDENT_ADV7180;
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
- + * @s: pointer to standard V4L2 device structure
- + */
- +static int ioctl_init(struct v4l2_int_device *s)
- +{
- + dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_init\n");
- + return 0;
- +}
- +
- +/*!
- + * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
- + * @s: pointer to standard V4L2 device structure
- + *
- + * Initialise the device when slave attaches to the master.
- + */
- +static int ioctl_dev_init(struct v4l2_int_device *s)
- +{
- + dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_dev_init\n");
- + return 0;
- +}
- +
- +/*!
- + * This structure defines all the ioctls for this module.
- + */
- +static struct v4l2_int_ioctl_desc adv7180_ioctl_desc[] = {
- +
- + {vidioc_int_dev_init_num, (v4l2_int_ioctl_func*)ioctl_dev_init},
- +
- + /*!
- + * Delinitialise the dev. at slave detach.
- + * The complement of ioctl_dev_init.
- + */
- +/* {vidioc_int_dev_exit_num, (v4l2_int_ioctl_func *)ioctl_dev_exit}, */
- +
- + {vidioc_int_s_power_num, (v4l2_int_ioctl_func*)ioctl_s_power},
- + {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func*)ioctl_g_ifparm},
- +/* {vidioc_int_g_needs_reset_num,
- + (v4l2_int_ioctl_func *)ioctl_g_needs_reset}, */
- +/* {vidioc_int_reset_num, (v4l2_int_ioctl_func *)ioctl_reset}, */
- + {vidioc_int_init_num, (v4l2_int_ioctl_func*)ioctl_init},
- +
- + /*!
- + * VIDIOC_ENUM_FMT ioctl for the CAPTURE buffer type.
- + */
- +/* {vidioc_int_enum_fmt_cap_num,
- + (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap}, */
- +
- + /*!
- + * VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type.
- + * This ioctl is used to negotiate the image capture size and
- + * pixel format without actually making it take effect.
- + */
- +/* {vidioc_int_try_fmt_cap_num,
- + (v4l2_int_ioctl_func *)ioctl_try_fmt_cap}, */
- +
- + {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func*)ioctl_g_fmt_cap},
- +
- + /*!
- + * If the requested format is supported, configures the HW to use that
- + * format, returns error code if format not supported or HW can't be
- + * correctly configured.
- + */
- +/* {vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *)ioctl_s_fmt_cap}, */
- +
- + {vidioc_int_g_parm_num, (v4l2_int_ioctl_func*)ioctl_g_parm},
- + {vidioc_int_s_parm_num, (v4l2_int_ioctl_func*)ioctl_s_parm},
- + {vidioc_int_queryctrl_num, (v4l2_int_ioctl_func*)ioctl_queryctrl},
- + {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func*)ioctl_g_ctrl},
- + {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func*)ioctl_s_ctrl},
- + {vidioc_int_enum_framesizes_num,
- + (v4l2_int_ioctl_func *) ioctl_enum_framesizes},
- + {vidioc_int_g_chip_ident_num,
- + (v4l2_int_ioctl_func *)ioctl_g_chip_ident},
- +};
- +
- +static struct v4l2_int_slave adv7180_slave = {
- + .ioctls = adv7180_ioctl_desc,
- + .num_ioctls = ARRAY_SIZE(adv7180_ioctl_desc),
- +};
- +
- +static struct v4l2_int_device adv7180_int_device = {
- + .module = THIS_MODULE,
- + .name = "adv7180",
- + .type = v4l2_int_type_slave,
- + .u = {
- + .slave = &adv7180_slave,
- + },
- +};
- +
- +
- +/***********************************************************************
- + * I2C client and driver.
- + ***********************************************************************/
- +
- +/*! ADV7180 Reset function.
- + *
- + * @return None.
- + */
- +static void adv7180_hard_reset(bool cvbs)
- +{
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + "In adv7180:adv7180_hard_reset\n");
- +
- + if (cvbs) {
- + /* Set CVBS input on AIN1 */
- + adv7180_write_reg(ADV7180_INPUT_CTL, 0x00);
- + } else {
- + /*
- + * Set YPbPr input on AIN1,4,5 and normal
- + * operations(autodection of all stds).
- + */
- + adv7180_write_reg(ADV7180_INPUT_CTL, 0x09);
- + }
- +
- + /* Datasheet recommends */
- + adv7180_write_reg(0x01, 0xc8);
- + adv7180_write_reg(0x02, 0x04);
- + adv7180_write_reg(0x03, 0x00);
- + adv7180_write_reg(0x04, 0x45);
- + adv7180_write_reg(0x05, 0x00);
- + adv7180_write_reg(0x06, 0x02);
- + adv7180_write_reg(0x07, 0x7F);
- + adv7180_write_reg(0x08, 0x80);
- + adv7180_write_reg(0x0A, 0x00);
- + adv7180_write_reg(0x0B, 0x00);
- + adv7180_write_reg(0x0C, 0x36);
- + adv7180_write_reg(0x0D, 0x7C);
- + adv7180_write_reg(0x0E, 0x00);
- + adv7180_write_reg(0x0F, 0x00);
- + adv7180_write_reg(0x13, 0x00);
- + adv7180_write_reg(0x14, 0x12);
- + adv7180_write_reg(0x15, 0x00);
- + adv7180_write_reg(0x16, 0x00);
- + adv7180_write_reg(0x17, 0x01);
- + adv7180_write_reg(0x18, 0x93);
- + adv7180_write_reg(0xF1, 0x19);
- + adv7180_write_reg(0x1A, 0x00);
- + adv7180_write_reg(0x1B, 0x00);
- + adv7180_write_reg(0x1C, 0x00);
- + adv7180_write_reg(0x1D, 0x40);
- + adv7180_write_reg(0x1E, 0x00);
- + adv7180_write_reg(0x1F, 0x00);
- + adv7180_write_reg(0x20, 0x00);
- + adv7180_write_reg(0x21, 0x00);
- + adv7180_write_reg(0x22, 0x00);
- + adv7180_write_reg(0x23, 0xC0);
- + adv7180_write_reg(0x24, 0x00);
- + adv7180_write_reg(0x25, 0x00);
- + adv7180_write_reg(0x26, 0x00);
- + adv7180_write_reg(0x27, 0x58);
- + adv7180_write_reg(0x28, 0x00);
- + adv7180_write_reg(0x29, 0x00);
- + adv7180_write_reg(0x2A, 0x00);
- + adv7180_write_reg(0x2B, 0xE1);
- + adv7180_write_reg(0x2C, 0xAE);
- + adv7180_write_reg(0x2D, 0xF4);
- + adv7180_write_reg(0x2E, 0x00);
- + adv7180_write_reg(0x2F, 0xF0);
- + adv7180_write_reg(0x30, 0x00);
- + adv7180_write_reg(0x31, 0x12);
- + adv7180_write_reg(0x32, 0x41);
- + adv7180_write_reg(0x33, 0x84);
- + adv7180_write_reg(0x34, 0x00);
- + adv7180_write_reg(0x35, 0x02);
- + adv7180_write_reg(0x36, 0x00);
- + adv7180_write_reg(0x37, 0x01);
- + adv7180_write_reg(0x38, 0x80);
- + adv7180_write_reg(0x39, 0xC0);
- + adv7180_write_reg(0x3A, 0x10);
- + adv7180_write_reg(0x3B, 0x05);
- + adv7180_write_reg(0x3C, 0x58);
- + adv7180_write_reg(0x3D, 0xB2);
- + adv7180_write_reg(0x3E, 0x64);
- + adv7180_write_reg(0x3F, 0xE4);
- + adv7180_write_reg(0x40, 0x90);
- + adv7180_write_reg(0x41, 0x01);
- + adv7180_write_reg(0x42, 0x7E);
- + adv7180_write_reg(0x43, 0xA4);
- + adv7180_write_reg(0x44, 0xFF);
- + adv7180_write_reg(0x45, 0xB6);
- + adv7180_write_reg(0x46, 0x12);
- + adv7180_write_reg(0x48, 0x00);
- + adv7180_write_reg(0x49, 0x00);
- + adv7180_write_reg(0x4A, 0x00);
- + adv7180_write_reg(0x4B, 0x00);
- + adv7180_write_reg(0x4C, 0x00);
- + adv7180_write_reg(0x4D, 0xEF);
- + adv7180_write_reg(0x4E, 0x08);
- + adv7180_write_reg(0x4F, 0x08);
- + adv7180_write_reg(0x50, 0x08);
- + adv7180_write_reg(0x51, 0x24);
- + adv7180_write_reg(0x52, 0x0B);
- + adv7180_write_reg(0x53, 0x4E);
- + adv7180_write_reg(0x54, 0x80);
- + adv7180_write_reg(0x55, 0x00);
- + adv7180_write_reg(0x56, 0x10);
- + adv7180_write_reg(0x57, 0x00);
- + adv7180_write_reg(0x58, 0x00);
- + adv7180_write_reg(0x59, 0x00);
- + adv7180_write_reg(0x5A, 0x00);
- + adv7180_write_reg(0x5B, 0x00);
- + adv7180_write_reg(0x5C, 0x00);
- + adv7180_write_reg(0x5D, 0x00);
- + adv7180_write_reg(0x5E, 0x00);
- + adv7180_write_reg(0x5F, 0x00);
- + adv7180_write_reg(0x60, 0x00);
- + adv7180_write_reg(0x61, 0x00);
- + adv7180_write_reg(0x62, 0x20);
- + adv7180_write_reg(0x63, 0x00);
- + adv7180_write_reg(0x64, 0x00);
- + adv7180_write_reg(0x65, 0x00);
- + adv7180_write_reg(0x66, 0x00);
- + adv7180_write_reg(0x67, 0x03);
- + adv7180_write_reg(0x68, 0x01);
- + adv7180_write_reg(0x69, 0x00);
- + adv7180_write_reg(0x6A, 0x00);
- + adv7180_write_reg(0x6B, 0xC0);
- + adv7180_write_reg(0x6C, 0x00);
- + adv7180_write_reg(0x6D, 0x00);
- + adv7180_write_reg(0x6E, 0x00);
- + adv7180_write_reg(0x6F, 0x00);
- + adv7180_write_reg(0x70, 0x00);
- + adv7180_write_reg(0x71, 0x00);
- + adv7180_write_reg(0x72, 0x00);
- + adv7180_write_reg(0x73, 0x10);
- + adv7180_write_reg(0x74, 0x04);
- + adv7180_write_reg(0x75, 0x01);
- + adv7180_write_reg(0x76, 0x00);
- + adv7180_write_reg(0x77, 0x3F);
- + adv7180_write_reg(0x78, 0xFF);
- + adv7180_write_reg(0x79, 0xFF);
- + adv7180_write_reg(0x7A, 0xFF);
- + adv7180_write_reg(0x7B, 0x1E);
- + adv7180_write_reg(0x7C, 0xC0);
- + adv7180_write_reg(0x7D, 0x00);
- + adv7180_write_reg(0x7E, 0x00);
- + adv7180_write_reg(0x7F, 0x00);
- + adv7180_write_reg(0x80, 0x00);
- + adv7180_write_reg(0x81, 0xC0);
- + adv7180_write_reg(0x82, 0x04);
- + adv7180_write_reg(0x83, 0x00);
- + adv7180_write_reg(0x84, 0x0C);
- + adv7180_write_reg(0x85, 0x02);
- + adv7180_write_reg(0x86, 0x03);
- + adv7180_write_reg(0x87, 0x63);
- + adv7180_write_reg(0x88, 0x5A);
- + adv7180_write_reg(0x89, 0x08);
- + adv7180_write_reg(0x8A, 0x10);
- + adv7180_write_reg(0x8B, 0x00);
- + adv7180_write_reg(0x8C, 0x40);
- + adv7180_write_reg(0x8D, 0x00);
- + adv7180_write_reg(0x8E, 0x40);
- + adv7180_write_reg(0x8F, 0x00);
- + adv7180_write_reg(0x90, 0x00);
- + adv7180_write_reg(0x91, 0x50);
- + adv7180_write_reg(0x92, 0x00);
- + adv7180_write_reg(0x93, 0x00);
- + adv7180_write_reg(0x94, 0x00);
- + adv7180_write_reg(0x95, 0x00);
- + adv7180_write_reg(0x96, 0x00);
- + adv7180_write_reg(0x97, 0xF0);
- + adv7180_write_reg(0x98, 0x00);
- + adv7180_write_reg(0x99, 0x00);
- + adv7180_write_reg(0x9A, 0x00);
- + adv7180_write_reg(0x9B, 0x00);
- + adv7180_write_reg(0x9C, 0x00);
- + adv7180_write_reg(0x9D, 0x00);
- + adv7180_write_reg(0x9E, 0x00);
- + adv7180_write_reg(0x9F, 0x00);
- + adv7180_write_reg(0xA0, 0x00);
- + adv7180_write_reg(0xA1, 0x00);
- + adv7180_write_reg(0xA2, 0x00);
- + adv7180_write_reg(0xA3, 0x00);
- + adv7180_write_reg(0xA4, 0x00);
- + adv7180_write_reg(0xA5, 0x00);
- + adv7180_write_reg(0xA6, 0x00);
- + adv7180_write_reg(0xA7, 0x00);
- + adv7180_write_reg(0xA8, 0x00);
- + adv7180_write_reg(0xA9, 0x00);
- + adv7180_write_reg(0xAA, 0x00);
- + adv7180_write_reg(0xAB, 0x00);
- + adv7180_write_reg(0xAC, 0x00);
- + adv7180_write_reg(0xAD, 0x00);
- + adv7180_write_reg(0xAE, 0x60);
- + adv7180_write_reg(0xAF, 0x00);
- + adv7180_write_reg(0xB0, 0x00);
- + adv7180_write_reg(0xB1, 0x60);
- + adv7180_write_reg(0xB2, 0x1C);
- + adv7180_write_reg(0xB3, 0x54);
- + adv7180_write_reg(0xB4, 0x00);
- + adv7180_write_reg(0xB5, 0x00);
- + adv7180_write_reg(0xB6, 0x00);
- + adv7180_write_reg(0xB7, 0x13);
- + adv7180_write_reg(0xB8, 0x03);
- + adv7180_write_reg(0xB9, 0x33);
- + adv7180_write_reg(0xBF, 0x02);
- + adv7180_write_reg(0xC0, 0x00);
- + adv7180_write_reg(0xC1, 0x00);
- + adv7180_write_reg(0xC2, 0x00);
- + adv7180_write_reg(0xC3, 0x00);
- + adv7180_write_reg(0xC4, 0x00);
- + adv7180_write_reg(0xC5, 0x81);
- + adv7180_write_reg(0xC6, 0x00);
- + adv7180_write_reg(0xC7, 0x00);
- + adv7180_write_reg(0xC8, 0x00);
- + adv7180_write_reg(0xC9, 0x04);
- + adv7180_write_reg(0xCC, 0x69);
- + adv7180_write_reg(0xCD, 0x00);
- + adv7180_write_reg(0xCE, 0x01);
- + adv7180_write_reg(0xCF, 0xB4);
- + adv7180_write_reg(0xD0, 0x00);
- + adv7180_write_reg(0xD1, 0x10);
- + adv7180_write_reg(0xD2, 0xFF);
- + adv7180_write_reg(0xD3, 0xFF);
- + adv7180_write_reg(0xD4, 0x7F);
- + adv7180_write_reg(0xD5, 0x7F);
- + adv7180_write_reg(0xD6, 0x3E);
- + adv7180_write_reg(0xD7, 0x08);
- + adv7180_write_reg(0xD8, 0x3C);
- + adv7180_write_reg(0xD9, 0x08);
- + adv7180_write_reg(0xDA, 0x3C);
- + adv7180_write_reg(0xDB, 0x9B);
- + adv7180_write_reg(0xDC, 0xAC);
- + adv7180_write_reg(0xDD, 0x4C);
- + adv7180_write_reg(0xDE, 0x00);
- + adv7180_write_reg(0xDF, 0x00);
- + adv7180_write_reg(0xE0, 0x14);
- + adv7180_write_reg(0xE1, 0x80);
- + adv7180_write_reg(0xE2, 0x80);
- + adv7180_write_reg(0xE3, 0x80);
- + adv7180_write_reg(0xE4, 0x80);
- + adv7180_write_reg(0xE5, 0x25);
- + adv7180_write_reg(0xE6, 0x44);
- + adv7180_write_reg(0xE7, 0x63);
- + adv7180_write_reg(0xE8, 0x65);
- + adv7180_write_reg(0xE9, 0x14);
- + adv7180_write_reg(0xEA, 0x63);
- + adv7180_write_reg(0xEB, 0x55);
- + adv7180_write_reg(0xEC, 0x55);
- + adv7180_write_reg(0xEE, 0x00);
- + adv7180_write_reg(0xEF, 0x4A);
- + adv7180_write_reg(0xF0, 0x44);
- + adv7180_write_reg(0xF1, 0x0C);
- + adv7180_write_reg(0xF2, 0x32);
- + adv7180_write_reg(0xF3, 0x00);
- + adv7180_write_reg(0xF4, 0x3F);
- + adv7180_write_reg(0xF5, 0xE0);
- + adv7180_write_reg(0xF6, 0x69);
- + adv7180_write_reg(0xF7, 0x10);
- + adv7180_write_reg(0xF8, 0x00);
- + adv7180_write_reg(0xF9, 0x03);
- + adv7180_write_reg(0xFA, 0xFA);
- + adv7180_write_reg(0xFB, 0x40);
- +}
- +
- +/*! ADV7180 I2C attach function.
- + *
- + * @param *adapter struct i2c_adapter *.
- + *
- + * @return Error code indicating success or failure.
- + */
- +
- +/*!
- + * ADV7180 I2C probe function.
- + * Function set in i2c_driver struct.
- + * Called by insmod.
- + *
- + * @param *adapter I2C adapter descriptor.
- + *
- + * @return Error code indicating success or failure.
- + */
- +static int adv7180_probe(struct i2c_client *client,
- + const struct i2c_device_id *id)
- +{
- + int rev_id;
- + int ret = 0;
- + u32 cvbs = true;
- + struct pinctrl *pinctrl;
- + struct device *dev = &client->dev;
- +
- + printk(KERN_ERR"DBG sensor data is at %p\n", &adv7180_data);
- +
- + /* ov5640 pinctrl */
- + pinctrl = devm_pinctrl_get_select_default(dev);
- + if (IS_ERR(pinctrl)) {
- + dev_err(dev, "setup pinctrl failed\n");
- + return PTR_ERR(pinctrl);
- + }
- +
- + /* request power down pin */
- + pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
- + if (!gpio_is_valid(pwn_gpio)) {
- + dev_err(dev, "no sensor pwdn pin available\n");
- + return -ENODEV;
- + }
- + ret = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
- + "adv7180_pwdn");
- + if (ret < 0) {
- + dev_err(dev, "no power pin available!\n");
- + return ret;
- + }
- +
- + adv7180_regulator_enable(dev);
- +
- + adv7180_power_down(0);
- +
- + msleep(1);
- +
- + /* Set initial values for the sensor struct. */
- + memset(&adv7180_data, 0, sizeof(adv7180_data));
- + adv7180_data.sen.i2c_client = client;
- + adv7180_data.sen.streamcap.timeperframe.denominator = 30;
- + adv7180_data.sen.streamcap.timeperframe.numerator = 1;
- + adv7180_data.std_id = V4L2_STD_ALL;
- + video_idx = ADV7180_NOT_LOCKED;
- + adv7180_data.sen.pix.width = video_fmts[video_idx].raw_width;
- + adv7180_data.sen.pix.height = video_fmts[video_idx].raw_height;
- + adv7180_data.sen.pix.pixelformat = V4L2_PIX_FMT_UYVY; /* YUV422 */
- + adv7180_data.sen.pix.priv = 1; /* 1 is used to indicate TV in */
- + adv7180_data.sen.on = true;
- +
- + adv7180_data.sen.sensor_clk = devm_clk_get(dev, "csi_mclk");
- + if (IS_ERR(adv7180_data.sen.sensor_clk)) {
- + dev_err(dev, "get mclk failed\n");
- + return PTR_ERR(adv7180_data.sen.sensor_clk);
- + }
- +
- + ret = of_property_read_u32(dev->of_node, "mclk",
- + &adv7180_data.sen.mclk);
- + if (ret) {
- + dev_err(dev, "mclk frequency is invalid\n");
- + return ret;
- + }
- +
- + ret = of_property_read_u32(
- + dev->of_node, "mclk_source",
- + (u32 *) &(adv7180_data.sen.mclk_source));
- + if (ret) {
- + dev_err(dev, "mclk_source invalid\n");
- + return ret;
- + }
- +
- + ret = of_property_read_u32(dev->of_node, "csi_id",
- + &(adv7180_data.sen.csi));
- + if (ret) {
- + dev_err(dev, "csi_id invalid\n");
- + return ret;
- + }
- +
- + clk_prepare_enable(adv7180_data.sen.sensor_clk);
- +
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + "%s:adv7180 probe i2c address is 0x%02X\n",
- + __func__, adv7180_data.sen.i2c_client->addr);
- +
- + /*! Read the revision ID of the tvin chip */
- + rev_id = adv7180_read(ADV7180_IDENT);
- + dev_dbg(dev,
- + "%s:Analog Device adv7%2X0 detected!\n", __func__,
- + rev_id);
- +
- + ret = of_property_read_u32(dev->of_node, "cvbs", &(cvbs));
- + if (ret) {
- + dev_err(dev, "cvbs setting is not found\n");
- + cvbs = true;
- + }
- +
- + /*! ADV7180 initialization. */
- + adv7180_hard_reset(cvbs);
- +
- + pr_debug(" type is %d (expect %d)\n",
- + adv7180_int_device.type, v4l2_int_type_slave);
- + pr_debug(" num ioctls is %d\n",
- + adv7180_int_device.u.slave->num_ioctls);
- +
- + /* This function attaches this structure to the /dev/video0 device.
- + * The pointer in priv points to the adv7180_data structure here.*/
- + adv7180_int_device.priv = &adv7180_data;
- + ret = v4l2_int_device_register(&adv7180_int_device);
- +
- + clk_disable_unprepare(adv7180_data.sen.sensor_clk);
- +
- + return ret;
- +}
- +
- +/*!
- + * ADV7180 I2C detach function.
- + * Called on rmmod.
- + *
- + * @param *client struct i2c_client*.
- + *
- + * @return Error code indicating success or failure.
- + */
- +static int adv7180_detach(struct i2c_client *client)
- +{
- + dev_dbg(&adv7180_data.sen.i2c_client->dev,
- + "%s:Removing %s video decoder @ 0x%02X from adapter %s\n",
- + __func__, IF_NAME, client->addr << 1, client->adapter->name);
- +
- + /* Power down via i2c */
- + adv7180_write_reg(ADV7180_PWR_MNG, 0x24);
- +
- + if (dvddio_regulator)
- + regulator_disable(dvddio_regulator);
- +
- + if (dvdd_regulator)
- + regulator_disable(dvdd_regulator);
- +
- + if (avdd_regulator)
- + regulator_disable(avdd_regulator);
- +
- + if (pvdd_regulator)
- + regulator_disable(pvdd_regulator);
- +
- + v4l2_int_device_unregister(&adv7180_int_device);
- +
- + return 0;
- +}
- +
- +/*!
- + * ADV7180 init function.
- + * Called on insmod.
- + *
- + * @return Error code indicating success or failure.
- + */
- +static __init int adv7180_init(void)
- +{
- + u8 err = 0;
- +
- + pr_debug("In adv7180_init\n");
- +
- + /* Tells the i2c driver what functions to call for this driver. */
- + err = i2c_add_driver(&adv7180_i2c_driver);
- + if (err != 0)
- + pr_err("%s:driver registration failed, error=%d\n",
- + __func__, err);
- +
- + return err;
- +}
- +
- +/*!
- + * ADV7180 cleanup function.
- + * Called on rmmod.
- + *
- + * @return Error code indicating success or failure.
- + */
- +static void __exit adv7180_clean(void)
- +{
- + dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180_clean\n");
- + i2c_del_driver(&adv7180_i2c_driver);
- +}
- +
- +module_init(adv7180_init);
- +module_exit(adv7180_clean);
- +
- +MODULE_AUTHOR("Freescale Semiconductor");
- +MODULE_DESCRIPTION("Anolog Device ADV7180 video decoder driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/csi_v4l2_capture.c linux-3.14.35/drivers/media/platform/mxc/capture/csi_v4l2_capture.c
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/csi_v4l2_capture.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/csi_v4l2_capture.c 2015-03-08 14:27:37.585684501 -0500
- @@ -0,0 +1,2047 @@
- +/*
- + * Copyright 2009-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file drivers/media/video/mxc/capture/csi_v4l2_capture.c
- + * This file is derived from mxc_v4l2_capture.c
- + *
- + * @brief Video For Linux 2 capture driver
- + *
- + * @ingroup MXC_V4L2_CAPTURE
- + */
- +#include <linux/version.h>
- +#include <linux/module.h>
- +#include <linux/init.h>
- +#include <linux/platform_device.h>
- +#include <linux/fs.h>
- +#include <linux/slab.h>
- +#include <linux/ctype.h>
- +#include <linux/clk.h>
- +#include <linux/io.h>
- +#include <linux/semaphore.h>
- +#include <linux/pagemap.h>
- +#include <linux/vmalloc.h>
- +#include <linux/types.h>
- +#include <linux/fb.h>
- +#include <linux/mxcfb.h>
- +#include <linux/dma-mapping.h>
- +#include <media/v4l2-ioctl.h>
- +#include <media/v4l2-int-device.h>
- +#include <media/v4l2-chip-ident.h>
- +#include "mxc_v4l2_capture.h"
- +#include "fsl_csi.h"
- +
- +static int video_nr = -1;
- +static cam_data *g_cam;
- +static int req_buf_number;
- +
- +static int csi_v4l2_master_attach(struct v4l2_int_device *slave);
- +static void csi_v4l2_master_detach(struct v4l2_int_device *slave);
- +static u8 camera_power(cam_data *cam, bool cameraOn);
- +struct v4l2_crop crop_current;
- +struct v4l2_window win_current;
- +
- +/*! Information about this driver. */
- +static struct v4l2_int_master csi_v4l2_master = {
- + .attach = csi_v4l2_master_attach,
- + .detach = csi_v4l2_master_detach,
- +};
- +
- +static struct v4l2_int_device csi_v4l2_int_device = {
- + .module = THIS_MODULE,
- + .name = "csi_v4l2_cap",
- + .type = v4l2_int_type_master,
- + .u = {
- + .master = &csi_v4l2_master,
- + },
- +};
- +
- +static struct v4l2_queryctrl pxp_controls[] = {
- + {
- + .id = V4L2_CID_HFLIP,
- + .type = V4L2_CTRL_TYPE_BOOLEAN,
- + .name = "Horizontal Flip",
- + .minimum = 0,
- + .maximum = 1,
- + .step = 1,
- + .default_value = 0,
- + .flags = 0,
- + }, {
- + .id = V4L2_CID_VFLIP,
- + .type = V4L2_CTRL_TYPE_BOOLEAN,
- + .name = "Vertical Flip",
- + .minimum = 0,
- + .maximum = 1,
- + .step = 1,
- + .default_value = 0,
- + .flags = 0,
- + }, {
- + .id = V4L2_CID_PRIVATE_BASE,
- + .type = V4L2_CTRL_TYPE_INTEGER,
- + .name = "Rotation",
- + .minimum = 0,
- + .maximum = 270,
- + .step = 90,
- + .default_value = 0,
- + .flags = 0,
- + },
- +};
- +
- +/* Callback function triggered after PxP receives an EOF interrupt */
- +static void pxp_dma_done(void *arg)
- +{
- + struct pxp_tx_desc *tx_desc = to_tx_desc(arg);
- + struct dma_chan *chan = tx_desc->txd.chan;
- + struct pxp_channel *pxp_chan = to_pxp_channel(chan);
- + cam_data *cam = pxp_chan->client;
- +
- + /* This call will signal wait_for_completion_timeout() */
- + complete(&cam->pxp_tx_cmpl);
- +}
- +
- +static bool chan_filter(struct dma_chan *chan, void *arg)
- +{
- + if (imx_dma_is_pxp(chan))
- + return true;
- + else
- + return false;
- +}
- +
- +/* Function to request PXP DMA channel */
- +static int pxp_chan_init(cam_data *cam)
- +{
- + dma_cap_mask_t mask;
- + struct dma_chan *chan;
- +
- + /* Request a free channel */
- + dma_cap_zero(mask);
- + dma_cap_set(DMA_SLAVE, mask);
- + dma_cap_set(DMA_PRIVATE, mask);
- + chan = dma_request_channel(mask, chan_filter, NULL);
- + if (!chan) {
- + pr_err("Unsuccessfully request channel!\n");
- + return -EBUSY;
- + }
- +
- + cam->pxp_chan = to_pxp_channel(chan);
- + cam->pxp_chan->client = cam;
- +
- + init_completion(&cam->pxp_tx_cmpl);
- +
- + return 0;
- +}
- +
- +/*
- + * Function to call PxP DMA driver and send our new V4L2 buffer
- + * through the PxP.
- + * Note: This is a blocking call, so upon return the PxP tx should be complete.
- + */
- +static int pxp_process_update(cam_data *cam)
- +{
- + dma_cookie_t cookie;
- + struct scatterlist *sg = cam->sg;
- + struct dma_chan *dma_chan;
- + struct pxp_tx_desc *desc;
- + struct dma_async_tx_descriptor *txd;
- + struct pxp_config_data *pxp_conf = &cam->pxp_conf;
- + struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data;
- + int i, ret;
- + int length;
- +
- + pr_debug("Starting PxP Send Buffer\n");
- +
- + /* First, check to see that we have acquired a PxP Channel object */
- + if (cam->pxp_chan == NULL) {
- + /*
- + * PxP Channel has not yet been created and initialized,
- + * so let's go ahead and try
- + */
- + ret = pxp_chan_init(cam);
- + if (ret) {
- + /*
- + * PxP channel init failed, and we can't use the
- + * PxP until the PxP DMA driver has loaded, so we abort
- + */
- + pr_err("PxP chan init failed\n");
- + return -ENODEV;
- + }
- + }
- +
- + /*
- + * Init completion, so that we can be properly informed of
- + * the completion of the PxP task when it is done.
- + */
- + init_completion(&cam->pxp_tx_cmpl);
- +
- + dma_chan = &cam->pxp_chan->dma_chan;
- +
- + txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg, 2,
- + DMA_TO_DEVICE,
- + DMA_PREP_INTERRUPT,
- + NULL);
- + if (!txd) {
- + pr_err("Error preparing a DMA transaction descriptor.\n");
- + return -EIO;
- + }
- +
- + txd->callback_param = txd;
- + txd->callback = pxp_dma_done;
- +
- + /*
- + * Configure PxP for processing of new v4l2 buf
- + */
- + pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_UYVY;
- + pxp_conf->s0_param.color_key = -1;
- + pxp_conf->s0_param.color_key_enable = false;
- + pxp_conf->s0_param.width = cam->v2f.fmt.pix.width;
- + pxp_conf->s0_param.height = cam->v2f.fmt.pix.height;
- +
- + pxp_conf->ol_param[0].combine_enable = false;
- +
- + proc_data->srect.top = 0;
- + proc_data->srect.left = 0;
- + proc_data->srect.width = pxp_conf->s0_param.width;
- + proc_data->srect.height = pxp_conf->s0_param.height;
- +
- + if (crop_current.c.top != 0)
- + proc_data->srect.top = crop_current.c.top;
- + if (crop_current.c.left != 0)
- + proc_data->srect.left = crop_current.c.left;
- + if (crop_current.c.width != 0)
- + proc_data->srect.width = crop_current.c.width;
- + if (crop_current.c.height != 0)
- + proc_data->srect.height = crop_current.c.height;
- +
- + proc_data->drect.left = 0;
- + proc_data->drect.top = 0;
- + proc_data->drect.width = proc_data->srect.width;
- + proc_data->drect.height = proc_data->srect.height;
- +
- + if (win_current.w.left != 0)
- + proc_data->drect.left = win_current.w.left;
- + if (win_current.w.top != 0)
- + proc_data->drect.top = win_current.w.top;
- + if (win_current.w.width != 0)
- + proc_data->drect.width = win_current.w.width;
- + if (win_current.w.height != 0)
- + proc_data->drect.height = win_current.w.height;
- +
- + pr_debug("srect l: %d, t: %d, w: %d, h: %d; "
- + "drect l: %d, t: %d, w: %d, h: %d\n",
- + proc_data->srect.left, proc_data->srect.top,
- + proc_data->srect.width, proc_data->srect.height,
- + proc_data->drect.left, proc_data->drect.top,
- + proc_data->drect.width, proc_data->drect.height);
- +
- + pxp_conf->out_param.pixel_fmt = PXP_PIX_FMT_RGB565;
- + pxp_conf->out_param.width = proc_data->drect.width;
- + pxp_conf->out_param.height = proc_data->drect.height;
- +
- + if (cam->rotation % 180)
- + pxp_conf->out_param.stride = pxp_conf->out_param.height;
- + else
- + pxp_conf->out_param.stride = pxp_conf->out_param.width;
- +
- + desc = to_tx_desc(txd);
- + length = desc->len;
- + for (i = 0; i < length; i++) {
- + if (i == 0) {/* S0 */
- + memcpy(&desc->proc_data, proc_data,
- + sizeof(struct pxp_proc_data));
- + pxp_conf->s0_param.paddr = sg_dma_address(&sg[0]);
- + memcpy(&desc->layer_param.s0_param, &pxp_conf->s0_param,
- + sizeof(struct pxp_layer_param));
- + } else if (i == 1) {
- + pxp_conf->out_param.paddr = sg_dma_address(&sg[1]);
- + memcpy(&desc->layer_param.out_param,
- + &pxp_conf->out_param,
- + sizeof(struct pxp_layer_param));
- + }
- +
- + desc = desc->next;
- + }
- +
- + /* Submitting our TX starts the PxP processing task */
- + cookie = txd->tx_submit(txd);
- + if (cookie < 0) {
- + pr_err("Error sending FB through PxP\n");
- + return -EIO;
- + }
- +
- + cam->txd = txd;
- +
- + /* trigger PxP */
- + dma_async_issue_pending(dma_chan);
- +
- + return 0;
- +}
- +
- +static int pxp_complete_update(cam_data *cam)
- +{
- + int ret;
- + /*
- + * Wait for completion event, which will be set
- + * through our TX callback function.
- + */
- + ret = wait_for_completion_timeout(&cam->pxp_tx_cmpl, HZ / 10);
- + if (ret <= 0) {
- + pr_warning("PxP operation failed due to %s\n",
- + ret < 0 ? "user interrupt" : "timeout");
- + dma_release_channel(&cam->pxp_chan->dma_chan);
- + cam->pxp_chan = NULL;
- + return ret ? : -ETIMEDOUT;
- + }
- +
- + dma_release_channel(&cam->pxp_chan->dma_chan);
- + cam->pxp_chan = NULL;
- +
- + pr_debug("TX completed\n");
- +
- + return 0;
- +}
- +
- +/*!
- + * Camera V4l2 callback function.
- + *
- + * @param mask u32
- + * @param dev void device structure
- + *
- + * @return none
- + */
- +static void camera_callback(u32 mask, void *dev)
- +{
- + struct mxc_v4l_frame *done_frame;
- + struct mxc_v4l_frame *ready_frame;
- + cam_data *cam;
- +
- + cam = (cam_data *) dev;
- + if (cam == NULL)
- + return;
- +
- + spin_lock(&cam->queue_int_lock);
- + spin_lock(&cam->dqueue_int_lock);
- + if (!list_empty(&cam->working_q)) {
- + done_frame = list_entry(cam->working_q.next,
- + struct mxc_v4l_frame, queue);
- +
- + if (done_frame->csi_buf_num != cam->ping_pong_csi)
- + goto next;
- +
- + if (done_frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) {
- + done_frame->buffer.flags |= V4L2_BUF_FLAG_DONE;
- + done_frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED;
- +
- + /* Added to the done queue */
- + list_del(cam->working_q.next);
- + list_add_tail(&done_frame->queue, &cam->done_q);
- + cam->enc_counter++;
- + wake_up_interruptible(&cam->enc_queue);
- + } else {
- + pr_err("ERROR: v4l2 capture: %s: "
- + "buffer not queued\n", __func__);
- + }
- + }
- +
- +next:
- + if (!list_empty(&cam->ready_q)) {
- + ready_frame = list_entry(cam->ready_q.next,
- + struct mxc_v4l_frame, queue);
- + list_del(cam->ready_q.next);
- + list_add_tail(&ready_frame->queue, &cam->working_q);
- +
- + __raw_writel(ready_frame->paddress,
- + cam->ping_pong_csi == 1 ? CSI_CSIDMASA_FB1 :
- + CSI_CSIDMASA_FB2);
- + ready_frame->csi_buf_num = cam->ping_pong_csi;
- + } else {
- + __raw_writel(cam->dummy_frame.paddress,
- + cam->ping_pong_csi == 1 ? CSI_CSIDMASA_FB1 :
- + CSI_CSIDMASA_FB2);
- + }
- + spin_unlock(&cam->dqueue_int_lock);
- + spin_unlock(&cam->queue_int_lock);
- +
- + return;
- +}
- +
- +/*!
- + * Make csi ready for capture image.
- + *
- + * @param cam structure cam_data *
- + *
- + * @return status 0 success
- + */
- +static int csi_cap_image(cam_data *cam)
- +{
- + unsigned int value;
- +
- + value = __raw_readl(CSI_CSICR3);
- + __raw_writel(value | BIT_FRMCNT_RST, CSI_CSICR3);
- + value = __raw_readl(CSI_CSISR);
- + __raw_writel(value, CSI_CSISR);
- +
- + return 0;
- +}
- +
- +/***************************************************************************
- + * Functions for handling Frame buffers.
- + **************************************************************************/
- +
- +/*!
- + * Free frame buffers
- + *
- + * @param cam Structure cam_data *
- + *
- + * @return status 0 success.
- + */
- +static int csi_free_frame_buf(cam_data *cam)
- +{
- + int i;
- +
- + pr_debug("MVC: In %s\n", __func__);
- +
- + for (i = 0; i < FRAME_NUM; i++) {
- + if (cam->frame[i].vaddress != 0) {
- + dma_free_coherent(0, cam->frame[i].buffer.length,
- + cam->frame[i].vaddress,
- + cam->frame[i].paddress);
- + cam->frame[i].vaddress = 0;
- + }
- + }
- +
- + if (cam->dummy_frame.vaddress != 0) {
- + dma_free_coherent(0, cam->dummy_frame.buffer.length,
- + cam->dummy_frame.vaddress,
- + cam->dummy_frame.paddress);
- + cam->dummy_frame.vaddress = 0;
- + }
- +
- + return 0;
- +}
- +
- +/*!
- + * Allocate frame buffers
- + *
- + * @param cam Structure cam_data *
- + * @param count int number of buffer need to allocated
- + *
- + * @return status -0 Successfully allocated a buffer, -ENOBUFS failed.
- + */
- +static int csi_allocate_frame_buf(cam_data *cam, int count)
- +{
- + int i;
- +
- + pr_debug("In MVC:%s- size=%d\n",
- + __func__, cam->v2f.fmt.pix.sizeimage);
- + for (i = 0; i < count; i++) {
- + cam->frame[i].vaddress = dma_alloc_coherent(0, PAGE_ALIGN
- + (cam->v2f.fmt.
- + pix.sizeimage),
- + &cam->frame[i].
- + paddress,
- + GFP_DMA |
- + GFP_KERNEL);
- + if (cam->frame[i].vaddress == 0) {
- + pr_err("ERROR: v4l2 capture: "
- + "%s failed.\n", __func__);
- + csi_free_frame_buf(cam);
- + return -ENOBUFS;
- + }
- + cam->frame[i].buffer.index = i;
- + cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED;
- + cam->frame[i].buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- + cam->frame[i].buffer.length = cam->v2f.fmt.pix.sizeimage;
- + cam->frame[i].buffer.memory = V4L2_MEMORY_MMAP;
- + cam->frame[i].buffer.m.offset = cam->frame[i].paddress;
- + cam->frame[i].index = i;
- + cam->frame[i].csi_buf_num = 0;
- + }
- +
- + return 0;
- +}
- +
- +/*!
- + * Free frame buffers status
- + *
- + * @param cam Structure cam_data *
- + *
- + * @return none
- + */
- +static void csi_free_frames(cam_data *cam)
- +{
- + int i;
- +
- + pr_debug("In MVC: %s\n", __func__);
- +
- + for (i = 0; i < FRAME_NUM; i++)
- + cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED;
- +
- + cam->enc_counter = 0;
- + INIT_LIST_HEAD(&cam->ready_q);
- + INIT_LIST_HEAD(&cam->working_q);
- + INIT_LIST_HEAD(&cam->done_q);
- +
- + return;
- +}
- +
- +/*!
- + * Return the buffer status
- + *
- + * @param cam Structure cam_data *
- + * @param buf Structure v4l2_buffer *
- + *
- + * @return status 0 success, EINVAL failed.
- + */
- +static int csi_v4l2_buffer_status(cam_data *cam, struct v4l2_buffer *buf)
- +{
- + pr_debug("In MVC: %s\n", __func__);
- +
- + if (buf->index < 0 || buf->index >= FRAME_NUM) {
- + pr_err("ERROR: v4l2 capture: %s buffers "
- + "not allocated\n", __func__);
- + return -EINVAL;
- + }
- +
- + memcpy(buf, &(cam->frame[buf->index].buffer), sizeof(*buf));
- +
- + return 0;
- +}
- +
- +static int csi_v4l2_release_bufs(cam_data *cam)
- +{
- + pr_debug("In MVC:csi_v4l2_release_bufs\n");
- + return 0;
- +}
- +
- +static int csi_v4l2_prepare_bufs(cam_data *cam, struct v4l2_buffer *buf)
- +{
- + pr_debug("In MVC:csi_v4l2_prepare_bufs\n");
- +
- + if (buf->index < 0 || buf->index >= FRAME_NUM || buf->length <
- + cam->v2f.fmt.pix.sizeimage) {
- + pr_err("ERROR: v4l2 capture: csi_v4l2_prepare_bufs buffers "
- + "not allocated,index=%d, length=%d\n", buf->index,
- + buf->length);
- + return -EINVAL;
- + }
- +
- + cam->frame[buf->index].buffer.index = buf->index;
- + cam->frame[buf->index].buffer.flags = V4L2_BUF_FLAG_MAPPED;
- + cam->frame[buf->index].buffer.length = buf->length;
- + cam->frame[buf->index].buffer.m.offset = cam->frame[buf->index].paddress
- + = buf->m.offset;
- + cam->frame[buf->index].buffer.type = buf->type;
- + cam->frame[buf->index].buffer.memory = V4L2_MEMORY_USERPTR;
- + cam->frame[buf->index].index = buf->index;
- +
- + return 0;
- +}
- +
- +/*!
- + * Indicates whether the palette is supported.
- + *
- + * @param palette V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_UYVY or V4L2_PIX_FMT_YUV420
- + *
- + * @return 0 if failed
- + */
- +static inline int valid_mode(u32 palette)
- +{
- + return (palette == V4L2_PIX_FMT_RGB565) ||
- + (palette == V4L2_PIX_FMT_YUYV) ||
- + (palette == V4L2_PIX_FMT_UYVY) || (palette == V4L2_PIX_FMT_YUV420);
- +}
- +
- +/*!
- + * Start stream I/O
- + *
- + * @param cam structure cam_data *
- + *
- + * @return status 0 Success
- + */
- +static int csi_streamon(cam_data *cam)
- +{
- + struct mxc_v4l_frame *frame;
- + unsigned long flags;
- + unsigned long val;
- + int timeout, timeout2;
- +
- + pr_debug("In MVC: %s\n", __func__);
- +
- + if (NULL == cam) {
- + pr_err("ERROR: v4l2 capture: %s cam parameter is NULL\n",
- + __func__);
- + return -1;
- + }
- + cam->dummy_frame.vaddress = dma_alloc_coherent(0,
- + PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
- + &cam->dummy_frame.paddress,
- + GFP_DMA | GFP_KERNEL);
- + if (cam->dummy_frame.vaddress == 0) {
- + pr_err("ERROR: v4l2 capture: Allocate dummy frame "
- + "failed.\n");
- + return -ENOBUFS;
- + }
- + cam->dummy_frame.buffer.type = V4L2_BUF_TYPE_PRIVATE;
- + cam->dummy_frame.buffer.length = cam->v2f.fmt.pix.sizeimage;
- + cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress;
- +
- + spin_lock_irqsave(&cam->queue_int_lock, flags);
- + /* move the frame from readyq to workingq */
- + if (list_empty(&cam->ready_q)) {
- + pr_err("ERROR: v4l2 capture: %s: "
- + "ready_q queue empty\n", __func__);
- + spin_unlock_irqrestore(&cam->queue_int_lock, flags);
- + return -1;
- + }
- + frame = list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue);
- + list_del(cam->ready_q.next);
- + list_add_tail(&frame->queue, &cam->working_q);
- + __raw_writel(frame->paddress, CSI_CSIDMASA_FB1);
- + frame->csi_buf_num = 1;
- +
- + if (list_empty(&cam->ready_q)) {
- + pr_err("ERROR: v4l2 capture: %s: "
- + "ready_q queue empty\n", __func__);
- + spin_unlock_irqrestore(&cam->queue_int_lock, flags);
- + return -1;
- + }
- + frame = list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue);
- + list_del(cam->ready_q.next);
- + list_add_tail(&frame->queue, &cam->working_q);
- + __raw_writel(frame->paddress, CSI_CSIDMASA_FB2);
- + frame->csi_buf_num = 2;
- + spin_unlock_irqrestore(&cam->queue_int_lock, flags);
- +
- + cam->capture_pid = current->pid;
- + cam->capture_on = true;
- + csi_cap_image(cam);
- +
- + local_irq_save(flags);
- + for (timeout = 1000000; timeout > 0; timeout--) {
- + if (__raw_readl(CSI_CSISR) & BIT_SOF_INT) {
- + val = __raw_readl(CSI_CSICR3);
- + __raw_writel(val | BIT_DMA_REFLASH_RFF, CSI_CSICR3);
- + for (timeout2 = 1000000; timeout2 > 0; timeout2--) {
- + if (__raw_readl(CSI_CSICR3) &
- + BIT_DMA_REFLASH_RFF)
- + cpu_relax();
- + else
- + break;
- + }
- + if (timeout2 <= 0) {
- + pr_err("timeout when wait for reflash done.\n");
- + local_irq_restore(flags);
- + return -ETIME;
- + }
- +
- + csi_dmareq_rff_enable();
- + csi_enable_int(1);
- + break;
- + } else
- + cpu_relax();
- + }
- + if (timeout <= 0) {
- + pr_err("timeout when wait for SOF\n");
- + local_irq_restore(flags);
- + return -ETIME;
- + }
- + local_irq_restore(flags);
- +
- + return 0;
- +}
- +
- +/*!
- + * Stop stream I/O
- + *
- + * @param cam structure cam_data *
- + *
- + * @return status 0 Success
- + */
- +static int csi_streamoff(cam_data *cam)
- +{
- + pr_debug("In MVC: %s\n", __func__);
- +
- + if (cam->capture_on == false)
- + return 0;
- +
- + csi_dmareq_rff_disable();
- + csi_disable_int();
- + cam->capture_on = false;
- +
- + /* set CSI_CSIDMASA_FB1 and CSI_CSIDMASA_FB2 to default value */
- + __raw_writel(0, CSI_CSIDMASA_FB1);
- + __raw_writel(0, CSI_CSIDMASA_FB2);
- +
- + csi_free_frames(cam);
- + csi_free_frame_buf(cam);
- +
- + return 0;
- +}
- +
- +/*!
- + * start the viewfinder job
- + *
- + * @param cam structure cam_data *
- + *
- + * @return status 0 Success
- + */
- +static int start_preview(cam_data *cam)
- +{
- + unsigned long fb_addr = (unsigned long)cam->v4l2_fb.base;
- +
- + __raw_writel(fb_addr, CSI_CSIDMASA_FB1);
- + __raw_writel(fb_addr, CSI_CSIDMASA_FB2);
- + __raw_writel(__raw_readl(CSI_CSICR3) | BIT_DMA_REFLASH_RFF, CSI_CSICR3);
- +
- + csi_enable_int(0);
- +
- + return 0;
- +}
- +
- +/*!
- + * shut down the viewfinder job
- + *
- + * @param cam structure cam_data *
- + *
- + * @return status 0 Success
- + */
- +static int stop_preview(cam_data *cam)
- +{
- + csi_disable_int();
- +
- + /* set CSI_CSIDMASA_FB1 and CSI_CSIDMASA_FB2 to default value */
- + __raw_writel(0, CSI_CSIDMASA_FB1);
- + __raw_writel(0, CSI_CSIDMASA_FB2);
- + __raw_writel(__raw_readl(CSI_CSICR3) | BIT_DMA_REFLASH_RFF, CSI_CSICR3);
- +
- + return 0;
- +}
- +
- +/***************************************************************************
- + * VIDIOC Functions.
- + **************************************************************************/
- +
- +/*!
- + *
- + * @param cam structure cam_data *
- + *
- + * @param f structure v4l2_format *
- + *
- + * @return status 0 success, EINVAL failed
- + */
- +static int csi_v4l2_g_fmt(cam_data *cam, struct v4l2_format *f)
- +{
- + int retval = 0;
- +
- + switch (f->type) {
- + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- + pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
- + f->fmt.pix = cam->v2f.fmt.pix;
- + break;
- + case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- + pr_debug(" type is V4L2_BUF_TYPE_VIDEO_OVERLAY\n");
- + f->fmt.win = cam->win;
- + break;
- + default:
- + pr_debug(" type is invalid\n");
- + retval = -EINVAL;
- + }
- +
- + pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
- + __func__, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
- +
- + return retval;
- +}
- +
- +/*!
- + * V4L2 - csi_v4l2_s_fmt function
- + *
- + * @param cam structure cam_data *
- + *
- + * @param f structure v4l2_format *
- + *
- + * @return status 0 success, EINVAL failed
- + */
- +static int csi_v4l2_s_fmt(cam_data *cam, struct v4l2_format *f)
- +{
- + int retval = 0;
- + int size = 0;
- + int bytesperline = 0;
- + int *width, *height;
- +
- + pr_debug("In MVC: %s\n", __func__);
- +
- + switch (f->type) {
- + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- + pr_debug(" type=V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
- + if (!valid_mode(f->fmt.pix.pixelformat)) {
- + pr_err("ERROR: v4l2 capture: %s: format "
- + "not supported\n", __func__);
- + return -EINVAL;
- + }
- +
- + /* Handle case where size requested is larger than cuurent
- + * camera setting. */
- + if ((f->fmt.pix.width > cam->crop_bounds.width)
- + || (f->fmt.pix.height > cam->crop_bounds.height)) {
- + /* Need the logic here, calling vidioc_s_param if
- + * camera can change. */
- + pr_debug("csi_v4l2_s_fmt size changed\n");
- + }
- + if (cam->rotation % 180) {
- + height = &f->fmt.pix.width;
- + width = &f->fmt.pix.height;
- + } else {
- + width = &f->fmt.pix.width;
- + height = &f->fmt.pix.height;
- + }
- +
- + if ((cam->crop_bounds.width / *width > 8) ||
- + ((cam->crop_bounds.width / *width == 8) &&
- + (cam->crop_bounds.width % *width))) {
- + *width = cam->crop_bounds.width / 8;
- + if (*width % 8)
- + *width += 8 - *width % 8;
- + pr_err("ERROR: v4l2 capture: width exceeds limit "
- + "resize to %d.\n", *width);
- + }
- +
- + if ((cam->crop_bounds.height / *height > 8) ||
- + ((cam->crop_bounds.height / *height == 8) &&
- + (cam->crop_bounds.height % *height))) {
- + *height = cam->crop_bounds.height / 8;
- + if (*height % 8)
- + *height += 8 - *height % 8;
- + pr_err("ERROR: v4l2 capture: height exceeds limit "
- + "resize to %d.\n", *height);
- + }
- +
- + switch (f->fmt.pix.pixelformat) {
- + case V4L2_PIX_FMT_RGB565:
- + size = f->fmt.pix.width * f->fmt.pix.height * 2;
- + csi_init_format(V4L2_PIX_FMT_UYVY);
- + csi_set_16bit_imagpara(f->fmt.pix.width,
- + f->fmt.pix.height);
- + bytesperline = f->fmt.pix.width * 2;
- + break;
- + case V4L2_PIX_FMT_UYVY:
- + size = f->fmt.pix.width * f->fmt.pix.height * 2;
- + csi_init_format(f->fmt.pix.pixelformat);
- + csi_set_16bit_imagpara(f->fmt.pix.width,
- + f->fmt.pix.height);
- + bytesperline = f->fmt.pix.width * 2;
- + break;
- + case V4L2_PIX_FMT_YUYV:
- + size = f->fmt.pix.width * f->fmt.pix.height * 2;
- + csi_init_format(f->fmt.pix.pixelformat);
- + csi_set_16bit_imagpara(f->fmt.pix.width,
- + f->fmt.pix.height);
- + bytesperline = f->fmt.pix.width * 2;
- + break;
- + case V4L2_PIX_FMT_YUV420:
- + size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2;
- + csi_set_12bit_imagpara(f->fmt.pix.width,
- + f->fmt.pix.height);
- + bytesperline = f->fmt.pix.width;
- + break;
- + case V4L2_PIX_FMT_YUV422P:
- + case V4L2_PIX_FMT_RGB24:
- + case V4L2_PIX_FMT_BGR24:
- + case V4L2_PIX_FMT_BGR32:
- + case V4L2_PIX_FMT_RGB32:
- + case V4L2_PIX_FMT_NV12:
- + default:
- + pr_debug(" case not supported\n");
- + break;
- + }
- +
- + if (f->fmt.pix.bytesperline < bytesperline)
- + f->fmt.pix.bytesperline = bytesperline;
- + else
- + bytesperline = f->fmt.pix.bytesperline;
- +
- + if (f->fmt.pix.sizeimage < size)
- + f->fmt.pix.sizeimage = size;
- + else
- + size = f->fmt.pix.sizeimage;
- +
- + cam->v2f.fmt.pix = f->fmt.pix;
- +
- + if (cam->v2f.fmt.pix.priv != 0) {
- + if (copy_from_user(&cam->offset,
- + (void *)cam->v2f.fmt.pix.priv,
- + sizeof(cam->offset))) {
- + retval = -EFAULT;
- + break;
- + }
- + }
- + break;
- + case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- + pr_debug(" type=V4L2_BUF_TYPE_VIDEO_OVERLAY\n");
- + cam->win = f->fmt.win;
- + win_current = f->fmt.win;
- + size = win_current.w.width * win_current.w.height * 2;
- + if (cam->v2f.fmt.pix.sizeimage < size)
- + cam->v2f.fmt.pix.sizeimage = size;
- +
- + break;
- + default:
- + retval = -EINVAL;
- + }
- +
- + pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
- + __func__, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
- +
- + return retval;
- +}
- +
- +/*!
- + * V4L2 - csi_v4l2_s_param function
- + * Allows setting of capturemode and frame rate.
- + *
- + * @param cam structure cam_data *
- + * @param parm structure v4l2_streamparm *
- + *
- + * @return status 0 success, EINVAL failed
- + */
- +static int csi_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm)
- +{
- + struct v4l2_ifparm ifparm;
- + struct v4l2_format cam_fmt;
- + struct v4l2_streamparm currentparm;
- + int err = 0;
- +
- + pr_debug("In %s\n", __func__);
- +
- + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- + pr_err(KERN_ERR "%s invalid type\n", __func__);
- + return -EINVAL;
- + }
- +
- + /* Stop the viewfinder */
- + if (cam->overlay_on == true)
- + stop_preview(cam);
- +
- + currentparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- +
- + /* First check that this device can support the changes requested. */
- + err = vidioc_int_g_parm(cam->sensor, ¤tparm);
- + if (err) {
- + pr_err("%s: vidioc_int_g_parm returned an error %d\n",
- + __func__, err);
- + goto exit;
- + }
- +
- + pr_debug(" Current capabilities are %x\n",
- + currentparm.parm.capture.capability);
- + pr_debug(" Current capturemode is %d change to %d\n",
- + currentparm.parm.capture.capturemode,
- + parm->parm.capture.capturemode);
- + pr_debug(" Current framerate is %d change to %d\n",
- + currentparm.parm.capture.timeperframe.denominator,
- + parm->parm.capture.timeperframe.denominator);
- +
- + err = vidioc_int_s_parm(cam->sensor, parm);
- + if (err) {
- + pr_err("%s: vidioc_int_s_parm returned an error %d\n",
- + __func__, err);
- + goto exit;
- + }
- +
- + vidioc_int_g_ifparm(cam->sensor, &ifparm);
- + cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- + vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt);
- + pr_debug(" g_fmt_cap returns widthxheight of input as %d x %d\n",
- + cam_fmt.fmt.pix.width, cam_fmt.fmt.pix.height);
- +
- + cam->crop_bounds.top = cam->crop_bounds.left = 0;
- + cam->crop_bounds.width = cam_fmt.fmt.pix.width;
- + cam->crop_bounds.height = cam_fmt.fmt.pix.height;
- + cam->crop_current.width = cam->crop_bounds.width;
- + cam->crop_current.height = cam->crop_bounds.height;
- +
- +exit:
- + return err;
- +}
- +
- +static int pxp_set_cstate(cam_data *cam, struct v4l2_control *vc)
- +{
- + struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data;
- +
- + if (vc->id == V4L2_CID_HFLIP) {
- + proc_data->hflip = vc->value;
- + } else if (vc->id == V4L2_CID_VFLIP) {
- + proc_data->vflip = vc->value;
- + } else if (vc->id == V4L2_CID_PRIVATE_BASE) {
- + if (vc->value % 90)
- + return -ERANGE;
- + proc_data->rotate = vc->value;
- + cam->rotation = vc->value;
- + }
- +
- + return 0;
- +}
- +
- +static int pxp_get_cstate(cam_data *cam, struct v4l2_control *vc)
- +{
- + struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data;
- +
- + if (vc->id == V4L2_CID_HFLIP)
- + vc->value = proc_data->hflip;
- + else if (vc->id == V4L2_CID_VFLIP)
- + vc->value = proc_data->vflip;
- + else if (vc->id == V4L2_CID_PRIVATE_BASE)
- + vc->value = proc_data->rotate;
- +
- + return 0;
- +}
- +
- +
- +/*!
- + * Dequeue one V4L capture buffer
- + *
- + * @param cam structure cam_data *
- + * @param buf structure v4l2_buffer *
- + *
- + * @return status 0 success, EINVAL invalid frame number
- + * ETIME timeout, ERESTARTSYS interrupted by user
- + */
- +static int csi_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf)
- +{
- + int retval = 0;
- + struct mxc_v4l_frame *frame;
- + unsigned long lock_flags;
- +
- + if (!wait_event_interruptible_timeout(cam->enc_queue,
- + cam->enc_counter != 0, 10 * HZ)) {
- + pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue timeout "
- + "enc_counter %x\n", cam->enc_counter);
- + return -ETIME;
- + } else if (signal_pending(current)) {
- + pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue() "
- + "interrupt received\n");
- + return -ERESTARTSYS;
- + }
- +
- + if (down_interruptible(&cam->busy_lock))
- + return -EBUSY;
- +
- + spin_lock_irqsave(&cam->dqueue_int_lock, lock_flags);
- +
- + if (list_empty(&cam->done_q)) {
- + spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags);
- + up(&cam->busy_lock);
- + return -EINVAL;
- + }
- +
- + cam->enc_counter--;
- +
- + frame = list_entry(cam->done_q.next, struct mxc_v4l_frame, queue);
- + list_del(cam->done_q.next);
- +
- + if (frame->buffer.flags & V4L2_BUF_FLAG_DONE) {
- + frame->buffer.flags &= ~V4L2_BUF_FLAG_DONE;
- + } else if (frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) {
- + pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: "
- + "Buffer not filled.\n");
- + frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED;
- + retval = -EINVAL;
- + } else if ((frame->buffer.flags & 0x7) == V4L2_BUF_FLAG_MAPPED) {
- + pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: "
- + "Buffer not queued.\n");
- + retval = -EINVAL;
- + }
- +
- + spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags);
- +
- + buf->bytesused = cam->v2f.fmt.pix.sizeimage;
- + buf->index = frame->index;
- + buf->flags = frame->buffer.flags;
- + buf->m = cam->frame[frame->index].buffer.m;
- +
- + /*
- + * Note:
- + * If want to do preview on LCD, use PxP CSC to convert from UYVY
- + * to RGB565; but for encoding, usually we don't use RGB format.
- + */
- + if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) {
- + sg_dma_address(&cam->sg[0]) = buf->m.offset;
- + sg_dma_address(&cam->sg[1]) =
- + cam->frame[req_buf_number].paddress;
- + retval = pxp_process_update(cam);
- + if (retval) {
- + pr_err("Unable to submit PxP update task.\n");
- + return retval;
- + }
- + pxp_complete_update(cam);
- + if (cam->frame[buf->index].vaddress)
- + memcpy(cam->frame[buf->index].vaddress,
- + cam->frame[req_buf_number].vaddress,
- + cam->v2f.fmt.pix.sizeimage);
- + }
- + up(&cam->busy_lock);
- +
- + return retval;
- +}
- +
- +/*!
- + * V4L interface - open function
- + *
- + * @param file structure file *
- + *
- + * @return status 0 success, ENODEV invalid device instance,
- + * ENODEV timeout, ERESTARTSYS interrupted by user
- + */
- +static int csi_v4l_open(struct file *file)
- +{
- + struct v4l2_ifparm ifparm;
- + struct v4l2_format cam_fmt;
- + struct video_device *dev = video_devdata(file);
- + cam_data *cam = video_get_drvdata(dev);
- + struct sensor_data *sensor;
- + int err = 0;
- +
- + pr_debug(" device name is %s\n", dev->name);
- +
- + if (!cam) {
- + pr_err("%s: Internal error, cam_data not found!\n", __func__);
- + return -EBADF;
- + }
- +
- + if (!cam->sensor) {
- + pr_err("%s: Internal error, camera is not found!\n", __func__);
- + return -EBADF;
- + }
- +
- + sensor = cam->sensor->priv;
- + if (!sensor) {
- + pr_err("%s: Internal error, sensor_data is not found!\n", __func__);
- + return -EBADF;
- + }
- +
- + down(&cam->busy_lock);
- + err = 0;
- + if (signal_pending(current))
- + goto oops;
- +
- + if (cam->open_count++ == 0) {
- + wait_event_interruptible(cam->power_queue,
- + cam->low_power == false);
- +
- + cam->enc_counter = 0;
- + INIT_LIST_HEAD(&cam->ready_q);
- + INIT_LIST_HEAD(&cam->working_q);
- + INIT_LIST_HEAD(&cam->done_q);
- +
- + vidioc_int_g_ifparm(cam->sensor, &ifparm);
- +
- + cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- + clk_prepare_enable(sensor->sensor_clk);
- + vidioc_int_s_power(cam->sensor, 1);
- + vidioc_int_init(cam->sensor);
- + vidioc_int_dev_init(cam->sensor);
- + }
- +
- + file->private_data = dev;
- +
- +oops:
- + up(&cam->busy_lock);
- + return err;
- +}
- +
- +/*!
- + * V4L interface - close function
- + *
- + * @param file struct file *
- + *
- + * @return 0 success
- + */
- +static int csi_v4l_close(struct file *file)
- +{
- + struct video_device *dev = video_devdata(file);
- + int err = 0;
- + cam_data *cam = video_get_drvdata(dev);
- + struct sensor_data *sensor;
- +
- + pr_debug("In MVC:%s\n", __func__);
- +
- + if (!cam) {
- + pr_err("%s: Internal error, cam_data not found!\n", __func__);
- + return -EBADF;
- + }
- +
- + if (!cam->sensor) {
- + pr_err("%s: Internal error, camera is not found!\n", __func__);
- + return -EBADF;
- + }
- +
- + sensor = cam->sensor->priv;
- + if (!sensor) {
- + pr_err("%s: Internal error, sensor_data is not found!\n", __func__);
- + return -EBADF;
- + }
- +
- + /* for the case somebody hit the ctrl C */
- + if (cam->overlay_pid == current->pid) {
- + err = stop_preview(cam);
- + cam->overlay_on = false;
- + }
- +
- + if (--cam->open_count == 0) {
- + wait_event_interruptible(cam->power_queue,
- + cam->low_power == false);
- + file->private_data = NULL;
- + vidioc_int_s_power(cam->sensor, 0);
- + clk_disable_unprepare(sensor->sensor_clk);
- + }
- +
- + return err;
- +}
- +
- +/*
- + * V4L interface - read function
- + *
- + * @param file struct file *
- + * @param read buf char *
- + * @param count size_t
- + * @param ppos structure loff_t *
- + *
- + * @return bytes read
- + */
- +static ssize_t csi_v4l_read(struct file *file, char *buf, size_t count,
- + loff_t *ppos)
- +{
- + int err = 0;
- + struct video_device *dev = video_devdata(file);
- + cam_data *cam = video_get_drvdata(dev);
- +
- + if (down_interruptible(&cam->busy_lock))
- + return -EINTR;
- +
- + /* Stop the viewfinder */
- + if (cam->overlay_on == true)
- + stop_preview(cam);
- +
- + if (cam->still_buf_vaddr == NULL) {
- + cam->still_buf_vaddr = dma_alloc_coherent(0,
- + PAGE_ALIGN
- + (cam->v2f.fmt.
- + pix.sizeimage),
- + &cam->
- + still_buf[0],
- + GFP_DMA | GFP_KERNEL);
- + if (cam->still_buf_vaddr == NULL) {
- + pr_err("alloc dma memory failed\n");
- + return -ENOMEM;
- + }
- + cam->still_counter = 0;
- + __raw_writel(cam->still_buf[0], CSI_CSIDMASA_FB2);
- + __raw_writel(cam->still_buf[0], CSI_CSIDMASA_FB1);
- + __raw_writel(__raw_readl(CSI_CSICR3) | BIT_DMA_REFLASH_RFF,
- + CSI_CSICR3);
- + __raw_writel(__raw_readl(CSI_CSISR), CSI_CSISR);
- + __raw_writel(__raw_readl(CSI_CSICR3) | BIT_FRMCNT_RST,
- + CSI_CSICR3);
- + csi_enable_int(1);
- + }
- +
- + wait_event_interruptible(cam->still_queue, cam->still_counter);
- + csi_disable_int();
- + err = copy_to_user(buf, cam->still_buf_vaddr,
- + cam->v2f.fmt.pix.sizeimage);
- +
- + if (cam->still_buf_vaddr != NULL) {
- + dma_free_coherent(0, PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
- + cam->still_buf_vaddr, cam->still_buf[0]);
- + cam->still_buf[0] = 0;
- + cam->still_buf_vaddr = NULL;
- + }
- +
- + if (cam->overlay_on == true)
- + start_preview(cam);
- +
- + up(&cam->busy_lock);
- + if (err < 0)
- + return err;
- +
- + return cam->v2f.fmt.pix.sizeimage - err;
- +}
- +
- +/*!
- + * V4L interface - ioctl function
- + *
- + * @param file struct file*
- + *
- + * @param ioctlnr unsigned int
- + *
- + * @param arg void*
- + *
- + * @return 0 success, ENODEV for invalid device instance,
- + * -1 for other errors.
- + */
- +static long csi_v4l_do_ioctl(struct file *file,
- + unsigned int ioctlnr, void *arg)
- +{
- + struct video_device *dev = video_devdata(file);
- + cam_data *cam = video_get_drvdata(dev);
- + int retval = 0;
- + unsigned long lock_flags;
- +
- + pr_debug("In MVC: %s, %x\n", __func__, ioctlnr);
- + wait_event_interruptible(cam->power_queue, cam->low_power == false);
- + /* make this _really_ smp-safe */
- + if (ioctlnr != VIDIOC_DQBUF)
- + if (down_interruptible(&cam->busy_lock))
- + return -EBUSY;
- +
- + switch (ioctlnr) {
- + /*!
- + * V4l2 VIDIOC_G_FMT ioctl
- + */
- + case VIDIOC_G_FMT:{
- + struct v4l2_format *gf = arg;
- + pr_debug(" case VIDIOC_G_FMT\n");
- + retval = csi_v4l2_g_fmt(cam, gf);
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_S_FMT ioctl
- + */
- + case VIDIOC_S_FMT:{
- + struct v4l2_format *sf = arg;
- + pr_debug(" case VIDIOC_S_FMT\n");
- + retval = csi_v4l2_s_fmt(cam, sf);
- + vidioc_int_s_fmt_cap(cam->sensor, sf);
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_OVERLAY ioctl
- + */
- + case VIDIOC_OVERLAY:{
- + int *on = arg;
- + pr_debug(" case VIDIOC_OVERLAY\n");
- + if (*on) {
- + cam->overlay_on = true;
- + cam->overlay_pid = current->pid;
- + start_preview(cam);
- + }
- + if (!*on) {
- + stop_preview(cam);
- + cam->overlay_on = false;
- + }
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_G_FBUF ioctl
- + */
- + case VIDIOC_G_FBUF:{
- + struct v4l2_framebuffer *fb = arg;
- + *fb = cam->v4l2_fb;
- + fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY;
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_S_FBUF ioctl
- + */
- + case VIDIOC_S_FBUF:{
- + struct v4l2_framebuffer *fb = arg;
- + cam->v4l2_fb = *fb;
- + break;
- + }
- +
- + case VIDIOC_G_PARM:{
- + struct v4l2_streamparm *parm = arg;
- + pr_debug(" case VIDIOC_G_PARM\n");
- + vidioc_int_g_parm(cam->sensor, parm);
- + break;
- + }
- +
- + case VIDIOC_S_PARM:{
- + struct v4l2_streamparm *parm = arg;
- + pr_debug(" case VIDIOC_S_PARM\n");
- + retval = csi_v4l2_s_param(cam, parm);
- + break;
- + }
- +
- + case VIDIOC_QUERYCAP:{
- + struct v4l2_capability *cap = arg;
- + pr_debug(" case VIDIOC_QUERYCAP\n");
- + strcpy(cap->driver, "csi_v4l2");
- + cap->version = KERNEL_VERSION(0, 1, 11);
- + cap->capabilities = V4L2_CAP_VIDEO_OVERLAY |
- + V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
- + V4L2_CAP_VIDEO_OUTPUT_OVERLAY | V4L2_CAP_READWRITE;
- + cap->card[0] = '\0';
- + cap->bus_info[0] = '\0';
- + break;
- + }
- +
- + case VIDIOC_CROPCAP:
- + {
- + struct v4l2_cropcap *cap = arg;
- +
- + if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
- + cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) {
- + retval = -EINVAL;
- + break;
- + }
- + cap->bounds = cam->crop_bounds;
- + cap->defrect = cam->crop_defrect;
- + break;
- + }
- + case VIDIOC_S_CROP:
- + {
- + struct v4l2_crop *crop = arg;
- + struct v4l2_rect *b = &cam->crop_bounds;
- +
- + if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- + retval = -EINVAL;
- + break;
- + }
- +
- + crop->c.top = (crop->c.top < b->top) ? b->top
- + : crop->c.top;
- + if (crop->c.top > b->top + b->height)
- + crop->c.top = b->top + b->height - 1;
- + if (crop->c.height > b->top + b->height - crop->c.top)
- + crop->c.height =
- + b->top + b->height - crop->c.top;
- +
- + crop->c.left = (crop->c.left < b->left) ? b->left
- + : crop->c.left;
- + if (crop->c.left > b->left + b->width)
- + crop->c.left = b->left + b->width - 1;
- + if (crop->c.width > b->left - crop->c.left + b->width)
- + crop->c.width =
- + b->left - crop->c.left + b->width;
- +
- + crop->c.width -= crop->c.width % 8;
- + crop->c.height -= crop->c.height % 8;
- +
- + crop_current.c = crop->c;
- +
- + break;
- + }
- + case VIDIOC_G_CROP:
- + {
- + struct v4l2_crop *crop = arg;
- +
- + if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- + retval = -EINVAL;
- + break;
- + }
- + crop->c = crop_current.c;
- +
- + break;
- +
- + }
- + case VIDIOC_REQBUFS: {
- + struct v4l2_requestbuffers *req = arg;
- + pr_debug(" case VIDIOC_REQBUFS\n");
- +
- + if (req->count > FRAME_NUM) {
- + pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: "
- + "not enough buffers\n");
- + req->count = FRAME_NUM;
- + }
- +
- + if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- + pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: "
- + "wrong buffer type\n");
- + retval = -EINVAL;
- + break;
- + }
- +
- + csi_streamoff(cam);
- + if (req->memory & V4L2_MEMORY_MMAP) {
- + csi_free_frame_buf(cam);
- + retval = csi_allocate_frame_buf(cam, req->count + 1);
- + req_buf_number = req->count;
- + }
- + break;
- + }
- +
- + case VIDIOC_QUERYBUF: {
- + struct v4l2_buffer *buf = arg;
- + int index = buf->index;
- + pr_debug(" case VIDIOC_QUERYBUF\n");
- +
- + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- + retval = -EINVAL;
- + break;
- + }
- +
- + if (buf->memory & V4L2_MEMORY_MMAP) {
- + memset(buf, 0, sizeof(buf));
- + buf->index = index;
- + }
- +
- + down(&cam->param_lock);
- + if (buf->memory & V4L2_MEMORY_USERPTR) {
- + csi_v4l2_release_bufs(cam);
- + retval = csi_v4l2_prepare_bufs(cam, buf);
- + }
- + if (buf->memory & V4L2_MEMORY_MMAP)
- + retval = csi_v4l2_buffer_status(cam, buf);
- + up(&cam->param_lock);
- + break;
- + }
- +
- + case VIDIOC_QBUF: {
- + struct v4l2_buffer *buf = arg;
- + int index = buf->index;
- + pr_debug(" case VIDIOC_QBUF\n");
- +
- + spin_lock_irqsave(&cam->queue_int_lock, lock_flags);
- + cam->frame[index].buffer.m.offset = buf->m.offset;
- + if ((cam->frame[index].buffer.flags & 0x7) ==
- + V4L2_BUF_FLAG_MAPPED) {
- + cam->frame[index].buffer.flags |= V4L2_BUF_FLAG_QUEUED;
- + list_add_tail(&cam->frame[index].queue, &cam->ready_q);
- + } else if (cam->frame[index].buffer.flags &
- + V4L2_BUF_FLAG_QUEUED) {
- + pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: "
- + "buffer already queued\n");
- + retval = -EINVAL;
- + } else if (cam->frame[index].buffer.
- + flags & V4L2_BUF_FLAG_DONE) {
- + pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: "
- + "overwrite done buffer.\n");
- + cam->frame[index].buffer.flags &=
- + ~V4L2_BUF_FLAG_DONE;
- + cam->frame[index].buffer.flags |=
- + V4L2_BUF_FLAG_QUEUED;
- + retval = -EINVAL;
- + }
- + buf->flags = cam->frame[index].buffer.flags;
- + spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags);
- +
- + break;
- + }
- +
- + case VIDIOC_DQBUF: {
- + struct v4l2_buffer *buf = arg;
- + pr_debug(" case VIDIOC_DQBUF\n");
- +
- + retval = csi_v4l_dqueue(cam, buf);
- +
- + break;
- + }
- +
- + case VIDIOC_STREAMON: {
- + pr_debug(" case VIDIOC_STREAMON\n");
- + retval = csi_streamon(cam);
- + break;
- + }
- +
- + case VIDIOC_STREAMOFF: {
- + pr_debug(" case VIDIOC_STREAMOFF\n");
- + retval = csi_streamoff(cam);
- + break;
- + }
- + case VIDIOC_ENUM_FMT: {
- + struct v4l2_fmtdesc *fmt = arg;
- + if (cam->sensor)
- + retval = vidioc_int_enum_fmt_cap(cam->sensor, fmt);
- + else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + retval = -ENODEV;
- + }
- + break;
- + }
- + case VIDIOC_ENUM_FRAMESIZES: {
- + struct v4l2_frmsizeenum *fsize = arg;
- + if (cam->sensor)
- + retval = vidioc_int_enum_framesizes(cam->sensor, fsize);
- + else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + retval = -ENODEV;
- + }
- + break;
- + }
- + case VIDIOC_ENUM_FRAMEINTERVALS: {
- + struct v4l2_frmivalenum *fival = arg;
- + if (cam->sensor)
- + retval = vidioc_int_enum_frameintervals(cam->sensor,
- + fival);
- + else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + retval = -ENODEV;
- + }
- + break;
- + }
- + case VIDIOC_DBG_G_CHIP_IDENT: {
- + struct v4l2_dbg_chip_ident *p = arg;
- + p->ident = V4L2_IDENT_NONE;
- + p->revision = 0;
- + if (cam->sensor)
- + retval = vidioc_int_g_chip_ident(cam->sensor, (int *)p);
- + else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + retval = -ENODEV;
- + }
- + break;
- + }
- +
- + case VIDIOC_S_CTRL:
- + {
- + struct v4l2_control *vc = arg;
- + int i;
- +
- + for (i = 0; i < ARRAY_SIZE(pxp_controls); i++)
- + if (vc->id == pxp_controls[i].id) {
- + if (vc->value < pxp_controls[i].minimum ||
- + vc->value > pxp_controls[i].maximum) {
- + retval = -ERANGE;
- + break;
- + }
- + retval = pxp_set_cstate(cam, vc);
- + break;
- + }
- +
- + if (i >= ARRAY_SIZE(pxp_controls))
- + retval = -EINVAL;
- + break;
- +
- + }
- + case VIDIOC_G_CTRL:
- + {
- + struct v4l2_control *vc = arg;
- + int i;
- +
- + for (i = 0; i < ARRAY_SIZE(pxp_controls); i++)
- + if (vc->id == pxp_controls[i].id) {
- + retval = pxp_get_cstate(cam, vc);
- + break;
- + }
- +
- + if (i >= ARRAY_SIZE(pxp_controls))
- + retval = -EINVAL;
- + break;
- + }
- + case VIDIOC_QUERYCTRL:
- + {
- + struct v4l2_queryctrl *qc = arg;
- + int i;
- +
- + for (i = 0; i < ARRAY_SIZE(pxp_controls); i++)
- + if (qc->id && qc->id == pxp_controls[i].id) {
- + memcpy(qc, &(pxp_controls[i]), sizeof(*qc));
- + break;
- + }
- +
- + if (i >= ARRAY_SIZE(pxp_controls))
- + retval = -EINVAL;
- + break;
- + }
- + case VIDIOC_G_STD:
- + case VIDIOC_G_OUTPUT:
- + case VIDIOC_S_OUTPUT:
- + case VIDIOC_ENUMSTD:
- + case VIDIOC_S_STD:
- + case VIDIOC_TRY_FMT:
- + case VIDIOC_ENUMINPUT:
- + case VIDIOC_G_INPUT:
- + case VIDIOC_S_INPUT:
- + case VIDIOC_G_TUNER:
- + case VIDIOC_S_TUNER:
- + case VIDIOC_G_FREQUENCY:
- + case VIDIOC_S_FREQUENCY:
- + case VIDIOC_ENUMOUTPUT:
- + default:
- + pr_debug(" case not supported\n");
- + retval = -EINVAL;
- + break;
- + }
- +
- + if (ioctlnr != VIDIOC_DQBUF)
- + up(&cam->busy_lock);
- + return retval;
- +}
- +
- +/*
- + * V4L interface - ioctl function
- + *
- + * @return None
- + */
- +static long csi_v4l_ioctl(struct file *file,
- + unsigned int cmd, unsigned long arg)
- +{
- + return video_usercopy(file, cmd, arg, csi_v4l_do_ioctl);
- +}
- +
- +/*!
- + * V4L interface - mmap function
- + *
- + * @param file structure file *
- + *
- + * @param vma structure vm_area_struct *
- + *
- + * @return status 0 Success, EINTR busy lock error, ENOBUFS remap_page error
- + */
- +static int csi_mmap(struct file *file, struct vm_area_struct *vma)
- +{
- + struct video_device *dev = video_devdata(file);
- + unsigned long size;
- + int res = 0;
- + cam_data *cam = video_get_drvdata(dev);
- +
- + pr_debug("%s\n", __func__);
- + pr_debug("\npgoff=0x%lx, start=0x%lx, end=0x%lx\n",
- + vma->vm_pgoff, vma->vm_start, vma->vm_end);
- +
- + /* make this _really_ smp-safe */
- + if (down_interruptible(&cam->busy_lock))
- + return -EINTR;
- +
- + size = vma->vm_end - vma->vm_start;
- + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- +
- + if (remap_pfn_range(vma, vma->vm_start,
- + vma->vm_pgoff, size, vma->vm_page_prot)) {
- + pr_err("ERROR: v4l2 capture: %s : "
- + "remap_pfn_range failed\n", __func__);
- + res = -ENOBUFS;
- + goto csi_mmap_exit;
- + }
- +
- + vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */
- +
- +csi_mmap_exit:
- + up(&cam->busy_lock);
- + return res;
- +}
- +
- +/*!
- + * This structure defines the functions to be called in this driver.
- + */
- +static struct v4l2_file_operations csi_v4l_fops = {
- + .owner = THIS_MODULE,
- + .open = csi_v4l_open,
- + .release = csi_v4l_close,
- + .read = csi_v4l_read,
- + .ioctl = csi_v4l_ioctl,
- + .mmap = csi_mmap,
- +};
- +
- +static struct video_device csi_v4l_template = {
- + .name = "Mx25 Camera",
- + .fops = &csi_v4l_fops,
- + .release = video_device_release,
- +};
- +
- +/*!
- + * initialize cam_data structure
- + *
- + * @param cam structure cam_data *
- + *
- + * @return status 0 Success
- + */
- +static void init_camera_struct(cam_data *cam)
- +{
- + struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data;
- + pr_debug("In MVC: %s\n", __func__);
- +
- + proc_data->hflip = 0;
- + proc_data->vflip = 0;
- + proc_data->rotate = 0;
- + proc_data->bgcolor = 0;
- +
- + /* Default everything to 0 */
- + memset(cam, 0, sizeof(cam_data));
- +
- + sema_init(&cam->param_lock, 1);
- + sema_init(&cam->busy_lock, 1);
- +
- + cam->video_dev = video_device_alloc();
- + if (cam->video_dev == NULL)
- + return;
- +
- + *(cam->video_dev) = csi_v4l_template;
- +
- + video_set_drvdata(cam->video_dev, cam);
- + cam->video_dev->minor = -1;
- +
- + init_waitqueue_head(&cam->enc_queue);
- + init_waitqueue_head(&cam->still_queue);
- +
- + cam->streamparm.parm.capture.capturemode = 0;
- +
- + cam->standard.index = 0;
- + cam->standard.id = V4L2_STD_UNKNOWN;
- + cam->standard.frameperiod.denominator = 30;
- + cam->standard.frameperiod.numerator = 1;
- + cam->standard.framelines = 480;
- + cam->standard_autodetect = true;
- + cam->streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- + cam->streamparm.parm.capture.timeperframe = cam->standard.frameperiod;
- + cam->streamparm.parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
- + cam->overlay_on = false;
- + cam->capture_on = false;
- + cam->v4l2_fb.flags = V4L2_FBUF_FLAG_OVERLAY;
- +
- + cam->v2f.fmt.pix.sizeimage = 480 * 640 * 2;
- + cam->v2f.fmt.pix.bytesperline = 640 * 2;
- + cam->v2f.fmt.pix.width = 640;
- + cam->v2f.fmt.pix.height = 480;
- + cam->v2f.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
- + cam->win.w.width = 160;
- + cam->win.w.height = 160;
- + cam->win.w.left = 0;
- + cam->win.w.top = 0;
- + cam->still_counter = 0;
- + /* setup cropping */
- + cam->crop_bounds.left = 0;
- + cam->crop_bounds.width = 640;
- + cam->crop_bounds.top = 0;
- + cam->crop_bounds.height = 480;
- + cam->crop_current = cam->crop_defrect = cam->crop_bounds;
- +
- + cam->enc_callback = camera_callback;
- + csi_start_callback(cam);
- + init_waitqueue_head(&cam->power_queue);
- + spin_lock_init(&cam->queue_int_lock);
- + spin_lock_init(&cam->dqueue_int_lock);
- +}
- +
- +/*!
- + * camera_power function
- + * Turns Sensor power On/Off
- + *
- + * @param cam cam data struct
- + * @param cameraOn true to turn camera on, false to turn off power.
- + *
- + * @return status
- + */
- +static u8 camera_power(cam_data *cam, bool cameraOn)
- +{
- + pr_debug("In MVC: %s on=%d\n", __func__, cameraOn);
- +
- + if (cameraOn == true) {
- + vidioc_int_s_power(cam->sensor, 1);
- + } else {
- + vidioc_int_s_power(cam->sensor, 0);
- + }
- + return 0;
- +}
- +
- +static const struct of_device_id imx_csi_v4l2_dt_ids[] = {
- + { .compatible = "fsl,imx6sl-csi-v4l2", },
- + { /* sentinel */ }
- +};
- +MODULE_DEVICE_TABLE(of, imx_csi_v4l2_dt_ids);
- +
- +static int csi_v4l2_probe(struct platform_device *pdev)
- +{
- + struct scatterlist *sg;
- + u8 err = 0;
- +
- + /* Create g_cam and initialize it. */
- + g_cam = kmalloc(sizeof(cam_data), GFP_KERNEL);
- + if (g_cam == NULL) {
- + pr_err("ERROR: v4l2 capture: failed to register camera\n");
- + err = -ENOMEM;
- + goto out;
- + }
- + memset(&crop_current, 0, sizeof(crop_current));
- + memset(&win_current, 0, sizeof(win_current));
- + init_camera_struct(g_cam);
- + platform_set_drvdata(pdev, (void *)g_cam);
- +
- + /* Set up the v4l2 device and register it */
- + csi_v4l2_int_device.priv = g_cam;
- + /* This function contains a bug that won't let this be rmmod'd. */
- + v4l2_int_device_register(&csi_v4l2_int_device);
- +
- + /* register v4l video device */
- + if (video_register_device(g_cam->video_dev, VFL_TYPE_GRABBER, video_nr)
- + == -1) {
- + kfree(g_cam);
- + g_cam = NULL;
- + pr_err("ERROR: v4l2 capture: video_register_device failed\n");
- + err = -ENODEV;
- + goto out;
- + }
- + pr_debug(" Video device registered: %s #%d\n",
- + g_cam->video_dev->name, g_cam->video_dev->minor);
- +
- + g_cam->pxp_chan = NULL;
- + /* Initialize Scatter-gather list containing 2 buffer addresses. */
- + sg = g_cam->sg;
- + sg_init_table(sg, 2);
- +
- +out:
- + return err;
- +}
- +
- +static int csi_v4l2_remove(struct platform_device *pdev)
- +{
- + if (g_cam->open_count) {
- + pr_err("ERROR: v4l2 capture:camera open "
- + "-- setting ops to NULL\n");
- + } else {
- + pr_info("V4L2 freeing image input device\n");
- + v4l2_int_device_unregister(&csi_v4l2_int_device);
- + csi_stop_callback(g_cam);
- + video_unregister_device(g_cam->video_dev);
- + platform_set_drvdata(pdev, NULL);
- +
- + kfree(g_cam);
- + g_cam = NULL;
- + }
- +
- + return 0;
- +}
- +
- +/*!
- + * This function is called to put the sensor in a low power state.
- + * Refer to the document driver-model/driver.txt in the kernel source tree
- + * for more information.
- + *
- + * @param pdev the device structure used to give information on which I2C
- + * to suspend
- + * @param state the power state the device is entering
- + *
- + * @return The function returns 0 on success and -1 on failure.
- + */
- +static int csi_v4l2_suspend(struct platform_device *pdev, pm_message_t state)
- +{
- + cam_data *cam = platform_get_drvdata(pdev);
- +
- + pr_debug("In MVC: %s\n", __func__);
- +
- + if (cam == NULL)
- + return -1;
- +
- + cam->low_power = true;
- +
- + if (cam->overlay_on == true)
- + stop_preview(cam);
- +
- + if (cam->capture_on == true || cam->overlay_on == true)
- + camera_power(cam, false);
- +
- + return 0;
- +}
- +
- +/*!
- + * This function is called to bring the sensor back from a low power state.
- + * Refer to the document driver-model/driver.txt in the kernel source tree
- + * for more information.
- + *
- + * @param pdev the device structure
- + *
- + * @return The function returns 0 on success and -1 on failure
- + */
- +static int csi_v4l2_resume(struct platform_device *pdev)
- +{
- + cam_data *cam = platform_get_drvdata(pdev);
- +
- + pr_debug("In MVC: %s\n", __func__);
- +
- + if (cam == NULL)
- + return -1;
- +
- + cam->low_power = false;
- + wake_up_interruptible(&cam->power_queue);
- + if (cam->capture_on == true || cam->overlay_on == true)
- + camera_power(cam, true);
- +
- + if (cam->overlay_on == true)
- + start_preview(cam);
- +
- + return 0;
- +}
- +
- +/*!
- + * This structure contains pointers to the power management callback functions.
- + */
- +static struct platform_driver csi_v4l2_driver = {
- + .driver = {
- + .name = "csi_v4l2",
- + .of_match_table = of_match_ptr(imx_csi_v4l2_dt_ids),
- + },
- + .probe = csi_v4l2_probe,
- + .remove = csi_v4l2_remove,
- +#ifdef CONFIG_PM
- + .suspend = csi_v4l2_suspend,
- + .resume = csi_v4l2_resume,
- +#endif
- + .shutdown = NULL,
- +};
- +
- +/*!
- + * Initializes the camera driver.
- + */
- +static int csi_v4l2_master_attach(struct v4l2_int_device *slave)
- +{
- + cam_data *cam = slave->u.slave->master->priv;
- + struct v4l2_format cam_fmt;
- +
- + pr_debug("In MVC: %s\n", __func__);
- + pr_debug(" slave.name = %s\n", slave->name);
- + pr_debug(" master.name = %s\n", slave->u.slave->master->name);
- +
- + cam->sensor = slave;
- + if (slave == NULL) {
- + pr_err("ERROR: v4l2 capture: slave parameter not valid.\n");
- + return -1;
- + }
- +
- + cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- + vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt);
- +
- + /* Used to detect TV in (type 1) vs. camera (type 0) */
- + cam->device_type = cam_fmt.fmt.pix.priv;
- +
- + cam->crop_bounds.top = cam->crop_bounds.left = 0;
- + cam->crop_bounds.width = cam_fmt.fmt.pix.width;
- + cam->crop_bounds.height = cam_fmt.fmt.pix.height;
- +
- + /* This also is the max crop size for this device. */
- + cam->crop_defrect.top = cam->crop_defrect.left = 0;
- + cam->crop_defrect.width = cam_fmt.fmt.pix.width;
- + cam->crop_defrect.height = cam_fmt.fmt.pix.height;
- +
- + /* At this point, this is also the current image size. */
- + cam->crop_current.top = cam->crop_current.left = 0;
- + cam->crop_current.width = cam_fmt.fmt.pix.width;
- + cam->crop_current.height = cam_fmt.fmt.pix.height;
- +
- + pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
- + __func__, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
- +
- + return 0;
- +}
- +
- +/*!
- + * Disconnects the camera driver.
- + */
- +static void csi_v4l2_master_detach(struct v4l2_int_device *slave)
- +{
- + pr_debug("In MVC: %s\n", __func__);
- +
- + vidioc_int_dev_exit(slave);
- +}
- +
- +module_platform_driver(csi_v4l2_driver);
- +
- +module_param(video_nr, int, 0444);
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("V4L2 capture driver for Mx25 based cameras");
- +MODULE_LICENSE("GPL");
- +MODULE_SUPPORTED_DEVICE("video");
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/fsl_csi.c linux-3.14.35/drivers/media/platform/mxc/capture/fsl_csi.c
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/fsl_csi.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/fsl_csi.c 2015-03-08 14:27:37.585684501 -0500
- @@ -0,0 +1,302 @@
- +/*
- + * Copyright 2009-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file fsl_csi.c, this file is derived from mx27_csi.c
- + *
- + * @brief mx25 CMOS Sensor interface functions
- + *
- + * @ingroup CSI
- + */
- +#include <linux/types.h>
- +#include <linux/init.h>
- +#include <linux/platform_device.h>
- +#include <linux/device.h>
- +#include <linux/err.h>
- +#include <linux/interrupt.h>
- +#include <linux/spinlock.h>
- +#include <linux/module.h>
- +#include <linux/clk.h>
- +#include <linux/of.h>
- +#include <linux/sched.h>
- +
- +#include "mxc_v4l2_capture.h"
- +#include "fsl_csi.h"
- +
- +void __iomem *csi_regbase;
- +EXPORT_SYMBOL(csi_regbase);
- +static int irq_nr;
- +static csi_irq_callback_t g_callback;
- +static void *g_callback_data;
- +
- +static irqreturn_t csi_irq_handler(int irq, void *data)
- +{
- + cam_data *cam = (cam_data *) data;
- + unsigned long status = __raw_readl(CSI_CSISR);
- +
- + __raw_writel(status, CSI_CSISR);
- +
- + if (status & BIT_HRESP_ERR_INT)
- + pr_warning("Hresponse error is detected.\n");
- +
- + if (status & BIT_DMA_TSF_DONE_FB1) {
- + if (cam->capture_on) {
- + spin_lock(&cam->queue_int_lock);
- + cam->ping_pong_csi = 1;
- + spin_unlock(&cam->queue_int_lock);
- + cam->enc_callback(0, cam);
- + } else {
- + cam->still_counter++;
- + wake_up_interruptible(&cam->still_queue);
- + }
- + }
- +
- + if (status & BIT_DMA_TSF_DONE_FB2) {
- + if (cam->capture_on) {
- + spin_lock(&cam->queue_int_lock);
- + cam->ping_pong_csi = 2;
- + spin_unlock(&cam->queue_int_lock);
- + cam->enc_callback(0, cam);
- + } else {
- + cam->still_counter++;
- + wake_up_interruptible(&cam->still_queue);
- + }
- + }
- +
- + if (g_callback)
- + g_callback(g_callback_data, status);
- +
- + pr_debug("CSI status = 0x%08lX\n", status);
- +
- + return IRQ_HANDLED;
- +}
- +
- +static void csihw_reset_frame_count(void)
- +{
- + __raw_writel(__raw_readl(CSI_CSICR3) | BIT_FRMCNT_RST, CSI_CSICR3);
- +}
- +
- +static void csihw_reset(void)
- +{
- + csihw_reset_frame_count();
- + __raw_writel(CSICR1_RESET_VAL, CSI_CSICR1);
- + __raw_writel(CSICR2_RESET_VAL, CSI_CSICR2);
- + __raw_writel(CSICR3_RESET_VAL, CSI_CSICR3);
- +}
- +
- +/*!
- + * csi_init_interface
- + * Init csi interface
- + */
- +void csi_init_interface(void)
- +{
- + unsigned int val = 0;
- + unsigned int imag_para;
- +
- + val |= BIT_SOF_POL;
- + val |= BIT_REDGE;
- + val |= BIT_GCLK_MODE;
- + val |= BIT_HSYNC_POL;
- + val |= BIT_PACK_DIR;
- + val |= BIT_FCC;
- + val |= BIT_SWAP16_EN;
- + val |= 1 << SHIFT_MCLKDIV;
- + val |= BIT_MCLKEN;
- + __raw_writel(val, CSI_CSICR1);
- +
- + imag_para = (640 << 16) | 960;
- + __raw_writel(imag_para, CSI_CSIIMAG_PARA);
- +
- + val = 0x1010;
- + val |= BIT_DMA_REFLASH_RFF;
- + __raw_writel(val, CSI_CSICR3);
- +}
- +EXPORT_SYMBOL(csi_init_interface);
- +
- +void csi_init_format(int fmt)
- +{
- + unsigned int val;
- +
- + val = __raw_readl(CSI_CSICR1);
- + if (fmt == V4L2_PIX_FMT_YUYV) {
- + val &= ~BIT_PACK_DIR;
- + val &= ~BIT_SWAP16_EN;
- + } else if (fmt == V4L2_PIX_FMT_UYVY) {
- + val |= BIT_PACK_DIR;
- + val |= BIT_SWAP16_EN;
- + } else
- + pr_warning("unsupported format, old format remains.\n");
- +
- + __raw_writel(val, CSI_CSICR1);
- +}
- +EXPORT_SYMBOL(csi_init_format);
- +
- +/*!
- + * csi_read_mclk_flag
- + *
- + * @return gcsi_mclk_source
- + */
- +int csi_read_mclk_flag(void)
- +{
- + return 0;
- +}
- +EXPORT_SYMBOL(csi_read_mclk_flag);
- +
- +void csi_start_callback(void *data)
- +{
- + cam_data *cam = (cam_data *) data;
- +
- + if (request_irq(irq_nr, csi_irq_handler, 0, "csi", cam) < 0)
- + pr_debug("CSI error: irq request fail\n");
- +
- +}
- +EXPORT_SYMBOL(csi_start_callback);
- +
- +void csi_stop_callback(void *data)
- +{
- + cam_data *cam = (cam_data *) data;
- +
- + free_irq(irq_nr, cam);
- +}
- +EXPORT_SYMBOL(csi_stop_callback);
- +
- +void csi_enable_int(int arg)
- +{
- + unsigned long cr1 = __raw_readl(CSI_CSICR1);
- +
- + cr1 |= BIT_SOF_INTEN;
- + if (arg == 1) {
- + /* still capture needs DMA intterrupt */
- + cr1 |= BIT_FB1_DMA_DONE_INTEN;
- + cr1 |= BIT_FB2_DMA_DONE_INTEN;
- + }
- + __raw_writel(cr1, CSI_CSICR1);
- +}
- +EXPORT_SYMBOL(csi_enable_int);
- +
- +void csi_disable_int(void)
- +{
- + unsigned long cr1 = __raw_readl(CSI_CSICR1);
- +
- + cr1 &= ~BIT_SOF_INTEN;
- + cr1 &= ~BIT_FB1_DMA_DONE_INTEN;
- + cr1 &= ~BIT_FB2_DMA_DONE_INTEN;
- + __raw_writel(cr1, CSI_CSICR1);
- +}
- +EXPORT_SYMBOL(csi_disable_int);
- +
- +void csi_set_16bit_imagpara(int width, int height)
- +{
- + int imag_para = 0;
- + unsigned long cr3 = __raw_readl(CSI_CSICR3);
- +
- + imag_para = (width << 16) | (height * 2);
- + __raw_writel(imag_para, CSI_CSIIMAG_PARA);
- +
- + /* reflash the embeded DMA controller */
- + __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, CSI_CSICR3);
- +}
- +EXPORT_SYMBOL(csi_set_16bit_imagpara);
- +
- +void csi_set_12bit_imagpara(int width, int height)
- +{
- + int imag_para = 0;
- + unsigned long cr3 = __raw_readl(CSI_CSICR3);
- +
- + imag_para = (width << 16) | (height * 3 / 2);
- + __raw_writel(imag_para, CSI_CSIIMAG_PARA);
- +
- + /* reflash the embeded DMA controller */
- + __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, CSI_CSICR3);
- +}
- +EXPORT_SYMBOL(csi_set_12bit_imagpara);
- +
- +void csi_dmareq_rff_enable(void)
- +{
- + unsigned long cr3 = __raw_readl(CSI_CSICR3);
- +
- + cr3 |= BIT_DMA_REQ_EN_RFF;
- + cr3 |= BIT_HRESP_ERR_EN;
- + __raw_writel(cr3, CSI_CSICR3);
- +}
- +EXPORT_SYMBOL(csi_dmareq_rff_enable);
- +
- +void csi_dmareq_rff_disable(void)
- +{
- + unsigned long cr3 = __raw_readl(CSI_CSICR3);
- +
- + cr3 &= ~BIT_DMA_REQ_EN_RFF;
- + cr3 &= ~BIT_HRESP_ERR_EN;
- + __raw_writel(cr3, CSI_CSICR3);
- +}
- +EXPORT_SYMBOL(csi_dmareq_rff_disable);
- +
- +static const struct of_device_id fsl_csi_dt_ids[] = {
- + { .compatible = "fsl,imx6sl-csi", },
- + { /* sentinel */ }
- +};
- +MODULE_DEVICE_TABLE(of, fsl_csi_dt_ids);
- +
- +static int csi_probe(struct platform_device *pdev)
- +{
- + int ret = 0;
- + struct resource *res;
- +
- + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- + if (!res) {
- + dev_err(&pdev->dev, "No csi irq found.\n");
- + ret = -ENODEV;
- + goto err;
- + }
- + irq_nr = res->start;
- +
- + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- + if (!res) {
- + dev_err(&pdev->dev, "No csi base address found.\n");
- + ret = -ENODEV;
- + goto err;
- + }
- + csi_regbase = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- + if (!csi_regbase) {
- + dev_err(&pdev->dev, "ioremap failed with csi base\n");
- + ret = -ENOMEM;
- + goto err;
- + }
- +
- + csihw_reset();
- + csi_init_interface();
- + csi_dmareq_rff_disable();
- +
- +err:
- + return ret;
- +}
- +
- +static int csi_remove(struct platform_device *pdev)
- +{
- + return 0;
- +}
- +
- +static struct platform_driver csi_driver = {
- + .driver = {
- + .name = "fsl_csi",
- + .of_match_table = of_match_ptr(fsl_csi_dt_ids),
- + },
- + .probe = csi_probe,
- + .remove = csi_remove,
- +};
- +
- +module_platform_driver(csi_driver);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("fsl CSI driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/fsl_csi.h linux-3.14.35/drivers/media/platform/mxc/capture/fsl_csi.h
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/fsl_csi.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/fsl_csi.h 2015-03-08 14:27:37.589684501 -0500
- @@ -0,0 +1,198 @@
- +/*
- + * Copyright 2009-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file fsl_csi.h
- + *
- + * @brief mx25 CMOS Sensor interface functions
- + *
- + * @ingroup CSI
- + */
- +
- +#ifndef MX25_CSI_H
- +#define MX25_CSI_H
- +
- +#include <linux/io.h>
- +
- +/* reset values */
- +#define CSICR1_RESET_VAL 0x40000800
- +#define CSICR2_RESET_VAL 0x0
- +#define CSICR3_RESET_VAL 0x0
- +
- +/* csi control reg 1 */
- +#define BIT_SWAP16_EN (0x1 << 31)
- +#define BIT_EXT_VSYNC (0x1 << 30)
- +#define BIT_EOF_INT_EN (0x1 << 29)
- +#define BIT_PRP_IF_EN (0x1 << 28)
- +#define BIT_CCIR_MODE (0x1 << 27)
- +#define BIT_COF_INT_EN (0x1 << 26)
- +#define BIT_SF_OR_INTEN (0x1 << 25)
- +#define BIT_RF_OR_INTEN (0x1 << 24)
- +#define BIT_SFF_DMA_DONE_INTEN (0x1 << 22)
- +#define BIT_STATFF_INTEN (0x1 << 21)
- +#define BIT_FB2_DMA_DONE_INTEN (0x1 << 20)
- +#define BIT_FB1_DMA_DONE_INTEN (0x1 << 19)
- +#define BIT_RXFF_INTEN (0x1 << 18)
- +#define BIT_SOF_POL (0x1 << 17)
- +#define BIT_SOF_INTEN (0x1 << 16)
- +#define BIT_MCLKDIV (0xF << 12)
- +#define BIT_HSYNC_POL (0x1 << 11)
- +#define BIT_CCIR_EN (0x1 << 10)
- +#define BIT_MCLKEN (0x1 << 9)
- +#define BIT_FCC (0x1 << 8)
- +#define BIT_PACK_DIR (0x1 << 7)
- +#define BIT_CLR_STATFIFO (0x1 << 6)
- +#define BIT_CLR_RXFIFO (0x1 << 5)
- +#define BIT_GCLK_MODE (0x1 << 4)
- +#define BIT_INV_DATA (0x1 << 3)
- +#define BIT_INV_PCLK (0x1 << 2)
- +#define BIT_REDGE (0x1 << 1)
- +#define BIT_PIXEL_BIT (0x1 << 0)
- +
- +#define SHIFT_MCLKDIV 12
- +
- +/* control reg 3 */
- +#define BIT_FRMCNT (0xFFFF << 16)
- +#define BIT_FRMCNT_RST (0x1 << 15)
- +#define BIT_DMA_REFLASH_RFF (0x1 << 14)
- +#define BIT_DMA_REFLASH_SFF (0x1 << 13)
- +#define BIT_DMA_REQ_EN_RFF (0x1 << 12)
- +#define BIT_DMA_REQ_EN_SFF (0x1 << 11)
- +#define BIT_STATFF_LEVEL (0x7 << 8)
- +#define BIT_HRESP_ERR_EN (0x1 << 7)
- +#define BIT_RXFF_LEVEL (0x7 << 4)
- +#define BIT_TWO_8BIT_SENSOR (0x1 << 3)
- +#define BIT_ZERO_PACK_EN (0x1 << 2)
- +#define BIT_ECC_INT_EN (0x1 << 1)
- +#define BIT_ECC_AUTO_EN (0x1 << 0)
- +
- +#define SHIFT_FRMCNT 16
- +
- +/* csi status reg */
- +#define BIT_SFF_OR_INT (0x1 << 25)
- +#define BIT_RFF_OR_INT (0x1 << 24)
- +#define BIT_DMA_TSF_DONE_SFF (0x1 << 22)
- +#define BIT_STATFF_INT (0x1 << 21)
- +#define BIT_DMA_TSF_DONE_FB2 (0x1 << 20)
- +#define BIT_DMA_TSF_DONE_FB1 (0x1 << 19)
- +#define BIT_RXFF_INT (0x1 << 18)
- +#define BIT_EOF_INT (0x1 << 17)
- +#define BIT_SOF_INT (0x1 << 16)
- +#define BIT_F2_INT (0x1 << 15)
- +#define BIT_F1_INT (0x1 << 14)
- +#define BIT_COF_INT (0x1 << 13)
- +#define BIT_HRESP_ERR_INT (0x1 << 7)
- +#define BIT_ECC_INT (0x1 << 1)
- +#define BIT_DRDY (0x1 << 0)
- +
- +#define CSI_MCLK_VF 1
- +#define CSI_MCLK_ENC 2
- +#define CSI_MCLK_RAW 4
- +#define CSI_MCLK_I2C 8
- +#endif
- +
- +extern void __iomem *csi_regbase;
- +#define CSI_CSICR1 (csi_regbase)
- +#define CSI_CSICR2 (csi_regbase + 0x4)
- +#define CSI_CSICR3 (csi_regbase + 0x8)
- +#define CSI_STATFIFO (csi_regbase + 0xC)
- +#define CSI_CSIRXFIFO (csi_regbase + 0x10)
- +#define CSI_CSIRXCNT (csi_regbase + 0x14)
- +#define CSI_CSISR (csi_regbase + 0x18)
- +
- +#define CSI_CSIDBG (csi_regbase + 0x1C)
- +#define CSI_CSIDMASA_STATFIFO (csi_regbase + 0x20)
- +#define CSI_CSIDMATS_STATFIFO (csi_regbase + 0x24)
- +#define CSI_CSIDMASA_FB1 (csi_regbase + 0x28)
- +#define CSI_CSIDMASA_FB2 (csi_regbase + 0x2C)
- +#define CSI_CSIFBUF_PARA (csi_regbase + 0x30)
- +#define CSI_CSIIMAG_PARA (csi_regbase + 0x34)
- +
- +static inline void csi_clear_status(unsigned long status)
- +{
- + __raw_writel(status, CSI_CSISR);
- +}
- +
- +struct csi_signal_cfg_t {
- + unsigned data_width:3;
- + unsigned clk_mode:2;
- + unsigned ext_vsync:1;
- + unsigned Vsync_pol:1;
- + unsigned Hsync_pol:1;
- + unsigned pixclk_pol:1;
- + unsigned data_pol:1;
- + unsigned sens_clksrc:1;
- +};
- +
- +struct csi_config_t {
- + /* control reg 1 */
- + unsigned int swap16_en:1;
- + unsigned int ext_vsync:1;
- + unsigned int eof_int_en:1;
- + unsigned int prp_if_en:1;
- + unsigned int ccir_mode:1;
- + unsigned int cof_int_en:1;
- + unsigned int sf_or_inten:1;
- + unsigned int rf_or_inten:1;
- + unsigned int sff_dma_done_inten:1;
- + unsigned int statff_inten:1;
- + unsigned int fb2_dma_done_inten:1;
- + unsigned int fb1_dma_done_inten:1;
- + unsigned int rxff_inten:1;
- + unsigned int sof_pol:1;
- + unsigned int sof_inten:1;
- + unsigned int mclkdiv:4;
- + unsigned int hsync_pol:1;
- + unsigned int ccir_en:1;
- + unsigned int mclken:1;
- + unsigned int fcc:1;
- + unsigned int pack_dir:1;
- + unsigned int gclk_mode:1;
- + unsigned int inv_data:1;
- + unsigned int inv_pclk:1;
- + unsigned int redge:1;
- + unsigned int pixel_bit:1;
- +
- + /* control reg 3 */
- + unsigned int frmcnt:16;
- + unsigned int frame_reset:1;
- + unsigned int dma_reflash_rff:1;
- + unsigned int dma_reflash_sff:1;
- + unsigned int dma_req_en_rff:1;
- + unsigned int dma_req_en_sff:1;
- + unsigned int statff_level:3;
- + unsigned int hresp_err_en:1;
- + unsigned int rxff_level:3;
- + unsigned int two_8bit_sensor:1;
- + unsigned int zero_pack_en:1;
- + unsigned int ecc_int_en:1;
- + unsigned int ecc_auto_en:1;
- + /* fifo counter */
- + unsigned int rxcnt;
- +};
- +
- +typedef void (*csi_irq_callback_t) (void *data, unsigned long status);
- +
- +void csi_init_interface(void);
- +void csi_init_format(int fmt);
- +void csi_set_16bit_imagpara(int width, int height);
- +void csi_set_12bit_imagpara(int width, int height);
- +int csi_read_mclk_flag(void);
- +void csi_start_callback(void *data);
- +void csi_stop_callback(void *data);
- +void csi_enable_int(int arg);
- +void csi_disable_int(void);
- +void csi_mclk_enable(void);
- +void csi_mclk_disable(void);
- +void csi_dmareq_rff_enable(void);
- +void csi_dmareq_rff_disable(void);
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c linux-3.14.35/drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c 2015-03-08 14:27:37.589684501 -0500
- @@ -0,0 +1,546 @@
- +
- +/*
- + * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file ipu_bg_overlay_sdc_bg.c
- + *
- + * @brief IPU Use case for PRP-VF back-ground
- + *
- + * @ingroup IPU
- + */
- +#include <linux/module.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/fb.h>
- +#include <linux/ipu.h>
- +#include <linux/mipi_csi2.h>
- +#include "mxc_v4l2_capture.h"
- +#include "ipu_prp_sw.h"
- +
- +static int csi_buffer_num;
- +static u32 bpp, csi_mem_bufsize = 3;
- +static u32 out_format;
- +static struct ipu_soc *disp_ipu;
- +static u32 offset;
- +
- +static void csi_buf_work_func(struct work_struct *work)
- +{
- + int err = 0;
- + cam_data *cam =
- + container_of(work, struct _cam_data, csi_work_struct);
- +
- + struct ipu_task task;
- + memset(&task, 0, sizeof(task));
- +
- + if (csi_buffer_num)
- + task.input.paddr = cam->vf_bufs[0];
- + else
- + task.input.paddr = cam->vf_bufs[1];
- + task.input.width = cam->crop_current.width;
- + task.input.height = cam->crop_current.height;
- + task.input.format = IPU_PIX_FMT_UYVY;
- +
- + task.output.paddr = offset;
- + task.output.width = cam->overlay_fb->var.xres;
- + task.output.height = cam->overlay_fb->var.yres;
- + task.output.format = out_format;
- + task.output.rotate = cam->rotation;
- + task.output.crop.pos.x = cam->win.w.left;
- + task.output.crop.pos.y = cam->win.w.top;
- + if (cam->win.w.width > 1024 || cam->win.w.height > 1024) {
- + task.output.crop.w = cam->overlay_fb->var.xres;
- + task.output.crop.h = cam->overlay_fb->var.yres;
- + } else {
- + task.output.crop.w = cam->win.w.width;
- + task.output.crop.h = cam->win.w.height;
- + }
- +again:
- + err = ipu_check_task(&task);
- + if (err != IPU_CHECK_OK) {
- + if (err > IPU_CHECK_ERR_MIN) {
- + if (err == IPU_CHECK_ERR_SPLIT_INPUTW_OVER) {
- + task.input.crop.w -= 8;
- + goto again;
- + }
- + if (err == IPU_CHECK_ERR_SPLIT_INPUTH_OVER) {
- + task.input.crop.h -= 8;
- + goto again;
- + }
- + if (err == IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER) {
- + task.output.width -= 8;
- + task.output.crop.w = task.output.width;
- + goto again;
- + }
- + if (err == IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER) {
- + task.output.height -= 8;
- + task.output.crop.h = task.output.height;
- + goto again;
- + }
- + printk(KERN_ERR "check ipu taks fail\n");
- + return;
- + }
- + printk(KERN_ERR "check ipu taks fail\n");
- + return;
- + }
- + err = ipu_queue_task(&task);
- + if (err < 0)
- + printk(KERN_ERR "queue ipu task error\n");
- +}
- +
- +static void get_disp_ipu(cam_data *cam)
- +{
- + if (cam->output > 2)
- + disp_ipu = ipu_get_soc(1); /* using DISP4 */
- + else
- + disp_ipu = ipu_get_soc(0);
- +}
- +
- +
- +/*!
- + * csi ENC callback function.
- + *
- + * @param irq int irq line
- + * @param dev_id void * device id
- + *
- + * @return status IRQ_HANDLED for handled
- + */
- +static irqreturn_t csi_enc_callback(int irq, void *dev_id)
- +{
- + cam_data *cam = (cam_data *) dev_id;
- +
- + ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, csi_buffer_num);
- + schedule_work(&cam->csi_work_struct);
- + csi_buffer_num = (csi_buffer_num == 0) ? 1 : 0;
- + return IRQ_HANDLED;
- +}
- +
- +static int csi_enc_setup(cam_data *cam)
- +{
- + ipu_channel_params_t params;
- + u32 pixel_fmt;
- + int err = 0, sensor_protocol = 0;
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + void *mipi_csi2_info;
- + int ipu_id;
- + int csi_id;
- +#endif
- +
- + if (!cam) {
- + printk(KERN_ERR "cam private is NULL\n");
- + return -ENXIO;
- + }
- +
- + memset(¶ms, 0, sizeof(ipu_channel_params_t));
- + params.csi_mem.csi = cam->csi;
- +
- + sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi);
- + switch (sensor_protocol) {
- + case IPU_CSI_CLK_MODE_GATED_CLK:
- + case IPU_CSI_CLK_MODE_NONGATED_CLK:
- + case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
- + case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
- + case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
- + params.csi_mem.interlaced = false;
- + break;
- + case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
- + case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
- + case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
- + params.csi_mem.interlaced = true;
- + break;
- + default:
- + printk(KERN_ERR "sensor protocol unsupported\n");
- + return -EINVAL;
- + }
- +
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + mipi_csi2_info = mipi_csi2_get_info();
- +
- + if (mipi_csi2_info) {
- + if (mipi_csi2_get_status(mipi_csi2_info)) {
- + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
- + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
- +
- + if (cam->ipu == ipu_get_soc(ipu_id)
- + && cam->csi == csi_id) {
- + params.csi_mem.mipi_en = true;
- + params.csi_mem.mipi_vc =
- + mipi_csi2_get_virtual_channel(mipi_csi2_info);
- + params.csi_mem.mipi_id =
- + mipi_csi2_get_datatype(mipi_csi2_info);
- +
- + mipi_csi2_pixelclk_enable(mipi_csi2_info);
- + } else {
- + params.csi_mem.mipi_en = false;
- + params.csi_mem.mipi_vc = 0;
- + params.csi_mem.mipi_id = 0;
- + }
- + } else {
- + params.csi_mem.mipi_en = false;
- + params.csi_mem.mipi_vc = 0;
- + params.csi_mem.mipi_id = 0;
- + }
- + }
- +#endif
- +
- + if (cam->vf_bufs_vaddr[0]) {
- + dma_free_coherent(0, cam->vf_bufs_size[0],
- + cam->vf_bufs_vaddr[0],
- + (dma_addr_t) cam->vf_bufs[0]);
- + }
- + if (cam->vf_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->vf_bufs_size[1],
- + cam->vf_bufs_vaddr[1],
- + (dma_addr_t) cam->vf_bufs[1]);
- + }
- + csi_mem_bufsize =
- + cam->crop_current.width * cam->crop_current.height * 2;
- + cam->vf_bufs_size[0] = PAGE_ALIGN(csi_mem_bufsize);
- + cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0,
- + cam->vf_bufs_size[0],
- + (dma_addr_t *) &
- + cam->vf_bufs[0],
- + GFP_DMA |
- + GFP_KERNEL);
- + if (cam->vf_bufs_vaddr[0] == NULL) {
- + printk(KERN_ERR "Error to allocate vf buffer\n");
- + err = -ENOMEM;
- + goto out_2;
- + }
- + cam->vf_bufs_size[1] = PAGE_ALIGN(csi_mem_bufsize);
- + cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0,
- + cam->vf_bufs_size[1],
- + (dma_addr_t *) &
- + cam->vf_bufs[1],
- + GFP_DMA |
- + GFP_KERNEL);
- + if (cam->vf_bufs_vaddr[1] == NULL) {
- + printk(KERN_ERR "Error to allocate vf buffer\n");
- + err = -ENOMEM;
- + goto out_1;
- + }
- + pr_debug("vf_bufs %x %x\n", cam->vf_bufs[0], cam->vf_bufs[1]);
- +
- + err = ipu_init_channel(cam->ipu, CSI_MEM, ¶ms);
- + if (err != 0) {
- + printk(KERN_ERR "ipu_init_channel %d\n", err);
- + goto out_1;
- + }
- +
- + pixel_fmt = IPU_PIX_FMT_UYVY;
- + err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
- + pixel_fmt, cam->crop_current.width,
- + cam->crop_current.height,
- + cam->crop_current.width, IPU_ROTATE_NONE,
- + cam->vf_bufs[0], cam->vf_bufs[1], 0,
- + cam->offset.u_offset, cam->offset.u_offset);
- + if (err != 0) {
- + printk(KERN_ERR "CSI_MEM output buffer\n");
- + goto out_1;
- + }
- + err = ipu_enable_channel(cam->ipu, CSI_MEM);
- + if (err < 0) {
- + printk(KERN_ERR "ipu_enable_channel CSI_MEM\n");
- + goto out_1;
- + }
- +
- + csi_buffer_num = 0;
- +
- + ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 0);
- + ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 1);
- + return err;
- +out_1:
- + if (cam->vf_bufs_vaddr[0]) {
- + dma_free_coherent(0, cam->vf_bufs_size[0],
- + cam->vf_bufs_vaddr[0],
- + (dma_addr_t) cam->vf_bufs[0]);
- + cam->vf_bufs_vaddr[0] = NULL;
- + cam->vf_bufs[0] = 0;
- + }
- + if (cam->vf_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->vf_bufs_size[1],
- + cam->vf_bufs_vaddr[1],
- + (dma_addr_t) cam->vf_bufs[1]);
- + cam->vf_bufs_vaddr[1] = NULL;
- + cam->vf_bufs[1] = 0;
- + }
- +out_2:
- + return err;
- +}
- +
- +/*!
- + * Enable encoder task
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int csi_enc_enabling_tasks(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + int err = 0;
- +
- + ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF);
- + err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF,
- + csi_enc_callback, 0, "Mxc Camera", cam);
- + if (err != 0) {
- + printk(KERN_ERR "Error registering CSI0_OUT_EOF irq\n");
- + return err;
- + }
- +
- + INIT_WORK(&cam->csi_work_struct, csi_buf_work_func);
- +
- + err = csi_enc_setup(cam);
- + if (err != 0) {
- + printk(KERN_ERR "csi_enc_setup %d\n", err);
- + goto out1;
- + }
- +
- + return err;
- +out1:
- + ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam);
- + return err;
- +}
- +
- +/*!
- + * bg_overlay_start - start the overlay task
- + *
- + * @param private cam_data * mxc v4l2 main structure
- + *
- + */
- +static int bg_overlay_start(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + int err = 0;
- +
- + if (!cam) {
- + printk(KERN_ERR "private is NULL\n");
- + return -EIO;
- + }
- +
- + if (cam->overlay_active == true) {
- + pr_debug("already start.\n");
- + return 0;
- + }
- +
- + get_disp_ipu(cam);
- +
- + out_format = cam->v4l2_fb.fmt.pixelformat;
- + if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR24) {
- + bpp = 3, csi_mem_bufsize = 3;
- + pr_info("BGR24\n");
- + } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_RGB565) {
- + bpp = 2, csi_mem_bufsize = 2;
- + pr_info("RGB565\n");
- + } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR32) {
- + bpp = 4, csi_mem_bufsize = 4;
- + pr_info("BGR32\n");
- + } else {
- + printk(KERN_ERR
- + "unsupported fix format from the framebuffer.\n");
- + return -EINVAL;
- + }
- +
- + offset = cam->v4l2_fb.fmt.bytesperline * cam->win.w.top +
- + csi_mem_bufsize * cam->win.w.left;
- +
- + if (cam->v4l2_fb.base == 0)
- + printk(KERN_ERR "invalid frame buffer address.\n");
- + else
- + offset += (u32) cam->v4l2_fb.base;
- +
- + csi_mem_bufsize = cam->win.w.width * cam->win.w.height
- + * csi_mem_bufsize;
- +
- + err = csi_enc_enabling_tasks(cam);
- + if (err != 0) {
- + printk(KERN_ERR "Error csi enc enable fail\n");
- + return err;
- + }
- +
- + cam->overlay_active = true;
- + return err;
- +}
- +
- +/*!
- + * bg_overlay_stop - stop the overlay task
- + *
- + * @param private cam_data * mxc v4l2 main structure
- + *
- + */
- +static int bg_overlay_stop(void *private)
- +{
- + int err = 0;
- + cam_data *cam = (cam_data *) private;
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + void *mipi_csi2_info;
- + int ipu_id;
- + int csi_id;
- +#endif
- +
- + if (cam->overlay_active == false)
- + return 0;
- +
- + err = ipu_disable_channel(cam->ipu, CSI_MEM, true);
- +
- + ipu_uninit_channel(cam->ipu, CSI_MEM);
- +
- + csi_buffer_num = 0;
- +
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + mipi_csi2_info = mipi_csi2_get_info();
- +
- + if (mipi_csi2_info) {
- + if (mipi_csi2_get_status(mipi_csi2_info)) {
- + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
- + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
- +
- + if (cam->ipu == ipu_get_soc(ipu_id)
- + && cam->csi == csi_id)
- + mipi_csi2_pixelclk_disable(mipi_csi2_info);
- + }
- + }
- +#endif
- +
- + flush_work(&cam->csi_work_struct);
- + cancel_work_sync(&cam->csi_work_struct);
- +
- + if (cam->vf_bufs_vaddr[0]) {
- + dma_free_coherent(0, cam->vf_bufs_size[0],
- + cam->vf_bufs_vaddr[0], cam->vf_bufs[0]);
- + cam->vf_bufs_vaddr[0] = NULL;
- + cam->vf_bufs[0] = 0;
- + }
- + if (cam->vf_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->vf_bufs_size[1],
- + cam->vf_bufs_vaddr[1], cam->vf_bufs[1]);
- + cam->vf_bufs_vaddr[1] = NULL;
- + cam->vf_bufs[1] = 0;
- + }
- + if (cam->rot_vf_bufs_vaddr[0]) {
- + dma_free_coherent(0, cam->rot_vf_buf_size[0],
- + cam->rot_vf_bufs_vaddr[0],
- + cam->rot_vf_bufs[0]);
- + cam->rot_vf_bufs_vaddr[0] = NULL;
- + cam->rot_vf_bufs[0] = 0;
- + }
- + if (cam->rot_vf_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->rot_vf_buf_size[1],
- + cam->rot_vf_bufs_vaddr[1],
- + cam->rot_vf_bufs[1]);
- + cam->rot_vf_bufs_vaddr[1] = NULL;
- + cam->rot_vf_bufs[1] = 0;
- + }
- +
- + cam->overlay_active = false;
- + return err;
- +}
- +
- +/*!
- + * Enable csi
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int bg_overlay_enable_csi(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +
- + return ipu_enable_csi(cam->ipu, cam->csi);
- +}
- +
- +/*!
- + * Disable csi
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int bg_overlay_disable_csi(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +
- + /* free csi eof irq firstly.
- + * when disable csi, wait for idmac eof.
- + * it requests eof irq again */
- + ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam);
- +
- + return ipu_disable_csi(cam->ipu, cam->csi);
- +}
- +
- +/*!
- + * function to select bg as the working path
- + *
- + * @param private cam_data * mxc v4l2 main structure
- + *
- + * @return status
- + */
- +int bg_overlay_sdc_select(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +
- + if (cam) {
- + cam->vf_start_sdc = bg_overlay_start;
- + cam->vf_stop_sdc = bg_overlay_stop;
- + cam->vf_enable_csi = bg_overlay_enable_csi;
- + cam->vf_disable_csi = bg_overlay_disable_csi;
- + cam->overlay_active = false;
- + }
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(bg_overlay_sdc_select);
- +
- +/*!
- + * function to de-select bg as the working path
- + *
- + * @param private cam_data * mxc v4l2 main structure
- + *
- + * @return status
- + */
- +int bg_overlay_sdc_deselect(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +
- + if (cam) {
- + cam->vf_start_sdc = NULL;
- + cam->vf_stop_sdc = NULL;
- + cam->vf_enable_csi = NULL;
- + cam->vf_disable_csi = NULL;
- + }
- + return 0;
- +}
- +EXPORT_SYMBOL(bg_overlay_sdc_deselect);
- +
- +/*!
- + * Init background overlay task.
- + *
- + * @return Error code indicating success or failure
- + */
- +__init int bg_overlay_sdc_init(void)
- +{
- + return 0;
- +}
- +
- +/*!
- + * Deinit background overlay task.
- + *
- + * @return Error code indicating success or failure
- + */
- +void __exit bg_overlay_sdc_exit(void)
- +{
- +}
- +
- +module_init(bg_overlay_sdc_init);
- +module_exit(bg_overlay_sdc_exit);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("IPU PRP VF SDC Backgroud Driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/ipu_csi_enc.c linux-3.14.35/drivers/media/platform/mxc/capture/ipu_csi_enc.c
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/ipu_csi_enc.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/ipu_csi_enc.c 2015-03-08 14:27:37.589684501 -0500
- @@ -0,0 +1,418 @@
- +/*
- + * Copyright 2009-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file ipu_csi_enc.c
- + *
- + * @brief CSI Use case for video capture
- + *
- + * @ingroup IPU
- + */
- +
- +#include <linux/module.h>
- +#include <linux/platform_device.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/ipu.h>
- +#include <linux/mipi_csi2.h>
- +#include "mxc_v4l2_capture.h"
- +#include "ipu_prp_sw.h"
- +
- +#ifdef CAMERA_DBG
- + #define CAMERA_TRACE(x) (printk)x
- +#else
- + #define CAMERA_TRACE(x)
- +#endif
- +
- +/*
- + * Function definitions
- + */
- +
- +/*!
- + * csi ENC callback function.
- + *
- + * @param irq int irq line
- + * @param dev_id void * device id
- + *
- + * @return status IRQ_HANDLED for handled
- + */
- +static irqreturn_t csi_enc_callback(int irq, void *dev_id)
- +{
- + cam_data *cam = (cam_data *) dev_id;
- +
- + if (cam->enc_callback == NULL)
- + return IRQ_HANDLED;
- +
- + cam->enc_callback(irq, dev_id);
- + return IRQ_HANDLED;
- +}
- +
- +/*!
- + * CSI ENC enable channel setup function
- + *
- + * @param cam struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int csi_enc_setup(cam_data *cam)
- +{
- + ipu_channel_params_t params;
- + u32 pixel_fmt;
- + int err = 0, sensor_protocol = 0;
- + dma_addr_t dummy = cam->dummy_frame.buffer.m.offset;
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + void *mipi_csi2_info;
- + int ipu_id;
- + int csi_id;
- +#endif
- +
- + CAMERA_TRACE("In csi_enc_setup\n");
- + if (!cam) {
- + printk(KERN_ERR "cam private is NULL\n");
- + return -ENXIO;
- + }
- +
- + memset(¶ms, 0, sizeof(ipu_channel_params_t));
- + params.csi_mem.csi = cam->csi;
- +
- + sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi);
- + switch (sensor_protocol) {
- + case IPU_CSI_CLK_MODE_GATED_CLK:
- + case IPU_CSI_CLK_MODE_NONGATED_CLK:
- + case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
- + case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
- + case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
- + params.csi_mem.interlaced = false;
- + break;
- + case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
- + case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
- + case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
- + params.csi_mem.interlaced = true;
- + break;
- + default:
- + printk(KERN_ERR "sensor protocol unsupported\n");
- + return -EINVAL;
- + }
- +
- + if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
- + pixel_fmt = IPU_PIX_FMT_YUV420P;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420)
- + pixel_fmt = IPU_PIX_FMT_YVU420P;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P)
- + pixel_fmt = IPU_PIX_FMT_YUV422P;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY)
- + pixel_fmt = IPU_PIX_FMT_UYVY;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
- + pixel_fmt = IPU_PIX_FMT_YUYV;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12)
- + pixel_fmt = IPU_PIX_FMT_NV12;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24)
- + pixel_fmt = IPU_PIX_FMT_BGR24;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24)
- + pixel_fmt = IPU_PIX_FMT_RGB24;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565)
- + pixel_fmt = IPU_PIX_FMT_RGB565;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32)
- + pixel_fmt = IPU_PIX_FMT_BGR32;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32)
- + pixel_fmt = IPU_PIX_FMT_RGB32;
- + else {
- + printk(KERN_ERR "format not supported\n");
- + return -EINVAL;
- + }
- +
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + mipi_csi2_info = mipi_csi2_get_info();
- +
- + if (mipi_csi2_info) {
- + if (mipi_csi2_get_status(mipi_csi2_info)) {
- + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
- + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
- +
- + if (cam->ipu == ipu_get_soc(ipu_id)
- + && cam->csi == csi_id) {
- + params.csi_mem.mipi_en = true;
- + params.csi_mem.mipi_vc =
- + mipi_csi2_get_virtual_channel(mipi_csi2_info);
- + params.csi_mem.mipi_id =
- + mipi_csi2_get_datatype(mipi_csi2_info);
- +
- + mipi_csi2_pixelclk_enable(mipi_csi2_info);
- + } else {
- + params.csi_mem.mipi_en = false;
- + params.csi_mem.mipi_vc = 0;
- + params.csi_mem.mipi_id = 0;
- + }
- + } else {
- + params.csi_mem.mipi_en = false;
- + params.csi_mem.mipi_vc = 0;
- + params.csi_mem.mipi_id = 0;
- + }
- + }
- +#endif
- +
- + err = ipu_init_channel(cam->ipu, CSI_MEM, ¶ms);
- + if (err != 0) {
- + printk(KERN_ERR "ipu_init_channel %d\n", err);
- + return err;
- + }
- +
- + err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
- + pixel_fmt, cam->v2f.fmt.pix.width,
- + cam->v2f.fmt.pix.height,
- + cam->v2f.fmt.pix.bytesperline,
- + IPU_ROTATE_NONE,
- + dummy, dummy, 0,
- + cam->offset.u_offset,
- + cam->offset.v_offset);
- + if (err != 0) {
- + printk(KERN_ERR "CSI_MEM output buffer\n");
- + return err;
- + }
- + err = ipu_enable_channel(cam->ipu, CSI_MEM);
- + if (err < 0) {
- + printk(KERN_ERR "ipu_enable_channel CSI_MEM\n");
- + return err;
- + }
- +
- + return err;
- +}
- +
- +/*!
- + * function to update physical buffer address for encorder IDMA channel
- + *
- + * @param eba physical buffer address for encorder IDMA channel
- + * @param buffer_num int buffer 0 or buffer 1
- + *
- + * @return status
- + */
- +static int csi_enc_eba_update(struct ipu_soc *ipu, dma_addr_t eba,
- + int *buffer_num)
- +{
- + int err = 0;
- +
- + pr_debug("eba %x\n", eba);
- + err = ipu_update_channel_buffer(ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
- + *buffer_num, eba);
- + if (err != 0) {
- + ipu_clear_buffer_ready(ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
- + *buffer_num);
- +
- + err = ipu_update_channel_buffer(ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
- + *buffer_num, eba);
- + if (err != 0) {
- + pr_err("ERROR: v4l2 capture: fail to update "
- + "buf%d\n", *buffer_num);
- + return err;
- + }
- + }
- +
- + ipu_select_buffer(ipu, CSI_MEM, IPU_OUTPUT_BUFFER, *buffer_num);
- +
- + *buffer_num = (*buffer_num == 0) ? 1 : 0;
- +
- + return 0;
- +}
- +
- +/*!
- + * Enable encoder task
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int csi_enc_enabling_tasks(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + int err = 0;
- + CAMERA_TRACE("IPU:In csi_enc_enabling_tasks\n");
- +
- + cam->dummy_frame.vaddress = dma_alloc_coherent(0,
- + PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
- + &cam->dummy_frame.paddress,
- + GFP_DMA | GFP_KERNEL);
- + if (cam->dummy_frame.vaddress == 0) {
- + pr_err("ERROR: v4l2 capture: Allocate dummy frame "
- + "failed.\n");
- + return -ENOBUFS;
- + }
- + cam->dummy_frame.buffer.type = V4L2_BUF_TYPE_PRIVATE;
- + cam->dummy_frame.buffer.length =
- + PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
- + cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress;
- +
- + ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF);
- + err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF,
- + csi_enc_callback, 0, "Mxc Camera", cam);
- + if (err != 0) {
- + printk(KERN_ERR "Error registering rot irq\n");
- + return err;
- + }
- +
- + err = csi_enc_setup(cam);
- + if (err != 0) {
- + printk(KERN_ERR "csi_enc_setup %d\n", err);
- + return err;
- + }
- +
- + return err;
- +}
- +
- +/*!
- + * Disable encoder task
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return int
- + */
- +static int csi_enc_disabling_tasks(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + int err = 0;
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + void *mipi_csi2_info;
- + int ipu_id;
- + int csi_id;
- +#endif
- +
- + err = ipu_disable_channel(cam->ipu, CSI_MEM, true);
- +
- + ipu_uninit_channel(cam->ipu, CSI_MEM);
- +
- + if (cam->dummy_frame.vaddress != 0) {
- + dma_free_coherent(0, cam->dummy_frame.buffer.length,
- + cam->dummy_frame.vaddress,
- + cam->dummy_frame.paddress);
- + cam->dummy_frame.vaddress = 0;
- + }
- +
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + mipi_csi2_info = mipi_csi2_get_info();
- +
- + if (mipi_csi2_info) {
- + if (mipi_csi2_get_status(mipi_csi2_info)) {
- + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
- + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
- +
- + if (cam->ipu == ipu_get_soc(ipu_id)
- + && cam->csi == csi_id)
- + mipi_csi2_pixelclk_disable(mipi_csi2_info);
- + }
- + }
- +#endif
- +
- + return err;
- +}
- +
- +/*!
- + * Enable csi
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int csi_enc_enable_csi(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +
- + return ipu_enable_csi(cam->ipu, cam->csi);
- +}
- +
- +/*!
- + * Disable csi
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int csi_enc_disable_csi(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +
- + /* free csi eof irq firstly.
- + * when disable csi, wait for idmac eof.
- + * it requests eof irq again */
- + ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam);
- +
- + return ipu_disable_csi(cam->ipu, cam->csi);
- +}
- +
- +/*!
- + * function to select CSI ENC as the working path
- + *
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return int
- + */
- +int csi_enc_select(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + int err = 0;
- +
- + if (cam) {
- + cam->enc_update_eba = csi_enc_eba_update;
- + cam->enc_enable = csi_enc_enabling_tasks;
- + cam->enc_disable = csi_enc_disabling_tasks;
- + cam->enc_enable_csi = csi_enc_enable_csi;
- + cam->enc_disable_csi = csi_enc_disable_csi;
- + } else {
- + err = -EIO;
- + }
- +
- + return err;
- +}
- +EXPORT_SYMBOL(csi_enc_select);
- +
- +/*!
- + * function to de-select CSI ENC as the working path
- + *
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return int
- + */
- +int csi_enc_deselect(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + int err = 0;
- +
- + if (cam) {
- + cam->enc_update_eba = NULL;
- + cam->enc_enable = NULL;
- + cam->enc_disable = NULL;
- + cam->enc_enable_csi = NULL;
- + cam->enc_disable_csi = NULL;
- + }
- +
- + return err;
- +}
- +EXPORT_SYMBOL(csi_enc_deselect);
- +
- +/*!
- + * Init the Encorder channels
- + *
- + * @return Error code indicating success or failure
- + */
- +__init int csi_enc_init(void)
- +{
- + return 0;
- +}
- +
- +/*!
- + * Deinit the Encorder channels
- + *
- + */
- +void __exit csi_enc_exit(void)
- +{
- +}
- +
- +module_init(csi_enc_init);
- +module_exit(csi_enc_exit);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("CSI ENC Driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c linux-3.14.35/drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c 2015-03-08 14:27:37.589684501 -0500
- @@ -0,0 +1,634 @@
- +/*
- + * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +/* * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file ipu_foreground_sdc.c
- + *
- + * @brief IPU Use case for PRP-VF
- + *
- + * @ingroup IPU
- + */
- +
- +#include <linux/module.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/console.h>
- +#include <linux/ipu.h>
- +#include <linux/mxcfb.h>
- +#include <linux/mipi_csi2.h>
- +
- +#include "mxc_v4l2_capture.h"
- +#include "ipu_prp_sw.h"
- +
- +#ifdef CAMERA_DBG
- + #define CAMERA_TRACE(x) (printk)x
- +#else
- + #define CAMERA_TRACE(x)
- +#endif
- +
- +static int csi_buffer_num, buffer_num;
- +static u32 csi_mem_bufsize;
- +static struct ipu_soc *disp_ipu;
- +static struct fb_info *fbi;
- +static struct fb_var_screeninfo fbvar;
- +static u32 vf_out_format;
- +static void csi_buf_work_func(struct work_struct *work)
- +{
- + int err = 0;
- + cam_data *cam =
- + container_of(work, struct _cam_data, csi_work_struct);
- +
- + struct ipu_task task;
- + memset(&task, 0, sizeof(task));
- +
- + if (csi_buffer_num)
- + task.input.paddr = cam->vf_bufs[0];
- + else
- + task.input.paddr = cam->vf_bufs[1];
- + task.input.width = cam->crop_current.width;
- + task.input.height = cam->crop_current.height;
- + task.input.format = IPU_PIX_FMT_NV12;
- +
- + if (buffer_num == 0)
- + task.output.paddr = fbi->fix.smem_start +
- + (fbi->fix.line_length * fbvar.yres);
- + else
- + task.output.paddr = fbi->fix.smem_start;
- + task.output.width = cam->win.w.width;
- + task.output.height = cam->win.w.height;
- + task.output.format = vf_out_format;
- + task.output.rotate = cam->rotation;
- +again:
- + err = ipu_check_task(&task);
- + if (err != IPU_CHECK_OK) {
- + if (err > IPU_CHECK_ERR_MIN) {
- + if (err == IPU_CHECK_ERR_SPLIT_INPUTW_OVER) {
- + task.input.crop.w -= 8;
- + goto again;
- + }
- + if (err == IPU_CHECK_ERR_SPLIT_INPUTH_OVER) {
- + task.input.crop.h -= 8;
- + goto again;
- + }
- + if (err == IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER) {
- + task.output.width -= 8;
- + task.output.crop.w = task.output.width;
- + goto again;
- + }
- + if (err == IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER) {
- + task.output.height -= 8;
- + task.output.crop.h = task.output.height;
- + goto again;
- + }
- + printk(KERN_ERR "check ipu taks fail\n");
- + return;
- + }
- + printk(KERN_ERR "check ipu taks fail\n");
- + return;
- + }
- + err = ipu_queue_task(&task);
- + if (err < 0)
- + printk(KERN_ERR "queue ipu task error\n");
- + ipu_select_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER, buffer_num);
- + buffer_num = (buffer_num == 0) ? 1 : 0;
- +}
- +
- +static void get_disp_ipu(cam_data *cam)
- +{
- + if (cam->output > 2)
- + disp_ipu = ipu_get_soc(1); /* using DISP4 */
- + else
- + disp_ipu = ipu_get_soc(0);
- +}
- +
- +/*!
- + * csi ENC callback function.
- + *
- + * @param irq int irq line
- + * @param dev_id void * device id
- + *
- + * @return status IRQ_HANDLED for handled
- + */
- +static irqreturn_t csi_enc_callback(int irq, void *dev_id)
- +{
- + cam_data *cam = (cam_data *) dev_id;
- +
- + ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, csi_buffer_num);
- + if ((cam->crop_current.width != cam->win.w.width) ||
- + (cam->crop_current.height != cam->win.w.height) ||
- + (vf_out_format != IPU_PIX_FMT_NV12) ||
- + (cam->rotation >= IPU_ROTATE_VERT_FLIP))
- + schedule_work(&cam->csi_work_struct);
- + csi_buffer_num = (csi_buffer_num == 0) ? 1 : 0;
- + return IRQ_HANDLED;
- +}
- +
- +static int csi_enc_setup(cam_data *cam)
- +{
- + ipu_channel_params_t params;
- + int err = 0, sensor_protocol = 0;
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + void *mipi_csi2_info;
- + int ipu_id;
- + int csi_id;
- +#endif
- +
- + CAMERA_TRACE("In csi_enc_setup\n");
- + if (!cam) {
- + printk(KERN_ERR "cam private is NULL\n");
- + return -ENXIO;
- + }
- +
- + memset(¶ms, 0, sizeof(ipu_channel_params_t));
- + params.csi_mem.csi = cam->csi;
- +
- + sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi);
- + switch (sensor_protocol) {
- + case IPU_CSI_CLK_MODE_GATED_CLK:
- + case IPU_CSI_CLK_MODE_NONGATED_CLK:
- + case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
- + case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
- + case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
- + params.csi_mem.interlaced = false;
- + break;
- + case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
- + case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
- + case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
- + params.csi_mem.interlaced = true;
- + break;
- + default:
- + printk(KERN_ERR "sensor protocol unsupported\n");
- + return -EINVAL;
- + }
- +
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + mipi_csi2_info = mipi_csi2_get_info();
- +
- + if (mipi_csi2_info) {
- + if (mipi_csi2_get_status(mipi_csi2_info)) {
- + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
- + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
- +
- + if (cam->ipu == ipu_get_soc(ipu_id)
- + && cam->csi == csi_id) {
- + params.csi_mem.mipi_en = true;
- + params.csi_mem.mipi_vc =
- + mipi_csi2_get_virtual_channel(mipi_csi2_info);
- + params.csi_mem.mipi_id =
- + mipi_csi2_get_datatype(mipi_csi2_info);
- +
- + mipi_csi2_pixelclk_enable(mipi_csi2_info);
- + } else {
- + params.csi_mem.mipi_en = false;
- + params.csi_mem.mipi_vc = 0;
- + params.csi_mem.mipi_id = 0;
- + }
- + } else {
- + params.csi_mem.mipi_en = false;
- + params.csi_mem.mipi_vc = 0;
- + params.csi_mem.mipi_id = 0;
- + }
- + }
- +#endif
- +
- + if (cam->vf_bufs_vaddr[0]) {
- + dma_free_coherent(0, cam->vf_bufs_size[0],
- + cam->vf_bufs_vaddr[0],
- + (dma_addr_t) cam->vf_bufs[0]);
- + }
- + if (cam->vf_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->vf_bufs_size[1],
- + cam->vf_bufs_vaddr[1],
- + (dma_addr_t) cam->vf_bufs[1]);
- + }
- + csi_mem_bufsize = cam->crop_current.width *
- + cam->crop_current.height * 3/2;
- + cam->vf_bufs_size[0] = PAGE_ALIGN(csi_mem_bufsize);
- + cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0,
- + cam->vf_bufs_size[0],
- + (dma_addr_t *) &
- + cam->vf_bufs[0],
- + GFP_DMA |
- + GFP_KERNEL);
- + if (cam->vf_bufs_vaddr[0] == NULL) {
- + printk(KERN_ERR "Error to allocate vf buffer\n");
- + err = -ENOMEM;
- + goto out_2;
- + }
- + cam->vf_bufs_size[1] = PAGE_ALIGN(csi_mem_bufsize);
- + cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0,
- + cam->vf_bufs_size[1],
- + (dma_addr_t *) &
- + cam->vf_bufs[1],
- + GFP_DMA |
- + GFP_KERNEL);
- + if (cam->vf_bufs_vaddr[1] == NULL) {
- + printk(KERN_ERR "Error to allocate vf buffer\n");
- + err = -ENOMEM;
- + goto out_1;
- + }
- + pr_debug("vf_bufs %x %x\n", cam->vf_bufs[0], cam->vf_bufs[1]);
- +
- + err = ipu_init_channel(cam->ipu, CSI_MEM, ¶ms);
- + if (err != 0) {
- + printk(KERN_ERR "ipu_init_channel %d\n", err);
- + goto out_1;
- + }
- +
- + if ((cam->crop_current.width == cam->win.w.width) &&
- + (cam->crop_current.height == cam->win.w.height) &&
- + (vf_out_format == IPU_PIX_FMT_NV12) &&
- + (cam->rotation < IPU_ROTATE_VERT_FLIP)) {
- + err = ipu_init_channel_buffer(cam->ipu, CSI_MEM,
- + IPU_OUTPUT_BUFFER,
- + IPU_PIX_FMT_NV12,
- + cam->crop_current.width,
- + cam->crop_current.height,
- + cam->crop_current.width, IPU_ROTATE_NONE,
- + fbi->fix.smem_start +
- + (fbi->fix.line_length * fbvar.yres),
- + fbi->fix.smem_start, 0,
- + cam->offset.u_offset, cam->offset.u_offset);
- + } else {
- + err = ipu_init_channel_buffer(cam->ipu, CSI_MEM,
- + IPU_OUTPUT_BUFFER,
- + IPU_PIX_FMT_NV12,
- + cam->crop_current.width,
- + cam->crop_current.height,
- + cam->crop_current.width, IPU_ROTATE_NONE,
- + cam->vf_bufs[0], cam->vf_bufs[1], 0,
- + cam->offset.u_offset, cam->offset.u_offset);
- + }
- + if (err != 0) {
- + printk(KERN_ERR "CSI_MEM output buffer\n");
- + goto out_1;
- + }
- + err = ipu_enable_channel(cam->ipu, CSI_MEM);
- + if (err < 0) {
- + printk(KERN_ERR "ipu_enable_channel CSI_MEM\n");
- + goto out_1;
- + }
- +
- + csi_buffer_num = 0;
- +
- + ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 0);
- + ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 1);
- + return err;
- +out_1:
- + if (cam->vf_bufs_vaddr[0]) {
- + dma_free_coherent(0, cam->vf_bufs_size[0],
- + cam->vf_bufs_vaddr[0],
- + (dma_addr_t) cam->vf_bufs[0]);
- + cam->vf_bufs_vaddr[0] = NULL;
- + cam->vf_bufs[0] = 0;
- + }
- + if (cam->vf_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->vf_bufs_size[1],
- + cam->vf_bufs_vaddr[1],
- + (dma_addr_t) cam->vf_bufs[1]);
- + cam->vf_bufs_vaddr[1] = NULL;
- + cam->vf_bufs[1] = 0;
- + }
- +out_2:
- + return err;
- +}
- +
- +/*!
- + * Enable encoder task
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int csi_enc_enabling_tasks(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + int err = 0;
- + CAMERA_TRACE("IPU:In csi_enc_enabling_tasks\n");
- +
- + ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF);
- + err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF,
- + csi_enc_callback, 0, "Mxc Camera", cam);
- + if (err != 0) {
- + printk(KERN_ERR "Error registering CSI0_OUT_EOF irq\n");
- + return err;
- + }
- +
- + INIT_WORK(&cam->csi_work_struct, csi_buf_work_func);
- +
- + err = csi_enc_setup(cam);
- + if (err != 0) {
- + printk(KERN_ERR "csi_enc_setup %d\n", err);
- + goto out1;
- + }
- +
- + return err;
- +out1:
- + ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam);
- + return err;
- +}
- +
- +/*
- + * Function definitions
- + */
- +
- +/*!
- + * foreground_start - start the vf task
- + *
- + * @param private cam_data * mxc v4l2 main structure
- + *
- + */
- +static int foreground_start(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + int err = 0, i = 0, screen_size;
- + char *base;
- +
- + if (!cam) {
- + printk(KERN_ERR "private is NULL\n");
- + return -EIO;
- + }
- +
- + if (cam->overlay_active == true) {
- + pr_debug("already started.\n");
- + return 0;
- + }
- +
- + get_disp_ipu(cam);
- +
- + for (i = 0; i < num_registered_fb; i++) {
- + char *idstr = registered_fb[i]->fix.id;
- + if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) ||
- + ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) {
- + fbi = registered_fb[i];
- + break;
- + }
- + }
- +
- + if (fbi == NULL) {
- + printk(KERN_ERR "DISP FG fb not found\n");
- + return -EPERM;
- + }
- +
- + fbvar = fbi->var;
- +
- + /* Store the overlay frame buffer's original std */
- + cam->fb_origin_std = fbvar.nonstd;
- +
- + if (cam->devtype == IMX5_V4L2 || cam->devtype == IMX6_V4L2) {
- + /* Use DP to do CSC so that we can get better performance */
- + vf_out_format = IPU_PIX_FMT_NV12;
- + fbvar.nonstd = vf_out_format;
- + } else {
- + vf_out_format = IPU_PIX_FMT_RGB565;
- + fbvar.nonstd = 0;
- + }
- +
- + fbvar.bits_per_pixel = 16;
- + fbvar.xres = fbvar.xres_virtual = cam->win.w.width;
- + fbvar.yres = cam->win.w.height;
- + fbvar.yres_virtual = cam->win.w.height * 2;
- + fbvar.yoffset = 0;
- + fbvar.vmode &= ~FB_VMODE_YWRAP;
- + fbvar.accel_flags = FB_ACCEL_DOUBLE_FLAG;
- + fbvar.activate |= FB_ACTIVATE_FORCE;
- + fb_set_var(fbi, &fbvar);
- +
- + ipu_disp_set_window_pos(disp_ipu, MEM_FG_SYNC, cam->win.w.left,
- + cam->win.w.top);
- +
- + /* Fill black color for framebuffer */
- + base = (char *) fbi->screen_base;
- + screen_size = fbi->var.xres * fbi->var.yres;
- + if (cam->devtype == IMX5_V4L2 || cam->devtype == IMX6_V4L2) {
- + memset(base, 0, screen_size);
- + base += screen_size;
- + for (i = 0; i < screen_size / 2; i++, base++)
- + *base = 0x80;
- + } else {
- + for (i = 0; i < screen_size * 2; i++, base++)
- + *base = 0x00;
- + }
- +
- + console_lock();
- + fb_blank(fbi, FB_BLANK_UNBLANK);
- + console_unlock();
- +
- + /* correct display ch buffer address */
- + ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER,
- + 0, fbi->fix.smem_start +
- + (fbi->fix.line_length * fbvar.yres));
- + ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER,
- + 1, fbi->fix.smem_start);
- +
- + err = csi_enc_enabling_tasks(cam);
- + if (err != 0) {
- + printk(KERN_ERR "Error csi enc enable fail\n");
- + return err;
- + }
- +
- + cam->overlay_active = true;
- + return err;
- +
- +}
- +
- +/*!
- + * foreground_stop - stop the vf task
- + *
- + * @param private cam_data * mxc v4l2 main structure
- + *
- + */
- +static int foreground_stop(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + int err = 0, i = 0;
- + struct fb_info *fbi = NULL;
- + struct fb_var_screeninfo fbvar;
- +
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + void *mipi_csi2_info;
- + int ipu_id;
- + int csi_id;
- +#endif
- +
- + if (cam->overlay_active == false)
- + return 0;
- +
- + err = ipu_disable_channel(cam->ipu, CSI_MEM, true);
- +
- + ipu_uninit_channel(cam->ipu, CSI_MEM);
- +
- + csi_buffer_num = 0;
- + buffer_num = 0;
- +
- + for (i = 0; i < num_registered_fb; i++) {
- + char *idstr = registered_fb[i]->fix.id;
- + if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) ||
- + ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) {
- + fbi = registered_fb[i];
- + break;
- + }
- + }
- +
- + if (fbi == NULL) {
- + printk(KERN_ERR "DISP FG fb not found\n");
- + return -EPERM;
- + }
- +
- + console_lock();
- + fb_blank(fbi, FB_BLANK_POWERDOWN);
- + console_unlock();
- +
- + /* Set the overlay frame buffer std to what it is used to be */
- + fbvar = fbi->var;
- + fbvar.accel_flags = FB_ACCEL_TRIPLE_FLAG;
- + fbvar.nonstd = cam->fb_origin_std;
- + fbvar.activate |= FB_ACTIVATE_FORCE;
- + fb_set_var(fbi, &fbvar);
- +
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + mipi_csi2_info = mipi_csi2_get_info();
- +
- + if (mipi_csi2_info) {
- + if (mipi_csi2_get_status(mipi_csi2_info)) {
- + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
- + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
- +
- + if (cam->ipu == ipu_get_soc(ipu_id)
- + && cam->csi == csi_id)
- + mipi_csi2_pixelclk_disable(mipi_csi2_info);
- + }
- + }
- +#endif
- +
- + flush_work(&cam->csi_work_struct);
- + cancel_work_sync(&cam->csi_work_struct);
- +
- + if (cam->vf_bufs_vaddr[0]) {
- + dma_free_coherent(0, cam->vf_bufs_size[0],
- + cam->vf_bufs_vaddr[0],
- + (dma_addr_t) cam->vf_bufs[0]);
- + cam->vf_bufs_vaddr[0] = NULL;
- + cam->vf_bufs[0] = 0;
- + }
- + if (cam->vf_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->vf_bufs_size[1],
- + cam->vf_bufs_vaddr[1],
- + (dma_addr_t) cam->vf_bufs[1]);
- + cam->vf_bufs_vaddr[1] = NULL;
- + cam->vf_bufs[1] = 0;
- + }
- +
- + cam->overlay_active = false;
- + return err;
- +}
- +
- +/*!
- + * Enable csi
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int foreground_enable_csi(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +
- + return ipu_enable_csi(cam->ipu, cam->csi);
- +}
- +
- +/*!
- + * Disable csi
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int foreground_disable_csi(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +
- + /* free csi eof irq firstly.
- + * when disable csi, wait for idmac eof.
- + * it requests eof irq again */
- + ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam);
- +
- + return ipu_disable_csi(cam->ipu, cam->csi);
- +}
- +
- +/*!
- + * function to select foreground as the working path
- + *
- + * @param private cam_data * mxc v4l2 main structure
- + *
- + * @return status
- + */
- +int foreground_sdc_select(void *private)
- +{
- + cam_data *cam;
- + int err = 0;
- + if (private) {
- + cam = (cam_data *) private;
- + cam->vf_start_sdc = foreground_start;
- + cam->vf_stop_sdc = foreground_stop;
- + cam->vf_enable_csi = foreground_enable_csi;
- + cam->vf_disable_csi = foreground_disable_csi;
- + cam->overlay_active = false;
- + } else
- + err = -EIO;
- +
- + return err;
- +}
- +EXPORT_SYMBOL(foreground_sdc_select);
- +
- +/*!
- + * function to de-select foreground as the working path
- + *
- + * @param private cam_data * mxc v4l2 main structure
- + *
- + * @return int
- + */
- +int foreground_sdc_deselect(void *private)
- +{
- + cam_data *cam;
- +
- + if (private) {
- + cam = (cam_data *) private;
- + cam->vf_start_sdc = NULL;
- + cam->vf_stop_sdc = NULL;
- + cam->vf_enable_csi = NULL;
- + cam->vf_disable_csi = NULL;
- + }
- + return 0;
- +}
- +EXPORT_SYMBOL(foreground_sdc_deselect);
- +
- +/*!
- + * Init viewfinder task.
- + *
- + * @return Error code indicating success or failure
- + */
- +__init int foreground_sdc_init(void)
- +{
- + return 0;
- +}
- +
- +/*!
- + * Deinit viewfinder task.
- + *
- + * @return Error code indicating success or failure
- + */
- +void __exit foreground_sdc_exit(void)
- +{
- +}
- +
- +module_init(foreground_sdc_init);
- +module_exit(foreground_sdc_exit);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("IPU PRP VF SDC Driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/ipu_prp_enc.c linux-3.14.35/drivers/media/platform/mxc/capture/ipu_prp_enc.c
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/ipu_prp_enc.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/ipu_prp_enc.c 2015-03-08 14:27:37.593684501 -0500
- @@ -0,0 +1,595 @@
- +/*
- + * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file ipu_prp_enc.c
- + *
- + * @brief IPU Use case for PRP-ENC
- + *
- + * @ingroup IPU
- + */
- +
- +#include <linux/module.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/platform_device.h>
- +#include <linux/ipu.h>
- +#include <linux/mipi_csi2.h>
- +#include "mxc_v4l2_capture.h"
- +#include "ipu_prp_sw.h"
- +
- +#ifdef CAMERA_DBG
- + #define CAMERA_TRACE(x) (printk)x
- +#else
- + #define CAMERA_TRACE(x)
- +#endif
- +
- +static ipu_rotate_mode_t grotation = IPU_ROTATE_NONE;
- +
- +/*
- + * Function definitions
- + */
- +
- +/*!
- + * IPU ENC callback function.
- + *
- + * @param irq int irq line
- + * @param dev_id void * device id
- + *
- + * @return status IRQ_HANDLED for handled
- + */
- +static irqreturn_t prp_enc_callback(int irq, void *dev_id)
- +{
- + cam_data *cam = (cam_data *) dev_id;
- +
- + if (cam->enc_callback == NULL)
- + return IRQ_HANDLED;
- +
- + cam->enc_callback(irq, dev_id);
- +
- + return IRQ_HANDLED;
- +}
- +
- +/*!
- + * PrpENC enable channel setup function
- + *
- + * @param cam struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int prp_enc_setup(cam_data *cam)
- +{
- + ipu_channel_params_t enc;
- + int err = 0;
- + dma_addr_t dummy = cam->dummy_frame.buffer.m.offset;
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + void *mipi_csi2_info;
- + int ipu_id;
- + int csi_id;
- +#endif
- +
- + CAMERA_TRACE("In prp_enc_setup\n");
- + if (!cam) {
- + printk(KERN_ERR "cam private is NULL\n");
- + return -ENXIO;
- + }
- + memset(&enc, 0, sizeof(ipu_channel_params_t));
- +
- + ipu_csi_get_window_size(cam->ipu, &enc.csi_prp_enc_mem.in_width,
- + &enc.csi_prp_enc_mem.in_height, cam->csi);
- +
- + enc.csi_prp_enc_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY;
- + enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.width;
- + enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.height;
- + enc.csi_prp_enc_mem.csi = cam->csi;
- + if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
- + enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.height;
- + enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.width;
- + }
- +
- + if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) {
- + enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV420P;
- + pr_info("YUV420\n");
- + } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420) {
- + enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YVU420P;
- + pr_info("YVU420\n");
- + } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) {
- + enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV422P;
- + pr_info("YUV422P\n");
- + } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
- + enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUYV;
- + pr_info("YUYV\n");
- + } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) {
- + enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_UYVY;
- + pr_info("UYVY\n");
- + } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) {
- + enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_NV12;
- + pr_info("NV12\n");
- + } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) {
- + enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR24;
- + pr_info("BGR24\n");
- + } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) {
- + enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB24;
- + pr_info("RGB24\n");
- + } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) {
- + enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB565;
- + pr_info("RGB565\n");
- + } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) {
- + enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR32;
- + pr_info("BGR32\n");
- + } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) {
- + enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB32;
- + pr_info("RGB32\n");
- + } else {
- + printk(KERN_ERR "format not supported\n");
- + return -EINVAL;
- + }
- +
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + mipi_csi2_info = mipi_csi2_get_info();
- +
- + if (mipi_csi2_info) {
- + if (mipi_csi2_get_status(mipi_csi2_info)) {
- + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
- + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
- +
- + if (cam->ipu == ipu_get_soc(ipu_id)
- + && cam->csi == csi_id) {
- + enc.csi_prp_enc_mem.mipi_en = true;
- + enc.csi_prp_enc_mem.mipi_vc =
- + mipi_csi2_get_virtual_channel(mipi_csi2_info);
- + enc.csi_prp_enc_mem.mipi_id =
- + mipi_csi2_get_datatype(mipi_csi2_info);
- +
- + mipi_csi2_pixelclk_enable(mipi_csi2_info);
- + } else {
- + enc.csi_prp_enc_mem.mipi_en = false;
- + enc.csi_prp_enc_mem.mipi_vc = 0;
- + enc.csi_prp_enc_mem.mipi_id = 0;
- + }
- + } else {
- + enc.csi_prp_enc_mem.mipi_en = false;
- + enc.csi_prp_enc_mem.mipi_vc = 0;
- + enc.csi_prp_enc_mem.mipi_id = 0;
- + }
- + }
- +#endif
- +
- + err = ipu_init_channel(cam->ipu, CSI_PRP_ENC_MEM, &enc);
- + if (err != 0) {
- + printk(KERN_ERR "ipu_init_channel %d\n", err);
- + return err;
- + }
- +
- + grotation = cam->rotation;
- + if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
- + if (cam->rot_enc_bufs_vaddr[0]) {
- + dma_free_coherent(0, cam->rot_enc_buf_size[0],
- + cam->rot_enc_bufs_vaddr[0],
- + cam->rot_enc_bufs[0]);
- + }
- + if (cam->rot_enc_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->rot_enc_buf_size[1],
- + cam->rot_enc_bufs_vaddr[1],
- + cam->rot_enc_bufs[1]);
- + }
- + cam->rot_enc_buf_size[0] =
- + PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
- + cam->rot_enc_bufs_vaddr[0] =
- + (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[0],
- + &cam->rot_enc_bufs[0],
- + GFP_DMA | GFP_KERNEL);
- + if (!cam->rot_enc_bufs_vaddr[0]) {
- + printk(KERN_ERR "alloc enc_bufs0\n");
- + return -ENOMEM;
- + }
- + cam->rot_enc_buf_size[1] =
- + PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
- + cam->rot_enc_bufs_vaddr[1] =
- + (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[1],
- + &cam->rot_enc_bufs[1],
- + GFP_DMA | GFP_KERNEL);
- + if (!cam->rot_enc_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->rot_enc_buf_size[0],
- + cam->rot_enc_bufs_vaddr[0],
- + cam->rot_enc_bufs[0]);
- + cam->rot_enc_bufs_vaddr[0] = NULL;
- + cam->rot_enc_bufs[0] = 0;
- + printk(KERN_ERR "alloc enc_bufs1\n");
- + return -ENOMEM;
- + }
- +
- + err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_ENC_MEM,
- + IPU_OUTPUT_BUFFER,
- + enc.csi_prp_enc_mem.out_pixel_fmt,
- + enc.csi_prp_enc_mem.out_width,
- + enc.csi_prp_enc_mem.out_height,
- + enc.csi_prp_enc_mem.out_width,
- + IPU_ROTATE_NONE,
- + cam->rot_enc_bufs[0],
- + cam->rot_enc_bufs[1], 0, 0, 0);
- + if (err != 0) {
- + printk(KERN_ERR "CSI_PRP_ENC_MEM err\n");
- + return err;
- + }
- +
- + err = ipu_init_channel(cam->ipu, MEM_ROT_ENC_MEM, NULL);
- + if (err != 0) {
- + printk(KERN_ERR "MEM_ROT_ENC_MEM channel err\n");
- + return err;
- + }
- +
- + err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_ENC_MEM,
- + IPU_INPUT_BUFFER,
- + enc.csi_prp_enc_mem.out_pixel_fmt,
- + enc.csi_prp_enc_mem.out_width,
- + enc.csi_prp_enc_mem.out_height,
- + enc.csi_prp_enc_mem.out_width,
- + cam->rotation,
- + cam->rot_enc_bufs[0],
- + cam->rot_enc_bufs[1], 0, 0, 0);
- + if (err != 0) {
- + printk(KERN_ERR "MEM_ROT_ENC_MEM input buffer\n");
- + return err;
- + }
- +
- + err =
- + ipu_init_channel_buffer(cam->ipu, MEM_ROT_ENC_MEM,
- + IPU_OUTPUT_BUFFER,
- + enc.csi_prp_enc_mem.out_pixel_fmt,
- + enc.csi_prp_enc_mem.out_height,
- + enc.csi_prp_enc_mem.out_width,
- + cam->v2f.fmt.pix.bytesperline /
- + bytes_per_pixel(enc.csi_prp_enc_mem.
- + out_pixel_fmt),
- + IPU_ROTATE_NONE,
- + dummy, dummy, 0,
- + cam->offset.u_offset,
- + cam->offset.v_offset);
- + if (err != 0) {
- + printk(KERN_ERR "MEM_ROT_ENC_MEM output buffer\n");
- + return err;
- + }
- +
- + err = ipu_link_channels(cam->ipu,
- + CSI_PRP_ENC_MEM, MEM_ROT_ENC_MEM);
- + if (err < 0) {
- + printk(KERN_ERR
- + "link CSI_PRP_ENC_MEM-MEM_ROT_ENC_MEM\n");
- + return err;
- + }
- +
- + err = ipu_enable_channel(cam->ipu, CSI_PRP_ENC_MEM);
- + if (err < 0) {
- + printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n");
- + return err;
- + }
- + err = ipu_enable_channel(cam->ipu, MEM_ROT_ENC_MEM);
- + if (err < 0) {
- + printk(KERN_ERR "ipu_enable_channel MEM_ROT_ENC_MEM\n");
- + return err;
- + }
- +
- + ipu_select_buffer(cam->ipu, CSI_PRP_ENC_MEM,
- + IPU_OUTPUT_BUFFER, 0);
- + ipu_select_buffer(cam->ipu, CSI_PRP_ENC_MEM,
- + IPU_OUTPUT_BUFFER, 1);
- + } else {
- + err =
- + ipu_init_channel_buffer(cam->ipu, CSI_PRP_ENC_MEM,
- + IPU_OUTPUT_BUFFER,
- + enc.csi_prp_enc_mem.out_pixel_fmt,
- + enc.csi_prp_enc_mem.out_width,
- + enc.csi_prp_enc_mem.out_height,
- + cam->v2f.fmt.pix.bytesperline /
- + bytes_per_pixel(enc.csi_prp_enc_mem.
- + out_pixel_fmt),
- + cam->rotation,
- + dummy, dummy, 0,
- + cam->offset.u_offset,
- + cam->offset.v_offset);
- + if (err != 0) {
- + printk(KERN_ERR "CSI_PRP_ENC_MEM output buffer\n");
- + return err;
- + }
- + err = ipu_enable_channel(cam->ipu, CSI_PRP_ENC_MEM);
- + if (err < 0) {
- + printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n");
- + return err;
- + }
- + }
- +
- + return err;
- +}
- +
- +/*!
- + * function to update physical buffer address for encorder IDMA channel
- + *
- + * @param eba physical buffer address for encorder IDMA channel
- + * @param buffer_num int buffer 0 or buffer 1
- + *
- + * @return status
- + */
- +static int prp_enc_eba_update(struct ipu_soc *ipu, dma_addr_t eba,
- + int *buffer_num)
- +{
- + int err = 0;
- +
- + pr_debug("eba %x\n", eba);
- + if (grotation >= IPU_ROTATE_90_RIGHT) {
- + err = ipu_update_channel_buffer(ipu, MEM_ROT_ENC_MEM,
- + IPU_OUTPUT_BUFFER, *buffer_num,
- + eba);
- + } else {
- + err = ipu_update_channel_buffer(ipu, CSI_PRP_ENC_MEM,
- + IPU_OUTPUT_BUFFER, *buffer_num,
- + eba);
- + }
- + if (err != 0) {
- + if (grotation >= IPU_ROTATE_90_RIGHT) {
- + ipu_clear_buffer_ready(ipu, MEM_ROT_ENC_MEM,
- + IPU_OUTPUT_BUFFER,
- + *buffer_num);
- + err = ipu_update_channel_buffer(ipu, MEM_ROT_ENC_MEM,
- + IPU_OUTPUT_BUFFER,
- + *buffer_num,
- + eba);
- + } else {
- + ipu_clear_buffer_ready(ipu, CSI_PRP_ENC_MEM,
- + IPU_OUTPUT_BUFFER,
- + *buffer_num);
- + err = ipu_update_channel_buffer(ipu, CSI_PRP_ENC_MEM,
- + IPU_OUTPUT_BUFFER,
- + *buffer_num,
- + eba);
- + }
- +
- + if (err != 0) {
- + pr_err("ERROR: v4l2 capture: fail to update "
- + "buf%d\n", *buffer_num);
- + return err;
- + }
- + }
- +
- + if (grotation >= IPU_ROTATE_90_RIGHT) {
- + ipu_select_buffer(ipu, MEM_ROT_ENC_MEM, IPU_OUTPUT_BUFFER,
- + *buffer_num);
- + } else {
- + ipu_select_buffer(ipu, CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER,
- + *buffer_num);
- + }
- +
- + *buffer_num = (*buffer_num == 0) ? 1 : 0;
- + return 0;
- +}
- +
- +/*!
- + * Enable encoder task
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int prp_enc_enabling_tasks(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + int err = 0;
- + CAMERA_TRACE("IPU:In prp_enc_enabling_tasks\n");
- +
- + cam->dummy_frame.vaddress = dma_alloc_coherent(0,
- + PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
- + &cam->dummy_frame.paddress,
- + GFP_DMA | GFP_KERNEL);
- + if (cam->dummy_frame.vaddress == 0) {
- + pr_err("ERROR: v4l2 capture: Allocate dummy frame "
- + "failed.\n");
- + return -ENOBUFS;
- + }
- + cam->dummy_frame.buffer.type = V4L2_BUF_TYPE_PRIVATE;
- + cam->dummy_frame.buffer.length =
- + PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
- + cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress;
- +
- + if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
- + err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_ENC_ROT_OUT_EOF,
- + prp_enc_callback, 0, "Mxc Camera", cam);
- + } else {
- + err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_ENC_OUT_EOF,
- + prp_enc_callback, 0, "Mxc Camera", cam);
- + }
- + if (err != 0) {
- + printk(KERN_ERR "Error registering rot irq\n");
- + return err;
- + }
- +
- + err = prp_enc_setup(cam);
- + if (err != 0) {
- + printk(KERN_ERR "prp_enc_setup %d\n", err);
- + return err;
- + }
- +
- + return err;
- +}
- +
- +/*!
- + * Disable encoder task
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return int
- + */
- +static int prp_enc_disabling_tasks(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + int err = 0;
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + void *mipi_csi2_info;
- + int ipu_id;
- + int csi_id;
- +#endif
- +
- + if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
- + ipu_free_irq(cam->ipu, IPU_IRQ_PRP_ENC_ROT_OUT_EOF, cam);
- + ipu_unlink_channels(cam->ipu, CSI_PRP_ENC_MEM, MEM_ROT_ENC_MEM);
- + }
- +
- + err = ipu_disable_channel(cam->ipu, CSI_PRP_ENC_MEM, true);
- + if (cam->rotation >= IPU_ROTATE_90_RIGHT)
- + err |= ipu_disable_channel(cam->ipu, MEM_ROT_ENC_MEM, true);
- +
- + ipu_uninit_channel(cam->ipu, CSI_PRP_ENC_MEM);
- + if (cam->rotation >= IPU_ROTATE_90_RIGHT)
- + ipu_uninit_channel(cam->ipu, MEM_ROT_ENC_MEM);
- +
- + if (cam->dummy_frame.vaddress != 0) {
- + dma_free_coherent(0, cam->dummy_frame.buffer.length,
- + cam->dummy_frame.vaddress,
- + cam->dummy_frame.paddress);
- + cam->dummy_frame.vaddress = 0;
- + }
- +
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + mipi_csi2_info = mipi_csi2_get_info();
- +
- + if (mipi_csi2_info) {
- + if (mipi_csi2_get_status(mipi_csi2_info)) {
- + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
- + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
- +
- + if (cam->ipu == ipu_get_soc(ipu_id)
- + && cam->csi == csi_id)
- + mipi_csi2_pixelclk_disable(mipi_csi2_info);
- + }
- + }
- +#endif
- +
- + return err;
- +}
- +
- +/*!
- + * Enable csi
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int prp_enc_enable_csi(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +
- + return ipu_enable_csi(cam->ipu, cam->csi);
- +}
- +
- +/*!
- + * Disable csi
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int prp_enc_disable_csi(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +
- + /* free csi eof irq firstly.
- + * when disable csi, wait for idmac eof.
- + * it requests eof irq again */
- + if (cam->rotation < IPU_ROTATE_90_RIGHT)
- + ipu_free_irq(cam->ipu, IPU_IRQ_PRP_ENC_OUT_EOF, cam);
- +
- + return ipu_disable_csi(cam->ipu, cam->csi);
- +}
- +
- +/*!
- + * function to select PRP-ENC as the working path
- + *
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return int
- + */
- +int prp_enc_select(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + int err = 0;
- +
- + if (cam) {
- + cam->enc_update_eba = prp_enc_eba_update;
- + cam->enc_enable = prp_enc_enabling_tasks;
- + cam->enc_disable = prp_enc_disabling_tasks;
- + cam->enc_enable_csi = prp_enc_enable_csi;
- + cam->enc_disable_csi = prp_enc_disable_csi;
- + } else {
- + err = -EIO;
- + }
- +
- + return err;
- +}
- +EXPORT_SYMBOL(prp_enc_select);
- +
- +/*!
- + * function to de-select PRP-ENC as the working path
- + *
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return int
- + */
- +int prp_enc_deselect(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + int err = 0;
- +
- + if (cam) {
- + cam->enc_update_eba = NULL;
- + cam->enc_enable = NULL;
- + cam->enc_disable = NULL;
- + cam->enc_enable_csi = NULL;
- + cam->enc_disable_csi = NULL;
- + if (cam->rot_enc_bufs_vaddr[0]) {
- + dma_free_coherent(0, cam->rot_enc_buf_size[0],
- + cam->rot_enc_bufs_vaddr[0],
- + cam->rot_enc_bufs[0]);
- + cam->rot_enc_bufs_vaddr[0] = NULL;
- + cam->rot_enc_bufs[0] = 0;
- + }
- + if (cam->rot_enc_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->rot_enc_buf_size[1],
- + cam->rot_enc_bufs_vaddr[1],
- + cam->rot_enc_bufs[1]);
- + cam->rot_enc_bufs_vaddr[1] = NULL;
- + cam->rot_enc_bufs[1] = 0;
- + }
- + }
- +
- + return err;
- +}
- +EXPORT_SYMBOL(prp_enc_deselect);
- +
- +/*!
- + * Init the Encorder channels
- + *
- + * @return Error code indicating success or failure
- + */
- +__init int prp_enc_init(void)
- +{
- + return 0;
- +}
- +
- +/*!
- + * Deinit the Encorder channels
- + *
- + */
- +void __exit prp_enc_exit(void)
- +{
- +}
- +
- +module_init(prp_enc_init);
- +module_exit(prp_enc_exit);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("IPU PRP ENC Driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/ipu_prp_sw.h linux-3.14.35/drivers/media/platform/mxc/capture/ipu_prp_sw.h
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/ipu_prp_sw.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/ipu_prp_sw.h 2015-03-08 14:27:37.593684501 -0500
- @@ -0,0 +1,43 @@
- +/*
- + * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file ipu_prp_sw.h
- + *
- + * @brief This file contains the IPU PRP use case driver header.
- + *
- + * @ingroup IPU
- + */
- +
- +#ifndef _INCLUDE_IPU__PRP_SW_H_
- +#define _INCLUDE_IPU__PRP_SW_H_
- +
- +int csi_enc_select(void *private);
- +int csi_enc_deselect(void *private);
- +int prp_enc_select(void *private);
- +int prp_enc_deselect(void *private);
- +#ifdef CONFIG_MXC_IPU_PRP_VF_SDC
- +int prp_vf_sdc_select(void *private);
- +int prp_vf_sdc_deselect(void *private);
- +int prp_vf_sdc_select_bg(void *private);
- +int prp_vf_sdc_deselect_bg(void *private);
- +#else
- +int foreground_sdc_select(void *private);
- +int foreground_sdc_deselect(void *private);
- +int bg_overlay_sdc_select(void *private);
- +int bg_overlay_sdc_deselect(void *private);
- +#endif
- +int prp_still_select(void *private);
- +int prp_still_deselect(void *private);
- +
- +#endif
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c linux-3.14.35/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c 2015-03-08 14:27:37.593684501 -0500
- @@ -0,0 +1,521 @@
- +/*
- + * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file ipu_prp_vf_sdc_bg.c
- + *
- + * @brief IPU Use case for PRP-VF back-ground
- + *
- + * @ingroup IPU
- + */
- +#include <linux/dma-mapping.h>
- +#include <linux/fb.h>
- +#include <linux/ipu.h>
- +#include <linux/module.h>
- +#include <mach/mipi_csi2.h>
- +#include "mxc_v4l2_capture.h"
- +#include "ipu_prp_sw.h"
- +
- +static int buffer_num;
- +static int buffer_ready;
- +static struct ipu_soc *disp_ipu;
- +
- +static void get_disp_ipu(cam_data *cam)
- +{
- + if (cam->output > 2)
- + disp_ipu = ipu_get_soc(1); /* using DISP4 */
- + else
- + disp_ipu = ipu_get_soc(0);
- +}
- +
- +/*
- + * Function definitions
- + */
- +
- +/*!
- + * SDC V-Sync callback function.
- + *
- + * @param irq int irq line
- + * @param dev_id void * device id
- + *
- + * @return status IRQ_HANDLED for handled
- + */
- +static irqreturn_t prpvf_sdc_vsync_callback(int irq, void *dev_id)
- +{
- + cam_data *cam = dev_id;
- + if (buffer_ready > 0) {
- + ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM,
- + IPU_OUTPUT_BUFFER, 0);
- + buffer_ready--;
- + }
- +
- + return IRQ_HANDLED;
- +}
- +
- +/*!
- + * VF EOF callback function.
- + *
- + * @param irq int irq line
- + * @param dev_id void * device id
- + *
- + * @return status IRQ_HANDLED for handled
- + */
- +static irqreturn_t prpvf_vf_eof_callback(int irq, void *dev_id)
- +{
- + cam_data *cam = dev_id;
- + pr_debug("buffer_ready %d buffer_num %d\n", buffer_ready, buffer_num);
- +
- + ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM,
- + IPU_INPUT_BUFFER, buffer_num);
- + buffer_num = (buffer_num == 0) ? 1 : 0;
- + ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM,
- + IPU_OUTPUT_BUFFER, buffer_num);
- + buffer_ready++;
- + return IRQ_HANDLED;
- +}
- +
- +/*!
- + * prpvf_start - start the vf task
- + *
- + * @param private cam_data * mxc v4l2 main structure
- + *
- + */
- +static int prpvf_start(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + ipu_channel_params_t vf;
- + u32 format;
- + u32 offset;
- + u32 bpp, size = 3;
- + int err = 0;
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + void *mipi_csi2_info;
- + int ipu_id;
- + int csi_id;
- +#endif
- +
- + if (!cam) {
- + printk(KERN_ERR "private is NULL\n");
- + return -EIO;
- + }
- +
- + if (cam->overlay_active == true) {
- + pr_debug("already start.\n");
- + return 0;
- + }
- +
- + get_disp_ipu(cam);
- +
- + format = cam->v4l2_fb.fmt.pixelformat;
- + if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR24) {
- + bpp = 3, size = 3;
- + pr_info("BGR24\n");
- + } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_RGB565) {
- + bpp = 2, size = 2;
- + pr_info("RGB565\n");
- + } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR32) {
- + bpp = 4, size = 4;
- + pr_info("BGR32\n");
- + } else {
- + printk(KERN_ERR
- + "unsupported fix format from the framebuffer.\n");
- + return -EINVAL;
- + }
- +
- + offset = cam->v4l2_fb.fmt.bytesperline * cam->win.w.top +
- + size * cam->win.w.left;
- +
- + if (cam->v4l2_fb.base == 0)
- + printk(KERN_ERR "invalid frame buffer address.\n");
- + else
- + offset += (u32) cam->v4l2_fb.base;
- +
- + memset(&vf, 0, sizeof(ipu_channel_params_t));
- + ipu_csi_get_window_size(cam->ipu, &vf.csi_prp_vf_mem.in_width,
- + &vf.csi_prp_vf_mem.in_height, cam->csi);
- + vf.csi_prp_vf_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY;
- + vf.csi_prp_vf_mem.out_width = cam->win.w.width;
- + vf.csi_prp_vf_mem.out_height = cam->win.w.height;
- + vf.csi_prp_vf_mem.csi = cam->csi;
- + if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) {
- + vf.csi_prp_vf_mem.out_width = cam->win.w.height;
- + vf.csi_prp_vf_mem.out_height = cam->win.w.width;
- + }
- + vf.csi_prp_vf_mem.out_pixel_fmt = format;
- + size = cam->win.w.width * cam->win.w.height * size;
- +
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + mipi_csi2_info = mipi_csi2_get_info();
- +
- + if (mipi_csi2_info) {
- + if (mipi_csi2_get_status(mipi_csi2_info)) {
- + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
- + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
- +
- + if (cam->ipu == ipu_get_soc(ipu_id)
- + && cam->csi == csi_id) {
- + vf.csi_prp_vf_mem.mipi_en = true;
- + vf.csi_prp_vf_mem.mipi_vc =
- + mipi_csi2_get_virtual_channel(mipi_csi2_info);
- + vf.csi_prp_vf_mem.mipi_id =
- + mipi_csi2_get_datatype(mipi_csi2_info);
- +
- + mipi_csi2_pixelclk_enable(mipi_csi2_info);
- + } else {
- + vf.csi_prp_vf_mem.mipi_en = false;
- + vf.csi_prp_vf_mem.mipi_vc = 0;
- + vf.csi_prp_vf_mem.mipi_id = 0;
- + }
- + } else {
- + vf.csi_prp_vf_mem.mipi_en = false;
- + vf.csi_prp_vf_mem.mipi_vc = 0;
- + vf.csi_prp_vf_mem.mipi_id = 0;
- + }
- + }
- +#endif
- +
- + err = ipu_init_channel(cam->ipu, CSI_PRP_VF_MEM, &vf);
- + if (err != 0)
- + goto out_4;
- +
- + if (cam->vf_bufs_vaddr[0]) {
- + dma_free_coherent(0, cam->vf_bufs_size[0],
- + cam->vf_bufs_vaddr[0], cam->vf_bufs[0]);
- + }
- + if (cam->vf_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->vf_bufs_size[1],
- + cam->vf_bufs_vaddr[1], cam->vf_bufs[1]);
- + }
- + cam->vf_bufs_size[0] = PAGE_ALIGN(size);
- + cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0,
- + cam->vf_bufs_size[0],
- + &cam->vf_bufs[0],
- + GFP_DMA |
- + GFP_KERNEL);
- + if (cam->vf_bufs_vaddr[0] == NULL) {
- + printk(KERN_ERR "Error to allocate vf buffer\n");
- + err = -ENOMEM;
- + goto out_3;
- + }
- + cam->vf_bufs_size[1] = PAGE_ALIGN(size);
- + cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0,
- + cam->vf_bufs_size[1],
- + &cam->vf_bufs[1],
- + GFP_DMA |
- + GFP_KERNEL);
- + if (cam->vf_bufs_vaddr[1] == NULL) {
- + printk(KERN_ERR "Error to allocate vf buffer\n");
- + err = -ENOMEM;
- + goto out_3;
- + }
- +
- + err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_VF_MEM,
- + IPU_OUTPUT_BUFFER,
- + format, vf.csi_prp_vf_mem.out_width,
- + vf.csi_prp_vf_mem.out_height,
- + vf.csi_prp_vf_mem.out_width,
- + IPU_ROTATE_NONE,
- + cam->vf_bufs[0],
- + cam->vf_bufs[1],
- + 0, 0, 0);
- + if (err != 0) {
- + printk(KERN_ERR "Error initializing CSI_PRP_VF_MEM\n");
- + goto out_3;
- + }
- + err = ipu_init_channel(cam->ipu, MEM_ROT_VF_MEM, NULL);
- + if (err != 0) {
- + printk(KERN_ERR "Error MEM_ROT_VF_MEM channel\n");
- + goto out_3;
- + }
- +
- + err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
- + IPU_INPUT_BUFFER,
- + format, vf.csi_prp_vf_mem.out_width,
- + vf.csi_prp_vf_mem.out_height,
- + vf.csi_prp_vf_mem.out_width,
- + cam->vf_rotation,
- + cam->vf_bufs[0],
- + cam->vf_bufs[1],
- + 0, 0, 0);
- + if (err != 0) {
- + printk(KERN_ERR "Error MEM_ROT_VF_MEM input buffer\n");
- + goto out_2;
- + }
- +
- + if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) {
- + err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
- + IPU_OUTPUT_BUFFER,
- + format,
- + vf.csi_prp_vf_mem.out_height,
- + vf.csi_prp_vf_mem.out_width,
- + cam->overlay_fb->var.xres * bpp,
- + IPU_ROTATE_NONE,
- + offset, 0, 0, 0, 0);
- +
- + if (err != 0) {
- + printk(KERN_ERR "Error MEM_ROT_VF_MEM output buffer\n");
- + goto out_2;
- + }
- + } else {
- + err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
- + IPU_OUTPUT_BUFFER,
- + format,
- + vf.csi_prp_vf_mem.out_width,
- + vf.csi_prp_vf_mem.out_height,
- + cam->overlay_fb->var.xres * bpp,
- + IPU_ROTATE_NONE,
- + offset, 0, 0, 0, 0);
- + if (err != 0) {
- + printk(KERN_ERR "Error MEM_ROT_VF_MEM output buffer\n");
- + goto out_2;
- + }
- + }
- +
- + ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF);
- + err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF,
- + prpvf_vf_eof_callback,
- + 0, "Mxc Camera", cam);
- + if (err != 0) {
- + printk(KERN_ERR
- + "Error registering IPU_IRQ_PRP_VF_OUT_EOF irq.\n");
- + goto out_2;
- + }
- +
- + ipu_clear_irq(disp_ipu, IPU_IRQ_BG_SF_END);
- + err = ipu_request_irq(disp_ipu, IPU_IRQ_BG_SF_END,
- + prpvf_sdc_vsync_callback,
- + 0, "Mxc Camera", cam);
- + if (err != 0) {
- + printk(KERN_ERR "Error registering IPU_IRQ_BG_SF_END irq.\n");
- + goto out_1;
- + }
- +
- + ipu_enable_channel(cam->ipu, CSI_PRP_VF_MEM);
- + ipu_enable_channel(cam->ipu, MEM_ROT_VF_MEM);
- +
- + buffer_num = 0;
- + buffer_ready = 0;
- + ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, IPU_OUTPUT_BUFFER, 0);
- +
- + cam->overlay_active = true;
- + return err;
- +
- +out_1:
- + ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, NULL);
- +out_2:
- + ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM);
- +out_3:
- + ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM);
- +out_4:
- + if (cam->vf_bufs_vaddr[0]) {
- + dma_free_coherent(0, cam->vf_bufs_size[0],
- + cam->vf_bufs_vaddr[0], cam->vf_bufs[0]);
- + cam->vf_bufs_vaddr[0] = NULL;
- + cam->vf_bufs[0] = 0;
- + }
- + if (cam->vf_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->vf_bufs_size[1],
- + cam->vf_bufs_vaddr[1], cam->vf_bufs[1]);
- + cam->vf_bufs_vaddr[1] = NULL;
- + cam->vf_bufs[1] = 0;
- + }
- + if (cam->rot_vf_bufs_vaddr[0]) {
- + dma_free_coherent(0, cam->rot_vf_buf_size[0],
- + cam->rot_vf_bufs_vaddr[0],
- + cam->rot_vf_bufs[0]);
- + cam->rot_vf_bufs_vaddr[0] = NULL;
- + cam->rot_vf_bufs[0] = 0;
- + }
- + if (cam->rot_vf_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->rot_vf_buf_size[1],
- + cam->rot_vf_bufs_vaddr[1],
- + cam->rot_vf_bufs[1]);
- + cam->rot_vf_bufs_vaddr[1] = NULL;
- + cam->rot_vf_bufs[1] = 0;
- + }
- + return err;
- +}
- +
- +/*!
- + * prpvf_stop - stop the vf task
- + *
- + * @param private cam_data * mxc v4l2 main structure
- + *
- + */
- +static int prpvf_stop(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + void *mipi_csi2_info;
- + int ipu_id;
- + int csi_id;
- +#endif
- +
- + if (cam->overlay_active == false)
- + return 0;
- +
- + ipu_free_irq(disp_ipu, IPU_IRQ_BG_SF_END, cam);
- +
- + ipu_disable_channel(cam->ipu, CSI_PRP_VF_MEM, true);
- + ipu_disable_channel(cam->ipu, MEM_ROT_VF_MEM, true);
- + ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM);
- + ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM);
- +
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + mipi_csi2_info = mipi_csi2_get_info();
- +
- + if (mipi_csi2_info) {
- + if (mipi_csi2_get_status(mipi_csi2_info)) {
- + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
- + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
- +
- + if (cam->ipu == ipu_get_soc(ipu_id)
- + && cam->csi == csi_id)
- + mipi_csi2_pixelclk_disable(mipi_csi2_info);
- + }
- + }
- +#endif
- +
- + if (cam->vf_bufs_vaddr[0]) {
- + dma_free_coherent(0, cam->vf_bufs_size[0],
- + cam->vf_bufs_vaddr[0], cam->vf_bufs[0]);
- + cam->vf_bufs_vaddr[0] = NULL;
- + cam->vf_bufs[0] = 0;
- + }
- + if (cam->vf_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->vf_bufs_size[1],
- + cam->vf_bufs_vaddr[1], cam->vf_bufs[1]);
- + cam->vf_bufs_vaddr[1] = NULL;
- + cam->vf_bufs[1] = 0;
- + }
- + if (cam->rot_vf_bufs_vaddr[0]) {
- + dma_free_coherent(0, cam->rot_vf_buf_size[0],
- + cam->rot_vf_bufs_vaddr[0],
- + cam->rot_vf_bufs[0]);
- + cam->rot_vf_bufs_vaddr[0] = NULL;
- + cam->rot_vf_bufs[0] = 0;
- + }
- + if (cam->rot_vf_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->rot_vf_buf_size[1],
- + cam->rot_vf_bufs_vaddr[1],
- + cam->rot_vf_bufs[1]);
- + cam->rot_vf_bufs_vaddr[1] = NULL;
- + cam->rot_vf_bufs[1] = 0;
- + }
- +
- + buffer_num = 0;
- + buffer_ready = 0;
- + cam->overlay_active = false;
- + return 0;
- +}
- +
- +/*!
- + * Enable csi
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int prp_vf_enable_csi(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +
- + return ipu_enable_csi(cam->ipu, cam->csi);
- +}
- +
- +/*!
- + * Disable csi
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int prp_vf_disable_csi(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +
- + /* free csi eof irq firstly.
- + * when disable csi, wait for idmac eof.
- + * it requests eof irq again */
- + ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, cam);
- +
- + return ipu_disable_csi(cam->ipu, cam->csi);
- +}
- +
- +/*!
- + * function to select PRP-VF as the working path
- + *
- + * @param private cam_data * mxc v4l2 main structure
- + *
- + * @return status
- + */
- +int prp_vf_sdc_select_bg(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +
- + if (cam) {
- + cam->vf_start_sdc = prpvf_start;
- + cam->vf_stop_sdc = prpvf_stop;
- + cam->vf_enable_csi = prp_vf_enable_csi;
- + cam->vf_disable_csi = prp_vf_disable_csi;
- + cam->overlay_active = false;
- + }
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(prp_vf_sdc_select_bg);
- +
- +/*!
- + * function to de-select PRP-VF as the working path
- + *
- + * @param private cam_data * mxc v4l2 main structure
- + *
- + * @return status
- + */
- +int prp_vf_sdc_deselect_bg(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +
- + if (cam) {
- + cam->vf_start_sdc = NULL;
- + cam->vf_stop_sdc = NULL;
- + cam->vf_enable_csi = NULL;
- + cam->vf_disable_csi = NULL;
- + }
- + return 0;
- +}
- +EXPORT_SYMBOL(prp_vf_sdc_deselect_bg);
- +
- +/*!
- + * Init viewfinder task.
- + *
- + * @return Error code indicating success or failure
- + */
- +__init int prp_vf_sdc_init_bg(void)
- +{
- + return 0;
- +}
- +
- +/*!
- + * Deinit viewfinder task.
- + *
- + * @return Error code indicating success or failure
- + */
- +void __exit prp_vf_sdc_exit_bg(void)
- +{
- +}
- +
- +module_init(prp_vf_sdc_init_bg);
- +module_exit(prp_vf_sdc_exit_bg);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("IPU PRP VF SDC Backgroud Driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c linux-3.14.35/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c 2015-03-08 14:27:37.593684501 -0500
- @@ -0,0 +1,582 @@
- +/*
- + * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +/* * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file ipu_prp_vf_sdc.c
- + *
- + * @brief IPU Use case for PRP-VF
- + *
- + * @ingroup IPU
- + */
- +
- +#include <linux/dma-mapping.h>
- +#include <linux/console.h>
- +#include <linux/ipu.h>
- +#include <linux/module.h>
- +#include <linux/mxcfb.h>
- +#include <mach/hardware.h>
- +#include <mach/mipi_csi2.h>
- +#include "mxc_v4l2_capture.h"
- +#include "ipu_prp_sw.h"
- +
- +static int buffer_num;
- +static struct ipu_soc *disp_ipu;
- +
- +static void get_disp_ipu(cam_data *cam)
- +{
- + if (cam->output > 2)
- + disp_ipu = ipu_get_soc(1); /* using DISP4 */
- + else
- + disp_ipu = ipu_get_soc(0);
- +}
- +
- +static irqreturn_t prpvf_rot_eof_callback(int irq, void *dev_id)
- +{
- + cam_data *cam = dev_id;
- + pr_debug("buffer_num %d\n", buffer_num);
- +
- + if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) {
- + ipu_select_buffer(disp_ipu, MEM_FG_SYNC,
- + IPU_INPUT_BUFFER, buffer_num);
- + buffer_num = (buffer_num == 0) ? 1 : 0;
- + ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM,
- + IPU_OUTPUT_BUFFER, buffer_num);
- + } else {
- + ipu_select_buffer(disp_ipu, MEM_FG_SYNC,
- + IPU_INPUT_BUFFER, buffer_num);
- + buffer_num = (buffer_num == 0) ? 1 : 0;
- + ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM,
- + IPU_OUTPUT_BUFFER, buffer_num);
- + }
- + return IRQ_HANDLED;
- +}
- +/*
- + * Function definitions
- + */
- +
- +/*!
- + * prpvf_start - start the vf task
- + *
- + * @param private cam_data * mxc v4l2 main structure
- + *
- + */
- +static int prpvf_start(void *private)
- +{
- + struct fb_var_screeninfo fbvar;
- + struct fb_info *fbi = NULL;
- + cam_data *cam = (cam_data *) private;
- + ipu_channel_params_t vf;
- + u32 vf_out_format = 0;
- + u32 size = 2, temp = 0;
- + int err = 0, i = 0;
- + short *tmp, color;
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + void *mipi_csi2_info;
- + int ipu_id;
- + int csi_id;
- +#endif
- +
- + if (!cam) {
- + printk(KERN_ERR "private is NULL\n");
- + return -EIO;
- + }
- +
- + if (cam->overlay_active == true) {
- + pr_debug("already started.\n");
- + return 0;
- + }
- +
- + get_disp_ipu(cam);
- +
- + for (i = 0; i < num_registered_fb; i++) {
- + char *idstr = registered_fb[i]->fix.id;
- + if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) ||
- + ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) {
- + fbi = registered_fb[i];
- + break;
- + }
- + }
- +
- + if (fbi == NULL) {
- + printk(KERN_ERR "DISP FG fb not found\n");
- + return -EPERM;
- + }
- +
- + fbvar = fbi->var;
- +
- + /* Store the overlay frame buffer's original std */
- + cam->fb_origin_std = fbvar.nonstd;
- +
- + if (cam->devtype == IMX5_V4L2 || cam->devtype == IMX6_V4L2) {
- + /* Use DP to do CSC so that we can get better performance */
- + vf_out_format = IPU_PIX_FMT_UYVY;
- + fbvar.nonstd = vf_out_format;
- + color = 0x80;
- + } else {
- + vf_out_format = IPU_PIX_FMT_RGB565;
- + fbvar.nonstd = 0;
- + color = 0x0;
- + }
- +
- + fbvar.bits_per_pixel = 16;
- + fbvar.xres = fbvar.xres_virtual = cam->win.w.width;
- + fbvar.yres = cam->win.w.height;
- + fbvar.yres_virtual = cam->win.w.height * 2;
- + fbvar.yoffset = 0;
- + fbvar.accel_flags = FB_ACCEL_DOUBLE_FLAG;
- + fbvar.activate |= FB_ACTIVATE_FORCE;
- + fb_set_var(fbi, &fbvar);
- +
- + ipu_disp_set_window_pos(disp_ipu, MEM_FG_SYNC, cam->win.w.left,
- + cam->win.w.top);
- +
- + /* Fill black color for framebuffer */
- + tmp = (short *) fbi->screen_base;
- + for (i = 0; i < (fbi->fix.line_length * fbi->var.yres)/2;
- + i++, tmp++)
- + *tmp = color;
- +
- + console_lock();
- + fb_blank(fbi, FB_BLANK_UNBLANK);
- + console_unlock();
- +
- + /* correct display ch buffer address */
- + ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER,
- + 0, fbi->fix.smem_start +
- + (fbi->fix.line_length * fbvar.yres));
- + ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER,
- + 1, fbi->fix.smem_start);
- +
- + memset(&vf, 0, sizeof(ipu_channel_params_t));
- + ipu_csi_get_window_size(cam->ipu, &vf.csi_prp_vf_mem.in_width,
- + &vf.csi_prp_vf_mem.in_height, cam->csi);
- + vf.csi_prp_vf_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY;
- + vf.csi_prp_vf_mem.out_width = cam->win.w.width;
- + vf.csi_prp_vf_mem.out_height = cam->win.w.height;
- + vf.csi_prp_vf_mem.csi = cam->csi;
- + if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) {
- + vf.csi_prp_vf_mem.out_width = cam->win.w.height;
- + vf.csi_prp_vf_mem.out_height = cam->win.w.width;
- + }
- + vf.csi_prp_vf_mem.out_pixel_fmt = vf_out_format;
- + size = cam->win.w.width * cam->win.w.height * size;
- +
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + mipi_csi2_info = mipi_csi2_get_info();
- +
- + if (mipi_csi2_info) {
- + if (mipi_csi2_get_status(mipi_csi2_info)) {
- + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
- + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
- +
- + if (cam->ipu == ipu_get_soc(ipu_id)
- + && cam->csi == csi_id) {
- + vf.csi_prp_vf_mem.mipi_en = true;
- + vf.csi_prp_vf_mem.mipi_vc =
- + mipi_csi2_get_virtual_channel(mipi_csi2_info);
- + vf.csi_prp_vf_mem.mipi_id =
- + mipi_csi2_get_datatype(mipi_csi2_info);
- +
- + mipi_csi2_pixelclk_enable(mipi_csi2_info);
- + } else {
- + vf.csi_prp_vf_mem.mipi_en = false;
- + vf.csi_prp_vf_mem.mipi_vc = 0;
- + vf.csi_prp_vf_mem.mipi_id = 0;
- + }
- + } else {
- + vf.csi_prp_vf_mem.mipi_en = false;
- + vf.csi_prp_vf_mem.mipi_vc = 0;
- + vf.csi_prp_vf_mem.mipi_id = 0;
- + }
- + }
- +#endif
- +
- + err = ipu_init_channel(cam->ipu, CSI_PRP_VF_MEM, &vf);
- + if (err != 0)
- + goto out_5;
- +
- + if (cam->vf_bufs_vaddr[0]) {
- + dma_free_coherent(0, cam->vf_bufs_size[0],
- + cam->vf_bufs_vaddr[0],
- + (dma_addr_t) cam->vf_bufs[0]);
- + }
- + if (cam->vf_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->vf_bufs_size[1],
- + cam->vf_bufs_vaddr[1],
- + (dma_addr_t) cam->vf_bufs[1]);
- + }
- + cam->vf_bufs_size[0] = PAGE_ALIGN(size);
- + cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0,
- + cam->vf_bufs_size[0],
- + (dma_addr_t *) &
- + cam->vf_bufs[0],
- + GFP_DMA |
- + GFP_KERNEL);
- + if (cam->vf_bufs_vaddr[0] == NULL) {
- + printk(KERN_ERR "Error to allocate vf buffer\n");
- + err = -ENOMEM;
- + goto out_4;
- + }
- + cam->vf_bufs_size[1] = PAGE_ALIGN(size);
- + cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0,
- + cam->vf_bufs_size[1],
- + (dma_addr_t *) &
- + cam->vf_bufs[1],
- + GFP_DMA |
- + GFP_KERNEL);
- + if (cam->vf_bufs_vaddr[1] == NULL) {
- + printk(KERN_ERR "Error to allocate vf buffer\n");
- + err = -ENOMEM;
- + goto out_3;
- + }
- + pr_debug("vf_bufs %x %x\n", cam->vf_bufs[0], cam->vf_bufs[1]);
- +
- + if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) {
- + err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_VF_MEM,
- + IPU_OUTPUT_BUFFER,
- + vf_out_format,
- + vf.csi_prp_vf_mem.out_width,
- + vf.csi_prp_vf_mem.out_height,
- + vf.csi_prp_vf_mem.out_width,
- + IPU_ROTATE_NONE,
- + cam->vf_bufs[0], cam->vf_bufs[1],
- + 0, 0, 0);
- + if (err != 0)
- + goto out_3;
- +
- + err = ipu_init_channel(cam->ipu, MEM_ROT_VF_MEM, NULL);
- + if (err != 0) {
- + printk(KERN_ERR "Error MEM_ROT_VF_MEM channel\n");
- + goto out_3;
- + }
- +
- + err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
- + IPU_INPUT_BUFFER,
- + vf_out_format,
- + vf.csi_prp_vf_mem.out_width,
- + vf.csi_prp_vf_mem.out_height,
- + vf.csi_prp_vf_mem.out_width,
- + cam->vf_rotation,
- + cam->vf_bufs[0],
- + cam->vf_bufs[1],
- + 0, 0, 0);
- + if (err != 0) {
- + printk(KERN_ERR "Error MEM_ROT_VF_MEM input buffer\n");
- + goto out_2;
- + }
- +
- + if (cam->vf_rotation < IPU_ROTATE_90_RIGHT) {
- + temp = vf.csi_prp_vf_mem.out_width;
- + vf.csi_prp_vf_mem.out_width =
- + vf.csi_prp_vf_mem.out_height;
- + vf.csi_prp_vf_mem.out_height = temp;
- + }
- +
- + err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
- + IPU_OUTPUT_BUFFER,
- + vf_out_format,
- + vf.csi_prp_vf_mem.out_height,
- + vf.csi_prp_vf_mem.out_width,
- + vf.csi_prp_vf_mem.out_height,
- + IPU_ROTATE_NONE,
- + fbi->fix.smem_start +
- + (fbi->fix.line_length *
- + fbi->var.yres),
- + fbi->fix.smem_start, 0, 0, 0);
- +
- + if (err != 0) {
- + printk(KERN_ERR "Error MEM_ROT_VF_MEM output buffer\n");
- + goto out_2;
- + }
- +
- + ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF);
- + err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF,
- + prpvf_rot_eof_callback,
- + 0, "Mxc Camera", cam);
- + if (err < 0) {
- + printk(KERN_ERR "Error request irq:IPU_IRQ_PRP_VF_ROT_OUT_EOF\n");
- + goto out_2;
- + }
- +
- + err = ipu_link_channels(cam->ipu,
- + CSI_PRP_VF_MEM, MEM_ROT_VF_MEM);
- + if (err < 0) {
- + printk(KERN_ERR
- + "Error link CSI_PRP_VF_MEM-MEM_ROT_VF_MEM\n");
- + goto out_1;
- + }
- +
- + ipu_enable_channel(cam->ipu, CSI_PRP_VF_MEM);
- + ipu_enable_channel(cam->ipu, MEM_ROT_VF_MEM);
- +
- + ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM,
- + IPU_OUTPUT_BUFFER, 0);
- + ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM,
- + IPU_OUTPUT_BUFFER, 1);
- + ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM,
- + IPU_OUTPUT_BUFFER, 0);
- + } else {
- + err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_VF_MEM,
- + IPU_OUTPUT_BUFFER,
- + vf_out_format, cam->win.w.width,
- + cam->win.w.height,
- + cam->win.w.width,
- + cam->vf_rotation,
- + fbi->fix.smem_start +
- + (fbi->fix.line_length *
- + fbi->var.yres),
- + fbi->fix.smem_start, 0, 0, 0);
- + if (err != 0) {
- + printk(KERN_ERR "Error initializing CSI_PRP_VF_MEM\n");
- + goto out_4;
- + }
- + ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF);
- + err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF,
- + prpvf_rot_eof_callback,
- + 0, "Mxc Camera", cam);
- + if (err < 0) {
- + printk(KERN_ERR "Error request irq:IPU_IRQ_PRP_VF_OUT_EOF\n");
- + goto out_4;
- + }
- +
- + ipu_enable_channel(cam->ipu, CSI_PRP_VF_MEM);
- +
- + ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM,
- + IPU_OUTPUT_BUFFER, 0);
- + }
- +
- + cam->overlay_active = true;
- + return err;
- +
- +out_1:
- + ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, NULL);
- +out_2:
- + if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP)
- + ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM);
- +out_3:
- + if (cam->vf_bufs_vaddr[0]) {
- + dma_free_coherent(0, cam->vf_bufs_size[0],
- + cam->vf_bufs_vaddr[0],
- + (dma_addr_t) cam->vf_bufs[0]);
- + cam->vf_bufs_vaddr[0] = NULL;
- + cam->vf_bufs[0] = 0;
- + }
- + if (cam->vf_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->vf_bufs_size[1],
- + cam->vf_bufs_vaddr[1],
- + (dma_addr_t) cam->vf_bufs[1]);
- + cam->vf_bufs_vaddr[1] = NULL;
- + cam->vf_bufs[1] = 0;
- + }
- +out_4:
- + ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM);
- +out_5:
- + return err;
- +}
- +
- +/*!
- + * prpvf_stop - stop the vf task
- + *
- + * @param private cam_data * mxc v4l2 main structure
- + *
- + */
- +static int prpvf_stop(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + int err = 0, i = 0;
- + struct fb_info *fbi = NULL;
- + struct fb_var_screeninfo fbvar;
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + void *mipi_csi2_info;
- + int ipu_id;
- + int csi_id;
- +#endif
- +
- + if (cam->overlay_active == false)
- + return 0;
- +
- + for (i = 0; i < num_registered_fb; i++) {
- + char *idstr = registered_fb[i]->fix.id;
- + if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) ||
- + ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) {
- + fbi = registered_fb[i];
- + break;
- + }
- + }
- +
- + if (fbi == NULL) {
- + printk(KERN_ERR "DISP FG fb not found\n");
- + return -EPERM;
- + }
- +
- + if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) {
- + ipu_unlink_channels(cam->ipu, CSI_PRP_VF_MEM, MEM_ROT_VF_MEM);
- + ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF, cam);
- + }
- + buffer_num = 0;
- +
- + ipu_disable_channel(cam->ipu, CSI_PRP_VF_MEM, true);
- +
- + if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) {
- + ipu_disable_channel(cam->ipu, MEM_ROT_VF_MEM, true);
- + ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM);
- + }
- + ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM);
- +
- + console_lock();
- + fb_blank(fbi, FB_BLANK_POWERDOWN);
- + console_unlock();
- +
- + /* Set the overlay frame buffer std to what it is used to be */
- + fbvar = fbi->var;
- + fbvar.accel_flags = FB_ACCEL_TRIPLE_FLAG;
- + fbvar.nonstd = cam->fb_origin_std;
- + fbvar.activate |= FB_ACTIVATE_FORCE;
- + fb_set_var(fbi, &fbvar);
- +
- +#ifdef CONFIG_MXC_MIPI_CSI2
- + mipi_csi2_info = mipi_csi2_get_info();
- +
- + if (mipi_csi2_info) {
- + if (mipi_csi2_get_status(mipi_csi2_info)) {
- + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
- + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
- +
- + if (cam->ipu == ipu_get_soc(ipu_id)
- + && cam->csi == csi_id)
- + mipi_csi2_pixelclk_disable(mipi_csi2_info);
- + }
- + }
- +#endif
- +
- + if (cam->vf_bufs_vaddr[0]) {
- + dma_free_coherent(0, cam->vf_bufs_size[0],
- + cam->vf_bufs_vaddr[0],
- + (dma_addr_t) cam->vf_bufs[0]);
- + cam->vf_bufs_vaddr[0] = NULL;
- + cam->vf_bufs[0] = 0;
- + }
- + if (cam->vf_bufs_vaddr[1]) {
- + dma_free_coherent(0, cam->vf_bufs_size[1],
- + cam->vf_bufs_vaddr[1],
- + (dma_addr_t) cam->vf_bufs[1]);
- + cam->vf_bufs_vaddr[1] = NULL;
- + cam->vf_bufs[1] = 0;
- + }
- +
- + cam->overlay_active = false;
- + return err;
- +}
- +
- +/*!
- + * Enable csi
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int prp_vf_enable_csi(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +
- + return ipu_enable_csi(cam->ipu, cam->csi);
- +}
- +
- +/*!
- + * Disable csi
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int prp_vf_disable_csi(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +
- + /* free csi eof irq firstly.
- + * when disable csi, wait for idmac eof.
- + * it requests eof irq again */
- + if (cam->vf_rotation < IPU_ROTATE_VERT_FLIP)
- + ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, cam);
- +
- + return ipu_disable_csi(cam->ipu, cam->csi);
- +}
- +
- +/*!
- + * function to select PRP-VF as the working path
- + *
- + * @param private cam_data * mxc v4l2 main structure
- + *
- + * @return status
- + */
- +int prp_vf_sdc_select(void *private)
- +{
- + cam_data *cam;
- + int err = 0;
- + if (private) {
- + cam = (cam_data *) private;
- + cam->vf_start_sdc = prpvf_start;
- + cam->vf_stop_sdc = prpvf_stop;
- + cam->vf_enable_csi = prp_vf_enable_csi;
- + cam->vf_disable_csi = prp_vf_disable_csi;
- + cam->overlay_active = false;
- + } else
- + err = -EIO;
- +
- + return err;
- +}
- +EXPORT_SYMBOL(prp_vf_sdc_select);
- +
- +/*!
- + * function to de-select PRP-VF as the working path
- + *
- + * @param private cam_data * mxc v4l2 main structure
- + *
- + * @return int
- + */
- +int prp_vf_sdc_deselect(void *private)
- +{
- + cam_data *cam;
- +
- + if (private) {
- + cam = (cam_data *) private;
- + cam->vf_start_sdc = NULL;
- + cam->vf_stop_sdc = NULL;
- + cam->vf_enable_csi = NULL;
- + cam->vf_disable_csi = NULL;
- + }
- + return 0;
- +}
- +EXPORT_SYMBOL(prp_vf_sdc_deselect);
- +
- +/*!
- + * Init viewfinder task.
- + *
- + * @return Error code indicating success or failure
- + */
- +__init int prp_vf_sdc_init(void)
- +{
- + return 0;
- +}
- +
- +/*!
- + * Deinit viewfinder task.
- + *
- + * @return Error code indicating success or failure
- + */
- +void __exit prp_vf_sdc_exit(void)
- +{
- +}
- +
- +module_init(prp_vf_sdc_init);
- +module_exit(prp_vf_sdc_exit);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("IPU PRP VF SDC Driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/ipu_still.c linux-3.14.35/drivers/media/platform/mxc/capture/ipu_still.c
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/ipu_still.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/ipu_still.c 2015-03-08 14:27:37.597684501 -0500
- @@ -0,0 +1,268 @@
- +/*
- + * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file ipu_still.c
- + *
- + * @brief IPU Use case for still image capture
- + *
- + * @ingroup IPU
- + */
- +
- +#include <linux/module.h>
- +#include <linux/semaphore.h>
- +#include <linux/sched.h>
- +#include <linux/ipu.h>
- +#include "mxc_v4l2_capture.h"
- +#include "ipu_prp_sw.h"
- +
- +static int callback_eof_flag;
- +#ifndef CONFIG_MXC_IPU_V1
- +static int buffer_num;
- +#endif
- +
- +#ifdef CONFIG_MXC_IPU_V1
- +static int callback_flag;
- +/*
- + * Function definitions
- + */
- +/*!
- + * CSI EOF callback function.
- + *
- + * @param irq int irq line
- + * @param dev_id void * device id
- + *
- + * @return status IRQ_HANDLED for handled
- + */
- +static irqreturn_t prp_csi_eof_callback(int irq, void *dev_id)
- +{
- + cam_data *cam = devid;
- + ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
- + callback_flag%2 ? 1 : 0);
- + if (callback_flag == 0)
- + ipu_enable_channel(cam->ipu, CSI_MEM);
- +
- + callback_flag++;
- + return IRQ_HANDLED;
- +}
- +#endif
- +
- +/*!
- + * CSI callback function.
- + *
- + * @param irq int irq line
- + * @param dev_id void * device id
- + *
- + * @return status IRQ_HANDLED for handled
- + */
- +static irqreturn_t prp_still_callback(int irq, void *dev_id)
- +{
- + cam_data *cam = (cam_data *) dev_id;
- +
- + callback_eof_flag++;
- + if (callback_eof_flag < 5) {
- +#ifndef CONFIG_MXC_IPU_V1
- + buffer_num = (buffer_num == 0) ? 1 : 0;
- + ipu_select_buffer(cam->ipu, CSI_MEM,
- + IPU_OUTPUT_BUFFER, buffer_num);
- +#endif
- + } else {
- + cam->still_counter++;
- + wake_up_interruptible(&cam->still_queue);
- + }
- +
- + return IRQ_HANDLED;
- +}
- +
- +/*!
- + * start csi->mem task
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int prp_still_start(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + u32 pixel_fmt;
- + int err;
- + ipu_channel_params_t params;
- +
- + if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
- + pixel_fmt = IPU_PIX_FMT_YUV420P;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12)
- + pixel_fmt = IPU_PIX_FMT_NV12;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P)
- + pixel_fmt = IPU_PIX_FMT_YUV422P;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY)
- + pixel_fmt = IPU_PIX_FMT_UYVY;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
- + pixel_fmt = IPU_PIX_FMT_YUYV;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24)
- + pixel_fmt = IPU_PIX_FMT_BGR24;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24)
- + pixel_fmt = IPU_PIX_FMT_RGB24;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565)
- + pixel_fmt = IPU_PIX_FMT_RGB565;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32)
- + pixel_fmt = IPU_PIX_FMT_BGR32;
- + else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32)
- + pixel_fmt = IPU_PIX_FMT_RGB32;
- + else {
- + printk(KERN_ERR "format not supported\n");
- + return -EINVAL;
- + }
- +
- + memset(¶ms, 0, sizeof(params));
- + err = ipu_init_channel(cam->ipu, CSI_MEM, ¶ms);
- + if (err != 0)
- + return err;
- +
- + err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
- + pixel_fmt, cam->v2f.fmt.pix.width,
- + cam->v2f.fmt.pix.height,
- + cam->v2f.fmt.pix.width, IPU_ROTATE_NONE,
- + cam->still_buf[0], cam->still_buf[1], 0,
- + 0, 0);
- + if (err != 0)
- + return err;
- +
- +#ifdef CONFIG_MXC_IPU_V1
- + ipu_clear_irq(IPU_IRQ_SENSOR_OUT_EOF);
- + err = ipu_request_irq(IPU_IRQ_SENSOR_OUT_EOF, prp_still_callback,
- + 0, "Mxc Camera", cam);
- + if (err != 0) {
- + printk(KERN_ERR "Error registering irq.\n");
- + return err;
- + }
- + callback_flag = 0;
- + callback_eof_flag = 0;
- + ipu_clear_irq(IPU_IRQ_SENSOR_EOF);
- + err = ipu_request_irq(IPU_IRQ_SENSOR_EOF, prp_csi_eof_callback,
- + 0, "Mxc Camera", cam);
- + if (err != 0) {
- + printk(KERN_ERR "Error IPU_IRQ_SENSOR_EOF\n");
- + return err;
- + }
- +#else
- + callback_eof_flag = 0;
- + buffer_num = 0;
- +
- + ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF);
- + err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF,
- + prp_still_callback,
- + 0, "Mxc Camera", cam);
- + if (err != 0) {
- + printk(KERN_ERR "Error registering irq.\n");
- + return err;
- + }
- +
- + ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 0);
- + ipu_enable_channel(cam->ipu, CSI_MEM);
- + ipu_enable_csi(cam->ipu, cam->csi);
- +#endif
- +
- + return err;
- +}
- +
- +/*!
- + * stop csi->mem encoder task
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +static int prp_still_stop(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + int err = 0;
- +
- +#ifdef CONFIG_MXC_IPU_V1
- + ipu_free_irq(IPU_IRQ_SENSOR_EOF, NULL);
- + ipu_free_irq(IPU_IRQ_SENSOR_OUT_EOF, cam);
- +#else
- + ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam);
- +#endif
- +
- + ipu_disable_csi(cam->ipu, cam->csi);
- + ipu_disable_channel(cam->ipu, CSI_MEM, true);
- + ipu_uninit_channel(cam->ipu, CSI_MEM);
- +
- + return err;
- +}
- +
- +/*!
- + * function to select CSI_MEM as the working path
- + *
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +int prp_still_select(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- +
- + if (cam) {
- + cam->csi_start = prp_still_start;
- + cam->csi_stop = prp_still_stop;
- + }
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(prp_still_select);
- +
- +/*!
- + * function to de-select CSI_MEM as the working path
- + *
- + * @param private struct cam_data * mxc capture instance
- + *
- + * @return status
- + */
- +int prp_still_deselect(void *private)
- +{
- + cam_data *cam = (cam_data *) private;
- + int err = 0;
- +
- + err = prp_still_stop(cam);
- +
- + if (cam) {
- + cam->csi_start = NULL;
- + cam->csi_stop = NULL;
- + }
- +
- + return err;
- +}
- +EXPORT_SYMBOL(prp_still_deselect);
- +
- +/*!
- + * Init the Encorder channels
- + *
- + * @return Error code indicating success or failure
- + */
- +__init int prp_still_init(void)
- +{
- + return 0;
- +}
- +
- +/*!
- + * Deinit the Encorder channels
- + *
- + */
- +void __exit prp_still_exit(void)
- +{
- +}
- +
- +module_init(prp_still_init);
- +module_exit(prp_still_exit);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("IPU PRP STILL IMAGE Driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/Kconfig linux-3.14.35/drivers/media/platform/mxc/capture/Kconfig
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/Kconfig 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/Kconfig 2015-03-08 14:27:37.597684501 -0500
- @@ -0,0 +1,86 @@
- +if VIDEO_MXC_CAPTURE
- +
- +menu "MXC Camera/V4L2 PRP Features support"
- +config VIDEO_MXC_IPU_CAMERA
- + bool
- + depends on VIDEO_MXC_CAPTURE && MXC_IPU
- + default y
- +
- +config VIDEO_MXC_CSI_CAMERA
- + tristate "CSI camera support"
- + depends on VIDEO_MXC_CAPTURE && VIDEO_V4L2
- + ---help---
- + This is the video4linux2 capture driver based on CSI module.
- +
- +config MXC_CAMERA_OV5640
- + tristate "OmniVision ov5640 camera support"
- + depends on !VIDEO_MXC_EMMA_CAMERA && I2C
- + ---help---
- + If you plan to use the ov5640 Camera with your MXC system, say Y here.
- +
- +config MXC_CAMERA_OV5642
- + tristate "OmniVision ov5642 camera support"
- + depends on !VIDEO_MXC_EMMA_CAMERA && I2C
- + ---help---
- + If you plan to use the ov5642 Camera with your MXC system, say Y here.
- +
- +config MXC_CAMERA_OV5640_MIPI
- + tristate "OmniVision ov5640 camera support using mipi"
- + depends on !VIDEO_MXC_EMMA_CAMERA && I2C
- + ---help---
- + If you plan to use the ov5640 Camera with mipi interface in your MXC system, say Y here.
- +
- +config MXC_TVIN_ADV7180
- + tristate "Analog Device adv7180 TV Decoder Input support"
- + depends on !VIDEO_MXC_EMMA_CAMERA && I2C
- + ---help---
- + If you plan to use the adv7180 video decoder with your MXC system, say Y here.
- +
- +choice
- + prompt "Select Overlay Rounting"
- + default MXC_IPU_DEVICE_QUEUE_SDC
- + depends on VIDEO_MXC_IPU_CAMERA && FB_MXC_SYNC_PANEL
- +
- +config MXC_IPU_DEVICE_QUEUE_SDC
- + tristate "Queue ipu device for overlay library"
- + depends on VIDEO_MXC_IPU_CAMERA
- + ---help---
- + Use case CSI->MEM->IPU DEVICE->SDC:
- + Images from sensor will be frist recieved in memory,then
- + queue to ipu device for processing if needed, and displaying
- + it on synchronous display with SDC use case.
- +
- +config MXC_IPU_PRP_VF_SDC
- + bool "Pre-Processor VF SDC library"
- + depends on VIDEO_MXC_IPU_CAMERA
- + ---help---
- + Use case PRP_VF_SDC:
- + Preprocessing image from smart sensor for viewfinder and
- + displaying it on synchronous display with SDC use case.
- + If SDC BG is selected, Rotation will not be supported.
- + CSI -> IC (PRP VF) -> MEM
- + MEM -> IC (ROT) -> MEM
- + MEM -> SDC (FG/BG)
- +
- +endchoice
- +
- +config MXC_IPU_PRP_ENC
- + tristate "Pre-processor Encoder library"
- + depends on VIDEO_MXC_IPU_CAMERA
- + default y
- + ---help---
- + Use case PRP_ENC:
- + Preprocessing image from smart sensor for encoder.
- + CSI -> IC (PRP ENC) -> MEM
- +
- +config MXC_IPU_CSI_ENC
- + tristate "IPU CSI Encoder library"
- + depends on VIDEO_MXC_IPU_CAMERA
- + default y
- + ---help---
- + Use case IPU_CSI_ENC:
- + Get raw image with CSI from smart sensor for encoder.
- + CSI -> MEM
- +endmenu
- +
- +endif
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/Makefile linux-3.14.35/drivers/media/platform/mxc/capture/Makefile
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/Makefile 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/Makefile 2015-03-08 14:27:37.597684501 -0500
- @@ -0,0 +1,21 @@
- +obj-$(CONFIG_VIDEO_MXC_CSI_CAMERA) += fsl_csi.o csi_v4l2_capture.o
- +
- +ifeq ($(CONFIG_VIDEO_MXC_IPU_CAMERA),y)
- + obj-$(CONFIG_VIDEO_MXC_CAPTURE) += mxc_v4l2_capture.o
- + obj-$(CONFIG_MXC_IPU_PRP_VF_SDC) += ipu_prp_vf_sdc.o ipu_prp_vf_sdc_bg.o
- + obj-$(CONFIG_MXC_IPU_DEVICE_QUEUE_SDC) += ipu_fg_overlay_sdc.o ipu_bg_overlay_sdc.o
- + obj-$(CONFIG_MXC_IPU_PRP_ENC) += ipu_prp_enc.o ipu_still.o
- + obj-$(CONFIG_MXC_IPU_CSI_ENC) += ipu_csi_enc.o ipu_still.o
- +endif
- +
- +ov5640_camera-objs := ov5640.o
- +obj-$(CONFIG_MXC_CAMERA_OV5640) += ov5640_camera.o
- +
- +ov5642_camera-objs := ov5642.o
- +obj-$(CONFIG_MXC_CAMERA_OV5642) += ov5642_camera.o
- +
- +ov5640_camera_mipi-objs := ov5640_mipi.o
- +obj-$(CONFIG_MXC_CAMERA_OV5640_MIPI) += ov5640_camera_mipi.o
- +
- +adv7180_tvin-objs := adv7180.o
- +obj-$(CONFIG_MXC_TVIN_ADV7180) += adv7180_tvin.o
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c linux-3.14.35/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c 2015-03-08 14:27:37.597684501 -0500
- @@ -0,0 +1,3102 @@
- +/*
- + * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file drivers/media/video/mxc/capture/mxc_v4l2_capture.c
- + *
- + * @brief Mxc Video For Linux 2 driver
- + *
- + * @ingroup MXC_V4L2_CAPTURE
- + */
- +#include <linux/version.h>
- +#include <linux/module.h>
- +#include <linux/init.h>
- +#include <linux/platform_device.h>
- +#include <linux/fs.h>
- +#include <linux/slab.h>
- +#include <linux/ctype.h>
- +#include <linux/clk.h>
- +#include <linux/io.h>
- +#include <linux/semaphore.h>
- +#include <linux/pagemap.h>
- +#include <linux/vmalloc.h>
- +#include <linux/types.h>
- +#include <linux/fb.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/delay.h>
- +#include <linux/mxcfb.h>
- +#include <linux/of_device.h>
- +#include <media/v4l2-chip-ident.h>
- +#include <media/v4l2-ioctl.h>
- +#include <media/v4l2-int-device.h>
- +#include <linux/fsl_devices.h>
- +#include "mxc_v4l2_capture.h"
- +#include "ipu_prp_sw.h"
- +
- +#define init_MUTEX(sem) sema_init(sem, 1)
- +
- +static struct platform_device_id imx_v4l2_devtype[] = {
- + {
- + .name = "v4l2-capture-imx5",
- + .driver_data = IMX5_V4L2,
- + }, {
- + .name = "v4l2-capture-imx6",
- + .driver_data = IMX6_V4L2,
- + }, {
- + /* sentinel */
- + }
- +};
- +MODULE_DEVICE_TABLE(platform, imx_v4l2_devtype);
- +
- +static const struct of_device_id mxc_v4l2_dt_ids[] = {
- + {
- + .compatible = "fsl,imx6q-v4l2-capture",
- + .data = &imx_v4l2_devtype[IMX6_V4L2],
- + }, {
- + /* sentinel */
- + }
- +};
- +MODULE_DEVICE_TABLE(of, mxc_v4l2_dt_ids);
- +
- +static int video_nr = -1;
- +
- +/*! This data is used for the output to the display. */
- +#define MXC_V4L2_CAPTURE_NUM_OUTPUTS 6
- +#define MXC_V4L2_CAPTURE_NUM_INPUTS 2
- +static struct v4l2_output mxc_capture_outputs[MXC_V4L2_CAPTURE_NUM_OUTPUTS] = {
- + {
- + .index = 0,
- + .name = "DISP3 BG",
- + .type = V4L2_OUTPUT_TYPE_ANALOG,
- + .audioset = 0,
- + .modulator = 0,
- + .std = V4L2_STD_UNKNOWN,
- + },
- + {
- + .index = 1,
- + .name = "DISP3 BG - DI1",
- + .type = V4L2_OUTPUT_TYPE_ANALOG,
- + .audioset = 0,
- + .modulator = 0,
- + .std = V4L2_STD_UNKNOWN,
- + },
- + {
- + .index = 2,
- + .name = "DISP3 FG",
- + .type = V4L2_OUTPUT_TYPE_ANALOG,
- + .audioset = 0,
- + .modulator = 0,
- + .std = V4L2_STD_UNKNOWN,
- + },
- + {
- + .index = 3,
- + .name = "DISP4 BG",
- + .type = V4L2_OUTPUT_TYPE_ANALOG,
- + .audioset = 0,
- + .modulator = 0,
- + .std = V4L2_STD_UNKNOWN,
- + },
- + {
- + .index = 4,
- + .name = "DISP4 BG - DI1",
- + .type = V4L2_OUTPUT_TYPE_ANALOG,
- + .audioset = 0,
- + .modulator = 0,
- + .std = V4L2_STD_UNKNOWN,
- + },
- + {
- + .index = 5,
- + .name = "DISP4 FG",
- + .type = V4L2_OUTPUT_TYPE_ANALOG,
- + .audioset = 0,
- + .modulator = 0,
- + .std = V4L2_STD_UNKNOWN,
- + },
- +};
- +
- +static struct v4l2_input mxc_capture_inputs[MXC_V4L2_CAPTURE_NUM_INPUTS] = {
- + {
- + .index = 0,
- + .name = "CSI IC MEM",
- + .type = V4L2_INPUT_TYPE_CAMERA,
- + .audioset = 0,
- + .tuner = 0,
- + .std = V4L2_STD_UNKNOWN,
- + .status = 0,
- + },
- + {
- + .index = 1,
- + .name = "CSI MEM",
- + .type = V4L2_INPUT_TYPE_CAMERA,
- + .audioset = 0,
- + .tuner = 0,
- + .std = V4L2_STD_UNKNOWN,
- + .status = V4L2_IN_ST_NO_POWER,
- + },
- +};
- +
- +/*! List of TV input video formats supported. The video formats is corresponding
- + * to the v4l2_id in video_fmt_t.
- + * Currently, only PAL and NTSC is supported. Needs to be expanded in the
- + * future.
- + */
- +typedef enum {
- + TV_NTSC = 0, /*!< Locked on (M) NTSC video signal. */
- + TV_PAL, /*!< (B, G, H, I, N)PAL video signal. */
- + TV_NOT_LOCKED, /*!< Not locked on a signal. */
- +} video_fmt_idx;
- +
- +/*! Number of video standards supported (including 'not locked' signal). */
- +#define TV_STD_MAX (TV_NOT_LOCKED + 1)
- +
- +/*! Video format structure. */
- +typedef struct {
- + int v4l2_id; /*!< Video for linux ID. */
- + char name[16]; /*!< Name (e.g., "NTSC", "PAL", etc.) */
- + u16 raw_width; /*!< Raw width. */
- + u16 raw_height; /*!< Raw height. */
- + u16 active_width; /*!< Active width. */
- + u16 active_height; /*!< Active height. */
- + u16 active_top; /*!< Active top. */
- + u16 active_left; /*!< Active left. */
- +} video_fmt_t;
- +
- +/*!
- + * Description of video formats supported.
- + *
- + * PAL: raw=720x625, active=720x576.
- + * NTSC: raw=720x525, active=720x480.
- + */
- +static video_fmt_t video_fmts[] = {
- + { /*! NTSC */
- + .v4l2_id = V4L2_STD_NTSC,
- + .name = "NTSC",
- + .raw_width = 720, /* SENS_FRM_WIDTH */
- + .raw_height = 525, /* SENS_FRM_HEIGHT */
- + .active_width = 720, /* ACT_FRM_WIDTH */
- + .active_height = 480, /* ACT_FRM_HEIGHT */
- + .active_top = 13,
- + .active_left = 0,
- + },
- + { /*! (B, G, H, I, N) PAL */
- + .v4l2_id = V4L2_STD_PAL,
- + .name = "PAL",
- + .raw_width = 720,
- + .raw_height = 625,
- + .active_width = 720,
- + .active_height = 576,
- + .active_top = 0,
- + .active_left = 0,
- + },
- + { /*! Unlocked standard */
- + .v4l2_id = V4L2_STD_ALL,
- + .name = "Autodetect",
- + .raw_width = 720,
- + .raw_height = 625,
- + .active_width = 720,
- + .active_height = 576,
- + .active_top = 0,
- + .active_left = 0,
- + },
- +};
- +
- +/*!* Standard index of TV. */
- +static video_fmt_idx video_index = TV_NOT_LOCKED;
- +
- +static int mxc_v4l2_master_attach(struct v4l2_int_device *slave);
- +static void mxc_v4l2_master_detach(struct v4l2_int_device *slave);
- +static int start_preview(cam_data *cam);
- +static int stop_preview(cam_data *cam);
- +
- +/*! Information about this driver. */
- +static struct v4l2_int_master mxc_v4l2_master = {
- + .attach = mxc_v4l2_master_attach,
- + .detach = mxc_v4l2_master_detach,
- +};
- +
- +/***************************************************************************
- + * Functions for handling Frame buffers.
- + **************************************************************************/
- +
- +/*!
- + * Free frame buffers
- + *
- + * @param cam Structure cam_data *
- + *
- + * @return status 0 success.
- + */
- +static int mxc_free_frame_buf(cam_data *cam)
- +{
- + int i;
- +
- + pr_debug("MVC: In mxc_free_frame_buf\n");
- +
- + for (i = 0; i < FRAME_NUM; i++) {
- + if (cam->frame[i].vaddress != 0) {
- + dma_free_coherent(0, cam->frame[i].buffer.length,
- + cam->frame[i].vaddress,
- + cam->frame[i].paddress);
- + cam->frame[i].vaddress = 0;
- + }
- + }
- +
- + return 0;
- +}
- +
- +/*!
- + * Allocate frame buffers
- + *
- + * @param cam Structure cam_data*
- + * @param count int number of buffer need to allocated
- + *
- + * @return status -0 Successfully allocated a buffer, -ENOBUFS failed.
- + */
- +static int mxc_allocate_frame_buf(cam_data *cam, int count)
- +{
- + int i;
- +
- + pr_debug("In MVC:mxc_allocate_frame_buf - size=%d\n",
- + cam->v2f.fmt.pix.sizeimage);
- +
- + for (i = 0; i < count; i++) {
- + cam->frame[i].vaddress =
- + dma_alloc_coherent(0,
- + PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
- + &cam->frame[i].paddress,
- + GFP_DMA | GFP_KERNEL);
- + if (cam->frame[i].vaddress == 0) {
- + pr_err("ERROR: v4l2 capture: "
- + "mxc_allocate_frame_buf failed.\n");
- + mxc_free_frame_buf(cam);
- + return -ENOBUFS;
- + }
- + cam->frame[i].buffer.index = i;
- + cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED;
- + cam->frame[i].buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- + cam->frame[i].buffer.length =
- + PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
- + cam->frame[i].buffer.memory = V4L2_MEMORY_MMAP;
- + cam->frame[i].buffer.m.offset = cam->frame[i].paddress;
- + cam->frame[i].index = i;
- + }
- +
- + return 0;
- +}
- +
- +/*!
- + * Free frame buffers status
- + *
- + * @param cam Structure cam_data *
- + *
- + * @return none
- + */
- +static void mxc_free_frames(cam_data *cam)
- +{
- + int i;
- +
- + pr_debug("In MVC:mxc_free_frames\n");
- +
- + for (i = 0; i < FRAME_NUM; i++)
- + cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED;
- +
- + cam->enc_counter = 0;
- + INIT_LIST_HEAD(&cam->ready_q);
- + INIT_LIST_HEAD(&cam->working_q);
- + INIT_LIST_HEAD(&cam->done_q);
- +}
- +
- +/*!
- + * Return the buffer status
- + *
- + * @param cam Structure cam_data *
- + * @param buf Structure v4l2_buffer *
- + *
- + * @return status 0 success, EINVAL failed.
- + */
- +static int mxc_v4l2_buffer_status(cam_data *cam, struct v4l2_buffer *buf)
- +{
- + pr_debug("In MVC:mxc_v4l2_buffer_status\n");
- +
- + if (buf->index < 0 || buf->index >= FRAME_NUM) {
- + pr_err("ERROR: v4l2 capture: mxc_v4l2_buffer_status buffers "
- + "not allocated\n");
- + return -EINVAL;
- + }
- +
- + memcpy(buf, &(cam->frame[buf->index].buffer), sizeof(*buf));
- + return 0;
- +}
- +
- +static int mxc_v4l2_release_bufs(cam_data *cam)
- +{
- + pr_debug("In MVC:mxc_v4l2_release_bufs\n");
- + return 0;
- +}
- +
- +static int mxc_v4l2_prepare_bufs(cam_data *cam, struct v4l2_buffer *buf)
- +{
- + pr_debug("In MVC:mxc_v4l2_prepare_bufs\n");
- +
- + if (buf->index < 0 || buf->index >= FRAME_NUM || buf->length <
- + PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage)) {
- + pr_err("ERROR: v4l2 capture: mxc_v4l2_prepare_bufs buffers "
- + "not allocated,index=%d, length=%d\n", buf->index,
- + buf->length);
- + return -EINVAL;
- + }
- +
- + cam->frame[buf->index].buffer.index = buf->index;
- + cam->frame[buf->index].buffer.flags = V4L2_BUF_FLAG_MAPPED;
- + cam->frame[buf->index].buffer.length = buf->length;
- + cam->frame[buf->index].buffer.m.offset = cam->frame[buf->index].paddress
- + = buf->m.offset;
- + cam->frame[buf->index].buffer.type = buf->type;
- + cam->frame[buf->index].buffer.memory = V4L2_MEMORY_USERPTR;
- + cam->frame[buf->index].index = buf->index;
- +
- + return 0;
- +}
- +
- +/***************************************************************************
- + * Functions for handling the video stream.
- + **************************************************************************/
- +
- +/*!
- + * Indicates whether the palette is supported.
- + *
- + * @param palette V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_BGR24 or V4L2_PIX_FMT_BGR32
- + *
- + * @return 0 if failed
- + */
- +static inline int valid_mode(u32 palette)
- +{
- + return ((palette == V4L2_PIX_FMT_RGB565) ||
- + (palette == V4L2_PIX_FMT_BGR24) ||
- + (palette == V4L2_PIX_FMT_RGB24) ||
- + (palette == V4L2_PIX_FMT_BGR32) ||
- + (palette == V4L2_PIX_FMT_RGB32) ||
- + (palette == V4L2_PIX_FMT_YUV422P) ||
- + (palette == V4L2_PIX_FMT_UYVY) ||
- + (palette == V4L2_PIX_FMT_YUYV) ||
- + (palette == V4L2_PIX_FMT_YUV420) ||
- + (palette == V4L2_PIX_FMT_YVU420) ||
- + (palette == V4L2_PIX_FMT_NV12));
- +}
- +
- +/*!
- + * Start the encoder job
- + *
- + * @param cam structure cam_data *
- + *
- + * @return status 0 Success
- + */
- +static int mxc_streamon(cam_data *cam)
- +{
- + struct mxc_v4l_frame *frame;
- + unsigned long lock_flags;
- + int err = 0;
- +
- + pr_debug("In MVC:mxc_streamon\n");
- +
- + if (NULL == cam) {
- + pr_err("ERROR! cam parameter is NULL\n");
- + return -1;
- + }
- +
- + if (cam->capture_on) {
- + pr_err("ERROR: v4l2 capture: Capture stream has been turned "
- + " on\n");
- + return -1;
- + }
- +
- + if (list_empty(&cam->ready_q)) {
- + pr_err("ERROR: v4l2 capture: mxc_streamon buffer has not been "
- + "queued yet\n");
- + return -EINVAL;
- + }
- + if (cam->enc_update_eba &&
- + cam->ready_q.prev == cam->ready_q.next) {
- + pr_err("ERROR: v4l2 capture: mxc_streamon buffer need "
- + "ping pong at least two buffers\n");
- + return -EINVAL;
- + }
- +
- + cam->capture_pid = current->pid;
- +
- + if (cam->overlay_on == true)
- + stop_preview(cam);
- +
- + if (cam->enc_enable) {
- + err = cam->enc_enable(cam);
- + if (err != 0)
- + return err;
- + }
- +
- + spin_lock_irqsave(&cam->queue_int_lock, lock_flags);
- + cam->ping_pong_csi = 0;
- + cam->local_buf_num = 0;
- + if (cam->enc_update_eba) {
- + frame =
- + list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue);
- + list_del(cam->ready_q.next);
- + list_add_tail(&frame->queue, &cam->working_q);
- + frame->ipu_buf_num = cam->ping_pong_csi;
- + err = cam->enc_update_eba(cam->ipu, frame->buffer.m.offset,
- + &cam->ping_pong_csi);
- +
- + frame =
- + list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue);
- + list_del(cam->ready_q.next);
- + list_add_tail(&frame->queue, &cam->working_q);
- + frame->ipu_buf_num = cam->ping_pong_csi;
- + err |= cam->enc_update_eba(cam->ipu, frame->buffer.m.offset,
- + &cam->ping_pong_csi);
- + spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags);
- + } else {
- + spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags);
- + return -EINVAL;
- + }
- +
- + if (cam->overlay_on == true)
- + start_preview(cam);
- +
- + if (cam->enc_enable_csi) {
- + err = cam->enc_enable_csi(cam);
- + if (err != 0)
- + return err;
- + }
- +
- + cam->capture_on = true;
- +
- + return err;
- +}
- +
- +/*!
- + * Shut down the encoder job
- + *
- + * @param cam structure cam_data *
- + *
- + * @return status 0 Success
- + */
- +static int mxc_streamoff(cam_data *cam)
- +{
- + int err = 0;
- +
- + pr_debug("In MVC:mxc_streamoff\n");
- +
- + if (cam->capture_on == false)
- + return 0;
- +
- + /* For both CSI--MEM and CSI--IC--MEM
- + * 1. wait for idmac eof
- + * 2. disable csi first
- + * 3. disable idmac
- + * 4. disable smfc (CSI--MEM channel)
- + */
- + if (mxc_capture_inputs[cam->current_input].name != NULL) {
- + if (cam->enc_disable_csi) {
- + err = cam->enc_disable_csi(cam);
- + if (err != 0)
- + return err;
- + }
- + if (cam->enc_disable) {
- + err = cam->enc_disable(cam);
- + if (err != 0)
- + return err;
- + }
- + }
- +
- + mxc_free_frames(cam);
- + mxc_capture_inputs[cam->current_input].status |= V4L2_IN_ST_NO_POWER;
- + cam->capture_on = false;
- + return err;
- +}
- +
- +/*!
- + * Valid and adjust the overlay window size, position
- + *
- + * @param cam structure cam_data *
- + * @param win struct v4l2_window *
- + *
- + * @return 0
- + */
- +static int verify_preview(cam_data *cam, struct v4l2_window *win)
- +{
- + int i = 0, width_bound = 0, height_bound = 0;
- + int *width, *height;
- + unsigned int ipu_ch = CHAN_NONE;
- + struct fb_info *bg_fbi = NULL, *fbi = NULL;
- + bool foregound_fb = false;
- + mm_segment_t old_fs;
- +
- + pr_debug("In MVC: verify_preview\n");
- +
- + do {
- + fbi = (struct fb_info *)registered_fb[i];
- + if (fbi == NULL) {
- + pr_err("ERROR: verify_preview frame buffer NULL.\n");
- + return -1;
- + }
- +
- + /* Which DI supports 2 layers? */
- + if (((strncmp(fbi->fix.id, "DISP3 BG", 8) == 0) &&
- + (cam->output < 3)) ||
- + ((strncmp(fbi->fix.id, "DISP4 BG", 8) == 0) &&
- + (cam->output >= 3))) {
- + if (fbi->fbops->fb_ioctl) {
- + old_fs = get_fs();
- + set_fs(KERNEL_DS);
- + fbi->fbops->fb_ioctl(fbi, MXCFB_GET_FB_IPU_CHAN,
- + (unsigned long)&ipu_ch);
- + set_fs(old_fs);
- + }
- + if (ipu_ch == MEM_BG_SYNC) {
- + bg_fbi = fbi;
- + pr_debug("Found background frame buffer.\n");
- + }
- + }
- +
- + /* Found the frame buffer to preview on. */
- + if (strcmp(fbi->fix.id,
- + mxc_capture_outputs[cam->output].name) == 0) {
- + if (((strcmp(fbi->fix.id, "DISP3 FG") == 0) &&
- + (cam->output < 3)) ||
- + ((strcmp(fbi->fix.id, "DISP4 FG") == 0) &&
- + (cam->output >= 3)))
- + foregound_fb = true;
- +
- + cam->overlay_fb = fbi;
- + break;
- + }
- + } while (++i < FB_MAX);
- +
- + if (foregound_fb) {
- + width_bound = bg_fbi->var.xres;
- + height_bound = bg_fbi->var.yres;
- +
- + if (win->w.width + win->w.left > bg_fbi->var.xres ||
- + win->w.height + win->w.top > bg_fbi->var.yres) {
- + pr_err("ERROR: FG window position exceeds.\n");
- + return -1;
- + }
- + } else {
- + /* 4 bytes alignment for BG */
- + width_bound = cam->overlay_fb->var.xres;
- + height_bound = cam->overlay_fb->var.yres;
- +
- + if (cam->overlay_fb->var.bits_per_pixel == 24)
- + win->w.left -= win->w.left % 4;
- + else if (cam->overlay_fb->var.bits_per_pixel == 16)
- + win->w.left -= win->w.left % 2;
- +
- + if (win->w.width + win->w.left > cam->overlay_fb->var.xres)
- + win->w.width = cam->overlay_fb->var.xres - win->w.left;
- + if (win->w.height + win->w.top > cam->overlay_fb->var.yres)
- + win->w.height = cam->overlay_fb->var.yres - win->w.top;
- + }
- +
- + /* stride line limitation */
- + win->w.height -= win->w.height % 8;
- + win->w.width -= win->w.width % 8;
- +
- + if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
- + height = &win->w.width;
- + width = &win->w.height;
- + } else {
- + width = &win->w.width;
- + height = &win->w.height;
- + }
- +
- + if (*width == 0 || *height == 0) {
- + pr_err("ERROR: v4l2 capture: width or height"
- + " too small.\n");
- + return -EINVAL;
- + }
- +
- + if ((cam->crop_bounds.width / *width > 8) ||
- + ((cam->crop_bounds.width / *width == 8) &&
- + (cam->crop_bounds.width % *width))) {
- + *width = cam->crop_bounds.width / 8;
- + if (*width % 8)
- + *width += 8 - *width % 8;
- + if (*width + win->w.left > width_bound) {
- + pr_err("ERROR: v4l2 capture: width exceeds "
- + "resize limit.\n");
- + return -1;
- + }
- + pr_err("ERROR: v4l2 capture: width exceeds limit. "
- + "Resize to %d.\n",
- + *width);
- + }
- +
- + if ((cam->crop_bounds.height / *height > 8) ||
- + ((cam->crop_bounds.height / *height == 8) &&
- + (cam->crop_bounds.height % *height))) {
- + *height = cam->crop_bounds.height / 8;
- + if (*height % 8)
- + *height += 8 - *height % 8;
- + if (*height + win->w.top > height_bound) {
- + pr_err("ERROR: v4l2 capture: height exceeds "
- + "resize limit.\n");
- + return -1;
- + }
- + pr_err("ERROR: v4l2 capture: height exceeds limit "
- + "resize to %d.\n",
- + *height);
- + }
- +
- + return 0;
- +}
- +
- +/*!
- + * start the viewfinder job
- + *
- + * @param cam structure cam_data *
- + *
- + * @return status 0 Success
- + */
- +static int start_preview(cam_data *cam)
- +{
- + int err = 0;
- +
- + pr_debug("MVC: start_preview\n");
- +
- + if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_OVERLAY)
- + #ifdef CONFIG_MXC_IPU_PRP_VF_SDC
- + err = prp_vf_sdc_select(cam);
- + #else
- + err = foreground_sdc_select(cam);
- + #endif
- + else if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_PRIMARY)
- + #ifdef CONFIG_MXC_IPU_PRP_VF_SDC
- + err = prp_vf_sdc_select_bg(cam);
- + #else
- + err = bg_overlay_sdc_select(cam);
- + #endif
- + if (err != 0)
- + return err;
- +
- + if (cam->vf_start_sdc) {
- + err = cam->vf_start_sdc(cam);
- + if (err != 0)
- + return err;
- + }
- +
- + if (cam->vf_enable_csi)
- + err = cam->vf_enable_csi(cam);
- +
- + pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
- + __func__,
- + cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
- + pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
- + __func__,
- + cam->crop_bounds.width, cam->crop_bounds.height);
- + pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
- + __func__,
- + cam->crop_defrect.width, cam->crop_defrect.height);
- + pr_debug("End of %s: crop_current widthxheight %d x %d\n",
- + __func__,
- + cam->crop_current.width, cam->crop_current.height);
- +
- + return err;
- +}
- +
- +/*!
- + * shut down the viewfinder job
- + *
- + * @param cam structure cam_data *
- + *
- + * @return status 0 Success
- + */
- +static int stop_preview(cam_data *cam)
- +{
- + int err = 0;
- +
- + if (cam->vf_disable_csi) {
- + err = cam->vf_disable_csi(cam);
- + if (err != 0)
- + return err;
- + }
- +
- + if (cam->vf_stop_sdc) {
- + err = cam->vf_stop_sdc(cam);
- + if (err != 0)
- + return err;
- + }
- +
- + if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_OVERLAY)
- + #ifdef CONFIG_MXC_IPU_PRP_VF_SDC
- + err = prp_vf_sdc_deselect(cam);
- + #else
- + err = foreground_sdc_deselect(cam);
- + #endif
- + else if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_PRIMARY)
- + #ifdef CONFIG_MXC_IPU_PRP_VF_SDC
- + err = prp_vf_sdc_deselect_bg(cam);
- + #else
- + err = bg_overlay_sdc_deselect(cam);
- + #endif
- +
- + return err;
- +}
- +
- +/***************************************************************************
- + * VIDIOC Functions.
- + **************************************************************************/
- +
- +/*!
- + * V4L2 - mxc_v4l2_g_fmt function
- + *
- + * @param cam structure cam_data *
- + *
- + * @param f structure v4l2_format *
- + *
- + * @return status 0 success, EINVAL failed
- + */
- +static int mxc_v4l2_g_fmt(cam_data *cam, struct v4l2_format *f)
- +{
- + int retval = 0;
- +
- + pr_debug("In MVC: mxc_v4l2_g_fmt type=%d\n", f->type);
- +
- + switch (f->type) {
- + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- + pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
- + f->fmt.pix = cam->v2f.fmt.pix;
- + break;
- + case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- + pr_debug(" type is V4L2_BUF_TYPE_VIDEO_OVERLAY\n");
- + f->fmt.win = cam->win;
- + break;
- + default:
- + pr_debug(" type is invalid\n");
- + retval = -EINVAL;
- + }
- +
- + pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
- + __func__,
- + cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
- + pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
- + __func__,
- + cam->crop_bounds.width, cam->crop_bounds.height);
- + pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
- + __func__,
- + cam->crop_defrect.width, cam->crop_defrect.height);
- + pr_debug("End of %s: crop_current widthxheight %d x %d\n",
- + __func__,
- + cam->crop_current.width, cam->crop_current.height);
- +
- + return retval;
- +}
- +
- +/*!
- + * V4L2 - mxc_v4l2_s_fmt function
- + *
- + * @param cam structure cam_data *
- + *
- + * @param f structure v4l2_format *
- + *
- + * @return status 0 success, EINVAL failed
- + */
- +static int mxc_v4l2_s_fmt(cam_data *cam, struct v4l2_format *f)
- +{
- + int retval = 0;
- + int size = 0;
- + int bytesperline = 0;
- + int *width, *height;
- +
- + pr_debug("In MVC: mxc_v4l2_s_fmt\n");
- +
- + switch (f->type) {
- + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- + pr_debug(" type=V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
- + if (!valid_mode(f->fmt.pix.pixelformat)) {
- + pr_err("ERROR: v4l2 capture: mxc_v4l2_s_fmt: format "
- + "not supported\n");
- + return -EINVAL;
- + }
- +
- + /*
- + * Force the capture window resolution to be crop bounds
- + * for CSI MEM input mode.
- + */
- + if (strcmp(mxc_capture_inputs[cam->current_input].name,
- + "CSI MEM") == 0) {
- + f->fmt.pix.width = cam->crop_current.width;
- + f->fmt.pix.height = cam->crop_current.height;
- + }
- +
- + if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
- + height = &f->fmt.pix.width;
- + width = &f->fmt.pix.height;
- + } else {
- + width = &f->fmt.pix.width;
- + height = &f->fmt.pix.height;
- + }
- +
- + /* stride line limitation */
- + *width -= *width % 8;
- + *height -= *height % 8;
- +
- + if (*width == 0 || *height == 0) {
- + pr_err("ERROR: v4l2 capture: width or height"
- + " too small.\n");
- + return -EINVAL;
- + }
- +
- + if ((cam->crop_current.width / *width > 8) ||
- + ((cam->crop_current.width / *width == 8) &&
- + (cam->crop_current.width % *width))) {
- + *width = cam->crop_current.width / 8;
- + if (*width % 8)
- + *width += 8 - *width % 8;
- + pr_err("ERROR: v4l2 capture: width exceeds limit "
- + "resize to %d.\n",
- + *width);
- + }
- +
- + if ((cam->crop_current.height / *height > 8) ||
- + ((cam->crop_current.height / *height == 8) &&
- + (cam->crop_current.height % *height))) {
- + *height = cam->crop_current.height / 8;
- + if (*height % 8)
- + *height += 8 - *height % 8;
- + pr_err("ERROR: v4l2 capture: height exceeds limit "
- + "resize to %d.\n",
- + *height);
- + }
- +
- + switch (f->fmt.pix.pixelformat) {
- + case V4L2_PIX_FMT_RGB565:
- + size = f->fmt.pix.width * f->fmt.pix.height * 2;
- + bytesperline = f->fmt.pix.width * 2;
- + break;
- + case V4L2_PIX_FMT_BGR24:
- + size = f->fmt.pix.width * f->fmt.pix.height * 3;
- + bytesperline = f->fmt.pix.width * 3;
- + break;
- + case V4L2_PIX_FMT_RGB24:
- + size = f->fmt.pix.width * f->fmt.pix.height * 3;
- + bytesperline = f->fmt.pix.width * 3;
- + break;
- + case V4L2_PIX_FMT_BGR32:
- + size = f->fmt.pix.width * f->fmt.pix.height * 4;
- + bytesperline = f->fmt.pix.width * 4;
- + break;
- + case V4L2_PIX_FMT_RGB32:
- + size = f->fmt.pix.width * f->fmt.pix.height * 4;
- + bytesperline = f->fmt.pix.width * 4;
- + break;
- + case V4L2_PIX_FMT_YUV422P:
- + size = f->fmt.pix.width * f->fmt.pix.height * 2;
- + bytesperline = f->fmt.pix.width;
- + break;
- + case V4L2_PIX_FMT_UYVY:
- + case V4L2_PIX_FMT_YUYV:
- + size = f->fmt.pix.width * f->fmt.pix.height * 2;
- + bytesperline = f->fmt.pix.width * 2;
- + break;
- + case V4L2_PIX_FMT_YUV420:
- + case V4L2_PIX_FMT_YVU420:
- + size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2;
- + bytesperline = f->fmt.pix.width;
- + break;
- + case V4L2_PIX_FMT_NV12:
- + size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2;
- + bytesperline = f->fmt.pix.width;
- + break;
- + default:
- + break;
- + }
- +
- + if (f->fmt.pix.bytesperline < bytesperline)
- + f->fmt.pix.bytesperline = bytesperline;
- + else
- + bytesperline = f->fmt.pix.bytesperline;
- +
- + if (f->fmt.pix.sizeimage < size)
- + f->fmt.pix.sizeimage = size;
- + else
- + size = f->fmt.pix.sizeimage;
- +
- + cam->v2f.fmt.pix = f->fmt.pix;
- +
- + if (cam->v2f.fmt.pix.priv != 0) {
- + if (copy_from_user(&cam->offset,
- + (void *)cam->v2f.fmt.pix.priv,
- + sizeof(cam->offset))) {
- + retval = -EFAULT;
- + break;
- + }
- + }
- + break;
- + case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- + pr_debug(" type=V4L2_BUF_TYPE_VIDEO_OVERLAY\n");
- + retval = verify_preview(cam, &f->fmt.win);
- + cam->win = f->fmt.win;
- + break;
- + default:
- + retval = -EINVAL;
- + }
- +
- + pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
- + __func__,
- + cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
- + pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
- + __func__,
- + cam->crop_bounds.width, cam->crop_bounds.height);
- + pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
- + __func__,
- + cam->crop_defrect.width, cam->crop_defrect.height);
- + pr_debug("End of %s: crop_current widthxheight %d x %d\n",
- + __func__,
- + cam->crop_current.width, cam->crop_current.height);
- +
- + return retval;
- +}
- +
- +/*!
- + * get control param
- + *
- + * @param cam structure cam_data *
- + *
- + * @param c structure v4l2_control *
- + *
- + * @return status 0 success, EINVAL failed
- + */
- +static int mxc_v4l2_g_ctrl(cam_data *cam, struct v4l2_control *c)
- +{
- + int status = 0;
- +
- + pr_debug("In MVC:mxc_v4l2_g_ctrl\n");
- +
- + /* probably don't need to store the values that can be retrieved,
- + * locally, but they are for now. */
- + switch (c->id) {
- + case V4L2_CID_HFLIP:
- + /* This is handled in the ipu. */
- + if (cam->rotation == IPU_ROTATE_HORIZ_FLIP)
- + c->value = 1;
- + break;
- + case V4L2_CID_VFLIP:
- + /* This is handled in the ipu. */
- + if (cam->rotation == IPU_ROTATE_VERT_FLIP)
- + c->value = 1;
- + break;
- + case V4L2_CID_MXC_ROT:
- + /* This is handled in the ipu. */
- + c->value = cam->rotation;
- + break;
- + case V4L2_CID_BRIGHTNESS:
- + if (cam->sensor) {
- + c->value = cam->bright;
- + status = vidioc_int_g_ctrl(cam->sensor, c);
- + cam->bright = c->value;
- + } else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + status = -ENODEV;
- + }
- + break;
- + case V4L2_CID_HUE:
- + if (cam->sensor) {
- + c->value = cam->hue;
- + status = vidioc_int_g_ctrl(cam->sensor, c);
- + cam->hue = c->value;
- + } else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + status = -ENODEV;
- + }
- + break;
- + case V4L2_CID_CONTRAST:
- + if (cam->sensor) {
- + c->value = cam->contrast;
- + status = vidioc_int_g_ctrl(cam->sensor, c);
- + cam->contrast = c->value;
- + } else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + status = -ENODEV;
- + }
- + break;
- + case V4L2_CID_SATURATION:
- + if (cam->sensor) {
- + c->value = cam->saturation;
- + status = vidioc_int_g_ctrl(cam->sensor, c);
- + cam->saturation = c->value;
- + } else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + status = -ENODEV;
- + }
- + break;
- + case V4L2_CID_RED_BALANCE:
- + if (cam->sensor) {
- + c->value = cam->red;
- + status = vidioc_int_g_ctrl(cam->sensor, c);
- + cam->red = c->value;
- + } else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + status = -ENODEV;
- + }
- + break;
- + case V4L2_CID_BLUE_BALANCE:
- + if (cam->sensor) {
- + c->value = cam->blue;
- + status = vidioc_int_g_ctrl(cam->sensor, c);
- + cam->blue = c->value;
- + } else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + status = -ENODEV;
- + }
- + break;
- + case V4L2_CID_BLACK_LEVEL:
- + if (cam->sensor) {
- + c->value = cam->ae_mode;
- + status = vidioc_int_g_ctrl(cam->sensor, c);
- + cam->ae_mode = c->value;
- + } else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + status = -ENODEV;
- + }
- + break;
- + default:
- + pr_err("ERROR: v4l2 capture: unsupported ioctrl!\n");
- + }
- +
- + return status;
- +}
- +
- +/*!
- + * V4L2 - set_control function
- + * V4L2_CID_PRIVATE_BASE is the extention for IPU preprocessing.
- + * 0 for normal operation
- + * 1 for vertical flip
- + * 2 for horizontal flip
- + * 3 for horizontal and vertical flip
- + * 4 for 90 degree rotation
- + * @param cam structure cam_data *
- + *
- + * @param c structure v4l2_control *
- + *
- + * @return status 0 success, EINVAL failed
- + */
- +static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c)
- +{
- + int i, ret = 0;
- + int tmp_rotation = IPU_ROTATE_NONE;
- + struct sensor_data *sensor_data;
- +
- + pr_debug("In MVC:mxc_v4l2_s_ctrl\n");
- +
- + switch (c->id) {
- + case V4L2_CID_HFLIP:
- + /* This is done by the IPU */
- + if (c->value == 1) {
- + if ((cam->rotation != IPU_ROTATE_VERT_FLIP) &&
- + (cam->rotation != IPU_ROTATE_180))
- + cam->rotation = IPU_ROTATE_HORIZ_FLIP;
- + else
- + cam->rotation = IPU_ROTATE_180;
- + } else {
- + if (cam->rotation == IPU_ROTATE_HORIZ_FLIP)
- + cam->rotation = IPU_ROTATE_NONE;
- + if (cam->rotation == IPU_ROTATE_180)
- + cam->rotation = IPU_ROTATE_VERT_FLIP;
- + }
- + break;
- + case V4L2_CID_VFLIP:
- + /* This is done by the IPU */
- + if (c->value == 1) {
- + if ((cam->rotation != IPU_ROTATE_HORIZ_FLIP) &&
- + (cam->rotation != IPU_ROTATE_180))
- + cam->rotation = IPU_ROTATE_VERT_FLIP;
- + else
- + cam->rotation = IPU_ROTATE_180;
- + } else {
- + if (cam->rotation == IPU_ROTATE_VERT_FLIP)
- + cam->rotation = IPU_ROTATE_NONE;
- + if (cam->rotation == IPU_ROTATE_180)
- + cam->rotation = IPU_ROTATE_HORIZ_FLIP;
- + }
- + break;
- + case V4L2_CID_MXC_ROT:
- + case V4L2_CID_MXC_VF_ROT:
- + /* This is done by the IPU */
- + switch (c->value) {
- + case V4L2_MXC_ROTATE_NONE:
- + tmp_rotation = IPU_ROTATE_NONE;
- + break;
- + case V4L2_MXC_ROTATE_VERT_FLIP:
- + tmp_rotation = IPU_ROTATE_VERT_FLIP;
- + break;
- + case V4L2_MXC_ROTATE_HORIZ_FLIP:
- + tmp_rotation = IPU_ROTATE_HORIZ_FLIP;
- + break;
- + case V4L2_MXC_ROTATE_180:
- + tmp_rotation = IPU_ROTATE_180;
- + break;
- + case V4L2_MXC_ROTATE_90_RIGHT:
- + tmp_rotation = IPU_ROTATE_90_RIGHT;
- + break;
- + case V4L2_MXC_ROTATE_90_RIGHT_VFLIP:
- + tmp_rotation = IPU_ROTATE_90_RIGHT_VFLIP;
- + break;
- + case V4L2_MXC_ROTATE_90_RIGHT_HFLIP:
- + tmp_rotation = IPU_ROTATE_90_RIGHT_HFLIP;
- + break;
- + case V4L2_MXC_ROTATE_90_LEFT:
- + tmp_rotation = IPU_ROTATE_90_LEFT;
- + break;
- + default:
- + ret = -EINVAL;
- + }
- + #ifdef CONFIG_MXC_IPU_PRP_VF_SDC
- + if (c->id == V4L2_CID_MXC_VF_ROT)
- + cam->vf_rotation = tmp_rotation;
- + else
- + cam->rotation = tmp_rotation;
- + #else
- + cam->rotation = tmp_rotation;
- + #endif
- +
- + break;
- + case V4L2_CID_HUE:
- + if (cam->sensor) {
- + cam->hue = c->value;
- + ret = vidioc_int_s_ctrl(cam->sensor, c);
- + } else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + ret = -ENODEV;
- + }
- + break;
- + case V4L2_CID_CONTRAST:
- + if (cam->sensor) {
- + cam->contrast = c->value;
- + ret = vidioc_int_s_ctrl(cam->sensor, c);
- + } else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + ret = -ENODEV;
- + }
- + break;
- + case V4L2_CID_BRIGHTNESS:
- + if (cam->sensor) {
- + cam->bright = c->value;
- + ret = vidioc_int_s_ctrl(cam->sensor, c);
- + } else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + ret = -ENODEV;
- + }
- + break;
- + case V4L2_CID_SATURATION:
- + if (cam->sensor) {
- + cam->saturation = c->value;
- + ret = vidioc_int_s_ctrl(cam->sensor, c);
- + } else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + ret = -ENODEV;
- + }
- + break;
- + case V4L2_CID_RED_BALANCE:
- + if (cam->sensor) {
- + cam->red = c->value;
- + ret = vidioc_int_s_ctrl(cam->sensor, c);
- + } else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + ret = -ENODEV;
- + }
- + break;
- + case V4L2_CID_BLUE_BALANCE:
- + if (cam->sensor) {
- + cam->blue = c->value;
- + ret = vidioc_int_s_ctrl(cam->sensor, c);
- + } else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + ret = -ENODEV;
- + }
- + break;
- + case V4L2_CID_EXPOSURE:
- + if (cam->sensor) {
- + cam->ae_mode = c->value;
- + ret = vidioc_int_s_ctrl(cam->sensor, c);
- + } else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + ret = -ENODEV;
- + }
- + break;
- + case V4L2_CID_MXC_FLASH:
- +#ifdef CONFIG_MXC_IPU_V1
- + ipu_csi_flash_strobe(true);
- +#endif
- + break;
- + case V4L2_CID_MXC_SWITCH_CAM:
- + if (cam->sensor == cam->all_sensors[c->value])
- + break;
- +
- + /* power down other cameraes before enable new one */
- + for (i = 0; i < cam->sensor_index; i++) {
- + if (i != c->value) {
- + vidioc_int_dev_exit(cam->all_sensors[i]);
- + vidioc_int_s_power(cam->all_sensors[i], 0);
- + if (cam->mclk_on[cam->mclk_source]) {
- + ipu_csi_enable_mclk_if(cam->ipu,
- + CSI_MCLK_I2C,
- + cam->mclk_source,
- + false, false);
- + cam->mclk_on[cam->mclk_source] =
- + false;
- + }
- + }
- + }
- + sensor_data = cam->all_sensors[c->value]->priv;
- + if (sensor_data->io_init)
- + sensor_data->io_init();
- + cam->sensor = cam->all_sensors[c->value];
- + cam->mclk_source = sensor_data->mclk_source;
- + ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C,
- + cam->mclk_source, true, true);
- + cam->mclk_on[cam->mclk_source] = true;
- + vidioc_int_s_power(cam->sensor, 1);
- + vidioc_int_dev_init(cam->sensor);
- + break;
- + default:
- + pr_debug(" default case\n");
- + ret = -EINVAL;
- + break;
- + }
- +
- + return ret;
- +}
- +
- +/*!
- + * V4L2 - mxc_v4l2_s_param function
- + * Allows setting of capturemode and frame rate.
- + *
- + * @param cam structure cam_data *
- + * @param parm structure v4l2_streamparm *
- + *
- + * @return status 0 success, EINVAL failed
- + */
- +static int mxc_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm)
- +{
- + struct v4l2_ifparm ifparm;
- + struct v4l2_format cam_fmt;
- + struct v4l2_streamparm currentparm;
- + ipu_csi_signal_cfg_t csi_param;
- + u32 current_fps, parm_fps;
- + int err = 0;
- +
- + pr_debug("In mxc_v4l2_s_param\n");
- +
- + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- + pr_err(KERN_ERR "mxc_v4l2_s_param invalid type\n");
- + return -EINVAL;
- + }
- +
- + /* Stop the viewfinder */
- + if (cam->overlay_on == true)
- + stop_preview(cam);
- +
- + currentparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- +
- + /* First check that this device can support the changes requested. */
- + err = vidioc_int_g_parm(cam->sensor, ¤tparm);
- + if (err) {
- + pr_err("%s: vidioc_int_g_parm returned an error %d\n",
- + __func__, err);
- + goto exit;
- + }
- +
- + current_fps = currentparm.parm.capture.timeperframe.denominator
- + / currentparm.parm.capture.timeperframe.numerator;
- + parm_fps = parm->parm.capture.timeperframe.denominator
- + / parm->parm.capture.timeperframe.numerator;
- +
- + pr_debug(" Current capabilities are %x\n",
- + currentparm.parm.capture.capability);
- + pr_debug(" Current capturemode is %d change to %d\n",
- + currentparm.parm.capture.capturemode,
- + parm->parm.capture.capturemode);
- + pr_debug(" Current framerate is %d change to %d\n",
- + current_fps, parm_fps);
- +
- + /* This will change any camera settings needed. */
- + err = vidioc_int_s_parm(cam->sensor, parm);
- + if (err) {
- + pr_err("%s: vidioc_int_s_parm returned an error %d\n",
- + __func__, err);
- + goto exit;
- + }
- +
- + /* If resolution changed, need to re-program the CSI */
- + /* Get new values. */
- + vidioc_int_g_ifparm(cam->sensor, &ifparm);
- +
- + csi_param.data_width = 0;
- + csi_param.clk_mode = 0;
- + csi_param.ext_vsync = 0;
- + csi_param.Vsync_pol = 0;
- + csi_param.Hsync_pol = 0;
- + csi_param.pixclk_pol = 0;
- + csi_param.data_pol = 0;
- + csi_param.sens_clksrc = 0;
- + csi_param.pack_tight = 0;
- + csi_param.force_eof = 0;
- + csi_param.data_en_pol = 0;
- + csi_param.data_fmt = 0;
- + csi_param.csi = cam->csi;
- + csi_param.mclk = 0;
- +
- + pr_debug(" clock_curr=mclk=%d\n", ifparm.u.bt656.clock_curr);
- + if (ifparm.u.bt656.clock_curr == 0)
- + csi_param.clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED;
- + else
- + csi_param.clk_mode = IPU_CSI_CLK_MODE_GATED_CLK;
- +
- + csi_param.pixclk_pol = ifparm.u.bt656.latch_clk_inv;
- +
- + if (ifparm.u.bt656.mode == V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT) {
- + csi_param.data_width = IPU_CSI_DATA_WIDTH_8;
- + } else if (ifparm.u.bt656.mode
- + == V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT) {
- + csi_param.data_width = IPU_CSI_DATA_WIDTH_10;
- + } else {
- + csi_param.data_width = IPU_CSI_DATA_WIDTH_8;
- + }
- +
- + csi_param.Vsync_pol = ifparm.u.bt656.nobt_vs_inv;
- + csi_param.Hsync_pol = ifparm.u.bt656.nobt_hs_inv;
- + csi_param.ext_vsync = ifparm.u.bt656.bt_sync_correct;
- +
- + /* if the capturemode changed, the size bounds will have changed. */
- + cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- + vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt);
- + pr_debug(" g_fmt_cap returns widthxheight of input as %d x %d\n",
- + cam_fmt.fmt.pix.width, cam_fmt.fmt.pix.height);
- +
- + csi_param.data_fmt = cam_fmt.fmt.pix.pixelformat;
- +
- + cam->crop_bounds.top = cam->crop_bounds.left = 0;
- + cam->crop_bounds.width = cam_fmt.fmt.pix.width;
- + cam->crop_bounds.height = cam_fmt.fmt.pix.height;
- +
- + /*
- + * Set the default current cropped resolution to be the same with
- + * the cropping boundary(except for tvin module).
- + */
- + if (cam->device_type != 1) {
- + cam->crop_current.width = cam->crop_bounds.width;
- + cam->crop_current.height = cam->crop_bounds.height;
- + }
- +
- + /* This essentially loses the data at the left and bottom of the image
- + * giving a digital zoom image, if crop_current is less than the full
- + * size of the image. */
- + ipu_csi_set_window_size(cam->ipu, cam->crop_current.width,
- + cam->crop_current.height, cam->csi);
- + ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left,
- + cam->crop_current.top,
- + cam->csi);
- + ipu_csi_init_interface(cam->ipu, cam->crop_bounds.width,
- + cam->crop_bounds.height,
- + cam_fmt.fmt.pix.pixelformat, csi_param);
- +
- +
- +exit:
- + if (cam->overlay_on == true)
- + start_preview(cam);
- +
- + return err;
- +}
- +
- +/*!
- + * V4L2 - mxc_v4l2_s_std function
- + *
- + * Sets the TV standard to be used.
- + *
- + * @param cam structure cam_data *
- + * @param parm structure v4l2_streamparm *
- + *
- + * @return status 0 success, EINVAL failed
- + */
- +static int mxc_v4l2_s_std(cam_data *cam, v4l2_std_id e)
- +{
- + pr_debug("In mxc_v4l2_s_std %Lx\n", e);
- +
- + if (e == V4L2_STD_PAL) {
- + pr_debug(" Setting standard to PAL %Lx\n", V4L2_STD_PAL);
- + cam->standard.id = V4L2_STD_PAL;
- + video_index = TV_PAL;
- + } else if (e == V4L2_STD_NTSC) {
- + pr_debug(" Setting standard to NTSC %Lx\n",
- + V4L2_STD_NTSC);
- + /* Get rid of the white dot line in NTSC signal input */
- + cam->standard.id = V4L2_STD_NTSC;
- + video_index = TV_NTSC;
- + } else {
- + cam->standard.id = V4L2_STD_ALL;
- + video_index = TV_NOT_LOCKED;
- + pr_err("ERROR: unrecognized std! %Lx (PAL=%Lx, NTSC=%Lx\n",
- + e, V4L2_STD_PAL, V4L2_STD_NTSC);
- + }
- +
- + cam->standard.index = video_index;
- + strcpy(cam->standard.name, video_fmts[video_index].name);
- + cam->crop_bounds.width = video_fmts[video_index].raw_width;
- + cam->crop_bounds.height = video_fmts[video_index].raw_height;
- + cam->crop_current.width = video_fmts[video_index].active_width;
- + cam->crop_current.height = video_fmts[video_index].active_height;
- + cam->crop_current.top = video_fmts[video_index].active_top;
- + cam->crop_current.left = video_fmts[video_index].active_left;
- +
- + return 0;
- +}
- +
- +/*!
- + * V4L2 - mxc_v4l2_g_std function
- + *
- + * Gets the TV standard from the TV input device.
- + *
- + * @param cam structure cam_data *
- + *
- + * @param e structure v4l2_streamparm *
- + *
- + * @return status 0 success, EINVAL failed
- + */
- +static int mxc_v4l2_g_std(cam_data *cam, v4l2_std_id *e)
- +{
- + struct v4l2_format tv_fmt;
- +
- + pr_debug("In mxc_v4l2_g_std\n");
- +
- + if (cam->device_type == 1) {
- + /* Use this function to get what the TV-In device detects the
- + * format to be. pixelformat is used to return the std value
- + * since the interface has no vidioc_g_std.*/
- + tv_fmt.type = V4L2_BUF_TYPE_PRIVATE;
- + vidioc_int_g_fmt_cap(cam->sensor, &tv_fmt);
- +
- + /* If the TV-in automatically detects the standard, then if it
- + * changes, the settings need to change. */
- + if (cam->standard_autodetect) {
- + if (cam->standard.id != tv_fmt.fmt.pix.pixelformat) {
- + pr_debug("MVC: mxc_v4l2_g_std: "
- + "Changing standard\n");
- + mxc_v4l2_s_std(cam, tv_fmt.fmt.pix.pixelformat);
- + }
- + }
- +
- + *e = tv_fmt.fmt.pix.pixelformat;
- + }
- +
- + return 0;
- +}
- +
- +/*!
- + * Dequeue one V4L capture buffer
- + *
- + * @param cam structure cam_data *
- + * @param buf structure v4l2_buffer *
- + *
- + * @return status 0 success, EINVAL invalid frame number,
- + * ETIME timeout, ERESTARTSYS interrupted by user
- + */
- +static int mxc_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf)
- +{
- + int retval = 0;
- + struct mxc_v4l_frame *frame;
- + unsigned long lock_flags;
- +
- + pr_debug("In MVC:mxc_v4l_dqueue\n");
- +
- + if (!wait_event_interruptible_timeout(cam->enc_queue,
- + cam->enc_counter != 0, 10 * HZ)) {
- + pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue timeout "
- + "enc_counter %x\n",
- + cam->enc_counter);
- + return -ETIME;
- + } else if (signal_pending(current)) {
- + pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue() "
- + "interrupt received\n");
- + return -ERESTARTSYS;
- + }
- +
- + if (down_interruptible(&cam->busy_lock))
- + return -EBUSY;
- +
- + spin_lock_irqsave(&cam->dqueue_int_lock, lock_flags);
- + cam->enc_counter--;
- +
- + frame = list_entry(cam->done_q.next, struct mxc_v4l_frame, queue);
- + list_del(cam->done_q.next);
- + if (frame->buffer.flags & V4L2_BUF_FLAG_DONE) {
- + frame->buffer.flags &= ~V4L2_BUF_FLAG_DONE;
- + } else if (frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) {
- + pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: "
- + "Buffer not filled.\n");
- + frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED;
- + retval = -EINVAL;
- + } else if ((frame->buffer.flags & 0x7) == V4L2_BUF_FLAG_MAPPED) {
- + pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: "
- + "Buffer not queued.\n");
- + retval = -EINVAL;
- + }
- +
- + cam->frame[frame->index].buffer.field = cam->device_type ?
- + V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE;
- +
- + buf->bytesused = cam->v2f.fmt.pix.sizeimage;
- + buf->index = frame->index;
- + buf->flags = frame->buffer.flags;
- + buf->m = cam->frame[frame->index].buffer.m;
- + buf->timestamp = cam->frame[frame->index].buffer.timestamp;
- + buf->field = cam->frame[frame->index].buffer.field;
- + spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags);
- +
- + up(&cam->busy_lock);
- + return retval;
- +}
- +
- +/*!
- + * V4L interface - open function
- + *
- + * @param file structure file *
- + *
- + * @return status 0 success, ENODEV invalid device instance,
- + * ENODEV timeout, ERESTARTSYS interrupted by user
- + */
- +static int mxc_v4l_open(struct file *file)
- +{
- + struct v4l2_ifparm ifparm;
- + struct v4l2_format cam_fmt;
- + ipu_csi_signal_cfg_t csi_param;
- + struct video_device *dev = video_devdata(file);
- + cam_data *cam = video_get_drvdata(dev);
- + int err = 0;
- + struct sensor_data *sensor;
- +
- + pr_debug("\nIn MVC: mxc_v4l_open\n");
- + pr_debug(" device name is %s\n", dev->name);
- +
- + if (!cam) {
- + pr_err("ERROR: v4l2 capture: Internal error, "
- + "cam_data not found!\n");
- + return -EBADF;
- + }
- +
- + if (cam->sensor == NULL ||
- + cam->sensor->type != v4l2_int_type_slave) {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + return -EAGAIN;
- + }
- +
- + sensor = cam->sensor->priv;
- + if (!sensor) {
- + pr_err("%s: Internal error, sensor_data is not found!\n", __func__);
- + return -EBADF;
- + }
- +
- + down(&cam->busy_lock);
- + err = 0;
- + if (signal_pending(current))
- + goto oops;
- +
- + if (cam->open_count++ == 0) {
- + wait_event_interruptible(cam->power_queue,
- + cam->low_power == false);
- +
- + if (strcmp(mxc_capture_inputs[cam->current_input].name,
- + "CSI MEM") == 0) {
- +#if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE)
- + err = csi_enc_select(cam);
- +#endif
- + } else if (strcmp(mxc_capture_inputs[cam->current_input].name,
- + "CSI IC MEM") == 0) {
- +#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE)
- + err = prp_enc_select(cam);
- +#endif
- + }
- +
- + cam->enc_counter = 0;
- + INIT_LIST_HEAD(&cam->ready_q);
- + INIT_LIST_HEAD(&cam->working_q);
- + INIT_LIST_HEAD(&cam->done_q);
- +
- + vidioc_int_g_ifparm(cam->sensor, &ifparm);
- +
- + csi_param.sens_clksrc = 0;
- +
- + csi_param.clk_mode = 0;
- + csi_param.data_pol = 0;
- + csi_param.ext_vsync = 0;
- +
- + csi_param.pack_tight = 0;
- + csi_param.force_eof = 0;
- + csi_param.data_en_pol = 0;
- +
- + csi_param.mclk = ifparm.u.bt656.clock_curr;
- +
- + csi_param.pixclk_pol = ifparm.u.bt656.latch_clk_inv;
- +
- + if (ifparm.u.bt656.mode
- + == V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT)
- + csi_param.data_width = IPU_CSI_DATA_WIDTH_8;
- + else if (ifparm.u.bt656.mode
- + == V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT)
- + csi_param.data_width = IPU_CSI_DATA_WIDTH_10;
- + else
- + csi_param.data_width = IPU_CSI_DATA_WIDTH_8;
- +
- +
- + csi_param.Vsync_pol = ifparm.u.bt656.nobt_vs_inv;
- + csi_param.Hsync_pol = ifparm.u.bt656.nobt_hs_inv;
- +
- + csi_param.csi = cam->csi;
- +
- + cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- + vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt);
- +
- + /* Reset the sizes. Needed to prevent carryover of last
- + * operation.*/
- + cam->crop_bounds.top = cam->crop_bounds.left = 0;
- + cam->crop_bounds.width = cam_fmt.fmt.pix.width;
- + cam->crop_bounds.height = cam_fmt.fmt.pix.height;
- +
- + /* This also is the max crop size for this device. */
- + cam->crop_defrect.top = cam->crop_defrect.left = 0;
- + cam->crop_defrect.width = cam_fmt.fmt.pix.width;
- + cam->crop_defrect.height = cam_fmt.fmt.pix.height;
- +
- + /* At this point, this is also the current image size. */
- + cam->crop_current.top = cam->crop_current.left = 0;
- + cam->crop_current.width = cam_fmt.fmt.pix.width;
- + cam->crop_current.height = cam_fmt.fmt.pix.height;
- +
- + pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
- + __func__,
- + cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
- + pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
- + __func__,
- + cam->crop_bounds.width, cam->crop_bounds.height);
- + pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
- + __func__,
- + cam->crop_defrect.width, cam->crop_defrect.height);
- + pr_debug("End of %s: crop_current widthxheight %d x %d\n",
- + __func__,
- + cam->crop_current.width, cam->crop_current.height);
- +
- + csi_param.data_fmt = cam_fmt.fmt.pix.pixelformat;
- + pr_debug("On Open: Input to ipu size is %d x %d\n",
- + cam_fmt.fmt.pix.width, cam_fmt.fmt.pix.height);
- + ipu_csi_set_window_size(cam->ipu, cam->crop_current.width,
- + cam->crop_current.height,
- + cam->csi);
- + ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left,
- + cam->crop_current.top,
- + cam->csi);
- + ipu_csi_init_interface(cam->ipu, cam->crop_bounds.width,
- + cam->crop_bounds.height,
- + cam_fmt.fmt.pix.pixelformat,
- + csi_param);
- + clk_prepare_enable(sensor->sensor_clk);
- + vidioc_int_s_power(cam->sensor, 1);
- + vidioc_int_init(cam->sensor);
- + vidioc_int_dev_init(cam->sensor);
- + }
- +
- + file->private_data = dev;
- +
- +oops:
- + up(&cam->busy_lock);
- + return err;
- +}
- +
- +/*!
- + * V4L interface - close function
- + *
- + * @param file struct file *
- + *
- + * @return 0 success
- + */
- +static int mxc_v4l_close(struct file *file)
- +{
- + struct video_device *dev = video_devdata(file);
- + int err = 0;
- + cam_data *cam = video_get_drvdata(dev);
- + struct sensor_data *sensor;
- + pr_debug("In MVC:mxc_v4l_close\n");
- +
- + if (!cam) {
- + pr_err("ERROR: v4l2 capture: Internal error, "
- + "cam_data not found!\n");
- + return -EBADF;
- + }
- +
- + if (!cam->sensor) {
- + pr_err("%s: Internal error, camera is not found!\n", __func__);
- + return -EBADF;
- + }
- +
- + sensor = cam->sensor->priv;
- + if (!sensor) {
- + pr_err("%s: Internal error, sensor_data is not found!\n", __func__);
- + return -EBADF;
- + }
- +
- + down(&cam->busy_lock);
- +
- + /* for the case somebody hit the ctrl C */
- + if (cam->overlay_pid == current->pid && cam->overlay_on) {
- + err = stop_preview(cam);
- + cam->overlay_on = false;
- + }
- + if (cam->capture_pid == current->pid) {
- + err |= mxc_streamoff(cam);
- + wake_up_interruptible(&cam->enc_queue);
- + }
- +
- + if (--cam->open_count == 0) {
- + vidioc_int_s_power(cam->sensor, 0);
- + clk_disable_unprepare(sensor->sensor_clk);
- + wait_event_interruptible(cam->power_queue,
- + cam->low_power == false);
- + pr_debug("mxc_v4l_close: release resource\n");
- +
- + if (strcmp(mxc_capture_inputs[cam->current_input].name,
- + "CSI MEM") == 0) {
- +#if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE)
- + err |= csi_enc_deselect(cam);
- +#endif
- + } else if (strcmp(mxc_capture_inputs[cam->current_input].name,
- + "CSI IC MEM") == 0) {
- +#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE)
- + err |= prp_enc_deselect(cam);
- +#endif
- + }
- +
- + mxc_free_frame_buf(cam);
- + file->private_data = NULL;
- +
- + /* capture off */
- + wake_up_interruptible(&cam->enc_queue);
- + mxc_free_frames(cam);
- + cam->enc_counter++;
- + }
- +
- + up(&cam->busy_lock);
- +
- + return err;
- +}
- +
- +#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC) || \
- + defined(CONFIG_MXC_IPU_PRP_ENC_MODULE) || \
- + defined(CONFIG_MXC_IPU_CSI_ENC_MODULE)
- +/*
- + * V4L interface - read function
- + *
- + * @param file struct file *
- + * @param read buf char *
- + * @param count size_t
- + * @param ppos structure loff_t *
- + *
- + * @return bytes read
- + */
- +static ssize_t mxc_v4l_read(struct file *file, char *buf, size_t count,
- + loff_t *ppos)
- +{
- + int err = 0;
- + u8 *v_address[2];
- + struct video_device *dev = video_devdata(file);
- + cam_data *cam = video_get_drvdata(dev);
- +
- + if (down_interruptible(&cam->busy_lock))
- + return -EINTR;
- +
- + /* Stop the viewfinder */
- + if (cam->overlay_on == true)
- + stop_preview(cam);
- +
- + v_address[0] = dma_alloc_coherent(0,
- + PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
- + &cam->still_buf[0],
- + GFP_DMA | GFP_KERNEL);
- +
- + v_address[1] = dma_alloc_coherent(0,
- + PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
- + &cam->still_buf[1],
- + GFP_DMA | GFP_KERNEL);
- +
- + if (!v_address[0] || !v_address[1]) {
- + err = -ENOBUFS;
- + goto exit0;
- + }
- +
- + err = prp_still_select(cam);
- + if (err != 0) {
- + err = -EIO;
- + goto exit0;
- + }
- +
- + cam->still_counter = 0;
- + err = cam->csi_start(cam);
- + if (err != 0) {
- + err = -EIO;
- + goto exit1;
- + }
- +
- + if (!wait_event_interruptible_timeout(cam->still_queue,
- + cam->still_counter != 0,
- + 10 * HZ)) {
- + pr_err("ERROR: v4l2 capture: mxc_v4l_read timeout counter %x\n",
- + cam->still_counter);
- + err = -ETIME;
- + goto exit1;
- + }
- + err = copy_to_user(buf, v_address[1], cam->v2f.fmt.pix.sizeimage);
- +
- +exit1:
- + prp_still_deselect(cam);
- +
- +exit0:
- + if (v_address[0] != 0)
- + dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address[0],
- + cam->still_buf[0]);
- + if (v_address[1] != 0)
- + dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address[1],
- + cam->still_buf[1]);
- +
- + cam->still_buf[0] = cam->still_buf[1] = 0;
- +
- + if (cam->overlay_on == true)
- + start_preview(cam);
- +
- + up(&cam->busy_lock);
- + if (err < 0)
- + return err;
- +
- + return cam->v2f.fmt.pix.sizeimage - err;
- +}
- +#endif
- +
- +/*!
- + * V4L interface - ioctl function
- + *
- + * @param file struct file*
- + *
- + * @param ioctlnr unsigned int
- + *
- + * @param arg void*
- + *
- + * @return 0 success, ENODEV for invalid device instance,
- + * -1 for other errors.
- + */
- +static long mxc_v4l_do_ioctl(struct file *file,
- + unsigned int ioctlnr, void *arg)
- +{
- + struct video_device *dev = video_devdata(file);
- + cam_data *cam = video_get_drvdata(dev);
- + int retval = 0;
- + unsigned long lock_flags;
- +
- + pr_debug("In MVC: mxc_v4l_do_ioctl %x\n", ioctlnr);
- + wait_event_interruptible(cam->power_queue, cam->low_power == false);
- + /* make this _really_ smp-safe */
- + if (ioctlnr != VIDIOC_DQBUF)
- + if (down_interruptible(&cam->busy_lock))
- + return -EBUSY;
- +
- + switch (ioctlnr) {
- + /*!
- + * V4l2 VIDIOC_QUERYCAP ioctl
- + */
- + case VIDIOC_QUERYCAP: {
- + struct v4l2_capability *cap = arg;
- + pr_debug(" case VIDIOC_QUERYCAP\n");
- + strcpy(cap->driver, "mxc_v4l2");
- + cap->version = KERNEL_VERSION(0, 1, 11);
- + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
- + V4L2_CAP_VIDEO_OVERLAY |
- + V4L2_CAP_STREAMING |
- + V4L2_CAP_READWRITE;
- + cap->card[0] = '\0';
- + cap->bus_info[0] = '\0';
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_G_FMT ioctl
- + */
- + case VIDIOC_G_FMT: {
- + struct v4l2_format *gf = arg;
- + pr_debug(" case VIDIOC_G_FMT\n");
- + retval = mxc_v4l2_g_fmt(cam, gf);
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_S_FMT ioctl
- + */
- + case VIDIOC_S_FMT: {
- + struct v4l2_format *sf = arg;
- + pr_debug(" case VIDIOC_S_FMT\n");
- + retval = mxc_v4l2_s_fmt(cam, sf);
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_REQBUFS ioctl
- + */
- + case VIDIOC_REQBUFS: {
- + struct v4l2_requestbuffers *req = arg;
- + pr_debug(" case VIDIOC_REQBUFS\n");
- +
- + if (req->count > FRAME_NUM) {
- + pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: "
- + "not enough buffers\n");
- + req->count = FRAME_NUM;
- + }
- +
- + if ((req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
- + pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: "
- + "wrong buffer type\n");
- + retval = -EINVAL;
- + break;
- + }
- +
- + mxc_streamoff(cam);
- + if (req->memory & V4L2_MEMORY_MMAP) {
- + mxc_free_frame_buf(cam);
- + retval = mxc_allocate_frame_buf(cam, req->count);
- + }
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_QUERYBUF ioctl
- + */
- + case VIDIOC_QUERYBUF: {
- + struct v4l2_buffer *buf = arg;
- + int index = buf->index;
- + pr_debug(" case VIDIOC_QUERYBUF\n");
- +
- + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- + pr_err("ERROR: v4l2 capture: "
- + "VIDIOC_QUERYBUFS: "
- + "wrong buffer type\n");
- + retval = -EINVAL;
- + break;
- + }
- +
- + if (buf->memory & V4L2_MEMORY_MMAP) {
- + memset(buf, 0, sizeof(buf));
- + buf->index = index;
- + }
- +
- + down(&cam->param_lock);
- + if (buf->memory & V4L2_MEMORY_USERPTR) {
- + mxc_v4l2_release_bufs(cam);
- + retval = mxc_v4l2_prepare_bufs(cam, buf);
- + }
- +
- + if (buf->memory & V4L2_MEMORY_MMAP)
- + retval = mxc_v4l2_buffer_status(cam, buf);
- + up(&cam->param_lock);
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_QBUF ioctl
- + */
- + case VIDIOC_QBUF: {
- + struct v4l2_buffer *buf = arg;
- + int index = buf->index;
- + pr_debug(" case VIDIOC_QBUF\n");
- +
- + spin_lock_irqsave(&cam->queue_int_lock, lock_flags);
- + if ((cam->frame[index].buffer.flags & 0x7) ==
- + V4L2_BUF_FLAG_MAPPED) {
- + cam->frame[index].buffer.flags |=
- + V4L2_BUF_FLAG_QUEUED;
- + list_add_tail(&cam->frame[index].queue,
- + &cam->ready_q);
- + } else if (cam->frame[index].buffer.
- + flags & V4L2_BUF_FLAG_QUEUED) {
- + pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: "
- + "buffer already queued\n");
- + retval = -EINVAL;
- + } else if (cam->frame[index].buffer.
- + flags & V4L2_BUF_FLAG_DONE) {
- + pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: "
- + "overwrite done buffer.\n");
- + cam->frame[index].buffer.flags &=
- + ~V4L2_BUF_FLAG_DONE;
- + cam->frame[index].buffer.flags |=
- + V4L2_BUF_FLAG_QUEUED;
- + retval = -EINVAL;
- + }
- +
- + buf->flags = cam->frame[index].buffer.flags;
- + spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags);
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_DQBUF ioctl
- + */
- + case VIDIOC_DQBUF: {
- + struct v4l2_buffer *buf = arg;
- + pr_debug(" case VIDIOC_DQBUF\n");
- +
- + if ((cam->enc_counter == 0) &&
- + (file->f_flags & O_NONBLOCK)) {
- + retval = -EAGAIN;
- + break;
- + }
- +
- + retval = mxc_v4l_dqueue(cam, buf);
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_STREAMON ioctl
- + */
- + case VIDIOC_STREAMON: {
- + pr_debug(" case VIDIOC_STREAMON\n");
- + retval = mxc_streamon(cam);
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_STREAMOFF ioctl
- + */
- + case VIDIOC_STREAMOFF: {
- + pr_debug(" case VIDIOC_STREAMOFF\n");
- + retval = mxc_streamoff(cam);
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_G_CTRL ioctl
- + */
- + case VIDIOC_G_CTRL: {
- + pr_debug(" case VIDIOC_G_CTRL\n");
- + retval = mxc_v4l2_g_ctrl(cam, arg);
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_S_CTRL ioctl
- + */
- + case VIDIOC_S_CTRL: {
- + pr_debug(" case VIDIOC_S_CTRL\n");
- + retval = mxc_v4l2_s_ctrl(cam, arg);
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_CROPCAP ioctl
- + */
- + case VIDIOC_CROPCAP: {
- + struct v4l2_cropcap *cap = arg;
- + pr_debug(" case VIDIOC_CROPCAP\n");
- + if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
- + cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) {
- + retval = -EINVAL;
- + break;
- + }
- + cap->bounds = cam->crop_bounds;
- + cap->defrect = cam->crop_defrect;
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_G_CROP ioctl
- + */
- + case VIDIOC_G_CROP: {
- + struct v4l2_crop *crop = arg;
- + pr_debug(" case VIDIOC_G_CROP\n");
- +
- + if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
- + crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) {
- + retval = -EINVAL;
- + break;
- + }
- + crop->c = cam->crop_current;
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_S_CROP ioctl
- + */
- + case VIDIOC_S_CROP: {
- + struct v4l2_crop *crop = arg;
- + struct v4l2_rect *b = &cam->crop_bounds;
- + pr_debug(" case VIDIOC_S_CROP\n");
- +
- + if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
- + crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) {
- + retval = -EINVAL;
- + break;
- + }
- +
- + crop->c.top = (crop->c.top < b->top) ? b->top
- + : crop->c.top;
- + if (crop->c.top > b->top + b->height)
- + crop->c.top = b->top + b->height - 1;
- + if (crop->c.height > b->top + b->height - crop->c.top)
- + crop->c.height =
- + b->top + b->height - crop->c.top;
- +
- + crop->c.left = (crop->c.left < b->left) ? b->left
- + : crop->c.left;
- + if (crop->c.left > b->left + b->width)
- + crop->c.left = b->left + b->width - 1;
- + if (crop->c.width > b->left - crop->c.left + b->width)
- + crop->c.width =
- + b->left - crop->c.left + b->width;
- +
- + crop->c.width -= crop->c.width % 8;
- + crop->c.left -= crop->c.left % 4;
- + cam->crop_current = crop->c;
- +
- + pr_debug(" Cropping Input to ipu size %d x %d\n",
- + cam->crop_current.width,
- + cam->crop_current.height);
- + ipu_csi_set_window_size(cam->ipu, cam->crop_current.width,
- + cam->crop_current.height,
- + cam->csi);
- + ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left,
- + cam->crop_current.top,
- + cam->csi);
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_OVERLAY ioctl
- + */
- + case VIDIOC_OVERLAY: {
- + int *on = arg;
- + pr_debug(" VIDIOC_OVERLAY on=%d\n", *on);
- + if (*on) {
- + cam->overlay_on = true;
- + cam->overlay_pid = current->pid;
- + retval = start_preview(cam);
- + }
- + if (!*on) {
- + retval = stop_preview(cam);
- + cam->overlay_on = false;
- + }
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_G_FBUF ioctl
- + */
- + case VIDIOC_G_FBUF: {
- + struct v4l2_framebuffer *fb = arg;
- + pr_debug(" case VIDIOC_G_FBUF\n");
- + *fb = cam->v4l2_fb;
- + fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY;
- + break;
- + }
- +
- + /*!
- + * V4l2 VIDIOC_S_FBUF ioctl
- + */
- + case VIDIOC_S_FBUF: {
- + struct v4l2_framebuffer *fb = arg;
- + pr_debug(" case VIDIOC_S_FBUF\n");
- + cam->v4l2_fb = *fb;
- + break;
- + }
- +
- + case VIDIOC_G_PARM: {
- + struct v4l2_streamparm *parm = arg;
- + pr_debug(" case VIDIOC_G_PARM\n");
- + if (cam->sensor)
- + retval = vidioc_int_g_parm(cam->sensor, parm);
- + else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + retval = -ENODEV;
- + }
- + break;
- + }
- +
- + case VIDIOC_S_PARM: {
- + struct v4l2_streamparm *parm = arg;
- + pr_debug(" case VIDIOC_S_PARM\n");
- + if (cam->sensor)
- + retval = mxc_v4l2_s_param(cam, parm);
- + else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + retval = -ENODEV;
- + }
- + break;
- + }
- +
- + /* linux v4l2 bug, kernel c0485619 user c0405619 */
- + case VIDIOC_ENUMSTD: {
- + struct v4l2_standard *e = arg;
- + pr_debug(" case VIDIOC_ENUMSTD\n");
- + *e = cam->standard;
- + break;
- + }
- +
- + case VIDIOC_G_STD: {
- + v4l2_std_id *e = arg;
- + pr_debug(" case VIDIOC_G_STD\n");
- + if (cam->sensor)
- + retval = mxc_v4l2_g_std(cam, e);
- + else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + retval = -ENODEV;
- + }
- + break;
- + }
- +
- + case VIDIOC_S_STD: {
- + v4l2_std_id *e = arg;
- + pr_debug(" case VIDIOC_S_STD\n");
- + retval = mxc_v4l2_s_std(cam, *e);
- +
- + break;
- + }
- +
- + case VIDIOC_ENUMOUTPUT: {
- + struct v4l2_output *output = arg;
- + pr_debug(" case VIDIOC_ENUMOUTPUT\n");
- + if (output->index >= MXC_V4L2_CAPTURE_NUM_OUTPUTS) {
- + retval = -EINVAL;
- + break;
- + }
- + *output = mxc_capture_outputs[output->index];
- +
- + break;
- + }
- + case VIDIOC_G_OUTPUT: {
- + int *p_output_num = arg;
- + pr_debug(" case VIDIOC_G_OUTPUT\n");
- + *p_output_num = cam->output;
- + break;
- + }
- +
- + case VIDIOC_S_OUTPUT: {
- + int *p_output_num = arg;
- + pr_debug(" case VIDIOC_S_OUTPUT\n");
- + if (*p_output_num >= MXC_V4L2_CAPTURE_NUM_OUTPUTS) {
- + retval = -EINVAL;
- + break;
- + }
- + cam->output = *p_output_num;
- + break;
- + }
- +
- + case VIDIOC_ENUMINPUT: {
- + struct v4l2_input *input = arg;
- + pr_debug(" case VIDIOC_ENUMINPUT\n");
- + if (input->index >= MXC_V4L2_CAPTURE_NUM_INPUTS) {
- + retval = -EINVAL;
- + break;
- + }
- + *input = mxc_capture_inputs[input->index];
- + break;
- + }
- +
- + case VIDIOC_G_INPUT: {
- + int *index = arg;
- + pr_debug(" case VIDIOC_G_INPUT\n");
- + *index = cam->current_input;
- + break;
- + }
- +
- + case VIDIOC_S_INPUT: {
- + int *index = arg;
- + pr_debug(" case VIDIOC_S_INPUT\n");
- + if (*index >= MXC_V4L2_CAPTURE_NUM_INPUTS) {
- + retval = -EINVAL;
- + break;
- + }
- +
- + if (*index == cam->current_input)
- + break;
- +
- + if ((mxc_capture_inputs[cam->current_input].status &
- + V4L2_IN_ST_NO_POWER) == 0) {
- + retval = mxc_streamoff(cam);
- + if (retval)
- + break;
- + mxc_capture_inputs[cam->current_input].status |=
- + V4L2_IN_ST_NO_POWER;
- + }
- +
- + if (strcmp(mxc_capture_inputs[*index].name, "CSI MEM") == 0) {
- +#if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE)
- + retval = csi_enc_select(cam);
- + if (retval)
- + break;
- +#endif
- + } else if (strcmp(mxc_capture_inputs[*index].name,
- + "CSI IC MEM") == 0) {
- +#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE)
- + retval = prp_enc_select(cam);
- + if (retval)
- + break;
- +#endif
- + }
- +
- + mxc_capture_inputs[*index].status &= ~V4L2_IN_ST_NO_POWER;
- + cam->current_input = *index;
- + break;
- + }
- + case VIDIOC_ENUM_FMT: {
- + struct v4l2_fmtdesc *f = arg;
- + if (cam->sensor)
- + retval = vidioc_int_enum_fmt_cap(cam->sensor, f);
- + else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + retval = -ENODEV;
- + }
- + break;
- + }
- + case VIDIOC_ENUM_FRAMESIZES: {
- + struct v4l2_frmsizeenum *fsize = arg;
- + if (cam->sensor)
- + retval = vidioc_int_enum_framesizes(cam->sensor, fsize);
- + else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + retval = -ENODEV;
- + }
- + break;
- + }
- + case VIDIOC_DBG_G_CHIP_IDENT: {
- + struct v4l2_dbg_chip_ident *p = arg;
- + p->ident = V4L2_IDENT_NONE;
- + p->revision = 0;
- + if (cam->sensor)
- + retval = vidioc_int_g_chip_ident(cam->sensor, (int *)p);
- + else {
- + pr_err("ERROR: v4l2 capture: slave not found!\n");
- + retval = -ENODEV;
- + }
- + break;
- + }
- + case VIDIOC_TRY_FMT:
- + case VIDIOC_QUERYCTRL:
- + case VIDIOC_G_TUNER:
- + case VIDIOC_S_TUNER:
- + case VIDIOC_G_FREQUENCY:
- + case VIDIOC_S_FREQUENCY:
- + default:
- + pr_debug(" case default or not supported\n");
- + retval = -EINVAL;
- + break;
- + }
- +
- + if (ioctlnr != VIDIOC_DQBUF)
- + up(&cam->busy_lock);
- + return retval;
- +}
- +
- +/*
- + * V4L interface - ioctl function
- + *
- + * @return None
- + */
- +static long mxc_v4l_ioctl(struct file *file, unsigned int cmd,
- + unsigned long arg)
- +{
- + pr_debug("In MVC:mxc_v4l_ioctl\n");
- + return video_usercopy(file, cmd, arg, mxc_v4l_do_ioctl);
- +}
- +
- +/*!
- + * V4L interface - mmap function
- + *
- + * @param file structure file *
- + *
- + * @param vma structure vm_area_struct *
- + *
- + * @return status 0 Success, EINTR busy lock error, ENOBUFS remap_page error
- + */
- +static int mxc_mmap(struct file *file, struct vm_area_struct *vma)
- +{
- + struct video_device *dev = video_devdata(file);
- + unsigned long size;
- + int res = 0;
- + cam_data *cam = video_get_drvdata(dev);
- +
- + pr_debug("In MVC:mxc_mmap\n");
- + pr_debug(" pgoff=0x%lx, start=0x%lx, end=0x%lx\n",
- + vma->vm_pgoff, vma->vm_start, vma->vm_end);
- +
- + /* make this _really_ smp-safe */
- + if (down_interruptible(&cam->busy_lock))
- + return -EINTR;
- +
- + size = vma->vm_end - vma->vm_start;
- + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- +
- + if (remap_pfn_range(vma, vma->vm_start,
- + vma->vm_pgoff, size, vma->vm_page_prot)) {
- + pr_err("ERROR: v4l2 capture: mxc_mmap: "
- + "remap_pfn_range failed\n");
- + res = -ENOBUFS;
- + goto mxc_mmap_exit;
- + }
- +
- + vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */
- +
- +mxc_mmap_exit:
- + up(&cam->busy_lock);
- + return res;
- +}
- +
- +/*!
- + * V4L interface - poll function
- + *
- + * @param file structure file *
- + *
- + * @param wait structure poll_table_struct *
- + *
- + * @return status POLLIN | POLLRDNORM
- + */
- +static unsigned int mxc_poll(struct file *file, struct poll_table_struct *wait)
- +{
- + struct video_device *dev = video_devdata(file);
- + cam_data *cam = video_get_drvdata(dev);
- + wait_queue_head_t *queue = NULL;
- + int res = POLLIN | POLLRDNORM;
- +
- + pr_debug("In MVC:mxc_poll\n");
- +
- + if (down_interruptible(&cam->busy_lock))
- + return -EINTR;
- +
- + queue = &cam->enc_queue;
- + poll_wait(file, queue, wait);
- +
- + up(&cam->busy_lock);
- +
- + return res;
- +}
- +
- +/*!
- + * This structure defines the functions to be called in this driver.
- + */
- +static struct v4l2_file_operations mxc_v4l_fops = {
- + .owner = THIS_MODULE,
- + .open = mxc_v4l_open,
- + .release = mxc_v4l_close,
- + .read = mxc_v4l_read,
- + .ioctl = mxc_v4l_ioctl,
- + .mmap = mxc_mmap,
- + .poll = mxc_poll,
- +};
- +
- +static struct video_device mxc_v4l_template = {
- + .name = "Mxc Camera",
- + .fops = &mxc_v4l_fops,
- + .release = video_device_release,
- +};
- +
- +/*!
- + * This function can be used to release any platform data on closing.
- + */
- +static void camera_platform_release(struct device *device)
- +{
- +}
- +
- +/*!
- + * Camera V4l2 callback function.
- + *
- + * @param mask u32
- + *
- + * @param dev void device structure
- + *
- + * @return status
- + */
- +static void camera_callback(u32 mask, void *dev)
- +{
- + struct mxc_v4l_frame *done_frame;
- + struct mxc_v4l_frame *ready_frame;
- + struct timeval cur_time;
- +
- + cam_data *cam = (cam_data *) dev;
- + if (cam == NULL)
- + return;
- +
- + pr_debug("In MVC:camera_callback\n");
- +
- + spin_lock(&cam->queue_int_lock);
- + spin_lock(&cam->dqueue_int_lock);
- + if (!list_empty(&cam->working_q)) {
- + do_gettimeofday(&cur_time);
- +
- + done_frame = list_entry(cam->working_q.next,
- + struct mxc_v4l_frame,
- + queue);
- +
- + if (done_frame->ipu_buf_num != cam->local_buf_num)
- + goto next;
- +
- + /*
- + * Set the current time to done frame buffer's
- + * timestamp. Users can use this information to judge
- + * the frame's usage.
- + */
- + done_frame->buffer.timestamp = cur_time;
- +
- + if (done_frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) {
- + done_frame->buffer.flags |= V4L2_BUF_FLAG_DONE;
- + done_frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED;
- +
- + /* Added to the done queue */
- + list_del(cam->working_q.next);
- + list_add_tail(&done_frame->queue, &cam->done_q);
- +
- + /* Wake up the queue */
- + cam->enc_counter++;
- + wake_up_interruptible(&cam->enc_queue);
- + } else
- + pr_err("ERROR: v4l2 capture: camera_callback: "
- + "buffer not queued\n");
- + }
- +
- +next:
- + if (!list_empty(&cam->ready_q)) {
- + ready_frame = list_entry(cam->ready_q.next,
- + struct mxc_v4l_frame,
- + queue);
- + if (cam->enc_update_eba)
- + if (cam->enc_update_eba(cam->ipu,
- + ready_frame->buffer.m.offset,
- + &cam->ping_pong_csi) == 0) {
- + list_del(cam->ready_q.next);
- + list_add_tail(&ready_frame->queue,
- + &cam->working_q);
- + ready_frame->ipu_buf_num = cam->local_buf_num;
- + }
- + } else {
- + if (cam->enc_update_eba)
- + cam->enc_update_eba(
- + cam->ipu, cam->dummy_frame.buffer.m.offset,
- + &cam->ping_pong_csi);
- + }
- +
- + cam->local_buf_num = (cam->local_buf_num == 0) ? 1 : 0;
- + spin_unlock(&cam->dqueue_int_lock);
- + spin_unlock(&cam->queue_int_lock);
- +
- + return;
- +}
- +
- +/*!
- + * initialize cam_data structure
- + *
- + * @param cam structure cam_data *
- + *
- + * @return status 0 Success
- + */
- +static int init_camera_struct(cam_data *cam, struct platform_device *pdev)
- +{
- + const struct of_device_id *of_id =
- + of_match_device(mxc_v4l2_dt_ids, &pdev->dev);
- + struct device_node *np = pdev->dev.of_node;
- + int ipu_id, csi_id, mclk_source;
- + int ret = 0;
- +
- + pr_debug("In MVC: init_camera_struct\n");
- +
- + ret = of_property_read_u32(np, "ipu_id", &ipu_id);
- + if (ret) {
- + dev_err(&pdev->dev, "ipu_id missing or invalid\n");
- + return ret;
- + }
- +
- + ret = of_property_read_u32(np, "csi_id", &csi_id);
- + if (ret) {
- + dev_err(&pdev->dev, "csi_id missing or invalid\n");
- + return ret;
- + }
- +
- + ret = of_property_read_u32(np, "mclk_source", &mclk_source);
- + if (ret) {
- + dev_err(&pdev->dev, "sensor mclk missing or invalid\n");
- + return ret;
- + }
- +
- + /* Default everything to 0 */
- + memset(cam, 0, sizeof(cam_data));
- +
- + /* get devtype to distinguish if the cpu is imx5 or imx6
- + * IMX5_V4L2 specify the cpu is imx5
- + * IMX6_V4L2 specify the cpu is imx6q or imx6sdl
- + */
- + if (of_id)
- + pdev->id_entry = of_id->data;
- + cam->devtype = pdev->id_entry->driver_data;
- +
- + cam->ipu = ipu_get_soc(ipu_id);
- + if (cam->ipu == NULL) {
- + pr_err("ERROR: v4l2 capture: failed to get ipu\n");
- + return -EINVAL;
- + } else if (cam->ipu == ERR_PTR(-ENODEV)) {
- + pr_err("ERROR: v4l2 capture: get invalid ipu\n");
- + return -ENODEV;
- + }
- +
- + init_MUTEX(&cam->param_lock);
- + init_MUTEX(&cam->busy_lock);
- +
- + cam->video_dev = video_device_alloc();
- + if (cam->video_dev == NULL)
- + return -ENODEV;
- +
- + *(cam->video_dev) = mxc_v4l_template;
- +
- + video_set_drvdata(cam->video_dev, cam);
- + dev_set_drvdata(&pdev->dev, (void *)cam);
- + cam->video_dev->minor = -1;
- +
- + init_waitqueue_head(&cam->enc_queue);
- + init_waitqueue_head(&cam->still_queue);
- +
- + /* setup cropping */
- + cam->crop_bounds.left = 0;
- + cam->crop_bounds.width = 640;
- + cam->crop_bounds.top = 0;
- + cam->crop_bounds.height = 480;
- + cam->crop_current = cam->crop_defrect = cam->crop_bounds;
- + ipu_csi_set_window_size(cam->ipu, cam->crop_current.width,
- + cam->crop_current.height, cam->csi);
- + ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left,
- + cam->crop_current.top, cam->csi);
- + cam->streamparm.parm.capture.capturemode = 0;
- +
- + cam->standard.index = 0;
- + cam->standard.id = V4L2_STD_UNKNOWN;
- + cam->standard.frameperiod.denominator = 30;
- + cam->standard.frameperiod.numerator = 1;
- + cam->standard.framelines = 480;
- + cam->standard_autodetect = true;
- + cam->streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- + cam->streamparm.parm.capture.timeperframe = cam->standard.frameperiod;
- + cam->streamparm.parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
- + cam->overlay_on = false;
- + cam->capture_on = false;
- + cam->v4l2_fb.flags = V4L2_FBUF_FLAG_OVERLAY;
- +
- + cam->v2f.fmt.pix.sizeimage = 352 * 288 * 3 / 2;
- + cam->v2f.fmt.pix.bytesperline = 288 * 3 / 2;
- + cam->v2f.fmt.pix.width = 288;
- + cam->v2f.fmt.pix.height = 352;
- + cam->v2f.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
- + cam->win.w.width = 160;
- + cam->win.w.height = 160;
- + cam->win.w.left = 0;
- + cam->win.w.top = 0;
- +
- + cam->ipu_id = ipu_id;
- + cam->csi = csi_id;
- + cam->mclk_source = mclk_source;
- + cam->mclk_on[cam->mclk_source] = false;
- +
- + cam->enc_callback = camera_callback;
- + init_waitqueue_head(&cam->power_queue);
- + spin_lock_init(&cam->queue_int_lock);
- + spin_lock_init(&cam->dqueue_int_lock);
- +
- + cam->self = kmalloc(sizeof(struct v4l2_int_device), GFP_KERNEL);
- + cam->self->module = THIS_MODULE;
- + sprintf(cam->self->name, "mxc_v4l2_cap%d", cam->csi);
- + cam->self->type = v4l2_int_type_master;
- + cam->self->u.master = &mxc_v4l2_master;
- +
- + return 0;
- +}
- +
- +static ssize_t show_streaming(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + struct video_device *video_dev = container_of(dev,
- + struct video_device, dev);
- + cam_data *cam = video_get_drvdata(video_dev);
- +
- + if (cam->capture_on)
- + return sprintf(buf, "stream on\n");
- + else
- + return sprintf(buf, "stream off\n");
- +}
- +static DEVICE_ATTR(fsl_v4l2_capture_property, S_IRUGO, show_streaming, NULL);
- +
- +static ssize_t show_overlay(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + struct video_device *video_dev = container_of(dev,
- + struct video_device, dev);
- + cam_data *cam = video_get_drvdata(video_dev);
- +
- + if (cam->overlay_on)
- + return sprintf(buf, "overlay on\n");
- + else
- + return sprintf(buf, "overlay off\n");
- +}
- +static DEVICE_ATTR(fsl_v4l2_overlay_property, S_IRUGO, show_overlay, NULL);
- +
- +static ssize_t show_csi(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + struct video_device *video_dev = container_of(dev,
- + struct video_device, dev);
- + cam_data *cam = video_get_drvdata(video_dev);
- +
- + return sprintf(buf, "ipu%d_csi%d\n", cam->ipu_id, cam->csi);
- +}
- +static DEVICE_ATTR(fsl_csi_property, S_IRUGO, show_csi, NULL);
- +
- +/*!
- + * This function is called to probe the devices if registered.
- + *
- + * @param pdev the device structure used to give information on which device
- + * to probe
- + *
- + * @return The function returns 0 on success and -1 on failure.
- + */
- +static int mxc_v4l2_probe(struct platform_device *pdev)
- +{
- + /* Create cam and initialize it. */
- + cam_data *cam = kmalloc(sizeof(cam_data), GFP_KERNEL);
- + if (cam == NULL) {
- + pr_err("ERROR: v4l2 capture: failed to register camera\n");
- + return -1;
- + }
- +
- + init_camera_struct(cam, pdev);
- + pdev->dev.release = camera_platform_release;
- +
- + /* Set up the v4l2 device and register it*/
- + cam->self->priv = cam;
- + v4l2_int_device_register(cam->self);
- +
- + /* register v4l video device */
- + if (video_register_device(cam->video_dev, VFL_TYPE_GRABBER, video_nr)
- + == -1) {
- + kfree(cam);
- + cam = NULL;
- + pr_err("ERROR: v4l2 capture: video_register_device failed\n");
- + return -1;
- + }
- + pr_debug(" Video device registered: %s #%d\n",
- + cam->video_dev->name, cam->video_dev->minor);
- +
- + if (device_create_file(&cam->video_dev->dev,
- + &dev_attr_fsl_v4l2_capture_property))
- + dev_err(&pdev->dev, "Error on creating sysfs file"
- + " for capture\n");
- +
- + if (device_create_file(&cam->video_dev->dev,
- + &dev_attr_fsl_v4l2_overlay_property))
- + dev_err(&pdev->dev, "Error on creating sysfs file"
- + " for overlay\n");
- +
- + if (device_create_file(&cam->video_dev->dev,
- + &dev_attr_fsl_csi_property))
- + dev_err(&pdev->dev, "Error on creating sysfs file"
- + " for csi number\n");
- +
- + return 0;
- +}
- +
- +/*!
- + * This function is called to remove the devices when device unregistered.
- + *
- + * @param pdev the device structure used to give information on which device
- + * to remove
- + *
- + * @return The function returns 0 on success and -1 on failure.
- + */
- +static int mxc_v4l2_remove(struct platform_device *pdev)
- +{
- + cam_data *cam = (cam_data *)platform_get_drvdata(pdev);
- + if (cam->open_count) {
- + pr_err("ERROR: v4l2 capture:camera open "
- + "-- setting ops to NULL\n");
- + return -EBUSY;
- + } else {
- + device_remove_file(&cam->video_dev->dev,
- + &dev_attr_fsl_v4l2_capture_property);
- + device_remove_file(&cam->video_dev->dev,
- + &dev_attr_fsl_v4l2_overlay_property);
- + device_remove_file(&cam->video_dev->dev,
- + &dev_attr_fsl_csi_property);
- +
- + pr_info("V4L2 freeing image input device\n");
- + v4l2_int_device_unregister(cam->self);
- + video_unregister_device(cam->video_dev);
- +
- + mxc_free_frame_buf(cam);
- + kfree(cam);
- + }
- +
- + pr_info("V4L2 unregistering video\n");
- + return 0;
- +}
- +
- +/*!
- + * This function is called to put the sensor in a low power state.
- + * Refer to the document driver-model/driver.txt in the kernel source tree
- + * for more information.
- + *
- + * @param pdev the device structure used to give information on which I2C
- + * to suspend
- + * @param state the power state the device is entering
- + *
- + * @return The function returns 0 on success and -1 on failure.
- + */
- +static int mxc_v4l2_suspend(struct platform_device *pdev, pm_message_t state)
- +{
- + cam_data *cam = platform_get_drvdata(pdev);
- +
- + pr_debug("In MVC:mxc_v4l2_suspend\n");
- +
- + if (cam == NULL)
- + return -1;
- +
- + down(&cam->busy_lock);
- +
- + cam->low_power = true;
- +
- + if (cam->overlay_on == true)
- + stop_preview(cam);
- + if ((cam->capture_on == true) && cam->enc_disable)
- + cam->enc_disable(cam);
- +
- + if (cam->sensor && cam->open_count) {
- + if (cam->mclk_on[cam->mclk_source]) {
- + ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C,
- + cam->mclk_source,
- + false, false);
- + cam->mclk_on[cam->mclk_source] = false;
- + }
- + vidioc_int_s_power(cam->sensor, 0);
- + }
- +
- + up(&cam->busy_lock);
- +
- + return 0;
- +}
- +
- +/*!
- + * This function is called to bring the sensor back from a low power state.
- + * Refer to the document driver-model/driver.txt in the kernel source tree
- + * for more information.
- + *
- + * @param pdev the device structure
- + *
- + * @return The function returns 0 on success and -1 on failure
- + */
- +static int mxc_v4l2_resume(struct platform_device *pdev)
- +{
- + cam_data *cam = platform_get_drvdata(pdev);
- +
- + pr_debug("In MVC:mxc_v4l2_resume\n");
- +
- + if (cam == NULL)
- + return -1;
- +
- + down(&cam->busy_lock);
- +
- + cam->low_power = false;
- + wake_up_interruptible(&cam->power_queue);
- +
- + if (cam->sensor && cam->open_count) {
- + vidioc_int_s_power(cam->sensor, 1);
- +
- + if (!cam->mclk_on[cam->mclk_source]) {
- + ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C,
- + cam->mclk_source,
- + true, true);
- + cam->mclk_on[cam->mclk_source] = true;
- + }
- + }
- +
- + if (cam->overlay_on == true)
- + start_preview(cam);
- + if (cam->capture_on == true)
- + mxc_streamon(cam);
- +
- + up(&cam->busy_lock);
- +
- + return 0;
- +}
- +
- +/*!
- + * This structure contains pointers to the power management callback functions.
- + */
- +static struct platform_driver mxc_v4l2_driver = {
- + .driver = {
- + .name = "mxc_v4l2_capture",
- + .owner = THIS_MODULE,
- + .of_match_table = mxc_v4l2_dt_ids,
- + },
- + .id_table = imx_v4l2_devtype,
- + .probe = mxc_v4l2_probe,
- + .remove = mxc_v4l2_remove,
- + .suspend = mxc_v4l2_suspend,
- + .resume = mxc_v4l2_resume,
- + .shutdown = NULL,
- +};
- +
- +/*!
- + * Initializes the camera driver.
- + */
- +static int mxc_v4l2_master_attach(struct v4l2_int_device *slave)
- +{
- + cam_data *cam = slave->u.slave->master->priv;
- + struct v4l2_format cam_fmt;
- + int i;
- + struct sensor_data *sdata = slave->priv;
- +
- + pr_debug("In MVC: mxc_v4l2_master_attach\n");
- + pr_debug(" slave.name = %s\n", slave->name);
- + pr_debug(" master.name = %s\n", slave->u.slave->master->name);
- +
- + if (slave == NULL) {
- + pr_err("ERROR: v4l2 capture: slave parameter not valid.\n");
- + return -1;
- + }
- +
- + if (sdata->csi != cam->csi) {
- + pr_debug("%s: csi doesn't match\n", __func__);
- + return -1;
- + }
- +
- + cam->sensor = slave;
- +
- + if (cam->sensor_index < MXC_SENSOR_NUM) {
- + cam->all_sensors[cam->sensor_index] = slave;
- + cam->sensor_index++;
- + } else {
- + pr_err("ERROR: v4l2 capture: slave number exceeds the maximum.\n");
- + return -1;
- + }
- +
- + for (i = 0; i < cam->sensor_index; i++) {
- + vidioc_int_dev_exit(cam->all_sensors[i]);
- + vidioc_int_s_power(cam->all_sensors[i], 0);
- + }
- +
- + cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- + vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt);
- +
- + /* Used to detect TV in (type 1) vs. camera (type 0)*/
- + cam->device_type = cam_fmt.fmt.pix.priv;
- +
- + /* Set the input size to the ipu for this device */
- + cam->crop_bounds.top = cam->crop_bounds.left = 0;
- + cam->crop_bounds.width = cam_fmt.fmt.pix.width;
- + cam->crop_bounds.height = cam_fmt.fmt.pix.height;
- +
- + /* This also is the max crop size for this device. */
- + cam->crop_defrect.top = cam->crop_defrect.left = 0;
- + cam->crop_defrect.width = cam_fmt.fmt.pix.width;
- + cam->crop_defrect.height = cam_fmt.fmt.pix.height;
- +
- + /* At this point, this is also the current image size. */
- + cam->crop_current.top = cam->crop_current.left = 0;
- + cam->crop_current.width = cam_fmt.fmt.pix.width;
- + cam->crop_current.height = cam_fmt.fmt.pix.height;
- +
- + pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
- + __func__,
- + cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
- + pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
- + __func__,
- + cam->crop_bounds.width, cam->crop_bounds.height);
- + pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
- + __func__,
- + cam->crop_defrect.width, cam->crop_defrect.height);
- + pr_debug("End of %s: crop_current widthxheight %d x %d\n",
- + __func__,
- + cam->crop_current.width, cam->crop_current.height);
- +
- + return 0;
- +}
- +
- +/*!
- + * Disconnects the camera driver.
- + */
- +static void mxc_v4l2_master_detach(struct v4l2_int_device *slave)
- +{
- + unsigned int i;
- + cam_data *cam = slave->u.slave->master->priv;
- +
- + pr_debug("In MVC:mxc_v4l2_master_detach\n");
- +
- + if (cam->sensor_index > 1) {
- + for (i = 0; i < cam->sensor_index; i++) {
- + if (cam->all_sensors[i] != slave)
- + continue;
- + /* Move all the sensors behind this
- + * sensor one step forward
- + */
- + for (; i <= MXC_SENSOR_NUM - 2; i++)
- + cam->all_sensors[i] = cam->all_sensors[i+1];
- + break;
- + }
- + /* Point current sensor to the last one */
- + cam->sensor = cam->all_sensors[cam->sensor_index - 2];
- + } else
- + cam->sensor = NULL;
- +
- + cam->sensor_index--;
- + vidioc_int_dev_exit(slave);
- +}
- +
- +/*!
- + * Entry point for the V4L2
- + *
- + * @return Error code indicating success or failure
- + */
- +static __init int camera_init(void)
- +{
- + u8 err = 0;
- +
- + pr_debug("In MVC:camera_init\n");
- +
- + /* Register the device driver structure. */
- + err = platform_driver_register(&mxc_v4l2_driver);
- + if (err != 0) {
- + pr_err("ERROR: v4l2 capture:camera_init: "
- + "platform_driver_register failed.\n");
- + return err;
- + }
- +
- + return err;
- +}
- +
- +/*!
- + * Exit and cleanup for the V4L2
- + */
- +static void __exit camera_exit(void)
- +{
- + pr_debug("In MVC: camera_exit\n");
- +
- + platform_driver_unregister(&mxc_v4l2_driver);
- +}
- +
- +module_init(camera_init);
- +module_exit(camera_exit);
- +
- +module_param(video_nr, int, 0444);
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("V4L2 capture driver for Mxc based cameras");
- +MODULE_LICENSE("GPL");
- +MODULE_SUPPORTED_DEVICE("video");
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h linux-3.14.35/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h 2015-03-08 14:27:37.597684501 -0500
- @@ -0,0 +1,260 @@
- +/*
- + * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @defgroup MXC_V4L2_CAPTURE MXC V4L2 Video Capture Driver
- + */
- +/*!
- + * @file mxc_v4l2_capture.h
- + *
- + * @brief mxc V4L2 capture device API Header file
- + *
- + * It include all the defines for frame operations, also three structure defines
- + * use case ops structure, common v4l2 driver structure and frame structure.
- + *
- + * @ingroup MXC_V4L2_CAPTURE
- + */
- +#ifndef __MXC_V4L2_CAPTURE_H__
- +#define __MXC_V4L2_CAPTURE_H__
- +
- +#include <linux/uaccess.h>
- +#include <linux/list.h>
- +#include <linux/mxc_v4l2.h>
- +#include <linux/completion.h>
- +#include <linux/dmaengine.h>
- +#include <linux/pxp_dma.h>
- +#include <linux/ipu-v3.h>
- +#include <linux/platform_data/dma-imx.h>
- +
- +#include <media/v4l2-dev.h>
- +#include <media/v4l2-int-device.h>
- +
- +
- +#define FRAME_NUM 10
- +#define MXC_SENSOR_NUM 2
- +
- +enum imx_v4l2_devtype {
- + IMX5_V4L2,
- + IMX6_V4L2,
- +};
- +
- +/*!
- + * v4l2 frame structure.
- + */
- +struct mxc_v4l_frame {
- + u32 paddress;
- + void *vaddress;
- + int count;
- + int width;
- + int height;
- +
- + struct v4l2_buffer buffer;
- + struct list_head queue;
- + int index;
- + union {
- + int ipu_buf_num;
- + int csi_buf_num;
- + };
- +};
- +
- +/* Only for old version. Will go away soon. */
- +typedef struct {
- + u8 clk_mode;
- + u8 ext_vsync;
- + u8 Vsync_pol;
- + u8 Hsync_pol;
- + u8 pixclk_pol;
- + u8 data_pol;
- + u8 data_width;
- + u8 pack_tight;
- + u8 force_eof;
- + u8 data_en_pol;
- + u16 width;
- + u16 height;
- + u32 pixel_fmt;
- + u32 mclk;
- + u16 active_width;
- + u16 active_height;
- +} sensor_interface;
- +
- +/* Sensor control function */
- +/* Only for old version. Will go away soon. */
- +struct camera_sensor {
- + void (*set_color) (int bright, int saturation, int red, int green,
- + int blue);
- + void (*get_color) (int *bright, int *saturation, int *red, int *green,
- + int *blue);
- + void (*set_ae_mode) (int ae_mode);
- + void (*get_ae_mode) (int *ae_mode);
- + sensor_interface *(*config) (int *frame_rate, int high_quality);
- + sensor_interface *(*reset) (void);
- + void (*get_std) (v4l2_std_id *std);
- + void (*set_std) (v4l2_std_id std);
- + unsigned int csi;
- +};
- +
- +/*!
- + * common v4l2 driver structure.
- + */
- +typedef struct _cam_data {
- + struct video_device *video_dev;
- + int device_type;
- +
- + /* semaphore guard against SMP multithreading */
- + struct semaphore busy_lock;
- +
- + int open_count;
- +
- + /* params lock for this camera */
- + struct semaphore param_lock;
- +
- + /* Encoder */
- + struct list_head ready_q;
- + struct list_head done_q;
- + struct list_head working_q;
- + int ping_pong_csi;
- + spinlock_t queue_int_lock;
- + spinlock_t dqueue_int_lock;
- + struct mxc_v4l_frame frame[FRAME_NUM];
- + struct mxc_v4l_frame dummy_frame;
- + wait_queue_head_t enc_queue;
- + int enc_counter;
- + dma_addr_t rot_enc_bufs[2];
- + void *rot_enc_bufs_vaddr[2];
- + int rot_enc_buf_size[2];
- + enum v4l2_buf_type type;
- +
- + /* still image capture */
- + wait_queue_head_t still_queue;
- + int still_counter;
- + dma_addr_t still_buf[2];
- + void *still_buf_vaddr;
- +
- + /* overlay */
- + struct v4l2_window win;
- + struct v4l2_framebuffer v4l2_fb;
- + dma_addr_t vf_bufs[2];
- + void *vf_bufs_vaddr[2];
- + int vf_bufs_size[2];
- + dma_addr_t rot_vf_bufs[2];
- + void *rot_vf_bufs_vaddr[2];
- + int rot_vf_buf_size[2];
- + bool overlay_active;
- + int output;
- + struct fb_info *overlay_fb;
- + int fb_origin_std;
- + struct work_struct csi_work_struct;
- +
- + /* v4l2 format */
- + struct v4l2_format v2f;
- + int rotation; /* for IPUv1 and IPUv3, this means encoder rotation */
- + int vf_rotation; /* viewfinder rotation only for IPUv1 and IPUv3 */
- + struct v4l2_mxc_offset offset;
- +
- + /* V4l2 control bit */
- + int bright;
- + int hue;
- + int contrast;
- + int saturation;
- + int red;
- + int green;
- + int blue;
- + int ae_mode;
- +
- + /* standard */
- + struct v4l2_streamparm streamparm;
- + struct v4l2_standard standard;
- + bool standard_autodetect;
- +
- + /* crop */
- + struct v4l2_rect crop_bounds;
- + struct v4l2_rect crop_defrect;
- + struct v4l2_rect crop_current;
- +
- + int (*enc_update_eba) (struct ipu_soc *ipu, dma_addr_t eba,
- + int *bufferNum);
- + int (*enc_enable) (void *private);
- + int (*enc_disable) (void *private);
- + int (*enc_enable_csi) (void *private);
- + int (*enc_disable_csi) (void *private);
- + void (*enc_callback) (u32 mask, void *dev);
- + int (*vf_start_adc) (void *private);
- + int (*vf_stop_adc) (void *private);
- + int (*vf_start_sdc) (void *private);
- + int (*vf_stop_sdc) (void *private);
- + int (*vf_enable_csi) (void *private);
- + int (*vf_disable_csi) (void *private);
- + int (*csi_start) (void *private);
- + int (*csi_stop) (void *private);
- +
- + /* misc status flag */
- + bool overlay_on;
- + bool capture_on;
- + int overlay_pid;
- + int capture_pid;
- + bool low_power;
- + wait_queue_head_t power_queue;
- + unsigned int ipu_id;
- + unsigned int csi;
- + u8 mclk_source;
- + bool mclk_on[2]; /* two mclk sources at most now */
- + int current_input;
- +
- + int local_buf_num;
- +
- + /* camera sensor interface */
- + struct camera_sensor *cam_sensor; /* old version */
- + struct v4l2_int_device *all_sensors[MXC_SENSOR_NUM];
- + struct v4l2_int_device *sensor;
- + struct v4l2_int_device *self;
- + int sensor_index;
- + void *ipu;
- + enum imx_v4l2_devtype devtype;
- +
- + /* v4l2 buf elements related to PxP DMA */
- + struct completion pxp_tx_cmpl;
- + struct pxp_channel *pxp_chan;
- + struct pxp_config_data pxp_conf;
- + struct dma_async_tx_descriptor *txd;
- + dma_cookie_t cookie;
- + struct scatterlist sg[2];
- +} cam_data;
- +
- +struct sensor_data {
- + const struct ov5642_platform_data *platform_data;
- + struct v4l2_int_device *v4l2_int_device;
- + struct i2c_client *i2c_client;
- + struct v4l2_pix_format pix;
- + struct v4l2_captureparm streamcap;
- + bool on;
- +
- + /* control settings */
- + int brightness;
- + int hue;
- + int contrast;
- + int saturation;
- + int red;
- + int green;
- + int blue;
- + int ae_mode;
- +
- + u32 mclk;
- + u8 mclk_source;
- + struct clk *sensor_clk;
- + int csi;
- +
- + void (*io_init)(void);
- +};
- +
- +void set_mclk_rate(uint32_t *p_mclk_freq, uint32_t csi);
- +#endif /* __MXC_V4L2_CAPTURE_H__ */
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/ov5640.c linux-3.14.35/drivers/media/platform/mxc/capture/ov5640.c
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/ov5640.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/ov5640.c 2015-03-08 14:27:37.597684501 -0500
- @@ -0,0 +1,1951 @@
- +/*
- + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#include <linux/clk.h>
- +#include <linux/delay.h>
- +#include <linux/device.h>
- +#include <linux/i2c.h>
- +#include <linux/init.h>
- +#include <linux/module.h>
- +#include <linux/of_device.h>
- +#include <linux/of_gpio.h>
- +#include <linux/pinctrl/consumer.h>
- +#include <linux/regulator/consumer.h>
- +#include <media/v4l2-chip-ident.h>
- +#include <media/v4l2-int-device.h>
- +#include "mxc_v4l2_capture.h"
- +
- +#define OV5640_VOLTAGE_ANALOG 2800000
- +#define OV5640_VOLTAGE_DIGITAL_CORE 1500000
- +#define OV5640_VOLTAGE_DIGITAL_IO 1800000
- +
- +#define MIN_FPS 15
- +#define MAX_FPS 30
- +#define DEFAULT_FPS 30
- +
- +#define OV5640_XCLK_MIN 6000000
- +#define OV5640_XCLK_MAX 24000000
- +
- +#define OV5640_CHIP_ID_HIGH_BYTE 0x300A
- +#define OV5640_CHIP_ID_LOW_BYTE 0x300B
- +
- +enum ov5640_mode {
- + ov5640_mode_MIN = 0,
- + ov5640_mode_VGA_640_480 = 0,
- + ov5640_mode_QVGA_320_240 = 1,
- + ov5640_mode_NTSC_720_480 = 2,
- + ov5640_mode_PAL_720_576 = 3,
- + ov5640_mode_720P_1280_720 = 4,
- + ov5640_mode_1080P_1920_1080 = 5,
- + ov5640_mode_QSXGA_2592_1944 = 6,
- + ov5640_mode_QCIF_176_144 = 7,
- + ov5640_mode_XGA_1024_768 = 8,
- + ov5640_mode_MAX = 8
- +};
- +
- +enum ov5640_frame_rate {
- + ov5640_15_fps,
- + ov5640_30_fps
- +};
- +
- +static int ov5640_framerates[] = {
- + [ov5640_15_fps] = 15,
- + [ov5640_30_fps] = 30,
- +};
- +
- +struct reg_value {
- + u16 u16RegAddr;
- + u8 u8Val;
- + u8 u8Mask;
- + u32 u32Delay_ms;
- +};
- +
- +struct ov5640_mode_info {
- + enum ov5640_mode mode;
- + u32 width;
- + u32 height;
- + struct reg_value *init_data_ptr;
- + u32 init_data_size;
- +};
- +
- +/*!
- + * Maintains the information on the current state of the sesor.
- + */
- +static struct sensor_data ov5640_data;
- +static int pwn_gpio, rst_gpio;
- +static int prev_sysclk;
- +static int AE_Target = 52, night_mode;
- +static int prev_HTS;
- +static int AE_high, AE_low;
- +
- +static struct reg_value ov5640_global_init_setting[] = {
- + {0x3008, 0x42, 0, 0},
- + {0x3103, 0x03, 0, 0}, {0x3017, 0xff, 0, 0}, {0x3018, 0xff, 0, 0},
- + {0x3034, 0x1a, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0},
- + {0x3630, 0x36, 0, 0}, {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0},
- + {0x3633, 0x12, 0, 0}, {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0},
- + {0x3703, 0x5a, 0, 0}, {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0},
- + {0x370b, 0x60, 0, 0}, {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0},
- + {0x3906, 0x10, 0, 0}, {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0},
- + {0x3600, 0x08, 0, 0}, {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0},
- + {0x3620, 0x52, 0, 0}, {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0},
- + {0x3a13, 0x43, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
- + {0x3635, 0x13, 0, 0}, {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0},
- + {0x3622, 0x01, 0, 0}, {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0},
- + {0x3c05, 0x98, 0, 0}, {0x3c06, 0x00, 0, 0}, {0x3c07, 0x07, 0, 0},
- + {0x3c08, 0x00, 0, 0}, {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0},
- + {0x3c0b, 0x40, 0, 0}, {0x3810, 0x00, 0, 0}, {0x3811, 0x10, 0, 0},
- + {0x3812, 0x00, 0, 0}, {0x3708, 0x64, 0, 0}, {0x4001, 0x02, 0, 0},
- + {0x4005, 0x1a, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3004, 0xff, 0, 0},
- + {0x300e, 0x58, 0, 0}, {0x302e, 0x00, 0, 0}, {0x4300, 0x30, 0, 0},
- + {0x501f, 0x00, 0, 0}, {0x440e, 0x00, 0, 0}, {0x5000, 0xa7, 0, 0},
- + {0x3008, 0x02, 0, 0},
- +};
- +
- +static struct reg_value ov5640_init_setting_30fps_VGA[] = {
- + {0x3008, 0x42, 0, 0},
- + {0x3103, 0x03, 0, 0}, {0x3017, 0xff, 0, 0}, {0x3018, 0xff, 0, 0},
- + {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, {0x3036, 0x46, 0, 0},
- + {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0},
- + {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
- + {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
- + {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
- + {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0},
- + {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0},
- + {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0},
- + {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0},
- + {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0},
- + {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0},
- + {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0},
- + {0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
- + {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
- + {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
- + {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
- + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
- + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0},
- + {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0},
- + {0x300e, 0x58, 0, 0}, {0x302e, 0x00, 0, 0}, {0x4300, 0x30, 0, 0},
- + {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0},
- + {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- + {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, {0x5000, 0xa7, 0, 0},
- + {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0xf2, 0, 0},
- + {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
- + {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0}, {0x5187, 0x09, 0, 0},
- + {0x5188, 0x09, 0, 0}, {0x5189, 0x88, 0, 0}, {0x518a, 0x54, 0, 0},
- + {0x518b, 0xee, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x50, 0, 0},
- + {0x518e, 0x34, 0, 0}, {0x518f, 0x6b, 0, 0}, {0x5190, 0x46, 0, 0},
- + {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
- + {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
- + {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x6c, 0, 0},
- + {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x09, 0, 0},
- + {0x519d, 0x2b, 0, 0}, {0x519e, 0x38, 0, 0}, {0x5381, 0x1e, 0, 0},
- + {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0}, {0x5384, 0x0a, 0, 0},
- + {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0}, {0x5387, 0x7c, 0, 0},
- + {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0}, {0x538a, 0x01, 0, 0},
- + {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0}, {0x5301, 0x30, 0, 0},
- + {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0}, {0x5304, 0x08, 0, 0},
- + {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0}, {0x5307, 0x16, 0, 0},
- + {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0}, {0x530b, 0x04, 0, 0},
- + {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0}, {0x5481, 0x08, 0, 0},
- + {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0}, {0x5484, 0x51, 0, 0},
- + {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0}, {0x5487, 0x7d, 0, 0},
- + {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0}, {0x548a, 0x9a, 0, 0},
- + {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0}, {0x548d, 0xcd, 0, 0},
- + {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0}, {0x5490, 0x1d, 0, 0},
- + {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x10, 0, 0},
- + {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0}, {0x558b, 0xf8, 0, 0},
- + {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0}, {0x5802, 0x0f, 0, 0},
- + {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0}, {0x5805, 0x26, 0, 0},
- + {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0}, {0x5808, 0x05, 0, 0},
- + {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0}, {0x580b, 0x0d, 0, 0},
- + {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0}, {0x580e, 0x00, 0, 0},
- + {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0}, {0x5811, 0x09, 0, 0},
- + {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x00, 0, 0},
- + {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0}, {0x5817, 0x08, 0, 0},
- + {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0}, {0x581a, 0x05, 0, 0},
- + {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0}, {0x581d, 0x0e, 0, 0},
- + {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0}, {0x5820, 0x11, 0, 0},
- + {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0}, {0x5823, 0x28, 0, 0},
- + {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0}, {0x5826, 0x08, 0, 0},
- + {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0}, {0x5829, 0x26, 0, 0},
- + {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0}, {0x582c, 0x24, 0, 0},
- + {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0}, {0x582f, 0x22, 0, 0},
- + {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0}, {0x5832, 0x24, 0, 0},
- + {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0}, {0x5835, 0x22, 0, 0},
- + {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0}, {0x5838, 0x44, 0, 0},
- + {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0}, {0x583b, 0x28, 0, 0},
- + {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0}, {0x5025, 0x00, 0, 0},
- + {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0}, {0x3a1b, 0x30, 0, 0},
- + {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x14, 0, 0},
- + {0x3008, 0x02, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
- + {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
- + {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
- + {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
- + {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
- + {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
- + {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0},
- + {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
- + {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
- + {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
- + {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
- + {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
- + {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
- + {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
- + {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
- + {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3503, 0x00, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
- + {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
- + {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
- + {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
- + {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
- + {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0},
- + {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
- + {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
- + {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
- + {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
- + {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
- + {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
- + {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
- + {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
- + {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3503, 0x00, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
- + {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
- + {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
- + {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
- + {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
- + {0x3807, 0x9b, 0, 0}, {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0},
- + {0x380a, 0x00, 0, 0}, {0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0},
- + {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
- + {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
- + {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
- + {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
- + {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
- + {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
- + {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
- + {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
- + {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
- + {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
- + {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
- + {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
- + {0x3807, 0x9b, 0, 0}, {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0},
- + {0x380a, 0x00, 0, 0}, {0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0},
- + {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
- + {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
- + {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
- + {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
- + {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
- + {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
- + {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
- + {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
- + {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
- + {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
- + {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
- + {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0},
- + {0x3807, 0xd4, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
- + {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
- + {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
- + {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
- + {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
- + {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
- + {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
- + {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
- + {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
- + {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_15fps_NTSC_720_480[] = {
- + {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
- + {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
- + {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
- + {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0},
- + {0x3807, 0xd4, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
- + {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
- + {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
- + {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
- + {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
- + {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
- + {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
- + {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
- + {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
- + {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
- + {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
- + {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
- + {0x3801, 0x60, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
- + {0x3804, 0x09, 0, 0}, {0x3805, 0x7e, 0, 0}, {0x3806, 0x07, 0, 0},
- + {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
- + {0x380a, 0x02, 0, 0}, {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0},
- + {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
- + {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
- + {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
- + {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
- + {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
- + {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
- + {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
- + {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_15fps_PAL_720_576[] = {
- + {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
- + {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
- + {0x3801, 0x60, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
- + {0x3804, 0x09, 0, 0}, {0x3805, 0x7e, 0, 0}, {0x3806, 0x07, 0, 0},
- + {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
- + {0x380a, 0x02, 0, 0}, {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0},
- + {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
- + {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
- + {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
- + {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
- + {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
- + {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
- + {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
- + {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
- + {0x3035, 0x21, 0, 0}, {0x3036, 0x69, 0, 0}, {0x3c07, 0x07, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
- + {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
- + {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
- + {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3813, 0x04, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3709, 0x52, 0, 0},
- + {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0}, {0x3a03, 0xe0, 0, 0},
- + {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe0, 0, 0}, {0x4004, 0x02, 0, 0},
- + {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
- + {0x4837, 0x16, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
- + {0x3503, 0x00, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_15fps_720P_1280_720[] = {
- + {0x3035, 0x41, 0, 0}, {0x3036, 0x69, 0, 0}, {0x3c07, 0x07, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
- + {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
- + {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
- + {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3813, 0x04, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3709, 0x52, 0, 0},
- + {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0}, {0x3a03, 0xe0, 0, 0},
- + {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe0, 0, 0}, {0x4004, 0x02, 0, 0},
- + {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
- + {0x4837, 0x16, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
- + {0x3503, 0x00, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
- + {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
- + {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
- + {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
- + {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
- + {0x3807, 0x9b, 0, 0}, {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0},
- + {0x380a, 0x00, 0, 0}, {0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0},
- + {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
- + {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
- + {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
- + {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
- + {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
- + {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
- + {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
- + {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
- + {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
- + {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
- + {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
- + {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
- + {0x3807, 0x9b, 0, 0}, {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0},
- + {0x380a, 0x00, 0, 0}, {0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0},
- + {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
- + {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
- + {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
- + {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
- + {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
- + {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
- + {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
- + {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
- + {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
- + {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
- + {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
- + {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
- + {0x3807, 0x9b, 0, 0}, {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0},
- + {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0}, {0x380c, 0x07, 0, 0},
- + {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
- + {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
- + {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
- + {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
- + {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
- + {0x460c, 0x20, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x01, 0, 0},
- + {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
- + {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
- + {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
- + {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
- + {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
- + {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
- + {0x3807, 0x9b, 0, 0}, {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0},
- + {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0}, {0x380c, 0x07, 0, 0},
- + {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
- + {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
- + {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
- + {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
- + {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
- + {0x460c, 0x20, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x01, 0, 0},
- + {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
- + {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
- +};
- +
- +
- +static struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
- + {0x3c07, 0x07, 0, 0}, {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0},
- + {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0},
- + {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0xee, 0, 0},
- + {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x05, 0, 0},
- + {0x3807, 0xc3, 0, 0}, {0x3808, 0x07, 0, 0}, {0x3809, 0x80, 0, 0},
- + {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0}, {0x380c, 0x0b, 0, 0},
- + {0x380d, 0x1c, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0},
- + {0x3813, 0x04, 0, 0}, {0x3618, 0x04, 0, 0}, {0x3612, 0x2b, 0, 0},
- + {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x07, 0, 0},
- + {0x3a03, 0xae, 0, 0}, {0x3a14, 0x07, 0, 0}, {0x3a15, 0xae, 0, 0},
- + {0x4004, 0x06, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
- + {0x4713, 0x02, 0, 0}, {0x4407, 0x0c, 0, 0}, {0x460b, 0x37, 0, 0},
- + {0x460c, 0x20, 0, 0}, {0x4837, 0x2c, 0, 0}, {0x3824, 0x01, 0, 0},
- + {0x5001, 0x83, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
- + {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
- + {0x3c07, 0x07, 0, 0}, {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0},
- + {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0},
- + {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0},
- + {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
- + {0x3807, 0x9f, 0, 0}, {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0},
- + {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0},
- + {0x380d, 0x1c, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0},
- + {0x3813, 0x04, 0, 0}, {0x3618, 0x04, 0, 0}, {0x3612, 0x2b, 0, 0},
- + {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x07, 0, 0},
- + {0x3a03, 0xae, 0, 0}, {0x3a14, 0x07, 0, 0}, {0x3a15, 0xae, 0, 0},
- + {0x4004, 0x06, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
- + {0x4713, 0x02, 0, 0}, {0x4407, 0x0c, 0, 0}, {0x460b, 0x37, 0, 0},
- + {0x460c, 0x20, 0, 0}, {0x4837, 0x2c, 0, 0}, {0x3824, 0x01, 0, 0},
- + {0x5001, 0x83, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
- + {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
- +};
- +
- +static struct ov5640_mode_info ov5640_mode_info_data[2][ov5640_mode_MAX + 1] = {
- + {
- + {ov5640_mode_VGA_640_480, 640, 480,
- + ov5640_setting_15fps_VGA_640_480,
- + ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)},
- + {ov5640_mode_QVGA_320_240, 320, 240,
- + ov5640_setting_15fps_QVGA_320_240,
- + ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)},
- + {ov5640_mode_NTSC_720_480, 720, 480,
- + ov5640_setting_15fps_NTSC_720_480,
- + ARRAY_SIZE(ov5640_setting_15fps_NTSC_720_480)},
- + {ov5640_mode_PAL_720_576, 720, 576,
- + ov5640_setting_15fps_PAL_720_576,
- + ARRAY_SIZE(ov5640_setting_15fps_PAL_720_576)},
- + {ov5640_mode_720P_1280_720, 1280, 720,
- + ov5640_setting_15fps_720P_1280_720,
- + ARRAY_SIZE(ov5640_setting_15fps_720P_1280_720)},
- + {ov5640_mode_1080P_1920_1080, 1920, 1080,
- + ov5640_setting_15fps_1080P_1920_1080,
- + ARRAY_SIZE(ov5640_setting_15fps_1080P_1920_1080)},
- + {ov5640_mode_QSXGA_2592_1944, 2592, 1944,
- + ov5640_setting_15fps_QSXGA_2592_1944,
- + ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
- + {ov5640_mode_QCIF_176_144, 176, 144,
- + ov5640_setting_15fps_QCIF_176_144,
- + ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)},
- + {ov5640_mode_XGA_1024_768, 1024, 768,
- + ov5640_setting_15fps_XGA_1024_768,
- + ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)},
- + },
- + {
- + {ov5640_mode_VGA_640_480, 640, 480,
- + ov5640_setting_30fps_VGA_640_480,
- + ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
- + {ov5640_mode_QVGA_320_240, 320, 240,
- + ov5640_setting_30fps_QVGA_320_240,
- + ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)},
- + {ov5640_mode_NTSC_720_480, 720, 480,
- + ov5640_setting_30fps_NTSC_720_480,
- + ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
- + {ov5640_mode_PAL_720_576, 720, 576,
- + ov5640_setting_30fps_PAL_720_576,
- + ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)},
- + {ov5640_mode_720P_1280_720, 1280, 720,
- + ov5640_setting_30fps_720P_1280_720,
- + ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)},
- + {ov5640_mode_1080P_1920_1080, 0, 0, NULL, 0},
- + {ov5640_mode_QSXGA_2592_1944, 0, 0, NULL, 0},
- + {ov5640_mode_QCIF_176_144, 176, 144,
- + ov5640_setting_30fps_QCIF_176_144,
- + ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)},
- + {ov5640_mode_XGA_1024_768, 1024, 768,
- + ov5640_setting_30fps_XGA_1024_768,
- + ARRAY_SIZE(ov5640_setting_30fps_XGA_1024_768)},
- + },
- +};
- +
- +static struct regulator *io_regulator;
- +static struct regulator *core_regulator;
- +static struct regulator *analog_regulator;
- +
- +static int ov5640_probe(struct i2c_client *adapter,
- + const struct i2c_device_id *device_id);
- +static int ov5640_remove(struct i2c_client *client);
- +
- +static s32 ov5640_read_reg(u16 reg, u8 *val);
- +static s32 ov5640_write_reg(u16 reg, u8 val);
- +
- +static const struct i2c_device_id ov5640_id[] = {
- + {"ov5640", 0},
- + {"ov564x", 0},
- + {},
- +};
- +
- +MODULE_DEVICE_TABLE(i2c, ov5640_id);
- +
- +static struct i2c_driver ov5640_i2c_driver = {
- + .driver = {
- + .owner = THIS_MODULE,
- + .name = "ov5640",
- + },
- + .probe = ov5640_probe,
- + .remove = ov5640_remove,
- + .id_table = ov5640_id,
- +};
- +
- +static inline void ov5640_power_down(int enable)
- +{
- + gpio_set_value(pwn_gpio, enable);
- +
- + msleep(2);
- +}
- +
- +static inline void ov5640_reset(void)
- +{
- + /* camera reset */
- + gpio_set_value(rst_gpio, 1);
- +
- + /* camera power down */
- + gpio_set_value(pwn_gpio, 1);
- + msleep(5);
- + gpio_set_value(pwn_gpio, 0);
- + msleep(5);
- + gpio_set_value(rst_gpio, 0);
- + msleep(1);
- + gpio_set_value(rst_gpio, 1);
- + msleep(5);
- + gpio_set_value(pwn_gpio, 1);
- +}
- +
- +static int ov5640_regulator_enable(struct device *dev)
- +{
- + int ret = 0;
- +
- + io_regulator = devm_regulator_get(dev, "DOVDD");
- + if (!IS_ERR(io_regulator)) {
- + regulator_set_voltage(io_regulator,
- + OV5640_VOLTAGE_DIGITAL_IO,
- + OV5640_VOLTAGE_DIGITAL_IO);
- + ret = regulator_enable(io_regulator);
- + if (ret) {
- + dev_err(dev, "set io voltage failed\n");
- + return ret;
- + } else {
- + dev_dbg(dev, "set io voltage ok\n");
- + }
- + } else {
- + io_regulator = NULL;
- + dev_warn(dev, "cannot get io voltage\n");
- + }
- +
- + core_regulator = devm_regulator_get(dev, "DVDD");
- + if (!IS_ERR(core_regulator)) {
- + regulator_set_voltage(core_regulator,
- + OV5640_VOLTAGE_DIGITAL_CORE,
- + OV5640_VOLTAGE_DIGITAL_CORE);
- + ret = regulator_enable(core_regulator);
- + if (ret) {
- + dev_err(dev, "set core voltage failed\n");
- + return ret;
- + } else {
- + dev_dbg(dev, "set core voltage ok\n");
- + }
- + } else {
- + core_regulator = NULL;
- + dev_warn(dev, "cannot get core voltage\n");
- + }
- +
- + analog_regulator = devm_regulator_get(dev, "AVDD");
- + if (!IS_ERR(analog_regulator)) {
- + regulator_set_voltage(analog_regulator,
- + OV5640_VOLTAGE_ANALOG,
- + OV5640_VOLTAGE_ANALOG);
- + ret = regulator_enable(analog_regulator);
- + if (ret) {
- + dev_err(dev, "set analog voltage failed\n");
- + return ret;
- + } else {
- + dev_dbg(dev, "set analog voltage ok\n");
- + }
- + } else {
- + analog_regulator = NULL;
- + dev_warn(dev, "cannot get analog voltage\n");
- + }
- +
- + return ret;
- +}
- +
- +static s32 ov5640_write_reg(u16 reg, u8 val)
- +{
- + u8 au8Buf[3] = {0};
- +
- + au8Buf[0] = reg >> 8;
- + au8Buf[1] = reg & 0xff;
- + au8Buf[2] = val;
- +
- + if (i2c_master_send(ov5640_data.i2c_client, au8Buf, 3) < 0) {
- + pr_err("%s:write reg error:reg=%x,val=%x\n",
- + __func__, reg, val);
- + return -1;
- + }
- +
- + return 0;
- +}
- +
- +static s32 ov5640_read_reg(u16 reg, u8 *val)
- +{
- + u8 au8RegBuf[2] = {0};
- + u8 u8RdVal = 0;
- +
- + au8RegBuf[0] = reg >> 8;
- + au8RegBuf[1] = reg & 0xff;
- +
- + if (2 != i2c_master_send(ov5640_data.i2c_client, au8RegBuf, 2)) {
- + pr_err("%s:write reg error:reg=%x\n",
- + __func__, reg);
- + return -1;
- + }
- +
- + if (1 != i2c_master_recv(ov5640_data.i2c_client, &u8RdVal, 1)) {
- + pr_err("%s:read reg error:reg=%x,val=%x\n",
- + __func__, reg, u8RdVal);
- + return -1;
- + }
- +
- + *val = u8RdVal;
- +
- + return u8RdVal;
- +}
- +
- +static void ov5640_soft_reset(void)
- +{
- + /* sysclk from pad */
- + ov5640_write_reg(0x3103, 0x11);
- +
- + /* software reset */
- + ov5640_write_reg(0x3008, 0x82);
- +
- + /* delay at least 5ms */
- + msleep(10);
- +}
- +
- +/* set sensor driver capability
- + * 0x302c[7:6] - strength
- + 00 - 1x
- + 01 - 2x
- + 10 - 3x
- + 11 - 4x
- + */
- +static int ov5640_driver_capability(int strength)
- +{
- + u8 temp = 0;
- +
- + if (strength > 4 || strength < 1) {
- + pr_err("The valid driver capability of ov5640 is 1x~4x\n");
- + return -EINVAL;
- + }
- +
- + ov5640_read_reg(0x302c, &temp);
- +
- + temp &= ~0xc0; /* clear [7:6] */
- + temp |= ((strength - 1) << 6); /* set [7:6] */
- +
- + ov5640_write_reg(0x302c, temp);
- +
- + return 0;
- +}
- +
- +/* calculate sysclk */
- +static int ov5640_get_sysclk(void)
- +{
- + int xvclk = ov5640_data.mclk / 10000;
- + int sysclk;
- + int temp1, temp2;
- + int Multiplier, PreDiv, VCO, SysDiv, Pll_rdiv, Bit_div2x, sclk_rdiv;
- + int sclk_rdiv_map[] = {1, 2, 4, 8};
- + u8 regval = 0;
- +
- + temp1 = ov5640_read_reg(0x3034, ®val);
- + temp2 = temp1 & 0x0f;
- + if (temp2 == 8 || temp2 == 10) {
- + Bit_div2x = temp2 / 2;
- + } else {
- + pr_err("ov5640: unsupported bit mode %d\n", temp2);
- + return -1;
- + }
- +
- + temp1 = ov5640_read_reg(0x3035, ®val);
- + SysDiv = temp1 >> 4;
- + if (SysDiv == 0)
- + SysDiv = 16;
- +
- + temp1 = ov5640_read_reg(0x3036, ®val);
- + Multiplier = temp1;
- + temp1 = ov5640_read_reg(0x3037, ®val);
- + PreDiv = temp1 & 0x0f;
- + Pll_rdiv = ((temp1 >> 4) & 0x01) + 1;
- +
- + temp1 = ov5640_read_reg(0x3108, ®val);
- + temp2 = temp1 & 0x03;
- +
- + sclk_rdiv = sclk_rdiv_map[temp2];
- + VCO = xvclk * Multiplier / PreDiv;
- + sysclk = VCO / SysDiv / Pll_rdiv * 2 / Bit_div2x / sclk_rdiv;
- +
- + return sysclk;
- +}
- +
- +/* read HTS from register settings */
- +static int ov5640_get_HTS(void)
- +{
- + int HTS;
- + u8 temp = 0;
- +
- + HTS = ov5640_read_reg(0x380c, &temp);
- + HTS = (HTS<<8) + ov5640_read_reg(0x380d, &temp);
- + return HTS;
- +}
- +
- +/* read VTS from register settings */
- +static int ov5640_get_VTS(void)
- +{
- + int VTS;
- + u8 temp = 0;
- +
- + VTS = ov5640_read_reg(0x380e, &temp);
- + VTS = (VTS<<8) + ov5640_read_reg(0x380f, &temp);
- +
- + return VTS;
- +}
- +
- +/* write VTS to registers */
- +static int ov5640_set_VTS(int VTS)
- +{
- + int temp;
- +
- + temp = VTS & 0xff;
- + ov5640_write_reg(0x380f, temp);
- +
- + temp = VTS>>8;
- + ov5640_write_reg(0x380e, temp);
- + return 0;
- +}
- +
- +/* read shutter, in number of line period */
- +static int ov5640_get_shutter(void)
- +{
- + int shutter;
- + u8 regval;
- +
- + shutter = (ov5640_read_reg(0x03500, ®val) & 0x0f);
- +
- + shutter = (shutter<<8) + ov5640_read_reg(0x3501, ®val);
- + shutter = (shutter<<4) + (ov5640_read_reg(0x3502, ®val)>>4);
- +
- + return shutter;
- +}
- +
- +/* write shutter, in number of line period */
- +static int ov5640_set_shutter(int shutter)
- +{
- + int temp;
- +
- + shutter = shutter & 0xffff;
- + temp = shutter & 0x0f;
- + temp = temp<<4;
- + ov5640_write_reg(0x3502, temp);
- +
- + temp = shutter & 0xfff;
- + temp = temp>>4;
- + ov5640_write_reg(0x3501, temp);
- +
- + temp = shutter>>12;
- + ov5640_write_reg(0x3500, temp);
- +
- + return 0;
- +}
- +
- +/* read gain, 16 = 1x */
- +static int ov5640_get_gain16(void)
- +{
- + int gain16;
- + u8 regval;
- +
- + gain16 = ov5640_read_reg(0x350a, ®val) & 0x03;
- + gain16 = (gain16<<8) + ov5640_read_reg(0x350b, ®val);
- +
- + return gain16;
- +}
- +
- +/* write gain, 16 = 1x */
- +static int ov5640_set_gain16(int gain16)
- +{
- + int temp;
- +
- + gain16 = gain16 & 0x3ff;
- + temp = gain16 & 0xff;
- +
- + ov5640_write_reg(0x350b, temp);
- + temp = gain16>>8;
- +
- + ov5640_write_reg(0x350a, temp);
- + return 0;
- +}
- +
- +/* get banding filter value */
- +static int ov5640_get_light_freq(void)
- +{
- + int temp, temp1, light_frequency;
- + u8 regval;
- +
- + temp = ov5640_read_reg(0x3c01, ®val);
- + if (temp & 0x80) {
- + /* manual */
- + temp1 = ov5640_read_reg(0x3c00, ®val);
- + if (temp1 & 0x04) {
- + /* 50Hz */
- + light_frequency = 50;
- + } else {
- + /* 60Hz */
- + light_frequency = 60;
- + }
- + } else {
- + /* auto */
- + temp1 = ov5640_read_reg(0x3c0c, ®val);
- + if (temp1 & 0x01) {
- + /* 50Hz */
- + light_frequency = 50;
- + } else {
- + /* 60Hz */
- + light_frequency = 60;
- + }
- + }
- +
- + return light_frequency;
- +}
- +
- +static void ov5640_set_bandingfilter(void)
- +{
- + int prev_VTS;
- + int band_step60, max_band60, band_step50, max_band50;
- +
- + /* read preview PCLK */
- + prev_sysclk = ov5640_get_sysclk();
- +
- + /* read preview HTS */
- + prev_HTS = ov5640_get_HTS();
- +
- + /* read preview VTS */
- + prev_VTS = ov5640_get_VTS();
- +
- + /* calculate banding filter */
- + /* 60Hz */
- + band_step60 = prev_sysclk * 100/prev_HTS * 100/120;
- + ov5640_write_reg(0x3a0a, (band_step60 >> 8));
- + ov5640_write_reg(0x3a0b, (band_step60 & 0xff));
- +
- + max_band60 = (int)((prev_VTS-4)/band_step60);
- + ov5640_write_reg(0x3a0d, max_band60);
- +
- + /* 50Hz */
- + band_step50 = prev_sysclk * 100/prev_HTS;
- + ov5640_write_reg(0x3a08, (band_step50 >> 8));
- + ov5640_write_reg(0x3a09, (band_step50 & 0xff));
- +
- + max_band50 = (int)((prev_VTS-4)/band_step50);
- + ov5640_write_reg(0x3a0e, max_band50);
- +}
- +
- +/* stable in high */
- +static int ov5640_set_AE_target(int target)
- +{
- + int fast_high, fast_low;
- +
- + AE_low = target * 23 / 25; /* 0.92 */
- + AE_high = target * 27 / 25; /* 1.08 */
- + fast_high = AE_high << 1;
- +
- + if (fast_high > 255)
- + fast_high = 255;
- + fast_low = AE_low >> 1;
- +
- + ov5640_write_reg(0x3a0f, AE_high);
- + ov5640_write_reg(0x3a10, AE_low);
- + ov5640_write_reg(0x3a1b, AE_high);
- + ov5640_write_reg(0x3a1e, AE_low);
- + ov5640_write_reg(0x3a11, fast_high);
- + ov5640_write_reg(0x3a1f, fast_low);
- +
- + return 0;
- +}
- +
- +/* enable = 0 to turn off night mode
- + enable = 1 to turn on night mode */
- +static int ov5640_set_night_mode(int enable)
- +{
- + u8 mode;
- +
- + ov5640_read_reg(0x3a00, &mode);
- +
- + if (enable) {
- + /* night mode on */
- + mode |= 0x04;
- + ov5640_write_reg(0x3a00, mode);
- + } else {
- + /* night mode off */
- + mode &= 0xfb;
- + ov5640_write_reg(0x3a00, mode);
- + }
- +
- + return 0;
- +}
- +
- +/* enable = 0 to turn off AEC/AGC
- + enable = 1 to turn on AEC/AGC */
- +void ov5640_turn_on_AE_AG(int enable)
- +{
- + u8 ae_ag_ctrl;
- +
- + ov5640_read_reg(0x3503, &ae_ag_ctrl);
- + if (enable) {
- + /* turn on auto AE/AG */
- + ae_ag_ctrl = ae_ag_ctrl & ~(0x03);
- + } else {
- + /* turn off AE/AG */
- + ae_ag_ctrl = ae_ag_ctrl | 0x03;
- + }
- + ov5640_write_reg(0x3503, ae_ag_ctrl);
- +}
- +
- +/* download ov5640 settings to sensor through i2c */
- +static int ov5640_download_firmware(struct reg_value *pModeSetting, s32 ArySize)
- +{
- + register u32 Delay_ms = 0;
- + register u16 RegAddr = 0;
- + register u8 Mask = 0;
- + register u8 Val = 0;
- + u8 RegVal = 0;
- + int i, retval = 0;
- +
- + for (i = 0; i < ArySize; ++i, ++pModeSetting) {
- + Delay_ms = pModeSetting->u32Delay_ms;
- + RegAddr = pModeSetting->u16RegAddr;
- + Val = pModeSetting->u8Val;
- + Mask = pModeSetting->u8Mask;
- +
- + if (Mask) {
- + retval = ov5640_read_reg(RegAddr, &RegVal);
- + if (retval < 0)
- + goto err;
- +
- + RegVal &= ~(u8)Mask;
- + Val &= Mask;
- + Val |= RegVal;
- + }
- +
- + retval = ov5640_write_reg(RegAddr, Val);
- + if (retval < 0)
- + goto err;
- +
- + if (Delay_ms)
- + msleep(Delay_ms);
- + }
- +err:
- + return retval;
- +}
- +
- +static int ov5640_init_mode(void)
- +{
- + struct reg_value *pModeSetting = NULL;
- + int ArySize = 0, retval = 0;
- +
- + ov5640_soft_reset();
- +
- + pModeSetting = ov5640_global_init_setting;
- + ArySize = ARRAY_SIZE(ov5640_global_init_setting);
- + retval = ov5640_download_firmware(pModeSetting, ArySize);
- + if (retval < 0)
- + goto err;
- +
- + pModeSetting = ov5640_init_setting_30fps_VGA;
- + ArySize = ARRAY_SIZE(ov5640_init_setting_30fps_VGA);
- + retval = ov5640_download_firmware(pModeSetting, ArySize);
- + if (retval < 0)
- + goto err;
- +
- + /* change driver capability to 2x according to validation board.
- + * if the image is not stable, please increase the driver strength.
- + */
- + ov5640_driver_capability(2);
- + ov5640_set_bandingfilter();
- + ov5640_set_AE_target(AE_Target);
- + ov5640_set_night_mode(night_mode);
- +
- + /* skip 9 vysnc: start capture at 10th vsync */
- + msleep(300);
- +
- + /* turn off night mode */
- + night_mode = 0;
- + ov5640_data.pix.width = 640;
- + ov5640_data.pix.height = 480;
- +err:
- + return retval;
- +}
- +
- +/* change to or back to subsampling mode set the mode directly
- + * image size below 1280 * 960 is subsampling mode */
- +static int ov5640_change_mode_direct(enum ov5640_frame_rate frame_rate,
- + enum ov5640_mode mode)
- +{
- + struct reg_value *pModeSetting = NULL;
- + s32 ArySize = 0;
- + int retval = 0;
- +
- + if (mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) {
- + pr_err("Wrong ov5640 mode detected!\n");
- + return -1;
- + }
- +
- + pModeSetting = ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
- + ArySize =
- + ov5640_mode_info_data[frame_rate][mode].init_data_size;
- +
- + ov5640_data.pix.width = ov5640_mode_info_data[frame_rate][mode].width;
- + ov5640_data.pix.height = ov5640_mode_info_data[frame_rate][mode].height;
- +
- + if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
- + pModeSetting == NULL || ArySize == 0)
- + return -EINVAL;
- +
- + /* set ov5640 to subsampling mode */
- + retval = ov5640_download_firmware(pModeSetting, ArySize);
- +
- + /* turn on AE AG for subsampling mode, in case the firmware didn't */
- + ov5640_turn_on_AE_AG(1);
- +
- + /* calculate banding filter */
- + ov5640_set_bandingfilter();
- +
- + /* set AE target */
- + ov5640_set_AE_target(AE_Target);
- +
- + /* update night mode setting */
- + ov5640_set_night_mode(night_mode);
- +
- + /* skip 9 vysnc: start capture at 10th vsync */
- + if (mode == ov5640_mode_XGA_1024_768 && frame_rate == ov5640_30_fps) {
- + pr_warning("ov5640: actual frame rate of XGA is 22.5fps\n");
- + /* 1/22.5 * 9*/
- + msleep(400);
- + return retval;
- + }
- +
- + if (frame_rate == ov5640_15_fps) {
- + /* 1/15 * 9*/
- + msleep(600);
- + } else if (frame_rate == ov5640_30_fps) {
- + /* 1/30 * 9*/
- + msleep(300);
- + }
- +
- + return retval;
- +}
- +
- +/* change to scaling mode go through exposure calucation
- + * image size above 1280 * 960 is scaling mode */
- +static int ov5640_change_mode_exposure_calc(enum ov5640_frame_rate frame_rate,
- + enum ov5640_mode mode)
- +{
- + int prev_shutter, prev_gain16, average;
- + int cap_shutter, cap_gain16;
- + int cap_sysclk, cap_HTS, cap_VTS;
- + int light_freq, cap_bandfilt, cap_maxband;
- + long cap_gain16_shutter;
- + u8 temp;
- + struct reg_value *pModeSetting = NULL;
- + s32 ArySize = 0;
- + int retval = 0;
- +
- + /* check if the input mode and frame rate is valid */
- + pModeSetting =
- + ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
- + ArySize =
- + ov5640_mode_info_data[frame_rate][mode].init_data_size;
- +
- + ov5640_data.pix.width =
- + ov5640_mode_info_data[frame_rate][mode].width;
- + ov5640_data.pix.height =
- + ov5640_mode_info_data[frame_rate][mode].height;
- +
- + if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
- + pModeSetting == NULL || ArySize == 0)
- + return -EINVAL;
- +
- + /* read preview shutter */
- + prev_shutter = ov5640_get_shutter();
- +
- + /* read preview gain */
- + prev_gain16 = ov5640_get_gain16();
- +
- + /* get average */
- + average = ov5640_read_reg(0x56a1, &temp);
- +
- + /* turn off night mode for capture */
- + ov5640_set_night_mode(0);
- +
- + /* turn off overlay */
- + ov5640_write_reg(0x3022, 0x06);
- +
- + /* Write capture setting */
- + retval = ov5640_download_firmware(pModeSetting, ArySize);
- + if (retval < 0)
- + goto err;
- +
- + /* turn off AE AG when capture image. */
- + ov5640_turn_on_AE_AG(0);
- +
- + /* read capture VTS */
- + cap_VTS = ov5640_get_VTS();
- + cap_HTS = ov5640_get_HTS();
- + cap_sysclk = ov5640_get_sysclk();
- +
- + /* calculate capture banding filter */
- + light_freq = ov5640_get_light_freq();
- + if (light_freq == 60) {
- + /* 60Hz */
- + cap_bandfilt = cap_sysclk * 100 / cap_HTS * 100 / 120;
- + } else {
- + /* 50Hz */
- + cap_bandfilt = cap_sysclk * 100 / cap_HTS;
- + }
- + cap_maxband = (int)((cap_VTS - 4)/cap_bandfilt);
- + /* calculate capture shutter/gain16 */
- + if (average > AE_low && average < AE_high) {
- + /* in stable range */
- + cap_gain16_shutter =
- + prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk *
- + prev_HTS/cap_HTS * AE_Target / average;
- + } else {
- + cap_gain16_shutter =
- + prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk *
- + prev_HTS/cap_HTS;
- + }
- +
- + /* gain to shutter */
- + if (cap_gain16_shutter < (cap_bandfilt * 16)) {
- + /* shutter < 1/100 */
- + cap_shutter = cap_gain16_shutter/16;
- + if (cap_shutter < 1)
- + cap_shutter = 1;
- + cap_gain16 = cap_gain16_shutter/cap_shutter;
- + if (cap_gain16 < 16)
- + cap_gain16 = 16;
- + } else {
- + if (cap_gain16_shutter > (cap_bandfilt*cap_maxband*16)) {
- + /* exposure reach max */
- + cap_shutter = cap_bandfilt*cap_maxband;
- + cap_gain16 = cap_gain16_shutter / cap_shutter;
- + } else {
- + /* 1/100 < cap_shutter =< max, cap_shutter = n/100 */
- + cap_shutter =
- + ((int)(cap_gain16_shutter/16/cap_bandfilt))
- + * cap_bandfilt;
- + cap_gain16 = cap_gain16_shutter / cap_shutter;
- + }
- + }
- +
- + /* write capture gain */
- + ov5640_set_gain16(cap_gain16);
- +
- + /* write capture shutter */
- + if (cap_shutter > (cap_VTS - 4)) {
- + cap_VTS = cap_shutter + 4;
- + ov5640_set_VTS(cap_VTS);
- + }
- +
- + ov5640_set_shutter(cap_shutter);
- +
- + /* skip 2 vysnc: start capture at 3rd vsync
- + * frame rate of QSXGA and 1080P is 7.5fps: 1/7.5 * 2
- + */
- + pr_warning("ov5640: the actual frame rate of %s is 7.5fps\n",
- + mode == ov5640_mode_1080P_1920_1080 ? "1080P" : "QSXGA");
- + msleep(267);
- +err:
- + return retval;
- +}
- +
- +static int ov5640_change_mode(enum ov5640_frame_rate frame_rate,
- + enum ov5640_mode mode)
- +{
- + int retval = 0;
- +
- + if (mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) {
- + pr_err("Wrong ov5640 mode detected!\n");
- + return -1;
- + }
- +
- + if (mode == ov5640_mode_1080P_1920_1080 ||
- + mode == ov5640_mode_QSXGA_2592_1944) {
- + /* change to scaling mode go through exposure calucation
- + * image size above 1280 * 960 is scaling mode */
- + retval = ov5640_change_mode_exposure_calc(frame_rate, mode);
- + } else {
- + /* change back to subsampling modem download firmware directly
- + * image size below 1280 * 960 is subsampling mode */
- + retval = ov5640_change_mode_direct(frame_rate, mode);
- + }
- +
- + return retval;
- +}
- +
- +/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */
- +
- +static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
- +{
- + if (s == NULL) {
- + pr_err(" ERROR!! no slave device set!\n");
- + return -1;
- + }
- +
- + memset(p, 0, sizeof(*p));
- + p->u.bt656.clock_curr = ov5640_data.mclk;
- + pr_debug(" clock_curr=mclk=%d\n", ov5640_data.mclk);
- + p->if_type = V4L2_IF_TYPE_BT656;
- + p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
- + p->u.bt656.clock_min = OV5640_XCLK_MIN;
- + p->u.bt656.clock_max = OV5640_XCLK_MAX;
- + p->u.bt656.bt_sync_correct = 1; /* Indicate external vsync */
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @on: indicates power mode (on or off)
- + *
- + * Turns the power on or off, depending on the value of on and returns the
- + * appropriate error code.
- + */
- +static int ioctl_s_power(struct v4l2_int_device *s, int on)
- +{
- + struct sensor_data *sensor = s->priv;
- +
- + if (on && !sensor->on) {
- + if (io_regulator)
- + if (regulator_enable(io_regulator) != 0)
- + return -EIO;
- + if (core_regulator)
- + if (regulator_enable(core_regulator) != 0)
- + return -EIO;
- + if (analog_regulator)
- + if (regulator_enable(analog_regulator) != 0)
- + return -EIO;
- + /* Make sure power on */
- + ov5640_power_down(0);
- + } else if (!on && sensor->on) {
- + if (analog_regulator)
- + regulator_disable(analog_regulator);
- + if (core_regulator)
- + regulator_disable(core_regulator);
- + if (io_regulator)
- + regulator_disable(io_regulator);
- +
- + ov5640_power_down(1);
- +}
- +
- + sensor->on = on;
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
- + *
- + * Returns the sensor's video CAPTURE parameters.
- + */
- +static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
- +{
- + struct sensor_data *sensor = s->priv;
- + struct v4l2_captureparm *cparm = &a->parm.capture;
- + int ret = 0;
- +
- + switch (a->type) {
- + /* This is the only case currently handled. */
- + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- + memset(a, 0, sizeof(*a));
- + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- + cparm->capability = sensor->streamcap.capability;
- + cparm->timeperframe = sensor->streamcap.timeperframe;
- + cparm->capturemode = sensor->streamcap.capturemode;
- + ret = 0;
- + break;
- +
- + /* These are all the possible cases. */
- + case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- + case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- + case V4L2_BUF_TYPE_VBI_CAPTURE:
- + case V4L2_BUF_TYPE_VBI_OUTPUT:
- + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- + ret = -EINVAL;
- + break;
- +
- + default:
- + pr_debug(" type is unknown - %d\n", a->type);
- + ret = -EINVAL;
- + break;
- + }
- +
- + return ret;
- +}
- +
- +/*!
- + * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
- + *
- + * Configures the sensor to use the input parameters, if possible. If
- + * not possible, reverts to the old parameters and returns the
- + * appropriate error code.
- + */
- +static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
- +{
- + struct sensor_data *sensor = s->priv;
- + struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
- + u32 tgt_fps; /* target frames per secound */
- + enum ov5640_frame_rate frame_rate;
- + int ret = 0;
- +
- + /* Make sure power on */
- + ov5640_power_down(0);
- +
- + switch (a->type) {
- + /* This is the only case currently handled. */
- + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- + /* Check that the new frame rate is allowed. */
- + if ((timeperframe->numerator == 0) ||
- + (timeperframe->denominator == 0)) {
- + timeperframe->denominator = DEFAULT_FPS;
- + timeperframe->numerator = 1;
- + }
- +
- + tgt_fps = timeperframe->denominator /
- + timeperframe->numerator;
- +
- + if (tgt_fps > MAX_FPS) {
- + timeperframe->denominator = MAX_FPS;
- + timeperframe->numerator = 1;
- + } else if (tgt_fps < MIN_FPS) {
- + timeperframe->denominator = MIN_FPS;
- + timeperframe->numerator = 1;
- + }
- +
- + /* Actual frame rate we use */
- + tgt_fps = timeperframe->denominator /
- + timeperframe->numerator;
- +
- + if (tgt_fps == 15)
- + frame_rate = ov5640_15_fps;
- + else if (tgt_fps == 30)
- + frame_rate = ov5640_30_fps;
- + else {
- + pr_err(" The camera frame rate is not supported!\n");
- + return -EINVAL;
- + }
- +
- + ret = ov5640_change_mode(frame_rate,
- + a->parm.capture.capturemode);
- + if (ret < 0)
- + return ret;
- +
- + sensor->streamcap.timeperframe = *timeperframe;
- + sensor->streamcap.capturemode = a->parm.capture.capturemode;
- +
- + break;
- +
- + /* These are all the possible cases. */
- + case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- + case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- + case V4L2_BUF_TYPE_VBI_CAPTURE:
- + case V4L2_BUF_TYPE_VBI_OUTPUT:
- + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- + pr_debug(" type is not " \
- + "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
- + a->type);
- + ret = -EINVAL;
- + break;
- +
- + default:
- + pr_debug(" type is unknown - %d\n", a->type);
- + ret = -EINVAL;
- + break;
- + }
- +
- + return ret;
- +}
- +
- +/*!
- + * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
- + * @s: pointer to standard V4L2 device structure
- + * @f: pointer to standard V4L2 v4l2_format structure
- + *
- + * Returns the sensor's current pixel format in the v4l2_format
- + * parameter.
- + */
- +static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
- +{
- + struct sensor_data *sensor = s->priv;
- +
- + f->fmt.pix = sensor->pix;
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
- + *
- + * If the requested control is supported, returns the control's current
- + * value from the video_control[] array. Otherwise, returns -EINVAL
- + * if the control is not supported.
- + */
- +static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
- +{
- + int ret = 0;
- +
- + switch (vc->id) {
- + case V4L2_CID_BRIGHTNESS:
- + vc->value = ov5640_data.brightness;
- + break;
- + case V4L2_CID_HUE:
- + vc->value = ov5640_data.hue;
- + break;
- + case V4L2_CID_CONTRAST:
- + vc->value = ov5640_data.contrast;
- + break;
- + case V4L2_CID_SATURATION:
- + vc->value = ov5640_data.saturation;
- + break;
- + case V4L2_CID_RED_BALANCE:
- + vc->value = ov5640_data.red;
- + break;
- + case V4L2_CID_BLUE_BALANCE:
- + vc->value = ov5640_data.blue;
- + break;
- + case V4L2_CID_EXPOSURE:
- + vc->value = ov5640_data.ae_mode;
- + break;
- + default:
- + ret = -EINVAL;
- + }
- +
- + return ret;
- +}
- +
- +/*!
- + * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
- + *
- + * If the requested control is supported, sets the control's current
- + * value in HW (and updates the video_control[] array). Otherwise,
- + * returns -EINVAL if the control is not supported.
- + */
- +static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
- +{
- + int retval = 0;
- +
- + pr_debug("In ov5640:ioctl_s_ctrl %d\n",
- + vc->id);
- +
- + switch (vc->id) {
- + case V4L2_CID_BRIGHTNESS:
- + break;
- + case V4L2_CID_CONTRAST:
- + break;
- + case V4L2_CID_SATURATION:
- + break;
- + case V4L2_CID_HUE:
- + break;
- + case V4L2_CID_AUTO_WHITE_BALANCE:
- + break;
- + case V4L2_CID_DO_WHITE_BALANCE:
- + break;
- + case V4L2_CID_RED_BALANCE:
- + break;
- + case V4L2_CID_BLUE_BALANCE:
- + break;
- + case V4L2_CID_GAMMA:
- + break;
- + case V4L2_CID_EXPOSURE:
- + break;
- + case V4L2_CID_AUTOGAIN:
- + break;
- + case V4L2_CID_GAIN:
- + break;
- + case V4L2_CID_HFLIP:
- + break;
- + case V4L2_CID_VFLIP:
- + break;
- + default:
- + retval = -EPERM;
- + break;
- + }
- +
- + return retval;
- +}
- +
- +/*!
- + * ioctl_enum_framesizes - V4L2 sensor interface handler for
- + * VIDIOC_ENUM_FRAMESIZES ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
- + *
- + * Return 0 if successful, otherwise -EINVAL.
- + */
- +static int ioctl_enum_framesizes(struct v4l2_int_device *s,
- + struct v4l2_frmsizeenum *fsize)
- +{
- + if (fsize->index > ov5640_mode_MAX)
- + return -EINVAL;
- +
- + fsize->pixel_format = ov5640_data.pix.pixelformat;
- + fsize->discrete.width =
- + max(ov5640_mode_info_data[0][fsize->index].width,
- + ov5640_mode_info_data[1][fsize->index].width);
- + fsize->discrete.height =
- + max(ov5640_mode_info_data[0][fsize->index].height,
- + ov5640_mode_info_data[1][fsize->index].height);
- + return 0;
- +}
- +
- +/*!
- + * ioctl_enum_frameintervals - V4L2 sensor interface handler for
- + * VIDIOC_ENUM_FRAMEINTERVALS ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
- + *
- + * Return 0 if successful, otherwise -EINVAL.
- + */
- +static int ioctl_enum_frameintervals(struct v4l2_int_device *s,
- + struct v4l2_frmivalenum *fival)
- +{
- + int i, j, count;
- +
- + if (fival->index < 0 || fival->index > ov5640_mode_MAX)
- + return -EINVAL;
- +
- + if (fival->width == 0 || fival->height == 0 ||
- + fival->pixel_format == 0) {
- + pr_warning("Please assign pixelformat, width and height.\n");
- + return -EINVAL;
- + }
- +
- + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
- + fival->discrete.numerator = 1;
- +
- + count = 0;
- + for (i = 0; i < ARRAY_SIZE(ov5640_mode_info_data); i++) {
- + for (j = 0; j < (ov5640_mode_MAX + 1); j++) {
- + if (fival->pixel_format == ov5640_data.pix.pixelformat
- + && fival->width == ov5640_mode_info_data[i][j].width
- + && fival->height == ov5640_mode_info_data[i][j].height
- + && ov5640_mode_info_data[i][j].init_data_ptr != NULL) {
- + count++;
- + }
- + if (fival->index == (count - 1)) {
- + fival->discrete.denominator =
- + ov5640_framerates[i];
- + return 0;
- + }
- + }
- + }
- +
- + return -EINVAL;
- +}
- +
- +/*!
- + * ioctl_g_chip_ident - V4L2 sensor interface handler for
- + * VIDIOC_DBG_G_CHIP_IDENT ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @id: pointer to int
- + *
- + * Return 0.
- + */
- +static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
- +{
- + ((struct v4l2_dbg_chip_ident *)id)->match.type =
- + V4L2_CHIP_MATCH_I2C_DRIVER;
- + strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, "ov5640_camera");
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
- + * @s: pointer to standard V4L2 device structure
- + */
- +static int ioctl_init(struct v4l2_int_device *s)
- +{
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT
- + * @s: pointer to standard V4L2 device structure
- + * @fmt: pointer to standard V4L2 fmt description structure
- + *
- + * Return 0.
- + */
- +static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
- + struct v4l2_fmtdesc *fmt)
- +{
- + if (fmt->index > ov5640_mode_MAX)
- + return -EINVAL;
- +
- + fmt->pixelformat = ov5640_data.pix.pixelformat;
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
- + * @s: pointer to standard V4L2 device structure
- + *
- + * Initialise the device when slave attaches to the master.
- + */
- +static int ioctl_dev_init(struct v4l2_int_device *s)
- +{
- + struct sensor_data *sensor = s->priv;
- + u32 tgt_xclk; /* target xclk */
- + u32 tgt_fps; /* target frames per secound */
- + enum ov5640_frame_rate frame_rate;
- + int ret;
- +
- + ov5640_data.on = true;
- +
- + /* mclk */
- + tgt_xclk = ov5640_data.mclk;
- + tgt_xclk = min(tgt_xclk, (u32)OV5640_XCLK_MAX);
- + tgt_xclk = max(tgt_xclk, (u32)OV5640_XCLK_MIN);
- + ov5640_data.mclk = tgt_xclk;
- +
- + pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000);
- + clk_set_rate(ov5640_data.sensor_clk, ov5640_data.mclk);
- +
- + /* Default camera frame rate is set in probe */
- + tgt_fps = sensor->streamcap.timeperframe.denominator /
- + sensor->streamcap.timeperframe.numerator;
- +
- + if (tgt_fps == 15)
- + frame_rate = ov5640_15_fps;
- + else if (tgt_fps == 30)
- + frame_rate = ov5640_30_fps;
- + else
- + return -EINVAL; /* Only support 15fps or 30fps now. */
- +
- + ret = ov5640_init_mode();
- + return ret;
- +}
- +
- +/*!
- + * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num
- + * @s: pointer to standard V4L2 device structure
- + *
- + * Delinitialise the device when slave detaches to the master.
- + */
- +static int ioctl_dev_exit(struct v4l2_int_device *s)
- +{
- + return 0;
- +}
- +
- +/*!
- + * This structure defines all the ioctls for this module and links them to the
- + * enumeration.
- + */
- +static struct v4l2_int_ioctl_desc ov5640_ioctl_desc[] = {
- + { vidioc_int_dev_init_num,
- + (v4l2_int_ioctl_func *)ioctl_dev_init },
- + { vidioc_int_dev_exit_num,
- + ioctl_dev_exit},
- + { vidioc_int_s_power_num,
- + (v4l2_int_ioctl_func *)ioctl_s_power },
- + { vidioc_int_g_ifparm_num,
- + (v4l2_int_ioctl_func *)ioctl_g_ifparm },
- + { vidioc_int_init_num,
- + (v4l2_int_ioctl_func *)ioctl_init },
- + { vidioc_int_enum_fmt_cap_num,
- + (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap },
- + { vidioc_int_g_fmt_cap_num,
- + (v4l2_int_ioctl_func *)ioctl_g_fmt_cap },
- + { vidioc_int_g_parm_num,
- + (v4l2_int_ioctl_func *)ioctl_g_parm },
- + { vidioc_int_s_parm_num,
- + (v4l2_int_ioctl_func *)ioctl_s_parm },
- + { vidioc_int_g_ctrl_num,
- + (v4l2_int_ioctl_func *)ioctl_g_ctrl },
- + { vidioc_int_s_ctrl_num,
- + (v4l2_int_ioctl_func *)ioctl_s_ctrl },
- + { vidioc_int_enum_framesizes_num,
- + (v4l2_int_ioctl_func *)ioctl_enum_framesizes },
- + { vidioc_int_enum_frameintervals_num,
- + (v4l2_int_ioctl_func *)ioctl_enum_frameintervals },
- + { vidioc_int_g_chip_ident_num,
- + (v4l2_int_ioctl_func *)ioctl_g_chip_ident },
- +};
- +
- +static struct v4l2_int_slave ov5640_slave = {
- + .ioctls = ov5640_ioctl_desc,
- + .num_ioctls = ARRAY_SIZE(ov5640_ioctl_desc),
- +};
- +
- +static struct v4l2_int_device ov5640_int_device = {
- + .module = THIS_MODULE,
- + .name = "ov5640",
- + .type = v4l2_int_type_slave,
- + .u = {
- + .slave = &ov5640_slave,
- + },
- +};
- +
- +/*!
- + * ov5640 I2C probe function
- + *
- + * @param adapter struct i2c_adapter *
- + * @return Error code indicating success or failure
- + */
- +static int ov5640_probe(struct i2c_client *client,
- + const struct i2c_device_id *id)
- +{
- + struct pinctrl *pinctrl;
- + struct device *dev = &client->dev;
- + int retval;
- + u8 chip_id_high, chip_id_low;
- +
- + /* ov5640 pinctrl */
- + pinctrl = devm_pinctrl_get_select_default(dev);
- + if (IS_ERR(pinctrl)) {
- + dev_err(dev, "setup pinctrl failed\n");
- + return PTR_ERR(pinctrl);
- + }
- +
- + /* request power down pin */
- + pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
- + if (!gpio_is_valid(pwn_gpio)) {
- + dev_err(dev, "no sensor pwdn pin available\n");
- + return -ENODEV;
- + }
- + retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
- + "ov5640_pwdn");
- + if (retval < 0)
- + return retval;
- +
- + /* request reset pin */
- + rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
- + if (!gpio_is_valid(rst_gpio)) {
- + dev_err(dev, "no sensor reset pin available\n");
- + return -EINVAL;
- + }
- + retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
- + "ov5640_reset");
- + if (retval < 0)
- + return retval;
- +
- + /* Set initial values for the sensor struct. */
- + memset(&ov5640_data, 0, sizeof(ov5640_data));
- + ov5640_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
- + if (IS_ERR(ov5640_data.sensor_clk)) {
- + dev_err(dev, "get mclk failed\n");
- + return PTR_ERR(ov5640_data.sensor_clk);
- + }
- +
- + retval = of_property_read_u32(dev->of_node, "mclk",
- + &ov5640_data.mclk);
- + if (retval) {
- + dev_err(dev, "mclk frequency is invalid\n");
- + return retval;
- + }
- +
- + retval = of_property_read_u32(dev->of_node, "mclk_source",
- + (u32 *) &(ov5640_data.mclk_source));
- + if (retval) {
- + dev_err(dev, "mclk_source invalid\n");
- + return retval;
- + }
- +
- + retval = of_property_read_u32(dev->of_node, "csi_id",
- + &(ov5640_data.csi));
- + if (retval) {
- + dev_err(dev, "csi_id invalid\n");
- + return retval;
- + }
- +
- + clk_prepare_enable(ov5640_data.sensor_clk);
- +
- + ov5640_data.io_init = ov5640_reset;
- + ov5640_data.i2c_client = client;
- + ov5640_data.pix.pixelformat = V4L2_PIX_FMT_YUYV;
- + ov5640_data.pix.width = 640;
- + ov5640_data.pix.height = 480;
- + ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
- + V4L2_CAP_TIMEPERFRAME;
- + ov5640_data.streamcap.capturemode = 0;
- + ov5640_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
- + ov5640_data.streamcap.timeperframe.numerator = 1;
- +
- + ov5640_regulator_enable(&client->dev);
- +
- + ov5640_reset();
- +
- + ov5640_power_down(0);
- +
- + retval = ov5640_read_reg(OV5640_CHIP_ID_HIGH_BYTE, &chip_id_high);
- + if (retval < 0 || chip_id_high != 0x56) {
- + clk_disable_unprepare(ov5640_data.sensor_clk);
- + pr_warning("camera ov5640 is not found\n");
- + return -ENODEV;
- + }
- + retval = ov5640_read_reg(OV5640_CHIP_ID_LOW_BYTE, &chip_id_low);
- + if (retval < 0 || chip_id_low != 0x40) {
- + clk_disable_unprepare(ov5640_data.sensor_clk);
- + pr_warning("camera ov5640 is not found\n");
- + return -ENODEV;
- + }
- +
- + ov5640_power_down(1);
- +
- + clk_disable_unprepare(ov5640_data.sensor_clk);
- +
- + ov5640_int_device.priv = &ov5640_data;
- + retval = v4l2_int_device_register(&ov5640_int_device);
- +
- + pr_info("camera ov5640 is found\n");
- + return retval;
- +}
- +
- +/*!
- + * ov5640 I2C detach function
- + *
- + * @param client struct i2c_client *
- + * @return Error code indicating success or failure
- + */
- +static int ov5640_remove(struct i2c_client *client)
- +{
- + v4l2_int_device_unregister(&ov5640_int_device);
- +
- + if (analog_regulator)
- + regulator_disable(analog_regulator);
- +
- + if (core_regulator)
- + regulator_disable(core_regulator);
- +
- + if (io_regulator)
- + regulator_disable(io_regulator);
- +
- + return 0;
- +}
- +
- +module_i2c_driver(ov5640_i2c_driver);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("OV5640 Camera Driver");
- +MODULE_LICENSE("GPL");
- +MODULE_VERSION("1.0");
- +MODULE_ALIAS("CSI");
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/ov5640_mipi.c linux-3.14.35/drivers/media/platform/mxc/capture/ov5640_mipi.c
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/ov5640_mipi.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/ov5640_mipi.c 2015-03-08 14:27:37.601684501 -0500
- @@ -0,0 +1,2104 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/init.h>
- +#include <linux/slab.h>
- +#include <linux/ctype.h>
- +#include <linux/types.h>
- +#include <linux/delay.h>
- +#include <linux/clk.h>
- +#include <linux/of_device.h>
- +#include <linux/i2c.h>
- +#include <linux/of_gpio.h>
- +#include <linux/pinctrl/consumer.h>
- +#include <linux/regulator/consumer.h>
- +#include <linux/fsl_devices.h>
- +#include <linux/mipi_csi2.h>
- +#include <media/v4l2-chip-ident.h>
- +#include <media/v4l2-int-device.h>
- +#include "mxc_v4l2_capture.h"
- +
- +#define OV5640_VOLTAGE_ANALOG 2800000
- +#define OV5640_VOLTAGE_DIGITAL_CORE 1500000
- +#define OV5640_VOLTAGE_DIGITAL_IO 1800000
- +
- +#define MIN_FPS 15
- +#define MAX_FPS 30
- +#define DEFAULT_FPS 30
- +
- +#define OV5640_XCLK_MIN 6000000
- +#define OV5640_XCLK_MAX 24000000
- +
- +#define OV5640_CHIP_ID_HIGH_BYTE 0x300A
- +#define OV5640_CHIP_ID_LOW_BYTE 0x300B
- +
- +enum ov5640_mode {
- + ov5640_mode_MIN = 0,
- + ov5640_mode_VGA_640_480 = 0,
- + ov5640_mode_QVGA_320_240 = 1,
- + ov5640_mode_NTSC_720_480 = 2,
- + ov5640_mode_PAL_720_576 = 3,
- + ov5640_mode_720P_1280_720 = 4,
- + ov5640_mode_1080P_1920_1080 = 5,
- + ov5640_mode_QSXGA_2592_1944 = 6,
- + ov5640_mode_QCIF_176_144 = 7,
- + ov5640_mode_XGA_1024_768 = 8,
- + ov5640_mode_MAX = 8,
- + ov5640_mode_INIT = 0xff, /*only for sensor init*/
- +};
- +
- +enum ov5640_frame_rate {
- + ov5640_15_fps,
- + ov5640_30_fps
- +};
- +
- +/* image size under 1280 * 960 are SUBSAMPLING
- + * image size upper 1280 * 960 are SCALING
- + */
- +enum ov5640_downsize_mode {
- + SUBSAMPLING,
- + SCALING,
- +};
- +
- +struct reg_value {
- + u16 u16RegAddr;
- + u8 u8Val;
- + u8 u8Mask;
- + u32 u32Delay_ms;
- +};
- +
- +struct ov5640_mode_info {
- + enum ov5640_mode mode;
- + enum ov5640_downsize_mode dn_mode;
- + u32 width;
- + u32 height;
- + struct reg_value *init_data_ptr;
- + u32 init_data_size;
- +};
- +
- +/*!
- + * Maintains the information on the current state of the sesor.
- + */
- +static struct sensor_data ov5640_data;
- +static int pwn_gpio, rst_gpio;
- +
- +static struct reg_value ov5640_init_setting_30fps_VGA[] = {
- +
- + {0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
- + {0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0},
- + {0x3034, 0x18, 0, 0}, {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0},
- + {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0},
- + {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
- + {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
- + {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
- + {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0},
- + {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0},
- + {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0},
- + {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0},
- + {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0},
- + {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0},
- + {0x3c01, 0xa4, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0},
- + {0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
- + {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
- + {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
- + {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
- + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
- + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0},
- + {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0},
- + {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0},
- + {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0},
- + {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- + {0x4837, 0x0a, 0, 0}, {0x4800, 0x04, 0, 0}, {0x3824, 0x02, 0, 0},
- + {0x5000, 0xa7, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0},
- + {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0},
- + {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0},
- + {0x5187, 0x09, 0, 0}, {0x5188, 0x09, 0, 0}, {0x5189, 0x88, 0, 0},
- + {0x518a, 0x54, 0, 0}, {0x518b, 0xee, 0, 0}, {0x518c, 0xb2, 0, 0},
- + {0x518d, 0x50, 0, 0}, {0x518e, 0x34, 0, 0}, {0x518f, 0x6b, 0, 0},
- + {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0},
- + {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0},
- + {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0},
- + {0x5199, 0x6c, 0, 0}, {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0},
- + {0x519c, 0x09, 0, 0}, {0x519d, 0x2b, 0, 0}, {0x519e, 0x38, 0, 0},
- + {0x5381, 0x1e, 0, 0}, {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0},
- + {0x5384, 0x0a, 0, 0}, {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0},
- + {0x5387, 0x7c, 0, 0}, {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0},
- + {0x538a, 0x01, 0, 0}, {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0},
- + {0x5301, 0x30, 0, 0}, {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0},
- + {0x5304, 0x08, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0},
- + {0x5307, 0x16, 0, 0}, {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0},
- + {0x530b, 0x04, 0, 0}, {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0},
- + {0x5481, 0x08, 0, 0}, {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0},
- + {0x5484, 0x51, 0, 0}, {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0},
- + {0x5487, 0x7d, 0, 0}, {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0},
- + {0x548a, 0x9a, 0, 0}, {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0},
- + {0x548d, 0xcd, 0, 0}, {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0},
- + {0x5490, 0x1d, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0},
- + {0x5584, 0x10, 0, 0}, {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0},
- + {0x558b, 0xf8, 0, 0}, {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0},
- + {0x5802, 0x0f, 0, 0}, {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0},
- + {0x5805, 0x26, 0, 0}, {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0},
- + {0x5808, 0x05, 0, 0}, {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0},
- + {0x580b, 0x0d, 0, 0}, {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0},
- + {0x580e, 0x00, 0, 0}, {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0},
- + {0x5811, 0x09, 0, 0}, {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0},
- + {0x5814, 0x00, 0, 0}, {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0},
- + {0x5817, 0x08, 0, 0}, {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0},
- + {0x581a, 0x05, 0, 0}, {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0},
- + {0x581d, 0x0e, 0, 0}, {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0},
- + {0x5820, 0x11, 0, 0}, {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0},
- + {0x5823, 0x28, 0, 0}, {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0},
- + {0x5826, 0x08, 0, 0}, {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0},
- + {0x5829, 0x26, 0, 0}, {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0},
- + {0x582c, 0x24, 0, 0}, {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0},
- + {0x582f, 0x22, 0, 0}, {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0},
- + {0x5832, 0x24, 0, 0}, {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0},
- + {0x5835, 0x22, 0, 0}, {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0},
- + {0x5838, 0x44, 0, 0}, {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0},
- + {0x583b, 0x28, 0, 0}, {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0},
- + {0x5025, 0x00, 0, 0}, {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0},
- + {0x3a1b, 0x30, 0, 0}, {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0},
- + {0x3a1f, 0x14, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3c00, 0x04, 0, 300},
- +};
- +
- +static struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
- +
- + {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
- + {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
- + {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
- + {0x380e, 0x04, 0, 0}, {0x380f, 0x38, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
- + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x0e, 0, 0},
- + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- + {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3503, 0x00, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
- + {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
- + {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
- + {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
- + {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
- + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
- + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- + {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
- +
- + {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
- + {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
- + {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
- + {0x380e, 0x04, 0, 0}, {0x380f, 0x38, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
- + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x0e, 0, 0},
- + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- + {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3503, 0x00, 0, 0},
- + {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0},
- + {0x380b, 0x00, 0, 0}, {0x3035, 0x12, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
- + {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
- + {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
- + {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
- + {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
- + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
- + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- + {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3808, 0x04, 0, 0},
- + {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
- + {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
- + {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0},
- + {0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
- + {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
- + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
- + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- + {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
- + {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
- + {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0},
- + {0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
- + {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
- + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
- + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- + {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
- + {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
- + {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0},
- + {0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
- + {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
- + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
- + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- + {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
- +};
- +static struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
- + {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
- + {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0},
- + {0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
- + {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
- + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
- + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- + {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
- + {0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
- + {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0},
- + {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
- + {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
- + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
- + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- + {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_15fps_NTSC_720_480[] = {
- + {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
- + {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0},
- + {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
- + {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
- + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
- + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- + {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
- + {0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
- + {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x02, 0, 0},
- + {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
- + {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x38, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
- + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
- + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- + {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_15fps_PAL_720_576[] = {
- + {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
- + {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x02, 0, 0},
- + {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
- + {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x38, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
- + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
- + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- + {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
- + {0x3008, 0x42, 0, 0},
- + {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
- + {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
- + {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
- + {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
- + {0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0},
- + {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0},
- + {0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x02, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
- + {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0}, {0x4005, 0x1a, 0, 0},
- + {0x3008, 0x02, 0, 0}, {0x3503, 0, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_15fps_720P_1280_720[] = {
- + {0x3035, 0x41, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
- + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
- + {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
- + {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
- + {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
- + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
- + {0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0},
- + {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0},
- + {0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x02, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
- + {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_30fps_1080P_1920_1080[] = {
- + {0x3008, 0x42, 0, 0},
- + {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
- + {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
- + {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
- + {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
- + {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
- + {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
- + {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
- + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
- + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- + {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0}, {0x3035, 0x11, 0, 0},
- + {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
- + {0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
- + {0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3808, 0x07, 0, 0},
- + {0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0},
- + {0x380c, 0x09, 0, 0}, {0x380d, 0xc4, 0, 0}, {0x380e, 0x04, 0, 0},
- + {0x380f, 0x60, 0, 0}, {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
- + {0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
- + {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
- + {0x3a15, 0x60, 0, 0}, {0x4713, 0x02, 0, 0}, {0x4407, 0x04, 0, 0},
- + {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3824, 0x04, 0, 0},
- + {0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0},
- + {0x3503, 0, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
- + {0x3008, 0x42, 0, 0},
- + {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
- + {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
- + {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
- + {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
- + {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
- + {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
- + {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
- + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
- + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- + {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0}, {0x3035, 0x21, 0, 0},
- + {0x3036, 0x54, 0, 1}, {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
- + {0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
- + {0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3808, 0x07, 0, 0},
- + {0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0},
- + {0x380c, 0x09, 0, 0}, {0x380d, 0xc4, 0, 0}, {0x380e, 0x04, 0, 0},
- + {0x380f, 0x60, 0, 0}, {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
- + {0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
- + {0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
- + {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
- + {0x3a15, 0x60, 0, 0}, {0x4713, 0x02, 0, 0}, {0x4407, 0x04, 0, 0},
- + {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3824, 0x04, 0, 0},
- + {0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3503, 0, 0, 0},
- +};
- +
- +static struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
- + {0x4202, 0x0f, 0, 0}, /* stream off the sensor */
- + {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, /*disable flip*/
- + {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
- + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
- + {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
- + {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
- + {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
- + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
- + {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
- + {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
- + {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
- + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
- + {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
- + {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
- + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
- + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
- + {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- + {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 70},
- + {0x4202, 0x00, 0, 0}, /* stream on the sensor */
- +};
- +
- +static struct ov5640_mode_info ov5640_mode_info_data[2][ov5640_mode_MAX + 1] = {
- + {
- + {ov5640_mode_VGA_640_480, SUBSAMPLING, 640, 480,
- + ov5640_setting_15fps_VGA_640_480,
- + ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)},
- + {ov5640_mode_QVGA_320_240, SUBSAMPLING, 320, 240,
- + ov5640_setting_15fps_QVGA_320_240,
- + ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)},
- + {ov5640_mode_NTSC_720_480, SUBSAMPLING, 720, 480,
- + ov5640_setting_15fps_NTSC_720_480,
- + ARRAY_SIZE(ov5640_setting_15fps_NTSC_720_480)},
- + {ov5640_mode_PAL_720_576, SUBSAMPLING, 720, 576,
- + ov5640_setting_15fps_PAL_720_576,
- + ARRAY_SIZE(ov5640_setting_15fps_PAL_720_576)},
- + {ov5640_mode_720P_1280_720, SUBSAMPLING, 1280, 720,
- + ov5640_setting_15fps_720P_1280_720,
- + ARRAY_SIZE(ov5640_setting_15fps_720P_1280_720)},
- + {ov5640_mode_1080P_1920_1080, SCALING, 1920, 1080,
- + ov5640_setting_15fps_1080P_1920_1080,
- + ARRAY_SIZE(ov5640_setting_15fps_1080P_1920_1080)},
- + {ov5640_mode_QSXGA_2592_1944, SCALING, 2592, 1944,
- + ov5640_setting_15fps_QSXGA_2592_1944,
- + ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
- + {ov5640_mode_QCIF_176_144, SUBSAMPLING, 176, 144,
- + ov5640_setting_15fps_QCIF_176_144,
- + ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)},
- + {ov5640_mode_XGA_1024_768, SUBSAMPLING, 1024, 768,
- + ov5640_setting_15fps_XGA_1024_768,
- + ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)},
- + },
- + {
- + {ov5640_mode_VGA_640_480, SUBSAMPLING, 640, 480,
- + ov5640_setting_30fps_VGA_640_480,
- + ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
- + {ov5640_mode_QVGA_320_240, SUBSAMPLING, 320, 240,
- + ov5640_setting_30fps_QVGA_320_240,
- + ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)},
- + {ov5640_mode_NTSC_720_480, SUBSAMPLING, 720, 480,
- + ov5640_setting_30fps_NTSC_720_480,
- + ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
- + {ov5640_mode_PAL_720_576, SUBSAMPLING, 720, 576,
- + ov5640_setting_30fps_PAL_720_576,
- + ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)},
- + {ov5640_mode_720P_1280_720, SUBSAMPLING, 1280, 720,
- + ov5640_setting_30fps_720P_1280_720,
- + ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)},
- + {ov5640_mode_1080P_1920_1080, SCALING, 1920, 1080,
- + ov5640_setting_30fps_1080P_1920_1080,
- + ARRAY_SIZE(ov5640_setting_30fps_1080P_1920_1080)},
- + {ov5640_mode_QSXGA_2592_1944, -1, 0, 0, NULL, 0},
- + {ov5640_mode_QCIF_176_144, SUBSAMPLING, 176, 144,
- + ov5640_setting_30fps_QCIF_176_144,
- + ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)},
- + {ov5640_mode_XGA_1024_768, SUBSAMPLING, 1024, 768,
- + ov5640_setting_30fps_XGA_1024_768,
- + ARRAY_SIZE(ov5640_setting_30fps_XGA_1024_768)},
- + },
- +};
- +
- +static struct regulator *io_regulator;
- +static struct regulator *core_regulator;
- +static struct regulator *analog_regulator;
- +static struct regulator *gpo_regulator;
- +
- +static int ov5640_probe(struct i2c_client *adapter,
- + const struct i2c_device_id *device_id);
- +static int ov5640_remove(struct i2c_client *client);
- +
- +static s32 ov5640_read_reg(u16 reg, u8 *val);
- +static s32 ov5640_write_reg(u16 reg, u8 val);
- +
- +static const struct i2c_device_id ov5640_id[] = {
- + {"ov5640_mipi", 0},
- + {},
- +};
- +
- +MODULE_DEVICE_TABLE(i2c, ov5640_id);
- +
- +static struct i2c_driver ov5640_i2c_driver = {
- + .driver = {
- + .owner = THIS_MODULE,
- + .name = "ov5640_mipi",
- + },
- + .probe = ov5640_probe,
- + .remove = ov5640_remove,
- + .id_table = ov5640_id,
- +};
- +
- +static void ov5640_standby(s32 enable)
- +{
- + if (enable)
- + gpio_set_value(pwn_gpio, 1);
- + else
- + gpio_set_value(pwn_gpio, 0);
- +
- + msleep(2);
- +}
- +
- +static void ov5640_reset(void)
- +{
- + /* camera reset */
- + gpio_set_value(rst_gpio, 1);
- +
- + /* camera power dowmn */
- + gpio_set_value(pwn_gpio, 1);
- + msleep(5);
- +
- + gpio_set_value(pwn_gpio, 0);
- + msleep(5);
- +
- + gpio_set_value(rst_gpio, 0);
- + msleep(1);
- +
- + gpio_set_value(rst_gpio, 1);
- + msleep(5);
- +
- + gpio_set_value(pwn_gpio, 1);
- +}
- +
- +static int ov5640_power_on(struct device *dev)
- +{
- + int ret = 0;
- +
- + io_regulator = devm_regulator_get(dev, "DOVDD");
- + if (!IS_ERR(io_regulator)) {
- + regulator_set_voltage(io_regulator,
- + OV5640_VOLTAGE_DIGITAL_IO,
- + OV5640_VOLTAGE_DIGITAL_IO);
- + ret = regulator_enable(io_regulator);
- + if (ret) {
- + pr_err("%s:io set voltage error\n", __func__);
- + return ret;
- + } else {
- + dev_dbg(dev,
- + "%s:io set voltage ok\n", __func__);
- + }
- + } else {
- + pr_err("%s: cannot get io voltage error\n", __func__);
- + io_regulator = NULL;
- + }
- +
- + core_regulator = devm_regulator_get(dev, "DVDD");
- + if (!IS_ERR(core_regulator)) {
- + regulator_set_voltage(core_regulator,
- + OV5640_VOLTAGE_DIGITAL_CORE,
- + OV5640_VOLTAGE_DIGITAL_CORE);
- + ret = regulator_enable(core_regulator);
- + if (ret) {
- + pr_err("%s:core set voltage error\n", __func__);
- + return ret;
- + } else {
- + dev_dbg(dev,
- + "%s:core set voltage ok\n", __func__);
- + }
- + } else {
- + core_regulator = NULL;
- + pr_err("%s: cannot get core voltage error\n", __func__);
- + }
- +
- + analog_regulator = devm_regulator_get(dev, "AVDD");
- + if (!IS_ERR(analog_regulator)) {
- + regulator_set_voltage(analog_regulator,
- + OV5640_VOLTAGE_ANALOG,
- + OV5640_VOLTAGE_ANALOG);
- + ret = regulator_enable(analog_regulator);
- + if (ret) {
- + pr_err("%s:analog set voltage error\n",
- + __func__);
- + return ret;
- + } else {
- + dev_dbg(dev,
- + "%s:analog set voltage ok\n", __func__);
- + }
- + } else {
- + analog_regulator = NULL;
- + pr_err("%s: cannot get analog voltage error\n", __func__);
- + }
- +
- + return ret;
- +}
- +
- +static s32 ov5640_write_reg(u16 reg, u8 val)
- +{
- + u8 au8Buf[3] = {0};
- +
- + au8Buf[0] = reg >> 8;
- + au8Buf[1] = reg & 0xff;
- + au8Buf[2] = val;
- +
- + if (i2c_master_send(ov5640_data.i2c_client, au8Buf, 3) < 0) {
- + pr_err("%s:write reg error:reg=%x,val=%x\n",
- + __func__, reg, val);
- + return -1;
- + }
- +
- + return 0;
- +}
- +
- +static s32 ov5640_read_reg(u16 reg, u8 *val)
- +{
- + u8 au8RegBuf[2] = {0};
- + u8 u8RdVal = 0;
- +
- + au8RegBuf[0] = reg >> 8;
- + au8RegBuf[1] = reg & 0xff;
- +
- + if (2 != i2c_master_send(ov5640_data.i2c_client, au8RegBuf, 2)) {
- + pr_err("%s:write reg error:reg=%x\n",
- + __func__, reg);
- + return -1;
- + }
- +
- + if (1 != i2c_master_recv(ov5640_data.i2c_client, &u8RdVal, 1)) {
- + pr_err("%s:read reg error:reg=%x,val=%x\n",
- + __func__, reg, u8RdVal);
- + return -1;
- + }
- +
- + *val = u8RdVal;
- +
- + return u8RdVal;
- +}
- +
- +static int prev_sysclk, prev_HTS;
- +static int AE_low, AE_high, AE_Target = 52;
- +
- +void OV5640_stream_on(void)
- +{
- + ov5640_write_reg(0x4202, 0x00);
- +}
- +
- +void OV5640_stream_off(void)
- +{
- + ov5640_write_reg(0x4202, 0x0f);
- +}
- +
- +
- +int OV5640_get_sysclk(void)
- +{
- + /* calculate sysclk */
- + int xvclk = ov5640_data.mclk / 10000;
- + int temp1, temp2;
- + int Multiplier, PreDiv, VCO, SysDiv, Pll_rdiv;
- + int Bit_div2x = 1, sclk_rdiv, sysclk;
- + u8 temp;
- +
- + int sclk_rdiv_map[] = {1, 2, 4, 8};
- +
- + temp1 = ov5640_read_reg(0x3034, &temp);
- + temp2 = temp1 & 0x0f;
- + if (temp2 == 8 || temp2 == 10)
- + Bit_div2x = temp2 / 2;
- +
- + temp1 = ov5640_read_reg(0x3035, &temp);
- + SysDiv = temp1>>4;
- + if (SysDiv == 0)
- + SysDiv = 16;
- +
- + temp1 = ov5640_read_reg(0x3036, &temp);
- + Multiplier = temp1;
- +
- + temp1 = ov5640_read_reg(0x3037, &temp);
- + PreDiv = temp1 & 0x0f;
- + Pll_rdiv = ((temp1 >> 4) & 0x01) + 1;
- +
- + temp1 = ov5640_read_reg(0x3108, &temp);
- + temp2 = temp1 & 0x03;
- + sclk_rdiv = sclk_rdiv_map[temp2];
- +
- + VCO = xvclk * Multiplier / PreDiv;
- +
- + sysclk = VCO / SysDiv / Pll_rdiv * 2 / Bit_div2x / sclk_rdiv;
- +
- + return sysclk;
- +}
- +
- +void OV5640_set_night_mode(void)
- +{
- + /* read HTS from register settings */
- + u8 mode;
- +
- + ov5640_read_reg(0x3a00, &mode);
- + mode &= 0xfb;
- + ov5640_write_reg(0x3a00, mode);
- +}
- +
- +int OV5640_get_HTS(void)
- +{
- + /* read HTS from register settings */
- + int HTS;
- + u8 temp;
- +
- + HTS = ov5640_read_reg(0x380c, &temp);
- + HTS = (HTS<<8) + ov5640_read_reg(0x380d, &temp);
- +
- + return HTS;
- +}
- +
- +int OV5640_get_VTS(void)
- +{
- + /* read VTS from register settings */
- + int VTS;
- + u8 temp;
- +
- + /* total vertical size[15:8] high byte */
- + VTS = ov5640_read_reg(0x380e, &temp);
- +
- + VTS = (VTS<<8) + ov5640_read_reg(0x380f, &temp);
- +
- + return VTS;
- +}
- +
- +int OV5640_set_VTS(int VTS)
- +{
- + /* write VTS to registers */
- + int temp;
- +
- + temp = VTS & 0xff;
- + ov5640_write_reg(0x380f, temp);
- +
- + temp = VTS>>8;
- + ov5640_write_reg(0x380e, temp);
- +
- + return 0;
- +}
- +
- +int OV5640_get_shutter(void)
- +{
- + /* read shutter, in number of line period */
- + int shutter;
- + u8 temp;
- +
- + shutter = (ov5640_read_reg(0x03500, &temp) & 0x0f);
- + shutter = (shutter<<8) + ov5640_read_reg(0x3501, &temp);
- + shutter = (shutter<<4) + (ov5640_read_reg(0x3502, &temp)>>4);
- +
- + return shutter;
- +}
- +
- +int OV5640_set_shutter(int shutter)
- +{
- + /* write shutter, in number of line period */
- + int temp;
- +
- + shutter = shutter & 0xffff;
- +
- + temp = shutter & 0x0f;
- + temp = temp<<4;
- + ov5640_write_reg(0x3502, temp);
- +
- + temp = shutter & 0xfff;
- + temp = temp>>4;
- + ov5640_write_reg(0x3501, temp);
- +
- + temp = shutter>>12;
- + ov5640_write_reg(0x3500, temp);
- +
- + return 0;
- +}
- +
- +int OV5640_get_gain16(void)
- +{
- + /* read gain, 16 = 1x */
- + int gain16;
- + u8 temp;
- +
- + gain16 = ov5640_read_reg(0x350a, &temp) & 0x03;
- + gain16 = (gain16<<8) + ov5640_read_reg(0x350b, &temp);
- +
- + return gain16;
- +}
- +
- +int OV5640_set_gain16(int gain16)
- +{
- + /* write gain, 16 = 1x */
- + u8 temp;
- + gain16 = gain16 & 0x3ff;
- +
- + temp = gain16 & 0xff;
- + ov5640_write_reg(0x350b, temp);
- +
- + temp = gain16>>8;
- + ov5640_write_reg(0x350a, temp);
- +
- + return 0;
- +}
- +
- +int OV5640_get_light_freq(void)
- +{
- + /* get banding filter value */
- + int temp, temp1, light_freq = 0;
- + u8 tmp;
- +
- + temp = ov5640_read_reg(0x3c01, &tmp);
- +
- + if (temp & 0x80) {
- + /* manual */
- + temp1 = ov5640_read_reg(0x3c00, &tmp);
- + if (temp1 & 0x04) {
- + /* 50Hz */
- + light_freq = 50;
- + } else {
- + /* 60Hz */
- + light_freq = 60;
- + }
- + } else {
- + /* auto */
- + temp1 = ov5640_read_reg(0x3c0c, &tmp);
- + if (temp1 & 0x01) {
- + /* 50Hz */
- + light_freq = 50;
- + } else {
- + /* 60Hz */
- + }
- + }
- + return light_freq;
- +}
- +
- +void OV5640_set_bandingfilter(void)
- +{
- + int prev_VTS;
- + int band_step60, max_band60, band_step50, max_band50;
- +
- + /* read preview PCLK */
- + prev_sysclk = OV5640_get_sysclk();
- + /* read preview HTS */
- + prev_HTS = OV5640_get_HTS();
- +
- + /* read preview VTS */
- + prev_VTS = OV5640_get_VTS();
- +
- + /* calculate banding filter */
- + /* 60Hz */
- + band_step60 = prev_sysclk * 100/prev_HTS * 100/120;
- + ov5640_write_reg(0x3a0a, (band_step60 >> 8));
- + ov5640_write_reg(0x3a0b, (band_step60 & 0xff));
- +
- + max_band60 = (int)((prev_VTS-4)/band_step60);
- + ov5640_write_reg(0x3a0d, max_band60);
- +
- + /* 50Hz */
- + band_step50 = prev_sysclk * 100/prev_HTS;
- + ov5640_write_reg(0x3a08, (band_step50 >> 8));
- + ov5640_write_reg(0x3a09, (band_step50 & 0xff));
- +
- + max_band50 = (int)((prev_VTS-4)/band_step50);
- + ov5640_write_reg(0x3a0e, max_band50);
- +}
- +
- +int OV5640_set_AE_target(int target)
- +{
- + /* stable in high */
- + int fast_high, fast_low;
- + AE_low = target * 23 / 25; /* 0.92 */
- + AE_high = target * 27 / 25; /* 1.08 */
- +
- + fast_high = AE_high<<1;
- + if (fast_high > 255)
- + fast_high = 255;
- +
- + fast_low = AE_low >> 1;
- +
- + ov5640_write_reg(0x3a0f, AE_high);
- + ov5640_write_reg(0x3a10, AE_low);
- + ov5640_write_reg(0x3a1b, AE_high);
- + ov5640_write_reg(0x3a1e, AE_low);
- + ov5640_write_reg(0x3a11, fast_high);
- + ov5640_write_reg(0x3a1f, fast_low);
- +
- + return 0;
- +}
- +
- +void OV5640_turn_on_AE_AG(int enable)
- +{
- + u8 ae_ag_ctrl;
- +
- + ov5640_read_reg(0x3503, &ae_ag_ctrl);
- + if (enable) {
- + /* turn on auto AE/AG */
- + ae_ag_ctrl = ae_ag_ctrl & ~(0x03);
- + } else {
- + /* turn off AE/AG */
- + ae_ag_ctrl = ae_ag_ctrl | 0x03;
- + }
- + ov5640_write_reg(0x3503, ae_ag_ctrl);
- +}
- +
- +bool binning_on(void)
- +{
- + u8 temp;
- + ov5640_read_reg(0x3821, &temp);
- + temp &= 0xfe;
- + if (temp)
- + return true;
- + else
- + return false;
- +}
- +
- +static void ov5640_set_virtual_channel(int channel)
- +{
- + u8 channel_id;
- +
- + ov5640_read_reg(0x4814, &channel_id);
- + channel_id &= ~(3 << 6);
- + ov5640_write_reg(0x4814, channel_id | (channel << 6));
- +}
- +
- +/* download ov5640 settings to sensor through i2c */
- +static int ov5640_download_firmware(struct reg_value *pModeSetting, s32 ArySize)
- +{
- + register u32 Delay_ms = 0;
- + register u16 RegAddr = 0;
- + register u8 Mask = 0;
- + register u8 Val = 0;
- + u8 RegVal = 0;
- + int i, retval = 0;
- +
- + for (i = 0; i < ArySize; ++i, ++pModeSetting) {
- + Delay_ms = pModeSetting->u32Delay_ms;
- + RegAddr = pModeSetting->u16RegAddr;
- + Val = pModeSetting->u8Val;
- + Mask = pModeSetting->u8Mask;
- +
- + if (Mask) {
- + retval = ov5640_read_reg(RegAddr, &RegVal);
- + if (retval < 0)
- + goto err;
- +
- + RegVal &= ~(u8)Mask;
- + Val &= Mask;
- + Val |= RegVal;
- + }
- +
- + retval = ov5640_write_reg(RegAddr, Val);
- + if (retval < 0)
- + goto err;
- +
- + if (Delay_ms)
- + msleep(Delay_ms);
- + }
- +err:
- + return retval;
- +}
- +
- +/* sensor changes between scaling and subsampling
- + * go through exposure calcualtion
- + */
- +static int ov5640_change_mode_exposure_calc(enum ov5640_frame_rate frame_rate,
- + enum ov5640_mode mode)
- +{
- + struct reg_value *pModeSetting = NULL;
- + s32 ArySize = 0;
- + u8 average;
- + int prev_shutter, prev_gain16;
- + int cap_shutter, cap_gain16;
- + int cap_sysclk, cap_HTS, cap_VTS;
- + int light_freq, cap_bandfilt, cap_maxband;
- + long cap_gain16_shutter;
- + int retval = 0;
- +
- + /* check if the input mode and frame rate is valid */
- + pModeSetting =
- + ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
- + ArySize =
- + ov5640_mode_info_data[frame_rate][mode].init_data_size;
- +
- + ov5640_data.pix.width =
- + ov5640_mode_info_data[frame_rate][mode].width;
- + ov5640_data.pix.height =
- + ov5640_mode_info_data[frame_rate][mode].height;
- +
- + if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
- + pModeSetting == NULL || ArySize == 0)
- + return -EINVAL;
- +
- + /* auto focus */
- + /* OV5640_auto_focus();//if no af function, just skip it */
- +
- + /* turn off AE/AG */
- + OV5640_turn_on_AE_AG(0);
- +
- + /* read preview shutter */
- + prev_shutter = OV5640_get_shutter();
- + if ((binning_on()) && (mode != ov5640_mode_720P_1280_720)
- + && (mode != ov5640_mode_1080P_1920_1080))
- + prev_shutter *= 2;
- +
- + /* read preview gain */
- + prev_gain16 = OV5640_get_gain16();
- +
- + /* get average */
- + ov5640_read_reg(0x56a1, &average);
- +
- + /* turn off night mode for capture */
- + OV5640_set_night_mode();
- +
- + /* turn off overlay */
- + /* ov5640_write_reg(0x3022, 0x06);//if no af function, just skip it */
- +
- + OV5640_stream_off();
- +
- + /* Write capture setting */
- + retval = ov5640_download_firmware(pModeSetting, ArySize);
- + if (retval < 0)
- + goto err;
- +
- + /* read capture VTS */
- + cap_VTS = OV5640_get_VTS();
- + cap_HTS = OV5640_get_HTS();
- + cap_sysclk = OV5640_get_sysclk();
- +
- + /* calculate capture banding filter */
- + light_freq = OV5640_get_light_freq();
- + if (light_freq == 60) {
- + /* 60Hz */
- + cap_bandfilt = cap_sysclk * 100 / cap_HTS * 100 / 120;
- + } else {
- + /* 50Hz */
- + cap_bandfilt = cap_sysclk * 100 / cap_HTS;
- + }
- + cap_maxband = (int)((cap_VTS - 4)/cap_bandfilt);
- +
- + /* calculate capture shutter/gain16 */
- + if (average > AE_low && average < AE_high) {
- + /* in stable range */
- + cap_gain16_shutter =
- + prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk
- + * prev_HTS/cap_HTS * AE_Target / average;
- + } else {
- + cap_gain16_shutter =
- + prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk
- + * prev_HTS/cap_HTS;
- + }
- +
- + /* gain to shutter */
- + if (cap_gain16_shutter < (cap_bandfilt * 16)) {
- + /* shutter < 1/100 */
- + cap_shutter = cap_gain16_shutter/16;
- + if (cap_shutter < 1)
- + cap_shutter = 1;
- +
- + cap_gain16 = cap_gain16_shutter/cap_shutter;
- + if (cap_gain16 < 16)
- + cap_gain16 = 16;
- + } else {
- + if (cap_gain16_shutter >
- + (cap_bandfilt * cap_maxband * 16)) {
- + /* exposure reach max */
- + cap_shutter = cap_bandfilt * cap_maxband;
- + cap_gain16 = cap_gain16_shutter / cap_shutter;
- + } else {
- + /* 1/100 < (cap_shutter = n/100) =< max */
- + cap_shutter =
- + ((int) (cap_gain16_shutter/16 / cap_bandfilt))
- + *cap_bandfilt;
- + cap_gain16 = cap_gain16_shutter / cap_shutter;
- + }
- + }
- +
- + /* write capture gain */
- + OV5640_set_gain16(cap_gain16);
- +
- + /* write capture shutter */
- + if (cap_shutter > (cap_VTS - 4)) {
- + cap_VTS = cap_shutter + 4;
- + OV5640_set_VTS(cap_VTS);
- + }
- + OV5640_set_shutter(cap_shutter);
- +
- + OV5640_stream_on();
- +
- +err:
- + return retval;
- +}
- +
- +/* if sensor changes inside scaling or subsampling
- + * change mode directly
- + * */
- +static int ov5640_change_mode_direct(enum ov5640_frame_rate frame_rate,
- + enum ov5640_mode mode)
- +{
- + struct reg_value *pModeSetting = NULL;
- + s32 ArySize = 0;
- + int retval = 0;
- +
- + /* check if the input mode and frame rate is valid */
- + pModeSetting =
- + ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
- + ArySize =
- + ov5640_mode_info_data[frame_rate][mode].init_data_size;
- +
- + ov5640_data.pix.width =
- + ov5640_mode_info_data[frame_rate][mode].width;
- + ov5640_data.pix.height =
- + ov5640_mode_info_data[frame_rate][mode].height;
- +
- + if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
- + pModeSetting == NULL || ArySize == 0)
- + return -EINVAL;
- +
- + /* turn off AE/AG */
- + OV5640_turn_on_AE_AG(0);
- +
- + OV5640_stream_off();
- +
- + /* Write capture setting */
- + retval = ov5640_download_firmware(pModeSetting, ArySize);
- + if (retval < 0)
- + goto err;
- +
- + OV5640_stream_on();
- +
- + OV5640_turn_on_AE_AG(1);
- +
- +err:
- + return retval;
- +}
- +
- +static int ov5640_init_mode(enum ov5640_frame_rate frame_rate,
- + enum ov5640_mode mode, enum ov5640_mode orig_mode)
- +{
- + struct reg_value *pModeSetting = NULL;
- + s32 ArySize = 0;
- + int retval = 0;
- + void *mipi_csi2_info;
- + u32 mipi_reg, msec_wait4stable = 0;
- + enum ov5640_downsize_mode dn_mode, orig_dn_mode;
- +
- + if ((mode > ov5640_mode_MAX || mode < ov5640_mode_MIN)
- + && (mode != ov5640_mode_INIT)) {
- + pr_err("Wrong ov5640 mode detected!\n");
- + return -1;
- + }
- +
- + mipi_csi2_info = mipi_csi2_get_info();
- +
- + /* initial mipi dphy */
- + if (!mipi_csi2_info) {
- + printk(KERN_ERR "%s() in %s: Fail to get mipi_csi2_info!\n",
- + __func__, __FILE__);
- + return -1;
- + }
- +
- + if (!mipi_csi2_get_status(mipi_csi2_info))
- + mipi_csi2_enable(mipi_csi2_info);
- +
- + if (!mipi_csi2_get_status(mipi_csi2_info)) {
- + pr_err("Can not enable mipi csi2 driver!\n");
- + return -1;
- + }
- +
- + mipi_csi2_set_lanes(mipi_csi2_info);
- +
- + /*Only reset MIPI CSI2 HW at sensor initialize*/
- + if (mode == ov5640_mode_INIT)
- + mipi_csi2_reset(mipi_csi2_info);
- +
- + if (ov5640_data.pix.pixelformat == V4L2_PIX_FMT_UYVY)
- + mipi_csi2_set_datatype(mipi_csi2_info, MIPI_DT_YUV422);
- + else if (ov5640_data.pix.pixelformat == V4L2_PIX_FMT_RGB565)
- + mipi_csi2_set_datatype(mipi_csi2_info, MIPI_DT_RGB565);
- + else
- + pr_err("currently this sensor format can not be supported!\n");
- +
- + dn_mode = ov5640_mode_info_data[frame_rate][mode].dn_mode;
- + orig_dn_mode = ov5640_mode_info_data[frame_rate][orig_mode].dn_mode;
- + if (mode == ov5640_mode_INIT) {
- + pModeSetting = ov5640_init_setting_30fps_VGA;
- + ArySize = ARRAY_SIZE(ov5640_init_setting_30fps_VGA);
- +
- + ov5640_data.pix.width = 640;
- + ov5640_data.pix.height = 480;
- + retval = ov5640_download_firmware(pModeSetting, ArySize);
- + if (retval < 0)
- + goto err;
- +
- + pModeSetting = ov5640_setting_30fps_VGA_640_480;
- + ArySize = ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480);
- + retval = ov5640_download_firmware(pModeSetting, ArySize);
- + } else if ((dn_mode == SUBSAMPLING && orig_dn_mode == SCALING) ||
- + (dn_mode == SCALING && orig_dn_mode == SUBSAMPLING)) {
- + /* change between subsampling and scaling
- + * go through exposure calucation */
- + retval = ov5640_change_mode_exposure_calc(frame_rate, mode);
- + } else {
- + /* change inside subsampling or scaling
- + * download firmware directly */
- + retval = ov5640_change_mode_direct(frame_rate, mode);
- + }
- +
- + if (retval < 0)
- + goto err;
- +
- + OV5640_set_AE_target(AE_Target);
- + OV5640_get_light_freq();
- + OV5640_set_bandingfilter();
- + ov5640_set_virtual_channel(ov5640_data.csi);
- +
- + /* add delay to wait for sensor stable */
- + if (mode == ov5640_mode_QSXGA_2592_1944) {
- + /* dump the first two frames: 1/7.5*2
- + * the frame rate of QSXGA is 7.5fps */
- + msec_wait4stable = 267;
- + } else if (frame_rate == ov5640_15_fps) {
- + /* dump the first nine frames: 1/15*9 */
- + msec_wait4stable = 600;
- + } else if (frame_rate == ov5640_30_fps) {
- + /* dump the first nine frames: 1/30*9 */
- + msec_wait4stable = 300;
- + }
- + msleep(msec_wait4stable);
- +
- + if (mipi_csi2_info) {
- + unsigned int i;
- +
- + i = 0;
- +
- + /* wait for mipi sensor ready */
- + mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info);
- + while ((mipi_reg == 0x200) && (i < 10)) {
- + mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info);
- + i++;
- + msleep(10);
- + }
- +
- + if (i >= 10) {
- + pr_err("mipi csi2 can not receive sensor clk!\n");
- + return -1;
- + }
- +
- + i = 0;
- +
- + /* wait for mipi stable */
- + mipi_reg = mipi_csi2_get_error1(mipi_csi2_info);
- + while ((mipi_reg != 0x0) && (i < 10)) {
- + mipi_reg = mipi_csi2_get_error1(mipi_csi2_info);
- + i++;
- + msleep(10);
- + }
- +
- + if (i >= 10) {
- + pr_err("mipi csi2 can not reveive data correctly!\n");
- + return -1;
- + }
- + }
- +err:
- + return retval;
- +}
- +
- +/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */
- +
- +static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
- +{
- + if (s == NULL) {
- + pr_err(" ERROR!! no slave device set!\n");
- + return -1;
- + }
- +
- + memset(p, 0, sizeof(*p));
- + p->u.bt656.clock_curr = ov5640_data.mclk;
- + pr_debug(" clock_curr=mclk=%d\n", ov5640_data.mclk);
- + p->if_type = V4L2_IF_TYPE_BT656;
- + p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
- + p->u.bt656.clock_min = OV5640_XCLK_MIN;
- + p->u.bt656.clock_max = OV5640_XCLK_MAX;
- + p->u.bt656.bt_sync_correct = 1; /* Indicate external vsync */
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @on: indicates power mode (on or off)
- + *
- + * Turns the power on or off, depending on the value of on and returns the
- + * appropriate error code.
- + */
- +static int ioctl_s_power(struct v4l2_int_device *s, int on)
- +{
- + struct sensor_data *sensor = s->priv;
- +
- + if (on && !sensor->on) {
- + if (io_regulator)
- + if (regulator_enable(io_regulator) != 0)
- + return -EIO;
- + if (core_regulator)
- + if (regulator_enable(core_regulator) != 0)
- + return -EIO;
- + if (gpo_regulator)
- + if (regulator_enable(gpo_regulator) != 0)
- + return -EIO;
- + if (analog_regulator)
- + if (regulator_enable(analog_regulator) != 0)
- + return -EIO;
- + /* Make sure power on */
- + ov5640_standby(0);
- + } else if (!on && sensor->on) {
- + if (analog_regulator)
- + regulator_disable(analog_regulator);
- + if (core_regulator)
- + regulator_disable(core_regulator);
- + if (io_regulator)
- + regulator_disable(io_regulator);
- + if (gpo_regulator)
- + regulator_disable(gpo_regulator);
- +
- + ov5640_standby(1);
- + }
- +
- + sensor->on = on;
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
- + *
- + * Returns the sensor's video CAPTURE parameters.
- + */
- +static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
- +{
- + struct sensor_data *sensor = s->priv;
- + struct v4l2_captureparm *cparm = &a->parm.capture;
- + int ret = 0;
- +
- + switch (a->type) {
- + /* This is the only case currently handled. */
- + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- + memset(a, 0, sizeof(*a));
- + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- + cparm->capability = sensor->streamcap.capability;
- + cparm->timeperframe = sensor->streamcap.timeperframe;
- + cparm->capturemode = sensor->streamcap.capturemode;
- + ret = 0;
- + break;
- +
- + /* These are all the possible cases. */
- + case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- + case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- + case V4L2_BUF_TYPE_VBI_CAPTURE:
- + case V4L2_BUF_TYPE_VBI_OUTPUT:
- + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- + ret = -EINVAL;
- + break;
- +
- + default:
- + pr_debug(" type is unknown - %d\n", a->type);
- + ret = -EINVAL;
- + break;
- + }
- +
- + return ret;
- +}
- +
- +/*!
- + * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
- + *
- + * Configures the sensor to use the input parameters, if possible. If
- + * not possible, reverts to the old parameters and returns the
- + * appropriate error code.
- + */
- +static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
- +{
- + struct sensor_data *sensor = s->priv;
- + struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
- + u32 tgt_fps; /* target frames per secound */
- + enum ov5640_frame_rate frame_rate;
- + enum ov5640_mode orig_mode;
- + int ret = 0;
- +
- + /* Make sure power on */
- + ov5640_standby(0);
- +
- + switch (a->type) {
- + /* This is the only case currently handled. */
- + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- + /* Check that the new frame rate is allowed. */
- + if ((timeperframe->numerator == 0) ||
- + (timeperframe->denominator == 0)) {
- + timeperframe->denominator = DEFAULT_FPS;
- + timeperframe->numerator = 1;
- + }
- +
- + tgt_fps = timeperframe->denominator /
- + timeperframe->numerator;
- +
- + if (tgt_fps > MAX_FPS) {
- + timeperframe->denominator = MAX_FPS;
- + timeperframe->numerator = 1;
- + } else if (tgt_fps < MIN_FPS) {
- + timeperframe->denominator = MIN_FPS;
- + timeperframe->numerator = 1;
- + }
- +
- + /* Actual frame rate we use */
- + tgt_fps = timeperframe->denominator /
- + timeperframe->numerator;
- +
- + if (tgt_fps == 15)
- + frame_rate = ov5640_15_fps;
- + else if (tgt_fps == 30)
- + frame_rate = ov5640_30_fps;
- + else {
- + pr_err(" The camera frame rate is not supported!\n");
- + return -EINVAL;
- + }
- +
- + orig_mode = sensor->streamcap.capturemode;
- + ret = ov5640_init_mode(frame_rate,
- + (u32)a->parm.capture.capturemode, orig_mode);
- + if (ret < 0)
- + return ret;
- +
- + sensor->streamcap.timeperframe = *timeperframe;
- + sensor->streamcap.capturemode =
- + (u32)a->parm.capture.capturemode;
- +
- + break;
- +
- + /* These are all the possible cases. */
- + case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- + case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- + case V4L2_BUF_TYPE_VBI_CAPTURE:
- + case V4L2_BUF_TYPE_VBI_OUTPUT:
- + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- + pr_debug(" type is not " \
- + "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
- + a->type);
- + ret = -EINVAL;
- + break;
- +
- + default:
- + pr_debug(" type is unknown - %d\n", a->type);
- + ret = -EINVAL;
- + break;
- + }
- +
- + return ret;
- +}
- +
- +/*!
- + * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
- + * @s: pointer to standard V4L2 device structure
- + * @f: pointer to standard V4L2 v4l2_format structure
- + *
- + * Returns the sensor's current pixel format in the v4l2_format
- + * parameter.
- + */
- +static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
- +{
- + struct sensor_data *sensor = s->priv;
- +
- + f->fmt.pix = sensor->pix;
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
- + *
- + * If the requested control is supported, returns the control's current
- + * value from the video_control[] array. Otherwise, returns -EINVAL
- + * if the control is not supported.
- + */
- +static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
- +{
- + int ret = 0;
- +
- + switch (vc->id) {
- + case V4L2_CID_BRIGHTNESS:
- + vc->value = ov5640_data.brightness;
- + break;
- + case V4L2_CID_HUE:
- + vc->value = ov5640_data.hue;
- + break;
- + case V4L2_CID_CONTRAST:
- + vc->value = ov5640_data.contrast;
- + break;
- + case V4L2_CID_SATURATION:
- + vc->value = ov5640_data.saturation;
- + break;
- + case V4L2_CID_RED_BALANCE:
- + vc->value = ov5640_data.red;
- + break;
- + case V4L2_CID_BLUE_BALANCE:
- + vc->value = ov5640_data.blue;
- + break;
- + case V4L2_CID_EXPOSURE:
- + vc->value = ov5640_data.ae_mode;
- + break;
- + default:
- + ret = -EINVAL;
- + }
- +
- + return ret;
- +}
- +
- +/*!
- + * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
- + *
- + * If the requested control is supported, sets the control's current
- + * value in HW (and updates the video_control[] array). Otherwise,
- + * returns -EINVAL if the control is not supported.
- + */
- +static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
- +{
- + int retval = 0;
- +
- + pr_debug("In ov5640:ioctl_s_ctrl %d\n",
- + vc->id);
- +
- + switch (vc->id) {
- + case V4L2_CID_BRIGHTNESS:
- + break;
- + case V4L2_CID_CONTRAST:
- + break;
- + case V4L2_CID_SATURATION:
- + break;
- + case V4L2_CID_HUE:
- + break;
- + case V4L2_CID_AUTO_WHITE_BALANCE:
- + break;
- + case V4L2_CID_DO_WHITE_BALANCE:
- + break;
- + case V4L2_CID_RED_BALANCE:
- + break;
- + case V4L2_CID_BLUE_BALANCE:
- + break;
- + case V4L2_CID_GAMMA:
- + break;
- + case V4L2_CID_EXPOSURE:
- + break;
- + case V4L2_CID_AUTOGAIN:
- + break;
- + case V4L2_CID_GAIN:
- + break;
- + case V4L2_CID_HFLIP:
- + break;
- + case V4L2_CID_VFLIP:
- + break;
- + default:
- + retval = -EPERM;
- + break;
- + }
- +
- + return retval;
- +}
- +
- +/*!
- + * ioctl_enum_framesizes - V4L2 sensor interface handler for
- + * VIDIOC_ENUM_FRAMESIZES ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
- + *
- + * Return 0 if successful, otherwise -EINVAL.
- + */
- +static int ioctl_enum_framesizes(struct v4l2_int_device *s,
- + struct v4l2_frmsizeenum *fsize)
- +{
- + if (fsize->index > ov5640_mode_MAX)
- + return -EINVAL;
- +
- + fsize->pixel_format = ov5640_data.pix.pixelformat;
- + fsize->discrete.width =
- + max(ov5640_mode_info_data[0][fsize->index].width,
- + ov5640_mode_info_data[1][fsize->index].width);
- + fsize->discrete.height =
- + max(ov5640_mode_info_data[0][fsize->index].height,
- + ov5640_mode_info_data[1][fsize->index].height);
- + return 0;
- +}
- +
- +/*!
- + * ioctl_g_chip_ident - V4L2 sensor interface handler for
- + * VIDIOC_DBG_G_CHIP_IDENT ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @id: pointer to int
- + *
- + * Return 0.
- + */
- +static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
- +{
- + ((struct v4l2_dbg_chip_ident *)id)->match.type =
- + V4L2_CHIP_MATCH_I2C_DRIVER;
- + strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name,
- + "ov5640_mipi_camera");
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
- + * @s: pointer to standard V4L2 device structure
- + */
- +static int ioctl_init(struct v4l2_int_device *s)
- +{
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT
- + * @s: pointer to standard V4L2 device structure
- + * @fmt: pointer to standard V4L2 fmt description structure
- + *
- + * Return 0.
- + */
- +static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
- + struct v4l2_fmtdesc *fmt)
- +{
- + if (fmt->index > ov5640_mode_MAX)
- + return -EINVAL;
- +
- + fmt->pixelformat = ov5640_data.pix.pixelformat;
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
- + * @s: pointer to standard V4L2 device structure
- + *
- + * Initialise the device when slave attaches to the master.
- + */
- +static int ioctl_dev_init(struct v4l2_int_device *s)
- +{
- + struct sensor_data *sensor = s->priv;
- + u32 tgt_xclk; /* target xclk */
- + u32 tgt_fps; /* target frames per secound */
- + int ret;
- + enum ov5640_frame_rate frame_rate;
- + void *mipi_csi2_info;
- +
- + ov5640_data.on = true;
- +
- + /* mclk */
- + tgt_xclk = ov5640_data.mclk;
- + tgt_xclk = min(tgt_xclk, (u32)OV5640_XCLK_MAX);
- + tgt_xclk = max(tgt_xclk, (u32)OV5640_XCLK_MIN);
- + ov5640_data.mclk = tgt_xclk;
- +
- + pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000);
- +
- + /* Default camera frame rate is set in probe */
- + tgt_fps = sensor->streamcap.timeperframe.denominator /
- + sensor->streamcap.timeperframe.numerator;
- +
- + if (tgt_fps == 15)
- + frame_rate = ov5640_15_fps;
- + else if (tgt_fps == 30)
- + frame_rate = ov5640_30_fps;
- + else
- + return -EINVAL; /* Only support 15fps or 30fps now. */
- +
- + mipi_csi2_info = mipi_csi2_get_info();
- +
- + /* enable mipi csi2 */
- + if (mipi_csi2_info)
- + mipi_csi2_enable(mipi_csi2_info);
- + else {
- + printk(KERN_ERR "%s() in %s: Fail to get mipi_csi2_info!\n",
- + __func__, __FILE__);
- + return -EPERM;
- + }
- +
- + ret = ov5640_init_mode(frame_rate, ov5640_mode_INIT, ov5640_mode_INIT);
- +
- + return ret;
- +}
- +
- +/*!
- + * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num
- + * @s: pointer to standard V4L2 device structure
- + *
- + * Delinitialise the device when slave detaches to the master.
- + */
- +static int ioctl_dev_exit(struct v4l2_int_device *s)
- +{
- + void *mipi_csi2_info;
- +
- + mipi_csi2_info = mipi_csi2_get_info();
- +
- + /* disable mipi csi2 */
- + if (mipi_csi2_info)
- + if (mipi_csi2_get_status(mipi_csi2_info))
- + mipi_csi2_disable(mipi_csi2_info);
- +
- + return 0;
- +}
- +
- +/*!
- + * This structure defines all the ioctls for this module and links them to the
- + * enumeration.
- + */
- +static struct v4l2_int_ioctl_desc ov5640_ioctl_desc[] = {
- + {vidioc_int_dev_init_num, (v4l2_int_ioctl_func *) ioctl_dev_init},
- + {vidioc_int_dev_exit_num, ioctl_dev_exit},
- + {vidioc_int_s_power_num, (v4l2_int_ioctl_func *) ioctl_s_power},
- + {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func *) ioctl_g_ifparm},
- +/* {vidioc_int_g_needs_reset_num,
- + (v4l2_int_ioctl_func *)ioctl_g_needs_reset}, */
- +/* {vidioc_int_reset_num, (v4l2_int_ioctl_func *)ioctl_reset}, */
- + {vidioc_int_init_num, (v4l2_int_ioctl_func *) ioctl_init},
- + {vidioc_int_enum_fmt_cap_num,
- + (v4l2_int_ioctl_func *) ioctl_enum_fmt_cap},
- +/* {vidioc_int_try_fmt_cap_num,
- + (v4l2_int_ioctl_func *)ioctl_try_fmt_cap}, */
- + {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func *) ioctl_g_fmt_cap},
- +/* {vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *) ioctl_s_fmt_cap}, */
- + {vidioc_int_g_parm_num, (v4l2_int_ioctl_func *) ioctl_g_parm},
- + {vidioc_int_s_parm_num, (v4l2_int_ioctl_func *) ioctl_s_parm},
- +/* {vidioc_int_queryctrl_num, (v4l2_int_ioctl_func *)ioctl_queryctrl}, */
- + {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func *) ioctl_g_ctrl},
- + {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func *) ioctl_s_ctrl},
- + {vidioc_int_enum_framesizes_num,
- + (v4l2_int_ioctl_func *) ioctl_enum_framesizes},
- + {vidioc_int_g_chip_ident_num,
- + (v4l2_int_ioctl_func *) ioctl_g_chip_ident},
- +};
- +
- +static struct v4l2_int_slave ov5640_slave = {
- + .ioctls = ov5640_ioctl_desc,
- + .num_ioctls = ARRAY_SIZE(ov5640_ioctl_desc),
- +};
- +
- +static struct v4l2_int_device ov5640_int_device = {
- + .module = THIS_MODULE,
- + .name = "ov5640",
- + .type = v4l2_int_type_slave,
- + .u = {
- + .slave = &ov5640_slave,
- + },
- +};
- +
- +/*!
- + * ov5640 I2C probe function
- + *
- + * @param adapter struct i2c_adapter *
- + * @return Error code indicating success or failure
- + */
- +static int ov5640_probe(struct i2c_client *client,
- + const struct i2c_device_id *id)
- +{
- + struct device *dev = &client->dev;
- + int retval;
- + u8 chip_id_high, chip_id_low;
- +
- + /* request power down pin */
- + pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
- + if (!gpio_is_valid(pwn_gpio)) {
- + dev_warn(dev, "no sensor pwdn pin available");
- + return -EINVAL;
- + }
- + retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
- + "ov5640_mipi_pwdn");
- + if (retval < 0)
- + return retval;
- +
- + /* request reset pin */
- + rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
- + if (!gpio_is_valid(rst_gpio)) {
- + dev_warn(dev, "no sensor reset pin available");
- + return -EINVAL;
- + }
- + retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
- + "ov5640_mipi_reset");
- + if (retval < 0)
- + return retval;
- +
- + /* Set initial values for the sensor struct. */
- + memset(&ov5640_data, 0, sizeof(ov5640_data));
- + ov5640_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
- + if (IS_ERR(ov5640_data.sensor_clk)) {
- + /* assuming clock enabled by default */
- + ov5640_data.sensor_clk = NULL;
- + dev_err(dev, "clock-frequency missing or invalid\n");
- + return PTR_ERR(ov5640_data.sensor_clk);
- + }
- +
- + retval = of_property_read_u32(dev->of_node, "mclk",
- + &(ov5640_data.mclk));
- + if (retval) {
- + dev_err(dev, "mclk missing or invalid\n");
- + return retval;
- + }
- +
- + retval = of_property_read_u32(dev->of_node, "mclk_source",
- + (u32 *) &(ov5640_data.mclk_source));
- + if (retval) {
- + dev_err(dev, "mclk_source missing or invalid\n");
- + return retval;
- + }
- +
- + retval = of_property_read_u32(dev->of_node, "csi_id",
- + &(ov5640_data.csi));
- + if (retval) {
- + dev_err(dev, "csi id missing or invalid\n");
- + return retval;
- + }
- +
- + clk_prepare_enable(ov5640_data.sensor_clk);
- +
- + ov5640_data.io_init = ov5640_reset;
- + ov5640_data.i2c_client = client;
- + ov5640_data.pix.pixelformat = V4L2_PIX_FMT_UYVY;
- + ov5640_data.pix.width = 640;
- + ov5640_data.pix.height = 480;
- + ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
- + V4L2_CAP_TIMEPERFRAME;
- + ov5640_data.streamcap.capturemode = 0;
- + ov5640_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
- + ov5640_data.streamcap.timeperframe.numerator = 1;
- +
- + ov5640_power_on(dev);
- +
- + ov5640_reset();
- +
- + ov5640_standby(0);
- +
- + retval = ov5640_read_reg(OV5640_CHIP_ID_HIGH_BYTE, &chip_id_high);
- + if (retval < 0 || chip_id_high != 0x56) {
- + pr_warning("camera ov5640_mipi is not found\n");
- + clk_disable_unprepare(ov5640_data.sensor_clk);
- + return -ENODEV;
- + }
- + retval = ov5640_read_reg(OV5640_CHIP_ID_LOW_BYTE, &chip_id_low);
- + if (retval < 0 || chip_id_low != 0x40) {
- + pr_warning("camera ov5640_mipi is not found\n");
- + clk_disable_unprepare(ov5640_data.sensor_clk);
- + return -ENODEV;
- + }
- +
- + ov5640_standby(1);
- +
- + ov5640_int_device.priv = &ov5640_data;
- + retval = v4l2_int_device_register(&ov5640_int_device);
- +
- + clk_disable_unprepare(ov5640_data.sensor_clk);
- +
- + pr_info("camera ov5640_mipi is found\n");
- + return retval;
- +}
- +
- +/*!
- + * ov5640 I2C detach function
- + *
- + * @param client struct i2c_client *
- + * @return Error code indicating success or failure
- + */
- +static int ov5640_remove(struct i2c_client *client)
- +{
- + v4l2_int_device_unregister(&ov5640_int_device);
- +
- + if (gpo_regulator)
- + regulator_disable(gpo_regulator);
- +
- + if (analog_regulator)
- + regulator_disable(analog_regulator);
- +
- + if (core_regulator)
- + regulator_disable(core_regulator);
- +
- + if (io_regulator)
- + regulator_disable(io_regulator);
- +
- + return 0;
- +}
- +
- +/*!
- + * ov5640 init function
- + * Called by insmod ov5640_camera.ko.
- + *
- + * @return Error code indicating success or failure
- + */
- +static __init int ov5640_init(void)
- +{
- + u8 err;
- +
- + err = i2c_add_driver(&ov5640_i2c_driver);
- + if (err != 0)
- + pr_err("%s:driver registration failed, error=%d\n",
- + __func__, err);
- +
- + return err;
- +}
- +
- +/*!
- + * OV5640 cleanup function
- + * Called on rmmod ov5640_camera.ko
- + *
- + * @return Error code indicating success or failure
- + */
- +static void __exit ov5640_clean(void)
- +{
- + i2c_del_driver(&ov5640_i2c_driver);
- +}
- +
- +module_init(ov5640_init);
- +module_exit(ov5640_clean);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("OV5640 MIPI Camera Driver");
- +MODULE_LICENSE("GPL");
- +MODULE_VERSION("1.0");
- +MODULE_ALIAS("CSI");
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/capture/ov5642.c linux-3.14.35/drivers/media/platform/mxc/capture/ov5642.c
- --- linux-3.14.35.orig/drivers/media/platform/mxc/capture/ov5642.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/capture/ov5642.c 2015-03-08 14:27:37.601684501 -0500
- @@ -0,0 +1,4252 @@
- +/*
- + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/init.h>
- +#include <linux/slab.h>
- +#include <linux/ctype.h>
- +#include <linux/types.h>
- +#include <linux/delay.h>
- +#include <linux/clk.h>
- +#include <linux/of_device.h>
- +#include <linux/i2c.h>
- +#include <linux/of_gpio.h>
- +#include <linux/pinctrl/consumer.h>
- +#include <linux/regulator/consumer.h>
- +#include <linux/fsl_devices.h>
- +#include <media/v4l2-chip-ident.h>
- +#include <media/v4l2-int-device.h>
- +#include "mxc_v4l2_capture.h"
- +
- +#define OV5642_VOLTAGE_ANALOG 2800000
- +#define OV5642_VOLTAGE_DIGITAL_CORE 1500000
- +#define OV5642_VOLTAGE_DIGITAL_IO 1800000
- +
- +#define MIN_FPS 15
- +#define MAX_FPS 30
- +#define DEFAULT_FPS 30
- +
- +#define OV5642_XCLK_MIN 6000000
- +#define OV5642_XCLK_MAX 24000000
- +
- +#define OV5642_CHIP_ID_HIGH_BYTE 0x300A
- +#define OV5642_CHIP_ID_LOW_BYTE 0x300B
- +
- +enum ov5642_mode {
- + ov5642_mode_MIN = 0,
- + ov5642_mode_VGA_640_480 = 0,
- + ov5642_mode_QVGA_320_240 = 1,
- + ov5642_mode_NTSC_720_480 = 2,
- + ov5642_mode_PAL_720_576 = 3,
- + ov5642_mode_720P_1280_720 = 4,
- + ov5642_mode_1080P_1920_1080 = 5,
- + ov5642_mode_QSXGA_2592_1944 = 6,
- + ov5642_mode_QCIF_176_144 = 7,
- + ov5642_mode_XGA_1024_768 = 8,
- + ov5642_mode_MAX = 8
- +};
- +
- +enum ov5642_frame_rate {
- + ov5642_15_fps,
- + ov5642_30_fps
- +};
- +
- +static int ov5642_framerates[] = {
- + [ov5642_15_fps] = 15,
- + [ov5642_30_fps] = 30,
- +};
- +
- +struct reg_value {
- + u16 u16RegAddr;
- + u8 u8Val;
- + u8 u8Mask;
- + u32 u32Delay_ms;
- +};
- +
- +struct ov5642_mode_info {
- + enum ov5642_mode mode;
- + u32 width;
- + u32 height;
- + struct reg_value *init_data_ptr;
- + u32 init_data_size;
- +};
- +
- +/*!
- + * Maintains the information on the current state of the sesor.
- + */
- +static struct sensor_data ov5642_data;
- +static int pwn_gpio, rst_gpio;
- +
- +static struct reg_value ov5642_rot_none_VGA[] = {
- + {0x3818, 0xc1, 0x00, 0x00}, {0x3621, 0x87, 0x00, 0x00},
- +};
- +
- +static struct reg_value ov5642_rot_vert_flip_VGA[] = {
- + {0x3818, 0x20, 0xbf, 0x00}, {0x3621, 0x20, 0xff, 0x00},
- +};
- +
- +static struct reg_value ov5642_rot_horiz_flip_VGA[] = {
- + {0x3818, 0x81, 0x00, 0x01}, {0x3621, 0xa7, 0x00, 0x00},
- +};
- +
- +static struct reg_value ov5642_rot_180_VGA[] = {
- + {0x3818, 0x60, 0xff, 0x00}, {0x3621, 0x00, 0xdf, 0x00},
- +};
- +
- +
- +static struct reg_value ov5642_rot_none_FULL[] = {
- + {0x3818, 0xc0, 0x00, 0x00}, {0x3621, 0x09, 0x00, 0x00},
- +};
- +
- +static struct reg_value ov5642_rot_vert_flip_FULL[] = {
- + {0x3818, 0x20, 0xbf, 0x01}, {0x3621, 0x20, 0xff, 0x00},
- +};
- +
- +static struct reg_value ov5642_rot_horiz_flip_FULL[] = {
- + {0x3818, 0x80, 0x00, 0x01}, {0x3621, 0x29, 0x00, 0x00},
- +};
- +
- +static struct reg_value ov5642_rot_180_FULL[] = {
- + {0x3818, 0x60, 0xff, 0x00}, {0x3621, 0x00, 0xdf, 0x00},
- +};
- +
- +
- +static struct reg_value ov5642_initial_setting[] = {
- + {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
- + {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
- + {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
- + {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
- + {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0},
- + {0x3010, 0x00, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
- + {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
- + {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
- + {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
- + {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
- + {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
- + {0x3606, 0x3f, 0, 0}, {0x3c00, 0x04, 0, 0}, {0x3c01, 0x80, 0, 0},
- + {0x5000, 0x4f, 0, 0}, {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0},
- + {0x5182, 0x00, 0, 0}, {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0},
- + {0x5001, 0xff, 0, 0}, {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0},
- + {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0},
- + {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0},
- + {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
- + {0x380b, 0xe0, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0},
- + {0x501f, 0x00, 0, 0}, {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0},
- + {0x3503, 0x07, 0, 0}, {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0},
- + {0x350b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0},
- + {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
- + {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0},
- + {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
- + {0x3801, 0x80, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0},
- + {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0},
- + {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
- + {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
- + {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
- + {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
- + {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
- + {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
- + {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
- + {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
- + {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
- + {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
- + {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
- + {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
- + {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
- + {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
- + {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
- + {0x3a1f, 0x10, 0, 0}, {0x3030, 0x0b, 0, 0}, {0x3a02, 0x00, 0, 0},
- + {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
- + {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
- + {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
- + {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
- + {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
- + {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
- + {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
- + {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
- + {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
- + {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
- + {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
- + {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
- + {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
- + {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
- + {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
- + {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
- + {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
- + {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
- + {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
- + {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
- + {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
- + {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
- + {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
- + {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
- + {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
- + {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
- + {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
- + {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
- + {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
- + {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
- + {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
- + {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
- + {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
- + {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
- + {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
- + {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
- + {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
- + {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
- + {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
- + {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
- + {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
- + {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
- + {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
- + {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
- + {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
- + {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
- + {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
- + {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
- + {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
- + {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
- + {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
- + {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
- + {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
- + {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
- + {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
- + {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
- + {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
- + {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
- + {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
- + {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
- + {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
- + {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
- + {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
- + {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
- + {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
- + {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
- + {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
- + {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
- + {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
- + {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
- + {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
- + {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
- + {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
- + {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
- + {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
- + {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
- + {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
- + {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
- + {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
- + {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
- + {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
- + {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
- + {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
- + {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
- + {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
- + {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
- + {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
- + {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
- + {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
- + {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
- + {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
- + {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
- + {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
- + {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
- + {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
- + {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
- + {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
- + {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
- + {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
- + {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
- + {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
- + {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
- + {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
- + {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
- + {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
- + {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
- + {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
- + {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
- + {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
- + {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
- + {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
- + {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
- + {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
- + {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
- + {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
- + {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
- + {0x302b, 0x00, 0, 300},
- +};
- +
- +static struct reg_value ov5642_setting_15fps_QCIF_176_144[] = {
- + {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
- + {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
- + {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
- + {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
- + {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0},
- + {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
- + {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
- + {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
- + {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
- + {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
- + {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
- + {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
- + {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
- + {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
- + {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
- + {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
- + {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
- + {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
- + {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
- + {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
- + {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0},
- + {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0},
- + {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0},
- + {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0},
- + {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
- + {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0},
- + {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
- + {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0},
- + {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0},
- + {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
- + {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
- + {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
- + {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0},
- + {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0},
- + {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
- + {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0},
- + {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0},
- + {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0},
- + {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0},
- + {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0},
- + {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0},
- + {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0},
- + {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0},
- + {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0},
- + {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0},
- + {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0},
- + {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0},
- + {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0},
- + {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0},
- + {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0},
- + {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0},
- + {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0},
- + {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0},
- + {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0},
- + {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0},
- + {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0},
- + {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0},
- + {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0},
- + {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0},
- + {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0},
- + {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0},
- + {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0},
- + {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0},
- + {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0},
- + {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0},
- + {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0},
- + {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0},
- + {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0},
- + {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0},
- + {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0},
- + {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0},
- + {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0},
- + {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0},
- + {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0},
- + {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0},
- + {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0},
- + {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0},
- + {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0},
- + {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0},
- + {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0},
- + {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0},
- + {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0},
- + {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0},
- + {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0},
- + {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0},
- + {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0},
- + {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0},
- + {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0},
- + {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0},
- + {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0},
- + {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0},
- + {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0},
- + {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0},
- + {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0},
- + {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0},
- + {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0},
- + {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0},
- + {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0},
- + {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0},
- + {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0},
- + {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0},
- + {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0},
- + {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0},
- + {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0},
- + {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0},
- + {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0},
- + {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0},
- + {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0},
- + {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0},
- + {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0},
- + {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0},
- + {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0},
- + {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0},
- + {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0},
- + {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0},
- + {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0},
- + {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0},
- + {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0},
- + {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0},
- + {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0},
- + {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0},
- + {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0},
- + {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0},
- + {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0},
- + {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0},
- + {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0},
- + {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0},
- + {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0},
- + {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0},
- + {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0},
- + {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0},
- + {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0},
- + {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0},
- + {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0},
- + {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0},
- + {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0},
- + {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0},
- + {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0},
- + {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0},
- + {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0},
- + {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0},
- + {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0},
- + {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0},
- + {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0},
- + {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0},
- + {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0},
- + {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0},
- + {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0},
- + {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0},
- + {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0},
- + {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0},
- + {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0},
- + {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0},
- + {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0},
- + {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0},
- + {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0},
- + {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0},
- + {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0},
- + {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0},
- + {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0},
- + {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0},
- + {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0},
- + {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0},
- + {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0},
- + {0x380b, 0x90, 0, 0}, {0x3a00, 0x78, 0, 0},
- +};
- +
- +static struct reg_value ov5642_setting_30fps_QCIF_176_144[] = {
- + {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
- + {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
- + {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
- + {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
- + {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x10, 0, 0},
- + {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
- + {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
- + {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
- + {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
- + {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
- + {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
- + {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
- + {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
- + {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
- + {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
- + {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
- + {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
- + {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
- + {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
- + {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
- + {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0},
- + {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0},
- + {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0},
- + {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0},
- + {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
- + {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0},
- + {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
- + {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0},
- + {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0},
- + {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
- + {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
- + {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
- + {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0},
- + {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0},
- + {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
- + {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0},
- + {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0},
- + {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0},
- + {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0},
- + {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0},
- + {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0},
- + {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0},
- + {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0},
- + {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0},
- + {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0},
- + {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0},
- + {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0},
- + {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0},
- + {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0},
- + {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0},
- + {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0},
- + {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0},
- + {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0},
- + {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0},
- + {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0},
- + {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0},
- + {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0},
- + {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0},
- + {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0},
- + {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0},
- + {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0},
- + {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0},
- + {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0},
- + {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0},
- + {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0},
- + {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0},
- + {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0},
- + {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0},
- + {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0},
- + {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0},
- + {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0},
- + {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0},
- + {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0},
- + {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0},
- + {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0},
- + {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0},
- + {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0},
- + {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0},
- + {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0},
- + {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0},
- + {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0},
- + {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0},
- + {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0},
- + {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0},
- + {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0},
- + {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0},
- + {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0},
- + {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0},
- + {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0},
- + {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0},
- + {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0},
- + {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0},
- + {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0},
- + {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0},
- + {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0},
- + {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0},
- + {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0},
- + {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0},
- + {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0},
- + {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0},
- + {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0},
- + {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0},
- + {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0},
- + {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0},
- + {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0},
- + {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0},
- + {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0},
- + {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0},
- + {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0},
- + {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0},
- + {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0},
- + {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0},
- + {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0},
- + {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0},
- + {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0},
- + {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0},
- + {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0},
- + {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0},
- + {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0},
- + {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0},
- + {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0},
- + {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0},
- + {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0},
- + {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0},
- + {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0},
- + {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0},
- + {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0},
- + {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0},
- + {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0},
- + {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0},
- + {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0},
- + {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0},
- + {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0},
- + {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0},
- + {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0},
- + {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0},
- + {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0},
- + {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0},
- + {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0},
- + {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0},
- + {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0},
- + {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0},
- + {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0},
- + {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0},
- + {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0},
- + {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0},
- + {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0},
- + {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0},
- + {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0},
- + {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0},
- + {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0},
- + {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0},
- + {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0},
- + {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0},
- + {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0},
- + {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0},
- + {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0},
- + {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0},
- + {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0},
- + {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0},
- + {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0},
- + {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0},
- + {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0},
- + {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0},
- + {0x380b, 0x90, 0, 0}, {0x3a00, 0x78, 0, 0},
- +};
- +
- +static struct reg_value ov5642_setting_15fps_QSXGA_2592_1944[] = {
- + {0x3503, 0x07, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0},
- + {0x3002, 0x00, 0, 0}, {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0},
- + {0x3005, 0xff, 0, 0}, {0x3006, 0xff, 0, 0}, {0x3007, 0x3f, 0, 0},
- + {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3818, 0xc0, 0, 0},
- + {0x3621, 0x09, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
- + {0x3602, 0xe4, 0, 0}, {0x3612, 0xac, 0, 0}, {0x3613, 0x44, 0, 0},
- + {0x3622, 0x60, 0, 0}, {0x3623, 0x22, 0, 0}, {0x3604, 0x48, 0, 0},
- + {0x3705, 0xda, 0, 0}, {0x370a, 0x80, 0, 0}, {0x3801, 0x95, 0, 0},
- + {0x3803, 0x0e, 0, 0}, {0x3804, 0x0a, 0, 0}, {0x3805, 0x20, 0, 0},
- + {0x3806, 0x07, 0, 0}, {0x3807, 0x98, 0, 0}, {0x3808, 0x0a, 0, 0},
- + {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0},
- + {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0},
- + {0x380f, 0xd0, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3815, 0x44, 0, 0},
- + {0x3824, 0x11, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0},
- + {0x3a00, 0x78, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0},
- + {0x5682, 0x0a, 0, 0}, {0x5683, 0x20, 0, 0}, {0x5686, 0x07, 0, 0},
- + {0x5687, 0x98, 0, 0}, {0x5001, 0xff, 0, 0}, {0x589b, 0x00, 0, 0},
- + {0x589a, 0xc0, 0, 0}, {0x4407, 0x04, 0, 0}, {0x3008, 0x02, 0, 0},
- + {0x460b, 0x37, 0, 0}, {0x460c, 0x22, 0, 0}, {0x471d, 0x05, 0, 0},
- + {0x4713, 0x03, 0, 0}, {0x471c, 0xd0, 0, 0}, {0x3815, 0x01, 0, 0},
- + {0x501f, 0x00, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3819, 0x80, 0, 0},
- + {0x5002, 0xe0, 0, 0}, {0x530a, 0x01, 0, 0}, {0x530d, 0x10, 0, 0},
- + {0x530c, 0x04, 0, 0}, {0x5312, 0x20, 0, 0}, {0x5282, 0x01, 0, 0},
- + {0x3010, 0x10, 0, 0}, {0x3012, 0x00, 0, 0},
- +};
- +
- +
- +static struct reg_value ov5642_setting_VGA_2_QVGA[] = {
- + {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0},
- + {0x380b, 0xf0, 0, 0}, {0x3815, 0x04, 0, 0},
- +};
- +
- +static struct reg_value ov5642_setting_QSXGA_2_VGA[] = {
- + {0x3503, 0x00, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0},
- + {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0},
- + {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0},
- + {0x3010, 0x00, 0, 0}, {0x3818, 0xc1, 0, 0}, {0x3621, 0x87, 0, 0},
- + {0x350c, 0x03, 0, 0}, {0x350d, 0xe8, 0, 0}, {0x3602, 0xfc, 0, 0},
- + {0x3612, 0xff, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3622, 0x60, 0, 0},
- + {0x3623, 0x01, 0, 0}, {0x3604, 0x48, 0, 0}, {0x3705, 0xdb, 0, 0},
- + {0x370a, 0x81, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
- + {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x3806, 0x03, 0, 0},
- + {0x3807, 0xc0, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0},
- + {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x0c, 0, 0},
- + {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
- + {0x3810, 0x40, 0, 0}, {0x3815, 0x04, 0, 0}, {0x3824, 0x11, 0, 0},
- + {0x3825, 0xb4, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x5682, 0x05, 0, 0},
- + {0x5683, 0x00, 0, 0}, {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0},
- + {0x5001, 0xff, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
- + {0x4407, 0x0c, 0, 0}, {0x3008, 0x02, 0, 0}, {0x460b, 0x37, 0, 0},
- + {0x460c, 0x22, 0, 0}, {0x471d, 0x05, 0, 0}, {0x4713, 0x02, 0, 0},
- + {0x471c, 0xd0, 0, 0}, {0x3815, 0x04, 0, 0}, {0x501f, 0x00, 0, 0},
- + {0x3002, 0x5c, 0, 0}, {0x3819, 0x80, 0, 0}, {0x5002, 0xe0, 0, 0},
- + {0x530a, 0x01, 0, 0}, {0x530d, 0x0c, 0, 0}, {0x530c, 0x00, 0, 0},
- + {0x5312, 0x40, 0, 0}, {0x5282, 0x00, 0, 0},
- + {0x3012, 0x02, 0, 0}, {0x3010, 0x00, 0, 0},
- +};
- +
- +static struct reg_value ov5642_setting_30fps_VGA_640_480[] = {
- + {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
- + {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
- + {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
- + {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
- + {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
- + {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
- + {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
- + {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
- + {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
- + {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
- + {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
- + {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
- + {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
- + {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
- + {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
- + {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
- + {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
- + {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
- + {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
- + {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
- + {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
- + {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
- + {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0},
- + {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
- + {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
- + {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0},
- + {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
- + {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
- + {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
- + {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
- + {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
- + {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
- + {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
- + {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
- + {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
- + {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
- + {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
- + {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
- + {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
- + {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
- + {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
- + {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
- + {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
- + {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
- + {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
- + {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
- + {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
- + {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
- + {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
- + {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
- + {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
- + {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
- + {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
- + {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
- + {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
- + {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
- + {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
- + {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
- + {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
- + {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
- + {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
- + {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
- + {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
- + {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
- + {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
- + {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
- + {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
- + {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
- + {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
- + {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
- + {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
- + {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
- + {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
- + {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
- + {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
- + {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
- + {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
- + {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
- + {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
- + {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
- + {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
- + {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
- + {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
- + {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
- + {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
- + {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
- + {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
- + {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
- + {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
- + {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
- + {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
- + {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
- + {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
- + {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
- + {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
- + {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
- + {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
- + {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
- + {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
- + {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
- + {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
- + {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
- + {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
- + {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
- + {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
- + {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
- + {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
- + {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
- + {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
- + {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
- + {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
- + {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
- + {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
- + {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
- + {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
- + {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
- + {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
- + {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
- + {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
- + {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
- + {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
- + {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
- + {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
- + {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
- + {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
- + {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
- + {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
- + {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
- + {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
- + {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
- + {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
- + {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
- + {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
- + {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
- + {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
- + {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
- + {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
- + {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
- + {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
- + {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
- + {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
- + {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
- + {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
- + {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
- + {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
- + {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
- + {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
- + {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
- + {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
- + {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
- + {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
- + {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
- + {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
- + {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
- + {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
- + {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
- + {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
- + {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
- + {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
- + {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
- +};
- +
- +static struct reg_value ov5642_setting_15fps_VGA_640_480[] = {
- + {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
- + {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
- + {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
- + {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
- + {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
- + {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
- + {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
- + {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
- + {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
- + {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
- + {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
- + {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
- + {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
- + {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
- + {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
- + {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
- + {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
- + {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
- + {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
- + {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
- + {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
- + {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
- + {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x07, 0, 0},
- + {0x380f, 0xd0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
- + {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
- + {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0},
- + {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
- + {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
- + {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
- + {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
- + {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
- + {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
- + {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
- + {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
- + {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
- + {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
- + {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
- + {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
- + {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
- + {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
- + {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
- + {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
- + {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
- + {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
- + {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
- + {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
- + {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
- + {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
- + {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
- + {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
- + {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
- + {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
- + {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
- + {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
- + {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
- + {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
- + {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
- + {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
- + {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
- + {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
- + {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
- + {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
- + {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
- + {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
- + {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
- + {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
- + {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
- + {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
- + {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
- + {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
- + {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
- + {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
- + {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
- + {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
- + {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
- + {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
- + {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
- + {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
- + {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
- + {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
- + {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
- + {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
- + {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
- + {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
- + {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
- + {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
- + {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
- + {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
- + {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
- + {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
- + {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
- + {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
- + {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
- + {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
- + {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
- + {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
- + {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
- + {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
- + {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
- + {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
- + {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
- + {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
- + {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
- + {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
- + {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
- + {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
- + {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
- + {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
- + {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
- + {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
- + {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
- + {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
- + {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
- + {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
- + {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
- + {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
- + {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
- + {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
- + {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
- + {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
- + {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
- + {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
- + {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
- + {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
- + {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
- + {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
- + {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
- + {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
- + {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
- + {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
- + {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
- + {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
- + {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
- + {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
- + {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
- + {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
- + {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
- + {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
- + {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
- + {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
- + {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
- + {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
- + {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
- + {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
- + {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
- + {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
- + {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
- + {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
- + {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
- + {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
- + {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
- + {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
- + {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
- + {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
- + {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
- + {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
- + {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
- + {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
- + {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
- + {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
- +};
- +
- +
- +static struct reg_value ov5642_setting_30fps_XGA_1024_768[] = {
- + {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
- + {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
- + {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
- + {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
- + {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
- + {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
- + {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
- + {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
- + {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
- + {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
- + {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
- + {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
- + {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
- + {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
- + {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
- + {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
- + {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
- + {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
- + {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
- + {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
- + {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
- + {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
- + {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0},
- + {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
- + {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
- + {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0},
- + {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
- + {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
- + {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
- + {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
- + {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
- + {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
- + {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
- + {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
- + {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
- + {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
- + {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
- + {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
- + {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
- + {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
- + {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
- + {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
- + {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
- + {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
- + {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
- + {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
- + {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
- + {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
- + {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
- + {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
- + {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
- + {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
- + {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
- + {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
- + {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
- + {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
- + {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
- + {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
- + {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
- + {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
- + {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
- + {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
- + {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
- + {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
- + {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
- + {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
- + {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
- + {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
- + {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
- + {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
- + {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
- + {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
- + {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
- + {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
- + {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
- + {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
- + {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
- + {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
- + {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
- + {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
- + {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
- + {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
- + {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
- + {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
- + {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
- + {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
- + {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
- + {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
- + {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
- + {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
- + {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
- + {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
- + {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
- + {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
- + {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
- + {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
- + {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
- + {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
- + {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
- + {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
- + {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
- + {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
- + {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
- + {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
- + {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
- + {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
- + {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
- + {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
- + {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
- + {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
- + {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
- + {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
- + {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
- + {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
- + {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
- + {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
- + {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
- + {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
- + {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
- + {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
- + {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
- + {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
- + {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
- + {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
- + {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
- + {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
- + {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
- + {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
- + {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
- + {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
- + {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
- + {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
- + {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
- + {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
- + {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
- + {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
- + {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
- + {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
- + {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
- + {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
- + {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
- + {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
- + {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
- + {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
- + {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
- + {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
- + {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
- + {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
- + {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
- + {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
- + {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
- + {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
- + {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
- + {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
- + {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
- + {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
- + {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
- + {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
- + {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
- + {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0},
- + {0x380b, 0x00, 0, 0}, {0x3815, 0x02, 0, 0}, {0x302c, 0x60, 0x60, 0},
- +};
- +
- +static struct reg_value ov5642_setting_15fps_XGA_1024_768[] = {
- + {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
- + {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
- + {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
- + {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
- + {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
- + {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
- + {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
- + {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
- + {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
- + {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
- + {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
- + {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
- + {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
- + {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
- + {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
- + {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
- + {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
- + {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
- + {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
- + {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
- + {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
- + {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
- + {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x07, 0, 0},
- + {0x380f, 0xd0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
- + {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
- + {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0},
- + {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
- + {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
- + {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
- + {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
- + {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
- + {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
- + {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
- + {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
- + {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
- + {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
- + {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
- + {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
- + {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
- + {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
- + {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
- + {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
- + {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
- + {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
- + {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
- + {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
- + {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
- + {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
- + {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
- + {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
- + {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
- + {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
- + {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
- + {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
- + {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
- + {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
- + {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
- + {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
- + {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
- + {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
- + {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
- + {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
- + {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
- + {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
- + {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
- + {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
- + {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
- + {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
- + {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
- + {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
- + {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
- + {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
- + {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
- + {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
- + {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
- + {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
- + {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
- + {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
- + {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
- + {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
- + {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
- + {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
- + {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
- + {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
- + {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
- + {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
- + {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
- + {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
- + {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
- + {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
- + {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
- + {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
- + {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
- + {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
- + {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
- + {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
- + {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
- + {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
- + {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
- + {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
- + {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
- + {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
- + {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
- + {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
- + {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
- + {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
- + {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
- + {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
- + {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
- + {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
- + {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
- + {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
- + {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
- + {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
- + {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
- + {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
- + {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
- + {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
- + {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
- + {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
- + {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
- + {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
- + {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
- + {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
- + {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
- + {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
- + {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
- + {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
- + {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
- + {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
- + {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
- + {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
- + {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
- + {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
- + {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
- + {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
- + {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
- + {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
- + {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
- + {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
- + {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
- + {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
- + {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
- + {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
- + {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
- + {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
- + {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
- + {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
- + {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
- + {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
- + {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
- + {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
- + {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
- + {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
- + {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
- + {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
- + {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
- + {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
- + {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
- + {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0},
- + {0x380b, 0x00, 0, 0}, {0x3815, 0x02, 0, 0}, {0x302c, 0x60, 0x60, 0},
- +};
- +
- +static struct reg_value ov5642_setting_30fps_QVGA_320_240[] = {
- + {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
- + {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
- + {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
- + {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
- + {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
- + {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
- + {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
- + {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
- + {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
- + {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
- + {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
- + {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
- + {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
- + {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
- + {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
- + {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
- + {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
- + {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
- + {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
- + {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
- + {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
- + {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
- + {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0},
- + {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
- + {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
- + {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0},
- + {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
- + {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
- + {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
- + {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
- + {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
- + {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
- + {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
- + {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
- + {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
- + {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
- + {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
- + {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
- + {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
- + {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
- + {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
- + {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
- + {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
- + {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
- + {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
- + {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
- + {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
- + {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
- + {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
- + {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
- + {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
- + {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
- + {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
- + {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
- + {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
- + {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
- + {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
- + {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
- + {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
- + {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
- + {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
- + {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
- + {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
- + {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
- + {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
- + {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
- + {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
- + {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
- + {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
- + {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
- + {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
- + {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
- + {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
- + {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
- + {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
- + {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
- + {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
- + {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
- + {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
- + {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
- + {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
- + {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
- + {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
- + {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
- + {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
- + {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
- + {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
- + {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
- + {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
- + {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
- + {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
- + {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
- + {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
- + {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
- + {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
- + {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
- + {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
- + {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
- + {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
- + {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
- + {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
- + {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
- + {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
- + {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
- + {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
- + {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
- + {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
- + {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
- + {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
- + {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
- + {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
- + {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
- + {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
- + {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
- + {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
- + {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
- + {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
- + {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
- + {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
- + {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
- + {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
- + {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
- + {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
- + {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
- + {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
- + {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
- + {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
- + {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
- + {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
- + {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
- + {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
- + {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
- + {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
- + {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
- + {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
- + {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
- + {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
- + {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
- + {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
- + {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
- + {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
- + {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
- + {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
- + {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
- + {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
- + {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
- + {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
- + {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
- + {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
- + {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
- + {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
- + {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
- + {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
- + {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
- + {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
- + {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
- + {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
- + {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
- + {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
- + {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3808, 0x01, 0, 0},
- + {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0}, {0x380b, 0xf0, 0, 0},
- +};
- +
- +static struct reg_value ov5642_setting_30fps_NTSC_720_480[] = {
- + {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
- + {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
- + {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
- + {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
- + {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
- + {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
- + {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
- + {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
- + {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
- + {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
- + {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
- + {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
- + {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
- + {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
- + {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
- + {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
- + {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
- + {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
- + {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
- + {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
- + {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
- + {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
- + {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0},
- + {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
- + {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
- + {0x3803, 0x08, 0, 0}, {0x3827, 0x3c, 0, 0}, {0x3810, 0x80, 0, 0},
- + {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
- + {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0x58, 0, 0},
- + {0x5686, 0x03, 0, 0}, {0x5687, 0x58, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
- + {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
- + {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
- + {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
- + {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
- + {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
- + {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
- + {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
- + {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
- + {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
- + {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
- + {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
- + {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
- + {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
- + {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
- + {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
- + {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
- + {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
- + {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
- + {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
- + {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
- + {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
- + {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
- + {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
- + {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
- + {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
- + {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
- + {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
- + {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
- + {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
- + {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
- + {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
- + {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
- + {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
- + {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
- + {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
- + {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
- + {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
- + {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
- + {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
- + {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
- + {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
- + {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
- + {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
- + {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
- + {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
- + {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
- + {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
- + {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
- + {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
- + {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
- + {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
- + {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
- + {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
- + {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
- + {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
- + {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
- + {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
- + {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
- + {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
- + {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
- + {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
- + {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
- + {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
- + {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
- + {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
- + {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
- + {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
- + {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
- + {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
- + {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
- + {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
- + {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
- + {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
- + {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
- + {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
- + {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
- + {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
- + {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
- + {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
- + {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
- + {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
- + {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
- + {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
- + {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
- + {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
- + {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
- + {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
- + {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
- + {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
- + {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
- + {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
- + {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
- + {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
- + {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
- + {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
- + {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
- + {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
- + {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
- + {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
- + {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
- + {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
- + {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
- + {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
- + {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
- + {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
- + {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
- + {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
- + {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
- + {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
- + {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
- + {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
- + {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
- + {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
- + {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
- + {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
- + {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
- + {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
- + {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
- + {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
- + {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
- + {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
- + {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
- + {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
- + {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
- + {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
- + {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
- + {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
- + {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
- + {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
- + {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
- + {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x302c, 0x60, 0x60, 0},
- +};
- +
- +static struct reg_value ov5642_setting_30fps_PAL_720_576[] = {
- + {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
- + {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
- + {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
- + {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
- + {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
- + {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
- + {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
- + {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
- + {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
- + {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
- + {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
- + {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
- + {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
- + {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
- + {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
- + {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
- + {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
- + {0x3809, 0xd0, 0, 0}, {0x380a, 0x02, 0, 0}, {0x380b, 0x40, 0, 0},
- + {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
- + {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
- + {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xd8, 0, 0},
- + {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
- + {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0},
- + {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
- + {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
- + {0x3803, 0x08, 0, 0}, {0x3827, 0x3c, 0, 0}, {0x3810, 0x80, 0, 0},
- + {0x3804, 0x04, 0, 0}, {0x3805, 0xb0, 0, 0}, {0x5682, 0x04, 0, 0},
- + {0x5683, 0xb0, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0x58, 0, 0},
- + {0x5686, 0x03, 0, 0}, {0x5687, 0x58, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
- + {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
- + {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
- + {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
- + {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
- + {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
- + {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
- + {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
- + {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
- + {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
- + {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
- + {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
- + {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
- + {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
- + {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
- + {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
- + {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
- + {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
- + {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
- + {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
- + {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
- + {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
- + {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
- + {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
- + {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
- + {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
- + {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
- + {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
- + {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
- + {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
- + {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
- + {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
- + {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
- + {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
- + {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
- + {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
- + {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
- + {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
- + {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
- + {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
- + {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
- + {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
- + {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
- + {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
- + {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
- + {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
- + {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
- + {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
- + {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
- + {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
- + {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
- + {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
- + {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
- + {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
- + {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
- + {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
- + {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
- + {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
- + {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
- + {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
- + {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
- + {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
- + {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
- + {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
- + {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
- + {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
- + {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
- + {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
- + {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
- + {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
- + {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
- + {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
- + {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
- + {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
- + {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
- + {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
- + {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
- + {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
- + {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
- + {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
- + {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
- + {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
- + {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
- + {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
- + {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
- + {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
- + {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
- + {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
- + {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
- + {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
- + {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
- + {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
- + {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
- + {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
- + {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
- + {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
- + {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
- + {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
- + {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
- + {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
- + {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
- + {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
- + {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
- + {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
- + {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
- + {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
- + {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
- + {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
- + {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
- + {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
- + {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
- + {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
- + {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
- + {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
- + {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
- + {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
- + {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
- + {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
- + {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
- + {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
- + {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
- + {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
- + {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
- + {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
- + {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
- + {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
- + {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
- + {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
- + {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
- + {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
- + {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
- + {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
- + {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x302c, 0x60, 0x60, 0},
- +};
- +
- +static struct reg_value ov5642_setting_15fps_720P_1280_720[] = {
- + {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
- + {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
- + {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0},
- + {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3030, 0x2b, 0, 0},
- + {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3604, 0x60, 0, 0},
- + {0x3622, 0x60, 0, 0}, {0x3621, 0x09, 0, 0}, {0x3709, 0x00, 0, 0},
- + {0x4000, 0x21, 0, 0}, {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0},
- + {0x3605, 0x04, 0, 0}, {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0},
- + {0x300d, 0x22, 0, 0}, {0x3623, 0x22, 0, 0}, {0x5000, 0x4f, 0, 0},
- + {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
- + {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5500, 0x0a, 0, 0},
- + {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0},
- + {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0},
- + {0x4708, 0x06, 0, 0}, {0x370c, 0xa0, 0, 0}, {0x3808, 0x0a, 0, 0},
- + {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0},
- + {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0},
- + {0x380f, 0xd0, 0, 0}, {0x5687, 0x94, 0, 0}, {0x501f, 0x00, 0, 0},
- + {0x5000, 0x4f, 0, 0}, {0x5001, 0xcf, 0, 0}, {0x4300, 0x30, 0, 0},
- + {0x4300, 0x30, 0, 0}, {0x460b, 0x35, 0, 0}, {0x471d, 0x00, 0, 0},
- + {0x3002, 0x0c, 0, 0}, {0x3002, 0x00, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x471c, 0x50, 0, 0}, {0x4721, 0x02, 0, 0}, {0x4402, 0x90, 0, 0},
- + {0x460c, 0x22, 0, 0}, {0x3815, 0x44, 0, 0}, {0x3503, 0x07, 0, 0},
- + {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3818, 0xc8, 0, 0}, {0x3801, 0x88, 0, 0}, {0x3824, 0x11, 0, 0},
- + {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x04, 0, 0}, {0x3a13, 0x30, 0, 0},
- + {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0},
- + {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0},
- + {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, {0x3a0d, 0x08, 0, 0},
- + {0x3a0e, 0x06, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
- + {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x00, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x32, 0, 0},
- + {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x32, 0, 0}, {0x3a11, 0x80, 0, 0},
- + {0x3a1f, 0x20, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
- + {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
- + {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a08, 0x09, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0},
- + {0x3a0b, 0xd0, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x589b, 0x00, 0, 0},
- + {0x589a, 0xc0, 0, 0}, {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0},
- + {0x401c, 0x06, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0},
- + {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
- + {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
- + {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
- + {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
- + {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
- + {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
- + {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
- + {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
- + {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
- + {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
- + {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
- + {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
- + {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
- + {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
- + {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
- + {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
- + {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
- + {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
- + {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
- + {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
- + {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
- + {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
- + {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
- + {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
- + {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
- + {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
- + {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
- + {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
- + {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
- + {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
- + {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
- + {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
- + {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
- + {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
- + {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
- + {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
- + {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
- + {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
- + {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
- + {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
- + {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
- + {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
- + {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
- + {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
- + {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
- + {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
- + {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
- + {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
- + {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
- + {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
- + {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
- + {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
- + {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
- + {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
- + {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
- + {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
- + {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
- + {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
- + {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
- + {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
- + {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
- + {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
- + {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
- + {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
- + {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
- + {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
- + {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
- + {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
- + {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
- + {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
- + {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
- + {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
- + {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
- + {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
- + {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
- + {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
- + {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
- + {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
- + {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
- + {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
- + {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
- + {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
- + {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
- + {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
- + {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
- + {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
- + {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
- + {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
- + {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
- + {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
- + {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
- + {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
- + {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
- + {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
- + {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
- + {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
- + {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
- + {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
- + {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
- + {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
- + {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
- + {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
- + {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
- + {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
- + {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
- + {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
- + {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
- + {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
- + {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
- + {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
- + {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
- + {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
- + {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
- + {0x302b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3011, 0x08, 0, 0},
- + {0x350c, 0x02, 0, 0}, {0x350d, 0xe4, 0, 0}, {0x3621, 0xc9, 0, 0},
- + {0x370a, 0x81, 0, 0}, {0x3803, 0x08, 0, 0}, {0x3804, 0x05, 0, 0},
- + {0x3805, 0x00, 0, 0}, {0x3806, 0x02, 0, 0}, {0x3807, 0xd0, 0, 0},
- + {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
- + {0x380b, 0xd0, 0, 0}, {0x380c, 0x08, 0, 0}, {0x380d, 0x72, 0, 0},
- + {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0xc0, 0, 0},
- + {0x3818, 0xc9, 0, 0}, {0x381c, 0x10, 0, 0}, {0x381d, 0xa0, 0, 0},
- + {0x381e, 0x05, 0, 0}, {0x381f, 0xb0, 0, 0}, {0x3820, 0x00, 0, 0},
- + {0x3821, 0x00, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3a08, 0x1b, 0, 0},
- + {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x17, 0, 0}, {0x3a0b, 0x20, 0, 0},
- + {0x3a0d, 0x02, 0, 0}, {0x3a0e, 0x01, 0, 0}, {0x401c, 0x04, 0, 0},
- + {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, {0x5686, 0x02, 0, 0},
- + {0x5687, 0xcc, 0, 0}, {0x5001, 0x7f, 0, 0}, {0x589b, 0x06, 0, 0},
- + {0x589a, 0xc5, 0, 0}, {0x3503, 0x00, 0, 0}, {0x3010, 0x10, 0, 0},
- + {0x460c, 0x20, 0, 0}, {0x460b, 0x37, 0, 0}, {0x471c, 0xd0, 0, 0},
- + {0x471d, 0x05, 0, 0}, {0x3815, 0x01, 0, 0}, {0x3818, 0x00, 0x08, 0},
- + {0x501f, 0x00, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3002, 0x1c, 0, 0},
- + {0x3819, 0x80, 0, 0}, {0x5002, 0xe0, 0, 0}, {0x3010, 0x30, 0, 0},
- + {0x3a08, 0x06, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x05, 0, 0},
- + {0x3a0b, 0x50, 0, 0}, {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x07, 0, 0},
- +};
- +
- +static struct reg_value ov5642_setting_30fps_720P_1280_720[] = {
- + {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
- + {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
- + {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0},
- + {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3030, 0x2b, 0, 0},
- + {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3604, 0x60, 0, 0},
- + {0x3622, 0x60, 0, 0}, {0x3621, 0x09, 0, 0}, {0x3709, 0x00, 0, 0},
- + {0x4000, 0x21, 0, 0}, {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0},
- + {0x3605, 0x04, 0, 0}, {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0},
- + {0x300d, 0x22, 0, 0}, {0x3623, 0x22, 0, 0}, {0x5000, 0x4f, 0, 0},
- + {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
- + {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5500, 0x0a, 0, 0},
- + {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0},
- + {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0},
- + {0x4708, 0x06, 0, 0}, {0x370c, 0xa0, 0, 0}, {0x3808, 0x0a, 0, 0},
- + {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0},
- + {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0},
- + {0x380f, 0xd0, 0, 0}, {0x5687, 0x94, 0, 0}, {0x501f, 0x00, 0, 0},
- + {0x5000, 0x4f, 0, 0}, {0x5001, 0xcf, 0, 0}, {0x4300, 0x30, 0, 0},
- + {0x4300, 0x30, 0, 0}, {0x460b, 0x35, 0, 0}, {0x471d, 0x00, 0, 0},
- + {0x3002, 0x0c, 0, 0}, {0x3002, 0x00, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x471c, 0x50, 0, 0}, {0x4721, 0x02, 0, 0}, {0x4402, 0x90, 0, 0},
- + {0x460c, 0x22, 0, 0}, {0x3815, 0x44, 0, 0}, {0x3503, 0x07, 0, 0},
- + {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3818, 0xc8, 0, 0}, {0x3801, 0x88, 0, 0}, {0x3824, 0x11, 0, 0},
- + {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x04, 0, 0}, {0x3a13, 0x30, 0, 0},
- + {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0},
- + {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0},
- + {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, {0x3a0d, 0x08, 0, 0},
- + {0x3a0e, 0x06, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
- + {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x00, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x32, 0, 0},
- + {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x32, 0, 0}, {0x3a11, 0x80, 0, 0},
- + {0x3a1f, 0x20, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
- + {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
- + {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a08, 0x09, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0},
- + {0x3a0b, 0xd0, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x589b, 0x00, 0, 0},
- + {0x589a, 0xc0, 0, 0}, {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0},
- + {0x401c, 0x06, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0},
- + {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
- + {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
- + {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
- + {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
- + {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
- + {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
- + {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
- + {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
- + {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
- + {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
- + {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
- + {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
- + {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
- + {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
- + {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
- + {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
- + {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
- + {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
- + {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
- + {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
- + {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
- + {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
- + {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
- + {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
- + {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
- + {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
- + {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
- + {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
- + {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
- + {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
- + {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
- + {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
- + {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
- + {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
- + {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
- + {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
- + {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
- + {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
- + {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
- + {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
- + {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
- + {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
- + {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
- + {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
- + {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
- + {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
- + {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
- + {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
- + {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
- + {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
- + {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
- + {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
- + {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
- + {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
- + {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
- + {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
- + {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
- + {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
- + {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
- + {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
- + {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
- + {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
- + {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
- + {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
- + {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
- + {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
- + {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
- + {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
- + {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
- + {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
- + {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
- + {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
- + {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
- + {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
- + {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
- + {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
- + {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
- + {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
- + {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
- + {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
- + {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
- + {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
- + {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
- + {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
- + {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
- + {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
- + {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
- + {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
- + {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
- + {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
- + {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
- + {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
- + {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
- + {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
- + {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
- + {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
- + {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
- + {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
- + {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
- + {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
- + {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
- + {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
- + {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
- + {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
- + {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
- + {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
- + {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
- + {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
- + {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
- + {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
- + {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
- + {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
- + {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
- + {0x302b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3011, 0x08, 0, 0},
- + {0x350c, 0x02, 0, 0}, {0x350d, 0xe4, 0, 0}, {0x3621, 0xc9, 0, 0},
- + {0x370a, 0x81, 0, 0}, {0x3803, 0x08, 0, 0}, {0x3804, 0x05, 0, 0},
- + {0x3805, 0x00, 0, 0}, {0x3806, 0x02, 0, 0}, {0x3807, 0xd0, 0, 0},
- + {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
- + {0x380b, 0xd0, 0, 0}, {0x380c, 0x08, 0, 0}, {0x380d, 0x72, 0, 0},
- + {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0xc0, 0, 0},
- + {0x3818, 0xc9, 0, 0}, {0x381c, 0x10, 0, 0}, {0x381d, 0xa0, 0, 0},
- + {0x381e, 0x05, 0, 0}, {0x381f, 0xb0, 0, 0}, {0x3820, 0x00, 0, 0},
- + {0x3821, 0x00, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3a08, 0x1b, 0, 0},
- + {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x17, 0, 0}, {0x3a0b, 0x20, 0, 0},
- + {0x3a0d, 0x02, 0, 0}, {0x3a0e, 0x01, 0, 0}, {0x401c, 0x04, 0, 0},
- + {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, {0x5686, 0x02, 0, 0},
- + {0x5687, 0xcc, 0, 0}, {0x5001, 0x7f, 0, 0}, {0x589b, 0x06, 0, 0},
- + {0x589a, 0xc5, 0, 0}, {0x3503, 0x00, 0, 0}, {0x3010, 0x10, 0, 0},
- + {0x460c, 0x20, 0, 0}, {0x460b, 0x37, 0, 0}, {0x471c, 0xd0, 0, 0},
- + {0x471d, 0x05, 0, 0}, {0x3815, 0x01, 0, 0}, {0x3818, 0x00, 0x08, 0},
- + {0x501f, 0x00, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3002, 0x1c, 0, 0},
- + {0x3819, 0x80, 0, 0}, {0x5002, 0xe0, 0, 0},
- +};
- +
- +static struct reg_value ov5642_setting_15fps_1080P_1920_1080[] = {
- + {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
- + {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
- + {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0},
- + {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3030, 0x2b, 0, 0},
- + {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3604, 0x60, 0, 0},
- + {0x3622, 0x60, 0, 0}, {0x3621, 0x09, 0, 0}, {0x3709, 0x00, 0, 0},
- + {0x4000, 0x21, 0, 0}, {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0},
- + {0x3605, 0x04, 0, 0}, {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0},
- + {0x300d, 0x22, 0, 0}, {0x3623, 0x22, 0, 0}, {0x5000, 0x4f, 0, 0},
- + {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
- + {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5500, 0x0a, 0, 0},
- + {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0},
- + {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0},
- + {0x4708, 0x06, 0, 0}, {0x370c, 0xa0, 0, 0}, {0x3808, 0x0a, 0, 0},
- + {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0},
- + {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0},
- + {0x380f, 0xd0, 0, 0}, {0x5687, 0x94, 0, 0}, {0x501f, 0x00, 0, 0},
- + {0x5000, 0x4f, 0, 0}, {0x5001, 0xcf, 0, 0}, {0x4300, 0x30, 0, 0},
- + {0x4300, 0x30, 0, 0}, {0x460b, 0x35, 0, 0}, {0x471d, 0x00, 0, 0},
- + {0x3002, 0x0c, 0, 0}, {0x3002, 0x00, 0, 0}, {0x4713, 0x03, 0, 0},
- + {0x471c, 0x50, 0, 0}, {0x4721, 0x02, 0, 0}, {0x4402, 0x90, 0, 0},
- + {0x460c, 0x22, 0, 0}, {0x3815, 0x44, 0, 0}, {0x3503, 0x07, 0, 0},
- + {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3818, 0xc8, 0, 0}, {0x3801, 0x88, 0, 0}, {0x3824, 0x11, 0, 0},
- + {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x04, 0, 0}, {0x3a13, 0x30, 0, 0},
- + {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0},
- + {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0},
- + {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, {0x3a0d, 0x08, 0, 0},
- + {0x3a0e, 0x06, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
- + {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x00, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x32, 0, 0},
- + {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x32, 0, 0}, {0x3a11, 0x80, 0, 0},
- + {0x3a1f, 0x20, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
- + {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
- + {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
- + {0x3a08, 0x09, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0},
- + {0x3a0b, 0xd0, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0},
- + {0x4407, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x589b, 0x00, 0, 0},
- + {0x589a, 0xc0, 0, 0}, {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0},
- + {0x401c, 0x06, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0},
- + {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
- + {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
- + {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
- + {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
- + {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
- + {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
- + {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
- + {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
- + {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
- + {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
- + {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
- + {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
- + {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
- + {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
- + {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
- + {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
- + {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
- + {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
- + {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
- + {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
- + {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
- + {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
- + {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
- + {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
- + {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
- + {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
- + {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
- + {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
- + {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
- + {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
- + {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
- + {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
- + {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
- + {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
- + {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
- + {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
- + {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
- + {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
- + {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
- + {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
- + {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
- + {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
- + {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
- + {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
- + {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
- + {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
- + {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
- + {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
- + {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
- + {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
- + {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
- + {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
- + {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
- + {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
- + {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
- + {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
- + {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
- + {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
- + {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
- + {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
- + {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
- + {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
- + {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
- + {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
- + {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
- + {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
- + {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
- + {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
- + {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
- + {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
- + {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
- + {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
- + {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
- + {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
- + {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
- + {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
- + {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
- + {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
- + {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
- + {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
- + {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
- + {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
- + {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
- + {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
- + {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
- + {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
- + {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
- + {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
- + {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
- + {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
- + {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
- + {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
- + {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
- + {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
- + {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
- + {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
- + {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
- + {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
- + {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
- + {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
- + {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
- + {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
- + {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
- + {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
- + {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
- + {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
- + {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
- + {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
- + {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
- + {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
- + {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
- + {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
- + {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
- + {0x302b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3011, 0x07, 0, 0},
- + {0x350c, 0x04, 0, 0}, {0x350d, 0x58, 0, 0}, {0x3801, 0x8a, 0, 0},
- + {0x3803, 0x0a, 0, 0}, {0x3804, 0x07, 0, 0}, {0x3805, 0x80, 0, 0},
- + {0x3806, 0x04, 0, 0}, {0x3807, 0x39, 0, 0}, {0x3808, 0x07, 0, 0},
- + {0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0},
- + {0x380c, 0x09, 0, 0}, {0x380d, 0xd6, 0, 0}, {0x380e, 0x04, 0, 0},
- + {0x380f, 0x58, 0, 0}, {0x381c, 0x11, 0, 0}, {0x381d, 0xba, 0, 0},
- + {0x381e, 0x04, 0, 0}, {0x381f, 0x48, 0, 0}, {0x3820, 0x04, 0, 0},
- + {0x3821, 0x18, 0, 0}, {0x3a08, 0x14, 0, 0}, {0x3a09, 0xe0, 0, 0},
- + {0x3a0a, 0x11, 0, 0}, {0x3a0b, 0x60, 0, 0}, {0x3a0d, 0x04, 0, 0},
- + {0x3a0e, 0x03, 0, 0}, {0x5682, 0x07, 0, 0}, {0x5683, 0x60, 0, 0},
- + {0x5686, 0x04, 0, 0}, {0x5687, 0x1c, 0, 0}, {0x5001, 0x7f, 0, 0},
- + {0x3503, 0x00, 0, 0}, {0x3010, 0x10, 0, 0}, {0x460c, 0x20, 0, 0},
- + {0x460b, 0x37, 0, 0}, {0x471c, 0xd0, 0, 0}, {0x471d, 0x05, 0, 0},
- + {0x3815, 0x01, 0, 0}, {0x3818, 0x00, 0x08, 0}, {0x501f, 0x00, 0, 0},
- + {0x4300, 0x30, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3819, 0x80, 0, 0},
- + {0x5002, 0xe0, 0, 0},
- +};
- +
- +static struct reg_value ov5642_setting_15fps_QVGA_320_240[] = {
- + {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
- + {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
- + {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
- + {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
- + {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0},
- + {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
- + {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
- + {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
- + {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
- + {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
- + {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
- + {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
- + {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
- + {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
- + {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
- + {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
- + {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
- + {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
- + {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
- + {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
- + {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0},
- + {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0},
- + {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0},
- + {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0},
- + {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
- + {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0},
- + {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
- + {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0},
- + {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0},
- + {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
- + {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
- + {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
- + {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0},
- + {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0},
- + {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
- + {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0},
- + {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0},
- + {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0},
- + {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0},
- + {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0},
- + {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0},
- + {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0},
- + {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0},
- + {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0},
- + {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0},
- + {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0},
- + {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0},
- + {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0},
- + {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0},
- + {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0},
- + {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0},
- + {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0},
- + {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0},
- + {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0},
- + {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0},
- + {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0},
- + {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0},
- + {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0},
- + {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0},
- + {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0},
- + {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0},
- + {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0},
- + {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0},
- + {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0},
- + {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0},
- + {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0},
- + {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0},
- + {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0},
- + {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0},
- + {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0},
- + {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0},
- + {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0},
- + {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0},
- + {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0},
- + {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0},
- + {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0},
- + {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0},
- + {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0},
- + {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0},
- + {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0},
- + {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0},
- + {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0},
- + {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0},
- + {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0},
- + {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0},
- + {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0},
- + {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0},
- + {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0},
- + {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0},
- + {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0},
- + {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0},
- + {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0},
- + {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0},
- + {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0},
- + {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0},
- + {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0},
- + {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0},
- + {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0},
- + {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0},
- + {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0},
- + {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0},
- + {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0},
- + {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0},
- + {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0},
- + {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0},
- + {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0},
- + {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0},
- + {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0},
- + {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0},
- + {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0},
- + {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0},
- + {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0},
- + {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0},
- + {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0},
- + {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0},
- + {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0},
- + {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0},
- + {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0},
- + {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0},
- + {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0},
- + {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0},
- + {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0},
- + {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0},
- + {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0},
- + {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0},
- + {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0},
- + {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0},
- + {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0},
- + {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0},
- + {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0},
- + {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0},
- + {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0},
- + {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0},
- + {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0},
- + {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0},
- + {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0},
- + {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0},
- + {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0},
- + {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0},
- + {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0},
- + {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0},
- + {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0},
- + {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0},
- + {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0},
- + {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0},
- + {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0},
- + {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0},
- + {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0},
- + {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0},
- + {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0},
- + {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0},
- + {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0},
- + {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0},
- + {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0},
- + {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0},
- + {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0},
- + {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0},
- + {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0},
- + {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0},
- + {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0},
- + {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0},
- + {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0},
- + {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0},
- + {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0},
- + {0x380b, 0xf0, 0, 0}, {0x3a00, 0x78, 0, 0},
- +};
- +
- +static struct reg_value ov5642_setting_15fps_NTSC_720_480[] = {
- + {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
- + {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
- + {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
- + {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
- + {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0},
- + {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
- + {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
- + {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
- + {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
- + {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
- + {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
- + {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
- + {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
- + {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
- + {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
- + {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
- + {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
- + {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
- + {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
- + {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
- + {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0},
- + {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0},
- + {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0},
- + {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0},
- + {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
- + {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0},
- + {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
- + {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0},
- + {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0},
- + {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
- + {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
- + {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
- + {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0},
- + {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0},
- + {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
- + {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0},
- + {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0},
- + {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0},
- + {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0},
- + {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0},
- + {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0},
- + {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0},
- + {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0},
- + {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0},
- + {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0},
- + {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0},
- + {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0},
- + {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0},
- + {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0},
- + {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0},
- + {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0},
- + {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0},
- + {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0},
- + {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0},
- + {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0},
- + {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0},
- + {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0},
- + {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0},
- + {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0},
- + {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0},
- + {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0},
- + {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0},
- + {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0},
- + {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0},
- + {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0},
- + {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0},
- + {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0},
- + {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0},
- + {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0},
- + {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0},
- + {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0},
- + {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0},
- + {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0},
- + {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0},
- + {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0},
- + {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0},
- + {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0},
- + {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0},
- + {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0},
- + {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0},
- + {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0},
- + {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0},
- + {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0},
- + {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0},
- + {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0},
- + {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0},
- + {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0},
- + {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0},
- + {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0},
- + {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0},
- + {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0},
- + {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0},
- + {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0},
- + {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0},
- + {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0},
- + {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0},
- + {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0},
- + {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0},
- + {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0},
- + {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0},
- + {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0},
- + {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0},
- + {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0},
- + {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0},
- + {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0},
- + {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0},
- + {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0},
- + {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0},
- + {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0},
- + {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0},
- + {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0},
- + {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0},
- + {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0},
- + {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0},
- + {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0},
- + {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0},
- + {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0},
- + {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0},
- + {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0},
- + {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0},
- + {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0},
- + {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0},
- + {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0},
- + {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0},
- + {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0},
- + {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0},
- + {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0},
- + {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0},
- + {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0},
- + {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0},
- + {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0},
- + {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0},
- + {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0},
- + {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0},
- + {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0},
- + {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0},
- + {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0},
- + {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0},
- + {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0},
- + {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0},
- + {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0},
- + {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0},
- + {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0},
- + {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0},
- + {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0},
- + {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0},
- + {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0},
- + {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0},
- + {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0},
- + {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0},
- + {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0},
- + {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0},
- + {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0},
- + {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0},
- + {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0},
- + {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0},
- + {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0},
- + {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0},
- + {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0},
- + {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0},
- + {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0},
- + {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0},
- + {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0},
- + {0x3824, 0x11, 0, 0}, {0x3825, 0xb4, 0, 0}, {0x3826, 0x00, 0, 0},
- + {0x3827, 0x3d, 0, 0}, {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0},
- + {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, {0x3808, 0x02, 0, 0},
- + {0x3809, 0xd0, 0, 0}, {0x380A, 0x01, 0, 0}, {0x380B, 0xe0, 0, 0},
- + {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x3806, 0x03, 0, 0},
- + {0x3807, 0x55, 0, 0}, {0x5686, 0x03, 0, 0}, {0x5687, 0x55, 0, 0},
- + {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
- +};
- +
- +static struct reg_value ov5642_setting_15fps_PAL_720_576[] = {
- + {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
- + {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
- + {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
- + {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
- + {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0},
- + {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
- + {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
- + {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
- + {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
- + {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
- + {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
- + {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
- + {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
- + {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
- + {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
- + {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
- + {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
- + {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
- + {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
- + {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
- + {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
- + {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0},
- + {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0},
- + {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
- + {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0},
- + {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0},
- + {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
- + {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0},
- + {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
- + {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0},
- + {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0},
- + {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
- + {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
- + {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
- + {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0},
- + {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0},
- + {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
- + {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0},
- + {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0},
- + {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0},
- + {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0},
- + {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0},
- + {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0},
- + {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0},
- + {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0},
- + {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0},
- + {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0},
- + {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0},
- + {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0},
- + {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0},
- + {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0},
- + {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0},
- + {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0},
- + {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0},
- + {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0},
- + {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0},
- + {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0},
- + {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0},
- + {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0},
- + {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0},
- + {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0},
- + {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0},
- + {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0},
- + {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0},
- + {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0},
- + {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0},
- + {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0},
- + {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0},
- + {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0},
- + {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0},
- + {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0},
- + {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0},
- + {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0},
- + {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0},
- + {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0},
- + {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0},
- + {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0},
- + {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0},
- + {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0},
- + {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0},
- + {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0},
- + {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0},
- + {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0},
- + {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0},
- + {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0},
- + {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0},
- + {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0},
- + {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0},
- + {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0},
- + {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0},
- + {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0},
- + {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0},
- + {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0},
- + {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0},
- + {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0},
- + {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0},
- + {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0},
- + {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0},
- + {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0},
- + {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0},
- + {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0},
- + {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0},
- + {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0},
- + {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0},
- + {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0},
- + {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0},
- + {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0},
- + {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0},
- + {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0},
- + {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0},
- + {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0},
- + {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0},
- + {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0},
- + {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0},
- + {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0},
- + {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0},
- + {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0},
- + {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0},
- + {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0},
- + {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0},
- + {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0},
- + {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0},
- + {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0},
- + {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0},
- + {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0},
- + {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0},
- + {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0},
- + {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0},
- + {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0},
- + {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0},
- + {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0},
- + {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0},
- + {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0},
- + {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0},
- + {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0},
- + {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0},
- + {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0},
- + {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0},
- + {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0},
- + {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0},
- + {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0},
- + {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0},
- + {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0},
- + {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0},
- + {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0},
- + {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0},
- + {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0},
- + {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0},
- + {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0},
- + {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0},
- + {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0},
- + {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0},
- + {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0},
- + {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0},
- + {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0},
- + {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0},
- + {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0},
- + {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0},
- + {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0},
- + {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0},
- + {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0},
- + {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0},
- + {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0},
- + {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0},
- + {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0},
- + {0x3824, 0x11, 0, 0}, {0x3825, 0xdc, 0, 0}, {0x3826, 0x00, 0, 0},
- + {0x3827, 0x08, 0, 0}, {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0},
- + {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, {0x3808, 0x02, 0, 0},
- + {0x3809, 0xd0, 0, 0}, {0x380A, 0x02, 0, 0}, {0x380B, 0x40, 0, 0},
- + {0x3804, 0x04, 0, 0}, {0x3805, 0xb0, 0, 0}, {0x3806, 0x03, 0, 0},
- + {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0}, {0x5687, 0xc0, 0, 0},
- + {0x5682, 0x04, 0, 0}, {0x5683, 0xb0, 0, 0},
- +};
- +
- +static struct ov5642_mode_info ov5642_mode_info_data[2][ov5642_mode_MAX + 1] = {
- + {
- + {ov5642_mode_VGA_640_480, 640, 480,
- + ov5642_setting_15fps_VGA_640_480,
- + ARRAY_SIZE(ov5642_setting_15fps_VGA_640_480)},
- + {ov5642_mode_QVGA_320_240, 320, 240,
- + ov5642_setting_15fps_QVGA_320_240,
- + ARRAY_SIZE(ov5642_setting_15fps_QVGA_320_240)},
- + {ov5642_mode_NTSC_720_480, 720, 480,
- + ov5642_setting_15fps_NTSC_720_480,
- + ARRAY_SIZE(ov5642_setting_15fps_NTSC_720_480)},
- + {ov5642_mode_PAL_720_576, 720, 576,
- + ov5642_setting_15fps_PAL_720_576,
- + ARRAY_SIZE(ov5642_setting_15fps_PAL_720_576)},
- + {ov5642_mode_720P_1280_720, 1280, 720,
- + ov5642_setting_15fps_720P_1280_720,
- + ARRAY_SIZE(ov5642_setting_15fps_720P_1280_720)},
- + {ov5642_mode_1080P_1920_1080, 1920, 1080,
- + ov5642_setting_15fps_1080P_1920_1080,
- + ARRAY_SIZE(ov5642_setting_15fps_1080P_1920_1080)},
- + {ov5642_mode_QSXGA_2592_1944, 2592, 1944,
- + ov5642_setting_15fps_QSXGA_2592_1944,
- + ARRAY_SIZE(ov5642_setting_15fps_QSXGA_2592_1944)},
- + {ov5642_mode_QCIF_176_144, 176, 144,
- + ov5642_setting_15fps_QCIF_176_144,
- + ARRAY_SIZE(ov5642_setting_15fps_QCIF_176_144)},
- + {ov5642_mode_XGA_1024_768, 1024, 768,
- + ov5642_setting_15fps_XGA_1024_768,
- + ARRAY_SIZE(ov5642_setting_15fps_XGA_1024_768)},
- + },
- + {
- + {ov5642_mode_VGA_640_480, 640, 480,
- + ov5642_setting_30fps_VGA_640_480,
- + ARRAY_SIZE(ov5642_setting_30fps_VGA_640_480)},
- + {ov5642_mode_QVGA_320_240, 320, 240,
- + ov5642_setting_30fps_QVGA_320_240,
- + ARRAY_SIZE(ov5642_setting_30fps_QVGA_320_240)},
- + {ov5642_mode_NTSC_720_480, 720, 480,
- + ov5642_setting_30fps_NTSC_720_480,
- + ARRAY_SIZE(ov5642_setting_30fps_NTSC_720_480)},
- + {ov5642_mode_PAL_720_576, 720, 576,
- + ov5642_setting_30fps_PAL_720_576,
- + ARRAY_SIZE(ov5642_setting_30fps_PAL_720_576)},
- + {ov5642_mode_720P_1280_720, 1280, 720,
- + ov5642_setting_30fps_720P_1280_720,
- + ARRAY_SIZE(ov5642_setting_30fps_720P_1280_720)},
- + {ov5642_mode_1080P_1920_1080, 0, 0, NULL, 0},
- + {ov5642_mode_QSXGA_2592_1944, 0, 0, NULL, 0},
- + {ov5642_mode_QCIF_176_144, 176, 144,
- + ov5642_setting_30fps_QCIF_176_144,
- + ARRAY_SIZE(ov5642_setting_30fps_QCIF_176_144)},
- + {ov5642_mode_XGA_1024_768, 1024, 768,
- + ov5642_setting_30fps_XGA_1024_768,
- + ARRAY_SIZE(ov5642_setting_30fps_XGA_1024_768)},
- + },
- +};
- +
- +static struct regulator *io_regulator;
- +static struct regulator *core_regulator;
- +static struct regulator *analog_regulator;
- +static struct regulator *gpo_regulator;
- +
- +static int ov5642_probe(struct i2c_client *adapter,
- + const struct i2c_device_id *device_id);
- +static int ov5642_remove(struct i2c_client *client);
- +
- +static s32 ov5642_read_reg(u16 reg, u8 *val);
- +static s32 ov5642_write_reg(u16 reg, u8 val);
- +
- +static const struct i2c_device_id ov5642_id[] = {
- + {"ov5642", 0},
- + {"ov564x", 0},
- + {},
- +};
- +
- +MODULE_DEVICE_TABLE(i2c, ov5642_id);
- +
- +static struct i2c_driver ov5642_i2c_driver = {
- + .driver = {
- + .owner = THIS_MODULE,
- + .name = "ov5642",
- + },
- + .probe = ov5642_probe,
- + .remove = ov5642_remove,
- + .id_table = ov5642_id,
- +};
- +
- +static void ov5642_standby(s32 enable)
- +{
- + if (enable)
- + gpio_set_value(pwn_gpio, 1);
- + else
- + gpio_set_value(pwn_gpio, 0);
- +
- + msleep(2);
- +}
- +
- +static void ov5642_reset(void)
- +{
- + /* camera reset */
- + gpio_set_value(rst_gpio, 1);
- +
- + /* camera power down */
- + gpio_set_value(pwn_gpio, 1);
- + msleep(5);
- +
- + gpio_set_value(pwn_gpio, 0);
- + msleep(5);
- +
- + gpio_set_value(rst_gpio, 0);
- + msleep(1);
- +
- + gpio_set_value(rst_gpio, 1);
- + msleep(5);
- +
- + gpio_set_value(pwn_gpio, 1);
- +}
- +
- +static int ov5642_power_on(struct device *dev)
- +{
- + int ret = 0;
- +
- + io_regulator = devm_regulator_get(dev, "DOVDD");
- + if (!IS_ERR(io_regulator)) {
- + regulator_set_voltage(io_regulator,
- + OV5642_VOLTAGE_DIGITAL_IO,
- + OV5642_VOLTAGE_DIGITAL_IO);
- + ret = regulator_enable(io_regulator);
- + if (ret) {
- + pr_err("%s:io set voltage error\n", __func__);
- + return ret;
- + } else {
- + dev_dbg(dev,
- + "%s:io set voltage ok\n", __func__);
- + }
- + } else {
- + pr_err("%s: cannot get io voltage error\n", __func__);
- + io_regulator = NULL;
- + }
- +
- + core_regulator = devm_regulator_get(dev, "DVDD");
- + if (!IS_ERR(core_regulator)) {
- + regulator_set_voltage(core_regulator,
- + OV5642_VOLTAGE_DIGITAL_CORE,
- + OV5642_VOLTAGE_DIGITAL_CORE);
- + ret = regulator_enable(core_regulator);
- + if (ret) {
- + pr_err("%s:core set voltage error\n", __func__);
- + return ret;
- + } else {
- + dev_dbg(dev,
- + "%s:core set voltage ok\n", __func__);
- + }
- + } else {
- + core_regulator = NULL;
- + pr_err("%s: cannot get core voltage error\n", __func__);
- + }
- +
- + analog_regulator = devm_regulator_get(dev, "AVDD");
- + if (!IS_ERR(analog_regulator)) {
- + regulator_set_voltage(analog_regulator,
- + OV5642_VOLTAGE_ANALOG,
- + OV5642_VOLTAGE_ANALOG);
- + ret = regulator_enable(analog_regulator);
- + if (ret) {
- + pr_err("%s:analog set voltage error\n",
- + __func__);
- + return ret;
- + } else {
- + dev_dbg(dev,
- + "%s:analog set voltage ok\n", __func__);
- + }
- + } else {
- + analog_regulator = NULL;
- + pr_err("%s: cannot get analog voltage error\n", __func__);
- + }
- +
- + return ret;
- +}
- +
- +static s32 ov5642_write_reg(u16 reg, u8 val)
- +{
- + u8 au8Buf[3] = {0};
- +
- + au8Buf[0] = reg >> 8;
- + au8Buf[1] = reg & 0xff;
- + au8Buf[2] = val;
- +
- + if (i2c_master_send(ov5642_data.i2c_client, au8Buf, 3) < 0) {
- + pr_err("%s:write reg error:reg=%x,val=%x\n",
- + __func__, reg, val);
- + return -1;
- + }
- +
- + return 0;
- +}
- +
- +static s32 ov5642_read_reg(u16 reg, u8 *val)
- +{
- + u8 au8RegBuf[2] = {0};
- + u8 u8RdVal = 0;
- +
- + au8RegBuf[0] = reg >> 8;
- + au8RegBuf[1] = reg & 0xff;
- +
- + if (2 != i2c_master_send(ov5642_data.i2c_client, au8RegBuf, 2)) {
- + pr_err("%s:write reg error:reg=%x\n",
- + __func__, reg);
- + return -1;
- + }
- +
- + if (1 != i2c_master_recv(ov5642_data.i2c_client, &u8RdVal, 1)) {
- + pr_err("%s:read reg error:reg=%x,val=%x\n",
- + __func__, reg, u8RdVal);
- + return -1;
- + }
- +
- + *val = u8RdVal;
- +
- + return u8RdVal;
- +}
- +
- +static int ov5642_set_rot_mode(struct reg_value *rot_mode)
- +{
- + s32 i = 0;
- + s32 iModeSettingArySize = 2;
- + register u32 Delay_ms = 0;
- + register u16 RegAddr = 0;
- + register u8 Mask = 0;
- + register u8 Val = 0;
- + u8 RegVal = 0;
- + int retval = 0;
- + for (i = 0; i < iModeSettingArySize; ++i, ++rot_mode) {
- + Delay_ms = rot_mode->u32Delay_ms;
- + RegAddr = rot_mode->u16RegAddr;
- + Val = rot_mode->u8Val;
- + Mask = rot_mode->u8Mask;
- +
- + if (Mask) {
- + retval = ov5642_read_reg(RegAddr, &RegVal);
- + if (retval < 0) {
- + pr_err("%s, read reg 0x%x failed\n",
- + __func__, RegAddr);
- + goto err;
- + }
- +
- + Val |= RegVal;
- + Val &= Mask;
- + }
- +
- + retval = ov5642_write_reg(RegAddr, Val);
- + if (retval < 0) {
- + pr_err("%s, write reg 0x%x failed\n",
- + __func__, RegAddr);
- + goto err;
- + }
- +
- + if (Delay_ms)
- + mdelay(Delay_ms);
- + }
- +err:
- + return retval;
- +}
- +static int ov5642_init_mode(enum ov5642_frame_rate frame_rate,
- + enum ov5642_mode mode);
- +static int ov5642_write_snapshot_para(enum ov5642_frame_rate frame_rate,
- + enum ov5642_mode mode);
- +static int ov5642_change_mode(enum ov5642_frame_rate new_frame_rate,
- + enum ov5642_frame_rate old_frame_rate,
- + enum ov5642_mode new_mode,
- + enum ov5642_mode orig_mode)
- +{
- + struct reg_value *pModeSetting = NULL;
- + s32 i = 0;
- + s32 iModeSettingArySize = 0;
- + register u32 Delay_ms = 0;
- + register u16 RegAddr = 0;
- + register u8 Mask = 0;
- + register u8 Val = 0;
- + u8 RegVal = 0;
- + int retval = 0;
- +
- + if (new_mode > ov5642_mode_MAX || new_mode < ov5642_mode_MIN) {
- + pr_err("Wrong ov5642 mode detected!\n");
- + return -1;
- + }
- +
- + if ((new_frame_rate == old_frame_rate) &&
- + (new_mode == ov5642_mode_VGA_640_480) &&
- + (orig_mode == ov5642_mode_QSXGA_2592_1944)) {
- + pModeSetting = ov5642_setting_QSXGA_2_VGA;
- + iModeSettingArySize = ARRAY_SIZE(ov5642_setting_QSXGA_2_VGA);
- + ov5642_data.pix.width = 640;
- + ov5642_data.pix.height = 480;
- + } else if ((new_frame_rate == old_frame_rate) &&
- + (new_mode == ov5642_mode_QVGA_320_240) &&
- + (orig_mode == ov5642_mode_VGA_640_480)) {
- + pModeSetting = ov5642_setting_VGA_2_QVGA;
- + iModeSettingArySize = ARRAY_SIZE(ov5642_setting_VGA_2_QVGA);
- + ov5642_data.pix.width = 320;
- + ov5642_data.pix.height = 240;
- + } else {
- + retval = ov5642_write_snapshot_para(new_frame_rate, new_mode);
- + goto err;
- + }
- +
- + if (ov5642_data.pix.width == 0 || ov5642_data.pix.height == 0 ||
- + pModeSetting == NULL || iModeSettingArySize == 0)
- + return -EINVAL;
- +
- + for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) {
- + Delay_ms = pModeSetting->u32Delay_ms;
- + RegAddr = pModeSetting->u16RegAddr;
- + Val = pModeSetting->u8Val;
- + Mask = pModeSetting->u8Mask;
- +
- + if (Mask) {
- + retval = ov5642_read_reg(RegAddr, &RegVal);
- + if (retval < 0) {
- + pr_err("read reg error addr=0x%x", RegAddr);
- + goto err;
- + }
- +
- + RegVal &= ~(u8)Mask;
- + Val &= Mask;
- + Val |= RegVal;
- + }
- +
- + retval = ov5642_write_reg(RegAddr, Val);
- + if (retval < 0) {
- + pr_err("write reg error addr=0x%x", RegAddr);
- + goto err;
- + }
- +
- + if (Delay_ms)
- + msleep(Delay_ms);
- + }
- +err:
- + return retval;
- +}
- +static int ov5642_init_mode(enum ov5642_frame_rate frame_rate,
- + enum ov5642_mode mode)
- +{
- + struct reg_value *pModeSetting = NULL;
- + s32 i = 0;
- + s32 iModeSettingArySize = 0;
- + register u32 Delay_ms = 0;
- + register u16 RegAddr = 0;
- + register u8 Mask = 0;
- + register u8 Val = 0;
- + u8 RegVal = 0;
- + int retval = 0;
- +
- + if (mode > ov5642_mode_MAX || mode < ov5642_mode_MIN) {
- + pr_err("Wrong ov5642 mode detected!\n");
- + return -1;
- + }
- +
- + pModeSetting = ov5642_mode_info_data[frame_rate][mode].init_data_ptr;
- + iModeSettingArySize =
- + ov5642_mode_info_data[frame_rate][mode].init_data_size;
- +
- + ov5642_data.pix.width = ov5642_mode_info_data[frame_rate][mode].width;
- + ov5642_data.pix.height = ov5642_mode_info_data[frame_rate][mode].height;
- +
- + if (ov5642_data.pix.width == 0 || ov5642_data.pix.height == 0 ||
- + pModeSetting == NULL || iModeSettingArySize == 0)
- + return -EINVAL;
- +
- + for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) {
- + Delay_ms = pModeSetting->u32Delay_ms;
- + RegAddr = pModeSetting->u16RegAddr;
- + Val = pModeSetting->u8Val;
- + Mask = pModeSetting->u8Mask;
- +
- + if (Mask) {
- + retval = ov5642_read_reg(RegAddr, &RegVal);
- + if (retval < 0) {
- + pr_err("read reg error addr=0x%x", RegAddr);
- + goto err;
- + }
- +
- + RegVal &= ~(u8)Mask;
- + Val &= Mask;
- + Val |= RegVal;
- + }
- +
- + retval = ov5642_write_reg(RegAddr, Val);
- + if (retval < 0) {
- + pr_err("write reg error addr=0x%x", RegAddr);
- + goto err;
- + }
- +
- + if (Delay_ms)
- + msleep(Delay_ms);
- + }
- +err:
- + return retval;
- +}
- +
- +static int ov5642_write_snapshot_para(enum ov5642_frame_rate frame_rate,
- + enum ov5642_mode mode)
- +{
- + int ret = 0;
- + bool m_60Hz = false;
- + u16 cap_frame_rate = 50;
- + u16 g_prev_frame_rate = 225;
- +
- + u8 ev_low, ev_mid, ev_high;
- + u8 ret_l, ret_m, ret_h, gain, lines_10ms;
- + u16 ulcap_ev, icap_gain, prev_maxlines;
- + u32 ulcap_ev_gain, cap_maxlines, g_prev_ev;
- +
- + ov5642_write_reg(0x3503, 0x07);
- +
- + ret_h = ret_m = ret_l = 0;
- + g_prev_ev = 0;
- + ov5642_read_reg(0x3500, &ret_h);
- + ov5642_read_reg(0x3501, &ret_m);
- + ov5642_read_reg(0x3502, &ret_l);
- + g_prev_ev = (ret_h << 12) + (ret_m << 4) + (ret_l >> 4);
- +
- + ret_h = ret_m = ret_l = 0;
- + prev_maxlines = 0;
- + ov5642_read_reg(0x380e, &ret_h);
- + ov5642_read_reg(0x380f, &ret_l);
- + prev_maxlines = (ret_h << 8) + ret_l;
- + /*Read back AGC Gain for preview*/
- + gain = 0;
- + ov5642_read_reg(0x350b, &gain);
- +
- + ret = ov5642_init_mode(frame_rate, mode);
- + if (ret < 0)
- + return ret;
- +
- + ret_h = ret_m = ret_l = 0;
- + ov5642_read_reg(0x380e, &ret_h);
- + ov5642_read_reg(0x380f, &ret_l);
- + cap_maxlines = (ret_h << 8) + ret_l;
- + if (m_60Hz == true)
- + lines_10ms = cap_frame_rate * cap_maxlines/12000;
- + else
- + lines_10ms = cap_frame_rate * cap_maxlines/10000;
- +
- + if (prev_maxlines == 0)
- + prev_maxlines = 1;
- +
- + ulcap_ev = (g_prev_ev*(cap_frame_rate)*(cap_maxlines))/
- + (((prev_maxlines)*(g_prev_frame_rate)));
- + icap_gain = (gain & 0x0f) + 16;
- + if (gain & 0x10)
- + icap_gain = icap_gain << 1;
- +
- + if (gain & 0x20)
- + icap_gain = icap_gain << 1;
- +
- + if (gain & 0x40)
- + icap_gain = icap_gain << 1;
- +
- + if (gain & 0x80)
- + icap_gain = icap_gain << 1;
- +
- + ulcap_ev_gain = 2 * ulcap_ev * icap_gain;
- +
- + if (ulcap_ev_gain < cap_maxlines*16) {
- + ulcap_ev = ulcap_ev_gain/16;
- + if (ulcap_ev > lines_10ms) {
- + ulcap_ev /= lines_10ms;
- + ulcap_ev *= lines_10ms;
- + }
- + } else
- + ulcap_ev = cap_maxlines;
- +
- + if (ulcap_ev == 0)
- + ulcap_ev = 1;
- +
- + icap_gain = (ulcap_ev_gain*2/ulcap_ev + 1)/2;
- + ev_low = ((unsigned char)ulcap_ev)<<4;
- + ev_mid = (unsigned char)(ulcap_ev >> 4) & 0xff;
- + ev_high = (unsigned char)(ulcap_ev >> 12);
- +
- + gain = 0;
- + if (icap_gain > 31) {
- + gain |= 0x10;
- + icap_gain = icap_gain >> 1;
- + }
- + if (icap_gain > 31) {
- + gain |= 0x20;
- + icap_gain = icap_gain >> 1;
- + }
- + if (icap_gain > 31) {
- + gain |= 0x40;
- + icap_gain = icap_gain >> 1;
- + }
- + if (icap_gain > 31) {
- + gain |= 0x80;
- + icap_gain = icap_gain >> 1;
- + }
- + if (icap_gain > 16)
- + gain |= ((icap_gain - 16) & 0x0f);
- +
- + if (gain == 0x10)
- + gain = 0x11;
- +
- + ov5642_write_reg(0x350b, gain);
- + ov5642_write_reg(0x3502, ev_low);
- + ov5642_write_reg(0x3501, ev_mid);
- + ov5642_write_reg(0x3500, ev_high);
- + msleep(500);
- +
- + return ret ;
- +}
- +
- +
- +/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */
- +
- +static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
- +{
- + if (s == NULL) {
- + pr_err(" ERROR!! no slave device set!\n");
- + return -1;
- + }
- +
- + memset(p, 0, sizeof(*p));
- + p->u.bt656.clock_curr = ov5642_data.mclk;
- + pr_debug(" clock_curr=mclk=%d\n", ov5642_data.mclk);
- + p->if_type = V4L2_IF_TYPE_BT656;
- + p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
- + p->u.bt656.clock_min = OV5642_XCLK_MIN;
- + p->u.bt656.clock_max = OV5642_XCLK_MAX;
- + p->u.bt656.bt_sync_correct = 1; /* Indicate external vsync */
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @on: indicates power mode (on or off)
- + *
- + * Turns the power on or off, depending on the value of on and returns the
- + * appropriate error code.
- + */
- +static int ioctl_s_power(struct v4l2_int_device *s, int on)
- +{
- + struct sensor_data *sensor = s->priv;
- +
- + if (on && !sensor->on) {
- + if (io_regulator)
- + if (regulator_enable(io_regulator) != 0)
- + return -EIO;
- + if (core_regulator)
- + if (regulator_enable(core_regulator) != 0)
- + return -EIO;
- + if (gpo_regulator)
- + if (regulator_enable(gpo_regulator) != 0)
- + return -EIO;
- + if (analog_regulator)
- + if (regulator_enable(analog_regulator) != 0)
- + return -EIO;
- + /* Make sure power on */
- + ov5642_standby(0);
- + } else if (!on && sensor->on) {
- + if (analog_regulator)
- + regulator_disable(analog_regulator);
- + if (core_regulator)
- + regulator_disable(core_regulator);
- + if (io_regulator)
- + regulator_disable(io_regulator);
- + if (gpo_regulator)
- + regulator_disable(gpo_regulator);
- +
- + ov5642_standby(1);
- + }
- +
- + sensor->on = on;
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
- + *
- + * Returns the sensor's video CAPTURE parameters.
- + */
- +static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
- +{
- + struct sensor_data *sensor = s->priv;
- + struct v4l2_captureparm *cparm = &a->parm.capture;
- + int ret = 0;
- +
- + switch (a->type) {
- + /* This is the only case currently handled. */
- + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- + memset(a, 0, sizeof(*a));
- + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- + cparm->capability = sensor->streamcap.capability;
- + cparm->timeperframe = sensor->streamcap.timeperframe;
- + cparm->capturemode = sensor->streamcap.capturemode;
- + ret = 0;
- + break;
- +
- + /* These are all the possible cases. */
- + case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- + case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- + case V4L2_BUF_TYPE_VBI_CAPTURE:
- + case V4L2_BUF_TYPE_VBI_OUTPUT:
- + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- + ret = -EINVAL;
- + break;
- +
- + default:
- + pr_debug(" type is unknown - %d\n", a->type);
- + ret = -EINVAL;
- + break;
- + }
- +
- + return ret;
- +}
- +
- +/*!
- + * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
- + *
- + * Configures the sensor to use the input parameters, if possible. If
- + * not possible, reverts to the old parameters and returns the
- + * appropriate error code.
- + */
- +static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
- +{
- + struct sensor_data *sensor = s->priv;
- + struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
- + u32 tgt_fps, old_fps; /* target frames per secound */
- + enum ov5642_frame_rate new_frame_rate, old_frame_rate;
- + int ret = 0;
- +
- + /* Make sure power on */
- + ov5642_standby(0);
- +
- + switch (a->type) {
- + /* This is the only case currently handled. */
- + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- + /* Check that the new frame rate is allowed. */
- + if ((timeperframe->numerator == 0) ||
- + (timeperframe->denominator == 0)) {
- + timeperframe->denominator = DEFAULT_FPS;
- + timeperframe->numerator = 1;
- + }
- +
- + tgt_fps = timeperframe->denominator /
- + timeperframe->numerator;
- +
- + if (tgt_fps > MAX_FPS) {
- + timeperframe->denominator = MAX_FPS;
- + timeperframe->numerator = 1;
- + } else if (tgt_fps < MIN_FPS) {
- + timeperframe->denominator = MIN_FPS;
- + timeperframe->numerator = 1;
- + }
- +
- + /* Actual frame rate we use */
- + tgt_fps = timeperframe->denominator /
- + timeperframe->numerator;
- +
- + if (tgt_fps == 15)
- + new_frame_rate = ov5642_15_fps;
- + else if (tgt_fps == 30)
- + new_frame_rate = ov5642_30_fps;
- + else {
- + pr_err(" The camera frame rate is not supported!\n");
- + return -EINVAL;
- + }
- +
- + if (sensor->streamcap.timeperframe.numerator != 0)
- + old_fps = sensor->streamcap.timeperframe.denominator /
- + sensor->streamcap.timeperframe.numerator;
- + else
- + old_fps = 30;
- +
- + if (old_fps == 15)
- + old_frame_rate = ov5642_15_fps;
- + else if (old_fps == 30)
- + old_frame_rate = ov5642_30_fps;
- + else {
- + pr_warning(" No valid frame rate set!\n");
- + old_frame_rate = ov5642_30_fps;
- + }
- +
- + ret = ov5642_change_mode(new_frame_rate, old_frame_rate,
- + a->parm.capture.capturemode,
- + sensor->streamcap.capturemode);
- + if (ret < 0)
- + return ret;
- +
- + sensor->streamcap.timeperframe = *timeperframe;
- + sensor->streamcap.capturemode =
- + (u32)a->parm.capture.capturemode;
- + break;
- +
- + /* These are all the possible cases. */
- + case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- + case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- + case V4L2_BUF_TYPE_VBI_CAPTURE:
- + case V4L2_BUF_TYPE_VBI_OUTPUT:
- + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- + pr_debug(" type is not " \
- + "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
- + a->type);
- + ret = -EINVAL;
- + break;
- +
- + default:
- + pr_debug(" type is unknown - %d\n", a->type);
- + ret = -EINVAL;
- + break;
- + }
- +
- + return ret;
- +}
- +
- +/*!
- + * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
- + * @s: pointer to standard V4L2 device structure
- + * @f: pointer to standard V4L2 v4l2_format structure
- + *
- + * Returns the sensor's current pixel format in the v4l2_format
- + * parameter.
- + */
- +static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
- +{
- + struct sensor_data *sensor = s->priv;
- +
- + f->fmt.pix = sensor->pix;
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
- + *
- + * If the requested control is supported, returns the control's current
- + * value from the video_control[] array. Otherwise, returns -EINVAL
- + * if the control is not supported.
- + */
- +static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
- +{
- + int ret = 0;
- +
- + switch (vc->id) {
- + case V4L2_CID_BRIGHTNESS:
- + vc->value = ov5642_data.brightness;
- + break;
- + case V4L2_CID_HUE:
- + vc->value = ov5642_data.hue;
- + break;
- + case V4L2_CID_CONTRAST:
- + vc->value = ov5642_data.contrast;
- + break;
- + case V4L2_CID_SATURATION:
- + vc->value = ov5642_data.saturation;
- + break;
- + case V4L2_CID_RED_BALANCE:
- + vc->value = ov5642_data.red;
- + break;
- + case V4L2_CID_BLUE_BALANCE:
- + vc->value = ov5642_data.blue;
- + break;
- + case V4L2_CID_EXPOSURE:
- + vc->value = ov5642_data.ae_mode;
- + break;
- + default:
- + ret = -EINVAL;
- + }
- +
- + return ret;
- +}
- +
- +/*!
- + * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
- + *
- + * If the requested control is supported, sets the control's current
- + * value in HW (and updates the video_control[] array). Otherwise,
- + * returns -EINVAL if the control is not supported.
- + */
- +static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
- +{
- + int retval = 0;
- + struct sensor_data *sensor = s->priv;
- + __u32 captureMode = sensor->streamcap.capturemode;
- + struct reg_value *rot_mode = NULL;
- +
- + pr_debug("In ov5642:ioctl_s_ctrl %d\n",
- + vc->id);
- +
- + switch (vc->id) {
- + case V4L2_CID_BRIGHTNESS:
- + break;
- + case V4L2_CID_CONTRAST:
- + break;
- + case V4L2_CID_SATURATION:
- + break;
- + case V4L2_CID_HUE:
- + break;
- + case V4L2_CID_AUTO_WHITE_BALANCE:
- + break;
- + case V4L2_CID_DO_WHITE_BALANCE:
- + break;
- + case V4L2_CID_RED_BALANCE:
- + break;
- + case V4L2_CID_BLUE_BALANCE:
- + break;
- + case V4L2_CID_GAMMA:
- + break;
- + case V4L2_CID_EXPOSURE:
- + break;
- + case V4L2_CID_AUTOGAIN:
- + break;
- + case V4L2_CID_GAIN:
- + break;
- + case V4L2_CID_HFLIP:
- + break;
- + case V4L2_CID_VFLIP:
- + break;
- + case V4L2_CID_MXC_ROT:
- + case V4L2_CID_MXC_VF_ROT:
- + switch (vc->value) {
- + case V4L2_MXC_ROTATE_NONE:
- + if (captureMode == ov5642_mode_QSXGA_2592_1944)
- + rot_mode = ov5642_rot_none_FULL;
- + else
- + rot_mode = ov5642_rot_none_VGA;
- +
- + if (ov5642_set_rot_mode(rot_mode))
- + retval = -EPERM;
- + break;
- + case V4L2_MXC_ROTATE_VERT_FLIP:
- + if (captureMode == ov5642_mode_QSXGA_2592_1944)
- + rot_mode = ov5642_rot_vert_flip_FULL;
- + else
- + rot_mode = ov5642_rot_vert_flip_VGA ;
- +
- + if (ov5642_set_rot_mode(rot_mode))
- + retval = -EPERM;
- + break;
- + case V4L2_MXC_ROTATE_HORIZ_FLIP:
- + if (captureMode == ov5642_mode_QSXGA_2592_1944)
- + rot_mode = ov5642_rot_horiz_flip_FULL;
- + else
- + rot_mode = ov5642_rot_horiz_flip_VGA;
- +
- + if (ov5642_set_rot_mode(rot_mode))
- + retval = -EPERM;
- + break;
- + case V4L2_MXC_ROTATE_180:
- + if (captureMode == ov5642_mode_QSXGA_2592_1944)
- + rot_mode = ov5642_rot_180_FULL;
- + else
- + rot_mode = ov5642_rot_180_VGA;
- +
- + if (ov5642_set_rot_mode(rot_mode))
- + retval = -EPERM;
- + break;
- + default:
- + retval = -EPERM;
- + break;
- + }
- + break;
- + default:
- + retval = -EPERM;
- + break;
- + }
- +
- + return retval;
- +}
- +
- +/*!
- + * ioctl_enum_framesizes - V4L2 sensor interface handler for
- + * VIDIOC_ENUM_FRAMESIZES ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
- + *
- + * Return 0 if successful, otherwise -EINVAL.
- + */
- +static int ioctl_enum_framesizes(struct v4l2_int_device *s,
- + struct v4l2_frmsizeenum *fsize)
- +{
- + if (fsize->index > ov5642_mode_MAX)
- + return -EINVAL;
- +
- + fsize->pixel_format = ov5642_data.pix.pixelformat;
- + fsize->discrete.width =
- + max(ov5642_mode_info_data[0][fsize->index].width,
- + ov5642_mode_info_data[1][fsize->index].width);
- + fsize->discrete.height =
- + max(ov5642_mode_info_data[0][fsize->index].height,
- + ov5642_mode_info_data[1][fsize->index].height);
- + return 0;
- +}
- +
- +/*!
- + * ioctl_enum_frameintervals - V4L2 sensor interface handler for
- + * VIDIOC_ENUM_FRAMEINTERVALS ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
- + *
- + * Return 0 if successful, otherwise -EINVAL.
- + */
- +static int ioctl_enum_frameintervals(struct v4l2_int_device *s,
- + struct v4l2_frmivalenum *fival)
- +{
- + int i, j, count;
- +
- + if (fival->index < 0 || fival->index > ov5642_mode_MAX)
- + return -EINVAL;
- +
- + if (fival->pixel_format == 0 || fival->width == 0 ||
- + fival->height == 0) {
- + pr_warning("Please assign pixelformat, width and height.\n");
- + return -EINVAL;
- + }
- +
- + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
- + fival->discrete.numerator = 1;
- +
- + count = 0;
- + for (i = 0; i < ARRAY_SIZE(ov5642_mode_info_data); i++) {
- + for (j = 0; j < (ov5642_mode_MAX + 1); j++) {
- + if (fival->pixel_format == ov5642_data.pix.pixelformat
- + && fival->width == ov5642_mode_info_data[i][j].width
- + && fival->height == ov5642_mode_info_data[i][j].height
- + && ov5642_mode_info_data[i][j].init_data_ptr != NULL) {
- + count++;
- + }
- + if (fival->index == (count - 1)) {
- + fival->discrete.denominator =
- + ov5642_framerates[i];
- + return 0;
- + }
- + }
- + }
- +
- + return -EINVAL;
- +}
- +
- +/*!
- + * ioctl_g_chip_ident - V4L2 sensor interface handler for
- + * VIDIOC_DBG_G_CHIP_IDENT ioctl
- + * @s: pointer to standard V4L2 device structure
- + * @id: pointer to int
- + *
- + * Return 0.
- + */
- +static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
- +{
- + ((struct v4l2_dbg_chip_ident *)id)->match.type =
- + V4L2_CHIP_MATCH_I2C_DRIVER;
- + strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, "ov5642_camera");
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
- + * @s: pointer to standard V4L2 device structure
- + */
- +static int ioctl_init(struct v4l2_int_device *s)
- +{
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT
- + * @s: pointer to standard V4L2 device structure
- + * @fmt: pointer to standard V4L2 fmt description structure
- + *
- + * Return 0.
- + */
- +static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
- + struct v4l2_fmtdesc *fmt)
- +{
- + if (fmt->index > 0) /* only 1 pixelformat support so far */
- + return -EINVAL;
- +
- + fmt->pixelformat = ov5642_data.pix.pixelformat;
- +
- + return 0;
- +}
- +
- +/*!
- + * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
- + * @s: pointer to standard V4L2 device structure
- + *
- + * Initialise the device when slave attaches to the master.
- + */
- +static int ioctl_dev_init(struct v4l2_int_device *s)
- +{
- + struct reg_value *pModeSetting = NULL;
- + s32 i = 0;
- + s32 iModeSettingArySize = 0;
- + register u32 Delay_ms = 0;
- + register u16 RegAddr = 0;
- + register u8 Mask = 0;
- + register u8 Val = 0;
- + u8 RegVal = 0;
- + int retval = 0;
- +
- + struct sensor_data *sensor = s->priv;
- + u32 tgt_xclk; /* target xclk */
- + u32 tgt_fps; /* target frames per secound */
- + enum ov5642_frame_rate frame_rate;
- +
- + ov5642_data.on = true;
- +
- + /* mclk */
- + tgt_xclk = ov5642_data.mclk;
- + tgt_xclk = min(tgt_xclk, (u32)OV5642_XCLK_MAX);
- + tgt_xclk = max(tgt_xclk, (u32)OV5642_XCLK_MIN);
- + ov5642_data.mclk = tgt_xclk;
- +
- + pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000);
- +
- + /* Default camera frame rate is set in probe */
- + tgt_fps = sensor->streamcap.timeperframe.denominator /
- + sensor->streamcap.timeperframe.numerator;
- +
- + if (tgt_fps == 15)
- + frame_rate = ov5642_15_fps;
- + else if (tgt_fps == 30)
- + frame_rate = ov5642_30_fps;
- + else
- + return -EINVAL; /* Only support 15fps or 30fps now. */
- +
- + pModeSetting = ov5642_initial_setting;
- + iModeSettingArySize = ARRAY_SIZE(ov5642_initial_setting);
- +
- + for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) {
- + Delay_ms = pModeSetting->u32Delay_ms;
- + RegAddr = pModeSetting->u16RegAddr;
- + Val = pModeSetting->u8Val;
- + Mask = pModeSetting->u8Mask;
- + if (Mask) {
- + retval = ov5642_read_reg(RegAddr, &RegVal);
- + if (retval < 0)
- + goto err;
- +
- + RegVal &= ~(u8)Mask;
- + Val &= Mask;
- + Val |= RegVal;
- + }
- +
- + retval = ov5642_write_reg(RegAddr, Val);
- + if (retval < 0)
- + goto err;
- +
- + if (Delay_ms)
- + msleep(Delay_ms);
- + }
- +err:
- + return retval;
- +}
- +
- +/*!
- + * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num
- + * @s: pointer to standard V4L2 device structure
- + *
- + * Delinitialise the device when slave detaches to the master.
- + */
- +static int ioctl_dev_exit(struct v4l2_int_device *s)
- +{
- + return 0;
- +}
- +
- +/*!
- + * This structure defines all the ioctls for this module and links them to the
- + * enumeration.
- + */
- +static struct v4l2_int_ioctl_desc ov5642_ioctl_desc[] = {
- + { vidioc_int_dev_init_num,
- + (v4l2_int_ioctl_func *)ioctl_dev_init },
- + { vidioc_int_dev_exit_num, ioctl_dev_exit},
- + { vidioc_int_s_power_num,
- + (v4l2_int_ioctl_func *)ioctl_s_power },
- + { vidioc_int_g_ifparm_num,
- + (v4l2_int_ioctl_func *)ioctl_g_ifparm },
- +/* { vidioc_int_g_needs_reset_num,
- + (v4l2_int_ioctl_func *)ioctl_g_needs_reset }, */
- +/* { vidioc_int_reset_num,
- + (v4l2_int_ioctl_func *)ioctl_reset }, */
- + { vidioc_int_init_num,
- + (v4l2_int_ioctl_func *)ioctl_init },
- + { vidioc_int_enum_fmt_cap_num,
- + (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap },
- +/* { vidioc_int_try_fmt_cap_num,
- + (v4l2_int_ioctl_func *)ioctl_try_fmt_cap }, */
- + { vidioc_int_g_fmt_cap_num,
- + (v4l2_int_ioctl_func *)ioctl_g_fmt_cap },
- +/* { vidioc_int_s_fmt_cap_num,
- + (v4l2_int_ioctl_func *)ioctl_s_fmt_cap }, */
- + { vidioc_int_g_parm_num,
- + (v4l2_int_ioctl_func *)ioctl_g_parm },
- + { vidioc_int_s_parm_num,
- + (v4l2_int_ioctl_func *)ioctl_s_parm },
- +/* { vidioc_int_queryctrl_num,
- + (v4l2_int_ioctl_func *)ioctl_queryctrl }, */
- + { vidioc_int_g_ctrl_num,
- + (v4l2_int_ioctl_func *)ioctl_g_ctrl },
- + { vidioc_int_s_ctrl_num,
- + (v4l2_int_ioctl_func *)ioctl_s_ctrl },
- + { vidioc_int_enum_framesizes_num,
- + (v4l2_int_ioctl_func *)ioctl_enum_framesizes },
- + { vidioc_int_enum_frameintervals_num,
- + (v4l2_int_ioctl_func *)ioctl_enum_frameintervals },
- + { vidioc_int_g_chip_ident_num,
- + (v4l2_int_ioctl_func *)ioctl_g_chip_ident },
- +};
- +
- +static struct v4l2_int_slave ov5642_slave = {
- + .ioctls = ov5642_ioctl_desc,
- + .num_ioctls = ARRAY_SIZE(ov5642_ioctl_desc),
- +};
- +
- +static struct v4l2_int_device ov5642_int_device = {
- + .module = THIS_MODULE,
- + .name = "ov5642",
- + .type = v4l2_int_type_slave,
- + .u = {
- + .slave = &ov5642_slave,
- + },
- +};
- +
- +/*!
- + * ov5642 I2C probe function
- + *
- + * @param adapter struct i2c_adapter *
- + * @return Error code indicating success or failure
- + */
- +static int ov5642_probe(struct i2c_client *client,
- + const struct i2c_device_id *id)
- +{
- + struct pinctrl *pinctrl;
- + struct device *dev = &client->dev;
- + int retval;
- + u8 chip_id_high, chip_id_low;
- +
- + /* ov5642 pinctrl */
- + pinctrl = devm_pinctrl_get_select_default(dev);
- + if (IS_ERR(pinctrl)) {
- + dev_err(dev, "ov5642 setup pinctrl failed!");
- + return PTR_ERR(pinctrl);
- + }
- +
- + /* request power down pin */
- + pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
- + if (!gpio_is_valid(pwn_gpio)) {
- + dev_warn(dev, "no sensor pwdn pin available");
- + return -EINVAL;
- + }
- + retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
- + "ov5642_pwdn");
- + if (retval < 0)
- + return retval;
- +
- + /* request reset pin */
- + rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
- + if (!gpio_is_valid(rst_gpio)) {
- + dev_warn(dev, "no sensor reset pin available");
- + return -EINVAL;
- + }
- + retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
- + "ov5642_reset");
- + if (retval < 0)
- + return retval;
- +
- + /* Set initial values for the sensor struct. */
- + memset(&ov5642_data, 0, sizeof(ov5642_data));
- + ov5642_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
- + if (IS_ERR(ov5642_data.sensor_clk)) {
- + /* assuming clock enabled by default */
- + ov5642_data.sensor_clk = NULL;
- + dev_err(dev, "clock-frequency missing or invalid\n");
- + return PTR_ERR(ov5642_data.sensor_clk);
- + }
- +
- + retval = of_property_read_u32(dev->of_node, "mclk",
- + (u32 *) &(ov5642_data.mclk));
- + if (retval) {
- + dev_err(dev, "mclk missing or invalid\n");
- + return retval;
- + }
- +
- + retval = of_property_read_u32(dev->of_node, "mclk_source",
- + (u32 *) &(ov5642_data.mclk_source));
- + if (retval) {
- + dev_err(dev, "mclk_source missing or invalid\n");
- + return retval;
- + }
- +
- + retval = of_property_read_u32(dev->of_node, "csi_id",
- + &(ov5642_data.csi));
- + if (retval) {
- + dev_err(dev, "csi_id missing or invalid\n");
- + return retval;
- + }
- +
- + clk_prepare_enable(ov5642_data.sensor_clk);
- +
- + ov5642_data.io_init = ov5642_reset;
- + ov5642_data.i2c_client = client;
- + ov5642_data.pix.pixelformat = V4L2_PIX_FMT_YUYV;
- + ov5642_data.pix.width = 640;
- + ov5642_data.pix.height = 480;
- + ov5642_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
- + V4L2_CAP_TIMEPERFRAME;
- + ov5642_data.streamcap.capturemode = 0;
- + ov5642_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
- + ov5642_data.streamcap.timeperframe.numerator = 1;
- +
- + ov5642_power_on(&client->dev);
- +
- + ov5642_reset();
- +
- + ov5642_standby(0);
- +
- + retval = ov5642_read_reg(OV5642_CHIP_ID_HIGH_BYTE, &chip_id_high);
- + if (retval < 0 || chip_id_high != 0x56) {
- + pr_warning("camera ov5642 is not found\n");
- + clk_disable_unprepare(ov5642_data.sensor_clk);
- + return -ENODEV;
- + }
- + retval = ov5642_read_reg(OV5642_CHIP_ID_LOW_BYTE, &chip_id_low);
- + if (retval < 0 || chip_id_low != 0x42) {
- + pr_warning("camera ov5642 is not found\n");
- + clk_disable_unprepare(ov5642_data.sensor_clk);
- + return -ENODEV;
- + }
- +
- + ov5642_standby(1);
- +
- + ov5642_int_device.priv = &ov5642_data;
- + retval = v4l2_int_device_register(&ov5642_int_device);
- +
- + clk_disable_unprepare(ov5642_data.sensor_clk);
- +
- + pr_info("camera ov5642 is found\n");
- + return retval;
- +}
- +
- +/*!
- + * ov5642 I2C detach function
- + *
- + * @param client struct i2c_client *
- + * @return Error code indicating success or failure
- + */
- +static int ov5642_remove(struct i2c_client *client)
- +{
- + v4l2_int_device_unregister(&ov5642_int_device);
- +
- + if (gpo_regulator)
- + regulator_disable(gpo_regulator);
- +
- + if (analog_regulator)
- + regulator_disable(analog_regulator);
- +
- + if (core_regulator)
- + regulator_disable(core_regulator);
- +
- + if (io_regulator)
- + regulator_disable(io_regulator);
- +
- + return 0;
- +}
- +
- +/*!
- + * ov5642 init function
- + * Called by insmod ov5642_camera.ko.
- + *
- + * @return Error code indicating success or failure
- + */
- +static __init int ov5642_init(void)
- +{
- + u8 err;
- +
- + err = i2c_add_driver(&ov5642_i2c_driver);
- + if (err != 0)
- + pr_err("%s:driver registration failed, error=%d\n",
- + __func__, err);
- +
- + return err;
- +}
- +
- +/*!
- + * OV5642 cleanup function
- + * Called on rmmod ov5642_camera.ko
- + *
- + * @return Error code indicating success or failure
- + */
- +static void __exit ov5642_clean(void)
- +{
- + i2c_del_driver(&ov5642_i2c_driver);
- +}
- +
- +module_init(ov5642_init);
- +module_exit(ov5642_clean);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("OV5642 Camera Driver");
- +MODULE_LICENSE("GPL");
- +MODULE_VERSION("1.0");
- +MODULE_ALIAS("CSI");
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/output/Kconfig linux-3.14.35/drivers/media/platform/mxc/output/Kconfig
- --- linux-3.14.35.orig/drivers/media/platform/mxc/output/Kconfig 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/output/Kconfig 2015-03-08 14:27:37.601684501 -0500
- @@ -0,0 +1,5 @@
- +config VIDEO_MXC_IPU_OUTPUT
- + tristate "IPU v4l2 output support"
- + depends on VIDEO_MXC_OUTPUT && MXC_IPU
- + ---help---
- + This is the video4linux2 driver for IPU post processing video output.
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/output/Makefile linux-3.14.35/drivers/media/platform/mxc/output/Makefile
- --- linux-3.14.35.orig/drivers/media/platform/mxc/output/Makefile 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/output/Makefile 2015-03-08 14:27:37.601684501 -0500
- @@ -0,0 +1 @@
- +obj-$(CONFIG_VIDEO_MXC_IPU_OUTPUT) += mxc_vout.o
- diff -Nur linux-3.14.35.orig/drivers/media/platform/mxc/output/mxc_vout.c linux-3.14.35/drivers/media/platform/mxc/output/mxc_vout.c
- --- linux-3.14.35.orig/drivers/media/platform/mxc/output/mxc_vout.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/media/platform/mxc/output/mxc_vout.c 2015-03-08 14:27:37.605684501 -0500
- @@ -0,0 +1,2265 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#include <linux/console.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/init.h>
- +#include <linux/ipu-v3.h>
- +#include <linux/module.h>
- +#include <linux/mxcfb.h>
- +#include <linux/mxc_v4l2.h>
- +#include <linux/platform_device.h>
- +#include <linux/sched.h>
- +#include <linux/types.h>
- +#include <linux/videodev2.h>
- +#include <linux/vmalloc.h>
- +
- +#include <media/videobuf-dma-contig.h>
- +#include <media/v4l2-device.h>
- +#include <media/v4l2-ioctl.h>
- +
- +#define UYVY_BLACK (0x00800080)
- +#define RGB_BLACK (0x0)
- +#define UV_BLACK (0x80)
- +#define Y_BLACK (0x0)
- +
- +#define MAX_FB_NUM 6
- +#define FB_BUFS 3
- +#define VDOA_FB_BUFS (FB_BUFS - 1)
- +#define VALID_HEIGHT_1080P (1080)
- +#define FRAME_HEIGHT_1080P (1088)
- +#define FRAME_WIDTH_1080P (1920)
- +#define CHECK_TILED_1080P_DISPLAY(vout) \
- + ((((vout)->task.input.format == IPU_PIX_FMT_TILED_NV12) || \
- + ((vout)->task.input.format == IPU_PIX_FMT_TILED_NV12F)) &&\
- + ((vout)->task.input.width == FRAME_WIDTH_1080P) && \
- + ((vout)->task.input.height == FRAME_HEIGHT_1080P) && \
- + ((vout)->task.input.crop.w == FRAME_WIDTH_1080P) && \
- + (((vout)->task.input.crop.h == FRAME_HEIGHT_1080P) || \
- + ((vout)->task.input.crop.h == VALID_HEIGHT_1080P)) && \
- + ((vout)->task.output.width == FRAME_WIDTH_1080P) && \
- + ((vout)->task.output.height == VALID_HEIGHT_1080P) && \
- + ((vout)->task.output.crop.w == FRAME_WIDTH_1080P) && \
- + ((vout)->task.output.crop.h == VALID_HEIGHT_1080P))
- +#define CHECK_TILED_1080P_STREAM(vout) \
- + ((((vout)->task.input.format == IPU_PIX_FMT_TILED_NV12) || \
- + ((vout)->task.input.format == IPU_PIX_FMT_TILED_NV12F)) &&\
- + ((vout)->task.input.width == FRAME_WIDTH_1080P) && \
- + ((vout)->task.input.crop.w == FRAME_WIDTH_1080P) && \
- + ((vout)->task.input.height == FRAME_HEIGHT_1080P) && \
- + ((vout)->task.input.crop.h == FRAME_HEIGHT_1080P))
- +#define IS_PLANAR_PIXEL_FORMAT(format) \
- + (format == IPU_PIX_FMT_NV12 || \
- + format == IPU_PIX_FMT_YUV420P2 || \
- + format == IPU_PIX_FMT_YUV420P || \
- + format == IPU_PIX_FMT_YVU420P || \
- + format == IPU_PIX_FMT_YUV422P || \
- + format == IPU_PIX_FMT_YVU422P || \
- + format == IPU_PIX_FMT_YUV444P)
- +
- +#define NSEC_PER_FRAME_30FPS (33333333)
- +
- +struct mxc_vout_fb {
- + char *name;
- + int ipu_id;
- + struct v4l2_rect crop_bounds;
- + unsigned int disp_fmt;
- + bool disp_support_csc;
- + bool disp_support_windows;
- +};
- +
- +struct dma_mem {
- + void *vaddr;
- + dma_addr_t paddr;
- + size_t size;
- +};
- +
- +struct mxc_vout_output {
- + int open_cnt;
- + struct fb_info *fbi;
- + unsigned long fb_smem_start;
- + unsigned long fb_smem_len;
- + struct video_device *vfd;
- + struct mutex mutex;
- + struct mutex task_lock;
- + enum v4l2_buf_type type;
- +
- + struct videobuf_queue vbq;
- + spinlock_t vbq_lock;
- +
- + struct list_head queue_list;
- + struct list_head active_list;
- +
- + struct v4l2_rect crop_bounds;
- + unsigned int disp_fmt;
- + struct mxcfb_pos win_pos;
- + bool disp_support_windows;
- + bool disp_support_csc;
- +
- + bool fmt_init;
- + bool release;
- + bool linear_bypass_pp;
- + bool vdoa_1080p;
- + bool tiled_bypass_pp;
- + struct v4l2_rect in_rect;
- + struct ipu_task task;
- + struct ipu_task vdoa_task;
- + struct dma_mem vdoa_work;
- + struct dma_mem vdoa_output[VDOA_FB_BUFS];
- +
- + bool timer_stop;
- + struct hrtimer timer;
- + struct workqueue_struct *v4l_wq;
- + struct work_struct disp_work;
- + unsigned long frame_count;
- + unsigned long vdi_frame_cnt;
- + ktime_t start_ktime;
- +
- + int ctrl_rotate;
- + int ctrl_vflip;
- + int ctrl_hflip;
- +
- + dma_addr_t disp_bufs[FB_BUFS];
- +
- + struct videobuf_buffer *pre1_vb;
- + struct videobuf_buffer *pre2_vb;
- +};
- +
- +struct mxc_vout_dev {
- + struct device *dev;
- + struct v4l2_device v4l2_dev;
- + struct mxc_vout_output *out[MAX_FB_NUM];
- + int out_num;
- +};
- +
- +/* Driver Configuration macros */
- +#define VOUT_NAME "mxc_vout"
- +
- +/* Variables configurable through module params*/
- +static int debug;
- +static int vdi_rate_double;
- +static int video_nr = 16;
- +
- +/* Module parameters */
- +module_param(video_nr, int, S_IRUGO);
- +MODULE_PARM_DESC(video_nr, "video device numbers");
- +module_param(debug, int, 0600);
- +MODULE_PARM_DESC(debug, "Debug level (0-1)");
- +module_param(vdi_rate_double, int, 0600);
- +MODULE_PARM_DESC(vdi_rate_double, "vdi frame rate double on/off");
- +
- +static const struct v4l2_fmtdesc mxc_formats[] = {
- + {
- + .description = "RGB565",
- + .pixelformat = V4L2_PIX_FMT_RGB565,
- + },
- + {
- + .description = "BGR24",
- + .pixelformat = V4L2_PIX_FMT_BGR24,
- + },
- + {
- + .description = "RGB24",
- + .pixelformat = V4L2_PIX_FMT_RGB24,
- + },
- + {
- + .description = "RGB32",
- + .pixelformat = V4L2_PIX_FMT_RGB32,
- + },
- + {
- + .description = "BGR32",
- + .pixelformat = V4L2_PIX_FMT_BGR32,
- + },
- + {
- + .description = "NV12",
- + .pixelformat = V4L2_PIX_FMT_NV12,
- + },
- + {
- + .description = "UYVY",
- + .pixelformat = V4L2_PIX_FMT_UYVY,
- + },
- + {
- + .description = "YUYV",
- + .pixelformat = V4L2_PIX_FMT_YUYV,
- + },
- + {
- + .description = "YUV422 planar",
- + .pixelformat = V4L2_PIX_FMT_YUV422P,
- + },
- + {
- + .description = "YUV444",
- + .pixelformat = V4L2_PIX_FMT_YUV444,
- + },
- + {
- + .description = "YUV420",
- + .pixelformat = V4L2_PIX_FMT_YUV420,
- + },
- + {
- + .description = "YVU420",
- + .pixelformat = V4L2_PIX_FMT_YVU420,
- + },
- + {
- + .description = "TILED NV12P",
- + .pixelformat = IPU_PIX_FMT_TILED_NV12,
- + },
- + {
- + .description = "TILED NV12F",
- + .pixelformat = IPU_PIX_FMT_TILED_NV12F,
- + },
- + {
- + .description = "YUV444 planar",
- + .pixelformat = IPU_PIX_FMT_YUV444P,
- + },
- +};
- +
- +#define NUM_MXC_VOUT_FORMATS (ARRAY_SIZE(mxc_formats))
- +
- +#define DEF_INPUT_WIDTH 320
- +#define DEF_INPUT_HEIGHT 240
- +
- +static int mxc_vidioc_streamoff(struct file *file, void *fh,
- + enum v4l2_buf_type i);
- +
- +static struct mxc_vout_fb g_fb_setting[MAX_FB_NUM];
- +static int config_disp_output(struct mxc_vout_output *vout);
- +static void release_disp_output(struct mxc_vout_output *vout);
- +
- +static unsigned int get_frame_size(struct mxc_vout_output *vout)
- +{
- + unsigned int size;
- +
- + if (IPU_PIX_FMT_TILED_NV12 == vout->task.input.format)
- + size = TILED_NV12_FRAME_SIZE(vout->task.input.width,
- + vout->task.input.height);
- + else if (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format) {
- + size = TILED_NV12_FRAME_SIZE(vout->task.input.width,
- + vout->task.input.height/2);
- + size *= 2;
- + } else
- + size = vout->task.input.width * vout->task.input.height *
- + fmt_to_bpp(vout->task.input.format)/8;
- +
- + return size;
- +}
- +
- +static void free_dma_buf(struct mxc_vout_output *vout, struct dma_mem *buf)
- +{
- + dma_free_coherent(vout->vbq.dev, buf->size, buf->vaddr, buf->paddr);
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
- + "free dma size:0x%x, paddr:0x%x\n",
- + buf->size, buf->paddr);
- + memset(buf, 0, sizeof(*buf));
- +}
- +
- +static int alloc_dma_buf(struct mxc_vout_output *vout, struct dma_mem *buf)
- +{
- +
- + buf->vaddr = dma_alloc_coherent(vout->vbq.dev, buf->size, &buf->paddr,
- + GFP_DMA | GFP_KERNEL);
- + if (!buf->vaddr) {
- + v4l2_err(vout->vfd->v4l2_dev,
- + "cannot get dma buf size:0x%x\n", buf->size);
- + return -ENOMEM;
- + }
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
- + "alloc dma buf size:0x%x, paddr:0x%x\n", buf->size, buf->paddr);
- + return 0;
- +}
- +
- +static ipu_channel_t get_ipu_channel(struct fb_info *fbi)
- +{
- + ipu_channel_t ipu_ch = CHAN_NONE;
- + mm_segment_t old_fs;
- +
- + if (fbi->fbops->fb_ioctl) {
- + old_fs = get_fs();
- + set_fs(KERNEL_DS);
- + fbi->fbops->fb_ioctl(fbi, MXCFB_GET_FB_IPU_CHAN,
- + (unsigned long)&ipu_ch);
- + set_fs(old_fs);
- + }
- +
- + return ipu_ch;
- +}
- +
- +static unsigned int get_ipu_fmt(struct fb_info *fbi)
- +{
- + mm_segment_t old_fs;
- + unsigned int fb_fmt;
- +
- + if (fbi->fbops->fb_ioctl) {
- + old_fs = get_fs();
- + set_fs(KERNEL_DS);
- + fbi->fbops->fb_ioctl(fbi, MXCFB_GET_DIFMT,
- + (unsigned long)&fb_fmt);
- + set_fs(old_fs);
- + }
- +
- + return fb_fmt;
- +}
- +
- +static void update_display_setting(void)
- +{
- + int i;
- + struct fb_info *fbi;
- + struct v4l2_rect bg_crop_bounds[2];
- +
- + for (i = 0; i < num_registered_fb; i++) {
- + fbi = registered_fb[i];
- +
- + memset(&g_fb_setting[i], 0, sizeof(struct mxc_vout_fb));
- +
- + if (!strncmp(fbi->fix.id, "DISP3", 5))
- + g_fb_setting[i].ipu_id = 0;
- + else
- + g_fb_setting[i].ipu_id = 1;
- +
- + g_fb_setting[i].name = fbi->fix.id;
- + g_fb_setting[i].crop_bounds.left = 0;
- + g_fb_setting[i].crop_bounds.top = 0;
- + g_fb_setting[i].crop_bounds.width = fbi->var.xres;
- + g_fb_setting[i].crop_bounds.height = fbi->var.yres;
- + g_fb_setting[i].disp_fmt = get_ipu_fmt(fbi);
- +
- + if (get_ipu_channel(fbi) == MEM_BG_SYNC) {
- + bg_crop_bounds[g_fb_setting[i].ipu_id] =
- + g_fb_setting[i].crop_bounds;
- + g_fb_setting[i].disp_support_csc = true;
- + } else if (get_ipu_channel(fbi) == MEM_FG_SYNC) {
- + g_fb_setting[i].disp_support_csc = true;
- + g_fb_setting[i].disp_support_windows = true;
- + }
- + }
- +
- + for (i = 0; i < num_registered_fb; i++) {
- + fbi = registered_fb[i];
- +
- + if (get_ipu_channel(fbi) == MEM_FG_SYNC)
- + g_fb_setting[i].crop_bounds =
- + bg_crop_bounds[g_fb_setting[i].ipu_id];
- + }
- +}
- +
- +/* called after g_fb_setting filled by update_display_setting */
- +static int update_setting_from_fbi(struct mxc_vout_output *vout,
- + struct fb_info *fbi)
- +{
- + int i;
- + bool found = false;
- +
- + for (i = 0; i < MAX_FB_NUM; i++) {
- + if (g_fb_setting[i].name) {
- + if (!strcmp(fbi->fix.id, g_fb_setting[i].name)) {
- + vout->crop_bounds = g_fb_setting[i].crop_bounds;
- + vout->disp_fmt = g_fb_setting[i].disp_fmt;
- + vout->disp_support_csc =
- + g_fb_setting[i].disp_support_csc;
- + vout->disp_support_windows =
- + g_fb_setting[i].disp_support_windows;
- + found = true;
- + break;
- + }
- + }
- + }
- +
- + if (!found) {
- + v4l2_err(vout->vfd->v4l2_dev, "can not find output\n");
- + return -EINVAL;
- + }
- + strlcpy(vout->vfd->name, fbi->fix.id, sizeof(vout->vfd->name));
- +
- + memset(&vout->task, 0, sizeof(struct ipu_task));
- +
- + vout->task.input.width = DEF_INPUT_WIDTH;
- + vout->task.input.height = DEF_INPUT_HEIGHT;
- + vout->task.input.crop.pos.x = 0;
- + vout->task.input.crop.pos.y = 0;
- + vout->task.input.crop.w = DEF_INPUT_WIDTH;
- + vout->task.input.crop.h = DEF_INPUT_HEIGHT;
- +
- + vout->task.output.width = vout->crop_bounds.width;
- + vout->task.output.height = vout->crop_bounds.height;
- + vout->task.output.crop.pos.x = 0;
- + vout->task.output.crop.pos.y = 0;
- + vout->task.output.crop.w = vout->crop_bounds.width;
- + vout->task.output.crop.h = vout->crop_bounds.height;
- + if (colorspaceofpixel(vout->disp_fmt) == YUV_CS)
- + vout->task.output.format = IPU_PIX_FMT_UYVY;
- + else
- + vout->task.output.format = IPU_PIX_FMT_RGB565;
- +
- + return 0;
- +}
- +
- +static inline unsigned long get_jiffies(struct timeval *t)
- +{
- + struct timeval cur;
- +
- + if (t->tv_usec >= 1000000) {
- + t->tv_sec += t->tv_usec / 1000000;
- + t->tv_usec = t->tv_usec % 1000000;
- + }
- +
- + do_gettimeofday(&cur);
- + if ((t->tv_sec < cur.tv_sec)
- + || ((t->tv_sec == cur.tv_sec) && (t->tv_usec < cur.tv_usec)))
- + return jiffies;
- +
- + if (t->tv_usec < cur.tv_usec) {
- + cur.tv_sec = t->tv_sec - cur.tv_sec - 1;
- + cur.tv_usec = t->tv_usec + 1000000 - cur.tv_usec;
- + } else {
- + cur.tv_sec = t->tv_sec - cur.tv_sec;
- + cur.tv_usec = t->tv_usec - cur.tv_usec;
- + }
- +
- + return jiffies + timeval_to_jiffies(&cur);
- +}
- +
- +static bool deinterlace_3_field(struct mxc_vout_output *vout)
- +{
- + return (vout->task.input.deinterlace.enable &&
- + (vout->task.input.deinterlace.motion != HIGH_MOTION));
- +}
- +
- +static int set_field_fmt(struct mxc_vout_output *vout, enum v4l2_field field)
- +{
- + struct ipu_deinterlace *deinterlace = &vout->task.input.deinterlace;
- +
- + switch (field) {
- + /* Images are in progressive format, not interlaced */
- + case V4L2_FIELD_NONE:
- + case V4L2_FIELD_ANY:
- + deinterlace->enable = false;
- + deinterlace->field_fmt = 0;
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "Progressive frame.\n");
- + break;
- + case V4L2_FIELD_INTERLACED_TB:
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
- + "Enable deinterlace TB.\n");
- + deinterlace->enable = true;
- + deinterlace->field_fmt = IPU_DEINTERLACE_FIELD_TOP;
- + break;
- + case V4L2_FIELD_INTERLACED_BT:
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
- + "Enable deinterlace BT.\n");
- + deinterlace->enable = true;
- + deinterlace->field_fmt = IPU_DEINTERLACE_FIELD_BOTTOM;
- + break;
- + default:
- + v4l2_err(vout->vfd->v4l2_dev,
- + "field format:%d not supported yet!\n", field);
- + return -EINVAL;
- + }
- +
- + if (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format) {
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
- + "tiled fmt enable deinterlace.\n");
- + deinterlace->enable = true;
- + }
- +
- + if (deinterlace->enable && vdi_rate_double)
- + deinterlace->field_fmt |= IPU_DEINTERLACE_RATE_EN;
- +
- + return 0;
- +}
- +
- +static bool is_pp_bypass(struct mxc_vout_output *vout)
- +{
- + if ((IPU_PIX_FMT_TILED_NV12 == vout->task.input.format) ||
- + (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format))
- + return false;
- + if ((vout->task.input.width == vout->task.output.width) &&
- + (vout->task.input.height == vout->task.output.height) &&
- + (vout->task.input.crop.w == vout->task.output.crop.w) &&
- + (vout->task.input.crop.h == vout->task.output.crop.h) &&
- + (vout->task.output.rotate < IPU_ROTATE_HORIZ_FLIP) &&
- + !vout->task.input.deinterlace.enable) {
- + if (vout->disp_support_csc)
- + return true;
- + else if (!need_csc(vout->task.input.format, vout->disp_fmt))
- + return true;
- + /*
- + * input crop show to full output which can show based on
- + * xres_virtual/yres_virtual
- + */
- + } else if ((vout->task.input.crop.w == vout->task.output.crop.w) &&
- + (vout->task.output.crop.w == vout->task.output.width) &&
- + (vout->task.input.crop.h == vout->task.output.crop.h) &&
- + (vout->task.output.crop.h ==
- + vout->task.output.height) &&
- + (vout->task.output.rotate < IPU_ROTATE_HORIZ_FLIP) &&
- + !vout->task.input.deinterlace.enable) {
- + if (vout->disp_support_csc)
- + return true;
- + else if (!need_csc(vout->task.input.format, vout->disp_fmt))
- + return true;
- + }
- + return false;
- +}
- +
- +static void setup_buf_timer(struct mxc_vout_output *vout,
- + struct videobuf_buffer *vb)
- +{
- + ktime_t expiry_time, now;
- +
- + /* if timestamp is 0, then default to 30fps */
- + if ((vb->ts.tv_sec == 0) && (vb->ts.tv_usec == 0))
- + expiry_time = ktime_add_ns(vout->start_ktime,
- + NSEC_PER_FRAME_30FPS * vout->frame_count);
- + else
- + expiry_time = timeval_to_ktime(vb->ts);
- +
- + now = hrtimer_cb_get_time(&vout->timer);
- + if ((now.tv64 > expiry_time.tv64)) {
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
- + "warning: timer timeout already expired.\n");
- + expiry_time = now;
- + }
- +
- + hrtimer_start(&vout->timer, expiry_time, HRTIMER_MODE_ABS);
- +
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "timer handler next "
- + "schedule: %lldnsecs\n", expiry_time.tv64);
- +}
- +
- +static int show_buf(struct mxc_vout_output *vout, int idx,
- + struct ipu_pos *ipos)
- +{
- + struct fb_info *fbi = vout->fbi;
- + struct fb_var_screeninfo var;
- + int ret;
- + u32 fb_base = 0;
- +
- + memcpy(&var, &fbi->var, sizeof(var));
- +
- + if (vout->linear_bypass_pp || vout->tiled_bypass_pp) {
- + /*
- + * crack fb base
- + * NOTE: should not do other fb operation during v4l2
- + */
- + console_lock();
- + fb_base = fbi->fix.smem_start;
- + fbi->fix.smem_start = vout->task.output.paddr;
- + fbi->var.yoffset = ipos->y + 1;
- + var.xoffset = ipos->x;
- + var.yoffset = ipos->y;
- + var.vmode |= FB_VMODE_YWRAP;
- + ret = fb_pan_display(fbi, &var);
- + fbi->fix.smem_start = fb_base;
- + console_unlock();
- + } else {
- + console_lock();
- + var.yoffset = idx * fbi->var.yres;
- + var.vmode &= ~FB_VMODE_YWRAP;
- + ret = fb_pan_display(fbi, &var);
- + console_unlock();
- + }
- +
- + return ret;
- +}
- +
- +static void disp_work_func(struct work_struct *work)
- +{
- + struct mxc_vout_output *vout =
- + container_of(work, struct mxc_vout_output, disp_work);
- + struct videobuf_queue *q = &vout->vbq;
- + struct videobuf_buffer *vb, *vb_next = NULL;
- + unsigned long flags = 0;
- + struct ipu_pos ipos;
- + int ret = 0;
- + u32 in_fmt = 0;
- + u32 vdi_cnt = 0;
- + u32 vdi_frame;
- + u32 index = 0;
- + u32 ocrop_h = 0;
- + u32 o_height = 0;
- + u32 tiled_interlaced = 0;
- + bool tiled_fmt = false;
- +
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "disp work begin one frame\n");
- +
- + spin_lock_irqsave(q->irqlock, flags);
- +
- + if (list_empty(&vout->active_list)) {
- + v4l2_warn(vout->vfd->v4l2_dev,
- + "no entry in active_list, should not be here\n");
- + spin_unlock_irqrestore(q->irqlock, flags);
- + return;
- + }
- +
- + vb = list_first_entry(&vout->active_list,
- + struct videobuf_buffer, queue);
- + ret = set_field_fmt(vout, vb->field);
- + if (ret < 0) {
- + spin_unlock_irqrestore(q->irqlock, flags);
- + return;
- + }
- + if (deinterlace_3_field(vout)) {
- + if (list_is_singular(&vout->active_list)) {
- + if (list_empty(&vout->queue_list)) {
- + vout->timer_stop = true;
- + spin_unlock_irqrestore(q->irqlock, flags);
- + v4l2_warn(vout->vfd->v4l2_dev,
- + "no enough entry for 3 fields "
- + "deinterlacer\n");
- + return;
- + }
- +
- + /*
- + * We need to use the next vb even if it is
- + * not on the active list.
- + */
- + vb_next = list_first_entry(&vout->queue_list,
- + struct videobuf_buffer, queue);
- + } else
- + vb_next = list_first_entry(vout->active_list.next,
- + struct videobuf_buffer, queue);
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
- + "cur field_fmt:%d, next field_fmt:%d.\n",
- + vb->field, vb_next->field);
- + /* repeat the last field during field format changing */
- + if ((vb->field != vb_next->field) &&
- + (vb_next->field != V4L2_FIELD_NONE))
- + vb_next = vb;
- + }
- +
- + spin_unlock_irqrestore(q->irqlock, flags);
- +
- +vdi_frame_rate_double:
- + mutex_lock(&vout->task_lock);
- +
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
- + "v4l2 frame_cnt:%ld, vb_field:%d, fmt:%d\n",
- + vout->frame_count, vb->field,
- + vout->task.input.deinterlace.field_fmt);
- + if (vb->memory == V4L2_MEMORY_USERPTR)
- + vout->task.input.paddr = vb->baddr;
- + else
- + vout->task.input.paddr = videobuf_to_dma_contig(vb);
- +
- + if (vout->task.input.deinterlace.field_fmt & IPU_DEINTERLACE_RATE_EN)
- + index = vout->vdi_frame_cnt % FB_BUFS;
- + else
- + index = vout->frame_count % FB_BUFS;
- + if (vout->linear_bypass_pp) {
- + vout->task.output.paddr = vout->task.input.paddr;
- + ipos.x = vout->task.input.crop.pos.x;
- + ipos.y = vout->task.input.crop.pos.y;
- + } else {
- + if (deinterlace_3_field(vout)) {
- + if (vb->memory == V4L2_MEMORY_USERPTR)
- + vout->task.input.paddr_n = vb_next->baddr;
- + else
- + vout->task.input.paddr_n =
- + videobuf_to_dma_contig(vb_next);
- + }
- + vout->task.output.paddr = vout->disp_bufs[index];
- + if (vout->vdoa_1080p) {
- + o_height = vout->task.output.height;
- + ocrop_h = vout->task.output.crop.h;
- + vout->task.output.height = FRAME_HEIGHT_1080P;
- + vout->task.output.crop.h = FRAME_HEIGHT_1080P;
- + }
- + tiled_fmt =
- + (IPU_PIX_FMT_TILED_NV12 == vout->task.input.format) ||
- + (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format);
- + if (vout->tiled_bypass_pp) {
- + ipos.x = vout->task.input.crop.pos.x;
- + ipos.y = vout->task.input.crop.pos.y;
- + } else if (tiled_fmt) {
- + vout->vdoa_task.input.paddr = vout->task.input.paddr;
- + if (deinterlace_3_field(vout))
- + vout->vdoa_task.input.paddr_n =
- + vout->task.input.paddr_n;
- + vout->vdoa_task.output.paddr = vout->vdoa_work.paddr;
- + ret = ipu_queue_task(&vout->vdoa_task);
- + if (ret < 0) {
- + mutex_unlock(&vout->task_lock);
- + goto err;
- + }
- + vout->task.input.paddr = vout->vdoa_task.output.paddr;
- + in_fmt = vout->task.input.format;
- + vout->task.input.format = vout->vdoa_task.output.format;
- + if (vout->task.input.deinterlace.enable) {
- + tiled_interlaced = 1;
- + vout->task.input.deinterlace.enable = 0;
- + }
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
- + "tiled queue task\n");
- + }
- + ret = ipu_queue_task(&vout->task);
- + if ((!vout->tiled_bypass_pp) && tiled_fmt)
- + vout->task.input.format = in_fmt;
- + if (tiled_interlaced)
- + vout->task.input.deinterlace.enable = 1;
- + if (ret < 0) {
- + mutex_unlock(&vout->task_lock);
- + goto err;
- + }
- + if (vout->vdoa_1080p) {
- + vout->task.output.crop.h = ocrop_h;
- + vout->task.output.height = o_height;
- + }
- + }
- +
- + mutex_unlock(&vout->task_lock);
- +
- + ret = show_buf(vout, index, &ipos);
- + if (ret < 0)
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
- + "show buf with ret %d\n", ret);
- +
- + if (vout->task.input.deinterlace.field_fmt & IPU_DEINTERLACE_RATE_EN) {
- + vdi_frame = vout->task.input.deinterlace.field_fmt
- + & IPU_DEINTERLACE_RATE_FRAME1;
- + if (vdi_frame)
- + vout->task.input.deinterlace.field_fmt &=
- + ~IPU_DEINTERLACE_RATE_FRAME1;
- + else
- + vout->task.input.deinterlace.field_fmt |=
- + IPU_DEINTERLACE_RATE_FRAME1;
- + vout->vdi_frame_cnt++;
- + vdi_cnt++;
- + if (vdi_cnt < IPU_DEINTERLACE_MAX_FRAME)
- + goto vdi_frame_rate_double;
- + }
- + spin_lock_irqsave(q->irqlock, flags);
- +
- + list_del(&vb->queue);
- +
- + /*
- + * The videobuf before the last one has been shown. Set
- + * VIDEOBUF_DONE state here to avoid tearing issue in ic bypass
- + * case, which makes sure a buffer being shown will not be
- + * dequeued to be overwritten. It also brings side-effect that
- + * the last 2 buffers can not be dequeued correctly, apps need
- + * to take care of it.
- + */
- + if (vout->pre2_vb) {
- + vout->pre2_vb->state = VIDEOBUF_DONE;
- + wake_up_interruptible(&vout->pre2_vb->done);
- + vout->pre2_vb = NULL;
- + }
- +
- + if (vout->linear_bypass_pp) {
- + vout->pre2_vb = vout->pre1_vb;
- + vout->pre1_vb = vb;
- + } else {
- + if (vout->pre1_vb) {
- + vout->pre1_vb->state = VIDEOBUF_DONE;
- + wake_up_interruptible(&vout->pre1_vb->done);
- + vout->pre1_vb = NULL;
- + }
- + vb->state = VIDEOBUF_DONE;
- + wake_up_interruptible(&vb->done);
- + }
- +
- + vout->frame_count++;
- +
- + /* pick next queue buf to setup timer */
- + if (list_empty(&vout->queue_list))
- + vout->timer_stop = true;
- + else {
- + vb = list_first_entry(&vout->queue_list,
- + struct videobuf_buffer, queue);
- + setup_buf_timer(vout, vb);
- + }
- +
- + spin_unlock_irqrestore(q->irqlock, flags);
- +
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "disp work finish one frame\n");
- +
- + return;
- +err:
- + v4l2_err(vout->vfd->v4l2_dev, "display work fail ret = %d\n", ret);
- + vout->timer_stop = true;
- + vb->state = VIDEOBUF_ERROR;
- + return;
- +}
- +
- +static enum hrtimer_restart mxc_vout_timer_handler(struct hrtimer *timer)
- +{
- + struct mxc_vout_output *vout = container_of(timer,
- + struct mxc_vout_output,
- + timer);
- + struct videobuf_queue *q = &vout->vbq;
- + struct videobuf_buffer *vb;
- + unsigned long flags = 0;
- +
- + spin_lock_irqsave(q->irqlock, flags);
- +
- + /*
- + * put first queued entry into active, if previous entry did not
- + * finish, setup current entry's timer again.
- + */
- + if (list_empty(&vout->queue_list)) {
- + spin_unlock_irqrestore(q->irqlock, flags);
- + return HRTIMER_NORESTART;
- + }
- +
- + /* move videobuf from queued list to active list */
- + vb = list_first_entry(&vout->queue_list,
- + struct videobuf_buffer, queue);
- + list_del(&vb->queue);
- + list_add_tail(&vb->queue, &vout->active_list);
- +
- + if (queue_work(vout->v4l_wq, &vout->disp_work) == 0) {
- + v4l2_warn(vout->vfd->v4l2_dev,
- + "disp work was in queue already, queue buf again next time\n");
- + list_del(&vb->queue);
- + list_add(&vb->queue, &vout->queue_list);
- + spin_unlock_irqrestore(q->irqlock, flags);
- + return HRTIMER_NORESTART;
- + }
- +
- + vb->state = VIDEOBUF_ACTIVE;
- +
- + spin_unlock_irqrestore(q->irqlock, flags);
- +
- + return HRTIMER_NORESTART;
- +}
- +
- +/* Video buffer call backs */
- +
- +/*
- + * Buffer setup function is called by videobuf layer when REQBUF ioctl is
- + * called. This is used to setup buffers and return size and count of
- + * buffers allocated. After the call to this buffer, videobuf layer will
- + * setup buffer queue depending on the size and count of buffers
- + */
- +static int mxc_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
- + unsigned int *size)
- +{
- + struct mxc_vout_output *vout = q->priv_data;
- + unsigned int frame_size;
- +
- + if (!vout)
- + return -EINVAL;
- +
- + if (V4L2_BUF_TYPE_VIDEO_OUTPUT != q->type)
- + return -EINVAL;
- +
- + frame_size = get_frame_size(vout);
- + *size = PAGE_ALIGN(frame_size);
- +
- + return 0;
- +}
- +
- +/*
- + * This function will be called when VIDIOC_QBUF ioctl is called.
- + * It prepare buffers before give out for the display. This function
- + * converts user space virtual address into physical address if userptr memory
- + * exchange mechanism is used.
- + */
- +static int mxc_vout_buffer_prepare(struct videobuf_queue *q,
- + struct videobuf_buffer *vb,
- + enum v4l2_field field)
- +{
- + vb->state = VIDEOBUF_PREPARED;
- + return 0;
- +}
- +
- +/*
- + * Buffer queue funtion will be called from the videobuf layer when _QBUF
- + * ioctl is called. It is used to enqueue buffer, which is ready to be
- + * displayed.
- + * This function is protected by q->irqlock.
- + */
- +static void mxc_vout_buffer_queue(struct videobuf_queue *q,
- + struct videobuf_buffer *vb)
- +{
- + struct mxc_vout_output *vout = q->priv_data;
- + struct videobuf_buffer *active_vb;
- +
- + list_add_tail(&vb->queue, &vout->queue_list);
- + vb->state = VIDEOBUF_QUEUED;
- +
- + if (vout->timer_stop) {
- + if (deinterlace_3_field(vout) &&
- + !list_empty(&vout->active_list)) {
- + active_vb = list_first_entry(&vout->active_list,
- + struct videobuf_buffer, queue);
- + setup_buf_timer(vout, active_vb);
- + } else {
- + setup_buf_timer(vout, vb);
- + }
- + vout->timer_stop = false;
- + }
- +}
- +
- +/*
- + * Buffer release function is called from videobuf layer to release buffer
- + * which are already allocated
- + */
- +static void mxc_vout_buffer_release(struct videobuf_queue *q,
- + struct videobuf_buffer *vb)
- +{
- + vb->state = VIDEOBUF_NEEDS_INIT;
- +}
- +
- +static int mxc_vout_mmap(struct file *file, struct vm_area_struct *vma)
- +{
- + int ret;
- + struct mxc_vout_output *vout = file->private_data;
- +
- + if (!vout)
- + return -ENODEV;
- +
- + ret = videobuf_mmap_mapper(&vout->vbq, vma);
- + if (ret < 0)
- + v4l2_err(vout->vfd->v4l2_dev,
- + "offset invalid [offset=0x%lx]\n",
- + (vma->vm_pgoff << PAGE_SHIFT));
- +
- + return ret;
- +}
- +
- +static int mxc_vout_release(struct file *file)
- +{
- + unsigned int ret = 0;
- + struct videobuf_queue *q;
- + struct mxc_vout_output *vout = file->private_data;
- +
- + if (!vout)
- + return 0;
- +
- + if (--vout->open_cnt == 0) {
- + q = &vout->vbq;
- + if (q->streaming)
- + mxc_vidioc_streamoff(file, vout, vout->type);
- + else {
- + release_disp_output(vout);
- + videobuf_queue_cancel(q);
- + }
- + destroy_workqueue(vout->v4l_wq);
- + ret = videobuf_mmap_free(q);
- + }
- +
- + return ret;
- +}
- +
- +static int mxc_vout_open(struct file *file)
- +{
- + struct mxc_vout_output *vout = NULL;
- + int ret = 0;
- +
- + vout = video_drvdata(file);
- +
- + if (vout == NULL)
- + return -ENODEV;
- +
- + if (vout->open_cnt++ == 0) {
- + vout->ctrl_rotate = 0;
- + vout->ctrl_vflip = 0;
- + vout->ctrl_hflip = 0;
- + update_display_setting();
- + ret = update_setting_from_fbi(vout, vout->fbi);
- + if (ret < 0)
- + goto err;
- +
- + vout->v4l_wq = create_singlethread_workqueue("v4l2q");
- + if (!vout->v4l_wq) {
- + v4l2_err(vout->vfd->v4l2_dev,
- + "Could not create work queue\n");
- + ret = -ENOMEM;
- + goto err;
- + }
- +
- + INIT_WORK(&vout->disp_work, disp_work_func);
- +
- + INIT_LIST_HEAD(&vout->queue_list);
- + INIT_LIST_HEAD(&vout->active_list);
- +
- + vout->fmt_init = false;
- + vout->frame_count = 0;
- + vout->vdi_frame_cnt = 0;
- +
- + vout->win_pos.x = 0;
- + vout->win_pos.y = 0;
- + vout->release = true;
- + }
- +
- + file->private_data = vout;
- +
- +err:
- + return ret;
- +}
- +
- +/*
- + * V4L2 ioctls
- + */
- +static int mxc_vidioc_querycap(struct file *file, void *fh,
- + struct v4l2_capability *cap)
- +{
- + struct mxc_vout_output *vout = fh;
- +
- + strlcpy(cap->driver, VOUT_NAME, sizeof(cap->driver));
- + strlcpy(cap->card, vout->vfd->name, sizeof(cap->card));
- + cap->bus_info[0] = '\0';
- + cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT;
- +
- + return 0;
- +}
- +
- +static int mxc_vidioc_enum_fmt_vid_out(struct file *file, void *fh,
- + struct v4l2_fmtdesc *fmt)
- +{
- + if (fmt->index >= NUM_MXC_VOUT_FORMATS)
- + return -EINVAL;
- +
- + strlcpy(fmt->description, mxc_formats[fmt->index].description,
- + sizeof(fmt->description));
- + fmt->pixelformat = mxc_formats[fmt->index].pixelformat;
- +
- + return 0;
- +}
- +
- +static int mxc_vidioc_g_fmt_vid_out(struct file *file, void *fh,
- + struct v4l2_format *f)
- +{
- + struct mxc_vout_output *vout = fh;
- + struct v4l2_rect rect;
- +
- + f->fmt.pix.width = vout->task.input.width;
- + f->fmt.pix.height = vout->task.input.height;
- + f->fmt.pix.pixelformat = vout->task.input.format;
- + f->fmt.pix.sizeimage = get_frame_size(vout);
- +
- + if (f->fmt.pix.priv) {
- + rect.left = vout->task.input.crop.pos.x;
- + rect.top = vout->task.input.crop.pos.y;
- + rect.width = vout->task.input.crop.w;
- + rect.height = vout->task.input.crop.h;
- + if (copy_to_user((void __user *)f->fmt.pix.priv,
- + &rect, sizeof(rect)))
- + return -EFAULT;
- + }
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
- + "frame_size:0x%x, pix_fmt:0x%x\n",
- + f->fmt.pix.sizeimage,
- + vout->task.input.format);
- +
- + return 0;
- +}
- +
- +static inline int ipu_try_task(struct mxc_vout_output *vout)
- +{
- + int ret;
- + struct ipu_task *task = &vout->task;
- +
- +again:
- + ret = ipu_check_task(task);
- + if (ret != IPU_CHECK_OK) {
- + if (ret > IPU_CHECK_ERR_MIN) {
- + if (ret == IPU_CHECK_ERR_SPLIT_INPUTW_OVER ||
- + ret == IPU_CHECK_ERR_W_DOWNSIZE_OVER) {
- + task->input.crop.w -= 8;
- + goto again;
- + }
- + if (ret == IPU_CHECK_ERR_SPLIT_INPUTH_OVER ||
- + ret == IPU_CHECK_ERR_H_DOWNSIZE_OVER) {
- + task->input.crop.h -= 8;
- + goto again;
- + }
- + if (ret == IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER) {
- + if (vout->disp_support_windows) {
- + task->output.width -= 8;
- + task->output.crop.w =
- + task->output.width;
- + } else
- + task->output.crop.w -= 8;
- + goto again;
- + }
- + if (ret == IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER) {
- + if (vout->disp_support_windows) {
- + task->output.height -= 8;
- + task->output.crop.h =
- + task->output.height;
- + } else
- + task->output.crop.h -= 8;
- + goto again;
- + }
- + ret = -EINVAL;
- + }
- + } else
- + ret = 0;
- +
- + return ret;
- +}
- +
- +static inline int vdoaipu_try_task(struct mxc_vout_output *vout)
- +{
- + int ret;
- + int is_1080p_stream;
- + size_t size;
- + struct ipu_task *ipu_task = &vout->task;
- + struct ipu_crop *icrop = &ipu_task->input.crop;
- + struct ipu_task *vdoa_task = &vout->vdoa_task;
- + u32 deinterlace = 0;
- + u32 in_fmt;
- +
- + if (vout->task.input.deinterlace.enable)
- + deinterlace = 1;
- +
- + memset(vdoa_task, 0, sizeof(*vdoa_task));
- + vdoa_task->output.format = IPU_PIX_FMT_NV12;
- + memcpy(&vdoa_task->input, &ipu_task->input,
- + sizeof(ipu_task->input));
- + if ((icrop->w % IPU_PIX_FMT_TILED_NV12_MBALIGN) ||
- + (icrop->h % IPU_PIX_FMT_TILED_NV12_MBALIGN)) {
- + vdoa_task->input.crop.w =
- + ALIGN(icrop->w, IPU_PIX_FMT_TILED_NV12_MBALIGN);
- + vdoa_task->input.crop.h =
- + ALIGN(icrop->h, IPU_PIX_FMT_TILED_NV12_MBALIGN);
- + }
- + vdoa_task->output.width = vdoa_task->input.crop.w;
- + vdoa_task->output.height = vdoa_task->input.crop.h;
- + vdoa_task->output.crop.w = vdoa_task->input.crop.w;
- + vdoa_task->output.crop.h = vdoa_task->input.crop.h;
- +
- + size = PAGE_ALIGN(vdoa_task->input.crop.w *
- + vdoa_task->input.crop.h *
- + fmt_to_bpp(vdoa_task->output.format)/8);
- + if (size > vout->vdoa_work.size) {
- + if (vout->vdoa_work.vaddr)
- + free_dma_buf(vout, &vout->vdoa_work);
- + vout->vdoa_work.size = size;
- + ret = alloc_dma_buf(vout, &vout->vdoa_work);
- + if (ret < 0)
- + return ret;
- + }
- + ret = ipu_check_task(vdoa_task);
- + if (ret != IPU_CHECK_OK)
- + return -EINVAL;
- +
- + is_1080p_stream = CHECK_TILED_1080P_STREAM(vout);
- + if (is_1080p_stream)
- + ipu_task->input.crop.h = VALID_HEIGHT_1080P;
- + in_fmt = ipu_task->input.format;
- + ipu_task->input.format = vdoa_task->output.format;
- + ipu_task->input.height = vdoa_task->output.height;
- + ipu_task->input.width = vdoa_task->output.width;
- + if (deinterlace)
- + ipu_task->input.deinterlace.enable = 0;
- + ret = ipu_try_task(vout);
- + if (deinterlace)
- + ipu_task->input.deinterlace.enable = 1;
- + ipu_task->input.format = in_fmt;
- +
- + return ret;
- +}
- +
- +static int mxc_vout_try_task(struct mxc_vout_output *vout)
- +{
- + int ret = 0;
- + struct ipu_output *output = &vout->task.output;
- + struct ipu_input *input = &vout->task.input;
- + struct ipu_crop *crop = &input->crop;
- + u32 o_height = 0;
- + u32 ocrop_h = 0;
- + bool tiled_fmt = false;
- + bool tiled_need_pp = false;
- +
- + vout->vdoa_1080p = CHECK_TILED_1080P_DISPLAY(vout);
- + if (vout->vdoa_1080p) {
- + input->crop.h = FRAME_HEIGHT_1080P;
- + o_height = output->height;
- + ocrop_h = output->crop.h;
- + output->height = FRAME_HEIGHT_1080P;
- + output->crop.h = FRAME_HEIGHT_1080P;
- + }
- +
- + if ((IPU_PIX_FMT_TILED_NV12 == input->format) ||
- + (IPU_PIX_FMT_TILED_NV12F == input->format)) {
- + if ((input->width % IPU_PIX_FMT_TILED_NV12_MBALIGN) ||
- + (input->height % IPU_PIX_FMT_TILED_NV12_MBALIGN) ||
- + (crop->pos.x % IPU_PIX_FMT_TILED_NV12_MBALIGN) ||
- + (crop->pos.y % IPU_PIX_FMT_TILED_NV12_MBALIGN)) {
- + v4l2_err(vout->vfd->v4l2_dev,
- + "ERR: tiled fmt needs 16 pixel align.\n");
- + return -EINVAL;
- + }
- + if ((crop->w % IPU_PIX_FMT_TILED_NV12_MBALIGN) ||
- + (crop->h % IPU_PIX_FMT_TILED_NV12_MBALIGN))
- + tiled_need_pp = true;
- + } else {
- + crop->w -= crop->w % 8;
- + crop->h -= crop->h % 8;
- + }
- + /* assume task.output already set by S_CROP */
- + vout->linear_bypass_pp = is_pp_bypass(vout);
- + if (vout->linear_bypass_pp) {
- + v4l2_info(vout->vfd->v4l2_dev, "Bypass IC.\n");
- + output->format = input->format;
- + } else {
- + /* if need CSC, choose IPU-DP or IPU_IC do it */
- + if (vout->disp_support_csc) {
- + if (colorspaceofpixel(input->format) == YUV_CS)
- + output->format = IPU_PIX_FMT_UYVY;
- + else
- + output->format = IPU_PIX_FMT_RGB565;
- + } else {
- + if (colorspaceofpixel(vout->disp_fmt) == YUV_CS)
- + output->format = IPU_PIX_FMT_UYVY;
- + else
- + output->format = IPU_PIX_FMT_RGB565;
- + }
- +
- + vout->tiled_bypass_pp = false;
- + if ((IPU_PIX_FMT_TILED_NV12 == input->format) ||
- + (IPU_PIX_FMT_TILED_NV12F == input->format)) {
- + /* check resize/rotate/flip, or csc task */
- + if (!(tiled_need_pp ||
- + (IPU_ROTATE_NONE != output->rotate) ||
- + (input->crop.w != output->crop.w) ||
- + (input->crop.h != output->crop.h) ||
- + (!vout->disp_support_csc &&
- + (colorspaceofpixel(vout->disp_fmt) == RGB_CS)))
- + ) {
- + /* IC bypass */
- + output->format = IPU_PIX_FMT_NV12;
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
- + "tiled bypass pp\n");
- + vout->tiled_bypass_pp = true;
- + }
- + tiled_fmt = true;
- + }
- +
- + if ((!vout->tiled_bypass_pp) && tiled_fmt)
- + ret = vdoaipu_try_task(vout);
- + else
- + ret = ipu_try_task(vout);
- + }
- +
- + if (vout->vdoa_1080p) {
- + output->height = o_height;
- + output->crop.h = ocrop_h;
- + }
- +
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
- + "icrop.w:%u, icrop.h:%u, iw:%u, ih:%u,"
- + "ocrop.w:%u, ocrop.h:%u, ow:%u, oh:%u\n",
- + input->crop.w, input->crop.h,
- + input->width, input->height,
- + output->crop.w, output->crop.h,
- + output->width, output->height);
- + return ret;
- +}
- +
- +static int mxc_vout_try_format(struct mxc_vout_output *vout,
- + struct v4l2_format *f)
- +{
- + int ret = 0;
- + struct v4l2_rect rect;
- +
- + if ((f->fmt.pix.field != V4L2_FIELD_NONE) &&
- + (IPU_PIX_FMT_TILED_NV12 == vout->task.input.format)) {
- + v4l2_err(vout->vfd->v4l2_dev,
- + "progressive tiled fmt should used V4L2_FIELD_NONE!\n");
- + return -EINVAL;
- + }
- +
- + if (f->fmt.pix.priv && copy_from_user(&rect,
- + (void __user *)f->fmt.pix.priv, sizeof(rect)))
- + return -EFAULT;
- +
- + vout->task.input.width = f->fmt.pix.width;
- + vout->task.input.height = f->fmt.pix.height;
- + vout->task.input.format = f->fmt.pix.pixelformat;
- +
- + ret = set_field_fmt(vout, f->fmt.pix.field);
- + if (ret < 0)
- + return ret;
- +
- + if (f->fmt.pix.priv) {
- + vout->task.input.crop.pos.x = rect.left;
- + vout->task.input.crop.pos.y = rect.top;
- + vout->task.input.crop.w = rect.width;
- + vout->task.input.crop.h = rect.height;
- + } else {
- + vout->task.input.crop.pos.x = 0;
- + vout->task.input.crop.pos.y = 0;
- + vout->task.input.crop.w = f->fmt.pix.width;
- + vout->task.input.crop.h = f->fmt.pix.height;
- + }
- + memcpy(&vout->in_rect, &vout->task.input.crop, sizeof(vout->in_rect));
- +
- + ret = mxc_vout_try_task(vout);
- + if (!ret) {
- + if (f->fmt.pix.priv) {
- + rect.width = vout->task.input.crop.w;
- + rect.height = vout->task.input.crop.h;
- + if (copy_to_user((void __user *)f->fmt.pix.priv,
- + &rect, sizeof(rect)))
- + ret = -EFAULT;
- + } else {
- + f->fmt.pix.width = vout->task.input.crop.w;
- + f->fmt.pix.height = vout->task.input.crop.h;
- + }
- + }
- +
- + return ret;
- +}
- +
- +static bool mxc_vout_need_fb_reconfig(struct mxc_vout_output *vout,
- + struct mxc_vout_output *pre_vout)
- +{
- + if (!vout->vbq.streaming)
- + return false;
- +
- + if (vout->tiled_bypass_pp)
- + return true;
- +
- + if (vout->linear_bypass_pp != pre_vout->linear_bypass_pp)
- + return true;
- +
- + /* cropped output resolution or format are changed */
- + if (vout->task.output.format != pre_vout->task.output.format ||
- + vout->task.output.crop.w != pre_vout->task.output.crop.w ||
- + vout->task.output.crop.h != pre_vout->task.output.crop.h)
- + return true;
- +
- + /* overlay: window position or resolution are changed */
- + if (vout->disp_support_windows &&
- + (vout->win_pos.x != pre_vout->win_pos.x ||
- + vout->win_pos.y != pre_vout->win_pos.y ||
- + vout->task.output.width != pre_vout->task.output.width ||
- + vout->task.output.height != pre_vout->task.output.height))
- + return true;
- +
- + /* background: cropped position is changed */
- + if (!vout->disp_support_windows &&
- + (vout->task.output.crop.pos.x !=
- + pre_vout->task.output.crop.pos.x ||
- + vout->task.output.crop.pos.y !=
- + pre_vout->task.output.crop.pos.y))
- + return true;
- +
- + return false;
- +}
- +
- +static int mxc_vidioc_s_fmt_vid_out(struct file *file, void *fh,
- + struct v4l2_format *f)
- +{
- + struct mxc_vout_output *vout = fh;
- + int ret = 0;
- +
- + if (vout->vbq.streaming)
- + return -EBUSY;
- +
- + mutex_lock(&vout->task_lock);
- + ret = mxc_vout_try_format(vout, f);
- + if (ret >= 0)
- + vout->fmt_init = true;
- + mutex_unlock(&vout->task_lock);
- +
- + return ret;
- +}
- +
- +static int mxc_vidioc_cropcap(struct file *file, void *fh,
- + struct v4l2_cropcap *cropcap)
- +{
- + struct mxc_vout_output *vout = fh;
- +
- + if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
- + return -EINVAL;
- +
- + cropcap->bounds = vout->crop_bounds;
- + cropcap->defrect = vout->crop_bounds;
- +
- + return 0;
- +}
- +
- +static int mxc_vidioc_g_crop(struct file *file, void *fh,
- + struct v4l2_crop *crop)
- +{
- + struct mxc_vout_output *vout = fh;
- +
- + if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
- + return -EINVAL;
- +
- + if (vout->disp_support_windows) {
- + crop->c.left = vout->win_pos.x;
- + crop->c.top = vout->win_pos.y;
- + crop->c.width = vout->task.output.width;
- + crop->c.height = vout->task.output.height;
- + } else {
- + if (vout->task.output.crop.w && vout->task.output.crop.h) {
- + crop->c.left = vout->task.output.crop.pos.x;
- + crop->c.top = vout->task.output.crop.pos.y;
- + crop->c.width = vout->task.output.crop.w;
- + crop->c.height = vout->task.output.crop.h;
- + } else {
- + crop->c.left = 0;
- + crop->c.top = 0;
- + crop->c.width = vout->task.output.width;
- + crop->c.height = vout->task.output.height;
- + }
- + }
- +
- + return 0;
- +}
- +
- +static int mxc_vidioc_s_crop(struct file *file, void *fh,
- + const struct v4l2_crop *crop)
- +{
- + struct mxc_vout_output *vout = fh, *pre_vout;
- + struct v4l2_rect *b = &vout->crop_bounds;
- + struct v4l2_crop fix_up_crop;
- + int ret = 0;
- +
- + memcpy(&fix_up_crop, crop, sizeof(*crop));
- +
- + if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
- + return -EINVAL;
- +
- + if (crop->c.width < 0 || crop->c.height < 0)
- + return -EINVAL;
- +
- + if (crop->c.width == 0)
- + fix_up_crop.c.width = b->width - b->left;
- + if (crop->c.height == 0)
- + fix_up_crop.c.height = b->height - b->top;
- +
- + if (crop->c.top < b->top)
- + fix_up_crop.c.top = b->top;
- + if (crop->c.top >= b->top + b->height)
- + fix_up_crop.c.top = b->top + b->height - 1;
- + if (crop->c.height > b->top - crop->c.top + b->height)
- + fix_up_crop.c.height =
- + b->top - fix_up_crop.c.top + b->height;
- +
- + if (crop->c.left < b->left)
- + fix_up_crop.c.left = b->left;
- + if (crop->c.left >= b->left + b->width)
- + fix_up_crop.c.left = b->left + b->width - 1;
- + if (crop->c.width > b->left - crop->c.left + b->width)
- + fix_up_crop.c.width =
- + b->left - fix_up_crop.c.left + b->width;
- +
- + /* stride line limitation */
- + fix_up_crop.c.height -= fix_up_crop.c.height % 8;
- + fix_up_crop.c.width -= fix_up_crop.c.width % 8;
- + if ((fix_up_crop.c.width <= 0) || (fix_up_crop.c.height <= 0) ||
- + ((fix_up_crop.c.left + fix_up_crop.c.width) >
- + (b->left + b->width)) ||
- + ((fix_up_crop.c.top + fix_up_crop.c.height) >
- + (b->top + b->height))) {
- + v4l2_err(vout->vfd->v4l2_dev, "s_crop err: %d, %d, %d, %d",
- + fix_up_crop.c.left, fix_up_crop.c.top,
- + fix_up_crop.c.width, fix_up_crop.c.height);
- + return -EINVAL;
- + }
- +
- + /* the same setting, return */
- + if (vout->disp_support_windows) {
- + if ((vout->win_pos.x == fix_up_crop.c.left) &&
- + (vout->win_pos.y == fix_up_crop.c.top) &&
- + (vout->task.output.crop.w == fix_up_crop.c.width) &&
- + (vout->task.output.crop.h == fix_up_crop.c.height))
- + return 0;
- + } else {
- + if ((vout->task.output.crop.pos.x == fix_up_crop.c.left) &&
- + (vout->task.output.crop.pos.y == fix_up_crop.c.top) &&
- + (vout->task.output.crop.w == fix_up_crop.c.width) &&
- + (vout->task.output.crop.h == fix_up_crop.c.height))
- + return 0;
- + }
- +
- + pre_vout = vmalloc(sizeof(*pre_vout));
- + if (!pre_vout)
- + return -ENOMEM;
- +
- + /* wait current work finish */
- + if (vout->vbq.streaming)
- + flush_workqueue(vout->v4l_wq);
- +
- + mutex_lock(&vout->task_lock);
- +
- + memcpy(pre_vout, vout, sizeof(*vout));
- +
- + if (vout->disp_support_windows) {
- + vout->task.output.crop.pos.x = 0;
- + vout->task.output.crop.pos.y = 0;
- + vout->win_pos.x = fix_up_crop.c.left;
- + vout->win_pos.y = fix_up_crop.c.top;
- + vout->task.output.width = fix_up_crop.c.width;
- + vout->task.output.height = fix_up_crop.c.height;
- + } else {
- + vout->task.output.crop.pos.x = fix_up_crop.c.left;
- + vout->task.output.crop.pos.y = fix_up_crop.c.top;
- + }
- +
- + vout->task.output.crop.w = fix_up_crop.c.width;
- + vout->task.output.crop.h = fix_up_crop.c.height;
- +
- + /*
- + * must S_CROP before S_FMT, for fist time S_CROP, will not check
- + * ipu task, it will check in S_FMT, after S_FMT, S_CROP should
- + * check ipu task too.
- + */
- + if (vout->fmt_init) {
- + memcpy(&vout->task.input.crop, &vout->in_rect,
- + sizeof(vout->in_rect));
- + ret = mxc_vout_try_task(vout);
- + if (ret < 0) {
- + v4l2_err(vout->vfd->v4l2_dev,
- + "vout check task failed\n");
- + memcpy(vout, pre_vout, sizeof(*vout));
- + goto done;
- + }
- +
- + if (mxc_vout_need_fb_reconfig(vout, pre_vout)) {
- + ret = config_disp_output(vout);
- + if (ret < 0)
- + v4l2_err(vout->vfd->v4l2_dev,
- + "Config display output failed\n");
- + }
- + }
- +
- +done:
- + vfree(pre_vout);
- + mutex_unlock(&vout->task_lock);
- +
- + return ret;
- +}
- +
- +static int mxc_vidioc_queryctrl(struct file *file, void *fh,
- + struct v4l2_queryctrl *ctrl)
- +{
- + int ret = 0;
- +
- + switch (ctrl->id) {
- + case V4L2_CID_ROTATE:
- + ret = v4l2_ctrl_query_fill(ctrl, 0, 270, 90, 0);
- + break;
- + case V4L2_CID_VFLIP:
- + ret = v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0);
- + break;
- + case V4L2_CID_HFLIP:
- + ret = v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0);
- + break;
- + case V4L2_CID_MXC_MOTION:
- + ret = v4l2_ctrl_query_fill(ctrl, 0, 2, 1, 0);
- + break;
- + default:
- + ctrl->name[0] = '\0';
- + ret = -EINVAL;
- + }
- + return ret;
- +}
- +
- +static int mxc_vidioc_g_ctrl(struct file *file, void *fh,
- + struct v4l2_control *ctrl)
- +{
- + int ret = 0;
- + struct mxc_vout_output *vout = fh;
- +
- + switch (ctrl->id) {
- + case V4L2_CID_ROTATE:
- + ctrl->value = vout->ctrl_rotate;
- + break;
- + case V4L2_CID_VFLIP:
- + ctrl->value = vout->ctrl_vflip;
- + break;
- + case V4L2_CID_HFLIP:
- + ctrl->value = vout->ctrl_hflip;
- + break;
- + case V4L2_CID_MXC_MOTION:
- + if (vout->task.input.deinterlace.enable)
- + ctrl->value = vout->task.input.deinterlace.motion;
- + else
- + ctrl->value = 0;
- + break;
- + default:
- + ret = -EINVAL;
- + }
- + return ret;
- +}
- +
- +static void setup_task_rotation(struct mxc_vout_output *vout)
- +{
- + if (vout->ctrl_rotate == 0) {
- + if (vout->ctrl_vflip && vout->ctrl_hflip)
- + vout->task.output.rotate = IPU_ROTATE_180;
- + else if (vout->ctrl_vflip)
- + vout->task.output.rotate = IPU_ROTATE_VERT_FLIP;
- + else if (vout->ctrl_hflip)
- + vout->task.output.rotate = IPU_ROTATE_HORIZ_FLIP;
- + else
- + vout->task.output.rotate = IPU_ROTATE_NONE;
- + } else if (vout->ctrl_rotate == 90) {
- + if (vout->ctrl_vflip && vout->ctrl_hflip)
- + vout->task.output.rotate = IPU_ROTATE_90_LEFT;
- + else if (vout->ctrl_vflip)
- + vout->task.output.rotate = IPU_ROTATE_90_RIGHT_VFLIP;
- + else if (vout->ctrl_hflip)
- + vout->task.output.rotate = IPU_ROTATE_90_RIGHT_HFLIP;
- + else
- + vout->task.output.rotate = IPU_ROTATE_90_RIGHT;
- + } else if (vout->ctrl_rotate == 180) {
- + if (vout->ctrl_vflip && vout->ctrl_hflip)
- + vout->task.output.rotate = IPU_ROTATE_NONE;
- + else if (vout->ctrl_vflip)
- + vout->task.output.rotate = IPU_ROTATE_HORIZ_FLIP;
- + else if (vout->ctrl_hflip)
- + vout->task.output.rotate = IPU_ROTATE_VERT_FLIP;
- + else
- + vout->task.output.rotate = IPU_ROTATE_180;
- + } else if (vout->ctrl_rotate == 270) {
- + if (vout->ctrl_vflip && vout->ctrl_hflip)
- + vout->task.output.rotate = IPU_ROTATE_90_RIGHT;
- + else if (vout->ctrl_vflip)
- + vout->task.output.rotate = IPU_ROTATE_90_RIGHT_HFLIP;
- + else if (vout->ctrl_hflip)
- + vout->task.output.rotate = IPU_ROTATE_90_RIGHT_VFLIP;
- + else
- + vout->task.output.rotate = IPU_ROTATE_90_LEFT;
- + }
- +}
- +
- +static int mxc_vidioc_s_ctrl(struct file *file, void *fh,
- + struct v4l2_control *ctrl)
- +{
- + int ret = 0;
- + struct mxc_vout_output *vout = fh, *pre_vout;
- +
- + pre_vout = vmalloc(sizeof(*pre_vout));
- + if (!pre_vout)
- + return -ENOMEM;
- +
- + /* wait current work finish */
- + if (vout->vbq.streaming)
- + flush_workqueue(vout->v4l_wq);
- +
- + mutex_lock(&vout->task_lock);
- +
- + memcpy(pre_vout, vout, sizeof(*vout));
- +
- + switch (ctrl->id) {
- + case V4L2_CID_ROTATE:
- + {
- + vout->ctrl_rotate = (ctrl->value/90) * 90;
- + if (vout->ctrl_rotate > 270)
- + vout->ctrl_rotate = 270;
- + setup_task_rotation(vout);
- + break;
- + }
- + case V4L2_CID_VFLIP:
- + {
- + vout->ctrl_vflip = ctrl->value;
- + setup_task_rotation(vout);
- + break;
- + }
- + case V4L2_CID_HFLIP:
- + {
- + vout->ctrl_hflip = ctrl->value;
- + setup_task_rotation(vout);
- + break;
- + }
- + case V4L2_CID_MXC_MOTION:
- + {
- + vout->task.input.deinterlace.motion = ctrl->value;
- + break;
- + }
- + default:
- + ret = -EINVAL;
- + goto done;
- + }
- +
- + if (vout->fmt_init) {
- + memcpy(&vout->task.input.crop, &vout->in_rect,
- + sizeof(vout->in_rect));
- + ret = mxc_vout_try_task(vout);
- + if (ret < 0) {
- + v4l2_err(vout->vfd->v4l2_dev,
- + "vout check task failed\n");
- + memcpy(vout, pre_vout, sizeof(*vout));
- + goto done;
- + }
- +
- + if (mxc_vout_need_fb_reconfig(vout, pre_vout)) {
- + ret = config_disp_output(vout);
- + if (ret < 0)
- + v4l2_err(vout->vfd->v4l2_dev,
- + "Config display output failed\n");
- + }
- + }
- +
- +done:
- + vfree(pre_vout);
- + mutex_unlock(&vout->task_lock);
- +
- + return ret;
- +}
- +
- +static int mxc_vidioc_reqbufs(struct file *file, void *fh,
- + struct v4l2_requestbuffers *req)
- +{
- + int ret = 0;
- + struct mxc_vout_output *vout = fh;
- + struct videobuf_queue *q = &vout->vbq;
- +
- + if (req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
- + return -EINVAL;
- +
- + /* should not be here after streaming, videobuf_reqbufs will control */
- + mutex_lock(&vout->task_lock);
- +
- + ret = videobuf_reqbufs(q, req);
- +
- + mutex_unlock(&vout->task_lock);
- + return ret;
- +}
- +
- +static int mxc_vidioc_querybuf(struct file *file, void *fh,
- + struct v4l2_buffer *b)
- +{
- + int ret;
- + struct mxc_vout_output *vout = fh;
- +
- + ret = videobuf_querybuf(&vout->vbq, b);
- + if (!ret) {
- + /* return physical address */
- + struct videobuf_buffer *vb = vout->vbq.bufs[b->index];
- + if (b->flags & V4L2_BUF_FLAG_MAPPED)
- + b->m.offset = videobuf_to_dma_contig(vb);
- + }
- +
- + return ret;
- +}
- +
- +static int mxc_vidioc_qbuf(struct file *file, void *fh,
- + struct v4l2_buffer *buffer)
- +{
- + struct mxc_vout_output *vout = fh;
- +
- + return videobuf_qbuf(&vout->vbq, buffer);
- +}
- +
- +static int mxc_vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
- +{
- + struct mxc_vout_output *vout = fh;
- +
- + if (!vout->vbq.streaming)
- + return -EINVAL;
- +
- + if (file->f_flags & O_NONBLOCK)
- + return videobuf_dqbuf(&vout->vbq, (struct v4l2_buffer *)b, 1);
- + else
- + return videobuf_dqbuf(&vout->vbq, (struct v4l2_buffer *)b, 0);
- +}
- +
- +static int set_window_position(struct mxc_vout_output *vout,
- + struct mxcfb_pos *pos)
- +{
- + struct fb_info *fbi = vout->fbi;
- + mm_segment_t old_fs;
- + int ret = 0;
- +
- + if (vout->disp_support_windows) {
- + old_fs = get_fs();
- + set_fs(KERNEL_DS);
- + ret = fbi->fbops->fb_ioctl(fbi, MXCFB_SET_OVERLAY_POS,
- + (unsigned long)pos);
- + set_fs(old_fs);
- + }
- +
- + return ret;
- +}
- +
- +static int config_disp_output(struct mxc_vout_output *vout)
- +{
- + struct dma_mem *buf = NULL;
- + struct fb_info *fbi = vout->fbi;
- + struct fb_var_screeninfo var;
- + struct mxcfb_pos pos;
- + int i, fb_num, ret;
- + u32 fb_base;
- + u32 size;
- + u32 display_buf_size;
- + u32 *pixel = NULL;
- + u32 color;
- + int j;
- +
- + memcpy(&var, &fbi->var, sizeof(var));
- + fb_base = fbi->fix.smem_start;
- +
- + var.xres = vout->task.output.width;
- + var.yres = vout->task.output.height;
- + if (vout->linear_bypass_pp || vout->tiled_bypass_pp) {
- + fb_num = 1;
- + /* input crop */
- + if (vout->task.input.width > vout->task.output.width)
- + var.xres_virtual = vout->task.input.width;
- + else
- + var.xres_virtual = var.xres;
- + if (vout->task.input.height > vout->task.output.height)
- + var.yres_virtual = vout->task.input.height;
- + else
- + var.yres_virtual = var.yres;
- + var.rotate = vout->task.output.rotate;
- + var.vmode |= FB_VMODE_YWRAP;
- + } else {
- + fb_num = FB_BUFS;
- + var.xres_virtual = var.xres;
- + var.yres_virtual = fb_num * var.yres;
- + var.vmode &= ~FB_VMODE_YWRAP;
- + }
- + var.bits_per_pixel = fmt_to_bpp(vout->task.output.format);
- + var.nonstd = vout->task.output.format;
- +
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
- + "set display fb to %d %d\n",
- + var.xres, var.yres);
- +
- + /*
- + * To setup the overlay fb from scratch without
- + * the last time overlay fb position or resolution's
- + * impact, we take the following steps:
- + * - blank fb
- + * - set fb position to the starting point
- + * - reconfigure fb
- + * - set fb position to a specific point
- + * - unblank fb
- + * This procedure applies to non-overlay fbs as well.
- + */
- + console_lock();
- + fbi->flags |= FBINFO_MISC_USEREVENT;
- + fb_blank(fbi, FB_BLANK_POWERDOWN);
- + fbi->flags &= ~FBINFO_MISC_USEREVENT;
- + console_unlock();
- +
- + pos.x = 0;
- + pos.y = 0;
- + ret = set_window_position(vout, &pos);
- + if (ret < 0) {
- + v4l2_err(vout->vfd->v4l2_dev, "failed to set fb position "
- + "to starting point\n");
- + return ret;
- + }
- +
- + /* Init display channel through fb API */
- + var.yoffset = 0;
- + var.activate |= FB_ACTIVATE_FORCE;
- + console_lock();
- + fbi->flags |= FBINFO_MISC_USEREVENT;
- + ret = fb_set_var(fbi, &var);
- + fbi->flags &= ~FBINFO_MISC_USEREVENT;
- + console_unlock();
- + if (ret < 0) {
- + v4l2_err(vout->vfd->v4l2_dev,
- + "ERR:%s fb_set_var ret:%d\n", __func__, ret);
- + return ret;
- + }
- +
- + ret = set_window_position(vout, &vout->win_pos);
- + if (ret < 0) {
- + v4l2_err(vout->vfd->v4l2_dev, "failed to set fb position\n");
- + return ret;
- + }
- +
- + if (vout->linear_bypass_pp || vout->tiled_bypass_pp)
- + display_buf_size = fbi->fix.line_length * fbi->var.yres_virtual;
- + else
- + display_buf_size = fbi->fix.line_length * fbi->var.yres;
- + for (i = 0; i < fb_num; i++)
- + vout->disp_bufs[i] = fbi->fix.smem_start + i * display_buf_size;
- + if (vout->tiled_bypass_pp) {
- + size = PAGE_ALIGN(vout->task.input.crop.w *
- + vout->task.input.crop.h *
- + fmt_to_bpp(vout->task.output.format)/8);
- + if (size > vout->vdoa_output[0].size) {
- + for (i = 0; i < VDOA_FB_BUFS; i++) {
- + buf = &vout->vdoa_output[i];
- + if (buf->vaddr)
- + free_dma_buf(vout, buf);
- + buf->size = size;
- + ret = alloc_dma_buf(vout, buf);
- + if (ret < 0)
- + goto err;
- + }
- + }
- + for (i = fb_num; i < (fb_num + VDOA_FB_BUFS); i++)
- + vout->disp_bufs[i] =
- + vout->vdoa_output[i - fb_num].paddr;
- + }
- + vout->fb_smem_len = fbi->fix.smem_len;
- + vout->fb_smem_start = fbi->fix.smem_start;
- + if (fb_base != fbi->fix.smem_start) {
- + v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
- + "realloc fb mem size:0x%x@0x%lx,old paddr @0x%x\n",
- + fbi->fix.smem_len, fbi->fix.smem_start, fb_base);
- + }
- +
- + /* fill black when video config changed */
- + color = colorspaceofpixel(vout->task.output.format) == YUV_CS ?
- + UYVY_BLACK : RGB_BLACK;
- + if (IS_PLANAR_PIXEL_FORMAT(vout->task.output.format)) {
- + size = display_buf_size * 8 /
- + fmt_to_bpp(vout->task.output.format);
- + memset(fbi->screen_base, Y_BLACK, size);
- + memset(fbi->screen_base + size, UV_BLACK,
- + display_buf_size - size);
- + } else {
- + pixel = (u32 *)fbi->screen_base;
- + for (i = 0; i < (display_buf_size >> 2); i++)
- + *pixel++ = color;
- + }
- + console_lock();
- + fbi->flags |= FBINFO_MISC_USEREVENT;
- + ret = fb_blank(fbi, FB_BLANK_UNBLANK);
- + fbi->flags &= ~FBINFO_MISC_USEREVENT;
- + console_unlock();
- + vout->release = false;
- +
- + return ret;
- +err:
- + for (j = i - 1; j >= 0; j--) {
- + buf = &vout->vdoa_output[j];
- + if (buf->vaddr)
- + free_dma_buf(vout, buf);
- + }
- + return ret;
- +}
- +
- +static inline void wait_for_vsync(struct mxc_vout_output *vout)
- +{
- + struct fb_info *fbi = vout->fbi;
- + mm_segment_t old_fs;
- +
- + if (fbi->fbops->fb_ioctl) {
- + old_fs = get_fs();
- + set_fs(KERNEL_DS);
- + fbi->fbops->fb_ioctl(fbi, MXCFB_WAIT_FOR_VSYNC,
- + (unsigned long)NULL);
- + set_fs(old_fs);
- + }
- +
- + return;
- +}
- +
- +static void release_disp_output(struct mxc_vout_output *vout)
- +{
- + struct fb_info *fbi = vout->fbi;
- + struct mxcfb_pos pos;
- +
- + if (vout->release)
- + return;
- + console_lock();
- + fbi->flags |= FBINFO_MISC_USEREVENT;
- + fb_blank(fbi, FB_BLANK_POWERDOWN);
- + fbi->flags &= ~FBINFO_MISC_USEREVENT;
- + console_unlock();
- +
- + /* restore pos to 0,0 avoid fb pan display hang? */
- + pos.x = 0;
- + pos.y = 0;
- + set_window_position(vout, &pos);
- +
- + if (get_ipu_channel(fbi) == MEM_BG_SYNC) {
- + console_lock();
- + fbi->fix.smem_start = vout->disp_bufs[0];
- + fbi->flags |= FBINFO_MISC_USEREVENT;
- + fb_blank(fbi, FB_BLANK_UNBLANK);
- + fbi->flags &= ~FBINFO_MISC_USEREVENT;
- + console_unlock();
- +
- + }
- +
- + vout->release = true;
- +}
- +
- +static int mxc_vidioc_streamon(struct file *file, void *fh,
- + enum v4l2_buf_type i)
- +{
- + struct mxc_vout_output *vout = fh;
- + struct videobuf_queue *q = &vout->vbq;
- + int ret;
- +
- + if (q->streaming) {
- + v4l2_err(vout->vfd->v4l2_dev,
- + "video output already run\n");
- + ret = -EBUSY;
- + goto done;
- + }
- +
- + if (deinterlace_3_field(vout) && list_is_singular(&q->stream)) {
- + v4l2_err(vout->vfd->v4l2_dev,
- + "deinterlacing: need queue 2 frame before streamon\n");
- + ret = -EINVAL;
- + goto done;
- + }
- +
- + ret = config_disp_output(vout);
- + if (ret < 0) {
- + v4l2_err(vout->vfd->v4l2_dev,
- + "Config display output failed\n");
- + goto done;
- + }
- +
- + hrtimer_init(&vout->timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
- + vout->timer.function = mxc_vout_timer_handler;
- + vout->timer_stop = true;
- +
- + vout->start_ktime = hrtimer_cb_get_time(&vout->timer);
- +
- + vout->pre1_vb = NULL;
- + vout->pre2_vb = NULL;
- +
- + ret = videobuf_streamon(q);
- +done:
- + return ret;
- +}
- +
- +static int mxc_vidioc_streamoff(struct file *file, void *fh,
- + enum v4l2_buf_type i)
- +{
- + struct mxc_vout_output *vout = fh;
- + struct videobuf_queue *q = &vout->vbq;
- + int ret = 0;
- +
- + if (q->streaming) {
- + flush_workqueue(vout->v4l_wq);
- +
- + hrtimer_cancel(&vout->timer);
- +
- + /*
- + * Wait for 2 vsyncs to make sure
- + * frames are drained on triple
- + * buffer.
- + */
- + wait_for_vsync(vout);
- + wait_for_vsync(vout);
- +
- + release_disp_output(vout);
- +
- + ret = videobuf_streamoff(&vout->vbq);
- + }
- + INIT_LIST_HEAD(&vout->queue_list);
- + INIT_LIST_HEAD(&vout->active_list);
- +
- + return ret;
- +}
- +
- +static const struct v4l2_ioctl_ops mxc_vout_ioctl_ops = {
- + .vidioc_querycap = mxc_vidioc_querycap,
- + .vidioc_enum_fmt_vid_out = mxc_vidioc_enum_fmt_vid_out,
- + .vidioc_g_fmt_vid_out = mxc_vidioc_g_fmt_vid_out,
- + .vidioc_s_fmt_vid_out = mxc_vidioc_s_fmt_vid_out,
- + .vidioc_cropcap = mxc_vidioc_cropcap,
- + .vidioc_g_crop = mxc_vidioc_g_crop,
- + .vidioc_s_crop = mxc_vidioc_s_crop,
- + .vidioc_queryctrl = mxc_vidioc_queryctrl,
- + .vidioc_g_ctrl = mxc_vidioc_g_ctrl,
- + .vidioc_s_ctrl = mxc_vidioc_s_ctrl,
- + .vidioc_reqbufs = mxc_vidioc_reqbufs,
- + .vidioc_querybuf = mxc_vidioc_querybuf,
- + .vidioc_qbuf = mxc_vidioc_qbuf,
- + .vidioc_dqbuf = mxc_vidioc_dqbuf,
- + .vidioc_streamon = mxc_vidioc_streamon,
- + .vidioc_streamoff = mxc_vidioc_streamoff,
- +};
- +
- +static const struct v4l2_file_operations mxc_vout_fops = {
- + .owner = THIS_MODULE,
- + .unlocked_ioctl = video_ioctl2,
- + .mmap = mxc_vout_mmap,
- + .open = mxc_vout_open,
- + .release = mxc_vout_release,
- +};
- +
- +static struct video_device mxc_vout_template = {
- + .name = "MXC Video Output",
- + .fops = &mxc_vout_fops,
- + .ioctl_ops = &mxc_vout_ioctl_ops,
- + .release = video_device_release,
- +};
- +
- +static struct videobuf_queue_ops mxc_vout_vbq_ops = {
- + .buf_setup = mxc_vout_buffer_setup,
- + .buf_prepare = mxc_vout_buffer_prepare,
- + .buf_release = mxc_vout_buffer_release,
- + .buf_queue = mxc_vout_buffer_queue,
- +};
- +
- +static void mxc_vout_free_output(struct mxc_vout_dev *dev)
- +{
- + int i;
- + int j;
- + struct mxc_vout_output *vout;
- + struct video_device *vfd;
- +
- + for (i = 0; i < dev->out_num; i++) {
- + vout = dev->out[i];
- + vfd = vout->vfd;
- + if (vout->vdoa_work.vaddr)
- + free_dma_buf(vout, &vout->vdoa_work);
- + for (j = 0; j < VDOA_FB_BUFS; j++) {
- + if (vout->vdoa_output[j].vaddr)
- + free_dma_buf(vout, &vout->vdoa_output[j]);
- + }
- + if (vfd) {
- + if (!video_is_registered(vfd))
- + video_device_release(vfd);
- + else
- + video_unregister_device(vfd);
- + }
- + kfree(vout);
- + }
- +}
- +
- +static int mxc_vout_setup_output(struct mxc_vout_dev *dev)
- +{
- + struct videobuf_queue *q;
- + struct fb_info *fbi;
- + struct mxc_vout_output *vout;
- + int i, ret = 0;
- +
- + update_display_setting();
- +
- + /* all output/overlay based on fb */
- + for (i = 0; i < num_registered_fb; i++) {
- + fbi = registered_fb[i];
- +
- + vout = kzalloc(sizeof(struct mxc_vout_output), GFP_KERNEL);
- + if (!vout) {
- + ret = -ENOMEM;
- + break;
- + }
- +
- + dev->out[dev->out_num] = vout;
- + dev->out_num++;
- +
- + vout->fbi = fbi;
- + vout->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
- + vout->vfd = video_device_alloc();
- + if (!vout->vfd) {
- + ret = -ENOMEM;
- + break;
- + }
- +
- + *vout->vfd = mxc_vout_template;
- + vout->vfd->debug = debug;
- + vout->vfd->v4l2_dev = &dev->v4l2_dev;
- + vout->vfd->lock = &vout->mutex;
- + vout->vfd->vfl_dir = VFL_DIR_TX;
- +
- + mutex_init(&vout->mutex);
- + mutex_init(&vout->task_lock);
- +
- + strlcpy(vout->vfd->name, fbi->fix.id, sizeof(vout->vfd->name));
- +
- + video_set_drvdata(vout->vfd, vout);
- +
- + if (video_register_device(vout->vfd,
- + VFL_TYPE_GRABBER, video_nr + i) < 0) {
- + ret = -ENODEV;
- + break;
- + }
- +
- + q = &vout->vbq;
- + q->dev = dev->dev;
- + spin_lock_init(&vout->vbq_lock);
- + videobuf_queue_dma_contig_init(q, &mxc_vout_vbq_ops, q->dev,
- + &vout->vbq_lock, vout->type, V4L2_FIELD_NONE,
- + sizeof(struct videobuf_buffer), vout, NULL);
- +
- + v4l2_info(vout->vfd->v4l2_dev, "V4L2 device registered as %s\n",
- + video_device_node_name(vout->vfd));
- +
- + }
- +
- + return ret;
- +}
- +
- +static int mxc_vout_probe(struct platform_device *pdev)
- +{
- + int ret;
- + struct mxc_vout_dev *dev;
- +
- + dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- + if (!dev)
- + return -ENOMEM;
- +
- + dev->dev = &pdev->dev;
- + dev->dev->dma_mask = kmalloc(sizeof(*dev->dev->dma_mask), GFP_KERNEL);
- + *dev->dev->dma_mask = DMA_BIT_MASK(32);
- + dev->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- +
- + ret = v4l2_device_register(dev->dev, &dev->v4l2_dev);
- + if (ret) {
- + dev_err(dev->dev, "v4l2_device_register failed\n");
- + goto free_dev;
- + }
- +
- + ret = mxc_vout_setup_output(dev);
- + if (ret < 0)
- + goto rel_vdev;
- +
- + return 0;
- +
- +rel_vdev:
- + mxc_vout_free_output(dev);
- + v4l2_device_unregister(&dev->v4l2_dev);
- +free_dev:
- + kfree(dev);
- + return ret;
- +}
- +
- +static int mxc_vout_remove(struct platform_device *pdev)
- +{
- + struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
- + struct mxc_vout_dev *dev = container_of(v4l2_dev, struct
- + mxc_vout_dev, v4l2_dev);
- +
- + mxc_vout_free_output(dev);
- + v4l2_device_unregister(v4l2_dev);
- + kfree(dev);
- + return 0;
- +}
- +
- +static const struct of_device_id mxc_v4l2_dt_ids[] = {
- + { .compatible = "fsl,mxc_v4l2_output", },
- + { /* sentinel */ }
- +};
- +
- +static struct platform_driver mxc_vout_driver = {
- + .driver = {
- + .name = "mxc_v4l2_output",
- + .of_match_table = mxc_v4l2_dt_ids,
- + },
- + .probe = mxc_vout_probe,
- + .remove = mxc_vout_remove,
- +};
- +
- +static int __init mxc_vout_init(void)
- +{
- + if (platform_driver_register(&mxc_vout_driver) != 0) {
- + printk(KERN_ERR VOUT_NAME ":Could not register Video driver\n");
- + return -EINVAL;
- + }
- + return 0;
- +}
- +
- +static void mxc_vout_cleanup(void)
- +{
- + platform_driver_unregister(&mxc_vout_driver);
- +}
- +
- +module_init(mxc_vout_init);
- +module_exit(mxc_vout_cleanup);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("V4L2-driver for MXC video output");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/media/v4l2-core/videobuf2-dma-contig.c linux-3.14.35/drivers/media/v4l2-core/videobuf2-dma-contig.c
- --- linux-3.14.35.orig/drivers/media/v4l2-core/videobuf2-dma-contig.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/media/v4l2-core/videobuf2-dma-contig.c 2015-03-08 14:27:37.605684501 -0500
- @@ -719,7 +719,7 @@
-
- /* get the associated scatterlist for this buffer */
- sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir);
- - if (IS_ERR_OR_NULL(sgt)) {
- + if (IS_ERR(sgt)) {
- pr_err("Error getting dmabuf scatterlist\n");
- return -EINVAL;
- }
- diff -Nur linux-3.14.35.orig/drivers/media/v4l2-core/videobuf-dma-contig.c linux-3.14.35/drivers/media/v4l2-core/videobuf-dma-contig.c
- --- linux-3.14.35.orig/drivers/media/v4l2-core/videobuf-dma-contig.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/media/v4l2-core/videobuf-dma-contig.c 2015-03-08 14:27:37.605684501 -0500
- @@ -304,7 +304,7 @@
-
- /* Try to remap memory */
- size = vma->vm_end - vma->vm_start;
- - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- retval = vm_iomap_memory(vma, vma->vm_start, size);
- if (retval) {
- dev_err(q->dev, "mmap: remap failed with error %d. ",
- diff -Nur linux-3.14.35.orig/drivers/mfd/ab8500-core.c linux-3.14.35/drivers/mfd/ab8500-core.c
- --- linux-3.14.35.orig/drivers/mfd/ab8500-core.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mfd/ab8500-core.c 2015-03-08 14:27:37.605684501 -0500
- @@ -592,7 +592,7 @@
-
- /* If ->irq_base is zero this will give a linear mapping */
- ab8500->domain = irq_domain_add_simple(NULL,
- - num_irqs, ab8500->irq_base,
- + num_irqs, 0,
- &ab8500_irq_ops, ab8500);
-
- if (!ab8500->domain) {
- @@ -1583,14 +1583,13 @@
- if (!ab8500)
- return -ENOMEM;
-
- - if (plat)
- - ab8500->irq_base = plat->irq_base;
- -
- ab8500->dev = &pdev->dev;
-
- resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- - if (!resource)
- + if (!resource) {
- + dev_err(&pdev->dev, "no IRQ resource\n");
- return -ENODEV;
- + }
-
- ab8500->irq = resource->start;
-
- @@ -1612,8 +1611,10 @@
- else {
- ret = get_register_interruptible(ab8500, AB8500_MISC,
- AB8500_IC_NAME_REG, &value);
- - if (ret < 0)
- + if (ret < 0) {
- + dev_err(&pdev->dev, "could not probe HW\n");
- return ret;
- + }
-
- ab8500->version = value;
- }
- @@ -1759,30 +1760,30 @@
- if (is_ab9540(ab8500))
- ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
- ARRAY_SIZE(ab9540_devs), NULL,
- - ab8500->irq_base, ab8500->domain);
- + 0, ab8500->domain);
- else if (is_ab8540(ab8500)) {
- ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs,
- ARRAY_SIZE(ab8540_devs), NULL,
- - ab8500->irq_base, NULL);
- + 0, ab8500->domain);
- if (ret)
- return ret;
-
- if (is_ab8540_1p2_or_earlier(ab8500))
- ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut1_devs,
- ARRAY_SIZE(ab8540_cut1_devs), NULL,
- - ab8500->irq_base, NULL);
- + 0, ab8500->domain);
- else /* ab8540 >= cut2 */
- ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut2_devs,
- ARRAY_SIZE(ab8540_cut2_devs), NULL,
- - ab8500->irq_base, NULL);
- + 0, ab8500->domain);
- } else if (is_ab8505(ab8500))
- ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs,
- ARRAY_SIZE(ab8505_devs), NULL,
- - ab8500->irq_base, ab8500->domain);
- + 0, ab8500->domain);
- else
- ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
- ARRAY_SIZE(ab8500_devs), NULL,
- - ab8500->irq_base, ab8500->domain);
- + 0, ab8500->domain);
- if (ret)
- return ret;
-
- @@ -1790,7 +1791,7 @@
- /* Add battery management devices */
- ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
- ARRAY_SIZE(ab8500_bm_devs), NULL,
- - ab8500->irq_base, ab8500->domain);
- + 0, ab8500->domain);
- if (ret)
- dev_err(ab8500->dev, "error adding bm devices\n");
- }
- diff -Nur linux-3.14.35.orig/drivers/mfd/db8500-prcmu.c linux-3.14.35/drivers/mfd/db8500-prcmu.c
- --- linux-3.14.35.orig/drivers/mfd/db8500-prcmu.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mfd/db8500-prcmu.c 2015-03-08 14:27:37.605684501 -0500
- @@ -25,6 +25,7 @@
- #include <linux/bitops.h>
- #include <linux/fs.h>
- #include <linux/of.h>
- +#include <linux/of_irq.h>
- #include <linux/platform_device.h>
- #include <linux/uaccess.h>
- #include <linux/mfd/core.h>
- @@ -2678,16 +2679,12 @@
- .xlate = irq_domain_xlate_twocell,
- };
-
- -static int db8500_irq_init(struct device_node *np, int irq_base)
- +static int db8500_irq_init(struct device_node *np)
- {
- int i;
-
- - /* In the device tree case, just take some IRQs */
- - if (np)
- - irq_base = 0;
- -
- db8500_irq_domain = irq_domain_add_simple(
- - np, NUM_PRCMU_WAKEUPS, irq_base,
- + np, NUM_PRCMU_WAKEUPS, 0,
- &db8500_irq_ops, NULL);
-
- if (!db8500_irq_domain) {
- @@ -3114,10 +3111,10 @@
- }
-
- static int db8500_prcmu_register_ab8500(struct device *parent,
- - struct ab8500_platform_data *pdata,
- - int irq)
- + struct ab8500_platform_data *pdata)
- {
- - struct resource ab8500_resource = DEFINE_RES_IRQ(irq);
- + struct device_node *np;
- + struct resource ab8500_resource;
- struct mfd_cell ab8500_cell = {
- .name = "ab8500-core",
- .of_compatible = "stericsson,ab8500",
- @@ -3128,6 +3125,20 @@
- .num_resources = 1,
- };
-
- + if (!parent->of_node)
- + return -ENODEV;
- +
- + /* Look up the device node, sneak the IRQ out of it */
- + for_each_child_of_node(parent->of_node, np) {
- + if (of_device_is_compatible(np, ab8500_cell.of_compatible))
- + break;
- + }
- + if (!np) {
- + dev_info(parent, "could not find AB8500 node in the device tree\n");
- + return -ENODEV;
- + }
- + of_irq_to_resource_table(np, &ab8500_resource, 1);
- +
- return mfd_add_devices(parent, 0, &ab8500_cell, 1, NULL, 0, NULL);
- }
-
- @@ -3180,7 +3191,7 @@
- goto no_irq_return;
- }
-
- - db8500_irq_init(np, pdata->irq_base);
- + db8500_irq_init(np);
-
- prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
-
- @@ -3205,8 +3216,7 @@
- }
- }
-
- - err = db8500_prcmu_register_ab8500(&pdev->dev, pdata->ab_platdata,
- - pdata->ab_irq);
- + err = db8500_prcmu_register_ab8500(&pdev->dev, pdata->ab_platdata);
- if (err) {
- mfd_remove_devices(&pdev->dev);
- pr_err("prcmu: Failed to add ab8500 subdevice\n");
- diff -Nur linux-3.14.35.orig/drivers/mfd/Kconfig linux-3.14.35/drivers/mfd/Kconfig
- --- linux-3.14.35.orig/drivers/mfd/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mfd/Kconfig 2015-03-08 14:27:37.605684501 -0500
- @@ -163,6 +163,14 @@
- Additional drivers must be enabled in order to use the functionality
- of the device.
-
- +config MFD_MXC_HDMI
- + tristate "Freescale HDMI Core"
- + select MFD_CORE
- + help
- + This is the core driver for the Freescale i.MX6 on-chip HDMI.
- + This MFD driver connects with the video and audio drivers for HDMI.
- +
- +
- config MFD_MC13XXX
- tristate
- depends on (SPI_MASTER || I2C)
- @@ -1226,3 +1234,4 @@
- help
- Platform configuration infrastructure for the ARM Ltd.
- Versatile Express.
- +
- diff -Nur linux-3.14.35.orig/drivers/mfd/Makefile linux-3.14.35/drivers/mfd/Makefile
- --- linux-3.14.35.orig/drivers/mfd/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mfd/Makefile 2015-03-08 14:27:37.605684501 -0500
- @@ -166,3 +166,4 @@
- obj-$(CONFIG_MFD_AS3711) += as3711.o
- obj-$(CONFIG_MFD_AS3722) += as3722.o
- obj-$(CONFIG_MFD_STW481X) += stw481x.o
- +obj-$(CONFIG_MFD_MXC_HDMI) += mxc-hdmi-core.o
- diff -Nur linux-3.14.35.orig/drivers/mfd/mxc-hdmi-core.c linux-3.14.35/drivers/mfd/mxc-hdmi-core.c
- --- linux-3.14.35.orig/drivers/mfd/mxc-hdmi-core.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mfd/mxc-hdmi-core.c 2015-03-08 14:27:37.605684501 -0500
- @@ -0,0 +1,798 @@
- +/*
- + * Copyright (C) 2011-2014 Freescale Semiconductor, 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + */
- +#include <linux/kernel.h>
- +#include <linux/module.h>
- +#include <linux/init.h>
- +#include <linux/slab.h>
- +#include <linux/device.h>
- +#include <linux/err.h>
- +#include <linux/io.h>
- +#include <linux/clk.h>
- +#include <linux/spinlock.h>
- +#include <linux/irq.h>
- +#include <linux/interrupt.h>
- +
- +#include <linux/platform_device.h>
- +#include <linux/regulator/machine.h>
- +#include <asm/mach-types.h>
- +
- +#include <video/mxc_hdmi.h>
- +#include <linux/ipu-v3.h>
- +#include <video/mxc_edid.h>
- +#include "../mxc/ipu3/ipu_prv.h"
- +#include <linux/mfd/mxc-hdmi-core.h>
- +#include <linux/of_device.h>
- +#include <linux/mod_devicetable.h>
- +
- +struct mxc_hdmi_data {
- + struct platform_device *pdev;
- + unsigned long __iomem *reg_base;
- + unsigned long reg_phys_base;
- + struct device *dev;
- +};
- +
- +static void __iomem *hdmi_base;
- +static struct clk *isfr_clk;
- +static struct clk *iahb_clk;
- +static spinlock_t irq_spinlock;
- +static spinlock_t edid_spinlock;
- +static unsigned int sample_rate;
- +static unsigned long pixel_clk_rate;
- +static struct clk *pixel_clk;
- +static int hdmi_ratio;
- +int mxc_hdmi_ipu_id;
- +int mxc_hdmi_disp_id;
- +static int hdmi_core_edid_status;
- +static struct mxc_edid_cfg hdmi_core_edid_cfg;
- +static int hdmi_core_init;
- +static unsigned int hdmi_dma_running;
- +static struct snd_pcm_substream *hdmi_audio_stream_playback;
- +static unsigned int hdmi_cable_state;
- +static unsigned int hdmi_blank_state;
- +static unsigned int hdmi_abort_state;
- +static spinlock_t hdmi_audio_lock, hdmi_blank_state_lock, hdmi_cable_state_lock;
- +
- +void hdmi_set_dvi_mode(unsigned int state)
- +{
- + if (state) {
- + mxc_hdmi_abort_stream();
- + hdmi_cec_stop_device();
- + } else {
- + hdmi_cec_start_device();
- + }
- +}
- +EXPORT_SYMBOL(hdmi_set_dvi_mode);
- +
- +unsigned int hdmi_set_cable_state(unsigned int state)
- +{
- + unsigned long flags;
- + struct snd_pcm_substream *substream = hdmi_audio_stream_playback;
- +
- + spin_lock_irqsave(&hdmi_cable_state_lock, flags);
- + hdmi_cable_state = state;
- + spin_unlock_irqrestore(&hdmi_cable_state_lock, flags);
- +
- + if (check_hdmi_state() && substream && hdmi_abort_state) {
- + hdmi_abort_state = 0;
- + substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
- + }
- + return 0;
- +}
- +EXPORT_SYMBOL(hdmi_set_cable_state);
- +
- +unsigned int hdmi_set_blank_state(unsigned int state)
- +{
- + unsigned long flags;
- + struct snd_pcm_substream *substream = hdmi_audio_stream_playback;
- +
- + spin_lock_irqsave(&hdmi_blank_state_lock, flags);
- + hdmi_blank_state = state;
- + spin_unlock_irqrestore(&hdmi_blank_state_lock, flags);
- +
- + if (check_hdmi_state() && substream && hdmi_abort_state) {
- + hdmi_abort_state = 0;
- + substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
- + }
- + return 0;
- +}
- +EXPORT_SYMBOL(hdmi_set_blank_state);
- +
- +static void hdmi_audio_abort_stream(struct snd_pcm_substream *substream)
- +{
- + unsigned long flags;
- +
- + snd_pcm_stream_lock_irqsave(substream, flags);
- +
- + if (snd_pcm_running(substream)) {
- + hdmi_abort_state = 1;
- + substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
- + }
- +
- + snd_pcm_stream_unlock_irqrestore(substream, flags);
- +}
- +
- +int mxc_hdmi_abort_stream(void)
- +{
- + unsigned long flags;
- + spin_lock_irqsave(&hdmi_audio_lock, flags);
- + if (hdmi_audio_stream_playback)
- + hdmi_audio_abort_stream(hdmi_audio_stream_playback);
- + spin_unlock_irqrestore(&hdmi_audio_lock, flags);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(mxc_hdmi_abort_stream);
- +
- +int check_hdmi_state(void)
- +{
- + unsigned long flags1, flags2;
- + unsigned int ret;
- +
- + spin_lock_irqsave(&hdmi_cable_state_lock, flags1);
- + spin_lock_irqsave(&hdmi_blank_state_lock, flags2);
- +
- + ret = hdmi_cable_state && hdmi_blank_state;
- +
- + spin_unlock_irqrestore(&hdmi_blank_state_lock, flags2);
- + spin_unlock_irqrestore(&hdmi_cable_state_lock, flags1);
- +
- + return ret;
- +}
- +EXPORT_SYMBOL(check_hdmi_state);
- +
- +int mxc_hdmi_register_audio(struct snd_pcm_substream *substream)
- +{
- + unsigned long flags, flags1;
- + int ret = 0;
- +
- + snd_pcm_stream_lock_irqsave(substream, flags);
- +
- + if (substream && check_hdmi_state()) {
- + spin_lock_irqsave(&hdmi_audio_lock, flags1);
- + if (hdmi_audio_stream_playback) {
- + pr_err("%s unconsist hdmi auido stream!\n", __func__);
- + ret = -EINVAL;
- + }
- + hdmi_audio_stream_playback = substream;
- + hdmi_abort_state = 0;
- + spin_unlock_irqrestore(&hdmi_audio_lock, flags1);
- + } else
- + ret = -EINVAL;
- +
- + snd_pcm_stream_unlock_irqrestore(substream, flags);
- +
- + return ret;
- +}
- +EXPORT_SYMBOL(mxc_hdmi_register_audio);
- +
- +void mxc_hdmi_unregister_audio(struct snd_pcm_substream *substream)
- +{
- + unsigned long flags;
- +
- + spin_lock_irqsave(&hdmi_audio_lock, flags);
- + hdmi_audio_stream_playback = NULL;
- + hdmi_abort_state = 0;
- + spin_unlock_irqrestore(&hdmi_audio_lock, flags);
- +}
- +EXPORT_SYMBOL(mxc_hdmi_unregister_audio);
- +
- +u8 hdmi_readb(unsigned int reg)
- +{
- + u8 value;
- +
- + value = __raw_readb(hdmi_base + reg);
- +
- + return value;
- +}
- +EXPORT_SYMBOL(hdmi_readb);
- +
- +#ifdef DEBUG
- +static bool overflow_lo;
- +static bool overflow_hi;
- +
- +bool hdmi_check_overflow(void)
- +{
- + u8 val, lo, hi;
- +
- + val = hdmi_readb(HDMI_IH_FC_STAT2);
- + lo = (val & HDMI_IH_FC_STAT2_LOW_PRIORITY_OVERFLOW) != 0;
- + hi = (val & HDMI_IH_FC_STAT2_HIGH_PRIORITY_OVERFLOW) != 0;
- +
- + if ((lo != overflow_lo) || (hi != overflow_hi)) {
- + pr_debug("%s LowPriority=%d HighPriority=%d <=======================\n",
- + __func__, lo, hi);
- + overflow_lo = lo;
- + overflow_hi = hi;
- + return true;
- + }
- + return false;
- +}
- +#else
- +bool hdmi_check_overflow(void)
- +{
- + return false;
- +}
- +#endif
- +EXPORT_SYMBOL(hdmi_check_overflow);
- +
- +void hdmi_writeb(u8 value, unsigned int reg)
- +{
- + hdmi_check_overflow();
- + __raw_writeb(value, hdmi_base + reg);
- + hdmi_check_overflow();
- +}
- +EXPORT_SYMBOL(hdmi_writeb);
- +
- +void hdmi_mask_writeb(u8 data, unsigned int reg, u8 shift, u8 mask)
- +{
- + u8 value = hdmi_readb(reg) & ~mask;
- + value |= (data << shift) & mask;
- + hdmi_writeb(value, reg);
- +}
- +EXPORT_SYMBOL(hdmi_mask_writeb);
- +
- +unsigned int hdmi_read4(unsigned int reg)
- +{
- + /* read a four byte address from registers */
- + return (hdmi_readb(reg + 3) << 24) |
- + (hdmi_readb(reg + 2) << 16) |
- + (hdmi_readb(reg + 1) << 8) |
- + hdmi_readb(reg);
- +}
- +EXPORT_SYMBOL(hdmi_read4);
- +
- +void hdmi_write4(unsigned int value, unsigned int reg)
- +{
- + /* write a four byte address to hdmi regs */
- + hdmi_writeb(value & 0xff, reg);
- + hdmi_writeb((value >> 8) & 0xff, reg + 1);
- + hdmi_writeb((value >> 16) & 0xff, reg + 2);
- + hdmi_writeb((value >> 24) & 0xff, reg + 3);
- +}
- +EXPORT_SYMBOL(hdmi_write4);
- +
- +static void initialize_hdmi_ih_mutes(void)
- +{
- + u8 ih_mute;
- +
- + /*
- + * Boot up defaults are:
- + * HDMI_IH_MUTE = 0x03 (disabled)
- + * HDMI_IH_MUTE_* = 0x00 (enabled)
- + */
- +
- + /* Disable top level interrupt bits in HDMI block */
- + ih_mute = hdmi_readb(HDMI_IH_MUTE) |
- + HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
- + HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
- +
- + hdmi_writeb(ih_mute, HDMI_IH_MUTE);
- +
- + /* by default mask all interrupts */
- + hdmi_writeb(0xff, HDMI_VP_MASK);
- + hdmi_writeb(0xff, HDMI_FC_MASK0);
- + hdmi_writeb(0xff, HDMI_FC_MASK1);
- + hdmi_writeb(0xff, HDMI_FC_MASK2);
- + hdmi_writeb(0xff, HDMI_PHY_MASK0);
- + hdmi_writeb(0xff, HDMI_PHY_I2CM_INT_ADDR);
- + hdmi_writeb(0xff, HDMI_PHY_I2CM_CTLINT_ADDR);
- + hdmi_writeb(0xff, HDMI_AUD_INT);
- + hdmi_writeb(0xff, HDMI_AUD_SPDIFINT);
- + hdmi_writeb(0xff, HDMI_AUD_HBR_MASK);
- + hdmi_writeb(0xff, HDMI_GP_MASK);
- + hdmi_writeb(0xff, HDMI_A_APIINTMSK);
- + hdmi_writeb(0xff, HDMI_CEC_MASK);
- + hdmi_writeb(0xff, HDMI_I2CM_INT);
- + hdmi_writeb(0xff, HDMI_I2CM_CTLINT);
- +
- + /* Disable interrupts in the IH_MUTE_* registers */
- + hdmi_writeb(0xff, HDMI_IH_MUTE_FC_STAT0);
- + hdmi_writeb(0xff, HDMI_IH_MUTE_FC_STAT1);
- + hdmi_writeb(0xff, HDMI_IH_MUTE_FC_STAT2);
- + hdmi_writeb(0xff, HDMI_IH_MUTE_AS_STAT0);
- + hdmi_writeb(0xff, HDMI_IH_MUTE_PHY_STAT0);
- + hdmi_writeb(0xff, HDMI_IH_MUTE_I2CM_STAT0);
- + hdmi_writeb(0xff, HDMI_IH_MUTE_CEC_STAT0);
- + hdmi_writeb(0xff, HDMI_IH_MUTE_VP_STAT0);
- + hdmi_writeb(0xff, HDMI_IH_MUTE_I2CMPHY_STAT0);
- + hdmi_writeb(0xff, HDMI_IH_MUTE_AHBDMAAUD_STAT0);
- +
- + /* Enable top level interrupt bits in HDMI block */
- + ih_mute &= ~(HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
- + HDMI_IH_MUTE_MUTE_ALL_INTERRUPT);
- + hdmi_writeb(ih_mute, HDMI_IH_MUTE);
- +}
- +
- +static void hdmi_set_clock_regenerator_n(unsigned int value)
- +{
- + u8 val;
- +
- + if (!hdmi_dma_running) {
- + hdmi_writeb(value & 0xff, HDMI_AUD_N1);
- + hdmi_writeb(0, HDMI_AUD_N2);
- + hdmi_writeb(0, HDMI_AUD_N3);
- + }
- +
- + hdmi_writeb(value & 0xff, HDMI_AUD_N1);
- + hdmi_writeb((value >> 8) & 0xff, HDMI_AUD_N2);
- + hdmi_writeb((value >> 16) & 0x0f, HDMI_AUD_N3);
- +
- + /* nshift factor = 0 */
- + val = hdmi_readb(HDMI_AUD_CTS3);
- + val &= ~HDMI_AUD_CTS3_N_SHIFT_MASK;
- + hdmi_writeb(val, HDMI_AUD_CTS3);
- +}
- +
- +static void hdmi_set_clock_regenerator_cts(unsigned int cts)
- +{
- + u8 val;
- +
- + if (!hdmi_dma_running) {
- + hdmi_writeb(cts & 0xff, HDMI_AUD_CTS1);
- + hdmi_writeb(0, HDMI_AUD_CTS2);
- + hdmi_writeb(0, HDMI_AUD_CTS3);
- + }
- +
- + /* Must be set/cleared first */
- + val = hdmi_readb(HDMI_AUD_CTS3);
- + val &= ~HDMI_AUD_CTS3_CTS_MANUAL;
- + hdmi_writeb(val, HDMI_AUD_CTS3);
- +
- + hdmi_writeb(cts & 0xff, HDMI_AUD_CTS1);
- + hdmi_writeb((cts >> 8) & 0xff, HDMI_AUD_CTS2);
- + hdmi_writeb(((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
- + HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
- +}
- +
- +static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk,
- + unsigned int ratio)
- +{
- + unsigned int n = (128 * freq) / 1000;
- +
- + switch (freq) {
- + case 32000:
- + if (pixel_clk == 25174000)
- + n = (ratio == 150) ? 9152 : 4576;
- + else if (pixel_clk == 27020000)
- + n = (ratio == 150) ? 8192 : 4096;
- + else if (pixel_clk == 74170000 || pixel_clk == 148350000)
- + n = 11648;
- + else if (pixel_clk == 297000000)
- + n = (ratio == 150) ? 6144 : 3072;
- + else
- + n = 4096;
- + break;
- +
- + case 44100:
- + if (pixel_clk == 25174000)
- + n = 7007;
- + else if (pixel_clk == 74170000)
- + n = 17836;
- + else if (pixel_clk == 148350000)
- + n = (ratio == 150) ? 17836 : 8918;
- + else if (pixel_clk == 297000000)
- + n = (ratio == 150) ? 9408 : 4704;
- + else
- + n = 6272;
- + break;
- +
- + case 48000:
- + if (pixel_clk == 25174000)
- + n = (ratio == 150) ? 9152 : 6864;
- + else if (pixel_clk == 27020000)
- + n = (ratio == 150) ? 8192 : 6144;
- + else if (pixel_clk == 74170000)
- + n = 11648;
- + else if (pixel_clk == 148350000)
- + n = (ratio == 150) ? 11648 : 5824;
- + else if (pixel_clk == 297000000)
- + n = (ratio == 150) ? 10240 : 5120;
- + else
- + n = 6144;
- + break;
- +
- + case 88200:
- + n = hdmi_compute_n(44100, pixel_clk, ratio) * 2;
- + break;
- +
- + case 96000:
- + n = hdmi_compute_n(48000, pixel_clk, ratio) * 2;
- + break;
- +
- + case 176400:
- + n = hdmi_compute_n(44100, pixel_clk, ratio) * 4;
- + break;
- +
- + case 192000:
- + n = hdmi_compute_n(48000, pixel_clk, ratio) * 4;
- + break;
- +
- + default:
- + break;
- + }
- +
- + return n;
- +}
- +
- +static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
- + unsigned int ratio)
- +{
- + unsigned int cts = 0;
- + switch (freq) {
- + case 32000:
- + if (pixel_clk == 297000000) {
- + cts = 222750;
- + break;
- + } else if (pixel_clk == 25174000) {
- + cts = 28125;
- + break;
- + }
- + case 48000:
- + case 96000:
- + case 192000:
- + switch (pixel_clk) {
- + case 25200000:
- + case 27000000:
- + case 54000000:
- + case 74250000:
- + case 148500000:
- + cts = pixel_clk / 1000;
- + break;
- + case 297000000:
- + cts = 247500;
- + break;
- + case 25174000:
- + cts = 28125l;
- + break;
- + /*
- + * All other TMDS clocks are not supported by
- + * DWC_hdmi_tx. The TMDS clocks divided or
- + * multiplied by 1,001 coefficients are not
- + * supported.
- + */
- + default:
- + break;
- + }
- + break;
- + case 44100:
- + case 88200:
- + case 176400:
- + switch (pixel_clk) {
- + case 25200000:
- + cts = 28000;
- + break;
- + case 25174000:
- + cts = 31250;
- + break;
- + case 27000000:
- + cts = 30000;
- + break;
- + case 54000000:
- + cts = 60000;
- + break;
- + case 74250000:
- + cts = 82500;
- + break;
- + case 148500000:
- + cts = 165000;
- + break;
- + case 297000000:
- + cts = 247500;
- + break;
- + default:
- + break;
- + }
- + break;
- + default:
- + break;
- + }
- + if (ratio == 100)
- + return cts;
- + else
- + return (cts * ratio) / 100;
- +}
- +
- +static void hdmi_set_clk_regenerator(void)
- +{
- + unsigned int clk_n, clk_cts;
- +
- + clk_n = hdmi_compute_n(sample_rate, pixel_clk_rate, hdmi_ratio);
- + clk_cts = hdmi_compute_cts(sample_rate, pixel_clk_rate, hdmi_ratio);
- +
- + if (clk_cts == 0) {
- + pr_debug("%s: pixel clock not supported: %d\n",
- + __func__, (int)pixel_clk_rate);
- + return;
- + }
- +
- + pr_debug("%s: samplerate=%d ratio=%d pixelclk=%d N=%d cts=%d\n",
- + __func__, sample_rate, hdmi_ratio, (int)pixel_clk_rate,
- + clk_n, clk_cts);
- +
- + hdmi_set_clock_regenerator_cts(clk_cts);
- + hdmi_set_clock_regenerator_n(clk_n);
- +}
- +
- +static int hdmi_core_get_of_property(struct platform_device *pdev)
- +{
- + struct device_node *np = pdev->dev.of_node;
- + int err;
- + int ipu_id, disp_id;
- +
- + err = of_property_read_u32(np, "ipu_id", &ipu_id);
- + if (err) {
- + dev_dbg(&pdev->dev, "get of property ipu_id fail\n");
- + return err;
- + }
- + err = of_property_read_u32(np, "disp_id", &disp_id);
- + if (err) {
- + dev_dbg(&pdev->dev, "get of property disp_id fail\n");
- + return err;
- + }
- +
- + mxc_hdmi_ipu_id = ipu_id;
- + mxc_hdmi_disp_id = disp_id;
- +
- + return err;
- +}
- +
- +/* Need to run this before phy is enabled the first time to prevent
- + * overflow condition in HDMI_IH_FC_STAT2 */
- +void hdmi_init_clk_regenerator(void)
- +{
- + if (pixel_clk_rate == 0) {
- + pixel_clk_rate = 74250000;
- + hdmi_set_clk_regenerator();
- + }
- +}
- +EXPORT_SYMBOL(hdmi_init_clk_regenerator);
- +
- +void hdmi_clk_regenerator_update_pixel_clock(u32 pixclock)
- +{
- +
- + /* Translate pixel clock in ps (pico seconds) to Hz */
- + pixel_clk_rate = PICOS2KHZ(pixclock) * 1000UL;
- + hdmi_set_clk_regenerator();
- +}
- +EXPORT_SYMBOL(hdmi_clk_regenerator_update_pixel_clock);
- +
- +void hdmi_set_dma_mode(unsigned int dma_running)
- +{
- + hdmi_dma_running = dma_running;
- + hdmi_set_clk_regenerator();
- +}
- +EXPORT_SYMBOL(hdmi_set_dma_mode);
- +
- +void hdmi_set_sample_rate(unsigned int rate)
- +{
- + sample_rate = rate;
- +}
- +EXPORT_SYMBOL(hdmi_set_sample_rate);
- +
- +void hdmi_set_edid_cfg(int edid_status, struct mxc_edid_cfg *cfg)
- +{
- + unsigned long flags;
- +
- + spin_lock_irqsave(&edid_spinlock, flags);
- + hdmi_core_edid_status = edid_status;
- + memcpy(&hdmi_core_edid_cfg, cfg, sizeof(struct mxc_edid_cfg));
- + spin_unlock_irqrestore(&edid_spinlock, flags);
- +}
- +EXPORT_SYMBOL(hdmi_set_edid_cfg);
- +
- +int hdmi_get_edid_cfg(struct mxc_edid_cfg *cfg)
- +{
- + unsigned long flags;
- +
- + spin_lock_irqsave(&edid_spinlock, flags);
- + memcpy(cfg, &hdmi_core_edid_cfg, sizeof(struct mxc_edid_cfg));
- + spin_unlock_irqrestore(&edid_spinlock, flags);
- +
- + return hdmi_core_edid_status;
- +}
- +EXPORT_SYMBOL(hdmi_get_edid_cfg);
- +
- +void hdmi_set_registered(int registered)
- +{
- + hdmi_core_init = registered;
- +}
- +EXPORT_SYMBOL(hdmi_set_registered);
- +
- +int hdmi_get_registered(void)
- +{
- + return hdmi_core_init;
- +}
- +EXPORT_SYMBOL(hdmi_get_registered);
- +
- +static int mxc_hdmi_core_probe(struct platform_device *pdev)
- +{
- + struct mxc_hdmi_data *hdmi_data;
- + struct resource *res;
- + unsigned long flags;
- + int ret = 0;
- +
- +#ifdef DEBUG
- + overflow_lo = false;
- + overflow_hi = false;
- +#endif
- +
- + hdmi_core_init = 0;
- + hdmi_dma_running = 0;
- +
- + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- + if (!res)
- + return -ENOENT;
- +
- + ret = hdmi_core_get_of_property(pdev);
- + if (ret < 0) {
- + dev_err(&pdev->dev, "get hdmi of property fail\n");
- + return -ENOENT;
- + }
- +
- + hdmi_data = devm_kzalloc(&pdev->dev, sizeof(struct mxc_hdmi_data), GFP_KERNEL);
- + if (!hdmi_data) {
- + dev_err(&pdev->dev, "Couldn't allocate mxc hdmi mfd device\n");
- + return -ENOMEM;
- + }
- + hdmi_data->pdev = pdev;
- +
- + pixel_clk = NULL;
- + sample_rate = 48000;
- + pixel_clk_rate = 0;
- + hdmi_ratio = 100;
- +
- + spin_lock_init(&irq_spinlock);
- + spin_lock_init(&edid_spinlock);
- +
- +
- + spin_lock_init(&hdmi_cable_state_lock);
- + spin_lock_init(&hdmi_blank_state_lock);
- + spin_lock_init(&hdmi_audio_lock);
- +
- + spin_lock_irqsave(&hdmi_cable_state_lock, flags);
- + hdmi_cable_state = 0;
- + spin_unlock_irqrestore(&hdmi_cable_state_lock, flags);
- +
- + spin_lock_irqsave(&hdmi_blank_state_lock, flags);
- + hdmi_blank_state = 0;
- + spin_unlock_irqrestore(&hdmi_blank_state_lock, flags);
- +
- + spin_lock_irqsave(&hdmi_audio_lock, flags);
- + hdmi_audio_stream_playback = NULL;
- + hdmi_abort_state = 0;
- + spin_unlock_irqrestore(&hdmi_audio_lock, flags);
- +
- + isfr_clk = clk_get(&hdmi_data->pdev->dev, "hdmi_isfr");
- + if (IS_ERR(isfr_clk)) {
- + ret = PTR_ERR(isfr_clk);
- + dev_err(&hdmi_data->pdev->dev,
- + "Unable to get HDMI isfr clk: %d\n", ret);
- + goto eclkg;
- + }
- +
- + ret = clk_prepare_enable(isfr_clk);
- + if (ret < 0) {
- + dev_err(&pdev->dev, "Cannot enable HDMI clock: %d\n", ret);
- + goto eclke;
- + }
- +
- + pr_debug("%s isfr_clk:%d\n", __func__,
- + (int)clk_get_rate(isfr_clk));
- +
- + iahb_clk = clk_get(&hdmi_data->pdev->dev, "hdmi_iahb");
- + if (IS_ERR(iahb_clk)) {
- + ret = PTR_ERR(iahb_clk);
- + dev_err(&hdmi_data->pdev->dev,
- + "Unable to get HDMI iahb clk: %d\n", ret);
- + goto eclkg2;
- + }
- +
- + ret = clk_prepare_enable(iahb_clk);
- + if (ret < 0) {
- + dev_err(&pdev->dev, "Cannot enable HDMI clock: %d\n", ret);
- + goto eclke2;
- + }
- +
- + hdmi_data->reg_phys_base = res->start;
- + if (!request_mem_region(res->start, resource_size(res),
- + dev_name(&pdev->dev))) {
- + dev_err(&pdev->dev, "request_mem_region failed\n");
- + ret = -EBUSY;
- + goto emem;
- + }
- +
- + hdmi_data->reg_base = ioremap(res->start, resource_size(res));
- + if (!hdmi_data->reg_base) {
- + dev_err(&pdev->dev, "ioremap failed\n");
- + ret = -ENOMEM;
- + goto eirq;
- + }
- + hdmi_base = hdmi_data->reg_base;
- +
- + pr_debug("\n%s hdmi hw base = 0x%08x\n\n", __func__, (int)res->start);
- +
- + initialize_hdmi_ih_mutes();
- +
- + /* Disable HDMI clocks until video/audio sub-drivers are initialized */
- + clk_disable_unprepare(isfr_clk);
- + clk_disable_unprepare(iahb_clk);
- +
- + /* Replace platform data coming in with a local struct */
- + platform_set_drvdata(pdev, hdmi_data);
- +
- + return ret;
- +
- +eirq:
- + release_mem_region(res->start, resource_size(res));
- +emem:
- + clk_disable_unprepare(iahb_clk);
- +eclke2:
- + clk_put(iahb_clk);
- +eclkg2:
- + clk_disable_unprepare(isfr_clk);
- +eclke:
- + clk_put(isfr_clk);
- +eclkg:
- + return ret;
- +}
- +
- +
- +static int __exit mxc_hdmi_core_remove(struct platform_device *pdev)
- +{
- + struct mxc_hdmi_data *hdmi_data = platform_get_drvdata(pdev);
- + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- +
- + iounmap(hdmi_data->reg_base);
- + release_mem_region(res->start, resource_size(res));
- +
- + return 0;
- +}
- +
- +static const struct of_device_id imx_hdmi_dt_ids[] = {
- + { .compatible = "fsl,imx6q-hdmi-core", },
- + { .compatible = "fsl,imx6dl-hdmi-core", },
- + { /* sentinel */ }
- +};
- +
- +static struct platform_driver mxc_hdmi_core_driver = {
- + .driver = {
- + .name = "mxc_hdmi_core",
- + .of_match_table = imx_hdmi_dt_ids,
- + .owner = THIS_MODULE,
- + },
- + .remove = __exit_p(mxc_hdmi_core_remove),
- +};
- +
- +static int __init mxc_hdmi_core_init(void)
- +{
- + return platform_driver_probe(&mxc_hdmi_core_driver,
- + mxc_hdmi_core_probe);
- +}
- +
- +static void __exit mxc_hdmi_core_exit(void)
- +{
- + platform_driver_unregister(&mxc_hdmi_core_driver);
- +}
- +
- +subsys_initcall(mxc_hdmi_core_init);
- +module_exit(mxc_hdmi_core_exit);
- +
- +MODULE_DESCRIPTION("Core driver for Freescale i.Mx on-chip HDMI");
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/mfd/si476x-cmd.c linux-3.14.35/drivers/mfd/si476x-cmd.c
- --- linux-3.14.35.orig/drivers/mfd/si476x-cmd.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mfd/si476x-cmd.c 2015-03-08 14:27:37.605684501 -0500
- @@ -303,13 +303,13 @@
- * possible racing conditions when working in polling mode */
- atomic_set(&core->cts, 0);
-
- - /* if (unlikely(command == CMD_POWER_DOWN) */
- - if (!wait_event_timeout(core->command,
- - atomic_read(&core->cts),
- - usecs_to_jiffies(usecs) + 1))
- - dev_warn(&core->client->dev,
- - "(%s) [CMD 0x%02x] Answer timeout.\n",
- - __func__, command);
- + if (!(command == CMD_POWER_DOWN))
- + if (!wait_event_timeout(core->command,
- + atomic_read(&core->cts),
- + usecs_to_jiffies(usecs) + 1))
- + dev_warn(&core->client->dev,
- + "(%s) [CMD 0x%02x] Answer timeout.\n",
- + __func__, command);
-
- /*
- When working in polling mode, for some reason the tuner will
- diff -Nur linux-3.14.35.orig/drivers/mfd/si476x-i2c.c linux-3.14.35/drivers/mfd/si476x-i2c.c
- --- linux-3.14.35.orig/drivers/mfd/si476x-i2c.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mfd/si476x-i2c.c 2015-03-08 14:27:37.605684501 -0500
- @@ -303,7 +303,7 @@
- */
- udelay(100);
-
- - err = si476x_core_start(core, false);
- + err = si476x_core_start(core, true);
- if (err < 0)
- goto disable_regulators;
-
- @@ -312,7 +312,7 @@
-
- case SI476X_POWER_DOWN:
- core->power_state = next_state;
- - err = si476x_core_stop(core, false);
- + err = si476x_core_stop(core, true);
- if (err < 0)
- core->power_state = SI476X_POWER_INCONSISTENT;
- disable_regulators:
- @@ -740,8 +740,15 @@
- memcpy(&core->pinmux, &pdata->pinmux,
- sizeof(struct si476x_pinmux));
- } else {
- - dev_err(&client->dev, "No platform data provided\n");
- - return -EINVAL;
- + dev_warn(&client->dev, "Using default platform data.\n");
- + core->power_up_parameters.xcload = 0x28;
- + core->power_up_parameters.func = SI476X_FUNC_FM_RECEIVER;
- + core->power_up_parameters.freq = SI476X_FREQ_37P209375_MHZ;
- + core->diversity_mode = SI476X_PHDIV_DISABLED;
- + core->pinmux.dclk = SI476X_DCLK_DAUDIO;
- + core->pinmux.dfs = SI476X_DFS_DAUDIO;
- + core->pinmux.dout = SI476X_DOUT_I2S_OUTPUT;
- + core->pinmux.xout = SI476X_XOUT_TRISTATE;
- }
-
- core->supplies[0].supply = "vd";
- @@ -799,6 +806,10 @@
-
- core->chip_id = id->driver_data;
-
- + /* Power down si476x first */
- + core->power_state = SI476X_POWER_UP_FULL;
- + si476x_core_set_power_state(core, SI476X_POWER_DOWN);
- +
- rval = si476x_core_get_revision_info(core);
- if (rval < 0) {
- rval = -ENODEV;
- diff -Nur linux-3.14.35.orig/drivers/mfd/si476x-prop.c linux-3.14.35/drivers/mfd/si476x-prop.c
- --- linux-3.14.35.orig/drivers/mfd/si476x-prop.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mfd/si476x-prop.c 2015-03-08 14:27:37.605684501 -0500
- @@ -217,15 +217,36 @@
- return 0;
- }
-
- +static bool si476x_core_regmap_volatile_register(struct device *dev, unsigned int reg)
- +{
- + switch (reg) {
- + case SI476X_PROP_DIGITAL_IO_OUTPUT_SAMPLE_RATE:
- + case SI476X_PROP_DIGITAL_IO_OUTPUT_FORMAT:
- + return false;
- + default:
- + return true;
- + }
- +
- + return true;
- +}
- +
- +/* These two register is used by the codec, so add reg_default here */
- +static struct reg_default si476x_core_reg[] = {
- + { 0x202, 0xBB80 },
- + { 0x203, 0x1700 },
- +};
-
- static const struct regmap_config si476x_regmap_config = {
- .reg_bits = 16,
- .val_bits = 16,
-
- .max_register = 0x4003,
- + .reg_defaults = si476x_core_reg,
- + .num_reg_defaults = ARRAY_SIZE(si476x_core_reg),
-
- .writeable_reg = si476x_core_regmap_writable_register,
- .readable_reg = si476x_core_regmap_readable_register,
- + .volatile_reg = si476x_core_regmap_volatile_register,
-
- .reg_read = si476x_core_regmap_read,
- .reg_write = si476x_core_regmap_write,
- diff -Nur linux-3.14.35.orig/drivers/misc/sram.c linux-3.14.35/drivers/misc/sram.c
- --- linux-3.14.35.orig/drivers/misc/sram.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/misc/sram.c 2015-03-08 14:27:37.605684501 -0500
- @@ -29,7 +29,7 @@
- #include <linux/spinlock.h>
- #include <linux/genalloc.h>
-
- -#define SRAM_GRANULARITY 32
- +#define SRAM_GRANULARITY 4096
-
- struct sram_dev {
- struct gen_pool *pool;
- diff -Nur linux-3.14.35.orig/drivers/mmc/core/core.c linux-3.14.35/drivers/mmc/core/core.c
- --- linux-3.14.35.orig/drivers/mmc/core/core.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/core/core.c 2015-03-08 14:27:37.609684501 -0500
- @@ -13,11 +13,13 @@
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/interrupt.h>
- +#include <linux/clk.h>
- #include <linux/completion.h>
- #include <linux/device.h>
- #include <linux/delay.h>
- #include <linux/pagemap.h>
- #include <linux/err.h>
- +#include <linux/gpio.h>
- #include <linux/leds.h>
- #include <linux/scatterlist.h>
- #include <linux/log2.h>
- @@ -1519,6 +1521,43 @@
- mmc_host_clk_release(host);
- }
-
- +static void mmc_card_power_up(struct mmc_host *host)
- +{
- + int i;
- + struct gpio_desc **gds = host->card_reset_gpios;
- +
- + for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
- + if (gds[i]) {
- + dev_dbg(host->parent, "Asserting reset line %d", i);
- + gpiod_set_value(gds[i], 1);
- + }
- + }
- +
- + if (host->card_regulator) {
- + dev_dbg(host->parent, "Enabling external regulator");
- + if (regulator_enable(host->card_regulator))
- + dev_err(host->parent, "Failed to enable external regulator");
- + }
- +
- + if (host->card_clk) {
- + dev_dbg(host->parent, "Enabling external clock");
- + clk_prepare_enable(host->card_clk);
- + }
- +
- + /* 2ms delay to let clocks and power settle */
- + mmc_delay(20);
- +
- + for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
- + if (gds[i]) {
- + dev_dbg(host->parent, "Deasserting reset line %d", i);
- + gpiod_set_value(gds[i], 0);
- + }
- + }
- +
- + /* 2ms delay to after reset release */
- + mmc_delay(20);
- +}
- +
- /*
- * Apply power to the MMC stack. This is a two-stage process.
- * First, we enable power to the card without the clock running.
- @@ -1535,6 +1574,9 @@
- if (host->ios.power_mode == MMC_POWER_ON)
- return;
-
- + /* Power up the card/module first, if needed */
- + mmc_card_power_up(host);
- +
- mmc_host_clk_hold(host);
-
- host->ios.vdd = fls(ocr) - 1;
- diff -Nur linux-3.14.35.orig/drivers/mmc/core/host.c linux-3.14.35/drivers/mmc/core/host.c
- --- linux-3.14.35.orig/drivers/mmc/core/host.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/core/host.c 2015-03-08 14:27:37.609684501 -0500
- @@ -12,14 +12,18 @@
- * MMC host class device management
- */
-
- +#include <linux/kernel.h>
- +#include <linux/clk.h>
- #include <linux/device.h>
- #include <linux/err.h>
- +#include <linux/gpio/consumer.h>
- #include <linux/idr.h>
- #include <linux/of.h>
- #include <linux/of_gpio.h>
- #include <linux/pagemap.h>
- #include <linux/export.h>
- #include <linux/leds.h>
- +#include <linux/regulator/consumer.h>
- #include <linux/slab.h>
- #include <linux/suspend.h>
-
- @@ -439,6 +443,66 @@
-
- EXPORT_SYMBOL(mmc_of_parse);
-
- +static int mmc_of_parse_child(struct mmc_host *host)
- +{
- + struct device_node *np;
- + struct clk *clk;
- + int i;
- +
- + if (!host->parent || !host->parent->of_node)
- + return 0;
- +
- + np = host->parent->of_node;
- +
- + host->card_regulator = regulator_get(host->parent, "card-external-vcc");
- + if (IS_ERR(host->card_regulator)) {
- + if (PTR_ERR(host->card_regulator) == -EPROBE_DEFER)
- + return PTR_ERR(host->card_regulator);
- + host->card_regulator = NULL;
- + }
- +
- + /* Parse card power/reset/clock control */
- + if (of_find_property(np, "card-reset-gpios", NULL)) {
- + struct gpio_desc *gpd;
- + int level = 0;
- +
- + /*
- + * If the regulator is enabled, then we can hold the
- + * card in reset with an active high resets. Otherwise,
- + * hold the resets low.
- + */
- + if (host->card_regulator && regulator_is_enabled(host->card_regulator))
- + level = 1;
- +
- + for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
- + gpd = devm_gpiod_get_index(host->parent, "card-reset", i);
- + if (IS_ERR(gpd)) {
- + if (PTR_ERR(gpd) == -EPROBE_DEFER)
- + return PTR_ERR(gpd);
- + break;
- + }
- + gpiod_direction_output(gpd, gpiod_is_active_low(gpd) | level);
- + host->card_reset_gpios[i] = gpd;
- + }
- +
- + gpd = devm_gpiod_get_index(host->parent, "card-reset", ARRAY_SIZE(host->card_reset_gpios));
- + if (!IS_ERR(gpd)) {
- + dev_warn(host->parent, "More reset gpios than we can handle");
- + gpiod_put(gpd);
- + }
- + }
- +
- + clk = of_clk_get_by_name(np, "card_ext_clock");
- + if (IS_ERR(clk)) {
- + if (PTR_ERR(clk) == -EPROBE_DEFER)
- + return PTR_ERR(clk);
- + clk = NULL;
- + }
- + host->card_clk = clk;
- +
- + return 0;
- +}
- +
- /**
- * mmc_alloc_host - initialise the per-host structure.
- * @extra: sizeof private data structure
- @@ -518,6 +582,10 @@
- {
- int err;
-
- + err = mmc_of_parse_child(host);
- + if (err)
- + return err;
- +
- WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
- !host->ops->enable_sdio_irq);
-
- diff -Nur linux-3.14.35.orig/drivers/mmc/core/mmc.c linux-3.14.35/drivers/mmc/core/mmc.c
- --- linux-3.14.35.orig/drivers/mmc/core/mmc.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/core/mmc.c 2015-03-08 14:27:37.609684501 -0500
- @@ -317,6 +317,11 @@
- mmc_card_set_blockaddr(card);
- }
-
- + card->ext_csd.boot_info = ext_csd[EXT_CSD_BOOT_INFO];
- + card->ext_csd.boot_config = ext_csd[EXT_CSD_PART_CONFIG];
- + card->ext_csd.boot_size = ext_csd[EXT_CSD_BOOT_MULT];
- + card->ext_csd.boot_bus_width = ext_csd[EXT_CSD_BOOT_BUS_WIDTH];
- +
- card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE];
- mmc_select_card_type(card);
-
- @@ -655,6 +660,372 @@
- return err;
- }
-
- +static ssize_t mmc_boot_info_show(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + char *boot_partition[8] = {
- + "Device not boot enabled",
- + "Boot partition 1 enabled",
- + "Boot partition 2 enabled",
- + "Reserved",
- + "Reserved",
- + "Reserved",
- + "Reserved",
- + "User area enabled for boot"};
- +
- + char *bus_width[4] = {
- + "x1 (sdr) or x4 (ddr) bus width in boot operation mode",
- + "x4 (sdr/ddr) bus width in boot operation mode",
- + "x8 (sdr/ddr) bus width in boot operation mode",
- + "Reserved"};
- +
- + char *boot_mode[4] = {
- + "Use single data rate + backward compatible timings in boot operation",
- + "Use single data rate + high speed timings in boot operation mode",
- + "Use dual data rate in boot operation",
- + "Reserved"};
- +
- + int partition;
- + int width;
- + int mode;
- + int err;
- + u8 *ext_csd = NULL;
- + struct mmc_card *card = container_of(dev, struct mmc_card, dev);
- +
- + /* read it again because user may change it */
- + mmc_claim_host(card->host);
- + err = mmc_get_ext_csd(card, &ext_csd);
- + mmc_release_host(card->host);
- + if (err || !ext_csd) {
- + pr_err("%s: failed to get ext_csd, err=%d\n",
- + mmc_hostname(card->host),
- + err);
- + return err;
- + }
- +
- + mmc_read_ext_csd(card, ext_csd);
- + mmc_free_ext_csd(ext_csd);
- +
- + partition = (card->ext_csd.boot_config >> 3) & 0x7;
- + width = card->ext_csd.boot_bus_width & 0x3;
- + mode = (card->ext_csd.boot_bus_width >> 3) & 0x3;
- +
- + return sprintf(buf,
- + "boot_info:0x%02x;\n"
- + " ALT_BOOT_MODE:%x - %s\n"
- + " DDR_BOOT_MODE:%x - %s\n"
- + " HS_BOOTMODE:%x - %s\n"
- + "boot_size:%04dKB\n"
- + "boot_partition:0x%02x;\n"
- + " BOOT_ACK:%x - %s\n"
- + " BOOT_PARTITION-ENABLE: %x - %s\n"
- + "boot_bus:0x%02x\n"
- + " BOOT_MODE:%x - %s\n"
- + " RESET_BOOT_BUS_WIDTH:%x - %s\n"
- + " BOOT_BUS_WIDTH:%x - %s\n",
- +
- + card->ext_csd.boot_info,
- + !!(card->ext_csd.boot_info & 0x1),
- + (card->ext_csd.boot_info & 0x1) ?
- + "Supports alternate boot method" :
- + "Does not support alternate boot method",
- + !!(card->ext_csd.boot_info & 0x2),
- + (card->ext_csd.boot_info & 0x2) ?
- + "Supports alternate dual data rate during boot" :
- + "Does not support dual data rate during boot",
- + !!(card->ext_csd.boot_info & 0x4),
- + (card->ext_csd.boot_info & 0x4) ?
- + "Supports high speed timing during boot" :
- + "Does not support high speed timing during boot",
- +
- + card->ext_csd.boot_size * 128,
- +
- + card->ext_csd.boot_config,
- + !!(card->ext_csd.boot_config & 0x40),
- + (card->ext_csd.boot_config & 0x40) ?
- + "Boot acknowledge sent during boot operation" :
- + "No boot acknowledge sent",
- + partition,
- + boot_partition[partition],
- +
- + card->ext_csd.boot_bus_width,
- + mode,
- + boot_mode[mode],
- + !!(card->ext_csd.boot_bus_width & 0x4),
- + (card->ext_csd.boot_bus_width & 0x4) ?
- + "Retain boot bus width and boot mode after boot operation" :
- + "Reset bus width to x1, single data rate and backward"
- + "compatible timings after boot operation",
- + width,
- + bus_width[width]);
- +}
- +
- +/* set up boot partitions */
- +static ssize_t
- +setup_boot_partitions(struct device *dev, struct device_attribute *attr,
- + const char *buf, size_t count)
- +{
- + int err, busy = 0;
- + u32 part;
- + u8 *ext_csd, boot_config;
- + struct mmc_command cmd;
- + struct mmc_card *card = container_of(dev, struct mmc_card, dev);
- +
- + BUG_ON(!card);
- +
- + sscanf(buf, "%d\n", &part);
- +
- + if (card->csd.mmca_vsn < CSD_SPEC_VER_4) {
- + pr_err("%s: invalid mmc version" \
- + " mmc version is below version 4!)\n",
- + mmc_hostname(card->host));
- + return -EINVAL;
- + }
- +
- + /* it's a normal SD/MMC but user request to configure boot partition */
- + if (card->ext_csd.boot_size <= 0) {
- + pr_err("%s: fail to send SWITCH command to card " \
- + "to update boot_config of the EXT_CSD!\n",
- + mmc_hostname(card->host));
- + return -EINVAL;
- + }
- +
- + /*
- + * partition must be -
- + * 0 - user area
- + * 1 - boot partition 1
- + * 2 - boot partition 2
- + * DO NOT switch the partitions that used to be accessed
- + * in OS layer HERE
- + */
- + if (part & EXT_CSD_BOOT_PARTITION_ACCESS_MASK) {
- + pr_err("%s: DO NOT switch the partitions that used to be\n" \
- + " accessed in OS layer HERE. please following the\n" \
- + " guidance of Documentation/mmc/mmc-dev-parts.txt.\n",
- + mmc_hostname(card->host));
- + return -EINVAL;
- + }
- +
- + ext_csd = kmalloc(512, GFP_KERNEL);
- + if (!ext_csd) {
- + pr_err("%s: could not allocate a buffer to " \
- + "receive the ext_csd.\n", mmc_hostname(card->host));
- + return -ENOMEM;
- + }
- +
- + mmc_claim_host(card->host);
- + err = mmc_send_ext_csd(card, ext_csd);
- + if (err) {
- + pr_err("%s: unable to read EXT_CSD.\n",
- + mmc_hostname(card->host));
- + goto err_rtn;
- + }
- +
- + /* enable the boot partition in boot mode */
- + /* boot enable be -
- + * 0x00 - disable boot enable.
- + * 0x08 - boot partition 1 is enabled for boot.
- + * 0x10 - boot partition 2 is enabled for boot.
- + * 0x38 - User area is enabled for boot.
- + */
- + switch (part & EXT_CSD_BOOT_PARTITION_ENABLE_MASK) {
- + case 0:
- + boot_config = (ext_csd[EXT_CSD_PART_CONFIG]
- + & ~EXT_CSD_BOOT_PARTITION_ENABLE_MASK
- + & ~EXT_CSD_BOOT_ACK_ENABLE);
- + break;
- + case EXT_CSD_BOOT_PARTITION_PART1:
- + boot_config = ((ext_csd[EXT_CSD_PART_CONFIG]
- + & ~EXT_CSD_BOOT_PARTITION_ENABLE_MASK)
- + | EXT_CSD_BOOT_PARTITION_PART1
- + | EXT_CSD_BOOT_ACK_ENABLE);
- + break;
- + case EXT_CSD_BOOT_PARTITION_PART2:
- + boot_config = ((ext_csd[EXT_CSD_PART_CONFIG]
- + & ~EXT_CSD_BOOT_PARTITION_ENABLE_MASK)
- + | EXT_CSD_BOOT_PARTITION_PART2
- + | EXT_CSD_BOOT_ACK_ENABLE);
- + break;
- + case EXT_CSD_BOOT_PARTITION_ENABLE_MASK:
- + boot_config = ((ext_csd[EXT_CSD_PART_CONFIG]
- + | EXT_CSD_BOOT_PARTITION_ENABLE_MASK)
- + & ~EXT_CSD_BOOT_ACK_ENABLE);
- + break;
- + default:
- + pr_err("%s: wrong boot config parameter" \
- + " 00 (disable boot), 08 (enable boot1)," \
- + "16 (enable boot2), 56 (User area)\n",
- + mmc_hostname(card->host));
- + err = -EINVAL;
- + goto err_rtn;
- + }
- +
- + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- + EXT_CSD_PART_CONFIG, boot_config, card->ext_csd.part_time);
- + if (err) {
- + pr_err("%s: fail to send SWITCH command to card " \
- + "to update boot_config of the EXT_CSD!\n",
- + mmc_hostname(card->host));
- + goto err_rtn;
- + }
- +
- + /* waiting for the card to finish the busy state */
- + do {
- + memset(&cmd, 0, sizeof(struct mmc_command));
- +
- + cmd.opcode = MMC_SEND_STATUS;
- + cmd.arg = card->rca << 16;
- + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
- +
- + err = mmc_wait_for_cmd(card->host, &cmd, 0);
- + if (err || busy > 100) {
- + pr_err("%s: failed to wait for" \
- + "the busy state to end.\n",
- + mmc_hostname(card->host));
- + break;
- + }
- +
- + if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) {
- + pr_info("%s: card is in busy state" \
- + "pls wait for busy state to end.\n",
- + mmc_hostname(card->host));
- + }
- + busy++;
- + } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
- +
- + /* Now check whether it works */
- + err = mmc_send_ext_csd(card, ext_csd);
- + if (err) {
- + pr_err("%s: %d unable to re-read EXT_CSD.\n",
- + mmc_hostname(card->host), err);
- + goto err_rtn;
- + }
- +
- + card->ext_csd.boot_config = ext_csd[EXT_CSD_PART_CONFIG];
- +
- +err_rtn:
- + mmc_release_host(card->host);
- + kfree(ext_csd);
- + if (err)
- + return err;
- + else
- + return count;
- +}
- +
- +/* configure the boot bus */
- +static ssize_t
- +setup_boot_bus(struct device *dev, struct device_attribute *attr,
- + const char *buf, size_t count)
- +{
- + int err, busy = 0;
- + u32 boot_bus, new_bus;
- + u8 *ext_csd;
- + struct mmc_command cmd;
- + struct mmc_card *card = container_of(dev, struct mmc_card, dev);
- +
- + BUG_ON(!card);
- +
- + sscanf(buf, "%d\n", &boot_bus);
- +
- + if (card->csd.mmca_vsn < CSD_SPEC_VER_4) {
- + pr_err("%s: invalid mmc version" \
- + " mmc version is below version 4!)\n",
- + mmc_hostname(card->host));
- + return -EINVAL;
- + }
- +
- + /* it's a normal SD/MMC but user request to configure boot bus */
- + if (card->ext_csd.boot_size <= 0) {
- + pr_err("%s: this is a normal SD/MMC card" \
- + " but you request to configure boot bus !\n",
- + mmc_hostname(card->host));
- + return -EINVAL;
- + }
- +
- + ext_csd = kmalloc(512, GFP_KERNEL);
- + if (!ext_csd) {
- + pr_err("%s: could not allocate a buffer to " \
- + "receive the ext_csd.\n", mmc_hostname(card->host));
- + return -ENOMEM;
- + }
- +
- + mmc_claim_host(card->host);
- + err = mmc_send_ext_csd(card, ext_csd);
- + if (err) {
- + pr_err("%s: unable to read EXT_CSD.\n",
- + mmc_hostname(card->host));
- + goto err_rtn;
- + }
- +
- + /* Configure the boot bus width when boot partition is enabled */
- + if (((boot_bus & EXT_CSD_BOOT_BUS_WIDTH_MODE_MASK) >> 3) > 2
- + || (boot_bus & EXT_CSD_BOOT_BUS_WIDTH_WIDTH_MASK) > 2
- + || (boot_bus & ~EXT_CSD_BOOT_BUS_WIDTH_MASK) > 0) {
- + pr_err("%s: Invalid inputs!\n",
- + mmc_hostname(card->host));
- + err = -EINVAL;
- + goto err_rtn;
- + }
- +
- + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- + EXT_CSD_BOOT_BUS_WIDTH, boot_bus, card->ext_csd.part_time);
- + if (err) {
- + pr_err("%s: fail to send SWITCH command to card " \
- + "to update boot_config of the EXT_CSD!\n",
- + mmc_hostname(card->host));
- + goto err_rtn;
- + }
- +
- + /* waiting for the card to finish the busy state */
- + do {
- + memset(&cmd, 0, sizeof(struct mmc_command));
- +
- + cmd.opcode = MMC_SEND_STATUS;
- + cmd.arg = card->rca << 16;
- + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
- +
- + err = mmc_wait_for_cmd(card->host, &cmd, 0);
- + if (err || busy > 100) {
- + pr_err("%s: failed to wait for" \
- + "the busy state to end.\n",
- + mmc_hostname(card->host));
- + break;
- + }
- +
- + if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) {
- + pr_info("%s: card is in busy state" \
- + "pls wait for busy state to end.\n",
- + mmc_hostname(card->host));
- + }
- + busy++;
- + } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
- +
- + /* Now check whether it works */
- + err = mmc_send_ext_csd(card, ext_csd);
- + if (err) {
- + pr_err("%s: %d unable to re-read EXT_CSD.\n",
- + mmc_hostname(card->host), err);
- + goto err_rtn;
- + }
- +
- + new_bus = ext_csd[EXT_CSD_BOOT_BUS_WIDTH];
- + if (boot_bus != new_bus) {
- + pr_err("%s: after SWITCH, current boot bus mode %d" \
- + " is not same as requested bus mode %d!\n",
- + mmc_hostname(card->host), new_bus, boot_bus);
- + goto err_rtn;
- + }
- + card->ext_csd.boot_bus_width = ext_csd[EXT_CSD_BOOT_BUS_WIDTH];
- +
- +err_rtn:
- + mmc_release_host(card->host);
- + mmc_free_ext_csd(ext_csd);
- + if (err)
- + return err;
- + else
- + return count;
- +}
- +
- MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
- card->raw_cid[2], card->raw_cid[3]);
- MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
- @@ -674,6 +1045,9 @@
- MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size);
- MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult);
- MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors);
- +DEVICE_ATTR(boot_info, S_IRUGO, mmc_boot_info_show, NULL);
- +DEVICE_ATTR(boot_config, S_IWUGO, NULL, setup_boot_partitions);
- +DEVICE_ATTR(boot_bus_config, S_IWUGO, NULL, setup_boot_bus);
-
- static struct attribute *mmc_std_attrs[] = {
- &dev_attr_cid.attr,
- @@ -692,6 +1066,9 @@
- &dev_attr_enhanced_area_size.attr,
- &dev_attr_raw_rpmb_size_mult.attr,
- &dev_attr_rel_sectors.attr,
- + &dev_attr_boot_info.attr,
- + &dev_attr_boot_config.attr,
- + &dev_attr_boot_bus_config.attr,
- NULL,
- };
-
- diff -Nur linux-3.14.35.orig/drivers/mmc/core/sdio_irq.c linux-3.14.35/drivers/mmc/core/sdio_irq.c
- --- linux-3.14.35.orig/drivers/mmc/core/sdio_irq.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/core/sdio_irq.c 2015-03-08 14:27:37.609684501 -0500
- @@ -90,6 +90,15 @@
- return ret;
- }
-
- +void sdio_run_irqs(struct mmc_host *host)
- +{
- + mmc_claim_host(host);
- + host->sdio_irq_pending = true;
- + process_sdio_pending_irqs(host);
- + mmc_release_host(host);
- +}
- +EXPORT_SYMBOL_GPL(sdio_run_irqs);
- +
- static int sdio_irq_thread(void *_host)
- {
- struct mmc_host *host = _host;
- @@ -189,14 +198,20 @@
- WARN_ON(!host->claimed);
-
- if (!host->sdio_irqs++) {
- - atomic_set(&host->sdio_irq_thread_abort, 0);
- - host->sdio_irq_thread =
- - kthread_run(sdio_irq_thread, host, "ksdioirqd/%s",
- - mmc_hostname(host));
- - if (IS_ERR(host->sdio_irq_thread)) {
- - int err = PTR_ERR(host->sdio_irq_thread);
- - host->sdio_irqs--;
- - return err;
- + if (!(host->caps2 & MMC_CAP2_SDIO_NOTHREAD)) {
- + atomic_set(&host->sdio_irq_thread_abort, 0);
- + host->sdio_irq_thread =
- + kthread_run(sdio_irq_thread, host,
- + "ksdioirqd/%s", mmc_hostname(host));
- + if (IS_ERR(host->sdio_irq_thread)) {
- + int err = PTR_ERR(host->sdio_irq_thread);
- + host->sdio_irqs--;
- + return err;
- + }
- + } else {
- + mmc_host_clk_hold(host);
- + host->ops->enable_sdio_irq(host, 1);
- + mmc_host_clk_release(host);
- }
- }
-
- @@ -211,8 +226,14 @@
- BUG_ON(host->sdio_irqs < 1);
-
- if (!--host->sdio_irqs) {
- - atomic_set(&host->sdio_irq_thread_abort, 1);
- - kthread_stop(host->sdio_irq_thread);
- + if (!(host->caps2 & MMC_CAP2_SDIO_NOTHREAD)) {
- + atomic_set(&host->sdio_irq_thread_abort, 1);
- + kthread_stop(host->sdio_irq_thread);
- + } else {
- + mmc_host_clk_hold(host);
- + host->ops->enable_sdio_irq(host, 0);
- + mmc_host_clk_release(host);
- + }
- }
-
- return 0;
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/dw_mmc.c linux-3.14.35/drivers/mmc/host/dw_mmc.c
- --- linux-3.14.35.orig/drivers/mmc/host/dw_mmc.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/dw_mmc.c 2015-03-08 14:27:37.609684501 -0500
- @@ -2147,6 +2147,8 @@
- if (!mmc)
- return -ENOMEM;
-
- + mmc_of_parse(mmc);
- +
- slot = mmc_priv(mmc);
- slot->id = id;
- slot->mmc = mmc;
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/Kconfig linux-3.14.35/drivers/mmc/host/Kconfig
- --- linux-3.14.35.orig/drivers/mmc/host/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/Kconfig 2015-03-08 14:27:37.609684501 -0500
- @@ -25,8 +25,7 @@
- If unsure, say N.
-
- config MMC_SDHCI
- - tristate "Secure Digital Host Controller Interface support"
- - depends on HAS_DMA
- + tristate
- help
- This selects the generic Secure Digital Host Controller Interface.
- It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
- @@ -59,7 +58,8 @@
-
- config MMC_SDHCI_PCI
- tristate "SDHCI support on PCI bus"
- - depends on MMC_SDHCI && PCI
- + depends on PCI && HAS_DMA
- + select MMC_SDHCI
- help
- This selects the PCI Secure Digital Host Controller Interface.
- Most controllers found today are PCI devices.
- @@ -83,7 +83,8 @@
-
- config MMC_SDHCI_ACPI
- tristate "SDHCI support for ACPI enumerated SDHCI controllers"
- - depends on MMC_SDHCI && ACPI
- + depends on ACPI && HAS_DMA
- + select MMC_SDHCI
- help
- This selects support for ACPI enumerated SDHCI controllers,
- identified by ACPI Compatibility ID PNP0D40 or specific
- @@ -94,8 +95,8 @@
- If unsure, say N.
-
- config MMC_SDHCI_PLTFM
- - tristate "SDHCI platform and OF driver helper"
- - depends on MMC_SDHCI
- + tristate
- + select MMC_SDHCI
- help
- This selects the common helper functions support for Secure Digital
- Host Controller Interface based platform and OF drivers.
- @@ -106,8 +107,8 @@
-
- config MMC_SDHCI_OF_ARASAN
- tristate "SDHCI OF support for the Arasan SDHCI controllers"
- - depends on MMC_SDHCI_PLTFM
- - depends on OF
- + depends on OF && HAS_DMA
- + select MMC_SDHCI_PLTFM
- help
- This selects the Arasan Secure Digital Host Controller Interface
- (SDHCI). This hardware is found e.g. in Xilinx' Zynq SoC.
- @@ -118,9 +119,9 @@
-
- config MMC_SDHCI_OF_ESDHC
- tristate "SDHCI OF support for the Freescale eSDHC controller"
- - depends on MMC_SDHCI_PLTFM
- - depends on PPC_OF
- + depends on PPC_OF && HAS_DMA
- select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
- + select MMC_SDHCI_PLTFM
- help
- This selects the Freescale eSDHC controller support.
-
- @@ -130,9 +131,9 @@
-
- config MMC_SDHCI_OF_HLWD
- tristate "SDHCI OF support for the Nintendo Wii SDHCI controllers"
- - depends on MMC_SDHCI_PLTFM
- - depends on PPC_OF
- + depends on PPC_OF && HAS_DMA
- select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
- + select MMC_SDHCI_PLTFM
- help
- This selects the Secure Digital Host Controller Interface (SDHCI)
- found in the "Hollywood" chipset of the Nintendo Wii video game
- @@ -144,8 +145,8 @@
-
- config MMC_SDHCI_CNS3XXX
- tristate "SDHCI support on the Cavium Networks CNS3xxx SoC"
- - depends on ARCH_CNS3XXX
- - depends on MMC_SDHCI_PLTFM
- + depends on ARCH_CNS3XXX && HAS_DMA
- + select MMC_SDHCI_PLTFM
- help
- This selects the SDHCI support for CNS3xxx System-on-Chip devices.
-
- @@ -155,9 +156,9 @@
-
- config MMC_SDHCI_ESDHC_IMX
- tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller"
- - depends on ARCH_MXC
- - depends on MMC_SDHCI_PLTFM
- + depends on ARCH_MXC && HAS_DMA
- select MMC_SDHCI_IO_ACCESSORS
- + select MMC_SDHCI_PLTFM
- help
- This selects the Freescale eSDHC/uSDHC controller support
- found on i.MX25, i.MX35 i.MX5x and i.MX6x.
- @@ -168,9 +169,9 @@
-
- config MMC_SDHCI_DOVE
- tristate "SDHCI support on Marvell's Dove SoC"
- - depends on ARCH_DOVE
- - depends on MMC_SDHCI_PLTFM
- + depends on ARCH_DOVE && HAS_DMA
- select MMC_SDHCI_IO_ACCESSORS
- + select MMC_SDHCI_PLTFM
- help
- This selects the Secure Digital Host Controller Interface in
- Marvell's Dove SoC.
- @@ -181,9 +182,9 @@
-
- config MMC_SDHCI_TEGRA
- tristate "SDHCI platform support for the Tegra SD/MMC Controller"
- - depends on ARCH_TEGRA
- - depends on MMC_SDHCI_PLTFM
- + depends on ARCH_TEGRA && HAS_DMA
- select MMC_SDHCI_IO_ACCESSORS
- + select MMC_SDHCI_PLTFM
- help
- This selects the Tegra SD/MMC controller. If you have a Tegra
- platform with SD or MMC devices, say Y or M here.
- @@ -192,7 +193,8 @@
-
- config MMC_SDHCI_S3C
- tristate "SDHCI support on Samsung S3C SoC"
- - depends on MMC_SDHCI && PLAT_SAMSUNG
- + depends on PLAT_SAMSUNG && HAS_DMA
- + select MMC_SDHCI
- help
- This selects the Secure Digital Host Controller Interface (SDHCI)
- often referrered to as the HSMMC block in some of the Samsung S3C
- @@ -204,8 +206,8 @@
-
- config MMC_SDHCI_SIRF
- tristate "SDHCI support on CSR SiRFprimaII and SiRFmarco SoCs"
- - depends on ARCH_SIRF
- - depends on MMC_SDHCI_PLTFM
- + depends on ARCH_SIRF && HAS_DMA
- + select MMC_SDHCI_PLTFM
- help
- This selects the SDHCI support for SiRF System-on-Chip devices.
-
- @@ -215,8 +217,7 @@
-
- config MMC_SDHCI_PXAV3
- tristate "Marvell MMP2 SD Host Controller support (PXAV3)"
- - depends on CLKDEV_LOOKUP
- - select MMC_SDHCI
- + depends on CLKDEV_LOOKUP && HAS_DMA
- select MMC_SDHCI_PLTFM
- default CPU_MMP2
- help
- @@ -228,8 +229,7 @@
-
- config MMC_SDHCI_PXAV2
- tristate "Marvell PXA9XX SD Host Controller support (PXAV2)"
- - depends on CLKDEV_LOOKUP
- - select MMC_SDHCI
- + depends on CLKDEV_LOOKUP && HAS_DMA
- select MMC_SDHCI_PLTFM
- default CPU_PXA910
- help
- @@ -241,7 +241,8 @@
-
- config MMC_SDHCI_SPEAR
- tristate "SDHCI support on ST SPEAr platform"
- - depends on MMC_SDHCI && PLAT_SPEAR
- + depends on PLAT_SPEAR && HAS_DMA
- + select MMC_SDHCI
- help
- This selects the Secure Digital Host Controller Interface (SDHCI)
- often referrered to as the HSMMC block in some of the ST SPEAR range
- @@ -263,7 +264,7 @@
-
- config MMC_SDHCI_BCM_KONA
- tristate "SDHCI support on Broadcom KONA platform"
- - depends on ARCH_BCM
- + depends on ARCH_BCM && HAS_DMA
- select MMC_SDHCI_PLTFM
- help
- This selects the Broadcom Kona Secure Digital Host Controller
- @@ -274,9 +275,9 @@
-
- config MMC_SDHCI_BCM2835
- tristate "SDHCI platform support for the BCM2835 SD/MMC Controller"
- - depends on ARCH_BCM2835
- - depends on MMC_SDHCI_PLTFM
- + depends on ARCH_BCM2835 && HAS_DMA
- select MMC_SDHCI_IO_ACCESSORS
- + select MMC_SDHCI_PLTFM
- help
- This selects the BCM2835 SD/MMC controller. If you have a BCM2835
- platform with SD or MMC devices, say Y or M here.
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-acpi.c linux-3.14.35/drivers/mmc/host/sdhci-acpi.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-acpi.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-acpi.c 2015-03-08 14:27:37.609684501 -0500
- @@ -101,11 +101,19 @@
- }
-
- static const struct sdhci_ops sdhci_acpi_ops_dflt = {
- + .set_clock = sdhci_set_clock,
- .enable_dma = sdhci_acpi_enable_dma,
- + .set_bus_width = sdhci_set_bus_width,
- + .reset = sdhci_reset,
- + .set_uhs_signaling = sdhci_set_uhs_signaling,
- };
-
- static const struct sdhci_ops sdhci_acpi_ops_int = {
- + .set_clock = sdhci_set_clock,
- .enable_dma = sdhci_acpi_enable_dma,
- + .set_bus_width = sdhci_set_bus_width,
- + .reset = sdhci_reset,
- + .set_uhs_signaling = sdhci_set_uhs_signaling,
- .hw_reset = sdhci_acpi_int_hw_reset,
- };
-
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-bcm2835.c linux-3.14.35/drivers/mmc/host/sdhci-bcm2835.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-bcm2835.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-bcm2835.c 2015-03-08 14:27:37.609684501 -0500
- @@ -131,8 +131,12 @@
- .read_l = bcm2835_sdhci_readl,
- .read_w = bcm2835_sdhci_readw,
- .read_b = bcm2835_sdhci_readb,
- + .set_clock = sdhci_set_clock,
- .get_max_clock = sdhci_pltfm_clk_get_max_clock,
- .get_min_clock = bcm2835_sdhci_get_min_clock,
- + .set_bus_width = sdhci_set_bus_width,
- + .reset = sdhci_reset,
- + .set_uhs_signaling = sdhci_set_uhs_signaling,
- };
-
- static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-bcm-kona.c linux-3.14.35/drivers/mmc/host/sdhci-bcm-kona.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-bcm-kona.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-bcm-kona.c 2015-03-08 14:27:37.609684501 -0500
- @@ -205,9 +205,13 @@
- }
-
- static struct sdhci_ops sdhci_bcm_kona_ops = {
- + .set_clock = sdhci_set_clock,
- .get_max_clock = sdhci_bcm_kona_get_max_clk,
- .get_timeout_clock = sdhci_bcm_kona_get_timeout_clock,
- .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
- + .set_bus_width = sdhci_set_bus_width,
- + .reset = sdhci_reset,
- + .set_uhs_signaling = sdhci_set_uhs_signaling,
- .card_event = sdhci_bcm_kona_card_event,
- };
-
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci.c linux-3.14.35/drivers/mmc/host/sdhci.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci.c 2015-03-08 15:06:25.217663190 -0500
- @@ -44,6 +44,8 @@
-
- #define MAX_TUNING_LOOP 40
-
- +#define ADMA_SIZE ((128 * 2 + 1) * 4)
- +
- static unsigned int debug_quirks = 0;
- static unsigned int debug_quirks2;
-
- @@ -131,43 +133,28 @@
- * *
- \*****************************************************************************/
-
- -static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set)
- -{
- - u32 ier;
- -
- - ier = sdhci_readl(host, SDHCI_INT_ENABLE);
- - ier &= ~clear;
- - ier |= set;
- - sdhci_writel(host, ier, SDHCI_INT_ENABLE);
- - sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);
- -}
- -
- -static void sdhci_unmask_irqs(struct sdhci_host *host, u32 irqs)
- -{
- - sdhci_clear_set_irqs(host, 0, irqs);
- -}
- -
- -static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs)
- -{
- - sdhci_clear_set_irqs(host, irqs, 0);
- -}
- -
- static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
- {
- - u32 present, irqs;
- + u32 present;
- + int gpio_cd = mmc_gpio_get_cd(host->mmc);
-
- if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) ||
- - (host->mmc->caps & MMC_CAP_NONREMOVABLE))
- + (host->mmc->caps & MMC_CAP_NONREMOVABLE) ||
- + !IS_ERR_VALUE(gpio_cd))
- return;
-
- - present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
- - SDHCI_CARD_PRESENT;
- - irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
- + if (enable) {
- + present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
- + SDHCI_CARD_PRESENT;
-
- - if (enable)
- - sdhci_unmask_irqs(host, irqs);
- - else
- - sdhci_mask_irqs(host, irqs);
- + host->ier |= present ? SDHCI_INT_CARD_REMOVE :
- + SDHCI_INT_CARD_INSERT;
- + } else {
- + host->ier &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
- + }
- +
- + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
- + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
- }
-
- static void sdhci_enable_card_detection(struct sdhci_host *host)
- @@ -180,22 +167,9 @@
- sdhci_set_card_detection(host, false);
- }
-
- -static void sdhci_reset(struct sdhci_host *host, u8 mask)
- +void sdhci_reset(struct sdhci_host *host, u8 mask)
- {
- unsigned long timeout;
- - u32 uninitialized_var(ier);
- -
- - if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
- - if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) &
- - SDHCI_CARD_PRESENT))
- - return;
- - }
- -
- - if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
- - ier = sdhci_readl(host, SDHCI_INT_ENABLE);
- -
- - if (host->ops->platform_reset_enter)
- - host->ops->platform_reset_enter(host, mask);
-
- sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
-
- @@ -220,16 +194,27 @@
- timeout--;
- mdelay(1);
- }
- +}
- +EXPORT_SYMBOL_GPL(sdhci_reset);
- +
- +static void sdhci_do_reset(struct sdhci_host *host, u8 mask)
- +{
- + if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
- + if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) &
- + SDHCI_CARD_PRESENT))
- + return;
- + }
-
- - if (host->ops->platform_reset_exit)
- - host->ops->platform_reset_exit(host, mask);
- + host->ops->reset(host, mask);
-
- - if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
- - sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier);
- + if (mask & SDHCI_RESET_ALL) {
- + if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
- + if (host->ops->enable_dma)
- + host->ops->enable_dma(host);
- + }
-
- - if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
- - if ((host->ops->enable_dma) && (mask & SDHCI_RESET_ALL))
- - host->ops->enable_dma(host);
- + /* Resetting the controller clears many */
- + host->preset_enabled = false;
- }
- }
-
- @@ -238,15 +223,18 @@
- static void sdhci_init(struct sdhci_host *host, int soft)
- {
- if (soft)
- - sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
- + sdhci_do_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
- else
- - sdhci_reset(host, SDHCI_RESET_ALL);
- + sdhci_do_reset(host, SDHCI_RESET_ALL);
- +
- + host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
- + SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT |
- + SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC |
- + SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
- + SDHCI_INT_RESPONSE;
-
- - sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK,
- - SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
- - SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
- - SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
- - SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE);
- + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
- + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
-
- if (soft) {
- /* force clock reconfiguration */
- @@ -502,11 +490,6 @@
- else
- direction = DMA_TO_DEVICE;
-
- - /*
- - * The ADMA descriptor table is mapped further down as we
- - * need to fill it with data first.
- - */
- -
- host->align_addr = dma_map_single(mmc_dev(host->mmc),
- host->align_buffer, 128 * 4, direction);
- if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr))
- @@ -567,7 +550,7 @@
- * If this triggers then we have a calculation bug
- * somewhere. :/
- */
- - WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4);
- + WARN_ON((desc - host->adma_desc) > ADMA_SIZE);
- }
-
- if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) {
- @@ -595,17 +578,8 @@
- host->align_addr, 128 * 4, direction);
- }
-
- - host->adma_addr = dma_map_single(mmc_dev(host->mmc),
- - host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE);
- - if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr))
- - goto unmap_entries;
- - BUG_ON(host->adma_addr & 0x3);
- -
- return 0;
-
- -unmap_entries:
- - dma_unmap_sg(mmc_dev(host->mmc), data->sg,
- - data->sg_len, direction);
- unmap_align:
- dma_unmap_single(mmc_dev(host->mmc), host->align_addr,
- 128 * 4, direction);
- @@ -623,19 +597,25 @@
- u8 *align;
- char *buffer;
- unsigned long flags;
- + bool has_unaligned;
-
- if (data->flags & MMC_DATA_READ)
- direction = DMA_FROM_DEVICE;
- else
- direction = DMA_TO_DEVICE;
-
- - dma_unmap_single(mmc_dev(host->mmc), host->adma_addr,
- - (128 * 2 + 1) * 4, DMA_TO_DEVICE);
- -
- dma_unmap_single(mmc_dev(host->mmc), host->align_addr,
- 128 * 4, direction);
-
- - if (data->flags & MMC_DATA_READ) {
- + /* Do a quick scan of the SG list for any unaligned mappings */
- + has_unaligned = false;
- + for_each_sg(data->sg, sg, host->sg_count, i)
- + if (sg_dma_address(sg) & 3) {
- + has_unaligned = true;
- + break;
- + }
- +
- + if (has_unaligned && data->flags & MMC_DATA_READ) {
- dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg,
- data->sg_len, direction);
-
- @@ -721,9 +701,12 @@
- u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR;
-
- if (host->flags & SDHCI_REQ_USE_DMA)
- - sdhci_clear_set_irqs(host, pio_irqs, dma_irqs);
- + host->ier = (host->ier & ~pio_irqs) | dma_irqs;
- else
- - sdhci_clear_set_irqs(host, dma_irqs, pio_irqs);
- + host->ier = (host->ier & ~dma_irqs) | pio_irqs;
- +
- + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
- + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
- }
-
- static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
- @@ -976,8 +959,8 @@
- * upon error conditions.
- */
- if (data->error) {
- - sdhci_reset(host, SDHCI_RESET_CMD);
- - sdhci_reset(host, SDHCI_RESET_DATA);
- + sdhci_do_reset(host, SDHCI_RESET_CMD);
- + sdhci_do_reset(host, SDHCI_RESET_DATA);
- }
-
- sdhci_send_command(host, data->stop);
- @@ -1107,24 +1090,23 @@
-
- static u16 sdhci_get_preset_value(struct sdhci_host *host)
- {
- - u16 ctrl, preset = 0;
- -
- - ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- + u16 preset = 0;
-
- - switch (ctrl & SDHCI_CTRL_UHS_MASK) {
- - case SDHCI_CTRL_UHS_SDR12:
- + switch (host->timing) {
- + case MMC_TIMING_UHS_SDR12:
- preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);
- break;
- - case SDHCI_CTRL_UHS_SDR25:
- + case MMC_TIMING_UHS_SDR25:
- preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR25);
- break;
- - case SDHCI_CTRL_UHS_SDR50:
- + case MMC_TIMING_UHS_SDR50:
- preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR50);
- break;
- - case SDHCI_CTRL_UHS_SDR104:
- + case MMC_TIMING_UHS_SDR104:
- + case MMC_TIMING_MMC_HS200:
- preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104);
- break;
- - case SDHCI_CTRL_UHS_DDR50:
- + case MMC_TIMING_UHS_DDR50:
- preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50);
- break;
- default:
- @@ -1136,32 +1118,22 @@
- return preset;
- }
-
- -static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
- +void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
- {
- int div = 0; /* Initialized for compiler warning */
- int real_div = div, clk_mul = 1;
- u16 clk = 0;
- unsigned long timeout;
-
- - if (clock && clock == host->clock)
- - return;
- -
- host->mmc->actual_clock = 0;
-
- - if (host->ops->set_clock) {
- - host->ops->set_clock(host, clock);
- - if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK)
- - return;
- - }
- -
- sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
-
- if (clock == 0)
- - goto out;
- + return;
-
- if (host->version >= SDHCI_SPEC_300) {
- - if (sdhci_readw(host, SDHCI_HOST_CONTROL2) &
- - SDHCI_CTRL_PRESET_VAL_ENABLE) {
- + if (host->preset_enabled) {
- u16 pre_val;
-
- clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
- @@ -1247,26 +1219,16 @@
-
- clk |= SDHCI_CLOCK_CARD_EN;
- sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
- -
- -out:
- - host->clock = clock;
- -}
- -
- -static inline void sdhci_update_clock(struct sdhci_host *host)
- -{
- - unsigned int clock;
- -
- - clock = host->clock;
- - host->clock = 0;
- - sdhci_set_clock(host, clock);
- }
- +EXPORT_SYMBOL_GPL(sdhci_set_clock);
-
- -static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
- +static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
- + unsigned short vdd)
- {
- u8 pwr = 0;
-
- - if (power != (unsigned short)-1) {
- - switch (1 << power) {
- + if (mode != MMC_POWER_OFF) {
- + switch (1 << vdd) {
- case MMC_VDD_165_195:
- pwr = SDHCI_POWER_180;
- break;
- @@ -1284,7 +1246,7 @@
- }
-
- if (host->pwr == pwr)
- - return -1;
- + return;
-
- host->pwr = pwr;
-
- @@ -1292,38 +1254,43 @@
- sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
- if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
- sdhci_runtime_pm_bus_off(host);
- - return 0;
- - }
- -
- - /*
- - * Spec says that we should clear the power reg before setting
- - * a new value. Some controllers don't seem to like this though.
- - */
- - if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
- - sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
- + vdd = 0;
- + } else {
- + /*
- + * Spec says that we should clear the power reg before setting
- + * a new value. Some controllers don't seem to like this though.
- + */
- + if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
- + sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
-
- - /*
- - * At least the Marvell CaFe chip gets confused if we set the voltage
- - * and set turn on power at the same time, so set the voltage first.
- - */
- - if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
- - sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
- + /*
- + * At least the Marvell CaFe chip gets confused if we set the
- + * voltage and set turn on power at the same time, so set the
- + * voltage first.
- + */
- + if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
- + sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
-
- - pwr |= SDHCI_POWER_ON;
- + pwr |= SDHCI_POWER_ON;
-
- - sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
- + sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
-
- - if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
- - sdhci_runtime_pm_bus_on(host);
- + if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
- + sdhci_runtime_pm_bus_on(host);
-
- - /*
- - * Some controllers need an extra 10ms delay of 10ms before they
- - * can apply clock after applying power
- - */
- - if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
- - mdelay(10);
- + /*
- + * Some controllers need an extra 10ms delay of 10ms before
- + * they can apply clock after applying power
- + */
- + if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
- + mdelay(10);
- + }
-
- - return power;
- + if (host->vmmc) {
- + spin_unlock_irq(&host->lock);
- + mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd);
- + spin_lock_irq(&host->lock);
- + }
- }
-
- /*****************************************************************************\
- @@ -1428,10 +1395,52 @@
- spin_unlock_irqrestore(&host->lock, flags);
- }
-
- +void sdhci_set_bus_width(struct sdhci_host *host, int width)
- +{
- + u8 ctrl;
- +
- + ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
- + if (width == MMC_BUS_WIDTH_8) {
- + ctrl &= ~SDHCI_CTRL_4BITBUS;
- + if (host->version >= SDHCI_SPEC_300)
- + ctrl |= SDHCI_CTRL_8BITBUS;
- + } else {
- + if (host->version >= SDHCI_SPEC_300)
- + ctrl &= ~SDHCI_CTRL_8BITBUS;
- + if (width == MMC_BUS_WIDTH_4)
- + ctrl |= SDHCI_CTRL_4BITBUS;
- + else
- + ctrl &= ~SDHCI_CTRL_4BITBUS;
- + }
- + sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
- +}
- +EXPORT_SYMBOL_GPL(sdhci_set_bus_width);
- +
- +void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
- +{
- + u16 ctrl_2;
- +
- + ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- + /* Select Bus Speed Mode for host */
- + ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
- + if ((timing == MMC_TIMING_MMC_HS200) ||
- + (timing == MMC_TIMING_UHS_SDR104))
- + ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
- + else if (timing == MMC_TIMING_UHS_SDR12)
- + ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
- + else if (timing == MMC_TIMING_UHS_SDR25)
- + ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
- + else if (timing == MMC_TIMING_UHS_SDR50)
- + ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
- + else if (timing == MMC_TIMING_UHS_DDR50)
- + ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
- + sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
- +}
- +EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);
- +
- static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
- {
- unsigned long flags;
- - int vdd_bit = -1;
- u8 ctrl;
-
- spin_lock_irqsave(&host->lock, flags);
- @@ -1457,45 +1466,17 @@
- !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN))
- sdhci_enable_preset_value(host, false);
-
- - sdhci_set_clock(host, ios->clock);
- -
- - if (ios->power_mode == MMC_POWER_OFF)
- - vdd_bit = sdhci_set_power(host, -1);
- - else
- - vdd_bit = sdhci_set_power(host, ios->vdd);
- -
- - if (host->vmmc && vdd_bit != -1) {
- - spin_unlock_irqrestore(&host->lock, flags);
- - mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd_bit);
- - spin_lock_irqsave(&host->lock, flags);
- + if (!ios->clock || ios->clock != host->clock) {
- + host->ops->set_clock(host, ios->clock);
- + host->clock = ios->clock;
- }
-
- + sdhci_set_power(host, ios->power_mode, ios->vdd);
- +
- if (host->ops->platform_send_init_74_clocks)
- host->ops->platform_send_init_74_clocks(host, ios->power_mode);
-
- - /*
- - * If your platform has 8-bit width support but is not a v3 controller,
- - * or if it requires special setup code, you should implement that in
- - * platform_bus_width().
- - */
- - if (host->ops->platform_bus_width) {
- - host->ops->platform_bus_width(host, ios->bus_width);
- - } else {
- - ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
- - if (ios->bus_width == MMC_BUS_WIDTH_8) {
- - ctrl &= ~SDHCI_CTRL_4BITBUS;
- - if (host->version >= SDHCI_SPEC_300)
- - ctrl |= SDHCI_CTRL_8BITBUS;
- - } else {
- - if (host->version >= SDHCI_SPEC_300)
- - ctrl &= ~SDHCI_CTRL_8BITBUS;
- - if (ios->bus_width == MMC_BUS_WIDTH_4)
- - ctrl |= SDHCI_CTRL_4BITBUS;
- - else
- - ctrl &= ~SDHCI_CTRL_4BITBUS;
- - }
- - sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
- - }
- + host->ops->set_bus_width(host, ios->bus_width);
-
- ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
-
- @@ -1517,13 +1498,13 @@
- (ios->timing == MMC_TIMING_UHS_SDR25))
- ctrl |= SDHCI_CTRL_HISPD;
-
- - ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- - if (!(ctrl_2 & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
- + if (!host->preset_enabled) {
- sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
- /*
- * We only need to set Driver Strength if the
- * preset value enable is not set.
- */
- + ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK;
- if (ios->drv_type == MMC_SET_DRIVER_TYPE_A)
- ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A;
- @@ -1547,34 +1528,16 @@
- sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-
- /* Re-enable SD Clock */
- - sdhci_update_clock(host);
- + host->ops->set_clock(host, host->clock);
- }
-
- -
- /* Reset SD Clock Enable */
- clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
- clk &= ~SDHCI_CLOCK_CARD_EN;
- sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-
- - if (host->ops->set_uhs_signaling)
- - host->ops->set_uhs_signaling(host, ios->timing);
- - else {
- - ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- - /* Select Bus Speed Mode for host */
- - ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
- - if ((ios->timing == MMC_TIMING_MMC_HS200) ||
- - (ios->timing == MMC_TIMING_UHS_SDR104))
- - ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
- - else if (ios->timing == MMC_TIMING_UHS_SDR12)
- - ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
- - else if (ios->timing == MMC_TIMING_UHS_SDR25)
- - ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
- - else if (ios->timing == MMC_TIMING_UHS_SDR50)
- - ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
- - else if (ios->timing == MMC_TIMING_UHS_DDR50)
- - ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
- - sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
- - }
- + host->ops->set_uhs_signaling(host, ios->timing);
- + host->timing = ios->timing;
-
- if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&
- ((ios->timing == MMC_TIMING_UHS_SDR12) ||
- @@ -1590,8 +1553,7 @@
- >> SDHCI_PRESET_DRV_SHIFT;
- }
-
- - /* Re-enable SD Clock */
- - sdhci_update_clock(host);
- + host->ops->set_clock(host, host->clock);
- } else
- sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-
- @@ -1601,7 +1563,7 @@
- * it on each ios seems to solve the problem.
- */
- if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS)
- - sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
- + sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
-
- mmiowb();
- spin_unlock_irqrestore(&host->lock, flags);
- @@ -1710,24 +1672,16 @@
-
- static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
- {
- - if (host->flags & SDHCI_DEVICE_DEAD)
- - goto out;
- -
- - if (enable)
- - host->flags |= SDHCI_SDIO_IRQ_ENABLED;
- - else
- - host->flags &= ~SDHCI_SDIO_IRQ_ENABLED;
- -
- - /* SDIO IRQ will be enabled as appropriate in runtime resume */
- - if (host->runtime_suspended)
- - goto out;
- + if (!(host->flags & SDHCI_DEVICE_DEAD)) {
- + if (enable)
- + host->ier |= SDHCI_INT_CARD_INT;
- + else
- + host->ier &= ~SDHCI_INT_CARD_INT;
-
- - if (enable)
- - sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT);
- - else
- - sdhci_mask_irqs(host, SDHCI_INT_CARD_INT);
- -out:
- - mmiowb();
- + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
- + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
- + mmiowb();
- + }
- }
-
- static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
- @@ -1735,9 +1689,18 @@
- struct sdhci_host *host = mmc_priv(mmc);
- unsigned long flags;
-
- + sdhci_runtime_pm_get(host);
- +
- spin_lock_irqsave(&host->lock, flags);
- + if (enable)
- + host->flags |= SDHCI_SDIO_IRQ_ENABLED;
- + else
- + host->flags &= ~SDHCI_SDIO_IRQ_ENABLED;
- +
- sdhci_enable_sdio_irq_nolock(host, enable);
- spin_unlock_irqrestore(&host->lock, flags);
- +
- + sdhci_runtime_pm_put(host);
- }
-
- static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
- @@ -1856,22 +1819,16 @@
-
- static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
- {
- - struct sdhci_host *host;
- + struct sdhci_host *host = mmc_priv(mmc);
- u16 ctrl;
- - u32 ier;
- int tuning_loop_counter = MAX_TUNING_LOOP;
- unsigned long timeout;
- int err = 0;
- - bool requires_tuning_nonuhs = false;
- unsigned long flags;
-
- - host = mmc_priv(mmc);
- -
- sdhci_runtime_pm_get(host);
- spin_lock_irqsave(&host->lock, flags);
-
- - ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- -
- /*
- * The Host Controller needs tuning only in case of SDR104 mode
- * and for SDR50 mode when Use Tuning for SDR50 is set in the
- @@ -1879,15 +1836,18 @@
- * If the Host Controller supports the HS200 mode then the
- * tuning function has to be executed.
- */
- - if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) &&
- - (host->flags & SDHCI_SDR50_NEEDS_TUNING ||
- - host->flags & SDHCI_SDR104_NEEDS_TUNING))
- - requires_tuning_nonuhs = true;
- -
- - if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) ||
- - requires_tuning_nonuhs)
- - ctrl |= SDHCI_CTRL_EXEC_TUNING;
- - else {
- + switch (host->timing) {
- + case MMC_TIMING_MMC_HS200:
- + case MMC_TIMING_UHS_SDR104:
- + break;
- +
- + case MMC_TIMING_UHS_SDR50:
- + if (host->flags & SDHCI_SDR50_NEEDS_TUNING ||
- + host->flags & SDHCI_SDR104_NEEDS_TUNING)
- + break;
- + /* FALLTHROUGH */
- +
- + default:
- spin_unlock_irqrestore(&host->lock, flags);
- sdhci_runtime_pm_put(host);
- return 0;
- @@ -1900,6 +1860,8 @@
- return err;
- }
-
- + ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- + ctrl |= SDHCI_CTRL_EXEC_TUNING;
- sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-
- /*
- @@ -1912,8 +1874,8 @@
- * to make sure we don't hit a controller bug, we _only_
- * enable Buffer Read Ready interrupt here.
- */
- - ier = sdhci_readl(host, SDHCI_INT_ENABLE);
- - sdhci_clear_set_irqs(host, ier, SDHCI_INT_DATA_AVAIL);
- + sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
- + sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
-
- /*
- * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number
- @@ -2046,7 +2008,8 @@
- if (err && (host->flags & SDHCI_USING_RETUNING_TIMER))
- err = 0;
-
- - sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier);
- + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
- + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
- spin_unlock_irqrestore(&host->lock, flags);
- sdhci_runtime_pm_put(host);
-
- @@ -2056,26 +2019,30 @@
-
- static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)
- {
- - u16 ctrl;
- -
- /* Host Controller v3.00 defines preset value registers */
- if (host->version < SDHCI_SPEC_300)
- return;
-
- - ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- -
- /*
- * We only enable or disable Preset Value if they are not already
- * enabled or disabled respectively. Otherwise, we bail out.
- */
- - if (enable && !(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
- - ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
- - sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
- - host->flags |= SDHCI_PV_ENABLED;
- - } else if (!enable && (ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
- - ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
- + if (host->preset_enabled != enable) {
- + u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- +
- + if (enable)
- + ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
- + else
- + ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
- +
- sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
- - host->flags &= ~SDHCI_PV_ENABLED;
- +
- + if (enable)
- + host->flags |= SDHCI_PV_ENABLED;
- + else
- + host->flags &= ~SDHCI_PV_ENABLED;
- +
- + host->preset_enabled = enable;
- }
- }
-
- @@ -2100,8 +2067,8 @@
- pr_err("%s: Resetting controller.\n",
- mmc_hostname(host->mmc));
-
- - sdhci_reset(host, SDHCI_RESET_CMD);
- - sdhci_reset(host, SDHCI_RESET_DATA);
- + sdhci_do_reset(host, SDHCI_RESET_CMD);
- + sdhci_do_reset(host, SDHCI_RESET_DATA);
-
- host->mrq->cmd->error = -ENOMEDIUM;
- tasklet_schedule(&host->finish_tasklet);
- @@ -2129,15 +2096,6 @@
- * *
- \*****************************************************************************/
-
- -static void sdhci_tasklet_card(unsigned long param)
- -{
- - struct sdhci_host *host = (struct sdhci_host*)param;
- -
- - sdhci_card_event(host->mmc);
- -
- - mmc_detect_change(host->mmc, msecs_to_jiffies(200));
- -}
- -
- static void sdhci_tasklet_finish(unsigned long param)
- {
- struct sdhci_host *host;
- @@ -2174,12 +2132,12 @@
- /* Some controllers need this kick or reset won't work here */
- if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
- /* This is to force an update */
- - sdhci_update_clock(host);
- + host->ops->set_clock(host, host->clock);
-
- /* Spec says we should do both at the same time, but Ricoh
- controllers do not like that. */
- - sdhci_reset(host, SDHCI_RESET_CMD);
- - sdhci_reset(host, SDHCI_RESET_DATA);
- + sdhci_do_reset(host, SDHCI_RESET_CMD);
- + sdhci_do_reset(host, SDHCI_RESET_DATA);
- }
-
- host->mrq = NULL;
- @@ -2429,14 +2387,14 @@
-
- static irqreturn_t sdhci_irq(int irq, void *dev_id)
- {
- - irqreturn_t result;
- + irqreturn_t result = IRQ_NONE;
- struct sdhci_host *host = dev_id;
- - u32 intmask, unexpected = 0;
- - int cardint = 0, max_loops = 16;
- + u32 intmask, mask, unexpected = 0;
- + int max_loops = 16;
-
- spin_lock(&host->lock);
-
- - if (host->runtime_suspended) {
- + if (host->runtime_suspended && !sdhci_sdio_irq_enabled(host)) {
- spin_unlock(&host->lock);
- pr_warning("%s: got irq while runtime suspended\n",
- mmc_hostname(host->mmc));
- @@ -2444,88 +2402,81 @@
- }
-
- intmask = sdhci_readl(host, SDHCI_INT_STATUS);
- -
- if (!intmask || intmask == 0xffffffff) {
- result = IRQ_NONE;
- goto out;
- }
-
- -again:
- - DBG("*** %s got interrupt: 0x%08x\n",
- - mmc_hostname(host->mmc), intmask);
- -
- - if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
- - u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
- - SDHCI_CARD_PRESENT;
- -
- - /*
- - * There is a observation on i.mx esdhc. INSERT bit will be
- - * immediately set again when it gets cleared, if a card is
- - * inserted. We have to mask the irq to prevent interrupt
- - * storm which will freeze the system. And the REMOVE gets
- - * the same situation.
- - *
- - * More testing are needed here to ensure it works for other
- - * platforms though.
- - */
- - sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
- - SDHCI_INT_CARD_REMOVE);
- - sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
- - SDHCI_INT_CARD_INSERT);
- -
- - sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
- - SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
- - intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
- - tasklet_schedule(&host->card_tasklet);
- - }
- -
- - if (intmask & SDHCI_INT_CMD_MASK) {
- - sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
- - SDHCI_INT_STATUS);
- - sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
- - }
- + do {
- + /* Clear selected interrupts. */
- + mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
- + SDHCI_INT_BUS_POWER);
- + sdhci_writel(host, mask, SDHCI_INT_STATUS);
- +
- + DBG("*** %s got interrupt: 0x%08x\n",
- + mmc_hostname(host->mmc), intmask);
- +
- + if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
- + u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
- + SDHCI_CARD_PRESENT;
-
- - if (intmask & SDHCI_INT_DATA_MASK) {
- - sdhci_writel(host, intmask & SDHCI_INT_DATA_MASK,
- - SDHCI_INT_STATUS);
- - sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
- - }
- + /*
- + * There is a observation on i.mx esdhc. INSERT
- + * bit will be immediately set again when it gets
- + * cleared, if a card is inserted. We have to mask
- + * the irq to prevent interrupt storm which will
- + * freeze the system. And the REMOVE gets the
- + * same situation.
- + *
- + * More testing are needed here to ensure it works
- + * for other platforms though.
- + */
- + host->ier &= ~(SDHCI_INT_CARD_INSERT |
- + SDHCI_INT_CARD_REMOVE);
- + host->ier |= present ? SDHCI_INT_CARD_REMOVE :
- + SDHCI_INT_CARD_INSERT;
- + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
- + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
-
- - intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK);
- + sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
- + SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
-
- - intmask &= ~SDHCI_INT_ERROR;
- + host->thread_isr |= intmask & (SDHCI_INT_CARD_INSERT |
- + SDHCI_INT_CARD_REMOVE);
- + result = IRQ_WAKE_THREAD;
- + }
-
- - if (intmask & SDHCI_INT_BUS_POWER) {
- - pr_err("%s: Card is consuming too much power!\n",
- - mmc_hostname(host->mmc));
- - sdhci_writel(host, SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS);
- - }
- + if (intmask & SDHCI_INT_CMD_MASK)
- + sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
-
- - intmask &= ~SDHCI_INT_BUS_POWER;
- + if (intmask & SDHCI_INT_DATA_MASK)
- + sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
-
- - if (intmask & SDHCI_INT_CARD_INT)
- - cardint = 1;
- + if (intmask & SDHCI_INT_BUS_POWER)
- + pr_err("%s: Card is consuming too much power!\n",
- + mmc_hostname(host->mmc));
-
- - intmask &= ~SDHCI_INT_CARD_INT;
- + if (intmask & SDHCI_INT_CARD_INT) {
- + sdhci_enable_sdio_irq_nolock(host, false);
- + host->thread_isr |= SDHCI_INT_CARD_INT;
- + result = IRQ_WAKE_THREAD;
- + }
-
- - if (intmask) {
- - unexpected |= intmask;
- - sdhci_writel(host, intmask, SDHCI_INT_STATUS);
- - }
- + intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE |
- + SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
- + SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER |
- + SDHCI_INT_CARD_INT);
-
- - result = IRQ_HANDLED;
- + if (intmask) {
- + unexpected |= intmask;
- + sdhci_writel(host, intmask, SDHCI_INT_STATUS);
- + }
-
- - intmask = sdhci_readl(host, SDHCI_INT_STATUS);
- + if (result == IRQ_NONE)
- + result = IRQ_HANDLED;
-
- - /*
- - * If we know we'll call the driver to signal SDIO IRQ, disregard
- - * further indications of Card Interrupt in the status to avoid a
- - * needless loop.
- - */
- - if (cardint)
- - intmask &= ~SDHCI_INT_CARD_INT;
- - if (intmask && --max_loops)
- - goto again;
- + intmask = sdhci_readl(host, SDHCI_INT_STATUS);
- + } while (intmask && --max_loops);
- out:
- spin_unlock(&host->lock);
-
- @@ -2534,15 +2485,38 @@
- mmc_hostname(host->mmc), unexpected);
- sdhci_dumpregs(host);
- }
- - /*
- - * We have to delay this as it calls back into the driver.
- - */
- - if (cardint && host->mmc->sdio_irqs)
- - mmc_signal_sdio_irq(host->mmc);
- -
- return result;
- }
-
- +static irqreturn_t sdhci_thread_irq(int irq, void *dev_id)
- +{
- + struct sdhci_host *host = dev_id;
- + unsigned long flags;
- + u32 isr;
- +
- + spin_lock_irqsave(&host->lock, flags);
- + isr = host->thread_isr;
- + host->thread_isr = 0;
- + spin_unlock_irqrestore(&host->lock, flags);
- +
- + if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
- + sdhci_card_event(host->mmc);
- + mmc_detect_change(host->mmc, msecs_to_jiffies(200));
- + }
- +
- + if (isr & SDHCI_INT_CARD_INT) {
- + sdio_run_irqs(host->mmc);
- +
- + spin_lock_irqsave(&host->lock, flags);
- + if (host->flags & SDHCI_SDIO_IRQ_ENABLED)
- + sdhci_enable_sdio_irq_nolock(host, true);
- + spin_unlock_irqrestore(&host->lock, flags);
- + }
- +
- + return isr ? IRQ_HANDLED : IRQ_NONE;
- +}
- +
- +
- /*****************************************************************************\
- * *
- * Suspend/resume *
- @@ -2552,6 +2526,7 @@
- #ifdef CONFIG_PM
- void sdhci_enable_irq_wakeups(struct sdhci_host *host)
- {
- + int gpio_cd = mmc_gpio_get_cd(host->mmc);
- u8 val;
- u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE
- | SDHCI_WAKE_ON_INT;
- @@ -2559,7 +2534,8 @@
- val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL);
- val |= mask ;
- /* Avoid fake wake up */
- - if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
- + if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION ||
- + !IS_ERR_VALUE(gpio_cd))
- val &= ~(SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE);
- sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL);
- }
- @@ -2579,9 +2555,6 @@
-
- int sdhci_suspend_host(struct sdhci_host *host)
- {
- - if (host->ops->platform_suspend)
- - host->ops->platform_suspend(host);
- -
- sdhci_disable_card_detection(host);
-
- /* Disable tuning since we are suspending */
- @@ -2591,7 +2564,9 @@
- }
-
- if (!device_may_wakeup(mmc_dev(host->mmc))) {
- - sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
- + host->ier = 0;
- + sdhci_writel(host, 0, SDHCI_INT_ENABLE);
- + sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
- free_irq(host->irq, host);
- } else {
- sdhci_enable_irq_wakeups(host);
- @@ -2612,8 +2587,9 @@
- }
-
- if (!device_may_wakeup(mmc_dev(host->mmc))) {
- - ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
- - mmc_hostname(host->mmc), host);
- + ret = request_threaded_irq(host->irq, sdhci_irq,
- + sdhci_thread_irq, IRQF_SHARED,
- + mmc_hostname(host->mmc), host);
- if (ret)
- return ret;
- } else {
- @@ -2635,9 +2611,6 @@
-
- sdhci_enable_card_detection(host);
-
- - if (host->ops->platform_resume)
- - host->ops->platform_resume(host);
- -
- /* Set the re-tuning expiration flag */
- if (host->flags & SDHCI_USING_RETUNING_TIMER)
- host->flags |= SDHCI_NEEDS_RETUNING;
- @@ -2689,10 +2662,12 @@
- }
-
- spin_lock_irqsave(&host->lock, flags);
- - sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
- + host->ier &= SDHCI_INT_CARD_INT;
- + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
- + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
- spin_unlock_irqrestore(&host->lock, flags);
-
- - synchronize_irq(host->irq);
- + synchronize_hardirq(host->irq);
-
- spin_lock_irqsave(&host->lock, flags);
- host->runtime_suspended = true;
- @@ -2736,7 +2711,7 @@
- host->runtime_suspended = false;
-
- /* Enable SDIO IRQ */
- - if ((host->flags & SDHCI_SDIO_IRQ_ENABLED))
- + if (host->flags & SDHCI_SDIO_IRQ_ENABLED)
- sdhci_enable_sdio_irq_nolock(host, true);
-
- /* Enable Card Detection */
- @@ -2750,6 +2725,7 @@
-
- #endif
-
- +
- /*****************************************************************************\
- * *
- * Device allocation/registration *
- @@ -2795,7 +2771,7 @@
- if (debug_quirks2)
- host->quirks2 = debug_quirks2;
-
- - sdhci_reset(host, SDHCI_RESET_ALL);
- + sdhci_do_reset(host, SDHCI_RESET_ALL);
-
- host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
- host->version = (host->version & SDHCI_SPEC_VER_MASK)
- @@ -2855,15 +2831,29 @@
- * (128) and potentially one alignment transfer for
- * each of those entries.
- */
- - host->adma_desc = kmalloc((128 * 2 + 1) * 4, GFP_KERNEL);
- + host->adma_desc = dma_alloc_coherent(mmc_dev(host->mmc),
- + ADMA_SIZE, &host->adma_addr,
- + GFP_KERNEL);
- host->align_buffer = kmalloc(128 * 4, GFP_KERNEL);
- if (!host->adma_desc || !host->align_buffer) {
- - kfree(host->adma_desc);
- + dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
- + host->adma_desc, host->adma_addr);
- kfree(host->align_buffer);
- pr_warning("%s: Unable to allocate ADMA "
- "buffers. Falling back to standard DMA.\n",
- mmc_hostname(mmc));
- host->flags &= ~SDHCI_USE_ADMA;
- + host->adma_desc = NULL;
- + host->align_buffer = NULL;
- + } else if (host->adma_addr & 3) {
- + pr_warning("%s: unable to allocate aligned ADMA descriptor\n",
- + mmc_hostname(mmc));
- + host->flags &= ~SDHCI_USE_ADMA;
- + dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
- + host->adma_desc, host->adma_addr);
- + kfree(host->align_buffer);
- + host->adma_desc = NULL;
- + host->align_buffer = NULL;
- }
- }
-
- @@ -2945,9 +2935,22 @@
- if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
- host->timeout_clk = mmc->f_max / 1000;
-
- - mmc->max_discard_to = (1 << 27) / host->timeout_clk;
- + if (host->quirks2 & SDHCI_QUIRK2_NOSTD_TIMEOUT_COUNTER) {
- + if (host->ops->get_max_timeout_counter) {
- + mmc->max_discard_to =
- + host->ops->get_max_timeout_counter(host)
- + / host->timeout_clk;
- + } else {
- + pr_err("%s: Hardware doesn't specify max timeout "
- + "counter\n", mmc_hostname(mmc));
- + return -ENODEV;
- + }
- + } else {
- + mmc->max_discard_to = (1 << 27) / host->timeout_clk;
- + }
-
- mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
- + mmc->caps2 |= MMC_CAP2_SDIO_NOTHREAD;
-
- if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
- host->flags |= SDHCI_AUTO_CMD12;
- @@ -3218,8 +3221,6 @@
- /*
- * Init tasklets.
- */
- - tasklet_init(&host->card_tasklet,
- - sdhci_tasklet_card, (unsigned long)host);
- tasklet_init(&host->finish_tasklet,
- sdhci_tasklet_finish, (unsigned long)host);
-
- @@ -3236,8 +3237,8 @@
-
- sdhci_init(host, 0);
-
- - ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
- - mmc_hostname(mmc), host);
- + ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq,
- + IRQF_SHARED, mmc_hostname(mmc), host);
- if (ret) {
- pr_err("%s: Failed to request IRQ %d: %d\n",
- mmc_hostname(mmc), host->irq, ret);
- @@ -3279,12 +3280,12 @@
-
- #ifdef SDHCI_USE_LEDS_CLASS
- reset:
- - sdhci_reset(host, SDHCI_RESET_ALL);
- - sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
- + sdhci_do_reset(host, SDHCI_RESET_ALL);
- + sdhci_writel(host, 0, SDHCI_INT_ENABLE);
- + sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
- free_irq(host->irq, host);
- #endif
- untasklet:
- - tasklet_kill(&host->card_tasklet);
- tasklet_kill(&host->finish_tasklet);
-
- return ret;
- @@ -3321,14 +3322,14 @@
- #endif
-
- if (!dead)
- - sdhci_reset(host, SDHCI_RESET_ALL);
- + sdhci_do_reset(host, SDHCI_RESET_ALL);
-
- - sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
- + sdhci_writel(host, 0, SDHCI_INT_ENABLE);
- + sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
- free_irq(host->irq, host);
-
- del_timer_sync(&host->timer);
-
- - tasklet_kill(&host->card_tasklet);
- tasklet_kill(&host->finish_tasklet);
-
- if (host->vmmc) {
- @@ -3341,7 +3342,9 @@
- regulator_put(host->vqmmc);
- }
-
- - kfree(host->adma_desc);
- + if (host->adma_desc)
- + dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
- + host->adma_desc, host->adma_addr);
- kfree(host->align_buffer);
-
- host->adma_desc = NULL;
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-cns3xxx.c linux-3.14.35/drivers/mmc/host/sdhci-cns3xxx.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-cns3xxx.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-cns3xxx.c 2015-03-08 14:27:37.613684501 -0500
- @@ -30,13 +30,12 @@
- u16 clk;
- unsigned long timeout;
-
- - if (clock == host->clock)
- - return;
- + host->mmc->actual_clock = 0;
-
- sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
-
- if (clock == 0)
- - goto out;
- + return;
-
- while (host->max_clk / div > clock) {
- /*
- @@ -75,13 +74,14 @@
-
- clk |= SDHCI_CLOCK_CARD_EN;
- sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
- -out:
- - host->clock = clock;
- }
-
- static const struct sdhci_ops sdhci_cns3xxx_ops = {
- .get_max_clock = sdhci_cns3xxx_get_max_clk,
- .set_clock = sdhci_cns3xxx_set_clock,
- + .set_bus_width = sdhci_set_bus_width,
- + .reset = sdhci_reset,
- + .set_uhs_signaling = sdhci_set_uhs_signaling,
- };
-
- static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
- @@ -90,8 +90,7 @@
- SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
- SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
- SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
- - SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
- - SDHCI_QUIRK_NONSTANDARD_CLOCK,
- + SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
- };
-
- static int sdhci_cns3xxx_probe(struct platform_device *pdev)
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-dove.c linux-3.14.35/drivers/mmc/host/sdhci-dove.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-dove.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-dove.c 2015-03-08 14:27:37.613684501 -0500
- @@ -86,6 +86,10 @@
- static const struct sdhci_ops sdhci_dove_ops = {
- .read_w = sdhci_dove_readw,
- .read_l = sdhci_dove_readl,
- + .set_clock = sdhci_set_clock,
- + .set_bus_width = sdhci_set_bus_width,
- + .reset = sdhci_reset,
- + .set_uhs_signaling = sdhci_set_uhs_signaling,
- };
-
- static const struct sdhci_pltfm_data sdhci_dove_pdata = {
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-esdhc.h linux-3.14.35/drivers/mmc/host/sdhci-esdhc.h
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-esdhc.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-esdhc.h 2015-03-08 14:27:37.613684501 -0500
- @@ -20,12 +20,11 @@
-
- #define ESDHC_DEFAULT_QUIRKS (SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \
- SDHCI_QUIRK_NO_BUSY_IRQ | \
- - SDHCI_QUIRK_NONSTANDARD_CLOCK | \
- SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
- - SDHCI_QUIRK_PIO_NEEDS_DELAY | \
- - SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
- + SDHCI_QUIRK_PIO_NEEDS_DELAY)
-
- #define ESDHC_SYSTEM_CONTROL 0x2c
- +#define ESDHC_SYS_CTRL_RSTA (1 << 24)
- #define ESDHC_CLOCK_MASK 0x0000fff0
- #define ESDHC_PREDIV_SHIFT 8
- #define ESDHC_DIVIDER_SHIFT 4
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-esdhc-imx.c linux-3.14.35/drivers/mmc/host/sdhci-esdhc-imx.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-esdhc-imx.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-esdhc-imx.c 2015-03-08 14:27:37.613684501 -0500
- @@ -11,6 +11,7 @@
- * the Free Software Foundation; either version 2 of the License.
- */
-
- +#include <linux/busfreq-imx6.h>
- #include <linux/io.h>
- #include <linux/delay.h>
- #include <linux/err.h>
- @@ -114,6 +115,10 @@
- #define ESDHC_FLAG_STD_TUNING BIT(5)
- /* The IP has SDHCI_CAPABILITIES_1 register */
- #define ESDHC_FLAG_HAVE_CAP1 BIT(6)
- +/* The IP has errata ERR004536 */
- +#define ESDHC_FLAG_ERR004536 BIT(7)
- +/* need request bus freq during low power */
- +#define ESDHC_FLAG_BUSFREQ BIT(8)
-
- struct esdhc_soc_data {
- u32 flags;
- @@ -141,7 +146,8 @@
-
- static struct esdhc_soc_data usdhc_imx6sl_data = {
- .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
- - | ESDHC_FLAG_HAVE_CAP1,
- + | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_ERR004536
- + | ESDHC_FLAG_BUSFREQ,
- };
-
- struct pltfm_imx_data {
- @@ -160,7 +166,6 @@
- MULTIBLK_IN_PROCESS, /* exact multiblock cmd in process */
- WAIT_FOR_INT, /* sent CMD12, waiting for response INT */
- } multiblock_status;
- - u32 uhs_mode;
- u32 is_ddr;
- };
-
- @@ -382,7 +387,6 @@
- if (val & ESDHC_MIX_CTRL_SMPCLK_SEL)
- ret |= SDHCI_CTRL_TUNED_CLK;
-
- - ret |= (imx_data->uhs_mode & SDHCI_CTRL_UHS_MASK);
- ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
-
- return ret;
- @@ -429,7 +433,6 @@
- else
- new_val &= ~ESDHC_VENDOR_SPEC_VSELECT;
- writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
- - imx_data->uhs_mode = val & SDHCI_CTRL_UHS_MASK;
- if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
- new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
- if (val & SDHCI_CTRL_TUNED_CLK)
- @@ -600,12 +603,14 @@
- u32 temp, val;
-
- if (clock == 0) {
- + host->mmc->actual_clock = 0;
- +
- if (esdhc_is_usdhc(imx_data)) {
- val = readl(host->ioaddr + ESDHC_VENDOR_SPEC);
- writel(val & ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
- host->ioaddr + ESDHC_VENDOR_SPEC);
- }
- - goto out;
- + return;
- }
-
- if (esdhc_is_usdhc(imx_data) && !imx_data->is_ddr)
- @@ -645,8 +650,6 @@
- }
-
- mdelay(1);
- -out:
- - host->clock = clock;
- }
-
- static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
- @@ -668,7 +671,7 @@
- return -ENOSYS;
- }
-
- -static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
- +static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
- {
- u32 ctrl;
-
- @@ -686,17 +689,56 @@
-
- esdhc_clrset_le(host, ESDHC_CTRL_BUSWIDTH_MASK, ctrl,
- SDHCI_HOST_CONTROL);
- +}
-
- - return 0;
- +static void esdhc_tuning_reset(struct sdhci_host *host, u32 rst_bits)
- +{
- + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- + struct pltfm_imx_data *imx_data = pltfm_host->priv;
- + u32 timeout;
- + u32 reg;
- +
- + reg = readl(host->ioaddr + ESDHC_SYSTEM_CONTROL);
- + reg |= rst_bits;
- + writel(reg, host->ioaddr + ESDHC_SYSTEM_CONTROL);
- +
- + /* Wait for max 100ms */
- + timeout = 100;
- +
- + /* hw clears the bit when it's done */
- + while (readl(host->ioaddr + ESDHC_SYSTEM_CONTROL) & rst_bits) {
- + if (timeout == 0) {
- + dev_err(mmc_dev(host->mmc),
- + "Reset never completes!\n");
- + return;
- + }
- + timeout--;
- + mdelay(1);
- + }
- +
- + /*
- + * The RSTA, reset all, on usdhc will not clear following regs:
- + * > SDHCI_MIX_CTRL
- + * > SDHCI_TUNE_CTRL_STATUS
- + *
- + * Do it manually here.
- + */
- + if ((rst_bits & ESDHC_SYS_CTRL_RSTA) && is_imx6q_usdhc(imx_data)) {
- + writel(0, host->ioaddr + ESDHC_MIX_CTRL);
- + writel(0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
- + /* FIXME: delay for clear tuning status or some cards may not work */
- + mdelay(1);
- + }
- }
-
- static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
- {
- u32 reg;
-
- - /* FIXME: delay a bit for card to be ready for next tuning due to errors */
- - mdelay(1);
- + /* reset controller before tuning or it may fail on some cards */
- + esdhc_tuning_reset(host, ESDHC_SYS_CTRL_RSTA);
-
- + /* This is balanced by the runtime put in sdhci_tasklet_finish */
- pm_runtime_get_sync(host->mmc->parent);
- reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
- reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL |
- @@ -713,13 +755,12 @@
- complete(&mrq->completion);
- }
-
- -static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode)
- +static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode,
- + struct scatterlist *sg)
- {
- struct mmc_command cmd = {0};
- struct mmc_request mrq = {NULL};
- struct mmc_data data = {0};
- - struct scatterlist sg;
- - char tuning_pattern[ESDHC_TUNING_BLOCK_PATTERN_LEN];
-
- cmd.opcode = opcode;
- cmd.arg = 0;
- @@ -728,11 +769,9 @@
- data.blksz = ESDHC_TUNING_BLOCK_PATTERN_LEN;
- data.blocks = 1;
- data.flags = MMC_DATA_READ;
- - data.sg = &sg;
- + data.sg = sg;
- data.sg_len = 1;
-
- - sg_init_one(&sg, tuning_pattern, sizeof(tuning_pattern));
- -
- mrq.cmd = &cmd;
- mrq.cmd->mrq = &mrq;
- mrq.data = &data;
- @@ -742,14 +781,12 @@
- mrq.done = esdhc_request_done;
- init_completion(&(mrq.completion));
-
- - disable_irq(host->irq);
- - spin_lock(&host->lock);
- + spin_lock_irq(&host->lock);
- host->mrq = &mrq;
-
- sdhci_send_command(host, mrq.cmd);
-
- - spin_unlock(&host->lock);
- - enable_irq(host->irq);
- + spin_unlock_irq(&host->lock);
-
- wait_for_completion(&mrq.completion);
-
- @@ -772,13 +809,21 @@
-
- static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
- {
- + struct scatterlist sg;
- + char *tuning_pattern;
- int min, max, avg, ret;
-
- + tuning_pattern = kmalloc(ESDHC_TUNING_BLOCK_PATTERN_LEN, GFP_KERNEL);
- + if (!tuning_pattern)
- + return -ENOMEM;
- +
- + sg_init_one(&sg, tuning_pattern, ESDHC_TUNING_BLOCK_PATTERN_LEN);
- +
- /* find the mininum delay first which can pass tuning */
- min = ESDHC_TUNE_CTRL_MIN;
- while (min < ESDHC_TUNE_CTRL_MAX) {
- esdhc_prepare_tuning(host, min);
- - if (!esdhc_send_tuning_cmd(host, opcode))
- + if (!esdhc_send_tuning_cmd(host, opcode, &sg))
- break;
- min += ESDHC_TUNE_CTRL_STEP;
- }
- @@ -787,7 +832,7 @@
- max = min + ESDHC_TUNE_CTRL_STEP;
- while (max < ESDHC_TUNE_CTRL_MAX) {
- esdhc_prepare_tuning(host, max);
- - if (esdhc_send_tuning_cmd(host, opcode)) {
- + if (esdhc_send_tuning_cmd(host, opcode, &sg)) {
- max -= ESDHC_TUNE_CTRL_STEP;
- break;
- }
- @@ -797,9 +842,11 @@
- /* use average delay to get the best timing */
- avg = (min + max) / 2;
- esdhc_prepare_tuning(host, avg);
- - ret = esdhc_send_tuning_cmd(host, opcode);
- + ret = esdhc_send_tuning_cmd(host, opcode, &sg);
- esdhc_post_tuning(host);
-
- + kfree(tuning_pattern);
- +
- dev_dbg(mmc_dev(host->mmc), "tunning %s at 0x%x ret %d\n",
- ret ? "failed" : "passed", avg, ret);
-
- @@ -837,28 +884,20 @@
- return pinctrl_select_state(imx_data->pinctrl, pinctrl);
- }
-
- -static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
- +static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
- {
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct pltfm_imx_data *imx_data = pltfm_host->priv;
- struct esdhc_platform_data *boarddata = &imx_data->boarddata;
-
- - switch (uhs) {
- + switch (timing) {
- case MMC_TIMING_UHS_SDR12:
- - imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR12;
- - break;
- case MMC_TIMING_UHS_SDR25:
- - imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR25;
- - break;
- case MMC_TIMING_UHS_SDR50:
- - imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR50;
- - break;
- case MMC_TIMING_UHS_SDR104:
- case MMC_TIMING_MMC_HS200:
- - imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR104;
- break;
- case MMC_TIMING_UHS_DDR50:
- - imx_data->uhs_mode = SDHCI_CTRL_UHS_DDR50;
- writel(readl(host->ioaddr + ESDHC_MIX_CTRL) |
- ESDHC_MIX_CTRL_DDREN,
- host->ioaddr + ESDHC_MIX_CTRL);
- @@ -875,7 +914,20 @@
- break;
- }
-
- - return esdhc_change_pinstate(host, uhs);
- + esdhc_change_pinstate(host, timing);
- +}
- +
- +static void esdhc_reset(struct sdhci_host *host, u8 mask)
- +{
- + sdhci_reset(host, mask);
- +
- + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
- + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
- +}
- +
- +static unsigned int esdhc_get_max_timeout_counter(struct sdhci_host *host)
- +{
- + return 1 << 28;
- }
-
- static struct sdhci_ops sdhci_esdhc_ops = {
- @@ -888,8 +940,9 @@
- .get_max_clock = esdhc_pltfm_get_max_clock,
- .get_min_clock = esdhc_pltfm_get_min_clock,
- .get_ro = esdhc_pltfm_get_ro,
- - .platform_bus_width = esdhc_pltfm_bus_width,
- + .set_bus_width = esdhc_pltfm_set_bus_width,
- .set_uhs_signaling = esdhc_set_uhs_signaling,
- + .reset = esdhc_reset,
- };
-
- static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
- @@ -906,6 +959,7 @@
- struct esdhc_platform_data *boarddata)
- {
- struct device_node *np = pdev->dev.of_node;
- + struct sdhci_host *host = platform_get_drvdata(pdev);
-
- if (!np)
- return -ENODEV;
- @@ -939,6 +993,12 @@
- if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line))
- boarddata->delay_line = 0;
-
- + if (of_find_property(np, "keep-power-in-suspend", NULL))
- + host->mmc->pm_caps |= MMC_PM_KEEP_POWER;
- +
- + if (of_find_property(np, "enable-sdio-wakeup", NULL))
- + host->mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
- +
- return 0;
- }
- #else
- @@ -994,6 +1054,9 @@
- goto free_sdhci;
- }
-
- + if (imx_data->socdata->flags & ESDHC_FLAG_BUSFREQ)
- + request_bus_freq(BUS_FREQ_HIGH);
- +
- pltfm_host->clk = imx_data->clk_per;
- pltfm_host->clock = clk_get_rate(pltfm_host->clk);
- clk_prepare_enable(imx_data->clk_per);
- @@ -1027,8 +1090,17 @@
- */
- if (esdhc_is_usdhc(imx_data)) {
- writel(0x08100810, host->ioaddr + ESDHC_WTMK_LVL);
- - host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
- + host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
- + SDHCI_QUIRK2_NOSTD_TIMEOUT_COUNTER;
- host->mmc->caps |= MMC_CAP_1_8V_DDR;
- +
- + /*
- + * errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
- + * TO1.1, it's harmless for MX6SL
- + */
- + writel(readl(host->ioaddr + 0x6c) | BIT(7), host->ioaddr + 0x6c);
- + sdhci_esdhc_ops.get_max_timeout_counter =
- + esdhc_get_max_timeout_counter;
- }
-
- if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
- @@ -1040,6 +1112,9 @@
- ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP,
- host->ioaddr + ESDHC_TUNING_CTRL);
-
- + if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
- + host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
- +
- boarddata = &imx_data->boarddata;
- if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) {
- if (!host->mmc->parent->platform_data) {
- @@ -1116,6 +1191,10 @@
- host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
- }
-
- + if (host->mmc->pm_caps & MMC_PM_KEEP_POWER &&
- + host->mmc->pm_caps & MMC_PM_WAKE_SDIO_IRQ)
- + device_init_wakeup(&pdev->dev, 1);
- +
- err = sdhci_add_host(host);
- if (err)
- goto disable_clk;
- @@ -1132,6 +1211,8 @@
- clk_disable_unprepare(imx_data->clk_per);
- clk_disable_unprepare(imx_data->clk_ipg);
- clk_disable_unprepare(imx_data->clk_ahb);
- + if (imx_data->socdata->flags & ESDHC_FLAG_BUSFREQ)
- + release_bus_freq(BUS_FREQ_HIGH);
- free_sdhci:
- sdhci_pltfm_free(pdev);
- return err;
- @@ -1170,10 +1251,15 @@
-
- ret = sdhci_runtime_suspend_host(host);
-
- - clk_disable_unprepare(imx_data->clk_per);
- - clk_disable_unprepare(imx_data->clk_ipg);
- + if (!sdhci_sdio_irq_enabled(host)) {
- + clk_disable_unprepare(imx_data->clk_per);
- + clk_disable_unprepare(imx_data->clk_ipg);
- + }
- clk_disable_unprepare(imx_data->clk_ahb);
-
- + if (imx_data->socdata->flags & ESDHC_FLAG_BUSFREQ)
- + release_bus_freq(BUS_FREQ_HIGH);
- +
- return ret;
- }
-
- @@ -1183,8 +1269,10 @@
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct pltfm_imx_data *imx_data = pltfm_host->priv;
-
- - clk_prepare_enable(imx_data->clk_per);
- - clk_prepare_enable(imx_data->clk_ipg);
- + if (!sdhci_sdio_irq_enabled(host)) {
- + clk_prepare_enable(imx_data->clk_per);
- + clk_prepare_enable(imx_data->clk_ipg);
- + }
- clk_prepare_enable(imx_data->clk_ahb);
-
- return sdhci_runtime_resume_host(host);
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci.h linux-3.14.35/drivers/mmc/host/sdhci.h
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci.h 2015-03-08 14:27:37.613684501 -0500
- @@ -281,18 +281,15 @@
- unsigned int (*get_max_clock)(struct sdhci_host *host);
- unsigned int (*get_min_clock)(struct sdhci_host *host);
- unsigned int (*get_timeout_clock)(struct sdhci_host *host);
- - int (*platform_bus_width)(struct sdhci_host *host,
- - int width);
- + unsigned int (*get_max_timeout_counter)(struct sdhci_host *host);
- + void (*set_bus_width)(struct sdhci_host *host, int width);
- void (*platform_send_init_74_clocks)(struct sdhci_host *host,
- u8 power_mode);
- unsigned int (*get_ro)(struct sdhci_host *host);
- - void (*platform_reset_enter)(struct sdhci_host *host, u8 mask);
- - void (*platform_reset_exit)(struct sdhci_host *host, u8 mask);
- + void (*reset)(struct sdhci_host *host, u8 mask);
- int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
- - int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
- + void (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
- void (*hw_reset)(struct sdhci_host *host);
- - void (*platform_suspend)(struct sdhci_host *host);
- - void (*platform_resume)(struct sdhci_host *host);
- void (*adma_workaround)(struct sdhci_host *host, u32 intmask);
- void (*platform_init)(struct sdhci_host *host);
- void (*card_event)(struct sdhci_host *host);
- @@ -397,6 +394,16 @@
- extern void sdhci_send_command(struct sdhci_host *host,
- struct mmc_command *cmd);
-
- +static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host)
- +{
- + return !!(host->flags & SDHCI_SDIO_IRQ_ENABLED);
- +}
- +
- +void sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
- +void sdhci_set_bus_width(struct sdhci_host *host, int width);
- +void sdhci_reset(struct sdhci_host *host, u8 mask);
- +void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
- +
- #ifdef CONFIG_PM
- extern int sdhci_suspend_host(struct sdhci_host *host);
- extern int sdhci_resume_host(struct sdhci_host *host);
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-of-arasan.c linux-3.14.35/drivers/mmc/host/sdhci-of-arasan.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-of-arasan.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-of-arasan.c 2015-03-08 14:27:37.613684501 -0500
- @@ -52,8 +52,12 @@
- }
-
- static struct sdhci_ops sdhci_arasan_ops = {
- + .set_clock = sdhci_set_clock,
- .get_max_clock = sdhci_pltfm_clk_get_max_clock,
- .get_timeout_clock = sdhci_arasan_get_timeout_clock,
- + .set_bus_width = sdhci_set_bus_width,
- + .reset = sdhci_reset,
- + .set_uhs_signaling = sdhci_set_uhs_signaling,
- };
-
- static struct sdhci_pltfm_data sdhci_arasan_pdata = {
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-of-esdhc.c linux-3.14.35/drivers/mmc/host/sdhci-of-esdhc.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-of-esdhc.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-of-esdhc.c 2015-03-08 14:27:37.613684501 -0500
- @@ -199,13 +199,14 @@
-
- static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
- {
- -
- int pre_div = 2;
- int div = 1;
- u32 temp;
-
- + host->mmc->actual_clock = 0;
- +
- if (clock == 0)
- - goto out;
- + return;
-
- /* Workaround to reduce the clock frequency for p1010 esdhc */
- if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) {
- @@ -238,24 +239,8 @@
- | (pre_div << ESDHC_PREDIV_SHIFT));
- sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
- mdelay(1);
- -out:
- - host->clock = clock;
- }
-
- -#ifdef CONFIG_PM
- -static u32 esdhc_proctl;
- -static void esdhc_of_suspend(struct sdhci_host *host)
- -{
- - esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
- -}
- -
- -static void esdhc_of_resume(struct sdhci_host *host)
- -{
- - esdhc_of_enable_dma(host);
- - sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
- -}
- -#endif
- -
- static void esdhc_of_platform_init(struct sdhci_host *host)
- {
- u32 vvn;
- @@ -269,7 +254,7 @@
- host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
- }
-
- -static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
- +static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
- {
- u32 ctrl;
-
- @@ -289,8 +274,6 @@
-
- clrsetbits_be32(host->ioaddr + SDHCI_HOST_CONTROL,
- ESDHC_CTRL_BUSWIDTH_MASK, ctrl);
- -
- - return 0;
- }
-
- static const struct sdhci_ops sdhci_esdhc_ops = {
- @@ -305,13 +288,46 @@
- .get_max_clock = esdhc_of_get_max_clock,
- .get_min_clock = esdhc_of_get_min_clock,
- .platform_init = esdhc_of_platform_init,
- -#ifdef CONFIG_PM
- - .platform_suspend = esdhc_of_suspend,
- - .platform_resume = esdhc_of_resume,
- -#endif
- .adma_workaround = esdhci_of_adma_workaround,
- - .platform_bus_width = esdhc_pltfm_bus_width,
- + .set_bus_width = esdhc_pltfm_set_bus_width,
- + .reset = sdhci_reset,
- + .set_uhs_signaling = sdhci_set_uhs_signaling,
- +};
- +
- +#ifdef CONFIG_PM
- +
- +static u32 esdhc_proctl;
- +static int esdhc_of_suspend(struct device *dev)
- +{
- + struct sdhci_host *host = dev_get_drvdata(dev);
- +
- + esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
- +
- + return sdhci_suspend_host(host);
- +}
- +
- +static void esdhc_of_resume(device *dev)
- +{
- + struct sdhci_host *host = dev_get_drvdata(dev);
- + int ret = sdhci_resume_host(host);
- +
- + if (ret == 0) {
- + /* Isn't this already done by sdhci_resume_host() ? --rmk */
- + esdhc_of_enable_dma(host);
- + sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
- + }
- +
- + return ret;
- +}
- +
- +static const struct dev_pm_ops esdhc_pmops = {
- + .suspend = esdhci_of_suspend,
- + .resume = esdhci_of_resume,
- };
- +#define ESDHC_PMOPS (&esdhc_pmops)
- +#else
- +#define ESDHC_PMOPS NULL
- +#endif
-
- static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
- /*
- @@ -374,7 +390,7 @@
- .name = "sdhci-esdhc",
- .owner = THIS_MODULE,
- .of_match_table = sdhci_esdhc_of_match,
- - .pm = SDHCI_PLTFM_PMOPS,
- + .pm = ESDHC_PMOPS,
- },
- .probe = sdhci_esdhc_probe,
- .remove = sdhci_esdhc_remove,
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-of-hlwd.c linux-3.14.35/drivers/mmc/host/sdhci-of-hlwd.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-of-hlwd.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-of-hlwd.c 2015-03-08 14:27:37.613684501 -0500
- @@ -58,6 +58,10 @@
- .write_l = sdhci_hlwd_writel,
- .write_w = sdhci_hlwd_writew,
- .write_b = sdhci_hlwd_writeb,
- + .set_clock = sdhci_set_clock,
- + .set_bus_width = sdhci_set_bus_width,
- + .reset = sdhci_reset,
- + .set_uhs_signaling = sdhci_set_uhs_signaling,
- };
-
- static const struct sdhci_pltfm_data sdhci_hlwd_pdata = {
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-pci.c linux-3.14.35/drivers/mmc/host/sdhci-pci.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-pci.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-pci.c 2015-03-08 14:27:37.613684501 -0500
- @@ -1023,7 +1023,7 @@
- return 0;
- }
-
- -static int sdhci_pci_bus_width(struct sdhci_host *host, int width)
- +static void sdhci_pci_set_bus_width(struct sdhci_host *host, int width)
- {
- u8 ctrl;
-
- @@ -1044,8 +1044,6 @@
- }
-
- sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
- -
- - return 0;
- }
-
- static void sdhci_pci_gpio_hw_reset(struct sdhci_host *host)
- @@ -1072,8 +1070,11 @@
- }
-
- static const struct sdhci_ops sdhci_pci_ops = {
- + .set_clock = sdhci_set_clock,
- .enable_dma = sdhci_pci_enable_dma,
- - .platform_bus_width = sdhci_pci_bus_width,
- + .set_bus_width = sdhci_pci_set_bus_width,
- + .reset = sdhci_reset,
- + .set_uhs_signaling = sdhci_set_uhs_signaling,
- .hw_reset = sdhci_pci_hw_reset,
- };
-
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-pltfm.c linux-3.14.35/drivers/mmc/host/sdhci-pltfm.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-pltfm.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-pltfm.c 2015-03-08 14:27:37.613684501 -0500
- @@ -45,6 +45,10 @@
- EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock);
-
- static const struct sdhci_ops sdhci_pltfm_ops = {
- + .set_clock = sdhci_set_clock,
- + .set_bus_width = sdhci_set_bus_width,
- + .reset = sdhci_reset,
- + .set_uhs_signaling = sdhci_set_uhs_signaling,
- };
-
- #ifdef CONFIG_OF
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-pxav2.c linux-3.14.35/drivers/mmc/host/sdhci-pxav2.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-pxav2.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-pxav2.c 2015-03-08 14:27:37.613684501 -0500
- @@ -51,11 +51,13 @@
- #define MMC_CARD 0x1000
- #define MMC_WIDTH 0x0100
-
- -static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask)
- +static void pxav2_reset(struct sdhci_host *host, u8 mask)
- {
- struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
- struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
-
- + sdhci_reset(host, mask);
- +
- if (mask == SDHCI_RESET_ALL) {
- u16 tmp = 0;
-
- @@ -88,7 +90,7 @@
- }
- }
-
- -static int pxav2_mmc_set_width(struct sdhci_host *host, int width)
- +static void pxav2_mmc_set_bus_width(struct sdhci_host *host, int width)
- {
- u8 ctrl;
- u16 tmp;
- @@ -107,14 +109,14 @@
- }
- writew(tmp, host->ioaddr + SD_CE_ATA_2);
- writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
- -
- - return 0;
- }
-
- static const struct sdhci_ops pxav2_sdhci_ops = {
- + .set_clock = sdhci_set_clock,
- .get_max_clock = sdhci_pltfm_clk_get_max_clock,
- - .platform_reset_exit = pxav2_set_private_registers,
- - .platform_bus_width = pxav2_mmc_set_width,
- + .set_bus_width = pxav2_mmc_set_bus_width,
- + .reset = pxav2_reset,
- + .set_uhs_signaling = sdhci_set_uhs_signaling,
- };
-
- #ifdef CONFIG_OF
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-pxav3.c linux-3.14.35/drivers/mmc/host/sdhci-pxav3.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-pxav3.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-pxav3.c 2015-03-08 14:27:37.613684501 -0500
- @@ -57,11 +57,13 @@
- #define SDCE_MISC_INT (1<<2)
- #define SDCE_MISC_INT_EN (1<<1)
-
- -static void pxav3_set_private_registers(struct sdhci_host *host, u8 mask)
- +static void pxav3_reset(struct sdhci_host *host, u8 mask)
- {
- struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
- struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
-
- + sdhci_reset(host, mask);
- +
- if (mask == SDHCI_RESET_ALL) {
- /*
- * tune timing of read data/command when crc error happen
- @@ -129,7 +131,7 @@
- pxa->power_mode = power_mode;
- }
-
- -static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
- +static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
- {
- u16 ctrl_2;
-
- @@ -163,15 +165,16 @@
- dev_dbg(mmc_dev(host->mmc),
- "%s uhs = %d, ctrl_2 = %04X\n",
- __func__, uhs, ctrl_2);
- -
- - return 0;
- }
-
- static const struct sdhci_ops pxav3_sdhci_ops = {
- - .platform_reset_exit = pxav3_set_private_registers,
- + .set_clock = sdhci_set_clock,
- .set_uhs_signaling = pxav3_set_uhs_signaling,
- .platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
- .get_max_clock = sdhci_pltfm_clk_get_max_clock,
- + .set_bus_width = sdhci_set_bus_width,
- + .reset = pxav3_reset,
- + .set_uhs_signaling = sdhci_set_uhs_signaling,
- };
-
- static struct sdhci_pltfm_data sdhci_pxav3_pdata = {
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-s3c.c linux-3.14.35/drivers/mmc/host/sdhci-s3c.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-s3c.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-s3c.c 2015-03-08 14:27:37.613684501 -0500
- @@ -57,6 +57,8 @@
-
- struct clk *clk_io;
- struct clk *clk_bus[MAX_BUS_CLK];
- +
- + bool no_divider;
- };
-
- /**
- @@ -69,6 +71,7 @@
- */
- struct sdhci_s3c_drv_data {
- unsigned int sdhci_quirks;
- + bool no_divider;
- };
-
- static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
- @@ -153,7 +156,7 @@
- * If controller uses a non-standard clock division, find the best clock
- * speed possible with selected clock source and skip the division.
- */
- - if (ourhost->host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
- + if (ourhost->no_divider) {
- rate = clk_round_rate(clksrc, wanted);
- return wanted - rate;
- }
- @@ -188,9 +191,13 @@
- int src;
- u32 ctrl;
-
- + host->mmc->actual_clock = 0;
- +
- /* don't bother if the clock is going off. */
- - if (clock == 0)
- + if (clock == 0) {
- + sdhci_set_clock(host, clock);
- return;
- + }
-
- for (src = 0; src < MAX_BUS_CLK; src++) {
- delta = sdhci_s3c_consider_clock(ourhost, src, clock);
- @@ -240,6 +247,8 @@
- if (clock < 25 * 1000000)
- ctrl |= (S3C_SDHCI_CTRL3_FCSEL3 | S3C_SDHCI_CTRL3_FCSEL2);
- writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL3);
- +
- + sdhci_set_clock(host, clock);
- }
-
- /**
- @@ -296,10 +305,11 @@
- unsigned long timeout;
- u16 clk = 0;
-
- + host->mmc->actual_clock = 0;
- +
- /* If the clock is going off, set to 0 at clock control register */
- if (clock == 0) {
- sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
- - host->clock = clock;
- return;
- }
-
- @@ -307,8 +317,6 @@
-
- clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);
-
- - host->clock = clock;
- -
- clk = SDHCI_CLOCK_INT_EN;
- sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-
- @@ -330,14 +338,14 @@
- }
-
- /**
- - * sdhci_s3c_platform_bus_width - support 8bit buswidth
- + * sdhci_s3c_set_bus_width - support 8bit buswidth
- * @host: The SDHCI host being queried
- * @width: MMC_BUS_WIDTH_ macro for the bus width being requested
- *
- * We have 8-bit width support but is not a v3 controller.
- * So we add platform_bus_width() and support 8bit width.
- */
- -static int sdhci_s3c_platform_bus_width(struct sdhci_host *host, int width)
- +static void sdhci_s3c_set_bus_width(struct sdhci_host *host, int width)
- {
- u8 ctrl;
-
- @@ -359,15 +367,15 @@
- }
-
- sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
- -
- - return 0;
- }
-
- static struct sdhci_ops sdhci_s3c_ops = {
- .get_max_clock = sdhci_s3c_get_max_clk,
- .set_clock = sdhci_s3c_set_clock,
- .get_min_clock = sdhci_s3c_get_min_clock,
- - .platform_bus_width = sdhci_s3c_platform_bus_width,
- + .set_bus_width = sdhci_s3c_set_bus_width,
- + .reset = sdhci_reset,
- + .set_uhs_signaling = sdhci_set_uhs_signaling,
- };
-
- static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
- @@ -617,8 +625,10 @@
- /* Setup quirks for the controller */
- host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
- host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
- - if (drv_data)
- + if (drv_data) {
- host->quirks |= drv_data->sdhci_quirks;
- + sc->no_divider = drv_data->no_divider;
- + }
-
- #ifndef CONFIG_MMC_SDHCI_S3C_DMA
-
- @@ -667,7 +677,7 @@
- * If controller does not have internal clock divider,
- * we can use overriding functions instead of default.
- */
- - if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
- + if (sc->no_divider) {
- sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock;
- sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock;
- sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock;
- @@ -813,7 +823,7 @@
-
- #if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212)
- static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = {
- - .sdhci_quirks = SDHCI_QUIRK_NONSTANDARD_CLOCK,
- + .no_divider = true,
- };
- #define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)&exynos4_sdhci_drv_data)
- #else
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-sirf.c linux-3.14.35/drivers/mmc/host/sdhci-sirf.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-sirf.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-sirf.c 2015-03-08 14:27:37.613684501 -0500
- @@ -28,7 +28,11 @@
- }
-
- static struct sdhci_ops sdhci_sirf_ops = {
- + .set_clock = sdhci_set_clock,
- .get_max_clock = sdhci_sirf_get_max_clk,
- + .set_bus_width = sdhci_set_bus_width,
- + .reset = sdhci_reset,
- + .set_uhs_signaling = sdhci_set_uhs_signaling,
- };
-
- static struct sdhci_pltfm_data sdhci_sirf_pdata = {
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-spear.c linux-3.14.35/drivers/mmc/host/sdhci-spear.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-spear.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-spear.c 2015-03-08 14:27:37.613684501 -0500
- @@ -37,7 +37,10 @@
-
- /* sdhci ops */
- static const struct sdhci_ops sdhci_pltfm_ops = {
- - /* Nothing to do for now. */
- + .set_clock = sdhci_set_clock,
- + .set_bus_width = sdhci_set_bus_width,
- + .reset = sdhci_reset,
- + .set_uhs_signaling = sdhci_set_uhs_signaling,
- };
-
- /* gpio card detection interrupt handler */
- diff -Nur linux-3.14.35.orig/drivers/mmc/host/sdhci-tegra.c linux-3.14.35/drivers/mmc/host/sdhci-tegra.c
- --- linux-3.14.35.orig/drivers/mmc/host/sdhci-tegra.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mmc/host/sdhci-tegra.c 2015-03-08 14:27:37.613684501 -0500
- @@ -48,19 +48,6 @@
- int power_gpio;
- };
-
- -static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg)
- -{
- - u32 val;
- -
- - if (unlikely(reg == SDHCI_PRESENT_STATE)) {
- - /* Use wp_gpio here instead? */
- - val = readl(host->ioaddr + reg);
- - return val | SDHCI_WRITE_PROTECT;
- - }
- -
- - return readl(host->ioaddr + reg);
- -}
- -
- static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
- {
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- @@ -108,12 +95,14 @@
- return mmc_gpio_get_ro(host->mmc);
- }
-
- -static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask)
- +static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
- {
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct sdhci_tegra *tegra_host = pltfm_host->priv;
- const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
-
- + sdhci_reset(host, mask);
- +
- if (!(mask & SDHCI_RESET_ALL))
- return;
-
- @@ -127,7 +116,7 @@
- }
- }
-
- -static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width)
- +static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width)
- {
- u32 ctrl;
-
- @@ -144,16 +133,16 @@
- ctrl &= ~SDHCI_CTRL_4BITBUS;
- }
- sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
- - return 0;
- }
-
- static const struct sdhci_ops tegra_sdhci_ops = {
- .get_ro = tegra_sdhci_get_ro,
- - .read_l = tegra_sdhci_readl,
- .read_w = tegra_sdhci_readw,
- .write_l = tegra_sdhci_writel,
- - .platform_bus_width = tegra_sdhci_buswidth,
- - .platform_reset_exit = tegra_sdhci_reset_exit,
- + .set_clock = sdhci_set_clock,
- + .set_bus_width = tegra_sdhci_set_bus_width,
- + .reset = tegra_sdhci_reset,
- + .set_uhs_signaling = sdhci_set_uhs_signaling,
- };
-
- static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
- diff -Nur linux-3.14.35.orig/drivers/mtd/chips/cfi_cmdset_0002.c linux-3.14.35/drivers/mtd/chips/cfi_cmdset_0002.c
- --- linux-3.14.35.orig/drivers/mtd/chips/cfi_cmdset_0002.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mtd/chips/cfi_cmdset_0002.c 2015-03-08 14:27:37.613684501 -0500
- @@ -1058,17 +1058,13 @@
-
- #define UDELAY(map, chip, adr, usec) \
- do { \
- - mutex_unlock(&chip->mutex); \
- cfi_udelay(usec); \
- - mutex_lock(&chip->mutex); \
- } while (0)
-
- #define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \
- do { \
- - mutex_unlock(&chip->mutex); \
- INVALIDATE_CACHED_RANGE(map, adr, len); \
- cfi_udelay(usec); \
- - mutex_lock(&chip->mutex); \
- } while (0)
-
- #endif
- diff -Nur linux-3.14.35.orig/drivers/mtd/ubi/build.c linux-3.14.35/drivers/mtd/ubi/build.c
- --- linux-3.14.35.orig/drivers/mtd/ubi/build.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/mtd/ubi/build.c 2015-03-08 14:27:37.617684501 -0500
- @@ -640,7 +640,7 @@
- dbg_gen("sizeof(struct ubi_ainf_peb) %zu", sizeof(struct ubi_ainf_peb));
- dbg_gen("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry));
-
- - if (ubi->mtd->numeraseregions != 0) {
- + if (ubi->mtd->numeraseregions > 1) {
- /*
- * Some flashes have several erase regions. Different regions
- * may have different eraseblock size and other
- diff -Nur linux-3.14.35.orig/drivers/mxc/asrc/Kconfig linux-3.14.35/drivers/mxc/asrc/Kconfig
- --- linux-3.14.35.orig/drivers/mxc/asrc/Kconfig 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/asrc/Kconfig 2015-03-08 14:27:37.617684501 -0500
- @@ -0,0 +1,14 @@
- +#
- +# ASRC configuration
- +#
- +
- +menu "MXC Asynchronous Sample Rate Converter support"
- +
- +config MXC_ASRC
- + tristate "ASRC support"
- + depends on SOC_IMX35 || SOC_IMX53 || SOC_IMX6Q
- + select SND_SOC_FSL_ASRC
- + ---help---
- + Say Y to get the ASRC service.
- +
- +endmenu
- diff -Nur linux-3.14.35.orig/drivers/mxc/asrc/Makefile linux-3.14.35/drivers/mxc/asrc/Makefile
- --- linux-3.14.35.orig/drivers/mxc/asrc/Makefile 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/asrc/Makefile 2015-03-08 14:27:37.617684501 -0500
- @@ -0,0 +1,4 @@
- +#
- +# Makefile for the kernel Asynchronous Sample Rate Converter driver
- +#
- +obj-$(CONFIG_MXC_ASRC) += mxc_asrc.o
- diff -Nur linux-3.14.35.orig/drivers/mxc/asrc/mxc_asrc.c linux-3.14.35/drivers/mxc/asrc/mxc_asrc.c
- --- linux-3.14.35.orig/drivers/mxc/asrc/mxc_asrc.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/asrc/mxc_asrc.c 2015-03-08 14:27:37.617684501 -0500
- @@ -0,0 +1,1957 @@
- +/*
- + * Freescale Asynchronous Sample Rate Converter (ASRC) driver
- + *
- + * Copyright 2008-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * This file is licensed under the terms of the GNU General Public License
- + * version 2. This program is licensed "as is" without any warranty of any
- + * kind, whether express or implied.
- + */
- +
- +#include <linux/clk.h>
- +#include <linux/slab.h>
- +#include <linux/delay.h>
- +#include <linux/sched.h>
- +#include <linux/regmap.h>
- +#include <linux/module.h>
- +#include <linux/proc_fs.h>
- +#include <linux/pagemap.h>
- +#include <linux/interrupt.h>
- +#include <linux/miscdevice.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/of_platform.h>
- +#include <linux/platform_data/dma-imx.h>
- +
- +#include <linux/mxc_asrc.h>
- +
- +#define ASRC_PROC_PATH "driver/asrc"
- +
- +#define ASRC_RATIO_DECIMAL_DEPTH 26
- +
- +#define pair_err(fmt, ...) \
- + dev_err(asrc->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
- +
- +#define pair_dbg(fmt, ...) \
- + dev_dbg(asrc->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
- +
- +DEFINE_SPINLOCK(data_lock);
- +DEFINE_SPINLOCK(pair_lock);
- +
- +/* Sample rates are aligned with that defined in pcm.h file */
- +static const unsigned char asrc_process_table[][8][2] = {
- + /* 32kHz 44.1kHz 48kHz 64kHz 88.2kHz 96kHz 176kHz 192kHz */
- + {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 5512Hz */
- + {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 8kHz */
- + {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 11025Hz */
- + {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 16kHz */
- + {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 22050Hz */
- + {{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0},}, /* 32kHz */
- + {{0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 44.1kHz */
- + {{0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 48kHz */
- + {{1, 2}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},}, /* 64kHz */
- + {{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 88.2kHz */
- + {{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 96kHz */
- + {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 176kHz */
- + {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 192kHz */
- +};
- +
- +static struct asrc_data *asrc;
- +
- +/*
- + * The following tables map the relationship between asrc_inclk/asrc_outclk in
- + * mxc_asrc.h and the registers of ASRCSR
- + */
- +static unsigned char input_clk_map_v1[] = {
- + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
- +};
- +
- +static unsigned char output_clk_map_v1[] = {
- + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
- +};
- +
- +/* V2 uses the same map for input and output */
- +static unsigned char input_clk_map_v2[] = {
- +/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */
- + 0x0, 0x1, 0x2, 0x7, 0x4, 0x5, 0x6, 0x3, 0x8, 0x9, 0xa, 0xb, 0xc, 0xf, 0xe, 0xd,
- +};
- +
- +static unsigned char output_clk_map_v2[] = {
- +/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */
- + 0x8, 0x9, 0xa, 0x7, 0xc, 0x5, 0x6, 0xb, 0x0, 0x1, 0x2, 0x3, 0x4, 0xf, 0xe, 0xd,
- +};
- +
- +static unsigned char *input_clk_map, *output_clk_map;
- +
- +enum mxc_asrc_type {
- + IMX35_ASRC,
- + IMX53_ASRC,
- +};
- +
- +static const struct platform_device_id mxc_asrc_devtype[] = {
- + {
- + .name = "imx35-asrc",
- + .driver_data = IMX35_ASRC,
- + }, {
- + .name = "imx53-asrc",
- + .driver_data = IMX53_ASRC,
- + }, {
- + /* sentinel */
- + }
- +};
- +MODULE_DEVICE_TABLE(platform, mxc_asrc_devtype);
- +
- +static const struct of_device_id fsl_asrc_ids[] = {
- + {
- + .compatible = "fsl,imx35-asrc",
- + .data = &mxc_asrc_devtype[IMX35_ASRC],
- + }, {
- + .compatible = "fsl,imx53-asrc",
- + .data = &mxc_asrc_devtype[IMX53_ASRC],
- + }, {
- + /* sentinel */
- + }
- +};
- +MODULE_DEVICE_TABLE(of, fsl_asrc_ids);
- +
- +
- +#ifdef DEBUG
- +u32 asrc_reg[] = {
- + REG_ASRCTR,
- + REG_ASRIER,
- + REG_ASRCNCR,
- + REG_ASRCFG,
- + REG_ASRCSR,
- + REG_ASRCDR1,
- + REG_ASRCDR2,
- + REG_ASRSTR,
- + REG_ASRRA,
- + REG_ASRRB,
- + REG_ASRRC,
- + REG_ASRPM1,
- + REG_ASRPM2,
- + REG_ASRPM3,
- + REG_ASRPM4,
- + REG_ASRPM5,
- + REG_ASRTFR1,
- + REG_ASRCCR,
- + REG_ASRIDRHA,
- + REG_ASRIDRLA,
- + REG_ASRIDRHB,
- + REG_ASRIDRLB,
- + REG_ASRIDRHC,
- + REG_ASRIDRLC,
- + REG_ASR76K,
- + REG_ASR56K,
- + REG_ASRMCRA,
- + REG_ASRFSTA,
- + REG_ASRMCRB,
- + REG_ASRFSTB,
- + REG_ASRMCRC,
- + REG_ASRFSTC,
- + REG_ASRMCR1A,
- + REG_ASRMCR1B,
- + REG_ASRMCR1C,
- +};
- +
- +static void dump_regs(void)
- +{
- + u32 reg, val;
- + int i;
- +
- + for (i = 0; i < ARRAY_SIZE(asrc_reg); i++) {
- + reg = asrc_reg[i];
- + regmap_read(asrc->regmap, reg, &val);
- + dev_dbg(asrc->dev, "REG addr=0x%x val=0x%x\n", reg, val);
- + }
- +}
- +#else
- +static void dump_regs(void) {}
- +#endif
- +
- +/* Only used for Ideal Ratio mode */
- +static int asrc_set_clock_ratio(enum asrc_pair_index index,
- + int inrate, int outrate)
- +{
- + unsigned long val = 0;
- + int integ, i;
- +
- + if (outrate == 0) {
- + dev_err(asrc->dev, "wrong output sample rate: %d\n", outrate);
- + return -EINVAL;
- + }
- +
- + /* Formula: r = (1 << ASRC_RATIO_DECIMAL_DEPTH) / outrate * inrate; */
- + for (integ = 0; inrate >= outrate; integ++)
- + inrate -= outrate;
- +
- + val |= (integ << ASRC_RATIO_DECIMAL_DEPTH);
- +
- + for (i = 1; i <= ASRC_RATIO_DECIMAL_DEPTH; i++) {
- + if ((inrate * 2) >= outrate) {
- + val |= (1 << (ASRC_RATIO_DECIMAL_DEPTH - i));
- + inrate = inrate * 2 - outrate;
- + } else
- + inrate = inrate << 1;
- +
- + if (inrate == 0)
- + break;
- + }
- +
- + regmap_write(asrc->regmap, REG_ASRIDRL(index), val);
- + regmap_write(asrc->regmap, REG_ASRIDRH(index), (val >> 24));
- +
- + return 0;
- +}
- +
- +/* Corresponding to asrc_process_table */
- +static int supported_input_rate[] = {
- + 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200,
- + 96000, 176400, 192000,
- +};
- +
- +static int supported_output_rate[] = {
- + 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000,
- +};
- +
- +static int asrc_set_process_configuration(enum asrc_pair_index index,
- + int inrate, int outrate)
- +{
- + int in, out;
- +
- + for (in = 0; in < ARRAY_SIZE(supported_input_rate); in++) {
- + if (inrate == supported_input_rate[in])
- + break;
- + }
- +
- + if (in == ARRAY_SIZE(supported_input_rate)) {
- + dev_err(asrc->dev, "unsupported input sample rate: %d\n", in);
- + return -EINVAL;
- + }
- +
- + for (out = 0; out < ARRAY_SIZE(supported_output_rate); out++) {
- + if (outrate == supported_output_rate[out])
- + break;
- + }
- +
- + if (out == ARRAY_SIZE(supported_output_rate)) {
- + dev_err(asrc->dev, "unsupported output sample rate: %d\n", out);
- + return -EINVAL;
- + }
- +
- + regmap_update_bits(asrc->regmap, REG_ASRCFG,
- + ASRCFG_PREMODx_MASK(index) | ASRCFG_POSTMODx_MASK(index),
- + ASRCFG_PREMOD(index, asrc_process_table[in][out][0]) |
- + ASRCFG_POSTMOD(index, asrc_process_table[in][out][1]));
- +
- + return 0;
- +}
- +
- +static int asrc_get_asrck_clock_divider(int samplerate)
- +{
- + unsigned int prescaler, divider, ratio, ra, i;
- + unsigned long bitclk;
- +
- + if (samplerate == 0) {
- + dev_err(asrc->dev, "invalid sample rate: %d\n", samplerate);
- + return -EINVAL;
- + }
- +
- + bitclk = clk_get_rate(asrc->asrc_clk);
- +
- + ra = bitclk / samplerate;
- + ratio = ra;
- +
- + /* Calculate the prescaler */
- + for (i = 0; ratio > 8; i++)
- + ratio >>= 1;
- +
- + prescaler = i;
- +
- + /* Calculate the divider */
- + divider = i ? (((ra + (1 << (i - 1)) - 1) >> i) - 1) : (ra - 1);
- +
- + /* The totally divider is (2 ^ prescaler) * divider */
- + return (divider << ASRCDRx_AxCPx_WIDTH) + prescaler;
- +}
- +
- +int asrc_req_pair(int chn_num, enum asrc_pair_index *index)
- +{
- + int imax = 0, busy = 0, i, ret = 0;
- + unsigned long lock_flags;
- + struct asrc_pair *pair;
- +
- + spin_lock_irqsave(&data_lock, lock_flags);
- +
- + for (i = ASRC_PAIR_A; i < ASRC_PAIR_MAX_NUM; i++) {
- + pair = &asrc->asrc_pair[i];
- + if (chn_num > pair->chn_max) {
- + imax++;
- + continue;
- + } else if (pair->active) {
- + busy++;
- + continue;
- + }
- + /* Save the current qualified pair */
- + *index = i;
- +
- + /* Check if this pair is a perfect one */
- + if (chn_num == pair->chn_max)
- + break;
- + }
- +
- + if (imax == ASRC_PAIR_MAX_NUM) {
- + dev_err(asrc->dev, "no pair could afford required channel number\n");
- + ret = -EINVAL;
- + } else if (busy == ASRC_PAIR_MAX_NUM) {
- + dev_err(asrc->dev, "all pairs are busy now\n");
- + ret = -EBUSY;
- + } else if (busy + imax >= ASRC_PAIR_MAX_NUM) {
- + dev_err(asrc->dev, "all affordable pairs are busy now\n");
- + ret = -EBUSY;
- + } else {
- + pair = &asrc->asrc_pair[*index];
- + pair->chn_num = chn_num;
- + pair->active = 1;
- + }
- +
- + spin_unlock_irqrestore(&data_lock, lock_flags);
- +
- + if (!ret) {
- + clk_enable(asrc->asrc_clk);
- + clk_prepare_enable(asrc->dma_clk);
- + }
- +
- + return ret;
- +}
- +EXPORT_SYMBOL(asrc_req_pair);
- +
- +void asrc_release_pair(enum asrc_pair_index index)
- +{
- + struct asrc_pair *pair = &asrc->asrc_pair[index];
- + unsigned long lock_flags;
- +
- + spin_lock_irqsave(&data_lock, lock_flags);
- +
- + pair->active = 0;
- + pair->overload_error = 0;
- +
- + spin_unlock_irqrestore(&data_lock, lock_flags);
- +
- + /* Disable PAIR */
- + regmap_update_bits(asrc->regmap, REG_ASRCTR, ASRCTR_ASRCEx_MASK(index), 0);
- +}
- +EXPORT_SYMBOL(asrc_release_pair);
- +
- +int asrc_config_pair(struct asrc_config *config)
- +{
- + u32 inrate = config->input_sample_rate, indiv;
- + u32 outrate = config->output_sample_rate, outdiv;
- + int ret, channels, index = config->pair;
- + unsigned long lock_flags;
- +
- + /* Set the channel number */
- + spin_lock_irqsave(&data_lock, lock_flags);
- + asrc->asrc_pair[index].chn_num = config->channel_num;
- + spin_unlock_irqrestore(&data_lock, lock_flags);
- +
- + if (asrc->channel_bits > 3)
- + channels = config->channel_num;
- + else
- + channels = (config->channel_num + 1) / 2;
- +
- + /* Update channel number of current pair */
- + regmap_update_bits(asrc->regmap, REG_ASRCNCR,
- + ASRCNCR_ANCx_MASK(index, asrc->channel_bits),
- + ASRCNCR_ANCx_set(index, channels, asrc->channel_bits));
- +
- + /* Set the clock source */
- + regmap_update_bits(asrc->regmap, REG_ASRCSR,
- + ASRCSR_AICSx_MASK(index) | ASRCSR_AOCSx_MASK(index),
- + ASRCSR_AICS(index, input_clk_map[config->inclk]) |
- + ASRCSR_AOCS(index, output_clk_map[config->outclk]));
- +
- + /* Default setting: Automatic selection for processing mode */
- + regmap_update_bits(asrc->regmap, REG_ASRCTR,
- + ASRCTR_ATSx_MASK(index), ASRCTR_ATS(index));
- + regmap_update_bits(asrc->regmap, REG_ASRCTR, ASRCTR_USRx_MASK(index), 0);
- +
- + /* Default Input Clock Divider Setting */
- + switch (config->inclk & ASRCSR_AxCSx_MASK) {
- + case INCLK_SPDIF_RX:
- + indiv = ASRC_PRESCALER_SPDIF_RX;
- + break;
- + case INCLK_SPDIF_TX:
- + indiv = ASRC_PRESCALER_SPDIF_TX;
- + break;
- + case INCLK_ASRCK1_CLK:
- + indiv = asrc_get_asrck_clock_divider(inrate);
- + break;
- + default:
- + switch (config->input_word_width) {
- + case ASRC_WIDTH_16_BIT:
- + indiv = ASRC_PRESCALER_I2S_16BIT;
- + break;
- + case ASRC_WIDTH_24_BIT:
- + indiv = ASRC_PRESCALER_I2S_24BIT;
- + break;
- + default:
- + pair_err("unsupported input word width %d\n",
- + config->input_word_width);
- + return -EINVAL;
- + }
- + break;
- + }
- +
- + /* Default Output Clock Divider Setting */
- + switch (config->outclk & ASRCSR_AxCSx_MASK) {
- + case OUTCLK_SPDIF_RX:
- + outdiv = ASRC_PRESCALER_SPDIF_RX;
- + break;
- + case OUTCLK_SPDIF_TX:
- + outdiv = ASRC_PRESCALER_SPDIF_TX;
- + break;
- + case OUTCLK_ASRCK1_CLK:
- + if ((config->inclk & ASRCSR_AxCSx_MASK) == INCLK_NONE)
- + outdiv = ASRC_PRESCALER_IDEAL_RATIO;
- + else
- + outdiv = asrc_get_asrck_clock_divider(outrate);
- + break;
- + default:
- + switch (config->output_word_width) {
- + case ASRC_WIDTH_16_BIT:
- + outdiv = ASRC_PRESCALER_I2S_16BIT;
- + break;
- + case ASRC_WIDTH_24_BIT:
- + outdiv = ASRC_PRESCALER_I2S_24BIT;
- + break;
- + default:
- + pair_err("unsupported output word width %d\n",
- + config->input_word_width);
- + return -EINVAL;
- + }
- + break;
- + }
- +
- + /* indiv and outdiv'd include prescaler's value, so add its MASK too */
- + regmap_update_bits(asrc->regmap, REG_ASRCDR(index),
- + ASRCDRx_AOCPx_MASK(index) | ASRCDRx_AICPx_MASK(index) |
- + ASRCDRx_AOCDx_MASK(index) | ASRCDRx_AICDx_MASK(index),
- + ASRCDRx_AOCP(index, outdiv) | ASRCDRx_AICP(index, indiv));
- +
- + /* Check whether ideal ratio is a must */
- + switch (config->inclk & ASRCSR_AxCSx_MASK) {
- + case INCLK_NONE:
- + /* Clear ASTSx bit to use ideal ratio */
- + regmap_update_bits(asrc->regmap, REG_ASRCTR,
- + ASRCTR_ATSx_MASK(index), 0);
- +
- + regmap_update_bits(asrc->regmap, REG_ASRCTR,
- + ASRCTR_IDRx_MASK(index) | ASRCTR_USRx_MASK(index),
- + ASRCTR_IDR(index) | ASRCTR_USR(index));
- +
- + ret = asrc_set_clock_ratio(index, inrate, outrate);
- + if (ret)
- + return ret;
- +
- + ret = asrc_set_process_configuration(index, inrate, outrate);
- + if (ret)
- + return ret;
- +
- + break;
- + case INCLK_ASRCK1_CLK:
- + /* This case and default are both remained for v1 */
- + if (inrate == 44100 || inrate == 88200) {
- + pair_err("unsupported sample rate %d by selected clock\n",
- + inrate);
- + return -EINVAL;
- + }
- + break;
- + default:
- + if ((config->outclk & ASRCSR_AxCSx_MASK) != OUTCLK_ASRCK1_CLK)
- + break;
- +
- + if (outrate == 44100 || outrate == 88200) {
- + pair_err("unsupported sample rate %d by selected clock\n",
- + outrate);
- + return -EINVAL;
- + }
- + break;
- + }
- +
- + /* Config input and output wordwidth */
- + if (config->output_word_width == ASRC_WIDTH_8_BIT) {
- + pair_err("unsupported wordwidth for output: 8bit\n");
- + pair_err("output only support: 16bit or 24bit\n");
- + return -EINVAL;
- + }
- +
- + regmap_update_bits(asrc->regmap, REG_ASRMCR1(index),
- + ASRMCR1x_OW16_MASK | ASRMCR1x_IWD_MASK,
- + ASRMCR1x_OW16(config->output_word_width) |
- + ASRMCR1x_IWD(config->input_word_width));
- +
- + /* Enable BUFFER STALL */
- + regmap_update_bits(asrc->regmap, REG_ASRMCR(index),
- + ASRMCRx_BUFSTALLx_MASK, ASRMCRx_BUFSTALLx);
- +
- + /* Set Threshold for input and output FIFO */
- + return asrc_set_watermark(index, ASRC_INPUTFIFO_THRESHOLD,
- + ASRC_INPUTFIFO_THRESHOLD);
- +}
- +EXPORT_SYMBOL(asrc_config_pair);
- +
- +int asrc_set_watermark(enum asrc_pair_index index, u32 in_wm, u32 out_wm)
- +{
- + if (in_wm > ASRC_FIFO_THRESHOLD_MAX || out_wm > ASRC_FIFO_THRESHOLD_MAX) {
- + pair_err("invalid watermark!\n");
- + return -EINVAL;
- + }
- +
- + return regmap_update_bits(asrc->regmap, REG_ASRMCR(index),
- + ASRMCRx_EXTTHRSHx_MASK | ASRMCRx_INFIFO_THRESHOLD_MASK |
- + ASRMCRx_OUTFIFO_THRESHOLD_MASK,
- + ASRMCRx_EXTTHRSHx | ASRMCRx_INFIFO_THRESHOLD(in_wm) |
- + ASRMCRx_OUTFIFO_THRESHOLD(out_wm));
- +}
- +EXPORT_SYMBOL(asrc_set_watermark);
- +
- +void asrc_start_conv(enum asrc_pair_index index)
- +{
- + int reg, retry, channels, i;
- +
- + regmap_update_bits(asrc->regmap, REG_ASRCTR,
- + ASRCTR_ASRCEx_MASK(index), ASRCTR_ASRCE(index));
- +
- + /* Wait for status of initialization */
- + for (retry = 10, reg = 0; !reg && retry; --retry) {
- + udelay(5);
- + regmap_read(asrc->regmap, REG_ASRCFG, ®);
- + reg &= ASRCFG_INIRQx_MASK(index);
- + }
- +
- + /* Set the input fifo to ASRC STALL level */
- + regmap_read(asrc->regmap, REG_ASRCNCR, ®);
- + channels = ASRCNCR_ANCx_get(index, reg, asrc->channel_bits);
- + for (i = 0; i < channels * 4; i++)
- + regmap_write(asrc->regmap, REG_ASRDI(index), 0);
- +
- + /* Overload Interrupt Enable */
- + regmap_write(asrc->regmap, REG_ASRIER, ASRIER_AOLIE);
- +}
- +EXPORT_SYMBOL(asrc_start_conv);
- +
- +void asrc_stop_conv(enum asrc_pair_index index)
- +{
- + regmap_update_bits(asrc->regmap, REG_ASRCTR, ASRCTR_ASRCEx_MASK(index), 0);
- +}
- +EXPORT_SYMBOL(asrc_stop_conv);
- +
- +void asrc_finish_conv(enum asrc_pair_index index)
- +{
- + clk_disable_unprepare(asrc->dma_clk);
- + clk_disable(asrc->asrc_clk);
- +}
- +EXPORT_SYMBOL(asrc_finish_conv);
- +
- +#define SET_OVERLOAD_ERR(index, err, msg) \
- + do { \
- + asrc->asrc_pair[index].overload_error |= err; \
- + pair_dbg(msg); \
- + } while (0)
- +
- +static irqreturn_t asrc_isr(int irq, void *dev_id)
- +{
- + enum asrc_pair_index index;
- + u32 status;
- +
- + regmap_read(asrc->regmap, REG_ASRSTR, &status);
- +
- + for (index = ASRC_PAIR_A; index < ASRC_PAIR_MAX_NUM; index++) {
- + if (asrc->asrc_pair[index].active == 0)
- + continue;
- + if (status & ASRSTR_ATQOL)
- + SET_OVERLOAD_ERR(index, ASRC_TASK_Q_OVERLOAD,
- + "Task Queue FIFO overload");
- + if (status & ASRSTR_AOOL(index))
- + SET_OVERLOAD_ERR(index, ASRC_OUTPUT_TASK_OVERLOAD,
- + "Output Task Overload");
- + if (status & ASRSTR_AIOL(index))
- + SET_OVERLOAD_ERR(index, ASRC_INPUT_TASK_OVERLOAD,
- + "Input Task Overload");
- + if (status & ASRSTR_AODO(index))
- + SET_OVERLOAD_ERR(index, ASRC_OUTPUT_BUFFER_OVERFLOW,
- + "Output Data Buffer has overflowed");
- + if (status & ASRSTR_AIDU(index))
- + SET_OVERLOAD_ERR(index, ASRC_INPUT_BUFFER_UNDERRUN,
- + "Input Data Buffer has underflowed");
- + }
- +
- + /* Clean overload error */
- + regmap_write(asrc->regmap, REG_ASRSTR, ASRSTR_AOLE);
- +
- + return IRQ_HANDLED;
- +}
- +
- +void asrc_get_status(struct asrc_status_flags *flags)
- +{
- + enum asrc_pair_index index = flags->index;
- + unsigned long lock_flags;
- +
- + spin_lock_irqsave(&data_lock, lock_flags);
- +
- + flags->overload_error = asrc->asrc_pair[index].overload_error;
- +
- + spin_unlock_irqrestore(&data_lock, lock_flags);
- +}
- +EXPORT_SYMBOL(asrc_get_status);
- +
- +u32 asrc_get_per_addr(enum asrc_pair_index index, bool in)
- +{
- + return asrc->paddr + (in ? REG_ASRDI(index) : REG_ASRDO(index));
- +}
- +EXPORT_SYMBOL(asrc_get_per_addr);
- +
- +static int mxc_init_asrc(void)
- +{
- + /* Halt ASRC internal FP when input FIFO needs data for pair A, B, C */
- + regmap_write(asrc->regmap, REG_ASRCTR, ASRCTR_ASRCEN);
- +
- + /* Disable interrupt by default */
- + regmap_write(asrc->regmap, REG_ASRIER, 0x0);
- +
- + /* Default 2: 6: 2 channel assignment */
- + regmap_update_bits(asrc->regmap, REG_ASRCNCR,
- + ASRCNCR_ANCx_MASK(ASRC_PAIR_A, asrc->channel_bits),
- + ASRCNCR_ANCx_set(ASRC_PAIR_A, 2, asrc->channel_bits));
- + regmap_update_bits(asrc->regmap, REG_ASRCNCR,
- + ASRCNCR_ANCx_MASK(ASRC_PAIR_B, asrc->channel_bits),
- + ASRCNCR_ANCx_set(ASRC_PAIR_B, 6, asrc->channel_bits));
- + regmap_update_bits(asrc->regmap, REG_ASRCNCR,
- + ASRCNCR_ANCx_MASK(ASRC_PAIR_C, asrc->channel_bits),
- + ASRCNCR_ANCx_set(ASRC_PAIR_C, 2, asrc->channel_bits));
- +
- + /* Parameter Registers recommended settings */
- + regmap_write(asrc->regmap, REG_ASRPM1, 0x7fffff);
- + regmap_write(asrc->regmap, REG_ASRPM2, 0x255555);
- + regmap_write(asrc->regmap, REG_ASRPM3, 0xff7280);
- + regmap_write(asrc->regmap, REG_ASRPM4, 0xff7280);
- + regmap_write(asrc->regmap, REG_ASRPM5, 0xff7280);
- +
- + /* Base address for task queue FIFO. Set to 0x7C */
- + regmap_update_bits(asrc->regmap, REG_ASRTFR1,
- + ASRTFR1_TF_BASE_MASK, ASRTFR1_TF_BASE(0xfc));
- +
- + /* Set the processing clock for 76KHz, 133M */
- + regmap_write(asrc->regmap, REG_ASR76K, 0x06D6);
- +
- + /* Set the processing clock for 56KHz, 133M */
- + return regmap_write(asrc->regmap, REG_ASR56K, 0x0947);
- +}
- +
- +#define ASRC_xPUT_DMA_CALLBACK(in) \
- + ((in) ? asrc_input_dma_callback : asrc_output_dma_callback)
- +
- +static void asrc_input_dma_callback(void *data)
- +{
- + struct asrc_pair_params *params = (struct asrc_pair_params *)data;
- +
- + dma_unmap_sg(NULL, params->input_sg, params->input_sg_nodes,
- + DMA_MEM_TO_DEV);
- +
- + complete(¶ms->input_complete);
- +
- + schedule_work(¶ms->task_output_work);
- +}
- +
- +static void asrc_output_dma_callback(void *data)
- +{
- + struct asrc_pair_params *params = (struct asrc_pair_params *)data;
- +
- + dma_unmap_sg(NULL, params->output_sg, params->output_sg_nodes,
- + DMA_DEV_TO_MEM);
- +
- + complete(¶ms->output_complete);
- +}
- +
- +static unsigned int asrc_get_output_FIFO_size(enum asrc_pair_index index)
- +{
- + u32 val;
- +
- + regmap_read(asrc->regmap, REG_ASRFST(index), &val);
- +
- + val &= ASRFSTx_OUTPUT_FIFO_MASK;
- +
- + return val >> ASRFSTx_OUTPUT_FIFO_SHIFT;
- +}
- +
- +static u32 asrc_read_one_from_output_FIFO(enum asrc_pair_index index)
- +{
- + u32 val;
- +
- + regmap_read(asrc->regmap, REG_ASRDO(index), &val);
- +
- + return val;
- +}
- +
- +static void asrc_read_output_FIFO(struct asrc_pair_params *params)
- +{
- + u32 *reg24 = params->output_last_period.dma_vaddr;
- + u16 *reg16 = params->output_last_period.dma_vaddr;
- + enum asrc_pair_index index = params->index;
- + u32 i, j, reg, size, t_size;
- + bool bit24 = false;
- +
- + if (params->output_word_width == ASRC_WIDTH_24_BIT)
- + bit24 = true;
- +
- + t_size = 0;
- + do {
- + size = asrc_get_output_FIFO_size(index);
- + for (i = 0; i < size; i++) {
- + for (j = 0; j < params->channel_nums; j++) {
- + reg = asrc_read_one_from_output_FIFO(index);
- + if (bit24) {
- + *(reg24) = reg;
- + reg24++;
- + } else {
- + *(reg16) = (u16)reg;
- + reg16++;
- + }
- + }
- + }
- + t_size += size;
- + } while (size);
- +
- + if (t_size > params->last_period_sample)
- + t_size = params->last_period_sample;
- +
- + params->output_last_period.length = t_size * params->channel_nums * 2;
- + if (bit24)
- + params->output_last_period.length *= 2;
- +}
- +
- +static void asrc_output_task_worker(struct work_struct *w)
- +{
- + struct asrc_pair_params *params =
- + container_of(w, struct asrc_pair_params, task_output_work);
- + enum asrc_pair_index index = params->index;
- + unsigned long lock_flags;
- +
- + if (!wait_for_completion_interruptible_timeout(¶ms->output_complete, HZ / 10)) {
- + pair_err("output dma task timeout\n");
- + return;
- + }
- +
- + init_completion(¶ms->output_complete);
- +
- + spin_lock_irqsave(&pair_lock, lock_flags);
- + if (!params->pair_hold) {
- + spin_unlock_irqrestore(&pair_lock, lock_flags);
- + return;
- + }
- + asrc_read_output_FIFO(params);
- + spin_unlock_irqrestore(&pair_lock, lock_flags);
- +
- + complete(¶ms->lastperiod_complete);
- +}
- +
- +static void mxc_free_dma_buf(struct asrc_pair_params *params)
- +{
- + if (params->input_dma_total.dma_vaddr != NULL) {
- + kfree(params->input_dma_total.dma_vaddr);
- + params->input_dma_total.dma_vaddr = NULL;
- + }
- +
- + if (params->output_dma_total.dma_vaddr != NULL) {
- + kfree(params->output_dma_total.dma_vaddr);
- + params->output_dma_total.dma_vaddr = NULL;
- + }
- +
- + if (params->output_last_period.dma_vaddr) {
- + dma_free_coherent(asrc->dev, 1024 * params->last_period_sample,
- + params->output_last_period.dma_vaddr,
- + params->output_last_period.dma_paddr);
- + params->output_last_period.dma_vaddr = NULL;
- + }
- +}
- +
- +static int mxc_allocate_dma_buf(struct asrc_pair_params *params)
- +{
- + struct dma_block *input_a, *output_a, *last_period;
- + enum asrc_pair_index index = params->index;
- +
- + input_a = ¶ms->input_dma_total;
- + output_a = ¶ms->output_dma_total;
- + last_period = ¶ms->output_last_period;
- +
- + input_a->dma_vaddr = kzalloc(input_a->length, GFP_KERNEL);
- + if (!input_a->dma_vaddr) {
- + pair_err("failed to allocate input dma buffer\n");
- + goto exit;
- + }
- + input_a->dma_paddr = virt_to_dma(NULL, input_a->dma_vaddr);
- +
- + output_a->dma_vaddr = kzalloc(output_a->length, GFP_KERNEL);
- + if (!output_a->dma_vaddr) {
- + pair_err("failed to allocate output dma buffer\n");
- + goto exit;
- + }
- + output_a->dma_paddr = virt_to_dma(NULL, output_a->dma_vaddr);
- +
- + last_period->dma_vaddr = dma_alloc_coherent(asrc->dev,
- + 1024 * params->last_period_sample,
- + &last_period->dma_paddr, GFP_KERNEL);
- + if (!last_period->dma_vaddr) {
- + pair_err("failed to allocate last period buffer\n");
- + goto exit;
- + }
- +
- + return 0;
- +
- +exit:
- + mxc_free_dma_buf(params);
- +
- + return -ENOBUFS;
- +}
- +
- +static struct dma_chan *imx_asrc_get_dma_channel(enum asrc_pair_index index, bool in)
- +{
- + char name[4];
- +
- + sprintf(name, "%cx%c", in ? 'r' : 't', index + 'a');
- +
- + return dma_request_slave_channel(asrc->dev, name);
- +}
- +
- +static int imx_asrc_dma_config(struct asrc_pair_params *params,
- + struct dma_chan *chan, u32 dma_addr,
- + void *buf_addr, u32 buf_len, bool in,
- + enum asrc_word_width word_width)
- +{
- + enum asrc_pair_index index = params->index;
- + struct dma_async_tx_descriptor *desc;
- + struct dma_slave_config slave_config;
- + enum dma_slave_buswidth buswidth;
- + struct scatterlist *sg;
- + unsigned int sg_nent, i;
- + int ret;
- +
- + if (in) {
- + sg = params->input_sg;
- + sg_nent = params->input_sg_nodes;
- + desc = params->desc_in;
- + } else {
- + sg = params->output_sg;
- + sg_nent = params->output_sg_nodes;
- + desc = params->desc_out;
- + }
- +
- + switch (word_width) {
- + case ASRC_WIDTH_16_BIT:
- + buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
- + break;
- + case ASRC_WIDTH_24_BIT:
- + buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
- + break;
- + default:
- + pair_err("invalid word width\n");
- + return -EINVAL;
- + }
- +
- + slave_config.dma_request0 = 0;
- + slave_config.dma_request1 = 0;
- +
- + if (in) {
- + slave_config.direction = DMA_MEM_TO_DEV;
- + slave_config.dst_addr = dma_addr;
- + slave_config.dst_addr_width = buswidth;
- + slave_config.dst_maxburst =
- + params->input_wm * params->channel_nums / buswidth;
- + } else {
- + slave_config.direction = DMA_DEV_TO_MEM;
- + slave_config.src_addr = dma_addr;
- + slave_config.src_addr_width = buswidth;
- + slave_config.src_maxburst =
- + params->output_wm * params->channel_nums / buswidth;
- + }
- + ret = dmaengine_slave_config(chan, &slave_config);
- + if (ret) {
- + pair_err("failed to config dmaengine for %sput task: %d\n",
- + in ? "in" : "out", ret);
- + return -EINVAL;
- + }
- +
- + sg_init_table(sg, sg_nent);
- + switch (sg_nent) {
- + case 1:
- + sg_init_one(sg, buf_addr, buf_len);
- + break;
- + case 2:
- + case 3:
- + case 4:
- + for (i = 0; i < (sg_nent - 1); i++)
- + sg_set_buf(&sg[i], buf_addr + i * ASRC_MAX_BUFFER_SIZE,
- + ASRC_MAX_BUFFER_SIZE);
- +
- + sg_set_buf(&sg[i], buf_addr + i * ASRC_MAX_BUFFER_SIZE,
- + buf_len - ASRC_MAX_BUFFER_SIZE * i);
- + break;
- + default:
- + pair_err("invalid input DMA nodes number: %d\n", sg_nent);
- + return -EINVAL;
- + }
- +
- + ret = dma_map_sg(NULL, sg, sg_nent, slave_config.direction);
- + if (ret != sg_nent) {
- + pair_err("failed to map dma sg for %sput task\n",
- + in ? "in" : "out");
- + return -EINVAL;
- + }
- +
- + desc = dmaengine_prep_slave_sg(chan, sg, sg_nent,
- + slave_config.direction, DMA_PREP_INTERRUPT);
- + if (!desc) {
- + pair_err("failed to prepare slave sg for %sput task\n",
- + in ? "in" : "out");
- + return -EINVAL;
- + }
- +
- + if (in) {
- + params->desc_in = desc;
- + params->desc_in->callback = asrc_input_dma_callback;
- + } else {
- + params->desc_out = desc;
- + params->desc_out->callback = asrc_output_dma_callback;
- + }
- +
- + desc->callback = ASRC_xPUT_DMA_CALLBACK(in);
- + desc->callback_param = params;
- +
- + return 0;
- +}
- +
- +static int mxc_asrc_prepare_io_buffer(struct asrc_pair_params *params,
- + struct asrc_convert_buffer *pbuf, bool in)
- +{
- + enum asrc_pair_index index = params->index;
- + struct dma_chan *dma_channel;
- + enum asrc_word_width width;
- + unsigned int *dma_len, *sg_nodes, buf_len, wm;
- + void __user *buf_vaddr;
- + void *dma_vaddr;
- + u32 word_size, fifo_addr;
- +
- + if (in) {
- + dma_channel = params->input_dma_channel;
- + dma_vaddr = params->input_dma_total.dma_vaddr;
- + dma_len = ¶ms->input_dma_total.length;
- + width = params->input_word_width;
- + sg_nodes = ¶ms->input_sg_nodes;
- + wm = params->input_wm;
- + buf_vaddr = (void __user *)pbuf->input_buffer_vaddr;
- + buf_len = pbuf->input_buffer_length;
- + } else {
- + dma_channel = params->output_dma_channel;
- + dma_vaddr = params->output_dma_total.dma_vaddr;
- + dma_len = ¶ms->output_dma_total.length;
- + width = params->output_word_width;
- + sg_nodes = ¶ms->output_sg_nodes;
- + wm = params->last_period_sample;
- + buf_vaddr = (void __user *)pbuf->output_buffer_vaddr;
- + buf_len = pbuf->output_buffer_length;
- + }
- +
- + switch (width) {
- + case ASRC_WIDTH_24_BIT:
- + word_size = 4;
- + break;
- + case ASRC_WIDTH_16_BIT:
- + case ASRC_WIDTH_8_BIT:
- + word_size = 2;
- + break;
- + default:
- + pair_err("invalid %sput word size!\n", in ? "in" : "out");
- + return -EINVAL;
- + }
- +
- + if (buf_len < word_size * params->channel_nums * wm) {
- + pair_err("%sput buffer size[%d] is too small!\n",
- + in ? "in" : "out", buf_len);
- + return -EINVAL;
- + }
- +
- + /* Copy origin data into input buffer */
- + if (in && copy_from_user(dma_vaddr, buf_vaddr, buf_len))
- + return -EFAULT;
- +
- + *dma_len = buf_len;
- + if (!in)
- + *dma_len -= wm * word_size * params->channel_nums;
- +
- + *sg_nodes = *dma_len / ASRC_MAX_BUFFER_SIZE + 1;
- +
- + fifo_addr = asrc_get_per_addr(params->index, in);
- +
- + return imx_asrc_dma_config(params, dma_channel, fifo_addr, dma_vaddr,
- + *dma_len, in, width);
- +}
- +
- +static int mxc_asrc_prepare_buffer(struct asrc_pair_params *params,
- + struct asrc_convert_buffer *pbuf)
- +{
- + enum asrc_pair_index index = params->index;
- + int ret;
- +
- + ret = mxc_asrc_prepare_io_buffer(params, pbuf, true);
- + if (ret) {
- + pair_err("failed to prepare input buffer: %d\n", ret);
- + return ret;
- + }
- +
- + ret = mxc_asrc_prepare_io_buffer(params, pbuf, false);
- + if (ret) {
- + pair_err("failed to prepare output buffer: %d\n", ret);
- + return ret;
- + }
- +
- + return 0;
- +}
- +
- +int mxc_asrc_process_io_buffer(struct asrc_pair_params *params,
- + struct asrc_convert_buffer *pbuf, bool in)
- +{
- + void *last_vaddr = params->output_last_period.dma_vaddr;
- + unsigned int *last_len = ¶ms->output_last_period.length;
- + enum asrc_pair_index index = params->index;
- + unsigned int dma_len, *buf_len;
- + struct completion *complete;
- + void __user *buf_vaddr;
- + void *dma_vaddr;
- +
- + if (in) {
- + dma_vaddr = params->input_dma_total.dma_vaddr;
- + dma_len = params->input_dma_total.length;
- + buf_len = &pbuf->input_buffer_length;
- + complete = ¶ms->input_complete;
- + buf_vaddr = (void __user *)pbuf->input_buffer_vaddr;
- + } else {
- + dma_vaddr = params->output_dma_total.dma_vaddr;
- + dma_len = params->output_dma_total.length;
- + buf_len = &pbuf->output_buffer_length;
- + complete = ¶ms->lastperiod_complete;
- + buf_vaddr = (void __user *)pbuf->output_buffer_vaddr;
- + }
- +
- + if (!wait_for_completion_interruptible_timeout(complete, 10 * HZ)) {
- + pair_err("%s task timeout\n", in ? "input dma" : "last period");
- + return -ETIME;
- + } else if (signal_pending(current)) {
- + pair_err("%sput task forcibly aborted\n", in ? "in" : "out");
- + return -ERESTARTSYS;
- + }
- +
- + init_completion(complete);
- +
- + *buf_len = dma_len;
- +
- + /* Only output need return data to user space */
- + if (!in) {
- + if (copy_to_user(buf_vaddr, dma_vaddr, dma_len))
- + return -EFAULT;
- +
- + *buf_len += *last_len;
- +
- + if (copy_to_user(buf_vaddr + dma_len, last_vaddr, *last_len))
- + return -EFAULT;
- + }
- +
- + return 0;
- +}
- +
- +int mxc_asrc_process_buffer(struct asrc_pair_params *params,
- + struct asrc_convert_buffer *pbuf)
- +{
- + enum asrc_pair_index index = params->index;
- + int ret;
- +
- + ret = mxc_asrc_process_io_buffer(params, pbuf, true);
- + if (ret) {
- + pair_err("failed to process input buffer: %d\n", ret);
- + return ret;
- + }
- +
- + ret = mxc_asrc_process_io_buffer(params, pbuf, false);
- + if (ret) {
- + pair_err("failed to process output buffer: %d\n", ret);
- + return ret;
- + }
- +
- + return 0;
- +}
- +
- +#ifdef ASRC_POLLING_WITHOUT_DMA
- +static void asrc_write_one_to_input_FIFO(enum asrc_pair_index index, u32 val)
- +{
- + regmap_write(asrc->regmap, REG_ASRDI(index), val);
- +}
- +
- +/* THIS FUNCTION ONLY EXISTS FOR DEBUGGING AND ONLY SUPPORTS TWO CHANNELS */
- +static void asrc_polling_debug(struct asrc_pair_params *params)
- +{
- + enum asrc_pair_index index = params->index;
- + u32 *in24 = params->input_dma_total.dma_vaddr;
- + u32 dma_len = params->input_dma_total.length / (params->channel_nums * 4);
- + u32 size, i, j, t_size, reg;
- + u32 *reg24 = params->output_dma_total.dma_vaddr;
- +
- + t_size = 0;
- +
- + for (i = 0; i < dma_len; ) {
- + for (j = 0; j < 2; j++) {
- + asrc_write_one_to_input_FIFO(index, *in24);
- + in24++;
- + asrc_write_one_to_input_FIFO(index, *in24);
- + in24++;
- + i++;
- + }
- + udelay(50);
- + udelay(50 * params->output_sample_rate / params->input_sample_rate);
- +
- + size = asrc_get_output_FIFO_size(index);
- + for (j = 0; j < size; j++) {
- + reg = asrc_read_one_from_output_FIFO(index);
- + *(reg24) = reg;
- + reg24++;
- + reg = asrc_read_one_from_output_FIFO(index);
- + *(reg24) = reg;
- + reg24++;
- + }
- + t_size += size;
- + }
- +
- + mdelay(1);
- + size = asrc_get_output_FIFO_size(index);
- + for (j = 0; j < size; j++) {
- + reg = asrc_read_one_from_output_FIFO(index);
- + *(reg24) = reg;
- + reg24++;
- + reg = asrc_read_one_from_output_FIFO(index);
- + *(reg24) = reg;
- + reg24++;
- + }
- + t_size += size;
- +
- + params->output_dma_total.length = t_size * params->channel_nums * 4;
- + params->output_last_period.length = 0;
- +
- + dma_unmap_sg(NULL, params->input_sg, params->input_sg_nodes,
- + DMA_MEM_TO_DEV);
- + dma_unmap_sg(NULL, params->output_sg, params->output_sg_nodes,
- + DMA_DEV_TO_MEM);
- +
- + complete(¶ms->input_complete);
- + complete(¶ms->lastperiod_complete);
- +}
- +#else
- +static void mxc_asrc_submit_dma(struct asrc_pair_params *params)
- +{
- + enum asrc_pair_index index = params->index;
- + u32 size = asrc_get_output_FIFO_size(params->index);
- + int i, j;
- +
- + /* Read all data in OUTPUT FIFO */
- + while (size) {
- + for (j = 0; j < size; j++)
- + for (i = 0; i < params->channel_nums; i++)
- + asrc_read_one_from_output_FIFO(index);
- + /* Fetch the data every 100us */
- + udelay(100);
- +
- + size = asrc_get_output_FIFO_size(index);
- + }
- +
- + /* Submit dma request */
- + dmaengine_submit(params->desc_in);
- + dma_async_issue_pending(params->desc_in->chan);
- +
- + dmaengine_submit(params->desc_out);
- + dma_async_issue_pending(params->desc_out->chan);
- +
- + /*
- + * Clear dma request during the stall state of ASRC:
- + * During STALL state, the remaining in input fifo would never be
- + * smaller than the input threshold while the output fifo would not
- + * be bigger than output one. Thus the dma request would be cleared.
- + */
- + asrc_set_watermark(index, ASRC_FIFO_THRESHOLD_MIN, ASRC_FIFO_THRESHOLD_MAX);
- +
- + /* Update the real input threshold to raise dma request */
- + asrc_set_watermark(index, params->input_wm, params->output_wm);
- +}
- +#endif
- +
- +static long asrc_ioctl_req_pair(struct asrc_pair_params *params,
- + void __user *user)
- +{
- + struct asrc_req req;
- + long ret;
- +
- + ret = copy_from_user(&req, user, sizeof(req));
- + if (ret) {
- + dev_err(asrc->dev, "failed to get req from user space: %ld\n", ret);
- + return ret;
- + }
- +
- + ret = asrc_req_pair(req.chn_num, &req.index);
- + if (ret) {
- + dev_err(asrc->dev, "failed to request pair: %ld\n", ret);
- + return ret;
- + }
- +
- + params->pair_hold = 1;
- + params->index = req.index;
- + params->channel_nums = req.chn_num;
- +
- + ret = copy_to_user(user, &req, sizeof(req));
- + if (ret) {
- + dev_err(asrc->dev, "failed to send req to user space: %ld\n", ret);
- + return ret;
- + }
- +
- + return 0;
- +}
- +
- +static long asrc_ioctl_config_pair(struct asrc_pair_params *params,
- + void __user *user)
- +{
- + struct asrc_config config;
- + enum asrc_pair_index index;
- + long ret;
- +
- + ret = copy_from_user(&config, user, sizeof(config));
- + if (ret) {
- + dev_err(asrc->dev, "failed to get config from user space: %ld\n", ret);
- + return ret;
- + }
- +
- + index = config.pair;
- +
- + ret = asrc_config_pair(&config);
- + if (ret) {
- + pair_err("failed to config pair: %ld\n", ret);
- + return ret;
- + }
- +
- + params->input_wm = 4;
- + params->output_wm = 2;
- +
- + ret = asrc_set_watermark(index, params->input_wm, params->output_wm);
- + if (ret)
- + return ret;
- +
- + params->output_buffer_size = config.dma_buffer_size;
- + params->input_buffer_size = config.dma_buffer_size;
- + if (config.buffer_num > ASRC_DMA_BUFFER_NUM)
- + params->buffer_num = ASRC_DMA_BUFFER_NUM;
- + else
- + params->buffer_num = config.buffer_num;
- +
- + params->input_dma_total.length = ASRC_DMA_BUFFER_SIZE;
- + params->output_dma_total.length = ASRC_DMA_BUFFER_SIZE;
- +
- + params->input_word_width = config.input_word_width;
- + params->output_word_width = config.output_word_width;
- +
- + params->input_sample_rate = config.input_sample_rate;
- + params->output_sample_rate = config.output_sample_rate;
- +
- + params->last_period_sample = ASRC_OUTPUT_LAST_SAMPLE_DEFAULT;
- +
- + ret = mxc_allocate_dma_buf(params);
- + if (ret) {
- + pair_err("failed to allocate dma buffer: %ld\n", ret);
- + return ret;
- + }
- +
- + /* Request DMA channel for both input and output */
- + params->input_dma_channel = imx_asrc_get_dma_channel(index, true);
- + if (params->input_dma_channel == NULL) {
- + pair_err("failed to request input task dma channel\n");
- + return -EBUSY;
- + }
- +
- + params->output_dma_channel = imx_asrc_get_dma_channel(index, false);
- + if (params->output_dma_channel == NULL) {
- + pair_err("failed to request output task dma channel\n");
- + return -EBUSY;
- + }
- +
- + init_completion(¶ms->input_complete);
- + init_completion(¶ms->output_complete);
- + init_completion(¶ms->lastperiod_complete);
- +
- + /* Add work struct to receive last period of output data */
- + INIT_WORK(¶ms->task_output_work, asrc_output_task_worker);
- +
- + ret = copy_to_user(user, &config, sizeof(config));
- + if (ret) {
- + pair_err("failed to send config to user space: %ld\n", ret);
- + return ret;
- + }
- +
- + return 0;
- +}
- +
- +static long asrc_ioctl_release_pair(struct asrc_pair_params *params,
- + void __user *user)
- +{
- + enum asrc_pair_index index;
- + unsigned long lock_flags;
- + long ret;
- +
- + ret = copy_from_user(&index, user, sizeof(index));
- + if (ret) {
- + dev_err(asrc->dev, "failed to get index from user space: %ld\n", ret);
- + return ret;
- + }
- +
- + /* index might be not valid due to some application failure. */
- + if (index < 0)
- + return -EINVAL;
- +
- + params->asrc_active = 0;
- +
- + spin_lock_irqsave(&pair_lock, lock_flags);
- + params->pair_hold = 0;
- + spin_unlock_irqrestore(&pair_lock, lock_flags);
- +
- + if (params->input_dma_channel)
- + dma_release_channel(params->input_dma_channel);
- + if (params->output_dma_channel)
- + dma_release_channel(params->output_dma_channel);
- + mxc_free_dma_buf(params);
- + asrc_release_pair(index);
- + asrc_finish_conv(index);
- +
- + return 0;
- +}
- +
- +static long asrc_ioctl_convert(struct asrc_pair_params *params,
- + void __user *user)
- +{
- + enum asrc_pair_index index = params->index;
- + struct asrc_convert_buffer buf;
- + long ret;
- +
- + ret = copy_from_user(&buf, user, sizeof(buf));
- + if (ret) {
- + pair_err("failed to get buf from user space: %ld\n", ret);
- + return ret;
- + }
- +
- + ret = mxc_asrc_prepare_buffer(params, &buf);
- + if (ret) {
- + pair_err("failed to prepare buffer: %ld\n", ret);
- + return ret;
- + }
- +
- +#ifdef ASRC_POLLING_WITHOUT_DMA
- + asrc_polling_debug(params);
- +#else
- + mxc_asrc_submit_dma(params);
- +#endif
- +
- + ret = mxc_asrc_process_buffer(params, &buf);
- + if (ret) {
- + pair_err("failed to process buffer: %ld\n", ret);
- + return ret;
- + }
- +
- + ret = copy_to_user(user, &buf, sizeof(buf));
- + if (ret) {
- + pair_err("failed to send buf to user space: %ld\n", ret);
- + return ret;
- + }
- +
- + return 0;
- +}
- +
- +static long asrc_ioctl_start_conv(struct asrc_pair_params *params,
- + void __user *user)
- +{
- + enum asrc_pair_index index;
- + long ret;
- +
- + ret = copy_from_user(&index, user, sizeof(index));
- + if (ret) {
- + dev_err(asrc->dev, "failed to get index from user space: %ld\n", ret);
- + return ret;
- + }
- +
- + params->asrc_active = 1;
- + asrc_start_conv(index);
- +
- + return 0;
- +}
- +
- +static long asrc_ioctl_stop_conv(struct asrc_pair_params *params,
- + void __user *user)
- +{
- + enum asrc_pair_index index;
- + long ret;
- +
- + ret = copy_from_user(&index, user, sizeof(index));
- + if (ret) {
- + dev_err(asrc->dev, "failed to get index from user space: %ld\n", ret);
- + return ret;
- + }
- +
- + dmaengine_terminate_all(params->input_dma_channel);
- + dmaengine_terminate_all(params->output_dma_channel);
- +
- + asrc_stop_conv(index);
- + params->asrc_active = 0;
- +
- + return 0;
- +}
- +
- +static long asrc_ioctl_status(struct asrc_pair_params *params,
- + void __user *user)
- +{
- + enum asrc_pair_index index = params->index;
- + struct asrc_status_flags flags;
- + long ret;
- +
- + ret = copy_from_user(&flags, user, sizeof(flags));
- + if (ret) {
- + pair_err("failed to get flags from user space: %ld\n", ret);
- + return ret;
- + }
- +
- + asrc_get_status(&flags);
- +
- + ret = copy_to_user(user, &flags, sizeof(flags));
- + if (ret) {
- + pair_err("failed to send flags to user space: %ld\n", ret);
- + return ret;
- + }
- +
- + return 0;
- +}
- +
- +static long asrc_ioctl_flush(struct asrc_pair_params *params,
- + void __user *user)
- +{
- + enum asrc_pair_index index = params->index;
- + init_completion(¶ms->input_complete);
- + init_completion(¶ms->output_complete);
- + init_completion(¶ms->lastperiod_complete);
- +
- + /* Release DMA and request again */
- + dma_release_channel(params->input_dma_channel);
- + dma_release_channel(params->output_dma_channel);
- +
- + params->input_dma_channel = imx_asrc_get_dma_channel(index, true);
- + if (params->input_dma_channel == NULL) {
- + pair_err("failed to request input task dma channel\n");
- + return -EBUSY;
- + }
- +
- + params->output_dma_channel = imx_asrc_get_dma_channel(index, false);
- + if (params->output_dma_channel == NULL) {
- + pair_err("failed to request output task dma channel\n");
- + return -EBUSY;
- + }
- +
- + return 0;
- +}
- +
- +static long asrc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
- +{
- + struct asrc_pair_params *params = file->private_data;
- + void __user *user = (void __user *)arg;
- + long ret = 0;
- +
- + switch (cmd) {
- + case ASRC_REQ_PAIR:
- + ret = asrc_ioctl_req_pair(params, user);
- + break;
- + case ASRC_CONFIG_PAIR:
- + ret = asrc_ioctl_config_pair(params, user);
- + break;
- + case ASRC_RELEASE_PAIR:
- + ret = asrc_ioctl_release_pair(params, user);
- + break;
- + case ASRC_CONVERT:
- + ret = asrc_ioctl_convert(params, user);
- + break;
- + case ASRC_START_CONV:
- + ret = asrc_ioctl_start_conv(params, user);
- + dump_regs();
- + break;
- + case ASRC_STOP_CONV:
- + ret = asrc_ioctl_stop_conv(params, user);
- + break;
- + case ASRC_STATUS:
- + ret = asrc_ioctl_status(params, user);
- + break;
- + case ASRC_FLUSH:
- + ret = asrc_ioctl_flush(params, user);
- + break;
- + default:
- + dev_err(asrc->dev, "invalid ioctl cmd!\n");
- + break;
- + }
- +
- + return ret;
- +}
- +
- +static int mxc_asrc_open(struct inode *inode, struct file *file)
- +{
- + struct asrc_pair_params *params;
- + int ret = 0;
- +
- + ret = signal_pending(current);
- + if (ret) {
- + dev_err(asrc->dev, "current process has a signal pending\n");
- + return ret;
- + }
- +
- + params = kzalloc(sizeof(struct asrc_pair_params), GFP_KERNEL);
- + if (params == NULL) {
- + dev_err(asrc->dev, "failed to allocate pair_params\n");
- + return -ENOBUFS;
- + }
- +
- + file->private_data = params;
- +
- + return ret;
- +}
- +
- +static int mxc_asrc_close(struct inode *inode, struct file *file)
- +{
- + struct asrc_pair_params *params;
- + unsigned long lock_flags;
- +
- + params = file->private_data;
- +
- + if (!params)
- + return 0;
- +
- + if (params->asrc_active) {
- + params->asrc_active = 0;
- +
- + dmaengine_terminate_all(params->input_dma_channel);
- + dmaengine_terminate_all(params->output_dma_channel);
- +
- + asrc_stop_conv(params->index);
- +
- + complete(¶ms->input_complete);
- + complete(¶ms->output_complete);
- + complete(¶ms->lastperiod_complete);
- + }
- +
- + if (params->pair_hold) {
- + spin_lock_irqsave(&pair_lock, lock_flags);
- + params->pair_hold = 0;
- + spin_unlock_irqrestore(&pair_lock, lock_flags);
- +
- + if (params->input_dma_channel)
- + dma_release_channel(params->input_dma_channel);
- + if (params->output_dma_channel)
- + dma_release_channel(params->output_dma_channel);
- +
- + mxc_free_dma_buf(params);
- +
- + asrc_release_pair(params->index);
- + asrc_finish_conv(params->index);
- + }
- +
- + kfree(params);
- + file->private_data = NULL;
- +
- + return 0;
- +}
- +
- +static int mxc_asrc_mmap(struct file *file, struct vm_area_struct *vma)
- +{
- + unsigned long size = vma->vm_end - vma->vm_start;
- + int ret;
- +
- + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- +
- + ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- + size, vma->vm_page_prot);
- + if (ret) {
- + dev_err(asrc->dev, "failed to memory map!\n");
- + return ret;
- + }
- +
- + vma->vm_flags &= ~VM_IO;
- +
- + return ret;
- +}
- +
- +static const struct file_operations asrc_fops = {
- + .owner = THIS_MODULE,
- + .unlocked_ioctl = asrc_ioctl,
- + .mmap = mxc_asrc_mmap,
- + .open = mxc_asrc_open,
- + .release = mxc_asrc_close,
- +};
- +
- +static struct miscdevice asrc_miscdev = {
- + .name = "mxc_asrc",
- + .fops = &asrc_fops,
- + .minor = MISC_DYNAMIC_MINOR,
- +};
- +
- +static int asrc_read_proc_attr(struct file *file, char __user *buf,
- + size_t count, loff_t *off)
- +{
- + char tmpbuf[80];
- + int len = 0;
- + u32 reg;
- +
- + if (*off)
- + return 0;
- +
- + regmap_read(asrc->regmap, REG_ASRCNCR, ®);
- +
- + len += sprintf(tmpbuf, "ANCA: %d\nANCB: %d\nANCC: %d\n",
- + ASRCNCR_ANCx_get(ASRC_PAIR_A, reg, asrc->channel_bits),
- + ASRCNCR_ANCx_get(ASRC_PAIR_B, reg, asrc->channel_bits),
- + ASRCNCR_ANCx_get(ASRC_PAIR_C, reg, asrc->channel_bits));
- +
- + if (len > count)
- + return 0;
- +
- + if (copy_to_user(buf, &tmpbuf, len))
- + return -EFAULT;
- +
- + *off += len;
- +
- + return len;
- +}
- +
- +#define ASRC_MAX_PROC_BUFFER_SIZE 63
- +
- +static int asrc_write_proc_attr(struct file *file, const char __user *buffer,
- + size_t count, loff_t *data)
- +{
- + char buf[ASRC_MAX_PROC_BUFFER_SIZE];
- + int na, nb, nc;
- + int total;
- +
- + if (count > ASRC_MAX_PROC_BUFFER_SIZE) {
- + dev_err(asrc->dev, "proc write: the input string was too long\n");
- + return -EINVAL;
- + }
- +
- + if (copy_from_user(buf, buffer, count)) {
- + dev_err(asrc->dev, "proc write: failed to copy buffer from user\n");
- + return -EFAULT;
- + }
- +
- + sscanf(buf, "ANCA: %d\nANCB: %d\nANCC: %d", &na, &nb, &nc);
- +
- + total = asrc->channel_bits > 3 ? 10 : 5;
- +
- + if (na + nb + nc > total) {
- + dev_err(asrc->dev, "don't surpass %d for total\n", total);
- + return -EINVAL;
- + } else if (na % 2 != 0 || nb % 2 != 0 || nc % 2 != 0) {
- + dev_err(asrc->dev, "please set an even number for each pair\n");
- + return -EINVAL;
- + } else if (na < 0 || nb < 0 || nc < 0) {
- + dev_err(asrc->dev, "please set an positive number for each pair\n");
- + return -EINVAL;
- + }
- +
- +
- + asrc->asrc_pair[ASRC_PAIR_A].chn_max = na;
- + asrc->asrc_pair[ASRC_PAIR_B].chn_max = nb;
- + asrc->asrc_pair[ASRC_PAIR_C].chn_max = nc;
- +
- + /* Update channel number settings */
- + regmap_update_bits(asrc->regmap, REG_ASRCNCR,
- + ASRCNCR_ANCx_MASK(ASRC_PAIR_A, asrc->channel_bits),
- + ASRCNCR_ANCx_set(ASRC_PAIR_A, na, asrc->channel_bits));
- + regmap_update_bits(asrc->regmap, REG_ASRCNCR,
- + ASRCNCR_ANCx_MASK(ASRC_PAIR_B, asrc->channel_bits),
- + ASRCNCR_ANCx_set(ASRC_PAIR_B, nb, asrc->channel_bits));
- + regmap_update_bits(asrc->regmap, REG_ASRCNCR,
- + ASRCNCR_ANCx_MASK(ASRC_PAIR_C, asrc->channel_bits),
- + ASRCNCR_ANCx_set(ASRC_PAIR_C, nc, asrc->channel_bits));
- +
- + return count;
- +}
- +
- +static const struct file_operations asrc_proc_fops = {
- + .read = asrc_read_proc_attr,
- + .write = asrc_write_proc_attr,
- +};
- +
- +static void asrc_proc_create(void)
- +{
- + struct proc_dir_entry *proc_attr;
- +
- + asrc->proc_asrc = proc_mkdir(ASRC_PROC_PATH, NULL);
- + if (!asrc->proc_asrc) {
- + dev_err(asrc->dev, "failed to create proc entry %s\n", ASRC_PROC_PATH);
- + return;
- + }
- +
- + proc_attr = proc_create("ChSettings", S_IFREG | S_IRUGO | S_IWUSR,
- + asrc->proc_asrc, &asrc_proc_fops);
- + if (!proc_attr) {
- + remove_proc_entry(ASRC_PROC_PATH, NULL);
- + dev_err(asrc->dev, "failed to create proc attribute entry\n");
- + }
- +}
- +
- +static void asrc_proc_remove(void)
- +{
- + remove_proc_entry("ChSettings", asrc->proc_asrc);
- + remove_proc_entry(ASRC_PROC_PATH, NULL);
- +}
- +
- +
- +static bool asrc_readable_reg(struct device *dev, unsigned int reg)
- +{
- + switch (reg) {
- + case REG_ASRCTR:
- + case REG_ASRIER:
- + case REG_ASRCNCR:
- + case REG_ASRCFG:
- + case REG_ASRCSR:
- + case REG_ASRCDR1:
- + case REG_ASRCDR2:
- + case REG_ASRSTR:
- + case REG_ASRPM1:
- + case REG_ASRPM2:
- + case REG_ASRPM3:
- + case REG_ASRPM4:
- + case REG_ASRPM5:
- + case REG_ASRTFR1:
- + case REG_ASRCCR:
- + case REG_ASRDOA:
- + case REG_ASRDOB:
- + case REG_ASRDOC:
- + case REG_ASRIDRHA:
- + case REG_ASRIDRLA:
- + case REG_ASRIDRHB:
- + case REG_ASRIDRLB:
- + case REG_ASRIDRHC:
- + case REG_ASRIDRLC:
- + case REG_ASR76K:
- + case REG_ASR56K:
- + case REG_ASRMCRA:
- + case REG_ASRFSTA:
- + case REG_ASRMCRB:
- + case REG_ASRFSTB:
- + case REG_ASRMCRC:
- + case REG_ASRFSTC:
- + case REG_ASRMCR1A:
- + case REG_ASRMCR1B:
- + case REG_ASRMCR1C:
- + return true;
- + default:
- + return false;
- + }
- +}
- +
- +static bool asrc_writeable_reg(struct device *dev, unsigned int reg)
- +{
- + switch (reg) {
- + case REG_ASRCTR:
- + case REG_ASRIER:
- + case REG_ASRCNCR:
- + case REG_ASRCFG:
- + case REG_ASRCSR:
- + case REG_ASRCDR1:
- + case REG_ASRCDR2:
- + case REG_ASRSTR:
- + case REG_ASRPM1:
- + case REG_ASRPM2:
- + case REG_ASRPM3:
- + case REG_ASRPM4:
- + case REG_ASRPM5:
- + case REG_ASRTFR1:
- + case REG_ASRCCR:
- + case REG_ASRDIA:
- + case REG_ASRDIB:
- + case REG_ASRDIC:
- + case REG_ASRIDRHA:
- + case REG_ASRIDRLA:
- + case REG_ASRIDRHB:
- + case REG_ASRIDRLB:
- + case REG_ASRIDRHC:
- + case REG_ASRIDRLC:
- + case REG_ASR76K:
- + case REG_ASR56K:
- + case REG_ASRMCRA:
- + case REG_ASRMCRB:
- + case REG_ASRMCRC:
- + case REG_ASRMCR1A:
- + case REG_ASRMCR1B:
- + case REG_ASRMCR1C:
- + return true;
- + default:
- + return false;
- + }
- +}
- +
- +static struct regmap_config asrc_regmap_config = {
- + .reg_bits = 32,
- + .reg_stride = 4,
- + .val_bits = 32,
- +
- + .max_register = REG_ASRMCR1C,
- + .readable_reg = asrc_readable_reg,
- + .writeable_reg = asrc_writeable_reg,
- +};
- +
- +static int mxc_asrc_probe(struct platform_device *pdev)
- +{
- + const struct of_device_id *of_id = of_match_device(fsl_asrc_ids, &pdev->dev);
- + struct device_node *np = pdev->dev.of_node;
- + enum mxc_asrc_type devtype;
- + struct resource *res;
- + void __iomem *regs;
- + int ret;
- +
- + /* Check if the device is existed */
- + if (!np)
- + return -ENODEV;
- +
- + asrc = devm_kzalloc(&pdev->dev, sizeof(struct asrc_data), GFP_KERNEL);
- + if (!asrc)
- + return -ENOMEM;
- +
- + if (of_id) {
- + const struct platform_device_id *id_entry = of_id->data;
- + devtype = id_entry->driver_data;
- + } else {
- + devtype = pdev->id_entry->driver_data;
- + }
- +
- + asrc->dev = &pdev->dev;
- + asrc->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- +
- + asrc->asrc_pair[ASRC_PAIR_A].chn_max = 2;
- + asrc->asrc_pair[ASRC_PAIR_B].chn_max = 6;
- + asrc->asrc_pair[ASRC_PAIR_C].chn_max = 2;
- + asrc->asrc_pair[ASRC_PAIR_A].overload_error = 0;
- + asrc->asrc_pair[ASRC_PAIR_B].overload_error = 0;
- + asrc->asrc_pair[ASRC_PAIR_C].overload_error = 0;
- +
- + /* Map the address */
- + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- + if (IS_ERR(res)) {
- + dev_err(&pdev->dev, "could not determine device resources\n");
- + return PTR_ERR(res);
- + }
- +
- + regs = devm_ioremap_resource(&pdev->dev, res);
- + if (IS_ERR(regs)) {
- + dev_err(&pdev->dev, "could not map device resources\n");
- + return PTR_ERR(regs);
- + }
- + asrc->paddr = res->start;
- +
- + /* Register regmap and let it prepare core clock */
- + asrc->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
- + "core", regs, &asrc_regmap_config);
- + if (IS_ERR(asrc->regmap)) {
- + dev_err(&pdev->dev, "regmap init failed\n");
- + return PTR_ERR(asrc->regmap);
- + }
- +
- + asrc->irq = platform_get_irq(pdev, 0);
- + if (asrc->irq == NO_IRQ) {
- + dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
- + return asrc->irq;
- + }
- +
- + ret = devm_request_irq(&pdev->dev, asrc->irq, asrc_isr, 0, np->name, NULL);
- + if (ret) {
- + dev_err(&pdev->dev, "could not claim irq %u: %d\n", asrc->irq, ret);
- + return ret;
- + }
- +
- + asrc->asrc_clk = devm_clk_get(&pdev->dev, "core");
- + if (IS_ERR(asrc->asrc_clk)) {
- + dev_err(&pdev->dev, "failed to get core clock\n");
- + return PTR_ERR(asrc->asrc_clk);
- + }
- +
- + asrc->dma_clk = devm_clk_get(&pdev->dev, "dma");
- + if (IS_ERR(asrc->dma_clk)) {
- + dev_err(&pdev->dev, "failed to get dma script clock\n");
- + return PTR_ERR(asrc->dma_clk);
- + }
- +
- + switch (devtype) {
- + case IMX35_ASRC:
- + asrc->channel_bits = 3;
- + input_clk_map = input_clk_map_v1;
- + output_clk_map = output_clk_map_v1;
- + break;
- + case IMX53_ASRC:
- + asrc->channel_bits = 4;
- + input_clk_map = input_clk_map_v2;
- + output_clk_map = output_clk_map_v2;
- + break;
- + default:
- + dev_err(&pdev->dev, "unsupported device type\n");
- + return -EINVAL;
- + }
- +
- + ret = misc_register(&asrc_miscdev);
- + if (ret) {
- + dev_err(&pdev->dev, "failed to register char device %d\n", ret);
- + return ret;
- + }
- +
- + asrc_proc_create();
- +
- + ret = mxc_init_asrc();
- + if (ret) {
- + dev_err(&pdev->dev, "failed to init asrc %d\n", ret);
- + goto err_misc;
- + }
- +
- + dev_info(&pdev->dev, "mxc_asrc registered\n");
- +
- + return ret;
- +
- +err_misc:
- + misc_deregister(&asrc_miscdev);
- +
- + return ret;
- +}
- +
- +static int mxc_asrc_remove(struct platform_device *pdev)
- +{
- + asrc_proc_remove();
- + misc_deregister(&asrc_miscdev);
- +
- + return 0;
- +}
- +
- +static struct platform_driver mxc_asrc_driver = {
- + .driver = {
- + .name = "mxc_asrc",
- + .of_match_table = fsl_asrc_ids,
- + },
- + .probe = mxc_asrc_probe,
- + .remove = mxc_asrc_remove,
- +};
- +
- +module_platform_driver(mxc_asrc_driver);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("Asynchronous Sample Rate Converter");
- +MODULE_LICENSE("GPL");
- +MODULE_ALIAS("platform:mxc_asrc");
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.c linux-3.14.35/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.c 2015-03-08 14:27:37.617684501 -0500
- @@ -0,0 +1,932 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal.h"
- +#include "gc_hal_kernel.h"
- +
- +#if gcdENABLE_VG
- +
- +#include "gc_hal_kernel_hardware_command_vg.h"
- +
- +#define _GC_OBJ_ZONE gcvZONE_COMMAND
- +
- +/******************************************************************************\
- +****************************** gckVGCOMMAND API code *****************************
- +\******************************************************************************/
- +
- +/*******************************************************************************
- +**
- +** gckVGCOMMAND_InitializeInfo
- +**
- +** Initialize architecture dependent command buffer information.
- +**
- +** INPUT:
- +**
- +** gckVGCOMMAND Command
- +** Pointer to the Command object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckVGCOMMAND_InitializeInfo(
- + IN gckVGCOMMAND Command
- + )
- +{
- + gceSTATUS status;
- + gcmkHEADER_ARG("Command=0x%x", Command);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + do
- + {
- + /* Reset interrupts. */
- + Command->info.feBufferInt = -1;
- + Command->info.tsOverflowInt = -1;
- +
- + /* Set command buffer attributes. */
- + Command->info.addressAlignment = 64;
- + Command->info.commandAlignment = 8;
- +
- + /* Determine command alignment address mask. */
- + Command->info.addressMask = ((((gctUINT32) (Command->info.addressAlignment - 1)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) ((gctUINT32) (0 ) & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
- +
- + /* Query the number of bytes needed by the STATE command. */
- + gcmkERR_BREAK(gckVGCOMMAND_StateCommand(
- + Command, 0x0, gcvNULL, (gctUINT32)~0, 0,
- + &Command->info.stateCommandSize
- + ));
- +
- + /* Query the number of bytes needed by the RESTART command. */
- + gcmkERR_BREAK(gckVGCOMMAND_RestartCommand(
- + Command, gcvNULL, (gctUINT32)~0, 0,
- + &Command->info.restartCommandSize
- + ));
- +
- + /* Query the number of bytes needed by the FETCH command. */
- + gcmkERR_BREAK(gckVGCOMMAND_FetchCommand(
- + Command, gcvNULL, (gctUINT32)~0, 0,
- + &Command->info.fetchCommandSize
- + ));
- +
- + /* Query the number of bytes needed by the CALL command. */
- + gcmkERR_BREAK(gckVGCOMMAND_CallCommand(
- + Command, gcvNULL, (gctUINT32)~0, 0,
- + &Command->info.callCommandSize
- + ));
- +
- + /* Query the number of bytes needed by the RETURN command. */
- + gcmkERR_BREAK(gckVGCOMMAND_ReturnCommand(
- + Command, gcvNULL,
- + &Command->info.returnCommandSize
- + ));
- +
- + /* Query the number of bytes needed by the EVENT command. */
- + gcmkERR_BREAK(gckVGCOMMAND_EventCommand(
- + Command, gcvNULL, gcvBLOCK_PIXEL, -1,
- + &Command->info.eventCommandSize
- + ));
- +
- + /* Query the number of bytes needed by the END command. */
- + gcmkERR_BREAK(gckVGCOMMAND_EndCommand(
- + Command, gcvNULL, -1,
- + &Command->info.endCommandSize
- + ));
- +
- + /* Determine the tail reserve size. */
- + Command->info.staticTailSize = gcmMAX(
- + Command->info.fetchCommandSize,
- + gcmMAX(
- + Command->info.returnCommandSize,
- + Command->info.endCommandSize
- + )
- + );
- +
- + /* Determine the maximum tail size. */
- + Command->info.dynamicTailSize
- + = Command->info.staticTailSize
- + + Command->info.eventCommandSize * gcvBLOCK_COUNT;
- + }
- + while (gcvFALSE);
- +
- + gcmkFOOTER();
- + /* Return status. */
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGCOMMAND_StateCommand
- +**
- +** Append a STATE command at the specified location in the command buffer.
- +**
- +** INPUT:
- +**
- +** gckVGCOMMAND Command
- +** Pointer to an gckVGCOMMAND object.
- +**
- +** gctUINT32 Pipe
- +** Harwdare destination pipe.
- +**
- +** gctPOINTER Logical
- +** Pointer to the current location inside the command buffer to append
- +** STATE command at or gcvNULL to query the size of the command.
- +**
- +** gctUINT32 Address
- +** Starting register address of the state buffer.
- +** If 'Logical' is gcvNULL, this argument is ignored.
- +**
- +** gctUINT32 Count
- +** Number of states in state buffer.
- +** If 'Logical' is gcvNULL, this argument is ignored.
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to the number of bytes available for the STATE command.
- +** If 'Logical' is gcvNULL, the value from this argument is ignored.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to a variable that will receive the number of bytes required
- +** for the STATE command. If 'Bytes' is gcvNULL, nothing is returned.
- +*/
- +gceSTATUS
- +gckVGCOMMAND_StateCommand(
- + IN gckVGCOMMAND Command,
- + IN gctUINT32 Pipe,
- + IN gctPOINTER Logical,
- + IN gctUINT32 Address,
- + IN gctSIZE_T Count,
- + IN OUT gctSIZE_T * Bytes
- + )
- +{
- + gcmkHEADER_ARG("Command=0x%x Pipe=0x%x Logical=0x%x Address=0x%x Count=0x%x Bytes = 0x%x",
- + Command, Pipe, Logical, Address, Count, Bytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + if (Command->fe20)
- + {
- + if (Logical != gcvNULL)
- + {
- + gctUINT32_PTR buffer;
- +
- + /* Cast the buffer pointer. */
- + buffer = (gctUINT32_PTR) Logical;
- +
- + /* Append STATE. */
- + buffer[0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:0) - (0 ? 11:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:0) - (0 ? 11:0) + 1))))))) << (0 ? 11:0))) | (((gctUINT32) ((gctUINT32) (Address) & ((gctUINT32) ((((1 ? 11:0) - (0 ? 11:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:0) - (0 ? 11:0) + 1))))))) << (0 ? 11:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:16) - (0 ? 27:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:16) - (0 ? 27:16) + 1))))))) << (0 ? 27:16))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ? 27:16) - (0 ? 27:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:16) - (0 ? 27:16) + 1))))))) << (0 ? 27:16)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 13:12) - (0 ? 13:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:12) - (0 ? 13:12) + 1))))))) << (0 ? 13:12))) | (((gctUINT32) ((gctUINT32) (Pipe) & ((gctUINT32) ((((1 ? 13:12) - (0 ? 13:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:12) - (0 ? 13:12) + 1))))))) << (0 ? 13:12)));
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return number of bytes required by the STATE command. */
- + *Bytes = 4 * (Count + 1);
- + }
- + }
- + else
- + {
- + if (Logical != gcvNULL)
- + {
- + gctUINT32_PTR buffer;
- +
- + /* Cast the buffer pointer. */
- + buffer = (gctUINT32_PTR) Logical;
- +
- + /* Append LOAD_STATE. */
- + buffer[0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Address) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return number of bytes required by the STATE command. */
- + *Bytes = 4 * (Count + 1);
- + }
- + }
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGCOMMAND_RestartCommand
- +**
- +** Form a RESTART command at the specified location in the command buffer.
- +**
- +** INPUT:
- +**
- +** gckVGCOMMAND Command
- +** Pointer to an gckVGCOMMAND object.
- +**
- +** gctPOINTER Logical
- +** Pointer to the current location inside the command buffer to append
- +** RESTART command at or gcvNULL to query the size of the command.
- +**
- +** gctUINT32 FetchAddress
- +** The address of another command buffer to be executed by this RESTART
- +** command. If 'Logical' is gcvNULL, this argument is ignored.
- +**
- +** gctUINT FetchCount
- +** The number of 64-bit data quantities in another command buffer to
- +** be executed by this RESTART command. If 'Logical' is gcvNULL, this
- +** argument is ignored.
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to the number of bytes available for the RESTART command.
- +** If 'Logical' is gcvNULL, the value from this argument is ignored.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to a variable that will receive the number of bytes required
- +** for the RESTART command. If 'Bytes' is gcvNULL, nothing is returned.
- +*/
- +gceSTATUS
- +gckVGCOMMAND_RestartCommand(
- + IN gckVGCOMMAND Command,
- + IN gctPOINTER Logical,
- + IN gctUINT32 FetchAddress,
- + IN gctUINT FetchCount,
- + IN OUT gctSIZE_T * Bytes
- + )
- +{
- + gcmkHEADER_ARG("Command=0x%x Logical=0x%x FetchAddress=0x%x FetchCount=0x%x Bytes = 0x%x",
- + Command, Logical, FetchAddress, FetchCount, Bytes);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + if (Command->fe20)
- + {
- + if (Logical != gcvNULL)
- + {
- + gctUINT32_PTR buffer;
- + gctUINT32 beginEndMark;
- +
- + /* Cast the buffer pointer. */
- + buffer = (gctUINT32_PTR) Logical;
- +
- + /* Determine Begin/End flag. */
- + beginEndMark = (FetchCount > 0)
- + ? ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24)))
- + : ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24)));
- +
- + /* Append RESTART. */
- + buffer[0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x9 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0))) | (((gctUINT32) ((gctUINT32) (FetchCount) & ((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0)))
- + | beginEndMark;
- +
- + buffer[1]
- + = FetchAddress;
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return number of bytes required by the RESTART command. */
- + *Bytes = 8;
- + }
- + }
- + else
- + {
- + gcmkFOOTER_NO();
- + return gcvSTATUS_NOT_SUPPORTED;
- + }
- +
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGCOMMAND_FetchCommand
- +**
- +** Form a FETCH command at the specified location in the command buffer.
- +**
- +** INPUT:
- +**
- +** gckVGCOMMAND Command
- +** Pointer to an gckVGCOMMAND object.
- +**
- +** gctPOINTER Logical
- +** Pointer to the current location inside the command buffer to append
- +** FETCH command at or gcvNULL to query the size of the command.
- +**
- +** gctUINT32 FetchAddress
- +** The address of another command buffer to be executed by this FETCH
- +** command. If 'Logical' is gcvNULL, this argument is ignored.
- +**
- +** gctUINT FetchCount
- +** The number of 64-bit data quantities in another command buffer to
- +** be executed by this FETCH command. If 'Logical' is gcvNULL, this
- +** argument is ignored.
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to the number of bytes available for the FETCH command.
- +** If 'Logical' is gcvNULL, the value from this argument is ignored.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to a variable that will receive the number of bytes required
- +** for the FETCH command. If 'Bytes' is gcvNULL, nothing is returned.
- +*/
- +gceSTATUS
- +gckVGCOMMAND_FetchCommand(
- + IN gckVGCOMMAND Command,
- + IN gctPOINTER Logical,
- + IN gctUINT32 FetchAddress,
- + IN gctUINT FetchCount,
- + IN OUT gctSIZE_T * Bytes
- + )
- +{
- + gcmkHEADER_ARG("Command=0x%x Logical=0x%x FetchAddress=0x%x FetchCount=0x%x Bytes = 0x%x",
- + Command, Logical, FetchAddress, FetchCount, Bytes);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + if (Command->fe20)
- + {
- + if (Logical != gcvNULL)
- + {
- + gctUINT32_PTR buffer;
- +
- + /* Cast the buffer pointer. */
- + buffer = (gctUINT32_PTR) Logical;
- +
- + /* Append FETCH. */
- + buffer[0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x5 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0))) | (((gctUINT32) ((gctUINT32) (FetchCount) & ((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0)));
- +
- + buffer[1]
- + = gcmkFIXADDRESS(FetchAddress);
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return number of bytes required by the FETCH command. */
- + *Bytes = 8;
- + }
- + }
- + else
- + {
- + if (Logical != gcvNULL)
- + {
- + gctUINT32_PTR buffer;
- +
- + /* Cast the buffer pointer. */
- + buffer = (gctUINT32_PTR) Logical;
- +
- + /* Append LINK. */
- + buffer[0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (FetchCount) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + buffer[1]
- + = gcmkFIXADDRESS(FetchAddress);
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return number of bytes required by the LINK command. */
- + *Bytes = 8;
- + }
- + }
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGCOMMAND_CallCommand
- +**
- +** Append a CALL command at the specified location in the command buffer.
- +**
- +** INPUT:
- +**
- +** gckVGCOMMAND Command
- +** Pointer to an gckVGCOMMAND object.
- +**
- +** gctPOINTER Logical
- +** Pointer to the current location inside the command buffer to append
- +** CALL command at or gcvNULL to query the size of the command.
- +**
- +** gctUINT32 FetchAddress
- +** The address of another command buffer to be executed by this CALL
- +** command. If 'Logical' is gcvNULL, this argument is ignored.
- +**
- +** gctUINT FetchCount
- +** The number of 64-bit data quantities in another command buffer to
- +** be executed by this CALL command. If 'Logical' is gcvNULL, this
- +** argument is ignored.
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to the number of bytes available for the CALL command.
- +** If 'Logical' is gcvNULL, the value from this argument is ignored.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to a variable that will receive the number of bytes required
- +** for the CALL command. If 'Bytes' is gcvNULL, nothing is returned.
- +*/
- +gceSTATUS
- +gckVGCOMMAND_CallCommand(
- + IN gckVGCOMMAND Command,
- + IN gctPOINTER Logical,
- + IN gctUINT32 FetchAddress,
- + IN gctUINT FetchCount,
- + IN OUT gctSIZE_T * Bytes
- + )
- +{
- + gcmkHEADER_ARG("Command=0x%x Logical=0x%x FetchAddress=0x%x FetchCount=0x%x Bytes = 0x%x",
- + Command, Logical, FetchAddress, FetchCount, Bytes);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + if (Command->fe20)
- + {
- + if (Logical != gcvNULL)
- + {
- + gctUINT32_PTR buffer;
- +
- + /* Cast the buffer pointer. */
- + buffer = (gctUINT32_PTR) Logical;
- +
- + /* Append CALL. */
- + buffer[0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x6 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0))) | (((gctUINT32) ((gctUINT32) (FetchCount) & ((gctUINT32) ((((1 ? 20:0) - (0 ? 20:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ? 20:0)));
- +
- + buffer[1]
- + = gcmkFIXADDRESS(FetchAddress);
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return number of bytes required by the CALL command. */
- + *Bytes = 8;
- + }
- + }
- + else
- + {
- + gcmkFOOTER_NO();
- + return gcvSTATUS_NOT_SUPPORTED;
- + }
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGCOMMAND_ReturnCommand
- +**
- +** Append a RETURN command at the specified location in the command buffer.
- +**
- +** INPUT:
- +**
- +** gckVGCOMMAND Command
- +** Pointer to an gckVGCOMMAND object.
- +**
- +** gctPOINTER Logical
- +** Pointer to the current location inside the command buffer to append
- +** RETURN command at or gcvNULL to query the size of the command.
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to the number of bytes available for the RETURN command.
- +** If 'Logical' is gcvNULL, the value from this argument is ignored.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to a variable that will receive the number of bytes required
- +** for the RETURN command. If 'Bytes' is gcvNULL, nothing is returned.
- +*/
- +gceSTATUS
- +gckVGCOMMAND_ReturnCommand(
- + IN gckVGCOMMAND Command,
- + IN gctPOINTER Logical,
- + IN OUT gctSIZE_T * Bytes
- + )
- +{
- + gcmkHEADER_ARG("Command=0x%x Logical=0x%x Bytes = 0x%x",
- + Command, Logical, Bytes);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + if (Command->fe20)
- + {
- + if (Logical != gcvNULL)
- + {
- + gctUINT32_PTR buffer;
- +
- + /* Cast the buffer pointer. */
- + buffer = (gctUINT32_PTR) Logical;
- +
- + /* Append RETURN. */
- + buffer[0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x7 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)));
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return number of bytes required by the RETURN command. */
- + *Bytes = 8;
- + }
- + }
- + else
- + {
- + gcmkFOOTER_NO();
- + return gcvSTATUS_NOT_SUPPORTED;
- + }
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGCOMMAND_EventCommand
- +**
- +** Form an EVENT command at the specified location in the command buffer.
- +**
- +** INPUT:
- +**
- +** gckVGCOMMAND Command
- +** Pointer to the Command object.
- +**
- +** gctPOINTER Logical
- +** Pointer to the current location inside the command buffer to append
- +** EVENT command at or gcvNULL to query the size of the command.
- +**
- +** gctINT32 InterruptId
- +** The ID of the interrupt to generate.
- +** If 'Logical' is gcvNULL, this argument is ignored.
- +**
- +** gceBLOCK Block
- +** Block that will generate the interrupt.
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to the number of bytes available for the EVENT command.
- +** If 'Logical' is gcvNULL, the value from this argument is ignored.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to a variable that will receive the number of bytes required
- +** for the END command. If 'Bytes' is gcvNULL, nothing is returned.
- +*/
- +gceSTATUS
- +gckVGCOMMAND_EventCommand(
- + IN gckVGCOMMAND Command,
- + IN gctPOINTER Logical,
- + IN gceBLOCK Block,
- + IN gctINT32 InterruptId,
- + IN OUT gctSIZE_T * Bytes
- + )
- +{
- + gcmkHEADER_ARG("Command=0x%x Logical=0x%x Block=0x%x InterruptId=0x%x Bytes = 0x%x",
- + Command, Logical, Block, InterruptId, Bytes);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + if (Command->fe20)
- + {
- + typedef struct _gcsEVENTSTATES
- + {
- + /* Chips before VG21 use these values. */
- + gctUINT eventFromFE;
- + gctUINT eventFromPE;
- +
- + /* VG21 chips and later use SOURCE field. */
- + gctUINT eventSource;
- + }
- + gcsEVENTSTATES;
- +
- + static gcsEVENTSTATES states[] =
- + {
- + /* gcvBLOCK_COMMAND */
- + {
- + (gctUINT)~0,
- + (gctUINT)~0,
- + (gctUINT)~0
- + },
- +
- + /* gcvBLOCK_TESSELLATOR */
- + {
- + 0x0,
- + 0x1,
- + 0x10
- + },
- +
- + /* gcvBLOCK_TESSELLATOR2 */
- + {
- + 0x0,
- + 0x1,
- + 0x12
- + },
- +
- + /* gcvBLOCK_TESSELLATOR3 */
- + {
- + 0x0,
- + 0x1,
- + 0x14
- + },
- +
- + /* gcvBLOCK_RASTER */
- + {
- + 0x0,
- + 0x1,
- + 0x07,
- + },
- +
- + /* gcvBLOCK_VG */
- + {
- + 0x0,
- + 0x1,
- + 0x0F
- + },
- +
- + /* gcvBLOCK_VG2 */
- + {
- + 0x0,
- + 0x1,
- + 0x11
- + },
- +
- + /* gcvBLOCK_VG3 */
- + {
- + 0x0,
- + 0x1,
- + 0x13
- + },
- +
- + /* gcvBLOCK_PIXEL */
- + {
- + 0x0,
- + 0x1,
- + 0x07
- + },
- + };
- +
- + /* Verify block ID. */
- + gcmkVERIFY_ARGUMENT(gcmIS_VALID_INDEX(Block, states));
- +
- + if (Logical != gcvNULL)
- + {
- + gctUINT32_PTR buffer;
- +
- + /* Verify the event ID. */
- + gcmkVERIFY_ARGUMENT(InterruptId >= 0);
- + gcmkVERIFY_ARGUMENT(InterruptId <= ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))));
- +
- + /* Cast the buffer pointer. */
- + buffer = (gctUINT32_PTR) Logical;
- +
- + /* Append EVENT. */
- + buffer[0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:0) - (0 ? 11:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:0) - (0 ? 11:0) + 1))))))) << (0 ? 11:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 11:0) - (0 ? 11:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:0) - (0 ? 11:0) + 1))))))) << (0 ? 11:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:16) - (0 ? 27:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:16) - (0 ? 27:16) + 1))))))) << (0 ? 27:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 27:16) - (0 ? 27:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:16) - (0 ? 27:16) + 1))))))) << (0 ? 27:16)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 13:12) - (0 ? 13:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:12) - (0 ? 13:12) + 1))))))) << (0 ? 13:12))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 13:12) - (0 ? 13:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:12) - (0 ? 13:12) + 1))))))) << (0 ? 13:12)));
- +
- + /* Determine chip version. */
- + if (Command->vg21)
- + {
- + /* Get the event source for the block. */
- + gctUINT eventSource = states[Block].eventSource;
- +
- + /* Supported? */
- + if (eventSource == ~0)
- + {
- + gcmkFOOTER_NO();
- + return gcvSTATUS_NOT_SUPPORTED;
- + }
- +
- + buffer[1]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) ((gctUINT32) (eventSource) & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
- + }
- + else
- + {
- + /* Get the event source for the block. */
- + gctUINT eventFromFE = states[Block].eventFromFE;
- + gctUINT eventFromPE = states[Block].eventFromPE;
- +
- + /* Supported? */
- + if (eventFromFE == ~0)
- + {
- + gcmkFOOTER_NO();
- + return gcvSTATUS_NOT_SUPPORTED;
- + }
- +
- + buffer[1]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) ((gctUINT32) (eventFromFE) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) ((gctUINT32) (eventFromPE) & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
- + }
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Make sure the events are directly supported for the block. */
- + if (states[Block].eventSource == ~0)
- + {
- + gcmkFOOTER_NO();
- + return gcvSTATUS_NOT_SUPPORTED;
- + }
- +
- + /* Return number of bytes required by the END command. */
- + *Bytes = 8;
- + }
- + }
- + else
- + {
- + if (Logical != gcvNULL)
- + {
- + gctUINT32_PTR buffer;
- +
- + /* Verify the event ID. */
- + gcmkVERIFY_ARGUMENT(InterruptId >= 0);
- + gcmkVERIFY_ARGUMENT(InterruptId <= ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))));
- +
- + /* Cast the buffer pointer. */
- + buffer = (gctUINT32_PTR) Logical;
- +
- + /* Append EVENT. */
- + buffer[0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + /* Determine event source. */
- + if (Block == gcvBLOCK_COMMAND)
- + {
- + buffer[1]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
- + }
- + else
- + {
- + buffer[1]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
- + }
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return number of bytes required by the EVENT and END commands. */
- + *Bytes = 8;
- + }
- + }
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGCOMMAND_EndCommand
- +**
- +** Form an END command at the specified location in the command buffer.
- +**
- +** INPUT:
- +**
- +** gckVGCOMMAND Command
- +** Pointer to the Command object.
- +**
- +** gctPOINTER Logical
- +** Pointer to the current location inside the command buffer to append
- +** END command at or gcvNULL to query the size of the command.
- +**
- +** gctINT32 InterruptId
- +** The ID of the interrupt to generate.
- +** If 'Logical' is gcvNULL, this argument will be ignored.
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to the number of bytes available for the END command.
- +** If 'Logical' is gcvNULL, the value from this argument is ignored.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to a variable that will receive the number of bytes required
- +** for the END command. If 'Bytes' is gcvNULL, nothing is returned.
- +*/
- +gceSTATUS
- +gckVGCOMMAND_EndCommand(
- + IN gckVGCOMMAND Command,
- + IN gctPOINTER Logical,
- + IN gctINT32 InterruptId,
- + IN OUT gctSIZE_T * Bytes
- + )
- +{
- + gcmkHEADER_ARG("Command=0x%x Logical=0x%x InterruptId=0x%x Bytes = 0x%x",
- + Command, Logical, InterruptId, Bytes);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + if (Command->fe20)
- + {
- + if (Logical != gcvNULL)
- + {
- + gctUINT32_PTR buffer;
- +
- + /* Verify the event ID. */
- + gcmkVERIFY_ARGUMENT(InterruptId >= 0);
- +
- + /* Cast the buffer pointer. */
- + buffer = (gctUINT32_PTR) Logical;
- +
- + /* Append END. */
- + buffer[0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1))))))) << (0 ? 31:28)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)));
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return number of bytes required by the END command. */
- + *Bytes = 8;
- + }
- + }
- + else
- + {
- + if (Logical != gcvNULL)
- + {
- + gctUINT32_PTR memory;
- +
- + /* Verify the event ID. */
- + gcmkVERIFY_ARGUMENT(InterruptId >= 0);
- +
- + /* Cast the buffer pointer. */
- + memory = (gctUINT32_PTR) Logical;
- +
- + /* Append EVENT. */
- + memory[0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + memory[1]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
- +
- + /* Append END. */
- + memory[2]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x02 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return number of bytes required by the EVENT and END commands. */
- + *Bytes = 16;
- + }
- + }
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +#endif /* gcdENABLE_VG */
- +
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.h linux-3.14.35/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_command_vg.h 2015-03-08 14:27:37.617684501 -0500
- @@ -0,0 +1,319 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_kernel_hardware_command_vg_h_
- +#define __gc_hal_kernel_hardware_command_vg_h_
- +
- +/******************************************************************************\
- +******************* Task and Interrupt Management Structures. ******************
- +\******************************************************************************/
- +
- +/* Task storage header. */
- +typedef struct _gcsTASK_STORAGE * gcsTASK_STORAGE_PTR;
- +typedef struct _gcsTASK_STORAGE
- +{
- + /* Next allocated storage buffer. */
- + gcsTASK_STORAGE_PTR next;
- +}
- +gcsTASK_STORAGE;
- +
- +/* Task container header. */
- +typedef struct _gcsTASK_CONTAINER * gcsTASK_CONTAINER_PTR;
- +typedef struct _gcsTASK_CONTAINER
- +{
- + /* The number of tasks left to be processed in the container. */
- + gctINT referenceCount;
- +
- + /* Size of the buffer. */
- + gctUINT size;
- +
- + /* Link to the previous and the next allocated containers. */
- + gcsTASK_CONTAINER_PTR allocPrev;
- + gcsTASK_CONTAINER_PTR allocNext;
- +
- + /* Link to the previous and the next containers in the free list. */
- + gcsTASK_CONTAINER_PTR freePrev;
- + gcsTASK_CONTAINER_PTR freeNext;
- +}
- +gcsTASK_CONTAINER;
- +
- +/* Kernel space task master table entry. */
- +typedef struct _gcsBLOCK_TASK_ENTRY * gcsBLOCK_TASK_ENTRY_PTR;
- +typedef struct _gcsBLOCK_TASK_ENTRY
- +{
- + /* Pointer to the current task container for the block. */
- + gcsTASK_CONTAINER_PTR container;
- +
- + /* Pointer to the current task data within the container. */
- + gcsTASK_HEADER_PTR task;
- +
- + /* Pointer to the last link task within the container. */
- + gcsTASK_LINK_PTR link;
- +
- + /* Number of interrupts allocated for this block. */
- + gctUINT interruptCount;
- +
- + /* The index of the current interrupt. */
- + gctUINT interruptIndex;
- +
- + /* Interrupt semaphore. */
- + gctSEMAPHORE interruptSemaphore;
- +
- + /* Interrupt value array. */
- + gctINT32 interruptArray[32];
- +}
- +gcsBLOCK_TASK_ENTRY;
- +
- +
- +/******************************************************************************\
- +********************* Command Queue Management Structures. *********************
- +\******************************************************************************/
- +
- +/* Command queue kernel element pointer. */
- +typedef struct _gcsKERNEL_CMDQUEUE * gcsKERNEL_CMDQUEUE_PTR;
- +
- +/* Command queue object handler function type. */
- +typedef gceSTATUS (* gctOBJECT_HANDLER) (
- + gckVGKERNEL Kernel,
- + gcsKERNEL_CMDQUEUE_PTR Entry
- + );
- +
- +/* Command queue kernel element. */
- +typedef struct _gcsKERNEL_CMDQUEUE
- +{
- + /* The number of buffers in the queue. */
- + gcsCMDBUFFER_PTR commandBuffer;
- +
- + /* Pointer to the object handler function. */
- + gctOBJECT_HANDLER handler;
- +}
- +gcsKERNEL_CMDQUEUE;
- +
- +/* Command queue header. */
- +typedef struct _gcsKERNEL_QUEUE_HEADER * gcsKERNEL_QUEUE_HEADER_PTR;
- +typedef struct _gcsKERNEL_QUEUE_HEADER
- +{
- + /* The size of the buffer in bytes. */
- + gctUINT size;
- +
- + /* The number of pending entries to be processed. */
- + volatile gctUINT pending;
- +
- + /* The current command queue entry. */
- + gcsKERNEL_CMDQUEUE_PTR currentEntry;
- +
- + /* Next buffer. */
- + gcsKERNEL_QUEUE_HEADER_PTR next;
- +}
- +gcsKERNEL_QUEUE_HEADER;
- +
- +
- +/******************************************************************************\
- +******************************* gckVGCOMMAND Object *******************************
- +\******************************************************************************/
- +
- +/* gckVGCOMMAND object. */
- +struct _gckVGCOMMAND
- +{
- + /***************************************************************************
- + ** Object data and pointers.
- + */
- +
- + gcsOBJECT object;
- + gckVGKERNEL kernel;
- + gckOS os;
- + gckVGHARDWARE hardware;
- +
- + /* Features. */
- + gctBOOL fe20;
- + gctBOOL vg20;
- + gctBOOL vg21;
- +
- +
- + /***************************************************************************
- + ** Enable command queue dumping.
- + */
- +
- + gctBOOL enableDumping;
- +
- +
- + /***************************************************************************
- + ** Bus Error interrupt.
- + */
- +
- + gctINT32 busErrorInt;
- +
- +
- + /***************************************************************************
- + ** Command buffer information.
- + */
- +
- + gcsCOMMAND_BUFFER_INFO info;
- +
- +
- + /***************************************************************************
- + ** Synchronization objects.
- + */
- +
- + gctPOINTER queueMutex;
- + gctPOINTER taskMutex;
- + gctPOINTER commitMutex;
- +
- +
- + /***************************************************************************
- + ** Task management.
- + */
- +
- + /* The head of the storage buffer linked list. */
- + gcsTASK_STORAGE_PTR taskStorage;
- +
- + /* Allocation size. */
- + gctUINT taskStorageGranularity;
- + gctUINT taskStorageUsable;
- +
- + /* The free container list. */
- + gcsTASK_CONTAINER_PTR taskFreeHead;
- + gcsTASK_CONTAINER_PTR taskFreeTail;
- +
- + /* Task table */
- + gcsBLOCK_TASK_ENTRY taskTable[gcvBLOCK_COUNT];
- +
- +
- + /***************************************************************************
- + ** Command queue.
- + */
- +
- + /* Pointer to the allocated queue memory. */
- + gcsKERNEL_QUEUE_HEADER_PTR queue;
- +
- + /* Pointer to the current available queue from which new queue entries
- + will be allocated. */
- + gcsKERNEL_QUEUE_HEADER_PTR queueHead;
- +
- + /* If different from queueHead, points to the command queue which is
- + currently being executed by the hardware. */
- + gcsKERNEL_QUEUE_HEADER_PTR queueTail;
- +
- + /* Points to the queue to merge the tail with when the tail is processed. */
- + gcsKERNEL_QUEUE_HEADER_PTR mergeQueue;
- +
- + /* Queue overflow counter. */
- + gctUINT queueOverflow;
- +
- +
- + /***************************************************************************
- + ** Context.
- + */
- +
- + /* Context counter used for unique ID. */
- + gctUINT64 contextCounter;
- +
- + /* Current context ID. */
- + gctUINT64 currentContext;
- +
- + /* Command queue power semaphore. */
- + gctPOINTER powerSemaphore;
- + gctINT32 powerStallInt;
- + gcsCMDBUFFER_PTR powerStallBuffer;
- + gctSIGNAL powerStallSignal;
- +
- +};
- +
- +/******************************************************************************\
- +************************ gckVGCOMMAND Object Internal API. ***********************
- +\******************************************************************************/
- +
- +/* Initialize architecture dependent command buffer information. */
- +gceSTATUS
- +gckVGCOMMAND_InitializeInfo(
- + IN gckVGCOMMAND Command
- + );
- +
- +/* Form a STATE command at the specified location in the command buffer. */
- +gceSTATUS
- +gckVGCOMMAND_StateCommand(
- + IN gckVGCOMMAND Command,
- + IN gctUINT32 Pipe,
- + IN gctPOINTER Logical,
- + IN gctUINT32 Address,
- + IN gctSIZE_T Count,
- + IN OUT gctSIZE_T * Bytes
- + );
- +
- +/* Form a RESTART command at the specified location in the command buffer. */
- +gceSTATUS
- +gckVGCOMMAND_RestartCommand(
- + IN gckVGCOMMAND Command,
- + IN gctPOINTER Logical,
- + IN gctUINT32 FetchAddress,
- + IN gctUINT FetchCount,
- + IN OUT gctSIZE_T * Bytes
- + );
- +
- +/* Form a FETCH command at the specified location in the command buffer. */
- +gceSTATUS
- +gckVGCOMMAND_FetchCommand(
- + IN gckVGCOMMAND Command,
- + IN gctPOINTER Logical,
- + IN gctUINT32 FetchAddress,
- + IN gctUINT FetchCount,
- + IN OUT gctSIZE_T * Bytes
- + );
- +
- +/* Form a CALL command at the specified location in the command buffer. */
- +gceSTATUS
- +gckVGCOMMAND_CallCommand(
- + IN gckVGCOMMAND Command,
- + IN gctPOINTER Logical,
- + IN gctUINT32 FetchAddress,
- + IN gctUINT FetchCount,
- + IN OUT gctSIZE_T * Bytes
- + );
- +
- +/* Form a RETURN command at the specified location in the command buffer. */
- +gceSTATUS
- +gckVGCOMMAND_ReturnCommand(
- + IN gckVGCOMMAND Command,
- + IN gctPOINTER Logical,
- + IN OUT gctSIZE_T * Bytes
- + );
- +
- +/* Form an EVENT command at the specified location in the command buffer. */
- +gceSTATUS
- +gckVGCOMMAND_EventCommand(
- + IN gckVGCOMMAND Command,
- + IN gctPOINTER Logical,
- + IN gceBLOCK Block,
- + IN gctINT32 InterruptId,
- + IN OUT gctSIZE_T * Bytes
- + );
- +
- +/* Form an END command at the specified location in the command buffer. */
- +gceSTATUS
- +gckVGCOMMAND_EndCommand(
- + IN gckVGCOMMAND Command,
- + IN gctPOINTER Logical,
- + IN gctINT32 InterruptId,
- + IN OUT gctSIZE_T * Bytes
- + );
- +
- +#endif /* __gc_hal_kernel_hardware_command_h_ */
- +
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c linux-3.14.35/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c 2015-03-08 14:27:37.617684501 -0500
- @@ -0,0 +1,2114 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal.h"
- +#include "gc_hal_kernel.h"
- +#include "gc_hal_kernel_hardware_command_vg.h"
- +
- +#if gcdENABLE_VG
- +
- +#define _GC_OBJ_ZONE gcvZONE_HARDWARE
- +
- +typedef enum
- +{
- + gcvPOWER_FLAG_INITIALIZE = 1 << 0,
- + gcvPOWER_FLAG_STALL = 1 << 1,
- + gcvPOWER_FLAG_STOP = 1 << 2,
- + gcvPOWER_FLAG_START = 1 << 3,
- + gcvPOWER_FLAG_RELEASE = 1 << 4,
- + gcvPOWER_FLAG_DELAY = 1 << 5,
- + gcvPOWER_FLAG_SAVE = 1 << 6,
- + gcvPOWER_FLAG_ACQUIRE = 1 << 7,
- + gcvPOWER_FLAG_POWER_OFF = 1 << 8,
- + gcvPOWER_FLAG_CLOCK_OFF = 1 << 9,
- + gcvPOWER_FLAG_CLOCK_ON = 1 << 10,
- + gcvPOWER_FLAG_NOP = 1 << 11,
- +}
- +gcePOWER_FLAGS;
- +
- +/******************************************************************************\
- +********************************* Support Code *********************************
- +\******************************************************************************/
- +static gceSTATUS
- +_ResetGPU(
- + IN gckOS Os
- + )
- +{
- + gctUINT32 control, idle;
- + gceSTATUS status;
- +
- + /* Read register. */
- + gcmkONERROR(gckOS_ReadRegisterEx(Os,
- + gcvCORE_VG,
- + 0x00000,
- + &control));
- +
- + for (;;)
- + {
- + /* Disable clock gating. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Os,
- + gcvCORE_VG,
- + 0x00104,
- + 0x00000000));
- +
- + /* Wait for clock being stable. */
- + gcmkONERROR(gckOS_Delay(Os, 1));
- +
- + /* Isolate the GPU. */
- + control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Os,
- + gcvCORE_VG,
- + 0x00000,
- + control));
- +
- + /* Set soft reset. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Os,
- + gcvCORE_VG,
- + 0x00000,
- + ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))));
- +
- + /* Wait for reset. */
- + gcmkONERROR(gckOS_Delay(Os, 1));
- +
- + /* Reset soft reset bit. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Os,
- + gcvCORE_VG,
- + 0x00000,
- + ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))));
- +
- + /* Reset GPU isolation. */
- + control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Os,
- + gcvCORE_VG,
- + 0x00000,
- + control));
- +
- + /* Read idle register. */
- + gcmkONERROR(gckOS_ReadRegisterEx(Os,
- + gcvCORE_VG,
- + 0x00004,
- + &idle));
- +
- + if ((((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ) == 0)
- + {
- + continue;
- + }
- +
- + /* Read reset register. */
- + gcmkONERROR(gckOS_ReadRegisterEx(Os,
- + gcvCORE_VG,
- + 0x00000,
- + &control));
- +
- + if (((((((gctUINT32) (control)) >> (0 ? 16:16)) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) ) == 0)
- + || ((((((gctUINT32) (control)) >> (0 ? 17:17)) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1)))))) ) == 0)
- + )
- + {
- + continue;
- + }
- +
- + /* GPU is idle. */
- + break;
- + }
- +
- + /* Success. */
- + return gcvSTATUS_OK;
- +
- +OnError:
- +
- + /* Return the error. */
- + return status;
- +}
- +
- +
- +static gceSTATUS
- +_IdentifyHardware(
- + IN gckOS Os,
- + OUT gceCHIPMODEL * ChipModel,
- + OUT gctUINT32 * ChipRevision,
- + OUT gctUINT32 * ChipFeatures,
- + OUT gctUINT32 * ChipMinorFeatures,
- + OUT gctUINT32 * ChipMinorFeatures2
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 chipIdentity;
- +
- + do
- + {
- + /* Read chip identity register. */
- + gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG, 0x00018, &chipIdentity));
- +
- + /* Special case for older graphic cores. */
- + if (((((gctUINT32) (chipIdentity)) >> (0 ? 31:24) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))))
- + {
- + *ChipModel = gcv500;
- + *ChipRevision = (((((gctUINT32) (chipIdentity)) >> (0 ? 15:12)) & ((gctUINT32) ((((1 ? 15:12) - (0 ? 15:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:12) - (0 ? 15:12) + 1)))))) );
- + }
- +
- + else
- + {
- + /* Read chip identity register. */
- + gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG,
- + 0x00020,
- + (gctUINT32 *) ChipModel));
- +
- + /* Read CHIP_REV register. */
- + gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG,
- + 0x00024,
- + ChipRevision));
- + }
- +
- + /* Read chip feature register. */
- + gcmkERR_BREAK(gckOS_ReadRegisterEx(
- + Os, gcvCORE_VG, 0x0001C, ChipFeatures
- + ));
- +
- + /* Read chip minor feature register. */
- + gcmkERR_BREAK(gckOS_ReadRegisterEx(
- + Os, gcvCORE_VG, 0x00034, ChipMinorFeatures
- + ));
- +
- + /* Read chip minor feature register #2. */
- + gcmkERR_BREAK(gckOS_ReadRegisterEx(
- + Os, gcvCORE_VG, 0x00074, ChipMinorFeatures2
- + ));
- +
- + gcmkTRACE(
- + gcvLEVEL_VERBOSE,
- + "ChipModel=0x%08X\n"
- + "ChipRevision=0x%08X\n"
- + "ChipFeatures=0x%08X\n"
- + "ChipMinorFeatures=0x%08X\n"
- + "ChipMinorFeatures2=0x%08X\n",
- + *ChipModel,
- + *ChipRevision,
- + *ChipFeatures,
- + *ChipMinorFeatures,
- + *ChipMinorFeatures2
- + );
- +
- + /* Success. */
- + return gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + /* Return the status. */
- + return status;
- +}
- +
- +#if gcdPOWEROFF_TIMEOUT
- +void
- +_VGPowerTimerFunction(
- + gctPOINTER Data
- + )
- +{
- + gckVGHARDWARE hardware = (gckVGHARDWARE)Data;
- + gcmkVERIFY_OK(
- + gckVGHARDWARE_SetPowerManagementState(hardware, gcvPOWER_OFF_TIMEOUT));
- +}
- +#endif
- +
- +/******************************************************************************\
- +****************************** gckVGHARDWARE API code *****************************
- +\******************************************************************************/
- +
- +/*******************************************************************************
- +**
- +** gckVGHARDWARE_Construct
- +**
- +** Construct a new gckVGHARDWARE object.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an initialized gckOS object.
- +**
- +** OUTPUT:
- +**
- +** gckVGHARDWARE * Hardware
- +** Pointer to a variable that will hold the pointer to the gckVGHARDWARE
- +** object.
- +*/
- +gceSTATUS
- +gckVGHARDWARE_Construct(
- + IN gckOS Os,
- + OUT gckVGHARDWARE * Hardware
- + )
- +{
- + gckVGHARDWARE hardware = gcvNULL;
- + gceSTATUS status;
- + gceCHIPMODEL chipModel;
- + gctUINT32 chipRevision;
- + gctUINT32 chipFeatures;
- + gctUINT32 chipMinorFeatures;
- + gctUINT32 chipMinorFeatures2;
- +
- + gcmkHEADER_ARG("Os=0x%x Hardware=0x%x ", Os, Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
- +
- + do
- + {
- + gcmkERR_BREAK(gckOS_SetGPUPower(Os, gcvCORE_VG, gcvTRUE, gcvTRUE));
- +
- + status = _ResetGPU(Os);
- +
- + if (status != gcvSTATUS_OK)
- + {
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "_ResetGPU failed: status=%d\n", status);
- + }
- +
- + /* Identify the hardware. */
- + gcmkERR_BREAK(_IdentifyHardware(Os,
- + &chipModel, &chipRevision,
- + &chipFeatures, &chipMinorFeatures, &chipMinorFeatures2
- + ));
- +
- + /* Allocate the gckVGHARDWARE object. */
- + gcmkERR_BREAK(gckOS_Allocate(Os,
- + gcmSIZEOF(struct _gckVGHARDWARE), (gctPOINTER *) &hardware
- + ));
- +
- + /* Initialize the gckVGHARDWARE object. */
- + hardware->object.type = gcvOBJ_HARDWARE;
- + hardware->os = Os;
- +
- + /* Set chip identity. */
- + hardware->chipModel = chipModel;
- + hardware->chipRevision = chipRevision;
- + hardware->chipFeatures = chipFeatures;
- + hardware->chipMinorFeatures = chipMinorFeatures;
- + hardware->chipMinorFeatures2 = chipMinorFeatures2;
- +
- + hardware->powerMutex = gcvNULL;
- + hardware->chipPowerState = gcvPOWER_ON;
- + hardware->chipPowerStateGlobal = gcvPOWER_ON;
- + hardware->clockState = gcvTRUE;
- + hardware->powerState = gcvTRUE;
- +
- +#if gcdPOWEROFF_TIMEOUT
- + hardware->powerOffTime = 0;
- + hardware->powerOffTimeout = gcdPOWEROFF_TIMEOUT;
- +
- + gcmkVERIFY_OK(gckOS_CreateTimer(Os,
- + _VGPowerTimerFunction,
- + (gctPOINTER)hardware,
- + &hardware->powerOffTimer));
- +#endif
- +
- + /* Determine whether FE 2.0 is present. */
- + hardware->fe20 = ((((gctUINT32) (hardware->chipFeatures)) >> (0 ? 28:28) & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 28:28) - (0 ? 28:28) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 28:28) - (0 ? 28:28) + 1)))))));
- +
- + /* Determine whether VG 2.0 is present. */
- + hardware->vg20 = ((((gctUINT32) (hardware->chipMinorFeatures)) >> (0 ? 13:13) & ((gctUINT32) ((((1 ? 13:13) - (0 ? 13:13) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:13) - (0 ? 13:13) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 13:13) - (0 ? 13:13) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:13) - (0 ? 13:13) + 1)))))));
- +
- + /* Determine whether VG 2.1 is present. */
- + hardware->vg21 = ((((gctUINT32) (hardware->chipMinorFeatures)) >> (0 ? 18:18) & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1)))))));
- +
- + /* Set default event mask. */
- + hardware->eventMask = 0xFFFFFFFF;
- +
- + gcmkERR_BREAK(gckOS_AtomConstruct(Os, &hardware->pageTableDirty));
- +
- + /* Set fast clear to auto. */
- + gcmkVERIFY_OK(gckVGHARDWARE_SetFastClear(hardware, -1));
- +
- + gcmkERR_BREAK(gckOS_CreateMutex(Os, &hardware->powerMutex));
- +
- + /* Enable power management by default. */
- + hardware->powerManagement = gcvTRUE;
- +
- + /* Return pointer to the gckVGHARDWARE object. */
- + *Hardware = hardware;
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- +#if gcdPOWEROFF_TIMEOUT
- + if (hardware->powerOffTimer != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_StopTimer(Os, hardware->powerOffTimer));
- + gcmkVERIFY_OK(gckOS_DestroyTimer(Os, hardware->powerOffTimer));
- + }
- +#endif
- +
- + if (hardware->pageTableDirty != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_AtomDestroy(Os, hardware->pageTableDirty));
- + }
- +
- + if (hardware != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_Free(Os, hardware));
- + }
- +
- + gcmkVERIFY_OK(gckOS_SetGPUPower(Os, gcvCORE_VG, gcvFALSE, gcvFALSE));
- +
- + gcmkFOOTER();
- + /* Return the status. */
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGHARDWARE_Destroy
- +**
- +** Destroy an gckVGHARDWARE object.
- +**
- +** INPUT:
- +**
- +** gckVGHARDWARE Hardware
- +** Pointer to the gckVGHARDWARE object that needs to be destroyed.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckVGHARDWARE_Destroy(
- + IN gckVGHARDWARE Hardware
- + )
- +{
- + gceSTATUS status;
- + gcmkHEADER_ARG("Hardware=0x%x ", Hardware);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + /* Mark the object as unknown. */
- + Hardware->object.type = gcvOBJ_UNKNOWN;
- +
- + if (Hardware->powerMutex != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_DeleteMutex(
- + Hardware->os, Hardware->powerMutex));
- + }
- +
- +#if gcdPOWEROFF_TIMEOUT
- + gcmkVERIFY_OK(gckOS_StopTimer(Hardware->os, Hardware->powerOffTimer));
- + gcmkVERIFY_OK(gckOS_DestroyTimer(Hardware->os, Hardware->powerOffTimer));
- +#endif
- +
- + if (Hardware->pageTableDirty != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_AtomDestroy(Hardware->os, Hardware->pageTableDirty));
- + }
- +
- + /* Free the object. */
- + status = gckOS_Free(Hardware->os, Hardware);
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGHARDWARE_QueryMemory
- +**
- +** Query the amount of memory available on the hardware.
- +**
- +** INPUT:
- +**
- +** gckVGHARDWARE Hardware
- +** Pointer to the gckVGHARDWARE object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * InternalSize
- +** Pointer to a variable that will hold the size of the internal video
- +** memory in bytes. If 'InternalSize' is gcvNULL, no information of the
- +** internal memory will be returned.
- +**
- +** gctUINT32 * InternalBaseAddress
- +** Pointer to a variable that will hold the hardware's base address for
- +** the internal video memory. This pointer cannot be gcvNULL if
- +** 'InternalSize' is also non-gcvNULL.
- +**
- +** gctUINT32 * InternalAlignment
- +** Pointer to a variable that will hold the hardware's base address for
- +** the internal video memory. This pointer cannot be gcvNULL if
- +** 'InternalSize' is also non-gcvNULL.
- +**
- +** gctSIZE_T * ExternalSize
- +** Pointer to a variable that will hold the size of the external video
- +** memory in bytes. If 'ExternalSize' is gcvNULL, no information of the
- +** external memory will be returned.
- +**
- +** gctUINT32 * ExternalBaseAddress
- +** Pointer to a variable that will hold the hardware's base address for
- +** the external video memory. This pointer cannot be gcvNULL if
- +** 'ExternalSize' is also non-gcvNULL.
- +**
- +** gctUINT32 * ExternalAlignment
- +** Pointer to a variable that will hold the hardware's base address for
- +** the external video memory. This pointer cannot be gcvNULL if
- +** 'ExternalSize' is also non-gcvNULL.
- +**
- +** gctUINT32 * HorizontalTileSize
- +** Number of horizontal pixels per tile. If 'HorizontalTileSize' is
- +** gcvNULL, no horizontal pixel per tile will be returned.
- +**
- +** gctUINT32 * VerticalTileSize
- +** Number of vertical pixels per tile. If 'VerticalTileSize' is
- +** gcvNULL, no vertical pixel per tile will be returned.
- +*/
- +gceSTATUS
- +gckVGHARDWARE_QueryMemory(
- + IN gckVGHARDWARE Hardware,
- + OUT gctSIZE_T * InternalSize,
- + OUT gctUINT32 * InternalBaseAddress,
- + OUT gctUINT32 * InternalAlignment,
- + OUT gctSIZE_T * ExternalSize,
- + OUT gctUINT32 * ExternalBaseAddress,
- + OUT gctUINT32 * ExternalAlignment,
- + OUT gctUINT32 * HorizontalTileSize,
- + OUT gctUINT32 * VerticalTileSize
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x InternalSize=0x%x InternalBaseAddress=0x%x InternalAlignment=0x%x"
- + "ExternalSize=0x%x ExternalBaseAddress=0x%x ExternalAlignment=0x%x HorizontalTileSize=0x%x VerticalTileSize=0x%x",
- + Hardware, InternalSize, InternalBaseAddress, InternalAlignment,
- + ExternalSize, ExternalBaseAddress, ExternalAlignment, HorizontalTileSize, VerticalTileSize);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + if (InternalSize != gcvNULL)
- + {
- + /* No internal memory. */
- + *InternalSize = 0;
- + }
- +
- + if (ExternalSize != gcvNULL)
- + {
- + /* No external memory. */
- + *ExternalSize = 0;
- + }
- +
- + if (HorizontalTileSize != gcvNULL)
- + {
- + /* 4x4 tiles. */
- + *HorizontalTileSize = 4;
- + }
- +
- + if (VerticalTileSize != gcvNULL)
- + {
- + /* 4x4 tiles. */
- + *VerticalTileSize = 4;
- + }
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGHARDWARE_QueryChipIdentity
- +**
- +** Query the identity of the hardware.
- +**
- +** INPUT:
- +**
- +** gckVGHARDWARE Hardware
- +** Pointer to the gckVGHARDWARE object.
- +**
- +** OUTPUT:
- +**
- +** gceCHIPMODEL * ChipModel
- +** If 'ChipModel' is not gcvNULL, the variable it points to will
- +** receive the model of the chip.
- +**
- +** gctUINT32 * ChipRevision
- +** If 'ChipRevision' is not gcvNULL, the variable it points to will
- +** receive the revision of the chip.
- +**
- +** gctUINT32 * ChipFeatures
- +** If 'ChipFeatures' is not gcvNULL, the variable it points to will
- +** receive the feature set of the chip.
- +**
- +** gctUINT32 * ChipMinorFeatures
- +** If 'ChipMinorFeatures' is not gcvNULL, the variable it points to
- +** will receive the minor feature set of the chip.
- +**
- +** gctUINT32 * ChipMinorFeatures2
- +** If 'ChipMinorFeatures2' is not gcvNULL, the variable it points to
- +** will receive the minor feature set of the chip.
- +**
- +*/
- +gceSTATUS
- +gckVGHARDWARE_QueryChipIdentity(
- + IN gckVGHARDWARE Hardware,
- + OUT gceCHIPMODEL * ChipModel,
- + OUT gctUINT32 * ChipRevision,
- + OUT gctUINT32* ChipFeatures,
- + OUT gctUINT32* ChipMinorFeatures,
- + OUT gctUINT32* ChipMinorFeatures2
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x ChipModel=0x%x ChipRevision=0x%x ChipFeatures = 0x%x ChipMinorFeatures = 0x%x ChipMinorFeatures2 = 0x%x",
- + Hardware, ChipModel, ChipRevision, ChipFeatures, ChipMinorFeatures, ChipMinorFeatures2);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + /* Return chip model. */
- + if (ChipModel != gcvNULL)
- + {
- + *ChipModel = Hardware->chipModel;
- + }
- +
- + /* Return revision number. */
- + if (ChipRevision != gcvNULL)
- + {
- + *ChipRevision = Hardware->chipRevision;
- + }
- +
- + /* Return feature set. */
- + if (ChipFeatures != gcvNULL)
- + {
- + gctUINT32 features = Hardware->chipFeatures;
- +
- + if ((((((gctUINT32) (features)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
- + {
- + features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (Hardware->allowFastClear) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
- + }
- +
- + /* Mark 2D pipe as available for GC500.0 since it did not have this *\
- + \* bit. */
- + if ((Hardware->chipModel == gcv500)
- + && (Hardware->chipRevision == 0)
- + )
- + {
- + features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
- + }
- +
- + /* Mark 2D pipe as available for GC300 since it did not have this *\
- + \* bit. */
- + if (Hardware->chipModel == gcv300)
- + {
- + features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
- + }
- +
- + *ChipFeatures = features;
- + }
- +
- + /* Return minor feature set. */
- + if (ChipMinorFeatures != gcvNULL)
- + {
- + *ChipMinorFeatures = Hardware->chipMinorFeatures;
- + }
- +
- + /* Return minor feature set #2. */
- + if (ChipMinorFeatures2 != gcvNULL)
- + {
- + *ChipMinorFeatures2 = Hardware->chipMinorFeatures2;
- + }
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGHARDWARE_ConvertFormat
- +**
- +** Convert an API format to hardware parameters.
- +**
- +** INPUT:
- +**
- +** gckVGHARDWARE Hardware
- +** Pointer to the gckVGHARDWARE object.
- +**
- +** gceSURF_FORMAT Format
- +** API format to convert.
- +**
- +** OUTPUT:
- +**
- +** gctUINT32 * BitsPerPixel
- +** Pointer to a variable that will hold the number of bits per pixel.
- +**
- +** gctUINT32 * BytesPerTile
- +** Pointer to a variable that will hold the number of bytes per tile.
- +*/
- +gceSTATUS
- +gckVGHARDWARE_ConvertFormat(
- + IN gckVGHARDWARE Hardware,
- + IN gceSURF_FORMAT Format,
- + OUT gctUINT32 * BitsPerPixel,
- + OUT gctUINT32 * BytesPerTile
- + )
- +{
- + gctUINT32 bitsPerPixel;
- + gctUINT32 bytesPerTile;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Format=0x%x BitsPerPixel=0x%x BytesPerTile = 0x%x",
- + Hardware, Format, BitsPerPixel, BytesPerTile);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + /* Dispatch on format. */
- + switch (Format)
- + {
- + case gcvSURF_A1:
- + case gcvSURF_L1:
- + /* 1-bpp format. */
- + bitsPerPixel = 1;
- + bytesPerTile = (1 * 4 * 4) / 8;
- + break;
- +
- + case gcvSURF_A4:
- + /* 4-bpp format. */
- + bitsPerPixel = 4;
- + bytesPerTile = (4 * 4 * 4) / 8;
- + break;
- +
- + case gcvSURF_INDEX8:
- + case gcvSURF_A8:
- + case gcvSURF_L8:
- + /* 8-bpp format. */
- + bitsPerPixel = 8;
- + bytesPerTile = (8 * 4 * 4) / 8;
- + break;
- +
- + case gcvSURF_YV12:
- + /* 12-bpp planar YUV formats. */
- + bitsPerPixel = 12;
- + bytesPerTile = (12 * 4 * 4) / 8;
- + break;
- +
- + case gcvSURF_NV12:
- + /* 12-bpp planar YUV formats. */
- + bitsPerPixel = 12;
- + bytesPerTile = (12 * 4 * 4) / 8;
- + break;
- +
- + /* 4444 variations. */
- + case gcvSURF_X4R4G4B4:
- + case gcvSURF_A4R4G4B4:
- + case gcvSURF_R4G4B4X4:
- + case gcvSURF_R4G4B4A4:
- + case gcvSURF_B4G4R4X4:
- + case gcvSURF_B4G4R4A4:
- + case gcvSURF_X4B4G4R4:
- + case gcvSURF_A4B4G4R4:
- +
- + /* 1555 variations. */
- + case gcvSURF_X1R5G5B5:
- + case gcvSURF_A1R5G5B5:
- + case gcvSURF_R5G5B5X1:
- + case gcvSURF_R5G5B5A1:
- + case gcvSURF_X1B5G5R5:
- + case gcvSURF_A1B5G5R5:
- + case gcvSURF_B5G5R5X1:
- + case gcvSURF_B5G5R5A1:
- +
- + /* 565 variations. */
- + case gcvSURF_R5G6B5:
- + case gcvSURF_B5G6R5:
- +
- + case gcvSURF_A8L8:
- + case gcvSURF_YUY2:
- + case gcvSURF_UYVY:
- + case gcvSURF_D16:
- + /* 16-bpp format. */
- + bitsPerPixel = 16;
- + bytesPerTile = (16 * 4 * 4) / 8;
- + break;
- +
- + case gcvSURF_X8R8G8B8:
- + case gcvSURF_A8R8G8B8:
- + case gcvSURF_X8B8G8R8:
- + case gcvSURF_A8B8G8R8:
- + case gcvSURF_R8G8B8X8:
- + case gcvSURF_R8G8B8A8:
- + case gcvSURF_B8G8R8X8:
- + case gcvSURF_B8G8R8A8:
- + case gcvSURF_D32:
- + /* 32-bpp format. */
- + bitsPerPixel = 32;
- + bytesPerTile = (32 * 4 * 4) / 8;
- + break;
- +
- + case gcvSURF_D24S8:
- + /* 24-bpp format. */
- + bitsPerPixel = 32;
- + bytesPerTile = (32 * 4 * 4) / 8;
- + break;
- +
- + case gcvSURF_DXT1:
- + case gcvSURF_ETC1:
- + bitsPerPixel = 4;
- + bytesPerTile = (4 * 4 * 4) / 8;
- + break;
- +
- + case gcvSURF_DXT2:
- + case gcvSURF_DXT3:
- + case gcvSURF_DXT4:
- + case gcvSURF_DXT5:
- + bitsPerPixel = 8;
- + bytesPerTile = (8 * 4 * 4) / 8;
- + break;
- +
- + default:
- + /* Invalid format. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_INVALID_ARGUMENT;
- + }
- +
- + /* Set the result. */
- + if (BitsPerPixel != gcvNULL)
- + {
- + * BitsPerPixel = bitsPerPixel;
- + }
- +
- + if (BytesPerTile != gcvNULL)
- + {
- + * BytesPerTile = bytesPerTile;
- + }
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGHARDWARE_SplitMemory
- +**
- +** Split a hardware specific memory address into a pool and offset.
- +**
- +** INPUT:
- +**
- +** gckVGHARDWARE Hardware
- +** Pointer to the gckVGHARDWARE object.
- +**
- +** gctUINT32 Address
- +** Address in hardware specific format.
- +**
- +** OUTPUT:
- +**
- +** gcePOOL * Pool
- +** Pointer to a variable that will hold the pool type for the address.
- +**
- +** gctUINT32 * Offset
- +** Pointer to a variable that will hold the offset for the address.
- +*/
- +gceSTATUS
- +gckVGHARDWARE_SplitMemory(
- + IN gckVGHARDWARE Hardware,
- + IN gctUINT32 Address,
- + OUT gcePOOL * Pool,
- + OUT gctUINT32 * Offset
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x Address=0x%x Pool=0x%x Offset = 0x%x",
- + Hardware, Address, Pool, Offset);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Offset != gcvNULL);
- +
- + /* Dispatch on memory type. */
- + switch ((((((gctUINT32) (Address)) >> (0 ? 1:0)) & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1)))))) ))
- + {
- + case 0x0:
- + /* System memory. */
- + *Pool = gcvPOOL_SYSTEM;
- + break;
- +
- + case 0x2:
- + /* Virtual memory. */
- + *Pool = gcvPOOL_VIRTUAL;
- + break;
- +
- + default:
- + /* Invalid memory type. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_INVALID_ARGUMENT;
- + }
- +
- + /* Return offset of address. */
- + *Offset = ((((gctUINT32) (Address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGHARDWARE_Execute
- +**
- +** Kickstart the hardware's command processor with an initialized command
- +** buffer.
- +**
- +** INPUT:
- +**
- +** gckVGHARDWARE Hardware
- +** Pointer to the gckVGHARDWARE object.
- +**
- +** gctUINT32 Address
- +** Address of the command buffer.
- +**
- +** gctSIZE_T Count
- +** Number of command-sized data units to be executed.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckVGHARDWARE_Execute(
- + IN gckVGHARDWARE Hardware,
- + IN gctUINT32 Address,
- + IN gctSIZE_T Count
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Address=0x%x Count=0x%x",
- + Hardware, Address, Count);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + do
- + {
- + /* Enable all events. */
- + gcmkERR_BREAK(gckOS_WriteRegisterEx(
- + Hardware->os,
- + gcvCORE_VG,
- + 0x00014,
- + Hardware->eventMask
- + ));
- +
- + if (Hardware->fe20)
- + {
- + /* Write address register. */
- + gcmkERR_BREAK(gckOS_WriteRegisterEx(
- + Hardware->os,
- + gcvCORE_VG,
- + 0x00500,
- + gcmkFIXADDRESS(Address)
- + ));
- +
- + /* Write control register. */
- + gcmkERR_BREAK(gckOS_WriteRegisterEx(
- + Hardware->os,
- + gcvCORE_VG,
- + 0x00504,
- + Count
- + ));
- + }
- + else
- + {
- + /* Write address register. */
- + gcmkERR_BREAK(gckOS_WriteRegisterEx(
- + Hardware->os,
- + gcvCORE_VG,
- + 0x00654,
- + gcmkFIXADDRESS(Address)
- + ));
- +
- + /* Write control register. */
- + gcmkERR_BREAK(gckOS_WriteRegisterEx(
- + Hardware->os,
- + gcvCORE_VG,
- + 0x00658,
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) |
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + ));
- + }
- +
- + /* Success. */
- + gcmkFOOTER();
- + return gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- +
- + gcmkFOOTER();
- + /* Return the status. */
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGHARDWARE_AlignToTile
- +**
- +** Align the specified width and height to tile boundaries.
- +**
- +** INPUT:
- +**
- +** gckVGHARDWARE Hardware
- +** Pointer to an gckVGHARDWARE object.
- +**
- +** gceSURF_TYPE Type
- +** Type of alignment.
- +**
- +** gctUINT32 * Width
- +** Pointer to the width to be aligned. If 'Width' is gcvNULL, no width
- +** will be aligned.
- +**
- +** gctUINT32 * Height
- +** Pointer to the height to be aligned. If 'Height' is gcvNULL, no height
- +** will be aligned.
- +**
- +** OUTPUT:
- +**
- +** gctUINT32 * Width
- +** Pointer to a variable that will receive the aligned width.
- +**
- +** gctUINT32 * Height
- +** Pointer to a variable that will receive the aligned height.
- +*/
- +gceSTATUS
- +gckVGHARDWARE_AlignToTile(
- + IN gckVGHARDWARE Hardware,
- + IN gceSURF_TYPE Type,
- + IN OUT gctUINT32 * Width,
- + IN OUT gctUINT32 * Height
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x Type=0x%x Width=0x%x Height=0x%x",
- + Hardware, Type, Width, Height);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + if (Width != gcvNULL)
- + {
- + /* Align the width. */
- + *Width = gcmALIGN(*Width, (Type == gcvSURF_TEXTURE) ? 4 : 16);
- + }
- +
- + if (Height != gcvNULL)
- + {
- + /* Special case for VG images. */
- + if ((*Height == 0) && (Type == gcvSURF_IMAGE))
- + {
- + *Height = 4;
- + }
- + else
- + {
- + /* Align the height. */
- + *Height = gcmALIGN(*Height, 4);
- + }
- + }
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGHARDWARE_ConvertLogical
- +**
- +** Convert a logical system address into a hardware specific address.
- +**
- +** INPUT:
- +**
- +** gckVGHARDWARE Hardware
- +** Pointer to an gckVGHARDWARE object.
- +**
- +** gctPOINTER Logical
- +** Logical address to convert.
- +**
- +** gctUINT32* Address
- +** Return hardware specific address.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckVGHARDWARE_ConvertLogical(
- + IN gckVGHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + OUT gctUINT32 * Address
- + )
- +{
- + gctUINT32 address;
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Address=0x%x",
- + Hardware, Logical, Address);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Address != gcvNULL);
- +
- + do
- + {
- + /* Convert logical address into a physical address. */
- + gcmkERR_BREAK(gckOS_GetPhysicalAddress(
- + Hardware->os, Logical, &address
- + ));
- +
- + /* Return hardware specific address. */
- + *Address = ((((gctUINT32) (address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
- +
- + /* Success. */
- + gcmkFOOTER();
- + return gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + gcmkFOOTER();
- + /* Return the status. */
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGHARDWARE_QuerySystemMemory
- +**
- +** Query the command buffer alignment and number of reserved bytes.
- +**
- +** INPUT:
- +**
- +** gckVGHARDWARE Harwdare
- +** Pointer to an gckVGHARDWARE object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * SystemSize
- +** Pointer to a variable that receives the maximum size of the system
- +** memory.
- +**
- +** gctUINT32 * SystemBaseAddress
- +** Poinetr to a variable that receives the base address for system
- +** memory.
- +*/
- +gceSTATUS gckVGHARDWARE_QuerySystemMemory(
- + IN gckVGHARDWARE Hardware,
- + OUT gctSIZE_T * SystemSize,
- + OUT gctUINT32 * SystemBaseAddress
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x SystemSize=0x%x SystemBaseAddress=0x%x",
- + Hardware, SystemSize, SystemBaseAddress);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + if (SystemSize != gcvNULL)
- + {
- + /* Maximum system memory can be 2GB. */
- + *SystemSize = (gctSIZE_T)(1 << 31);
- + }
- +
- + if (SystemBaseAddress != gcvNULL)
- + {
- + /* Set system memory base address. */
- + *SystemBaseAddress = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
- + }
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGHARDWARE_SetMMU
- +**
- +** Set the page table base address.
- +**
- +** INPUT:
- +**
- +** gckVGHARDWARE Harwdare
- +** Pointer to an gckVGHARDWARE object.
- +**
- +** gctPOINTER Logical
- +** Logical address of the page table.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS gckVGHARDWARE_SetMMU(
- + IN gckVGHARDWARE Hardware,
- + IN gctPOINTER Logical
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 address = 0;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x",
- + Hardware, Logical);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- +
- + do
- + {
- + /* Convert the logical address into an hardware address. */
- + gcmkERR_BREAK(gckVGHARDWARE_ConvertLogical(Hardware, Logical, &address) );
- +
- + /* Write the AQMemoryFePageTable register. */
- + gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
- + 0x00400,
- + gcmkFIXADDRESS(address)) );
- +
- + /* Write the AQMemoryTxPageTable register. */
- + gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
- + 0x00404,
- + gcmkFIXADDRESS(address)) );
- +
- + /* Write the AQMemoryPePageTable register. */
- + gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
- + 0x00408,
- + gcmkFIXADDRESS(address)) );
- +
- + /* Write the AQMemoryPezPageTable register. */
- + gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
- + 0x0040C,
- + gcmkFIXADDRESS(address)) );
- +
- + /* Write the AQMemoryRaPageTable register. */
- + gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
- + 0x00410,
- + gcmkFIXADDRESS(address)) );
- + }
- + while (gcvFALSE);
- +
- + gcmkFOOTER();
- + /* Return the status. */
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGHARDWARE_FlushMMU
- +**
- +** Flush the page table.
- +**
- +** INPUT:
- +**
- +** gckVGHARDWARE Harwdare
- +** Pointer to an gckVGHARDWARE object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS gckVGHARDWARE_FlushMMU(
- + IN gckVGHARDWARE Hardware
- + )
- +{
- + gceSTATUS status;
- + gckVGCOMMAND command;
- +
- + gcmkHEADER_ARG("Hardware=0x%x ", Hardware);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + do
- + {
- + gcsCMDBUFFER_PTR commandBuffer;
- + gctUINT32_PTR buffer;
- +
- + /* Create a shortcut to the command buffer object. */
- + command = Hardware->kernel->command;
- +
- + /* Allocate command buffer space. */
- + gcmkERR_BREAK(gckVGCOMMAND_Allocate(
- + command, 8, &commandBuffer, (gctPOINTER *) &buffer
- + ));
- +
- + buffer[0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E04) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + buffer[1]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
- + }
- + while(gcvFALSE);
- +
- + gcmkFOOTER();
- + /* Return the status. */
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGHARDWARE_BuildVirtualAddress
- +**
- +** Build a virtual address.
- +**
- +** INPUT:
- +**
- +** gckVGHARDWARE Harwdare
- +** Pointer to an gckVGHARDWARE object.
- +**
- +** gctUINT32 Index
- +** Index into page table.
- +**
- +** gctUINT32 Offset
- +** Offset into page.
- +**
- +** OUTPUT:
- +**
- +** gctUINT32 * Address
- +** Pointer to a variable receiving te hardware address.
- +*/
- +gceSTATUS gckVGHARDWARE_BuildVirtualAddress(
- + IN gckVGHARDWARE Hardware,
- + IN gctUINT32 Index,
- + IN gctUINT32 Offset,
- + OUT gctUINT32 * Address
- + )
- +{
- + gctUINT32 address;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Index=0x%x Offset=0x%x Address=0x%x",
- + Hardware, Index, Offset, Address);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(Address != gcvNULL);
- +
- + /* Build virtual address. */
- + address = (Index << 12) | Offset;
- +
- + /* Set virtual type. */
- + address = ((((gctUINT32) (address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x2 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
- +
- + /* Set the result. */
- + *Address = address;
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckVGHARDWARE_GetIdle(
- + IN gckVGHARDWARE Hardware,
- + OUT gctUINT32 * Data
- + )
- +{
- + gceSTATUS status;
- + gcmkHEADER_ARG("Hardware=0x%x Data=0x%x", Hardware, Data);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(Data != gcvNULL);
- +
- + /* Read register and return. */
- + status = gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG, 0x00004, Data);
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckVGHARDWARE_SetFastClear(
- + IN gckVGHARDWARE Hardware,
- + IN gctINT Enable
- + )
- +{
- + gctUINT32 debug;
- + gceSTATUS status;
- +
- + if (!(((((gctUINT32) (Hardware->chipFeatures)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
- + {
- + return gcvSTATUS_OK;
- + }
- +
- + do
- + {
- + if (Enable == -1)
- + {
- + Enable = (Hardware->chipModel > gcv500) ||
- + ((Hardware->chipModel == gcv500) && (Hardware->chipRevision >= 3));
- + }
- +
- + gcmkERR_BREAK(gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG,
- + 0x00414,
- + &debug));
- +
- + debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20))) | (((gctUINT32) ((gctUINT32) (Enable == 0) & ((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20)));
- +
- +#ifdef AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION
- + debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1) == 32) ? ~0 : (~(~0 << ((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1))))))) << (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION))) | (((gctUINT32) ((gctUINT32) (Enable == 0) & ((gctUINT32) ((((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1) == 32) ? ~0 : (~(~0 << ((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1))))))) << (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION)));
- +#endif
- +
- + gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
- + 0x00414,
- + debug));
- +
- + Hardware->allowFastClear = Enable;
- +
- + status = gcvFALSE;
- + }
- + while (gcvFALSE);
- +
- + return status;
- +}
- +
- +gceSTATUS
- +gckVGHARDWARE_ReadInterrupt(
- + IN gckVGHARDWARE Hardware,
- + OUT gctUINT32_PTR IDs
- + )
- +{
- + gceSTATUS status;
- + gcmkHEADER_ARG("Hardware=0x%x IDs=0x%x", Hardware, IDs);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(IDs != gcvNULL);
- +
- + /* Read AQIntrAcknowledge register. */
- + status = gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG,
- + 0x00010,
- + IDs);
- + gcmkFOOTER();
- + return status;
- +}
- +
- +static gceSTATUS _CommandStall(
- + gckVGHARDWARE Hardware)
- +{
- + gceSTATUS status;
- + gckVGCOMMAND command;
- +
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + do
- + {
- + gctUINT32_PTR buffer;
- + command = Hardware->kernel->command;
- +
- + /* Allocate command buffer space. */
- + gcmkERR_BREAK(gckVGCOMMAND_Allocate(
- + command, 8, &command->powerStallBuffer,
- + (gctPOINTER *) &buffer
- + ));
- +
- + gcmkERR_BREAK(gckVGCOMMAND_EventCommand(
- + command, buffer, gcvBLOCK_PIXEL,
- + command->powerStallInt, gcvNULL));
- +
- + gcmkERR_BREAK(gckVGCOMMAND_Execute(
- + command,
- + command->powerStallBuffer
- + ));
- +
- + /* Wait the signal. */
- + gcmkERR_BREAK(gckOS_WaitSignal(
- + command->os,
- + command->powerStallSignal,
- + gcdGPU_TIMEOUT));
- +
- +
- + }
- + while(gcvFALSE);
- +
- + gcmkFOOTER();
- + /* Return the status. */
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_SetPowerManagementState
- +**
- +** Set GPU to a specified power state.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Harwdare
- +** Pointer to an gckHARDWARE object.
- +**
- +** gceCHIPPOWERSTATE State
- +** Power State.
- +**
- +*/
- +gceSTATUS
- +gckVGHARDWARE_SetPowerManagementState(
- + IN gckVGHARDWARE Hardware,
- + IN gceCHIPPOWERSTATE State
- + )
- +{
- + gceSTATUS status;
- + gckVGCOMMAND command = gcvNULL;
- + gckOS os;
- + gctUINT flag/*, clock*/;
- +
- + gctBOOL acquired = gcvFALSE;
- + gctBOOL stall = gcvTRUE;
- + gctBOOL commitMutex = gcvFALSE;
- + gctBOOL mutexAcquired = gcvFALSE;
- +
- +#if gcdPOWEROFF_TIMEOUT
- + gctBOOL timeout = gcvFALSE;
- + gctBOOL isAfter = gcvFALSE;
- + gctUINT32 currentTime;
- +#endif
- +
- + gctBOOL broadcast = gcvFALSE;
- + gctUINT32 process, thread;
- + gctBOOL global = gcvFALSE;
- +
- +#if gcdENABLE_PROFILING
- + gctUINT64 time, freq, mutexTime, onTime, stallTime, stopTime, delayTime,
- + initTime, offTime, startTime, totalTime;
- +#endif
- +
- + /* State transition flags. */
- + static const gctUINT flags[4][4] =
- + {
- + /* gcvPOWER_ON */
- + { /* ON */ 0,
- + /* OFF */ gcvPOWER_FLAG_ACQUIRE |
- + gcvPOWER_FLAG_STALL |
- + gcvPOWER_FLAG_STOP |
- + gcvPOWER_FLAG_POWER_OFF |
- + gcvPOWER_FLAG_CLOCK_OFF,
- + /* IDLE */ gcvPOWER_FLAG_NOP,
- + /* SUSPEND */ gcvPOWER_FLAG_ACQUIRE |
- + gcvPOWER_FLAG_STALL |
- + gcvPOWER_FLAG_STOP |
- + gcvPOWER_FLAG_CLOCK_OFF,
- + },
- +
- + /* gcvPOWER_OFF */
- + { /* ON */ gcvPOWER_FLAG_INITIALIZE |
- + gcvPOWER_FLAG_START |
- + gcvPOWER_FLAG_RELEASE |
- + gcvPOWER_FLAG_DELAY,
- + /* OFF */ 0,
- + /* IDLE */ gcvPOWER_FLAG_INITIALIZE |
- + gcvPOWER_FLAG_START |
- + gcvPOWER_FLAG_RELEASE |
- + gcvPOWER_FLAG_DELAY,
- + /* SUSPEND */ gcvPOWER_FLAG_INITIALIZE |
- + gcvPOWER_FLAG_CLOCK_OFF,
- + },
- +
- + /* gcvPOWER_IDLE */
- + { /* ON */ gcvPOWER_FLAG_NOP,
- + /* OFF */ gcvPOWER_FLAG_ACQUIRE |
- + gcvPOWER_FLAG_STOP |
- + gcvPOWER_FLAG_POWER_OFF |
- + gcvPOWER_FLAG_CLOCK_OFF,
- + /* IDLE */ 0,
- + /* SUSPEND */ gcvPOWER_FLAG_ACQUIRE |
- + gcvPOWER_FLAG_STOP |
- + gcvPOWER_FLAG_CLOCK_OFF,
- + },
- +
- + /* gcvPOWER_SUSPEND */
- + { /* ON */ gcvPOWER_FLAG_START |
- + gcvPOWER_FLAG_RELEASE |
- + gcvPOWER_FLAG_DELAY |
- + gcvPOWER_FLAG_CLOCK_ON,
- + /* OFF */ gcvPOWER_FLAG_SAVE |
- + gcvPOWER_FLAG_POWER_OFF |
- + gcvPOWER_FLAG_CLOCK_OFF,
- + /* IDLE */ gcvPOWER_FLAG_START |
- + gcvPOWER_FLAG_DELAY |
- + gcvPOWER_FLAG_RELEASE |
- + gcvPOWER_FLAG_CLOCK_ON,
- + /* SUSPEND */ 0,
- + },
- + };
- +
- + gcmkHEADER_ARG("Hardware=0x%x State=%d", Hardware, State);
- +#if gcmIS_DEBUG(gcdDEBUG_TRACE)
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Switching to power state %d",
- + State);
- +#endif
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + /* Get the gckOS object pointer. */
- + os = Hardware->os;
- + gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
- +
- + /* Get the gckCOMMAND object pointer. */
- + gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
- + command = Hardware->kernel->command;
- + gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
- +
- + if (Hardware->powerManagement == gcvFALSE)
- + {
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- +
- + /* Start profiler. */
- + gcmkPROFILE_INIT(freq, time);
- +
- + /* Convert the broadcast power state. */
- + switch (State)
- + {
- + case gcvPOWER_SUSPEND_ATPOWERON:
- + /* Convert to SUSPEND and don't wait for STALL. */
- + State = gcvPOWER_SUSPEND;
- + stall = gcvFALSE;
- + break;
- +
- + case gcvPOWER_OFF_ATPOWERON:
- + /* Convert to OFF and don't wait for STALL. */
- + State = gcvPOWER_OFF;
- + stall = gcvFALSE;
- + break;
- +
- + case gcvPOWER_IDLE_BROADCAST:
- + /* Convert to IDLE and note we are inside broadcast. */
- + State = gcvPOWER_IDLE;
- + broadcast = gcvTRUE;
- + break;
- +
- + case gcvPOWER_SUSPEND_BROADCAST:
- + /* Convert to SUSPEND and note we are inside broadcast. */
- + State = gcvPOWER_SUSPEND;
- + broadcast = gcvTRUE;
- + break;
- +
- + case gcvPOWER_OFF_BROADCAST:
- + /* Convert to OFF and note we are inside broadcast. */
- + State = gcvPOWER_OFF;
- + broadcast = gcvTRUE;
- + break;
- +
- + case gcvPOWER_OFF_RECOVERY:
- + /* Convert to OFF and note we are inside recovery. */
- + State = gcvPOWER_OFF;
- + stall = gcvFALSE;
- + broadcast = gcvTRUE;
- + break;
- +
- + case gcvPOWER_ON_AUTO:
- + /* Convert to ON and note we are inside recovery. */
- + State = gcvPOWER_ON;
- + break;
- +
- + case gcvPOWER_ON:
- + case gcvPOWER_IDLE:
- + case gcvPOWER_SUSPEND:
- + case gcvPOWER_OFF:
- + /* Mark as global power management. */
- + global = gcvTRUE;
- + break;
- +
- +#if gcdPOWEROFF_TIMEOUT
- + case gcvPOWER_OFF_TIMEOUT:
- + /* Convert to OFF and note we are inside broadcast. */
- + State = gcvPOWER_OFF;
- + broadcast = gcvTRUE;
- + /* Check time out */
- + timeout = gcvTRUE;
- + break;
- +#endif
- +
- + default:
- + break;
- + }
- +
- + /* Get current process and thread IDs. */
- + gcmkONERROR(gckOS_GetProcessID(&process));
- + gcmkONERROR(gckOS_GetThreadID(&thread));
- +
- + /* Acquire the power mutex. */
- + if (broadcast)
- + {
- + /* Try to acquire the power mutex. */
- + status = gckOS_AcquireMutex(os, Hardware->powerMutex, 0);
- +
- + if (status == gcvSTATUS_TIMEOUT)
- + {
- + /* Check if we already own this mutex. */
- + if ((Hardware->powerProcess == process)
- + && (Hardware->powerThread == thread)
- + )
- + {
- + /* Bail out on recursive power management. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- + else if (State == gcvPOWER_IDLE)
- + {
- + /* gcvPOWER_IDLE_BROADCAST is from IST,
- + ** so waiting here will cause deadlock,
- + ** if lock holder call gckCOMMAND_Stall() */
- + gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
- + }
- + else
- + {
- + /* Acquire the power mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(os,
- + Hardware->powerMutex,
- + gcvINFINITE));
- + }
- + }
- + }
- + else
- + {
- + /* Acquire the power mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(os, Hardware->powerMutex, gcvINFINITE));
- + }
- +
- + /* Get time until mtuex acquired. */
- + gcmkPROFILE_QUERY(time, mutexTime);
- +
- + Hardware->powerProcess = process;
- + Hardware->powerThread = thread;
- + mutexAcquired = gcvTRUE;
- +
- + /* Grab control flags and clock. */
- + flag = flags[Hardware->chipPowerState][State];
- + /*clock = clocks[State];*/
- +
- +#if gcdPOWEROFF_TIMEOUT
- + if (timeout)
- + {
- + gcmkONERROR(gckOS_GetTicks(¤tTime));
- +
- + gcmkONERROR(
- + gckOS_TicksAfter(Hardware->powerOffTime, currentTime, &isAfter));
- +
- + /* powerOffTime is pushed forward, give up.*/
- + if (isAfter
- + /* Expect a transition start from IDLE. */
- + || (Hardware->chipPowerState == gcvPOWER_ON)
- + || (Hardware->chipPowerState == gcvPOWER_OFF)
- + )
- + {
- + /* Release the power mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
- +
- + /* No need to do anything. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- + }
- +#endif
- +
- + if (flag == 0)
- + {
- + /* Release the power mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
- +
- + /* No need to do anything. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- +
- + /* internal power control */
- + if (!global)
- + {
- + if (Hardware->chipPowerStateGlobal == gcvPOWER_OFF)
- + {
- + /* Release the power mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
- +
- + /* No need to do anything. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- + }
- + else
- + {
- + if (flag & gcvPOWER_FLAG_ACQUIRE)
- + {
- + /* Acquire the power management semaphore. */
- + gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
- + acquired = gcvTRUE;
- +
- + /* avoid acquiring again. */
- + flag &= ~gcvPOWER_FLAG_ACQUIRE;
- + }
- + }
- +
- + if (flag & (gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_CLOCK_ON))
- + {
- + /* Turn on the power. */
- + gcmkONERROR(gckOS_SetGPUPower(os, gcvCORE_VG, gcvTRUE, gcvTRUE));
- +
- + /* Mark clock and power as enabled. */
- + Hardware->clockState = gcvTRUE;
- + Hardware->powerState = gcvTRUE;
- + }
- +
- + /* Get time until powered on. */
- + gcmkPROFILE_QUERY(time, onTime);
- +
- + if ((flag & gcvPOWER_FLAG_STALL) && stall)
- + {
- + /* Acquire the mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(
- + command->os,
- + command->commitMutex,
- + gcvINFINITE
- + ));
- +
- + commitMutex = gcvTRUE;
- +
- + gcmkONERROR(_CommandStall(Hardware));
- + }
- +
- + /* Get time until stalled. */
- + gcmkPROFILE_QUERY(time, stallTime);
- +
- + if (flag & gcvPOWER_FLAG_ACQUIRE)
- + {
- + /* Acquire the power management semaphore. */
- + gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
- +
- + acquired = gcvTRUE;
- + }
- +
- + if (flag & gcvPOWER_FLAG_STOP)
- + {
- + }
- +
- + /* Get time until stopped. */
- + gcmkPROFILE_QUERY(time, stopTime);
- +
- + /* Only process this when hardware is enabled. */
- + if (Hardware->clockState && Hardware->powerState)
- + {
- + }
- +
- + if (flag & gcvPOWER_FLAG_DELAY)
- + {
- + /* Wait for the specified amount of time to settle coming back from
- + ** power-off or suspend state. */
- + gcmkONERROR(gckOS_Delay(os, gcdPOWER_CONTROL_DELAY));
- + }
- +
- + /* Get time until delayed. */
- + gcmkPROFILE_QUERY(time, delayTime);
- +
- + if (flag & gcvPOWER_FLAG_INITIALIZE)
- + {
- + gcmkONERROR(gckVGHARDWARE_SetMMU(Hardware, Hardware->kernel->mmu->pageTableLogical));
- +
- + /* Force the command queue to reload the next context. */
- + command->currentContext = 0;
- + }
- +
- + /* Get time until initialized. */
- + gcmkPROFILE_QUERY(time, initTime);
- +
- + if (flag & (gcvPOWER_FLAG_POWER_OFF | gcvPOWER_FLAG_CLOCK_OFF))
- + {
- + /* Turn off the GPU power. */
- + gcmkONERROR(
- + gckOS_SetGPUPower(os,
- + gcvCORE_VG,
- + (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
- + : gcvTRUE,
- + (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
- + : gcvTRUE));
- +
- + /* Save current hardware power and clock states. */
- + Hardware->clockState = (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
- + : gcvTRUE;
- + Hardware->powerState = (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
- + : gcvTRUE;
- + }
- +
- + /* Get time until off. */
- + gcmkPROFILE_QUERY(time, offTime);
- +
- + if (flag & gcvPOWER_FLAG_START)
- + {
- + }
- +
- + /* Get time until started. */
- + gcmkPROFILE_QUERY(time, startTime);
- +
- + if (flag & gcvPOWER_FLAG_RELEASE)
- + {
- + /* Release the power management semaphore. */
- + gcmkONERROR(gckOS_ReleaseSemaphore(os, command->powerSemaphore));
- + acquired = gcvFALSE;
- + }
- +
- + /* Save the new power state. */
- + Hardware->chipPowerState = State;
- +
- + if (global)
- + {
- + /* Save the new power state. */
- + Hardware->chipPowerStateGlobal = State;
- + }
- +
- + if (commitMutex)
- + {
- + /* Acquire the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(
- + command->os,
- + command->commitMutex
- + ));
- + }
- +
- +#if gcdPOWEROFF_TIMEOUT
- + /* Reset power off time */
- + gcmkONERROR(gckOS_GetTicks(¤tTime));
- +
- + Hardware->powerOffTime = currentTime + Hardware->powerOffTimeout;
- +
- + if (State == gcvPOWER_IDLE)
- + {
- + /* Start a timer to power off GPU when GPU enters IDLE or SUSPEND. */
- + gcmkVERIFY_OK(gckOS_StartTimer(os,
- + Hardware->powerOffTimer,
- + Hardware->powerOffTimeout));
- + }
- + else
- + {
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "Cancel powerOfftimer");
- +
- + /* Cancel running timer when GPU enters ON or OFF. */
- + gcmkVERIFY_OK(gckOS_StopTimer(os, Hardware->powerOffTimer));
- + }
- +#endif
- +
- + /* Release the power mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
- +
- + /* Get total time. */
- + gcmkPROFILE_QUERY(time, totalTime);
- +#if gcdENABLE_PROFILING
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "PROF(%llu): mutex:%llu on:%llu stall:%llu stop:%llu",
- + freq, mutexTime, onTime, stallTime, stopTime);
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + " delay:%llu init:%llu off:%llu start:%llu total:%llu",
- + delayTime, initTime, offTime, startTime, totalTime);
- +#endif
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- +
- + if (acquired)
- + {
- + /* Release semaphore. */
- + gcmkVERIFY_OK(gckOS_ReleaseSemaphore(Hardware->os,
- + command->powerSemaphore));
- + }
- +
- + if (mutexAcquired)
- + {
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
- + }
- +
- + if (commitMutex)
- + {
- + /* Acquire the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(
- + command->os,
- + command->commitMutex
- + ));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_QueryPowerManagementState
- +**
- +** Get GPU power state.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Harwdare
- +** Pointer to an gckHARDWARE object.
- +**
- +** gceCHIPPOWERSTATE* State
- +** Power State.
- +**
- +*/
- +gceSTATUS
- +gckVGHARDWARE_QueryPowerManagementState(
- + IN gckVGHARDWARE Hardware,
- + OUT gceCHIPPOWERSTATE* State
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(State != gcvNULL);
- +
- + /* Return the statue. */
- + *State = Hardware->chipPowerState;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*State=%d", *State);
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGHARDWARE_SetPowerManagement
- +**
- +** Configure GPU power management function.
- +** Only used in driver initialization stage.
- +**
- +** INPUT:
- +**
- +** gckVGHARDWARE Harwdare
- +** Pointer to an gckHARDWARE object.
- +**
- +** gctBOOL PowerManagement
- +** Power Mangement State.
- +**
- +*/
- +gceSTATUS
- +gckVGHARDWARE_SetPowerManagement(
- + IN gckVGHARDWARE Hardware,
- + IN gctBOOL PowerManagement
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + Hardware->powerManagement = PowerManagement;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckVGHARDWARE_SetPowerOffTimeout(
- + IN gckVGHARDWARE Hardware,
- + IN gctUINT32 Timeout
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x Timeout=%d", Hardware, Timeout);
- +
- +#if gcdPOWEROFF_TIMEOUT
- + Hardware->powerOffTimeout = Timeout;
- +#endif
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +
- +gceSTATUS
- +gckVGHARDWARE_QueryPowerOffTimeout(
- + IN gckVGHARDWARE Hardware,
- + OUT gctUINT32* Timeout
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- +#if gcdPOWEROFF_TIMEOUT
- + *Timeout = Hardware->powerOffTimeout;
- +#endif
- +
- + gcmkFOOTER_ARG("*Timeout=%d", *Timeout);
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckVGHARDWARE_QueryIdle(
- + IN gckVGHARDWARE Hardware,
- + OUT gctBOOL_PTR IsIdle
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 idle;
- +
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(IsIdle != gcvNULL);
- +
- + /* We are idle when the power is not ON. */
- + if (Hardware->chipPowerState != gcvPOWER_ON)
- + {
- + *IsIdle = gcvTRUE;
- + }
- +
- + else
- + {
- + /* Read idle register. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG, 0x00004, &idle));
- +
- + /* Pipe must be idle. */
- + if (((((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ) != 1)
- + || ((((((gctUINT32) (idle)) >> (0 ? 8:8)) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1)))))) ) != 1)
- + || ((((((gctUINT32) (idle)) >> (0 ? 9:9)) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) ) != 1)
- + || ((((((gctUINT32) (idle)) >> (0 ? 10:10)) & ((gctUINT32) ((((1 ? 10:10) - (0 ? 10:10) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 10:10) - (0 ? 10:10) + 1)))))) ) != 1)
- + || ((((((gctUINT32) (idle)) >> (0 ? 11:11)) & ((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1)))))) ) != 1)
- + )
- + {
- + /* Something is busy. */
- + *IsIdle = gcvFALSE;
- + }
- +
- + else
- + {
- + *IsIdle = gcvTRUE;
- + }
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +#endif /* gcdENABLE_VG */
- +
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.h linux-3.14.35/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.h 2015-03-08 14:27:37.617684501 -0500
- @@ -0,0 +1,75 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_kernel_hardware_vg_h_
- +#define __gc_hal_kernel_hardware_vg_h_
- +
- +/* gckHARDWARE object. */
- +struct _gckVGHARDWARE
- +{
- + /* Object. */
- + gcsOBJECT object;
- +
- + /* Pointer to gckKERNEL object. */
- + gckVGKERNEL kernel;
- +
- + /* Pointer to gckOS object. */
- + gckOS os;
- +
- + /* Chip characteristics. */
- + gceCHIPMODEL chipModel;
- + gctUINT32 chipRevision;
- + gctUINT32 chipFeatures;
- + gctUINT32 chipMinorFeatures;
- + gctUINT32 chipMinorFeatures2;
- + gctBOOL allowFastClear;
- +
- + /* Features. */
- + gctBOOL fe20;
- + gctBOOL vg20;
- + gctBOOL vg21;
- +
- + /* Event mask. */
- + gctUINT32 eventMask;
- +
- + gctBOOL clockState;
- + gctBOOL powerState;
- + gctPOINTER powerMutex;
- + gctUINT32 powerProcess;
- + gctUINT32 powerThread;
- + gceCHIPPOWERSTATE chipPowerState;
- + gceCHIPPOWERSTATE chipPowerStateGlobal;
- + gctISRMANAGERFUNC startIsr;
- + gctISRMANAGERFUNC stopIsr;
- + gctPOINTER isrContext;
- + gctPOINTER pageTableDirty;
- +
- +#if gcdPOWEROFF_TIMEOUT
- + gctUINT32 powerOffTime;
- + gctUINT32 powerOffTimeout;
- + gctPOINTER powerOffTimer;
- +#endif
- +
- + gctBOOL powerManagement;
- +};
- +
- +#endif /* __gc_hal_kernel_hardware_h_ */
- +
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c linux-3.14.35/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c 2015-03-08 14:27:37.621684501 -0500
- @@ -0,0 +1,1735 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal.h"
- +#include "gc_hal_kernel.h"
- +#include "gc_hal_kernel_context.h"
- +#include "gc_hal_kernel_buffer.h"
- +
- +/******************************************************************************\
- +******************************** Debugging Macro *******************************
- +\******************************************************************************/
- +
- +/* Zone used for header/footer. */
- +#define _GC_OBJ_ZONE gcvZONE_HARDWARE
- +
- +
- +/******************************************************************************\
- +************************** Context State Buffer Helpers ************************
- +\******************************************************************************/
- +
- +#define _STATE(reg) \
- + _State(\
- + Context, index, \
- + reg ## _Address >> 2, \
- + reg ## _ResetValue, \
- + reg ## _Count, \
- + gcvFALSE, gcvFALSE \
- + )
- +
- +#define _STATE_COUNT(reg, count) \
- + _State(\
- + Context, index, \
- + reg ## _Address >> 2, \
- + reg ## _ResetValue, \
- + count, \
- + gcvFALSE, gcvFALSE \
- + )
- +
- +#define _STATE_COUNT_OFFSET(reg, offset, count) \
- + _State(\
- + Context, index, \
- + (reg ## _Address >> 2) + offset, \
- + reg ## _ResetValue, \
- + count, \
- + gcvFALSE, gcvFALSE \
- + )
- +
- +#define _STATE_MIRROR_COUNT(reg, mirror, count) \
- + _StateMirror(\
- + Context, \
- + reg ## _Address >> 2, \
- + count, \
- + mirror ## _Address >> 2 \
- + )
- +
- +#define _STATE_HINT(reg) \
- + _State(\
- + Context, index, \
- + reg ## _Address >> 2, \
- + reg ## _ResetValue, \
- + reg ## _Count, \
- + gcvFALSE, gcvTRUE \
- + )
- +
- +#define _STATE_HINT_BLOCK(reg, block, count) \
- + _State(\
- + Context, index, \
- + (reg ## _Address >> 2) + (block << reg ## _BLK), \
- + reg ## _ResetValue, \
- + count, \
- + gcvFALSE, gcvTRUE \
- + )
- +
- +#define _STATE_X(reg) \
- + _State(\
- + Context, index, \
- + reg ## _Address >> 2, \
- + reg ## _ResetValue, \
- + reg ## _Count, \
- + gcvTRUE, gcvFALSE \
- + )
- +
- +#define _CLOSE_RANGE() \
- + _TerminateStateBlock(Context, index)
- +
- +#define _ENABLE(reg, field) \
- + do \
- + { \
- + if (gcmVERIFYFIELDVALUE(data, reg, MASK_ ## field, ENABLED)) \
- + { \
- + enable |= gcmFIELDMASK(reg, field); \
- + } \
- + } \
- + while (gcvFALSE)
- +
- +#define _BLOCK_COUNT(reg) \
- + ((reg ## _Count) >> (reg ## _BLK))
- +
- +
- +/******************************************************************************\
- +*********************** Support Functions and Definitions **********************
- +\******************************************************************************/
- +
- +#define gcdSTATE_MASK \
- + (((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x03 | 0xC0FFEE & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))))
- +
- +#if !defined(VIVANTE_NO_3D)
- +static gctSIZE_T
- +_TerminateStateBlock(
- + IN gckCONTEXT Context,
- + IN gctSIZE_T Index
- + )
- +{
- + gctUINT32_PTR buffer;
- + gctSIZE_T align;
- +
- + /* Determine if we need alignment. */
- + align = (Index & 1) ? 1 : 0;
- +
- + /* Address correct index. */
- + buffer = (Context->buffer == gcvNULL)
- + ? gcvNULL
- + : Context->buffer->logical;
- +
- + /* Flush the current state block; make sure no pairing with the states
- + to follow happens. */
- + if (align && (buffer != gcvNULL))
- + {
- + buffer[Index] = 0xDEADDEAD;
- + }
- +
- + /* Reset last address. */
- + Context->lastAddress = ~0U;
- +
- + /* Return alignment requirement. */
- + return align;
- +}
- +#endif
- +
- +
- +static gctSIZE_T
- +_FlushPipe(
- + IN gckCONTEXT Context,
- + IN gctSIZE_T Index,
- + IN gcePIPE_SELECT Pipe
- + )
- +{
- + if (Context->buffer != gcvNULL)
- + {
- + gctUINT32_PTR buffer;
- +
- + /* Address correct index. */
- + buffer = Context->buffer->logical + Index;
- +
- + /* Flush the current pipe. */
- + *buffer++
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + *buffer++
- + = (Pipe == gcvPIPE_2D)
- + ? ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
- + : ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
- +
- + /* Semaphore from FE to PE. */
- + *buffer++
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + *buffer++
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
- +
- + /* Stall from FE to PE. */
- + *buffer++
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
- +
- + *buffer
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
- + }
- +
- + /* Flushing 3D pipe takes 6 slots. */
- + return 6;
- +}
- +
- +#if !defined(VIVANTE_NO_3D)
- +static gctSIZE_T
- +_SemaphoreStall(
- + IN gckCONTEXT Context,
- + IN gctSIZE_T Index
- + )
- +{
- + if (Context->buffer != gcvNULL)
- + {
- + gctUINT32_PTR buffer;
- +
- + /* Address correct index. */
- + buffer = Context->buffer->logical + Index;
- +
- + /* Semaphore from FE to PE. */
- + *buffer++
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + *buffer++
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
- +
- + /* Stall from FE to PE. */
- + *buffer++
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
- +
- + *buffer
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
- + }
- +
- + /* Semaphore/stall takes 4 slots. */
- + return 4;
- +}
- +#endif
- +
- +static gctSIZE_T
- +_SwitchPipe(
- + IN gckCONTEXT Context,
- + IN gctSIZE_T Index,
- + IN gcePIPE_SELECT Pipe
- + )
- +{
- + if (Context->buffer != gcvNULL)
- + {
- + gctUINT32_PTR buffer;
- +
- + /* Address correct index. */
- + buffer = Context->buffer->logical + Index;
- +
- + /* LoadState(AQPipeSelect, 1), pipe. */
- + *buffer++
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + *buffer
- + = (Pipe == gcvPIPE_2D)
- + ? 0x1
- + : 0x0;
- + }
- +
- + return 2;
- +}
- +
- +#if !defined(VIVANTE_NO_3D)
- +static gctSIZE_T
- +_State(
- + IN gckCONTEXT Context,
- + IN gctSIZE_T Index,
- + IN gctUINT32 Address,
- + IN gctUINT32 Value,
- + IN gctSIZE_T Size,
- + IN gctBOOL FixedPoint,
- + IN gctBOOL Hinted
- + )
- +{
- + gctUINT32_PTR buffer;
- + gctSIZE_T align, i;
- +
- + /* Determine if we need alignment. */
- + align = (Index & 1) ? 1 : 0;
- +
- + /* Address correct index. */
- + buffer = (Context->buffer == gcvNULL)
- + ? gcvNULL
- + : Context->buffer->logical;
- +
- + if ((buffer == gcvNULL) && (Address + Size > Context->stateCount))
- + {
- + /* Determine maximum state. */
- + Context->stateCount = Address + Size;
- + }
- +
- + /* Do we need a new entry? */
- + if ((Address != Context->lastAddress) || (FixedPoint != Context->lastFixed))
- + {
- + if (buffer != gcvNULL)
- + {
- + if (align)
- + {
- + /* Add filler. */
- + buffer[Index++] = 0xDEADDEAD;
- + }
- +
- + /* LoadState(Address, Count). */
- + gcmkASSERT((Index & 1) == 0);
- +
- + if (FixedPoint)
- + {
- + buffer[Index]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1))))))) << (0 ? 26:26))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1))))))) << (0 ? 26:26)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (Size) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Address) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- + }
- + else
- + {
- + buffer[Index]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1))))))) << (0 ? 26:26))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1))))))) << (0 ? 26:26)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (Size) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Address) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- + }
- +
- + /* Walk all the states. */
- + for (i = 0; i < Size; i += 1)
- + {
- + /* Set state to uninitialized value. */
- + buffer[Index + 1 + i] = Value;
- +
- + /* Set index in state mapping table. */
- + Context->map[Address + i].index = Index + 1 + i;
- +
- +#if gcdSECURE_USER
- + /* Save hint. */
- + if (Context->hint != gcvNULL)
- + {
- + Context->hint[Address + i] = Hinted;
- + }
- +#endif
- + }
- + }
- +
- + /* Save information for this LoadState. */
- + Context->lastIndex = Index;
- + Context->lastAddress = Address + Size;
- + Context->lastSize = Size;
- + Context->lastFixed = FixedPoint;
- +
- + /* Return size for load state. */
- + return align + 1 + Size;
- + }
- +
- + /* Append this state to the previous one. */
- + if (buffer != gcvNULL)
- + {
- + /* Update last load state. */
- + buffer[Context->lastIndex] =
- + ((((gctUINT32) (buffer[Context->lastIndex])) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (Context->lastSize + Size) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + /* Walk all the states. */
- + for (i = 0; i < Size; i += 1)
- + {
- + /* Set state to uninitialized value. */
- + buffer[Index + i] = Value;
- +
- + /* Set index in state mapping table. */
- + Context->map[Address + i].index = Index + i;
- +
- +#if gcdSECURE_USER
- + /* Save hint. */
- + if (Context->hint != gcvNULL)
- + {
- + Context->hint[Address + i] = Hinted;
- + }
- +#endif
- + }
- + }
- +
- + /* Update last address and size. */
- + Context->lastAddress += Size;
- + Context->lastSize += Size;
- +
- + /* Return number of slots required. */
- + return Size;
- +}
- +
- +static gctSIZE_T
- +_StateMirror(
- + IN gckCONTEXT Context,
- + IN gctUINT32 Address,
- + IN gctSIZE_T Size,
- + IN gctUINT32 AddressMirror
- + )
- +{
- + gctSIZE_T i;
- +
- + /* Process when buffer is set. */
- + if (Context->buffer != gcvNULL)
- + {
- + /* Walk all states. */
- + for (i = 0; i < Size; i++)
- + {
- + /* Copy the mapping address. */
- + Context->map[Address + i].index =
- + Context->map[AddressMirror + i].index;
- + }
- + }
- +
- + /* Return the number of required maps. */
- + return Size;
- +}
- +#endif
- +
- +static gceSTATUS
- +_InitializeContextBuffer(
- + IN gckCONTEXT Context
- + )
- +{
- + gctUINT32_PTR buffer;
- + gctSIZE_T index;
- +
- +#if !defined(VIVANTE_NO_3D)
- + gctUINT i;
- + gctUINT vertexUniforms, fragmentUniforms;
- + gctUINT fe2vsCount;
- + gctBOOL halti0;
- +#endif
- +
- + /* Reset the buffer index. */
- + index = 0;
- +
- + /* Reset the last state address. */
- + Context->lastAddress = ~0U;
- +
- + /* Get the buffer pointer. */
- + buffer = (Context->buffer == gcvNULL)
- + ? gcvNULL
- + : Context->buffer->logical;
- +
- +
- + /**************************************************************************/
- + /* Build 2D states. *******************************************************/
- +
- +
- +#if !defined(VIVANTE_NO_3D)
- + /**************************************************************************/
- + /* Build 3D states. *******************************************************/
- + halti0 = (((((gctUINT32) (Context->hardware->identity.chipMinorFeatures1)) >> (0 ? 23:23)) & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1)))))) );
- +
- + /* Query shader support. */
- + gcmkVERIFY_OK(gckHARDWARE_QueryShaderCaps(
- + Context->hardware, &vertexUniforms, &fragmentUniforms, gcvNULL));
- +
- + /* Store the 3D entry index. */
- + Context->entryOffset3D = index * gcmSIZEOF(gctUINT32);
- +
- + /* Flush 2D pipe. */
- + index += _FlushPipe(Context, index, gcvPIPE_2D);
- +
- + /* Switch to 3D pipe. */
- + index += _SwitchPipe(Context, index, gcvPIPE_3D);
- +
- + /* Current context pointer. */
- +#if gcdDEBUG
- + index += _State(Context, index, 0x03850 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- +#endif
- +
- + index += _FlushPipe(Context, index, gcvPIPE_3D);
- +
- + /* Global states. */
- + index += _State(Context, index, 0x03814 >> 2, 0x00000001, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x03818 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x0381C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x03820 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x03828 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x0382C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x03834 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x03838 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x0384C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- +
- + /* Front End states. */
- + fe2vsCount = 12;
- + if ((((((gctUINT32) (Context->hardware->identity.chipMinorFeatures1)) >> (0 ? 23:23)) & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1)))))) ))
- + {
- + fe2vsCount = 16;
- + }
- + index += _State(Context, index, 0x00600 >> 2, 0x00000000, fe2vsCount, gcvFALSE, gcvFALSE);
- + index += _CLOSE_RANGE();
- +
- + index += _State(Context, index, 0x00644 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, 0x00648 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x0064C >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, 0x00650 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00680 >> 2, 0x00000000, 8, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, 0x006A0 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00670 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00678 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x0067C >> 2, 0xFFFFFFFF, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x006C0 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00700 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00740 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00780 >> 2, 0x3F800000, 16, gcvFALSE, gcvFALSE);
- +
- + /* Vertex Shader states. */
- + index += _State(Context, index, 0x00800 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00804 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00808 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x0080C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00810 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00820 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00830 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00838 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + if (Context->hardware->identity.instructionCount <= 256)
- + {
- + index += _State(Context, index, 0x04000 >> 2, 0x00000000, 1024, gcvFALSE, gcvFALSE);
- + }
- +
- + index += _CLOSE_RANGE();
- + index += _State(Context, index, 0x05000 >> 2, 0x00000000, vertexUniforms * 4, gcvFALSE, gcvFALSE);
- +
- + /* Primitive Assembly states. */
- + index += _State(Context, index, 0x00A00 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
- + index += _State(Context, index, 0x00A04 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
- + index += _State(Context, index, 0x00A08 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00A0C >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
- + index += _State(Context, index, 0x00A10 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
- + index += _State(Context, index, 0x00A14 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00A18 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00A1C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00A28 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00A2C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00A30 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00A40 >> 2, 0x00000000, 10, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00A34 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00A38 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00A3C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00A80 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00A84 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
- + index += _State(Context, index, 0x00A8C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- +
- + /* Setup states. */
- + index += _State(Context, index, 0x00C00 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
- + index += _State(Context, index, 0x00C04 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
- + index += _State(Context, index, 0x00C08 >> 2, 0x45000000, 1, gcvTRUE, gcvFALSE);
- + index += _State(Context, index, 0x00C0C >> 2, 0x45000000, 1, gcvTRUE, gcvFALSE);
- + index += _State(Context, index, 0x00C10 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00C14 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00C18 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00C1C >> 2, 0x42000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00C20 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
- + index += _State(Context, index, 0x00C24 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
- +
- + /* Raster states. */
- + index += _State(Context, index, 0x00E00 >> 2, 0x00000001, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00E10 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00E04 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00E40 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00E08 >> 2, 0x00000031, 1, gcvFALSE, gcvFALSE);
- +
- + /* Pixel Shader states. */
- + index += _State(Context, index, 0x01000 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01004 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01008 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x0100C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01010 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01018 >> 2, 0x01000000, 1, gcvFALSE, gcvFALSE);
- + if (Context->hardware->identity.instructionCount <= 256)
- + {
- + index += _State(Context, index, 0x06000 >> 2, 0x00000000, 1024, gcvFALSE, gcvFALSE);
- + }
- +
- + index += _CLOSE_RANGE();
- + index += _State(Context, index, 0x07000 >> 2, 0x00000000, fragmentUniforms * 4, gcvFALSE, gcvFALSE);
- +
- + /* Texture states. */
- + index += _State(Context, index, 0x02000 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x02040 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x02080 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x020C0 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x02100 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x02140 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x02180 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x021C0 >> 2, 0x00321000, 12, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x02200 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x02240 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, (0x02400 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, (0x02440 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, (0x02480 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, (0x024C0 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, (0x02500 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, (0x02540 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, (0x02580 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, (0x025C0 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, (0x02600 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, (0x02640 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, (0x02680 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, (0x026C0 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, (0x02700 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, (0x02740 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
- + index += _CLOSE_RANGE();
- +
- + if ((((((gctUINT32) (Context->hardware->identity.chipMinorFeatures2)) >> (0 ? 11:11)) & ((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1)))))) ))
- + {
- + gctUINT texBlockCount;
- +
- + /* New texture block. */
- + index += _State(Context, index, 0x10000 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x10080 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x10100 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x10180 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x10200 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x10280 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
- + for (i = 0; i < 256 / 16; i += 1)
- + {
- + index += _State(Context, index, (0x02C00 >> 2) + i * 16, 0x00000000, 14, gcvFALSE, gcvFALSE);
- + }
- + index += _State(Context, index, 0x10300 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x10380 >> 2, 0x00321000, 32, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x10400 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x10480 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
- +
- + if ((((((gctUINT32) (Context->hardware->identity.chipMinorFeatures2)) >> (0 ? 15:15)) & ((gctUINT32) ((((1 ? 15:15) - (0 ? 15:15) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:15) - (0 ? 15:15) + 1)))))) ))
- + {
- + index += _State(Context, index, 0x12000 >> 2, 0x00000000, 256, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x12400 >> 2, 0x00000000, 256, gcvFALSE, gcvFALSE);
- + }
- +
- + if ((Context->hardware->identity.chipModel == gcv2000)
- + && (Context->hardware->identity.chipRevision == 0x5108))
- + {
- + texBlockCount = 12;
- + }
- + else
- + {
- + texBlockCount = ((512) >> (4));
- + }
- + for (i = 0; i < texBlockCount; i += 1)
- + {
- + index += _State(Context, index, (0x10800 >> 2) + (i << 4), 0x00000000, 14, gcvFALSE, gcvTRUE);
- + }
- + }
- +
- + /* YUV. */
- + index += _State(Context, index, 0x01678 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x0167C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01680 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, 0x01684 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01688 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, 0x0168C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01690 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, 0x01694 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01698 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, 0x0169C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _CLOSE_RANGE();
- +
- + /* Thread walker states. */
- + index += _State(Context, index, 0x00900 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00904 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00908 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x0090C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00910 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00914 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00918 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x0091C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00924 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _CLOSE_RANGE();
- +
- + if (Context->hardware->identity.instructionCount > 1024)
- + {
- + /* New Shader instruction memory. */
- + index += _State(Context, index, 0x0085C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x0101C >> 2, 0x00000100, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x00860 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _CLOSE_RANGE();
- +
- + for (i = 0;
- + i < Context->hardware->identity.instructionCount << 2;
- + i += 256 << 2
- + )
- + {
- + index += _State(Context, index, (0x20000 >> 2) + i, 0x00000000, 256 << 2, gcvFALSE, gcvFALSE);
- + index += _CLOSE_RANGE();
- + }
- + }
- + else if (Context->hardware->identity.instructionCount > 256)
- + {
- + /* New Shader instruction memory. */
- + index += _State(Context, index, 0x0085C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x0101C >> 2, 0x00000100, 1, gcvFALSE, gcvFALSE);
- + index += _CLOSE_RANGE();
- +
- + /* VX instruction memory. */
- + for (i = 0;
- + i < Context->hardware->identity.instructionCount << 2;
- + i += 256 << 2
- + )
- + {
- + index += _State(Context, index, (0x0C000 >> 2) + i, 0x00000000, 256 << 2, gcvFALSE, gcvFALSE);
- + index += _CLOSE_RANGE();
- + }
- +
- + _StateMirror(Context, 0x08000 >> 2, Context->hardware->identity.instructionCount << 2 , 0x0C000 >> 2);
- + }
- +
- + /* Store the index of the "XD" entry. */
- + Context->entryOffsetXDFrom3D = index * gcmSIZEOF(gctUINT32);
- +
- +
- + /* Pixel Engine states. */
- + index += _State(Context, index, 0x01400 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01404 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01408 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x0140C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01414 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01418 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x0141C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01420 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01424 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01428 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x0142C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01434 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01454 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01458 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, 0x0145C >> 2, 0x00000010, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x014A0 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x014A8 >> 2, 0xFFFFFFFF, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x014AC >> 2, 0xFFFFFFFF, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x014B0 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x014B4 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x014A4 >> 2, 0x000E400C, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01580 >> 2, 0x00000000, 3, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x014B8 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- +
- + /* Composition states. */
- + index += _State(Context, index, 0x03008 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- +
- + if (Context->hardware->identity.pixelPipes == 1)
- + {
- + index += _State(Context, index, 0x01460 >> 2, 0x00000000, 8, gcvFALSE, gcvTRUE);
- +
- + index += _State(Context, index, 0x01430 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, 0x01410 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
- + }
- + else
- + {
- + index += _State(Context, index, (0x01460 >> 2) + (0 << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
- +
- + for (i = 0; i < 2; i++)
- + {
- + index += _State(Context, index, (0x01500 >> 2) + (i << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
- + }
- + }
- +
- + if (Context->hardware->identity.pixelPipes > 1 || halti0)
- + {
- + index += _State(Context, index, (0x01480 >> 2) + (0 << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
- + }
- +
- + /* Resolve states. */
- + index += _State(Context, index, 0x01604 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01608 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, 0x0160C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01610 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, 0x01614 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01620 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01630 >> 2, 0x00000000, 2, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01640 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x0163C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x016A0 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x016B4 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _CLOSE_RANGE();
- +
- + if (Context->hardware->identity.pixelPipes > 1)
- + {
- + index += _State(Context, index, (0x016C0 >> 2) + (0 << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
- +
- + index += _State(Context, index, (0x016E0 >> 2) + (0 << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
- +
- + index += _State(Context, index, 0x01700 >> 2, 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvFALSE);
- + }
- +
- + /* Tile status. */
- + index += _State(Context, index, 0x01654 >> 2, 0x00200000, 1, gcvFALSE, gcvFALSE);
- +
- + index += _CLOSE_RANGE();
- + index += _State(Context, index, 0x01658 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, 0x0165C >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, 0x01660 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01664 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, 0x01668 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, 0x0166C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01670 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01674 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x016A4 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, 0x016AC >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x016A8 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01720 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
- + index += _State(Context, index, 0x01740 >> 2, 0x00000000, 8, gcvFALSE, gcvTRUE);
- + index += _State(Context, index, 0x01760 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
- + index += _CLOSE_RANGE();
- +
- + /* Semaphore/stall. */
- + index += _SemaphoreStall(Context, index);
- +#endif
- +
- + /**************************************************************************/
- + /* Link to another address. ***********************************************/
- +
- + Context->linkIndex3D = index;
- +
- + if (buffer != gcvNULL)
- + {
- + buffer[index + 0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + buffer[index + 1]
- + = 0;
- + }
- +
- + index += 2;
- +
- + /* Store the end of the context buffer. */
- + Context->bufferSize = index * gcmSIZEOF(gctUINT32);
- +
- +
- + /**************************************************************************/
- + /* Pipe switch for the case where neither 2D nor 3D are used. *************/
- +
- + /* Store the 3D entry index. */
- + Context->entryOffsetXDFrom2D = index * gcmSIZEOF(gctUINT32);
- +
- + /* Flush 2D pipe. */
- + index += _FlushPipe(Context, index, gcvPIPE_2D);
- +
- + /* Switch to 3D pipe. */
- + index += _SwitchPipe(Context, index, gcvPIPE_3D);
- +
- + /* Store the location of the link. */
- + Context->linkIndexXD = index;
- +
- + if (buffer != gcvNULL)
- + {
- + buffer[index + 0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + buffer[index + 1]
- + = 0;
- + }
- +
- + index += 2;
- +
- +
- + /**************************************************************************/
- + /* Save size for buffer. **************************************************/
- +
- + Context->totalSize = index * gcmSIZEOF(gctUINT32);
- +
- +
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +static gceSTATUS
- +_DestroyContext(
- + IN gckCONTEXT Context
- + )
- +{
- + gceSTATUS status = gcvSTATUS_OK;
- +
- + if (Context != gcvNULL)
- + {
- + gcsCONTEXT_PTR bufferHead;
- +
- + /* Free context buffers. */
- + for (bufferHead = Context->buffer; Context->buffer != gcvNULL;)
- + {
- + /* Get a shortcut to the current buffer. */
- + gcsCONTEXT_PTR buffer = Context->buffer;
- +
- + /* Get the next buffer. */
- + gcsCONTEXT_PTR next = buffer->next;
- +
- + /* Last item? */
- + if (next == bufferHead)
- + {
- + next = gcvNULL;
- + }
- +
- + /* Destroy the signal. */
- + if (buffer->signal != gcvNULL)
- + {
- + gcmkONERROR(gckOS_DestroySignal(
- + Context->os, buffer->signal
- + ));
- +
- + buffer->signal = gcvNULL;
- + }
- +
- + /* Free state delta map. */
- + if (buffer->logical != gcvNULL)
- + {
- +#if gcdVIRTUAL_COMMAND_BUFFER
- + gcmkONERROR(gckEVENT_DestroyVirtualCommandBuffer(
- + Context->hardware->kernel->eventObj,
- + Context->totalSize,
- + buffer->physical,
- + buffer->logical,
- + gcvKERNEL_PIXEL
- + ));
- +
- +#else
- + gcmkONERROR(gckEVENT_FreeContiguousMemory(
- + Context->hardware->kernel->eventObj,
- + Context->totalSize,
- + buffer->physical,
- + buffer->logical,
- + gcvKERNEL_PIXEL
- + ));
- +#endif
- +
- + buffer->logical = gcvNULL;
- + }
- +
- + /* Free context buffer. */
- + gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, buffer));
- +
- + /* Remove from the list. */
- + Context->buffer = next;
- + }
- +
- +#if gcdSECURE_USER
- + /* Free the hint array. */
- + if (Context->hint != gcvNULL)
- + {
- + gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context->hint));
- + }
- +#endif
- + /* Free record array copy. */
- + if (Context->recordArray != gcvNULL)
- + {
- + gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context->recordArray));
- + }
- +
- + /* Free the state mapping. */
- + if (Context->map != gcvNULL)
- + {
- + gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context->map));
- + }
- +
- + /* Mark the gckCONTEXT object as unknown. */
- + Context->object.type = gcvOBJ_UNKNOWN;
- +
- + /* Free the gckCONTEXT object. */
- + gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context));
- + }
- +
- +OnError:
- + return status;
- +}
- +
- +
- +/******************************************************************************\
- +**************************** Context Management API ****************************
- +\******************************************************************************/
- +
- +/******************************************************************************\
- +**
- +** gckCONTEXT_Construct
- +**
- +** Construct a new gckCONTEXT object.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to gckOS object.
- +**
- +** gctUINT32 ProcessID
- +** Current process ID.
- +**
- +** gckHARDWARE Hardware
- +** Pointer to gckHARDWARE object.
- +**
- +** OUTPUT:
- +**
- +** gckCONTEXT * Context
- +** Pointer to a variable thet will receive the gckCONTEXT object
- +** pointer.
- +*/
- +gceSTATUS
- +gckCONTEXT_Construct(
- + IN gckOS Os,
- + IN gckHARDWARE Hardware,
- + IN gctUINT32 ProcessID,
- + OUT gckCONTEXT * Context
- + )
- +{
- + gceSTATUS status;
- + gckCONTEXT context = gcvNULL;
- + gctSIZE_T allocationSize;
- + gctUINT i;
- + gctPOINTER pointer = gcvNULL;
- +
- + gcmkHEADER_ARG("Os=0x%08X Hardware=0x%08X", Os, Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Context != gcvNULL);
- +
- +
- + /**************************************************************************/
- + /* Allocate and initialize basic fields of gckCONTEXT. ********************/
- +
- + /* The context object size. */
- + allocationSize = gcmSIZEOF(struct _gckCONTEXT);
- +
- + /* Allocate the object. */
- + gcmkONERROR(gckOS_Allocate(
- + Os, allocationSize, &pointer
- + ));
- +
- + context = pointer;
- +
- + /* Reset the entire object. */
- + gcmkONERROR(gckOS_ZeroMemory(context, allocationSize));
- +
- + /* Initialize the gckCONTEXT object. */
- + context->object.type = gcvOBJ_CONTEXT;
- + context->os = Os;
- + context->hardware = Hardware;
- +
- +
- +#if defined(VIVANTE_NO_3D)
- + context->entryPipe = gcvPIPE_2D;
- + context->exitPipe = gcvPIPE_2D;
- +#elif gcdCMD_NO_2D_CONTEXT
- + context->entryPipe = gcvPIPE_3D;
- + context->exitPipe = gcvPIPE_3D;
- +#else
- + context->entryPipe
- + = (((((gctUINT32) (context->hardware->identity.chipFeatures)) >> (0 ? 9:9)) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) )
- + ? gcvPIPE_2D
- + : gcvPIPE_3D;
- + context->exitPipe = gcvPIPE_3D;
- +#endif
- +
- + /* Get the command buffer requirements. */
- + gcmkONERROR(gckHARDWARE_QueryCommandBuffer(
- + Hardware,
- + &context->alignment,
- + &context->reservedHead,
- + &context->reservedTail
- + ));
- +
- + /* Mark the context as dirty to force loading of the entire state table
- + the first time. */
- + context->dirty = gcvTRUE;
- +
- +
- + /**************************************************************************/
- + /* Get the size of the context buffer. ************************************/
- +
- + gcmkONERROR(_InitializeContextBuffer(context));
- +
- +
- + /**************************************************************************/
- + /* Compute the size of the record array. **********************************/
- +
- + context->recordArraySize
- + = gcmSIZEOF(gcsSTATE_DELTA_RECORD) * context->stateCount;
- +
- +
- + if (context->stateCount > 0)
- + {
- + /**************************************************************************/
- + /* Allocate and reset the state mapping table. ****************************/
- +
- + /* Allocate the state mapping table. */
- + gcmkONERROR(gckOS_Allocate(
- + Os,
- + gcmSIZEOF(gcsSTATE_MAP) * context->stateCount,
- + &pointer
- + ));
- +
- + context->map = pointer;
- +
- + /* Zero the state mapping table. */
- + gcmkONERROR(gckOS_ZeroMemory(
- + context->map, gcmSIZEOF(gcsSTATE_MAP) * context->stateCount
- + ));
- +
- +
- + /**************************************************************************/
- + /* Allocate the hint array. ***********************************************/
- +
- +#if gcdSECURE_USER
- + /* Allocate hints. */
- + gcmkONERROR(gckOS_Allocate(
- + Os,
- + gcmSIZEOF(gctBOOL) * context->stateCount,
- + &pointer
- + ));
- +
- + context->hint = pointer;
- +#endif
- + }
- +
- + /**************************************************************************/
- + /* Allocate the context and state delta buffers. **************************/
- +
- + for (i = 0; i < gcdCONTEXT_BUFFER_COUNT; i += 1)
- + {
- + /* Allocate a context buffer. */
- + gcsCONTEXT_PTR buffer;
- +
- + /* Allocate the context buffer structure. */
- + gcmkONERROR(gckOS_Allocate(
- + Os,
- + gcmSIZEOF(gcsCONTEXT),
- + &pointer
- + ));
- +
- + buffer = pointer;
- +
- + /* Reset the context buffer structure. */
- + gcmkVERIFY_OK(gckOS_ZeroMemory(
- + buffer, gcmSIZEOF(gcsCONTEXT)
- + ));
- +
- + /* Append to the list. */
- + if (context->buffer == gcvNULL)
- + {
- + buffer->next = buffer;
- + context->buffer = buffer;
- + }
- + else
- + {
- + buffer->next = context->buffer->next;
- + context->buffer->next = buffer;
- + }
- +
- + /* Set the number of delta in the order of creation. */
- +#if gcmIS_DEBUG(gcdDEBUG_CODE)
- + buffer->num = i;
- +#endif
- +
- + /* Create the busy signal. */
- + gcmkONERROR(gckOS_CreateSignal(
- + Os, gcvFALSE, &buffer->signal
- + ));
- +
- + /* Set the signal, buffer is currently not busy. */
- + gcmkONERROR(gckOS_Signal(
- + Os, buffer->signal, gcvTRUE
- + ));
- +
- + /* Create a new physical context buffer. */
- +#if gcdVIRTUAL_COMMAND_BUFFER
- + gcmkONERROR(gckKERNEL_AllocateVirtualCommandBuffer(
- + context->hardware->kernel,
- + gcvFALSE,
- + &context->totalSize,
- + &buffer->physical,
- + &pointer
- + ));
- +
- +#else
- + gcmkONERROR(gckOS_AllocateContiguous(
- + Os,
- + gcvFALSE,
- + &context->totalSize,
- + &buffer->physical,
- + &pointer
- + ));
- +#endif
- +
- + buffer->logical = pointer;
- +
- + /* Set gckEVENT object pointer. */
- + buffer->eventObj = Hardware->kernel->eventObj;
- +
- + /* Set the pointers to the LINK commands. */
- + if (context->linkIndex2D != 0)
- + {
- + buffer->link2D = &buffer->logical[context->linkIndex2D];
- + }
- +
- + if (context->linkIndex3D != 0)
- + {
- + buffer->link3D = &buffer->logical[context->linkIndex3D];
- + }
- +
- + if (context->linkIndexXD != 0)
- + {
- + gctPOINTER xdLink;
- + gctUINT8_PTR xdEntryLogical;
- + gctSIZE_T xdEntrySize;
- + gctSIZE_T linkBytes;
- +
- + /* Determine LINK parameters. */
- + xdLink
- + = &buffer->logical[context->linkIndexXD];
- +
- + xdEntryLogical
- + = (gctUINT8_PTR) buffer->logical
- + + context->entryOffsetXDFrom3D;
- +
- + xdEntrySize
- + = context->bufferSize
- + - context->entryOffsetXDFrom3D;
- +
- + /* Query LINK size. */
- + gcmkONERROR(gckHARDWARE_Link(
- + Hardware, gcvNULL, gcvNULL, 0, &linkBytes
- + ));
- +
- + /* Generate a LINK. */
- + gcmkONERROR(gckHARDWARE_Link(
- + Hardware,
- + xdLink,
- + xdEntryLogical,
- + xdEntrySize,
- + &linkBytes
- + ));
- + }
- + }
- +
- +
- + /**************************************************************************/
- + /* Initialize the context buffers. ****************************************/
- +
- + /* Initialize the current context buffer. */
- + gcmkONERROR(_InitializeContextBuffer(context));
- +
- + /* Make all created contexts equal. */
- + {
- + gcsCONTEXT_PTR currContext, tempContext;
- +
- + /* Set the current context buffer. */
- + currContext = context->buffer;
- +
- + /* Get the next context buffer. */
- + tempContext = currContext->next;
- +
- + /* Loop through all buffers. */
- + while (tempContext != currContext)
- + {
- + if (tempContext == gcvNULL)
- + {
- + gcmkONERROR(gcvSTATUS_NOT_FOUND);
- + }
- +
- + /* Copy the current context. */
- + gckOS_MemCopy(
- + tempContext->logical,
- + currContext->logical,
- + context->totalSize
- + );
- +
- + /* Get the next context buffer. */
- + tempContext = tempContext->next;
- + }
- + }
- +
- + /* Return pointer to the gckCONTEXT object. */
- + *Context = context;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Context=0x%08X", *Context);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Roll back on error. */
- + gcmkVERIFY_OK(_DestroyContext(context));
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/******************************************************************************\
- +**
- +** gckCONTEXT_Destroy
- +**
- +** Destroy a gckCONTEXT object.
- +**
- +** INPUT:
- +**
- +** gckCONTEXT Context
- +** Pointer to an gckCONTEXT object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckCONTEXT_Destroy(
- + IN gckCONTEXT Context
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Context=0x%08X", Context);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Context, gcvOBJ_CONTEXT);
- +
- + /* Destroy the context and all related objects. */
- + status = _DestroyContext(Context);
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return status;
- +}
- +
- +/******************************************************************************\
- +**
- +** gckCONTEXT_Update
- +**
- +** Merge all pending state delta buffers into the current context buffer.
- +**
- +** INPUT:
- +**
- +** gckCONTEXT Context
- +** Pointer to an gckCONTEXT object.
- +**
- +** gctUINT32 ProcessID
- +** Current process ID.
- +**
- +** gcsSTATE_DELTA_PTR StateDelta
- +** Pointer to the state delta.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckCONTEXT_Update(
- + IN gckCONTEXT Context,
- + IN gctUINT32 ProcessID,
- + IN gcsSTATE_DELTA_PTR StateDelta
- + )
- +{
- +#ifndef VIVANTE_NO_3D
- + gceSTATUS status = gcvSTATUS_OK;
- + gcsSTATE_DELTA _stateDelta;
- + gckKERNEL kernel;
- + gcsCONTEXT_PTR buffer;
- + gcsSTATE_MAP_PTR map;
- + gctBOOL needCopy = gcvFALSE;
- + gcsSTATE_DELTA_PTR nDelta;
- + gcsSTATE_DELTA_PTR uDelta = gcvNULL;
- + gcsSTATE_DELTA_PTR kDelta = gcvNULL;
- + gcsSTATE_DELTA_RECORD_PTR record;
- + gcsSTATE_DELTA_RECORD_PTR recordArray = gcvNULL;
- + gctUINT elementCount;
- + gctUINT address;
- + gctUINT32 mask;
- + gctUINT32 data;
- + gctUINT index;
- + gctUINT i, j;
- +
- +#if gcdSECURE_USER
- + gcskSECURE_CACHE_PTR cache;
- +#endif
- +
- + gcmkHEADER_ARG(
- + "Context=0x%08X ProcessID=%d StateDelta=0x%08X",
- + Context, ProcessID, StateDelta
- + );
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Context, gcvOBJ_CONTEXT);
- +
- + /* Get a shortcut to the kernel object. */
- + kernel = Context->hardware->kernel;
- +
- + /* Check wehther we need to copy the structures or not. */
- + gcmkONERROR(gckOS_QueryNeedCopy(Context->os, ProcessID, &needCopy));
- +
- + /* Allocate the copy buffer for the user record array. */
- + if (needCopy && (Context->recordArray == gcvNULL))
- + {
- + /* Allocate the buffer. */
- + gcmkONERROR(gckOS_Allocate(
- + Context->os,
- + Context->recordArraySize,
- + (gctPOINTER *) &Context->recordArray
- + ));
- + }
- +
- + /* Get the current context buffer. */
- + buffer = Context->buffer;
- +
- + /* Wait until the context buffer becomes available; this will
- + also reset the signal and mark the buffer as busy. */
- + gcmkONERROR(gckOS_WaitSignal(
- + Context->os, buffer->signal, gcvINFINITE
- + ));
- +
- +#if gcdSECURE_USER
- + /* Get the cache form the database. */
- + gcmkONERROR(gckKERNEL_GetProcessDBCache(kernel, ProcessID, &cache));
- +#endif
- +
- +#if gcmIS_DEBUG(gcdDEBUG_CODE) && 1 && !defined(VIVANTE_NO_3D)
- + /* Update current context token. */
- + buffer->logical[Context->map[0x0E14].index]
- + = gcmPTR2INT(Context);
- +#endif
- +
- + /* Are there any pending deltas? */
- + if (buffer->deltaCount != 0)
- + {
- + /* Get the state map. */
- + map = Context->map;
- +
- + /* Get the first delta item. */
- + uDelta = buffer->delta;
- +
- + /* Reset the vertex stream count. */
- + elementCount = 0;
- +
- + /* Merge all pending deltas. */
- + for (i = 0; i < buffer->deltaCount; i += 1)
- + {
- + /* Get access to the state delta. */
- + gcmkONERROR(gckKERNEL_OpenUserData(
- + kernel, needCopy,
- + &_stateDelta,
- + uDelta, gcmSIZEOF(gcsSTATE_DELTA),
- + (gctPOINTER *) &kDelta
- + ));
- +
- + /* Get access to the state records. */
- + gcmkONERROR(gckKERNEL_OpenUserData(
- + kernel, needCopy,
- + Context->recordArray,
- + gcmUINT64_TO_PTR(kDelta->recordArray), Context->recordArraySize,
- + (gctPOINTER *) &recordArray
- + ));
- +
- + /* Merge all pending states. */
- + for (j = 0; j < kDelta->recordCount; j += 1)
- + {
- + if (j >= Context->stateCount)
- + {
- + break;
- + }
- +
- + /* Get the current state record. */
- + record = &recordArray[j];
- +
- + /* Get the state address. */
- + address = record->address;
- +
- + /* Make sure the state is a part of the mapping table. */
- + if (address >= Context->stateCount)
- + {
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): State 0x%04X is not mapped.\n",
- + __FUNCTION__, __LINE__,
- + address
- + );
- +
- + continue;
- + }
- +
- + /* Get the state index. */
- + index = map[address].index;
- +
- + /* Skip the state if not mapped. */
- + if (index == 0)
- + {
- +#if gcdDEBUG
- + if ((address != 0x0594)
- + && (address != 0x0E00)
- + && (address != 0x0E03)
- + )
- + {
- +#endif
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): State 0x%04X is not mapped.\n",
- + __FUNCTION__, __LINE__,
- + address
- + );
- +#if gcdDEBUG
- + }
- +#endif
- + continue;
- + }
- +
- + /* Get the data mask. */
- + mask = record->mask;
- +
- + /* Masked states that are being completly reset or regular states. */
- + if ((mask == 0) || (mask == ~0U))
- + {
- + /* Get the new data value. */
- + data = record->data;
- +
- + /* Process special states. */
- + if (address == 0x0595)
- + {
- + /* Force auto-disable to be disabled. */
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 13:13) - (0 ? 13:13) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:13) - (0 ? 13:13) + 1))))))) << (0 ? 13:13))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 13:13) - (0 ? 13:13) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:13) - (0 ? 13:13) + 1))))))) << (0 ? 13:13)));
- + }
- +
- +#if gcdSECURE_USER
- + /* Do we need to convert the logical address? */
- + if (Context->hint[address])
- + {
- + /* Map handle into physical address. */
- + gcmkONERROR(gckKERNEL_MapLogicalToPhysical(
- + kernel, cache, (gctPOINTER) &data
- + ));
- + }
- +#endif
- +
- + /* Set new data. */
- + buffer->logical[index] = data;
- + }
- +
- + /* Masked states that are being set partially. */
- + else
- + {
- + buffer->logical[index]
- + = (~mask & buffer->logical[index])
- + | (mask & record->data);
- + }
- + }
- +
- + /* Get the element count. */
- + if (kDelta->elementCount != 0)
- + {
- + elementCount = kDelta->elementCount;
- + }
- +
- + /* Dereference delta. */
- + kDelta->refCount -= 1;
- + gcmkASSERT(kDelta->refCount >= 0);
- +
- + /* Get the next state delta. */
- + nDelta = gcmUINT64_TO_PTR(kDelta->next);
- +
- + /* Get access to the state records. */
- + gcmkONERROR(gckKERNEL_CloseUserData(
- + kernel, needCopy,
- + gcvFALSE,
- + gcmUINT64_TO_PTR(kDelta->recordArray), Context->recordArraySize,
- + (gctPOINTER *) &recordArray
- + ));
- +
- + /* Close access to the current state delta. */
- + gcmkONERROR(gckKERNEL_CloseUserData(
- + kernel, needCopy,
- + gcvTRUE,
- + uDelta, gcmSIZEOF(gcsSTATE_DELTA),
- + (gctPOINTER *) &kDelta
- + ));
- +
- + /* Update the user delta pointer. */
- + uDelta = nDelta;
- + }
- +
- + /* Hardware disables all input streams when the stream 0 is programmed,
- + it then reenables those streams that were explicitely programmed by
- + the software. Because of this we cannot program the entire array of
- + values, otherwise we'll get all streams reenabled, but rather program
- + only those that are actully needed by the software. */
- + if (elementCount != 0)
- + {
- + gctUINT base;
- + gctUINT nopCount;
- + gctUINT32_PTR nop;
- + gctUINT fe2vsCount = 12;
- +
- + if ((((((gctUINT32) (Context->hardware->identity.chipMinorFeatures1)) >> (0 ? 23:23)) & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1)))))) ))
- + {
- + fe2vsCount = 16;
- + }
- +
- + /* Determine the base index of the vertex stream array. */
- + base = map[0x0180].index;
- +
- + /* Set the proper state count. */
- + buffer->logical[base - 1]
- + = ((((gctUINT32) (buffer->logical[base - 1])) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (elementCount ) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + /* Determine the number of NOP commands. */
- + nopCount
- + = (fe2vsCount / 2)
- + - (elementCount / 2);
- +
- + /* Determine the location of the first NOP. */
- + nop = &buffer->logical[base + (elementCount | 1)];
- +
- + /* Fill the unused space with NOPs. */
- + for (i = 0; i < nopCount; i += 1)
- + {
- + if (nop >= buffer->logical + Context->totalSize)
- + {
- + break;
- + }
- +
- + /* Generate a NOP command. */
- + *nop = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
- +
- + /* Advance. */
- + nop += 2;
- + }
- + }
- +
- + /* Reset pending deltas. */
- + buffer->deltaCount = 0;
- + buffer->delta = gcvNULL;
- + }
- +
- + /* Set state delta user pointer. */
- + uDelta = StateDelta;
- +
- + /* Get access to the state delta. */
- + gcmkONERROR(gckKERNEL_OpenUserData(
- + kernel, needCopy,
- + &_stateDelta,
- + uDelta, gcmSIZEOF(gcsSTATE_DELTA),
- + (gctPOINTER *) &kDelta
- + ));
- +
- + /* State delta cannot be attached to anything yet. */
- + if (kDelta->refCount != 0)
- + {
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): kDelta->refCount = %d (has to be 0).\n",
- + __FUNCTION__, __LINE__,
- + kDelta->refCount
- + );
- + }
- +
- + /* Attach to all contexts. */
- + buffer = Context->buffer;
- +
- + do
- + {
- + /* Attach to the context if nothing is attached yet. If a delta
- + is allready attached, all we need to do is to increment
- + the number of deltas in the context. */
- + if (buffer->delta == gcvNULL)
- + {
- + buffer->delta = uDelta;
- + }
- +
- + /* Update reference count. */
- + kDelta->refCount += 1;
- +
- + /* Update counters. */
- + buffer->deltaCount += 1;
- +
- + /* Get the next context buffer. */
- + buffer = buffer->next;
- +
- + if (buffer == gcvNULL)
- + {
- + gcmkONERROR(gcvSTATUS_NOT_FOUND);
- + }
- + }
- + while (Context->buffer != buffer);
- +
- + /* Close access to the current state delta. */
- + gcmkONERROR(gckKERNEL_CloseUserData(
- + kernel, needCopy,
- + gcvTRUE,
- + uDelta, gcmSIZEOF(gcsSTATE_DELTA),
- + (gctPOINTER *) &kDelta
- + ));
- +
- + /* Schedule an event to mark the context buffer as available. */
- + gcmkONERROR(gckEVENT_Signal(
- + buffer->eventObj, buffer->signal, gcvKERNEL_PIXEL
- + ));
- +
- + /* Advance to the next context buffer. */
- + Context->buffer = buffer->next;
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Get access to the state records. */
- + if (kDelta != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckKERNEL_CloseUserData(
- + kernel, needCopy,
- + gcvFALSE,
- + gcmUINT64_TO_PTR(kDelta->recordArray), Context->recordArraySize,
- + (gctPOINTER *) &recordArray
- + ));
- + }
- +
- + /* Close access to the current state delta. */
- + gcmkVERIFY_OK(gckKERNEL_CloseUserData(
- + kernel, needCopy,
- + gcvTRUE,
- + uDelta, gcmSIZEOF(gcsSTATE_DELTA),
- + (gctPOINTER *) &kDelta
- + ));
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +#else
- + return gcvSTATUS_OK;
- +#endif
- +}
- +
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.h linux-3.14.35/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.h 2015-03-08 14:27:37.621684501 -0500
- @@ -0,0 +1,157 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_kernel_context_h_
- +#define __gc_hal_kernel_context_h_
- +
- +#include "gc_hal_kernel_buffer.h"
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +/* Maps state locations within the context buffer. */
- +typedef struct _gcsSTATE_MAP * gcsSTATE_MAP_PTR;
- +typedef struct _gcsSTATE_MAP
- +{
- + /* Index of the state in the context buffer. */
- + gctUINT index;
- +
- + /* State mask. */
- + gctUINT32 mask;
- +}
- +gcsSTATE_MAP;
- +
- +/* Context buffer. */
- +typedef struct _gcsCONTEXT * gcsCONTEXT_PTR;
- +typedef struct _gcsCONTEXT
- +{
- + /* For debugging: the number of context buffer in the order of creation. */
- +#if gcmIS_DEBUG(gcdDEBUG_CODE)
- + gctUINT num;
- +#endif
- +
- + /* Pointer to gckEVENT object. */
- + gckEVENT eventObj;
- +
- + /* Context busy signal. */
- + gctSIGNAL signal;
- +
- + /* Physical address of the context buffer. */
- + gctPHYS_ADDR physical;
- +
- + /* Logical address of the context buffer. */
- + gctUINT32_PTR logical;
- +
- + /* Pointer to the LINK commands. */
- + gctPOINTER link2D;
- + gctPOINTER link3D;
- +
- + /* The number of pending state deltas. */
- + gctUINT deltaCount;
- +
- + /* Pointer to the first delta to be applied. */
- + gcsSTATE_DELTA_PTR delta;
- +
- + /* Next context buffer. */
- + gcsCONTEXT_PTR next;
- +}
- +gcsCONTEXT;
- +
- +/* gckCONTEXT structure that hold the current context. */
- +struct _gckCONTEXT
- +{
- + /* Object. */
- + gcsOBJECT object;
- +
- + /* Pointer to gckOS object. */
- + gckOS os;
- +
- + /* Pointer to gckHARDWARE object. */
- + gckHARDWARE hardware;
- +
- + /* Command buffer alignment. */
- + gctSIZE_T alignment;
- + gctSIZE_T reservedHead;
- + gctSIZE_T reservedTail;
- +
- + /* Context buffer metrics. */
- + gctSIZE_T stateCount;
- + gctSIZE_T totalSize;
- + gctSIZE_T bufferSize;
- + gctUINT32 linkIndex2D;
- + gctUINT32 linkIndex3D;
- + gctUINT32 linkIndexXD;
- + gctUINT32 entryOffset3D;
- + gctUINT32 entryOffsetXDFrom2D;
- + gctUINT32 entryOffsetXDFrom3D;
- +
- + /* Dirty flags. */
- + gctBOOL dirty;
- + gctBOOL dirty2D;
- + gctBOOL dirty3D;
- + gcsCONTEXT_PTR dirtyBuffer;
- +
- + /* State mapping. */
- + gcsSTATE_MAP_PTR map;
- +
- + /* List of context buffers. */
- + gcsCONTEXT_PTR buffer;
- +
- + /* A copy of the user record array. */
- + gctUINT recordArraySize;
- + gcsSTATE_DELTA_RECORD_PTR recordArray;
- +
- + /* Requested pipe select for context. */
- + gcePIPE_SELECT entryPipe;
- + gcePIPE_SELECT exitPipe;
- +
- + /* Variables used for building state buffer. */
- + gctUINT32 lastAddress;
- + gctSIZE_T lastSize;
- + gctUINT32 lastIndex;
- + gctBOOL lastFixed;
- +
- + /* Hint array. */
- +#if gcdSECURE_USER
- + gctBOOL_PTR hint;
- +#endif
- +
- +#if VIVANTE_PROFILER_CONTEXT
- + gcsPROFILER_COUNTERS latestProfiler;
- + gcsPROFILER_COUNTERS histroyProfiler;
- + gctUINT32 prevVSInstCount;
- + gctUINT32 prevVSBranchInstCount;
- + gctUINT32 prevVSTexInstCount;
- + gctUINT32 prevVSVertexCount;
- + gctUINT32 prevPSInstCount;
- + gctUINT32 prevPSBranchInstCount;
- + gctUINT32 prevPSTexInstCount;
- + gctUINT32 prevPSPixelCount;
- +#endif
- +};
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* __gc_hal_kernel_context_h_ */
- +
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c linux-3.14.35/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c 2015-03-08 14:27:37.625684501 -0500
- @@ -0,0 +1,7280 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal.h"
- +#include "gc_hal_kernel.h"
- +#if VIVANTE_PROFILER_CONTEXT
- +#include "gc_hal_kernel_context.h"
- +#endif
- +
- +#define _GC_OBJ_ZONE gcvZONE_HARDWARE
- +
- +typedef struct _gcsiDEBUG_REGISTERS * gcsiDEBUG_REGISTERS_PTR;
- +typedef struct _gcsiDEBUG_REGISTERS
- +{
- + gctSTRING module;
- + gctUINT index;
- + gctUINT shift;
- + gctUINT data;
- + gctUINT count;
- + gctUINT32 signature;
- +}
- +gcsiDEBUG_REGISTERS;
- +
- +extern int gpu3DMinClock;
- +/******************************************************************************\
- +********************************* Support Code *********************************
- +\******************************************************************************/
- +static gceSTATUS
- +_ResetGPU(
- + IN gckHARDWARE Hardware,
- + IN gckOS Os,
- + IN gceCORE Core
- + );
- +
- +static gceSTATUS
- +_IdentifyHardware(
- + IN gckOS Os,
- + IN gceCORE Core,
- + OUT gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
- + )
- +{
- + gceSTATUS status;
- +
- + gctUINT32 chipIdentity;
- +
- + gctUINT32 streamCount = 0;
- + gctUINT32 registerMax = 0;
- + gctUINT32 threadCount = 0;
- + gctUINT32 shaderCoreCount = 0;
- + gctUINT32 vertexCacheSize = 0;
- + gctUINT32 vertexOutputBufferSize = 0;
- + gctUINT32 pixelPipes = 0;
- + gctUINT32 instructionCount = 0;
- + gctUINT32 numConstants = 0;
- + gctUINT32 bufferSize = 0;
- + gctUINT32 varyingsCount = 0;
- + gctBOOL useHZ;
- +
- + gcmkHEADER_ARG("Os=0x%x", Os);
- +
- + /***************************************************************************
- + ** Get chip ID and revision.
- + */
- +
- + /* Read chip identity register. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Os, Core,
- + 0x00018,
- + &chipIdentity));
- +
- + /* Special case for older graphic cores. */
- + if (((((gctUINT32) (chipIdentity)) >> (0 ? 31:24) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))))
- + {
- + Identity->chipModel = gcv500;
- + Identity->chipRevision = (((((gctUINT32) (chipIdentity)) >> (0 ? 15:12)) & ((gctUINT32) ((((1 ? 15:12) - (0 ? 15:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:12) - (0 ? 15:12) + 1)))))) );
- + }
- +
- + else
- + {
- + /* Read chip identity register. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Os, Core,
- + 0x00020,
- + (gctUINT32_PTR) &Identity->chipModel));
- +
- + /* !!!! HACK ALERT !!!! */
- + /* Because people change device IDs without letting software know
- + ** about it - here is the hack to make it all look the same. Only
- + ** for GC400 family. Next time - TELL ME!!! */
- + if (((Identity->chipModel & 0xFF00) == 0x0400)
- + && (Identity->chipModel != 0x0420))
- + {
- + Identity->chipModel = (gceCHIPMODEL) (Identity->chipModel & 0x0400);
- + }
- +
- + /* Read CHIP_REV register. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Os, Core,
- + 0x00024,
- + &Identity->chipRevision));
- +
- + if ((Identity->chipModel == gcv300)
- + && (Identity->chipRevision == 0x2201)
- + )
- + {
- + gctUINT32 chipDate;
- + gctUINT32 chipTime;
- +
- + /* Read date and time registers. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Os, Core,
- + 0x00028,
- + &chipDate));
- +
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Os, Core,
- + 0x0002C,
- + &chipTime));
- +
- + if ((chipDate == 0x20080814) && (chipTime == 0x12051100))
- + {
- + /* This IP has an ECO; put the correct revision in it. */
- + Identity->chipRevision = 0x1051;
- + }
- + }
- + }
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Identity: chipModel=%X",
- + Identity->chipModel);
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Identity: chipRevision=%X",
- + Identity->chipRevision);
- +
- +
- + /***************************************************************************
- + ** Get chip features.
- + */
- +
- + /* Read chip feature register. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Os, Core,
- + 0x0001C,
- + &Identity->chipFeatures));
- +
- +#ifndef VIVANTE_NO_3D
- + /* Disable fast clear on GC700. */
- + if (Identity->chipModel == gcv700)
- + {
- + Identity->chipFeatures
- + = ((((gctUINT32) (Identity->chipFeatures)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
- + }
- +#endif
- +
- + if (((Identity->chipModel == gcv500) && (Identity->chipRevision < 2))
- + || ((Identity->chipModel == gcv300) && (Identity->chipRevision < 0x2000))
- + )
- + {
- + /* GC500 rev 1.x and GC300 rev < 2.0 doesn't have these registers. */
- + Identity->chipMinorFeatures = 0;
- + Identity->chipMinorFeatures1 = 0;
- + Identity->chipMinorFeatures2 = 0;
- + Identity->chipMinorFeatures3 = 0;
- + Identity->chipMinorFeatures4 = 0;
- + }
- + else
- + {
- + /* Read chip minor feature register #0. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Os, Core,
- + 0x00034,
- + &Identity->chipMinorFeatures));
- +
- + if (((((gctUINT32) (Identity->chipMinorFeatures)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))))
- + )
- + {
- + /* Read chip minor featuress register #1. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Os, Core,
- + 0x00074,
- + &Identity->chipMinorFeatures1));
- +
- + /* Read chip minor featuress register #2. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Os, Core,
- + 0x00084,
- + &Identity->chipMinorFeatures2));
- +
- + /*Identity->chipMinorFeatures2 &= ~(0x1 << 3);*/
- +
- + /* Read chip minor featuress register #1. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Os, Core,
- + 0x00088,
- + &Identity->chipMinorFeatures3));
- +
- + /*The BG2 chip has no compression supertiled, and the bit of GCMinorFeature3BugFixes15 is n/a*/
- + if(Identity->chipModel == gcv1000 && Identity->chipRevision == 0x5036)
- + {
- + Identity->chipMinorFeatures3
- + = ((((gctUINT32) (Identity->chipMinorFeatures3)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
- + Identity->chipMinorFeatures3
- + = ((((gctUINT32) (Identity->chipMinorFeatures3)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1))))))) << (0 ? 27:27))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1))))))) << (0 ? 27:27)));
- + }
- +
- + /* Read chip minor featuress register #4. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Os, Core,
- + 0x00094,
- + &Identity->chipMinorFeatures4));
- + }
- + else
- + {
- + /* Chip doesn't has minor features register #1 or 2 or 3 or 4. */
- + Identity->chipMinorFeatures1 = 0;
- + Identity->chipMinorFeatures2 = 0;
- + Identity->chipMinorFeatures3 = 0;
- + Identity->chipMinorFeatures4 = 0;
- + }
- + }
- +
- + /* Get the Supertile layout in the hardware. */
- + if (((((gctUINT32) (Identity->chipMinorFeatures3)) >> (0 ? 26:26) & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1)))))))
- + || ((((gctUINT32) (Identity->chipMinorFeatures3)) >> (0 ? 8:8) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1))))))))
- + {
- + Identity->superTileMode = 2;
- + }
- + else if (((((gctUINT32) (Identity->chipMinorFeatures)) >> (0 ? 27:27) & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1))))))))
- + {
- + Identity->superTileMode = 1;
- + }
- + else
- + {
- + Identity->superTileMode = 0;
- + }
- +
- + /* Exception for GC1000, revision 5035 & GC800, revision 4612 */
- + if (((Identity->chipModel == gcv1000) && ((Identity->chipRevision == 0x5035)
- + || (Identity->chipRevision == 0x5036)
- + || (Identity->chipRevision == 0x5037)))
- + || ((Identity->chipModel == gcv800) && (Identity->chipRevision == 0x4612))
- + || ((Identity->chipModel == gcv860) && (Identity->chipRevision == 0x4647)))
- + {
- + Identity->superTileMode = 1;
- + }
- +
- + if (Identity->chipModel == gcv4000 && Identity->chipRevision == 0x5245)
- + {
- + useHZ = ((((gctUINT32) (Identity->chipMinorFeatures3)) >> (0 ? 26:26) & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1)))))))
- + || ((((gctUINT32) (Identity->chipMinorFeatures3)) >> (0 ? 8:8) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1)))))));
- + }
- + else
- + {
- + useHZ = gcvFALSE;
- + }
- +
- + if (useHZ)
- + {
- + /* Disable EZ. */
- + Identity->chipFeatures
- + = ((((gctUINT32) (Identity->chipFeatures)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16)));
- + }
- +
- + /* Disable HZ when EZ is present for older chips. */
- + else if (!((((gctUINT32) (Identity->chipFeatures)) >> (0 ? 16:16) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))))
- + {
- + /* Disable HIERARCHICAL_Z. */
- + Identity->chipMinorFeatures
- + = ((((gctUINT32) (Identity->chipMinorFeatures)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1))))))) << (0 ? 27:27))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1))))))) << (0 ? 27:27)));
- + }
- +
- + /* Disable rectangle primitive when chip is gc880_5_1_0_rc6*/
- + if ((Identity->chipModel == gcv880) && (Identity->chipRevision == 0x5106))
- + {
- + /* Disable rectangle primitive. */
- + Identity->chipMinorFeatures2
- + = ((((gctUINT32) (Identity->chipMinorFeatures2)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
- + }
- +
- + if ((Identity->chipModel == gcv800) && (Identity->chipRevision == 0x4605))
- + {
- + /* Correct feature bit: RTL does not have such feature. */
- + Identity->chipFeatures
- + = ((((gctUINT32) (Identity->chipFeatures)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)));
- + }
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Identity: chipFeatures=0x%08X",
- + Identity->chipFeatures);
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Identity: chipMinorFeatures=0x%08X",
- + Identity->chipMinorFeatures);
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Identity: chipMinorFeatures1=0x%08X",
- + Identity->chipMinorFeatures1);
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Identity: chipMinorFeatures2=0x%08X",
- + Identity->chipMinorFeatures2);
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Identity: chipMinorFeatures3=0x%08X",
- + Identity->chipMinorFeatures3);
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Identity: chipMinorFeatures4=0x%08X",
- + Identity->chipMinorFeatures4);
- +
- + /***************************************************************************
- + ** Get chip specs.
- + */
- +
- + if (((((gctUINT32) (Identity->chipMinorFeatures)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))))
- + {
- + gctUINT32 specs, specs2, specs3;
- +
- + /* Read gcChipSpecs register. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Os, Core,
- + 0x00048,
- + &specs));
- +
- + /* Extract the fields. */
- + streamCount = (((((gctUINT32) (specs)) >> (0 ? 3:0)) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1)))))) );
- + registerMax = (((((gctUINT32) (specs)) >> (0 ? 7:4)) & ((gctUINT32) ((((1 ? 7:4) - (0 ? 7:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:4) - (0 ? 7:4) + 1)))))) );
- + threadCount = (((((gctUINT32) (specs)) >> (0 ? 11:8)) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1)))))) );
- + shaderCoreCount = (((((gctUINT32) (specs)) >> (0 ? 24:20)) & ((gctUINT32) ((((1 ? 24:20) - (0 ? 24:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:20) - (0 ? 24:20) + 1)))))) );
- + vertexCacheSize = (((((gctUINT32) (specs)) >> (0 ? 16:12)) & ((gctUINT32) ((((1 ? 16:12) - (0 ? 16:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:12) - (0 ? 16:12) + 1)))))) );
- + vertexOutputBufferSize = (((((gctUINT32) (specs)) >> (0 ? 31:28)) & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1)))))) );
- + pixelPipes = (((((gctUINT32) (specs)) >> (0 ? 27:25)) & ((gctUINT32) ((((1 ? 27:25) - (0 ? 27:25) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:25) - (0 ? 27:25) + 1)))))) );
- +
- + /* Read gcChipSpecs2 register. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Os, Core,
- + 0x00080,
- + &specs2));
- +
- + instructionCount = (((((gctUINT32) (specs2)) >> (0 ? 15:8)) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1)))))) );
- + numConstants = (((((gctUINT32) (specs2)) >> (0 ? 31:16)) & ((gctUINT32) ((((1 ? 31:16) - (0 ? 31:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:16) - (0 ? 31:16) + 1)))))) );
- + bufferSize = (((((gctUINT32) (specs2)) >> (0 ? 7:0)) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1)))))) );
- +
- + /* Read gcChipSpecs3 register. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Os, Core,
- + 0x0008C,
- + &specs3));
- +
- + varyingsCount = (((((gctUINT32) (specs3)) >> (0 ? 8:4)) & ((gctUINT32) ((((1 ? 8:4) - (0 ? 8:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:4) - (0 ? 8:4) + 1)))))) );
- + }
- +
- + /* Get the number of pixel pipes. */
- + Identity->pixelPipes = gcmMAX(pixelPipes, 1);
- +
- + /* Get the stream count. */
- + Identity->streamCount = (streamCount != 0)
- + ? streamCount
- + : (Identity->chipModel >= gcv1000) ? 4 : 1;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Specs: streamCount=%u%s",
- + Identity->streamCount,
- + (streamCount == 0) ? " (default)" : "");
- +
- + /* Get the vertex output buffer size. */
- + Identity->vertexOutputBufferSize = (vertexOutputBufferSize != 0)
- + ? 1 << vertexOutputBufferSize
- + : (Identity->chipModel == gcv400)
- + ? (Identity->chipRevision < 0x4000) ? 512
- + : (Identity->chipRevision < 0x4200) ? 256
- + : 128
- + : (Identity->chipModel == gcv530)
- + ? (Identity->chipRevision < 0x4200) ? 512
- + : 128
- + : 512;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Specs: vertexOutputBufferSize=%u%s",
- + Identity->vertexOutputBufferSize,
- + (vertexOutputBufferSize == 0) ? " (default)" : "");
- +
- + /* Get the maximum number of threads. */
- + Identity->threadCount = (threadCount != 0)
- + ? 1 << threadCount
- + : (Identity->chipModel == gcv400) ? 64
- + : (Identity->chipModel == gcv500) ? 128
- + : (Identity->chipModel == gcv530) ? 128
- + : 256;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Specs: threadCount=%u%s",
- + Identity->threadCount,
- + (threadCount == 0) ? " (default)" : "");
- +
- + /* Get the number of shader cores. */
- + Identity->shaderCoreCount = (shaderCoreCount != 0)
- + ? shaderCoreCount
- + : (Identity->chipModel >= gcv1000) ? 2
- + : 1;
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Specs: shaderCoreCount=%u%s",
- + Identity->shaderCoreCount,
- + (shaderCoreCount == 0) ? " (default)" : "");
- +
- + /* Get the vertex cache size. */
- + Identity->vertexCacheSize = (vertexCacheSize != 0)
- + ? vertexCacheSize
- + : 8;
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Specs: vertexCacheSize=%u%s",
- + Identity->vertexCacheSize,
- + (vertexCacheSize == 0) ? " (default)" : "");
- +
- + /* Get the maximum number of temporary registers. */
- + Identity->registerMax = (registerMax != 0)
- + /* Maximum of registerMax/4 registers are accessible to 1 shader */
- + ? 1 << registerMax
- + : (Identity->chipModel == gcv400) ? 32
- + : 64;
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Specs: registerMax=%u%s",
- + Identity->registerMax,
- + (registerMax == 0) ? " (default)" : "");
- +
- + /* Get the instruction count. */
- + Identity->instructionCount = (instructionCount == 0) ? 256
- + : (instructionCount == 1) ? 1024
- + : (instructionCount == 2) ? 2048
- + : (instructionCount == 0xFF) ? 512
- + : 256;
- +
- + if (Identity->instructionCount == 256)
- + {
- + if ((Identity->chipModel == gcv2000 && Identity->chipRevision == 0x5108)
- + || Identity->chipModel == gcv880)
- + {
- + Identity->instructionCount = 512;
- + }
- + }
- +
- + if (((((gctUINT32) (Identity->chipMinorFeatures3)) >> (0 ? 3:3) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))))
- + {
- + Identity->instructionCount = 512;
- + }
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Specs: instructionCount=%u%s",
- + Identity->instructionCount,
- + (instructionCount == 0) ? " (default)" : "");
- +
- + /* Get the number of constants. */
- + Identity->numConstants = (numConstants == 0) ? 168 : numConstants;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Specs: numConstants=%u%s",
- + Identity->numConstants,
- + (numConstants == 0) ? " (default)" : "");
- +
- + /* Get the buffer size. */
- + Identity->bufferSize = bufferSize;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Specs: bufferSize=%u%s",
- + Identity->bufferSize,
- + (bufferSize == 0) ? " (default)" : "");
- +
- +
- + if (varyingsCount != 0)
- + {
- + /* Bug 4480. */
- + /*Identity->varyingsCount = varyingsCount;*/
- + Identity->varyingsCount = 12;
- + }
- + else if (((((gctUINT32) (Identity->chipMinorFeatures1)) >> (0 ? 23:23) & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1))))))))
- + {
- + Identity->varyingsCount = 12;
- + }
- + else
- + {
- + Identity->varyingsCount = 8;
- + }
- +
- + /* For some cores, it consumes two varying for position, so the max varying vectors should minus one. */
- + if ((Identity->chipModel == gcv4000 && Identity->chipRevision == 0x5222) ||
- + (Identity->chipModel == gcv4000 && Identity->chipRevision == 0x5208) ||
- + ((Identity->chipModel == gcv2100 || Identity->chipModel == gcv2000) && Identity->chipRevision == 0x5108) ||
- + (Identity->chipModel == gcv880 && (Identity->chipRevision == 0x5107 || Identity->chipRevision == 0x5106)))
- + {
- + Identity->varyingsCount -= 1;
- + }
- +
- + Identity->chip2DControl = 0;
- + if (Identity->chipModel == gcv320)
- + {
- + gctUINT32 data;
- +
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Os,
- + Core,
- + 0x0002C,
- + &data));
- +
- + if ((data != 33956864) &&
- + ((Identity->chipRevision == 0x5007) ||
- + (Identity->chipRevision == 0x5220)))
- + {
- + Identity->chip2DControl |= 0xFF &
- + (Identity->chipRevision == 0x5220 ? 8 :
- + (Identity->chipRevision == 0x5007 ? 12 : 0));
- + }
- +
- + if (Identity->chipRevision == 0x5007)
- + {
- + /* Disable splitting rectangle. */
- + Identity->chip2DControl |= 0x100;
- +
- + /* Enable 2D Flush. */
- + Identity->chip2DControl |= 0x200;
- + }
- + }
- +
- + /* Success. */
- + gcmkFOOTER();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +#if gcdPOWEROFF_TIMEOUT
- +void
- +_PowerTimerFunction(
- + gctPOINTER Data
- + )
- +{
- + gckHARDWARE hardware = (gckHARDWARE)Data;
- + gcmkVERIFY_OK(
- + gckHARDWARE_SetPowerManagementState(hardware, gcvPOWER_OFF_TIMEOUT));
- +}
- +#endif
- +
- +static gceSTATUS
- +_VerifyDMA(
- + IN gckOS Os,
- + IN gceCORE Core,
- + gctUINT32_PTR Address1,
- + gctUINT32_PTR Address2,
- + gctUINT32_PTR State1,
- + gctUINT32_PTR State2
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 i;
- +
- + gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x660, State1));
- + gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x664, Address1));
- +
- + for (i = 0; i < 500; i += 1)
- + {
- + gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x660, State2));
- + gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x664, Address2));
- +
- + if (*Address1 != *Address2)
- + {
- + break;
- + }
- +
- + if (*State1 != *State2)
- + {
- + break;
- + }
- + }
- +
- +OnError:
- + return status;
- +}
- +
- +static gceSTATUS
- +_DumpDebugRegisters(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gcsiDEBUG_REGISTERS_PTR Descriptor
- + )
- +{
- + gceSTATUS status = gcvSTATUS_OK;
- + gctUINT32 select;
- + gctUINT32 data = 0;
- + gctUINT i;
- +
- + gcmkHEADER_ARG("Os=0x%X Descriptor=0x%X", Os, Descriptor);
- +
- + gcmkPRINT_N(4, " %s debug registers:\n", Descriptor->module);
- +
- + for (i = 0; i < Descriptor->count; i += 1)
- + {
- + select = i << Descriptor->shift;
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, Descriptor->index, select));
- +#if gcdFPGA_BUILD
- + gcmkONERROR(gckOS_Delay(Os, 1000));
- +#endif
- + gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, Descriptor->data, &data));
- +
- + gcmkPRINT_N(12, " [0x%02X] 0x%08X\n", i, data);
- + }
- +
- + select = 0xF << Descriptor->shift;
- +
- + for (i = 0; i < 500; i += 1)
- + {
- + gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, Descriptor->index, select));
- +#if gcdFPGA_BUILD
- + gcmkONERROR(gckOS_Delay(Os, 1000));
- +#endif
- + gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, Descriptor->data, &data));
- +
- + if (data == Descriptor->signature)
- + {
- + break;
- + }
- + }
- +
- + if (i == 500)
- + {
- + gcmkPRINT_N(4, " failed to obtain the signature (read 0x%08X).\n", data);
- + }
- + else
- + {
- + gcmkPRINT_N(8, " signature = 0x%08X (%d read attempt(s))\n", data, i + 1);
- + }
- +
- +OnError:
- + /* Return the error. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +static gceSTATUS
- +_IsGPUPresent(
- + IN gckHARDWARE Hardware
- + )
- +{
- + gceSTATUS status;
- + gcsHAL_QUERY_CHIP_IDENTITY identity;
- + gctUINT32 control;
- +
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00000,
- + &control));
- +
- + control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)));
- + control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00000,
- + control));
- +
- + /* Identify the hardware. */
- + gcmkONERROR(_IdentifyHardware(Hardware->os,
- + Hardware->core,
- + &identity));
- +
- + /* Check if these are the same values as saved before. */
- + if ((Hardware->identity.chipModel != identity.chipModel)
- + || (Hardware->identity.chipRevision != identity.chipRevision)
- + || (Hardware->identity.chipFeatures != identity.chipFeatures)
- + || (Hardware->identity.chipMinorFeatures != identity.chipMinorFeatures)
- + || (Hardware->identity.chipMinorFeatures1 != identity.chipMinorFeatures1)
- + || (Hardware->identity.chipMinorFeatures2 != identity.chipMinorFeatures2)
- + )
- + {
- + gcmkPRINT("[galcore]: GPU is not present.");
- + gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the error. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +_FlushCache(
- + gckHARDWARE Hardware,
- + gckCOMMAND Command
- + )
- +{
- + gceSTATUS status;
- + gctSIZE_T bytes, requested;
- + gctPOINTER buffer;
- +
- + /* Get the size of the flush command. */
- + gcmkONERROR(gckHARDWARE_Flush(Hardware,
- + gcvFLUSH_ALL,
- + gcvNULL,
- + &requested));
- +
- + /* Reserve space in the command queue. */
- + gcmkONERROR(gckCOMMAND_Reserve(Command,
- + requested,
- + &buffer,
- + &bytes));
- +
- + /* Append a flush. */
- + gcmkONERROR(gckHARDWARE_Flush(
- + Hardware, gcvFLUSH_ALL, buffer, &bytes
- + ));
- +
- + /* Execute the command queue. */
- + gcmkONERROR(gckCOMMAND_Execute(Command, requested));
- +
- + return gcvSTATUS_OK;
- +
- +OnError:
- + return status;
- +}
- +
- +/******************************************************************************\
- +****************************** gckHARDWARE API code *****************************
- +\******************************************************************************/
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_Construct
- +**
- +** Construct a new gckHARDWARE object.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an initialized gckOS object.
- +**
- +** gceCORE Core
- +** Specified core.
- +**
- +** OUTPUT:
- +**
- +** gckHARDWARE * Hardware
- +** Pointer to a variable that will hold the pointer to the gckHARDWARE
- +** object.
- +*/
- +gceSTATUS
- +gckHARDWARE_Construct(
- + IN gckOS Os,
- + IN gceCORE Core,
- + OUT gckHARDWARE * Hardware
- + )
- +{
- + gceSTATUS status;
- + gckHARDWARE hardware = gcvNULL;
- + gctUINT16 data = 0xff00;
- + gctUINT32 axi_ot;
- + gctPOINTER pointer = gcvNULL;
- +
- + gcmkHEADER_ARG("Os=0x%x", Os);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
- +
- + /* Enable the GPU. */
- + gcmkONERROR(gckOS_SetGPUPower(Os, Core, gcvTRUE, gcvTRUE));
- + gcmkONERROR(gckOS_WriteRegisterEx(Os,
- + Core,
- + 0x00000,
- + 0x00000900));
- +
- + /* Allocate the gckHARDWARE object. */
- + gcmkONERROR(gckOS_Allocate(Os,
- + gcmSIZEOF(struct _gckHARDWARE),
- + &pointer));
- +
- + hardware = (gckHARDWARE) pointer;
- +
- + /* Initialize the gckHARDWARE object. */
- + hardware->object.type = gcvOBJ_HARDWARE;
- + hardware->os = Os;
- + hardware->core = Core;
- +
- + /* Identify the hardware. */
- + gcmkONERROR(_IdentifyHardware(Os, Core, &hardware->identity));
- +
- + /* Determine the hardware type */
- + switch (hardware->identity.chipModel)
- + {
- + case gcv350:
- + case gcv355:
- + hardware->type = gcvHARDWARE_VG;
- + break;
- +
- + case gcv300:
- + case gcv320:
- + case gcv420:
- + hardware->type = gcvHARDWARE_2D;
- + /*set outstanding limit*/
- + gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x00414, &axi_ot));
- + axi_ot = (axi_ot & (~0xFF)) | 0x10;
- + gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, 0x00414, axi_ot));
- + break;
- +
- + default:
- + hardware->type = gcvHARDWARE_3D;
- + if(hardware->identity.chipModel == gcv880)
- + {
- + /*set outstanding limit*/
- + gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x00414, &axi_ot));
- + axi_ot = (axi_ot & (~0xFF)) | 0x10;
- + gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, 0x00414, axi_ot));
- + }
- +
- + if ((((((gctUINT32) (hardware->identity.chipFeatures)) >> (0 ? 9:9)) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) ))
- + {
- + hardware->type = (gceHARDWARE_TYPE) (hardware->type | gcvHARDWARE_2D);
- + }
- + }
- +
- + hardware->powerBaseAddress
- + = ((hardware->identity.chipModel == gcv300)
- + && (hardware->identity.chipRevision < 0x2000))
- + ? 0x0100
- + : 0x0000;
- +
- + /* _ResetGPU need powerBaseAddress. */
- + status = _ResetGPU(hardware, Os, Core);
- +
- + if (status != gcvSTATUS_OK)
- + {
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "_ResetGPU failed: status=%d\n", status);
- + }
- +
- + hardware->powerMutex = gcvNULL;
- +
- + hardware->mmuVersion
- + = (((((gctUINT32) (hardware->identity.chipMinorFeatures1)) >> (0 ? 28:28)) & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 28:28) - (0 ? 28:28) + 1)))))) );
- +
- + /* Determine whether bug fixes #1 are present. */
- + hardware->extraEventStates = ((((gctUINT32) (hardware->identity.chipMinorFeatures1)) >> (0 ? 3:3) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) == (0x0 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))));
- +
- + /* Check if big endian */
- + hardware->bigEndian = (*(gctUINT8 *)&data == 0xff);
- +
- + /* Initialize the fast clear. */
- + gcmkONERROR(gckHARDWARE_SetFastClear(hardware, -1, -1));
- +
- +#if !gcdENABLE_128B_MERGE
- +
- + if (((((gctUINT32) (hardware->identity.chipMinorFeatures2)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))))
- + {
- + /* 128B merge is turned on by default. Disable it. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, 0x00558, 0));
- + }
- +
- +#endif
- +
- + /* Set power state to ON. */
- + hardware->chipPowerState = gcvPOWER_ON;
- + hardware->clockState = gcvTRUE;
- + hardware->powerState = gcvTRUE;
- + hardware->lastWaitLink = ~0U;
- + hardware->globalSemaphore = gcvNULL;
- +#if gcdENABLE_FSCALE_VAL_ADJUST
- + hardware->powerOnFscaleVal = 64;
- +#endif
- +
- + gcmkONERROR(gckOS_CreateMutex(Os, &hardware->powerMutex));
- + gcmkONERROR(gckOS_CreateSemaphore(Os, &hardware->globalSemaphore));
- + hardware->startIsr = gcvNULL;
- + hardware->stopIsr = gcvNULL;
- +
- +#if gcdPOWEROFF_TIMEOUT
- + hardware->powerOffTimeout = gcdPOWEROFF_TIMEOUT;
- +
- + gcmkVERIFY_OK(gckOS_CreateTimer(Os,
- + _PowerTimerFunction,
- + (gctPOINTER)hardware,
- + &hardware->powerOffTimer));
- +#endif
- +
- + gcmkONERROR(gckOS_AtomConstruct(Os, &hardware->pageTableDirty));
- +
- +#if gcdLINK_QUEUE_SIZE
- + hardware->linkQueue.front = 0;
- + hardware->linkQueue.rear = 0;
- + hardware->linkQueue.count = 0;
- +#endif
- +
- + /* Enable power management by default. */
- + hardware->powerManagement = gcvTRUE;
- +
- + /* Disable profiler by default */
- + hardware->gpuProfiler = gcvFALSE;
- +
- + /* Return pointer to the gckHARDWARE object. */
- + *Hardware = hardware;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Hardware=0x%x", *Hardware);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Roll back. */
- + if (hardware != gcvNULL)
- + {
- + /* Turn off the power. */
- + gcmkVERIFY_OK(gckOS_SetGPUPower(Os, Core, gcvFALSE, gcvFALSE));
- +
- + if (hardware->globalSemaphore != gcvNULL)
- + {
- + /* Destroy the global semaphore. */
- + gcmkVERIFY_OK(gckOS_DestroySemaphore(Os,
- + hardware->globalSemaphore));
- + }
- +
- + if (hardware->powerMutex != gcvNULL)
- + {
- + /* Destroy the power mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Os, hardware->powerMutex));
- + }
- +
- +#if gcdPOWEROFF_TIMEOUT
- + if (hardware->powerOffTimer != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_StopTimer(Os, hardware->powerOffTimer));
- + gcmkVERIFY_OK(gckOS_DestroyTimer(Os, hardware->powerOffTimer));
- + }
- +#endif
- +
- + if (hardware->pageTableDirty != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_AtomDestroy(Os, hardware->pageTableDirty));
- + }
- +
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, hardware));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_Destroy
- +**
- +** Destroy an gckHARDWARE object.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to the gckHARDWARE object that needs to be destroyed.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckHARDWARE_Destroy(
- + IN gckHARDWARE Hardware
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + /* Destroy the power semaphore. */
- + gcmkVERIFY_OK(gckOS_DestroySemaphore(Hardware->os,
- + Hardware->globalSemaphore));
- +
- + /* Destroy the power mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Hardware->os, Hardware->powerMutex));
- +
- +#if gcdPOWEROFF_TIMEOUT
- + gcmkVERIFY_OK(gckOS_StopTimer(Hardware->os, Hardware->powerOffTimer));
- + gcmkVERIFY_OK(gckOS_DestroyTimer(Hardware->os, Hardware->powerOffTimer));
- +#endif
- +
- + gcmkVERIFY_OK(gckOS_AtomDestroy(Hardware->os, Hardware->pageTableDirty));
- +
- + /* Mark the object as unknown. */
- + Hardware->object.type = gcvOBJ_UNKNOWN;
- +
- + /* Free the object. */
- + gcmkONERROR(gcmkOS_SAFE_FREE(Hardware->os, Hardware));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_GetType
- +**
- +** Get the hardware type.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Harwdare
- +** Pointer to an gckHARDWARE object.
- +**
- +** OUTPUT:
- +**
- +** gceHARDWARE_TYPE * Type
- +** Pointer to a variable that receives the type of hardware object.
- +*/
- +gceSTATUS
- +gckHARDWARE_GetType(
- + IN gckHARDWARE Hardware,
- + OUT gceHARDWARE_TYPE * Type
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- + gcmkVERIFY_ARGUMENT(Type != gcvNULL);
- +
- + *Type = Hardware->type;
- +
- + gcmkFOOTER_ARG("*Type=%d", *Type);
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_InitializeHardware
- +**
- +** Initialize the hardware.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to the gckHARDWARE object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckHARDWARE_InitializeHardware(
- + IN gckHARDWARE Hardware
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 baseAddress;
- + gctUINT32 chipRev;
- + gctUINT32 control;
- +
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + /* Read the chip revision register. */
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00024,
- + &chipRev));
- +
- + if (chipRev != Hardware->identity.chipRevision)
- + {
- + /* Chip is not there! */
- + gcmkONERROR(gcvSTATUS_CONTEXT_LOSSED);
- + }
- +
- + /* Disable isolate GPU bit. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00000,
- + ((((gctUINT32) (0x00000900)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)))));
- +
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00000,
- + &control));
- +
- + /* Enable debug register. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00000,
- + ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1))))))) << (0 ? 11:11))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1))))))) << (0 ? 11:11)))));
- +
- + /* Reset memory counters. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x0003C,
- + ~0U));
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x0003C,
- + 0));
- +
- + /* Get the system's physical base address. */
- + gcmkONERROR(gckOS_GetBaseAddress(Hardware->os, &baseAddress));
- +
- + /* Program the base addesses. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x0041C,
- + baseAddress));
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00418,
- + baseAddress));
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00428,
- + baseAddress));
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00420,
- + baseAddress));
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00424,
- + baseAddress));
- +
- +#if !VIVANTE_PROFILER
- + {
- + gctUINT32 data;
- +
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + Hardware->powerBaseAddress +
- + 0x00100,
- + &data));
- +
- + /* Enable clock gating. */
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
- +
- + if ((Hardware->identity.chipRevision == 0x4301)
- + || (Hardware->identity.chipRevision == 0x4302)
- + )
- + {
- + /* Disable stall module level clock gating for 4.3.0.1 and 4.3.0.2
- + ** revisions. */
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)));
- + }
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + Hardware->powerBaseAddress
- + + 0x00100,
- + data));
- +
- +#ifndef VIVANTE_NO_3D
- + /* Disable PE clock gating on revs < 5.0 when HZ is present without a
- + ** bug fix. */
- + if ((Hardware->identity.chipRevision < 0x5000)
- + && ((((gctUINT32) (Hardware->identity.chipMinorFeatures1)) >> (0 ? 9:9) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) == (0x0 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))))
- + && ((((gctUINT32) (Hardware->identity.chipMinorFeatures)) >> (0 ? 27:27) & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1)))))))
- + )
- + {
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + Hardware->powerBaseAddress
- + + 0x00104,
- + &data));
- +
- + /* Disable PE clock gating. */
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)));
- +
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + Hardware->powerBaseAddress
- + + 0x00104,
- + data));
- + }
- +
- +#endif
- + }
- +#endif
- +
- + /* Special workaround for this core
- + ** Make sure pulse eater kicks in only when SH is idle */
- + if (Hardware->identity.chipModel == gcv4000 &&
- + Hardware->identity.chipRevision == 0x5208)
- + {
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x0010C,
- + ((((gctUINT32) (0x01590880)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1))))))) << (0 ? 23:23))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1))))))) << (0 ? 23:23)))));
- + }
- +
- + if ((gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_HALTI2) == gcvFALSE)
- + || (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_HALTI2) && (Hardware->identity.chipRevision < 0x5422))
- + )
- + {
- + gctUINT32 data;
- +
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + Hardware->powerBaseAddress
- + + 0x00104,
- + &data));
- +
- +
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:15) - (0 ? 15:15) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:15) - (0 ? 15:15) + 1))))))) << (0 ? 15:15))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:15) - (0 ? 15:15) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:15) - (0 ? 15:15) + 1))))))) << (0 ? 15:15)));
- +
- +
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + Hardware->powerBaseAddress
- + + 0x00104,
- + data));
- + }
- +
- + /* Special workaround for this core
- + ** Make sure FE and TX are on different buses */
- + if ((Hardware->identity.chipModel == gcv2000)
- + && (Hardware->identity.chipRevision == 0x5108))
- + {
- + gctUINT32 data;
- +
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00480,
- + &data));
- +
- + /* Set FE bus to one, TX bus to zero */
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)));
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7)));
- +
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00480,
- + data));
- + }
- +
- + /* Test if MMU is initialized. */
- + if ((Hardware->kernel != gcvNULL)
- + && (Hardware->kernel->mmu != gcvNULL)
- + )
- + {
- + /* Reset MMU. */
- + if (Hardware->mmuVersion == 0)
- + {
- + gcmkONERROR(
- + gckHARDWARE_SetMMU(Hardware,
- + Hardware->kernel->mmu->pageTableLogical));
- + }
- + }
- +
- + if (Hardware->identity.chipModel >= gcv400
- + && Hardware->identity.chipModel != gcv420
- + && (((((gctUINT32) (Hardware->identity.chipMinorFeatures3)) >> (0 ? 15:15) & ((gctUINT32) ((((1 ? 15:15) - (0 ? 15:15) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:15) - (0 ? 15:15) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 15:15) - (0 ? 15:15) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:15) - (0 ? 15:15) + 1))))))) != gcvTRUE)
- + )
- + {
- + gctUINT32 data;
- +
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + Hardware->powerBaseAddress
- + + 0x00104,
- + &data));
- +
- + /* Disable PA clock gating. */
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
- +
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + Hardware->powerBaseAddress
- + + 0x00104,
- + data));
- + }
- +
- +#if gcdHZ_L2_DISALBE
- + /* Disable HZ-L2. */
- + if (((((gctUINT32) (Hardware->identity.chipMinorFeatures3)) >> (0 ? 26:26) & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1))))))) == gcvTRUE ||
- + ((((gctUINT32) (Hardware->identity.chipMinorFeatures3)) >> (0 ? 8:8) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) == gcvTRUE)
- + {
- + gctUINT32 data;
- +
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00414,
- + &data));
- +
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)));
- +
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00414,
- + data));
- + }
- +#endif
- +
- + /* Limit 2D outstanding request. */
- + if(Hardware->identity.chipModel == gcv880)
- + {
- + gctUINT32 axi_ot;
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00414, &axi_ot));
- + axi_ot = (axi_ot & (~0xFF)) | 0x10;
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00414, axi_ot));
- + }
- +
- + if (Hardware->identity.chip2DControl & 0xFF)
- + {
- + gctUINT32 data;
- +
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00414,
- + &data));
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (Hardware->identity.chip2DControl & 0xFF) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)));
- +
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00414,
- + data));
- + }
- +
- + /* Update GPU AXI cache atttribute. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00008,
- + 0x00002200));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the error. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_QueryMemory
- +**
- +** Query the amount of memory available on the hardware.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to the gckHARDWARE object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * InternalSize
- +** Pointer to a variable that will hold the size of the internal video
- +** memory in bytes. If 'InternalSize' is gcvNULL, no information of the
- +** internal memory will be returned.
- +**
- +** gctUINT32 * InternalBaseAddress
- +** Pointer to a variable that will hold the hardware's base address for
- +** the internal video memory. This pointer cannot be gcvNULL if
- +** 'InternalSize' is also non-gcvNULL.
- +**
- +** gctUINT32 * InternalAlignment
- +** Pointer to a variable that will hold the hardware's base address for
- +** the internal video memory. This pointer cannot be gcvNULL if
- +** 'InternalSize' is also non-gcvNULL.
- +**
- +** gctSIZE_T * ExternalSize
- +** Pointer to a variable that will hold the size of the external video
- +** memory in bytes. If 'ExternalSize' is gcvNULL, no information of the
- +** external memory will be returned.
- +**
- +** gctUINT32 * ExternalBaseAddress
- +** Pointer to a variable that will hold the hardware's base address for
- +** the external video memory. This pointer cannot be gcvNULL if
- +** 'ExternalSize' is also non-gcvNULL.
- +**
- +** gctUINT32 * ExternalAlignment
- +** Pointer to a variable that will hold the hardware's base address for
- +** the external video memory. This pointer cannot be gcvNULL if
- +** 'ExternalSize' is also non-gcvNULL.
- +**
- +** gctUINT32 * HorizontalTileSize
- +** Number of horizontal pixels per tile. If 'HorizontalTileSize' is
- +** gcvNULL, no horizontal pixel per tile will be returned.
- +**
- +** gctUINT32 * VerticalTileSize
- +** Number of vertical pixels per tile. If 'VerticalTileSize' is
- +** gcvNULL, no vertical pixel per tile will be returned.
- +*/
- +gceSTATUS
- +gckHARDWARE_QueryMemory(
- + IN gckHARDWARE Hardware,
- + OUT gctSIZE_T * InternalSize,
- + OUT gctUINT32 * InternalBaseAddress,
- + OUT gctUINT32 * InternalAlignment,
- + OUT gctSIZE_T * ExternalSize,
- + OUT gctUINT32 * ExternalBaseAddress,
- + OUT gctUINT32 * ExternalAlignment,
- + OUT gctUINT32 * HorizontalTileSize,
- + OUT gctUINT32 * VerticalTileSize
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + if (InternalSize != gcvNULL)
- + {
- + /* No internal memory. */
- + *InternalSize = 0;
- + }
- +
- + if (ExternalSize != gcvNULL)
- + {
- + /* No external memory. */
- + *ExternalSize = 0;
- + }
- +
- + if (HorizontalTileSize != gcvNULL)
- + {
- + /* 4x4 tiles. */
- + *HorizontalTileSize = 4;
- + }
- +
- + if (VerticalTileSize != gcvNULL)
- + {
- + /* 4x4 tiles. */
- + *VerticalTileSize = 4;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*InternalSize=%lu *InternalBaseAddress=0x%08x "
- + "*InternalAlignment=0x%08x *ExternalSize=%lu "
- + "*ExternalBaseAddress=0x%08x *ExtenalAlignment=0x%08x "
- + "*HorizontalTileSize=%u *VerticalTileSize=%u",
- + gcmOPT_VALUE(InternalSize),
- + gcmOPT_VALUE(InternalBaseAddress),
- + gcmOPT_VALUE(InternalAlignment),
- + gcmOPT_VALUE(ExternalSize),
- + gcmOPT_VALUE(ExternalBaseAddress),
- + gcmOPT_VALUE(ExternalAlignment),
- + gcmOPT_VALUE(HorizontalTileSize),
- + gcmOPT_VALUE(VerticalTileSize));
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_QueryChipIdentity
- +**
- +** Query the identity of the hardware.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to the gckHARDWARE object.
- +**
- +** OUTPUT:
- +**
- +** gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
- +** Pointer to the identity structure.
- +**
- +*/
- +gceSTATUS
- +gckHARDWARE_QueryChipIdentity(
- + IN gckHARDWARE Hardware,
- + OUT gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
- + )
- +{
- + gctUINT32 features;
- +
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(Identity != gcvNULL);
- +
- + /* Return chip model and revision. */
- + Identity->chipModel = Hardware->identity.chipModel;
- + Identity->chipRevision = Hardware->identity.chipRevision;
- +
- + /* Return feature set. */
- + features = Hardware->identity.chipFeatures;
- +
- + if ((((((gctUINT32) (features)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
- + {
- + /* Override fast clear by command line. */
- + features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (Hardware->allowFastClear) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
- + }
- +
- + if ((((((gctUINT32) (features)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) ))
- + {
- + /* Override compression by command line. */
- + features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) ((gctUINT32) (Hardware->allowCompression) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
- + }
- +
- + /* Mark 2D pipe as available for GC500.0 through GC500.2 and GC300,
- + ** since they did not have this bit. */
- + if (((Hardware->identity.chipModel == gcv500) && (Hardware->identity.chipRevision <= 2))
- + || (Hardware->identity.chipModel == gcv300)
- + )
- + {
- + features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
- + }
- +
- + Identity->chipFeatures = features;
- +
- + /* Return minor features. */
- + Identity->chipMinorFeatures = Hardware->identity.chipMinorFeatures;
- + Identity->chipMinorFeatures1 = Hardware->identity.chipMinorFeatures1;
- + Identity->chipMinorFeatures2 = Hardware->identity.chipMinorFeatures2;
- + Identity->chipMinorFeatures3 = Hardware->identity.chipMinorFeatures3;
- + Identity->chipMinorFeatures4 = Hardware->identity.chipMinorFeatures4;
- +
- + /* Return chip specs. */
- + Identity->streamCount = Hardware->identity.streamCount;
- + Identity->registerMax = Hardware->identity.registerMax;
- + Identity->threadCount = Hardware->identity.threadCount;
- + Identity->shaderCoreCount = Hardware->identity.shaderCoreCount;
- + Identity->vertexCacheSize = Hardware->identity.vertexCacheSize;
- + Identity->vertexOutputBufferSize = Hardware->identity.vertexOutputBufferSize;
- + Identity->pixelPipes = Hardware->identity.pixelPipes;
- + Identity->instructionCount = Hardware->identity.instructionCount;
- + Identity->numConstants = Hardware->identity.numConstants;
- + Identity->bufferSize = Hardware->identity.bufferSize;
- + Identity->varyingsCount = Hardware->identity.varyingsCount;
- + Identity->superTileMode = Hardware->identity.superTileMode;
- + Identity->chip2DControl = Hardware->identity.chip2DControl;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_SplitMemory
- +**
- +** Split a hardware specific memory address into a pool and offset.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to the gckHARDWARE object.
- +**
- +** gctUINT32 Address
- +** Address in hardware specific format.
- +**
- +** OUTPUT:
- +**
- +** gcePOOL * Pool
- +** Pointer to a variable that will hold the pool type for the address.
- +**
- +** gctUINT32 * Offset
- +** Pointer to a variable that will hold the offset for the address.
- +*/
- +gceSTATUS
- +gckHARDWARE_SplitMemory(
- + IN gckHARDWARE Hardware,
- + IN gctUINT32 Address,
- + OUT gcePOOL * Pool,
- + OUT gctUINT32 * Offset
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x Addres=0x%08x", Hardware, Address);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Offset != gcvNULL);
- +
- + if (Hardware->mmuVersion == 0)
- + {
- + /* Dispatch on memory type. */
- + switch ((((((gctUINT32) (Address)) >> (0 ? 31:31)) & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1)))))) ))
- + {
- + case 0x0:
- + /* System memory. */
- + *Pool = gcvPOOL_SYSTEM;
- + break;
- +
- + case 0x1:
- + /* Virtual memory. */
- + *Pool = gcvPOOL_VIRTUAL;
- + break;
- +
- + default:
- + /* Invalid memory type. */
- + gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
- + return gcvSTATUS_INVALID_ARGUMENT;
- + }
- +
- + /* Return offset of address. */
- + *Offset = (((((gctUINT32) (Address)) >> (0 ? 30:0)) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1)))))) );
- + }
- + else
- + {
- + *Pool = gcvPOOL_SYSTEM;
- + *Offset = Address;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Pool=%d *Offset=0x%08x", *Pool, *Offset);
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_Execute
- +**
- +** Kickstart the hardware's command processor with an initialized command
- +** buffer.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to the gckHARDWARE object.
- +**
- +** gctPOINTER Logical
- +** Logical address of command buffer.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes for the prefetch unit (until after the first LINK).
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckHARDWARE_Execute(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- +#ifdef __QNXNTO__
- + IN gctPOINTER Physical,
- + IN gctBOOL PhysicalAddresses,
- +#endif
- + IN gctSIZE_T Bytes
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 address = 0, control;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Bytes=%lu",
- + Hardware, Logical, Bytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- +
- +#ifdef __QNXNTO__
- + if (PhysicalAddresses && (Hardware->mmuVersion == 0))
- + {
- + /* Convert physical into hardware specific address. */
- + gcmkONERROR(
- + gckHARDWARE_ConvertPhysical(Hardware, Physical, &address));
- + }
- + else
- + {
- +#endif
- + /* Convert logical into hardware specific address. */
- + gcmkONERROR(
- + gckHARDWARE_ConvertLogical(Hardware, Logical, &address));
- +#ifdef __QNXNTO__
- + }
- +#endif
- +
- + /* Enable all events. */
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00014, ~0U));
- +
- + /* Write address register. */
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00654, address));
- +
- + /* Build control register. */
- + control = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) ((Bytes + 7) >> 3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + /* Set big endian */
- + if (Hardware->bigEndian)
- + {
- + control |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 21:20) - (0 ? 21:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:20) - (0 ? 21:20) + 1))))))) << (0 ? 21:20))) | (((gctUINT32) (0x2 & ((gctUINT32) ((((1 ? 21:20) - (0 ? 21:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:20) - (0 ? 21:20) + 1))))))) << (0 ? 21:20)));
- + }
- +
- + /* Write control register. */
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00658, control));
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Started command buffer @ 0x%08x",
- + address);
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_WaitLink
- +**
- +** Append a WAIT/LINK command sequence at the specified location in the command
- +** queue.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to an gckHARDWARE object.
- +**
- +** gctPOINTER Logical
- +** Pointer to the current location inside the command queue to append
- +** WAIT/LINK command sequence at or gcvNULL just to query the size of the
- +** WAIT/LINK command sequence.
- +**
- +** gctUINT32 Offset
- +** Offset into command buffer required for alignment.
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to the number of bytes available for the WAIT/LINK command
- +** sequence. If 'Logical' is gcvNULL, this argument will be ignored.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to a variable that will receive the number of bytes required
- +** by the WAIT/LINK command sequence. If 'Bytes' is gcvNULL, nothing will
- +** be returned.
- +**
- +** gctUINT32 * WaitOffset
- +** Pointer to a variable that will receive the offset of the WAIT command
- +** from the specified logcial pointer.
- +** If 'WaitOffset' is gcvNULL nothing will be returned.
- +**
- +** gctSIZE_T * WaitSize
- +** Pointer to a variable that will receive the number of bytes used by
- +** the WAIT command. If 'LinkSize' is gcvNULL nothing will be returned.
- +*/
- +gceSTATUS
- +gckHARDWARE_WaitLink(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + IN gctUINT32 Offset,
- + IN OUT gctSIZE_T * Bytes,
- + OUT gctUINT32 * WaitOffset,
- + OUT gctSIZE_T * WaitSize
- + )
- +{
- + static const gctUINT waitCount = 200;
- +
- + gceSTATUS status;
- + gctUINT32 address;
- + gctUINT32_PTR logical;
- + gctSIZE_T bytes;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Offset=0x%08x *Bytes=%lu",
- + Hardware, Logical, Offset, gcmOPT_VALUE(Bytes));
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT((Logical != gcvNULL) || (Bytes != gcvNULL));
- +
- + /* Compute number of bytes required. */
- +#if gcd6000_SUPPORT
- + bytes = gcmALIGN(Offset + 96, 8) - Offset;
- +#else
- + bytes = gcmALIGN(Offset + 16, 8) - Offset;
- +#endif
- +
- + /* Cast the input pointer. */
- + logical = (gctUINT32_PTR) Logical;
- +
- + if (logical != gcvNULL)
- + {
- + /* Not enough space? */
- + if (*Bytes < bytes)
- + {
- + /* Command queue too small. */
- + gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
- + }
- +
- + /* Convert logical into hardware specific address. */
- + gcmkONERROR(gckHARDWARE_ConvertLogical(Hardware, logical, &address));
- +
- + /* Store the WAIT/LINK address. */
- + Hardware->lastWaitLink = address;
- +
- + /* Append WAIT(count). */
- + logical[0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (waitCount) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- +#if gcd6000_SUPPORT
- + /* Send FE-PE sempahore token. */
- + logical[2]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + logical[3]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
- +
- + /* Send FE-PE stall token. */
- + logical[4]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
- +
- + logical[5]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
- +
- + /*************************************************************/
- + /* Enable chip ID 0. */
- + logical[6] =
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x0D & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | (1 << 0);
- +
- + /* Send semaphore from FE to ChipID 1. */
- + logical[8] =
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + logical[9] =
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x0F & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)));
- +
- + /* Send semaphore from FE to ChipID 1. */
- + logical[10] =
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
- +
- + logical[11] =
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x0F & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)));
- +
- + /*************************************************************/
- + /* Enable chip ID 1. */
- + logical[12] =
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x0D & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | (1 << 1);
- +
- + /* Send semaphore from FE to ChipID 1. */
- + logical[14] =
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + logical[15] =
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x0F & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)));
- +
- + /* Wait for semaphore from ChipID 0. */
- + logical[16] =
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
- +
- + logical[17] =
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x0F & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)));
- +
- + /*************************************************************/
- + /* Enable all chips. */
- + logical[18] =
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x0D & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | (0xFFFF);
- +
- + /* LoadState(AQFlush, 1), flush. */
- + logical[20]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + logical[21]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
- +
- + /* Append LINK(2, address). */
- + logical[22]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (bytes >> 3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + logical[23] = address;
- +#else
- + /* Append LINK(2, address). */
- + logical[2]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (bytes >> 3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + logical[3] = address;
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "0x%08x: WAIT %u", address, waitCount
- + );
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "0x%08x: LINK 0x%08x, #%lu",
- + address + 8, address, bytes
- + );
- +#endif
- +
- + if (WaitOffset != gcvNULL)
- + {
- + /* Return the offset pointer to WAIT command. */
- + *WaitOffset = 0;
- + }
- +
- + if (WaitSize != gcvNULL)
- + {
- + /* Return number of bytes used by the WAIT command. */
- + *WaitSize = 8;
- + }
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return number of bytes required by the WAIT/LINK command
- + ** sequence. */
- + *Bytes = bytes;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Bytes=%lu *WaitOffset=0x%x *WaitSize=%lu",
- + gcmOPT_VALUE(Bytes), gcmOPT_VALUE(WaitOffset),
- + gcmOPT_VALUE(WaitSize));
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_End
- +**
- +** Append an END command at the specified location in the command queue.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to an gckHARDWARE object.
- +**
- +** gctPOINTER Logical
- +** Pointer to the current location inside the command queue to append
- +** END command at or gcvNULL just to query the size of the END command.
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to the number of bytes available for the END command. If
- +** 'Logical' is gcvNULL, this argument will be ignored.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to a variable that will receive the number of bytes required
- +** for the END command. If 'Bytes' is gcvNULL, nothing will be returned.
- +*/
- +gceSTATUS
- +gckHARDWARE_End(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + IN OUT gctSIZE_T * Bytes
- + )
- +{
- + gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
- + Hardware, Logical, gcmOPT_VALUE(Bytes));
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
- +
- + if (Logical != gcvNULL)
- + {
- + if (*Bytes < 8)
- + {
- + /* Command queue too small. */
- + gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
- + }
- +
- + /* Append END. */
- + logical[0] =
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x02 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: END", Logical);
- +
- + /* Make sure the CPU writes out the data to memory. */
- + gcmkONERROR(
- + gckOS_MemoryBarrier(Hardware->os, Logical));
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return number of bytes required by the END command. */
- + *Bytes = 8;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_Nop
- +**
- +** Append a NOP command at the specified location in the command queue.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to an gckHARDWARE object.
- +**
- +** gctPOINTER Logical
- +** Pointer to the current location inside the command queue to append
- +** NOP command at or gcvNULL just to query the size of the NOP command.
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to the number of bytes available for the NOP command. If
- +** 'Logical' is gcvNULL, this argument will be ignored.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to a variable that will receive the number of bytes required
- +** for the NOP command. If 'Bytes' is gcvNULL, nothing will be returned.
- +*/
- +gceSTATUS
- +gckHARDWARE_Nop(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + IN OUT gctSIZE_T * Bytes
- + )
- +{
- + gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
- + Hardware, Logical, gcmOPT_VALUE(Bytes));
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
- +
- + if (Logical != gcvNULL)
- + {
- + if (*Bytes < 8)
- + {
- + /* Command queue too small. */
- + gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
- + }
- +
- + /* Append NOP. */
- + logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: NOP", Logical);
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return number of bytes required by the NOP command. */
- + *Bytes = 8;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_Wait
- +**
- +** Append a WAIT command at the specified location in the command queue.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to an gckHARDWARE object.
- +**
- +** gctPOINTER Logical
- +** Pointer to the current location inside the command queue to append
- +** WAIT command at or gcvNULL just to query the size of the WAIT command.
- +**
- +** gctUINT32 Count
- +** Number of cycles to wait.
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to the number of bytes available for the WAIT command. If
- +** 'Logical' is gcvNULL, this argument will be ignored.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to a variable that will receive the number of bytes required
- +** for the NOP command. If 'Bytes' is gcvNULL, nothing will be returned.
- +*/
- +gceSTATUS
- +gckHARDWARE_Wait(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + IN gctUINT32 Count,
- + IN OUT gctSIZE_T * Bytes
- + )
- +{
- + gceSTATUS status;
- + gctUINT32_PTR logical;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Count=%u *Bytes=%lu",
- + Hardware, Logical, Count, gcmOPT_VALUE(Bytes));
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
- +
- + /* Cast the input pointer. */
- + logical = (gctUINT32_PTR) Logical;
- +
- + if (Logical != gcvNULL)
- + {
- + if (*Bytes < 8)
- + {
- + /* Command queue too small. */
- + gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
- + }
- +
- + /* Append WAIT. */
- + logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- +#if gcmIS_DEBUG(gcdDEBUG_TRACE)
- + {
- + gctUINT32 address;
- +
- + /* Convert logical into hardware specific address. */
- + gcmkONERROR(gckHARDWARE_ConvertLogical(
- + Hardware, logical, &address
- + ));
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "0x%08x: WAIT %u", address, Count
- + );
- + }
- +#endif
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return number of bytes required by the WAIT command. */
- + *Bytes = 8;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_Event
- +**
- +** Append an EVENT command at the specified location in the command queue.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to an gckHARDWARE object.
- +**
- +** gctPOINTER Logical
- +** Pointer to the current location inside the command queue to append
- +** the EVENT command at or gcvNULL just to query the size of the EVENT
- +** command.
- +**
- +** gctUINT8 Event
- +** Event ID to program.
- +**
- +** gceKERNEL_WHERE FromWhere
- +** Location of the pipe to send the event.
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to the number of bytes available for the EVENT command. If
- +** 'Logical' is gcvNULL, this argument will be ignored.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to a variable that will receive the number of bytes required
- +** for the EVENT command. If 'Bytes' is gcvNULL, nothing will be
- +** returned.
- +*/
- +gceSTATUS
- +gckHARDWARE_Event(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + IN gctUINT8 Event,
- + IN gceKERNEL_WHERE FromWhere,
- + IN OUT gctSIZE_T * Bytes
- + )
- +{
- + gctUINT size;
- + gctUINT32 destination = 0;
- + gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Event=%u FromWhere=%d *Bytes=%lu",
- + Hardware, Logical, Event, FromWhere, gcmOPT_VALUE(Bytes));
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
- + gcmkVERIFY_ARGUMENT(Event < 32);
- +
- + /* Determine the size of the command. */
- +
- + size = (Hardware->extraEventStates && (FromWhere == gcvKERNEL_PIXEL))
- + ? gcmALIGN(8 + (1 + 5) * 4, 8) /* EVENT + 5 STATES */
- + : 8;
- +
- + if (Logical != gcvNULL)
- + {
- + if (*Bytes < size)
- + {
- + /* Command queue too small. */
- + gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
- + }
- +
- + switch (FromWhere)
- + {
- + case gcvKERNEL_COMMAND:
- + /* From command processor. */
- + destination = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
- + break;
- +
- + case gcvKERNEL_PIXEL:
- + /* From pixel engine. */
- + destination = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
- + break;
- +
- + default:
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + /* Append EVENT(Event, destiantion). */
- + logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + logical[1] = ((((gctUINT32) (destination)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (Event) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)));
- +
- + /* Make sure the event ID gets written out before GPU can access it. */
- + gcmkONERROR(
- + gckOS_MemoryBarrier(Hardware->os, logical + 1));
- +
- +#if gcmIS_DEBUG(gcdDEBUG_TRACE)
- + {
- + gctUINT32 phys;
- + gckOS_GetPhysicalAddress(Hardware->os, Logical, &phys);
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "0x%08x: EVENT %d", phys, Event);
- + }
- +#endif
- +
- + /* Append the extra states. These are needed for the chips that do not
- + ** support back-to-back events due to the async interface. The extra
- + ** states add the necessary delay to ensure that event IDs do not
- + ** collide. */
- + if (size > 8)
- + {
- + logical[2] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0100) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- + logical[3] = 0;
- + logical[4] = 0;
- + logical[5] = 0;
- + logical[6] = 0;
- + logical[7] = 0;
- + }
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return number of bytes required by the EVENT command. */
- + *Bytes = size;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_PipeSelect
- +**
- +** Append a PIPESELECT command at the specified location in the command queue.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to an gckHARDWARE object.
- +**
- +** gctPOINTER Logical
- +** Pointer to the current location inside the command queue to append
- +** the PIPESELECT command at or gcvNULL just to query the size of the
- +** PIPESELECT command.
- +**
- +** gcePIPE_SELECT Pipe
- +** Pipe value to select.
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to the number of bytes available for the PIPESELECT command.
- +** If 'Logical' is gcvNULL, this argument will be ignored.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to a variable that will receive the number of bytes required
- +** for the PIPESELECT command. If 'Bytes' is gcvNULL, nothing will be
- +** returned.
- +*/
- +gceSTATUS
- +gckHARDWARE_PipeSelect(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + IN gcePIPE_SELECT Pipe,
- + IN OUT gctSIZE_T * Bytes
- + )
- +{
- + gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Pipe=%d *Bytes=%lu",
- + Hardware, Logical, Pipe, gcmOPT_VALUE(Bytes));
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
- +
- + /* Append a PipeSelect. */
- + if (Logical != gcvNULL)
- + {
- + gctUINT32 flush, stall;
- +
- + if (*Bytes < 32)
- + {
- + /* Command queue too small. */
- + gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
- + }
- +
- + flush = (Pipe == gcvPIPE_2D)
- + ? ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
- + : ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)));
- +
- + stall = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
- +
- + /* LoadState(AQFlush, 1), flush. */
- + logical[0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + logical[1]
- + = flush;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "0x%x: FLUSH 0x%x", logical, flush);
- +
- + /* LoadState(AQSempahore, 1), stall. */
- + logical[2]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + logical[3]
- + = stall;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "0x%x: SEMAPHORE 0x%x", logical + 2, stall);
- +
- + /* Stall, stall. */
- + logical[4] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
- + logical[5] = stall;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "0x%x: STALL 0x%x", logical + 4, stall);
- +
- + /* LoadState(AQPipeSelect, 1), pipe. */
- + logical[6]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + logical[7] = (Pipe == gcvPIPE_2D)
- + ? 0x1
- + : 0x0;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "0x%x: PIPE %d", logical + 6, Pipe);
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return number of bytes required by the PIPESELECT command. */
- + *Bytes = 32;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_Link
- +**
- +** Append a LINK command at the specified location in the command queue.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to an gckHARDWARE object.
- +**
- +** gctPOINTER Logical
- +** Pointer to the current location inside the command queue to append
- +** the LINK command at or gcvNULL just to query the size of the LINK
- +** command.
- +**
- +** gctPOINTER FetchAddress
- +** Logical address of destination of LINK.
- +**
- +** gctSIZE_T FetchSize
- +** Number of bytes in destination of LINK.
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to the number of bytes available for the LINK command. If
- +** 'Logical' is gcvNULL, this argument will be ignored.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to a variable that will receive the number of bytes required
- +** for the LINK command. If 'Bytes' is gcvNULL, nothing will be returned.
- +*/
- +gceSTATUS
- +gckHARDWARE_Link(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + IN gctPOINTER FetchAddress,
- + IN gctSIZE_T FetchSize,
- + IN OUT gctSIZE_T * Bytes
- + )
- +{
- + gceSTATUS status;
- + gctSIZE_T bytes;
- + gctUINT32 address;
- + gctUINT32 link;
- + gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x FetchAddress=0x%x FetchSize=%lu "
- + "*Bytes=%lu",
- + Hardware, Logical, FetchAddress, FetchSize,
- + gcmOPT_VALUE(Bytes));
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
- +
- + if (Logical != gcvNULL)
- + {
- + if (*Bytes < 8)
- + {
- + /* Command queue too small. */
- + gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
- + }
- +
- + /* Convert logical address to hardware address. */
- + gcmkONERROR(
- + gckHARDWARE_ConvertLogical(Hardware, FetchAddress, &address));
- +
- + gcmkONERROR(
- + gckOS_WriteMemory(Hardware->os, logical + 1, address));
- +
- + /* Make sure the address got written before the LINK command. */
- + gcmkONERROR(
- + gckOS_MemoryBarrier(Hardware->os, logical + 1));
- +
- + /* Compute number of 64-byte aligned bytes to fetch. */
- + bytes = gcmALIGN(address + FetchSize, 8) - address;
- +
- + /* Append LINK(bytes / 8), FetchAddress. */
- + link = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (bytes >> 3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + gcmkONERROR(
- + gckOS_WriteMemory(Hardware->os, logical, link));
- +
- + /* Memory barrier. */
- + gcmkONERROR(
- + gckOS_MemoryBarrier(Hardware->os, logical));
- +
- +#if gcdLINK_QUEUE_SIZE && gcdVIRTUAL_COMMAND_BUFFER
- + if (address >= 0x80000000)
- + {
- + gckLINKQUEUE_Enqueue(&Hardware->linkQueue, address, address + bytes);
- + }
- +#endif
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return number of bytes required by the LINK command. */
- + *Bytes = 8;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_UpdateQueueTail
- +**
- +** Update the tail of the command queue.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to an gckHARDWARE object.
- +**
- +** gctPOINTER Logical
- +** Logical address of the start of the command queue.
- +**
- +** gctUINT32 Offset
- +** Offset into the command queue of the tail (last command).
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckHARDWARE_UpdateQueueTail(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + IN gctUINT32 Offset
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Offset=0x%08x",
- + Hardware, Logical, Offset);
- +
- + /* Verify the hardware. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + /* Force a barrier. */
- + gcmkONERROR(
- + gckOS_MemoryBarrier(Hardware->os, Logical));
- +
- + /* Notify gckKERNEL object of change. */
- + gcmkONERROR(
- + gckKERNEL_Notify(Hardware->kernel,
- + gcvNOTIFY_COMMAND_QUEUE,
- + gcvFALSE));
- +
- + if (status == gcvSTATUS_CHIP_NOT_READY)
- + {
- + gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_ConvertLogical
- +**
- +** Convert a logical system address into a hardware specific address.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to an gckHARDWARE object.
- +**
- +** gctPOINTER Logical
- +** Logical address to convert.
- +**
- +** gctUINT32* Address
- +** Return hardware specific address.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckHARDWARE_ConvertLogical(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + OUT gctUINT32 * Address
- + )
- +{
- + gctUINT32 address;
- + gceSTATUS status;
- + gctUINT32 baseAddress;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x", Hardware, Logical);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Address != gcvNULL);
- +
- +#if gcdVIRTUAL_COMMAND_BUFFER
- + status = gckKERNEL_GetGPUAddress(Hardware->kernel, Logical, Address);
- +
- + if (status == gcvSTATUS_INVALID_ADDRESS)
- +#endif
- + {
- + /* Convert logical address into a physical address. */
- + gcmkONERROR(
- + gckOS_GetPhysicalAddress(Hardware->os, Logical, &address));
- +
- + /* For old MMU, get GPU address according to baseAddress. */
- + if (Hardware->mmuVersion == 0)
- + {
- + gcmkONERROR(gckOS_GetBaseAddress(Hardware->os, &baseAddress));
- +
- + /* Subtract base address to get a GPU address. */
- + gcmkASSERT(address >= baseAddress);
- + address -= baseAddress;
- + }
- +
- + /* Return hardware specific address. */
- + *Address = (Hardware->mmuVersion == 0)
- + ? ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0))) | (((gctUINT32) ((gctUINT32) (address) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0)))
- + : address;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Address=0x%08x", *Address);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_ConvertPhysical
- +**
- +** Convert a physical address into a hardware specific address.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to an gckHARDWARE object.
- +**
- +** gctPHYS_ADDR Physical
- +** Physical address to convert.
- +**
- +** gctUINT32* Address
- +** Return hardware specific address.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckHARDWARE_ConvertPhysical(
- + IN gckHARDWARE Hardware,
- + IN gctPHYS_ADDR Physical,
- + OUT gctUINT32 * Address
- + )
- +{
- + gctUINT32 address;
- + gctUINT32 baseAddress;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Physical=0x%x", Hardware, Physical);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Address != gcvNULL);
- +
- + address = gcmPTR2INT(Physical);
- +
- + /* For old MMU, get GPU address according to baseAddress. */
- + if (Hardware->mmuVersion == 0)
- + {
- + gcmkVERIFY_OK(gckOS_GetBaseAddress(Hardware->os, &baseAddress));
- +
- + /* Subtract base address to get a GPU address. */
- + gcmkASSERT(address >= baseAddress);
- + address -= baseAddress;
- + }
- +
- + /* Return hardware specific address. */
- + *Address = (Hardware->mmuVersion == 0)
- + ? ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0))) | (((gctUINT32) ((gctUINT32) (address) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0)))
- + : address;
- +
- + /* Return the status. */
- + gcmkFOOTER_ARG("*Address=0x%08x", *Address);
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_Interrupt
- +**
- +** Process an interrupt.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to an gckHARDWARE object.
- +**
- +** gctBOOL InterruptValid
- +** If gcvTRUE, this function will read the interrupt acknowledge
- +** register, stores the data, and return whether or not the interrupt
- +** is ours or not. If gcvFALSE, this functions will read the interrupt
- +** acknowledge register and combine it with any stored value to handle
- +** the event notifications.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckHARDWARE_Interrupt(
- + IN gckHARDWARE Hardware,
- + IN gctBOOL InterruptValid
- + )
- +{
- + gckEVENT eventObj;
- + gctUINT32 data;
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Hardware=0x%x InterruptValid=%d", Hardware, InterruptValid);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + /* Extract gckEVENT object. */
- + eventObj = Hardware->kernel->eventObj;
- + gcmkVERIFY_OBJECT(eventObj, gcvOBJ_EVENT);
- +
- + if (InterruptValid)
- + {
- + /* Read AQIntrAcknowledge register. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00010,
- + &data));
- +
- + if (data == 0)
- + {
- + /* Not our interrupt. */
- + status = gcvSTATUS_NOT_OUR_INTERRUPT;
- + }
- + else
- + {
- + /* Inform gckEVENT of the interrupt. */
- + status = gckEVENT_Interrupt(eventObj, data);
- + }
- + }
- + else
- + {
- + /* Handle events. */
- + status = gckEVENT_Notify(eventObj, 0);
- + }
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_QueryCommandBuffer
- +**
- +** Query the command buffer alignment and number of reserved bytes.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Harwdare
- +** Pointer to an gckHARDWARE object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Alignment
- +** Pointer to a variable receiving the alignment for each command.
- +**
- +** gctSIZE_T * ReservedHead
- +** Pointer to a variable receiving the number of reserved bytes at the
- +** head of each command buffer.
- +**
- +** gctSIZE_T * ReservedTail
- +** Pointer to a variable receiving the number of bytes reserved at the
- +** tail of each command buffer.
- +*/
- +gceSTATUS
- +gckHARDWARE_QueryCommandBuffer(
- + IN gckHARDWARE Hardware,
- + OUT gctSIZE_T * Alignment,
- + OUT gctSIZE_T * ReservedHead,
- + OUT gctSIZE_T * ReservedTail
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + if (Alignment != gcvNULL)
- + {
- + /* Align every 8 bytes. */
- + *Alignment = 8;
- + }
- +
- + if (ReservedHead != gcvNULL)
- + {
- + /* Reserve space for SelectPipe(). */
- + *ReservedHead = 32;
- + }
- +
- + if (ReservedTail != gcvNULL)
- + {
- + /* Reserve space for Link(). */
- + *ReservedTail = 8;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Alignment=%lu *ReservedHead=%lu *ReservedTail=%lu",
- + gcmOPT_VALUE(Alignment), gcmOPT_VALUE(ReservedHead),
- + gcmOPT_VALUE(ReservedTail));
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_QuerySystemMemory
- +**
- +** Query the command buffer alignment and number of reserved bytes.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Harwdare
- +** Pointer to an gckHARDWARE object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * SystemSize
- +** Pointer to a variable that receives the maximum size of the system
- +** memory.
- +**
- +** gctUINT32 * SystemBaseAddress
- +** Poinetr to a variable that receives the base address for system
- +** memory.
- +*/
- +gceSTATUS
- +gckHARDWARE_QuerySystemMemory(
- + IN gckHARDWARE Hardware,
- + OUT gctSIZE_T * SystemSize,
- + OUT gctUINT32 * SystemBaseAddress
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + if (SystemSize != gcvNULL)
- + {
- + /* Maximum system memory can be 2GB. */
- + *SystemSize = 1U << 31;
- + }
- +
- + if (SystemBaseAddress != gcvNULL)
- + {
- + /* Set system memory base address. */
- + *SystemBaseAddress = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)));
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*SystemSize=%lu *SystemBaseAddress=%lu",
- + gcmOPT_VALUE(SystemSize), gcmOPT_VALUE(SystemBaseAddress));
- + return gcvSTATUS_OK;
- +}
- +
- +#ifndef VIVANTE_NO_3D
- +/*******************************************************************************
- +**
- +** gckHARDWARE_QueryShaderCaps
- +**
- +** Query the shader capabilities.
- +**
- +** INPUT:
- +**
- +** Nothing.
- +**
- +** OUTPUT:
- +**
- +** gctUINT * VertexUniforms
- +** Pointer to a variable receiving the number of uniforms in the vertex
- +** shader.
- +**
- +** gctUINT * FragmentUniforms
- +** Pointer to a variable receiving the number of uniforms in the
- +** fragment shader.
- +**
- +** gctUINT * Varyings
- +** Pointer to a variable receiving the maimum number of varyings.
- +*/
- +gceSTATUS
- +gckHARDWARE_QueryShaderCaps(
- + IN gckHARDWARE Hardware,
- + OUT gctUINT * VertexUniforms,
- + OUT gctUINT * FragmentUniforms,
- + OUT gctUINT * Varyings
- + )
- +{
- + gctUINT32 vsConstMax;
- + gctUINT32 psConstMax;
- +
- + gcmkHEADER_ARG("Hardware=0x%x VertexUniforms=0x%x "
- + "FragmentUniforms=0x%x Varyings=0x%x",
- + Hardware, VertexUniforms,
- + FragmentUniforms, Varyings);
- +
- + if ((Hardware->identity.chipModel == gcv2000)
- + && (Hardware->identity.chipRevision == 0x5118))
- + {
- + vsConstMax = 256;
- + psConstMax = 64;
- + }
- + else if (Hardware->identity.numConstants > 256)
- + {
- + vsConstMax = 256;
- + psConstMax = 256;
- + }
- + else if (Hardware->identity.numConstants == 256)
- + {
- + vsConstMax = 256;
- + psConstMax = 256;
- + }
- + else
- + {
- + vsConstMax = 168;
- + psConstMax = 64;
- + }
- +
- + if (VertexUniforms != gcvNULL)
- + {
- + *VertexUniforms = vsConstMax;
- + }
- +
- + if (FragmentUniforms != gcvNULL)
- + {
- + *FragmentUniforms = psConstMax;
- + }
- +
- + if (Varyings != gcvNULL)
- + {
- + /* Return the shader varyings count. */
- + *Varyings = Hardware->identity.varyingsCount;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_SetMMU
- +**
- +** Set the page table base address.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Harwdare
- +** Pointer to an gckHARDWARE object.
- +**
- +** gctPOINTER Logical
- +** Logical address of the page table.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckHARDWARE_SetMMU(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 address = 0;
- + gctUINT32 baseAddress;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x", Hardware, Logical);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- +
- + /* Convert the logical address into an hardware address. */
- + gcmkONERROR(
- + gckHARDWARE_ConvertLogical(Hardware, Logical, &address));
- +
- + /* Also get the base address - we need a real physical address. */
- + gcmkONERROR(
- + gckOS_GetBaseAddress(Hardware->os, &baseAddress));
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Setting page table to 0x%08X",
- + address + baseAddress);
- +
- + /* Write the AQMemoryFePageTable register. */
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00400,
- + address + baseAddress));
- +
- + /* Write the AQMemoryRaPageTable register. */
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00410,
- + address + baseAddress));
- +
- + /* Write the AQMemoryTxPageTable register. */
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00404,
- + address + baseAddress));
- +
- +
- + /* Write the AQMemoryPePageTable register. */
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00408,
- + address + baseAddress));
- +
- + /* Write the AQMemoryPezPageTable register. */
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x0040C,
- + address + baseAddress));
- +
- + /* Return the status. */
- + gcmkFOOTER_NO();
- + return status;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_FlushMMU
- +**
- +** Flush the page table.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Harwdare
- +** Pointer to an gckHARDWARE object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckHARDWARE_FlushMMU(
- + IN gckHARDWARE Hardware
- + )
- +{
- + gceSTATUS status;
- + gckCOMMAND command;
- + gctUINT32_PTR buffer;
- + gctSIZE_T bufferSize;
- + gctBOOL commitEntered = gcvFALSE;
- + gctPOINTER pointer = gcvNULL;
- + gctUINT32 flushSize;
- + gctUINT32 count;
- + gctUINT32 physical;
- +
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + /* Verify the gckCOMMAND object pointer. */
- + command = Hardware->kernel->command;
- +
- + /* Acquire the command queue. */
- + gcmkONERROR(gckCOMMAND_EnterCommit(command, gcvFALSE));
- + commitEntered = gcvTRUE;
- +
- + /* Flush the memory controller. */
- + if (Hardware->mmuVersion == 0)
- + {
- + gcmkONERROR(gckCOMMAND_Reserve(
- + command, 8, &pointer, &bufferSize
- + ));
- +
- + buffer = (gctUINT32_PTR) pointer;
- +
- + buffer[0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E04) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + buffer[1]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
- +
- + gcmkONERROR(gckCOMMAND_Execute(command, 8));
- + }
- + else
- + {
- + flushSize = 16 * 4;
- +
- + gcmkONERROR(gckCOMMAND_Reserve(
- + command, flushSize, &pointer, &bufferSize
- + ));
- +
- + buffer = (gctUINT32_PTR) pointer;
- +
- + count = (bufferSize - flushSize + 7) >> 3;
- +
- + gcmkONERROR(gckOS_GetPhysicalAddress(command->os, buffer, &physical));
- +
- + /* Flush cache. */
- + buffer[0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + buffer[1]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
- +
- + /* Arm the PE-FE Semaphore. */
- + buffer[2]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + buffer[3]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
- +
- + /* STALL FE until PE is done flushing. */
- + buffer[4]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
- +
- + buffer[5]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
- +
- + /* LINK to next slot to flush FE FIFO. */
- + buffer[6]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + buffer[7]
- + = physical + 8 * gcmSIZEOF(gctUINT32);
- +
- + /* Flush MMU cache. */
- + buffer[8]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + buffer[9]
- + = (((((gctUINT32) (~0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) & ((((gctUINT32) (~0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))));
- +
- + /* Arm the PE-FE Semaphore. */
- + buffer[10]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + buffer[11]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
- +
- + /* STALL FE until PE is done flushing. */
- + buffer[12]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
- +
- + buffer[13]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
- +
- + /* LINK to next slot to flush FE FIFO. */
- + buffer[14]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (count) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
- +
- + buffer[15]
- + = physical + flushSize;
- +
- + gcmkONERROR(gckCOMMAND_Execute(command, flushSize));
- + }
- +
- + /* Release the command queue. */
- + gcmkONERROR(gckCOMMAND_ExitCommit(command, gcvFALSE));
- + commitEntered = gcvFALSE;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (commitEntered)
- + {
- + /* Release the command queue mutex. */
- + gcmkVERIFY_OK(gckCOMMAND_ExitCommit(Hardware->kernel->command,
- + gcvFALSE));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_SetMMUv2
- +**
- +** Set the page table base address.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Harwdare
- +** Pointer to an gckHARDWARE object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckHARDWARE_SetMMUv2(
- + IN gckHARDWARE Hardware,
- + IN gctBOOL Enable,
- + IN gctPOINTER MtlbAddress,
- + IN gceMMU_MODE Mode,
- + IN gctPOINTER SafeAddress,
- + IN gctBOOL FromPower
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 config, address;
- + gckCOMMAND command;
- + gctUINT32_PTR buffer;
- + gctSIZE_T bufferSize;
- + gctBOOL commitEntered = gcvFALSE;
- + gctPOINTER pointer = gcvNULL;
- + gctBOOL acquired = gcvFALSE;
- + gctBOOL config2D;
- + gctSIZE_T configSize;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Enable=%d", Hardware, Enable);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + config2D = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_PIPE_3D)
- + && gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_PIPE_2D);
- +
- + configSize = 4 * 4;
- +
- + if (config2D)
- + {
- + configSize +=
- + /* Pipe Select. */
- + 4 * 4
- + /* Configure MMU States. */
- + + 4 * 4;
- + }
- +
- + /* Convert logical address into physical address. */
- + gcmkONERROR(
- + gckOS_GetPhysicalAddress(Hardware->os, MtlbAddress, &config));
- +
- + gcmkONERROR(
- + gckOS_GetPhysicalAddress(Hardware->os, SafeAddress, &address));
- +
- + if (address & 0x3F)
- + {
- + gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
- + }
- +
- + switch (Mode)
- + {
- + case gcvMMU_MODE_1K:
- + if (config & 0x3FF)
- + {
- + gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
- + }
- +
- + config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
- +
- + break;
- +
- + case gcvMMU_MODE_4K:
- + if (config & 0xFFF)
- + {
- + gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
- + }
- +
- + config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
- +
- + break;
- +
- + default:
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + /* Verify the gckCOMMAND object pointer. */
- + command = Hardware->kernel->command;
- +
- + /* Acquire the command queue. */
- + gcmkONERROR(gckCOMMAND_EnterCommit(command, FromPower));
- + commitEntered = gcvTRUE;
- +
- + gcmkONERROR(gckCOMMAND_Reserve(
- + command, configSize, &pointer, &bufferSize
- + ));
- +
- + buffer = pointer;
- +
- + buffer[0]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + buffer[1] = config;
- +
- + buffer[2]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0060) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + buffer[3] = address;
- +
- + if (config2D)
- + {
- + /* LoadState(AQPipeSelect, 1), pipe. */
- + buffer[4]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + buffer[5] = 0x1;
- +
- + buffer[6]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + buffer[7] = config;
- +
- + buffer[8]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0060) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + buffer[9] = address;
- +
- + /* LoadState(AQPipeSelect, 1), pipe. */
- + buffer[10]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + buffer[11] = 0x0;
- + }
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Setup MMU: config=%08x, Safe Address=%08x\n.", config, address);
- +
- + gcmkONERROR(gckCOMMAND_Execute(command, configSize));
- +
- + if (FromPower == gcvFALSE)
- + {
- + /* Acquire global semaphore to suspend power management until MMU
- + ** is enabled. And acquired it before gckCOMMAND_ExitCommit to
- + ** make sure GPU keeps ON. */
- + gcmkONERROR(
- + gckOS_AcquireSemaphore(Hardware->os, Hardware->globalSemaphore));
- +
- + acquired = gcvTRUE;
- + }
- +
- + /* Release the command queue. */
- + gcmkONERROR(gckCOMMAND_ExitCommit(command, FromPower));
- + commitEntered = gcvFALSE;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "call gckCOMMAND_Stall to make sure the config is done.\n ");
- +
- + gcmkONERROR(gckCOMMAND_Stall(command, FromPower));
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Enable MMU through GCREG_MMU_CONTROL.");
- +
- + /* Enable MMU. */
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x0018C,
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (Enable) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))));
- +
- + if (FromPower == gcvFALSE)
- + {
- + /* Relase global semaphore. */
- + gcmkVERIFY_OK(
- + gckOS_ReleaseSemaphore(Hardware->os, Hardware->globalSemaphore));
- +
- + acquired = gcvFALSE;
- + }
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "call gckCOMMAND_Stall to check MMU available.\n");
- +
- + gcmkONERROR(gckCOMMAND_Stall(command, FromPower));
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "The MMU is available.\n");
- +
- + /* Return the status. */
- + gcmkFOOTER_NO();
- + return status;
- +
- +OnError:
- + if (commitEntered)
- + {
- + /* Release the command queue mutex. */
- + gcmkVERIFY_OK(gckCOMMAND_ExitCommit(Hardware->kernel->command,
- + FromPower));
- + }
- +
- + if (acquired)
- + {
- + gcmkVERIFY_OK(
- + gckOS_ReleaseSemaphore(Hardware->os, Hardware->globalSemaphore));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_BuildVirtualAddress
- +**
- +** Build a virtual address.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Harwdare
- +** Pointer to an gckHARDWARE object.
- +**
- +** gctUINT32 Index
- +** Index into page table.
- +**
- +** gctUINT32 Offset
- +** Offset into page.
- +**
- +** OUTPUT:
- +**
- +** gctUINT32 * Address
- +** Pointer to a variable receiving te hardware address.
- +*/
- +gceSTATUS
- +gckHARDWARE_BuildVirtualAddress(
- + IN gckHARDWARE Hardware,
- + IN gctUINT32 Index,
- + IN gctUINT32 Offset,
- + OUT gctUINT32 * Address
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x Index=%u Offset=%u", Hardware, Index, Offset);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(Address != gcvNULL);
- +
- + /* Build virtual address. */
- + *Address = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0))) | (((gctUINT32) ((gctUINT32) (Offset | (Index << 12)) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0)));
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Address=0x%08x", *Address);
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckHARDWARE_GetIdle(
- + IN gckHARDWARE Hardware,
- + IN gctBOOL Wait,
- + OUT gctUINT32 * Data
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 idle = 0;
- + gctINT retry, poll, pollCount;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Wait=%d", Hardware, Wait);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(Data != gcvNULL);
- +
- +
- + /* If we have to wait, try 100 polls per millisecond. */
- + pollCount = Wait ? 100 : 1;
- +
- + /* At most, try for 1 second. */
- + for (retry = 0; retry < 1000; ++retry)
- + {
- + /* If we have to wait, try 100 polls per millisecond. */
- + for (poll = pollCount; poll > 0; --poll)
- + {
- + /* Read register. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00004, &idle));
- +
- + /* See if we have to wait for FE idle. */
- + if ((((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
- + {
- + /* FE is idle. */
- + break;
- + }
- + }
- +
- + /* Check if we need to wait for FE and FE is busy. */
- + if (Wait && !(((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
- + {
- + /* Wait a little. */
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "%s: Waiting for idle: 0x%08X",
- + __FUNCTION__, idle);
- +
- + gcmkVERIFY_OK(gckOS_Delay(Hardware->os, 1));
- + }
- + else
- + {
- + break;
- + }
- + }
- +
- + /* Return idle to caller. */
- + *Data = idle;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Data=0x%08x", *Data);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/* Flush the caches. */
- +gceSTATUS
- +gckHARDWARE_Flush(
- + IN gckHARDWARE Hardware,
- + IN gceKERNEL_FLUSH Flush,
- + IN gctPOINTER Logical,
- + IN OUT gctSIZE_T * Bytes
- + )
- +{
- + gctUINT32 pipe;
- + gctUINT32 flush = 0;
- + gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
- + gceSTATUS status;
- + gctBOOL fcFlushStall;
- + gctUINT32 reserveBytes = 8;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Flush=0x%x Logical=0x%x *Bytes=%lu",
- + Hardware, Flush, Logical, gcmOPT_VALUE(Bytes));
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + /* Get current pipe. */
- + pipe = Hardware->kernel->command->pipeSelect;
- +
- + fcFlushStall
- + = ((((gctUINT32) (Hardware->identity.chipMinorFeatures1)) >> (0 ? 31:31) & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1)))))))
- + && (Flush == gcvFLUSH_ALL)
- + ;
- +
- + if (fcFlushStall)
- + {
- + reserveBytes += 8;
- + }
- +
- + /* Flush 3D color cache. */
- + if ((Flush & gcvFLUSH_COLOR) && (pipe == 0x0))
- + {
- + flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)));
- + }
- +
- + /* Flush 3D depth cache. */
- + if ((Flush & gcvFLUSH_DEPTH) && (pipe == 0x0))
- + {
- + flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
- + }
- +
- + /* Flush 3D texture cache. */
- + if ((Flush & gcvFLUSH_TEXTURE) && (pipe == 0x0))
- + {
- + flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)));
- + flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
- + }
- +
- + /* Flush 2D cache. */
- + if ((Flush & gcvFLUSH_2D) && (pipe == 0x1))
- + {
- + flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)));
- + }
- +
- + /* See if there is a valid flush. */
- + if (flush == 0)
- + {
- + if (Bytes != gcvNULL)
- + {
- + /* No bytes required. */
- + *Bytes = 0;
- + }
- + }
- +
- + else
- + {
- + /* Copy to command queue. */
- + if (Logical != gcvNULL)
- + {
- + if (*Bytes < reserveBytes)
- + {
- + /* Command queue too small. */
- + gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
- + }
- +
- + /* Append LOAD_STATE to AQFlush. */
- + logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + logical[1] = flush;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "0x%x: FLUSH 0x%x", logical, flush);
- +
- + if (fcFlushStall)
- + {
- + logical[2] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0594) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
- +
- + logical[3] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
- +
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "0x%x: FLUSH 0x%x", logical + 3, logical[3]);
- + }
- +
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* bytes required. */
- + *Bytes = reserveBytes;
- + }
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckHARDWARE_SetFastClear(
- + IN gckHARDWARE Hardware,
- + IN gctINT Enable,
- + IN gctINT Compression
- + )
- +{
- +#ifndef VIVANTE_NO_3D
- + gctUINT32 debug;
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Enable=%d Compression=%d",
- + Hardware, Enable, Compression);
- +
- + /* Only process if fast clear is available. */
- + if ((((((gctUINT32) (Hardware->identity.chipFeatures)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
- + {
- + if (Enable == -1)
- + {
- + /* Determine automatic value for fast clear. */
- + Enable = ((Hardware->identity.chipModel != gcv500)
- + || (Hardware->identity.chipRevision >= 3)
- + ) ? 1 : 0;
- + }
- +
- + if (Compression == -1)
- + {
- + /* Determine automatic value for compression. */
- + Compression = Enable
- + & (((((gctUINT32) (Hardware->identity.chipFeatures)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) );
- + }
- +
- + /* Read AQMemoryDebug register. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00414, &debug));
- +
- + /* Set fast clear bypass. */
- + debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20))) | (((gctUINT32) ((gctUINT32) (Enable == 0) & ((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20)));
- +
- + if (
- + ((((gctUINT32) (Hardware->identity.chipMinorFeatures2)) >> (0 ? 27:27) & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1))))))) ||
- + (Hardware->identity.chipModel >= gcv4000))
- + {
- + /* Set compression bypass. */
- + debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))) << (0 ? 21:21))) | (((gctUINT32) ((gctUINT32) (Compression == 0) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))) << (0 ? 21:21)));
- + }
- +
- + /* Write back AQMemoryDebug register. */
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00414,
- + debug));
- +
- + /* Store fast clear and comprersison flags. */
- + Hardware->allowFastClear = Enable;
- + Hardware->allowCompression = Compression;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "FastClear=%d Compression=%d", Enable, Compression);
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +#else
- + return gcvSTATUS_OK;
- +#endif
- +}
- +
- +typedef enum
- +{
- + gcvPOWER_FLAG_INITIALIZE = 1 << 0,
- + gcvPOWER_FLAG_STALL = 1 << 1,
- + gcvPOWER_FLAG_STOP = 1 << 2,
- + gcvPOWER_FLAG_START = 1 << 3,
- + gcvPOWER_FLAG_RELEASE = 1 << 4,
- + gcvPOWER_FLAG_DELAY = 1 << 5,
- + gcvPOWER_FLAG_SAVE = 1 << 6,
- + gcvPOWER_FLAG_ACQUIRE = 1 << 7,
- + gcvPOWER_FLAG_POWER_OFF = 1 << 8,
- + gcvPOWER_FLAG_CLOCK_OFF = 1 << 9,
- + gcvPOWER_FLAG_CLOCK_ON = 1 << 10,
- +}
- +gcePOWER_FLAGS;
- +
- +#if gcmIS_DEBUG(gcdDEBUG_TRACE)
- +static gctCONST_STRING
- +_PowerEnum(gceCHIPPOWERSTATE State)
- +{
- + const gctCONST_STRING states[] =
- + {
- + gcmSTRING(gcvPOWER_ON),
- + gcmSTRING(gcvPOWER_OFF),
- + gcmSTRING(gcvPOWER_IDLE),
- + gcmSTRING(gcvPOWER_SUSPEND),
- + gcmSTRING(gcvPOWER_SUSPEND_ATPOWERON),
- + gcmSTRING(gcvPOWER_OFF_ATPOWERON),
- + gcmSTRING(gcvPOWER_IDLE_BROADCAST),
- + gcmSTRING(gcvPOWER_SUSPEND_BROADCAST),
- + gcmSTRING(gcvPOWER_OFF_BROADCAST),
- + gcmSTRING(gcvPOWER_OFF_RECOVERY),
- + gcmSTRING(gcvPOWER_ON_AUTO)
- + };
- +
- + if ((State >= gcvPOWER_ON) && (State <= gcvPOWER_ON_AUTO))
- + {
- + return states[State - gcvPOWER_ON];
- + }
- +
- + return "unknown";
- +}
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_SetPowerManagementState
- +**
- +** Set GPU to a specified power state.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Harwdare
- +** Pointer to an gckHARDWARE object.
- +**
- +** gceCHIPPOWERSTATE State
- +** Power State.
- +**
- +*/
- +gceSTATUS
- +gckHARDWARE_SetPowerManagementState(
- + IN gckHARDWARE Hardware,
- + IN gceCHIPPOWERSTATE State
- + )
- +{
- + gceSTATUS status;
- + gckCOMMAND command = gcvNULL;
- + gckOS os;
- + gctUINT flag, clock;
- + gctPOINTER buffer;
- + gctSIZE_T bytes, requested;
- + gctBOOL acquired = gcvFALSE;
- + gctBOOL mutexAcquired = gcvFALSE;
- + gctBOOL stall = gcvTRUE;
- + gctBOOL broadcast = gcvFALSE;
- +#if gcdPOWEROFF_TIMEOUT
- + gctBOOL timeout = gcvFALSE;
- + gctBOOL isAfter = gcvFALSE;
- + gctUINT32 currentTime;
- +#endif
- + gctUINT32 process, thread;
- + gctBOOL commitEntered = gcvFALSE;
- + gctBOOL commandStarted = gcvFALSE;
- + gctBOOL isrStarted = gcvFALSE;
- +
- +#if gcdENABLE_PROFILING
- + gctUINT64 time, freq, mutexTime, onTime, stallTime, stopTime, delayTime,
- + initTime, offTime, startTime, totalTime;
- +#endif
- + gctBOOL global = gcvFALSE;
- + gctBOOL globalAcquired = gcvFALSE;
- + gctBOOL configMmu = gcvFALSE;
- +
- + /* State transition flags. */
- + static const gctUINT flags[4][4] =
- + {
- + /* gcvPOWER_ON */
- + { /* ON */ 0,
- + /* OFF */ gcvPOWER_FLAG_ACQUIRE |
- + gcvPOWER_FLAG_STALL |
- + gcvPOWER_FLAG_STOP |
- + gcvPOWER_FLAG_POWER_OFF |
- + gcvPOWER_FLAG_CLOCK_OFF,
- + /* IDLE */ gcvPOWER_FLAG_ACQUIRE |
- + gcvPOWER_FLAG_STALL,
- + /* SUSPEND */ gcvPOWER_FLAG_ACQUIRE |
- + gcvPOWER_FLAG_STALL |
- + gcvPOWER_FLAG_STOP |
- + gcvPOWER_FLAG_CLOCK_OFF,
- + },
- +
- + /* gcvPOWER_OFF */
- + { /* ON */ gcvPOWER_FLAG_INITIALIZE |
- + gcvPOWER_FLAG_START |
- + gcvPOWER_FLAG_RELEASE |
- + gcvPOWER_FLAG_DELAY,
- + /* OFF */ 0,
- + /* IDLE */ gcvPOWER_FLAG_INITIALIZE |
- + gcvPOWER_FLAG_START |
- + gcvPOWER_FLAG_DELAY,
- + /* SUSPEND */ gcvPOWER_FLAG_INITIALIZE |
- + gcvPOWER_FLAG_CLOCK_OFF,
- + },
- +
- + /* gcvPOWER_IDLE */
- + { /* ON */ gcvPOWER_FLAG_RELEASE,
- + /* OFF */ gcvPOWER_FLAG_STOP |
- + gcvPOWER_FLAG_POWER_OFF |
- + gcvPOWER_FLAG_CLOCK_OFF,
- + /* IDLE */ 0,
- + /* SUSPEND */ gcvPOWER_FLAG_STOP |
- + gcvPOWER_FLAG_CLOCK_OFF,
- + },
- +
- + /* gcvPOWER_SUSPEND */
- + { /* ON */ gcvPOWER_FLAG_START |
- + gcvPOWER_FLAG_RELEASE |
- + gcvPOWER_FLAG_DELAY |
- + gcvPOWER_FLAG_CLOCK_ON,
- + /* OFF */ gcvPOWER_FLAG_SAVE |
- + gcvPOWER_FLAG_POWER_OFF |
- + gcvPOWER_FLAG_CLOCK_OFF,
- + /* IDLE */ gcvPOWER_FLAG_START |
- + gcvPOWER_FLAG_DELAY |
- + gcvPOWER_FLAG_CLOCK_ON,
- + /* SUSPEND */ 0,
- + },
- + };
- +
- + /* Clocks. */
- + static const gctUINT clocks[4] =
- + {
- + /* gcvPOWER_ON */
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) |
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) |
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (64) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) |
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))),
- +
- + /* gcvPOWER_OFF */
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) |
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) |
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) |
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))),
- +
- + /* gcvPOWER_IDLE */
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) |
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) |
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) |
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))),
- +
- + /* gcvPOWER_SUSPEND */
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) |
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) |
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) |
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))),
- + };
- +
- + gcmkHEADER_ARG("Hardware=0x%x State=%d", Hardware, State);
- +#if gcmIS_DEBUG(gcdDEBUG_TRACE)
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Switching to power state %d(%s)",
- + State, _PowerEnum(State));
- +#endif
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + /* Get the gckOS object pointer. */
- + os = Hardware->os;
- + gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
- +
- + /* Get the gckCOMMAND object pointer. */
- + gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
- + command = Hardware->kernel->command;
- + gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
- +
- + if (Hardware->powerManagement == gcvFALSE)
- + {
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- +
- + /* Start profiler. */
- + gcmkPROFILE_INIT(freq, time);
- +
- + /* Convert the broadcast power state. */
- + switch (State)
- + {
- + case gcvPOWER_SUSPEND_ATPOWERON:
- + /* Convert to SUSPEND and don't wait for STALL. */
- + State = gcvPOWER_SUSPEND;
- + stall = gcvFALSE;
- + break;
- +
- + case gcvPOWER_OFF_ATPOWERON:
- + /* Convert to OFF and don't wait for STALL. */
- + State = gcvPOWER_OFF;
- + stall = gcvFALSE;
- + break;
- +
- + case gcvPOWER_IDLE_BROADCAST:
- + /* Convert to IDLE and note we are inside broadcast. */
- + State = gcvPOWER_IDLE;
- + broadcast = gcvTRUE;
- + break;
- +
- + case gcvPOWER_SUSPEND_BROADCAST:
- + /* Convert to SUSPEND and note we are inside broadcast. */
- + State = gcvPOWER_SUSPEND;
- + broadcast = gcvTRUE;
- + break;
- +
- + case gcvPOWER_OFF_BROADCAST:
- + /* Convert to OFF and note we are inside broadcast. */
- + State = gcvPOWER_OFF;
- + broadcast = gcvTRUE;
- + break;
- +
- + case gcvPOWER_OFF_RECOVERY:
- + /* Convert to OFF and note we are inside recovery. */
- + State = gcvPOWER_OFF;
- + stall = gcvFALSE;
- + broadcast = gcvTRUE;
- + break;
- +
- + case gcvPOWER_ON_AUTO:
- + /* Convert to ON and note we are inside recovery. */
- + State = gcvPOWER_ON;
- + break;
- +
- + case gcvPOWER_ON:
- + case gcvPOWER_IDLE:
- + case gcvPOWER_SUSPEND:
- + case gcvPOWER_OFF:
- + /* Mark as global power management. */
- + global = gcvTRUE;
- + break;
- +
- +#if gcdPOWEROFF_TIMEOUT
- + case gcvPOWER_OFF_TIMEOUT:
- + /* Convert to OFF and note we are inside broadcast. */
- + State = gcvPOWER_OFF;
- + broadcast = gcvTRUE;
- + /* Check time out */
- + timeout = gcvTRUE;
- + break;
- +#endif
- +
- + default:
- + break;
- + }
- +
- + /* Get current process and thread IDs. */
- + gcmkONERROR(gckOS_GetProcessID(&process));
- + gcmkONERROR(gckOS_GetThreadID(&thread));
- +
- + /* Before we grab locks see if this is actually a needed change */
- + if (State == Hardware->chipPowerState)
- + return gcvSTATUS_OK;
- +
- + if (broadcast)
- + {
- + /* Try to acquire the power mutex. */
- + status = gckOS_AcquireMutex(os, Hardware->powerMutex, 0);
- +
- + if (status == gcvSTATUS_TIMEOUT)
- + {
- + /* Check if we already own this mutex. */
- + if ((Hardware->powerProcess == process)
- + && (Hardware->powerThread == thread)
- + )
- + {
- + /* Bail out on recursive power management. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- + else if (State == gcvPOWER_IDLE || State == gcvPOWER_SUSPEND)
- + {
- + /* Called from IST,
- + ** so waiting here will cause deadlock,
- + ** if lock holder call gckCOMMAND_Stall() */
- + gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
- + }
- +#if gcdPOWEROFF_TIMEOUT
- + else if(State == gcvPOWER_OFF && timeout == gcvTRUE)
- + {
- + /*
- + ** try to aqcuire the mutex with more milliseconds,
- + ** flush_delayed_work should be running with timeout,
- + ** so waiting here will cause deadlock */
- + status = gckOS_AcquireMutex(os, Hardware->powerMutex, gcdPOWEROFF_TIMEOUT);
- +
- + if (status == gcvSTATUS_TIMEOUT)
- + {
- + gckOS_Print("GPU Timer deadlock, exit by timeout!!!!\n");
- +
- + gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
- + }
- + }
- +#endif
- + else
- + {
- + /* Acquire the power mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(os,
- + Hardware->powerMutex,
- + gcvINFINITE));
- + }
- + }
- + }
- + else
- + {
- + /* Acquire the power mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(os, Hardware->powerMutex, gcvINFINITE));
- + }
- +
- + /* Get time until mtuex acquired. */
- + gcmkPROFILE_QUERY(time, mutexTime);
- +
- + Hardware->powerProcess = process;
- + Hardware->powerThread = thread;
- + mutexAcquired = gcvTRUE;
- +
- + /* Grab control flags and clock. */
- + flag = flags[Hardware->chipPowerState][State];
- + clock = clocks[State];
- +
- +#if gcdENABLE_FSCALE_VAL_ADJUST
- + if (State == gcvPOWER_ON)
- + {
- + clock = ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (Hardware->powerOnFscaleVal) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2)));
- + }
- +#endif
- +
- + if (State == gcvPOWER_SUSPEND && Hardware->chipPowerState == gcvPOWER_OFF && broadcast)
- + {
- +#if gcdPOWER_SUSNPEND_WHEN_IDLE
- + /* Do nothing */
- +
- + /* Release the power mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +#else
- + /* Clock should be on when switch power from off to suspend */
- + clock = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) |
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) |
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) |
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) ;
- +#endif
- + }
- +
- +#if gcdPOWEROFF_TIMEOUT
- + if (timeout)
- + {
- + gcmkONERROR(gckOS_GetTicks(¤tTime));
- +
- + gcmkONERROR(
- + gckOS_TicksAfter(Hardware->powerOffTime, currentTime, &isAfter));
- +
- + /* powerOffTime is pushed forward, give up.*/
- + if (isAfter
- + /* Expect a transition start from IDLE or SUSPEND. */
- + || (Hardware->chipPowerState == gcvPOWER_ON)
- + || (Hardware->chipPowerState == gcvPOWER_OFF)
- + )
- + {
- + /* Release the power mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
- +
- + /* No need to do anything. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Power Off GPU[%d] at %u [supposed to be at %u]",
- + Hardware->core, currentTime, Hardware->powerOffTime);
- + }
- +
- + if (State == gcvPOWER_ON || State == gcvPOWER_OFF)
- + {
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "Cancel powerOfftimer");
- +
- + /* Cancel running timer when GPU enters ON or OFF. */
- + gcmkVERIFY_OK(gckOS_StopTimer(os, Hardware->powerOffTimer));
- + }
- +#endif
- +
- + if (flag == 0)
- + {
- + /* Release the power mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
- +
- + /* No need to do anything. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- +
- + /* If this is an internal power management, we have to check if we can grab
- + ** the global power semaphore. If we cannot, we have to wait until the
- + ** external world changes power management. */
- + if (!global)
- + {
- + /* Try to acquire the global semaphore. */
- + status = gckOS_TryAcquireSemaphore(os, Hardware->globalSemaphore);
- + if (status == gcvSTATUS_TIMEOUT)
- + {
- + if (State == gcvPOWER_IDLE || State == gcvPOWER_SUSPEND)
- + {
- + /* Called from thread routine which should NEVER sleep.*/
- + gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
- + }
- +
- + /* Release the power mutex. */
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Releasing the power mutex.");
- + gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
- + mutexAcquired = gcvFALSE;
- +
- + /* Wait for the semaphore. */
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Waiting for global semaphore.");
- + gcmkONERROR(gckOS_AcquireSemaphore(os, Hardware->globalSemaphore));
- + globalAcquired = gcvTRUE;
- +
- + /* Acquire the power mutex. */
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "Reacquiring the power mutex.");
- + gcmkONERROR(gckOS_AcquireMutex(os,
- + Hardware->powerMutex,
- + gcvINFINITE));
- + mutexAcquired = gcvTRUE;
- +
- + /* chipPowerState may be changed by external world during the time
- + ** we give up powerMutex, so updating flag now is necessary. */
- + flag = flags[Hardware->chipPowerState][State];
- +
- + if (flag == 0)
- + {
- + gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->globalSemaphore));
- + globalAcquired = gcvFALSE;
- +
- + gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
- + mutexAcquired = gcvFALSE;
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- + }
- + else
- + {
- + /* Error. */
- + gcmkONERROR(status);
- + }
- +
- + /* Release the global semaphore again. */
- + gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->globalSemaphore));
- + globalAcquired = gcvFALSE;
- + }
- + else
- + {
- + if (State == gcvPOWER_OFF || State == gcvPOWER_SUSPEND || State == gcvPOWER_IDLE)
- + {
- + /* Acquire the global semaphore if it has not been acquired. */
- + status = gckOS_TryAcquireSemaphore(os, Hardware->globalSemaphore);
- + if (status == gcvSTATUS_OK)
- + {
- + globalAcquired = gcvTRUE;
- + }
- + else if (status != gcvSTATUS_TIMEOUT)
- + {
- + /* Other errors. */
- + gcmkONERROR(status);
- + }
- + /* Ignore gcvSTATUS_TIMEOUT and leave globalAcquired as gcvFALSE.
- + ** gcvSTATUS_TIMEOUT means global semaphore has already
- + ** been acquired before this operation, so even if we fail,
- + ** we should not release it in our error handling. It should be
- + ** released by the next successful global gcvPOWER_ON. */
- + }
- +
- + /* Global power management can't be aborted, so sync with
- + ** proceeding last commit. */
- + if (flag & gcvPOWER_FLAG_ACQUIRE)
- + {
- + /* Acquire the power management semaphore. */
- + gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
- + acquired = gcvTRUE;
- +
- + /* avoid acquiring again. */
- + flag &= ~gcvPOWER_FLAG_ACQUIRE;
- + }
- + }
- +
- + if (flag & (gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_CLOCK_ON))
- + {
- + /* Turn on the power. */
- + gcmkONERROR(gckOS_SetGPUPower(os, Hardware->core, gcvTRUE, gcvTRUE));
- +
- + /* Mark clock and power as enabled. */
- + Hardware->clockState = gcvTRUE;
- + Hardware->powerState = gcvTRUE;
- +
- + for (;;)
- + {
- + /* Check if GPU is present and awake. */
- + status = _IsGPUPresent(Hardware);
- +
- + /* Check if the GPU is not responding. */
- + if (status == gcvSTATUS_GPU_NOT_RESPONDING)
- + {
- + /* Turn off the power and clock. */
- + gcmkONERROR(gckOS_SetGPUPower(os, Hardware->core, gcvFALSE, gcvFALSE));
- +
- + Hardware->clockState = gcvFALSE;
- + Hardware->powerState = gcvFALSE;
- +
- + /* Wait a little. */
- + gckOS_Delay(os, 1);
- +
- + /* Turn on the power and clock. */
- + gcmkONERROR(gckOS_SetGPUPower(os, Hardware->core, gcvTRUE, gcvTRUE));
- +
- + Hardware->clockState = gcvTRUE;
- + Hardware->powerState = gcvTRUE;
- +
- + /* We need to initialize the hardware and start the command
- + * processor. */
- + flag |= gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_START;
- + }
- + else
- + {
- + /* Test for error. */
- + gcmkONERROR(status);
- +
- + /* Break out of loop. */
- + break;
- + }
- + }
- + }
- +
- + /* Get time until powered on. */
- + gcmkPROFILE_QUERY(time, onTime);
- +
- + if ((flag & gcvPOWER_FLAG_STALL) && stall)
- + {
- + gctBOOL idle;
- + gctINT32 atomValue;
- +
- + /* For global operation, all pending commits have already been
- + ** blocked by globalSemaphore or powerSemaphore.*/
- + if (!global)
- + {
- + /* Check commit atom. */
- + gcmkONERROR(gckOS_AtomGet(os, command->atomCommit, &atomValue));
- +
- + if (atomValue > 0)
- + {
- + /* Commits are pending - abort power management. */
- + status = broadcast ? gcvSTATUS_CHIP_NOT_READY
- + : gcvSTATUS_MORE_DATA;
- + goto OnError;
- + }
- + }
- +
- + if (broadcast)
- + {
- + /* Check for idle. */
- + gcmkONERROR(gckHARDWARE_QueryIdle(Hardware, &idle));
- +
- + if (!idle)
- + {
- + status = gcvSTATUS_CHIP_NOT_READY;
- + goto OnError;
- + }
- + }
- +
- + else
- + {
- + /* Acquire the command queue. */
- + gcmkONERROR(gckCOMMAND_EnterCommit(command, gcvTRUE));
- + commitEntered = gcvTRUE;
- +
- + /* Get the size of the flush command. */
- + gcmkONERROR(gckHARDWARE_Flush(Hardware,
- + gcvFLUSH_ALL,
- + gcvNULL,
- + &requested));
- +
- + /* Reserve space in the command queue. */
- + gcmkONERROR(gckCOMMAND_Reserve(command,
- + requested,
- + &buffer,
- + &bytes));
- +
- + /* Append a flush. */
- + gcmkONERROR(gckHARDWARE_Flush(
- + Hardware, gcvFLUSH_ALL, buffer, &bytes
- + ));
- +
- + /* Execute the command queue. */
- + gcmkONERROR(gckCOMMAND_Execute(command, requested));
- +
- + /* Release the command queue. */
- + gcmkONERROR(gckCOMMAND_ExitCommit(command, gcvTRUE));
- + commitEntered = gcvFALSE;
- +
- + /* Wait to finish all commands. */
- + gcmkONERROR(gckCOMMAND_Stall(command, gcvTRUE));
- + }
- + }
- +
- + /* Get time until stalled. */
- + gcmkPROFILE_QUERY(time, stallTime);
- +
- + if (flag & gcvPOWER_FLAG_ACQUIRE)
- + {
- + /* Acquire the power management semaphore. */
- + gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
- + acquired = gcvTRUE;
- + }
- +
- + if (flag & gcvPOWER_FLAG_STOP)
- + {
- + /* Stop the command parser. */
- + gcmkONERROR(gckCOMMAND_Stop(command, gcvFALSE));
- +
- + /* Stop the Isr. */
- + if (Hardware->stopIsr)
- + {
- + gcmkONERROR(Hardware->stopIsr(Hardware->isrContext, Hardware->core));
- + }
- + }
- +
- + /* Flush Cache before Power Off. */
- + if (flag & gcvPOWER_FLAG_POWER_OFF)
- + {
- + if (Hardware->clockState == gcvFALSE)
- + {
- + /* Turn off the GPU power. */
- + gcmkONERROR(
- + gckOS_SetGPUPower(os,
- + Hardware->core,
- + gcvTRUE,
- + gcvTRUE));
- +
- + Hardware->clockState = gcvTRUE;
- +
- + if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_DYNAMIC_FREQUENCY_SCALING) != gcvTRUE)
- + {
- + /* Write the clock control register. */
- + gcmkONERROR(gckOS_WriteRegisterEx(os,
- + Hardware->core,
- + 0x00000,
- + clocks[0]));
- +
- + /* Done loading the frequency scaler. */
- + gcmkONERROR(gckOS_WriteRegisterEx(os,
- + Hardware->core,
- + 0x00000,
- + ((((gctUINT32) (clocks[0])) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)))));
- + }
- + }
- +
- + gcmkONERROR(gckCOMMAND_Start(command));
- +
- + gcmkONERROR(_FlushCache(Hardware, command));
- +
- + gckOS_Delay(gcvNULL, 1);
- +
- + /* Stop the command parser. */
- + gcmkONERROR(gckCOMMAND_Stop(command, gcvFALSE));
- +
- + flag |= gcvPOWER_FLAG_CLOCK_OFF;
- + }
- +
- + /* Get time until stopped. */
- + gcmkPROFILE_QUERY(time, stopTime);
- +
- + /* Only process this when hardware is enabled. */
- + if (Hardware->clockState && Hardware->powerState
- + /* Don't touch clock control if dynamic frequency scaling is available. */
- + && gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_DYNAMIC_FREQUENCY_SCALING) != gcvTRUE
- + )
- + {
- + if (flag & (gcvPOWER_FLAG_POWER_OFF | gcvPOWER_FLAG_CLOCK_OFF))
- + {
- + if (Hardware->identity.chipModel == gcv4000
- + && Hardware->identity.chipRevision == 0x5208)
- + {
- + clock &= ~2U;
- + }
- + }
- +
- + /* Write the clock control register. */
- + gcmkONERROR(gckOS_WriteRegisterEx(os,
- + Hardware->core,
- + 0x00000,
- + clock));
- +
- + /* Done loading the frequency scaler. */
- + gcmkONERROR(gckOS_WriteRegisterEx(os,
- + Hardware->core,
- + 0x00000,
- + ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)))));
- + }
- +
- + if (flag & gcvPOWER_FLAG_DELAY)
- + {
- + /* Wait for the specified amount of time to settle coming back from
- + ** power-off or suspend state. */
- + gcmkONERROR(gckOS_Delay(os, gcdPOWER_CONTROL_DELAY));
- + }
- +
- + /* Get time until delayed. */
- + gcmkPROFILE_QUERY(time, delayTime);
- +
- + if (flag & gcvPOWER_FLAG_INITIALIZE)
- + {
- + /* Initialize hardware. */
- + gcmkONERROR(gckHARDWARE_InitializeHardware(Hardware));
- +
- + gcmkONERROR(gckHARDWARE_SetFastClear(Hardware,
- + Hardware->allowFastClear,
- + Hardware->allowCompression));
- +
- + /* Force the command queue to reload the next context. */
- + command->currContext = gcvNULL;
- +
- + /* Need to config mmu after command start. */
- + configMmu = gcvTRUE;
- + }
- +
- + /* Get time until initialized. */
- + gcmkPROFILE_QUERY(time, initTime);
- +
- + if (flag & (gcvPOWER_FLAG_POWER_OFF | gcvPOWER_FLAG_CLOCK_OFF))
- + {
- + /* Turn off the GPU power. */
- + gcmkONERROR(
- + gckOS_SetGPUPower(os,
- + Hardware->core,
- + (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
- + : gcvTRUE,
- + (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
- + : gcvTRUE));
- +
- + /* Save current hardware power and clock states. */
- + Hardware->clockState = (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
- + : gcvTRUE;
- + Hardware->powerState = (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
- + : gcvTRUE;
- + }
- +
- + /* Get time until off. */
- + gcmkPROFILE_QUERY(time, offTime);
- +
- + if (flag & gcvPOWER_FLAG_START)
- + {
- + /* Start the command processor. */
- + gcmkONERROR(gckCOMMAND_Start(command));
- + commandStarted = gcvTRUE;
- +
- + if (Hardware->startIsr)
- + {
- + /* Start the Isr. */
- + gcmkONERROR(Hardware->startIsr(Hardware->isrContext, Hardware->core));
- + isrStarted = gcvTRUE;
- + }
- +
- + /* Set NEW MMU. */
- + if (Hardware->mmuVersion != 0 && configMmu)
- + {
- + gcmkONERROR(
- + gckHARDWARE_SetMMUv2(
- + Hardware,
- + gcvTRUE,
- + Hardware->kernel->mmu->mtlbLogical,
- + gcvMMU_MODE_4K,
- + (gctUINT8_PTR)Hardware->kernel->mmu->mtlbLogical + gcdMMU_MTLB_SIZE,
- + gcvTRUE
- + ));
- + }
- + }
- +
- + /* Get time until started. */
- + gcmkPROFILE_QUERY(time, startTime);
- +
- + if (flag & gcvPOWER_FLAG_RELEASE)
- + {
- + /* Release the power management semaphore. */
- + gcmkONERROR(gckOS_ReleaseSemaphore(os, command->powerSemaphore));
- + acquired = gcvFALSE;
- +
- + if (global)
- + {
- + /* Verify global semaphore has been acquired already before
- + ** we release it.
- + ** If it was acquired, gckOS_TryAcquireSemaphore will return
- + ** gcvSTATUS_TIMEOUT and we release it. Otherwise, global
- + ** semaphore will be acquried now, but it still is released
- + ** immediately. */
- + status = gckOS_TryAcquireSemaphore(os, Hardware->globalSemaphore);
- + if (status != gcvSTATUS_TIMEOUT)
- + {
- + gcmkONERROR(status);
- + }
- +
- + /* Release the global semaphore. */
- + gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->globalSemaphore));
- + globalAcquired = gcvFALSE;
- + }
- + }
- +
- + /* Save the new power state. */
- + Hardware->chipPowerState = State;
- +
- +#if gcdDVFS
- + if (State == gcvPOWER_ON && Hardware->kernel->dvfs)
- + {
- + gckDVFS_Start(Hardware->kernel->dvfs);
- + }
- +#endif
- +
- +#if gcdPOWEROFF_TIMEOUT
- + if (State == gcvPOWER_IDLE || State == gcvPOWER_SUSPEND)
- + {
- + gcmkONERROR(gckOS_GetTicks(¤tTime));
- +
- + Hardware->powerOffTime = currentTime + Hardware->powerOffTimeout;
- + /* Start a timer to power off GPU when GPU enters IDLE or SUSPEND. */
- + gcmkVERIFY_OK(gckOS_StartTimer(os,
- + Hardware->powerOffTimer,
- + Hardware->powerOffTimeout));
- + }
- +#endif
- +
- + /* Release the power mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
- +
- + /* Get total time. */
- + gcmkPROFILE_QUERY(time, totalTime);
- +#if gcdENABLE_PROFILING
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "PROF(%llu): mutex:%llu on:%llu stall:%llu stop:%llu",
- + freq, mutexTime, onTime, stallTime, stopTime);
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + " delay:%llu init:%llu off:%llu start:%llu total:%llu",
- + delayTime, initTime, offTime, startTime, totalTime);
- +#endif
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (commandStarted)
- + {
- + gcmkVERIFY_OK(gckCOMMAND_Stop(command, gcvFALSE));
- + }
- +
- + if (isrStarted)
- + {
- + gcmkVERIFY_OK(Hardware->stopIsr(Hardware->isrContext, Hardware->core));
- + }
- +
- + if (commitEntered)
- + {
- + /* Release the command queue mutex. */
- + gcmkVERIFY_OK(gckCOMMAND_ExitCommit(command, gcvTRUE));
- + }
- +
- + if (acquired)
- + {
- + /* Release semaphore. */
- + gcmkVERIFY_OK(gckOS_ReleaseSemaphore(Hardware->os,
- + command->powerSemaphore));
- + }
- +
- + if (globalAcquired)
- + {
- + gcmkVERIFY_OK(gckOS_ReleaseSemaphore(Hardware->os,
- + Hardware->globalSemaphore));
- + }
- +
- + if (mutexAcquired)
- + {
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_QueryPowerManagementState
- +**
- +** Get GPU power state.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Harwdare
- +** Pointer to an gckHARDWARE object.
- +**
- +** gceCHIPPOWERSTATE* State
- +** Power State.
- +**
- +*/
- +gceSTATUS
- +gckHARDWARE_QueryPowerManagementState(
- + IN gckHARDWARE Hardware,
- + OUT gceCHIPPOWERSTATE* State
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(State != gcvNULL);
- +
- + /* Return the statue. */
- + *State = Hardware->chipPowerState;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*State=%d", *State);
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_SetPowerManagement
- +**
- +** Configure GPU power management function.
- +** Only used in driver initialization stage.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Harwdare
- +** Pointer to an gckHARDWARE object.
- +**
- +** gctBOOL PowerManagement
- +** Power Mangement State.
- +**
- +*/
- +gceSTATUS
- +gckHARDWARE_SetPowerManagement(
- + IN gckHARDWARE Hardware,
- + IN gctBOOL PowerManagement
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + Hardware->powerManagement = PowerManagement;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_SetGpuProfiler
- +**
- +** Configure GPU profiler function.
- +** Only used in driver initialization stage.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Harwdare
- +** Pointer to an gckHARDWARE object.
- +**
- +** gctBOOL GpuProfiler
- +** GOU Profiler State.
- +**
- +*/
- +gceSTATUS
- +gckHARDWARE_SetGpuProfiler(
- + IN gckHARDWARE Hardware,
- + IN gctBOOL GpuProfiler
- + )
- +{
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + Hardware->gpuProfiler = GpuProfiler;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +#if gcdENABLE_FSCALE_VAL_ADJUST
- +gceSTATUS
- +gckHARDWARE_SetFscaleValue(
- + IN gckHARDWARE Hardware,
- + IN gctUINT32 FscaleValue
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 clock;
- + gctBOOL acquired = gcvFALSE;
- +
- + gcmkHEADER_ARG("Hardware=0x%x FscaleValue=%d", Hardware, FscaleValue);
- +
- + gcmkVERIFY_ARGUMENT(FscaleValue > 0 && FscaleValue <= 64);
- +
- + gcmkONERROR(
- + gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + Hardware->powerOnFscaleVal = FscaleValue;
- +
- + if (Hardware->chipPowerState == gcvPOWER_ON)
- + {
- + gctUINT32 data;
- +
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + Hardware->powerBaseAddress
- + + 0x00104,
- + &data));
- +
- + /* Disable all clock gating. */
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + Hardware->powerBaseAddress
- + + 0x00104,
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ? 8:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ? 8:8)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1))))))) << (0 ? 11:11))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1))))))) << (0 ? 11:11)))));
- +
- + clock = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (FscaleValue) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00000,
- + clock));
- +
- + /* Done loading the frequency scaler. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00000,
- + ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)))));
- +
- + /* Restore all clock gating. */
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + Hardware->powerBaseAddress
- + + 0x00104,
- + data));
- + }
- +
- + gcmkVERIFY(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + gcmkVERIFY(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckHARDWARE_GetFscaleValue(
- + IN gckHARDWARE Hardware,
- + IN gctUINT * FscaleValue,
- + IN gctUINT * MinFscaleValue,
- + IN gctUINT * MaxFscaleValue
- + )
- +{
- + *FscaleValue = Hardware->powerOnFscaleVal;
- + if ((gpu3DMinClock > 0) && (gpu3DMinClock <= 64) && (Hardware->core == gcvCORE_MAJOR))
- + *MinFscaleValue = gpu3DMinClock;
- + else
- + *MinFscaleValue = 1;
- + *MaxFscaleValue = 64;
- +
- + return gcvSTATUS_OK;
- +}
- +
- +#endif
- +
- +#if gcdPOWEROFF_TIMEOUT
- +gceSTATUS
- +gckHARDWARE_SetPowerOffTimeout(
- + IN gckHARDWARE Hardware,
- + IN gctUINT32 Timeout
- +)
- +{
- + gcmkHEADER_ARG("Hardware=0x%x Timeout=%d", Hardware, Timeout);
- +
- + Hardware->powerOffTimeout = Timeout;
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +
- +gceSTATUS
- +gckHARDWARE_QueryPowerOffTimeout(
- + IN gckHARDWARE Hardware,
- + OUT gctUINT32* Timeout
- +)
- +{
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + *Timeout = Hardware->powerOffTimeout;
- +
- + gcmkFOOTER_ARG("*Timeout=%d", *Timeout);
- + return gcvSTATUS_OK;
- +}
- +#endif
- +
- +gceSTATUS
- +gckHARDWARE_QueryIdle(
- + IN gckHARDWARE Hardware,
- + OUT gctBOOL_PTR IsIdle
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 idle, address;
- +
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(IsIdle != gcvNULL);
- +
- + /* We are idle when the power is not ON. */
- + if (Hardware->chipPowerState != gcvPOWER_ON)
- + {
- + *IsIdle = gcvTRUE;
- + }
- +
- + else
- + {
- + /* Read idle register. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00004, &idle));
- +
- + /* Pipe must be idle. */
- + if (((((((gctUINT32) (idle)) >> (0 ? 1:1)) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1)))))) ) != 1)
- + || ((((((gctUINT32) (idle)) >> (0 ? 3:3)) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) ) != 1)
- + || ((((((gctUINT32) (idle)) >> (0 ? 4:4)) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1)))))) ) != 1)
- + || ((((((gctUINT32) (idle)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) ) != 1)
- + || ((((((gctUINT32) (idle)) >> (0 ? 6:6)) & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1)))))) ) != 1)
- + || ((((((gctUINT32) (idle)) >> (0 ? 7:7)) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1)))))) ) != 1)
- + || ((((((gctUINT32) (idle)) >> (0 ? 2:2)) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))) ) != 1)
- + )
- + {
- + /* Something is busy. */
- + *IsIdle = gcvFALSE;
- + }
- +
- + else
- + {
- + /* Read the current FE address. */
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00664,
- + &address));
- +
- + /* Test if address is inside the last WAIT/LINK sequence. */
- + if ((address >= Hardware->lastWaitLink)
- + && (address <= Hardware->lastWaitLink + 16)
- + )
- + {
- + /* FE is in last WAIT/LINK and the pipe is idle. */
- + *IsIdle = gcvTRUE;
- + }
- + else
- + {
- + /* FE is not in WAIT/LINK yet. */
- + *IsIdle = gcvFALSE;
- + }
- + }
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +** Handy macros that will help in reading those debug registers.
- +*/
- +
- +#define gcmkREAD_DEBUG_REGISTER(control, block, index, data) \
- + gcmkONERROR(\
- + gckOS_WriteRegisterEx(Hardware->os, \
- + Hardware->core, \
- + GC_DEBUG_CONTROL##control##_Address, \
- + gcmSETFIELD(0, \
- + GC_DEBUG_CONTROL##control, \
- + block, \
- + index))); \
- + gcmkONERROR(\
- + gckOS_ReadRegisterEx(Hardware->os, \
- + Hardware->core, \
- + GC_DEBUG_SIGNALS_##block##_Address, \
- + &profiler->data))
- +
- +#define gcmkREAD_DEBUG_REGISTER_N(control, block, index, data) \
- + gcmkONERROR(\
- + gckOS_WriteRegisterEx(Hardware->os, \
- + Hardware->core, \
- + GC_DEBUG_CONTROL##control##_Address, \
- + gcmSETFIELD(0, \
- + GC_DEBUG_CONTROL##control, \
- + block, \
- + index))); \
- + gcmkONERROR(\
- + gckOS_ReadRegisterEx(Hardware->os, \
- + Hardware->core, \
- + GC_DEBUG_SIGNALS_##block##_Address, \
- + &data))
- +
- +#define gcmkRESET_DEBUG_REGISTER(control, block) \
- + gcmkONERROR(\
- + gckOS_WriteRegisterEx(Hardware->os, \
- + Hardware->core, \
- + GC_DEBUG_CONTROL##control##_Address, \
- + gcmSETFIELD(0, \
- + GC_DEBUG_CONTROL##control, \
- + block, \
- + 15))); \
- + gcmkONERROR(\
- + gckOS_WriteRegisterEx(Hardware->os, \
- + Hardware->core, \
- + GC_DEBUG_CONTROL##control##_Address, \
- + gcmSETFIELD(0, \
- + GC_DEBUG_CONTROL##control, \
- + block, \
- + 0)))
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_ProfileEngine2D
- +**
- +** Read the profile registers available in the 2D engine and sets them in the
- +** profile. The function will also reset the pixelsRendered counter every time.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to an gckHARDWARE object.
- +**
- +** OPTIONAL gcs2D_PROFILE_PTR Profile
- +** Pointer to a gcs2D_Profile structure.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckHARDWARE_ProfileEngine2D(
- + IN gckHARDWARE Hardware,
- + OPTIONAL gcs2D_PROFILE_PTR Profile
- + )
- +{
- + gceSTATUS status;
- + gcs2D_PROFILE_PTR profiler = Profile;
- +
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + if (Profile != gcvNULL)
- + {
- + /* Read the cycle count. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00438,
- + &Profile->cycleCount));
- +
- + /* Read pixels rendered by 2D engine. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &profiler->pixelsRendered));
- +
- + /* Reset counter. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))
- +));
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +#if VIVANTE_PROFILER
- +gceSTATUS
- +gckHARDWARE_QueryProfileRegisters(
- + IN gckHARDWARE Hardware,
- + IN gctBOOL Reset,
- + OUT gcsPROFILER_COUNTERS * Counters
- + )
- +{
- + gceSTATUS status;
- + gcsPROFILER_COUNTERS * profiler = Counters;
- + gctUINT i, clock;
- + gctUINT32 colorKilled, colorDrawn, depthKilled, depthDrawn;
- + gctUINT32 totalRead, totalWrite;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Counters=0x%x", Hardware, Counters);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + /* Read the counters. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00438,
- + &profiler->gpuCyclesCounter));
- +
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00078,
- + &profiler->gpuTotalCyclesCounter));
- +
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x0007C,
- + &profiler->gpuIdleCyclesCounter));
- +
- +
- + /* Read clock control register. */
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00000,
- + &clock));
- +
- + profiler->gpuTotalRead64BytesPerFrame = 0;
- + profiler->gpuTotalWrite64BytesPerFrame = 0;
- + profiler->pe_pixel_count_killed_by_color_pipe = 0;
- + profiler->pe_pixel_count_killed_by_depth_pipe = 0;
- + profiler->pe_pixel_count_drawn_by_color_pipe = 0;
- + profiler->pe_pixel_count_drawn_by_depth_pipe = 0;
- +
- + /* Walk through all avaiable pixel pipes. */
- + for (i = 0; i < Hardware->identity.pixelPipes; ++i)
- + {
- + /* Select proper pipe. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00000,
- + ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20)))));
- +
- + /* BW */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00040,
- + &totalRead));
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00044,
- + &totalWrite));
- +
- + profiler->gpuTotalRead64BytesPerFrame += totalRead;
- + profiler->gpuTotalWrite64BytesPerFrame += totalWrite;
- +
- + /* PE */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &colorKilled));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &depthKilled));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &colorDrawn));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &depthDrawn));
- +
- + profiler->pe_pixel_count_killed_by_color_pipe += colorKilled;
- + profiler->pe_pixel_count_killed_by_depth_pipe += depthKilled;
- + profiler->pe_pixel_count_drawn_by_color_pipe += colorDrawn;
- + profiler->pe_pixel_count_drawn_by_depth_pipe += depthDrawn;
- + }
- +
- + /* Reset clock control register. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00000,
- + clock));
- +
- + if(Reset){
- + /* Reset counters. */
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 1));
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 0));
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00438, 0));
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00078, 0));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))
- +));
- + }
- +
- + /* SH */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->ps_inst_counter));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->rendered_pixel_counter));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vs_inst_counter));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->rendered_vertice_counter));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vtx_branch_inst_counter));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vtx_texld_inst_counter));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->pxl_branch_inst_counter));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->pxl_texld_inst_counter));
- + if(Reset){ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24)))
- +));}
- +
- + /* PA */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_input_vtx_counter));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_input_prim_counter));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_output_prim_counter));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_depth_clipped_counter));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_trivial_rejected_counter));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_culled_counter));
- + if(Reset){ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)))
- +));}
- +
- + /* SE */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_culled_triangle_count));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_culled_lines_count));
- + if(Reset){ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
- +gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8)))
- +));}
- +
- + /* RA */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_valid_pixel_count));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_total_quad_count));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_valid_quad_count_after_early_z));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_total_primitive_count));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_pipe_cache_miss_counter));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_prefetch_cache_miss_counter));
- + if(Reset){ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))
- +));}
- +
- + /* TX */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_bilinear_requests));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_trilinear_requests));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_discarded_texture_requests));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_texture_requests));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_mem_read_count));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_mem_read_in_8B_count));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_miss_count));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_hit_texel_count));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_miss_texel_count));
- + if(Reset){ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24)))
- +));}
- +
- + /* MC */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_read_req_8B_from_pipeline));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_read_req_8B_from_IP));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_write_req_8B_from_pipeline));
- + if(Reset){ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)))
- +));}
- +
- + /* HI */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_read_request_stalled));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_write_request_stalled));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_write_data_stalled));
- + if(Reset){ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
- +gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8)))
- +));}
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +#endif
- +
- +#if VIVANTE_PROFILER_CONTEXT
- +#define gcmkUPDATE_PROFILE_DATA(data) \
- + profilerHistroy->data += profiler->data
- +
- +gceSTATUS
- +gckHARDWARE_QueryContextProfile(
- + IN gckHARDWARE Hardware,
- + IN gctBOOL Reset,
- + IN gckCONTEXT Context,
- + OUT gcsPROFILER_COUNTERS * Counters
- + )
- +{
- + gceSTATUS status;
- + gckCOMMAND command = Hardware->kernel->command;
- + gcsPROFILER_COUNTERS * profiler = Counters;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Counters=0x%x", Hardware, Counters);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + /* Acquire the context sequnence mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(
- + command->os, command->mutexContextSeq, gcvINFINITE
- + ));
- +
- + /* Read the counters. */
- + gcmkVERIFY_OK(gckOS_MemCopy(
- + profiler, &Context->histroyProfiler, gcmSIZEOF(gcsPROFILER_COUNTERS)
- + ));
- +
- + if (Reset)
- + {
- + /* Reset counters. */
- + gcmkVERIFY_OK(gckOS_ZeroMemory(
- + &Context->histroyProfiler, gcmSIZEOF(gcsPROFILER_COUNTERS)
- + ));
- + }
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(
- + command->os, command->mutexContextSeq
- + ));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +
- +gceSTATUS
- +gckHARDWARE_UpdateContextProfile(
- + IN gckHARDWARE Hardware,
- + IN gckCONTEXT Context
- + )
- +{
- + gceSTATUS status;
- + gcsPROFILER_COUNTERS * profiler = &Context->latestProfiler;
- + gcsPROFILER_COUNTERS * profilerHistroy = &Context->histroyProfiler;
- + gctUINT i, clock;
- + gctUINT32 colorKilled, colorDrawn, depthKilled, depthDrawn;
- + gctUINT32 totalRead, totalWrite;
- + gceCHIPMODEL chipModel;
- + gctUINT32 chipRevision;
- + gctUINT32 temp;
- + gctBOOL needResetShader = gcvFALSE;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Context=0x%x", Hardware, Context);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_OBJECT(Context, gcvOBJ_CONTEXT);
- +
- + chipModel = Hardware->identity.chipModel;
- + chipRevision = Hardware->identity.chipRevision;
- + if (chipModel == gcv2000 || (chipModel == gcv2100 && chipRevision == 0x5118))
- + {
- + needResetShader = gcvTRUE;
- + }
- +
- + /* Read the counters. */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00438,
- + &profiler->gpuCyclesCounter));
- + gcmkUPDATE_PROFILE_DATA(gpuCyclesCounter);
- +
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00078,
- + &profiler->gpuTotalCyclesCounter));
- + gcmkUPDATE_PROFILE_DATA(gpuTotalCyclesCounter);
- +
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x0007C,
- + &profiler->gpuIdleCyclesCounter));
- + gcmkUPDATE_PROFILE_DATA(gpuIdleCyclesCounter);
- +
- + /* Read clock control register. */
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00000,
- + &clock));
- +
- + profiler->gpuTotalRead64BytesPerFrame = 0;
- + profiler->gpuTotalWrite64BytesPerFrame = 0;
- + profiler->pe_pixel_count_killed_by_color_pipe = 0;
- + profiler->pe_pixel_count_killed_by_depth_pipe = 0;
- + profiler->pe_pixel_count_drawn_by_color_pipe = 0;
- + profiler->pe_pixel_count_drawn_by_depth_pipe = 0;
- +
- + /* Walk through all avaiable pixel pipes. */
- + for (i = 0; i < Hardware->identity.pixelPipes; ++i)
- + {
- + /* Select proper pipe. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00000,
- + ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20)))));
- +
- + /* BW */
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00040,
- + &totalRead));
- + gcmkONERROR(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00044,
- + &totalWrite));
- +
- + profiler->gpuTotalRead64BytesPerFrame += totalRead;
- + profiler->gpuTotalWrite64BytesPerFrame += totalWrite;
- + gcmkUPDATE_PROFILE_DATA(gpuTotalRead64BytesPerFrame);
- + gcmkUPDATE_PROFILE_DATA(gpuTotalWrite64BytesPerFrame);
- +
- + /* PE */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &colorKilled));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &depthKilled));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &colorDrawn));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &depthDrawn));
- +
- + profiler->pe_pixel_count_killed_by_color_pipe += colorKilled;
- + profiler->pe_pixel_count_killed_by_depth_pipe += depthKilled;
- + profiler->pe_pixel_count_drawn_by_color_pipe += colorDrawn;
- + profiler->pe_pixel_count_drawn_by_depth_pipe += depthDrawn;
- + gcmkUPDATE_PROFILE_DATA(pe_pixel_count_killed_by_color_pipe);
- + gcmkUPDATE_PROFILE_DATA(pe_pixel_count_killed_by_depth_pipe);
- + gcmkUPDATE_PROFILE_DATA(pe_pixel_count_drawn_by_color_pipe);
- + gcmkUPDATE_PROFILE_DATA(pe_pixel_count_drawn_by_depth_pipe);
- + }
- +
- + /* Reset clock control register. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00000,
- + clock));
- +
- +
- +
- +
- + /* Reset counters. */
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 1));
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 0));
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00438, 0));
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00078, 0));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))
- +));
- +
- + /* SH */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->ps_inst_counter));
- + if (needResetShader)
- + {
- + temp = profiler->ps_inst_counter;
- + profiler->ps_inst_counter -= Context->prevPSInstCount;
- + Context->prevPSInstCount = temp;
- + }
- + gcmkUPDATE_PROFILE_DATA(ps_inst_counter);
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->rendered_pixel_counter));
- + if (needResetShader)
- + {
- + temp = profiler->rendered_pixel_counter;
- + profiler->rendered_pixel_counter -= Context->prevPSPixelCount;
- + Context->prevPSPixelCount = temp;
- + }
- + gcmkUPDATE_PROFILE_DATA(rendered_pixel_counter);
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vs_inst_counter));
- + if (needResetShader)
- + {
- + temp = profiler->vs_inst_counter;
- + profiler->vs_inst_counter -= Context->prevVSInstCount;
- + Context->prevVSInstCount = temp;
- + }
- + gcmkUPDATE_PROFILE_DATA(vs_inst_counter);
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->rendered_vertice_counter));
- + if (needResetShader)
- + {
- + temp = profiler->rendered_vertice_counter;
- + profiler->rendered_vertice_counter -= Context->prevVSVertexCount;
- + Context->prevVSVertexCount = temp;
- + }
- + gcmkUPDATE_PROFILE_DATA(rendered_vertice_counter);
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vtx_branch_inst_counter));
- + if (needResetShader)
- + {
- + temp = profiler->vtx_branch_inst_counter;
- + profiler->vtx_branch_inst_counter -= Context->prevVSBranchInstCount;
- + Context->prevVSBranchInstCount = temp;
- + }
- + gcmkUPDATE_PROFILE_DATA(vtx_branch_inst_counter);
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vtx_texld_inst_counter));
- + if (needResetShader)
- + {
- + temp = profiler->vtx_texld_inst_counter;
- + profiler->vtx_texld_inst_counter -= Context->prevVSTexInstCount;
- + Context->prevVSTexInstCount = temp;
- + }
- + gcmkUPDATE_PROFILE_DATA(vtx_texld_inst_counter);
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->pxl_branch_inst_counter));
- + if (needResetShader)
- + {
- + temp = profiler->pxl_branch_inst_counter;
- + profiler->pxl_branch_inst_counter -= Context->prevPSBranchInstCount;
- + Context->prevPSBranchInstCount = temp;
- + }
- + gcmkUPDATE_PROFILE_DATA(pxl_branch_inst_counter);
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->pxl_texld_inst_counter));
- + if (needResetShader)
- + {
- + temp = profiler->pxl_texld_inst_counter;
- + profiler->pxl_texld_inst_counter -= Context->prevPSTexInstCount;
- + Context->prevPSTexInstCount = temp;
- + }
- + gcmkUPDATE_PROFILE_DATA(pxl_texld_inst_counter);
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24)))
- +));
- +
- + /* PA */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_input_vtx_counter));
- + gcmkUPDATE_PROFILE_DATA(pa_input_vtx_counter);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_input_prim_counter));
- + gcmkUPDATE_PROFILE_DATA(pa_input_prim_counter);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_output_prim_counter));
- + gcmkUPDATE_PROFILE_DATA(pa_output_prim_counter);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_depth_clipped_counter));
- + gcmkUPDATE_PROFILE_DATA(pa_depth_clipped_counter);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_trivial_rejected_counter));
- + gcmkUPDATE_PROFILE_DATA(pa_trivial_rejected_counter);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_culled_counter));
- + gcmkUPDATE_PROFILE_DATA(pa_culled_counter);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)))
- +));
- +
- + /* SE */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_culled_triangle_count));
- + gcmkUPDATE_PROFILE_DATA(se_culled_triangle_count);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_culled_lines_count));
- + gcmkUPDATE_PROFILE_DATA(se_culled_lines_count);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
- +gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8)))
- +));
- +
- + /* RA */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_valid_pixel_count));
- + gcmkUPDATE_PROFILE_DATA(ra_valid_pixel_count);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_total_quad_count));
- + gcmkUPDATE_PROFILE_DATA(ra_total_quad_count);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_valid_quad_count_after_early_z));
- + gcmkUPDATE_PROFILE_DATA(ra_valid_quad_count_after_early_z);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_total_primitive_count));
- + gcmkUPDATE_PROFILE_DATA(ra_total_primitive_count);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_pipe_cache_miss_counter));
- + gcmkUPDATE_PROFILE_DATA(ra_pipe_cache_miss_counter);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_prefetch_cache_miss_counter));
- + gcmkUPDATE_PROFILE_DATA(ra_prefetch_cache_miss_counter);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
- +gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))
- +));
- +
- + /* TX */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_bilinear_requests));
- + gcmkUPDATE_PROFILE_DATA(tx_total_bilinear_requests);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_trilinear_requests));
- + gcmkUPDATE_PROFILE_DATA(tx_total_trilinear_requests);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_discarded_texture_requests));
- + gcmkUPDATE_PROFILE_DATA(tx_total_discarded_texture_requests);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_texture_requests));
- + gcmkUPDATE_PROFILE_DATA(tx_total_texture_requests);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_mem_read_count));
- + gcmkUPDATE_PROFILE_DATA(tx_mem_read_count);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_mem_read_in_8B_count));
- + gcmkUPDATE_PROFILE_DATA(tx_mem_read_in_8B_count);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_miss_count));
- + gcmkUPDATE_PROFILE_DATA(tx_cache_miss_count);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_hit_texel_count));
- + gcmkUPDATE_PROFILE_DATA(tx_cache_hit_texel_count);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_miss_texel_count));
- + gcmkUPDATE_PROFILE_DATA(tx_cache_miss_texel_count);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
- +gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24)))
- +));
- +
- + /* MC */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_read_req_8B_from_pipeline));
- + gcmkUPDATE_PROFILE_DATA(mc_total_read_req_8B_from_pipeline);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_read_req_8B_from_IP));
- + gcmkUPDATE_PROFILE_DATA(mc_total_read_req_8B_from_IP);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_write_req_8B_from_pipeline));
- + gcmkUPDATE_PROFILE_DATA(mc_total_write_req_8B_from_pipeline);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
- +gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)))
- +));
- +
- + /* HI */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_read_request_stalled));
- + gcmkUPDATE_PROFILE_DATA(hi_axi_cycles_read_request_stalled);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_write_request_stalled));
- + gcmkUPDATE_PROFILE_DATA(hi_axi_cycles_write_request_stalled);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
- +gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_write_data_stalled));
- + gcmkUPDATE_PROFILE_DATA(hi_axi_cycles_write_data_stalled);
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
- +gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8)))
- +));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +#endif
- +
- +static gceSTATUS
- +_ResetGPU(
- + IN gckHARDWARE Hardware,
- + IN gckOS Os,
- + IN gceCORE Core
- + )
- +{
- + gctUINT32 control, idle;
- + gceSTATUS status;
- +
- + for (;;)
- + {
- + /* Disable clock gating. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Os,
- + Core,
- + Hardware->powerBaseAddress +
- + 0x00104,
- + 0x00000000));
- +
- + control = ((((gctUINT32) (0x01590880)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1))))))) << (0 ? 17:17))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1))))))) << (0 ? 17:17)));
- +
- + /* Disable pulse-eater. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Os,
- + Core,
- + 0x0010C,
- + control));
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Os,
- + Core,
- + 0x0010C,
- + ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))));
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Os,
- + Core,
- + 0x0010C,
- + control));
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Os,
- + Core,
- + 0x00000,
- + ((((gctUINT32) (0x00000900)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)))));
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Os,
- + Core,
- + 0x00000,
- + 0x00000900));
- +
- + /* Wait for clock being stable. */
- + gcmkONERROR(gckOS_Delay(Os, 1));
- +
- + /* Isolate the GPU. */
- + control = ((((gctUINT32) (0x00000900)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Os,
- + Core,
- + 0x00000,
- + control));
- +
- + /* Set soft reset. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Os,
- + Core,
- + 0x00000,
- + ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))));
- +
- + /* Wait for reset. */
- + gcmkONERROR(gckOS_Delay(Os, 1));
- +
- + /* Reset soft reset bit. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Os,
- + Core,
- + 0x00000,
- + ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))));
- +
- + /* Reset GPU isolation. */
- + control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Os,
- + Core,
- + 0x00000,
- + control));
- +
- + /* Read idle register. */
- + gcmkONERROR(gckOS_ReadRegisterEx(Os,
- + Core,
- + 0x00004,
- + &idle));
- +
- + if ((((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ) == 0)
- + {
- + continue;
- + }
- +
- + /* Read reset register. */
- + gcmkONERROR(gckOS_ReadRegisterEx(Os,
- + Core,
- + 0x00000,
- + &control));
- +
- + if (((((((gctUINT32) (control)) >> (0 ? 16:16)) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) ) == 0)
- + || ((((((gctUINT32) (control)) >> (0 ? 17:17)) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1)))))) ) == 0)
- + )
- + {
- + continue;
- + }
- +
- + /* GPU is idle. */
- + break;
- + }
- +
- + /* Success. */
- + return gcvSTATUS_OK;
- +
- +OnError:
- +
- + /* Return the error. */
- + return status;
- +}
- +
- +gceSTATUS
- +gckHARDWARE_Reset(
- + IN gckHARDWARE Hardware
- + )
- +{
- + gceSTATUS status;
- + gckCOMMAND command;
- + gctBOOL acquired = gcvFALSE;
- + gctBOOL mutexAcquired = gcvFALSE;
- + gctUINT32 process, thread;
- +
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
- + command = Hardware->kernel->command;
- + gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
- +
- + if (Hardware->identity.chipRevision < 0x4600)
- + {
- + /* Not supported - we need the isolation bit. */
- + gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
- + }
- +
- + status = gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, 0);
- + if (status == gcvSTATUS_TIMEOUT)
- + {
- + gcmkONERROR(gckOS_GetProcessID(&process));
- + gcmkONERROR(gckOS_GetThreadID(&thread));
- +
- + if ((Hardware->powerProcess == process)
- + && (Hardware->powerThread == thread))
- + {
- + /* No way to recovery from a error in power management. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- + }
- + else
- + {
- + mutexAcquired = gcvTRUE;
- + }
- +
- + if (Hardware->chipPowerState == gcvPOWER_ON)
- + {
- + /* Acquire the power management semaphore. */
- + gcmkONERROR(
- + gckOS_AcquireSemaphore(Hardware->os, command->powerSemaphore));
- + acquired = gcvTRUE;
- + }
- +
- + if ((Hardware->chipPowerState == gcvPOWER_ON)
- + || (Hardware->chipPowerState == gcvPOWER_IDLE)
- + )
- + {
- + /* Stop the command processor. */
- + gcmkONERROR(gckCOMMAND_Stop(command, gcvTRUE));
- + }
- +
- + /* Stop isr, we will start it again when power on GPU. */
- + if (Hardware->stopIsr)
- + {
- + gcmkONERROR(Hardware->stopIsr(Hardware->isrContext, Hardware->core));
- + }
- +
- + /* Hardware reset. */
- + status = gckOS_ResetGPU(Hardware->os, Hardware->core);
- +
- + if (gcmIS_ERROR(status))
- + {
- + /* Soft reset. */
- + gcmkONERROR(_ResetGPU(Hardware, Hardware->os, Hardware->core));
- + }
- +
- + /* Force an OFF to ON power switch. */
- + Hardware->chipPowerState = gcvPOWER_OFF;
- +
- + gcmkONERROR(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
- + mutexAcquired = gcvFALSE;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + /* Release the power management semaphore. */
- + gcmkVERIFY_OK(
- + gckOS_ReleaseSemaphore(Hardware->os, command->powerSemaphore));
- + }
- +
- + if (mutexAcquired)
- + {
- + gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex);
- + }
- +
- + /* Return the error. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckHARDWARE_GetBaseAddress(
- + IN gckHARDWARE Hardware,
- + OUT gctUINT32_PTR BaseAddress
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
- +
- + /* Test if we have a new Memory Controller. */
- + if (((((gctUINT32) (Hardware->identity.chipMinorFeatures)) >> (0 ? 22:22) & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1))))))))
- + {
- + /* No base address required. */
- + *BaseAddress = 0;
- + }
- + else
- + {
- + /* Get the base address from the OS. */
- + gcmkONERROR(gckOS_GetBaseAddress(Hardware->os, BaseAddress));
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckHARDWARE_NeedBaseAddress(
- + IN gckHARDWARE Hardware,
- + IN gctUINT32 State,
- + OUT gctBOOL_PTR NeedBase
- + )
- +{
- + gctBOOL need = gcvFALSE;
- +
- + gcmkHEADER_ARG("Hardware=0x%x State=0x%08x", Hardware, State);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(NeedBase != gcvNULL);
- +
- + /* Make sure this is a load state. */
- + if (((((gctUINT32) (State)) >> (0 ? 31:27) & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))))
- + {
- +#ifndef VIVANTE_NO_3D
- + /* Get the state address. */
- + switch ((((((gctUINT32) (State)) >> (0 ? 15:0)) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1)))))) ))
- + {
- + case 0x0596:
- + case 0x0597:
- + case 0x0599:
- + case 0x059A:
- + case 0x05A9:
- + /* These states need a TRUE physical address. */
- + need = gcvTRUE;
- + break;
- + }
- +#else
- + /* 2D addresses don't need a base address. */
- +#endif
- + }
- +
- + /* Return the flag. */
- + *NeedBase = need;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*NeedBase=%d", *NeedBase);
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckHARDWARE_SetIsrManager(
- + IN gckHARDWARE Hardware,
- + IN gctISRMANAGERFUNC StartIsr,
- + IN gctISRMANAGERFUNC StopIsr,
- + IN gctPOINTER Context
- + )
- +{
- + gceSTATUS status = gcvSTATUS_OK;
- +
- + gcmkHEADER_ARG("Hardware=0x%x, StartIsr=0x%x, StopIsr=0x%x, Context=0x%x",
- + Hardware, StartIsr, StopIsr, Context);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + if (StartIsr == gcvNULL ||
- + StopIsr == gcvNULL ||
- + Context == gcvNULL)
- + {
- + status = gcvSTATUS_INVALID_ARGUMENT;
- +
- + gcmkFOOTER();
- + return status;
- + }
- +
- + Hardware->startIsr = StartIsr;
- + Hardware->stopIsr = StopIsr;
- + Hardware->isrContext = Context;
- +
- + /* Success. */
- + gcmkFOOTER();
- +
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_Compose
- +**
- +** Start a composition.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to the gckHARDWARE object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckHARDWARE_Compose(
- + IN gckHARDWARE Hardware,
- + IN gctUINT32 ProcessID,
- + IN gctPHYS_ADDR Physical,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Offset,
- + IN gctSIZE_T Size,
- + IN gctUINT8 EventID
- + )
- +{
- +#ifndef VIVANTE_NO_3D
- + gceSTATUS status;
- + gctUINT32_PTR triggerState;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Physical=0x%x Logical=0x%x"
- + " Offset=%d Size=%d EventID=%d",
- + Hardware, Physical, Logical, Offset, Size, EventID);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(((Size + 8) & 63) == 0);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- +
- + /* Program the trigger state. */
- + triggerState = (gctUINT32_PTR) ((gctUINT8_PTR) Logical + Offset + Size);
- + triggerState[0] = 0x0C03;
- + triggerState[1]
- + = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:4) - (0 ? 5:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:4) - (0 ? 5:4) + 1))))))) << (0 ? 5:4))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ? 5:4) - (0 ? 5:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:4) - (0 ? 5:4) + 1))))))) << (0 ? 5:4)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ? 8:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ? 8:8)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 24:24) - (0 ? 24:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ? 24:24)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))
- + | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:16) - (0 ? 20:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:16) - (0 ? 20:16) + 1))))))) << (0 ? 20:16))) | (((gctUINT32) ((gctUINT32) (EventID) & ((gctUINT32) ((((1 ? 20:16) - (0 ? 20:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:16) - (0 ? 20:16) + 1))))))) << (0 ? 20:16)))
- + ;
- +
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + /* Flush the cache for the wait/link. */
- + gcmkONERROR(gckOS_CacheClean(
- + Hardware->os, ProcessID, gcvNULL,
- + Physical, Logical, Offset + Size
- + ));
- +#endif
- +
- + /* Start composition. */
- + gcmkONERROR(gckOS_WriteRegisterEx(
- + Hardware->os, Hardware->core, 0x00554,
- + ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)))
- + ));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +#else
- + /* Return the status. */
- + return gcvSTATUS_NOT_SUPPORTED;
- +#endif
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_IsFeatureAvailable
- +**
- +** Verifies whether the specified feature is available in hardware.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Hardware
- +** Pointer to an gckHARDWARE object.
- +**
- +** gceFEATURE Feature
- +** Feature to be verified.
- +*/
- +gceSTATUS
- +gckHARDWARE_IsFeatureAvailable(
- + IN gckHARDWARE Hardware,
- + IN gceFEATURE Feature
- + )
- +{
- + gctBOOL available;
- +
- + gcmkHEADER_ARG("Hardware=0x%x Feature=%d", Hardware, Feature);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + /* Only features needed by common kernel logic added here. */
- + switch (Feature)
- + {
- + case gcvFEATURE_END_EVENT:
- + /*available = gcmVERIFYFIELDVALUE(Hardware->identity.chipMinorFeatures2,
- + GC_MINOR_FEATURES2, END_EVENT, AVAILABLE
- + );*/
- + available = gcvFALSE;
- + break;
- + case gcvFEATURE_MC20:
- + available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures)) >> (0 ? 22:22) & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1)))))));
- + break;
- + case gcvFEATURE_DYNAMIC_FREQUENCY_SCALING:
- + /* This feature doesn't apply for 2D cores. */
- + available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures2)) >> (0 ? 14:14) & ((gctUINT32) ((((1 ? 14:14) - (0 ? 14:14) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 14:14) - (0 ? 14:14) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 14:14) - (0 ? 14:14) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 14:14) - (0 ? 14:14) + 1)))))))
- + && ((((gctUINT32) (Hardware->identity.chipFeatures)) >> (0 ? 2:2) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))));
- + break;
- +
- + case gcvFEATURE_PIPE_2D:
- + available = ((((gctUINT32) (Hardware->identity.chipFeatures)) >> (0 ? 9:9) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))));
- + break;
- +
- + case gcvFEATURE_PIPE_3D:
- +#ifndef VIVANTE_NO_3D
- + available = ((((gctUINT32) (Hardware->identity.chipFeatures)) >> (0 ? 2:2) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))));
- +#else
- + available = gcvFALSE;
- +#endif
- + break;
- +
- + case gcvFEATURE_HALTI2:
- + available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures4)) >> (0 ? 16:16) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))));
- + break;
- +
- + default:
- + gcmkFATAL("Invalid feature has been requested.");
- + available = gcvFALSE;
- + }
- +
- + /* Return result. */
- + gcmkFOOTER_ARG("%d", available ? gcvSTATUS_TRUE : gcvSTATUS_OK);
- + return available ? gcvSTATUS_TRUE : gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_DumpMMUException
- +**
- +** Dump the MMU debug info on an MMU exception.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Harwdare
- +** Pointer to an gckHARDWARE object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckHARDWARE_DumpMMUException(
- + IN gckHARDWARE Hardware
- + )
- +{
- +#if !gcdPOWER_SUSNPEND_WHEN_IDLE && !gcdPOWEROFF_TIMEOUT
- + gctUINT32 mmu, mmuStatus, address, i;
- +#if gcdDEBUG
- + gctUINT32 mtlb, stlb, offset;
- +#endif
- +
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + gcmkPRINT("GPU[%d](ChipModel=0x%x ChipRevision=0x%x):\n",
- + Hardware->core,
- + Hardware->identity.chipModel,
- + Hardware->identity.chipRevision);
- +
- + gcmkPRINT("**************************\n");
- + gcmkPRINT("*** MMU ERROR DUMP ***\n");
- + gcmkPRINT("**************************\n");
- +
- + gcmkVERIFY_OK(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00188,
- + &mmuStatus));
- +
- + gcmkPRINT(" MMU status = 0x%08X\n", mmuStatus);
- +
- + for (i = 0; i < 4; i += 1)
- + {
- + mmu = mmuStatus & 0xF;
- + mmuStatus >>= 4;
- +
- + if (mmu == 0)
- + {
- + continue;
- + }
- +
- + switch (mmu)
- + {
- + case 1:
- + gcmkPRINT(" MMU%d: slave not present\n", i);
- + break;
- +
- + case 2:
- + gcmkPRINT(" MMU%d: page not present\n", i);
- + break;
- +
- + case 3:
- + gcmkPRINT(" MMU%d: write violation\n", i);
- + break;
- +
- + default:
- + gcmkPRINT(" MMU%d: unknown state\n", i);
- + }
- +
- + gcmkVERIFY_OK(
- + gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00190 + i * 4,
- + &address));
- +
- + mtlb = (address & gcdMMU_MTLB_MASK) >> gcdMMU_MTLB_SHIFT;
- + stlb = (address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
- + offset = address & gcdMMU_OFFSET_4K_MASK;
- +
- + gcmkPRINT(" MMU%d: exception address = 0x%08X\n", i, address);
- +
- + gcmkPRINT(" MTLB entry = %d\n", mtlb);
- +
- + gcmkPRINT(" STLB entry = %d\n", stlb);
- +
- + gcmkPRINT(" Offset = 0x%08X (%d)\n", offset, offset);
- +
- + gckMMU_DumpPageTableEntry(Hardware->kernel->mmu, address);
- +
- + }
- +
- + gcmkFOOTER_NO();
- +#else
- + /* If clock could be off automatically, we can't read mmu debug
- + ** register here; build driver with gcdPOWER_SUSPEND_WHEN_IDLE = 0
- + ** and gcdPOWEROFF_TIMEOUT = 0 to make it safe to read mmu register. */
- + gcmkPRINT("[galcore] %s(%d): MMU Exception!", __FUNCTION__, __LINE__);
- +#endif
- +
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHARDWARE_DumpGPUState
- +**
- +** Dump the GPU debug registers.
- +**
- +** INPUT:
- +**
- +** gckHARDWARE Harwdare
- +** Pointer to an gckHARDWARE object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckHARDWARE_DumpGPUState(
- + IN gckHARDWARE Hardware
- + )
- +{
- + static gctCONST_STRING _cmdState[] =
- + {
- + "PAR_IDLE_ST", "PAR_DEC_ST", "PAR_ADR0_ST", "PAR_LOAD0_ST",
- + "PAR_ADR1_ST", "PAR_LOAD1_ST", "PAR_3DADR_ST", "PAR_3DCMD_ST",
- + "PAR_3DCNTL_ST", "PAR_3DIDXCNTL_ST", "PAR_INITREQDMA_ST",
- + "PAR_DRAWIDX_ST", "PAR_DRAW_ST", "PAR_2DRECT0_ST", "PAR_2DRECT1_ST",
- + "PAR_2DDATA0_ST", "PAR_2DDATA1_ST", "PAR_WAITFIFO_ST", "PAR_WAIT_ST",
- + "PAR_LINK_ST", "PAR_END_ST", "PAR_STALL_ST"
- + };
- +
- + static gctCONST_STRING _cmdDmaState[] =
- + {
- + "CMD_IDLE_ST", "CMD_START_ST", "CMD_REQ_ST", "CMD_END_ST"
- + };
- +
- + static gctCONST_STRING _cmdFetState[] =
- + {
- + "FET_IDLE_ST", "FET_RAMVALID_ST", "FET_VALID_ST"
- + };
- +
- + static gctCONST_STRING _reqDmaState[] =
- + {
- + "REQ_IDLE_ST", "REQ_WAITIDX_ST", "REQ_CAL_ST"
- + };
- +
- + static gctCONST_STRING _calState[] =
- + {
- + "CAL_IDLE_ST", "CAL_LDADR_ST", "CAL_IDXCALC_ST"
- + };
- +
- + static gctCONST_STRING _veReqState[] =
- + {
- + "VER_IDLE_ST", "VER_CKCACHE_ST", "VER_MISS_ST"
- + };
- +
- + static gcsiDEBUG_REGISTERS _dbgRegs[] =
- + {
- + { "RA", 0x474, 16, 0x448, 16, 0x12344321 },
- + { "TX", 0x474, 24, 0x44C, 16, 0x12211221 },
- + { "FE", 0x470, 0, 0x450, 16, 0xBABEF00D },
- + { "PE", 0x470, 16, 0x454, 16, 0xBABEF00D },
- + { "DE", 0x470, 8, 0x458, 16, 0xBABEF00D },
- + { "SH", 0x470, 24, 0x45C, 16, 0xDEADBEEF },
- + { "PA", 0x474, 0, 0x460, 16, 0x0000AAAA },
- + { "SE", 0x474, 8, 0x464, 16, 0x5E5E5E5E },
- + { "MC", 0x478, 0, 0x468, 16, 0x12345678 },
- + { "HI", 0x478, 8, 0x46C, 16, 0xAAAAAAAA }
- + };
- +
- + static gctUINT32 _otherRegs[] =
- + {
- + 0x040, 0x044, 0x04C, 0x050, 0x054, 0x058, 0x05C, 0x060,
- + 0x43c, 0x440, 0x444, 0x414,
- + };
- +
- + gceSTATUS status;
- + gckKERNEL kernel;
- + gctUINT32 idle, axi;
- + gctUINT32 dmaAddress1, dmaAddress2;
- + gctUINT32 dmaState1, dmaState2;
- + gctUINT32 dmaLow, dmaHigh;
- + gctUINT32 cmdState, cmdDmaState, cmdFetState;
- + gctUINT32 dmaReqState, calState, veReqState;
- + gctUINT i;
- + gctUINT pipe, pixelPipes;
- + gctUINT32 control, oldControl;
- + gckOS os = Hardware->os;
- + gceCORE core = Hardware->core;
- +
- + gcmkHEADER_ARG("Hardware=0x%X", Hardware);
- +
- + kernel = Hardware->kernel;
- +
- + gcmkPRINT_N(12, "GPU[%d](ChipModel=0x%x ChipRevision=0x%x):\n",
- + core,
- + Hardware->identity.chipModel,
- + Hardware->identity.chipRevision);
- +
- + pixelPipes = Hardware->identity.pixelPipes
- + ? Hardware->identity.pixelPipes
- + : 1;
- +
- + /* Reset register values. */
- + idle = axi =
- + dmaState1 = dmaState2 =
- + dmaAddress1 = dmaAddress2 =
- + dmaLow = dmaHigh = 0;
- +
- + /* Verify whether DMA is running. */
- + gcmkONERROR(_VerifyDMA(
- + os, core, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
- + ));
- +
- + cmdState = dmaState2 & 0x1F;
- + cmdDmaState = (dmaState2 >> 8) & 0x03;
- + cmdFetState = (dmaState2 >> 10) & 0x03;
- + dmaReqState = (dmaState2 >> 12) & 0x03;
- + calState = (dmaState2 >> 14) & 0x03;
- + veReqState = (dmaState2 >> 16) & 0x03;
- +
- + gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x004, &idle));
- + gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x00C, &axi));
- + gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x668, &dmaLow));
- + gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x66C, &dmaHigh));
- +
- + gcmkPRINT_N(0, "**************************\n");
- + gcmkPRINT_N(0, "*** GPU STATE DUMP ***\n");
- + gcmkPRINT_N(0, "**************************\n");
- +
- + gcmkPRINT_N(4, " axi = 0x%08X\n", axi);
- +
- + gcmkPRINT_N(4, " idle = 0x%08X\n", idle);
- + if ((idle & 0x00000001) == 0) gcmkPRINT_N(0, " FE not idle\n");
- + if ((idle & 0x00000002) == 0) gcmkPRINT_N(0, " DE not idle\n");
- + if ((idle & 0x00000004) == 0) gcmkPRINT_N(0, " PE not idle\n");
- + if ((idle & 0x00000008) == 0) gcmkPRINT_N(0, " SH not idle\n");
- + if ((idle & 0x00000010) == 0) gcmkPRINT_N(0, " PA not idle\n");
- + if ((idle & 0x00000020) == 0) gcmkPRINT_N(0, " SE not idle\n");
- + if ((idle & 0x00000040) == 0) gcmkPRINT_N(0, " RA not idle\n");
- + if ((idle & 0x00000080) == 0) gcmkPRINT_N(0, " TX not idle\n");
- + if ((idle & 0x00000100) == 0) gcmkPRINT_N(0, " VG not idle\n");
- + if ((idle & 0x00000200) == 0) gcmkPRINT_N(0, " IM not idle\n");
- + if ((idle & 0x00000400) == 0) gcmkPRINT_N(0, " FP not idle\n");
- + if ((idle & 0x00000800) == 0) gcmkPRINT_N(0, " TS not idle\n");
- + if ((idle & 0x80000000) != 0) gcmkPRINT_N(0, " AXI low power mode\n");
- +
- + if (
- + (dmaAddress1 == dmaAddress2)
- + && (dmaState1 == dmaState2)
- + )
- + {
- + gcmkPRINT_N(0, " DMA appears to be stuck at this address:\n");
- + gcmkPRINT_N(4, " 0x%08X\n", dmaAddress1);
- + }
- + else
- + {
- + if (dmaAddress1 == dmaAddress2)
- + {
- + gcmkPRINT_N(0, " DMA address is constant, but state is changing:\n");
- + gcmkPRINT_N(4, " 0x%08X\n", dmaState1);
- + gcmkPRINT_N(4, " 0x%08X\n", dmaState2);
- + }
- + else
- + {
- + gcmkPRINT_N(0, " DMA is running; known addresses are:\n");
- + gcmkPRINT_N(4, " 0x%08X\n", dmaAddress1);
- + gcmkPRINT_N(4, " 0x%08X\n", dmaAddress2);
- + }
- + }
- + gcmkPRINT_N(4, " dmaLow = 0x%08X\n", dmaLow);
- + gcmkPRINT_N(4, " dmaHigh = 0x%08X\n", dmaHigh);
- + gcmkPRINT_N(4, " dmaState = 0x%08X\n", dmaState2);
- + gcmkPRINT_N(8, " command state = %d (%s)\n", cmdState, _cmdState [cmdState]);
- + gcmkPRINT_N(8, " command DMA state = %d (%s)\n", cmdDmaState, _cmdDmaState[cmdDmaState]);
- + gcmkPRINT_N(8, " command fetch state = %d (%s)\n", cmdFetState, _cmdFetState[cmdFetState]);
- + gcmkPRINT_N(8, " DMA request state = %d (%s)\n", dmaReqState, _reqDmaState[dmaReqState]);
- + gcmkPRINT_N(8, " cal state = %d (%s)\n", calState, _calState [calState]);
- + gcmkPRINT_N(8, " VE request state = %d (%s)\n", veReqState, _veReqState [veReqState]);
- +
- + /* Record control. */
- + gckOS_ReadRegisterEx(os, core, 0x0, &oldControl);
- +
- + for (pipe = 0; pipe < pixelPipes; pipe++)
- + {
- + gcmkPRINT_N(4, " Debug registers of pipe[%d]:\n", pipe);
- +
- + /* Switch pipe. */
- + gckOS_ReadRegisterEx(os, core, 0x0, &control);
- + control &= ~(0xF << 20);
- + control |= (pipe << 20);
- + gckOS_WriteRegisterEx(os, core, 0x0, control);
- +
- + for (i = 0; i < gcmCOUNTOF(_dbgRegs); i += 1)
- + {
- + gcmkONERROR(_DumpDebugRegisters(os, core, &_dbgRegs[i]));
- + }
- +
- + gcmkPRINT_N(0, " Other Registers:\n");
- + for (i = 0; i < gcmCOUNTOF(_otherRegs); i += 1)
- + {
- + gctUINT32 read;
- + gcmkONERROR(gckOS_ReadRegisterEx(os, core, _otherRegs[i], &read));
- + gcmkPRINT_N(12, " [0x%04X] 0x%08X\n", _otherRegs[i], read);
- + }
- + }
- +
- + if (kernel->hardware->identity.chipFeatures & (1 << 4))
- + {
- + gctUINT32 read0, read1, write;
- +
- + read0 = read1 = write = 0;
- +
- + gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x43C, &read0));
- + gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x440, &read1));
- + gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x444, &write));
- +
- + gcmkPRINT_N(4, " read0 = 0x%08X\n", read0);
- + gcmkPRINT_N(4, " read1 = 0x%08X\n", read1);
- + gcmkPRINT_N(4, " write = 0x%08X\n", write);
- + }
- +
- + /* Restore control. */
- + gckOS_WriteRegisterEx(os, core, 0x0, oldControl);
- +
- + /* dump stack. */
- + gckOS_DumpCallStack(os);
- +
- +OnError:
- +
- + /* Return the error. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +
- +#if gcdFRAME_DB
- +static gceSTATUS
- +gckHARDWARE_ReadPerformanceRegister(
- + IN gckHARDWARE Hardware,
- + IN gctUINT PerformanceAddress,
- + IN gctUINT IndexAddress,
- + IN gctUINT IndexShift,
- + IN gctUINT Index,
- + OUT gctUINT32_PTR Value
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Hardware=0x%x PerformanceAddress=0x%x IndexAddress=0x%x "
- + "IndexShift=%u Index=%u",
- + Hardware, PerformanceAddress, IndexAddress, IndexShift,
- + Index);
- +
- + /* Write the index. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + IndexAddress,
- + Index << IndexShift));
- +
- + /* Read the register. */
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + PerformanceAddress,
- + Value));
- +
- + /* Test for reset. */
- + if (Index == 15)
- + {
- + /* Index another register to get out of reset. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, IndexAddress, 0));
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Value=0x%x", *Value);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckHARDWARE_GetFrameInfo(
- + IN gckHARDWARE Hardware,
- + OUT gcsHAL_FRAME_INFO * FrameInfo
- + )
- +{
- + gceSTATUS status;
- + gctUINT i, clock;
- + gcsHAL_FRAME_INFO info;
- +#if gcdFRAME_DB_RESET
- + gctUINT reset;
- +#endif
- +
- + gcmkHEADER_ARG("Hardware=0x%x", Hardware);
- +
- + /* Get profile tick. */
- + gcmkONERROR(gckOS_GetProfileTick(&info.ticks));
- +
- + /* Read SH counters and reset them. */
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x0045C,
- + 0x00470,
- + 24,
- + 4,
- + &info.shaderCycles));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x0045C,
- + 0x00470,
- + 24,
- + 9,
- + &info.vsInstructionCount));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x0045C,
- + 0x00470,
- + 24,
- + 12,
- + &info.vsTextureCount));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x0045C,
- + 0x00470,
- + 24,
- + 7,
- + &info.psInstructionCount));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x0045C,
- + 0x00470,
- + 24,
- + 14,
- + &info.psTextureCount));
- +#if gcdFRAME_DB_RESET
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x0045C,
- + 0x00470,
- + 24,
- + 15,
- + &reset));
- +#endif
- +
- + /* Read PA counters and reset them. */
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00460,
- + 0x00474,
- + 0,
- + 3,
- + &info.vertexCount));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00460,
- + 0x00474,
- + 0,
- + 4,
- + &info.primitiveCount));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00460,
- + 0x00474,
- + 0,
- + 7,
- + &info.rejectedPrimitives));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00460,
- + 0x00474,
- + 0,
- + 8,
- + &info.culledPrimitives));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00460,
- + 0x00474,
- + 0,
- + 6,
- + &info.clippedPrimitives));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00460,
- + 0x00474,
- + 0,
- + 5,
- + &info.outPrimitives));
- +#if gcdFRAME_DB_RESET
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00460,
- + 0x00474,
- + 0,
- + 15,
- + &reset));
- +#endif
- +
- + /* Read RA counters and reset them. */
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00448,
- + 0x00474,
- + 16,
- + 3,
- + &info.inPrimitives));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00448,
- + 0x00474,
- + 16,
- + 11,
- + &info.culledQuadCount));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00448,
- + 0x00474,
- + 16,
- + 1,
- + &info.totalQuadCount));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00448,
- + 0x00474,
- + 16,
- + 2,
- + &info.quadCount));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00448,
- + 0x00474,
- + 16,
- + 0,
- + &info.totalPixelCount));
- +#if gcdFRAME_DB_RESET
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00448,
- + 0x00474,
- + 16,
- + 15,
- + &reset));
- +#endif
- +
- + /* Read TX counters and reset them. */
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x0044C,
- + 0x00474,
- + 24,
- + 0,
- + &info.bilinearRequests));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x0044C,
- + 0x00474,
- + 24,
- + 1,
- + &info.trilinearRequests));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x0044C,
- + 0x00474,
- + 24,
- + 8,
- + &info.txHitCount));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x0044C,
- + 0x00474,
- + 24,
- + 9,
- + &info.txMissCount));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x0044C,
- + 0x00474,
- + 24,
- + 6,
- + &info.txBytes8));
- +#if gcdFRAME_DB_RESET
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x0044C,
- + 0x00474,
- + 24,
- + 15,
- + &reset));
- +#endif
- +
- + /* Read clock control register. */
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00000,
- + &clock));
- +
- + /* Walk through all avaiable pixel pipes. */
- + for (i = 0; i < Hardware->identity.pixelPipes; ++i)
- + {
- + /* Select proper pipe. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00000,
- + ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20)))));
- +
- + /* Read cycle registers. */
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00078,
- + &info.cycles[i]));
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x0007C,
- + &info.idleCycles[i]));
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00438,
- + &info.mcCycles[i]));
- +
- + /* Read bandwidth registers. */
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x0005C,
- + &info.readRequests[i]));
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00040,
- + &info.readBytes8[i]));
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00050,
- + &info.writeRequests[i]));
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00044,
- + &info.writeBytes8[i]));
- +
- + /* Read PE counters. */
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00454,
- + 0x00470,
- + 16,
- + 0,
- + &info.colorKilled[i]));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00454,
- + 0x00470,
- + 16,
- + 2,
- + &info.colorDrawn[i]));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00454,
- + 0x00470,
- + 16,
- + 1,
- + &info.depthKilled[i]));
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00454,
- + 0x00470,
- + 16,
- + 3,
- + &info.depthDrawn[i]));
- + }
- +
- + /* Zero out remaning reserved counters. */
- + for (; i < 8; ++i)
- + {
- + info.readBytes8[i] = 0;
- + info.writeBytes8[i] = 0;
- + info.cycles[i] = 0;
- + info.idleCycles[i] = 0;
- + info.mcCycles[i] = 0;
- + info.readRequests[i] = 0;
- + info.writeRequests[i] = 0;
- + info.colorKilled[i] = 0;
- + info.colorDrawn[i] = 0;
- + info.depthKilled[i] = 0;
- + info.depthDrawn[i] = 0;
- + }
- +
- + /* Reset clock control register. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00000,
- + clock));
- +
- + /* Reset cycle and bandwidth counters. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x0003C,
- + 1));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x0003C,
- + 0));
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00078,
- + 0));
- +
- +#if gcdFRAME_DB_RESET
- + /* Reset PE counters. */
- + gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
- + Hardware,
- + 0x00454,
- + 0x00470,
- + 16,
- + 15,
- + &reset));
- +#endif
- +
- + /* Copy to user. */
- + gcmkONERROR(gckOS_CopyToUserData(Hardware->os,
- + &info,
- + FrameInfo,
- + gcmSIZEOF(info)));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +#endif
- +
- +#if gcdDVFS
- +#define READ_FROM_EATER1 0
- +
- +gceSTATUS
- +gckHARDWARE_QueryLoad(
- + IN gckHARDWARE Hardware,
- + OUT gctUINT32 * Load
- + )
- +{
- + gctUINT32 debug1;
- + gceSTATUS status;
- + gcmkHEADER_ARG("Hardware=0x%X", Hardware);
- +
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(Load != gcvNULL);
- +
- + gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE);
- +
- + if (Hardware->chipPowerState == gcvPOWER_ON)
- + {
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00110,
- + Load));
- +#if READ_FROM_EATER1
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00134,
- + Load));
- +#endif
- +
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00114,
- + &debug1));
- +
- + /* Patch result of 0x110 with result of 0x114. */
- + if ((debug1 & 0xFF) == 1)
- + {
- + *Load &= ~0xFF;
- + *Load |= 1;
- + }
- +
- + if (((debug1 & 0xFF00) >> 8) == 1)
- + {
- + *Load &= ~(0xFF << 8);
- + *Load |= 1 << 8;
- + }
- +
- + if (((debug1 & 0xFF0000) >> 16) == 1)
- + {
- + *Load &= ~(0xFF << 16);
- + *Load |= 1 << 16;
- + }
- +
- + if (((debug1 & 0xFF000000) >> 24) == 1)
- + {
- + *Load &= ~(0xFF << 24);
- + *Load |= 1 << 24;
- + }
- + }
- + else
- + {
- + status = gcvSTATUS_INVALID_REQUEST;
- + }
- +
- +OnError:
- +
- + gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex);
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckHARDWARE_SetDVFSPeroid(
- + IN gckHARDWARE Hardware,
- + OUT gctUINT32 Frequency
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 period;
- + gctUINT32 eater;
- +
- +#if READ_FROM_EATER1
- + gctUINT32 period1;
- + gctUINT32 eater1;
- +#endif
- +
- + gcmkHEADER_ARG("Hardware=0x%X Frequency=%d", Hardware, Frequency);
- +
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + period = 0;
- +
- + while((64 << period) < (gcdDVFS_ANAYLSE_WINDOW * Frequency * 1000) )
- + {
- + period++;
- + }
- +
- +#if READ_FROM_EATER1
- + /*
- + * Peroid = F * 1000 * 1000 / (60 * 16 * 1024);
- + */
- + period1 = Frequency * 6250 / 6114;
- +#endif
- +
- + gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE);
- +
- + if (Hardware->chipPowerState == gcvPOWER_ON)
- + {
- + /* Get current configure. */
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x0010C,
- + &eater));
- +
- + /* Change peroid. */
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x0010C,
- + ((((gctUINT32) (eater)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (period) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8)))));
- +
- +#if READ_FROM_EATER1
- + /* Config eater1. */
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00130,
- + &eater1));
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x00130,
- + ((((gctUINT32) (eater1)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:16) - (0 ? 31:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:16) - (0 ? 31:16) + 1))))))) << (0 ? 31:16))) | (((gctUINT32) ((gctUINT32) (period1) & ((gctUINT32) ((((1 ? 31:16) - (0 ? 31:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:16) - (0 ? 31:16) + 1))))))) << (0 ? 31:16)))));
- +#endif
- + }
- + else
- + {
- + status = gcvSTATUS_INVALID_REQUEST;
- + }
- +
- +OnError:
- + gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex);
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckHARDWARE_InitDVFS(
- + IN gckHARDWARE Hardware
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 data;
- +
- + gcmkHEADER_ARG("Hardware=0x%X", Hardware);
- +
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x0010C,
- + &data));
- +
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16)));
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1))))))) << (0 ? 18:18))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1))))))) << (0 ? 18:18)));
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20)));
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1))))))) << (0 ? 23:23))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1))))))) << (0 ? 23:23)));
- + data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1))))))) << (0 ? 22:22))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1))))))) << (0 ? 22:22)));
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
- + "DVFS Configure=0x%X",
- + data);
- +
- + gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
- + Hardware->core,
- + 0x0010C,
- + data));
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +#endif
- +
- +
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.h linux-3.14.35/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.h 2015-03-08 14:27:37.625684501 -0500
- @@ -0,0 +1,136 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_kernel_hardware_h_
- +#define __gc_hal_kernel_hardware_h_
- +
- +#if gcdENABLE_VG
- +#include "gc_hal_kernel_hardware_vg.h"
- +#endif
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +/* gckHARDWARE object. */
- +struct _gckHARDWARE
- +{
- + /* Object. */
- + gcsOBJECT object;
- +
- + /* Pointer to gctKERNEL object. */
- + gckKERNEL kernel;
- +
- + /* Pointer to gctOS object. */
- + gckOS os;
- +
- + /* Core */
- + gceCORE core;
- +
- + /* Chip characteristics. */
- + gcsHAL_QUERY_CHIP_IDENTITY identity;
- + gctBOOL allowFastClear;
- + gctBOOL allowCompression;
- + gctUINT32 powerBaseAddress;
- + gctBOOL extraEventStates;
- +
- + /* Big endian */
- + gctBOOL bigEndian;
- +
- + /* Chip status */
- + gctPOINTER powerMutex;
- + gctUINT32 powerProcess;
- + gctUINT32 powerThread;
- + gceCHIPPOWERSTATE chipPowerState;
- + gctUINT32 lastWaitLink;
- + gctBOOL clockState;
- + gctBOOL powerState;
- + gctPOINTER globalSemaphore;
- +
- + gctISRMANAGERFUNC startIsr;
- + gctISRMANAGERFUNC stopIsr;
- + gctPOINTER isrContext;
- +
- + gctUINT32 mmuVersion;
- +
- + /* Type */
- + gceHARDWARE_TYPE type;
- +
- +#if gcdPOWEROFF_TIMEOUT
- + gctUINT32 powerOffTime;
- + gctUINT32 powerOffTimeout;
- + gctPOINTER powerOffTimer;
- +#endif
- +
- + gctPOINTER pageTableDirty;
- +
- +#if gcdENABLE_FSCALE_VAL_ADJUST
- + /* FSCALE_VAL when gcvPOWER_ON. */
- + gctUINT32 powerOnFscaleVal;
- +#endif
- +
- +#if gcdLINK_QUEUE_SIZE
- + struct _gckLINKQUEUE linkQueue;
- +#endif
- +
- + gctBOOL powerManagement;
- + gctBOOL gpuProfiler;
- +};
- +
- +gceSTATUS
- +gckHARDWARE_GetBaseAddress(
- + IN gckHARDWARE Hardware,
- + OUT gctUINT32_PTR BaseAddress
- + );
- +
- +gceSTATUS
- +gckHARDWARE_NeedBaseAddress(
- + IN gckHARDWARE Hardware,
- + IN gctUINT32 State,
- + OUT gctBOOL_PTR NeedBase
- + );
- +
- +gceSTATUS
- +gckHARDWARE_GetFrameInfo(
- + IN gckHARDWARE Hardware,
- + OUT gcsHAL_FRAME_INFO * FrameInfo
- + );
- +
- +gceSTATUS
- +gckHARDWARE_SetFscaleValue(
- + IN gckHARDWARE Hardware,
- + IN gctUINT32 FscaleValue
- + );
- +
- +gceSTATUS
- +gckHARDWARE_GetFscaleValue(
- + IN gckHARDWARE Hardware,
- + IN gctUINT * FscaleValue,
- + IN gctUINT * MinFscaleValue,
- + IN gctUINT * MaxFscaleValue
- + );
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* __gc_hal_kernel_hardware_h_ */
- +
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/config linux-3.14.35/drivers/mxc/gpu-viv/config
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/config 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/config 2015-03-08 14:27:37.625684501 -0500
- @@ -0,0 +1,38 @@
- +##############################################################################
- +#
- +# Copyright (C) 2005 - 2013 by Vivante Corp.
- +#
- +# 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 program is distributed in the hope that it will be useful,
- +# but WITHOUT ANY WARRANTY; without even the implied warranty of
- +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +# GNU General Public License for more details.
- +#
- +# 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.
- +#
- +##############################################################################
- +
- +
- +ARCH_TYPE ?= arm
- +SDK_DIR ?= $(AQROOT)/build/sdk
- +USE_3D_VG ?= 1
- +FORCE_ALL_VIDEO_MEMORY_CACHED ?= 0
- +NONPAGED_MEMORY_CACHEABLE ?= 0
- +NONPAGED_MEMORY_BUFFERABLE ?= 1
- +CACHE_FUNCTION_UNIMPLEMENTED ?= 0
- +VIVANTE_ENABLE_VG ?= 1
- +NO_USER_DIRECT_ACCESS_FROM_KERNEL ?= 1
- +VIVANTE_NO_3D ?= 0
- +ENABLE_OUTER_CACHE_PATCH ?= 1
- +USE_BANK_ALIGNMENT ?= 1
- +BANK_BIT_START ?= 13
- +BANK_BIT_END ?= 15
- +BANK_CHANNEL_BIT ?= 12
- +ENABLE_GPU_CLOCK_BY_DRIVER = 1
- +
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c 2015-03-08 14:27:37.629684500 -0500
- @@ -0,0 +1,3967 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal_kernel_precomp.h"
- +
- +#define _GC_OBJ_ZONE gcvZONE_KERNEL
- +
- +/*******************************************************************************
- +***** Version Signature *******************************************************/
- +
- +#define _gcmTXT2STR(t) #t
- +#define gcmTXT2STR(t) _gcmTXT2STR(t)
- +const char * _VERSION = "\n\0$VERSION$"
- + gcmTXT2STR(gcvVERSION_MAJOR) "."
- + gcmTXT2STR(gcvVERSION_MINOR) "."
- + gcmTXT2STR(gcvVERSION_PATCH) ":"
- + gcmTXT2STR(gcvVERSION_BUILD) "$\n";
- +
- +/******************************************************************************\
- +******************************* gckKERNEL API Code ******************************
- +\******************************************************************************/
- +
- +#if gcmIS_DEBUG(gcdDEBUG_TRACE)
- +#define gcmDEFINE2TEXT(d) #d
- +gctCONST_STRING _DispatchText[] =
- +{
- + gcmDEFINE2TEXT(gcvHAL_QUERY_VIDEO_MEMORY),
- + gcmDEFINE2TEXT(gcvHAL_QUERY_CHIP_IDENTITY),
- + gcmDEFINE2TEXT(gcvHAL_ALLOCATE_NON_PAGED_MEMORY),
- + gcmDEFINE2TEXT(gcvHAL_FREE_NON_PAGED_MEMORY),
- + gcmDEFINE2TEXT(gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY),
- + gcmDEFINE2TEXT(gcvHAL_FREE_CONTIGUOUS_MEMORY),
- + gcmDEFINE2TEXT(gcvHAL_ALLOCATE_VIDEO_MEMORY),
- + gcmDEFINE2TEXT(gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY),
- + gcmDEFINE2TEXT(gcvHAL_FREE_VIDEO_MEMORY),
- + gcmDEFINE2TEXT(gcvHAL_MAP_MEMORY),
- + gcmDEFINE2TEXT(gcvHAL_UNMAP_MEMORY),
- + gcmDEFINE2TEXT(gcvHAL_MAP_USER_MEMORY),
- + gcmDEFINE2TEXT(gcvHAL_UNMAP_USER_MEMORY),
- + gcmDEFINE2TEXT(gcvHAL_LOCK_VIDEO_MEMORY),
- + gcmDEFINE2TEXT(gcvHAL_UNLOCK_VIDEO_MEMORY),
- + gcmDEFINE2TEXT(gcvHAL_EVENT_COMMIT),
- + gcmDEFINE2TEXT(gcvHAL_USER_SIGNAL),
- + gcmDEFINE2TEXT(gcvHAL_SIGNAL),
- + gcmDEFINE2TEXT(gcvHAL_WRITE_DATA),
- + gcmDEFINE2TEXT(gcvHAL_COMMIT),
- + gcmDEFINE2TEXT(gcvHAL_STALL),
- + gcmDEFINE2TEXT(gcvHAL_READ_REGISTER),
- + gcmDEFINE2TEXT(gcvHAL_WRITE_REGISTER),
- + gcmDEFINE2TEXT(gcvHAL_GET_PROFILE_SETTING),
- + gcmDEFINE2TEXT(gcvHAL_SET_PROFILE_SETTING),
- + gcmDEFINE2TEXT(gcvHAL_READ_ALL_PROFILE_REGISTERS),
- +#if VIVANTE_PROFILER_PERDRAW
- + gcmDEFINE2TEXT(gcvHAL_READ_PROFILER_REGISTER_SETTING),
- +#endif
- + gcmDEFINE2TEXT(gcvHAL_PROFILE_REGISTERS_2D),
- + gcmDEFINE2TEXT(gcvHAL_SET_POWER_MANAGEMENT_STATE),
- + gcmDEFINE2TEXT(gcvHAL_QUERY_POWER_MANAGEMENT_STATE),
- + gcmDEFINE2TEXT(gcvHAL_GET_BASE_ADDRESS),
- + gcmDEFINE2TEXT(gcvHAL_SET_IDLE),
- + gcmDEFINE2TEXT(gcvHAL_QUERY_KERNEL_SETTINGS),
- + gcmDEFINE2TEXT(gcvHAL_RESET),
- + gcmDEFINE2TEXT(gcvHAL_MAP_PHYSICAL),
- + gcmDEFINE2TEXT(gcvHAL_DEBUG),
- + gcmDEFINE2TEXT(gcvHAL_CACHE),
- + gcmDEFINE2TEXT(gcvHAL_TIMESTAMP),
- + gcmDEFINE2TEXT(gcvHAL_DATABASE),
- + gcmDEFINE2TEXT(gcvHAL_VERSION),
- + gcmDEFINE2TEXT(gcvHAL_CHIP_INFO),
- + gcmDEFINE2TEXT(gcvHAL_ATTACH),
- + gcmDEFINE2TEXT(gcvHAL_DETACH)
- +};
- +#endif
- +
- +#if gcdENABLE_RECOVERY
- +void
- +_ResetFinishFunction(
- + gctPOINTER Data
- + )
- +{
- + gckKERNEL kernel = (gckKERNEL)Data;
- +
- + gckOS_AtomSet(kernel->os, kernel->resetAtom, 0);
- +}
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_Construct
- +**
- +** Construct a new gckKERNEL object.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gceCORE Core
- +** Specified core.
- +**
- +** IN gctPOINTER Context
- +** Pointer to a driver defined context.
- +**
- +** IN gckDB SharedDB,
- +** Pointer to a shared DB.
- +**
- +** OUTPUT:
- +**
- +** gckKERNEL * Kernel
- +** Pointer to a variable that will hold the pointer to the gckKERNEL
- +** object.
- +*/
- +
- +gceSTATUS
- +gckKERNEL_Construct(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctPOINTER Context,
- + IN gckDB SharedDB,
- + OUT gckKERNEL * Kernel
- + )
- +{
- + gckKERNEL kernel = gcvNULL;
- + gceSTATUS status;
- + gctSIZE_T i;
- + gctPOINTER pointer = gcvNULL;
- +
- + gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os, Context);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
- +
- + /* Allocate the gckKERNEL object. */
- + gcmkONERROR(gckOS_Allocate(Os,
- + gcmSIZEOF(struct _gckKERNEL),
- + &pointer));
- +
- + kernel = pointer;
- +
- + /* Zero the object pointers. */
- + kernel->hardware = gcvNULL;
- + kernel->command = gcvNULL;
- + kernel->eventObj = gcvNULL;
- + kernel->mmu = gcvNULL;
- +#if gcdDVFS
- + kernel->dvfs = gcvNULL;
- +#endif
- +
- + /* Initialize the gckKERNEL object. */
- + kernel->object.type = gcvOBJ_KERNEL;
- + kernel->os = Os;
- + kernel->core = Core;
- +
- +
- + if (SharedDB == gcvNULL)
- + {
- + gcmkONERROR(gckOS_Allocate(Os,
- + gcmSIZEOF(struct _gckDB),
- + &pointer));
- +
- + kernel->db = pointer;
- + kernel->dbCreated = gcvTRUE;
- + kernel->db->freeDatabase = gcvNULL;
- + kernel->db->freeRecord = gcvNULL;
- + kernel->db->dbMutex = gcvNULL;
- + kernel->db->lastDatabase = gcvNULL;
- + kernel->db->idleTime = 0;
- + kernel->db->lastIdle = 0;
- + kernel->db->lastSlowdown = 0;
- +
- + for (i = 0; i < gcmCOUNTOF(kernel->db->db); ++i)
- + {
- + kernel->db->db[i] = gcvNULL;
- + }
- +
- + /* Construct a database mutex. */
- + gcmkONERROR(gckOS_CreateMutex(Os, &kernel->db->dbMutex));
- +
- + /* Construct a id-pointer database. */
- + gcmkONERROR(gckKERNEL_CreateIntegerDatabase(kernel, &kernel->db->pointerDatabase));
- +
- + /* Construct a id-pointer database mutex. */
- + gcmkONERROR(gckOS_CreateMutex(Os, &kernel->db->pointerDatabaseMutex));
- + }
- + else
- + {
- + kernel->db = SharedDB;
- + kernel->dbCreated = gcvFALSE;
- + }
- +
- + for (i = 0; i < gcmCOUNTOF(kernel->timers); ++i)
- + {
- + kernel->timers[i].startTime = 0;
- + kernel->timers[i].stopTime = 0;
- + }
- +
- + kernel->timeOut = gcdGPU_TIMEOUT;
- +
- + /* Save context. */
- + kernel->context = Context;
- +
- +#if gcdVIRTUAL_COMMAND_BUFFER
- + kernel->virtualBufferHead =
- + kernel->virtualBufferTail = gcvNULL;
- +
- + gcmkONERROR(
- + gckOS_CreateMutex(Os, (gctPOINTER)&kernel->virtualBufferLock));
- +#endif
- +
- + /* Construct atom holding number of clients. */
- + kernel->atomClients = gcvNULL;
- + gcmkONERROR(gckOS_AtomConstruct(Os, &kernel->atomClients));
- +
- +#if gcdENABLE_VG
- + kernel->vg = gcvNULL;
- +
- + if (Core == gcvCORE_VG)
- + {
- + /* Construct the gckMMU object. */
- + gcmkONERROR(
- + gckVGKERNEL_Construct(Os, Context, kernel, &kernel->vg));
- + }
- + else
- +#endif
- + {
- + /* Construct the gckHARDWARE object. */
- + gcmkONERROR(
- + gckHARDWARE_Construct(Os, kernel->core, &kernel->hardware));
- +
- + /* Set pointer to gckKERNEL object in gckHARDWARE object. */
- + kernel->hardware->kernel = kernel;
- +
- + /* Initialize the hardware. */
- + gcmkONERROR(
- + gckHARDWARE_InitializeHardware(kernel->hardware));
- +
- + /* Construct the gckCOMMAND object. */
- + gcmkONERROR(
- + gckCOMMAND_Construct(kernel, &kernel->command));
- +
- + /* Construct the gckEVENT object. */
- + gcmkONERROR(
- + gckEVENT_Construct(kernel, &kernel->eventObj));
- +
- + /* Construct the gckMMU object. */
- + gcmkONERROR(
- + gckMMU_Construct(kernel, gcdMMU_SIZE, &kernel->mmu));
- +
- +#if gcdENABLE_RECOVERY
- + gcmkONERROR(
- + gckOS_AtomConstruct(Os, &kernel->resetAtom));
- +
- + gcmkVERIFY_OK(
- + gckOS_CreateTimer(Os,
- + (gctTIMERFUNCTION)_ResetFinishFunction,
- + (gctPOINTER)kernel,
- + &kernel->resetFlagClearTimer));
- + kernel->resetTimeStamp = 0;
- +#endif
- +
- +#if gcdDVFS
- + if (gckHARDWARE_IsFeatureAvailable(kernel->hardware,
- + gcvFEATURE_DYNAMIC_FREQUENCY_SCALING))
- + {
- + gcmkONERROR(gckDVFS_Construct(kernel->hardware, &kernel->dvfs));
- + gcmkONERROR(gckDVFS_Start(kernel->dvfs));
- + }
- +#endif
- + }
- +
- + spin_lock_init(&kernel->irq_lock);
- +
- +#if VIVANTE_PROFILER
- + /* Initialize profile setting */
- + kernel->profileEnable = gcvFALSE;
- + kernel->profileCleanRegister = gcvTRUE;
- +#endif
- +
- +#if gcdANDROID_NATIVE_FENCE_SYNC
- + gcmkONERROR(gckOS_CreateSyncTimeline(Os, &kernel->timeline));
- +#endif
- +
- + /* Return pointer to the gckKERNEL object. */
- + *Kernel = kernel;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (kernel != gcvNULL)
- + {
- +#if gcdENABLE_VG
- + if (Core != gcvCORE_VG)
- +#endif
- + {
- + if (kernel->eventObj != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckEVENT_Destroy(kernel->eventObj));
- + }
- +
- + if (kernel->command != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckCOMMAND_Destroy(kernel->command));
- + }
- +
- + if (kernel->hardware != gcvNULL)
- + {
- + /* Turn off the power. */
- + gcmkVERIFY_OK(gckOS_SetGPUPower(kernel->hardware->os,
- + kernel->hardware->core,
- + gcvFALSE,
- + gcvFALSE));
- + gcmkVERIFY_OK(gckHARDWARE_Destroy(kernel->hardware));
- + }
- + }
- +
- + if (kernel->atomClients != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_AtomDestroy(Os, kernel->atomClients));
- + }
- +
- +#if gcdENABLE_RECOVERY
- + if (kernel->resetAtom != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_AtomDestroy(Os, kernel->resetAtom));
- + }
- +
- + if (kernel->resetFlagClearTimer)
- + {
- + gcmkVERIFY_OK(gckOS_StopTimer(Os, kernel->resetFlagClearTimer));
- + gcmkVERIFY_OK(gckOS_DestroyTimer(Os, kernel->resetFlagClearTimer));
- + }
- +#endif
- +
- + if (kernel->dbCreated && kernel->db != gcvNULL)
- + {
- + if (kernel->db->dbMutex != gcvNULL)
- + {
- + /* Destroy the database mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Os, kernel->db->dbMutex));
- + }
- +
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, kernel->db));
- + }
- +
- +#if gcdVIRTUAL_COMMAND_BUFFER
- + if (kernel->virtualBufferLock != gcvNULL)
- + {
- + /* Destroy the virtual command buffer mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Os, kernel->virtualBufferLock));
- + }
- +#endif
- +
- +#if gcdDVFS
- + if (kernel->dvfs)
- + {
- + gcmkVERIFY_OK(gckDVFS_Stop(kernel->dvfs));
- + gcmkVERIFY_OK(gckDVFS_Destroy(kernel->dvfs));
- + }
- +#endif
- +
- +#if gcdANDROID_NATIVE_FENCE_SYNC
- + if (kernel->timeline)
- + {
- + gcmkVERIFY_OK(gckOS_DestroySyncTimeline(Os, kernel->timeline));
- + }
- +#endif
- +
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, kernel));
- + }
- +
- + /* Return the error. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_Destroy
- +**
- +** Destroy an gckKERNEL object.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object to destroy.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckKERNEL_Destroy(
- + IN gckKERNEL Kernel
- + )
- +{
- + gctSIZE_T i;
- + gcsDATABASE_PTR database, databaseNext;
- + gcsDATABASE_RECORD_PTR record, recordNext;
- +
- + gcmkHEADER_ARG("Kernel=0x%x", Kernel);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- +#if QNX_SINGLE_THREADED_DEBUGGING
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->debugMutex));
- +#endif
- +
- + /* Destroy the database. */
- + if (Kernel->dbCreated)
- + {
- + for (i = 0; i < gcmCOUNTOF(Kernel->db->db); ++i)
- + {
- + if (Kernel->db->db[i] != gcvNULL)
- + {
- + gcmkVERIFY_OK(
- + gckKERNEL_DestroyProcessDB(Kernel, Kernel->db->db[i]->processID));
- + }
- + }
- +
- + /* Free all databases. */
- + for (database = Kernel->db->freeDatabase;
- + database != gcvNULL;
- + database = databaseNext)
- + {
- + databaseNext = database->next;
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, database));
- + }
- +
- + if (Kernel->db->lastDatabase != gcvNULL)
- + {
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, Kernel->db->lastDatabase));
- + }
- +
- + /* Free all database records. */
- + for (record = Kernel->db->freeRecord; record != gcvNULL; record = recordNext)
- + {
- + recordNext = record->next;
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, record));
- + }
- +
- + /* Destroy the database mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->db->dbMutex));
- +
- +
- + /* Destroy id-pointer database. */
- + gcmkVERIFY_OK(gckKERNEL_DestroyIntegerDatabase(Kernel, Kernel->db->pointerDatabase));
- +
- + /* Destroy id-pointer database mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
- + }
- +
- +#if gcdENABLE_VG
- + if (Kernel->vg)
- + {
- + gcmkVERIFY_OK(gckVGKERNEL_Destroy(Kernel->vg));
- + }
- + else
- +#endif
- + {
- + /* Destroy the gckMMU object. */
- + gcmkVERIFY_OK(gckMMU_Destroy(Kernel->mmu));
- +
- + /* Destroy the gckCOMMNAND object. */
- + gcmkVERIFY_OK(gckCOMMAND_Destroy(Kernel->command));
- +
- + /* Destroy the gckEVENT object. */
- + gcmkVERIFY_OK(gckEVENT_Destroy(Kernel->eventObj));
- +
- + /* Destroy the gckHARDWARE object. */
- + gcmkVERIFY_OK(gckHARDWARE_Destroy(Kernel->hardware));
- +
- +#if gcdENABLE_RECOVERY
- + gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, Kernel->resetAtom));
- +
- + if (Kernel->resetFlagClearTimer)
- + {
- + gcmkVERIFY_OK(gckOS_StopTimer(Kernel->os, Kernel->resetFlagClearTimer));
- + gcmkVERIFY_OK(gckOS_DestroyTimer(Kernel->os, Kernel->resetFlagClearTimer));
- + }
- +#endif
- + }
- +
- + /* Detsroy the client atom. */
- + gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, Kernel->atomClients));
- +
- +#if gcdVIRTUAL_COMMAND_BUFFER
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->virtualBufferLock));
- +#endif
- +
- +#if gcdDVFS
- + if (Kernel->dvfs)
- + {
- + gcmkVERIFY_OK(gckDVFS_Stop(Kernel->dvfs));
- + gcmkVERIFY_OK(gckDVFS_Destroy(Kernel->dvfs));
- + }
- +#endif
- +
- +#if gcdANDROID_NATIVE_FENCE_SYNC
- + gcmkVERIFY_OK(gckOS_DestroySyncTimeline(Kernel->os, Kernel->timeline));
- +#endif
- +
- + /* Mark the gckKERNEL object as unknown. */
- + Kernel->object.type = gcvOBJ_UNKNOWN;
- +
- + /* Free the gckKERNEL object. */
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, Kernel));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +#ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
- +#include <linux/kernel.h>
- +#include <linux/mm.h>
- +#include <linux/oom.h>
- +#include <linux/sched.h>
- +#include <linux/notifier.h>
- +
- +extern struct task_struct *lowmem_deathpending;
- +static unsigned long lowmem_deathpending_timeout;
- +
- +static int force_contiguous_lowmem_shrink(IN gckKERNEL Kernel)
- +{
- + struct task_struct *p;
- + struct task_struct *selected = NULL;
- + int tasksize;
- + int ret = -1;
- + int min_adj = 0;
- + int selected_tasksize = 0;
- + int selected_oom_adj;
- + /*
- + * If we already have a death outstanding, then
- + * bail out right away; indicating to vmscan
- + * that we have nothing further to offer on
- + * this pass.
- + *
- + */
- + if (lowmem_deathpending &&
- + time_before_eq(jiffies, lowmem_deathpending_timeout))
- + return 0;
- + selected_oom_adj = min_adj;
- +
- + read_lock(&tasklist_lock);
- + for_each_process(p) {
- + struct mm_struct *mm;
- + struct signal_struct *sig;
- + gcuDATABASE_INFO info;
- + int oom_adj;
- +
- + task_lock(p);
- + mm = p->mm;
- + sig = p->signal;
- + if (!mm || !sig) {
- + task_unlock(p);
- + continue;
- + }
- + oom_adj = sig->oom_adj;
- + if (oom_adj < min_adj) {
- + task_unlock(p);
- + continue;
- + }
- +
- + tasksize = 0;
- + if (gckKERNEL_QueryProcessDB(Kernel, p->pid, gcvFALSE, gcvDB_VIDEO_MEMORY, &info) == gcvSTATUS_OK){
- + tasksize += info.counters.bytes / PAGE_SIZE;
- + }
- + if (gckKERNEL_QueryProcessDB(Kernel, p->pid, gcvFALSE, gcvDB_CONTIGUOUS, &info) == gcvSTATUS_OK){
- + tasksize += info.counters.bytes / PAGE_SIZE;
- + }
- +
- + task_unlock(p);
- +
- + if (tasksize <= 0)
- + continue;
- +
- + gckOS_Print("<gpu> pid %d (%s), adj %d, size %d \n", p->pid, p->comm, oom_adj, tasksize);
- +
- + if (selected) {
- + if (oom_adj < selected_oom_adj)
- + continue;
- + if (oom_adj == selected_oom_adj &&
- + tasksize <= selected_tasksize)
- + continue;
- + }
- + selected = p;
- + selected_tasksize = tasksize;
- + selected_oom_adj = oom_adj;
- + }
- + if (selected) {
- + gckOS_Print("<gpu> send sigkill to %d (%s), adj %d, size %d\n",
- + selected->pid, selected->comm,
- + selected_oom_adj, selected_tasksize);
- + lowmem_deathpending = selected;
- + lowmem_deathpending_timeout = jiffies + HZ;
- + force_sig(SIGKILL, selected);
- + ret = 0;
- + }
- + read_unlock(&tasklist_lock);
- + return ret;
- +}
- +
- +#endif
- +
- +/*******************************************************************************
- +**
- +** _AllocateMemory
- +**
- +** Private function to walk all required memory pools to allocate the requested
- +** amount of video memory.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gcsHAL_INTERFACE * Interface
- +** Pointer to a gcsHAL_INTERFACE structure that defines the command to
- +** be dispatched.
- +**
- +** OUTPUT:
- +**
- +** gcsHAL_INTERFACE * Interface
- +** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
- +** returned.
- +*/
- +static gceSTATUS
- +_AllocateMemory(
- + IN gckKERNEL Kernel,
- + IN OUT gcePOOL * Pool,
- + IN gctSIZE_T Bytes,
- + IN gctSIZE_T Alignment,
- + IN gceSURF_TYPE Type,
- + OUT gcuVIDMEM_NODE_PTR * Node
- + )
- +{
- + gcePOOL pool;
- + gceSTATUS status;
- + gckVIDMEM videoMemory;
- + gctINT loopCount;
- + gcuVIDMEM_NODE_PTR node = gcvNULL;
- + gctBOOL tileStatusInVirtual;
- + gctBOOL forceContiguous = gcvFALSE;
- +
- + gcmkHEADER_ARG("Kernel=0x%x *Pool=%d Bytes=%lu Alignment=%lu Type=%d",
- + Kernel, *Pool, Bytes, Alignment, Type);
- +
- + gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Bytes != 0);
- +
- +#ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
- +_AllocateMemory_Retry:
- +#endif
- + /* Get initial pool. */
- + switch (pool = *Pool)
- + {
- + case gcvPOOL_DEFAULT_FORCE_CONTIGUOUS:
- + forceContiguous = gcvTRUE;
- + case gcvPOOL_DEFAULT:
- + case gcvPOOL_LOCAL:
- + pool = gcvPOOL_LOCAL_INTERNAL;
- + loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
- + break;
- +
- + case gcvPOOL_UNIFIED:
- + pool = gcvPOOL_SYSTEM;
- + loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
- + break;
- +
- + case gcvPOOL_CONTIGUOUS:
- + loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
- + break;
- +
- + case gcvPOOL_DEFAULT_FORCE_CONTIGUOUS_CACHEABLE:
- + pool = gcvPOOL_CONTIGUOUS;
- + loopCount = 1;
- + forceContiguous = gcvTRUE;
- + break;
- +
- + default:
- + loopCount = 1;
- + break;
- + }
- +
- + while (loopCount-- > 0)
- + {
- + if (pool == gcvPOOL_VIRTUAL)
- + {
- + /* Create a gcuVIDMEM_NODE for virtual memory. */
- + gcmkONERROR(
- + gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, &node));
- +
- + /* Success. */
- + break;
- + }
- +
- + else
- + if (pool == gcvPOOL_CONTIGUOUS)
- + {
- +#if gcdCONTIGUOUS_SIZE_LIMIT
- + if (Bytes > gcdCONTIGUOUS_SIZE_LIMIT && forceContiguous == gcvFALSE)
- + {
- + status = gcvSTATUS_OUT_OF_MEMORY;
- + }
- + else
- +#endif
- + {
- + /* Create a gcuVIDMEM_NODE from contiguous memory. */
- + status = gckVIDMEM_ConstructVirtual(Kernel, gcvTRUE, Bytes, &node);
- + }
- +
- + if (gcmIS_SUCCESS(status) || forceContiguous == gcvTRUE)
- + {
- + /* Memory allocated. */
- + if(node && forceContiguous == gcvTRUE)
- + {
- + gctUINT32 physAddr=0;
- + gctUINT32 baseAddress = 0;
- +
- + gcmkONERROR(
- + gckOS_LockPages(Kernel->os,
- + node->Virtual.physical,
- + node->Virtual.bytes,
- + gcvFALSE,
- + &node->Virtual.logical,
- + &node->Virtual.pageCount));
- +
- + /* Convert logical address into a physical address. */
- + gcmkONERROR(
- + gckOS_GetPhysicalAddress(Kernel->os,
- + node->Virtual.logical,
- + &physAddr));
- +
- + gcmkONERROR(
- + gckOS_UnlockPages(Kernel->os,
- + node->Virtual.physical,
- + node->Virtual.bytes,
- + node->Virtual.logical));
- +
- + gcmkONERROR(gckOS_GetBaseAddress(Kernel->os, &baseAddress));
- +
- + gcmkASSERT(physAddr >= baseAddress);
- +
- + /* Subtract baseAddress to get a GPU address used for programming. */
- + physAddr -= baseAddress;
- +
- + if((physAddr & 0x80000000) || ((physAddr + Bytes) & 0x80000000))
- + {
- + gckOS_Print("gpu virtual memory 0x%x cannot be allocated in force contiguous request!\n", physAddr);
- +
- + gcmkONERROR(gckVIDMEM_Free(node));
- +
- + node = gcvNULL;
- + }
- + }
- +
- + break;
- + }
- + }
- +
- + else
- + {
- + /* Get pointer to gckVIDMEM object for pool. */
- +#if gcdUSE_VIDMEM_PER_PID
- + gctUINT32 pid;
- + gckOS_GetProcessID(&pid);
- +
- + status = gckKERNEL_GetVideoMemoryPoolPid(Kernel, pool, pid, &videoMemory);
- + if (status == gcvSTATUS_NOT_FOUND)
- + {
- + /* Create VidMem pool for this process. */
- + status = gckKERNEL_CreateVideoMemoryPoolPid(Kernel, pool, pid, &videoMemory);
- + }
- +#else
- + status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory);
- +#endif
- +
- + if (gcmIS_SUCCESS(status))
- + {
- + /* Allocate memory. */
- + status = gckVIDMEM_AllocateLinear(videoMemory,
- + Bytes,
- + Alignment,
- + Type,
- + &node);
- +
- + if (gcmIS_SUCCESS(status))
- + {
- + /* Memory allocated. */
- + node->VidMem.pool = pool;
- + break;
- + }
- + }
- + }
- +
- + if (pool == gcvPOOL_LOCAL_INTERNAL)
- + {
- + /* Advance to external memory. */
- + pool = gcvPOOL_LOCAL_EXTERNAL;
- + }
- +
- + else
- + if (pool == gcvPOOL_LOCAL_EXTERNAL)
- + {
- + /* Advance to contiguous system memory. */
- + pool = gcvPOOL_SYSTEM;
- + }
- +
- + else
- + if (pool == gcvPOOL_SYSTEM)
- + {
- + /* Advance to contiguous memory. */
- + pool = gcvPOOL_CONTIGUOUS;
- + }
- +
- + else
- + if (pool == gcvPOOL_CONTIGUOUS)
- + {
- + tileStatusInVirtual =
- + gckHARDWARE_IsFeatureAvailable(Kernel->hardware,
- + gcvFEATURE_MC20);
- +
- + if (Type == gcvSURF_TILE_STATUS && tileStatusInVirtual != gcvTRUE)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + /* Advance to virtual memory. */
- + pool = gcvPOOL_VIRTUAL;
- + }
- +
- + else
- + {
- + /* Out of pools. */
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- + }
- +
- + if (node == gcvNULL)
- + {
- +
- +#ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
- + if(forceContiguous == gcvTRUE)
- + {
- + if(force_contiguous_lowmem_shrink(Kernel) == 0)
- + {
- + /* Sleep 1 millisecond. */
- + gckOS_Delay(gcvNULL, 1);
- + goto _AllocateMemory_Retry;
- + }
- + }
- +#endif
- + /* Nothing allocated. */
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + /* Return node and pool used for allocation. */
- + *Node = node;
- + *Pool = pool;
- +
- + /* Return status. */
- + gcmkFOOTER_ARG("*Pool=%d *Node=0x%x", *Pool, *Node);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_Dispatch
- +**
- +** Dispatch a command received from the user HAL layer.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gctBOOL FromUser
- +** whether the call is from the user space.
- +**
- +** gcsHAL_INTERFACE * Interface
- +** Pointer to a gcsHAL_INTERFACE structure that defines the command to
- +** be dispatched.
- +**
- +** OUTPUT:
- +**
- +** gcsHAL_INTERFACE * Interface
- +** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
- +** returned.
- +*/
- +
- +gceSTATUS
- +gckKERNEL_Dispatch(
- + IN gckKERNEL Kernel,
- + IN gctBOOL FromUser,
- + IN OUT gcsHAL_INTERFACE * Interface
- + )
- +{
- + gceSTATUS status = gcvSTATUS_OK;
- + gctSIZE_T bytes;
- + gcuVIDMEM_NODE_PTR node;
- + gctBOOL locked = gcvFALSE;
- + gctPHYS_ADDR physical = gcvNULL;
- + gctPOINTER logical = gcvNULL;
- + gctPOINTER info = gcvNULL;
- + gckCONTEXT context = gcvNULL;
- + gctUINT32 address;
- + gctUINT32 processID;
- + gckKERNEL kernel = Kernel;
- +#if gcdSECURE_USER
- + gcskSECURE_CACHE_PTR cache;
- +#endif
- + gctBOOL asynchronous;
- + gctPOINTER paddr = gcvNULL;
- +#if !USE_NEW_LINUX_SIGNAL
- + gctSIGNAL signal;
- +#endif
- + gceSURF_TYPE type;
- +
- + gcmkHEADER_ARG("Kernel=0x%x FromUser=%d Interface=0x%x",
- + Kernel, FromUser, Interface);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
- +
- +#if gcmIS_DEBUG(gcdDEBUG_TRACE)
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
- + "Dispatching command %d (%s)",
- + Interface->command, _DispatchText[Interface->command]);
- +#endif
- +#if QNX_SINGLE_THREADED_DEBUGGING
- + gckOS_AcquireMutex(Kernel->os, Kernel->debugMutex, gcvINFINITE);
- +#endif
- +
- + /* Get the current process ID. */
- + gcmkONERROR(gckOS_GetProcessID(&processID));
- +
- +#if gcdSECURE_USER
- + gcmkONERROR(gckKERNEL_GetProcessDBCache(Kernel, processID, &cache));
- +#endif
- +
- + /* Dispatch on command. */
- + switch (Interface->command)
- + {
- + case gcvHAL_GET_BASE_ADDRESS:
- + /* Get base address. */
- + gcmkONERROR(
- + gckOS_GetBaseAddress(Kernel->os,
- + &Interface->u.GetBaseAddress.baseAddress));
- + break;
- +
- + case gcvHAL_QUERY_VIDEO_MEMORY:
- + /* Query video memory size. */
- + gcmkONERROR(gckKERNEL_QueryVideoMemory(Kernel, Interface));
- + break;
- +
- + case gcvHAL_QUERY_CHIP_IDENTITY:
- + /* Query chip identity. */
- + gcmkONERROR(
- + gckHARDWARE_QueryChipIdentity(
- + Kernel->hardware,
- + &Interface->u.QueryChipIdentity));
- + break;
- +
- + case gcvHAL_MAP_MEMORY:
- + physical = gcmINT2PTR(Interface->u.MapMemory.physical);
- +
- + /* Map memory. */
- + gcmkONERROR(
- + gckKERNEL_MapMemory(Kernel,
- + physical,
- + (gctSIZE_T) Interface->u.MapMemory.bytes,
- + &logical));
- +
- + Interface->u.MapMemory.logical = gcmPTR_TO_UINT64(logical);
- +
- + gcmkVERIFY_OK(
- + gckKERNEL_AddProcessDB(Kernel,
- + processID, gcvDB_MAP_MEMORY,
- + logical,
- + physical,
- + (gctSIZE_T) Interface->u.MapMemory.bytes));
- + break;
- +
- + case gcvHAL_UNMAP_MEMORY:
- + physical = gcmINT2PTR(Interface->u.UnmapMemory.physical);
- +
- + /* Unmap memory. */
- + gcmkONERROR(
- + gckKERNEL_UnmapMemory(Kernel,
- + physical,
- + (gctSIZE_T) Interface->u.UnmapMemory.bytes,
- + gcmUINT64_TO_PTR(Interface->u.UnmapMemory.logical)));
- + gcmkVERIFY_OK(
- + gckKERNEL_RemoveProcessDB(Kernel,
- + processID, gcvDB_MAP_MEMORY,
- + gcmUINT64_TO_PTR(Interface->u.UnmapMemory.logical)));
- + break;
- +
- + case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
- + bytes = (gctSIZE_T) Interface->u.AllocateNonPagedMemory.bytes;
- +
- + /* Allocate non-paged memory. */
- + gcmkONERROR(
- + gckOS_AllocateNonPagedMemory(
- + Kernel->os,
- + FromUser,
- + &bytes,
- + &physical,
- + &logical));
- +
- + Interface->u.AllocateNonPagedMemory.bytes = bytes;
- + Interface->u.AllocateNonPagedMemory.logical = gcmPTR_TO_UINT64(logical);
- + Interface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
- +
- + gcmkVERIFY_OK(
- + gckKERNEL_AddProcessDB(Kernel,
- + processID, gcvDB_NON_PAGED,
- + logical,
- + gcmINT2PTR(Interface->u.AllocateNonPagedMemory.physical),
- + bytes));
- +
- + break;
- +
- + case gcvHAL_ALLOCATE_VIRTUAL_COMMAND_BUFFER:
- +#if gcdVIRTUAL_COMMAND_BUFFER
- + bytes = (gctSIZE_T) Interface->u.AllocateVirtualCommandBuffer.bytes;
- +
- + gcmkONERROR(
- + gckKERNEL_AllocateVirtualCommandBuffer(
- + Kernel,
- + FromUser,
- + &bytes,
- + &physical,
- + &logical));
- +
- + Interface->u.AllocateVirtualCommandBuffer.bytes = bytes;
- + Interface->u.AllocateVirtualCommandBuffer.logical = gcmPTR_TO_UINT64(logical);
- + Interface->u.AllocateVirtualCommandBuffer.physical = gcmPTR_TO_NAME(physical);
- +
- + gcmkVERIFY_OK(
- + gckKERNEL_AddProcessDB(Kernel,
- + processID, gcvDB_COMMAND_BUFFER,
- + logical,
- + gcmINT2PTR(Interface->u.AllocateVirtualCommandBuffer.physical),
- + bytes));
- +#else
- + status = gcvSTATUS_NOT_SUPPORTED;
- +#endif
- + break;
- +
- + case gcvHAL_FREE_NON_PAGED_MEMORY:
- + physical = gcmNAME_TO_PTR(Interface->u.FreeNonPagedMemory.physical);
- +
- + /* Unmap user logical out of physical memory first. */
- + gcmkONERROR(gckOS_UnmapUserLogical(Kernel->os,
- + physical,
- + (gctSIZE_T) Interface->u.FreeNonPagedMemory.bytes,
- + gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
- +
- + /* Free non-paged memory. */
- + gcmkONERROR(
- + gckOS_FreeNonPagedMemory(Kernel->os,
- + (gctSIZE_T) Interface->u.FreeNonPagedMemory.bytes,
- + physical,
- + gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
- +
- + gcmkVERIFY_OK(
- + gckKERNEL_RemoveProcessDB(Kernel,
- + processID, gcvDB_NON_PAGED,
- + gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
- +
- +#if gcdSECURE_USER
- + gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
- + Kernel,
- + cache,
- + gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical),
- + Interface->u.FreeNonPagedMemory.bytes));
- +#endif
- +
- + gcmRELEASE_NAME(Interface->u.FreeNonPagedMemory.physical);
- +
- + break;
- +
- + case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
- + bytes = (gctSIZE_T) Interface->u.AllocateContiguousMemory.bytes;
- +
- + /* Allocate contiguous memory. */
- + gcmkONERROR(gckOS_AllocateContiguous(
- + Kernel->os,
- + FromUser,
- + &bytes,
- + &physical,
- + &logical));
- +
- + Interface->u.AllocateContiguousMemory.bytes = bytes;
- + Interface->u.AllocateContiguousMemory.logical = gcmPTR_TO_UINT64(logical);
- + Interface->u.AllocateContiguousMemory.physical = gcmPTR_TO_NAME(physical);
- +
- + gcmkONERROR(gckHARDWARE_ConvertLogical(
- + Kernel->hardware,
- + gcmUINT64_TO_PTR(Interface->u.AllocateContiguousMemory.logical),
- + &Interface->u.AllocateContiguousMemory.address));
- +
- + gcmkVERIFY_OK(gckKERNEL_AddProcessDB(
- + Kernel,
- + processID, gcvDB_CONTIGUOUS,
- + logical,
- + gcmINT2PTR(Interface->u.AllocateContiguousMemory.physical),
- + bytes));
- +
- + break;
- +
- + case gcvHAL_FREE_CONTIGUOUS_MEMORY:
- + physical = gcmNAME_TO_PTR(Interface->u.FreeContiguousMemory.physical);
- +
- + /* Unmap user logical out of physical memory first. */
- + gcmkONERROR(gckOS_UnmapUserLogical(Kernel->os,
- + physical,
- + (gctSIZE_T) Interface->u.FreeContiguousMemory.bytes,
- + gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical)));
- +
- + /* Free contiguous memory. */
- + gcmkONERROR(
- + gckOS_FreeContiguous(Kernel->os,
- + physical,
- + gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical),
- + (gctSIZE_T) Interface->u.FreeContiguousMemory.bytes));
- +
- + gcmkVERIFY_OK(
- + gckKERNEL_RemoveProcessDB(Kernel,
- + processID, gcvDB_CONTIGUOUS,
- + gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
- +
- +#if gcdSECURE_USER
- + gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
- + Kernel,
- + cache,
- + gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical),
- + Interface->u.FreeContiguousMemory.bytes));
- +#endif
- +
- + gcmRELEASE_NAME(Interface->u.FreeContiguousMemory.physical);
- +
- + break;
- +
- + case gcvHAL_ALLOCATE_VIDEO_MEMORY:
- +
- + gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
- +
- + break;
- +
- + case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
- + type = Interface->u.AllocateLinearVideoMemory.type;
- +
- + /* Allocate memory. */
- + gcmkONERROR(
- + _AllocateMemory(Kernel,
- + &Interface->u.AllocateLinearVideoMemory.pool,
- + Interface->u.AllocateLinearVideoMemory.bytes,
- + Interface->u.AllocateLinearVideoMemory.alignment,
- + Interface->u.AllocateLinearVideoMemory.type,
- + &node));
- +
- + if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
- + {
- + bytes = node->VidMem.bytes;
- + node->VidMem.type = type;
- +
- + gcmkONERROR(
- + gckKERNEL_AddProcessDB(Kernel,
- + processID, gcvDB_VIDEO_MEMORY_RESERVED,
- + node,
- + gcvNULL,
- + bytes));
- + }
- + else
- + {
- + bytes = node->Virtual.bytes;
- + node->Virtual.type = type;
- +
- + if(node->Virtual.contiguous)
- + {
- + gcmkONERROR(
- + gckKERNEL_AddProcessDB(Kernel,
- + processID, gcvDB_VIDEO_MEMORY_CONTIGUOUS,
- + node,
- + gcvNULL,
- + bytes));
- + }
- + else
- + {
- + gcmkONERROR(
- + gckKERNEL_AddProcessDB(Kernel,
- + processID, gcvDB_VIDEO_MEMORY_VIRTUAL,
- + node,
- + gcvNULL,
- + bytes));
- + }
- +
- + }
- +
- + gcmkONERROR(
- + gckKERNEL_AddProcessDB(Kernel,
- + processID, gcvDB_VIDEO_MEMORY,
- + node,
- + gcvNULL,
- + bytes));
- +
- + /* Get the node. */
- + Interface->u.AllocateLinearVideoMemory.node = gcmPTR_TO_UINT64(node);
- + break;
- +
- + case gcvHAL_FREE_VIDEO_MEMORY:
- + node = gcmUINT64_TO_PTR(Interface->u.FreeVideoMemory.node);
- +#ifdef __QNXNTO__
- + if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM
- + && node->VidMem.logical != gcvNULL)
- + {
- + gcmkONERROR(
- + gckKERNEL_UnmapVideoMemory(Kernel,
- + node->VidMem.logical,
- + processID,
- + node->VidMem.bytes));
- + node->VidMem.logical = gcvNULL;
- + }
- +#endif
- + /* Free video memory. */
- + gcmkONERROR(
- + gckVIDMEM_Free(node));
- +
- + gcmkONERROR(
- + gckKERNEL_RemoveProcessDB(Kernel,
- + processID, gcvDB_VIDEO_MEMORY,
- + node));
- +
- + if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
- + {
- + gcmkONERROR(
- + gckKERNEL_RemoveProcessDB(Kernel,
- + processID, gcvDB_VIDEO_MEMORY_RESERVED,
- + node));
- + }
- + else if(node->Virtual.contiguous)
- + {
- + gcmkONERROR(
- + gckKERNEL_RemoveProcessDB(Kernel,
- + processID, gcvDB_VIDEO_MEMORY_CONTIGUOUS,
- + node));
- + }
- + else
- + {
- + gcmkONERROR(
- + gckKERNEL_RemoveProcessDB(Kernel,
- + processID, gcvDB_VIDEO_MEMORY_VIRTUAL,
- + node));
- + }
- +
- + break;
- +
- + case gcvHAL_LOCK_VIDEO_MEMORY:
- + node = gcmUINT64_TO_PTR(Interface->u.LockVideoMemory.node);
- +
- + /* Lock video memory. */
- + gcmkONERROR(
- + gckVIDMEM_Lock(Kernel,
- + node,
- + Interface->u.LockVideoMemory.cacheable,
- + &Interface->u.LockVideoMemory.address));
- +
- + locked = gcvTRUE;
- +
- + if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
- + {
- + /* Map video memory address into user space. */
- +#ifdef __QNXNTO__
- + if (node->VidMem.logical == gcvNULL)
- + {
- + gcmkONERROR(
- + gckKERNEL_MapVideoMemory(Kernel,
- + FromUser,
- + Interface->u.LockVideoMemory.address,
- + processID,
- + node->VidMem.bytes,
- + &node->VidMem.logical));
- + }
- + gcmkASSERT(node->VidMem.logical != gcvNULL);
- +
- + Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(node->VidMem.logical);
- +#else
- + gcmkONERROR(
- + gckKERNEL_MapVideoMemory(Kernel,
- + FromUser,
- + Interface->u.LockVideoMemory.address,
- + &logical));
- +
- + Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(logical);
- +#endif
- + }
- + else
- + {
- + Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(node->Virtual.logical);
- +
- + /* Success. */
- + status = gcvSTATUS_OK;
- + }
- +
- +#if gcdSECURE_USER
- + /* Return logical address as physical address. */
- + Interface->u.LockVideoMemory.address =
- + Interface->u.LockVideoMemory.memory;
- +#endif
- + gcmkONERROR(
- + gckKERNEL_AddProcessDB(Kernel,
- + processID, gcvDB_VIDEO_MEMORY_LOCKED,
- + node,
- + gcvNULL,
- + 0));
- +
- + break;
- +
- + case gcvHAL_UNLOCK_VIDEO_MEMORY:
- + /* Unlock video memory. */
- + node = gcmUINT64_TO_PTR(Interface->u.UnlockVideoMemory.node);
- +
- +#if gcdSECURE_USER
- + /* Save node information before it disappears. */
- + if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
- + {
- + logical = gcvNULL;
- + bytes = 0;
- + }
- + else
- + {
- + logical = node->Virtual.logical;
- + bytes = node->Virtual.bytes;
- + }
- +#endif
- +
- + /* Unlock video memory. */
- + gcmkONERROR(
- + gckVIDMEM_Unlock(Kernel,
- + node,
- + Interface->u.UnlockVideoMemory.type,
- + &Interface->u.UnlockVideoMemory.asynchroneous));
- +
- +#if gcdSECURE_USER
- + /* Flush the translation cache for virtual surfaces. */
- + if (logical != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(Kernel,
- + cache,
- + logical,
- + bytes));
- + }
- +#endif
- + if (Interface->u.UnlockVideoMemory.asynchroneous == gcvFALSE)
- + {
- + /* There isn't a event to unlock this node, remove record now */
- + gcmkONERROR(
- + gckKERNEL_RemoveProcessDB(Kernel,
- + processID, gcvDB_VIDEO_MEMORY_LOCKED,
- + node));
- + }
- + break;
- +
- + case gcvHAL_EVENT_COMMIT:
- + /* Commit an event queue. */
- + gcmkONERROR(
- + gckEVENT_Commit(Kernel->eventObj,
- + gcmUINT64_TO_PTR(Interface->u.Event.queue)));
- + break;
- +
- + case gcvHAL_COMMIT:
- + /* Commit a command and context buffer. */
- + gcmkONERROR(
- + gckCOMMAND_Commit(Kernel->command,
- + Interface->u.Commit.context ?
- + gcmNAME_TO_PTR(Interface->u.Commit.context) : gcvNULL,
- + gcmUINT64_TO_PTR(Interface->u.Commit.commandBuffer),
- + gcmUINT64_TO_PTR(Interface->u.Commit.delta),
- + gcmUINT64_TO_PTR(Interface->u.Commit.queue),
- + processID));
- + break;
- +
- + case gcvHAL_STALL:
- + /* Stall the command queue. */
- + gcmkONERROR(gckCOMMAND_Stall(Kernel->command, gcvFALSE));
- + break;
- +
- + case gcvHAL_MAP_USER_MEMORY:
- + /* Map user memory to DMA. */
- + gcmkONERROR(
- + gckOS_MapUserMemory(Kernel->os,
- + Kernel->core,
- + gcmUINT64_TO_PTR(Interface->u.MapUserMemory.memory),
- + Interface->u.MapUserMemory.physical,
- + (gctSIZE_T) Interface->u.MapUserMemory.size,
- + &info,
- + &Interface->u.MapUserMemory.address));
- +
- + Interface->u.MapUserMemory.info = gcmPTR_TO_NAME(info);
- +
- + gcmkVERIFY_OK(
- + gckKERNEL_AddProcessDB(Kernel,
- + processID, gcvDB_MAP_USER_MEMORY,
- + gcmINT2PTR(Interface->u.MapUserMemory.info),
- + gcmUINT64_TO_PTR(Interface->u.MapUserMemory.memory),
- + (gctSIZE_T) Interface->u.MapUserMemory.size));
- + break;
- +
- + case gcvHAL_UNMAP_USER_MEMORY:
- + address = Interface->u.UnmapUserMemory.address;
- + info = gcmNAME_TO_PTR(Interface->u.UnmapUserMemory.info);
- +
- + /* Unmap user memory. */
- + gcmkONERROR(
- + gckOS_UnmapUserMemory(Kernel->os,
- + Kernel->core,
- + gcmUINT64_TO_PTR(Interface->u.UnmapUserMemory.memory),
- + (gctSIZE_T) Interface->u.UnmapUserMemory.size,
- + info,
- + address));
- +
- +#if gcdSECURE_USER
- + gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
- + Kernel,
- + cache,
- + gcmUINT64_TO_PTR(Interface->u.UnmapUserMemory.memory),
- + Interface->u.UnmapUserMemory.size));
- +#endif
- + gcmkVERIFY_OK(
- + gckKERNEL_RemoveProcessDB(Kernel,
- + processID, gcvDB_MAP_USER_MEMORY,
- + gcmINT2PTR(Interface->u.UnmapUserMemory.info)));
- +
- + gcmRELEASE_NAME(Interface->u.UnmapUserMemory.info);
- +
- + break;
- +
- +#if !USE_NEW_LINUX_SIGNAL
- + case gcvHAL_USER_SIGNAL:
- + /* Dispatch depends on the user signal subcommands. */
- + switch(Interface->u.UserSignal.command)
- + {
- + case gcvUSER_SIGNAL_CREATE:
- + /* Create a signal used in the user space. */
- + gcmkONERROR(
- + gckOS_CreateUserSignal(Kernel->os,
- + Interface->u.UserSignal.manualReset,
- + &Interface->u.UserSignal.id));
- +
- + gcmkVERIFY_OK(
- + gckKERNEL_AddProcessDB(Kernel,
- + processID, gcvDB_SIGNAL,
- + gcmINT2PTR(Interface->u.UserSignal.id),
- + gcvNULL,
- + 0));
- + break;
- +
- + case gcvUSER_SIGNAL_DESTROY:
- + /* Destroy the signal. */
- + gcmkONERROR(
- + gckOS_DestroyUserSignal(Kernel->os,
- + Interface->u.UserSignal.id));
- +
- + gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
- + Kernel,
- + processID, gcvDB_SIGNAL,
- + gcmINT2PTR(Interface->u.UserSignal.id)));
- + break;
- +
- + case gcvUSER_SIGNAL_SIGNAL:
- + /* Signal the signal. */
- + gcmkONERROR(
- + gckOS_SignalUserSignal(Kernel->os,
- + Interface->u.UserSignal.id,
- + Interface->u.UserSignal.state));
- + break;
- +
- + case gcvUSER_SIGNAL_WAIT:
- +#if gcdGPU_TIMEOUT
- + if (Interface->u.UserSignal.wait == gcvINFINITE)
- + {
- + gckHARDWARE hardware;
- + gctUINT32 timer = 0;
- +
- + for(;;)
- + {
- + /* Wait on the signal. */
- + status = gckOS_WaitUserSignal(Kernel->os,
- + Interface->u.UserSignal.id,
- + gcdGPU_ADVANCETIMER);
- +
- + if (status == gcvSTATUS_TIMEOUT)
- + {
- + gcmkONERROR(
- + gckOS_SignalQueryHardware(Kernel->os,
- + (gctSIGNAL)(gctUINTPTR_T)Interface->u.UserSignal.id,
- + &hardware));
- +
- + if (hardware)
- + {
- + /* This signal is bound to a hardware,
- + ** so the timeout is limited by Kernel->timeOut.
- + */
- + timer += gcdGPU_ADVANCETIMER;
- + }
- +
- + if (timer >= Kernel->timeOut)
- + {
- + gcmkONERROR(
- + gckOS_Broadcast(Kernel->os,
- + hardware,
- + gcvBROADCAST_GPU_STUCK));
- +
- + timer = 0;
- +
- + /* If a few process try to reset GPU, only one
- + ** of them can do the real reset, other processes
- + ** still need to wait for this signal is triggered,
- + ** which menas reset is finished.
- + */
- + continue;
- + }
- + }
- + else
- + {
- + /* Bail out on other error. */
- + gcmkONERROR(status);
- +
- + /* Wait for signal successfully. */
- + break;
- + }
- + }
- + }
- + else
- +#endif
- + {
- + /* Wait on the signal. */
- + status = gckOS_WaitUserSignal(Kernel->os,
- + Interface->u.UserSignal.id,
- + Interface->u.UserSignal.wait);
- + }
- +
- + break;
- +
- + case gcvUSER_SIGNAL_MAP:
- + gcmkONERROR(
- + gckOS_MapSignal(Kernel->os,
- + (gctSIGNAL)(gctUINTPTR_T)Interface->u.UserSignal.id,
- + (gctHANDLE)(gctUINTPTR_T)processID,
- + &signal));
- +
- + gcmkVERIFY_OK(
- + gckKERNEL_AddProcessDB(Kernel,
- + processID, gcvDB_SIGNAL,
- + gcmINT2PTR(Interface->u.UserSignal.id),
- + gcvNULL,
- + 0));
- + break;
- +
- + case gcvUSER_SIGNAL_UNMAP:
- + /* Destroy the signal. */
- + gcmkONERROR(
- + gckOS_DestroyUserSignal(Kernel->os,
- + Interface->u.UserSignal.id));
- +
- + gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
- + Kernel,
- + processID, gcvDB_SIGNAL,
- + gcmINT2PTR(Interface->u.UserSignal.id)));
- + break;
- +
- + default:
- + /* Invalid user signal command. */
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- + break;
- +#endif
- +
- + case gcvHAL_SET_POWER_MANAGEMENT_STATE:
- + /* Set the power management state. */
- + gcmkONERROR(
- + gckHARDWARE_SetPowerManagementState(
- + Kernel->hardware,
- + Interface->u.SetPowerManagement.state));
- + break;
- +
- + case gcvHAL_QUERY_POWER_MANAGEMENT_STATE:
- + /* Chip is not idle. */
- + Interface->u.QueryPowerManagement.isIdle = gcvFALSE;
- +
- + /* Query the power management state. */
- + gcmkONERROR(gckHARDWARE_QueryPowerManagementState(
- + Kernel->hardware,
- + &Interface->u.QueryPowerManagement.state));
- +
- + /* Query the idle state. */
- + gcmkONERROR(
- + gckHARDWARE_QueryIdle(Kernel->hardware,
- + &Interface->u.QueryPowerManagement.isIdle));
- + break;
- +
- + case gcvHAL_READ_REGISTER:
- +#if gcdREGISTER_ACCESS_FROM_USER
- + {
- + gceCHIPPOWERSTATE power;
- +
- + gckOS_AcquireMutex(Kernel->os, Kernel->hardware->powerMutex, gcvINFINITE);
- + gcmkONERROR(gckHARDWARE_QueryPowerManagementState(Kernel->hardware,
- + &power));
- + if (power == gcvPOWER_ON)
- + {
- + /* Read a register. */
- + gcmkONERROR(gckOS_ReadRegisterEx(
- + Kernel->os,
- + Kernel->core,
- + Interface->u.ReadRegisterData.address,
- + &Interface->u.ReadRegisterData.data));
- + }
- + else
- + {
- + /* Chip is in power-state. */
- + Interface->u.ReadRegisterData.data = 0;
- + status = gcvSTATUS_CHIP_NOT_READY;
- + }
- + gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->hardware->powerMutex));
- + }
- +#else
- + /* No access from user land to read registers. */
- + Interface->u.ReadRegisterData.data = 0;
- + status = gcvSTATUS_NOT_SUPPORTED;
- +#endif
- + break;
- +
- + case gcvHAL_WRITE_REGISTER:
- +#if gcdREGISTER_ACCESS_FROM_USER
- + {
- + gceCHIPPOWERSTATE power;
- +
- + gckOS_AcquireMutex(Kernel->os, Kernel->hardware->powerMutex, gcvINFINITE);
- + gcmkONERROR(gckHARDWARE_QueryPowerManagementState(Kernel->hardware,
- + &power));
- + if (power == gcvPOWER_ON)
- + {
- + /* Write a register. */
- + gcmkONERROR(
- + gckOS_WriteRegisterEx(Kernel->os,
- + Kernel->core,
- + Interface->u.WriteRegisterData.address,
- + Interface->u.WriteRegisterData.data));
- + }
- + else
- + {
- + /* Chip is in power-state. */
- + Interface->u.WriteRegisterData.data = 0;
- + status = gcvSTATUS_CHIP_NOT_READY;
- + }
- + gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->hardware->powerMutex));
- + }
- +#else
- + /* No access from user land to write registers. */
- + status = gcvSTATUS_NOT_SUPPORTED;
- +#endif
- + break;
- +
- + case gcvHAL_READ_ALL_PROFILE_REGISTERS:
- +#if VIVANTE_PROFILER && VIVANTE_PROFILER_CONTEXT
- + /* Read profile data according to the context. */
- + gcmkONERROR(
- + gckHARDWARE_QueryContextProfile(
- + Kernel->hardware,
- + Kernel->profileCleanRegister,
- + gcmNAME_TO_PTR(Interface->u.RegisterProfileData.context),
- + &Interface->u.RegisterProfileData.counters));
- +#elif VIVANTE_PROFILER
- + /* Read all 3D profile registers. */
- + gcmkONERROR(
- + gckHARDWARE_QueryProfileRegisters(
- + Kernel->hardware,
- + Kernel->profileCleanRegister,
- + &Interface->u.RegisterProfileData.counters));
- +#else
- + status = gcvSTATUS_OK;
- +#endif
- + break;
- +
- + case gcvHAL_PROFILE_REGISTERS_2D:
- +#if VIVANTE_PROFILER
- + /* Read all 2D profile registers. */
- + gcmkONERROR(
- + gckHARDWARE_ProfileEngine2D(
- + Kernel->hardware,
- + gcmUINT64_TO_PTR(Interface->u.RegisterProfileData2D.hwProfile2D)));
- +#else
- + status = gcvSTATUS_OK;
- +#endif
- + break;
- +
- + case gcvHAL_GET_PROFILE_SETTING:
- +#if VIVANTE_PROFILER
- + /* Get profile setting */
- + Interface->u.GetProfileSetting.enable = Kernel->profileEnable;
- +#endif
- +
- + status = gcvSTATUS_OK;
- + break;
- + case gcvHAL_SET_PROFILE_SETTING:
- +#if VIVANTE_PROFILER
- + /* Set profile setting */
- + if(Kernel->hardware->gpuProfiler)
- + Kernel->profileEnable = Interface->u.SetProfileSetting.enable;
- + else
- + {
- + status = gcvSTATUS_NOT_SUPPORTED;
- + break;
- + }
- +#endif
- +
- + status = gcvSTATUS_OK;
- + break;
- +
- +#if VIVANTE_PROFILER_PERDRAW
- + case gcvHAL_READ_PROFILER_REGISTER_SETTING:
- + #if VIVANTE_PROFILER
- + Kernel->profileCleanRegister = Interface->u.SetProfilerRegisterClear.bclear;
- + #endif
- + status = gcvSTATUS_OK;
- + break;
- +#endif
- +
- + case gcvHAL_QUERY_KERNEL_SETTINGS:
- + /* Get kernel settings. */
- + gcmkONERROR(
- + gckKERNEL_QuerySettings(Kernel,
- + &Interface->u.QueryKernelSettings.settings));
- + break;
- +
- + case gcvHAL_RESET:
- + /* Reset the hardware. */
- + gckKERNEL_Recovery(Kernel);
- + break;
- +
- + case gcvHAL_DEBUG:
- + /* Set debug level and zones. */
- + if (Interface->u.Debug.set)
- + {
- + gckOS_SetDebugLevel(Interface->u.Debug.level);
- + gckOS_SetDebugZones(Interface->u.Debug.zones,
- + Interface->u.Debug.enable);
- + }
- +
- + if (Interface->u.Debug.message[0] != '\0')
- + {
- + /* Print a message to the debugger. */
- + if (Interface->u.Debug.type == gcvMESSAGE_TEXT)
- + {
- + gckOS_CopyPrint(Interface->u.Debug.message);
- + }
- + else
- + {
- + gckOS_DumpBuffer(Kernel->os,
- + Interface->u.Debug.message,
- + Interface->u.Debug.messageSize,
- + gceDUMP_BUFFER_FROM_USER,
- + gcvTRUE);
- + }
- + }
- + status = gcvSTATUS_OK;
- + break;
- +
- + case gcvHAL_DUMP_GPU_STATE:
- + /* Dump GPU state */
- + {
- + gceCHIPPOWERSTATE power;
- + gcmkONERROR(gckHARDWARE_QueryPowerManagementState(Kernel->hardware,
- + &power));
- + if (power == gcvPOWER_ON)
- + {
- + Interface->u.ReadRegisterData.data = 1;
- + gcmkVERIFY_OK(
- + gckHARDWARE_DumpGPUState(Kernel->hardware));
- +#if gcdVIRTUAL_COMMAND_BUFFER
- + gcmkVERIFY_OK(
- + gckCOMMAND_DumpExecutingBuffer(Kernel->command));
- +#endif
- + }
- + else
- + {
- + Interface->u.ReadRegisterData.data = 0;
- + status = gcvSTATUS_CHIP_NOT_READY;
- + }
- + }
- + break;
- +
- + case gcvHAL_DUMP_EVENT:
- + /* Dump GPU event */
- + gcmkVERIFY_OK(gckEVENT_Dump(Kernel->eventObj));
- +
- + /* Dump Process DB. */
- + gcmkVERIFY_OK(gckKERNEL_DumpProcessDB(Kernel));
- + break;
- +
- + case gcvHAL_CACHE:
- + node = gcmUINT64_TO_PTR(Interface->u.Cache.node);
- + if (node == gcvNULL)
- + {
- + /* FIXME Surface wrap some memory which is not allocated by us,
- + ** So we don't have physical address to handle outer cache, ignore it*/
- + status = gcvSTATUS_OK;
- + break;
- + }
- + else if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
- + {
- + /* Video memory has no physical handles. */
- + physical = gcvNULL;
- + }
- + else
- + {
- + /* Grab physical handle. */
- + physical = node->Virtual.physical;
- + }
- +
- + logical = gcmUINT64_TO_PTR(Interface->u.Cache.logical);
- + bytes = (gctSIZE_T) Interface->u.Cache.bytes;
- + switch(Interface->u.Cache.operation)
- + {
- + case gcvCACHE_FLUSH:
- + /* Clean and invalidate the cache. */
- + status = gckOS_CacheFlush(Kernel->os,
- + processID,
- + physical,
- + paddr,
- + logical,
- + bytes);
- + break;
- + case gcvCACHE_CLEAN:
- + /* Clean the cache. */
- + status = gckOS_CacheClean(Kernel->os,
- + processID,
- + physical,
- + paddr,
- + logical,
- + bytes);
- + break;
- + case gcvCACHE_INVALIDATE:
- + /* Invalidate the cache. */
- + status = gckOS_CacheInvalidate(Kernel->os,
- + processID,
- + physical,
- + paddr,
- + logical,
- + bytes);
- + break;
- +
- + case gcvCACHE_MEMORY_BARRIER:
- + status = gckOS_MemoryBarrier(Kernel->os,
- + logical);
- + break;
- + default:
- + status = gcvSTATUS_INVALID_ARGUMENT;
- + break;
- + }
- + break;
- +
- + case gcvHAL_TIMESTAMP:
- + /* Check for invalid timer. */
- + if ((Interface->u.TimeStamp.timer >= gcmCOUNTOF(Kernel->timers))
- + || (Interface->u.TimeStamp.request != 2))
- + {
- + Interface->u.TimeStamp.timeDelta = 0;
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + /* Return timer results and reset timer. */
- + {
- + gcsTIMER_PTR timer = &(Kernel->timers[Interface->u.TimeStamp.timer]);
- + gctUINT64 timeDelta = 0;
- +
- + if (timer->stopTime < timer->startTime )
- + {
- + Interface->u.TimeStamp.timeDelta = 0;
- + gcmkONERROR(gcvSTATUS_TIMER_OVERFLOW);
- + }
- +
- + timeDelta = timer->stopTime - timer->startTime;
- +
- + /* Check truncation overflow. */
- + Interface->u.TimeStamp.timeDelta = (gctINT32) timeDelta;
- + /*bit0~bit30 is available*/
- + if (timeDelta>>31)
- + {
- + Interface->u.TimeStamp.timeDelta = 0;
- + gcmkONERROR(gcvSTATUS_TIMER_OVERFLOW);
- + }
- +
- + status = gcvSTATUS_OK;
- + }
- + break;
- +
- + case gcvHAL_DATABASE:
- + /* Query video memory. */
- + gcmkONERROR(
- + gckKERNEL_QueryProcessDB(Kernel,
- + Interface->u.Database.processID,
- + !Interface->u.Database.validProcessID,
- + gcvDB_VIDEO_MEMORY,
- + &Interface->u.Database.vidMem));
- +
- + /* Query non-paged memory. */
- + gcmkONERROR(
- + gckKERNEL_QueryProcessDB(Kernel,
- + Interface->u.Database.processID,
- + !Interface->u.Database.validProcessID,
- + gcvDB_NON_PAGED,
- + &Interface->u.Database.nonPaged));
- +
- + /* Query contiguous memory. */
- + gcmkONERROR(
- + gckKERNEL_QueryProcessDB(Kernel,
- + Interface->u.Database.processID,
- + !Interface->u.Database.validProcessID,
- + gcvDB_CONTIGUOUS,
- + &Interface->u.Database.contiguous));
- +
- + /* Query GPU idle time. */
- + gcmkONERROR(
- + gckKERNEL_QueryProcessDB(Kernel,
- + Interface->u.Database.processID,
- + !Interface->u.Database.validProcessID,
- + gcvDB_IDLE,
- + &Interface->u.Database.gpuIdle));
- + break;
- +
- + case gcvHAL_VIDMEM_DATABASE:
- + /* Query reserved video memory. */
- + gcmkONERROR(
- + gckKERNEL_QueryProcessDB(Kernel,
- + Interface->u.VidMemDatabase.processID,
- + !Interface->u.VidMemDatabase.validProcessID,
- + gcvDB_VIDEO_MEMORY_RESERVED,
- + &Interface->u.VidMemDatabase.vidMemResv));
- +
- + /* Query contiguous video memory. */
- + gcmkONERROR(
- + gckKERNEL_QueryProcessDB(Kernel,
- + Interface->u.VidMemDatabase.processID,
- + !Interface->u.VidMemDatabase.validProcessID,
- + gcvDB_VIDEO_MEMORY_CONTIGUOUS,
- + &Interface->u.VidMemDatabase.vidMemCont));
- +
- + /* Query virtual video memory. */
- + gcmkONERROR(
- + gckKERNEL_QueryProcessDB(Kernel,
- + Interface->u.VidMemDatabase.processID,
- + !Interface->u.VidMemDatabase.validProcessID,
- + gcvDB_VIDEO_MEMORY_VIRTUAL,
- + &Interface->u.VidMemDatabase.vidMemVirt));
- +
- + break;
- +
- + case gcvHAL_VERSION:
- + Interface->u.Version.major = gcvVERSION_MAJOR;
- + Interface->u.Version.minor = gcvVERSION_MINOR;
- + Interface->u.Version.patch = gcvVERSION_PATCH;
- + Interface->u.Version.build = gcvVERSION_BUILD;
- +#if gcmIS_DEBUG(gcdDEBUG_TRACE)
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
- + "KERNEL version %d.%d.%d build %u %s %s",
- + gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH,
- + gcvVERSION_BUILD, gcvVERSION_DATE, gcvVERSION_TIME);
- +#endif
- + break;
- +
- + case gcvHAL_CHIP_INFO:
- + /* Only if not support multi-core */
- + Interface->u.ChipInfo.count = 1;
- + Interface->u.ChipInfo.types[0] = Kernel->hardware->type;
- + break;
- +
- + case gcvHAL_ATTACH:
- + /* Attach user process. */
- + gcmkONERROR(
- + gckCOMMAND_Attach(Kernel->command,
- + &context,
- + &bytes,
- + processID));
- +
- + Interface->u.Attach.stateCount = bytes;
- + Interface->u.Attach.context = gcmPTR_TO_NAME(context);
- +
- + gcmkVERIFY_OK(
- + gckKERNEL_AddProcessDB(Kernel,
- + processID, gcvDB_CONTEXT,
- + gcmINT2PTR(Interface->u.Attach.context),
- + gcvNULL,
- + 0));
- + break;
- +
- + case gcvHAL_DETACH:
- + /* Detach user process. */
- + gcmkONERROR(
- + gckCOMMAND_Detach(Kernel->command,
- + gcmNAME_TO_PTR(Interface->u.Detach.context)));
- +
- + gcmkVERIFY_OK(
- + gckKERNEL_RemoveProcessDB(Kernel,
- + processID, gcvDB_CONTEXT,
- + gcmINT2PTR(Interface->u.Detach.context)));
- +
- + gcmRELEASE_NAME(Interface->u.Detach.context);
- + break;
- +
- + case gcvHAL_COMPOSE:
- + Interface->u.Compose.physical = gcmPTR_TO_UINT64(gcmNAME_TO_PTR(Interface->u.Compose.physical));
- + /* Start composition. */
- + gcmkONERROR(
- + gckEVENT_Compose(Kernel->eventObj,
- + &Interface->u.Compose));
- + break;
- +
- + case gcvHAL_SET_TIMEOUT:
- + /* set timeOut value from user */
- + gckKERNEL_SetTimeOut(Kernel, Interface->u.SetTimeOut.timeOut);
- + break;
- +
- +#if gcdFRAME_DB
- + case gcvHAL_GET_FRAME_INFO:
- + gcmkONERROR(gckHARDWARE_GetFrameInfo(
- + Kernel->hardware,
- + gcmUINT64_TO_PTR(Interface->u.GetFrameInfo.frameInfo)));
- + break;
- +#endif
- +
- + case gcvHAL_GET_SHARED_INFO:
- + if (Interface->u.GetSharedInfo.data == gcvNULL)
- + {
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- + else
- + {
- + gctUINT32 pid = Interface->u.GetSharedInfo.pid;
- + gctUINT32 dataId = Interface->u.GetSharedInfo.dataId;
- + gctSIZE_T bytes = Interface->u.GetSharedInfo.bytes;
- + gctPOINTER data = Interface->u.GetSharedInfo.data;
- + gcsDATABASE_RECORD record;
- +
- + /* Find record. */
- + gcmkONERROR(
- + gckKERNEL_FindProcessDB(Kernel,
- + pid,
- + 0,
- + gcvDB_SHARED_INFO,
- + gcmINT2PTR(dataId),
- + &record));
- +
- + /* Check memory size. */
- + if (bytes < record.bytes)
- + {
- + /* Insufficient memory to hold shared data. */
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + /* Copy to user. */
- + status = gckOS_CopyToUserData(Kernel->os,
- + record.physical,
- + data,
- + record.bytes);
- +
- + /*
- + * Remove from process db.
- + * Every time when shared info is taken, the record is erased in
- + * kernel side.
- + */
- + gcmkVERIFY_OK(
- + gckKERNEL_RemoveProcessDB(Kernel,
- + pid,
- + gcvDB_SHARED_INFO,
- + gcmINT2PTR(dataId)));
- + /* Free existed data. */
- + gcmkVERIFY_OK(
- + gckOS_FreeMemory(Kernel->os, record.physical));
- + }
- + break;
- +
- + case gcvHAL_SET_SHARED_INFO:
- + {
- + gctUINT32 dataId = Interface->u.SetSharedInfo.dataId;
- + gctPOINTER data = Interface->u.SetSharedInfo.data;
- + gctUINT32 bytes = Interface->u.SetSharedInfo.bytes;
- + gctPOINTER memory = gcvNULL;
- + gcsDATABASE_RECORD record;
- +
- + if (gcmIS_SUCCESS(gckKERNEL_FindProcessDB(Kernel,
- + processID,
- + 0,
- + gcvDB_SHARED_INFO,
- + gcmINT2PTR(dataId),
- + &record)))
- + {
- + /* Find a record with the same id. */
- + if (bytes != record.bytes)
- + {
- + /* Remove from process db. */
- + gcmkVERIFY_OK(
- + gckKERNEL_RemoveProcessDB(Kernel,
- + processID,
- + gcvDB_SHARED_INFO,
- + gcmINT2PTR(dataId)));
- +
- + /* Free existed data. */
- + gcmkVERIFY_OK(
- + gckOS_FreeMemory(Kernel->os, record.physical));
- + }
- + else
- + {
- + /* Re-use allocated memory. */
- + memory = record.physical;
- + }
- + }
- +
- + if ((data == gcvNULL) || (bytes == 0))
- + {
- + /* Nothing to record. */
- + break;
- + }
- +
- + if (bytes > 1024)
- + {
- + /* Limite data size. */
- + gcmkONERROR(gcvSTATUS_TOO_COMPLEX);
- + }
- +
- + if (memory == gcvNULL)
- + {
- + /* Allocate memory for holding shared data. */
- + gcmkONERROR(
- + gckOS_AllocateMemory(Kernel->os, bytes, &memory));
- +
- + /* Add to process db. */
- + status = gckKERNEL_AddProcessDB(Kernel,
- + processID,
- + gcvDB_SHARED_INFO,
- + gcmINT2PTR(dataId),
- + memory,
- + bytes);
- +
- + if (gcmIS_ERROR(status))
- + {
- + /* Failed to add process db. Free allocated memory. */
- + gcmkVERIFY_OK(gckOS_FreeMemory(Kernel->os, memory));
- + break;
- + }
- + }
- +
- + /* Copy shared data to kernel memory. */
- + gcmkONERROR(
- + gckOS_CopyFromUserData(Kernel->os,
- + memory,
- + data,
- + bytes));
- + }
- + break;
- +
- + case gcvHAL_SET_FSCALE_VALUE:
- +#if gcdENABLE_FSCALE_VAL_ADJUST
- + status = gckHARDWARE_SetFscaleValue(Kernel->hardware,
- + Interface->u.SetFscaleValue.value);
- +#else
- + status = gcvSTATUS_NOT_SUPPORTED;
- +#endif
- + break;
- + case gcvHAL_GET_FSCALE_VALUE:
- +#if gcdENABLE_FSCALE_VAL_ADJUST
- + status = gckHARDWARE_GetFscaleValue(Kernel->hardware,
- + &Interface->u.GetFscaleValue.value,
- + &Interface->u.GetFscaleValue.minValue,
- + &Interface->u.GetFscaleValue.maxValue);
- +#else
- + status = gcvSTATUS_NOT_SUPPORTED;
- +#endif
- + break;
- +
- + case gcvHAL_QUERY_RESET_TIME_STAMP:
- +#if gcdENABLE_RECOVERY
- + Interface->u.QueryResetTimeStamp.timeStamp = Kernel->resetTimeStamp;
- +#else
- + Interface->u.QueryResetTimeStamp.timeStamp = 0;
- +#endif
- + break;
- +
- +#if gcdANDROID_NATIVE_FENCE_SYNC
- + case gcvHAL_SYNC_POINT:
- + {
- + gctSYNC_POINT syncPoint;
- +
- + switch (Interface->u.SyncPoint.command)
- + {
- + case gcvSYNC_POINT_CREATE:
- + gcmkONERROR(gckOS_CreateSyncPoint(Kernel->os, &syncPoint));
- +
- + Interface->u.SyncPoint.syncPoint = gcmPTR_TO_UINT64(syncPoint);
- +
- + gcmkVERIFY_OK(
- + gckKERNEL_AddProcessDB(Kernel,
- + processID, gcvDB_SYNC_POINT,
- + syncPoint,
- + gcvNULL,
- + 0));
- + break;
- +
- + case gcvSYNC_POINT_DESTROY:
- + syncPoint = gcmUINT64_TO_PTR(Interface->u.SyncPoint.syncPoint);
- +
- + gcmkONERROR(gckOS_DestroySyncPoint(Kernel->os, syncPoint));
- +
- + gcmkVERIFY_OK(
- + gckKERNEL_RemoveProcessDB(Kernel,
- + processID, gcvDB_SYNC_POINT,
- + syncPoint));
- + break;
- +
- + default:
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + break;
- + }
- + }
- + break;
- +
- + case gcvHAL_CREATE_NATIVE_FENCE:
- + {
- + gctINT fenceFD;
- + gctSYNC_POINT syncPoint =
- + gcmUINT64_TO_PTR(Interface->u.CreateNativeFence.syncPoint);
- +
- + gcmkONERROR(
- + gckOS_CreateNativeFence(Kernel->os,
- + Kernel->timeline,
- + syncPoint,
- + &fenceFD));
- +
- + Interface->u.CreateNativeFence.fenceFD = fenceFD;
- + }
- + break;
- +#endif
- +
- + default:
- + /* Invalid command. */
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- +OnError:
- + /* Save status. */
- + Interface->status = status;
- +
- + if (gcmIS_ERROR(status))
- + {
- + if (locked)
- + {
- + /* Roll back the lock. */
- + gcmkVERIFY_OK(
- + gckVIDMEM_Unlock(Kernel,
- + gcmUINT64_TO_PTR(Interface->u.LockVideoMemory.node),
- + gcvSURF_TYPE_UNKNOWN,
- + &asynchronous));
- +
- + if (gcvTRUE == asynchronous)
- + {
- + /* Bottom Half */
- + gcmkVERIFY_OK(
- + gckVIDMEM_Unlock(Kernel,
- + gcmUINT64_TO_PTR(Interface->u.LockVideoMemory.node),
- + gcvSURF_TYPE_UNKNOWN,
- + gcvNULL));
- + }
- + }
- + }
- +
- +#if QNX_SINGLE_THREADED_DEBUGGING
- + gckOS_ReleaseMutex(Kernel->os, Kernel->debugMutex);
- +#endif
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +** gckKERNEL_AttachProcess
- +**
- +** Attach or detach a process.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gctBOOL Attach
- +** gcvTRUE if a new process gets attached or gcFALSE when a process
- +** gets detatched.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckKERNEL_AttachProcess(
- + IN gckKERNEL Kernel,
- + IN gctBOOL Attach
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 processID;
- +
- + gcmkHEADER_ARG("Kernel=0x%x Attach=%d", Kernel, Attach);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- +
- + /* Get current process ID. */
- + gcmkONERROR(gckOS_GetProcessID(&processID));
- +
- + gcmkONERROR(gckKERNEL_AttachProcessEx(Kernel, Attach, processID));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +** gckKERNEL_AttachProcessEx
- +**
- +** Attach or detach a process with the given PID. Can be paired with gckKERNEL_AttachProcess
- +** provided the programmer is aware of the consequences.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gctBOOL Attach
- +** gcvTRUE if a new process gets attached or gcFALSE when a process
- +** gets detatched.
- +**
- +** gctUINT32 PID
- +** PID of the process to attach or detach.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckKERNEL_AttachProcessEx(
- + IN gckKERNEL Kernel,
- + IN gctBOOL Attach,
- + IN gctUINT32 PID
- + )
- +{
- + gceSTATUS status;
- + gctINT32 old;
- +
- + gcmkHEADER_ARG("Kernel=0x%x Attach=%d PID=%d", Kernel, Attach, PID);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- +
- + if (Attach)
- + {
- + /* Increment the number of clients attached. */
- + gcmkONERROR(
- + gckOS_AtomIncrement(Kernel->os, Kernel->atomClients, &old));
- +
- + if (old == 0)
- + {
- +#if gcdENABLE_VG
- + if (Kernel->vg == gcvNULL)
- +#endif
- + {
- + gcmkONERROR(gckOS_Broadcast(Kernel->os,
- + Kernel->hardware,
- + gcvBROADCAST_FIRST_PROCESS));
- + }
- + }
- +
- + if (Kernel->dbCreated)
- + {
- + /* Create the process database. */
- + gcmkONERROR(gckKERNEL_CreateProcessDB(Kernel, PID));
- + }
- + }
- + else
- + {
- + if (Kernel->dbCreated)
- + {
- + /* Clean up the process database. */
- + gcmkONERROR(gckKERNEL_DestroyProcessDB(Kernel, PID));
- +
- + /* Save the last know process ID. */
- + Kernel->db->lastProcessID = PID;
- + }
- +
- +#if gcdENABLE_VG
- + if (Kernel->vg == gcvNULL)
- +#endif
- + {
- + status = gckEVENT_Submit(Kernel->eventObj, gcvTRUE, gcvFALSE);
- +
- + if (status == gcvSTATUS_INTERRUPTED && Kernel->eventObj->submitTimer)
- + {
- + gcmkONERROR(gckOS_StartTimer(Kernel->os,
- + Kernel->eventObj->submitTimer,
- + 1));
- + }
- + else
- + {
- + gcmkONERROR(status);
- + }
- + }
- +
- + /* Decrement the number of clients attached. */
- + gcmkONERROR(
- + gckOS_AtomDecrement(Kernel->os, Kernel->atomClients, &old));
- +
- + if (old == 1)
- + {
- +#if gcdENABLE_VG
- + if (Kernel->vg == gcvNULL)
- +#endif
- + {
- + /* Last client detached, switch to SUSPEND power state. */
- + gcmkONERROR(gckOS_Broadcast(Kernel->os,
- + Kernel->hardware,
- + gcvBROADCAST_LAST_PROCESS));
- + }
- +
- + /* Flush the debug cache. */
- + gcmkDEBUGFLUSH(~0U);
- + }
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +#if gcdSECURE_USER
- +gceSTATUS
- +gckKERNEL_MapLogicalToPhysical(
- + IN gckKERNEL Kernel,
- + IN gcskSECURE_CACHE_PTR Cache,
- + IN OUT gctPOINTER * Data
- + )
- +{
- + gceSTATUS status;
- + static gctBOOL baseAddressValid = gcvFALSE;
- + static gctUINT32 baseAddress;
- + gctBOOL needBase;
- + gcskLOGICAL_CACHE_PTR slot;
- +
- + gcmkHEADER_ARG("Kernel=0x%x Cache=0x%x *Data=0x%x",
- + Kernel, Cache, gcmOPT_POINTER(Data));
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- +
- + if (!baseAddressValid)
- + {
- + /* Get base address. */
- + gcmkONERROR(gckHARDWARE_GetBaseAddress(Kernel->hardware, &baseAddress));
- +
- + baseAddressValid = gcvTRUE;
- + }
- +
- + /* Does this state load need a base address? */
- + gcmkONERROR(gckHARDWARE_NeedBaseAddress(Kernel->hardware,
- + ((gctUINT32_PTR) Data)[-1],
- + &needBase));
- +
- +#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LRU
- + {
- + gcskLOGICAL_CACHE_PTR next;
- + gctINT i;
- +
- + /* Walk all used cache slots. */
- + for (i = 1, slot = Cache->cache[0].next, next = gcvNULL;
- + (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
- + ++i, slot = slot->next
- + )
- + {
- + if (slot->logical == *Data)
- + {
- + /* Bail out. */
- + next = slot;
- + break;
- + }
- + }
- +
- + /* See if we had a miss. */
- + if (next == gcvNULL)
- + {
- + /* Use the tail of the cache. */
- + slot = Cache->cache[0].prev;
- +
- + /* Initialize the cache line. */
- + slot->logical = *Data;
- +
- + /* Map the logical address to a DMA address. */
- + gcmkONERROR(
- + gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
- + }
- +
- + /* Move slot to head of list. */
- + if (slot != Cache->cache[0].next)
- + {
- + /* Unlink. */
- + slot->prev->next = slot->next;
- + slot->next->prev = slot->prev;
- +
- + /* Move to head of chain. */
- + slot->prev = &Cache->cache[0];
- + slot->next = Cache->cache[0].next;
- + slot->prev->next = slot;
- + slot->next->prev = slot;
- + }
- + }
- +#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
- + {
- + gctINT i;
- + gcskLOGICAL_CACHE_PTR next = gcvNULL;
- + gcskLOGICAL_CACHE_PTR oldestSlot = gcvNULL;
- + slot = gcvNULL;
- +
- + if (Cache->cacheIndex != gcvNULL)
- + {
- + /* Walk the cache forwards. */
- + for (i = 1, slot = Cache->cacheIndex;
- + (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
- + ++i, slot = slot->next)
- + {
- + if (slot->logical == *Data)
- + {
- + /* Bail out. */
- + next = slot;
- + break;
- + }
- +
- + /* Determine age of this slot. */
- + if ((oldestSlot == gcvNULL)
- + || (oldestSlot->stamp > slot->stamp)
- + )
- + {
- + oldestSlot = slot;
- + }
- + }
- +
- + if (next == gcvNULL)
- + {
- + /* Walk the cache backwards. */
- + for (slot = Cache->cacheIndex->prev;
- + (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
- + ++i, slot = slot->prev)
- + {
- + if (slot->logical == *Data)
- + {
- + /* Bail out. */
- + next = slot;
- + break;
- + }
- +
- + /* Determine age of this slot. */
- + if ((oldestSlot == gcvNULL)
- + || (oldestSlot->stamp > slot->stamp)
- + )
- + {
- + oldestSlot = slot;
- + }
- + }
- + }
- + }
- +
- + /* See if we had a miss. */
- + if (next == gcvNULL)
- + {
- + if (Cache->cacheFree != 0)
- + {
- + slot = &Cache->cache[Cache->cacheFree];
- + gcmkASSERT(slot->logical == gcvNULL);
- +
- + ++ Cache->cacheFree;
- + if (Cache->cacheFree >= gcmCOUNTOF(Cache->cache))
- + {
- + Cache->cacheFree = 0;
- + }
- + }
- + else
- + {
- + /* Use the oldest cache slot. */
- + gcmkASSERT(oldestSlot != gcvNULL);
- + slot = oldestSlot;
- +
- + /* Unlink from the chain. */
- + slot->prev->next = slot->next;
- + slot->next->prev = slot->prev;
- +
- + /* Append to the end. */
- + slot->prev = Cache->cache[0].prev;
- + slot->next = &Cache->cache[0];
- + slot->prev->next = slot;
- + slot->next->prev = slot;
- + }
- +
- + /* Initialize the cache line. */
- + slot->logical = *Data;
- +
- + /* Map the logical address to a DMA address. */
- + gcmkONERROR(
- + gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
- + }
- +
- + /* Save time stamp. */
- + slot->stamp = ++ Cache->cacheStamp;
- +
- + /* Save current slot for next lookup. */
- + Cache->cacheIndex = slot;
- + }
- +#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
- + {
- + gctINT i;
- + gctUINT32 data = gcmPTR2INT(*Data);
- + gctUINT32 key, index;
- + gcskLOGICAL_CACHE_PTR hash;
- +
- + /* Generate a hash key. */
- + key = (data >> 24) + (data >> 16) + (data >> 8) + data;
- + index = key % gcmCOUNTOF(Cache->hash);
- +
- + /* Get the hash entry. */
- + hash = &Cache->hash[index];
- +
- + for (slot = hash->nextHash, i = 0;
- + (slot != gcvNULL) && (i < gcdSECURE_CACHE_SLOTS);
- + slot = slot->nextHash, ++i
- + )
- + {
- + if (slot->logical == (*Data))
- + {
- + break;
- + }
- + }
- +
- + if (slot == gcvNULL)
- + {
- + /* Grab from the tail of the cache. */
- + slot = Cache->cache[0].prev;
- +
- + /* Unlink slot from any hash table it is part of. */
- + if (slot->prevHash != gcvNULL)
- + {
- + slot->prevHash->nextHash = slot->nextHash;
- + }
- + if (slot->nextHash != gcvNULL)
- + {
- + slot->nextHash->prevHash = slot->prevHash;
- + }
- +
- + /* Initialize the cache line. */
- + slot->logical = *Data;
- +
- + /* Map the logical address to a DMA address. */
- + gcmkONERROR(
- + gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
- +
- + if (hash->nextHash != gcvNULL)
- + {
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
- + "Hash Collision: logical=0x%x key=0x%08x",
- + *Data, key);
- + }
- +
- + /* Insert the slot at the head of the hash list. */
- + slot->nextHash = hash->nextHash;
- + if (slot->nextHash != gcvNULL)
- + {
- + slot->nextHash->prevHash = slot;
- + }
- + slot->prevHash = hash;
- + hash->nextHash = slot;
- + }
- +
- + /* Move slot to head of list. */
- + if (slot != Cache->cache[0].next)
- + {
- + /* Unlink. */
- + slot->prev->next = slot->next;
- + slot->next->prev = slot->prev;
- +
- + /* Move to head of chain. */
- + slot->prev = &Cache->cache[0];
- + slot->next = Cache->cache[0].next;
- + slot->prev->next = slot;
- + slot->next->prev = slot;
- + }
- + }
- +#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_TABLE
- + {
- + gctUINT32 index = (gcmPTR2INT(*Data) % gcdSECURE_CACHE_SLOTS) + 1;
- +
- + /* Get cache slot. */
- + slot = &Cache->cache[index];
- +
- + /* Check for cache miss. */
- + if (slot->logical != *Data)
- + {
- + /* Initialize the cache line. */
- + slot->logical = *Data;
- +
- + /* Map the logical address to a DMA address. */
- + gcmkONERROR(
- + gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
- + }
- + }
- +#endif
- +
- + /* Return DMA address. */
- + *Data = gcmINT2PTR(slot->dma + (needBase ? baseAddress : 0));
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Data=0x%08x", *Data);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckKERNEL_FlushTranslationCache(
- + IN gckKERNEL Kernel,
- + IN gcskSECURE_CACHE_PTR Cache,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes
- + )
- +{
- + gctINT i;
- + gcskLOGICAL_CACHE_PTR slot;
- + gctUINT8_PTR ptr;
- +
- + gcmkHEADER_ARG("Kernel=0x%x Cache=0x%x Logical=0x%x Bytes=%lu",
- + Kernel, Cache, Logical, Bytes);
- +
- + /* Do we need to flush the entire cache? */
- + if (Logical == gcvNULL)
- + {
- + /* Clear all cache slots. */
- + for (i = 1; i <= gcdSECURE_CACHE_SLOTS; ++i)
- + {
- + Cache->cache[i].logical = gcvNULL;
- +
- +#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
- + Cache->cache[i].nextHash = gcvNULL;
- + Cache->cache[i].prevHash = gcvNULL;
- +#endif
- +}
- +
- +#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
- + /* Zero the hash table. */
- + for (i = 0; i < gcmCOUNTOF(Cache->hash); ++i)
- + {
- + Cache->hash[i].nextHash = gcvNULL;
- + }
- +#endif
- +
- + /* Reset the cache functionality. */
- + Cache->cacheIndex = gcvNULL;
- + Cache->cacheFree = 1;
- + Cache->cacheStamp = 0;
- + }
- +
- + else
- + {
- + gctUINT8_PTR low = (gctUINT8_PTR) Logical;
- + gctUINT8_PTR high = low + Bytes;
- +
- +#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LRU
- + gcskLOGICAL_CACHE_PTR next;
- +
- + /* Walk all used cache slots. */
- + for (i = 1, slot = Cache->cache[0].next;
- + (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
- + ++i, slot = next
- + )
- + {
- + /* Save pointer to next slot. */
- + next = slot->next;
- +
- + /* Test if this slot falls within the range to flush. */
- + ptr = (gctUINT8_PTR) slot->logical;
- + if ((ptr >= low) && (ptr < high))
- + {
- + /* Unlink slot. */
- + slot->prev->next = slot->next;
- + slot->next->prev = slot->prev;
- +
- + /* Append slot to tail of cache. */
- + slot->prev = Cache->cache[0].prev;
- + slot->next = &Cache->cache[0];
- + slot->prev->next = slot;
- + slot->next->prev = slot;
- +
- + /* Mark slot as empty. */
- + slot->logical = gcvNULL;
- + }
- + }
- +
- +#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
- + gcskLOGICAL_CACHE_PTR next;
- +
- + for (i = 1, slot = Cache->cache[0].next;
- + (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
- + ++i, slot = next)
- + {
- + /* Save pointer to next slot. */
- + next = slot->next;
- +
- + /* Test if this slot falls within the range to flush. */
- + ptr = (gctUINT8_PTR) slot->logical;
- + if ((ptr >= low) && (ptr < high))
- + {
- + /* Test if this slot is the current slot. */
- + if (slot == Cache->cacheIndex)
- + {
- + /* Move to next or previous slot. */
- + Cache->cacheIndex = (slot->next->logical != gcvNULL)
- + ? slot->next
- + : (slot->prev->logical != gcvNULL)
- + ? slot->prev
- + : gcvNULL;
- + }
- +
- + /* Unlink slot from cache. */
- + slot->prev->next = slot->next;
- + slot->next->prev = slot->prev;
- +
- + /* Insert slot to head of cache. */
- + slot->prev = &Cache->cache[0];
- + slot->next = Cache->cache[0].next;
- + slot->prev->next = slot;
- + slot->next->prev = slot;
- +
- + /* Mark slot as empty. */
- + slot->logical = gcvNULL;
- + slot->stamp = 0;
- + }
- + }
- +
- +#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
- + gctINT j;
- + gcskLOGICAL_CACHE_PTR hash, next;
- +
- + /* Walk all hash tables. */
- + for (i = 0, hash = Cache->hash;
- + i < gcmCOUNTOF(Cache->hash);
- + ++i, ++hash)
- + {
- + /* Walk all slots in the hash. */
- + for (j = 0, slot = hash->nextHash;
- + (j < gcdSECURE_CACHE_SLOTS) && (slot != gcvNULL);
- + ++j, slot = next)
- + {
- + /* Save pointer to next slot. */
- + next = slot->next;
- +
- + /* Test if this slot falls within the range to flush. */
- + ptr = (gctUINT8_PTR) slot->logical;
- + if ((ptr >= low) && (ptr < high))
- + {
- + /* Unlink slot from hash table. */
- + if (slot->prevHash == hash)
- + {
- + hash->nextHash = slot->nextHash;
- + }
- + else
- + {
- + slot->prevHash->nextHash = slot->nextHash;
- + }
- +
- + if (slot->nextHash != gcvNULL)
- + {
- + slot->nextHash->prevHash = slot->prevHash;
- + }
- +
- + /* Unlink slot from cache. */
- + slot->prev->next = slot->next;
- + slot->next->prev = slot->prev;
- +
- + /* Append slot to tail of cache. */
- + slot->prev = Cache->cache[0].prev;
- + slot->next = &Cache->cache[0];
- + slot->prev->next = slot;
- + slot->next->prev = slot;
- +
- + /* Mark slot as empty. */
- + slot->logical = gcvNULL;
- + slot->prevHash = gcvNULL;
- + slot->nextHash = gcvNULL;
- + }
- + }
- + }
- +
- +#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_TABLE
- + gctUINT32 index;
- +
- + /* Loop while inside the range. */
- + for (i = 1; (low < high) && (i <= gcdSECURE_CACHE_SLOTS); ++i)
- + {
- + /* Get index into cache for this range. */
- + index = (gcmPTR2INT(low) % gcdSECURE_CACHE_SLOTS) + 1;
- + slot = &Cache->cache[index];
- +
- + /* Test if this slot falls within the range to flush. */
- + ptr = (gctUINT8_PTR) slot->logical;
- + if ((ptr >= low) && (ptr < high))
- + {
- + /* Remove entry from cache. */
- + slot->logical = gcvNULL;
- + }
- +
- + /* Next block. */
- + low += gcdSECURE_CACHE_SLOTS;
- + }
- +#endif
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_Recovery
- +**
- +** Try to recover the GPU from a fatal error.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckKERNEL_Recovery(
- + IN gckKERNEL Kernel
- + )
- +{
- +#if gcdENABLE_RECOVERY
- +#define gcdEVENT_MASK 0x3FFFFFFF
- + gceSTATUS status;
- + gckEVENT eventObj;
- + gckHARDWARE hardware;
- +#if gcdSECURE_USER
- + gctUINT32 processID;
- + gcskSECURE_CACHE_PTR cache;
- +#endif
- + gctUINT32 oldValue;
- + gcmkHEADER_ARG("Kernel=0x%x", Kernel);
- +
- + /* Validate the arguemnts. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- +
- + /* Grab gckEVENT object. */
- + eventObj = Kernel->eventObj;
- + gcmkVERIFY_OBJECT(eventObj, gcvOBJ_EVENT);
- +
- + /* Grab gckHARDWARE object. */
- + hardware = Kernel->hardware;
- + gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
- +
- +#if gcdSECURE_USER
- + /* Flush the secure mapping cache. */
- + gcmkONERROR(gckOS_GetProcessID(&processID));
- + gcmkONERROR(gckKERNEL_GetProcessDBCache(Kernel, processID, &cache));
- + gcmkONERROR(gckKERNEL_FlushTranslationCache(Kernel, cache, gcvNULL, 0));
- +#endif
- +
- + gcmkONERROR(
- + gckOS_AtomicExchange(Kernel->os, Kernel->resetAtom, 1, &oldValue));
- +
- + if (oldValue)
- + {
- + /* Some one else will recovery GPU. */
- + return gcvSTATUS_OK;
- + }
- +
- + gcmkPRINT("[galcore]: GPU[%d] hang, automatic recovery.", Kernel->core);
- +
- + /* Start a timer to clear reset flag, before timer is expired,
- + ** other recovery request is ignored. */
- + gcmkVERIFY_OK(
- + gckOS_StartTimer(Kernel->os,
- + Kernel->resetFlagClearTimer,
- + gcdGPU_TIMEOUT - 500));
- +
- +
- + /* Try issuing a soft reset for the GPU. */
- + status = gckHARDWARE_Reset(hardware);
- + if (status == gcvSTATUS_NOT_SUPPORTED)
- + {
- + /* Switch to OFF power. The next submit should return the GPU to ON
- + ** state. */
- + gcmkONERROR(
- + gckHARDWARE_SetPowerManagementState(hardware,
- + gcvPOWER_OFF_RECOVERY));
- + }
- + else
- + {
- + /* Bail out on reset error. */
- + gcmkONERROR(status);
- + }
- +
- + /* Handle all outstanding events now. */
- +#if gcdSMP
- + gcmkONERROR(gckOS_AtomSet(Kernel->os, eventObj->pending, gcdEVENT_MASK));
- +#else
- + eventObj->pending = gcdEVENT_MASK;
- +#endif
- + gcmkONERROR(gckEVENT_Notify(eventObj, 1));
- +
- + /* Again in case more events got submitted. */
- +#if gcdSMP
- + gcmkONERROR(gckOS_AtomSet(Kernel->os, eventObj->pending, gcdEVENT_MASK));
- +#else
- + eventObj->pending = gcdEVENT_MASK;
- +#endif
- + gcmkONERROR(gckEVENT_Notify(eventObj, 2));
- +
- + Kernel->resetTimeStamp++;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +#else
- + return gcvSTATUS_OK;
- +#endif
- +}
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_OpenUserData
- +**
- +** Get access to the user data.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gctBOOL NeedCopy
- +** The flag indicating whether or not the data should be copied.
- +**
- +** gctPOINTER StaticStorage
- +** Pointer to the kernel storage where the data is to be copied if
- +** NeedCopy is gcvTRUE.
- +**
- +** gctPOINTER UserPointer
- +** User pointer to the data.
- +**
- +** gctSIZE_T Size
- +** Size of the data.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * KernelPointer
- +** Pointer to the kernel pointer that will be pointing to the data.
- +*/
- +gceSTATUS
- +gckKERNEL_OpenUserData(
- + IN gckKERNEL Kernel,
- + IN gctBOOL NeedCopy,
- + IN gctPOINTER StaticStorage,
- + IN gctPOINTER UserPointer,
- + IN gctSIZE_T Size,
- + OUT gctPOINTER * KernelPointer
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG(
- + "Kernel=0x%08X NeedCopy=%d StaticStorage=0x%08X "
- + "UserPointer=0x%08X Size=%lu KernelPointer=0x%08X",
- + Kernel, NeedCopy, StaticStorage, UserPointer, Size, KernelPointer
- + );
- +
- + /* Validate the arguemnts. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(!NeedCopy || (StaticStorage != gcvNULL));
- + gcmkVERIFY_ARGUMENT(UserPointer != gcvNULL);
- + gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Size > 0);
- +
- + if (NeedCopy)
- + {
- + /* Copy the user data to the static storage. */
- + gcmkONERROR(gckOS_CopyFromUserData(
- + Kernel->os, StaticStorage, UserPointer, Size
- + ));
- +
- + /* Set the kernel pointer. */
- + * KernelPointer = StaticStorage;
- + }
- + else
- + {
- + gctPOINTER pointer = gcvNULL;
- +
- + /* Map the user pointer. */
- + gcmkONERROR(gckOS_MapUserPointer(
- + Kernel->os, UserPointer, Size, &pointer
- + ));
- +
- + /* Set the kernel pointer. */
- + * KernelPointer = pointer;
- + }
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_CloseUserData
- +**
- +** Release resources associated with the user data connection opened by
- +** gckKERNEL_OpenUserData.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gctBOOL NeedCopy
- +** The flag indicating whether or not the data should be copied.
- +**
- +** gctBOOL FlushData
- +** If gcvTRUE, the data is written back to the user.
- +**
- +** gctPOINTER UserPointer
- +** User pointer to the data.
- +**
- +** gctSIZE_T Size
- +** Size of the data.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * KernelPointer
- +** Kernel pointer to the data.
- +*/
- +gceSTATUS
- +gckKERNEL_CloseUserData(
- + IN gckKERNEL Kernel,
- + IN gctBOOL NeedCopy,
- + IN gctBOOL FlushData,
- + IN gctPOINTER UserPointer,
- + IN gctSIZE_T Size,
- + OUT gctPOINTER * KernelPointer
- + )
- +{
- + gceSTATUS status = gcvSTATUS_OK;
- + gctPOINTER pointer;
- +
- + gcmkHEADER_ARG(
- + "Kernel=0x%08X NeedCopy=%d FlushData=%d "
- + "UserPointer=0x%08X Size=%lu KernelPointer=0x%08X",
- + Kernel, NeedCopy, FlushData, UserPointer, Size, KernelPointer
- + );
- +
- + /* Validate the arguemnts. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(UserPointer != gcvNULL);
- + gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Size > 0);
- +
- + /* Get a shortcut to the kernel pointer. */
- + pointer = * KernelPointer;
- +
- + if (pointer != gcvNULL)
- + {
- + if (NeedCopy)
- + {
- + if (FlushData)
- + {
- + gcmkONERROR(gckOS_CopyToUserData(
- + Kernel->os, * KernelPointer, UserPointer, Size
- + ));
- + }
- + }
- + else
- + {
- + /* Unmap record from kernel memory. */
- + gcmkONERROR(gckOS_UnmapUserPointer(
- + Kernel->os,
- + UserPointer,
- + Size,
- + * KernelPointer
- + ));
- + }
- +
- + /* Reset the kernel pointer. */
- + * KernelPointer = gcvNULL;
- + }
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +void
- +gckKERNEL_SetTimeOut(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 timeOut
- + )
- +{
- + gcmkHEADER_ARG("Kernel=0x%x timeOut=%d", Kernel, timeOut);
- +#if gcdGPU_TIMEOUT
- + Kernel->timeOut = timeOut;
- +#endif
- + gcmkFOOTER_NO();
- +}
- +
- +#if gcdVIRTUAL_COMMAND_BUFFER
- +gceSTATUS
- +gckKERNEL_AllocateVirtualCommandBuffer(
- + IN gckKERNEL Kernel,
- + IN gctBOOL InUserSpace,
- + IN OUT gctSIZE_T * Bytes,
- + OUT gctPHYS_ADDR * Physical,
- + OUT gctPOINTER * Logical
- + )
- +{
- + gckOS os = Kernel->os;
- + gceSTATUS status;
- + gctPOINTER logical;
- + gctSIZE_T pageCount;
- + gctSIZE_T bytes = *Bytes;
- + gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
- +
- + gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
- + os, InUserSpace, gcmOPT_VALUE(Bytes));
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
- + gcmkVERIFY_ARGUMENT(*Bytes > 0);
- + gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- +
- + gcmkONERROR(gckOS_Allocate(os,
- + sizeof(gckVIRTUAL_COMMAND_BUFFER),
- + (gctPOINTER)&buffer));
- +
- + gcmkONERROR(gckOS_ZeroMemory(buffer, sizeof(gckVIRTUAL_COMMAND_BUFFER)));
- +
- + gcmkONERROR(gckOS_AllocatePagedMemoryEx(os,
- + gcvFALSE,
- + bytes,
- + &buffer->physical));
- +
- + if (InUserSpace)
- + {
- + gcmkONERROR(gckOS_LockPages(os,
- + buffer->physical,
- + bytes,
- + gcvFALSE,
- + &logical,
- + &pageCount));
- +
- + *Logical =
- + buffer->userLogical = logical;
- + }
- + else
- + {
- + gcmkONERROR(
- + gckOS_CreateKernelVirtualMapping(buffer->physical,
- + &pageCount,
- + &logical));
- + *Logical =
- + buffer->kernelLogical = logical;
- + }
- +
- + buffer->pageCount = pageCount;
- + buffer->kernel = Kernel;
- +
- + gcmkONERROR(gckOS_GetProcessID(&buffer->pid));
- +
- + gcmkONERROR(gckMMU_AllocatePages(Kernel->mmu,
- + pageCount,
- + &buffer->pageTable,
- + &buffer->gpuAddress));
- +
- + gcmkONERROR(gckOS_MapPagesEx(os,
- + Kernel->core,
- + buffer->physical,
- + pageCount,
- + buffer->pageTable));
- +
- + gcmkONERROR(gckMMU_Flush(Kernel->mmu));
- +
- + *Physical = buffer;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
- + "gpuAddress = %x pageCount = %d kernelLogical = %x userLogical=%x",
- + buffer->gpuAddress, buffer->pageCount,
- + buffer->kernelLogical, buffer->userLogical);
- +
- + gcmkVERIFY_OK(gckOS_AcquireMutex(os, Kernel->virtualBufferLock, gcvINFINITE));
- +
- + if (Kernel->virtualBufferHead == gcvNULL)
- + {
- + Kernel->virtualBufferHead =
- + Kernel->virtualBufferTail = buffer;
- + }
- + else
- + {
- + buffer->prev = Kernel->virtualBufferTail;
- + Kernel->virtualBufferTail->next = buffer;
- + Kernel->virtualBufferTail = buffer;
- + }
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Kernel->virtualBufferLock));
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (buffer->gpuAddress)
- + {
- + gcmkVERIFY_OK(
- + gckMMU_FreePages(Kernel->mmu, buffer->pageTable, buffer->pageCount));
- + }
- +
- + if (buffer->userLogical)
- + {
- + gcmkVERIFY_OK(
- + gckOS_UnlockPages(os, buffer->physical, bytes, buffer->userLogical));
- + }
- +
- + if (buffer->kernelLogical)
- + {
- + gcmkVERIFY_OK(
- + gckOS_DestroyKernelVirtualMapping(buffer->kernelLogical));
- + }
- +
- + if (buffer->physical)
- + {
- + gcmkVERIFY_OK(gckOS_FreePagedMemory(os, buffer->physical, bytes));
- + }
- +
- + gcmkVERIFY_OK(gckOS_Free(os, buffer));
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckKERNEL_DestroyVirtualCommandBuffer(
- + IN gckKERNEL Kernel,
- + IN gctSIZE_T Bytes,
- + IN gctPHYS_ADDR Physical,
- + IN gctPOINTER Logical
- + )
- +{
- + gckOS os;
- + gckKERNEL kernel;
- + gckVIRTUAL_COMMAND_BUFFER_PTR buffer = (gckVIRTUAL_COMMAND_BUFFER_PTR)Physical;
- +
- + gcmkHEADER();
- + gcmkVERIFY_ARGUMENT(buffer != gcvNULL);
- +
- + kernel = buffer->kernel;
- + os = kernel->os;
- +
- + if (buffer->userLogical)
- + {
- + gcmkVERIFY_OK(gckOS_UnlockPages(os, buffer->physical, Bytes, Logical));
- + }
- + else
- + {
- + gcmkVERIFY_OK(gckOS_DestroyKernelVirtualMapping(Logical));
- + }
- +
- + gcmkVERIFY_OK(
- + gckMMU_FreePages(kernel->mmu, buffer->pageTable, buffer->pageCount));
- +
- + gcmkVERIFY_OK(gckOS_FreePagedMemory(os, buffer->physical, Bytes));
- +
- + gcmkVERIFY_OK(gckOS_AcquireMutex(os, kernel->virtualBufferLock, gcvINFINITE));
- +
- + if (buffer == kernel->virtualBufferHead)
- + {
- + if ((kernel->virtualBufferHead = buffer->next) == gcvNULL)
- + {
- + kernel->virtualBufferTail = gcvNULL;
- + }
- + }
- + else
- + {
- + buffer->prev->next = buffer->next;
- +
- + if (buffer == kernel->virtualBufferTail)
- + {
- + kernel->virtualBufferTail = buffer->prev;
- + }
- + else
- + {
- + buffer->next->prev = buffer->prev;
- + }
- + }
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(os, kernel->virtualBufferLock));
- +
- + gcmkVERIFY_OK(gckOS_Free(os, buffer));
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckKERNEL_GetGPUAddress(
- + IN gckKERNEL Kernel,
- + IN gctPOINTER Logical,
- + OUT gctUINT32 * Address
- + )
- +{
- + gceSTATUS status;
- + gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
- + gctPOINTER start;
- + gctINT pid;
- +
- + gcmkHEADER_ARG("Logical = %x", Logical);
- +
- + gckOS_GetProcessID(&pid);
- +
- + status = gcvSTATUS_INVALID_ADDRESS;
- +
- + gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, Kernel->virtualBufferLock, gcvINFINITE));
- +
- + /* Walk all command buffer. */
- + for (buffer = Kernel->virtualBufferHead; buffer != gcvNULL; buffer = buffer->next)
- + {
- + if (buffer->userLogical)
- + {
- + start = buffer->userLogical;
- + }
- + else
- + {
- + start = buffer->kernelLogical;
- + }
- +
- + if (Logical >= start
- + && (Logical < (start + buffer->pageCount * 4096))
- + && pid == buffer->pid
- + )
- + {
- + * Address = buffer->gpuAddress + (Logical - start);
- + status = gcvSTATUS_OK;
- + break;
- + }
- + }
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->virtualBufferLock));
- +
- + gcmkFOOTER_NO();
- + return status;
- +}
- +
- +gceSTATUS
- +gckKERNEL_QueryGPUAddress(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 GpuAddress,
- + OUT gckVIRTUAL_COMMAND_BUFFER_PTR * Buffer
- + )
- +{
- + gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
- + gctUINT32 start;
- + gceSTATUS status = gcvSTATUS_NOT_SUPPORTED;
- +
- + gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, Kernel->virtualBufferLock, gcvINFINITE));
- +
- + /* Walk all command buffers. */
- + for (buffer = Kernel->virtualBufferHead; buffer != gcvNULL; buffer = buffer->next)
- + {
- + start = (gctUINT32)buffer->gpuAddress;
- +
- + if (GpuAddress >= start && GpuAddress < (start + buffer->pageCount * 4096))
- + {
- + /* Find a range matched. */
- + *Buffer = buffer;
- + status = gcvSTATUS_OK;
- + break;
- + }
- + }
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->virtualBufferLock));
- +
- + return status;
- +}
- +#endif
- +
- +#if gcdLINK_QUEUE_SIZE
- +static void
- +gckLINKQUEUE_Dequeue(
- + IN gckLINKQUEUE LinkQueue
- + )
- +{
- + gcmkASSERT(LinkQueue->count == gcdLINK_QUEUE_SIZE);
- +
- + LinkQueue->count--;
- + LinkQueue->front = (LinkQueue->front + 1) % gcdLINK_QUEUE_SIZE;
- +}
- +
- +void
- +gckLINKQUEUE_Enqueue(
- + IN gckLINKQUEUE LinkQueue,
- + IN gctUINT32 start,
- + IN gctUINT32 end
- + )
- +{
- + if (LinkQueue->count == gcdLINK_QUEUE_SIZE)
- + {
- + gckLINKQUEUE_Dequeue(LinkQueue);
- + }
- +
- + gcmkASSERT(LinkQueue->count < gcdLINK_QUEUE_SIZE);
- +
- + LinkQueue->count++;
- +
- + LinkQueue->data[LinkQueue->rear].start = start;
- + LinkQueue->data[LinkQueue->rear].end = end;
- +
- + gcmkVERIFY_OK(
- + gckOS_GetProcessID(&LinkQueue->data[LinkQueue->rear].pid));
- +
- + LinkQueue->rear = (LinkQueue->rear + 1) % gcdLINK_QUEUE_SIZE;
- +}
- +
- +void
- +gckLINKQUEUE_GetData(
- + IN gckLINKQUEUE LinkQueue,
- + IN gctUINT32 Index,
- + OUT gckLINKDATA * Data
- + )
- +{
- + gcmkASSERT(Index >= 0 && Index < gcdLINK_QUEUE_SIZE);
- +
- + *Data = &LinkQueue->data[(Index + LinkQueue->front) % gcdLINK_QUEUE_SIZE];
- +}
- +#endif
- +
- +/******************************************************************************\
- +*************************** Pointer - ID translation ***************************
- +\******************************************************************************/
- +#define gcdID_TABLE_LENGTH 1024
- +typedef struct _gcsINTEGERDB * gckINTEGERDB;
- +typedef struct _gcsINTEGERDB
- +{
- + gckOS os;
- + gctPOINTER* table;
- + gctPOINTER mutex;
- + gctUINT32 tableLen;
- + gctUINT32 currentID;
- + gctUINT32 unused;
- +}
- +gcsINTEGERDB;
- +
- +gceSTATUS
- +gckKERNEL_CreateIntegerDatabase(
- + IN gckKERNEL Kernel,
- + OUT gctPOINTER * Database
- + )
- +{
- + gceSTATUS status;
- + gckINTEGERDB database = gcvNULL;
- +
- + gcmkHEADER_ARG("Kernel=0x%08X Datbase=0x%08X", Kernel, Database);
- +
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(Database != gcvNULL);
- +
- + /* Allocate a database. */
- + gcmkONERROR(gckOS_Allocate(
- + Kernel->os, gcmSIZEOF(gcsINTEGERDB), (gctPOINTER *)&database));
- +
- + gckOS_ZeroMemory(database, gcmSIZEOF(gcsINTEGERDB));
- +
- + /* Allocate a pointer table. */
- + gcmkONERROR(gckOS_Allocate(
- + Kernel->os, gcmSIZEOF(gctPOINTER) * gcdID_TABLE_LENGTH, (gctPOINTER *)&database->table));
- +
- + gckOS_ZeroMemory(database->table, gcmSIZEOF(gctPOINTER) * gcdID_TABLE_LENGTH);
- +
- + /* Allocate a database mutex. */
- + gcmkONERROR(gckOS_CreateMutex(Kernel->os, &database->mutex));
- +
- + /* Initialize. */
- + database->currentID = 0;
- + database->unused = gcdID_TABLE_LENGTH;
- + database->os = Kernel->os;
- + database->tableLen = gcdID_TABLE_LENGTH;
- +
- + *Database = database;
- +
- + gcmkFOOTER_ARG("*Database=0x%08X", *Database);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Rollback. */
- + if (database)
- + {
- + if (database->table)
- + {
- + gcmkOS_SAFE_FREE(Kernel->os, database->table);
- + }
- +
- + gcmkOS_SAFE_FREE(Kernel->os, database);
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckKERNEL_DestroyIntegerDatabase(
- + IN gckKERNEL Kernel,
- + IN gctPOINTER Database
- + )
- +{
- + gckINTEGERDB database = Database;
- +
- + gcmkHEADER_ARG("Kernel=0x%08X Datbase=0x%08X", Kernel, Database);
- +
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(Database != gcvNULL);
- +
- + /* Destroy pointer table. */
- + gcmkOS_SAFE_FREE(Kernel->os, database->table);
- +
- + /* Destroy database mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, database->mutex));
- +
- + /* Destroy database. */
- + gcmkOS_SAFE_FREE(Kernel->os, database);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckKERNEL_AllocateIntegerId(
- + IN gctPOINTER Database,
- + IN gctPOINTER Pointer,
- + OUT gctUINT32 * Id
- + )
- +{
- + gceSTATUS status;
- + gckINTEGERDB database = Database;
- + gctUINT32 i, unused, currentID, tableLen;
- + gctPOINTER * table;
- + gckOS os = database->os;
- + gctBOOL acquired = gcvFALSE;
- +
- + gcmkHEADER_ARG("Database=0x%08X Pointer=0x%08X", Database, Pointer);
- +
- + gcmkVERIFY_ARGUMENT(Id != gcvNULL);
- +
- + gcmkVERIFY_OK(gckOS_AcquireMutex(os, database->mutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + if (database->unused < 1)
- + {
- + /* Extend table. */
- + gcmkONERROR(
- + gckOS_Allocate(os,
- + gcmSIZEOF(gctPOINTER) * (database->tableLen + gcdID_TABLE_LENGTH),
- + (gctPOINTER *)&table));
- +
- + gckOS_ZeroMemory(table + database->tableLen,
- + gcmSIZEOF(gctPOINTER) * gcdID_TABLE_LENGTH);
- +
- + /* Copy data from old table. */
- + gckOS_MemCopy(table,
- + database->table,
- + database->tableLen * gcmSIZEOF(gctPOINTER));
- +
- + gcmkOS_SAFE_FREE(os, database->table);
- +
- + /* Update databse with new allocated table. */
- + database->table = table;
- + database->currentID = database->tableLen;
- + database->tableLen += gcdID_TABLE_LENGTH;
- + database->unused += gcdID_TABLE_LENGTH;
- + }
- +
- + table = database->table;
- + currentID = database->currentID;
- + tableLen = database->tableLen;
- + unused = database->unused;
- +
- + /* Connect id with pointer. */
- + table[currentID] = Pointer;
- +
- + *Id = currentID + 1;
- +
- + /* Update the currentID. */
- + if (--unused > 0)
- + {
- + for (i = 0; i < tableLen; i++)
- + {
- + if (++currentID >= tableLen)
- + {
- + /* Wrap to the begin. */
- + currentID = 0;
- + }
- +
- + if (table[currentID] == gcvNULL)
- + {
- + break;
- + }
- + }
- + }
- +
- + database->table = table;
- + database->currentID = currentID;
- + database->tableLen = tableLen;
- + database->unused = unused;
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
- + acquired = gcvFALSE;
- +
- + gcmkFOOTER_ARG("*Id=%d", *Id);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckKERNEL_FreeIntegerId(
- + IN gctPOINTER Database,
- + IN gctUINT32 Id
- + )
- +{
- + gceSTATUS status;
- + gckINTEGERDB database = Database;
- + gckOS os = database->os;
- + gctBOOL acquired = gcvFALSE;
- +
- + gcmkHEADER_ARG("Database=0x%08X Id=%d", Database, Id);
- +
- + gcmkVERIFY_OK(gckOS_AcquireMutex(os, database->mutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + if (!(Id > 0 && Id <= database->tableLen))
- + {
- + gcmkONERROR(gcvSTATUS_NOT_FOUND);
- + }
- +
- + Id -= 1;
- +
- + database->table[Id] = gcvNULL;
- +
- + if (database->unused++ == 0)
- + {
- + database->currentID = Id;
- + }
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
- + acquired = gcvFALSE;
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckKERNEL_QueryIntegerId(
- + IN gctPOINTER Database,
- + IN gctUINT32 Id,
- + OUT gctPOINTER * Pointer
- + )
- +{
- + gceSTATUS status;
- + gckINTEGERDB database = Database;
- + gctPOINTER pointer;
- + gckOS os = database->os;
- + gctBOOL acquired = gcvFALSE;
- +
- + gcmkHEADER_ARG("Database=0x%08X Id=%d", Database, Id);
- + gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
- +
- + gcmkVERIFY_OK(gckOS_AcquireMutex(os, database->mutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + if (!(Id > 0 && Id <= database->tableLen))
- + {
- + gcmkONERROR(gcvSTATUS_NOT_FOUND);
- + }
- +
- + Id -= 1;
- +
- + pointer = database->table[Id];
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
- + acquired = gcvFALSE;
- +
- + if (pointer)
- + {
- + *Pointer = pointer;
- + }
- + else
- + {
- + gcmkONERROR(gcvSTATUS_NOT_FOUND);
- + }
- +
- + gcmkFOOTER_ARG("*Pointer=0x%08X", *Pointer);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +
- +gctUINT32
- +gckKERNEL_AllocateNameFromPointer(
- + IN gckKERNEL Kernel,
- + IN gctPOINTER Pointer
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 name;
- + gctPOINTER database = Kernel->db->pointerDatabase;
- +
- + gcmkHEADER_ARG("Kernel=0x%X Pointer=0x%X", Kernel, Pointer);
- +
- + gcmkONERROR(
- + gckKERNEL_AllocateIntegerId(database, Pointer, &name));
- +
- + gcmkFOOTER_ARG("name=%d", name);
- + return name;
- +
- +OnError:
- + gcmkFOOTER();
- + return 0;
- +}
- +
- +gctPOINTER
- +gckKERNEL_QueryPointerFromName(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 Name
- + )
- +{
- + gceSTATUS status;
- + gctPOINTER pointer = gcvNULL;
- + gctPOINTER database = Kernel->db->pointerDatabase;
- +
- + gcmkHEADER_ARG("Kernel=0x%X Name=%d", Kernel, Name);
- +
- + /* Lookup in database to get pointer. */
- + gcmkONERROR(gckKERNEL_QueryIntegerId(database, Name, &pointer));
- +
- + gcmkFOOTER_ARG("pointer=0x%X", pointer);
- + return pointer;
- +
- +OnError:
- + gcmkFOOTER();
- + return gcvNULL;
- +}
- +
- +gceSTATUS
- +gckKERNEL_DeleteName(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 Name
- + )
- +{
- + gctPOINTER database = Kernel->db->pointerDatabase;
- +
- + gcmkHEADER_ARG("Kernel=0x%X Name=0x%X", Kernel, Name);
- +
- + /* Free name if exists. */
- + gcmkVERIFY_OK(gckKERNEL_FreeIntegerId(database, Name));
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +/*******************************************************************************
- +***** Test Code ****************************************************************
- +*******************************************************************************/
- +
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c 2015-03-08 14:27:37.629684500 -0500
- @@ -0,0 +1,3042 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal_kernel_precomp.h"
- +#include "gc_hal_kernel_context.h"
- +
- +#ifdef __QNXNTO__
- +#include <sys/slog.h>
- +#endif
- +
- +#define _GC_OBJ_ZONE gcvZONE_COMMAND
- +
- +/******************************************************************************\
- +********************************* Support Code *********************************
- +\******************************************************************************/
- +
- +/*******************************************************************************
- +**
- +** _NewQueue
- +**
- +** Allocate a new command queue.
- +**
- +** INPUT:
- +**
- +** gckCOMMAND Command
- +** Pointer to an gckCOMMAND object.
- +**
- +** OUTPUT:
- +**
- +** gckCOMMAND Command
- +** gckCOMMAND object has been updated with a new command queue.
- +*/
- +static gceSTATUS
- +_NewQueue(
- + IN OUT gckCOMMAND Command
- + )
- +{
- + gceSTATUS status;
- + gctINT currentIndex, newIndex;
- +
- + gcmkHEADER_ARG("Command=0x%x", Command);
- +
- + /* Switch to the next command buffer. */
- + currentIndex = Command->index;
- + newIndex = (currentIndex + 1) % gcdCOMMAND_QUEUES;
- +
- + /* Wait for availability. */
- +#if gcdDUMP_COMMAND
- + gcmkPRINT("@[kernel.waitsignal]");
- +#endif
- +
- + gcmkONERROR(gckOS_WaitSignal(
- + Command->os,
- + Command->queues[newIndex].signal,
- + gcvINFINITE
- + ));
- +
- +#if gcmIS_DEBUG(gcdDEBUG_TRACE)
- + if (newIndex < currentIndex)
- + {
- + Command->wrapCount += 1;
- +
- + gcmkTRACE_ZONE_N(
- + gcvLEVEL_INFO, gcvZONE_COMMAND,
- + 2 * 4,
- + "%s(%d): queue array wrapped around.\n",
- + __FUNCTION__, __LINE__
- + );
- + }
- +
- + gcmkTRACE_ZONE_N(
- + gcvLEVEL_INFO, gcvZONE_COMMAND,
- + 3 * 4,
- + "%s(%d): total queue wrap arounds %d.\n",
- + __FUNCTION__, __LINE__, Command->wrapCount
- + );
- +
- + gcmkTRACE_ZONE_N(
- + gcvLEVEL_INFO, gcvZONE_COMMAND,
- + 3 * 4,
- + "%s(%d): switched to queue %d.\n",
- + __FUNCTION__, __LINE__, newIndex
- + );
- +#endif
- +
- + /* Update gckCOMMAND object with new command queue. */
- + Command->index = newIndex;
- + Command->newQueue = gcvTRUE;
- + Command->logical = Command->queues[newIndex].logical;
- + Command->offset = 0;
- +
- + gcmkONERROR(
- + gckOS_GetPhysicalAddress(
- + Command->os,
- + Command->logical,
- + (gctUINT32 *) &Command->physical
- + ));
- +
- + if (currentIndex != -1)
- + {
- + /* Mark the command queue as available. */
- + gcmkONERROR(gckEVENT_Signal(
- + Command->kernel->eventObj,
- + Command->queues[currentIndex].signal,
- + gcvKERNEL_COMMAND
- + ));
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("Command->index=%d", Command->index);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +static gceSTATUS
- +_IncrementCommitAtom(
- + IN gckCOMMAND Command,
- + IN gctBOOL Increment
- + )
- +{
- + gceSTATUS status;
- + gckHARDWARE hardware;
- + gctINT32 atomValue;
- + gctBOOL powerAcquired = gcvFALSE;
- +
- + gcmkHEADER_ARG("Command=0x%x", Command);
- +
- + /* Extract the gckHARDWARE and gckEVENT objects. */
- + hardware = Command->kernel->hardware;
- + gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
- +
- + /* Grab the power mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(
- + Command->os, hardware->powerMutex, gcvINFINITE
- + ));
- + powerAcquired = gcvTRUE;
- +
- + /* Increment the commit atom. */
- + if (Increment)
- + {
- + gcmkONERROR(gckOS_AtomIncrement(
- + Command->os, Command->atomCommit, &atomValue
- + ));
- + }
- + else
- + {
- + gcmkONERROR(gckOS_AtomDecrement(
- + Command->os, Command->atomCommit, &atomValue
- + ));
- + }
- +
- + /* Release the power mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(
- + Command->os, hardware->powerMutex
- + ));
- + powerAcquired = gcvFALSE;
- +
- + /* Success. */
- + gcmkFOOTER();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (powerAcquired)
- + {
- + /* Release the power mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(
- + Command->os, hardware->powerMutex
- + ));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +#if gcdSECURE_USER
- +static gceSTATUS
- +_ProcessHints(
- + IN gckCOMMAND Command,
- + IN gctUINT32 ProcessID,
- + IN gcoCMDBUF CommandBuffer
- + )
- +{
- + gceSTATUS status = gcvSTATUS_OK;
- + gckKERNEL kernel;
- + gctBOOL needCopy = gcvFALSE;
- + gcskSECURE_CACHE_PTR cache;
- + gctUINT8_PTR commandBufferLogical;
- + gctUINT8_PTR hintedData;
- + gctUINT32_PTR hintArray;
- + gctUINT i, hintCount;
- +
- + gcmkHEADER_ARG(
- + "Command=0x%08X ProcessID=%d CommandBuffer=0x%08X",
- + Command, ProcessID, CommandBuffer
- + );
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + /* Reset state array pointer. */
- + hintArray = gcvNULL;
- +
- + /* Get the kernel object. */
- + kernel = Command->kernel;
- +
- + /* Get the cache form the database. */
- + gcmkONERROR(gckKERNEL_GetProcessDBCache(kernel, ProcessID, &cache));
- +
- + /* Determine the start of the command buffer. */
- + commandBufferLogical
- + = (gctUINT8_PTR) CommandBuffer->logical
- + + CommandBuffer->startOffset;
- +
- + /* Determine the number of records in the state array. */
- + hintCount = CommandBuffer->hintArrayTail - CommandBuffer->hintArray;
- +
- + /* Check wehther we need to copy the structures or not. */
- + gcmkONERROR(gckOS_QueryNeedCopy(Command->os, ProcessID, &needCopy));
- +
- + /* Get access to the state array. */
- + if (needCopy)
- + {
- + gctUINT copySize;
- +
- + if (Command->hintArrayAllocated &&
- + (Command->hintArraySize < CommandBuffer->hintArraySize))
- + {
- + gcmkONERROR(gcmkOS_SAFE_FREE(Command->os, gcmUINT64_TO_PTR(Command->hintArray)));
- + Command->hintArraySize = gcvFALSE;
- + }
- +
- + if (!Command->hintArrayAllocated)
- + {
- + gctPOINTER pointer = gcvNULL;
- +
- + gcmkONERROR(gckOS_Allocate(
- + Command->os,
- + CommandBuffer->hintArraySize,
- + &pointer
- + ));
- +
- + Command->hintArray = gcmPTR_TO_UINT64(pointer);
- + Command->hintArrayAllocated = gcvTRUE;
- + Command->hintArraySize = CommandBuffer->hintArraySize;
- + }
- +
- + hintArray = gcmUINT64_TO_PTR(Command->hintArray);
- + copySize = hintCount * gcmSIZEOF(gctUINT32);
- +
- + gcmkONERROR(gckOS_CopyFromUserData(
- + Command->os,
- + hintArray,
- + gcmUINT64_TO_PTR(CommandBuffer->hintArray),
- + copySize
- + ));
- + }
- + else
- + {
- + gctPOINTER pointer = gcvNULL;
- +
- + gcmkONERROR(gckOS_MapUserPointer(
- + Command->os,
- + gcmUINT64_TO_PTR(CommandBuffer->hintArray),
- + CommandBuffer->hintArraySize,
- + &pointer
- + ));
- +
- + hintArray = pointer;
- + }
- +
- + /* Scan through the buffer. */
- + for (i = 0; i < hintCount; i += 1)
- + {
- + /* Determine the location of the hinted data. */
- + hintedData = commandBufferLogical + hintArray[i];
- +
- + /* Map handle into physical address. */
- + gcmkONERROR(gckKERNEL_MapLogicalToPhysical(
- + kernel, cache, (gctPOINTER) hintedData
- + ));
- + }
- +
- +OnError:
- + /* Get access to the state array. */
- + if (!needCopy && (hintArray != gcvNULL))
- + {
- + gcmkVERIFY_OK(gckOS_UnmapUserPointer(
- + Command->os,
- + gcmUINT64_TO_PTR(CommandBuffer->hintArray),
- + CommandBuffer->hintArraySize,
- + hintArray
- + ));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +#endif
- +
- +static gceSTATUS
- +_FlushMMU(
- + IN gckCOMMAND Command
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 oldValue;
- + gckHARDWARE hardware = Command->kernel->hardware;
- +
- + gcmkONERROR(gckOS_AtomicExchange(Command->os,
- + hardware->pageTableDirty,
- + 0,
- + &oldValue));
- +
- + if (oldValue)
- + {
- + /* Page Table is upated, flush mmu before commit. */
- + gcmkONERROR(gckHARDWARE_FlushMMU(hardware));
- + }
- +
- + return gcvSTATUS_OK;
- +OnError:
- + return status;
- +}
- +
- +#if gcdVIRTUAL_COMMAND_BUFFER
- +static void
- +_DumpBuffer(
- + IN gctPOINTER Buffer,
- + IN gctUINT32 GpuAddress,
- + IN gctSIZE_T Size
- + )
- +{
- + gctINT i, line, left;
- + gctUINT32_PTR data = Buffer;
- +
- + line = Size / 32;
- + left = Size % 32;
- +
- +
- + for (i = 0; i < line; i++)
- + {
- + gcmkPRINT("%X : %08X %08X %08X %08X %08X %08X %08X %08X ",
- + GpuAddress, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
- + data += 8;
- + GpuAddress += 8 * 4;
- + }
- +
- + switch(left)
- + {
- + case 28:
- + gcmkPRINT("%X : %08X %08X %08X %08X %08X %08X %08X ",
- + GpuAddress, data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
- + break;
- + case 24:
- + gcmkPRINT("%X : %08X %08X %08X %08X %08X %08X ",
- + GpuAddress, data[0], data[1], data[2], data[3], data[4], data[5]);
- + break;
- + case 20:
- + gcmkPRINT("%X : %08X %08X %08X %08X %08X ",
- + GpuAddress, data[0], data[1], data[2], data[3], data[4]);
- + break;
- + case 16:
- + gcmkPRINT("%X : %08X %08X %08X %08X ",
- + GpuAddress, data[0], data[1], data[2], data[3]);
- + break;
- + case 12:
- + gcmkPRINT("%X : %08X %08X %08X ",
- + GpuAddress, data[0], data[1], data[2]);
- + break;
- + case 8:
- + gcmkPRINT("%X : %08X %08X ",
- + GpuAddress, data[0], data[1]);
- + break;
- + case 4:
- + gcmkPRINT("%X : %08X ",
- + GpuAddress, data[0]);
- + break;
- + default:
- + break;
- + }
- +}
- +
- +static void
- +_DumpKernelCommandBuffer(
- + IN gckCOMMAND Command
- +)
- +{
- + gctINT i;
- + gctUINT32 physical;
- + gctPOINTER entry;
- +
- + for (i = 0; i < gcdCOMMAND_QUEUES; i++)
- + {
- + entry = Command->queues[i].logical;
- +
- + gckOS_GetPhysicalAddress(Command->os, entry, &physical);
- +
- + gcmkPRINT("Kernel command buffer %d\n", i);
- +
- + _DumpBuffer(entry, physical, Command->pageSize);
- + }
- +}
- +#endif
- +
- +/******************************************************************************\
- +****************************** gckCOMMAND API Code ******************************
- +\******************************************************************************/
- +
- +/*******************************************************************************
- +**
- +** gckCOMMAND_Construct
- +**
- +** Construct a new gckCOMMAND object.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** OUTPUT:
- +**
- +** gckCOMMAND * Command
- +** Pointer to a variable that will hold the pointer to the gckCOMMAND
- +** object.
- +*/
- +gceSTATUS
- +gckCOMMAND_Construct(
- + IN gckKERNEL Kernel,
- + OUT gckCOMMAND * Command
- + )
- +{
- + gckOS os;
- + gckCOMMAND command = gcvNULL;
- + gceSTATUS status;
- + gctINT i;
- + gctPOINTER pointer = gcvNULL;
- +
- + gcmkHEADER_ARG("Kernel=0x%x", Kernel);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(Command != gcvNULL);
- +
- + /* Extract the gckOS object. */
- + os = Kernel->os;
- +
- + /* Allocate the gckCOMMAND structure. */
- + gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct _gckCOMMAND), &pointer));
- + command = pointer;
- +
- + /* Reset the entire object. */
- + gcmkONERROR(gckOS_ZeroMemory(command, gcmSIZEOF(struct _gckCOMMAND)));
- +
- + /* Initialize the gckCOMMAND object.*/
- + command->object.type = gcvOBJ_COMMAND;
- + command->kernel = Kernel;
- + command->os = os;
- +
- + /* Get the command buffer requirements. */
- + gcmkONERROR(gckHARDWARE_QueryCommandBuffer(
- + Kernel->hardware,
- + &command->alignment,
- + &command->reservedHead,
- + &command->reservedTail
- + ));
- +
- + /* Create the command queue mutex. */
- + gcmkONERROR(gckOS_CreateMutex(os, &command->mutexQueue));
- +
- + /* Create the context switching mutex. */
- + gcmkONERROR(gckOS_CreateMutex(os, &command->mutexContext));
- +
- +#if VIVANTE_PROFILER_CONTEXT
- + /* Create the context switching mutex. */
- + gcmkONERROR(gckOS_CreateMutex(os, &command->mutexContextSeq));
- +#endif
- +
- + /* Create the power management semaphore. */
- + gcmkONERROR(gckOS_CreateSemaphore(os, &command->powerSemaphore));
- +
- + /* Create the commit atom. */
- + gcmkONERROR(gckOS_AtomConstruct(os, &command->atomCommit));
- +
- + /* Get the page size from teh OS. */
- + gcmkONERROR(gckOS_GetPageSize(os, &command->pageSize));
- +
- + /* Get process ID. */
- + gcmkONERROR(gckOS_GetProcessID(&command->kernelProcessID));
- +
- + /* Set hardware to pipe 0. */
- + command->pipeSelect = gcvPIPE_INVALID;
- +
- + /* Pre-allocate the command queues. */
- + for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
- + {
- + gcmkONERROR(gckOS_AllocateNonPagedMemory(
- + os,
- + gcvFALSE,
- + &command->pageSize,
- + &command->queues[i].physical,
- + &command->queues[i].logical
- + ));
- +
- + gcmkONERROR(gckOS_CreateSignal(
- + os, gcvFALSE, &command->queues[i].signal
- + ));
- +
- + gcmkONERROR(gckOS_Signal(
- + os, command->queues[i].signal, gcvTRUE
- + ));
- + }
- +
- + /* No command queue in use yet. */
- + command->index = -1;
- + command->logical = gcvNULL;
- + command->newQueue = gcvFALSE;
- +
- + /* Command is not yet running. */
- + command->running = gcvFALSE;
- +
- + /* Command queue is idle. */
- + command->idle = gcvTRUE;
- +
- + /* Commit stamp is zero. */
- + command->commitStamp = 0;
- +
- + /* END event signal not created. */
- + command->endEventSignal = gcvNULL;
- +
- + /* Return pointer to the gckCOMMAND object. */
- + *Command = command;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Command=0x%x", *Command);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Roll back. */
- + if (command != gcvNULL)
- + {
- + if (command->atomCommit != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_AtomDestroy(os, command->atomCommit));
- + }
- +
- + if (command->powerSemaphore != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_DestroySemaphore(os, command->powerSemaphore));
- + }
- +
- + if (command->mutexContext != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_DeleteMutex(os, command->mutexContext));
- + }
- +
- +#if VIVANTE_PROFILER_CONTEXT
- + if (command->mutexContextSeq != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_DeleteMutex(os, command->mutexContextSeq));
- + }
- +#endif
- +
- + if (command->mutexQueue != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_DeleteMutex(os, command->mutexQueue));
- + }
- +
- + for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
- + {
- + if (command->queues[i].signal != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_DestroySignal(
- + os, command->queues[i].signal
- + ));
- + }
- +
- + if (command->queues[i].logical != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
- + os,
- + command->pageSize,
- + command->queues[i].physical,
- + command->queues[i].logical
- + ));
- + }
- + }
- +
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, command));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckCOMMAND_Destroy
- +**
- +** Destroy an gckCOMMAND object.
- +**
- +** INPUT:
- +**
- +** gckCOMMAND Command
- +** Pointer to an gckCOMMAND object to destroy.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckCOMMAND_Destroy(
- + IN gckCOMMAND Command
- + )
- +{
- + gctINT i;
- +
- + gcmkHEADER_ARG("Command=0x%x", Command);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + /* Stop the command queue. */
- + gcmkVERIFY_OK(gckCOMMAND_Stop(Command, gcvFALSE));
- +
- + for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
- + {
- + gcmkASSERT(Command->queues[i].signal != gcvNULL);
- + gcmkVERIFY_OK(gckOS_DestroySignal(
- + Command->os, Command->queues[i].signal
- + ));
- +
- + gcmkASSERT(Command->queues[i].logical != gcvNULL);
- + gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
- + Command->os,
- + Command->pageSize,
- + Command->queues[i].physical,
- + Command->queues[i].logical
- + ));
- + }
- +
- + /* END event signal. */
- + if (Command->endEventSignal != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_DestroySignal(
- + Command->os, Command->endEventSignal
- + ));
- + }
- +
- + /* Delete the context switching mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexContext));
- +
- +#if VIVANTE_PROFILER_CONTEXT
- + if (Command->mutexContextSeq != gcvNULL)
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexContextSeq));
- +#endif
- +
- + /* Delete the command queue mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexQueue));
- +
- + /* Destroy the power management semaphore. */
- + gcmkVERIFY_OK(gckOS_DestroySemaphore(Command->os, Command->powerSemaphore));
- +
- + /* Destroy the commit atom. */
- + gcmkVERIFY_OK(gckOS_AtomDestroy(Command->os, Command->atomCommit));
- +
- +#if gcdSECURE_USER
- + /* Free state array. */
- + if (Command->hintArrayAllocated)
- + {
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Command->os, gcmUINT64_TO_PTR(Command->hintArray)));
- + Command->hintArrayAllocated = gcvFALSE;
- + }
- +#endif
- +
- + /* Mark object as unknown. */
- + Command->object.type = gcvOBJ_UNKNOWN;
- +
- + /* Free the gckCOMMAND object. */
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Command->os, Command));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckCOMMAND_EnterCommit
- +**
- +** Acquire command queue synchronization objects.
- +**
- +** INPUT:
- +**
- +** gckCOMMAND Command
- +** Pointer to an gckCOMMAND object to destroy.
- +**
- +** gctBOOL FromPower
- +** Determines whether the call originates from inside the power
- +** management or not.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckCOMMAND_EnterCommit(
- + IN gckCOMMAND Command,
- + IN gctBOOL FromPower
- + )
- +{
- + gceSTATUS status;
- + gckHARDWARE hardware;
- + gctBOOL atomIncremented = gcvFALSE;
- + gctBOOL semaAcquired = gcvFALSE;
- +
- + gcmkHEADER_ARG("Command=0x%x", Command);
- +
- + /* Extract the gckHARDWARE and gckEVENT objects. */
- + hardware = Command->kernel->hardware;
- + gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
- +
- + if (!FromPower)
- + {
- + /* Increment COMMIT atom to let power management know that a commit is
- + ** in progress. */
- + gcmkONERROR(_IncrementCommitAtom(Command, gcvTRUE));
- + atomIncremented = gcvTRUE;
- +
- + /* Notify the system the GPU has a commit. */
- + gcmkONERROR(gckOS_Broadcast(Command->os,
- + hardware,
- + gcvBROADCAST_GPU_COMMIT));
- +
- + /* Acquire the power management semaphore. */
- + gcmkONERROR(gckOS_AcquireSemaphore(Command->os,
- + Command->powerSemaphore));
- + semaAcquired = gcvTRUE;
- + }
- +
- + /* Grab the conmmand queue mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(Command->os,
- + Command->mutexQueue,
- + gcvINFINITE));
- +
- + /* Success. */
- + gcmkFOOTER();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (semaAcquired)
- + {
- + /* Release the power management semaphore. */
- + gcmkVERIFY_OK(gckOS_ReleaseSemaphore(
- + Command->os, Command->powerSemaphore
- + ));
- + }
- +
- + if (atomIncremented)
- + {
- + /* Decrement the commit atom. */
- + gcmkVERIFY_OK(_IncrementCommitAtom(
- + Command, gcvFALSE
- + ));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckCOMMAND_ExitCommit
- +**
- +** Release command queue synchronization objects.
- +**
- +** INPUT:
- +**
- +** gckCOMMAND Command
- +** Pointer to an gckCOMMAND object to destroy.
- +**
- +** gctBOOL FromPower
- +** Determines whether the call originates from inside the power
- +** management or not.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckCOMMAND_ExitCommit(
- + IN gckCOMMAND Command,
- + IN gctBOOL FromPower
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Command=0x%x", Command);
- +
- + /* Release the power mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
- +
- + if (!FromPower)
- + {
- + /* Release the power management semaphore. */
- + gcmkONERROR(gckOS_ReleaseSemaphore(Command->os,
- + Command->powerSemaphore));
- +
- + /* Decrement the commit atom. */
- + gcmkONERROR(_IncrementCommitAtom(Command, gcvFALSE));
- + }
- +
- + /* Success. */
- + gcmkFOOTER();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckCOMMAND_Start
- +**
- +** Start up the command queue.
- +**
- +** INPUT:
- +**
- +** gckCOMMAND Command
- +** Pointer to an gckCOMMAND object to start.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckCOMMAND_Start(
- + IN gckCOMMAND Command
- + )
- +{
- + gceSTATUS status;
- + gckHARDWARE hardware;
- + gctUINT32 waitOffset;
- + gctSIZE_T waitLinkBytes;
- +
- + gcmkHEADER_ARG("Command=0x%x", Command);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + if (Command->running)
- + {
- + /* Command queue already running. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- +
- + /* Extract the gckHARDWARE object. */
- + hardware = Command->kernel->hardware;
- + gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
- +
- + if (Command->logical == gcvNULL)
- + {
- + /* Start at beginning of a new queue. */
- + gcmkONERROR(_NewQueue(Command));
- + }
- +
- + /* Start at beginning of page. */
- + Command->offset = 0;
- +
- + /* Set abvailable number of bytes for WAIT/LINK command sequence. */
- + waitLinkBytes = Command->pageSize;
- +
- + /* Append WAIT/LINK. */
- + gcmkONERROR(gckHARDWARE_WaitLink(
- + hardware,
- + Command->logical,
- + 0,
- + &waitLinkBytes,
- + &waitOffset,
- + &Command->waitSize
- + ));
- +
- + Command->waitLogical = (gctUINT8_PTR) Command->logical + waitOffset;
- + Command->waitPhysical = (gctUINT8_PTR) Command->physical + waitOffset;
- +
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + /* Flush the cache for the wait/link. */
- + gcmkONERROR(gckOS_CacheClean(
- + Command->os,
- + Command->kernelProcessID,
- + gcvNULL,
- + Command->physical,
- + Command->logical,
- + waitLinkBytes
- + ));
- +#endif
- +
- + /* Adjust offset. */
- + Command->offset = waitLinkBytes;
- + Command->newQueue = gcvFALSE;
- +
- + /* Enable command processor. */
- +#ifdef __QNXNTO__
- + gcmkONERROR(gckHARDWARE_Execute(
- + hardware,
- + Command->logical,
- + Command->physical,
- + gcvTRUE,
- + waitLinkBytes
- + ));
- +#else
- + gcmkONERROR(gckHARDWARE_Execute(
- + hardware,
- + Command->logical,
- + waitLinkBytes
- + ));
- +#endif
- +
- + /* Command queue is running. */
- + Command->running = gcvTRUE;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckCOMMAND_Stop
- +**
- +** Stop the command queue.
- +**
- +** INPUT:
- +**
- +** gckCOMMAND Command
- +** Pointer to an gckCOMMAND object to stop.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckCOMMAND_Stop(
- + IN gckCOMMAND Command,
- + IN gctBOOL FromRecovery
- + )
- +{
- + gckHARDWARE hardware;
- + gceSTATUS status;
- + gctUINT32 idle;
- +
- + gcmkHEADER_ARG("Command=0x%x", Command);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + if (!Command->running)
- + {
- + /* Command queue is not running. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- +
- + /* Extract the gckHARDWARE object. */
- + hardware = Command->kernel->hardware;
- + gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
- +
- + if (gckHARDWARE_IsFeatureAvailable(hardware,
- + gcvFEATURE_END_EVENT) == gcvSTATUS_TRUE)
- + {
- + /* Allocate the signal. */
- + if (Command->endEventSignal == gcvNULL)
- + {
- + gcmkONERROR(gckOS_CreateSignal(Command->os,
- + gcvTRUE,
- + &Command->endEventSignal));
- + }
- +
- + /* Append the END EVENT command to trigger the signal. */
- + gcmkONERROR(gckEVENT_Stop(Command->kernel->eventObj,
- + Command->kernelProcessID,
- + Command->waitPhysical,
- + Command->waitLogical,
- + Command->endEventSignal,
- + &Command->waitSize));
- + }
- + else
- + {
- + /* Replace last WAIT with END. */
- + gcmkONERROR(gckHARDWARE_End(
- + hardware, Command->waitLogical, &Command->waitSize
- + ));
- +
- + /* Update queue tail pointer. */
- + gcmkONERROR(gckHARDWARE_UpdateQueueTail(Command->kernel->hardware,
- + Command->logical,
- + Command->offset));
- +
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + /* Flush the cache for the END. */
- + gcmkONERROR(gckOS_CacheClean(
- + Command->os,
- + Command->kernelProcessID,
- + gcvNULL,
- + Command->waitPhysical,
- + Command->waitLogical,
- + Command->waitSize
- + ));
- +#endif
- +
- + /* Wait for idle. */
- + gcmkONERROR(gckHARDWARE_GetIdle(hardware, !FromRecovery, &idle));
- + }
- +
- + /* Command queue is no longer running. */
- + Command->running = gcvFALSE;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckCOMMAND_Commit
- +**
- +** Commit a command buffer to the command queue.
- +**
- +** INPUT:
- +**
- +** gckCOMMAND Command
- +** Pointer to a gckCOMMAND object.
- +**
- +** gckCONTEXT Context
- +** Pointer to a gckCONTEXT object.
- +**
- +** gcoCMDBUF CommandBuffer
- +** Pointer to a gcoCMDBUF object.
- +**
- +** gcsSTATE_DELTA_PTR StateDelta
- +** Pointer to the state delta.
- +**
- +** gctUINT32 ProcessID
- +** Current process ID.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckCOMMAND_Commit(
- + IN gckCOMMAND Command,
- + IN gckCONTEXT Context,
- + IN gcoCMDBUF CommandBuffer,
- + IN gcsSTATE_DELTA_PTR StateDelta,
- + IN gcsQUEUE_PTR EventQueue,
- + IN gctUINT32 ProcessID
- + )
- +{
- + gceSTATUS status;
- + gctBOOL commitEntered = gcvFALSE;
- + gctBOOL contextAcquired = gcvFALSE;
- + gckHARDWARE hardware;
- + gctBOOL needCopy = gcvFALSE;
- + gcsQUEUE_PTR eventRecord = gcvNULL;
- + gcsQUEUE _eventRecord;
- + gcsQUEUE_PTR nextEventRecord;
- + gctBOOL commandBufferMapped = gcvFALSE;
- + gcoCMDBUF commandBufferObject = gcvNULL;
- +
- +#if !gcdNULL_DRIVER
- + gcsCONTEXT_PTR contextBuffer;
- + struct _gcoCMDBUF _commandBufferObject;
- + gctPHYS_ADDR commandBufferPhysical;
- + gctUINT8_PTR commandBufferLogical;
- + gctUINT8_PTR commandBufferLink;
- + gctUINT commandBufferSize;
- + gctSIZE_T nopBytes;
- + gctSIZE_T pipeBytes;
- + gctSIZE_T linkBytes;
- + gctSIZE_T bytes;
- + gctUINT32 offset;
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + gctPHYS_ADDR entryPhysical;
- +#endif
- + gctPOINTER entryLogical;
- + gctSIZE_T entryBytes;
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + gctPHYS_ADDR exitPhysical;
- +#endif
- + gctPOINTER exitLogical;
- + gctSIZE_T exitBytes;
- + gctPHYS_ADDR waitLinkPhysical;
- + gctPOINTER waitLinkLogical;
- + gctSIZE_T waitLinkBytes;
- + gctPHYS_ADDR waitPhysical;
- + gctPOINTER waitLogical;
- + gctUINT32 waitOffset;
- + gctSIZE_T waitSize;
- +
- +#if gcdDUMP_COMMAND
- + gctPOINTER contextDumpLogical = gcvNULL;
- + gctSIZE_T contextDumpBytes = 0;
- + gctPOINTER bufferDumpLogical = gcvNULL;
- + gctSIZE_T bufferDumpBytes = 0;
- +# endif
- +#endif
- +
- +#if VIVANTE_PROFILER_CONTEXT
- + gctBOOL sequenceAcquired = gcvFALSE;
- +#endif
- +
- + gctPOINTER pointer = gcvNULL;
- +
- + gcmkHEADER_ARG(
- + "Command=0x%x CommandBuffer=0x%x ProcessID=%d",
- + Command, CommandBuffer, ProcessID
- + );
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + if (Command->kernel->core == gcvCORE_2D)
- + {
- + /* There is no context for 2D. */
- + Context = gcvNULL;
- + }
- +
- + gcmkONERROR(_FlushMMU(Command));
- +
- +#if VIVANTE_PROFILER_CONTEXT
- + if((Command->kernel->hardware->gpuProfiler) && (Command->kernel->profileEnable))
- + {
- + /* Acquire the context sequnence mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(
- + Command->os, Command->mutexContextSeq, gcvINFINITE
- + ));
- + sequenceAcquired = gcvTRUE;
- + }
- +#endif
- +
- + /* Acquire the command queue. */
- + gcmkONERROR(gckCOMMAND_EnterCommit(Command, gcvFALSE));
- + commitEntered = gcvTRUE;
- +
- + /* Acquire the context switching mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(
- + Command->os, Command->mutexContext, gcvINFINITE
- + ));
- + contextAcquired = gcvTRUE;
- +
- + /* Extract the gckHARDWARE and gckEVENT objects. */
- + hardware = Command->kernel->hardware;
- +
- + /* Check wehther we need to copy the structures or not. */
- + gcmkONERROR(gckOS_QueryNeedCopy(Command->os, ProcessID, &needCopy));
- +
- +#if gcdNULL_DRIVER
- + /* Context switch required? */
- + if ((Context != gcvNULL) && (Command->currContext != Context))
- + {
- + /* Yes, merge in the deltas. */
- + gckCONTEXT_Update(Context, ProcessID, StateDelta);
- +
- + /* Update the current context. */
- + Command->currContext = Context;
- + }
- +#else
- + if (needCopy)
- + {
- + commandBufferObject = &_commandBufferObject;
- +
- + gcmkONERROR(gckOS_CopyFromUserData(
- + Command->os,
- + commandBufferObject,
- + CommandBuffer,
- + gcmSIZEOF(struct _gcoCMDBUF)
- + ));
- +
- + gcmkVERIFY_OBJECT(commandBufferObject, gcvOBJ_COMMANDBUFFER);
- + }
- + else
- + {
- + gcmkONERROR(gckOS_MapUserPointer(
- + Command->os,
- + CommandBuffer,
- + gcmSIZEOF(struct _gcoCMDBUF),
- + &pointer
- + ));
- +
- + commandBufferObject = pointer;
- +
- + gcmkVERIFY_OBJECT(commandBufferObject, gcvOBJ_COMMANDBUFFER);
- + commandBufferMapped = gcvTRUE;
- + }
- +
- + /* Query the size of NOP command. */
- + gcmkONERROR(gckHARDWARE_Nop(
- + hardware, gcvNULL, &nopBytes
- + ));
- +
- + /* Query the size of pipe select command sequence. */
- + gcmkONERROR(gckHARDWARE_PipeSelect(
- + hardware, gcvNULL, gcvPIPE_3D, &pipeBytes
- + ));
- +
- + /* Query the size of LINK command. */
- + gcmkONERROR(gckHARDWARE_Link(
- + hardware, gcvNULL, gcvNULL, 0, &linkBytes
- + ));
- +
- + /* Compute the command buffer entry and the size. */
- + commandBufferLogical
- + = (gctUINT8_PTR) gcmUINT64_TO_PTR(commandBufferObject->logical)
- + + commandBufferObject->startOffset;
- +
- + gcmkONERROR(gckOS_GetPhysicalAddress(
- + Command->os,
- + commandBufferLogical,
- + (gctUINT32_PTR)&commandBufferPhysical
- + ));
- +
- + commandBufferSize
- + = commandBufferObject->offset
- + + Command->reservedTail
- + - commandBufferObject->startOffset;
- +
- + /* Get the current offset. */
- + offset = Command->offset;
- +
- + /* Compute number of bytes left in current kernel command queue. */
- + bytes = Command->pageSize - offset;
- +
- + /* Query the size of WAIT/LINK command sequence. */
- + gcmkONERROR(gckHARDWARE_WaitLink(
- + hardware,
- + gcvNULL,
- + offset,
- + &waitLinkBytes,
- + gcvNULL,
- + gcvNULL
- + ));
- +
- + /* Is there enough space in the current command queue? */
- + if (bytes < waitLinkBytes)
- + {
- + /* No, create a new one. */
- + gcmkONERROR(_NewQueue(Command));
- +
- + /* Get the new current offset. */
- + offset = Command->offset;
- +
- + /* Recompute the number of bytes in the new kernel command queue. */
- + bytes = Command->pageSize - offset;
- + gcmkASSERT(bytes >= waitLinkBytes);
- + }
- +
- + /* Compute the location if WAIT/LINK command sequence. */
- + waitLinkPhysical = (gctUINT8_PTR) Command->physical + offset;
- + waitLinkLogical = (gctUINT8_PTR) Command->logical + offset;
- +
- + /* Context switch required? */
- + if (Context == gcvNULL)
- + {
- + /* See if we have to switch pipes for the command buffer. */
- + if (commandBufferObject->entryPipe == Command->pipeSelect)
- + {
- + /* Skip pipe switching sequence. */
- + offset = pipeBytes;
- + }
- + else
- + {
- + /* The current hardware and the entry command buffer pipes
- + ** are different, switch to the correct pipe. */
- + gcmkONERROR(gckHARDWARE_PipeSelect(
- + Command->kernel->hardware,
- + commandBufferLogical,
- + commandBufferObject->entryPipe,
- + &pipeBytes
- + ));
- +
- + /* Do not skip pipe switching sequence. */
- + offset = 0;
- + }
- +
- + /* Compute the entry. */
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + entryPhysical = (gctUINT8_PTR) commandBufferPhysical + offset;
- +#endif
- + entryLogical = commandBufferLogical + offset;
- + entryBytes = commandBufferSize - offset;
- + }
- + else if (Command->currContext != Context)
- + {
- + /* Temporary disable context length oprimization. */
- + Context->dirty = gcvTRUE;
- +
- + /* Get the current context buffer. */
- + contextBuffer = Context->buffer;
- +
- + /* Yes, merge in the deltas. */
- + gcmkONERROR(gckCONTEXT_Update(Context, ProcessID, StateDelta));
- +
- + /* Determine context entry and exit points. */
- + if (0)
- + {
- + /* Reset 2D dirty flag. */
- + Context->dirty2D = gcvFALSE;
- +
- + if (Context->dirty || commandBufferObject->using3D)
- + {
- + /***************************************************************
- + ** SWITCHING CONTEXT: 2D and 3D are used.
- + */
- +
- + /* Reset 3D dirty flag. */
- + Context->dirty3D = gcvFALSE;
- +
- + /* Compute the entry. */
- + if (Command->pipeSelect == gcvPIPE_2D)
- + {
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
- +#endif
- + entryLogical = (gctUINT8_PTR) contextBuffer->logical + pipeBytes;
- + entryBytes = Context->bufferSize - pipeBytes;
- + }
- + else
- + {
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
- +#endif
- + entryLogical = (gctUINT8_PTR) contextBuffer->logical;
- + entryBytes = Context->bufferSize;
- + }
- +
- + /* See if we have to switch pipes between the context
- + and command buffers. */
- + if (commandBufferObject->entryPipe == gcvPIPE_3D)
- + {
- + /* Skip pipe switching sequence. */
- + offset = pipeBytes;
- + }
- + else
- + {
- + /* The current hardware and the initial context pipes are
- + different, switch to the correct pipe. */
- + gcmkONERROR(gckHARDWARE_PipeSelect(
- + Command->kernel->hardware,
- + commandBufferLogical,
- + commandBufferObject->entryPipe,
- + &pipeBytes
- + ));
- +
- + /* Do not skip pipe switching sequence. */
- + offset = 0;
- + }
- +
- + /* Ensure the NOP between 2D and 3D is in place so that the
- + execution falls through from 2D to 3D. */
- + gcmkONERROR(gckHARDWARE_Nop(
- + hardware,
- + contextBuffer->link2D,
- + &nopBytes
- + ));
- +
- + /* Generate a LINK from the context buffer to
- + the command buffer. */
- + gcmkONERROR(gckHARDWARE_Link(
- + hardware,
- + contextBuffer->link3D,
- + commandBufferLogical + offset,
- + commandBufferSize - offset,
- + &linkBytes
- + ));
- +
- + /* Mark context as not dirty. */
- + Context->dirty = gcvFALSE;
- + }
- + else
- + {
- + /***************************************************************
- + ** SWITCHING CONTEXT: 2D only command buffer.
- + */
- +
- + /* Mark 3D as dirty. */
- + Context->dirty3D = gcvTRUE;
- +
- + /* Compute the entry. */
- + if (Command->pipeSelect == gcvPIPE_2D)
- + {
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
- +#endif
- + entryLogical = (gctUINT8_PTR) contextBuffer->logical + pipeBytes;
- + entryBytes = Context->entryOffset3D - pipeBytes;
- + }
- + else
- + {
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
- +#endif
- + entryLogical = (gctUINT8_PTR) contextBuffer->logical;
- + entryBytes = Context->entryOffset3D;
- + }
- +
- + /* Store the current context buffer. */
- + Context->dirtyBuffer = contextBuffer;
- +
- + /* See if we have to switch pipes between the context
- + and command buffers. */
- + if (commandBufferObject->entryPipe == gcvPIPE_2D)
- + {
- + /* Skip pipe switching sequence. */
- + offset = pipeBytes;
- + }
- + else
- + {
- + /* The current hardware and the initial context pipes are
- + different, switch to the correct pipe. */
- + gcmkONERROR(gckHARDWARE_PipeSelect(
- + Command->kernel->hardware,
- + commandBufferLogical,
- + commandBufferObject->entryPipe,
- + &pipeBytes
- + ));
- +
- + /* Do not skip pipe switching sequence. */
- + offset = 0;
- + }
- +
- + /* 3D is not used, generate a LINK from the end of 2D part of
- + the context buffer to the command buffer. */
- + gcmkONERROR(gckHARDWARE_Link(
- + hardware,
- + contextBuffer->link2D,
- + commandBufferLogical + offset,
- + commandBufferSize - offset,
- + &linkBytes
- + ));
- + }
- + }
- +
- + /* Not using 2D. */
- + else
- + {
- + /* Mark 2D as dirty. */
- + Context->dirty2D = gcvTRUE;
- +
- + /* Store the current context buffer. */
- + Context->dirtyBuffer = contextBuffer;
- +
- + if (Context->dirty || commandBufferObject->using3D)
- + {
- + /***************************************************************
- + ** SWITCHING CONTEXT: 3D only command buffer.
- + */
- +
- + /* Reset 3D dirty flag. */
- + Context->dirty3D = gcvFALSE;
- +
- + /* Determine context buffer entry offset. */
- + offset = (Command->pipeSelect == gcvPIPE_3D)
- +
- + /* Skip pipe switching sequence. */
- + ? Context->entryOffset3D + pipeBytes
- +
- + /* Do not skip pipe switching sequence. */
- + : Context->entryOffset3D;
- +
- + /* Compute the entry. */
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + entryPhysical = (gctUINT8_PTR) contextBuffer->physical + offset;
- +#endif
- + entryLogical = (gctUINT8_PTR) contextBuffer->logical + offset;
- + entryBytes = Context->bufferSize - offset;
- +
- + /* See if we have to switch pipes between the context
- + and command buffers. */
- + if (commandBufferObject->entryPipe == gcvPIPE_3D)
- + {
- + /* Skip pipe switching sequence. */
- + offset = pipeBytes;
- + }
- + else
- + {
- + /* The current hardware and the initial context pipes are
- + different, switch to the correct pipe. */
- + gcmkONERROR(gckHARDWARE_PipeSelect(
- + Command->kernel->hardware,
- + commandBufferLogical,
- + commandBufferObject->entryPipe,
- + &pipeBytes
- + ));
- +
- + /* Do not skip pipe switching sequence. */
- + offset = 0;
- + }
- +
- + /* Generate a LINK from the context buffer to
- + the command buffer. */
- + gcmkONERROR(gckHARDWARE_Link(
- + hardware,
- + contextBuffer->link3D,
- + commandBufferLogical + offset,
- + commandBufferSize - offset,
- + &linkBytes
- + ));
- + }
- + else
- + {
- + /***************************************************************
- + ** SWITCHING CONTEXT: "XD" command buffer - neither 2D nor 3D.
- + */
- +
- + /* Mark 3D as dirty. */
- + Context->dirty3D = gcvTRUE;
- +
- + /* Compute the entry. */
- + if (Command->pipeSelect == gcvPIPE_3D)
- + {
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + entryPhysical
- + = (gctUINT8_PTR) contextBuffer->physical
- + + Context->entryOffsetXDFrom3D;
- +#endif
- + entryLogical
- + = (gctUINT8_PTR) contextBuffer->logical
- + + Context->entryOffsetXDFrom3D;
- +
- + entryBytes
- + = Context->bufferSize
- + - Context->entryOffsetXDFrom3D;
- + }
- + else
- + {
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + entryPhysical
- + = (gctUINT8_PTR) contextBuffer->physical
- + + Context->entryOffsetXDFrom2D;
- +#endif
- + entryLogical
- + = (gctUINT8_PTR) contextBuffer->logical
- + + Context->entryOffsetXDFrom2D;
- +
- + entryBytes
- + = Context->totalSize
- + - Context->entryOffsetXDFrom2D;
- + }
- +
- + /* See if we have to switch pipes between the context
- + and command buffers. */
- + if (commandBufferObject->entryPipe == gcvPIPE_3D)
- + {
- + /* Skip pipe switching sequence. */
- + offset = pipeBytes;
- + }
- + else
- + {
- + /* The current hardware and the initial context pipes are
- + different, switch to the correct pipe. */
- + gcmkONERROR(gckHARDWARE_PipeSelect(
- + Command->kernel->hardware,
- + commandBufferLogical,
- + commandBufferObject->entryPipe,
- + &pipeBytes
- + ));
- +
- + /* Do not skip pipe switching sequence. */
- + offset = 0;
- + }
- +
- + /* Generate a LINK from the context buffer to
- + the command buffer. */
- + gcmkONERROR(gckHARDWARE_Link(
- + hardware,
- + contextBuffer->link3D,
- + commandBufferLogical + offset,
- + commandBufferSize - offset,
- + &linkBytes
- + ));
- + }
- + }
- +
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + /* Flush the context buffer cache. */
- + gcmkONERROR(gckOS_CacheClean(
- + Command->os,
- + Command->kernelProcessID,
- + gcvNULL,
- + entryPhysical,
- + entryLogical,
- + entryBytes
- + ));
- +#endif
- +
- + /* Update the current context. */
- + Command->currContext = Context;
- +
- +#if gcdDUMP_COMMAND
- + contextDumpLogical = entryLogical;
- + contextDumpBytes = entryBytes;
- +#endif
- + }
- +
- + /* Same context. */
- + else
- + {
- + /* Determine context entry and exit points. */
- + if (commandBufferObject->using2D && Context->dirty2D)
- + {
- + /* Reset 2D dirty flag. */
- + Context->dirty2D = gcvFALSE;
- +
- + /* Get the "dirty" context buffer. */
- + contextBuffer = Context->dirtyBuffer;
- +
- + if (commandBufferObject->using3D && Context->dirty3D)
- + {
- + /* Reset 3D dirty flag. */
- + Context->dirty3D = gcvFALSE;
- +
- + /* Compute the entry. */
- + if (Command->pipeSelect == gcvPIPE_2D)
- + {
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
- +#endif
- + entryLogical = (gctUINT8_PTR) contextBuffer->logical + pipeBytes;
- + entryBytes = Context->bufferSize - pipeBytes;
- + }
- + else
- + {
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
- +#endif
- + entryLogical = (gctUINT8_PTR) contextBuffer->logical;
- + entryBytes = Context->bufferSize;
- + }
- +
- + /* See if we have to switch pipes between the context
- + and command buffers. */
- + if (commandBufferObject->entryPipe == gcvPIPE_3D)
- + {
- + /* Skip pipe switching sequence. */
- + offset = pipeBytes;
- + }
- + else
- + {
- + /* The current hardware and the initial context pipes are
- + different, switch to the correct pipe. */
- + gcmkONERROR(gckHARDWARE_PipeSelect(
- + Command->kernel->hardware,
- + commandBufferLogical,
- + commandBufferObject->entryPipe,
- + &pipeBytes
- + ));
- +
- + /* Do not skip pipe switching sequence. */
- + offset = 0;
- + }
- +
- + /* Ensure the NOP between 2D and 3D is in place so that the
- + execution falls through from 2D to 3D. */
- + gcmkONERROR(gckHARDWARE_Nop(
- + hardware,
- + contextBuffer->link2D,
- + &nopBytes
- + ));
- +
- + /* Generate a LINK from the context buffer to
- + the command buffer. */
- + gcmkONERROR(gckHARDWARE_Link(
- + hardware,
- + contextBuffer->link3D,
- + commandBufferLogical + offset,
- + commandBufferSize - offset,
- + &linkBytes
- + ));
- + }
- + else
- + {
- + /* Compute the entry. */
- + if (Command->pipeSelect == gcvPIPE_2D)
- + {
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
- +#endif
- + entryLogical = (gctUINT8_PTR) contextBuffer->logical + pipeBytes;
- + entryBytes = Context->entryOffset3D - pipeBytes;
- + }
- + else
- + {
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
- +#endif
- + entryLogical = (gctUINT8_PTR) contextBuffer->logical;
- + entryBytes = Context->entryOffset3D;
- + }
- +
- + /* See if we have to switch pipes between the context
- + and command buffers. */
- + if (commandBufferObject->entryPipe == gcvPIPE_2D)
- + {
- + /* Skip pipe switching sequence. */
- + offset = pipeBytes;
- + }
- + else
- + {
- + /* The current hardware and the initial context pipes are
- + different, switch to the correct pipe. */
- + gcmkONERROR(gckHARDWARE_PipeSelect(
- + Command->kernel->hardware,
- + commandBufferLogical,
- + commandBufferObject->entryPipe,
- + &pipeBytes
- + ));
- +
- + /* Do not skip pipe switching sequence. */
- + offset = 0;
- + }
- +
- + /* 3D is not used, generate a LINK from the end of 2D part of
- + the context buffer to the command buffer. */
- + gcmkONERROR(gckHARDWARE_Link(
- + hardware,
- + contextBuffer->link2D,
- + commandBufferLogical + offset,
- + commandBufferSize - offset,
- + &linkBytes
- + ));
- + }
- + }
- + else
- + {
- + if (commandBufferObject->using3D && Context->dirty3D)
- + {
- + /* Reset 3D dirty flag. */
- + Context->dirty3D = gcvFALSE;
- +
- + /* Get the "dirty" context buffer. */
- + contextBuffer = Context->dirtyBuffer;
- +
- + /* Determine context buffer entry offset. */
- + offset = (Command->pipeSelect == gcvPIPE_3D)
- +
- + /* Skip pipe switching sequence. */
- + ? Context->entryOffset3D + pipeBytes
- +
- + /* Do not skip pipe switching sequence. */
- + : Context->entryOffset3D;
- +
- + /* Compute the entry. */
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + entryPhysical = (gctUINT8_PTR) contextBuffer->physical + offset;
- +#endif
- + entryLogical = (gctUINT8_PTR) contextBuffer->logical + offset;
- + entryBytes = Context->bufferSize - offset;
- +
- + /* See if we have to switch pipes between the context
- + and command buffers. */
- + if (commandBufferObject->entryPipe == gcvPIPE_3D)
- + {
- + /* Skip pipe switching sequence. */
- + offset = pipeBytes;
- + }
- + else
- + {
- + /* The current hardware and the initial context pipes are
- + different, switch to the correct pipe. */
- + gcmkONERROR(gckHARDWARE_PipeSelect(
- + Command->kernel->hardware,
- + commandBufferLogical,
- + commandBufferObject->entryPipe,
- + &pipeBytes
- + ));
- +
- + /* Do not skip pipe switching sequence. */
- + offset = 0;
- + }
- +
- + /* Generate a LINK from the context buffer to
- + the command buffer. */
- + gcmkONERROR(gckHARDWARE_Link(
- + hardware,
- + contextBuffer->link3D,
- + commandBufferLogical + offset,
- + commandBufferSize - offset,
- + &linkBytes
- + ));
- + }
- + else
- + {
- + /* See if we have to switch pipes for the command buffer. */
- + if (commandBufferObject->entryPipe == Command->pipeSelect)
- + {
- + /* Skip pipe switching sequence. */
- + offset = pipeBytes;
- + }
- + else
- + {
- + /* The current hardware and the entry command buffer pipes
- + ** are different, switch to the correct pipe. */
- + gcmkONERROR(gckHARDWARE_PipeSelect(
- + Command->kernel->hardware,
- + commandBufferLogical,
- + commandBufferObject->entryPipe,
- + &pipeBytes
- + ));
- +
- + /* Do not skip pipe switching sequence. */
- + offset = 0;
- + }
- +
- + /* Compute the entry. */
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + entryPhysical = (gctUINT8_PTR) commandBufferPhysical + offset;
- +#endif
- + entryLogical = commandBufferLogical + offset;
- + entryBytes = commandBufferSize - offset;
- + }
- + }
- + }
- +
- +#if gcdDUMP_COMMAND
- + bufferDumpLogical = commandBufferLogical + offset;
- + bufferDumpBytes = commandBufferSize - offset;
- +#endif
- +
- +#if gcdSECURE_USER
- + /* Process user hints. */
- + gcmkONERROR(_ProcessHints(Command, ProcessID, commandBufferObject));
- +#endif
- +
- + /* Determine the location to jump to for the command buffer being
- + ** scheduled. */
- + if (Command->newQueue)
- + {
- + /* New command queue, jump to the beginning of it. */
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + exitPhysical = Command->physical;
- +#endif
- + exitLogical = Command->logical;
- + exitBytes = Command->offset + waitLinkBytes;
- + }
- + else
- + {
- + /* Still within the preexisting command queue, jump to the new
- + WAIT/LINK command sequence. */
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + exitPhysical = waitLinkPhysical;
- +#endif
- + exitLogical = waitLinkLogical;
- + exitBytes = waitLinkBytes;
- + }
- +
- + /* Add a new WAIT/LINK command sequence. When the command buffer which is
- + currently being scheduled is fully executed by the GPU, the FE will
- + jump to this WAIT/LINK sequence. */
- + gcmkONERROR(gckHARDWARE_WaitLink(
- + hardware,
- + waitLinkLogical,
- + offset,
- + &waitLinkBytes,
- + &waitOffset,
- + &waitSize
- + ));
- +
- + /* Compute the location if WAIT command. */
- + waitPhysical = (gctUINT8_PTR) waitLinkPhysical + waitOffset;
- + waitLogical = (gctUINT8_PTR) waitLinkLogical + waitOffset;
- +
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + /* Flush the command queue cache. */
- + gcmkONERROR(gckOS_CacheClean(
- + Command->os,
- + Command->kernelProcessID,
- + gcvNULL,
- + exitPhysical,
- + exitLogical,
- + exitBytes
- + ));
- +#endif
- +
- + /* Determine the location of the LINK command in the command buffer. */
- + commandBufferLink
- + = (gctUINT8_PTR) gcmUINT64_TO_PTR(commandBufferObject->logical)
- + + commandBufferObject->offset;
- +
- + /* Generate a LINK from the end of the command buffer being scheduled
- + back to the kernel command queue. */
- + gcmkONERROR(gckHARDWARE_Link(
- + hardware,
- + commandBufferLink,
- + exitLogical,
- + exitBytes,
- + &linkBytes
- + ));
- +
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + /* Flush the command buffer cache. */
- + gcmkONERROR(gckOS_CacheClean(
- + Command->os,
- + ProcessID,
- + gcvNULL,
- + commandBufferPhysical,
- + commandBufferLogical,
- + commandBufferSize
- + ));
- +#endif
- +
- + /* Generate a LINK from the previous WAIT/LINK command sequence to the
- + entry determined above (either the context or the command buffer).
- + This LINK replaces the WAIT instruction from the previous WAIT/LINK
- + pair, therefore we use WAIT metrics for generation of this LINK.
- + This action will execute the entire sequence. */
- + gcmkONERROR(gckHARDWARE_Link(
- + hardware,
- + Command->waitLogical,
- + entryLogical,
- + entryBytes,
- + &Command->waitSize
- + ));
- +
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + /* Flush the cache for the link. */
- + gcmkONERROR(gckOS_CacheClean(
- + Command->os,
- + Command->kernelProcessID,
- + gcvNULL,
- + Command->waitPhysical,
- + Command->waitLogical,
- + Command->waitSize
- + ));
- +#endif
- +
- + gcmkDUMPCOMMAND(
- + Command->os,
- + Command->waitLogical,
- + Command->waitSize,
- + gceDUMP_BUFFER_LINK,
- + gcvFALSE
- + );
- +
- + gcmkDUMPCOMMAND(
- + Command->os,
- + contextDumpLogical,
- + contextDumpBytes,
- + gceDUMP_BUFFER_CONTEXT,
- + gcvFALSE
- + );
- +
- + gcmkDUMPCOMMAND(
- + Command->os,
- + bufferDumpLogical,
- + bufferDumpBytes,
- + gceDUMP_BUFFER_USER,
- + gcvFALSE
- + );
- +
- + gcmkDUMPCOMMAND(
- + Command->os,
- + waitLinkLogical,
- + waitLinkBytes,
- + gceDUMP_BUFFER_WAITLINK,
- + gcvFALSE
- + );
- +
- + /* Update the current pipe. */
- + Command->pipeSelect = commandBufferObject->exitPipe;
- +
- + /* Update command queue offset. */
- + Command->offset += waitLinkBytes;
- + Command->newQueue = gcvFALSE;
- +
- + /* Update address of last WAIT. */
- + Command->waitPhysical = waitPhysical;
- + Command->waitLogical = waitLogical;
- + Command->waitSize = waitSize;
- +
- + /* Update queue tail pointer. */
- + gcmkONERROR(gckHARDWARE_UpdateQueueTail(
- + hardware, Command->logical, Command->offset
- + ));
- +
- +#if gcdDUMP_COMMAND
- + gcmkPRINT("@[kernel.commit]");
- +#endif
- +#endif /* gcdNULL_DRIVER */
- +
- + /* Release the context switching mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
- + contextAcquired = gcvFALSE;
- +
- + /* Release the command queue. */
- + gcmkONERROR(gckCOMMAND_ExitCommit(Command, gcvFALSE));
- + commitEntered = gcvFALSE;
- +
- +#if VIVANTE_PROFILER_CONTEXT
- + if(sequenceAcquired)
- + {
- + gcmkONERROR(gckCOMMAND_Stall(Command, gcvTRUE));
- + if (Command->currContext)
- + {
- + gcmkONERROR(gckHARDWARE_UpdateContextProfile(
- + hardware,
- + Command->currContext));
- + }
- +
- + /* Release the context switching mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContextSeq));
- + sequenceAcquired = gcvFALSE;
- + }
- +#endif
- +
- + /* Loop while there are records in the queue. */
- + while (EventQueue != gcvNULL)
- + {
- + if (needCopy)
- + {
- + /* Point to stack record. */
- + eventRecord = &_eventRecord;
- +
- + /* Copy the data from the client. */
- + gcmkONERROR(gckOS_CopyFromUserData(
- + Command->os, eventRecord, EventQueue, gcmSIZEOF(gcsQUEUE)
- + ));
- + }
- + else
- + {
- + /* Map record into kernel memory. */
- + gcmkONERROR(gckOS_MapUserPointer(Command->os,
- + EventQueue,
- + gcmSIZEOF(gcsQUEUE),
- + &pointer));
- +
- + eventRecord = pointer;
- + }
- +
- + /* Append event record to event queue. */
- + gcmkONERROR(gckEVENT_AddList(
- + Command->kernel->eventObj, &eventRecord->iface, gcvKERNEL_PIXEL, gcvTRUE, gcvFALSE
- + ));
- +
- + /* Next record in the queue. */
- + nextEventRecord = gcmUINT64_TO_PTR(eventRecord->next);
- +
- + if (!needCopy)
- + {
- + /* Unmap record from kernel memory. */
- + gcmkONERROR(gckOS_UnmapUserPointer(
- + Command->os, EventQueue, gcmSIZEOF(gcsQUEUE), (gctPOINTER *) eventRecord
- + ));
- +
- + eventRecord = gcvNULL;
- + }
- +
- + EventQueue = nextEventRecord;
- + }
- +
- + if (Command->kernel->eventObj->queueHead == gcvNULL
- + && Command->kernel->hardware->powerManagement == gcvTRUE
- + )
- + {
- + /* Commit done event by which work thread knows all jobs done. */
- + gcmkVERIFY_OK(
- + gckEVENT_CommitDone(Command->kernel->eventObj, gcvKERNEL_PIXEL));
- + }
- +
- + /* Submit events. */
- + status = gckEVENT_Submit(Command->kernel->eventObj, gcvTRUE, gcvFALSE);
- +
- + if (status == gcvSTATUS_INTERRUPTED)
- + {
- + gcmkTRACE(
- + gcvLEVEL_INFO,
- + "%s(%d): Intterupted in gckEVENT_Submit",
- + __FUNCTION__, __LINE__
- + );
- + status = gcvSTATUS_OK;
- + }
- + else
- + {
- + gcmkONERROR(status);
- + }
- +
- + /* Unmap the command buffer pointer. */
- + if (commandBufferMapped)
- + {
- + gcmkONERROR(gckOS_UnmapUserPointer(
- + Command->os,
- + CommandBuffer,
- + gcmSIZEOF(struct _gcoCMDBUF),
- + commandBufferObject
- + ));
- +
- + commandBufferMapped = gcvFALSE;
- + }
- +
- + /* Return status. */
- + gcmkFOOTER();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if ((eventRecord != gcvNULL) && !needCopy)
- + {
- + /* Roll back. */
- + gcmkVERIFY_OK(gckOS_UnmapUserPointer(
- + Command->os,
- + EventQueue,
- + gcmSIZEOF(gcsQUEUE),
- + (gctPOINTER *) eventRecord
- + ));
- + }
- +
- + if (contextAcquired)
- + {
- + /* Release the context switching mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
- + }
- +
- + if (commitEntered)
- + {
- + /* Release the command queue mutex. */
- + gcmkVERIFY_OK(gckCOMMAND_ExitCommit(Command, gcvFALSE));
- + }
- +
- +#if VIVANTE_PROFILER_CONTEXT
- + if (sequenceAcquired)
- + {
- + /* Release the context sequence mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContextSeq));
- + }
- +#endif
- +
- + /* Unmap the command buffer pointer. */
- + if (commandBufferMapped)
- + {
- + gcmkVERIFY_OK(gckOS_UnmapUserPointer(
- + Command->os,
- + CommandBuffer,
- + gcmSIZEOF(struct _gcoCMDBUF),
- + commandBufferObject
- + ));
- + }
- +
- + /* Return status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckCOMMAND_Reserve
- +**
- +** Reserve space in the command queue. Also acquire the command queue mutex.
- +**
- +** INPUT:
- +**
- +** gckCOMMAND Command
- +** Pointer to an gckCOMMAND object.
- +**
- +** gctSIZE_T RequestedBytes
- +** Number of bytes previously reserved.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * Buffer
- +** Pointer to a variable that will receive the address of the reserved
- +** space.
- +**
- +** gctSIZE_T * BufferSize
- +** Pointer to a variable that will receive the number of bytes
- +** available in the command queue.
- +*/
- +gceSTATUS
- +gckCOMMAND_Reserve(
- + IN gckCOMMAND Command,
- + IN gctSIZE_T RequestedBytes,
- + OUT gctPOINTER * Buffer,
- + OUT gctSIZE_T * BufferSize
- + )
- +{
- + gceSTATUS status;
- + gctSIZE_T bytes;
- + gctSIZE_T requiredBytes;
- + gctUINT32 requestedAligned;
- +
- + gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + /* Compute aligned number of reuested bytes. */
- + requestedAligned = gcmALIGN(RequestedBytes, Command->alignment);
- +
- + /* Another WAIT/LINK command sequence will have to be appended after
- + the requested area being reserved. Compute the number of bytes
- + required for WAIT/LINK at the location after the reserved area. */
- + gcmkONERROR(gckHARDWARE_WaitLink(
- + Command->kernel->hardware,
- + gcvNULL,
- + Command->offset + requestedAligned,
- + &requiredBytes,
- + gcvNULL,
- + gcvNULL
- + ));
- +
- + /* Compute total number of bytes required. */
- + requiredBytes += requestedAligned;
- +
- + /* Compute number of bytes available in command queue. */
- + bytes = Command->pageSize - Command->offset;
- +
- + /* Is there enough space in the current command queue? */
- + if (bytes < requiredBytes)
- + {
- + /* Create a new command queue. */
- + gcmkONERROR(_NewQueue(Command));
- +
- + /* Recompute the number of bytes in the new kernel command queue. */
- + bytes = Command->pageSize - Command->offset;
- +
- + /* Still not enough space? */
- + if (bytes < requiredBytes)
- + {
- + /* Rare case, not enough room in command queue. */
- + gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
- + }
- + }
- +
- + /* Return pointer to empty slot command queue. */
- + *Buffer = (gctUINT8 *) Command->logical + Command->offset;
- +
- + /* Return number of bytes left in command queue. */
- + *BufferSize = bytes;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Buffer=0x%x *BufferSize=%lu", *Buffer, *BufferSize);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckCOMMAND_Execute
- +**
- +** Execute a previously reserved command queue by appending a WAIT/LINK command
- +** sequence after it and modifying the last WAIT into a LINK command. The
- +** command FIFO mutex will be released whether this function succeeds or not.
- +**
- +** INPUT:
- +**
- +** gckCOMMAND Command
- +** Pointer to an gckCOMMAND object.
- +**
- +** gctSIZE_T RequestedBytes
- +** Number of bytes previously reserved.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckCOMMAND_Execute(
- + IN gckCOMMAND Command,
- + IN gctSIZE_T RequestedBytes
- + )
- +{
- + gceSTATUS status;
- +
- + gctPHYS_ADDR waitLinkPhysical;
- + gctUINT8_PTR waitLinkLogical;
- + gctUINT32 waitLinkOffset;
- + gctSIZE_T waitLinkBytes;
- +
- + gctPHYS_ADDR waitPhysical;
- + gctPOINTER waitLogical;
- + gctUINT32 waitOffset;
- + gctSIZE_T waitBytes;
- +
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + gctPHYS_ADDR execPhysical;
- +#endif
- + gctPOINTER execLogical;
- + gctSIZE_T execBytes;
- +
- + gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + /* Compute offset for WAIT/LINK. */
- + waitLinkOffset = Command->offset + RequestedBytes;
- +
- + /* Compute number of bytes left in command queue. */
- + waitLinkBytes = Command->pageSize - waitLinkOffset;
- +
- + /* Compute the location if WAIT/LINK command sequence. */
- + waitLinkPhysical = (gctUINT8_PTR) Command->physical + waitLinkOffset;
- + waitLinkLogical = (gctUINT8_PTR) Command->logical + waitLinkOffset;
- +
- + /* Append WAIT/LINK in command queue. */
- + gcmkONERROR(gckHARDWARE_WaitLink(
- + Command->kernel->hardware,
- + waitLinkLogical,
- + waitLinkOffset,
- + &waitLinkBytes,
- + &waitOffset,
- + &waitBytes
- + ));
- +
- + /* Compute the location if WAIT command. */
- + waitPhysical = (gctUINT8_PTR) waitLinkPhysical + waitOffset;
- + waitLogical = waitLinkLogical + waitOffset;
- +
- + /* Determine the location to jump to for the command buffer being
- + ** scheduled. */
- + if (Command->newQueue)
- + {
- + /* New command queue, jump to the beginning of it. */
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + execPhysical = Command->physical;
- +#endif
- + execLogical = Command->logical;
- + execBytes = waitLinkOffset + waitLinkBytes;
- + }
- + else
- + {
- + /* Still within the preexisting command queue, jump directly to the
- + reserved area. */
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + execPhysical = (gctUINT8 *) Command->physical + Command->offset;
- +#endif
- + execLogical = (gctUINT8 *) Command->logical + Command->offset;
- + execBytes = RequestedBytes + waitLinkBytes;
- + }
- +
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + /* Flush the cache. */
- + gcmkONERROR(gckOS_CacheClean(
- + Command->os,
- + Command->kernelProcessID,
- + gcvNULL,
- + execPhysical,
- + execLogical,
- + execBytes
- + ));
- +#endif
- +
- + /* Convert the last WAIT into a LINK. */
- + gcmkONERROR(gckHARDWARE_Link(
- + Command->kernel->hardware,
- + Command->waitLogical,
- + execLogical,
- + execBytes,
- + &Command->waitSize
- + ));
- +
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + /* Flush the cache. */
- + gcmkONERROR(gckOS_CacheClean(
- + Command->os,
- + Command->kernelProcessID,
- + gcvNULL,
- + Command->waitPhysical,
- + Command->waitLogical,
- + Command->waitSize
- + ));
- +#endif
- +
- + gcmkDUMPCOMMAND(
- + Command->os,
- + Command->waitLogical,
- + Command->waitSize,
- + gceDUMP_BUFFER_LINK,
- + gcvFALSE
- + );
- +
- + gcmkDUMPCOMMAND(
- + Command->os,
- + execLogical,
- + execBytes,
- + gceDUMP_BUFFER_KERNEL,
- + gcvFALSE
- + );
- +
- + /* Update the pointer to the last WAIT. */
- + Command->waitPhysical = waitPhysical;
- + Command->waitLogical = waitLogical;
- + Command->waitSize = waitBytes;
- +
- + /* Update the command queue. */
- + Command->offset += RequestedBytes + waitLinkBytes;
- + Command->newQueue = gcvFALSE;
- +
- + /* Update queue tail pointer. */
- + gcmkONERROR(gckHARDWARE_UpdateQueueTail(
- + Command->kernel->hardware, Command->logical, Command->offset
- + ));
- +
- +#if gcdDUMP_COMMAND
- + gcmkPRINT("@[kernel.execute]");
- +#endif
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckCOMMAND_Stall
- +**
- +** The calling thread will be suspended until the command queue has been
- +** completed.
- +**
- +** INPUT:
- +**
- +** gckCOMMAND Command
- +** Pointer to an gckCOMMAND object.
- +**
- +** gctBOOL FromPower
- +** Determines whether the call originates from inside the power
- +** management or not.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckCOMMAND_Stall(
- + IN gckCOMMAND Command,
- + IN gctBOOL FromPower
- + )
- +{
- +#if gcdNULL_DRIVER
- + /* Do nothing with infinite hardware. */
- + return gcvSTATUS_OK;
- +#else
- + gckOS os;
- + gckHARDWARE hardware;
- + gckEVENT eventObject;
- + gceSTATUS status;
- + gctSIGNAL signal = gcvNULL;
- + gctUINT timer = 0;
- +
- + gcmkHEADER_ARG("Command=0x%x", Command);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + /* Extract the gckOS object pointer. */
- + os = Command->os;
- + gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
- +
- + /* Extract the gckHARDWARE object pointer. */
- + hardware = Command->kernel->hardware;
- + gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
- +
- + /* Extract the gckEVENT object pointer. */
- + eventObject = Command->kernel->eventObj;
- + gcmkVERIFY_OBJECT(eventObject, gcvOBJ_EVENT);
- +
- + /* Allocate the signal. */
- + gcmkONERROR(gckOS_CreateSignal(os, gcvTRUE, &signal));
- +
- + /* Append the EVENT command to trigger the signal. */
- + gcmkONERROR(gckEVENT_Signal(eventObject, signal, gcvKERNEL_PIXEL));
- +
- + /* Submit the event queue. */
- + gcmkONERROR(gckEVENT_Submit(eventObject, gcvTRUE, FromPower));
- +
- +#if gcdDUMP_COMMAND
- + gcmkPRINT("@[kernel.stall]");
- +#endif
- +
- + if (status == gcvSTATUS_CHIP_NOT_READY)
- + {
- + /* Error. */
- + goto OnError;
- + }
- +
- + do
- + {
- + /* Wait for the signal. */
- + status = gckOS_WaitSignal(os, signal, gcdGPU_ADVANCETIMER);
- +
- + if (status == gcvSTATUS_TIMEOUT)
- + {
- +#if gcmIS_DEBUG(gcdDEBUG_CODE)
- + gctUINT32 idle;
- +
- + /* Read idle register. */
- + gcmkVERIFY_OK(gckHARDWARE_GetIdle(
- + hardware, gcvFALSE, &idle
- + ));
- +
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): idle=%08x",
- + __FUNCTION__, __LINE__, idle
- + );
- +
- + gcmkONERROR(gckOS_MemoryBarrier(os, gcvNULL));
- +
- +#ifdef __QNXNTO__
- + gctUINT32 reg_cmdbuf_fetch;
- + gctUINT32 reg_intr;
- +
- + gcmkVERIFY_OK(gckOS_ReadRegisterEx(
- + Command->kernel->hardware->os, Command->kernel->core, 0x0664, ®_cmdbuf_fetch
- + ));
- +
- + if (idle == 0x7FFFFFFE)
- + {
- + /*
- + * GPU is idle so there should not be pending interrupts.
- + * Just double check.
- + *
- + * Note that reading interrupt register clears it.
- + * That's why we don't read it in all cases.
- + */
- + gcmkVERIFY_OK(gckOS_ReadRegisterEx(
- + Command->kernel->hardware->os, Command->kernel->core, 0x10, ®_intr
- + ));
- +
- + slogf(
- + _SLOG_SETCODE(1, 0),
- + _SLOG_CRITICAL,
- + "GALcore: Stall timeout (idle = 0x%X, command buffer fetch = 0x%X, interrupt = 0x%X)",
- + idle, reg_cmdbuf_fetch, reg_intr
- + );
- + }
- + else
- + {
- + slogf(
- + _SLOG_SETCODE(1, 0),
- + _SLOG_CRITICAL,
- + "GALcore: Stall timeout (idle = 0x%X, command buffer fetch = 0x%X)",
- + idle, reg_cmdbuf_fetch
- + );
- + }
- +#endif
- +#endif
- + /* Advance timer. */
- + timer += gcdGPU_ADVANCETIMER;
- + }
- + else if (status == gcvSTATUS_INTERRUPTED)
- + {
- + gcmkONERROR(gcvSTATUS_INTERRUPTED);
- + }
- +
- + }
- + while (gcmIS_ERROR(status)
- +#if gcdGPU_TIMEOUT
- + && (timer < Command->kernel->timeOut)
- +#endif
- + );
- +
- + /* Bail out on timeout. */
- + if (gcmIS_ERROR(status))
- + {
- + /* Broadcast the stuck GPU. */
- + gcmkONERROR(gckOS_Broadcast(
- + os, hardware, gcvBROADCAST_GPU_STUCK
- + ));
- + }
- +
- + /* Delete the signal. */
- + gcmkVERIFY_OK(gckOS_DestroySignal(os, signal));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (signal != gcvNULL)
- + {
- + /* Free the signal. */
- + gcmkVERIFY_OK(gckOS_DestroySignal(os, signal));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +#endif
- +}
- +
- +/*******************************************************************************
- +**
- +** gckCOMMAND_Attach
- +**
- +** Attach user process.
- +**
- +** INPUT:
- +**
- +** gckCOMMAND Command
- +** Pointer to a gckCOMMAND object.
- +**
- +** gctUINT32 ProcessID
- +** Current process ID.
- +**
- +** OUTPUT:
- +**
- +** gckCONTEXT * Context
- +** Pointer to a variable that will receive a pointer to a new
- +** gckCONTEXT object.
- +**
- +** gctSIZE_T * StateCount
- +** Pointer to a variable that will receive the number of states
- +** in the context buffer.
- +*/
- +gceSTATUS
- +gckCOMMAND_Attach(
- + IN gckCOMMAND Command,
- + OUT gckCONTEXT * Context,
- + OUT gctSIZE_T * StateCount,
- + IN gctUINT32 ProcessID
- + )
- +{
- + gceSTATUS status;
- + gctBOOL acquired = gcvFALSE;
- +
- + gcmkHEADER_ARG("Command=0x%x", Command);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + /* Acquire the context switching mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(
- + Command->os, Command->mutexContext, gcvINFINITE
- + ));
- + acquired = gcvTRUE;
- +
- + /* Construct a gckCONTEXT object. */
- + gcmkONERROR(gckCONTEXT_Construct(
- + Command->os,
- + Command->kernel->hardware,
- + ProcessID,
- + Context
- + ));
- +
- + /* Return the number of states in the context. */
- + * StateCount = (* Context)->stateCount;
- +
- + /* Release the context switching mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
- + acquired = gcvFALSE;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Context=0x%x", *Context);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Release mutex. */
- + if (acquired)
- + {
- + /* Release the context switching mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
- + acquired = gcvFALSE;
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckCOMMAND_Detach
- +**
- +** Detach user process.
- +**
- +** INPUT:
- +**
- +** gckCOMMAND Command
- +** Pointer to a gckCOMMAND object.
- +**
- +** gckCONTEXT Context
- +** Pointer to a gckCONTEXT object to be destroyed.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckCOMMAND_Detach(
- + IN gckCOMMAND Command,
- + IN gckCONTEXT Context
- + )
- +{
- + gceSTATUS status;
- + gctBOOL acquired = gcvFALSE;
- +
- + gcmkHEADER_ARG("Command=0x%x Context=0x%x", Command, Context);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + /* Acquire the context switching mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(
- + Command->os, Command->mutexContext, gcvINFINITE
- + ));
- + acquired = gcvTRUE;
- +
- + /* Construct a gckCONTEXT object. */
- + gcmkONERROR(gckCONTEXT_Destroy(Context));
- +
- + if (Command->currContext == Context)
- + {
- + /* Detach from gckCOMMAND object if the destoryed context is current context. */
- + Command->currContext = gcvNULL;
- + }
- +
- + /* Release the context switching mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
- + acquired = gcvFALSE;
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Release mutex. */
- + if (acquired)
- + {
- + /* Release the context switching mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
- + acquired = gcvFALSE;
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +#if gcdVIRTUAL_COMMAND_BUFFER
- +/*******************************************************************************
- +**
- +** gckCOMMAND_DumpExecutingBuffer
- +**
- +** Dump the command buffer which GPU is executing.
- +**
- +** INPUT:
- +**
- +** gckCOMMAND Command
- +** Pointer to a gckCOMMAND object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckCOMMAND_DumpExecutingBuffer(
- + IN gckCOMMAND Command
- + )
- +{
- + gceSTATUS status;
- + gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
- + gctUINT32 gpuAddress;
- + gctSIZE_T pageCount;
- + gctPOINTER entry;
- + gckOS os = Command->os;
- + gckKERNEL kernel = Command->kernel;
- +#if gcdLINK_QUEUE_SIZE
- + gctINT pid;
- + gctINT i, rear;
- + gctUINT32 start, end;
- + gctUINT32 dumpFront, dumpRear;
- + gckLINKQUEUE queue = &kernel->hardware->linkQueue;
- + gckLINKQUEUE queueMirror;
- + gctUINT32 bytes;
- + gckLINKDATA linkData;
- +#endif
- +
- + gcmkPRINT("**************************\n");
- + gcmkPRINT("**** COMMAND BUF DUMP ****\n");
- + gcmkPRINT("**************************\n");
- +
- + gcmkVERIFY_OK(gckOS_ReadRegisterEx(os, kernel->core, 0x664, &gpuAddress));
- +
- + gcmkPRINT("DMA Address 0x%08X", gpuAddress);
- +
- +#if gcdLINK_QUEUE_SIZE
- + /* Duplicate queue because it will be changed.*/
- + gcmkONERROR(gckOS_AllocateMemory(os,
- + sizeof(struct _gckLINKQUEUE),
- + (gctPOINTER *)&queueMirror));
- +
- + gcmkONERROR(gckOS_MemCopy(queueMirror,
- + queue,
- + sizeof(struct _gckLINKQUEUE)));
- +
- + /* If kernel command buffer link to a context buffer, then link to a user command
- + ** buffer, the second link will be in queue first, so we must fix this.
- + ** In Queue: C1 U1 U2 C2 U3 U4 U5 C3
- + ** Real: C1 X1 U1 C2 U2 U3 U4 C3 U5
- + ** Command buffer X1 which is after C1 is out of queue, so C1 is meaningless.
- + */
- + for (i = 0; i < gcdLINK_QUEUE_SIZE; i++)
- + {
- + gckLINKQUEUE_GetData(queueMirror, i, &linkData);
- +
- + status = gckKERNEL_QueryGPUAddress(kernel, linkData->start, &buffer);
- +
- + if (gcmIS_ERROR(status))
- + {
- + /* Can't find it in virtual command buffer list, ignore it. */
- + continue;
- + }
- +
- + if (buffer->kernelLogical)
- + {
- + /* It is a context buffer. */
- + if (i == 0)
- + {
- + /* The real command buffer is out, so clear this slot. */
- + linkData->start = 0;
- + linkData->end = 0;
- + linkData->pid = 0;
- + }
- + else
- + {
- + /* switch context buffer and command buffer. */
- + struct _gckLINKDATA tmp = *linkData;
- + gckLINKDATA linkDataPrevious;
- +
- + gckLINKQUEUE_GetData(queueMirror, i - 1, &linkDataPrevious);
- + *linkData = *linkDataPrevious;
- + *linkDataPrevious = tmp;
- + }
- + }
- + }
- +
- + /* Clear search result. */
- + dumpFront = dumpRear = gcvINFINITE;
- +
- + gcmkPRINT("Link Stack:");
- +
- + /* Search stuck address in link queue from rear. */
- + rear = gcdLINK_QUEUE_SIZE - 1;
- + for (i = 0; i < gcdLINK_QUEUE_SIZE; i++)
- + {
- + gckLINKQUEUE_GetData(queueMirror, rear, &linkData);
- +
- + start = linkData->start;
- + end = linkData->end;
- + pid = linkData->pid;
- +
- + if (gpuAddress >= start && gpuAddress < end)
- + {
- + /* Find latest matched command buffer. */
- + gcmkPRINT(" %d, [%08X - %08X]", pid, start, end);
- +
- + /* Initiliaze dump information. */
- + dumpFront = dumpRear = rear;
- + }
- +
- + /* Advance to previous one. */
- + rear--;
- +
- + if (dumpFront != gcvINFINITE)
- + {
- + break;
- + }
- + }
- +
- + if (dumpFront == gcvINFINITE)
- + {
- + /* Can't find matched record in link queue, dump kernel command buffer. */
- + _DumpKernelCommandBuffer(Command);
- +
- + /* Free local copy. */
- + gcmkOS_SAFE_FREE(os, queueMirror);
- + return gcvSTATUS_OK;
- + }
- +
- + /* Search the last context buffer linked. */
- + while (rear >= 0)
- + {
- + gckLINKQUEUE_GetData(queueMirror, rear, &linkData);
- +
- + gcmkPRINT(" %d, [%08X - %08X]",
- + linkData->pid,
- + linkData->start,
- + linkData->end);
- +
- + status = gckKERNEL_QueryGPUAddress(kernel, linkData->start, &buffer);
- +
- + if (gcmIS_SUCCESS(status) && buffer->kernelLogical)
- + {
- + /* Find a context buffer. */
- + dumpFront = rear;
- + break;
- + }
- +
- + rear--;
- + }
- +
- + /* Dump from last context buffer to last command buffer where hang happens. */
- + for (i = dumpFront; i <= dumpRear; i++)
- + {
- + gckLINKQUEUE_GetData(queueMirror, i, &linkData);
- +
- + /* Get gpu address of this command buffer. */
- + gpuAddress = linkData->start;
- + bytes = linkData->end - gpuAddress;
- +
- + /* Get the whole buffer. */
- + status = gckKERNEL_QueryGPUAddress(kernel, gpuAddress, &buffer);
- +
- + if (gcmIS_ERROR(status))
- + {
- + gcmkPRINT("Buffer [%08X - %08X] is lost",
- + linkData->start,
- + linkData->end);
- + continue;
- + }
- +
- + /* Get kernel logical for dump. */
- + if (buffer->kernelLogical)
- + {
- + /* Get kernel logical directly if it is a context buffer. */
- + entry = buffer->kernelLogical;
- + gcmkPRINT("Context Buffer:");
- + }
- + else
- + {
- + /* Make it accessiable by kernel if it is a user command buffer. */
- + gcmkVERIFY_OK(
- + gckOS_CreateKernelVirtualMapping(buffer->physical,
- + &pageCount,
- + &entry));
- + gcmkPRINT("User Command Buffer:");
- + }
- +
- + /* Dump from the entry. */
- + _DumpBuffer(entry + (gpuAddress - buffer->gpuAddress), gpuAddress, bytes);
- +
- + /* Release kernel logical address if neccessary. */
- + if (!buffer->kernelLogical)
- + {
- + gcmkVERIFY_OK(gckOS_DestroyKernelVirtualMapping(entry));
- + }
- + }
- +
- + /* Free local copy. */
- + gcmkOS_SAFE_FREE(os, queueMirror);
- + return gcvSTATUS_OK;
- +OnError:
- + return status;
- +#else
- + /* Without link queue information, we don't know the entry of last command
- + ** buffer, just dump the page where GPU stuck. */
- + status = gckKERNEL_QueryGPUAddress(kernel, gpuAddress, &buffer);
- +
- + if (gcmIS_SUCCESS(status))
- + {
- + gcmkVERIFY_OK(
- + gckOS_CreateKernelVirtualMapping(buffer->physical, &pageCount, &entry));
- +
- + if (entry)
- + {
- + gctUINT32 offset = gpuAddress - buffer->gpuAddress;
- + gctPOINTER entryDump = entry;
- +
- + /* Dump one pages. */
- + gctUINT32 bytes = 4096;
- +
- + /* Align to page. */
- + offset &= 0xfffff000;
- +
- + /* Kernel address of page where stall point stay. */
- + entryDump += offset;
- +
- + /* Align to page. */
- + gpuAddress &= 0xfffff000;
- +
- + gcmkPRINT("User Command Buffer:\n");
- + _DumpBuffer(entryDump, gpuAddress, bytes);
- + }
- +
- + gcmkVERIFY_OK(
- + gckOS_DestroyKernelVirtualMapping(entry));
- + }
- + else
- + {
- + _DumpKernelCommandBuffer(Command);
- + }
- +
- + return gcvSTATUS_OK;
- +#endif
- +}
- +#endif
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c 2015-03-08 14:27:37.629684500 -0500
- @@ -0,0 +1,3677 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal_kernel_precomp.h"
- +
- +#if gcdENABLE_VG
- +
- +#include "gc_hal_kernel_hardware_command_vg.h"
- +
- +#define _GC_OBJ_ZONE gcvZONE_COMMAND
- +
- +/******************************************************************************\
- +*********************************** Debugging **********************************
- +\******************************************************************************/
- +
- +#define gcvDISABLE_TIMEOUT 1
- +#define gcvDUMP_COMMAND_BUFFER 0
- +#define gcvDUMP_COMMAND_LINES 0
- +
- +
- +#if gcvDEBUG || defined(EMULATOR) || gcvDISABLE_TIMEOUT
- +# define gcvQUEUE_TIMEOUT ~0
- +#else
- +# define gcvQUEUE_TIMEOUT 10
- +#endif
- +
- +
- +/******************************************************************************\
- +********************************** Definitions *********************************
- +\******************************************************************************/
- +
- +/* Minimum buffer size. */
- +#define gcvMINUMUM_BUFFER \
- + gcmSIZEOF(gcsKERNEL_QUEUE_HEADER) + \
- + gcmSIZEOF(gcsKERNEL_CMDQUEUE) * 2
- +
- +#define gcmDECLARE_INTERRUPT_HANDLER(Block, Number) \
- + static gceSTATUS \
- + _EventHandler_##Block##_##Number( \
- + IN gckVGKERNEL Kernel \
- + )
- +
- +#define gcmDEFINE_INTERRUPT_HANDLER(Block, Number) \
- + gcmDECLARE_INTERRUPT_HANDLER(Block, Number) \
- + { \
- + return _EventHandler_Block( \
- + Kernel, \
- + &Kernel->command->taskTable[gcvBLOCK_##Block], \
- + gcvFALSE \
- + ); \
- + }
- +
- +#define gcmDEFINE_INTERRUPT_HANDLER_ENTRY(Block, Number) \
- + { gcvBLOCK_##Block, _EventHandler_##Block##_##Number }
- +
- +/* Block interrupt handling table entry. */
- +typedef struct _gcsBLOCK_INTERRUPT_HANDLER * gcsBLOCK_INTERRUPT_HANDLER_PTR;
- +typedef struct _gcsBLOCK_INTERRUPT_HANDLER
- +{
- + gceBLOCK block;
- + gctINTERRUPT_HANDLER handler;
- +}
- +gcsBLOCK_INTERRUPT_HANDLER;
- +
- +/* Queue control functions. */
- +typedef struct _gcsQUEUE_UPDATE_CONTROL * gcsQUEUE_UPDATE_CONTROL_PTR;
- +typedef struct _gcsQUEUE_UPDATE_CONTROL
- +{
- + gctOBJECT_HANDLER execute;
- + gctOBJECT_HANDLER update;
- + gctOBJECT_HANDLER lastExecute;
- + gctOBJECT_HANDLER lastUpdate;
- +}
- +gcsQUEUE_UPDATE_CONTROL;
- +
- +
- +/******************************************************************************\
- +********************************* Support Code *********************************
- +\******************************************************************************/
- +static gceSTATUS
- +_FlushMMU(
- + IN gckVGCOMMAND Command
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 oldValue;
- + gckVGHARDWARE hardware = Command->hardware;
- +
- + gcmkONERROR(gckOS_AtomicExchange(Command->os,
- + hardware->pageTableDirty,
- + 0,
- + &oldValue));
- +
- + if (oldValue)
- + {
- + /* Page Table is upated, flush mmu before commit. */
- + gcmkONERROR(gckVGHARDWARE_FlushMMU(hardware));
- + }
- +
- + return gcvSTATUS_OK;
- +OnError:
- + return status;
- +}
- +
- +static gceSTATUS
- +_WaitForIdle(
- + IN gckVGCOMMAND Command,
- + IN gcsKERNEL_QUEUE_HEADER_PTR Queue
- + )
- +{
- + gceSTATUS status = gcvSTATUS_OK;
- + gctUINT32 idle;
- + gctUINT timeout = 0;
- +
- + /* Loop while not idle. */
- + while (Queue->pending)
- + {
- + /* Did we reach the timeout limit? */
- + if (timeout == gcvQUEUE_TIMEOUT)
- + {
- + /* Hardware is probably dead... */
- + return gcvSTATUS_TIMEOUT;
- + }
- +
- + /* Sleep for 100ms. */
- + gcmkERR_BREAK(gckOS_Delay(Command->os, 100));
- +
- + /* Not the first loop? */
- + if (timeout > 0)
- + {
- + /* Read IDLE register. */
- + gcmkVERIFY_OK(gckVGHARDWARE_GetIdle(Command->hardware, &idle));
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_COMMAND,
- + "%s: timeout, IDLE=%08X\n",
- + __FUNCTION__, idle
- + );
- + }
- +
- + /* Increment the timeout counter. */
- + timeout += 1;
- + }
- +
- + /* Return status. */
- + return status;
- +}
- +
- +static gctINT32
- +_GetNextInterrupt(
- + IN gckVGCOMMAND Command,
- + IN gceBLOCK Block
- + )
- +{
- + gctUINT index;
- + gcsBLOCK_TASK_ENTRY_PTR entry;
- + gctINT32 interrupt;
- +
- + /* Get the block entry. */
- + entry = &Command->taskTable[Block];
- +
- + /* Make sure we have initialized interrupts. */
- + gcmkASSERT(entry->interruptCount > 0);
- +
- + /* Decrement the interrupt usage semaphore. */
- + gcmkVERIFY_OK(gckOS_DecrementSemaphore(
- + Command->os, entry->interruptSemaphore
- + ));
- +
- + /* Get the value index. */
- + index = entry->interruptIndex;
- +
- + /* Get the interrupt value. */
- + interrupt = entry->interruptArray[index];
- +
- + /* Must be a valid value. */
- + gcmkASSERT((interrupt >= 0) && (interrupt <= 31));
- +
- + /* Advance the index to the next value. */
- + index += 1;
- +
- + /* Set the new index. */
- + entry->interruptIndex = (index == entry->interruptCount)
- + ? 0
- + : index;
- +
- + /* Return interrupt value. */
- + return interrupt;
- +}
- +
- +
- +/******************************************************************************\
- +***************************** Task Storage Management **************************
- +\******************************************************************************/
- +
- +/* Minimum task buffer size. */
- +#define gcvMIN_TASK_BUFFER \
- +( \
- + gcmSIZEOF(gcsTASK_CONTAINER) + 128 \
- +)
- +
- +/* Free list terminator. */
- +#define gcvFREE_TASK_TERMINATOR \
- +( \
- + (gcsTASK_CONTAINER_PTR) gcmINT2PTR(~0) \
- +)
- +
- +
- +/*----------------------------------------------------------------------------*/
- +/*------------------- Allocated Task Buffer List Management ------------------*/
- +
- +static void
- +_InsertTaskBuffer(
- + IN gcsTASK_CONTAINER_PTR AddAfter,
- + IN gcsTASK_CONTAINER_PTR Buffer
- + )
- +{
- + gcsTASK_CONTAINER_PTR addBefore;
- +
- + /* Cannot add before the first buffer. */
- + gcmkASSERT(AddAfter != gcvNULL);
- +
- + /* Create a shortcut to the next buffer. */
- + addBefore = AddAfter->allocNext;
- +
- + /* Initialize the links. */
- + Buffer->allocPrev = AddAfter;
- + Buffer->allocNext = addBefore;
- +
- + /* Link to the previous buffer. */
- + AddAfter->allocNext = Buffer;
- +
- + /* Link to the next buffer. */
- + if (addBefore != gcvNULL)
- + {
- + addBefore->allocPrev = Buffer;
- + }
- +}
- +
- +static void
- +_RemoveTaskBuffer(
- + IN gcsTASK_CONTAINER_PTR Buffer
- + )
- +{
- + gcsTASK_CONTAINER_PTR prev;
- + gcsTASK_CONTAINER_PTR next;
- +
- + /* Cannot remove the first buffer. */
- + gcmkASSERT(Buffer->allocPrev != gcvNULL);
- +
- + /* Create shortcuts to the previous and next buffers. */
- + prev = Buffer->allocPrev;
- + next = Buffer->allocNext;
- +
- + /* Tail buffer? */
- + if (next == gcvNULL)
- + {
- + /* Remove from the list. */
- + prev->allocNext = gcvNULL;
- + }
- +
- + /* Buffer from the middle. */
- + else
- + {
- + prev->allocNext = next;
- + next->allocPrev = prev;
- + }
- +}
- +
- +
- +/*----------------------------------------------------------------------------*/
- +/*--------------------- Free Task Buffer List Management ---------------------*/
- +
- +static void
- +_AppendToFreeList(
- + IN gckVGCOMMAND Command,
- + IN gcsTASK_CONTAINER_PTR Buffer
- + )
- +{
- + /* Cannot be a part of the free list already. */
- + gcmkASSERT(Buffer->freePrev == gcvNULL);
- + gcmkASSERT(Buffer->freeNext == gcvNULL);
- +
- + /* First buffer to add? */
- + if (Command->taskFreeHead == gcvNULL)
- + {
- + /* Terminate the links. */
- + Buffer->freePrev = gcvFREE_TASK_TERMINATOR;
- + Buffer->freeNext = gcvFREE_TASK_TERMINATOR;
- +
- + /* Initialize the list pointer. */
- + Command->taskFreeHead = Command->taskFreeTail = Buffer;
- + }
- +
- + /* Not the first, add after the tail. */
- + else
- + {
- + /* Initialize the new tail buffer. */
- + Buffer->freePrev = Command->taskFreeTail;
- + Buffer->freeNext = gcvFREE_TASK_TERMINATOR;
- +
- + /* Add after the tail. */
- + Command->taskFreeTail->freeNext = Buffer;
- + Command->taskFreeTail = Buffer;
- + }
- +}
- +
- +static void
- +_RemoveFromFreeList(
- + IN gckVGCOMMAND Command,
- + IN gcsTASK_CONTAINER_PTR Buffer
- + )
- +{
- + /* Has to be a part of the free list. */
- + gcmkASSERT(Buffer->freePrev != gcvNULL);
- + gcmkASSERT(Buffer->freeNext != gcvNULL);
- +
- + /* Head buffer? */
- + if (Buffer->freePrev == gcvFREE_TASK_TERMINATOR)
- + {
- + /* Tail buffer as well? */
- + if (Buffer->freeNext == gcvFREE_TASK_TERMINATOR)
- + {
- + /* Reset the list pointer. */
- + Command->taskFreeHead = Command->taskFreeTail = gcvNULL;
- + }
- +
- + /* No, just the head. */
- + else
- + {
- + /* Update the head. */
- + Command->taskFreeHead = Buffer->freeNext;
- +
- + /* Terminate the next buffer. */
- + Command->taskFreeHead->freePrev = gcvFREE_TASK_TERMINATOR;
- + }
- + }
- +
- + /* Not the head. */
- + else
- + {
- + /* Tail buffer? */
- + if (Buffer->freeNext == gcvFREE_TASK_TERMINATOR)
- + {
- + /* Update the tail. */
- + Command->taskFreeTail = Buffer->freePrev;
- +
- + /* Terminate the previous buffer. */
- + Command->taskFreeTail->freeNext = gcvFREE_TASK_TERMINATOR;
- + }
- +
- + /* A buffer in the middle. */
- + else
- + {
- + /* Remove the buffer from the list. */
- + Buffer->freePrev->freeNext = Buffer->freeNext;
- + Buffer->freeNext->freePrev = Buffer->freePrev;
- + }
- + }
- +
- + /* Reset free list pointers. */
- + Buffer->freePrev = gcvNULL;
- + Buffer->freeNext = gcvNULL;
- +}
- +
- +
- +/*----------------------------------------------------------------------------*/
- +/*-------------------------- Task Buffer Allocation --------------------------*/
- +
- +static void
- +_SplitTaskBuffer(
- + IN gckVGCOMMAND Command,
- + IN gcsTASK_CONTAINER_PTR Buffer,
- + IN gctUINT Size
- + )
- +{
- + /* Determine the size of the new buffer. */
- + gctINT splitBufferSize = Buffer->size - Size;
- + gcmkASSERT(splitBufferSize >= 0);
- +
- + /* Is the split buffer big enough to become a separate buffer? */
- + if (splitBufferSize >= gcvMIN_TASK_BUFFER)
- + {
- + /* Place the new path data. */
- + gcsTASK_CONTAINER_PTR splitBuffer = (gcsTASK_CONTAINER_PTR)
- + (
- + (gctUINT8_PTR) Buffer + Size
- + );
- +
- + /* Set the trimmed buffer size. */
- + Buffer->size = Size;
- +
- + /* Initialize the split buffer. */
- + splitBuffer->referenceCount = 0;
- + splitBuffer->size = splitBufferSize;
- + splitBuffer->freePrev = gcvNULL;
- + splitBuffer->freeNext = gcvNULL;
- +
- + /* Link in. */
- + _InsertTaskBuffer(Buffer, splitBuffer);
- + _AppendToFreeList(Command, splitBuffer);
- + }
- +}
- +
- +static gceSTATUS
- +_AllocateTaskContainer(
- + IN gckVGCOMMAND Command,
- + IN gctUINT Size,
- + OUT gcsTASK_CONTAINER_PTR * Buffer
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Command=0x%x Size=0x%x, Buffer ==0x%x", Command, Size, Buffer);
- +
- + /* Verify arguments. */
- + gcmkVERIFY_ARGUMENT(Buffer != gcvNULL);
- +
- + do
- + {
- + gcsTASK_STORAGE_PTR storage;
- + gcsTASK_CONTAINER_PTR buffer;
- +
- + /* Adjust the size. */
- + Size += gcmSIZEOF(gcsTASK_CONTAINER);
- +
- + /* Adjust the allocation size if not big enough. */
- + if (Size > Command->taskStorageUsable)
- + {
- + Command->taskStorageGranularity
- + = gcmALIGN(Size + gcmSIZEOF(gcsTASK_STORAGE), 1024);
- +
- + Command->taskStorageUsable
- + = Command->taskStorageGranularity - gcmSIZEOF(gcsTASK_STORAGE);
- + }
- +
- + /* Is there a free buffer available? */
- + else if (Command->taskFreeHead != gcvNULL)
- + {
- + /* Set the initial free buffer. */
- + gcsTASK_CONTAINER_PTR buffer = Command->taskFreeHead;
- +
- + do
- + {
- + /* Is the buffer big enough? */
- + if (buffer->size >= Size)
- + {
- + /* Remove the buffer from the free list. */
- + _RemoveFromFreeList(Command, buffer);
- +
- + /* Split the buffer. */
- + _SplitTaskBuffer(Command, buffer, Size);
- +
- + /* Set the result. */
- + * Buffer = buffer;
- +
- + gcmkFOOTER_ARG("*Buffer=0x%x",*Buffer);
- + /* Success. */
- + return gcvSTATUS_OK;
- + }
- +
- + /* Get the next free buffer. */
- + buffer = buffer->freeNext;
- + }
- + while (buffer != gcvFREE_TASK_TERMINATOR);
- + }
- +
- + /* Allocate a container. */
- + gcmkERR_BREAK(gckOS_Allocate(
- + Command->os,
- + Command->taskStorageGranularity,
- + (gctPOINTER *) &storage
- + ));
- +
- + /* Link in the storage buffer. */
- + storage->next = Command->taskStorage;
- + Command->taskStorage = storage;
- +
- + /* Place the task buffer. */
- + buffer = (gcsTASK_CONTAINER_PTR) (storage + 1);
- +
- + /* Determine the size of the buffer. */
- + buffer->size
- + = Command->taskStorageGranularity
- + - gcmSIZEOF(gcsTASK_STORAGE);
- +
- + /* Initialize the task buffer. */
- + buffer->referenceCount = 0;
- + buffer->allocPrev = gcvNULL;
- + buffer->allocNext = gcvNULL;
- + buffer->freePrev = gcvNULL;
- + buffer->freeNext = gcvNULL;
- +
- + /* Split the buffer. */
- + _SplitTaskBuffer(Command, buffer, Size);
- +
- + /* Set the result. */
- + * Buffer = buffer;
- +
- + gcmkFOOTER_ARG("*Buffer=0x%x",*Buffer);
- + /* Success. */
- + return gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + gcmkFOOTER();
- + /* Return status. */
- + return status;
- +}
- +
- +static void
- +_FreeTaskContainer(
- + IN gckVGCOMMAND Command,
- + IN gcsTASK_CONTAINER_PTR Buffer
- + )
- +{
- + gcsTASK_CONTAINER_PTR prev;
- + gcsTASK_CONTAINER_PTR next;
- + gcsTASK_CONTAINER_PTR merged;
- +
- + gctSIZE_T mergedSize;
- +
- + /* Verify arguments. */
- + gcmkASSERT(Buffer != gcvNULL);
- + gcmkASSERT(Buffer->freePrev == gcvNULL);
- + gcmkASSERT(Buffer->freeNext == gcvNULL);
- +
- + /* Get shortcuts to the previous and next path data buffers. */
- + prev = Buffer->allocPrev;
- + next = Buffer->allocNext;
- +
- + /* Is the previous path data buffer already free? */
- + if (prev && prev->freeNext)
- + {
- + /* The previous path data buffer is the one that remains. */
- + merged = prev;
- +
- + /* Is the next path data buffer already free? */
- + if (next && next->freeNext)
- + {
- + /* Merge all three path data buffers into the previous. */
- + mergedSize = prev->size + Buffer->size + next->size;
- +
- + /* Remove the next path data buffer. */
- + _RemoveFromFreeList(Command, next);
- + _RemoveTaskBuffer(next);
- + }
- + else
- + {
- + /* Merge the current path data buffer into the previous. */
- + mergedSize = prev->size + Buffer->size;
- + }
- +
- + /* Delete the current path data buffer. */
- + _RemoveTaskBuffer(Buffer);
- +
- + /* Set new size. */
- + merged->size = mergedSize;
- + }
- + else
- + {
- + /* The current path data buffer is the one that remains. */
- + merged = Buffer;
- +
- + /* Is the next buffer already free? */
- + if (next && next->freeNext)
- + {
- + /* Merge the next into the current. */
- + mergedSize = Buffer->size + next->size;
- +
- + /* Remove the next buffer. */
- + _RemoveFromFreeList(Command, next);
- + _RemoveTaskBuffer(next);
- +
- + /* Set new size. */
- + merged->size = mergedSize;
- + }
- +
- + /* Add the current buffer into the free list. */
- + _AppendToFreeList(Command, merged);
- + }
- +}
- +
- +gceSTATUS
- +_RemoveRecordFromProcesDB(
- + IN gckVGCOMMAND Command,
- + IN gcsTASK_HEADER_PTR Task
- + )
- +{
- + gcsTASK_PTR task = (gcsTASK_PTR)((gctUINT8_PTR)Task - sizeof(gcsTASK));
- + gcsTASK_FREE_VIDEO_MEMORY_PTR freeVideoMemory;
- + gcsTASK_UNLOCK_VIDEO_MEMORY_PTR unlockVideoMemory;
- + gctINT pid;
- + gctUINT32 size;
- +
- + /* Get the total size of all tasks. */
- + size = task->size;
- +
- + gcmkVERIFY_OK(gckOS_GetProcessID((gctUINT32_PTR)&pid));
- +
- + do
- + {
- + switch (Task->id)
- + {
- + case gcvTASK_FREE_VIDEO_MEMORY:
- + freeVideoMemory = (gcsTASK_FREE_VIDEO_MEMORY_PTR)Task;
- +
- + /* Remove record from process db. */
- + gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
- + Command->kernel->kernel,
- + pid,
- + gcvDB_VIDEO_MEMORY,
- + gcmUINT64_TO_PTR(freeVideoMemory->node)));
- +
- + /* Advance to next task. */
- + size -= sizeof(gcsTASK_FREE_VIDEO_MEMORY);
- + Task = (gcsTASK_HEADER_PTR)(freeVideoMemory + 1);
- +
- + break;
- + case gcvTASK_UNLOCK_VIDEO_MEMORY:
- + unlockVideoMemory = (gcsTASK_UNLOCK_VIDEO_MEMORY_PTR)Task;
- +
- + /* Remove record from process db. */
- + gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
- + Command->kernel->kernel,
- + pid,
- + gcvDB_VIDEO_MEMORY_LOCKED,
- + gcmUINT64_TO_PTR(unlockVideoMemory->node)));
- +
- + /* Advance to next task. */
- + size -= sizeof(gcsTASK_UNLOCK_VIDEO_MEMORY);
- + Task = (gcsTASK_HEADER_PTR)(unlockVideoMemory + 1);
- +
- + break;
- + default:
- + /* Skip the whole task. */
- + size = 0;
- + break;
- + }
- + }
- + while(size);
- +
- + return gcvSTATUS_OK;
- +}
- +
- +/******************************************************************************\
- +********************************* Task Scheduling ******************************
- +\******************************************************************************/
- +
- +static gceSTATUS
- +_ScheduleTasks(
- + IN gckVGCOMMAND Command,
- + IN gcsTASK_MASTER_TABLE_PTR TaskTable,
- + IN gctUINT8_PTR PreviousEnd
- + )
- +{
- + gceSTATUS status;
- +
- + do
- + {
- + gctINT block;
- + gcsTASK_CONTAINER_PTR container;
- + gcsTASK_MASTER_ENTRY_PTR userTaskEntry;
- + gcsBLOCK_TASK_ENTRY_PTR kernelTaskEntry;
- + gcsTASK_PTR userTask;
- + gctUINT8_PTR kernelTask;
- + gctINT32 interrupt;
- + gctUINT8_PTR eventCommand;
- +
- + /* Nothing to schedule? */
- + if (TaskTable->size == 0)
- + {
- + status = gcvSTATUS_OK;
- + break;
- + }
- +
- + /* Acquire the mutex. */
- + gcmkERR_BREAK(gckOS_AcquireMutex(
- + Command->os,
- + Command->taskMutex,
- + gcvINFINITE
- + ));
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + "%s(%d)\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + do
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + " number of tasks scheduled = %d\n"
- + " size of event data in bytes = %d\n",
- + TaskTable->count,
- + TaskTable->size
- + );
- +
- + /* Allocate task buffer. */
- + gcmkERR_BREAK(_AllocateTaskContainer(
- + Command,
- + TaskTable->size,
- + &container
- + ));
- +
- + /* Determine the task data pointer. */
- + kernelTask = (gctUINT8_PTR) (container + 1);
- +
- + /* Initialize the reference count. */
- + container->referenceCount = TaskTable->count;
- +
- + /* Process tasks. */
- + for (block = gcvBLOCK_COUNT - 1; block >= 0; block -= 1)
- + {
- + /* Get the current user table entry. */
- + userTaskEntry = &TaskTable->table[block];
- +
- + /* Are there tasks scheduled? */
- + if (userTaskEntry->head == gcvNULL)
- + {
- + /* No, skip to the next block. */
- + continue;
- + }
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + " processing tasks for block %d\n",
- + block
- + );
- +
- + /* Get the current kernel table entry. */
- + kernelTaskEntry = &Command->taskTable[block];
- +
- + /* Are there tasks for the current block scheduled? */
- + if (kernelTaskEntry->container == gcvNULL)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + " first task container for the block added\n",
- + block
- + );
- +
- + /* Nothing yet, set the container buffer pointer. */
- + kernelTaskEntry->container = container;
- + kernelTaskEntry->task = (gcsTASK_HEADER_PTR) kernelTask;
- + }
- +
- + /* Yes, append to the end. */
- + else
- + {
- + kernelTaskEntry->link->cotainer = container;
- + kernelTaskEntry->link->task = (gcsTASK_HEADER_PTR) kernelTask;
- + }
- +
- + /* Set initial task. */
- + userTask = userTaskEntry->head;
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + " copying user tasks over to the kernel\n"
- + );
- +
- + /* Copy tasks. */
- + do
- + {
- + gcsTASK_HEADER_PTR taskHeader = (gcsTASK_HEADER_PTR) (userTask + 1);
- +
- + gcmkVERIFY_OK(_RemoveRecordFromProcesDB(Command, taskHeader));
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + " task ID = %d, size = %d\n",
- + ((gcsTASK_HEADER_PTR) (userTask + 1))->id,
- + userTask->size
- + );
- +
- +#ifdef __QNXNTO__
- + if (taskHeader->id == gcvTASK_SIGNAL)
- + {
- + ((gcsTASK_SIGNAL_PTR)taskHeader)->coid = TaskTable->coid;
- + ((gcsTASK_SIGNAL_PTR)taskHeader)->rcvid = TaskTable->rcvid;
- + }
- +#endif /* __QNXNTO__ */
- + /* Copy the task data. */
- + gcmkVERIFY_OK(gckOS_MemCopy(
- + kernelTask, taskHeader, userTask->size
- + ));
- +
- + /* Advance to the next task. */
- + kernelTask += userTask->size;
- + userTask = userTask->next;
- + }
- + while (userTask != gcvNULL);
- +
- + /* Update link pointer in the header. */
- + kernelTaskEntry->link = (gcsTASK_LINK_PTR) kernelTask;
- +
- + /* Initialize link task. */
- + kernelTaskEntry->link->id = gcvTASK_LINK;
- + kernelTaskEntry->link->cotainer = gcvNULL;
- + kernelTaskEntry->link->task = gcvNULL;
- +
- + /* Advance the task data pointer. */
- + kernelTask += gcmSIZEOF(gcsTASK_LINK);
- + }
- + }
- + while (gcvFALSE);
- +
- + /* Release the mutex. */
- + gcmkERR_BREAK(gckOS_ReleaseMutex(
- + Command->os,
- + Command->taskMutex
- + ));
- +
- + /* Assign interrupts to the blocks. */
- + eventCommand = PreviousEnd;
- +
- + for (block = gcvBLOCK_COUNT - 1; block >= 0; block -= 1)
- + {
- + /* Get the current user table entry. */
- + userTaskEntry = &TaskTable->table[block];
- +
- + /* Are there tasks scheduled? */
- + if (userTaskEntry->head == gcvNULL)
- + {
- + /* No, skip to the next block. */
- + continue;
- + }
- +
- + /* Get the interrupt number. */
- + interrupt = _GetNextInterrupt(Command, block);
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + "%s(%d): block = %d interrupt = %d\n",
- + __FUNCTION__, __LINE__,
- + block, interrupt
- + );
- +
- + /* Determine the command position. */
- + eventCommand -= Command->info.eventCommandSize;
- +
- + /* Append an EVENT command. */
- + gcmkERR_BREAK(gckVGCOMMAND_EventCommand(
- + Command, eventCommand, block, interrupt, gcvNULL
- + ));
- + }
- + }
- + while (gcvFALSE);
- +
- + /* Return status. */
- + return status;
- +}
- +
- +
- +/******************************************************************************\
- +******************************** Memory Management *****************************
- +\******************************************************************************/
- +
- +static gceSTATUS
- +_HardwareToKernel(
- + IN gckOS Os,
- + IN gcuVIDMEM_NODE_PTR Node,
- + IN gctUINT32 Address,
- + OUT gctPOINTER * KernelPointer
- + )
- +{
- + gceSTATUS status;
- + gckVIDMEM memory;
- + gctUINT32 offset;
- +#if gcdDYNAMIC_MAP_RESERVED_MEMORY
- + gctUINT32 nodePhysical;
- +#endif
- + status = gcvSTATUS_OK;
- + /* Assume a non-virtual node and get the pool manager object. */
- + memory = Node->VidMem.memory;
- +
- +#if gcdDYNAMIC_MAP_RESERVED_MEMORY
- + nodePhysical = memory->baseAddress
- + + Node->VidMem.offset
- + + Node->VidMem.alignment;
- +
- + if (Node->VidMem.kernelVirtual == gcvNULL)
- + {
- + status = gckOS_MapPhysical(Os,
- + nodePhysical,
- + Node->VidMem.bytes,
- + (gctPOINTER *)&Node->VidMem.kernelVirtual);
- +
- + if (gcmkIS_ERROR(status))
- + {
- + return status;
- + }
- + }
- +
- + offset = Address - nodePhysical;
- + *KernelPointer = (gctPOINTER)((gctUINT8_PTR)Node->VidMem.kernelVirtual + offset);
- +#else
- + /* Determine the header offset within the pool it is allocated in. */
- + offset = Address - memory->baseAddress;
- +
- + /* Translate the offset into the kernel side pointer. */
- + status = gckOS_GetKernelLogicalEx(
- + Os,
- + gcvCORE_VG,
- + offset,
- + KernelPointer
- + );
- +#endif
- +
- + /* Return status. */
- + return status;
- +}
- +
- +static gceSTATUS
- +_ConvertUserCommandBufferPointer(
- + IN gckVGCOMMAND Command,
- + IN gcsCMDBUFFER_PTR UserCommandBuffer,
- + OUT gcsCMDBUFFER_PTR * KernelCommandBuffer
- + )
- +{
- + gceSTATUS status, last;
- + gcsCMDBUFFER_PTR mappedUserCommandBuffer = gcvNULL;
- +
- + do
- + {
- + gctUINT32 headerAddress;
- +
- + /* Map the command buffer structure into the kernel space. */
- + gcmkERR_BREAK(gckOS_MapUserPointer(
- + Command->os,
- + UserCommandBuffer,
- + gcmSIZEOF(gcsCMDBUFFER),
- + (gctPOINTER *) &mappedUserCommandBuffer
- + ));
- +
- + /* Determine the address of the header. */
- + headerAddress
- + = mappedUserCommandBuffer->address
- + - mappedUserCommandBuffer->bufferOffset;
- +
- + /* Translate the logical address to the kernel space. */
- + gcmkERR_BREAK(_HardwareToKernel(
- + Command->os,
- + gcmUINT64_TO_PTR(mappedUserCommandBuffer->node),
- + headerAddress,
- + (gctPOINTER *) KernelCommandBuffer
- + ));
- + }
- + while (gcvFALSE);
- +
- + /* Unmap the user command buffer. */
- + if (mappedUserCommandBuffer != gcvNULL)
- + {
- + gcmkCHECK_STATUS(gckOS_UnmapUserPointer(
- + Command->os,
- + UserCommandBuffer,
- + gcmSIZEOF(gcsCMDBUFFER),
- + mappedUserCommandBuffer
- + ));
- + }
- +
- + /* Return status. */
- + return status;
- +}
- +
- +static gceSTATUS
- +_AllocateLinear(
- + IN gckVGCOMMAND Command,
- + IN gctUINT Size,
- + IN gctUINT Alignment,
- + OUT gcuVIDMEM_NODE_PTR * Node,
- + OUT gctUINT32 * Address,
- + OUT gctPOINTER * Logical
- + )
- +{
- + gceSTATUS status, last;
- + gcuVIDMEM_NODE_PTR node = gcvNULL;
- + gctUINT32 address = (gctUINT32)~0;
- +
- + do
- + {
- + gcePOOL pool;
- + gctPOINTER logical;
- +
- + /* Allocate from the system pool. */
- + pool = gcvPOOL_SYSTEM;
- +
- + /* Allocate memory. */
- + gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
- + Command->kernel->kernel, &pool,
- + Size, Alignment,
- + gcvSURF_TYPE_UNKNOWN,
- + &node
- + ));
- +
- + /* Do not accept virtual pools for now because we don't handle the
- + kernel pointer translation at the moment. */
- + if (pool == gcvPOOL_VIRTUAL)
- + {
- + status = gcvSTATUS_OUT_OF_MEMORY;
- + break;
- + }
- +
- + /* Lock the command buffer. */
- + gcmkERR_BREAK(gckVIDMEM_Lock(
- + Command->kernel->kernel,
- + node,
- + gcvFALSE,
- + &address
- + ));
- +
- + /* Translate the logical address to the kernel space. */
- + gcmkERR_BREAK(_HardwareToKernel(
- + Command->os,
- + node,
- + address,
- + &logical
- + ));
- +
- + /* Set return values. */
- + * Node = node;
- + * Address = address;
- + * Logical = logical;
- +
- + /* Success. */
- + return gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + /* Roll back. */
- + if (node != gcvNULL)
- + {
- + /* Unlock the command buffer. */
- + if (address != ~0)
- + {
- + gcmkCHECK_STATUS(gckVIDMEM_Unlock(
- + Command->kernel->kernel, node, gcvSURF_TYPE_UNKNOWN, gcvNULL
- + ));
- + }
- +
- + /* Free the command buffer. */
- + gcmkCHECK_STATUS(gckVIDMEM_Free(
- + node
- + ));
- + }
- +
- + /* Return status. */
- + return status;
- +}
- +
- +static gceSTATUS
- +_FreeLinear(
- + IN gckVGKERNEL Kernel,
- + IN gcuVIDMEM_NODE_PTR Node
- + )
- +{
- + gceSTATUS status;
- +
- + do
- + {
- + /* Unlock the linear buffer. */
- + gcmkERR_BREAK(gckVIDMEM_Unlock(Kernel->kernel, Node, gcvSURF_TYPE_UNKNOWN, gcvNULL));
- +
- + /* Free the linear buffer. */
- + gcmkERR_BREAK(gckVIDMEM_Free(Node));
- + }
- + while (gcvFALSE);
- +
- + /* Return status. */
- + return status;
- +}
- +
- +gceSTATUS
- +_AllocateCommandBuffer(
- + IN gckVGCOMMAND Command,
- + IN gctSIZE_T Size,
- + OUT gcsCMDBUFFER_PTR * CommandBuffer
- + )
- +{
- + gceSTATUS status, last;
- + gcuVIDMEM_NODE_PTR node = gcvNULL;
- +
- + do
- + {
- + gctUINT alignedHeaderSize;
- + gctUINT requestedSize;
- + gctUINT allocationSize;
- + gctUINT32 address = 0;
- + gcsCMDBUFFER_PTR commandBuffer;
- + gctUINT8_PTR endCommand;
- +
- + /* Determine the aligned header size. */
- + alignedHeaderSize
- + = gcmALIGN(gcmSIZEOF(gcsCMDBUFFER), Command->info.addressAlignment);
- +
- + /* Align the requested size. */
- + requestedSize
- + = gcmALIGN(Size, Command->info.commandAlignment);
- +
- + /* Determine the size of the buffer to allocate. */
- + allocationSize
- + = alignedHeaderSize
- + + requestedSize
- + + Command->info.staticTailSize;
- +
- + /* Allocate the command buffer. */
- + gcmkERR_BREAK(_AllocateLinear(
- + Command,
- + allocationSize,
- + Command->info.addressAlignment,
- + &node,
- + &address,
- + (gctPOINTER *) &commandBuffer
- + ));
- +
- + /* Initialize the structure. */
- + commandBuffer->completion = gcvVACANT_BUFFER;
- + commandBuffer->node = gcmPTR_TO_UINT64(node);
- + commandBuffer->address = address + alignedHeaderSize;
- + commandBuffer->bufferOffset = alignedHeaderSize;
- + commandBuffer->size = requestedSize;
- + commandBuffer->offset = requestedSize;
- + commandBuffer->nextAllocated = gcvNULL;
- + commandBuffer->nextSubBuffer = gcvNULL;
- +
- + /* Determine the data count. */
- + commandBuffer->dataCount
- + = (requestedSize + Command->info.staticTailSize)
- + / Command->info.commandAlignment;
- +
- + /* Determine the location of the END command. */
- + endCommand
- + = (gctUINT8_PTR) commandBuffer
- + + alignedHeaderSize
- + + requestedSize;
- +
- + /* Append an END command. */
- + gcmkERR_BREAK(gckVGCOMMAND_EndCommand(
- + Command,
- + endCommand,
- + Command->info.feBufferInt,
- + gcvNULL
- + ));
- +
- + /* Set the return pointer. */
- + * CommandBuffer = commandBuffer;
- +
- + /* Success. */
- + return gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + /* Roll back. */
- + if (node != gcvNULL)
- + {
- + /* Free the command buffer. */
- + gcmkCHECK_STATUS(_FreeLinear(Command->kernel, node));
- + }
- +
- + /* Return status. */
- + return status;
- +}
- +
- +static gceSTATUS
- +_FreeCommandBuffer(
- + IN gckVGKERNEL Kernel,
- + IN gcsCMDBUFFER_PTR CommandBuffer
- + )
- +{
- + gceSTATUS status;
- +
- + /* Free the buffer. */
- + status = _FreeLinear(Kernel, gcmUINT64_TO_PTR(CommandBuffer->node));
- +
- + /* Return status. */
- + return status;
- +}
- +
- +
- +/******************************************************************************\
- +****************************** TS Overflow Handler *****************************
- +\******************************************************************************/
- +
- +static gceSTATUS
- +_EventHandler_TSOverflow(
- + IN gckVGKERNEL Kernel
- + )
- +{
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): **** TS OVERFLOW ENCOUNTERED ****\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + return gcvSTATUS_OK;
- +}
- +
- +
- +/******************************************************************************\
- +****************************** Bus Error Handler *******************************
- +\******************************************************************************/
- +
- +static gceSTATUS
- +_EventHandler_BusError(
- + IN gckVGKERNEL Kernel
- + )
- +{
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): **** BUS ERROR ENCOUNTERED ****\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + return gcvSTATUS_OK;
- +}
- +
- +/******************************************************************************\
- +****************************** Power Stall Handler *******************************
- +\******************************************************************************/
- +
- +static gceSTATUS
- +_EventHandler_PowerStall(
- + IN gckVGKERNEL Kernel
- + )
- +{
- + /* Signal. */
- + return gckOS_Signal(
- + Kernel->os,
- + Kernel->command->powerStallSignal,
- + gcvTRUE);
- +}
- +
- +/******************************************************************************\
- +******************************** Task Routines *********************************
- +\******************************************************************************/
- +
- +typedef gceSTATUS (* gctTASKROUTINE) (
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + );
- +
- +static gceSTATUS
- +_TaskLink(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + );
- +
- +static gceSTATUS
- +_TaskCluster(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + );
- +
- +static gceSTATUS
- +_TaskIncrement(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + );
- +
- +static gceSTATUS
- +_TaskDecrement(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + );
- +
- +static gceSTATUS
- +_TaskSignal(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + );
- +
- +static gceSTATUS
- +_TaskLockdown(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + );
- +
- +static gceSTATUS
- +_TaskUnlockVideoMemory(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + );
- +
- +static gceSTATUS
- +_TaskFreeVideoMemory(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + );
- +
- +static gceSTATUS
- +_TaskFreeContiguousMemory(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + );
- +
- +static gceSTATUS
- +_TaskUnmapUserMemory(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + );
- +
- +static gctTASKROUTINE _taskRoutine[] =
- +{
- + _TaskLink, /* gcvTASK_LINK */
- + _TaskCluster, /* gcvTASK_CLUSTER */
- + _TaskIncrement, /* gcvTASK_INCREMENT */
- + _TaskDecrement, /* gcvTASK_DECREMENT */
- + _TaskSignal, /* gcvTASK_SIGNAL */
- + _TaskLockdown, /* gcvTASK_LOCKDOWN */
- + _TaskUnlockVideoMemory, /* gcvTASK_UNLOCK_VIDEO_MEMORY */
- + _TaskFreeVideoMemory, /* gcvTASK_FREE_VIDEO_MEMORY */
- + _TaskFreeContiguousMemory, /* gcvTASK_FREE_CONTIGUOUS_MEMORY */
- + _TaskUnmapUserMemory, /* gcvTASK_UNMAP_USER_MEMORY */
- +};
- +
- +static gceSTATUS
- +_TaskLink(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + )
- +{
- + /* Cast the task pointer. */
- + gcsTASK_LINK_PTR task = (gcsTASK_LINK_PTR) TaskHeader->task;
- +
- + /* Save the pointer to the container. */
- + gcsTASK_CONTAINER_PTR container = TaskHeader->container;
- +
- + /* No more tasks in the list? */
- + if (task->task == gcvNULL)
- + {
- + /* Reset the entry. */
- + TaskHeader->container = gcvNULL;
- + TaskHeader->task = gcvNULL;
- + TaskHeader->link = gcvNULL;
- + }
- + else
- + {
- + /* Update the entry. */
- + TaskHeader->container = task->cotainer;
- + TaskHeader->task = task->task;
- + }
- +
- + /* Decrement the task buffer reference. */
- + gcmkASSERT(container->referenceCount >= 0);
- + if (container->referenceCount == 0)
- + {
- + /* Free the container. */
- + _FreeTaskContainer(Command, container);
- + }
- +
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +static gceSTATUS
- +_TaskCluster(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + )
- +{
- + gceSTATUS status = gcvSTATUS_OK;
- +
- + /* Cast the task pointer. */
- + gcsTASK_CLUSTER_PTR cluster = (gcsTASK_CLUSTER_PTR) TaskHeader->task;
- +
- + /* Get the number of tasks. */
- + gctUINT taskCount = cluster->taskCount;
- +
- + /* Advance to the next task. */
- + TaskHeader->task = (gcsTASK_HEADER_PTR) (cluster + 1);
- +
- + /* Perform all tasks in the cluster. */
- + while (taskCount)
- + {
- + /* Perform the current task. */
- + gcmkERR_BREAK(_taskRoutine[TaskHeader->task->id](
- + Command,
- + TaskHeader
- + ));
- +
- + /* Update the task count. */
- + taskCount -= 1;
- + }
- +
- + /* Return status. */
- + return status;
- +}
- +
- +static gceSTATUS
- +_TaskIncrement(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + )
- +{
- + gceSTATUS status;
- +
- + do
- + {
- + /* Cast the task pointer. */
- + gcsTASK_INCREMENT_PTR task = (gcsTASK_INCREMENT_PTR) TaskHeader->task;
- +
- + /* Convert physical into logical address. */
- + gctUINT32_PTR logical;
- + gcmkERR_BREAK(gckOS_MapPhysical(
- + Command->os,
- + task->address,
- + gcmSIZEOF(gctUINT32),
- + (gctPOINTER *) &logical
- + ));
- +
- + /* Increment data. */
- + (* logical) += 1;
- +
- + /* Unmap the physical memory. */
- + gcmkERR_BREAK(gckOS_UnmapPhysical(
- + Command->os,
- + logical,
- + gcmSIZEOF(gctUINT32)
- + ));
- +
- + /* Update the reference counter. */
- + TaskHeader->container->referenceCount -= 1;
- +
- + /* Update the task pointer. */
- + TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
- + }
- + while (gcvFALSE);
- +
- + /* Return status. */
- + return status;
- +}
- +
- +static gceSTATUS
- +_TaskDecrement(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + )
- +{
- + gceSTATUS status;
- +
- + do
- + {
- + /* Cast the task pointer. */
- + gcsTASK_DECREMENT_PTR task = (gcsTASK_DECREMENT_PTR) TaskHeader->task;
- +
- + /* Convert physical into logical address. */
- + gctUINT32_PTR logical;
- + gcmkERR_BREAK(gckOS_MapPhysical(
- + Command->os,
- + task->address,
- + gcmSIZEOF(gctUINT32),
- + (gctPOINTER *) &logical
- + ));
- +
- + /* Decrement data. */
- + (* logical) -= 1;
- +
- + /* Unmap the physical memory. */
- + gcmkERR_BREAK(gckOS_UnmapPhysical(
- + Command->os,
- + logical,
- + gcmSIZEOF(gctUINT32)
- + ));
- +
- + /* Update the reference counter. */
- + TaskHeader->container->referenceCount -= 1;
- +
- + /* Update the task pointer. */
- + TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
- + }
- + while (gcvFALSE);
- +
- + /* Return status. */
- + return status;
- +}
- +
- +static gceSTATUS
- +_TaskSignal(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + )
- +{
- + gceSTATUS status;
- +
- + do
- + {
- + /* Cast the task pointer. */
- + gcsTASK_SIGNAL_PTR task = (gcsTASK_SIGNAL_PTR) TaskHeader->task;
- +
- +
- + /* Map the signal into kernel space. */
- +#ifdef __QNXNTO__
- + gcmkERR_BREAK(gckOS_UserSignal(
- + Command->os, task->signal, task->rcvid, task->coid
- + ));
- +#else
- + gcmkERR_BREAK(gckOS_UserSignal(
- + Command->os, task->signal, task->process
- + ));
- +#endif /* __QNXNTO__ */
- +
- + /* Update the reference counter. */
- + TaskHeader->container->referenceCount -= 1;
- +
- + /* Update the task pointer. */
- + TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
- + }
- + while (gcvFALSE);
- +
- + /* Return status. */
- + return status;
- +}
- +
- +static gceSTATUS
- +_TaskLockdown(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + )
- +{
- + gceSTATUS status;
- + gctUINT32_PTR userCounter = gcvNULL;
- + gctUINT32_PTR kernelCounter = gcvNULL;
- + gctSIGNAL signal = gcvNULL;
- +
- + do
- + {
- + /* Cast the task pointer. */
- + gcsTASK_LOCKDOWN_PTR task = (gcsTASK_LOCKDOWN_PTR) TaskHeader->task;
- +
- + /* Convert physical addresses into logical. */
- + gcmkERR_BREAK(gckOS_MapPhysical(
- + Command->os,
- + task->userCounter,
- + gcmSIZEOF(gctUINT32),
- + (gctPOINTER *) &userCounter
- + ));
- +
- + gcmkERR_BREAK(gckOS_MapPhysical(
- + Command->os,
- + task->kernelCounter,
- + gcmSIZEOF(gctUINT32),
- + (gctPOINTER *) &kernelCounter
- + ));
- +
- + /* Update the kernel counter. */
- + (* kernelCounter) += 1;
- +
- + /* Are the counters equal? */
- + if ((* userCounter) == (* kernelCounter))
- + {
- + /* Map the signal into kernel space. */
- + gcmkERR_BREAK(gckOS_MapSignal(
- + Command->os, task->signal, task->process, &signal
- + ));
- +
- + if (signal == gcvNULL)
- + {
- + /* Signal. */
- + gcmkERR_BREAK(gckOS_Signal(
- + Command->os, task->signal, gcvTRUE
- + ));
- + }
- + else
- + {
- + /* Signal. */
- + gcmkERR_BREAK(gckOS_Signal(
- + Command->os, signal, gcvTRUE
- + ));
- + }
- + }
- +
- + /* Update the reference counter. */
- + TaskHeader->container->referenceCount -= 1;
- +
- + /* Update the task pointer. */
- + TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
- + }
- + while (gcvFALSE);
- +
- + /* Destroy the mapped signal. */
- + if (signal != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_DestroySignal(
- + Command->os, signal
- + ));
- + }
- +
- + /* Unmap the physical memory. */
- + if (kernelCounter != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_UnmapPhysical(
- + Command->os,
- + kernelCounter,
- + gcmSIZEOF(gctUINT32)
- + ));
- + }
- +
- + if (userCounter != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_UnmapPhysical(
- + Command->os,
- + userCounter,
- + gcmSIZEOF(gctUINT32)
- + ));
- + }
- +
- + /* Return status. */
- + return status;
- +}
- +
- +static gceSTATUS
- +_TaskUnlockVideoMemory(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + )
- +{
- + gceSTATUS status;
- +
- + do
- + {
- + /* Cast the task pointer. */
- + gcsTASK_UNLOCK_VIDEO_MEMORY_PTR task
- + = (gcsTASK_UNLOCK_VIDEO_MEMORY_PTR) TaskHeader->task;
- +
- + /* Unlock video memory. */
- + gcmkERR_BREAK(gckVIDMEM_Unlock(
- + Command->kernel->kernel,
- + gcmUINT64_TO_PTR(task->node),
- + gcvSURF_TYPE_UNKNOWN,
- + gcvNULL));
- +
- + /* Update the reference counter. */
- + TaskHeader->container->referenceCount -= 1;
- +
- + /* Update the task pointer. */
- + TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
- + }
- + while (gcvFALSE);
- +
- + /* Return status. */
- + return status;
- +}
- +
- +static gceSTATUS
- +_TaskFreeVideoMemory(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + )
- +{
- + gceSTATUS status;
- +
- + do
- + {
- + /* Cast the task pointer. */
- + gcsTASK_FREE_VIDEO_MEMORY_PTR task
- + = (gcsTASK_FREE_VIDEO_MEMORY_PTR) TaskHeader->task;
- +
- + /* Free video memory. */
- + gcmkERR_BREAK(gckVIDMEM_Free(gcmUINT64_TO_PTR(task->node)));
- +
- + /* Update the reference counter. */
- + TaskHeader->container->referenceCount -= 1;
- +
- + /* Update the task pointer. */
- + TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
- + }
- + while (gcvFALSE);
- +
- + /* Return status. */
- + return status;
- +}
- +
- +static gceSTATUS
- +_TaskFreeContiguousMemory(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + )
- +{
- + gceSTATUS status;
- +
- + do
- + {
- + /* Cast the task pointer. */
- + gcsTASK_FREE_CONTIGUOUS_MEMORY_PTR task
- + = (gcsTASK_FREE_CONTIGUOUS_MEMORY_PTR) TaskHeader->task;
- +
- + /* Free contiguous memory. */
- + gcmkERR_BREAK(gckOS_FreeContiguous(
- + Command->os, task->physical, task->logical, task->bytes
- + ));
- +
- + /* Update the reference counter. */
- + TaskHeader->container->referenceCount -= 1;
- +
- + /* Update the task pointer. */
- + TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
- + }
- + while (gcvFALSE);
- +
- + /* Return status. */
- + return status;
- +}
- +
- +static gceSTATUS
- +_TaskUnmapUserMemory(
- + gckVGCOMMAND Command,
- + gcsBLOCK_TASK_ENTRY_PTR TaskHeader
- + )
- +{
- + gceSTATUS status;
- +
- + do
- + {
- + /* Cast the task pointer. */
- + gcsTASK_UNMAP_USER_MEMORY_PTR task
- + = (gcsTASK_UNMAP_USER_MEMORY_PTR) TaskHeader->task;
- +
- + /* Unmap the user memory. */
- + gcmkERR_BREAK(gckOS_UnmapUserMemory(
- + Command->os, gcvCORE_VG, task->memory, task->size, task->info, task->address
- + ));
- +
- + /* Update the reference counter. */
- + TaskHeader->container->referenceCount -= 1;
- +
- + /* Update the task pointer. */
- + TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
- + }
- + while (gcvFALSE);
- +
- + /* Return status. */
- + return status;
- +}
- +
- +/******************************************************************************\
- +************ Hardware Block Interrupt Handlers For Scheduled Events ************
- +\******************************************************************************/
- +
- +static gceSTATUS
- +_EventHandler_Block(
- + IN gckVGKERNEL Kernel,
- + IN gcsBLOCK_TASK_ENTRY_PTR TaskHeader,
- + IN gctBOOL ProcessAll
- + )
- +{
- + gceSTATUS status, last;
- +
- + gcmkHEADER_ARG("Kernel=0x%x TaskHeader=0x%x ProcessAll=0x%x", Kernel, TaskHeader, ProcessAll);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- +
- + do
- + {
- + gckVGCOMMAND command;
- +
- + /* Get the command buffer object. */
- + command = Kernel->command;
- +
- + /* Increment the interrupt usage semaphore. */
- + gcmkERR_BREAK(gckOS_IncrementSemaphore(
- + command->os, TaskHeader->interruptSemaphore
- + ));
- +
- + /* Acquire the mutex. */
- + gcmkERR_BREAK(gckOS_AcquireMutex(
- + command->os,
- + command->taskMutex,
- + gcvINFINITE
- + ));
- +
- + /* Verify inputs. */
- + gcmkASSERT(TaskHeader != gcvNULL);
- + gcmkASSERT(TaskHeader->container != gcvNULL);
- + gcmkASSERT(TaskHeader->task != gcvNULL);
- + gcmkASSERT(TaskHeader->link != gcvNULL);
- +
- + /* Process tasks. */
- + do
- + {
- + /* Process the current task. */
- + gcmkERR_BREAK(_taskRoutine[TaskHeader->task->id](
- + command,
- + TaskHeader
- + ));
- +
- + /* Is the next task is LINK? */
- + if (TaskHeader->task->id == gcvTASK_LINK)
- + {
- + gcmkERR_BREAK(_taskRoutine[TaskHeader->task->id](
- + command,
- + TaskHeader
- + ));
- +
- + /* Done. */
- + break;
- + }
- + }
- + while (ProcessAll);
- +
- + /* Release the mutex. */
- + gcmkCHECK_STATUS(gckOS_ReleaseMutex(
- + command->os,
- + command->taskMutex
- + ));
- + }
- + while (gcvFALSE);
- +
- + gcmkFOOTER();
- + /* Return status. */
- + return status;
- +}
- +
- +gcmDECLARE_INTERRUPT_HANDLER(COMMAND, 0)
- +{
- + gceSTATUS status, last;
- +
- + gcmkHEADER_ARG("Kernel=0x%x ", Kernel);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- +
- +
- + do
- + {
- + gckVGCOMMAND command;
- + gcsKERNEL_QUEUE_HEADER_PTR mergeQueue;
- + gcsKERNEL_QUEUE_HEADER_PTR queueTail;
- + gcsKERNEL_CMDQUEUE_PTR entry;
- + gctUINT entryCount;
- +
- + /* Get the command buffer object. */
- + command = Kernel->command;
- +
- + /* Acquire the mutex. */
- + gcmkERR_BREAK(gckOS_AcquireMutex(
- + command->os,
- + command->queueMutex,
- + gcvINFINITE
- + ));
- +
- + /* Get the current queue. */
- + queueTail = command->queueTail;
- +
- + /* Get the current queue entry. */
- + entry = queueTail->currentEntry;
- +
- + /* Get the number of entries in the queue. */
- + entryCount = queueTail->pending;
- +
- + /* Process all entries. */
- + while (gcvTRUE)
- + {
- + /* Call post-execution function. */
- + status = entry->handler(Kernel, entry);
- +
- + /* Failed? */
- + if (gcmkIS_ERROR(status))
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR,
- + gcvZONE_COMMAND,
- + "[%s] line %d: post action failed.\n",
- + __FUNCTION__, __LINE__
- + );
- + }
- +
- + /* Executed the next buffer? */
- + if (status == gcvSTATUS_EXECUTED)
- + {
- + /* Update the queue. */
- + queueTail->pending = entryCount;
- + queueTail->currentEntry = entry;
- +
- + /* Success. */
- + status = gcvSTATUS_OK;
- +
- + /* Break out of the loop. */
- + break;
- + }
- +
- + /* Advance to the next entry. */
- + entry += 1;
- + entryCount -= 1;
- +
- + /* Last entry? */
- + if (entryCount == 0)
- + {
- + /* Reset the queue to idle. */
- + queueTail->pending = 0;
- +
- + /* Get a shortcut to the queue to merge with. */
- + mergeQueue = command->mergeQueue;
- +
- + /* Merge the queues if necessary. */
- + if (mergeQueue != queueTail)
- + {
- + gcmkASSERT(mergeQueue < queueTail);
- + gcmkASSERT(mergeQueue->next == queueTail);
- +
- + mergeQueue->size
- + += gcmSIZEOF(gcsKERNEL_QUEUE_HEADER)
- + + queueTail->size;
- +
- + mergeQueue->next = queueTail->next;
- + }
- +
- + /* Advance to the next queue. */
- + queueTail = queueTail->next;
- +
- + /* Did it wrap around? */
- + if (command->queue == queueTail)
- + {
- + /* Reset merge queue. */
- + command->mergeQueue = queueTail;
- + }
- +
- + /* Set new queue. */
- + command->queueTail = queueTail;
- +
- + /* Is the next queue scheduled? */
- + if (queueTail->pending > 0)
- + {
- + gcsCMDBUFFER_PTR commandBuffer;
- +
- + /* The first entry must be a command buffer. */
- + commandBuffer = queueTail->currentEntry->commandBuffer;
- +
- + /* Start the command processor. */
- + status = gckVGHARDWARE_Execute(
- + command->hardware,
- + commandBuffer->address,
- + commandBuffer->dataCount
- + );
- +
- + /* Failed? */
- + if (gcmkIS_ERROR(status))
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR,
- + gcvZONE_COMMAND,
- + "[%s] line %d: failed to start the next queue.\n",
- + __FUNCTION__, __LINE__
- + );
- + }
- + }
- + else
- + {
- + status = gckVGHARDWARE_SetPowerManagementState(
- + Kernel->command->hardware, gcvPOWER_IDLE_BROADCAST
- + );
- + }
- +
- + /* Break out of the loop. */
- + break;
- + }
- + }
- +
- + /* Release the mutex. */
- + gcmkCHECK_STATUS(gckOS_ReleaseMutex(
- + command->os,
- + command->queueMutex
- + ));
- + }
- + while (gcvFALSE);
- +
- +
- + gcmkFOOTER();
- + /* Return status. */
- + return status;
- +}
- +
- +/* Define standard block interrupt handlers. */
- +gcmDEFINE_INTERRUPT_HANDLER(TESSELLATOR, 0)
- +gcmDEFINE_INTERRUPT_HANDLER(VG, 0)
- +gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 0)
- +gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 1)
- +gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 2)
- +gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 3)
- +gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 4)
- +gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 5)
- +gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 6)
- +gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 7)
- +gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 8)
- +gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 9)
- +
- +/* The entries in the array are arranged by event priority. */
- +static gcsBLOCK_INTERRUPT_HANDLER _blockHandlers[] =
- +{
- + gcmDEFINE_INTERRUPT_HANDLER_ENTRY(TESSELLATOR, 0),
- + gcmDEFINE_INTERRUPT_HANDLER_ENTRY(VG, 0),
- + gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 0),
- + gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 1),
- + gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 2),
- + gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 3),
- + gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 4),
- + gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 5),
- + gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 6),
- + gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 7),
- + gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 8),
- + gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 9),
- + gcmDEFINE_INTERRUPT_HANDLER_ENTRY(COMMAND, 0),
- +};
- +
- +
- +/******************************************************************************\
- +************************* Static Command Buffer Handlers ***********************
- +\******************************************************************************/
- +
- +static gceSTATUS
- +_UpdateStaticCommandBuffer(
- + IN gckVGKERNEL Kernel,
- + IN gcsKERNEL_CMDQUEUE_PTR Entry
- + )
- +{
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + "%s(%d)\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +static gceSTATUS
- +_ExecuteStaticCommandBuffer(
- + IN gckVGKERNEL Kernel,
- + IN gcsKERNEL_CMDQUEUE_PTR Entry
- + )
- +{
- + gceSTATUS status;
- +
- + do
- + {
- + gcsCMDBUFFER_PTR commandBuffer;
- +
- + /* Cast the command buffer header. */
- + commandBuffer = Entry->commandBuffer;
- +
- + /* Set to update the command buffer next time. */
- + Entry->handler = _UpdateStaticCommandBuffer;
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + "%s(%d): executing next buffer @ 0x%08X, data count = %d\n",
- + __FUNCTION__, __LINE__,
- + commandBuffer->address,
- + commandBuffer->dataCount
- + );
- +
- + /* Start the command processor. */
- + gcmkERR_BREAK(gckVGHARDWARE_Execute(
- + Kernel->hardware,
- + commandBuffer->address,
- + commandBuffer->dataCount
- + ));
- +
- + /* Success. */
- + return gcvSTATUS_EXECUTED;
- + }
- + while (gcvFALSE);
- +
- + /* Return status. */
- + return status;
- +}
- +
- +static gceSTATUS
- +_UpdateLastStaticCommandBuffer(
- + IN gckVGKERNEL Kernel,
- + IN gcsKERNEL_CMDQUEUE_PTR Entry
- + )
- +{
- +#if gcvDEBUG || gcdFORCE_MESSAGES
- + /* Get the command buffer header. */
- + gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
- +
- + /* Validate the command buffer. */
- + gcmkASSERT(commandBuffer->completion != gcvNULL);
- + gcmkASSERT(commandBuffer->completion != gcvVACANT_BUFFER);
- +
- +#endif
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + "%s(%d): processing all tasks scheduled for FE.\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + /* Perform scheduled tasks. */
- + return _EventHandler_Block(
- + Kernel,
- + &Kernel->command->taskTable[gcvBLOCK_COMMAND],
- + gcvTRUE
- + );
- +}
- +
- +static gceSTATUS
- +_ExecuteLastStaticCommandBuffer(
- + IN gckVGKERNEL Kernel,
- + IN gcsKERNEL_CMDQUEUE_PTR Entry
- + )
- +{
- + gceSTATUS status;
- +
- + do
- + {
- + /* Cast the command buffer header. */
- + gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
- +
- + /* Set to update the command buffer next time. */
- + Entry->handler = _UpdateLastStaticCommandBuffer;
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + "%s(%d): executing next buffer @ 0x%08X, data count = %d\n",
- + __FUNCTION__, __LINE__,
- + commandBuffer->address,
- + commandBuffer->dataCount
- + );
- +
- + /* Start the command processor. */
- + gcmkERR_BREAK(gckVGHARDWARE_Execute(
- + Kernel->hardware,
- + commandBuffer->address,
- + commandBuffer->dataCount
- + ));
- +
- + /* Success. */
- + return gcvSTATUS_EXECUTED;
- + }
- + while (gcvFALSE);
- +
- + /* Return status. */
- + return status;
- +}
- +
- +
- +/******************************************************************************\
- +************************* Dynamic Command Buffer Handlers **********************
- +\******************************************************************************/
- +
- +static gceSTATUS
- +_UpdateDynamicCommandBuffer(
- + IN gckVGKERNEL Kernel,
- + IN gcsKERNEL_CMDQUEUE_PTR Entry
- + )
- +{
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + "%s(%d)\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +static gceSTATUS
- +_ExecuteDynamicCommandBuffer(
- + IN gckVGKERNEL Kernel,
- + IN gcsKERNEL_CMDQUEUE_PTR Entry
- + )
- +{
- + gceSTATUS status;
- +
- + do
- + {
- + /* Cast the command buffer header. */
- + gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
- +
- + /* Set to update the command buffer next time. */
- + Entry->handler = _UpdateDynamicCommandBuffer;
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + "%s(%d): executing next buffer @ 0x%08X, data count = %d\n",
- + __FUNCTION__, __LINE__,
- + commandBuffer->address,
- + commandBuffer->dataCount
- + );
- +
- + /* Start the command processor. */
- + gcmkERR_BREAK(gckVGHARDWARE_Execute(
- + Kernel->hardware,
- + commandBuffer->address,
- + commandBuffer->dataCount
- + ));
- +
- + /* Success. */
- + return gcvSTATUS_EXECUTED;
- + }
- + while (gcvFALSE);
- +
- + /* Return status. */
- + return status;
- +}
- +
- +static gceSTATUS
- +_UpdateLastDynamicCommandBuffer(
- + IN gckVGKERNEL Kernel,
- + IN gcsKERNEL_CMDQUEUE_PTR Entry
- + )
- +{
- +#if gcvDEBUG || gcdFORCE_MESSAGES
- + /* Get the command buffer header. */
- + gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
- +
- + /* Validate the command buffer. */
- + gcmkASSERT(commandBuffer->completion != gcvNULL);
- + gcmkASSERT(commandBuffer->completion != gcvVACANT_BUFFER);
- +
- +#endif
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + "%s(%d): processing all tasks scheduled for FE.\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + /* Perform scheduled tasks. */
- + return _EventHandler_Block(
- + Kernel,
- + &Kernel->command->taskTable[gcvBLOCK_COMMAND],
- + gcvTRUE
- + );
- +}
- +
- +static gceSTATUS
- +_ExecuteLastDynamicCommandBuffer(
- + IN gckVGKERNEL Kernel,
- + IN gcsKERNEL_CMDQUEUE_PTR Entry
- + )
- +{
- + gceSTATUS status;
- +
- + do
- + {
- + /* Cast the command buffer header. */
- + gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
- +
- + /* Set to update the command buffer next time. */
- + Entry->handler = _UpdateLastDynamicCommandBuffer;
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + "%s(%d): executing next buffer @ 0x%08X, data count = %d\n",
- + __FUNCTION__, __LINE__,
- + commandBuffer->address,
- + commandBuffer->dataCount
- + );
- +
- + /* Start the command processor. */
- + gcmkERR_BREAK(gckVGHARDWARE_Execute(
- + Kernel->hardware,
- + commandBuffer->address,
- + commandBuffer->dataCount
- + ));
- +
- + /* Success. */
- + return gcvSTATUS_EXECUTED;
- + }
- + while (gcvFALSE);
- +
- + /* Return status. */
- + return status;
- +}
- +
- +
- +/******************************************************************************\
- +********************************* Other Handlers *******************************
- +\******************************************************************************/
- +
- +static gceSTATUS
- +_FreeKernelCommandBuffer(
- + IN gckVGKERNEL Kernel,
- + IN gcsKERNEL_CMDQUEUE_PTR Entry
- + )
- +{
- + gceSTATUS status;
- +
- + /* Free the command buffer. */
- + status = _FreeCommandBuffer(Kernel, Entry->commandBuffer);
- +
- + /* Return status. */
- + return status;
- +}
- +
- +
- +/******************************************************************************\
- +******************************* Queue Management *******************************
- +\******************************************************************************/
- +
- +#if gcvDUMP_COMMAND_BUFFER
- +static void
- +_DumpCommandQueue(
- + IN gckVGCOMMAND Command,
- + IN gcsKERNEL_QUEUE_HEADER_PTR QueueHeader,
- + IN gctUINT EntryCount
- + )
- +{
- + gcsKERNEL_CMDQUEUE_PTR entry;
- + gctUINT queueIndex;
- +
- +#if defined(gcvCOMMAND_BUFFER_NAME)
- + static gctUINT arrayCount = 0;
- +#endif
- +
- + /* Is dumpinng enabled? */
- + if (!Commad->enableDumping)
- + {
- + return;
- + }
- +
- +#if !defined(gcvCOMMAND_BUFFER_NAME)
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_COMMAND,
- + "COMMAND QUEUE DUMP: %d entries\n", EntryCount
- + );
- +#endif
- +
- + /* Get the pointer to the first entry. */
- + entry = QueueHeader->currentEntry;
- +
- + /* Iterate through the queue. */
- + for (queueIndex = 0; queueIndex < EntryCount; queueIndex += 1)
- + {
- + gcsCMDBUFFER_PTR buffer;
- + gctUINT bufferCount;
- + gctUINT bufferIndex;
- + gctUINT i, count;
- + gctUINT size;
- + gctUINT32_PTR data;
- +
- +#if gcvDUMP_COMMAND_LINES
- + gctUINT lineNumber;
- +#endif
- +
- +#if !defined(gcvCOMMAND_BUFFER_NAME)
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_COMMAND,
- + "ENTRY %d\n", queueIndex
- + );
- +#endif
- +
- + /* Reset the count. */
- + bufferCount = 0;
- +
- + /* Set the initial buffer. */
- + buffer = entry->commandBuffer;
- +
- + /* Loop through all subbuffers. */
- + while (buffer)
- + {
- + /* Update the count. */
- + bufferCount += 1;
- +
- + /* Advance to the next subbuffer. */
- + buffer = buffer->nextSubBuffer;
- + }
- +
- +#if !defined(gcvCOMMAND_BUFFER_NAME)
- + if (bufferCount > 1)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO,
- + gcvZONE_COMMAND,
- + " COMMAND BUFFER SET: %d buffers.\n",
- + bufferCount
- + );
- + }
- +#endif
- +
- + /* Reset the buffer index. */
- + bufferIndex = 0;
- +
- + /* Set the initial buffer. */
- + buffer = entry->commandBuffer;
- +
- + /* Loop through all subbuffers. */
- + while (buffer)
- + {
- + /* Determine the size of the buffer. */
- + size = buffer->dataCount * Command->info.commandAlignment;
- +
- +#if !defined(gcvCOMMAND_BUFFER_NAME)
- + /* A single buffer? */
- + if (bufferCount == 1)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO,
- + gcvZONE_COMMAND,
- + " COMMAND BUFFER: count=%d (0x%X), size=%d bytes @ %08X.\n",
- + buffer->dataCount,
- + buffer->dataCount,
- + size,
- + buffer->address
- + );
- + }
- + else
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO,
- + gcvZONE_COMMAND,
- + " COMMAND BUFFER %d: count=%d (0x%X), size=%d bytes @ %08X\n",
- + bufferIndex,
- + buffer->dataCount,
- + buffer->dataCount,
- + size,
- + buffer->address
- + );
- + }
- +#endif
- +
- + /* Determine the number of double words to print. */
- + count = size / 4;
- +
- + /* Determine the buffer location. */
- + data = (gctUINT32_PTR)
- + (
- + (gctUINT8_PTR) buffer + buffer->bufferOffset
- + );
- +
- +#if defined(gcvCOMMAND_BUFFER_NAME)
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO,
- + gcvZONE_COMMAND,
- + "unsigned int _" gcvCOMMAND_BUFFER_NAME "_%d[] =\n",
- + arrayCount
- + );
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO,
- + gcvZONE_COMMAND,
- + "{\n"
- + );
- +
- + arrayCount += 1;
- +#endif
- +
- +#if gcvDUMP_COMMAND_LINES
- + /* Reset the line number. */
- + lineNumber = 0;
- +#endif
- +
- +#if defined(gcvCOMMAND_BUFFER_NAME)
- + count -= 2;
- +#endif
- +
- + for (i = 0; i < count; i += 1)
- + {
- + if ((i % 8) == 0)
- + {
- +#if defined(gcvCOMMAND_BUFFER_NAME)
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, "\t");
- +#else
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, " ");
- +#endif
- + }
- +
- +#if gcvDUMP_COMMAND_LINES
- + if (lineNumber == gcvDUMP_COMMAND_LINES)
- + {
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, " . . . . . . . . .\n");
- + break;
- + }
- +#endif
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, "0x%08X", data[i]);
- +
- + if (i + 1 == count)
- + {
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, "\n");
- +
- +#if gcvDUMP_COMMAND_LINES
- + lineNumber += 1;
- +#endif
- + }
- + else
- + {
- + if (((i + 1) % 8) == 0)
- + {
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, ",\n");
- +
- +#if gcvDUMP_COMMAND_LINES
- + lineNumber += 1;
- +#endif
- + }
- + else
- + {
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, ", ");
- + }
- + }
- + }
- +
- +#if defined(gcvCOMMAND_BUFFER_NAME)
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO,
- + gcvZONE_COMMAND,
- + "};\n\n"
- + );
- +#endif
- +
- + /* Advance to the next subbuffer. */
- + buffer = buffer->nextSubBuffer;
- + bufferIndex += 1;
- + }
- +
- + /* Advance to the next entry. */
- + entry += 1;
- + }
- +}
- +#endif
- +
- +static gceSTATUS
- +_LockCurrentQueue(
- + IN gckVGCOMMAND Command,
- + OUT gcsKERNEL_CMDQUEUE_PTR * Entries,
- + OUT gctUINT_PTR EntryCount
- + )
- +{
- + gceSTATUS status;
- +
- + do
- + {
- + gcsKERNEL_QUEUE_HEADER_PTR queueHead;
- +
- + /* Get a shortcut to the head of the queue. */
- + queueHead = Command->queueHead;
- +
- + /* Is the head buffer still being worked on? */
- + if (queueHead->pending)
- + {
- + /* Increment overflow count. */
- + Command->queueOverflow += 1;
- +
- + /* Wait until the head becomes idle. */
- + gcmkERR_BREAK(_WaitForIdle(Command, queueHead));
- + }
- +
- + /* Acquire the mutex. */
- + gcmkERR_BREAK(gckOS_AcquireMutex(
- + Command->os,
- + Command->queueMutex,
- + gcvINFINITE
- + ));
- +
- + /* Determine the first queue entry. */
- + queueHead->currentEntry = (gcsKERNEL_CMDQUEUE_PTR)
- + (
- + (gctUINT8_PTR) queueHead + gcmSIZEOF(gcsKERNEL_QUEUE_HEADER)
- + );
- +
- + /* Set the pointer to the first entry. */
- + * Entries = queueHead->currentEntry;
- +
- + /* Determine the number of available entries. */
- + * EntryCount = queueHead->size / gcmSIZEOF(gcsKERNEL_CMDQUEUE);
- +
- + /* Success. */
- + return gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + /* Return status. */
- + return status;
- +}
- +
- +static gceSTATUS
- +_UnlockCurrentQueue(
- + IN gckVGCOMMAND Command,
- + IN gctUINT EntryCount
- + )
- +{
- + gceSTATUS status;
- +
- + do
- + {
- +#if !gcdENABLE_INFINITE_SPEED_HW
- + gcsKERNEL_QUEUE_HEADER_PTR queueTail;
- + gcsKERNEL_QUEUE_HEADER_PTR queueHead;
- + gcsKERNEL_QUEUE_HEADER_PTR queueNext;
- + gctUINT queueSize;
- + gctUINT newSize;
- + gctUINT unusedSize;
- +
- + /* Get shortcut to the head and to the tail of the queue. */
- + queueTail = Command->queueTail;
- + queueHead = Command->queueHead;
- +
- + /* Dump the command buffer. */
- +#if gcvDUMP_COMMAND_BUFFER
- + _DumpCommandQueue(Command, queueHead, EntryCount);
- +#endif
- +
- + /* Get a shortcut to the current queue size. */
- + queueSize = queueHead->size;
- +
- + /* Determine the new queue size. */
- + newSize = EntryCount * gcmSIZEOF(gcsKERNEL_CMDQUEUE);
- + gcmkASSERT(newSize <= queueSize);
- +
- + /* Determine the size of the unused area. */
- + unusedSize = queueSize - newSize;
- +
- + /* Is the unused area big enough to become a buffer? */
- + if (unusedSize >= gcvMINUMUM_BUFFER)
- + {
- + gcsKERNEL_QUEUE_HEADER_PTR nextHead;
- +
- + /* Place the new header. */
- + nextHead = (gcsKERNEL_QUEUE_HEADER_PTR)
- + (
- + (gctUINT8_PTR) queueHead
- + + gcmSIZEOF(gcsKERNEL_QUEUE_HEADER)
- + + newSize
- + );
- +
- + /* Initialize the buffer. */
- + nextHead->size = unusedSize - gcmSIZEOF(gcsKERNEL_QUEUE_HEADER);
- + nextHead->pending = 0;
- +
- + /* Link the buffer in. */
- + nextHead->next = queueHead->next;
- + queueHead->next = nextHead;
- + queueNext = nextHead;
- +
- + /* Update the size of the current buffer. */
- + queueHead->size = newSize;
- + }
- +
- + /* Not big enough. */
- + else
- + {
- + /* Determine the next queue. */
- + queueNext = queueHead->next;
- + }
- +
- + /* Mark the buffer as busy. */
- + queueHead->pending = EntryCount;
- +
- + /* Advance to the next buffer. */
- + Command->queueHead = queueNext;
- +
- + /* Start the command processor if the queue was empty. */
- + if (queueTail == queueHead)
- + {
- + gcsCMDBUFFER_PTR commandBuffer;
- +
- + /* The first entry must be a command buffer. */
- + commandBuffer = queueTail->currentEntry->commandBuffer;
- +
- + /* Start the command processor. */
- + gcmkERR_BREAK(gckVGHARDWARE_Execute(
- + Command->hardware,
- + commandBuffer->address,
- + commandBuffer->dataCount
- + ));
- + }
- +
- + /* The queue was not empty. */
- + else
- + {
- + /* Advance the merge buffer if needed. */
- + if (queueHead == Command->mergeQueue)
- + {
- + Command->mergeQueue = queueNext;
- + }
- + }
- +#endif
- +
- + /* Release the mutex. */
- + gcmkERR_BREAK(gckOS_ReleaseMutex(
- + Command->os,
- + Command->queueMutex
- + ));
- +
- + /* Success. */
- + return gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + /* Return status. */
- + return status;
- +}
- +
- +
- +
- +/******************************************************************************\
- +****************************** gckVGCOMMAND API Code *****************************
- +\******************************************************************************/
- +gceSTATUS
- +gckVGCOMMAND_Construct(
- + IN gckVGKERNEL Kernel,
- + IN gctUINT TaskGranularity,
- + IN gctUINT QueueSize,
- + OUT gckVGCOMMAND * Command
- + )
- +{
- + gceSTATUS status, last;
- + gckVGCOMMAND command = gcvNULL;
- + gcsKERNEL_QUEUE_HEADER_PTR queue;
- + gctUINT i, j;
- +
- + gcmkHEADER_ARG("Kernel=0x%x TaskGranularity=0x%x QueueSize=0x%x Command=0x%x",
- + Kernel, TaskGranularity, QueueSize, Command);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(QueueSize >= gcvMINUMUM_BUFFER);
- + gcmkVERIFY_ARGUMENT(Command != gcvNULL);
- +
- + do
- + {
- + /***********************************************************************
- + ** Generic object initialization.
- + */
- +
- + /* Allocate the gckVGCOMMAND structure. */
- + gcmkERR_BREAK(gckOS_Allocate(
- + Kernel->os,
- + gcmSIZEOF(struct _gckVGCOMMAND),
- + (gctPOINTER *) &command
- + ));
- +
- + /* Initialize the object. */
- + command->object.type = gcvOBJ_COMMAND;
- +
- + /* Set the object pointers. */
- + command->kernel = Kernel;
- + command->os = Kernel->os;
- + command->hardware = Kernel->hardware;
- +
- + /* Reset pointers. */
- + command->queue = gcvNULL;
- + command->queueMutex = gcvNULL;
- + command->taskMutex = gcvNULL;
- + command->commitMutex = gcvNULL;
- +
- + command->powerStallBuffer = gcvNULL;
- + command->powerStallSignal = gcvNULL;
- + command->powerSemaphore = gcvNULL;
- +
- + /* Reset context states. */
- + command->contextCounter = 0;
- + command->currentContext = 0;
- +
- + /* Enable command buffer dumping. */
- + command->enableDumping = gcvTRUE;
- +
- + /* Set features. */
- + command->fe20 = Kernel->hardware->fe20;
- + command->vg20 = Kernel->hardware->vg20;
- + command->vg21 = Kernel->hardware->vg21;
- +
- + /* Reset task table .*/
- + gcmkVERIFY_OK(gckOS_ZeroMemory(
- + command->taskTable, gcmSIZEOF(command->taskTable)
- + ));
- +
- + /* Query command buffer attributes. */
- + gcmkERR_BREAK(gckVGCOMMAND_InitializeInfo(command));
- +
- + /* Create the control mutexes. */
- + gcmkERR_BREAK(gckOS_CreateMutex(Kernel->os, &command->queueMutex));
- + gcmkERR_BREAK(gckOS_CreateMutex(Kernel->os, &command->taskMutex));
- + gcmkERR_BREAK(gckOS_CreateMutex(Kernel->os, &command->commitMutex));
- +
- + /* Create the power management semaphore. */
- + gcmkERR_BREAK(gckOS_CreateSemaphore(Kernel->os,
- + &command->powerSemaphore));
- +
- + gcmkERR_BREAK(gckOS_CreateSignal(Kernel->os,
- + gcvFALSE, &command->powerStallSignal));
- +
- + /***********************************************************************
- + ** Command queue initialization.
- + */
- +
- + /* Allocate the command queue. */
- + gcmkERR_BREAK(gckOS_Allocate(
- + Kernel->os,
- + QueueSize,
- + (gctPOINTER *) &command->queue
- + ));
- +
- + /* Initialize the command queue. */
- + queue = command->queue;
- +
- + queue->size = QueueSize - gcmSIZEOF(gcsKERNEL_QUEUE_HEADER);
- + queue->pending = 0;
- + queue->next = queue;
- +
- + command->queueHead =
- + command->queueTail =
- + command->mergeQueue = command->queue;
- +
- + command->queueOverflow = 0;
- +
- +
- + /***********************************************************************
- + ** Enable TS overflow interrupt.
- + */
- +
- + command->info.tsOverflowInt = 0;
- + gcmkERR_BREAK(gckVGINTERRUPT_Enable(
- + Kernel->interrupt,
- + &command->info.tsOverflowInt,
- + _EventHandler_TSOverflow
- + ));
- +
- + /* Mask out the interrupt. */
- + Kernel->hardware->eventMask &= ~(1 << command->info.tsOverflowInt);
- +
- +
- + /***********************************************************************
- + ** Enable Bus Error interrupt.
- + */
- +
- + /* Hardwired to bit 31. */
- + command->busErrorInt = 31;
- +
- + /* Enable the interrupt. */
- + gcmkERR_BREAK(gckVGINTERRUPT_Enable(
- + Kernel->interrupt,
- + &command->busErrorInt,
- + _EventHandler_BusError
- + ));
- +
- +
- + command->powerStallInt = 30;
- + /* Enable the interrupt. */
- + gcmkERR_BREAK(gckVGINTERRUPT_Enable(
- + Kernel->interrupt,
- + &command->powerStallInt,
- + _EventHandler_PowerStall
- + ));
- +
- + /***********************************************************************
- + ** Task management initialization.
- + */
- +
- + command->taskStorage = gcvNULL;
- + command->taskStorageGranularity = TaskGranularity;
- + command->taskStorageUsable = TaskGranularity - gcmSIZEOF(gcsTASK_STORAGE);
- +
- + command->taskFreeHead = gcvNULL;
- + command->taskFreeTail = gcvNULL;
- +
- + /* Enable block handlers. */
- + for (i = 0; i < gcmCOUNTOF(_blockHandlers); i += 1)
- + {
- + /* Get the target hardware block. */
- + gceBLOCK block = _blockHandlers[i].block;
- +
- + /* Get the interrupt array entry. */
- + gcsBLOCK_TASK_ENTRY_PTR entry = &command->taskTable[block];
- +
- + /* Determine the interrupt value index. */
- + gctUINT index = entry->interruptCount;
- +
- + /* Create the block semaphore. */
- + if (entry->interruptSemaphore == gcvNULL)
- + {
- + gcmkERR_BREAK(gckOS_CreateSemaphoreVG(
- + command->os, &entry->interruptSemaphore
- + ));
- + }
- +
- + /* Enable auto-detection. */
- + entry->interruptArray[index] = -1;
- +
- + /* Enable interrupt for the block. */
- + gcmkERR_BREAK(gckVGINTERRUPT_Enable(
- + Kernel->interrupt,
- + &entry->interruptArray[index],
- + _blockHandlers[i].handler
- + ));
- +
- + /* Update the number of registered interrupts. */
- + entry->interruptCount += 1;
- +
- + /* Inrement the semaphore to allow the usage of the registered
- + interrupt. */
- + gcmkERR_BREAK(gckOS_IncrementSemaphore(
- + command->os, entry->interruptSemaphore
- + ));
- +
- + }
- +
- + /* Error? */
- + if (gcmkIS_ERROR(status))
- + {
- + break;
- + }
- +
- + /* Get the FE interrupt. */
- + command->info.feBufferInt
- + = command->taskTable[gcvBLOCK_COMMAND].interruptArray[0];
- +
- + /* Return gckVGCOMMAND object pointer. */
- + *Command = command;
- +
- + gcmkFOOTER_ARG("*Command=0x%x",*Command);
- + /* Success. */
- + return gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + /* Roll back. */
- + if (command != gcvNULL)
- + {
- + /* Disable block handlers. */
- + for (i = 0; i < gcvBLOCK_COUNT; i += 1)
- + {
- + /* Get the task table entry. */
- + gcsBLOCK_TASK_ENTRY_PTR entry = &command->taskTable[i];
- +
- + /* Destroy the semaphore. */
- + if (entry->interruptSemaphore != gcvNULL)
- + {
- + gcmkCHECK_STATUS(gckOS_DestroySemaphore(
- + command->os, entry->interruptSemaphore
- + ));
- + }
- +
- + /* Disable all enabled interrupts. */
- + for (j = 0; j < entry->interruptCount; j += 1)
- + {
- + /* Must be a valid value. */
- + gcmkASSERT(entry->interruptArray[j] >= 0);
- + gcmkASSERT(entry->interruptArray[j] <= 31);
- +
- + /* Disable the interrupt. */
- + gcmkCHECK_STATUS(gckVGINTERRUPT_Disable(
- + Kernel->interrupt,
- + entry->interruptArray[j]
- + ));
- + }
- + }
- +
- + /* Disable the bus error interrupt. */
- + gcmkCHECK_STATUS(gckVGINTERRUPT_Disable(
- + Kernel->interrupt,
- + command->busErrorInt
- + ));
- +
- + /* Disable TS overflow interrupt. */
- + if (command->info.tsOverflowInt != -1)
- + {
- + gcmkCHECK_STATUS(gckVGINTERRUPT_Disable(
- + Kernel->interrupt,
- + command->info.tsOverflowInt
- + ));
- + }
- +
- + /* Delete the commit mutex. */
- + if (command->commitMutex != gcvNULL)
- + {
- + gcmkCHECK_STATUS(gckOS_DeleteMutex(
- + Kernel->os, command->commitMutex
- + ));
- + }
- +
- + /* Delete the command queue mutex. */
- + if (command->taskMutex != gcvNULL)
- + {
- + gcmkCHECK_STATUS(gckOS_DeleteMutex(
- + Kernel->os, command->taskMutex
- + ));
- + }
- +
- + /* Delete the command queue mutex. */
- + if (command->queueMutex != gcvNULL)
- + {
- + gcmkCHECK_STATUS(gckOS_DeleteMutex(
- + Kernel->os, command->queueMutex
- + ));
- + }
- +
- + /* Delete the command queue. */
- + if (command->queue != gcvNULL)
- + {
- + gcmkCHECK_STATUS(gckOS_Free(
- + Kernel->os, command->queue
- + ));
- + }
- +
- + if (command->powerSemaphore != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_DestroySemaphore(
- + Kernel->os, command->powerSemaphore));
- + }
- +
- + if (command->powerStallSignal != gcvNULL)
- + {
- + /* Create the power management semaphore. */
- + gcmkVERIFY_OK(gckOS_DestroySignal(
- + Kernel->os,
- + command->powerStallSignal));
- + }
- +
- + /* Free the gckVGCOMMAND structure. */
- + gcmkCHECK_STATUS(gckOS_Free(
- + Kernel->os, command
- + ));
- + }
- +
- + gcmkFOOTER();
- + /* Return the error. */
- + return status;
- +}
- +
- +gceSTATUS
- +gckVGCOMMAND_Destroy(
- + OUT gckVGCOMMAND Command
- + )
- +{
- + gceSTATUS status = gcvSTATUS_OK;
- +
- + gcmkHEADER_ARG("Command=0x%x", Command);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- +
- + do
- + {
- + gctUINT i;
- + gcsTASK_STORAGE_PTR nextStorage;
- +
- + if (Command->queueHead != gcvNULL)
- + {
- + /* Wait until the head becomes idle. */
- + gcmkERR_BREAK(_WaitForIdle(Command, Command->queueHead));
- + }
- +
- + /* Disable block handlers. */
- + for (i = 0; i < gcvBLOCK_COUNT; i += 1)
- + {
- + /* Get the interrupt array entry. */
- + gcsBLOCK_TASK_ENTRY_PTR entry = &Command->taskTable[i];
- +
- + /* Determine the index of the last interrupt in the array. */
- + gctINT index = entry->interruptCount - 1;
- +
- + /* Destroy the semaphore. */
- + if (entry->interruptSemaphore != gcvNULL)
- + {
- + gcmkERR_BREAK(gckOS_DestroySemaphore(
- + Command->os, entry->interruptSemaphore
- + ));
- + }
- +
- + /* Disable all enabled interrupts. */
- + while (index >= 0)
- + {
- + /* Must be a valid value. */
- + gcmkASSERT(entry->interruptArray[index] >= 0);
- + gcmkASSERT(entry->interruptArray[index] <= 31);
- +
- + /* Disable the interrupt. */
- + gcmkERR_BREAK(gckVGINTERRUPT_Disable(
- + Command->kernel->interrupt,
- + entry->interruptArray[index]
- + ));
- +
- + /* Update to the next interrupt. */
- + index -= 1;
- + entry->interruptCount -= 1;
- + }
- +
- + /* Error? */
- + if (gcmkIS_ERROR(status))
- + {
- + break;
- + }
- + }
- +
- + /* Error? */
- + if (gcmkIS_ERROR(status))
- + {
- + break;
- + }
- +
- + /* Disable the bus error interrupt. */
- + gcmkERR_BREAK(gckVGINTERRUPT_Disable(
- + Command->kernel->interrupt,
- + Command->busErrorInt
- + ));
- +
- + /* Disable TS overflow interrupt. */
- + if (Command->info.tsOverflowInt != -1)
- + {
- + gcmkERR_BREAK(gckVGINTERRUPT_Disable(
- + Command->kernel->interrupt,
- + Command->info.tsOverflowInt
- + ));
- +
- + Command->info.tsOverflowInt = -1;
- + }
- +
- + /* Delete the commit mutex. */
- + if (Command->commitMutex != gcvNULL)
- + {
- + gcmkERR_BREAK(gckOS_DeleteMutex(
- + Command->os, Command->commitMutex
- + ));
- +
- + Command->commitMutex = gcvNULL;
- + }
- +
- + /* Delete the command queue mutex. */
- + if (Command->taskMutex != gcvNULL)
- + {
- + gcmkERR_BREAK(gckOS_DeleteMutex(
- + Command->os, Command->taskMutex
- + ));
- +
- + Command->taskMutex = gcvNULL;
- + }
- +
- + /* Delete the command queue mutex. */
- + if (Command->queueMutex != gcvNULL)
- + {
- + gcmkERR_BREAK(gckOS_DeleteMutex(
- + Command->os, Command->queueMutex
- + ));
- +
- + Command->queueMutex = gcvNULL;
- + }
- +
- + if (Command->powerSemaphore != gcvNULL)
- + {
- + /* Destroy the power management semaphore. */
- + gcmkERR_BREAK(gckOS_DestroySemaphore(
- + Command->os, Command->powerSemaphore));
- + }
- +
- + if (Command->powerStallSignal != gcvNULL)
- + {
- + /* Create the power management semaphore. */
- + gcmkERR_BREAK(gckOS_DestroySignal(
- + Command->os,
- + Command->powerStallSignal));
- + }
- +
- + if (Command->queue != gcvNULL)
- + {
- + /* Delete the command queue. */
- + gcmkERR_BREAK(gckOS_Free(
- + Command->os, Command->queue
- + ));
- + }
- +
- + /* Destroy all allocated buffers. */
- + while (Command->taskStorage)
- + {
- + /* Copy the buffer pointer. */
- + nextStorage = Command->taskStorage->next;
- +
- + /* Free the current container. */
- + gcmkERR_BREAK(gckOS_Free(
- + Command->os, Command->taskStorage
- + ));
- +
- + /* Advance to the next one. */
- + Command->taskStorage = nextStorage;
- + }
- +
- + /* Error? */
- + if (gcmkIS_ERROR(status))
- + {
- + break;
- + }
- +
- + /* Mark the object as unknown. */
- + Command->object.type = gcvOBJ_UNKNOWN;
- +
- + /* Free the gckVGCOMMAND structure. */
- + gcmkERR_BREAK(gckOS_Free(Command->os, Command));
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + /* Restore the object type if failed. */
- + Command->object.type = gcvOBJ_COMMAND;
- +
- + gcmkFOOTER();
- + /* Return the error. */
- + return status;
- +}
- +
- +gceSTATUS
- +gckVGCOMMAND_QueryCommandBuffer(
- + IN gckVGCOMMAND Command,
- + OUT gcsCOMMAND_BUFFER_INFO_PTR Information
- + )
- +{
- + gcmkHEADER_ARG("Command=0x%x Information=0x%x", Command, Information);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- + gcmkVERIFY_ARGUMENT(Information != gcvNULL);
- +
- + /* Copy the information. */
- + gcmkVERIFY_OK(gckOS_MemCopy(
- + Information, &Command->info, sizeof(gcsCOMMAND_BUFFER_INFO)
- + ));
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckVGCOMMAND_Allocate(
- + IN gckVGCOMMAND Command,
- + IN gctSIZE_T Size,
- + OUT gcsCMDBUFFER_PTR * CommandBuffer,
- + OUT gctPOINTER * Data
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Command=0x%x Size=0x%x CommandBuffer=0x%x Data=0x%x",
- + Command, Size, CommandBuffer, Data);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- + gcmkVERIFY_ARGUMENT(Data != gcvNULL);
- +
- + do
- + {
- + /* Allocate the buffer. */
- + gcmkERR_BREAK(_AllocateCommandBuffer(Command, Size, CommandBuffer));
- +
- + /* Determine the data pointer. */
- + * Data = (gctUINT8_PTR) (*CommandBuffer) + (* CommandBuffer)->bufferOffset;
- + }
- + while (gcvFALSE);
- +
- + gcmkFOOTER();
- + /* Return status. */
- + return status;
- +}
- +
- +gceSTATUS
- +gckVGCOMMAND_Free(
- + IN gckVGCOMMAND Command,
- + IN gcsCMDBUFFER_PTR CommandBuffer
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Command=0x%x CommandBuffer=0x%x",
- + Command, CommandBuffer);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- + gcmkVERIFY_ARGUMENT(CommandBuffer != gcvNULL);
- +
- + /* Free command buffer. */
- + status = _FreeCommandBuffer(Command->kernel, CommandBuffer);
- +
- + gcmkFOOTER();
- + /* Return status. */
- + return status;
- +}
- +
- +gceSTATUS
- +gckVGCOMMAND_Execute(
- + IN gckVGCOMMAND Command,
- + IN gcsCMDBUFFER_PTR CommandBuffer
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Command=0x%x CommandBuffer=0x%x",
- + Command, CommandBuffer);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- + gcmkVERIFY_ARGUMENT(CommandBuffer != gcvNULL);
- +
- + do
- + {
- + gctUINT queueLength;
- + gcsKERNEL_CMDQUEUE_PTR kernelEntry;
- +
- + /* Lock the current queue. */
- + gcmkERR_BREAK(_LockCurrentQueue(
- + Command, &kernelEntry, &queueLength
- + ));
- +
- + /* Set the buffer. */
- + kernelEntry->commandBuffer = CommandBuffer;
- + kernelEntry->handler = _FreeKernelCommandBuffer;
- +
- + /* Lock the current queue. */
- + gcmkERR_BREAK(_UnlockCurrentQueue(
- + Command, 1
- + ));
- + }
- + while (gcvFALSE);
- +
- + gcmkFOOTER();
- + /* Return status. */
- + return status;
- +}
- +
- +gceSTATUS
- +gckVGCOMMAND_Commit(
- + IN gckVGCOMMAND Command,
- + IN gcsVGCONTEXT_PTR Context,
- + IN gcsVGCMDQUEUE_PTR Queue,
- + IN gctUINT EntryCount,
- + IN gcsTASK_MASTER_TABLE_PTR TaskTable
- + )
- +{
- + /*
- + The first buffer is executed through a direct gckVGHARDWARE_Execute call,
- + therefore only an update is needed after the execution is over. All
- + consequent buffers need to be executed upon the first update call from
- + the FE interrupt handler.
- + */
- +
- + static gcsQUEUE_UPDATE_CONTROL _dynamicBuffer[] =
- + {
- + {
- + _UpdateDynamicCommandBuffer,
- + _UpdateDynamicCommandBuffer,
- + _UpdateLastDynamicCommandBuffer,
- + _UpdateLastDynamicCommandBuffer
- + },
- + {
- + _ExecuteDynamicCommandBuffer,
- + _UpdateDynamicCommandBuffer,
- + _ExecuteLastDynamicCommandBuffer,
- + _UpdateLastDynamicCommandBuffer
- + }
- + };
- +
- + static gcsQUEUE_UPDATE_CONTROL _staticBuffer[] =
- + {
- + {
- + _UpdateStaticCommandBuffer,
- + _UpdateStaticCommandBuffer,
- + _UpdateLastStaticCommandBuffer,
- + _UpdateLastStaticCommandBuffer
- + },
- + {
- + _ExecuteStaticCommandBuffer,
- + _UpdateStaticCommandBuffer,
- + _ExecuteLastStaticCommandBuffer,
- + _UpdateLastStaticCommandBuffer
- + }
- + };
- +
- + gceSTATUS status, last;
- +
- + gcmkHEADER_ARG("Command=0x%x Context=0x%x Queue=0x%x EntryCount=0x%x TaskTable=0x%x",
- + Command, Context, Queue, EntryCount, TaskTable);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
- + gcmkVERIFY_ARGUMENT(Context != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Queue != gcvNULL);
- + gcmkVERIFY_ARGUMENT(EntryCount > 1);
- +
- +#ifdef __QNXNTO__
- + TaskTable->coid = Context->coid;
- + TaskTable->rcvid = Context->rcvid;
- +#endif /* __QNXNTO__ */
- +
- + do
- + {
- + gctBOOL haveFETasks;
- + gctUINT queueSize;
- + gcsVGCMDQUEUE_PTR mappedQueue;
- + gcsVGCMDQUEUE_PTR userEntry;
- + gcsKERNEL_CMDQUEUE_PTR kernelEntry;
- + gcsQUEUE_UPDATE_CONTROL_PTR queueControl;
- + gctUINT currentLength;
- + gctUINT queueLength;
- + gctUINT entriesQueued;
- + gctUINT8_PTR previousEnd;
- + gctBOOL previousDynamic;
- + gctBOOL previousExecuted;
- + gctUINT controlIndex;
- +
- + gcmkERR_BREAK(gckVGHARDWARE_SetPowerManagementState(
- + Command->hardware, gcvPOWER_ON_AUTO
- + ));
- +
- + /* Acquire the power semaphore. */
- + gcmkERR_BREAK(gckOS_AcquireSemaphore(
- + Command->os, Command->powerSemaphore
- + ));
- +
- + /* Acquire the mutex. */
- + status = gckOS_AcquireMutex(
- + Command->os,
- + Command->commitMutex,
- + gcvINFINITE
- + );
- +
- + if (gcmIS_ERROR(status))
- + {
- + gcmkVERIFY_OK(gckOS_ReleaseSemaphore(
- + Command->os, Command->powerSemaphore));
- + break;
- + }
- +
- + do
- + {
- + gcmkERR_BREAK(_FlushMMU(Command));
- +
- + /* Assign a context ID if not yet assigned. */
- + if (Context->id == 0)
- + {
- + /* Assign the next context number. */
- + Context->id = ++ Command->contextCounter;
- +
- + /* See if we overflowed. */
- + if (Command->contextCounter == 0)
- + {
- + /* We actually did overflow, wow... */
- + status = gcvSTATUS_OUT_OF_RESOURCES;
- + break;
- + }
- + }
- +
- + /* The first entry in the queue is always the context buffer.
- + Verify whether the user context is the same as the current
- + context and if that's the case, skip the first entry. */
- + if (Context->id == Command->currentContext)
- + {
- + /* Same context as before, skip the first entry. */
- + EntryCount -= 1;
- + Queue += 1;
- +
- + /* Set the signal to avoid user waiting. */
- +#ifdef __QNXNTO__
- + gcmkERR_BREAK(gckOS_UserSignal(
- + Command->os, Context->signal, Context->rcvid, Context->coid
- + ));
- +#else
- + gcmkERR_BREAK(gckOS_UserSignal(
- + Command->os, Context->signal, Context->process
- + ));
- +
- +#endif /* __QNXNTO__ */
- +
- + }
- + else
- + {
- + /* Different user context - keep the first entry.
- + Set the user context as the current one. */
- + Command->currentContext = Context->id;
- + }
- +
- + /* Reset pointers. */
- + queueControl = gcvNULL;
- + previousEnd = gcvNULL;
- +
- + /* Determine whether there are FE tasks to be performed. */
- + haveFETasks = (TaskTable->table[gcvBLOCK_COMMAND].head != gcvNULL);
- +
- + /* Determine the size of the queue. */
- + queueSize = EntryCount * gcmSIZEOF(gcsVGCMDQUEUE);
- +
- + /* Map the command queue into the kernel space. */
- + gcmkERR_BREAK(gckOS_MapUserPointer(
- + Command->os,
- + Queue,
- + queueSize,
- + (gctPOINTER *) &mappedQueue
- + ));
- +
- + /* Set the first entry. */
- + userEntry = mappedQueue;
- +
- + /* Process the command queue. */
- + while (EntryCount)
- + {
- + /* Lock the current queue. */
- + gcmkERR_BREAK(_LockCurrentQueue(
- + Command, &kernelEntry, &queueLength
- + ));
- +
- + /* Determine the number of entries to process. */
- + currentLength = (queueLength < EntryCount)
- + ? queueLength
- + : EntryCount;
- +
- + /* Update the number of the entries left to process. */
- + EntryCount -= currentLength;
- +
- + /* Reset previous flags. */
- + previousDynamic = gcvFALSE;
- + previousExecuted = gcvFALSE;
- +
- + /* Set the initial control index. */
- + controlIndex = 0;
- +
- + /* Process entries. */
- + for (entriesQueued = 0; entriesQueued < currentLength; entriesQueued += 1)
- + {
- + /* Get the kernel pointer to the command buffer header. */
- + gcsCMDBUFFER_PTR commandBuffer = gcvNULL;
- + gcmkERR_BREAK(_ConvertUserCommandBufferPointer(
- + Command,
- + userEntry->commandBuffer,
- + &commandBuffer
- + ));
- +
- + /* Is it a dynamic command buffer? */
- + if (userEntry->dynamic)
- + {
- + /* Select dynamic buffer control functions. */
- + queueControl = &_dynamicBuffer[controlIndex];
- + }
- +
- + /* No, a static command buffer. */
- + else
- + {
- + /* Select static buffer control functions. */
- + queueControl = &_staticBuffer[controlIndex];
- + }
- +
- + /* Set the command buffer pointer to the entry. */
- + kernelEntry->commandBuffer = commandBuffer;
- +
- + /* If the previous entry was a dynamic command buffer,
- + link it to the current. */
- + if (previousDynamic)
- + {
- + gcmkERR_BREAK(gckVGCOMMAND_FetchCommand(
- + Command,
- + previousEnd,
- + commandBuffer->address,
- + commandBuffer->dataCount,
- + gcvNULL
- + ));
- +
- + /* The buffer will be auto-executed, only need to
- + update it after it has been executed. */
- + kernelEntry->handler = queueControl->update;
- +
- + /* The buffer is only being updated. */
- + previousExecuted = gcvFALSE;
- + }
- + else
- + {
- + /* Set the buffer up for execution. */
- + kernelEntry->handler = queueControl->execute;
- +
- + /* The buffer is being updated. */
- + previousExecuted = gcvTRUE;
- + }
- +
- + /* The current buffer's END command becomes the last END. */
- + previousEnd
- + = ((gctUINT8_PTR) commandBuffer)
- + + commandBuffer->bufferOffset
- + + commandBuffer->dataCount * Command->info.commandAlignment
- + - Command->info.staticTailSize;
- +
- + /* Update the last entry info. */
- + previousDynamic = userEntry->dynamic;
- +
- + /* Advance entries. */
- + userEntry += 1;
- + kernelEntry += 1;
- +
- + /* Update the control index. */
- + controlIndex = 1;
- + }
- +
- + /* If the previous entry was a dynamic command buffer,
- + terminate it with an END. */
- + if (previousDynamic)
- + {
- + gcmkERR_BREAK(gckVGCOMMAND_EndCommand(
- + Command,
- + previousEnd,
- + Command->info.feBufferInt,
- + gcvNULL
- + ));
- + }
- +
- + /* Last buffer? */
- + if (EntryCount == 0)
- + {
- + /* Modify the last command buffer's routines to handle
- + tasks if any.*/
- + if (haveFETasks)
- + {
- + if (previousExecuted)
- + {
- + kernelEntry[-1].handler = queueControl->lastExecute;
- + }
- + else
- + {
- + kernelEntry[-1].handler = queueControl->lastUpdate;
- + }
- + }
- +
- + /* Release the mutex. */
- + gcmkERR_BREAK(gckOS_ReleaseMutex(
- + Command->os,
- + Command->queueMutex
- + ));
- + /* Schedule tasks. */
- + gcmkERR_BREAK(_ScheduleTasks(Command, TaskTable, previousEnd));
- +
- + /* Acquire the mutex. */
- + gcmkERR_BREAK(gckOS_AcquireMutex(
- + Command->os,
- + Command->queueMutex,
- + gcvINFINITE
- + ));
- + }
- +
- + /* Unkock and schedule the current queue for execution. */
- + gcmkERR_BREAK(_UnlockCurrentQueue(
- + Command, currentLength
- + ));
- + }
- +
- +
- + /* Unmap the user command buffer. */
- + gcmkERR_BREAK(gckOS_UnmapUserPointer(
- + Command->os,
- + Queue,
- + queueSize,
- + mappedQueue
- + ));
- + }
- + while (gcvFALSE);
- +
- + /* Release the mutex. */
- + gcmkCHECK_STATUS(gckOS_ReleaseMutex(
- + Command->os,
- + Command->commitMutex
- + ));
- +
- + gcmkVERIFY_OK(gckOS_ReleaseSemaphore(
- + Command->os, Command->powerSemaphore));
- + }
- + while (gcvFALSE);
- +
- + gcmkFOOTER();
- + /* Return status. */
- + return status;
- +}
- +
- +#endif /* gcdENABLE_VG */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c 2015-03-08 14:27:37.633684500 -0500
- @@ -0,0 +1,1604 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal_kernel_precomp.h"
- +
- +#define _GC_OBJ_ZONE gcvZONE_DATABASE
- +
- +/*******************************************************************************
- +***** Private fuctions ********************************************************/
- +
- +#define _GetSlot(database, x) \
- + (gctUINT32)(((gcmPTR_TO_UINT64(x) >> 7) % gcmCOUNTOF(database->list)))
- +
- +/*******************************************************************************
- +** gckKERNEL_NewDatabase
- +**
- +** Create a new database structure and insert it to the head of the hash list.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to a gckKERNEL object.
- +**
- +** gctUINT32 ProcessID
- +** ProcessID that identifies the database.
- +**
- +** OUTPUT:
- +**
- +** gcsDATABASE_PTR * Database
- +** Pointer to a variable receiving the database structure pointer on
- +** success.
- +*/
- +static gceSTATUS
- +gckKERNEL_NewDatabase(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 ProcessID,
- + OUT gcsDATABASE_PTR * Database
- + )
- +{
- + gceSTATUS status;
- + gcsDATABASE_PTR database;
- + gctBOOL acquired = gcvFALSE;
- + gctSIZE_T slot;
- + gcsDATABASE_PTR existingDatabase;
- +
- + gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
- +
- + /* Acquire the database mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + /* Compute the hash for the database. */
- + slot = ProcessID % gcmCOUNTOF(Kernel->db->db);
- +
- + /* Walk the hash list. */
- + for (existingDatabase = Kernel->db->db[slot];
- + existingDatabase != gcvNULL;
- + existingDatabase = existingDatabase->next)
- + {
- + if (existingDatabase->processID == ProcessID)
- + {
- + /* One process can't be added twice. */
- + gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
- + }
- + }
- +
- + if (Kernel->db->freeDatabase != gcvNULL)
- + {
- + /* Allocate a database from the free list. */
- + database = Kernel->db->freeDatabase;
- + Kernel->db->freeDatabase = database->next;
- + }
- + else
- + {
- + gctPOINTER pointer = gcvNULL;
- +
- + /* Allocate a new database from the heap. */
- + gcmkONERROR(gckOS_Allocate(Kernel->os,
- + gcmSIZEOF(gcsDATABASE),
- + &pointer));
- +
- + database = pointer;
- + }
- +
- + /* Insert the database into the hash. */
- + database->next = Kernel->db->db[slot];
- + Kernel->db->db[slot] = database;
- +
- + /* Save the hash slot. */
- + database->slot = slot;
- +
- + /* Release the database mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
- +
- + /* Return the database. */
- + *Database = database;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Database=0x%x", *Database);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + /* Release the database mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +** gckKERNEL_FindDatabase
- +**
- +** Find a database identified by a process ID and move it to the head of the
- +** hash list.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to a gckKERNEL object.
- +**
- +** gctUINT32 ProcessID
- +** ProcessID that identifies the database.
- +**
- +** gctBOOL LastProcessID
- +** gcvTRUE if searching for the last known process ID. gcvFALSE if
- +** we need to search for the process ID specified by the ProcessID
- +** argument.
- +**
- +** OUTPUT:
- +**
- +** gcsDATABASE_PTR * Database
- +** Pointer to a variable receiving the database structure pointer on
- +** success.
- +*/
- +static gceSTATUS
- +gckKERNEL_FindDatabase(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 ProcessID,
- + IN gctBOOL LastProcessID,
- + OUT gcsDATABASE_PTR * Database
- + )
- +{
- + gceSTATUS status;
- + gcsDATABASE_PTR database, previous;
- + gctSIZE_T slot;
- + gctBOOL acquired = gcvFALSE;
- +
- + gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d LastProcessID=%d",
- + Kernel, ProcessID, LastProcessID);
- +
- + /* Compute the hash for the database. */
- + slot = ProcessID % gcmCOUNTOF(Kernel->db->db);
- +
- + /* Acquire the database mutex. */
- + gcmkONERROR(
- + gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + /* Check whether we are getting the last known database. */
- + if (LastProcessID)
- + {
- + /* Use last database. */
- + database = Kernel->db->lastDatabase;
- +
- + if (database == gcvNULL)
- + {
- + /* Database not found. */
- + gcmkONERROR(gcvSTATUS_INVALID_DATA);
- + }
- + }
- + else
- + {
- + /* Walk the hash list. */
- + for (previous = gcvNULL, database = Kernel->db->db[slot];
- + database != gcvNULL;
- + database = database->next)
- + {
- + if (database->processID == ProcessID)
- + {
- + /* Found it! */
- + break;
- + }
- +
- + previous = database;
- + }
- +
- + if (database == gcvNULL)
- + {
- + /* Database not found. */
- + gcmkONERROR(gcvSTATUS_INVALID_DATA);
- + }
- +
- + if (previous != gcvNULL)
- + {
- + /* Move database to the head of the hash list. */
- + previous->next = database->next;
- + database->next = Kernel->db->db[slot];
- + Kernel->db->db[slot] = database;
- + }
- + }
- +
- + /* Release the database mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
- +
- + /* Return the database. */
- + *Database = database;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Database=0x%x", *Database);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + /* Release the database mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +** gckKERNEL_DeleteDatabase
- +**
- +** Remove a database from the hash list and delete its structure.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to a gckKERNEL object.
- +**
- +** gcsDATABASE_PTR Database
- +** Pointer to the database structure to remove.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +static gceSTATUS
- +gckKERNEL_DeleteDatabase(
- + IN gckKERNEL Kernel,
- + IN gcsDATABASE_PTR Database
- + )
- +{
- + gceSTATUS status;
- + gctBOOL acquired = gcvFALSE;
- + gcsDATABASE_PTR database;
- +
- + gcmkHEADER_ARG("Kernel=0x%x Database=0x%x", Kernel, Database);
- +
- + /* Acquire the database mutex. */
- + gcmkONERROR(
- + gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + /* Check slot value. */
- + gcmkVERIFY_ARGUMENT(Database->slot < gcmCOUNTOF(Kernel->db->db));
- +
- + if (Database->slot < gcmCOUNTOF(Kernel->db->db))
- + {
- + /* Check if database if the head of the hash list. */
- + if (Kernel->db->db[Database->slot] == Database)
- + {
- + /* Remove the database from the hash list. */
- + Kernel->db->db[Database->slot] = Database->next;
- + }
- + else
- + {
- + /* Walk the has list to find the database. */
- + for (database = Kernel->db->db[Database->slot];
- + database != gcvNULL;
- + database = database->next
- + )
- + {
- + /* Check if the next list entry is this database. */
- + if (database->next == Database)
- + {
- + /* Remove the database from the hash list. */
- + database->next = Database->next;
- + break;
- + }
- + }
- +
- + if (database == gcvNULL)
- + {
- + /* Ouch! Something got corrupted. */
- + gcmkONERROR(gcvSTATUS_INVALID_DATA);
- + }
- + }
- + }
- +
- + if (Kernel->db->lastDatabase != gcvNULL)
- + {
- + /* Insert database to the free list. */
- + Kernel->db->lastDatabase->next = Kernel->db->freeDatabase;
- + Kernel->db->freeDatabase = Kernel->db->lastDatabase;
- + }
- +
- + /* Keep database as the last database. */
- + Kernel->db->lastDatabase = Database;
- +
- + /* Release the database mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + /* Release the database mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +** gckKERNEL_NewRecord
- +**
- +** Create a new database record structure and insert it to the head of the
- +** database.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to a gckKERNEL object.
- +**
- +** gcsDATABASE_PTR Database
- +** Pointer to a database structure.
- +**
- +** OUTPUT:
- +**
- +** gcsDATABASE_RECORD_PTR * Record
- +** Pointer to a variable receiving the database record structure
- +** pointer on success.
- +*/
- +static gceSTATUS
- +gckKERNEL_NewRecord(
- + IN gckKERNEL Kernel,
- + IN gcsDATABASE_PTR Database,
- + IN gctUINT32 Slot,
- + OUT gcsDATABASE_RECORD_PTR * Record
- + )
- +{
- + gceSTATUS status;
- + gctBOOL acquired = gcvFALSE;
- + gcsDATABASE_RECORD_PTR record = gcvNULL;
- +
- + gcmkHEADER_ARG("Kernel=0x%x Database=0x%x", Kernel, Database);
- +
- + /* Acquire the database mutex. */
- + gcmkONERROR(
- + gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + if (Kernel->db->freeRecord != gcvNULL)
- + {
- + /* Allocate the record from the free list. */
- + record = Kernel->db->freeRecord;
- + Kernel->db->freeRecord = record->next;
- + }
- + else
- + {
- + gctPOINTER pointer = gcvNULL;
- +
- + /* Allocate the record from the heap. */
- + gcmkONERROR(gckOS_Allocate(Kernel->os,
- + gcmSIZEOF(gcsDATABASE_RECORD),
- + &pointer));
- +
- + record = pointer;
- + }
- +
- + /* Insert the record in the database. */
- + record->next = Database->list[Slot];
- + Database->list[Slot] = record;
- +
- + /* Release the database mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
- +
- + /* Return the record. */
- + *Record = record;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Record=0x%x", *Record);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + /* Release the database mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
- + }
- + if (record != gcvNULL)
- + {
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, record));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +** gckKERNEL_DeleteRecord
- +**
- +** Remove a database record from the database and delete its structure.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to a gckKERNEL object.
- +**
- +** gcsDATABASE_PTR Database
- +** Pointer to a database structure.
- +**
- +** gceDATABASE_TYPE Type
- +** Type of the record to remove.
- +**
- +** gctPOINTER Data
- +** Data of the record to remove.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T_PTR Bytes
- +** Pointer to a variable that receives the size of the record deleted.
- +** Can be gcvNULL if the size is not required.
- +*/
- +static gceSTATUS
- +gckKERNEL_DeleteRecord(
- + IN gckKERNEL Kernel,
- + IN gcsDATABASE_PTR Database,
- + IN gceDATABASE_TYPE Type,
- + IN gctPOINTER Data,
- + OUT gctSIZE_T_PTR Bytes OPTIONAL
- + )
- +{
- + gceSTATUS status;
- + gctBOOL acquired = gcvFALSE;
- + gcsDATABASE_RECORD_PTR record, previous;
- + gctUINT32 slot = _GetSlot(Database, Data);
- +
- + gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
- + Kernel, Database, Type, Data);
- +
- + /* Acquire the database mutex. */
- + gcmkONERROR(
- + gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- +
- + /* Scan the database for this record. */
- + for (record = Database->list[slot], previous = gcvNULL;
- + record != gcvNULL;
- + record = record->next
- + )
- + {
- + if ((record->type == Type)
- + && (record->data == Data)
- + )
- + {
- + /* Found it! */
- + break;
- + }
- +
- + previous = record;
- + }
- +
- + if (record == gcvNULL)
- + {
- + /* Ouch! This record is not found? */
- + gcmkONERROR(gcvSTATUS_INVALID_DATA);
- + }
- +
- + if (Bytes != gcvNULL)
- + {
- + /* Return size of record. */
- + *Bytes = record->bytes;
- + }
- +
- + /* Remove record from database. */
- + if (previous == gcvNULL)
- + {
- + Database->list[slot] = record->next;
- + }
- + else
- + {
- + previous->next = record->next;
- + }
- +
- + /* Insert record in free list. */
- + record->next = Kernel->db->freeRecord;
- + Kernel->db->freeRecord = record;
- +
- + /* Release the database mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + /* Release the database mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +** gckKERNEL_FindRecord
- +**
- +** Find a database record from the database.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to a gckKERNEL object.
- +**
- +** gcsDATABASE_PTR Database
- +** Pointer to a database structure.
- +**
- +** gceDATABASE_TYPE Type
- +** Type of the record to remove.
- +**
- +** gctPOINTER Data
- +** Data of the record to remove.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T_PTR Bytes
- +** Pointer to a variable that receives the size of the record deleted.
- +** Can be gcvNULL if the size is not required.
- +*/
- +static gceSTATUS
- +gckKERNEL_FindRecord(
- + IN gckKERNEL Kernel,
- + IN gcsDATABASE_PTR Database,
- + IN gceDATABASE_TYPE Type,
- + IN gctPOINTER Data,
- + OUT gcsDATABASE_RECORD_PTR Record
- + )
- +{
- + gceSTATUS status;
- + gctBOOL acquired = gcvFALSE;
- + gcsDATABASE_RECORD_PTR record;
- + gctUINT32 slot = _GetSlot(Database, Data);
- +
- + gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
- + Kernel, Database, Type, Data);
- +
- + /* Acquire the database mutex. */
- + gcmkONERROR(
- + gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + /* Scan the database for this record. */
- + for (record = Database->list[slot];
- + record != gcvNULL;
- + record = record->next
- + )
- + {
- + if ((record->type == Type)
- + && (record->data == Data)
- + )
- + {
- + /* Found it! */
- + break;
- + }
- + }
- +
- + if (record == gcvNULL)
- + {
- + /* Ouch! This record is not found? */
- + gcmkONERROR(gcvSTATUS_INVALID_DATA);
- + }
- +
- + if (Record != gcvNULL)
- + {
- + /* Return information of record. */
- + gcmkONERROR(
- + gckOS_MemCopy(Record, record, sizeof(gcsDATABASE_RECORD)));
- + }
- +
- + /* Release the database mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
- +
- + /* Success. */
- + gcmkFOOTER_ARG("Record=0x%x", Record);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + /* Release the database mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +
- +/*******************************************************************************
- +***** Public API **************************************************************/
- +
- +/*******************************************************************************
- +** gckKERNEL_CreateProcessDB
- +**
- +** Create a new process database.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to a gckKERNEL object.
- +**
- +** gctUINT32 ProcessID
- +** Process ID used to identify the database.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckKERNEL_CreateProcessDB(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 ProcessID
- + )
- +{
- + gceSTATUS status;
- + gcsDATABASE_PTR database = gcvNULL;
- + gctUINT32 i;
- +
- + gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- +
- + /* Create a new database. */
- + gcmkONERROR(gckKERNEL_NewDatabase(Kernel, ProcessID, &database));
- +
- + /* Initialize the database. */
- + database->processID = ProcessID;
- + database->vidMem.bytes = 0;
- + database->vidMem.maxBytes = 0;
- + database->vidMem.totalBytes = 0;
- + database->nonPaged.bytes = 0;
- + database->nonPaged.maxBytes = 0;
- + database->nonPaged.totalBytes = 0;
- + database->contiguous.bytes = 0;
- + database->contiguous.maxBytes = 0;
- + database->contiguous.totalBytes = 0;
- + database->mapMemory.bytes = 0;
- + database->mapMemory.maxBytes = 0;
- + database->mapMemory.totalBytes = 0;
- + database->mapUserMemory.bytes = 0;
- + database->mapUserMemory.maxBytes = 0;
- + database->mapUserMemory.totalBytes = 0;
- + database->vidMemResv.bytes = 0;
- + database->vidMemResv.maxBytes = 0;
- + database->vidMemResv.totalBytes = 0;
- + database->vidMemCont.bytes = 0;
- + database->vidMemCont.maxBytes = 0;
- + database->vidMemCont.totalBytes = 0;
- + database->vidMemVirt.bytes = 0;
- + database->vidMemVirt.maxBytes = 0;
- + database->vidMemVirt.totalBytes = 0;
- +
- + for (i = 0; i < gcmCOUNTOF(database->list); i++)
- + {
- + database->list[i] = gcvNULL;
- + }
- +
- +#if gcdSECURE_USER
- + {
- + gctINT slot;
- + gcskSECURE_CACHE * cache = &database->cache;
- +
- + /* Setup the linked list of cache nodes. */
- + for (slot = 1; slot <= gcdSECURE_CACHE_SLOTS; ++slot)
- + {
- + cache->cache[slot].logical = gcvNULL;
- +
- +#if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
- + cache->cache[slot].prev = &cache->cache[slot - 1];
- + cache->cache[slot].next = &cache->cache[slot + 1];
- +# endif
- +#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
- + cache->cache[slot].nextHash = gcvNULL;
- + cache->cache[slot].prevHash = gcvNULL;
- +# endif
- + }
- +
- +#if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
- + /* Setup the head and tail of the cache. */
- + cache->cache[0].next = &cache->cache[1];
- + cache->cache[0].prev = &cache->cache[gcdSECURE_CACHE_SLOTS];
- + cache->cache[0].logical = gcvNULL;
- +
- + /* Fix up the head and tail pointers. */
- + cache->cache[0].next->prev = &cache->cache[0];
- + cache->cache[0].prev->next = &cache->cache[0];
- +# endif
- +
- +#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
- + /* Zero out the hash table. */
- + for (slot = 0; slot < gcmCOUNTOF(cache->hash); ++slot)
- + {
- + cache->hash[slot].logical = gcvNULL;
- + cache->hash[slot].nextHash = gcvNULL;
- + }
- +# endif
- +
- + /* Initialize cache index. */
- + cache->cacheIndex = gcvNULL;
- + cache->cacheFree = 1;
- + cache->cacheStamp = 0;
- + }
- +#endif
- +
- + /* Reset idle timer. */
- + Kernel->db->lastIdle = 0;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +** gckKERNEL_AddProcessDB
- +**
- +** Add a record to a process database.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to a gckKERNEL object.
- +**
- +** gctUINT32 ProcessID
- +** Process ID used to identify the database.
- +**
- +** gceDATABASE_TYPE TYPE
- +** Type of the record to add.
- +**
- +** gctPOINTER Pointer
- +** Data of the record to add.
- +**
- +** gctPHYS_ADDR Physical
- +** Physical address of the record to add.
- +**
- +** gctSIZE_T Size
- +** Size of the record to add.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckKERNEL_AddProcessDB(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 ProcessID,
- + IN gceDATABASE_TYPE Type,
- + IN gctPOINTER Pointer,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Size
- + )
- +{
- + gceSTATUS status;
- + gcsDATABASE_PTR database;
- + gcsDATABASE_RECORD_PTR record = gcvNULL;
- + gcsDATABASE_COUNTERS * count;
- +
- + gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x "
- + "Physical=0x%x Size=%lu",
- + Kernel, ProcessID, Type, Pointer, Physical, Size);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- +
- + /* Special case the idle record. */
- + if (Type == gcvDB_IDLE)
- + {
- + gctUINT64 time;
- +
- + /* Get the current profile time. */
- + gcmkONERROR(gckOS_GetProfileTick(&time));
- +
- + if ((ProcessID == 0) && (Kernel->db->lastIdle != 0))
- + {
- + /* Out of idle, adjust time it was idle. */
- + Kernel->db->idleTime += time - Kernel->db->lastIdle;
- + Kernel->db->lastIdle = 0;
- + }
- + else if (ProcessID == 1)
- + {
- + /* Save current idle time. */
- + Kernel->db->lastIdle = time;
- + }
- +
- +#if gcdDYNAMIC_SPEED
- + {
- + /* Test for first call. */
- + if (Kernel->db->lastSlowdown == 0)
- + {
- + /* Save milliseconds. */
- + Kernel->db->lastSlowdown = time;
- + Kernel->db->lastSlowdownIdle = Kernel->db->idleTime;
- + }
- + else
- + {
- + /* Compute ellapsed time in milliseconds. */
- + gctUINT delta = gckOS_ProfileToMS(time - Kernel->db->lastSlowdown);
- +
- + /* Test for end of period. */
- + if (delta >= gcdDYNAMIC_SPEED)
- + {
- + /* Compute number of idle milliseconds. */
- + gctUINT idle = gckOS_ProfileToMS(
- + Kernel->db->idleTime - Kernel->db->lastSlowdownIdle);
- +
- + /* Broadcast to slow down the GPU. */
- + gcmkONERROR(gckOS_BroadcastCalibrateSpeed(Kernel->os,
- + Kernel->hardware,
- + idle,
- + delta));
- +
- + /* Save current time. */
- + Kernel->db->lastSlowdown = time;
- + Kernel->db->lastSlowdownIdle = Kernel->db->idleTime;
- + }
- + }
- + }
- +#endif
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
- +
- + /* Find the database. */
- + gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
- +
- + /* Create a new record in the database. */
- + gcmkONERROR(gckKERNEL_NewRecord(Kernel, database, _GetSlot(database, Pointer), &record));
- +
- + /* Initialize the record. */
- + record->kernel = Kernel;
- + record->type = Type;
- + record->data = Pointer;
- + record->physical = Physical;
- + record->bytes = Size;
- +
- + /* Get pointer to counters. */
- + switch (Type)
- + {
- + case gcvDB_VIDEO_MEMORY:
- + count = &database->vidMem;
- + break;
- +
- + case gcvDB_NON_PAGED:
- + count = &database->nonPaged;
- + break;
- +
- + case gcvDB_CONTIGUOUS:
- + count = &database->contiguous;
- + break;
- +
- + case gcvDB_MAP_MEMORY:
- + count = &database->mapMemory;
- + break;
- +
- + case gcvDB_MAP_USER_MEMORY:
- + count = &database->mapUserMemory;
- + break;
- +
- + case gcvDB_VIDEO_MEMORY_RESERVED:
- + count = &database->vidMemResv;
- + break;
- +
- + case gcvDB_VIDEO_MEMORY_CONTIGUOUS:
- + count = &database->vidMemCont;
- + break;
- +
- + case gcvDB_VIDEO_MEMORY_VIRTUAL:
- + count = &database->vidMemVirt;
- + break;
- +
- + default:
- + count = gcvNULL;
- + break;
- + }
- +
- + if (count != gcvNULL)
- + {
- + /* Adjust counters. */
- + count->totalBytes += Size;
- + count->bytes += Size;
- +
- + if (count->bytes > count->maxBytes)
- + {
- + count->maxBytes = count->bytes;
- + }
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +** gckKERNEL_RemoveProcessDB
- +**
- +** Remove a record from a process database.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to a gckKERNEL object.
- +**
- +** gctUINT32 ProcessID
- +** Process ID used to identify the database.
- +**
- +** gceDATABASE_TYPE TYPE
- +** Type of the record to remove.
- +**
- +** gctPOINTER Pointer
- +** Data of the record to remove.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckKERNEL_RemoveProcessDB(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 ProcessID,
- + IN gceDATABASE_TYPE Type,
- + IN gctPOINTER Pointer
- + )
- +{
- + gceSTATUS status;
- + gcsDATABASE_PTR database;
- + gctSIZE_T bytes = 0;
- +
- + gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x",
- + Kernel, ProcessID, Type, Pointer);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
- +
- + /* Find the database. */
- + gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
- +
- + /* Delete the record. */
- + gcmkONERROR(
- + gckKERNEL_DeleteRecord(Kernel, database, Type, Pointer, &bytes));
- +
- + /* Update counters. */
- + switch (Type)
- + {
- + case gcvDB_VIDEO_MEMORY:
- + database->vidMem.bytes -= bytes;
- + break;
- +
- + case gcvDB_NON_PAGED:
- + database->nonPaged.bytes -= bytes;
- + break;
- +
- + case gcvDB_CONTIGUOUS:
- + database->contiguous.bytes -= bytes;
- + break;
- +
- + case gcvDB_MAP_MEMORY:
- + database->mapMemory.bytes -= bytes;
- + break;
- +
- + case gcvDB_MAP_USER_MEMORY:
- + database->mapUserMemory.bytes -= bytes;
- + break;
- +
- + case gcvDB_VIDEO_MEMORY_RESERVED:
- + database->vidMemResv.bytes -= bytes;
- + break;
- +
- + case gcvDB_VIDEO_MEMORY_CONTIGUOUS:
- + database->vidMemCont.bytes -= bytes;
- + break;
- +
- + case gcvDB_VIDEO_MEMORY_VIRTUAL:
- + database->vidMemVirt.bytes -= bytes;
- + break;
- +
- + default:
- + break;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +** gckKERNEL_FindProcessDB
- +**
- +** Find a record from a process database.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to a gckKERNEL object.
- +**
- +** gctUINT32 ProcessID
- +** Process ID used to identify the database.
- +**
- +** gceDATABASE_TYPE TYPE
- +** Type of the record to remove.
- +**
- +** gctPOINTER Pointer
- +** Data of the record to remove.
- +**
- +** OUTPUT:
- +**
- +** gcsDATABASE_RECORD_PTR Record
- +** Copy of record.
- +*/
- +gceSTATUS
- +gckKERNEL_FindProcessDB(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 ProcessID,
- + IN gctUINT32 ThreadID,
- + IN gceDATABASE_TYPE Type,
- + IN gctPOINTER Pointer,
- + OUT gcsDATABASE_RECORD_PTR Record
- + )
- +{
- + gceSTATUS status;
- + gcsDATABASE_PTR database;
- +
- + gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x",
- + Kernel, ProcessID, ThreadID, Type, Pointer);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
- +
- + /* Find the database. */
- + gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
- +
- + /* Find the record. */
- + gcmkONERROR(
- + gckKERNEL_FindRecord(Kernel, database, Type, Pointer, Record));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +** gckKERNEL_DestroyProcessDB
- +**
- +** Destroy a process database. If the database contains any records, the data
- +** inside those records will be deleted as well. This aids in the cleanup if
- +** a process has died unexpectedly or has memory leaks.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to a gckKERNEL object.
- +**
- +** gctUINT32 ProcessID
- +** Process ID used to identify the database.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckKERNEL_DestroyProcessDB(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 ProcessID
- + )
- +{
- + gceSTATUS status;
- + gcsDATABASE_PTR database;
- + gcsDATABASE_RECORD_PTR record, next;
- + gctBOOL asynchronous;
- + gctPHYS_ADDR physical;
- + gcuVIDMEM_NODE_PTR node;
- + gckKERNEL kernel = Kernel;
- + gctUINT32 i;
- +
- + gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- +
- + /* Find the database. */
- + gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
- + "DB(%d): VidMem: total=%lu max=%lu",
- + ProcessID, database->vidMem.totalBytes,
- + database->vidMem.maxBytes);
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
- + "DB(%d): NonPaged: total=%lu max=%lu",
- + ProcessID, database->nonPaged.totalBytes,
- + database->nonPaged.maxBytes);
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
- + "DB(%d): Contiguous: total=%lu max=%lu",
- + ProcessID, database->contiguous.totalBytes,
- + database->contiguous.maxBytes);
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
- + "DB(%d): Idle time=%llu",
- + ProcessID, Kernel->db->idleTime);
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
- + "DB(%d): Map: total=%lu max=%lu",
- + ProcessID, database->mapMemory.totalBytes,
- + database->mapMemory.maxBytes);
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
- + "DB(%d): Map: total=%lu max=%lu",
- + ProcessID, database->mapUserMemory.totalBytes,
- + database->mapUserMemory.maxBytes);
- +
- + if (database->list != gcvNULL)
- + {
- + gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
- + "Process %d has entries in its database:",
- + ProcessID);
- + }
- +
- + for(i = 0; i < gcmCOUNTOF(database->list); i++)
- + {
- +
- + /* Walk all records. */
- + for (record = database->list[i]; record != gcvNULL; record = next)
- + {
- + /* Next next record. */
- + next = record->next;
- +
- + /* Dispatch on record type. */
- + switch (record->type)
- + {
- + case gcvDB_VIDEO_MEMORY:
- + /* Free the video memory. */
- + status = gckVIDMEM_Free(gcmUINT64_TO_PTR(record->data));
- +
- + gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
- + "DB: VIDEO_MEMORY 0x%x (status=%d)",
- + record->data, status);
- + break;
- +
- + case gcvDB_NON_PAGED:
- + physical = gcmNAME_TO_PTR(record->physical);
- + /* Unmap user logical memory first. */
- + status = gckOS_UnmapUserLogical(Kernel->os,
- + physical,
- + record->bytes,
- + record->data);
- +
- + /* Free the non paged memory. */
- + status = gckOS_FreeNonPagedMemory(Kernel->os,
- + record->bytes,
- + physical,
- + record->data);
- + gcmRELEASE_NAME(record->physical);
- +
- + gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
- + "DB: NON_PAGED 0x%x, bytes=%lu (status=%d)",
- + record->data, record->bytes, status);
- + break;
- +
- +#if gcdVIRTUAL_COMMAND_BUFFER
- + case gcvDB_COMMAND_BUFFER:
- + /* Free the command buffer. */
- + status = gckEVENT_DestroyVirtualCommandBuffer(record->kernel->eventObj,
- + record->bytes,
- + gcmNAME_TO_PTR(record->physical),
- + record->data,
- + gcvKERNEL_PIXEL);
- + gcmRELEASE_NAME(record->physical);
- +
- + gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
- + "DB: COMMAND_BUFFER 0x%x, bytes=%lu (status=%d)",
- + record->data, record->bytes, status);
- + break;
- +#endif
- +
- + case gcvDB_CONTIGUOUS:
- + physical = gcmNAME_TO_PTR(record->physical);
- + /* Unmap user logical memory first. */
- + status = gckOS_UnmapUserLogical(Kernel->os,
- + physical,
- + record->bytes,
- + record->data);
- +
- + /* Free the contiguous memory. */
- + status = gckEVENT_FreeContiguousMemory(Kernel->eventObj,
- + record->bytes,
- + physical,
- + record->data,
- + gcvKERNEL_PIXEL);
- + gcmRELEASE_NAME(record->physical);
- +
- + gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
- + "DB: CONTIGUOUS 0x%x bytes=%lu (status=%d)",
- + record->data, record->bytes, status);
- + break;
- +
- + case gcvDB_SIGNAL:
- +#if USE_NEW_LINUX_SIGNAL
- + status = gcvSTATUS_NOT_SUPPORTED;
- +#else
- + /* Free the user signal. */
- + status = gckOS_DestroyUserSignal(Kernel->os,
- + gcmPTR2INT(record->data));
- +#endif /* USE_NEW_LINUX_SIGNAL */
- +
- + gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
- + "DB: SIGNAL %d (status=%d)",
- + (gctINT)(gctUINTPTR_T)record->data, status);
- + break;
- +
- + case gcvDB_VIDEO_MEMORY_LOCKED:
- + node = gcmUINT64_TO_PTR(record->data);
- + /* Unlock what we still locked */
- + status = gckVIDMEM_Unlock(record->kernel,
- + node,
- + gcvSURF_TYPE_UNKNOWN,
- + &asynchronous);
- +
- + if (gcmIS_SUCCESS(status) && (gcvTRUE == asynchronous))
- + {
- + /* TODO: we maybe need to schedule a event here */
- + status = gckVIDMEM_Unlock(record->kernel,
- + node,
- + gcvSURF_TYPE_UNKNOWN,
- + gcvNULL);
- + }
- +
- + gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
- + "DB: VIDEO_MEMORY_LOCKED 0x%x (status=%d)",
- + node, status);
- + break;
- +
- + case gcvDB_CONTEXT:
- + /* TODO: Free the context */
- + status = gckCOMMAND_Detach(Kernel->command, gcmNAME_TO_PTR(record->data));
- + gcmRELEASE_NAME(record->data);
- +
- + gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
- + "DB: CONTEXT 0x%x (status=%d)",
- + record->data, status);
- + break;
- +
- + case gcvDB_MAP_MEMORY:
- + /* Unmap memory. */
- + status = gckKERNEL_UnmapMemory(Kernel,
- + record->physical,
- + record->bytes,
- + record->data);
- +
- + gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
- + "DB: MAP MEMORY %d (status=%d)",
- + gcmPTR2INT(record->data), status);
- + break;
- +
- + case gcvDB_MAP_USER_MEMORY:
- + /* TODO: Unmap user memory. */
- + status = gckOS_UnmapUserMemory(Kernel->os,
- + Kernel->core,
- + record->physical,
- + record->bytes,
- + gcmNAME_TO_PTR(record->data),
- + 0);
- + gcmRELEASE_NAME(record->data);
- +
- + gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
- + "DB: MAP USER MEMORY %d (status=%d)",
- + gcmPTR2INT(record->data), status);
- + break;
- +
- + case gcvDB_SHARED_INFO:
- + status = gckOS_FreeMemory(Kernel->os, record->physical);
- + break;
- +
- +#if gcdANDROID_NATIVE_FENCE_SYNC
- + case gcvDB_SYNC_POINT:
- + /* Free the user signal. */
- + status = gckOS_DestroySyncPoint(Kernel->os,
- + (gctSYNC_POINT) record->data);
- +
- + gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
- + "DB: SYNC POINT %d (status=%d)",
- + (gctINT)(gctUINTPTR_T)record->data, status);
- + break;
- +#endif
- +
- + case gcvDB_VIDEO_MEMORY_RESERVED:
- + case gcvDB_VIDEO_MEMORY_CONTIGUOUS:
- + case gcvDB_VIDEO_MEMORY_VIRTUAL:
- + break;//Nothing to do
- +
- + default:
- + gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DATABASE,
- + "DB: Correcupted record=0x%08x type=%d",
- + record, record->type);
- + break;
- + }
- +
- + /* Delete the record. */
- + gcmkONERROR(gckKERNEL_DeleteRecord(Kernel,
- + database,
- + record->type,
- + record->data,
- + gcvNULL));
- + }
- +
- + }
- +
- + /* Delete the database. */
- + gcmkONERROR(gckKERNEL_DeleteDatabase(Kernel, database));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +** gckKERNEL_QueryProcessDB
- +**
- +** Query a process database for the current usage of a particular record type.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to a gckKERNEL object.
- +**
- +** gctUINT32 ProcessID
- +** Process ID used to identify the database.
- +**
- +** gctBOOL LastProcessID
- +** gcvTRUE if searching for the last known process ID. gcvFALSE if
- +** we need to search for the process ID specified by the ProcessID
- +** argument.
- +**
- +** gceDATABASE_TYPE Type
- +** Type of the record to query.
- +**
- +** OUTPUT:
- +**
- +** gcuDATABASE_INFO * Info
- +** Pointer to a variable that receives the requested information.
- +*/
- +gceSTATUS
- +gckKERNEL_QueryProcessDB(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 ProcessID,
- + IN gctBOOL LastProcessID,
- + IN gceDATABASE_TYPE Type,
- + OUT gcuDATABASE_INFO * Info
- + )
- +{
- + gceSTATUS status;
- + gcsDATABASE_PTR database;
- +
- + gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Info=0x%x",
- + Kernel, ProcessID, Type, Info);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(Info != gcvNULL);
- +
- + /* Find the database. */
- + gcmkONERROR(
- + gckKERNEL_FindDatabase(Kernel, ProcessID, LastProcessID, &database));
- +
- + /* Get pointer to counters. */
- + switch (Type)
- + {
- + case gcvDB_VIDEO_MEMORY:
- + gckOS_MemCopy(&Info->counters,
- + &database->vidMem,
- + gcmSIZEOF(database->vidMem));
- + break;
- +
- + case gcvDB_NON_PAGED:
- + gckOS_MemCopy(&Info->counters,
- + &database->nonPaged,
- + gcmSIZEOF(database->vidMem));
- + break;
- +
- + case gcvDB_CONTIGUOUS:
- + gckOS_MemCopy(&Info->counters,
- + &database->contiguous,
- + gcmSIZEOF(database->vidMem));
- + break;
- +
- + case gcvDB_IDLE:
- + Info->time = Kernel->db->idleTime;
- + Kernel->db->idleTime = 0;
- + break;
- +
- + case gcvDB_MAP_MEMORY:
- + gckOS_MemCopy(&Info->counters,
- + &database->mapMemory,
- + gcmSIZEOF(database->mapMemory));
- + break;
- +
- + case gcvDB_MAP_USER_MEMORY:
- + gckOS_MemCopy(&Info->counters,
- + &database->mapUserMemory,
- + gcmSIZEOF(database->mapUserMemory));
- + break;
- +
- + case gcvDB_VIDEO_MEMORY_RESERVED:
- + gckOS_MemCopy(&Info->counters,
- + &database->vidMemResv,
- + gcmSIZEOF(database->vidMemResv));
- + break;
- +
- + case gcvDB_VIDEO_MEMORY_CONTIGUOUS:
- + gckOS_MemCopy(&Info->counters,
- + &database->vidMemCont,
- + gcmSIZEOF(database->vidMemCont));
- + break;
- +
- + case gcvDB_VIDEO_MEMORY_VIRTUAL:
- + gckOS_MemCopy(&Info->counters,
- + &database->vidMemVirt,
- + gcmSIZEOF(database->vidMemVirt));
- + break;
- +
- + default:
- + break;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +#if gcdSECURE_USER
- +/*******************************************************************************
- +** gckKERNEL_GetProcessDBCache
- +**
- +** Get teh secure cache from a process database.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to a gckKERNEL object.
- +**
- +** gctUINT32 ProcessID
- +** Process ID used to identify the database.
- +**
- +** OUTPUT:
- +**
- +** gcskSECURE_CACHE_PTR * Cache
- +** Pointer to a variable that receives the secure cache pointer.
- +*/
- +gceSTATUS
- +gckKERNEL_GetProcessDBCache(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 ProcessID,
- + OUT gcskSECURE_CACHE_PTR * Cache
- + )
- +{
- + gceSTATUS status;
- + gcsDATABASE_PTR database;
- +
- + gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(Cache != gcvNULL);
- +
- + /* Find the database. */
- + gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
- +
- + /* Return the pointer to the cache. */
- + *Cache = &database->cache;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Cache=0x%x", *Cache);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +#endif
- +
- +gceSTATUS
- +gckKERNEL_DumpProcessDB(
- + IN gckKERNEL Kernel
- + )
- +{
- + gcsDATABASE_PTR database;
- + gctINT i, pid;
- + gctUINT8 name[24];
- +
- + gcmkHEADER_ARG("Kernel=0x%x", Kernel);
- +
- + /* Acquire the database mutex. */
- + gcmkVERIFY_OK(
- + gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
- +
- + gcmkPRINT("**************************\n");
- + gcmkPRINT("*** PROCESS DB DUMP ***\n");
- + gcmkPRINT("**************************\n");
- +
- + gcmkPRINT_N(8, "%-8s%s\n", "PID", "NAME");
- + /* Walk the databases. */
- + for (i = 0; i < gcmCOUNTOF(Kernel->db->db); ++i)
- + {
- + for (database = Kernel->db->db[i];
- + database != gcvNULL;
- + database = database->next)
- + {
- + pid = database->processID;
- +
- + gcmkVERIFY_OK(gckOS_ZeroMemory(name, gcmSIZEOF(name)));
- +
- + gcmkVERIFY_OK(gckOS_GetProcessNameByPid(pid, gcmSIZEOF(name), name));
- +
- + gcmkPRINT_N(8, "%-8d%s\n", pid, name);
- + }
- + }
- +
- + /* Release the database mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_debug.c linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_debug.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_debug.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_debug.c 2015-03-08 14:27:37.633684500 -0500
- @@ -0,0 +1,2559 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal_kernel_precomp.h"
- +#include <gc_hal_kernel_debug.h>
- +
- +/******************************************************************************\
- +******************************** Debug Variables *******************************
- +\******************************************************************************/
- +
- +static gceSTATUS _lastError = gcvSTATUS_OK;
- +static gctUINT32 _debugLevel = gcvLEVEL_ERROR;
- +/*
- +_debugZones config value
- +Please Reference define in gc_hal_base.h
- +*/
- +static gctUINT32 _debugZones = gcvZONE_NONE;
- +
- +/******************************************************************************\
- +********************************* Debug Switches *******************************
- +\******************************************************************************/
- +
- +/*
- + gcdBUFFERED_OUTPUT
- +
- + When set to non-zero, all output is collected into a buffer with the
- + specified size. Once the buffer gets full, the debug buffer will be
- + printed to the console. gcdBUFFERED_SIZE determines the size of the buffer.
- +*/
- +#define gcdBUFFERED_OUTPUT 0
- +
- +/*
- + gcdBUFFERED_SIZE
- +
- + When set to non-zero, all output is collected into a buffer with the
- + specified size. Once the buffer gets full, the debug buffer will be
- + printed to the console.
- +*/
- +#define gcdBUFFERED_SIZE (1024 * 1024 * 2)
- +
- +/*
- + gcdDMA_BUFFER_COUNT
- +
- + If greater then zero, the debugger will attempt to find the command buffer
- + where DMA is currently executing and then print this buffer and
- + (gcdDMA_BUFFER_COUNT - 1) buffers before the current one. If set to zero
- + or the current buffer is not found, all buffers are printed.
- +*/
- +#define gcdDMA_BUFFER_COUNT 0
- +
- +/*
- + gcdTHREAD_BUFFERS
- +
- + When greater then one, will accumulate messages from the specified number
- + of threads in separate output buffers.
- +*/
- +#define gcdTHREAD_BUFFERS 1
- +
- +/*
- + gcdENABLE_OVERFLOW
- +
- + When set to non-zero, and the output buffer gets full, instead of being
- + printed, it will be allowed to overflow removing the oldest messages.
- +*/
- +#define gcdENABLE_OVERFLOW 1
- +
- +/*
- + gcdSHOW_LINE_NUMBER
- +
- + When enabledm each print statement will be preceeded with the current
- + line number.
- +*/
- +#define gcdSHOW_LINE_NUMBER 0
- +
- +/*
- + gcdSHOW_PROCESS_ID
- +
- + When enabledm each print statement will be preceeded with the current
- + process ID.
- +*/
- +#define gcdSHOW_PROCESS_ID 0
- +
- +/*
- + gcdSHOW_THREAD_ID
- +
- + When enabledm each print statement will be preceeded with the current
- + thread ID.
- +*/
- +#define gcdSHOW_THREAD_ID 0
- +
- +/*
- + gcdSHOW_TIME
- +
- + When enabled each print statement will be preceeded with the current
- + high-resolution time.
- +*/
- +#define gcdSHOW_TIME 0
- +
- +
- +/******************************************************************************\
- +****************************** Miscellaneous Macros ****************************
- +\******************************************************************************/
- +
- +#if gcmIS_DEBUG(gcdDEBUG_TRACE)
- +# define gcmDBGASSERT(Expression, Format, Value) \
- + if (!(Expression)) \
- + { \
- + _DirectPrint( \
- + "*** gcmDBGASSERT ***************************\n" \
- + " function : %s\n" \
- + " line : %d\n" \
- + " expression : " #Expression "\n" \
- + " actual value : " Format "\n", \
- + __FUNCTION__, __LINE__, Value \
- + ); \
- + }
- +#else
- +# define gcmDBGASSERT(Expression, Format, Value)
- +#endif
- +
- +#define gcmPTRALIGNMENT(Pointer, Alignemnt) \
- +( \
- + gcmALIGN(gcmPTR2INT(Pointer), Alignemnt) - gcmPTR2INT(Pointer) \
- +)
- +
- +#if gcdALIGNBYSIZE
- +# define gcmISALIGNED(Offset, Alignment) \
- + (((Offset) & ((Alignment) - 1)) == 0)
- +
- +# define gcmkALIGNPTR(Type, Pointer, Alignment) \
- + Pointer = (Type) gcmINT2PTR(gcmALIGN(gcmPTR2INT(Pointer), Alignment))
- +#else
- +# define gcmISALIGNED(Offset, Alignment) \
- + gcvTRUE
- +
- +# define gcmkALIGNPTR(Type, Pointer, Alignment)
- +#endif
- +
- +#define gcmALIGNSIZE(Offset, Size) \
- + ((Size - Offset) + Size)
- +
- +#define gcdHAVEPREFIX \
- +( \
- + gcdSHOW_TIME \
- + || gcdSHOW_LINE_NUMBER \
- + || gcdSHOW_PROCESS_ID \
- + || gcdSHOW_THREAD_ID \
- +)
- +
- +#if gcdHAVEPREFIX
- +
- +# define gcdOFFSET 0
- +
- +#if gcdSHOW_TIME
- +#if gcmISALIGNED(gcdOFFSET, 8)
- +# define gcdTIMESIZE gcmSIZEOF(gctUINT64)
- +# elif gcdOFFSET == 4
- +# define gcdTIMESIZE gcmALIGNSIZE(4, gcmSIZEOF(gctUINT64))
- +# else
- +# error "Unexpected offset value."
- +# endif
- +# undef gcdOFFSET
- +# define gcdOFFSET 8
- +#if !defined(gcdPREFIX_LEADER)
- +# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT64)
- +# define gcdTIMEFORMAT "0x%016llX"
- +# else
- +# define gcdTIMEFORMAT ", 0x%016llX"
- +# endif
- +# else
- +# define gcdTIMESIZE 0
- +# define gcdTIMEFORMAT
- +# endif
- +
- +#if gcdSHOW_LINE_NUMBER
- +#if gcmISALIGNED(gcdOFFSET, 8)
- +# define gcdNUMSIZE gcmSIZEOF(gctUINT64)
- +# elif gcdOFFSET == 4
- +# define gcdNUMSIZE gcmALIGNSIZE(4, gcmSIZEOF(gctUINT64))
- +# else
- +# error "Unexpected offset value."
- +# endif
- +# undef gcdOFFSET
- +# define gcdOFFSET 8
- +#if !defined(gcdPREFIX_LEADER)
- +# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT64)
- +# define gcdNUMFORMAT "%8llu"
- +# else
- +# define gcdNUMFORMAT ", %8llu"
- +# endif
- +# else
- +# define gcdNUMSIZE 0
- +# define gcdNUMFORMAT
- +# endif
- +
- +#if gcdSHOW_PROCESS_ID
- +#if gcmISALIGNED(gcdOFFSET, 4)
- +# define gcdPIDSIZE gcmSIZEOF(gctUINT32)
- +# else
- +# error "Unexpected offset value."
- +# endif
- +# undef gcdOFFSET
- +# define gcdOFFSET 4
- +#if !defined(gcdPREFIX_LEADER)
- +# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT32)
- +# define gcdPIDFORMAT "pid=%5d"
- +# else
- +# define gcdPIDFORMAT ", pid=%5d"
- +# endif
- +# else
- +# define gcdPIDSIZE 0
- +# define gcdPIDFORMAT
- +# endif
- +
- +#if gcdSHOW_THREAD_ID
- +#if gcmISALIGNED(gcdOFFSET, 4)
- +# define gcdTIDSIZE gcmSIZEOF(gctUINT32)
- +# else
- +# error "Unexpected offset value."
- +# endif
- +# undef gcdOFFSET
- +# define gcdOFFSET 4
- +#if !defined(gcdPREFIX_LEADER)
- +# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT32)
- +# define gcdTIDFORMAT "tid=%5d"
- +# else
- +# define gcdTIDFORMAT ", tid=%5d"
- +# endif
- +# else
- +# define gcdTIDSIZE 0
- +# define gcdTIDFORMAT
- +# endif
- +
- +# define gcdPREFIX_SIZE \
- + ( \
- + gcdTIMESIZE \
- + + gcdNUMSIZE \
- + + gcdPIDSIZE \
- + + gcdTIDSIZE \
- + )
- +
- + static const char * _prefixFormat =
- + "["
- + gcdTIMEFORMAT
- + gcdNUMFORMAT
- + gcdPIDFORMAT
- + gcdTIDFORMAT
- + "] ";
- +
- +#else
- +
- +# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT32)
- +# define gcdPREFIX_SIZE 0
- +
- +#endif
- +
- +/* Assumed largest variable argument leader size. */
- +#define gcdVARARG_LEADER gcmSIZEOF(gctUINT64)
- +
- +/* Alignnments. */
- +#if gcdALIGNBYSIZE
- +# define gcdPREFIX_ALIGNMENT gcdPREFIX_LEADER
- +# define gcdVARARG_ALIGNMENT gcdVARARG_LEADER
- +#else
- +# define gcdPREFIX_ALIGNMENT 0
- +# define gcdVARARG_ALIGNMENT 0
- +#endif
- +
- +#if gcdBUFFERED_OUTPUT
- +# define gcdOUTPUTPREFIX _AppendPrefix
- +# define gcdOUTPUTSTRING _AppendString
- +# define gcdOUTPUTCOPY _AppendCopy
- +# define gcdOUTPUTBUFFER _AppendBuffer
- +#else
- +# define gcdOUTPUTPREFIX _PrintPrefix
- +# define gcdOUTPUTSTRING _PrintString
- +# define gcdOUTPUTCOPY _PrintString
- +# define gcdOUTPUTBUFFER _PrintBuffer
- +#endif
- +
- +/******************************************************************************\
- +****************************** Private Structures ******************************
- +\******************************************************************************/
- +
- +typedef enum _gceBUFITEM
- +{
- + gceBUFITEM_NONE,
- + gcvBUFITEM_PREFIX,
- + gcvBUFITEM_STRING,
- + gcvBUFITEM_COPY,
- + gcvBUFITEM_BUFFER
- +}
- +gceBUFITEM;
- +
- +/* Common item head/buffer terminator. */
- +typedef struct _gcsBUFITEM_HEAD * gcsBUFITEM_HEAD_PTR;
- +typedef struct _gcsBUFITEM_HEAD
- +{
- + gceBUFITEM type;
- +}
- +gcsBUFITEM_HEAD;
- +
- +/* String prefix (for ex. [ 1,tid=0x019A]) */
- +typedef struct _gcsBUFITEM_PREFIX * gcsBUFITEM_PREFIX_PTR;
- +typedef struct _gcsBUFITEM_PREFIX
- +{
- + gceBUFITEM type;
- +#if gcdHAVEPREFIX
- + gctPOINTER prefixData;
- +#endif
- +}
- +gcsBUFITEM_PREFIX;
- +
- +/* Buffered string. */
- +typedef struct _gcsBUFITEM_STRING * gcsBUFITEM_STRING_PTR;
- +typedef struct _gcsBUFITEM_STRING
- +{
- + gceBUFITEM type;
- + gctINT indent;
- + gctCONST_STRING message;
- + gctPOINTER messageData;
- + gctUINT messageDataSize;
- +}
- +gcsBUFITEM_STRING;
- +
- +/* Buffered string (copy of the string is included with the record). */
- +typedef struct _gcsBUFITEM_COPY * gcsBUFITEM_COPY_PTR;
- +typedef struct _gcsBUFITEM_COPY
- +{
- + gceBUFITEM type;
- + gctINT indent;
- + gctPOINTER messageData;
- + gctUINT messageDataSize;
- +}
- +gcsBUFITEM_COPY;
- +
- +/* Memory buffer. */
- +typedef struct _gcsBUFITEM_BUFFER * gcsBUFITEM_BUFFER_PTR;
- +typedef struct _gcsBUFITEM_BUFFER
- +{
- + gceBUFITEM type;
- + gctINT indent;
- + gceDUMP_BUFFER bufferType;
- +
- +#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
- + gctUINT32 dmaAddress;
- +#endif
- +
- + gctUINT dataSize;
- + gctUINT32 address;
- +#if gcdHAVEPREFIX
- + gctPOINTER prefixData;
- +#endif
- +}
- +gcsBUFITEM_BUFFER;
- +
- +typedef struct _gcsBUFFERED_OUTPUT * gcsBUFFERED_OUTPUT_PTR;
- +typedef struct _gcsBUFFERED_OUTPUT
- +{
- +#if gcdTHREAD_BUFFERS > 1
- + gctUINT32 threadID;
- +#endif
- +
- +#if gcdSHOW_LINE_NUMBER
- + gctUINT64 lineNumber;
- +#endif
- +
- + gctINT indent;
- +
- +#if gcdBUFFERED_OUTPUT
- + gctINT start;
- + gctINT index;
- + gctINT count;
- + gctUINT8 buffer[gcdBUFFERED_SIZE];
- +#endif
- +
- + gcsBUFFERED_OUTPUT_PTR prev;
- + gcsBUFFERED_OUTPUT_PTR next;
- +}
- +gcsBUFFERED_OUTPUT;
- +
- +typedef gctUINT (* gcfPRINTSTRING) (
- + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
- + IN gcsBUFITEM_HEAD_PTR Item
- + );
- +
- +typedef gctINT (* gcfGETITEMSIZE) (
- + IN gcsBUFITEM_HEAD_PTR Item
- + );
- +
- +/******************************************************************************\
- +******************************* Private Variables ******************************
- +\******************************************************************************/
- +
- +static gcsBUFFERED_OUTPUT _outputBuffer[gcdTHREAD_BUFFERS];
- +static gcsBUFFERED_OUTPUT_PTR _outputBufferHead = gcvNULL;
- +static gcsBUFFERED_OUTPUT_PTR _outputBufferTail = gcvNULL;
- +
- +/******************************************************************************\
- +****************************** Item Size Functions *****************************
- +\******************************************************************************/
- +
- +#if gcdBUFFERED_OUTPUT
- +static gctINT
- +_GetTerminatorItemSize(
- + IN gcsBUFITEM_HEAD_PTR Item
- + )
- +{
- + return gcmSIZEOF(gcsBUFITEM_HEAD);
- +}
- +
- +static gctINT
- +_GetPrefixItemSize(
- + IN gcsBUFITEM_HEAD_PTR Item
- + )
- +{
- +#if gcdHAVEPREFIX
- + gcsBUFITEM_PREFIX_PTR item = (gcsBUFITEM_PREFIX_PTR) Item;
- + gctUINT vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
- + return vlen + gcdPREFIX_SIZE;
- +#else
- + return gcmSIZEOF(gcsBUFITEM_PREFIX);
- +#endif
- +}
- +
- +static gctINT
- +_GetStringItemSize(
- + IN gcsBUFITEM_HEAD_PTR Item
- + )
- +{
- + gcsBUFITEM_STRING_PTR item = (gcsBUFITEM_STRING_PTR) Item;
- + gctUINT vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
- + return vlen + item->messageDataSize;
- +}
- +
- +static gctINT
- +_GetCopyItemSize(
- + IN gcsBUFITEM_HEAD_PTR Item
- + )
- +{
- + gcsBUFITEM_COPY_PTR item = (gcsBUFITEM_COPY_PTR) Item;
- + gctUINT vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
- + return vlen + item->messageDataSize;
- +}
- +
- +static gctINT
- +_GetBufferItemSize(
- + IN gcsBUFITEM_HEAD_PTR Item
- + )
- +{
- +#if gcdHAVEPREFIX
- + gcsBUFITEM_BUFFER_PTR item = (gcsBUFITEM_BUFFER_PTR) Item;
- + gctUINT vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
- + return vlen + gcdPREFIX_SIZE + item->dataSize;
- +#else
- + gcsBUFITEM_BUFFER_PTR item = (gcsBUFITEM_BUFFER_PTR) Item;
- + return gcmSIZEOF(gcsBUFITEM_BUFFER) + item->dataSize;
- +#endif
- +}
- +
- +static gcfGETITEMSIZE _itemSize[] =
- +{
- + _GetTerminatorItemSize,
- + _GetPrefixItemSize,
- + _GetStringItemSize,
- + _GetCopyItemSize,
- + _GetBufferItemSize
- +};
- +#endif
- +
- +/******************************************************************************\
- +******************************* Printing Functions *****************************
- +\******************************************************************************/
- +
- +#if gcdDEBUG || gcdBUFFERED_OUTPUT
- +static void
- +_DirectPrint(
- + gctCONST_STRING Message,
- + ...
- + )
- +{
- + gctINT len;
- + char buffer[768];
- + gctARGUMENTS arguments;
- +
- + gcmkARGUMENTS_START(arguments, Message);
- + len = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), Message, arguments);
- + gcmkARGUMENTS_END(arguments);
- +
- + buffer[len] = '\0';
- + gcmkOUTPUT_STRING(buffer);
- +}
- +#endif
- +
- +static int
- +_AppendIndent(
- + IN gctINT Indent,
- + IN char * Buffer,
- + IN int BufferSize
- + )
- +{
- + gctINT i;
- +
- + gctINT len = 0;
- + gctINT indent = Indent % 40;
- +
- + for (i = 0; i < indent; i += 1)
- + {
- + Buffer[len++] = ' ';
- + }
- +
- + if (indent != Indent)
- + {
- + len += gcmkSPRINTF(
- + Buffer + len, BufferSize - len, " <%d> ", Indent
- + );
- +
- + Buffer[len] = '\0';
- + }
- +
- + return len;
- +}
- +
- +#if gcdHAVEPREFIX
- +static void
- +_PrintPrefix(
- + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
- + IN gctPOINTER Data
- + )
- +{
- + char buffer[768];
- + gctINT len;
- +
- + /* Format the string. */
- + len = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), _prefixFormat, Data);
- + buffer[len] = '\0';
- +
- + /* Print the string. */
- + gcmkOUTPUT_STRING(buffer);
- +}
- +#endif
- +
- +static void
- +_PrintString(
- + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
- + IN gctINT Indent,
- + IN gctCONST_STRING Message,
- + IN gctUINT ArgumentSize,
- + IN gctPOINTER Data
- + )
- +{
- + char buffer[768];
- + gctINT len;
- +
- + /* Append the indent string. */
- + len = _AppendIndent(Indent, buffer, gcmSIZEOF(buffer));
- +
- + /* Format the string. */
- + len += gcmkVSPRINTF(buffer + len, gcmSIZEOF(buffer) - len, Message, Data);
- + buffer[len] = '\0';
- +
- + /* Add end-of-line if missing. */
- + if (buffer[len - 1] != '\n')
- + {
- + buffer[len++] = '\n';
- + buffer[len] = '\0';
- + }
- +
- + /* Print the string. */
- + gcmkOUTPUT_STRING(buffer);
- +}
- +
- +static void
- +_PrintBuffer(
- + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
- + IN gctINT Indent,
- + IN gctPOINTER PrefixData,
- + IN gctPOINTER Data,
- + IN gctUINT Address,
- + IN gctUINT DataSize,
- + IN gceDUMP_BUFFER Type,
- + IN gctUINT32 DmaAddress
- + )
- +{
- + static gctCONST_STRING _titleString[] =
- + {
- + "CONTEXT BUFFER",
- + "USER COMMAND BUFFER",
- + "KERNEL COMMAND BUFFER",
- + "LINK BUFFER",
- + "WAIT LINK BUFFER",
- + ""
- + };
- +
- + static const gctINT COLUMN_COUNT = 8;
- +
- + gctUINT i, count, column, address;
- + gctUINT32_PTR data;
- + gctCHAR buffer[768];
- + gctUINT indent, len;
- + gctBOOL command;
- +
- + /* Append space for the prefix. */
- +#if gcdHAVEPREFIX
- + indent = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), _prefixFormat, PrefixData);
- + buffer[indent] = '\0';
- +#else
- + indent = 0;
- +#endif
- +
- + /* Append the indent string. */
- + indent += _AppendIndent(
- + Indent, buffer + indent, gcmSIZEOF(buffer) - indent
- + );
- +
- + switch (Type)
- + {
- + case gceDUMP_BUFFER_CONTEXT:
- + case gceDUMP_BUFFER_USER:
- + case gceDUMP_BUFFER_KERNEL:
- + case gceDUMP_BUFFER_LINK:
- + case gceDUMP_BUFFER_WAITLINK:
- + /* Form and print the title string. */
- + gcmkSPRINTF2(
- + buffer + indent, gcmSIZEOF(buffer) - indent,
- + "%s%s\n", _titleString[Type],
- + ((DmaAddress >= Address) && (DmaAddress < Address + DataSize))
- + ? " (CURRENT)" : ""
- + );
- +
- + gcmkOUTPUT_STRING(buffer);
- +
- + /* Terminate the string. */
- + buffer[indent] = '\0';
- +
- + /* This is a command buffer. */
- + command = gcvTRUE;
- + break;
- +
- + case gceDUMP_BUFFER_FROM_USER:
- + /* This is not a command buffer. */
- + command = gcvFALSE;
- +
- + /* No title. */
- + break;
- +
- + default:
- + gcmDBGASSERT(gcvFALSE, "%s", "invalid buffer type");
- +
- + /* This is not a command buffer. */
- + command = gcvFALSE;
- + }
- +
- + /* Overwrite the prefix with spaces. */
- + for (i = 0; i < indent; i += 1)
- + {
- + buffer[i] = ' ';
- + }
- +
- + /* Form and print the opening string. */
- + if (command)
- + {
- + gcmkSPRINTF2(
- + buffer + indent, gcmSIZEOF(buffer) - indent,
- + "@[kernel.command %08X %08X\n", Address, DataSize
- + );
- +
- + gcmkOUTPUT_STRING(buffer);
- +
- + /* Terminate the string. */
- + buffer[indent] = '\0';
- + }
- +
- + /* Get initial address. */
- + address = Address;
- +
- + /* Cast the data pointer. */
- + data = (gctUINT32_PTR) Data;
- +
- + /* Compute the number of double words. */
- + count = DataSize / gcmSIZEOF(gctUINT32);
- +
- + /* Print the buffer. */
- + for (i = 0, len = indent, column = 0; i < count; i += 1)
- + {
- + /* Append the address. */
- + if (column == 0)
- + {
- + len += gcmkSPRINTF(
- + buffer + len, gcmSIZEOF(buffer) - len, "0x%08X:", address
- + );
- + }
- +
- + /* Append the data value. */
- + len += gcmkSPRINTF2(
- + buffer + len, gcmSIZEOF(buffer) - len, "%c%08X",
- + (address == DmaAddress)? '>' : ' ', data[i]
- + );
- +
- + buffer[len] = '\0';
- +
- + /* Update the address. */
- + address += gcmSIZEOF(gctUINT32);
- +
- + /* Advance column count. */
- + column += 1;
- +
- + /* End of line? */
- + if ((column % COLUMN_COUNT) == 0)
- + {
- + /* Append EOL. */
- + gcmkSTRCAT(buffer + len, gcmSIZEOF(buffer) - len, "\n");
- +
- + /* Print the string. */
- + gcmkOUTPUT_STRING(buffer);
- +
- + /* Reset. */
- + len = indent;
- + column = 0;
- + }
- + }
- +
- + /* Print the last partial string. */
- + if (column != 0)
- + {
- + /* Append EOL. */
- + gcmkSTRCAT(buffer + len, gcmSIZEOF(buffer) - len, "\n");
- +
- + /* Print the string. */
- + gcmkOUTPUT_STRING(buffer);
- + }
- +
- + /* Form and print the opening string. */
- + if (command)
- + {
- + buffer[indent] = '\0';
- + gcmkSTRCAT(buffer, gcmSIZEOF(buffer), "] -- command\n");
- + gcmkOUTPUT_STRING(buffer);
- + }
- +}
- +
- +#if gcdBUFFERED_OUTPUT
- +static gctUINT
- +_PrintNone(
- + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
- + IN gcsBUFITEM_HEAD_PTR Item
- + )
- +{
- + /* Return the size of the node. */
- + return gcmSIZEOF(gcsBUFITEM_HEAD);
- +}
- +
- +static gctUINT
- +_PrintPrefixWrapper(
- + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
- + IN gcsBUFITEM_HEAD_PTR Item
- + )
- +{
- +#if gcdHAVEPREFIX
- + gcsBUFITEM_PREFIX_PTR item;
- + gctUINT vlen;
- +
- + /* Get access to the data. */
- + item = (gcsBUFITEM_PREFIX_PTR) Item;
- +
- + /* Print the message. */
- + _PrintPrefix(OutputBuffer, item->prefixData);
- +
- + /* Compute the size of the variable portion of the structure. */
- + vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
- +
- + /* Return the size of the node. */
- + return vlen + gcdPREFIX_SIZE;
- +#else
- + return gcmSIZEOF(gcsBUFITEM_PREFIX);
- +#endif
- +}
- +
- +static gctUINT
- +_PrintStringWrapper(
- + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
- + IN gcsBUFITEM_HEAD_PTR Item
- + )
- +{
- + gcsBUFITEM_STRING_PTR item;
- + gctUINT vlen;
- +
- + /* Get access to the data. */
- + item = (gcsBUFITEM_STRING_PTR) Item;
- +
- + /* Print the message. */
- + _PrintString(
- + OutputBuffer,
- + item->indent, item->message, item->messageDataSize, item->messageData
- + );
- +
- + /* Compute the size of the variable portion of the structure. */
- + vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
- +
- + /* Return the size of the node. */
- + return vlen + item->messageDataSize;
- +}
- +
- +static gctUINT
- +_PrintCopyWrapper(
- + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
- + IN gcsBUFITEM_HEAD_PTR Item
- + )
- +{
- + gcsBUFITEM_COPY_PTR item;
- + gctCONST_STRING message;
- + gctUINT vlen;
- +
- + /* Get access to the data. */
- + item = (gcsBUFITEM_COPY_PTR) Item;
- +
- + /* Determine the string pointer. */
- + message = (gctCONST_STRING) (item + 1);
- +
- + /* Print the message. */
- + _PrintString(
- + OutputBuffer,
- + item->indent, message, item->messageDataSize, item->messageData
- + );
- +
- + /* Compute the size of the variable portion of the structure. */
- + vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
- +
- + /* Return the size of the node. */
- + return vlen + item->messageDataSize;
- +}
- +
- +static gctUINT
- +_PrintBufferWrapper(
- + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
- + IN gcsBUFITEM_HEAD_PTR Item
- + )
- +{
- +#if gcdHAVEPREFIX
- + gctUINT32 dmaAddress;
- + gcsBUFITEM_BUFFER_PTR item;
- + gctPOINTER data;
- + gctUINT vlen;
- +
- + /* Get access to the data. */
- + item = (gcsBUFITEM_BUFFER_PTR) Item;
- +
- +#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
- + dmaAddress = item->dmaAddress;
- +#else
- + dmaAddress = 0xFFFFFFFF;
- +#endif
- +
- + if (dmaAddress != 0)
- + {
- + /* Compute the data address. */
- + data = ((gctUINT8_PTR) item->prefixData) + gcdPREFIX_SIZE;
- +
- + /* Print buffer. */
- + _PrintBuffer(
- + OutputBuffer,
- + item->indent, item->prefixData,
- + data, item->address, item->dataSize,
- + item->bufferType, dmaAddress
- + );
- + }
- +
- + /* Compute the size of the variable portion of the structure. */
- + vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
- +
- + /* Return the size of the node. */
- + return vlen + gcdPREFIX_SIZE + item->dataSize;
- +#else
- + gctUINT32 dmaAddress;
- + gcsBUFITEM_BUFFER_PTR item;
- +
- + /* Get access to the data. */
- + item = (gcsBUFITEM_BUFFER_PTR) Item;
- +
- +#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
- + dmaAddress = item->dmaAddress;
- +#else
- + dmaAddress = 0xFFFFFFFF;
- +#endif
- +
- + if (dmaAddress != 0)
- + {
- + /* Print buffer. */
- + _PrintBuffer(
- + OutputBuffer,
- + item->indent, gcvNULL,
- + item + 1, item->address, item->dataSize,
- + item->bufferType, dmaAddress
- + );
- + }
- +
- + /* Return the size of the node. */
- + return gcmSIZEOF(gcsBUFITEM_BUFFER) + item->dataSize;
- +#endif
- +}
- +
- +static gcfPRINTSTRING _printArray[] =
- +{
- + _PrintNone,
- + _PrintPrefixWrapper,
- + _PrintStringWrapper,
- + _PrintCopyWrapper,
- + _PrintBufferWrapper
- +};
- +#endif
- +
- +/******************************************************************************\
- +******************************* Private Functions ******************************
- +\******************************************************************************/
- +
- +#if gcdBUFFERED_OUTPUT
- +
- +#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
- +static gcsBUFITEM_BUFFER_PTR
- +_FindCurrentDMABuffer(
- + gctUINT32 DmaAddress
- + )
- +{
- + gctINT i, skip;
- + gcsBUFITEM_HEAD_PTR item;
- + gcsBUFITEM_BUFFER_PTR dmaCurrent;
- +
- + /* Reset the current buffer. */
- + dmaCurrent = gcvNULL;
- +
- + /* Get the first stored item. */
- + item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start];
- +
- + /* Run through all items. */
- + for (i = 0; i < _outputBufferHead->count; i += 1)
- + {
- + /* Buffer item? */
- + if (item->type == gcvBUFITEM_BUFFER)
- + {
- + gcsBUFITEM_BUFFER_PTR buffer = (gcsBUFITEM_BUFFER_PTR) item;
- +
- + if ((DmaAddress >= buffer->address) &&
- + (DmaAddress < buffer->address + buffer->dataSize))
- + {
- + dmaCurrent = buffer;
- + }
- + }
- +
- + /* Get the item size and skip it. */
- + skip = (* _itemSize[item->type]) (item);
- + item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
- +
- + /* End of the buffer? Wrap around. */
- + if (item->type == gceBUFITEM_NONE)
- + {
- + item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer;
- + }
- + }
- +
- + /* Return result. */
- + return dmaCurrent;
- +}
- +
- +static void
- +_EnableAllDMABuffers(
- + void
- + )
- +{
- + gctINT i, skip;
- + gcsBUFITEM_HEAD_PTR item;
- +
- + /* Get the first stored item. */
- + item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start];
- +
- + /* Run through all items. */
- + for (i = 0; i < _outputBufferHead->count; i += 1)
- + {
- + /* Buffer item? */
- + if (item->type == gcvBUFITEM_BUFFER)
- + {
- + gcsBUFITEM_BUFFER_PTR buffer = (gcsBUFITEM_BUFFER_PTR) item;
- +
- + /* Enable the buffer. */
- + buffer->dmaAddress = ~0U;
- + }
- +
- + /* Get the item size and skip it. */
- + skip = (* _itemSize[item->type]) (item);
- + item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
- +
- + /* End of the buffer? Wrap around. */
- + if (item->type == gceBUFITEM_NONE)
- + {
- + item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer;
- + }
- + }
- +}
- +
- +static void
- +_EnableDMABuffers(
- + gctUINT32 DmaAddress,
- + gcsBUFITEM_BUFFER_PTR CurrentDMABuffer
- + )
- +{
- + gctINT i, skip, index;
- + gcsBUFITEM_HEAD_PTR item;
- + gcsBUFITEM_BUFFER_PTR buffers[gcdDMA_BUFFER_COUNT];
- +
- + /* Reset buffer pointers. */
- + gckOS_ZeroMemory(buffers, gcmSIZEOF(buffers));
- +
- + /* Set the current buffer index. */
- + index = -1;
- +
- + /* Get the first stored item. */
- + item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start];
- +
- + /* Run through all items until the current DMA buffer is found. */
- + for (i = 0; i < _outputBufferHead->count; i += 1)
- + {
- + /* Buffer item? */
- + if (item->type == gcvBUFITEM_BUFFER)
- + {
- + /* Advance the index. */
- + index = (index + 1) % gcdDMA_BUFFER_COUNT;
- +
- + /* Add to the buffer array. */
- + buffers[index] = (gcsBUFITEM_BUFFER_PTR) item;
- +
- + /* Stop if this is the current DMA buffer. */
- + if ((gcsBUFITEM_BUFFER_PTR) item == CurrentDMABuffer)
- + {
- + break;
- + }
- + }
- +
- + /* Get the item size and skip it. */
- + skip = (* _itemSize[item->type]) (item);
- + item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
- +
- + /* End of the buffer? Wrap around. */
- + if (item->type == gceBUFITEM_NONE)
- + {
- + item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer;
- + }
- + }
- +
- + /* Enable the found buffers. */
- + gcmDBGASSERT(index != -1, "%d", index);
- +
- + for (i = 0; i < gcdDMA_BUFFER_COUNT; i += 1)
- + {
- + if (buffers[index] == gcvNULL)
- + {
- + break;
- + }
- +
- + buffers[index]->dmaAddress = DmaAddress;
- +
- + index -= 1;
- +
- + if (index == -1)
- + {
- + index = gcdDMA_BUFFER_COUNT - 1;
- + }
- + }
- +}
- +#endif
- +
- +static void
- +_Flush(
- + gctUINT32 DmaAddress
- + )
- +{
- + gctINT i, skip;
- + gcsBUFITEM_HEAD_PTR item;
- +
- + gcsBUFFERED_OUTPUT_PTR outputBuffer = _outputBufferHead;
- +
- +#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
- + if ((outputBuffer != gcvNULL) && (outputBuffer->count != 0))
- + {
- + /* Find the current DMA buffer. */
- + gcsBUFITEM_BUFFER_PTR dmaCurrent = _FindCurrentDMABuffer(DmaAddress);
- +
- + /* Was the current buffer found? */
- + if (dmaCurrent == gcvNULL)
- + {
- + /* No, print all buffers. */
- + _EnableAllDMABuffers();
- + }
- + else
- + {
- + /* Yes, enable only specified number of buffers. */
- + _EnableDMABuffers(DmaAddress, dmaCurrent);
- + }
- + }
- +#endif
- +
- + while (outputBuffer != gcvNULL)
- + {
- + if (outputBuffer->count != 0)
- + {
- + _DirectPrint("********************************************************************************\n");
- + _DirectPrint("FLUSHING DEBUG OUTPUT BUFFER (%d elements).\n", outputBuffer->count);
- + _DirectPrint("********************************************************************************\n");
- +
- + item = (gcsBUFITEM_HEAD_PTR) &outputBuffer->buffer[outputBuffer->start];
- +
- + for (i = 0; i < outputBuffer->count; i += 1)
- + {
- + skip = (* _printArray[item->type]) (outputBuffer, item);
- +
- + item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
- +
- + if (item->type == gceBUFITEM_NONE)
- + {
- + item = (gcsBUFITEM_HEAD_PTR) outputBuffer->buffer;
- + }
- + }
- +
- + outputBuffer->start = 0;
- + outputBuffer->index = 0;
- + outputBuffer->count = 0;
- + }
- +
- + outputBuffer = outputBuffer->next;
- + }
- +}
- +
- +static gcsBUFITEM_HEAD_PTR
- +_AllocateItem(
- + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
- + IN gctINT Size
- + )
- +{
- + gctINT skip;
- + gcsBUFITEM_HEAD_PTR item, next;
- +
- +#if gcdENABLE_OVERFLOW
- + if (
- + (OutputBuffer->index + Size >= gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD))
- + ||
- + (
- + (OutputBuffer->index < OutputBuffer->start) &&
- + (OutputBuffer->index + Size >= OutputBuffer->start)
- + )
- + )
- + {
- + if (OutputBuffer->index + Size >= gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD))
- + {
- + if (OutputBuffer->index < OutputBuffer->start)
- + {
- + item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->start];
- +
- + while (item->type != gceBUFITEM_NONE)
- + {
- + skip = (* _itemSize[item->type]) (item);
- +
- + OutputBuffer->start += skip;
- + OutputBuffer->count -= 1;
- +
- + item->type = gceBUFITEM_NONE;
- + item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
- + }
- +
- + OutputBuffer->start = 0;
- + }
- +
- + OutputBuffer->index = 0;
- + }
- +
- + item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->start];
- +
- + while (OutputBuffer->start - OutputBuffer->index <= Size)
- + {
- + skip = (* _itemSize[item->type]) (item);
- +
- + OutputBuffer->start += skip;
- + OutputBuffer->count -= 1;
- +
- + item->type = gceBUFITEM_NONE;
- + item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
- +
- + if (item->type == gceBUFITEM_NONE)
- + {
- + OutputBuffer->start = 0;
- + break;
- + }
- + }
- + }
- +#else
- + if (OutputBuffer->index + Size > gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD))
- + {
- + _DirectPrint("\nMessage buffer full; forcing message flush.\n\n");
- + _Flush(~0U);
- + }
- +#endif
- +
- + item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->index];
- +
- + OutputBuffer->index += Size;
- + OutputBuffer->count += 1;
- +
- + next = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + Size);
- + next->type = gceBUFITEM_NONE;
- +
- + return item;
- +}
- +
- +#if gcdALIGNBYSIZE
- +static void
- +_FreeExtraSpace(
- + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
- + IN gctPOINTER Item,
- + IN gctINT ItemSize,
- + IN gctINT FreeSize
- + )
- +{
- + gcsBUFITEM_HEAD_PTR next;
- +
- + OutputBuffer->index -= FreeSize;
- +
- + next = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) Item + ItemSize);
- + next->type = gceBUFITEM_NONE;
- +}
- +#endif
- +
- +#if gcdHAVEPREFIX
- +static void
- +_AppendPrefix(
- + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
- + IN gctPOINTER Data
- + )
- +{
- + gctUINT8_PTR prefixData;
- + gcsBUFITEM_PREFIX_PTR item;
- + gctINT allocSize;
- +
- +#if gcdALIGNBYSIZE
- + gctUINT alignment;
- + gctINT size, freeSize;
- +#endif
- +
- + gcmDBGASSERT(Data != gcvNULL, "%p", Data);
- +
- + /* Determine the maximum item size. */
- + allocSize
- + = gcmSIZEOF(gcsBUFITEM_PREFIX)
- + + gcdPREFIX_SIZE
- + + gcdPREFIX_ALIGNMENT;
- +
- + /* Allocate prefix item. */
- + item = (gcsBUFITEM_PREFIX_PTR) _AllocateItem(OutputBuffer, allocSize);
- +
- + /* Compute the initial prefix data pointer. */
- + prefixData = (gctUINT8_PTR) (item + 1);
- +
- + /* Align the data pointer as necessary. */
- +#if gcdALIGNBYSIZE
- + alignment = gcmPTRALIGNMENT(prefixData, gcdPREFIX_ALIGNMENT);
- + prefixData += alignment;
- +#endif
- +
- + /* Set item data. */
- + item->type = gcvBUFITEM_PREFIX;
- + item->prefixData = prefixData;
- +
- + /* Copy argument value. */
- + memcpy(prefixData, Data, gcdPREFIX_SIZE);
- +
- +#if gcdALIGNBYSIZE
- + /* Compute the actual node size. */
- + size = gcmSIZEOF(gcsBUFITEM_PREFIX) + gcdPREFIX_SIZE + alignment;
- +
- + /* Free extra memory if any. */
- + freeSize = allocSize - size;
- + if (freeSize != 0)
- + {
- + _FreeExtraSpace(OutputBuffer, item, size, freeSize);
- + }
- +#endif
- +}
- +#endif
- +
- +static void
- +_AppendString(
- + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
- + IN gctINT Indent,
- + IN gctCONST_STRING Message,
- + IN gctUINT ArgumentSize,
- + IN gctPOINTER Data
- + )
- +{
- + gctUINT8_PTR messageData;
- + gcsBUFITEM_STRING_PTR item;
- + gctINT allocSize;
- +
- +#if gcdALIGNBYSIZE
- + gctUINT alignment;
- + gctINT size, freeSize;
- +#endif
- +
- + /* Determine the maximum item size. */
- + allocSize
- + = gcmSIZEOF(gcsBUFITEM_STRING)
- + + ArgumentSize
- + + gcdVARARG_ALIGNMENT;
- +
- + /* Allocate prefix item. */
- + item = (gcsBUFITEM_STRING_PTR) _AllocateItem(OutputBuffer, allocSize);
- +
- + /* Compute the initial message data pointer. */
- + messageData = (gctUINT8_PTR) (item + 1);
- +
- + /* Align the data pointer as necessary. */
- +#if gcdALIGNBYSIZE
- + alignment = gcmPTRALIGNMENT(messageData, gcdVARARG_ALIGNMENT);
- + messageData += alignment;
- +#endif
- +
- + /* Set item data. */
- + item->type = gcvBUFITEM_STRING;
- + item->indent = Indent;
- + item->message = Message;
- + item->messageData = messageData;
- + item->messageDataSize = ArgumentSize;
- +
- + /* Copy argument value. */
- + if (ArgumentSize != 0)
- + {
- + memcpy(messageData, Data, ArgumentSize);
- + }
- +
- +#if gcdALIGNBYSIZE
- + /* Compute the actual node size. */
- + size = gcmSIZEOF(gcsBUFITEM_STRING) + ArgumentSize + alignment;
- +
- + /* Free extra memory if any. */
- + freeSize = allocSize - size;
- + if (freeSize != 0)
- + {
- + _FreeExtraSpace(OutputBuffer, item, size, freeSize);
- + }
- +#endif
- +}
- +
- +static void
- +_AppendCopy(
- + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
- + IN gctINT Indent,
- + IN gctCONST_STRING Message,
- + IN gctUINT ArgumentSize,
- + IN gctPOINTER Data
- + )
- +{
- + gctUINT8_PTR messageData;
- + gcsBUFITEM_COPY_PTR item;
- + gctINT allocSize;
- + gctINT messageLength;
- + gctCONST_STRING message;
- +
- +#if gcdALIGNBYSIZE
- + gctUINT alignment;
- + gctINT size, freeSize;
- +#endif
- +
- + /* Get the length of the string. */
- + messageLength = strlen(Message) + 1;
- +
- + /* Determine the maximum item size. */
- + allocSize
- + = gcmSIZEOF(gcsBUFITEM_COPY)
- + + messageLength
- + + ArgumentSize
- + + gcdVARARG_ALIGNMENT;
- +
- + /* Allocate prefix item. */
- + item = (gcsBUFITEM_COPY_PTR) _AllocateItem(OutputBuffer, allocSize);
- +
- + /* Determine the message placement. */
- + message = (gctCONST_STRING) (item + 1);
- +
- + /* Compute the initial message data pointer. */
- + messageData = (gctUINT8_PTR) message + messageLength;
- +
- + /* Align the data pointer as necessary. */
- +#if gcdALIGNBYSIZE
- + if (ArgumentSize == 0)
- + {
- + alignment = 0;
- + }
- + else
- + {
- + alignment = gcmPTRALIGNMENT(messageData, gcdVARARG_ALIGNMENT);
- + messageData += alignment;
- + }
- +#endif
- +
- + /* Set item data. */
- + item->type = gcvBUFITEM_COPY;
- + item->indent = Indent;
- + item->messageData = messageData;
- + item->messageDataSize = ArgumentSize;
- +
- + /* Copy the message. */
- + memcpy((gctPOINTER) message, Message, messageLength);
- +
- + /* Copy argument value. */
- + if (ArgumentSize != 0)
- + {
- + memcpy(messageData, Data, ArgumentSize);
- + }
- +
- +#if gcdALIGNBYSIZE
- + /* Compute the actual node size. */
- + size
- + = gcmSIZEOF(gcsBUFITEM_COPY)
- + + messageLength
- + + ArgumentSize
- + + alignment;
- +
- + /* Free extra memory if any. */
- + freeSize = allocSize - size;
- + if (freeSize != 0)
- + {
- + _FreeExtraSpace(OutputBuffer, item, size, freeSize);
- + }
- +#endif
- +}
- +
- +static void
- +_AppendBuffer(
- + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
- + IN gctINT Indent,
- + IN gctPOINTER PrefixData,
- + IN gctPOINTER Data,
- + IN gctUINT Address,
- + IN gctUINT DataSize,
- + IN gceDUMP_BUFFER Type,
- + IN gctUINT32 DmaAddress
- + )
- +{
- +#if gcdHAVEPREFIX
- + gctUINT8_PTR prefixData;
- + gcsBUFITEM_BUFFER_PTR item;
- + gctINT allocSize;
- + gctPOINTER data;
- +
- +#if gcdALIGNBYSIZE
- + gctUINT alignment;
- + gctINT size, freeSize;
- +#endif
- +
- + gcmDBGASSERT(DataSize != 0, "%d", DataSize);
- + gcmDBGASSERT(Data != gcvNULL, "%p", Data);
- +
- + /* Determine the maximum item size. */
- + allocSize
- + = gcmSIZEOF(gcsBUFITEM_BUFFER)
- + + gcdPREFIX_SIZE
- + + gcdPREFIX_ALIGNMENT
- + + DataSize;
- +
- + /* Allocate prefix item. */
- + item = (gcsBUFITEM_BUFFER_PTR) _AllocateItem(OutputBuffer, allocSize);
- +
- + /* Compute the initial prefix data pointer. */
- + prefixData = (gctUINT8_PTR) (item + 1);
- +
- +#if gcdALIGNBYSIZE
- + /* Align the data pointer as necessary. */
- + alignment = gcmPTRALIGNMENT(prefixData, gcdPREFIX_ALIGNMENT);
- + prefixData += alignment;
- +#endif
- +
- + /* Set item data. */
- + item->type = gcvBUFITEM_BUFFER;
- + item->indent = Indent;
- + item->bufferType = Type;
- + item->dataSize = DataSize;
- + item->address = Address;
- + item->prefixData = prefixData;
- +
- +#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
- + item->dmaAddress = DmaAddress;
- +#endif
- +
- + /* Copy prefix data. */
- + memcpy(prefixData, PrefixData, gcdPREFIX_SIZE);
- +
- + /* Compute the data pointer. */
- + data = prefixData + gcdPREFIX_SIZE;
- +
- + /* Copy argument value. */
- + memcpy(data, Data, DataSize);
- +
- +#if gcdALIGNBYSIZE
- + /* Compute the actual node size. */
- + size
- + = gcmSIZEOF(gcsBUFITEM_BUFFER)
- + + gcdPREFIX_SIZE
- + + alignment
- + + DataSize;
- +
- + /* Free extra memory if any. */
- + freeSize = allocSize - size;
- + if (freeSize != 0)
- + {
- + _FreeExtraSpace(OutputBuffer, item, size, freeSize);
- + }
- +#endif
- +#else
- + gcsBUFITEM_BUFFER_PTR item;
- + gctINT size;
- +
- + gcmDBGASSERT(DataSize != 0, "%d", DataSize);
- + gcmDBGASSERT(Data != gcvNULL, "%p", Data);
- +
- + /* Determine the maximum item size. */
- + size = gcmSIZEOF(gcsBUFITEM_BUFFER) + DataSize;
- +
- + /* Allocate prefix item. */
- + item = (gcsBUFITEM_BUFFER_PTR) _AllocateItem(OutputBuffer, size);
- +
- + /* Set item data. */
- + item->type = gcvBUFITEM_BUFFER;
- + item->indent = Indent;
- + item->dataSize = DataSize;
- + item->address = Address;
- +
- + /* Copy argument value. */
- + memcpy(item + 1, Data, DataSize);
- +#endif
- +}
- +#endif
- +
- +static gcmINLINE void
- +_InitBuffers(
- + void
- + )
- +{
- + int i;
- +
- + if (_outputBufferHead == gcvNULL)
- + {
- + for (i = 0; i < gcdTHREAD_BUFFERS; i += 1)
- + {
- + if (_outputBufferTail == gcvNULL)
- + {
- + _outputBufferHead = &_outputBuffer[i];
- + }
- + else
- + {
- + _outputBufferTail->next = &_outputBuffer[i];
- + }
- +
- +#if gcdTHREAD_BUFFERS > 1
- + _outputBuffer[i].threadID = ~0U;
- +#endif
- +
- + _outputBuffer[i].prev = _outputBufferTail;
- + _outputBuffer[i].next = gcvNULL;
- +
- + _outputBufferTail = &_outputBuffer[i];
- + }
- + }
- +}
- +
- +static gcmINLINE gcsBUFFERED_OUTPUT_PTR
- +_GetOutputBuffer(
- + void
- + )
- +{
- + gcsBUFFERED_OUTPUT_PTR outputBuffer;
- +
- +#if gcdTHREAD_BUFFERS > 1
- + /* Get the current thread ID. */
- + gctUINT32 ThreadID = gcmkGETTHREADID();
- +
- + /* Locate the output buffer for the thread. */
- + outputBuffer = _outputBufferHead;
- +
- + while (outputBuffer != gcvNULL)
- + {
- + if (outputBuffer->threadID == ThreadID)
- + {
- + break;
- + }
- +
- + outputBuffer = outputBuffer->next;
- + }
- +
- + /* No matching buffer found? */
- + if (outputBuffer == gcvNULL)
- + {
- + /* Get the tail for the buffer. */
- + outputBuffer = _outputBufferTail;
- +
- + /* Move it to the head. */
- + _outputBufferTail = _outputBufferTail->prev;
- + _outputBufferTail->next = gcvNULL;
- +
- + outputBuffer->prev = gcvNULL;
- + outputBuffer->next = _outputBufferHead;
- +
- + _outputBufferHead->prev = outputBuffer;
- + _outputBufferHead = outputBuffer;
- +
- + /* Reset the buffer. */
- + outputBuffer->threadID = ThreadID;
- +#if gcdBUFFERED_OUTPUT
- + outputBuffer->start = 0;
- + outputBuffer->index = 0;
- + outputBuffer->count = 0;
- +#endif
- +#if gcdSHOW_LINE_NUMBER
- + outputBuffer->lineNumber = 0;
- +#endif
- + }
- +#else
- + outputBuffer = _outputBufferHead;
- +#endif
- +
- + return outputBuffer;
- +}
- +
- +static gcmINLINE int _GetArgumentSize(
- + IN gctCONST_STRING Message
- + )
- +{
- + int i, count;
- +
- + gcmDBGASSERT(Message != gcvNULL, "%p", Message);
- +
- + for (i = 0, count = 0; Message[i]; i += 1)
- + {
- + if (Message[i] == '%')
- + {
- + count += 1;
- + }
- + }
- +
- + return count * gcmSIZEOF(gctUINT32);
- +}
- +
- +#if gcdHAVEPREFIX
- +static void
- +_InitPrefixData(
- + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
- + IN gctPOINTER Data
- + )
- +{
- + gctUINT8_PTR data = (gctUINT8_PTR) Data;
- +
- +#if gcdSHOW_TIME
- + {
- + gctUINT64 time;
- + gckOS_GetProfileTick(&time);
- + gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT64));
- + * ((gctUINT64_PTR) data) = time;
- + data += gcmSIZEOF(gctUINT64);
- + }
- +#endif
- +
- +#if gcdSHOW_LINE_NUMBER
- + {
- + gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT64));
- + * ((gctUINT64_PTR) data) = OutputBuffer->lineNumber;
- + data += gcmSIZEOF(gctUINT64);
- + }
- +#endif
- +
- +#if gcdSHOW_PROCESS_ID
- + {
- + gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT32));
- + * ((gctUINT32_PTR) data) = gcmkGETPROCESSID();
- + data += gcmSIZEOF(gctUINT32);
- + }
- +#endif
- +
- +#if gcdSHOW_THREAD_ID
- + {
- + gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT32));
- + * ((gctUINT32_PTR) data) = gcmkGETTHREADID();
- + }
- +#endif
- +}
- +#endif
- +
- +static void
- +_Print(
- + IN gctUINT ArgumentSize,
- + IN gctBOOL CopyMessage,
- + IN gctCONST_STRING Message,
- + IN gctARGUMENTS Arguments
- + )
- +{
- + gcsBUFFERED_OUTPUT_PTR outputBuffer;
- + gcmkDECLARE_LOCK(lockHandle);
- +
- + gcmkLOCKSECTION(lockHandle);
- +
- + /* Initialize output buffer list. */
- + _InitBuffers();
- +
- + /* Locate the proper output buffer. */
- + outputBuffer = _GetOutputBuffer();
- +
- + /* Update the line number. */
- +#if gcdSHOW_LINE_NUMBER
- + outputBuffer->lineNumber += 1;
- +#endif
- +
- + /* Print prefix. */
- +#if gcdHAVEPREFIX
- + {
- + gctUINT8_PTR alignedPrefixData;
- + gctUINT8 prefixData[gcdPREFIX_SIZE + gcdPREFIX_ALIGNMENT];
- +
- + /* Compute aligned pointer. */
- + alignedPrefixData = prefixData;
- + gcmkALIGNPTR(gctUINT8_PTR, alignedPrefixData, gcdPREFIX_ALIGNMENT);
- +
- + /* Initialize the prefix data. */
- + _InitPrefixData(outputBuffer, alignedPrefixData);
- +
- + /* Print the prefix. */
- + gcdOUTPUTPREFIX(outputBuffer, alignedPrefixData);
- + }
- +#endif
- +
- + /* Form the indent string. */
- + if (strncmp(Message, "--", 2) == 0)
- + {
- + outputBuffer->indent -= 2;
- + }
- +
- + /* Print the message. */
- + if (CopyMessage)
- + {
- + gcdOUTPUTCOPY(
- + outputBuffer, outputBuffer->indent,
- + Message, ArgumentSize, * (gctPOINTER *) &Arguments
- + );
- + }
- + else
- + {
- + gcdOUTPUTSTRING(
- + outputBuffer, outputBuffer->indent,
- + Message, ArgumentSize, * (gctPOINTER *) &Arguments
- + );
- + }
- +
- + /* Check increasing indent. */
- + if (strncmp(Message, "++", 2) == 0)
- + {
- + outputBuffer->indent += 2;
- + }
- +
- + gcmkUNLOCKSECTION(lockHandle);
- +}
- +
- +
- +/******************************************************************************\
- +********************************* Debug Macros *********************************
- +\******************************************************************************/
- +
- +#ifdef __QNXNTO__
- +
- +extern volatile unsigned g_nQnxInIsrs;
- +
- +#define gcmDEBUGPRINT(ArgumentSize, CopyMessage, Message) \
- +{ \
- + if (atomic_add_value(&g_nQnxInIsrs, 1) == 0) \
- + { \
- + gctARGUMENTS __arguments__; \
- + gcmkARGUMENTS_START(__arguments__, Message); \
- + _Print(ArgumentSize, CopyMessage, Message, __arguments__); \
- + gcmkARGUMENTS_END(__arguments__); \
- + } \
- + atomic_sub(&g_nQnxInIsrs, 1); \
- +}
- +
- +#else
- +
- +#define gcmDEBUGPRINT(ArgumentSize, CopyMessage, Message) \
- +{ \
- + gctARGUMENTS __arguments__; \
- + gcmkARGUMENTS_START(__arguments__, Message); \
- + _Print(ArgumentSize, CopyMessage, Message, __arguments__); \
- + gcmkARGUMENTS_END(__arguments__); \
- +}
- +
- +#endif
- +
- +/******************************************************************************\
- +********************************** Debug Code **********************************
- +\******************************************************************************/
- +
- +/*******************************************************************************
- +**
- +** gckOS_Print
- +**
- +** Send a message to the debugger.
- +**
- +** INPUT:
- +**
- +** gctCONST_STRING Message
- +** Pointer to message.
- +**
- +** ...
- +** Optional arguments.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +void
- +gckOS_Print(
- + IN gctCONST_STRING Message,
- + ...
- + )
- +{
- + gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_PrintN
- +**
- +** Send a message to the debugger.
- +**
- +** INPUT:
- +**
- +** gctUINT ArgumentSize
- +** The size of the optional arguments in bytes.
- +**
- +** gctCONST_STRING Message
- +** Pointer to message.
- +**
- +** ...
- +** Optional arguments.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +void
- +gckOS_PrintN(
- + IN gctUINT ArgumentSize,
- + IN gctCONST_STRING Message,
- + ...
- + )
- +{
- + gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message);
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_CopyPrint
- +**
- +** Send a message to the debugger. If in buffered output mode, the entire
- +** message will be copied into the buffer instead of using the pointer to
- +** the string.
- +**
- +** INPUT:
- +**
- +** gctCONST_STRING Message
- +** Pointer to message.
- +**
- +** ...
- +** Optional arguments.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +void
- +gckOS_CopyPrint(
- + IN gctCONST_STRING Message,
- + ...
- + )
- +{
- + gcmDEBUGPRINT(_GetArgumentSize(Message), gcvTRUE, Message);
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_DumpBuffer
- +**
- +** Print the contents of the specified buffer.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to gckOS object.
- +**
- +** gctPOINTER Buffer
- +** Pointer to the buffer to print.
- +**
- +** gctUINT Size
- +** Size of the buffer.
- +**
- +** gceDUMP_BUFFER Type
- +** Buffer type.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +void
- +gckOS_DumpBuffer(
- + IN gckOS Os,
- + IN gctPOINTER Buffer,
- + IN gctUINT Size,
- + IN gceDUMP_BUFFER Type,
- + IN gctBOOL CopyMessage
- + )
- +{
- + gctUINT32 address;
- + gcsBUFFERED_OUTPUT_PTR outputBuffer;
- + static gctBOOL userLocked;
- + gctCHAR *buffer = (gctCHAR*)Buffer;
- +
- + gcmkDECLARE_LOCK(lockHandle);
- +
- + /* Request lock when not coming from user,
- + or coming from user and not yet locked
- + and message is starting with @[. */
- + if (Type == gceDUMP_BUFFER_FROM_USER)
- + {
- + if ((Size > 2)
- + && (buffer[0] == '@')
- + && (buffer[1] == '['))
- + {
- + /* Beginning of a user dump. */
- + gcmkLOCKSECTION(lockHandle);
- + userLocked = gcvTRUE;
- + }
- + /* Else, let it pass through. */
- + }
- + else
- + {
- + gcmkLOCKSECTION(lockHandle);
- + userLocked = gcvFALSE;
- + }
- +
- + if (Buffer != gcvNULL)
- + {
- + /* Initialize output buffer list. */
- + _InitBuffers();
- +
- + /* Locate the proper output buffer. */
- + outputBuffer = _GetOutputBuffer();
- +
- + /* Update the line number. */
- +#if gcdSHOW_LINE_NUMBER
- + outputBuffer->lineNumber += 1;
- +#endif
- +
- + /* Get the physical address of the buffer. */
- + if (Type != gceDUMP_BUFFER_FROM_USER)
- + {
- + gcmkVERIFY_OK(gckOS_GetPhysicalAddress(Os, Buffer, &address));
- + }
- + else
- + {
- + address = 0;
- + }
- +
- +#if gcdHAVEPREFIX
- + {
- + gctUINT8_PTR alignedPrefixData;
- + gctUINT8 prefixData[gcdPREFIX_SIZE + gcdPREFIX_ALIGNMENT];
- +
- + /* Compute aligned pointer. */
- + alignedPrefixData = prefixData;
- + gcmkALIGNPTR(gctUINT8_PTR, alignedPrefixData, gcdPREFIX_ALIGNMENT);
- +
- + /* Initialize the prefix data. */
- + _InitPrefixData(outputBuffer, alignedPrefixData);
- +
- + /* Print/schedule the buffer. */
- + gcdOUTPUTBUFFER(
- + outputBuffer, outputBuffer->indent,
- + alignedPrefixData, Buffer, address, Size, Type, 0
- + );
- + }
- +#else
- + /* Print/schedule the buffer. */
- + if (Type == gceDUMP_BUFFER_FROM_USER)
- + {
- + gcdOUTPUTSTRING(
- + outputBuffer, outputBuffer->indent,
- + Buffer, 0, gcvNULL
- + );
- + }
- + else
- + {
- + gcdOUTPUTBUFFER(
- + outputBuffer, outputBuffer->indent,
- + gcvNULL, Buffer, address, Size, Type, 0
- + );
- + }
- +#endif
- + }
- +
- + /* Unlock when not coming from user,
- + or coming from user and not yet locked. */
- + if (userLocked)
- + {
- + if ((Size > 4)
- + && (buffer[0] == ']')
- + && (buffer[1] == ' ')
- + && (buffer[2] == '-')
- + && (buffer[3] == '-'))
- + {
- + /* End of a user dump. */
- + gcmkUNLOCKSECTION(lockHandle);
- + userLocked = gcvFALSE;
- + }
- + /* Else, let it pass through, don't unlock. */
- + }
- + else
- + {
- + gcmkUNLOCKSECTION(lockHandle);
- + }
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_DebugTrace
- +**
- +** Send a leveled message to the debugger.
- +**
- +** INPUT:
- +**
- +** gctUINT32 Level
- +** Debug level of message.
- +**
- +** gctCONST_STRING Message
- +** Pointer to message.
- +**
- +** ...
- +** Optional arguments.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +void
- +gckOS_DebugTrace(
- + IN gctUINT32 Level,
- + IN gctCONST_STRING Message,
- + ...
- + )
- +{
- + if (Level > _debugLevel)
- + {
- + return;
- + }
- +
- + gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_DebugTraceN
- +**
- +** Send a leveled message to the debugger.
- +**
- +** INPUT:
- +**
- +** gctUINT32 Level
- +** Debug level of message.
- +**
- +** gctUINT ArgumentSize
- +** The size of the optional arguments in bytes.
- +**
- +** gctCONST_STRING Message
- +** Pointer to message.
- +**
- +** ...
- +** Optional arguments.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +void
- +gckOS_DebugTraceN(
- + IN gctUINT32 Level,
- + IN gctUINT ArgumentSize,
- + IN gctCONST_STRING Message,
- + ...
- + )
- +{
- + if (Level > _debugLevel)
- + {
- + return;
- + }
- +
- + gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message);
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_DebugTraceZone
- +**
- +** Send a leveled and zoned message to the debugger.
- +**
- +** INPUT:
- +**
- +** gctUINT32 Level
- +** Debug level for message.
- +**
- +** gctUINT32 Zone
- +** Debug zone for message.
- +**
- +** gctCONST_STRING Message
- +** Pointer to message.
- +**
- +** ...
- +** Optional arguments.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +void
- +gckOS_DebugTraceZone(
- + IN gctUINT32 Level,
- + IN gctUINT32 Zone,
- + IN gctCONST_STRING Message,
- + ...
- + )
- +{
- + if ((Level > _debugLevel) || !(Zone & _debugZones))
- + {
- + return;
- + }
- +
- + gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_DebugTraceZoneN
- +**
- +** Send a leveled and zoned message to the debugger.
- +**
- +** INPUT:
- +**
- +** gctUINT32 Level
- +** Debug level for message.
- +**
- +** gctUINT32 Zone
- +** Debug zone for message.
- +**
- +** gctUINT ArgumentSize
- +** The size of the optional arguments in bytes.
- +**
- +** gctCONST_STRING Message
- +** Pointer to message.
- +**
- +** ...
- +** Optional arguments.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +void
- +gckOS_DebugTraceZoneN(
- + IN gctUINT32 Level,
- + IN gctUINT32 Zone,
- + IN gctUINT ArgumentSize,
- + IN gctCONST_STRING Message,
- + ...
- + )
- +{
- + if ((Level > _debugLevel) || !(Zone & _debugZones))
- + {
- + return;
- + }
- +
- + gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message);
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_DebugBreak
- +**
- +** Break into the debugger.
- +**
- +** INPUT:
- +**
- +** Nothing.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +void
- +gckOS_DebugBreak(
- + void
- + )
- +{
- + gckOS_DebugTrace(gcvLEVEL_ERROR, "%s(%d)", __FUNCTION__, __LINE__);
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_DebugFatal
- +**
- +** Send a message to the debugger and break into the debugger.
- +**
- +** INPUT:
- +**
- +** gctCONST_STRING Message
- +** Pointer to message.
- +**
- +** ...
- +** Optional arguments.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +void
- +gckOS_DebugFatal(
- + IN gctCONST_STRING Message,
- + ...
- + )
- +{
- + gcmkPRINT_VERSION();
- + gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
- +
- + /* Break into the debugger. */
- + gckOS_DebugBreak();
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_SetDebugLevel
- +**
- +** Set the debug level.
- +**
- +** INPUT:
- +**
- +** gctUINT32 Level
- +** New debug level.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +void
- +gckOS_SetDebugLevel(
- + IN gctUINT32 Level
- + )
- +{
- + _debugLevel = Level;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_SetDebugZone
- +**
- +** Set the debug zone.
- +**
- +** INPUT:
- +**
- +** gctUINT32 Zone
- +** New debug zone.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +void
- +gckOS_SetDebugZone(
- + IN gctUINT32 Zone
- + )
- +{
- + _debugZones = Zone;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_SetDebugLevelZone
- +**
- +** Set the debug level and zone.
- +**
- +** INPUT:
- +**
- +** gctUINT32 Level
- +** New debug level.
- +**
- +** gctUINT32 Zone
- +** New debug zone.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +void
- +gckOS_SetDebugLevelZone(
- + IN gctUINT32 Level,
- + IN gctUINT32 Zone
- + )
- +{
- + _debugLevel = Level;
- + _debugZones = Zone;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_SetDebugZones
- +**
- +** Enable or disable debug zones.
- +**
- +** INPUT:
- +**
- +** gctUINT32 Zones
- +** Debug zones to enable or disable.
- +**
- +** gctBOOL Enable
- +** Set to gcvTRUE to enable the zones (or the Zones with the current
- +** zones) or gcvFALSE to disable the specified Zones.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +void
- +gckOS_SetDebugZones(
- + IN gctUINT32 Zones,
- + IN gctBOOL Enable
- + )
- +{
- + if (Enable)
- + {
- + /* Enable the zones. */
- + _debugZones |= Zones;
- + }
- + else
- + {
- + /* Disable the zones. */
- + _debugZones &= ~Zones;
- + }
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_Verify
- +**
- +** Called to verify the result of a function call.
- +**
- +** INPUT:
- +**
- +** gceSTATUS Status
- +** Function call result.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +void
- +gckOS_Verify(
- + IN gceSTATUS status
- + )
- +{
- + _lastError = status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_DebugFlush
- +**
- +** Force messages to be flushed out.
- +**
- +** INPUT:
- +**
- +** gctCONST_STRING CallerName
- +** Name of the caller function.
- +**
- +** gctUINT LineNumber
- +** Line number of the caller.
- +**
- +** gctUINT32 DmaAddress
- +** The current DMA address or ~0U to ignore.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +void
- +gckOS_DebugFlush(
- + gctCONST_STRING CallerName,
- + gctUINT LineNumber,
- + gctUINT32 DmaAddress
- + )
- +{
- +#if gcdBUFFERED_OUTPUT
- + _DirectPrint("\nFlush requested by %s(%d).\n\n", CallerName, LineNumber);
- + _Flush(DmaAddress);
- +#endif
- +}
- +gctCONST_STRING
- +gckOS_DebugStatus2Name(
- + gceSTATUS status
- + )
- +{
- + switch (status)
- + {
- + case gcvSTATUS_OK:
- + return "gcvSTATUS_OK";
- + case gcvSTATUS_TRUE:
- + return "gcvSTATUS_TRUE";
- + case gcvSTATUS_NO_MORE_DATA:
- + return "gcvSTATUS_NO_MORE_DATA";
- + case gcvSTATUS_CACHED:
- + return "gcvSTATUS_CACHED";
- + case gcvSTATUS_MIPMAP_TOO_LARGE:
- + return "gcvSTATUS_MIPMAP_TOO_LARGE";
- + case gcvSTATUS_NAME_NOT_FOUND:
- + return "gcvSTATUS_NAME_NOT_FOUND";
- + case gcvSTATUS_NOT_OUR_INTERRUPT:
- + return "gcvSTATUS_NOT_OUR_INTERRUPT";
- + case gcvSTATUS_MISMATCH:
- + return "gcvSTATUS_MISMATCH";
- + case gcvSTATUS_MIPMAP_TOO_SMALL:
- + return "gcvSTATUS_MIPMAP_TOO_SMALL";
- + case gcvSTATUS_LARGER:
- + return "gcvSTATUS_LARGER";
- + case gcvSTATUS_SMALLER:
- + return "gcvSTATUS_SMALLER";
- + case gcvSTATUS_CHIP_NOT_READY:
- + return "gcvSTATUS_CHIP_NOT_READY";
- + case gcvSTATUS_NEED_CONVERSION:
- + return "gcvSTATUS_NEED_CONVERSION";
- + case gcvSTATUS_SKIP:
- + return "gcvSTATUS_SKIP";
- + case gcvSTATUS_DATA_TOO_LARGE:
- + return "gcvSTATUS_DATA_TOO_LARGE";
- + case gcvSTATUS_INVALID_CONFIG:
- + return "gcvSTATUS_INVALID_CONFIG";
- + case gcvSTATUS_CHANGED:
- + return "gcvSTATUS_CHANGED";
- + case gcvSTATUS_NOT_SUPPORT_DITHER:
- + return "gcvSTATUS_NOT_SUPPORT_DITHER";
- +
- + case gcvSTATUS_INVALID_ARGUMENT:
- + return "gcvSTATUS_INVALID_ARGUMENT";
- + case gcvSTATUS_INVALID_OBJECT:
- + return "gcvSTATUS_INVALID_OBJECT";
- + case gcvSTATUS_OUT_OF_MEMORY:
- + return "gcvSTATUS_OUT_OF_MEMORY";
- + case gcvSTATUS_MEMORY_LOCKED:
- + return "gcvSTATUS_MEMORY_LOCKED";
- + case gcvSTATUS_MEMORY_UNLOCKED:
- + return "gcvSTATUS_MEMORY_UNLOCKED";
- + case gcvSTATUS_HEAP_CORRUPTED:
- + return "gcvSTATUS_HEAP_CORRUPTED";
- + case gcvSTATUS_GENERIC_IO:
- + return "gcvSTATUS_GENERIC_IO";
- + case gcvSTATUS_INVALID_ADDRESS:
- + return "gcvSTATUS_INVALID_ADDRESS";
- + case gcvSTATUS_CONTEXT_LOSSED:
- + return "gcvSTATUS_CONTEXT_LOSSED";
- + case gcvSTATUS_TOO_COMPLEX:
- + return "gcvSTATUS_TOO_COMPLEX";
- + case gcvSTATUS_BUFFER_TOO_SMALL:
- + return "gcvSTATUS_BUFFER_TOO_SMALL";
- + case gcvSTATUS_INTERFACE_ERROR:
- + return "gcvSTATUS_INTERFACE_ERROR";
- + case gcvSTATUS_NOT_SUPPORTED:
- + return "gcvSTATUS_NOT_SUPPORTED";
- + case gcvSTATUS_MORE_DATA:
- + return "gcvSTATUS_MORE_DATA";
- + case gcvSTATUS_TIMEOUT:
- + return "gcvSTATUS_TIMEOUT";
- + case gcvSTATUS_OUT_OF_RESOURCES:
- + return "gcvSTATUS_OUT_OF_RESOURCES";
- + case gcvSTATUS_INVALID_DATA:
- + return "gcvSTATUS_INVALID_DATA";
- + case gcvSTATUS_INVALID_MIPMAP:
- + return "gcvSTATUS_INVALID_MIPMAP";
- + case gcvSTATUS_NOT_FOUND:
- + return "gcvSTATUS_NOT_FOUND";
- + case gcvSTATUS_NOT_ALIGNED:
- + return "gcvSTATUS_NOT_ALIGNED";
- + case gcvSTATUS_INVALID_REQUEST:
- + return "gcvSTATUS_INVALID_REQUEST";
- + case gcvSTATUS_GPU_NOT_RESPONDING:
- + return "gcvSTATUS_GPU_NOT_RESPONDING";
- + case gcvSTATUS_TIMER_OVERFLOW:
- + return "gcvSTATUS_TIMER_OVERFLOW";
- + case gcvSTATUS_VERSION_MISMATCH:
- + return "gcvSTATUS_VERSION_MISMATCH";
- + case gcvSTATUS_LOCKED:
- + return "gcvSTATUS_LOCKED";
- +
- + /* Linker errors. */
- + case gcvSTATUS_GLOBAL_TYPE_MISMATCH:
- + return "gcvSTATUS_GLOBAL_TYPE_MISMATCH";
- + case gcvSTATUS_TOO_MANY_ATTRIBUTES:
- + return "gcvSTATUS_TOO_MANY_ATTRIBUTES";
- + case gcvSTATUS_TOO_MANY_UNIFORMS:
- + return "gcvSTATUS_TOO_MANY_UNIFORMS";
- + case gcvSTATUS_TOO_MANY_VARYINGS:
- + return "gcvSTATUS_TOO_MANY_VARYINGS";
- + case gcvSTATUS_UNDECLARED_VARYING:
- + return "gcvSTATUS_UNDECLARED_VARYING";
- + case gcvSTATUS_VARYING_TYPE_MISMATCH:
- + return "gcvSTATUS_VARYING_TYPE_MISMATCH";
- + case gcvSTATUS_MISSING_MAIN:
- + return "gcvSTATUS_MISSING_MAIN";
- + case gcvSTATUS_NAME_MISMATCH:
- + return "gcvSTATUS_NAME_MISMATCH";
- + case gcvSTATUS_INVALID_INDEX:
- + return "gcvSTATUS_INVALID_INDEX";
- + default:
- + return "nil";
- + }
- +}
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c 2015-03-08 14:27:37.633684500 -0500
- @@ -0,0 +1,2898 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal_kernel_precomp.h"
- +#include "gc_hal_kernel_buffer.h"
- +
- +#ifdef __QNXNTO__
- +#include <atomic.h>
- +#include "gc_hal_kernel_qnx.h"
- +#endif
- +
- +#define _GC_OBJ_ZONE gcvZONE_EVENT
- +
- +#define gcdEVENT_ALLOCATION_COUNT (4096 / gcmSIZEOF(gcsHAL_INTERFACE))
- +#define gcdEVENT_MIN_THRESHOLD 4
- +
- +/******************************************************************************\
- +********************************* Support Code *********************************
- +\******************************************************************************/
- +
- +static gceSTATUS
- +gckEVENT_AllocateQueue(
- + IN gckEVENT Event,
- + OUT gcsEVENT_QUEUE_PTR * Queue
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Event=0x%x", Event);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- + gcmkVERIFY_ARGUMENT(Queue != gcvNULL);
- +
- + /* Do we have free queues? */
- + if (Event->freeList == gcvNULL)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +
- + /* Move one free queue from the free list. */
- + * Queue = Event->freeList;
- + Event->freeList = Event->freeList->next;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Queue=0x%x", gcmOPT_POINTER(Queue));
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +static gceSTATUS
- +gckEVENT_FreeQueue(
- + IN gckEVENT Event,
- + OUT gcsEVENT_QUEUE_PTR Queue
- + )
- +{
- + gceSTATUS status = gcvSTATUS_OK;
- +
- + gcmkHEADER_ARG("Event=0x%x", Event);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- + gcmkVERIFY_ARGUMENT(Queue != gcvNULL);
- +
- + /* Move one free queue from the free list. */
- + Queue->next = Event->freeList;
- + Event->freeList = Queue;
- +
- + /* Success. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +static gceSTATUS
- +gckEVENT_FreeRecord(
- + IN gckEVENT Event,
- + IN gcsEVENT_PTR Record
- + )
- +{
- + gceSTATUS status;
- + gctBOOL acquired = gcvFALSE;
- +
- + gcmkHEADER_ARG("Event=0x%x Record=0x%x", Event, Record);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- + gcmkVERIFY_ARGUMENT(Record != gcvNULL);
- +
- + /* Acquire the mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(Event->os,
- + Event->freeEventMutex,
- + gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + /* Push the record on the free list. */
- + Record->next = Event->freeEventList;
- + Event->freeEventList = Record;
- + Event->freeEventCount += 1;
- +
- + /* Release the mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Roll back. */
- + if (acquired)
- + {
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return gcvSTATUS_OK;
- +}
- +
- +static gceSTATUS
- +gckEVENT_IsEmpty(
- + IN gckEVENT Event,
- + OUT gctBOOL_PTR IsEmpty
- + )
- +{
- + gceSTATUS status;
- + gctSIZE_T i;
- +
- + gcmkHEADER_ARG("Event=0x%x", Event);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- + gcmkVERIFY_ARGUMENT(IsEmpty != gcvNULL);
- +
- + /* Assume the event queue is empty. */
- + *IsEmpty = gcvTRUE;
- +
- + /* Try acquiring the mutex. */
- + status = gckOS_AcquireMutex(Event->os, Event->eventQueueMutex, 0);
- + if (status == gcvSTATUS_TIMEOUT)
- + {
- + /* Timeout - queue is no longer empty. */
- + *IsEmpty = gcvFALSE;
- + }
- + else
- + {
- + /* Bail out on error. */
- + gcmkONERROR(status);
- +
- + /* Walk the event queue. */
- + for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
- + {
- + /* Check whether this event is in use. */
- + if (Event->queues[i].head != gcvNULL)
- + {
- + /* The event is in use, hence the queue is not empty. */
- + *IsEmpty = gcvFALSE;
- + break;
- + }
- + }
- +
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*IsEmpty=%d", gcmOPT_VALUE(IsEmpty));
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +static gceSTATUS
- +_TryToIdleGPU(
- + IN gckEVENT Event
- +)
- +{
- + gceSTATUS status;
- + gctBOOL empty = gcvFALSE, idle = gcvFALSE;
- + gctBOOL powerLocked = gcvFALSE;
- + gckHARDWARE hardware;
- +
- + gcmkHEADER_ARG("Event=0x%x", Event);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- +
- + /* Grab gckHARDWARE object. */
- + hardware = Event->kernel->hardware;
- + gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
- +
- + /* Check whether the event queue is empty. */
- + gcmkONERROR(gckEVENT_IsEmpty(Event, &empty));
- +
- + if (empty)
- + {
- + status = gckOS_AcquireMutex(hardware->os, hardware->powerMutex, 0);
- + if (status == gcvSTATUS_TIMEOUT)
- + {
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- +
- + powerLocked = gcvTRUE;
- +
- + /* Query whether the hardware is idle. */
- + gcmkONERROR(gckHARDWARE_QueryIdle(Event->kernel->hardware, &idle));
- +
- + gcmkONERROR(gckOS_ReleaseMutex(hardware->os, hardware->powerMutex));
- + powerLocked = gcvFALSE;
- +
- + if (idle)
- + {
- + /* Inform the system of idle GPU. */
- + gcmkONERROR(gckOS_Broadcast(Event->os,
- + Event->kernel->hardware,
- + gcvBROADCAST_GPU_IDLE));
- + }
- + }
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (powerLocked)
- + {
- + gcmkONERROR(gckOS_ReleaseMutex(hardware->os, hardware->powerMutex));
- + powerLocked = gcvFALSE;
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +static gceSTATUS
- +__RemoveRecordFromProcessDB(
- + IN gckEVENT Event,
- + IN gcsEVENT_PTR Record
- + )
- +{
- + gcmkHEADER_ARG("Event=0x%x Record=0x%x", Event, Record);
- + gcmkVERIFY_ARGUMENT(Record != gcvNULL);
- +
- + while (Record != gcvNULL)
- + {
- + if (Record->info.command == gcvHAL_SIGNAL)
- + {
- + /* TODO: Find a better place to bind signal to hardware.*/
- + gcmkVERIFY_OK(gckOS_SignalSetHardware(Event->os,
- + gcmUINT64_TO_PTR(Record->info.u.Signal.signal),
- + Event->kernel->hardware));
- + }
- +
- + if (Record->fromKernel)
- + {
- + /* No need to check db if event is from kernel. */
- + Record = Record->next;
- + continue;
- + }
- +
- + switch (Record->info.command)
- + {
- + case gcvHAL_FREE_NON_PAGED_MEMORY:
- + gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
- + Event->kernel,
- + Record->processID,
- + gcvDB_NON_PAGED,
- + gcmUINT64_TO_PTR(Record->info.u.FreeNonPagedMemory.logical)));
- + break;
- +
- + case gcvHAL_FREE_CONTIGUOUS_MEMORY:
- + gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
- + Event->kernel,
- + Record->processID,
- + gcvDB_CONTIGUOUS,
- + gcmUINT64_TO_PTR(Record->info.u.FreeContiguousMemory.logical)));
- + break;
- +
- + case gcvHAL_FREE_VIDEO_MEMORY:
- + gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
- + Event->kernel,
- + Record->processID,
- + gcvDB_VIDEO_MEMORY,
- + gcmUINT64_TO_PTR(Record->info.u.FreeVideoMemory.node)));
- +
- + {
- + gcuVIDMEM_NODE_PTR node = (gcuVIDMEM_NODE_PTR)(gcmUINT64_TO_PTR(Record->info.u.FreeVideoMemory.node));
- +
- + if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
- + {
- + gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(Event->kernel,
- + Record->processID,
- + gcvDB_VIDEO_MEMORY_RESERVED,
- + node));
- + }
- + else if(node->Virtual.contiguous)
- + {
- + gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(Event->kernel,
- + Record->processID,
- + gcvDB_VIDEO_MEMORY_CONTIGUOUS,
- + node));
- + }
- + else
- + {
- + gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(Event->kernel,
- + Record->processID,
- + gcvDB_VIDEO_MEMORY_VIRTUAL,
- + node));
- + }
- + }
- +
- + break;
- +
- + case gcvHAL_UNLOCK_VIDEO_MEMORY:
- + gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
- + Event->kernel,
- + Record->processID,
- + gcvDB_VIDEO_MEMORY_LOCKED,
- + gcmUINT64_TO_PTR(Record->info.u.UnlockVideoMemory.node)));
- + break;
- +
- + case gcvHAL_UNMAP_USER_MEMORY:
- + gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
- + Event->kernel,
- + Record->processID,
- + gcvDB_MAP_USER_MEMORY,
- + gcmINT2PTR(Record->info.u.UnmapUserMemory.info)));
- + break;
- +
- + case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
- + gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
- + Event->kernel,
- + Record->processID,
- + gcvDB_COMMAND_BUFFER,
- + gcmUINT64_TO_PTR(Record->info.u.FreeVirtualCommandBuffer.logical)));
- + break;
- +
- + default:
- + break;
- + }
- +
- + Record = Record->next;
- + }
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +void
- +_SubmitTimerFunction(
- + gctPOINTER Data
- + )
- +{
- + gckEVENT event = (gckEVENT)Data;
- + gcmkVERIFY_OK(gckEVENT_Submit(event, gcvTRUE, gcvFALSE));
- +}
- +
- +/******************************************************************************\
- +******************************* gckEVENT API Code *******************************
- +\******************************************************************************/
- +
- +/*******************************************************************************
- +**
- +** gckEVENT_Construct
- +**
- +** Construct a new gckEVENT object.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** OUTPUT:
- +**
- +** gckEVENT * Event
- +** Pointer to a variable that receives the gckEVENT object pointer.
- +*/
- +gceSTATUS
- +gckEVENT_Construct(
- + IN gckKERNEL Kernel,
- + OUT gckEVENT * Event
- + )
- +{
- + gckOS os;
- + gceSTATUS status;
- + gckEVENT eventObj = gcvNULL;
- + int i;
- + gcsEVENT_PTR record;
- + gctPOINTER pointer = gcvNULL;
- +
- + gcmkHEADER_ARG("Kernel=0x%x", Kernel);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(Event != gcvNULL);
- +
- + /* Extract the pointer to the gckOS object. */
- + os = Kernel->os;
- + gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
- +
- + /* Allocate the gckEVENT object. */
- + gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct _gckEVENT), &pointer));
- +
- + eventObj = pointer;
- +
- + /* Reset the object. */
- + gcmkVERIFY_OK(gckOS_ZeroMemory(eventObj, gcmSIZEOF(struct _gckEVENT)));
- +
- + /* Initialize the gckEVENT object. */
- + eventObj->object.type = gcvOBJ_EVENT;
- + eventObj->kernel = Kernel;
- + eventObj->os = os;
- +
- + /* Create the mutexes. */
- + gcmkONERROR(gckOS_CreateMutex(os, &eventObj->eventQueueMutex));
- + gcmkONERROR(gckOS_CreateMutex(os, &eventObj->freeEventMutex));
- + gcmkONERROR(gckOS_CreateMutex(os, &eventObj->eventListMutex));
- +
- + /* Create a bunch of event reccords. */
- + for (i = 0; i < gcdEVENT_ALLOCATION_COUNT; i += 1)
- + {
- + /* Allocate an event record. */
- + gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcsEVENT), &pointer));
- +
- + record = pointer;
- +
- + /* Push it on the free list. */
- + record->next = eventObj->freeEventList;
- + eventObj->freeEventList = record;
- + eventObj->freeEventCount += 1;
- + }
- +
- + /* Initialize the free list of event queues. */
- + for (i = 0; i < gcdREPO_LIST_COUNT; i += 1)
- + {
- + eventObj->repoList[i].next = eventObj->freeList;
- + eventObj->freeList = &eventObj->repoList[i];
- + }
- +
- + /* Construct the atom. */
- + gcmkONERROR(gckOS_AtomConstruct(os, &eventObj->freeAtom));
- + gcmkONERROR(gckOS_AtomSet(os,
- + eventObj->freeAtom,
- + gcmCOUNTOF(eventObj->queues)));
- +
- +#if gcdSMP
- + gcmkONERROR(gckOS_AtomConstruct(os, &eventObj->pending));
- +#endif
- +
- + gcmkVERIFY_OK(gckOS_CreateTimer(os,
- + _SubmitTimerFunction,
- + (gctPOINTER)eventObj,
- + &eventObj->submitTimer));
- +
- + /* Return pointer to the gckEVENT object. */
- + *Event = eventObj;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Event=0x%x", *Event);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Roll back. */
- + if (eventObj != gcvNULL)
- + {
- + if (eventObj->eventQueueMutex != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_DeleteMutex(os, eventObj->eventQueueMutex));
- + }
- +
- + if (eventObj->freeEventMutex != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_DeleteMutex(os, eventObj->freeEventMutex));
- + }
- +
- + if (eventObj->eventListMutex != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_DeleteMutex(os, eventObj->eventListMutex));
- + }
- +
- + while (eventObj->freeEventList != gcvNULL)
- + {
- + record = eventObj->freeEventList;
- + eventObj->freeEventList = record->next;
- +
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, record));
- + }
- +
- + if (eventObj->freeAtom != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_AtomDestroy(os, eventObj->freeAtom));
- + }
- +
- +#if gcdSMP
- + if (eventObj->pending != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_AtomDestroy(os, eventObj->pending));
- + }
- +#endif
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, eventObj));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckEVENT_Destroy
- +**
- +** Destroy an gckEVENT object.
- +**
- +** INPUT:
- +**
- +** gckEVENT Event
- +** Pointer to an gckEVENT object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckEVENT_Destroy(
- + IN gckEVENT Event
- + )
- +{
- + gcsEVENT_PTR record;
- + gcsEVENT_QUEUE_PTR queue;
- +
- + gcmkHEADER_ARG("Event=0x%x", Event);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- +
- + if (Event->submitTimer != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_StopTimer(Event->os, Event->submitTimer));
- + gcmkVERIFY_OK(gckOS_DestroyTimer(Event->os, Event->submitTimer));
- + }
- +
- + /* Delete the queue mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->eventQueueMutex));
- +
- + /* Free all free events. */
- + while (Event->freeEventList != gcvNULL)
- + {
- + record = Event->freeEventList;
- + Event->freeEventList = record->next;
- +
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Event->os, record));
- + }
- +
- + /* Delete the free mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->freeEventMutex));
- +
- + /* Free all pending queues. */
- + while (Event->queueHead != gcvNULL)
- + {
- + /* Get the current queue. */
- + queue = Event->queueHead;
- +
- + /* Free all pending events. */
- + while (queue->head != gcvNULL)
- + {
- + record = queue->head;
- + queue->head = record->next;
- +
- + gcmkTRACE_ZONE_N(
- + gcvLEVEL_WARNING, gcvZONE_EVENT,
- + gcmSIZEOF(record) + gcmSIZEOF(queue->source),
- + "Event record 0x%x is still pending for %d.",
- + record, queue->source
- + );
- +
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Event->os, record));
- + }
- +
- + /* Remove the top queue from the list. */
- + if (Event->queueHead == Event->queueTail)
- + {
- + Event->queueHead =
- + Event->queueTail = gcvNULL;
- + }
- + else
- + {
- + Event->queueHead = Event->queueHead->next;
- + }
- +
- + /* Free the queue. */
- + gcmkVERIFY_OK(gckEVENT_FreeQueue(Event, queue));
- + }
- +
- + /* Delete the list mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->eventListMutex));
- +
- + /* Delete the atom. */
- + gcmkVERIFY_OK(gckOS_AtomDestroy(Event->os, Event->freeAtom));
- +
- +#if gcdSMP
- + gcmkVERIFY_OK(gckOS_AtomDestroy(Event->os, Event->pending));
- +#endif
- +
- + /* Mark the gckEVENT object as unknown. */
- + Event->object.type = gcvOBJ_UNKNOWN;
- +
- + /* Free the gckEVENT object. */
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Event->os, Event));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckEVENT_GetEvent
- +**
- +** Reserve the next available hardware event.
- +**
- +** INPUT:
- +**
- +** gckEVENT Event
- +** Pointer to an gckEVENT object.
- +**
- +** gctBOOL Wait
- +** Set to gcvTRUE to force the function to wait if no events are
- +** immediately available.
- +**
- +** gceKERNEL_WHERE Source
- +** Source of the event.
- +**
- +** OUTPUT:
- +**
- +** gctUINT8 * EventID
- +** Reserved event ID.
- +*/
- +static gceSTATUS
- +gckEVENT_GetEvent(
- + IN gckEVENT Event,
- + IN gctBOOL Wait,
- + OUT gctUINT8 * EventID,
- + IN gcsEVENT_PTR Head,
- + IN gceKERNEL_WHERE Source
- + )
- +{
- + gctINT i, id;
- + gceSTATUS status;
- + gctBOOL acquired = gcvFALSE;
- + gctINT32 free;
- +
- +#if gcdGPU_TIMEOUT
- + gctUINT32 timer = 0;
- +#endif
- +
- + gcmkHEADER_ARG("Event=0x%x Head=%p Source=%d", Event, Head, Source);
- +
- + while (gcvTRUE)
- + {
- + /* Grab the queue mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(Event->os,
- + Event->eventQueueMutex,
- + gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + /* Walk through all events. */
- + id = Event->lastID;
- + for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
- + {
- + gctINT nextID = gckMATH_ModuloInt((id + 1),
- + gcmCOUNTOF(Event->queues));
- +
- + if (Event->queues[id].head == gcvNULL)
- + {
- + *EventID = (gctUINT8) id;
- +
- + Event->lastID = (gctUINT8) nextID;
- +
- + /* Save time stamp of event. */
- + Event->queues[id].stamp = ++(Event->stamp);
- + Event->queues[id].head = Head;
- + Event->queues[id].source = Source;
- +
- + gcmkONERROR(gckOS_AtomDecrement(Event->os,
- + Event->freeAtom,
- + &free));
- +#if gcdDYNAMIC_SPEED
- + if (free <= gcdDYNAMIC_EVENT_THRESHOLD)
- + {
- + gcmkONERROR(gckOS_BroadcastHurry(
- + Event->os,
- + Event->kernel->hardware,
- + gcdDYNAMIC_EVENT_THRESHOLD - free));
- + }
- +#endif
- +
- + /* Release the queue mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(Event->os,
- + Event->eventQueueMutex));
- +
- + /* Success. */
- + gcmkTRACE_ZONE_N(
- + gcvLEVEL_INFO, gcvZONE_EVENT,
- + gcmSIZEOF(id),
- + "Using id=%d",
- + id
- + );
- +
- + gcmkFOOTER_ARG("*EventID=%u", *EventID);
- + return gcvSTATUS_OK;
- + }
- +
- + id = nextID;
- + }
- +
- +#if gcdDYNAMIC_SPEED
- + /* No free events, speed up the GPU right now! */
- + gcmkONERROR(gckOS_BroadcastHurry(Event->os,
- + Event->kernel->hardware,
- + gcdDYNAMIC_EVENT_THRESHOLD));
- +#endif
- +
- + /* Release the queue mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
- + acquired = gcvFALSE;
- +
- + /* Fail if wait is not requested. */
- + if (!Wait)
- + {
- + /* Out of resources. */
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +
- + /* Delay a while. */
- + gcmkONERROR(gckOS_Delay(Event->os, 1));
- +
- +#if gcdGPU_TIMEOUT
- + /* Increment the wait timer. */
- + timer += 1;
- +
- + if (timer == Event->kernel->timeOut)
- + {
- + /* Try to call any outstanding events. */
- + gcmkONERROR(gckHARDWARE_Interrupt(Event->kernel->hardware,
- + gcvTRUE));
- + }
- + else if (timer > Event->kernel->timeOut)
- + {
- + gcmkTRACE_N(
- + gcvLEVEL_ERROR,
- + gcmSIZEOF(gctCONST_STRING) + gcmSIZEOF(gctINT),
- + "%s(%d): no available events\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + /* Bail out. */
- + gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
- + }
- +#endif
- + }
- +
- +OnError:
- + if (acquired)
- + {
- + /* Release the queue mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckEVENT_AllocateRecord
- +**
- +** Allocate a record for the new event.
- +**
- +** INPUT:
- +**
- +** gckEVENT Event
- +** Pointer to an gckEVENT object.
- +**
- +** gctBOOL AllocateAllowed
- +** State for allocation if out of free events.
- +**
- +** OUTPUT:
- +**
- +** gcsEVENT_PTR * Record
- +** Allocated event record.
- +*/
- +gceSTATUS
- +gckEVENT_AllocateRecord(
- + IN gckEVENT Event,
- + IN gctBOOL AllocateAllowed,
- + OUT gcsEVENT_PTR * Record
- + )
- +{
- + gceSTATUS status;
- + gctBOOL acquired = gcvFALSE;
- + gctINT i;
- + gcsEVENT_PTR record;
- + gctPOINTER pointer = gcvNULL;
- +
- + gcmkHEADER_ARG("Event=0x%x AllocateAllowed=%d", Event, AllocateAllowed);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- + gcmkVERIFY_ARGUMENT(Record != gcvNULL);
- +
- + /* Acquire the mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->freeEventMutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + /* Test if we are below the allocation threshold. */
- + if ( (AllocateAllowed && (Event->freeEventCount < gcdEVENT_MIN_THRESHOLD)) ||
- + (Event->freeEventCount == 0) )
- + {
- + /* Allocate a bunch of records. */
- + for (i = 0; i < gcdEVENT_ALLOCATION_COUNT; i += 1)
- + {
- + /* Allocate an event record. */
- + gcmkONERROR(gckOS_Allocate(Event->os,
- + gcmSIZEOF(gcsEVENT),
- + &pointer));
- +
- + record = pointer;
- +
- + /* Push it on the free list. */
- + record->next = Event->freeEventList;
- + Event->freeEventList = record;
- + Event->freeEventCount += 1;
- + }
- + }
- +
- + *Record = Event->freeEventList;
- + Event->freeEventList = Event->freeEventList->next;
- + Event->freeEventCount -= 1;
- +
- + /* Release the mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
- + acquired = gcvFALSE;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Record=0x%x", gcmOPT_POINTER(Record));
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Roll back. */
- + if (acquired)
- + {
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckEVENT_AddList
- +**
- +** Add a new event to the list of events.
- +**
- +** INPUT:
- +**
- +** gckEVENT Event
- +** Pointer to an gckEVENT object.
- +**
- +** gcsHAL_INTERFACE_PTR Interface
- +** Pointer to the interface for the event to be added.
- +**
- +** gceKERNEL_WHERE FromWhere
- +** Place in the pipe where the event needs to be generated.
- +**
- +** gctBOOL AllocateAllowed
- +** State for allocation if out of free events.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckEVENT_AddList(
- + IN gckEVENT Event,
- + IN gcsHAL_INTERFACE_PTR Interface,
- + IN gceKERNEL_WHERE FromWhere,
- + IN gctBOOL AllocateAllowed,
- + IN gctBOOL FromKernel
- + )
- +{
- + gceSTATUS status;
- + gctBOOL acquired = gcvFALSE;
- + gcsEVENT_PTR record = gcvNULL;
- + gcsEVENT_QUEUE_PTR queue;
- + gckKERNEL kernel = Event->kernel;
- +
- + gcmkHEADER_ARG("Event=0x%x Interface=0x%x",
- + Event, Interface);
- +
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, _GC_OBJ_ZONE,
- + "FromWhere=%d AllocateAllowed=%d",
- + FromWhere, AllocateAllowed);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- + gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
- +
- + /* Verify the event command. */
- + gcmkASSERT
- + ( (Interface->command == gcvHAL_FREE_NON_PAGED_MEMORY)
- + || (Interface->command == gcvHAL_FREE_CONTIGUOUS_MEMORY)
- + || (Interface->command == gcvHAL_FREE_VIDEO_MEMORY)
- + || (Interface->command == gcvHAL_WRITE_DATA)
- + || (Interface->command == gcvHAL_UNLOCK_VIDEO_MEMORY)
- + || (Interface->command == gcvHAL_SIGNAL)
- + || (Interface->command == gcvHAL_UNMAP_USER_MEMORY)
- + || (Interface->command == gcvHAL_TIMESTAMP)
- + || (Interface->command == gcvHAL_COMMIT_DONE)
- + || (Interface->command == gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER)
- + || (Interface->command == gcvHAL_SYNC_POINT)
- + );
- +
- + /* Validate the source. */
- + if ((FromWhere != gcvKERNEL_COMMAND) && (FromWhere != gcvKERNEL_PIXEL))
- + {
- + /* Invalid argument. */
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + /* Allocate a free record. */
- + gcmkONERROR(gckEVENT_AllocateRecord(Event, AllocateAllowed, &record));
- +
- + /* Termninate the record. */
- + record->next = gcvNULL;
- +
- + /* Record the committer. */
- + record->fromKernel = FromKernel;
- +
- + /* Copy the event interface into the record. */
- + gckOS_MemCopy(&record->info, Interface, gcmSIZEOF(record->info));
- +
- + /* Get process ID. */
- + gcmkONERROR(gckOS_GetProcessID(&record->processID));
- +
- +#ifdef __QNXNTO__
- + record->kernel = Event->kernel;
- +#endif
- +
- + gcmkONERROR(__RemoveRecordFromProcessDB(Event, record));
- +
- + /* Acquire the mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->eventListMutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + /* Do we need to allocate a new queue? */
- + if ((Event->queueTail == gcvNULL) || (Event->queueTail->source < FromWhere))
- + {
- + /* Allocate a new queue. */
- + gcmkONERROR(gckEVENT_AllocateQueue(Event, &queue));
- +
- + /* Initialize the queue. */
- + queue->source = FromWhere;
- + queue->head = gcvNULL;
- + queue->next = gcvNULL;
- +
- + /* Attach it to the list of allocated queues. */
- + if (Event->queueTail == gcvNULL)
- + {
- + Event->queueHead =
- + Event->queueTail = queue;
- + }
- + else
- + {
- + Event->queueTail->next = queue;
- + Event->queueTail = queue;
- + }
- + }
- + else
- + {
- + queue = Event->queueTail;
- + }
- +
- + /* Attach the record to the queue. */
- + if (queue->head == gcvNULL)
- + {
- + queue->head = record;
- + queue->tail = record;
- + }
- + else
- + {
- + queue->tail->next = record;
- + queue->tail = record;
- + }
- +
- + /* Unmap user space logical address.
- + * Linux kernel does not support unmap the memory of other process any more since 3.5.
- + * Let's unmap memory of self process before submit the event to gpu.
- + * */
- + switch(Interface->command)
- + {
- + case gcvHAL_FREE_NON_PAGED_MEMORY:
- + gcmkONERROR(gckOS_UnmapUserLogical(
- + Event->os,
- + gcmNAME_TO_PTR(Interface->u.FreeNonPagedMemory.physical),
- + (gctSIZE_T) Interface->u.FreeNonPagedMemory.bytes,
- + gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
- + break;
- + case gcvHAL_FREE_CONTIGUOUS_MEMORY:
- + gcmkONERROR(gckOS_UnmapUserLogical(
- + Event->os,
- + gcmNAME_TO_PTR(Interface->u.FreeContiguousMemory.physical),
- + (gctSIZE_T) Interface->u.FreeContiguousMemory.bytes,
- + gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical)));
- + break;
- + default:
- + break;
- + }
- +
- +
- + /* Release the mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Roll back. */
- + if (acquired)
- + {
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
- + }
- +
- + if (record != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckEVENT_FreeRecord(Event, record));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckEVENT_Unlock
- +**
- +** Schedule an event to unlock virtual memory.
- +**
- +** INPUT:
- +**
- +** gckEVENT Event
- +** Pointer to an gckEVENT object.
- +**
- +** gceKERNEL_WHERE FromWhere
- +** Place in the pipe where the event needs to be generated.
- +**
- +** gcuVIDMEM_NODE_PTR Node
- +** Pointer to a gcuVIDMEM_NODE union that specifies the virtual memory
- +** to unlock.
- +**
- +** gceSURF_TYPE Type
- +** Type of surface to unlock.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckEVENT_Unlock(
- + IN gckEVENT Event,
- + IN gceKERNEL_WHERE FromWhere,
- + IN gcuVIDMEM_NODE_PTR Node,
- + IN gceSURF_TYPE Type
- + )
- +{
- + gceSTATUS status;
- + gcsHAL_INTERFACE iface;
- +
- + gcmkHEADER_ARG("Event=0x%x FromWhere=%d Node=0x%x Type=%d",
- + Event, FromWhere, Node, Type);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- + gcmkVERIFY_ARGUMENT(Node != gcvNULL);
- +
- + /* Mark the event as an unlock. */
- + iface.command = gcvHAL_UNLOCK_VIDEO_MEMORY;
- + iface.u.UnlockVideoMemory.node = gcmPTR_TO_UINT64(Node);
- + iface.u.UnlockVideoMemory.type = Type;
- + iface.u.UnlockVideoMemory.asynchroneous = 0;
- +
- + /* Append it to the queue. */
- + gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckEVENT_FreeVideoMemory
- +**
- +** Schedule an event to free video memory.
- +**
- +** INPUT:
- +**
- +** gckEVENT Event
- +** Pointer to an gckEVENT object.
- +**
- +** gcuVIDMEM_NODE_PTR VideoMemory
- +** Pointer to a gcuVIDMEM_NODE object to free.
- +**
- +** gceKERNEL_WHERE FromWhere
- +** Place in the pipe where the event needs to be generated.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckEVENT_FreeVideoMemory(
- + IN gckEVENT Event,
- + IN gcuVIDMEM_NODE_PTR VideoMemory,
- + IN gceKERNEL_WHERE FromWhere
- + )
- +{
- + gceSTATUS status;
- + gcsHAL_INTERFACE iface;
- +
- + gcmkHEADER_ARG("Event=0x%x VideoMemory=0x%x FromWhere=%d",
- + Event, VideoMemory, FromWhere);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- + gcmkVERIFY_ARGUMENT(VideoMemory != gcvNULL);
- +
- + /* Create an event. */
- + iface.command = gcvHAL_FREE_VIDEO_MEMORY;
- + iface.u.FreeVideoMemory.node = gcmPTR_TO_UINT64(VideoMemory);
- +
- + /* Append it to the queue. */
- + gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckEVENT_FreeNonPagedMemory
- +**
- +** Schedule an event to free non-paged memory.
- +**
- +** INPUT:
- +**
- +** gckEVENT Event
- +** Pointer to an gckEVENT object.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes of non-paged memory to free.
- +**
- +** gctPHYS_ADDR Physical
- +** Physical address of non-paged memory to free.
- +**
- +** gctPOINTER Logical
- +** Logical address of non-paged memory to free.
- +**
- +** gceKERNEL_WHERE FromWhere
- +** Place in the pipe where the event needs to be generated.
- +*/
- +gceSTATUS
- +gckEVENT_FreeNonPagedMemory(
- + IN gckEVENT Event,
- + IN gctSIZE_T Bytes,
- + IN gctPHYS_ADDR Physical,
- + IN gctPOINTER Logical,
- + IN gceKERNEL_WHERE FromWhere
- + )
- +{
- + gceSTATUS status;
- + gcsHAL_INTERFACE iface;
- + gckKERNEL kernel = Event->kernel;
- +
- + gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
- + "FromWhere=%d",
- + Event, Bytes, Physical, Logical, FromWhere);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- + gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- +
- + /* Create an event. */
- + iface.command = gcvHAL_FREE_NON_PAGED_MEMORY;
- + iface.u.FreeNonPagedMemory.bytes = Bytes;
- + iface.u.FreeNonPagedMemory.physical = gcmPTR_TO_NAME(Physical);
- + iface.u.FreeNonPagedMemory.logical = gcmPTR_TO_UINT64(Logical);
- +
- + /* Append it to the queue. */
- + gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckEVENT_DestroyVirtualCommandBuffer(
- + IN gckEVENT Event,
- + IN gctSIZE_T Bytes,
- + IN gctPHYS_ADDR Physical,
- + IN gctPOINTER Logical,
- + IN gceKERNEL_WHERE FromWhere
- + )
- +{
- + gceSTATUS status;
- + gcsHAL_INTERFACE iface;
- + gckKERNEL kernel = Event->kernel;
- +
- + gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
- + "FromWhere=%d",
- + Event, Bytes, Physical, Logical, FromWhere);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- + gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- +
- + /* Create an event. */
- + iface.command = gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER;
- + iface.u.FreeVirtualCommandBuffer.bytes = Bytes;
- + iface.u.FreeVirtualCommandBuffer.physical = gcmPTR_TO_NAME(Physical);
- + iface.u.FreeVirtualCommandBuffer.logical = gcmPTR_TO_UINT64(Logical);
- +
- + /* Append it to the queue. */
- + gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckEVENT_FreeContigiuousMemory
- +**
- +** Schedule an event to free contiguous memory.
- +**
- +** INPUT:
- +**
- +** gckEVENT Event
- +** Pointer to an gckEVENT object.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes of contiguous memory to free.
- +**
- +** gctPHYS_ADDR Physical
- +** Physical address of contiguous memory to free.
- +**
- +** gctPOINTER Logical
- +** Logical address of contiguous memory to free.
- +**
- +** gceKERNEL_WHERE FromWhere
- +** Place in the pipe where the event needs to be generated.
- +*/
- +gceSTATUS
- +gckEVENT_FreeContiguousMemory(
- + IN gckEVENT Event,
- + IN gctSIZE_T Bytes,
- + IN gctPHYS_ADDR Physical,
- + IN gctPOINTER Logical,
- + IN gceKERNEL_WHERE FromWhere
- + )
- +{
- + gceSTATUS status;
- + gcsHAL_INTERFACE iface;
- + gckKERNEL kernel = Event->kernel;
- +
- + gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
- + "FromWhere=%d",
- + Event, Bytes, Physical, Logical, FromWhere);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- + gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- +
- + /* Create an event. */
- + iface.command = gcvHAL_FREE_CONTIGUOUS_MEMORY;
- + iface.u.FreeContiguousMemory.bytes = Bytes;
- + iface.u.FreeContiguousMemory.physical = gcmPTR_TO_NAME(Physical);
- + iface.u.FreeContiguousMemory.logical = gcmPTR_TO_UINT64(Logical);
- +
- + /* Append it to the queue. */
- + gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckEVENT_Signal
- +**
- +** Schedule an event to trigger a signal.
- +**
- +** INPUT:
- +**
- +** gckEVENT Event
- +** Pointer to an gckEVENT object.
- +**
- +** gctSIGNAL Signal
- +** Pointer to the signal to trigger.
- +**
- +** gceKERNEL_WHERE FromWhere
- +** Place in the pipe where the event needs to be generated.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckEVENT_Signal(
- + IN gckEVENT Event,
- + IN gctSIGNAL Signal,
- + IN gceKERNEL_WHERE FromWhere
- + )
- +{
- + gceSTATUS status;
- + gcsHAL_INTERFACE iface;
- +
- + gcmkHEADER_ARG("Event=0x%x Signal=0x%x FromWhere=%d",
- + Event, Signal, FromWhere);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- + gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
- +
- + /* Mark the event as a signal. */
- + iface.command = gcvHAL_SIGNAL;
- + iface.u.Signal.signal = gcmPTR_TO_UINT64(Signal);
- +#ifdef __QNXNTO__
- + iface.u.Signal.coid = 0;
- + iface.u.Signal.rcvid = 0;
- +#endif
- + iface.u.Signal.auxSignal = 0;
- + iface.u.Signal.process = 0;
- +
- + /* Append it to the queue. */
- + gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckEVENT_CommitDone
- +**
- +** Schedule an event to wake up work thread when commit is done by GPU.
- +**
- +** INPUT:
- +**
- +** gckEVENT Event
- +** Pointer to an gckEVENT object.
- +**
- +** gceKERNEL_WHERE FromWhere
- +** Place in the pipe where the event needs to be generated.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckEVENT_CommitDone(
- + IN gckEVENT Event,
- + IN gceKERNEL_WHERE FromWhere
- + )
- +{
- + gceSTATUS status;
- + gcsHAL_INTERFACE iface;
- +
- + gcmkHEADER_ARG("Event=0x%x FromWhere=%d", Event, FromWhere);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- +
- + iface.command = gcvHAL_COMMIT_DONE;
- +
- + /* Append it to the queue. */
- + gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +/*******************************************************************************
- +**
- +** gckEVENT_Submit
- +**
- +** Submit the current event queue to the GPU.
- +**
- +** INPUT:
- +**
- +** gckEVENT Event
- +** Pointer to an gckEVENT object.
- +**
- +** gctBOOL Wait
- +** Submit requires one vacant event; if Wait is set to not zero,
- +** and there are no vacant events at this time, the function will
- +** wait until an event becomes vacant so that submission of the
- +** queue is successful.
- +**
- +** gctBOOL FromPower
- +** Determines whether the call originates from inside the power
- +** management or not.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckEVENT_Submit(
- + IN gckEVENT Event,
- + IN gctBOOL Wait,
- + IN gctBOOL FromPower
- + )
- +{
- + gceSTATUS status;
- + gctUINT8 id = 0xFF;
- + gcsEVENT_QUEUE_PTR queue;
- + gctBOOL acquired = gcvFALSE;
- + gckCOMMAND command = gcvNULL;
- + gctBOOL commitEntered = gcvFALSE;
- +#if !gcdNULL_DRIVER
- + gctSIZE_T bytes;
- + gctPOINTER buffer;
- +#endif
- +
- + gcmkHEADER_ARG("Event=0x%x Wait=%d", Event, Wait);
- +
- + /* Get gckCOMMAND object. */
- + command = Event->kernel->command;
- +
- + /* Are there event queues? */
- + if (Event->queueHead != gcvNULL)
- + {
- + /* Acquire the command queue. */
- + gcmkONERROR(gckCOMMAND_EnterCommit(command, FromPower));
- + commitEntered = gcvTRUE;
- +
- + /* Process all queues. */
- + while (Event->queueHead != gcvNULL)
- + {
- + /* Acquire the list mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(Event->os,
- + Event->eventListMutex,
- + gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + /* Get the current queue. */
- + queue = Event->queueHead;
- +
- + /* Allocate an event ID. */
- + gcmkONERROR(gckEVENT_GetEvent(Event, Wait, &id, queue->head, queue->source));
- +
- + /* Copy event list to event ID queue. */
- + Event->queues[id].head = queue->head;
- +
- + /* Remove the top queue from the list. */
- + if (Event->queueHead == Event->queueTail)
- + {
- + Event->queueHead = gcvNULL;
- + Event->queueTail = gcvNULL;
- + }
- + else
- + {
- + Event->queueHead = Event->queueHead->next;
- + }
- +
- + /* Free the queue. */
- + gcmkONERROR(gckEVENT_FreeQueue(Event, queue));
- +
- + /* Release the list mutex. */
- + gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
- + acquired = gcvFALSE;
- +
- +#if gcdNULL_DRIVER
- + /* Notify immediately on infinite hardware. */
- + gcmkONERROR(gckEVENT_Interrupt(Event, 1 << id));
- +
- + gcmkONERROR(gckEVENT_Notify(Event, 0));
- +#else
- + /* Get the size of the hardware event. */
- + gcmkONERROR(gckHARDWARE_Event(Event->kernel->hardware,
- + gcvNULL,
- + id,
- + Event->queues[id].source,
- + &bytes));
- +
- + /* Reserve space in the command queue. */
- + gcmkONERROR(gckCOMMAND_Reserve(command,
- + bytes,
- + &buffer,
- + &bytes));
- +
- + /* Set the hardware event in the command queue. */
- + gcmkONERROR(gckHARDWARE_Event(Event->kernel->hardware,
- + buffer,
- + id,
- + Event->queues[id].source,
- + &bytes));
- +
- + /* Execute the hardware event. */
- + gcmkONERROR(gckCOMMAND_Execute(command, bytes));
- +#endif
- + }
- +
- + /* Release the command queue. */
- + gcmkONERROR(gckCOMMAND_ExitCommit(command, FromPower));
- + commitEntered = gcvFALSE;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (commitEntered)
- + {
- + /* Release the command queue mutex. */
- + gcmkVERIFY_OK(gckCOMMAND_ExitCommit(command, FromPower));
- + }
- +
- + if (acquired)
- + {
- + /* Need to unroll the mutex acquire. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
- + }
- +
- + if (id != 0xFF)
- + {
- + /* Need to unroll the event allocation. */
- + Event->queues[id].head = gcvNULL;
- + }
- +
- + if (status == gcvSTATUS_GPU_NOT_RESPONDING)
- + {
- + /* Broadcast GPU stuck. */
- + status = gckOS_Broadcast(Event->os,
- + Event->kernel->hardware,
- + gcvBROADCAST_GPU_STUCK);
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckEVENT_Commit
- +**
- +** Commit an event queue from the user.
- +**
- +** INPUT:
- +**
- +** gckEVENT Event
- +** Pointer to an gckEVENT object.
- +**
- +** gcsQUEUE_PTR Queue
- +** User event queue.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckEVENT_Commit(
- + IN gckEVENT Event,
- + IN gcsQUEUE_PTR Queue
- + )
- +{
- + gceSTATUS status;
- + gcsQUEUE_PTR record = gcvNULL, next;
- + gctUINT32 processID;
- + gctBOOL needCopy = gcvFALSE;
- +
- + gcmkHEADER_ARG("Event=0x%x Queue=0x%x", Event, Queue);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- +
- + /* Get the current process ID. */
- + gcmkONERROR(gckOS_GetProcessID(&processID));
- +
- + /* Query if we need to copy the client data. */
- + gcmkONERROR(gckOS_QueryNeedCopy(Event->os, processID, &needCopy));
- +
- + /* Loop while there are records in the queue. */
- + while (Queue != gcvNULL)
- + {
- + gcsQUEUE queue;
- +
- + if (needCopy)
- + {
- + /* Point to stack record. */
- + record = &queue;
- +
- + /* Copy the data from the client. */
- + gcmkONERROR(gckOS_CopyFromUserData(Event->os,
- + record,
- + Queue,
- + gcmSIZEOF(gcsQUEUE)));
- + }
- + else
- + {
- + gctPOINTER pointer = gcvNULL;
- +
- + /* Map record into kernel memory. */
- + gcmkONERROR(gckOS_MapUserPointer(Event->os,
- + Queue,
- + gcmSIZEOF(gcsQUEUE),
- + &pointer));
- +
- + record = pointer;
- + }
- +
- + /* Append event record to event queue. */
- + gcmkONERROR(
- + gckEVENT_AddList(Event, &record->iface, gcvKERNEL_PIXEL, gcvTRUE, gcvFALSE));
- +
- + /* Next record in the queue. */
- + next = gcmUINT64_TO_PTR(record->next);
- +
- + if (!needCopy)
- + {
- + /* Unmap record from kernel memory. */
- + gcmkONERROR(
- + gckOS_UnmapUserPointer(Event->os,
- + Queue,
- + gcmSIZEOF(gcsQUEUE),
- + (gctPOINTER *) record));
- + record = gcvNULL;
- + }
- +
- + Queue = next;
- + }
- +
- + /* Submit the event list. */
- + gcmkONERROR(gckEVENT_Submit(Event, gcvTRUE, gcvFALSE));
- +
- + /* Success */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if ((record != gcvNULL) && !needCopy)
- + {
- + /* Roll back. */
- + gcmkVERIFY_OK(gckOS_UnmapUserPointer(Event->os,
- + Queue,
- + gcmSIZEOF(gcsQUEUE),
- + (gctPOINTER *) record));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckEVENT_Compose
- +**
- +** Schedule a composition event and start a composition.
- +**
- +** INPUT:
- +**
- +** gckEVENT Event
- +** Pointer to an gckEVENT object.
- +**
- +** gcsHAL_COMPOSE_PTR Info
- +** Pointer to the composition structure.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckEVENT_Compose(
- + IN gckEVENT Event,
- + IN gcsHAL_COMPOSE_PTR Info
- + )
- +{
- + gceSTATUS status;
- + gcsEVENT_PTR headRecord;
- + gcsEVENT_PTR tailRecord;
- + gcsEVENT_PTR tempRecord;
- + gctUINT8 id = 0xFF;
- + gctUINT32 processID;
- +
- + gcmkHEADER_ARG("Event=0x%x Info=0x%x", Event, Info);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- + gcmkVERIFY_ARGUMENT(Info != gcvNULL);
- +
- + /* Get process ID. */
- + gcmkONERROR(gckOS_GetProcessID(&processID));
- +
- + /* Allocate a record. */
- + gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &tempRecord));
- + headRecord = tailRecord = tempRecord;
- +
- + /* Initialize the record. */
- + tempRecord->info.command = gcvHAL_SIGNAL;
- + tempRecord->info.u.Signal.process = Info->process;
- +#ifdef __QNXNTO__
- + tempRecord->info.u.Signal.coid = Info->coid;
- + tempRecord->info.u.Signal.rcvid = Info->rcvid;
- +#endif
- + tempRecord->info.u.Signal.signal = Info->signal;
- + tempRecord->info.u.Signal.auxSignal = 0;
- + tempRecord->next = gcvNULL;
- + tempRecord->processID = processID;
- +
- + /* Allocate another record for user signal #1. */
- + if (gcmUINT64_TO_PTR(Info->userSignal1) != gcvNULL)
- + {
- + /* Allocate a record. */
- + gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &tempRecord));
- + tailRecord->next = tempRecord;
- + tailRecord = tempRecord;
- +
- + /* Initialize the record. */
- + tempRecord->info.command = gcvHAL_SIGNAL;
- + tempRecord->info.u.Signal.process = Info->userProcess;
- +#ifdef __QNXNTO__
- + tempRecord->info.u.Signal.coid = Info->coid;
- + tempRecord->info.u.Signal.rcvid = Info->rcvid;
- +#endif
- + tempRecord->info.u.Signal.signal = Info->userSignal1;
- + tempRecord->info.u.Signal.auxSignal = 0;
- + tempRecord->next = gcvNULL;
- + tempRecord->processID = processID;
- + }
- +
- + /* Allocate another record for user signal #2. */
- + if (gcmUINT64_TO_PTR(Info->userSignal2) != gcvNULL)
- + {
- + /* Allocate a record. */
- + gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &tempRecord));
- + tailRecord->next = tempRecord;
- + tailRecord = tempRecord;
- +
- + /* Initialize the record. */
- + tempRecord->info.command = gcvHAL_SIGNAL;
- + tempRecord->info.u.Signal.process = Info->userProcess;
- +#ifdef __QNXNTO__
- + tempRecord->info.u.Signal.coid = Info->coid;
- + tempRecord->info.u.Signal.rcvid = Info->rcvid;
- +#endif
- + tempRecord->info.u.Signal.signal = Info->userSignal2;
- + tempRecord->info.u.Signal.auxSignal = 0;
- + tempRecord->next = gcvNULL;
- + tempRecord->processID = processID;
- + }
- +
- + /* Allocate an event ID. */
- + gcmkONERROR(gckEVENT_GetEvent(Event, gcvTRUE, &id, headRecord, gcvKERNEL_PIXEL));
- +
- + /* Start composition. */
- + gcmkONERROR(gckHARDWARE_Compose(
- + Event->kernel->hardware, processID,
- + gcmUINT64_TO_PTR(Info->physical), gcmUINT64_TO_PTR(Info->logical), Info->offset, Info->size, id
- + ));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckEVENT_Interrupt
- +**
- +** Called by the interrupt service routine to store the triggered interrupt
- +** mask to be later processed by gckEVENT_Notify.
- +**
- +** INPUT:
- +**
- +** gckEVENT Event
- +** Pointer to an gckEVENT object.
- +**
- +** gctUINT32 Data
- +** Mask for the 32 interrupts.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckEVENT_Interrupt(
- + IN gckEVENT Event,
- + IN gctUINT32 Data
- + )
- +{
- + unsigned long flags;
- + gcmkHEADER_ARG("Event=0x%x Data=0x%x", Event, Data);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- +
- + /* Combine current interrupt status with pending flags. */
- + spin_lock_irqsave(&Event->kernel->irq_lock, flags);
- +#if gcdSMP
- + gckOS_AtomSetMask(Event->pending, Data);
- +#elif defined(__QNXNTO__)
- + atomic_set(&Event->pending, Data);
- +#else
- + Event->pending |= Data;
- +#endif
- + spin_unlock_irqrestore(&Event->kernel->irq_lock, flags);
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckEVENT_Notify
- +**
- +** Process all triggered interrupts.
- +**
- +** INPUT:
- +**
- +** gckEVENT Event
- +** Pointer to an gckEVENT object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckEVENT_Notify(
- + IN gckEVENT Event,
- + IN gctUINT32 IDs
- + )
- +{
- + gceSTATUS status = gcvSTATUS_OK;
- + gctINT i;
- + gcsEVENT_QUEUE * queue;
- + gctUINT mask = 0;
- + gctBOOL acquired = gcvFALSE;
- + gcuVIDMEM_NODE_PTR node;
- + gctPOINTER info;
- + gctSIGNAL signal;
- + gctUINT pending;
- + gckKERNEL kernel = Event->kernel;
- +#if !gcdSMP
- + gctBOOL suspended = gcvFALSE;
- +#endif
- +#if gcmIS_DEBUG(gcdDEBUG_TRACE)
- + gctINT eventNumber = 0;
- +#endif
- + gctINT32 free;
- +#if gcdSECURE_USER
- + gcskSECURE_CACHE_PTR cache;
- +#endif
- + unsigned long flags;
- +
- + gcmkHEADER_ARG("Event=0x%x IDs=0x%x", Event, IDs);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- +
- + gcmDEBUG_ONLY(
- + if (IDs != 0)
- + {
- + for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
- + {
- + if (Event->queues[i].head != gcvNULL)
- + {
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
- + "Queue(%d): stamp=%llu source=%d",
- + i,
- + Event->queues[i].stamp,
- + Event->queues[i].source);
- + }
- + }
- + }
- + );
- +
- + for (;;)
- + {
- + gcsEVENT_PTR record;
- +
- + spin_lock_irqsave(&Event->kernel->irq_lock, flags);
- +#if gcdSMP
- + /* Get current interrupts. */
- + gckOS_AtomGet(Event->os, Event->pending, (gctINT32_PTR)&pending);
- +#else
- + /* Get current interrupts. */
- + pending = Event->pending;
- +#endif
- + spin_unlock_irqrestore(&Event->kernel->irq_lock, flags);
- +
- + if (pending & 0x80000000)
- + {
- + //gckOS_Print("!!!!!!!!!!!!! AXI BUS ERROR !!!!!!!!!!!!!\n");
- + gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_EVENT, "AXI BUS ERROR");
- + pending &= 0x7FFFFFFF;
- + }
- +
- + if (pending & 0x40000000)
- + {
- + gckHARDWARE_DumpMMUException(Event->kernel->hardware);
- +
- + pending &= 0x3FFFFFFF;
- + }
- +
- + gcmkTRACE_ZONE_N(
- + gcvLEVEL_INFO, gcvZONE_EVENT,
- + gcmSIZEOF(pending),
- + "Pending interrupts 0x%x",
- + pending
- + );
- +
- + if (pending == 0)
- + {
- + /* No more pending interrupts - done. */
- + break;
- + }
- +
- + queue = gcvNULL;
- +
- + /* Grab the mutex queue. */
- + gcmkONERROR(gckOS_AcquireMutex(Event->os,
- + Event->eventQueueMutex,
- + gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + gcmDEBUG_ONLY(
- + if (IDs == 0)
- + {
- + for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
- + {
- + if (Event->queues[i].head != gcvNULL)
- + {
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
- + "Queue(%d): stamp=%llu source=%d",
- + i,
- + Event->queues[i].stamp,
- + Event->queues[i].source);
- + }
- + }
- + }
- + );
- +
- + /* Find the oldest pending interrupt. */
- + for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
- + {
- + if ((Event->queues[i].head != gcvNULL)
- + && (pending & (1 << i))
- + )
- + {
- + if ((queue == gcvNULL)
- + || (Event->queues[i].stamp < queue->stamp)
- + )
- + {
- + queue = &Event->queues[i];
- + mask = 1 << i;
- +#if gcmIS_DEBUG(gcdDEBUG_TRACE)
- + eventNumber = i;
- +#endif
- + }
- + }
- + }
- +
- + if (queue == gcvNULL)
- + {
- + gcmkTRACE_ZONE_N(
- + gcvLEVEL_ERROR, gcvZONE_EVENT,
- + gcmSIZEOF(pending),
- + "Interrupts 0x%x are not pending.",
- + pending
- + );
- +
- + /* Release the mutex queue. */
- + gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
- + acquired = gcvFALSE;
- +
- + spin_lock_irqsave(&Event->kernel->irq_lock, flags);
- +#if gcdSMP
- + /* Mark pending interrupts as handled. */
- + gckOS_AtomClearMask(Event->pending, pending);
- +#elif defined(__QNXNTO__)
- + /* Mark pending interrupts as handled. */
- + atomic_clr((gctUINT32_PTR)&Event->pending, pending);
- +#else
- + /* Mark pending interrupts as handled. */
- + Event->pending &= ~pending;
- +#endif
- + spin_unlock_irqrestore(&Event->kernel->irq_lock, flags);
- + break;
- + }
- +
- + /* Check whether there is a missed interrupt. */
- + for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
- + {
- + if ((Event->queues[i].head != gcvNULL)
- + && (Event->queues[i].stamp < queue->stamp)
- + && (Event->queues[i].source <= queue->source)
- + )
- + {
- + gcmkTRACE_N(
- + gcvLEVEL_ERROR,
- + gcmSIZEOF(i) + gcmSIZEOF(Event->queues[i].stamp),
- + "Event %d lost (stamp %llu)",
- + i, Event->queues[i].stamp
- + );
- +
- + /* Use this event instead. */
- + queue = &Event->queues[i];
- + mask = 0;
- + }
- + }
- +
- + if (mask != 0)
- + {
- +#if gcmIS_DEBUG(gcdDEBUG_TRACE)
- + gcmkTRACE_ZONE_N(
- + gcvLEVEL_INFO, gcvZONE_EVENT,
- + gcmSIZEOF(eventNumber),
- + "Processing interrupt %d",
- + eventNumber
- + );
- +#endif
- + }
- +
- + spin_lock_irqsave(&Event->kernel->irq_lock, flags);
- +#if gcdSMP
- + /* Mark pending interrupt as handled. */
- + gckOS_AtomClearMask(Event->pending, mask);
- +#elif defined(__QNXNTO__)
- + /* Mark pending interrupt as handled. */
- + atomic_clr(&Event->pending, mask);
- +#else
- + /* Mark pending interrupt as handled. */
- + Event->pending &= ~mask;
- +#endif
- + spin_unlock_irqrestore(&Event->kernel->irq_lock, flags);
- +
- + /* We are in the notify loop. */
- + Event->inNotify = gcvTRUE;
- +
- + /* We are in the notify loop. */
- + Event->inNotify = gcvTRUE;
- +
- + /* Grab the event head. */
- + record = queue->head;
- +
- + /* Now quickly clear its event list. */
- + queue->head = gcvNULL;
- +
- + /* Release the mutex queue. */
- + gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
- + acquired = gcvFALSE;
- +
- + /* Increase the number of free events. */
- + gcmkONERROR(gckOS_AtomIncrement(Event->os, Event->freeAtom, &free));
- +
- + /* Walk all events for this interrupt. */
- + while (record != gcvNULL)
- + {
- + gcsEVENT_PTR recordNext;
- +#ifndef __QNXNTO__
- + gctPOINTER logical;
- +#endif
- +#if gcdSECURE_USER
- + gctSIZE_T bytes;
- +#endif
- +
- + /* Grab next record. */
- + recordNext = record->next;
- +
- +#ifdef __QNXNTO__
- + /* Assign record->processID as the pid for this galcore thread.
- + * Used in OS calls like gckOS_UnlockMemory() which do not take a pid.
- + */
- + drv_thread_specific_key_assign(record->processID, 0, Event->kernel->core);
- +#endif
- +
- +#if gcdSECURE_USER
- + /* Get the cache that belongs to this process. */
- + gcmkONERROR(gckKERNEL_GetProcessDBCache(Event->kernel,
- + record->processID,
- + &cache));
- +#endif
- +
- + gcmkTRACE_ZONE_N(
- + gcvLEVEL_INFO, gcvZONE_EVENT,
- + gcmSIZEOF(record->info.command),
- + "Processing event type: %d",
- + record->info.command
- + );
- +
- + switch (record->info.command)
- + {
- + case gcvHAL_FREE_NON_PAGED_MEMORY:
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
- + "gcvHAL_FREE_NON_PAGED_MEMORY: 0x%x",
- + gcmNAME_TO_PTR(record->info.u.FreeNonPagedMemory.physical));
- +
- + /* Free non-paged memory. */
- + status = gckOS_FreeNonPagedMemory(
- + Event->os,
- + (gctSIZE_T) record->info.u.FreeNonPagedMemory.bytes,
- + gcmNAME_TO_PTR(record->info.u.FreeNonPagedMemory.physical),
- + gcmUINT64_TO_PTR(record->info.u.FreeNonPagedMemory.logical));
- +
- + if (gcmIS_SUCCESS(status))
- + {
- +#if gcdSECURE_USER
- + gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
- + Event->kernel,
- + cache,
- + gcmUINT64_TO_PTR(record->record.u.FreeNonPagedMemory.logical),
- + (gctSIZE_T) record->record.u.FreeNonPagedMemory.bytes));
- +#endif
- + }
- + gcmRELEASE_NAME(record->info.u.FreeNonPagedMemory.physical);
- + break;
- +
- + case gcvHAL_FREE_CONTIGUOUS_MEMORY:
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_EVENT,
- + "gcvHAL_FREE_CONTIGUOUS_MEMORY: 0x%x",
- + gcmNAME_TO_PTR(record->info.u.FreeContiguousMemory.physical));
- +
- + /* Unmap the user memory. */
- + status = gckOS_FreeContiguous(
- + Event->os,
- + gcmNAME_TO_PTR(record->info.u.FreeContiguousMemory.physical),
- + gcmUINT64_TO_PTR(record->info.u.FreeContiguousMemory.logical),
- + (gctSIZE_T) record->info.u.FreeContiguousMemory.bytes);
- +
- + if (gcmIS_SUCCESS(status))
- + {
- +#if gcdSECURE_USER
- + gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
- + Event->kernel,
- + cache,
- + gcmUINT64_TO_PTR(record->record.u.FreeContiguousMemory.logical),
- + (gctSIZE_T) record->record.u.FreeContiguousMemory.bytes));
- +#endif
- + }
- + gcmRELEASE_NAME(record->info.u.FreeContiguousMemory.physical);
- + break;
- +
- + case gcvHAL_FREE_VIDEO_MEMORY:
- + node = gcmUINT64_TO_PTR(record->info.u.FreeVideoMemory.node);
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
- + "gcvHAL_FREE_VIDEO_MEMORY: 0x%x",
- + node);
- +#ifdef __QNXNTO__
- +#if gcdUSE_VIDMEM_PER_PID
- + /* Check if the VidMem object still exists. */
- + if (gckKERNEL_GetVideoMemoryPoolPid(record->kernel,
- + gcvPOOL_SYSTEM,
- + record->processID,
- + gcvNULL) == gcvSTATUS_NOT_FOUND)
- + {
- + /*printf("Vidmem not found for process:%d\n", queue->processID);*/
- + status = gcvSTATUS_OK;
- + break;
- + }
- +#else
- + if ((node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
- + && (node->VidMem.logical != gcvNULL)
- + )
- + {
- + gcmkERR_BREAK(
- + gckKERNEL_UnmapVideoMemory(record->kernel,
- + node->VidMem.logical,
- + record->processID,
- + node->VidMem.bytes));
- + node->VidMem.logical = gcvNULL;
- + }
- +#endif
- +#endif
- +
- + /* Free video memory. */
- + status =
- + gckVIDMEM_Free(node);
- +
- + break;
- +
- + case gcvHAL_WRITE_DATA:
- +#ifndef __QNXNTO__
- + /* Convert physical into logical address. */
- + gcmkERR_BREAK(
- + gckOS_MapPhysical(Event->os,
- + record->info.u.WriteData.address,
- + gcmSIZEOF(gctUINT32),
- + &logical));
- +
- + /* Write data. */
- + gcmkERR_BREAK(
- + gckOS_WriteMemory(Event->os,
- + logical,
- + record->info.u.WriteData.data));
- +
- + /* Unmap the physical memory. */
- + gcmkERR_BREAK(
- + gckOS_UnmapPhysical(Event->os,
- + logical,
- + gcmSIZEOF(gctUINT32)));
- +#else
- + /* Write data. */
- + gcmkERR_BREAK(
- + gckOS_WriteMemory(Event->os,
- + (gctPOINTER)
- + record->info.u.WriteData.address,
- + record->info.u.WriteData.data));
- +#endif
- + break;
- +
- + case gcvHAL_UNLOCK_VIDEO_MEMORY:
- + node = gcmUINT64_TO_PTR(record->info.u.UnlockVideoMemory.node);
- +
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
- + "gcvHAL_UNLOCK_VIDEO_MEMORY: 0x%x",
- + node);
- +
- + /* Save node information before it disappears. */
- +#if gcdSECURE_USER
- + if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
- + {
- + logical = gcvNULL;
- + bytes = 0;
- + }
- + else
- + {
- + logical = node->Virtual.logical;
- + bytes = node->Virtual.bytes;
- + }
- +#endif
- +
- + /* Unlock. */
- + status = gckVIDMEM_Unlock(
- + Event->kernel,
- + node,
- + record->info.u.UnlockVideoMemory.type,
- + gcvNULL);
- +
- +#if gcdSECURE_USER
- + if (gcmIS_SUCCESS(status) && (logical != gcvNULL))
- + {
- + gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
- + Event->kernel,
- + cache,
- + logical,
- + bytes));
- + }
- +#endif
- + break;
- +
- + case gcvHAL_SIGNAL:
- + signal = gcmUINT64_TO_PTR(record->info.u.Signal.signal);
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
- + "gcvHAL_SIGNAL: 0x%x",
- + signal);
- +
- +#ifdef __QNXNTO__
- + if ((record->info.u.Signal.coid == 0)
- + && (record->info.u.Signal.rcvid == 0)
- + )
- + {
- + /* Kernel signal. */
- + gcmkERR_BREAK(
- + gckOS_Signal(Event->os,
- + signal,
- + gcvTRUE));
- + }
- + else
- + {
- + /* User signal. */
- + gcmkERR_BREAK(
- + gckOS_UserSignal(Event->os,
- + signal,
- + record->info.u.Signal.rcvid,
- + record->info.u.Signal.coid));
- + }
- +#else
- + /* Set signal. */
- + if (gcmUINT64_TO_PTR(record->info.u.Signal.process) == gcvNULL)
- + {
- + /* Kernel signal. */
- + gcmkERR_BREAK(
- + gckOS_Signal(Event->os,
- + signal,
- + gcvTRUE));
- + }
- + else
- + {
- + /* User signal. */
- + gcmkERR_BREAK(
- + gckOS_UserSignal(Event->os,
- + signal,
- + gcmUINT64_TO_PTR(record->info.u.Signal.process)));
- + }
- +
- + gcmkASSERT(record->info.u.Signal.auxSignal == 0);
- +#endif
- + break;
- +
- + case gcvHAL_UNMAP_USER_MEMORY:
- + info = gcmNAME_TO_PTR(record->info.u.UnmapUserMemory.info);
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
- + "gcvHAL_UNMAP_USER_MEMORY: 0x%x",
- + info);
- +
- + /* Unmap the user memory. */
- + status = gckOS_UnmapUserMemory(
- + Event->os,
- + Event->kernel->core,
- + gcmUINT64_TO_PTR(record->info.u.UnmapUserMemory.memory),
- + (gctSIZE_T) record->info.u.UnmapUserMemory.size,
- + info,
- + record->info.u.UnmapUserMemory.address);
- +
- +#if gcdSECURE_USER
- + if (gcmIS_SUCCESS(status))
- + {
- + gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
- + Event->kernel,
- + cache,
- + gcmUINT64_TO_PTR(record->info.u.UnmapUserMemory.memory),
- + (gctSIZE_T) record->info.u.UnmapUserMemory.size));
- + }
- +#endif
- + gcmRELEASE_NAME(record->info.u.UnmapUserMemory.info);
- + break;
- +
- + case gcvHAL_TIMESTAMP:
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
- + "gcvHAL_TIMESTAMP: %d %d",
- + record->info.u.TimeStamp.timer,
- + record->info.u.TimeStamp.request);
- +
- + /* Process the timestamp. */
- + switch (record->info.u.TimeStamp.request)
- + {
- + case 0:
- + status = gckOS_GetTime(&Event->kernel->timers[
- + record->info.u.TimeStamp.timer].
- + stopTime);
- + break;
- +
- + case 1:
- + status = gckOS_GetTime(&Event->kernel->timers[
- + record->info.u.TimeStamp.timer].
- + startTime);
- + break;
- +
- + default:
- + gcmkTRACE_ZONE_N(
- + gcvLEVEL_ERROR, gcvZONE_EVENT,
- + gcmSIZEOF(record->info.u.TimeStamp.request),
- + "Invalid timestamp request: %d",
- + record->info.u.TimeStamp.request
- + );
- +
- + status = gcvSTATUS_INVALID_ARGUMENT;
- + break;
- + }
- + break;
- +
- +#if gcdVIRTUAL_COMMAND_BUFFER
- + case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
- + gcmkVERIFY_OK(
- + gckKERNEL_DestroyVirtualCommandBuffer(Event->kernel,
- + (gctSIZE_T) record->info.u.FreeVirtualCommandBuffer.bytes,
- + gcmNAME_TO_PTR(record->info.u.FreeVirtualCommandBuffer.physical),
- + gcmUINT64_TO_PTR(record->info.u.FreeVirtualCommandBuffer.logical)
- + ));
- + gcmRELEASE_NAME(record->info.u.FreeVirtualCommandBuffer.physical);
- + break;
- +#endif
- +
- +#if gcdANDROID_NATIVE_FENCE_SYNC
- + case gcvHAL_SYNC_POINT:
- + {
- + gctSYNC_POINT syncPoint;
- +
- + syncPoint = gcmUINT64_TO_PTR(record->info.u.SyncPoint.syncPoint);
- + status = gckOS_SignalSyncPoint(Event->os, syncPoint);
- + }
- + break;
- +#endif
- +
- + case gcvHAL_COMMIT_DONE:
- + break;
- +
- + default:
- + /* Invalid argument. */
- + gcmkTRACE_ZONE_N(
- + gcvLEVEL_ERROR, gcvZONE_EVENT,
- + gcmSIZEOF(record->info.command),
- + "Unknown event type: %d",
- + record->info.command
- + );
- +
- + status = gcvSTATUS_INVALID_ARGUMENT;
- + break;
- + }
- +
- + /* Make sure there are no errors generated. */
- + if (gcmIS_ERROR(status))
- + {
- + gcmkTRACE_ZONE_N(
- + gcvLEVEL_WARNING, gcvZONE_EVENT,
- + gcmSIZEOF(status),
- + "Event produced status: %d(%s)",
- + status, gckOS_DebugStatus2Name(status));
- + }
- +
- + /* Free the event. */
- + gcmkVERIFY_OK(gckEVENT_FreeRecord(Event, record));
- +
- + /* Advance to next record. */
- + record = recordNext;
- + }
- +
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
- + "Handled interrupt 0x%x", mask);
- + }
- +
- + if (IDs == 0)
- + {
- + gcmkONERROR(_TryToIdleGPU(Event));
- + }
- +
- + /* We are out the notify loop. */
- + Event->inNotify = gcvFALSE;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + /* Release mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
- + }
- +
- +#if !gcdSMP
- + if (suspended)
- + {
- + /* Resume interrupts. */
- + gcmkVERIFY_OK(gckOS_ResumeInterruptEx(Event->os, Event->kernel->core));
- + }
- +#endif
- +
- + /* We are out the notify loop. */
- + Event->inNotify = gcvFALSE;
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +** gckEVENT_FreeProcess
- +**
- +** Free all events owned by a particular process ID.
- +**
- +** INPUT:
- +**
- +** gckEVENT Event
- +** Pointer to an gckEVENT object.
- +**
- +** gctUINT32 ProcessID
- +** Process ID of the process to be freed up.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckEVENT_FreeProcess(
- + IN gckEVENT Event,
- + IN gctUINT32 ProcessID
- + )
- +{
- + gctSIZE_T i;
- + gctBOOL acquired = gcvFALSE;
- + gcsEVENT_PTR record, next;
- + gceSTATUS status;
- + gcsEVENT_PTR deleteHead, deleteTail;
- +
- + gcmkHEADER_ARG("Event=0x%x ProcessID=%d", Event, ProcessID);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- +
- + /* Walk through all queues. */
- + for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
- + {
- + if (Event->queues[i].head != gcvNULL)
- + {
- + /* Grab the event queue mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(Event->os,
- + Event->eventQueueMutex,
- + gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + /* Grab the mutex head. */
- + record = Event->queues[i].head;
- + Event->queues[i].head = gcvNULL;
- + Event->queues[i].tail = gcvNULL;
- + deleteHead = gcvNULL;
- + deleteTail = gcvNULL;
- +
- + while (record != gcvNULL)
- + {
- + next = record->next;
- + if (record->processID == ProcessID)
- + {
- + if (deleteHead == gcvNULL)
- + {
- + deleteHead = record;
- + }
- + else
- + {
- + deleteTail->next = record;
- + }
- +
- + deleteTail = record;
- + }
- + else
- + {
- + if (Event->queues[i].head == gcvNULL)
- + {
- + Event->queues[i].head = record;
- + }
- + else
- + {
- + Event->queues[i].tail->next = record;
- + }
- +
- + Event->queues[i].tail = record;
- + }
- +
- + record->next = gcvNULL;
- + record = next;
- + }
- +
- + /* Release the mutex queue. */
- + gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
- + acquired = gcvFALSE;
- +
- + /* Loop through the entire list of events. */
- + for (record = deleteHead; record != gcvNULL; record = next)
- + {
- + /* Get the next event record. */
- + next = record->next;
- +
- + /* Free the event record. */
- + gcmkONERROR(gckEVENT_FreeRecord(Event, record));
- + }
- + }
- + }
- +
- + gcmkONERROR(_TryToIdleGPU(Event));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Release the event queue mutex. */
- + if (acquired)
- + {
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +** gckEVENT_Stop
- +**
- +** Stop the hardware using the End event mechanism.
- +**
- +** INPUT:
- +**
- +** gckEVENT Event
- +** Pointer to an gckEVENT object.
- +**
- +** gctUINT32 ProcessID
- +** Process ID Logical belongs.
- +**
- +** gctPHYS_ADDR Handle
- +** Physical address handle. If gcvNULL it is video memory.
- +**
- +** gctPOINTER Logical
- +** Logical address to flush.
- +**
- +** gctSIGNAL Signal
- +** Pointer to the signal to trigger.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckEVENT_Stop(
- + IN gckEVENT Event,
- + IN gctUINT32 ProcessID,
- + IN gctPHYS_ADDR Handle,
- + IN gctPOINTER Logical,
- + IN gctSIGNAL Signal,
- + IN OUT gctSIZE_T * waitSize
- + )
- +{
- + gceSTATUS status;
- + /* gctSIZE_T waitSize;*/
- + gcsEVENT_PTR record;
- + gctUINT8 id = 0xFF;
- +
- + gcmkHEADER_ARG("Event=0x%x ProcessID=%u Handle=0x%x Logical=0x%x "
- + "Signal=0x%x",
- + Event, ProcessID, Handle, Logical, Signal);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
- +
- + /* Submit the current event queue. */
- + gcmkONERROR(gckEVENT_Submit(Event, gcvTRUE, gcvFALSE));
- +
- + /* Allocate a record. */
- + gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &record));
- +
- + /* Initialize the record. */
- + record->next = gcvNULL;
- + record->processID = ProcessID;
- + record->info.command = gcvHAL_SIGNAL;
- + record->info.u.Signal.signal = gcmPTR_TO_UINT64(Signal);
- +#ifdef __QNXNTO__
- + record->info.u.Signal.coid = 0;
- + record->info.u.Signal.rcvid = 0;
- +#endif
- + record->info.u.Signal.auxSignal = 0;
- + record->info.u.Signal.process = 0;
- +
- +
- + gcmkONERROR(gckEVENT_GetEvent(Event, gcvTRUE, &id, record, gcvKERNEL_PIXEL));
- +
- + /* Replace last WAIT with END. */
- + gcmkONERROR(gckHARDWARE_End(
- + Event->kernel->hardware, Logical, waitSize
- + ));
- +
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + /* Flush the cache for the END. */
- + gcmkONERROR(gckOS_CacheClean(
- + Event->os,
- + ProcessID,
- + gcvNULL,
- + Handle,
- + Logical,
- + *waitSize
- + ));
- +#endif
- +
- + /* Wait for the signal. */
- + gcmkONERROR(gckOS_WaitSignal(Event->os, Signal, gcvINFINITE));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +static void
- +_PrintRecord(
- + gcsEVENT_PTR record
- + )
- +{
- + switch (record->info.command)
- + {
- + case gcvHAL_FREE_NON_PAGED_MEMORY:
- + gcmkPRINT(" gcvHAL_FREE_NON_PAGED_MEMORY");
- + break;
- +
- + case gcvHAL_FREE_CONTIGUOUS_MEMORY:
- + gcmkPRINT(" gcvHAL_FREE_CONTIGUOUS_MEMORY");
- + break;
- +
- + case gcvHAL_FREE_VIDEO_MEMORY:
- + gcmkPRINT(" gcvHAL_FREE_VIDEO_MEMORY");
- + break;
- +
- + case gcvHAL_WRITE_DATA:
- + gcmkPRINT(" gcvHAL_WRITE_DATA");
- + break;
- +
- + case gcvHAL_UNLOCK_VIDEO_MEMORY:
- + gcmkPRINT(" gcvHAL_UNLOCK_VIDEO_MEMORY");
- + break;
- +
- + case gcvHAL_SIGNAL:
- + gcmkPRINT(" gcvHAL_SIGNAL process=%d signal=0x%x",
- + record->info.u.Signal.process,
- + record->info.u.Signal.signal);
- + break;
- +
- + case gcvHAL_UNMAP_USER_MEMORY:
- + gcmkPRINT(" gcvHAL_UNMAP_USER_MEMORY");
- + break;
- +
- + case gcvHAL_TIMESTAMP:
- + gcmkPRINT(" gcvHAL_TIMESTAMP");
- + break;
- +
- + case gcvHAL_COMMIT_DONE:
- + gcmkPRINT(" gcvHAL_COMMIT_DONE");
- + break;
- +
- + case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
- + gcmkPRINT(" gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER logical=0x%08x",
- + record->info.u.FreeVirtualCommandBuffer.logical);
- + break;
- +
- + default:
- + gcmkPRINT(" Illegal Event %d", record->info.command);
- + break;
- + }
- +}
- +
- +/*******************************************************************************
- +** gckEVENT_Dump
- +**
- +** Dump record in event queue when stuck happens.
- +** No protection for the event queue.
- +**/
- +gceSTATUS
- +gckEVENT_Dump(
- + IN gckEVENT Event
- + )
- +{
- + gcsEVENT_QUEUE_PTR queueHead = Event->queueHead;
- + gcsEVENT_QUEUE_PTR queue;
- + gcsEVENT_PTR record = gcvNULL;
- + gctINT i;
- +
- + gcmkHEADER_ARG("Event=0x%x", Event);
- +
- + gcmkPRINT("**************************\n");
- + gcmkPRINT("*** EVENT STATE DUMP ***\n");
- + gcmkPRINT("**************************\n");
- +
- +
- + gcmkPRINT(" Unsumbitted Event:");
- + while(queueHead)
- + {
- + queue = queueHead;
- + record = queueHead->head;
- +
- + gcmkPRINT(" [%x]:", queue);
- + while(record)
- + {
- + _PrintRecord(record);
- + record = record->next;
- + }
- +
- + if (queueHead == Event->queueTail)
- + {
- + queueHead = gcvNULL;
- + }
- + else
- + {
- + queueHead = queueHead->next;
- + }
- + }
- +
- + gcmkPRINT(" Untriggered Event:");
- + for (i = 0; i < 30; i++)
- + {
- + queue = &Event->queues[i];
- + record = queue->head;
- +
- + gcmkPRINT(" [%d]:", i);
- + while(record)
- + {
- + _PrintRecord(record);
- + record = record->next;
- + }
- + }
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS gckEVENT_WaitEmpty(gckEVENT Event)
- +{
- + gctBOOL isEmpty;
- +
- + while (Event->inNotify || (gcmIS_SUCCESS(gckEVENT_IsEmpty(Event, &isEmpty)) && !isEmpty)) ;
- +
- + return gcvSTATUS_OK;
- +}
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h 2015-03-08 14:27:37.633684500 -0500
- @@ -0,0 +1,1011 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_kernel_h_
- +#define __gc_hal_kernel_h_
- +
- +#include <linux/spinlock.h>
- +
- +#include "gc_hal.h"
- +#include "gc_hal_kernel_hardware.h"
- +#include "gc_hal_driver.h"
- +
- +#if gcdENABLE_VG
- +#include "gc_hal_kernel_vg.h"
- +#endif
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +
- +/*******************************************************************************
- +***** New MMU Defination *******************************************************/
- +#define gcdMMU_MTLB_SHIFT 22
- +#define gcdMMU_STLB_4K_SHIFT 12
- +#define gcdMMU_STLB_64K_SHIFT 16
- +
- +#define gcdMMU_MTLB_BITS (32 - gcdMMU_MTLB_SHIFT)
- +#define gcdMMU_PAGE_4K_BITS gcdMMU_STLB_4K_SHIFT
- +#define gcdMMU_STLB_4K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_PAGE_4K_BITS)
- +#define gcdMMU_PAGE_64K_BITS gcdMMU_STLB_64K_SHIFT
- +#define gcdMMU_STLB_64K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_PAGE_64K_BITS)
- +
- +#define gcdMMU_MTLB_ENTRY_NUM (1 << gcdMMU_MTLB_BITS)
- +#define gcdMMU_MTLB_SIZE (gcdMMU_MTLB_ENTRY_NUM << 2)
- +#define gcdMMU_STLB_4K_ENTRY_NUM (1 << gcdMMU_STLB_4K_BITS)
- +#define gcdMMU_STLB_4K_SIZE (gcdMMU_STLB_4K_ENTRY_NUM << 2)
- +#define gcdMMU_PAGE_4K_SIZE (1 << gcdMMU_STLB_4K_SHIFT)
- +#define gcdMMU_STLB_64K_ENTRY_NUM (1 << gcdMMU_STLB_64K_BITS)
- +#define gcdMMU_STLB_64K_SIZE (gcdMMU_STLB_64K_ENTRY_NUM << 2)
- +#define gcdMMU_PAGE_64K_SIZE (1 << gcdMMU_STLB_64K_SHIFT)
- +
- +#define gcdMMU_MTLB_MASK (~((1U << gcdMMU_MTLB_SHIFT)-1))
- +#define gcdMMU_STLB_4K_MASK ((~0U << gcdMMU_STLB_4K_SHIFT) ^ gcdMMU_MTLB_MASK)
- +#define gcdMMU_PAGE_4K_MASK (gcdMMU_PAGE_4K_SIZE - 1)
- +#define gcdMMU_STLB_64K_MASK ((~((1U << gcdMMU_STLB_64K_SHIFT)-1)) ^ gcdMMU_MTLB_MASK)
- +#define gcdMMU_PAGE_64K_MASK (gcdMMU_PAGE_64K_SIZE - 1)
- +
- +/* Page offset definitions. */
- +#define gcdMMU_OFFSET_4K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_STLB_4K_BITS)
- +#define gcdMMU_OFFSET_4K_MASK ((1U << gcdMMU_OFFSET_4K_BITS) - 1)
- +#define gcdMMU_OFFSET_16K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_STLB_16K_BITS)
- +#define gcdMMU_OFFSET_16K_MASK ((1U << gcdMMU_OFFSET_16K_BITS) - 1)
- +
- +/*******************************************************************************
- +***** Process Secure Cache ****************************************************/
- +
- +#define gcdSECURE_CACHE_LRU 1
- +#define gcdSECURE_CACHE_LINEAR 2
- +#define gcdSECURE_CACHE_HASH 3
- +#define gcdSECURE_CACHE_TABLE 4
- +
- +typedef struct _gcskLOGICAL_CACHE * gcskLOGICAL_CACHE_PTR;
- +typedef struct _gcskLOGICAL_CACHE gcskLOGICAL_CACHE;
- +struct _gcskLOGICAL_CACHE
- +{
- + /* Logical address. */
- + gctPOINTER logical;
- +
- + /* DMAable address. */
- + gctUINT32 dma;
- +
- +#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
- + /* Pointer to the previous and next hash tables. */
- + gcskLOGICAL_CACHE_PTR nextHash;
- + gcskLOGICAL_CACHE_PTR prevHash;
- +#endif
- +
- +#if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
- + /* Pointer to the previous and next slot. */
- + gcskLOGICAL_CACHE_PTR next;
- + gcskLOGICAL_CACHE_PTR prev;
- +#endif
- +
- +#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
- + /* Time stamp. */
- + gctUINT64 stamp;
- +#endif
- +};
- +
- +typedef struct _gcskSECURE_CACHE * gcskSECURE_CACHE_PTR;
- +typedef struct _gcskSECURE_CACHE
- +{
- + /* Cache memory. */
- + gcskLOGICAL_CACHE cache[1 + gcdSECURE_CACHE_SLOTS];
- +
- + /* Last known index for LINEAR mode. */
- + gcskLOGICAL_CACHE_PTR cacheIndex;
- +
- + /* Current free slot for LINEAR mode. */
- + gctUINT32 cacheFree;
- +
- + /* Time stamp for LINEAR mode. */
- + gctUINT64 cacheStamp;
- +
- +#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
- + /* Hash table for HASH mode. */
- + gcskLOGICAL_CACHE hash[256];
- +#endif
- +}
- +gcskSECURE_CACHE;
- +
- +/*******************************************************************************
- +***** Process Database Management *********************************************/
- +
- +typedef enum _gceDATABASE_TYPE
- +{
- + gcvDB_VIDEO_MEMORY = 1, /* Video memory created. */
- + gcvDB_COMMAND_BUFFER, /* Command Buffer. */
- + gcvDB_NON_PAGED, /* Non paged memory. */
- + gcvDB_CONTIGUOUS, /* Contiguous memory. */
- + gcvDB_SIGNAL, /* Signal. */
- + gcvDB_VIDEO_MEMORY_LOCKED, /* Video memory locked. */
- + gcvDB_CONTEXT, /* Context */
- + gcvDB_IDLE, /* GPU idle. */
- + gcvDB_MAP_MEMORY, /* Map memory */
- + gcvDB_SHARED_INFO, /* Private data */
- + gcvDB_MAP_USER_MEMORY, /* Map user memory */
- + gcvDB_SYNC_POINT, /* Sync point. */
- + gcvDB_VIDEO_MEMORY_RESERVED, /* Reserved video memory */
- + gcvDB_VIDEO_MEMORY_CONTIGUOUS, /* Contiguous video memory */
- + gcvDB_VIDEO_MEMORY_VIRTUAL, /* Virtual video memory */
- +}
- +gceDATABASE_TYPE;
- +
- +typedef struct _gcsDATABASE_RECORD * gcsDATABASE_RECORD_PTR;
- +typedef struct _gcsDATABASE_RECORD
- +{
- + /* Pointer to kernel. */
- + gckKERNEL kernel;
- +
- + /* Pointer to next database record. */
- + gcsDATABASE_RECORD_PTR next;
- +
- + /* Type of record. */
- + gceDATABASE_TYPE type;
- +
- + /* Data for record. */
- + gctPOINTER data;
- + gctPHYS_ADDR physical;
- + gctSIZE_T bytes;
- +}
- +gcsDATABASE_RECORD;
- +
- +typedef struct _gcsDATABASE * gcsDATABASE_PTR;
- +typedef struct _gcsDATABASE
- +{
- + /* Pointer to next entry is hash list. */
- + gcsDATABASE_PTR next;
- + gctSIZE_T slot;
- +
- + /* Process ID. */
- + gctUINT32 processID;
- +
- + /* Sizes to query. */
- + gcsDATABASE_COUNTERS vidMem;
- + gcsDATABASE_COUNTERS nonPaged;
- + gcsDATABASE_COUNTERS contiguous;
- + gcsDATABASE_COUNTERS mapUserMemory;
- + gcsDATABASE_COUNTERS mapMemory;
- + gcsDATABASE_COUNTERS vidMemResv;
- + gcsDATABASE_COUNTERS vidMemCont;
- + gcsDATABASE_COUNTERS vidMemVirt;
- +
- + /* Idle time management. */
- + gctUINT64 lastIdle;
- + gctUINT64 idle;
- +
- + /* Pointer to database. */
- + gcsDATABASE_RECORD_PTR list[48];
- +
- +#if gcdSECURE_USER
- + /* Secure cache. */
- + gcskSECURE_CACHE cache;
- +#endif
- +
- + gctPOINTER handleDatabase;
- + gctPOINTER handleDatabaseMutex;
- +}
- +gcsDATABASE;
- +
- +/* Create a process database that will contain all its allocations. */
- +gceSTATUS
- +gckKERNEL_CreateProcessDB(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 ProcessID
- + );
- +
- +/* Add a record to the process database. */
- +gceSTATUS
- +gckKERNEL_AddProcessDB(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 ProcessID,
- + IN gceDATABASE_TYPE Type,
- + IN gctPOINTER Pointer,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Size
- + );
- +
- +/* Remove a record to the process database. */
- +gceSTATUS
- +gckKERNEL_RemoveProcessDB(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 ProcessID,
- + IN gceDATABASE_TYPE Type,
- + IN gctPOINTER Pointer
- + );
- +
- +/* Destroy the process database. */
- +gceSTATUS
- +gckKERNEL_DestroyProcessDB(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 ProcessID
- + );
- +
- +/* Find a record to the process database. */
- +gceSTATUS
- +gckKERNEL_FindProcessDB(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 ProcessID,
- + IN gctUINT32 ThreadID,
- + IN gceDATABASE_TYPE Type,
- + IN gctPOINTER Pointer,
- + OUT gcsDATABASE_RECORD_PTR Record
- + );
- +
- +/* Query the process database. */
- +gceSTATUS
- +gckKERNEL_QueryProcessDB(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 ProcessID,
- + IN gctBOOL LastProcessID,
- + IN gceDATABASE_TYPE Type,
- + OUT gcuDATABASE_INFO * Info
- + );
- +
- +/* Dump the process database. */
- +gceSTATUS
- +gckKERNEL_DumpProcessDB(
- + IN gckKERNEL Kernel
- + );
- +
- +/* ID database */
- +gceSTATUS
- +gckKERNEL_CreateIntegerDatabase(
- + IN gckKERNEL Kernel,
- + OUT gctPOINTER * Database
- + );
- +
- +gceSTATUS
- +gckKERNEL_DestroyIntegerDatabase(
- + IN gckKERNEL Kernel,
- + IN gctPOINTER Database
- + );
- +
- +gceSTATUS
- +gckKERNEL_AllocateIntegerId(
- + IN gctPOINTER Database,
- + IN gctPOINTER Pointer,
- + OUT gctUINT32 * Id
- + );
- +
- +gceSTATUS
- +gckKERNEL_FreeIntegerId(
- + IN gctPOINTER Database,
- + IN gctUINT32 Id
- + );
- +
- +gceSTATUS
- +gckKERNEL_QueryIntegerId(
- + IN gctPOINTER Database,
- + IN gctUINT32 Id,
- + OUT gctPOINTER * Pointer
- + );
- +
- +gctUINT32
- +gckKERNEL_AllocateNameFromPointer(
- + IN gckKERNEL Kernel,
- + IN gctPOINTER Pointer
- + );
- +
- +gctPOINTER
- +gckKERNEL_QueryPointerFromName(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 Name
- + );
- +
- +gceSTATUS
- +gckKERNEL_DeleteName(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 Name
- + );
- +
- +#if gcdSECURE_USER
- +/* Get secure cache from the process database. */
- +gceSTATUS
- +gckKERNEL_GetProcessDBCache(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 ProcessID,
- + OUT gcskSECURE_CACHE_PTR * Cache
- + );
- +#endif
- +
- +/*******************************************************************************
- +********* Timer Management ****************************************************/
- +typedef struct _gcsTIMER * gcsTIMER_PTR;
- +typedef struct _gcsTIMER
- +{
- + /* Start and Stop time holders. */
- + gctUINT64 startTime;
- + gctUINT64 stopTime;
- +}
- +gcsTIMER;
- +
- +/******************************************************************************\
- +********************************** Structures **********************************
- +\******************************************************************************/
- +
- +/* gckDB object. */
- +struct _gckDB
- +{
- + /* Database management. */
- + gcsDATABASE_PTR db[16];
- + gctPOINTER dbMutex;
- + gcsDATABASE_PTR freeDatabase;
- + gcsDATABASE_RECORD_PTR freeRecord;
- + gcsDATABASE_PTR lastDatabase;
- + gctUINT32 lastProcessID;
- + gctUINT64 lastIdle;
- + gctUINT64 idleTime;
- + gctUINT64 lastSlowdown;
- + gctUINT64 lastSlowdownIdle;
- + /* ID - Pointer database*/
- + gctPOINTER pointerDatabase;
- + gctPOINTER pointerDatabaseMutex;
- +};
- +
- +#if gcdVIRTUAL_COMMAND_BUFFER
- +typedef struct _gckVIRTUAL_COMMAND_BUFFER * gckVIRTUAL_COMMAND_BUFFER_PTR;
- +typedef struct _gckVIRTUAL_COMMAND_BUFFER
- +{
- + gctPHYS_ADDR physical;
- + gctPOINTER userLogical;
- + gctPOINTER kernelLogical;
- + gctSIZE_T pageCount;
- + gctPOINTER pageTable;
- + gctUINT32 gpuAddress;
- + gctUINT pid;
- + gckVIRTUAL_COMMAND_BUFFER_PTR next;
- + gckVIRTUAL_COMMAND_BUFFER_PTR prev;
- + gckKERNEL kernel;
- +}
- +gckVIRTUAL_COMMAND_BUFFER;
- +#endif
- +
- +/* gckKERNEL object. */
- +struct _gckKERNEL
- +{
- + /* Object. */
- + gcsOBJECT object;
- +
- + /* Pointer to gckOS object. */
- + gckOS os;
- +
- + /* Core */
- + gceCORE core;
- +
- + /* Pointer to gckHARDWARE object. */
- + gckHARDWARE hardware;
- +
- + /* Pointer to gckCOMMAND object. */
- + gckCOMMAND command;
- +
- + /* Pointer to gckEVENT object. */
- + gckEVENT eventObj;
- +
- + /* Pointer to context. */
- + gctPOINTER context;
- +
- + /* Pointer to gckMMU object. */
- + gckMMU mmu;
- +
- + /* Arom holding number of clients. */
- + gctPOINTER atomClients;
- +
- +#if VIVANTE_PROFILER
- + /* Enable profiling */
- + gctBOOL profileEnable;
- +
- + /* Clear profile register or not*/
- + gctBOOL profileCleanRegister;
- +
- +#endif
- +
- +#ifdef QNX_SINGLE_THREADED_DEBUGGING
- + gctPOINTER debugMutex;
- +#endif
- +
- + /* Database management. */
- + gckDB db;
- + gctBOOL dbCreated;
- +
- +#if gcdENABLE_RECOVERY
- + gctPOINTER resetFlagClearTimer;
- + gctPOINTER resetAtom;
- + gctUINT64 resetTimeStamp;
- +#endif
- +
- + /* Pointer to gckEVENT object. */
- + gcsTIMER timers[8];
- + gctUINT32 timeOut;
- +
- +#if gcdENABLE_VG
- + gckVGKERNEL vg;
- +#endif
- +
- +#if gcdVIRTUAL_COMMAND_BUFFER
- + gckVIRTUAL_COMMAND_BUFFER_PTR virtualBufferHead;
- + gckVIRTUAL_COMMAND_BUFFER_PTR virtualBufferTail;
- + gctPOINTER virtualBufferLock;
- +#endif
- +
- +#if gcdDVFS
- + gckDVFS dvfs;
- +#endif
- +
- +#if gcdANDROID_NATIVE_FENCE_SYNC
- + gctHANDLE timeline;
- +#endif
- +
- + spinlock_t irq_lock;
- +};
- +
- +struct _FrequencyHistory
- +{
- + gctUINT32 frequency;
- + gctUINT32 count;
- +};
- +
- +/* gckDVFS object. */
- +struct _gckDVFS
- +{
- + gckOS os;
- + gckHARDWARE hardware;
- + gctPOINTER timer;
- + gctUINT32 pollingTime;
- + gctBOOL stop;
- + gctUINT32 totalConfig;
- + gctUINT32 loads[8];
- + gctUINT8 currentScale;
- + struct _FrequencyHistory frequencyHistory[16];
- +};
- +
- +/* gckCOMMAND object. */
- +struct _gckCOMMAND
- +{
- + /* Object. */
- + gcsOBJECT object;
- +
- + /* Pointer to required object. */
- + gckKERNEL kernel;
- + gckOS os;
- +
- + /* Number of bytes per page. */
- + gctSIZE_T pageSize;
- +
- + /* Current pipe select. */
- + gcePIPE_SELECT pipeSelect;
- +
- + /* Command queue running flag. */
- + gctBOOL running;
- +
- + /* Idle flag and commit stamp. */
- + gctBOOL idle;
- + gctUINT64 commitStamp;
- +
- + /* Command queue mutex. */
- + gctPOINTER mutexQueue;
- +
- + /* Context switching mutex. */
- + gctPOINTER mutexContext;
- +
- +#if VIVANTE_PROFILER_CONTEXT
- + /* Context sequence mutex. */
- + gctPOINTER mutexContextSeq;
- +#endif
- +
- + /* Command queue power semaphore. */
- + gctPOINTER powerSemaphore;
- +
- + /* Current command queue. */
- + struct _gcskCOMMAND_QUEUE
- + {
- + gctSIGNAL signal;
- + gctPHYS_ADDR physical;
- + gctPOINTER logical;
- + }
- + queues[gcdCOMMAND_QUEUES];
- +
- + gctPHYS_ADDR physical;
- + gctPOINTER logical;
- + gctUINT32 offset;
- + gctINT index;
- +#if gcmIS_DEBUG(gcdDEBUG_TRACE)
- + gctUINT wrapCount;
- +#endif
- +
- + /* The command queue is new. */
- + gctBOOL newQueue;
- +
- + /* Context management. */
- + gckCONTEXT currContext;
- +
- + /* Pointer to last WAIT command. */
- + gctPHYS_ADDR waitPhysical;
- + gctPOINTER waitLogical;
- + gctSIZE_T waitSize;
- +
- + /* Command buffer alignment. */
- + gctSIZE_T alignment;
- + gctSIZE_T reservedHead;
- + gctSIZE_T reservedTail;
- +
- + /* Commit counter. */
- + gctPOINTER atomCommit;
- +
- + /* Kernel process ID. */
- + gctUINT32 kernelProcessID;
- +
- + /* End Event signal. */
- + gctSIGNAL endEventSignal;
- +
- +#if gcdSECURE_USER
- + /* Hint array copy buffer. */
- + gctBOOL hintArrayAllocated;
- + gctUINT hintArraySize;
- + gctUINT32_PTR hintArray;
- +#endif
- +};
- +
- +typedef struct _gcsEVENT * gcsEVENT_PTR;
- +
- +/* Structure holding one event to be processed. */
- +typedef struct _gcsEVENT
- +{
- + /* Pointer to next event in queue. */
- + gcsEVENT_PTR next;
- +
- + /* Event information. */
- + gcsHAL_INTERFACE info;
- +
- + /* Process ID owning the event. */
- + gctUINT32 processID;
- +
- +#ifdef __QNXNTO__
- + /* Kernel. */
- + gckKERNEL kernel;
- +#endif
- +
- + gctBOOL fromKernel;
- +}
- +gcsEVENT;
- +
- +/* Structure holding a list of events to be processed by an interrupt. */
- +typedef struct _gcsEVENT_QUEUE * gcsEVENT_QUEUE_PTR;
- +typedef struct _gcsEVENT_QUEUE
- +{
- + /* Time stamp. */
- + gctUINT64 stamp;
- +
- + /* Source of the event. */
- + gceKERNEL_WHERE source;
- +
- + /* Pointer to head of event queue. */
- + gcsEVENT_PTR head;
- +
- + /* Pointer to tail of event queue. */
- + gcsEVENT_PTR tail;
- +
- + /* Next list of events. */
- + gcsEVENT_QUEUE_PTR next;
- +}
- +gcsEVENT_QUEUE;
- +
- +/*
- + gcdREPO_LIST_COUNT defines the maximum number of event queues with different
- + hardware module sources that may coexist at the same time. Only two sources
- + are supported - gcvKERNEL_COMMAND and gcvKERNEL_PIXEL. gcvKERNEL_COMMAND
- + source is used only for managing the kernel command queue and is only issued
- + when the current command queue gets full. Since we commit event queues every
- + time we commit command buffers, in the worst case we can have up to three
- + pending event queues:
- + - gcvKERNEL_PIXEL
- + - gcvKERNEL_COMMAND (queue overflow)
- + - gcvKERNEL_PIXEL
- +*/
- +#define gcdREPO_LIST_COUNT 3
- +
- +/* gckEVENT object. */
- +struct _gckEVENT
- +{
- + /* The object. */
- + gcsOBJECT object;
- +
- + /* Pointer to required objects. */
- + gckOS os;
- + gckKERNEL kernel;
- +
- + /* Time stamp. */
- + gctUINT64 stamp;
- + gctUINT64 lastCommitStamp;
- +
- + /* Queue mutex. */
- + gctPOINTER eventQueueMutex;
- +
- + /* Array of event queues. */
- + gcsEVENT_QUEUE queues[30];
- + gctUINT8 lastID;
- + gctPOINTER freeAtom;
- +
- + /* Pending events. */
- +#if gcdSMP
- + gctPOINTER pending;
- +#else
- + volatile gctUINT pending;
- +#endif
- +
- + /* List of free event structures and its mutex. */
- + gcsEVENT_PTR freeEventList;
- + gctSIZE_T freeEventCount;
- + gctPOINTER freeEventMutex;
- +
- + /* Event queues. */
- + gcsEVENT_QUEUE_PTR queueHead;
- + gcsEVENT_QUEUE_PTR queueTail;
- + gcsEVENT_QUEUE_PTR freeList;
- + gcsEVENT_QUEUE repoList[gcdREPO_LIST_COUNT];
- + gctPOINTER eventListMutex;
- +
- + gctPOINTER submitTimer;
- +
- + volatile gctBOOL inNotify;
- +};
- +
- +/* Free all events belonging to a process. */
- +gceSTATUS
- +gckEVENT_FreeProcess(
- + IN gckEVENT Event,
- + IN gctUINT32 ProcessID
- + );
- +
- +gceSTATUS
- +gckEVENT_Stop(
- + IN gckEVENT Event,
- + IN gctUINT32 ProcessID,
- + IN gctPHYS_ADDR Handle,
- + IN gctPOINTER Logical,
- + IN gctSIGNAL Signal,
- + IN OUT gctSIZE_T * waitSize
- + );
- +
- +gceSTATUS
- +gckEVENT_WaitEmpty(
- + IN gckEVENT Event
- + );
- +
- +/* gcuVIDMEM_NODE structure. */
- +typedef union _gcuVIDMEM_NODE
- +{
- + /* Allocated from gckVIDMEM. */
- + struct _gcsVIDMEM_NODE_VIDMEM
- + {
- + /* Owner of this node. */
- + gckVIDMEM memory;
- +
- + /* Dual-linked list of nodes. */
- + gcuVIDMEM_NODE_PTR next;
- + gcuVIDMEM_NODE_PTR prev;
- +
- + /* Dual linked list of free nodes. */
- + gcuVIDMEM_NODE_PTR nextFree;
- + gcuVIDMEM_NODE_PTR prevFree;
- +
- + /* Information for this node. */
- + gctUINT32 offset;
- + gctSIZE_T bytes;
- + gctUINT32 alignment;
- +
- +#ifdef __QNXNTO__
- + /* Client/server vaddr (mapped using mmap_join). */
- + gctPOINTER logical;
- +#endif
- +
- + /* Locked counter. */
- + gctINT32 locked;
- +
- + /* Memory pool. */
- + gcePOOL pool;
- + gctUINT32 physical;
- +
- + /* Process ID owning this memory. */
- + gctUINT32 processID;
- +
- + /* Prevent compositor from freeing until client unlocks. */
- + gctBOOL freePending;
- +
- + /* */
- + gcsVIDMEM_NODE_SHARED_INFO sharedInfo;
- +
- +#if gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
- + gctPOINTER kernelVirtual;
- +#endif
- +
- + /* Surface type. */
- + gceSURF_TYPE type;
- + }
- + VidMem;
- +
- + /* Allocated from gckOS. */
- + struct _gcsVIDMEM_NODE_VIRTUAL
- + {
- + /* Pointer to gckKERNEL object. */
- + gckKERNEL kernel;
- +
- + /* Information for this node. */
- + /* Contiguously allocated? */
- + gctBOOL contiguous;
- + /* mdl record pointer... a kmalloc address. Process agnostic. */
- + gctPHYS_ADDR physical;
- + gctSIZE_T bytes;
- + /* do_mmap_pgoff address... mapped per-process. */
- + gctPOINTER logical;
- +
- + /* Page table information. */
- + /* Used only when node is not contiguous */
- + gctSIZE_T pageCount;
- +
- + /* Used only when node is not contiguous */
- + gctPOINTER pageTables[gcdMAX_GPU_COUNT];
- + /* Pointer to gckKERNEL object who lock this. */
- + gckKERNEL lockKernels[gcdMAX_GPU_COUNT];
- + /* Actual physical address */
- + gctUINT32 addresses[gcdMAX_GPU_COUNT];
- +
- + /* Mutex. */
- + gctPOINTER mutex;
- +
- + /* Locked counter. */
- + gctINT32 lockeds[gcdMAX_GPU_COUNT];
- +
- +#ifdef __QNXNTO__
- + /* Single linked list of nodes. */
- + gcuVIDMEM_NODE_PTR next;
- +
- + /* Unlock pending flag. */
- + gctBOOL unlockPendings[gcdMAX_GPU_COUNT];
- +
- + /* Free pending flag. */
- + gctBOOL freePending;
- +#endif
- +
- + /* Process ID owning this memory. */
- + gctUINT32 processID;
- +
- + /* Owner process sets freed to true
- + * when it trys to free a locked
- + * node */
- + gctBOOL freed;
- +
- + /* */
- + gcsVIDMEM_NODE_SHARED_INFO sharedInfo;
- +
- + /* Surface type. */
- + gceSURF_TYPE type;
- + }
- + Virtual;
- +}
- +gcuVIDMEM_NODE;
- +
- +/* gckVIDMEM object. */
- +struct _gckVIDMEM
- +{
- + /* Object. */
- + gcsOBJECT object;
- +
- + /* Pointer to gckOS object. */
- + gckOS os;
- +
- + /* Information for this video memory heap. */
- + gctUINT32 baseAddress;
- + gctSIZE_T bytes;
- + gctSIZE_T freeBytes;
- +
- + /* Mapping for each type of surface. */
- + gctINT mapping[gcvSURF_NUM_TYPES];
- +
- + /* Sentinel nodes for up to 8 banks. */
- + gcuVIDMEM_NODE sentinel[8];
- +
- + /* Allocation threshold. */
- + gctSIZE_T threshold;
- +
- + /* The heap mutex. */
- + gctPOINTER mutex;
- +
- +#if gcdUSE_VIDMEM_PER_PID
- + /* The Pid this VidMem belongs to. */
- + gctUINT32 pid;
- +
- + struct _gckVIDMEM* next;
- +#endif
- +};
- +
- +/* gckMMU object. */
- +struct _gckMMU
- +{
- + /* The object. */
- + gcsOBJECT object;
- +
- + /* Pointer to gckOS object. */
- + gckOS os;
- +
- + /* Pointer to gckHARDWARE object. */
- + gckHARDWARE hardware;
- +
- + /* The page table mutex. */
- + gctPOINTER pageTableMutex;
- +
- + /* Page table information. */
- + gctSIZE_T pageTableSize;
- + gctPHYS_ADDR pageTablePhysical;
- + gctUINT32_PTR pageTableLogical;
- + gctUINT32 pageTableEntries;
- +
- + /* Master TLB information. */
- + gctSIZE_T mtlbSize;
- + gctPHYS_ADDR mtlbPhysical;
- + gctUINT32_PTR mtlbLogical;
- + gctUINT32 mtlbEntries;
- +
- + /* Free entries. */
- + gctUINT32 heapList;
- + gctBOOL freeNodes;
- +
- + gctPOINTER staticSTLB;
- + gctBOOL enabled;
- +
- + gctUINT32 dynamicMappingStart;
- +
- +#ifdef __QNXNTO__
- + /* Single linked list of all allocated nodes. */
- + gctPOINTER nodeMutex;
- + gcuVIDMEM_NODE_PTR nodeList;
- +#endif
- +};
- +
- +#if gcdVIRTUAL_COMMAND_BUFFER
- +gceSTATUS
- +gckOS_CreateKernelVirtualMapping(
- + IN gctPHYS_ADDR Physical,
- + OUT gctSIZE_T * PageCount,
- + OUT gctPOINTER * Logical
- + );
- +
- +gceSTATUS
- +gckOS_DestroyKernelVirtualMapping(
- + IN gctPOINTER Logical
- + );
- +
- +gceSTATUS
- +gckKERNEL_AllocateVirtualCommandBuffer(
- + IN gckKERNEL Kernel,
- + IN gctBOOL InUserSpace,
- + IN OUT gctSIZE_T * Bytes,
- + OUT gctPHYS_ADDR * Physical,
- + OUT gctPOINTER * Logical
- + );
- +
- +gceSTATUS
- +gckKERNEL_DestroyVirtualCommandBuffer(
- + IN gckKERNEL Kernel,
- + IN gctSIZE_T Bytes,
- + IN gctPHYS_ADDR Physical,
- + IN gctPOINTER Logical
- + );
- +
- +gceSTATUS
- +gckKERNEL_GetGPUAddress(
- + IN gckKERNEL Kernel,
- + IN gctPOINTER Logical,
- + OUT gctUINT32 * Address
- + );
- +
- +gceSTATUS
- +gckKERNEL_QueryGPUAddress(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 GpuAddress,
- + OUT gckVIRTUAL_COMMAND_BUFFER_PTR * Buffer
- + );
- +#endif
- +
- +gceSTATUS
- +gckKERNEL_AttachProcess(
- + IN gckKERNEL Kernel,
- + IN gctBOOL Attach
- + );
- +
- +gceSTATUS
- +gckKERNEL_AttachProcessEx(
- + IN gckKERNEL Kernel,
- + IN gctBOOL Attach,
- + IN gctUINT32 PID
- + );
- +
- +#if gcdSECURE_USER
- +gceSTATUS
- +gckKERNEL_MapLogicalToPhysical(
- + IN gckKERNEL Kernel,
- + IN gcskSECURE_CACHE_PTR Cache,
- + IN OUT gctPOINTER * Data
- + );
- +
- +gceSTATUS
- +gckKERNEL_FlushTranslationCache(
- + IN gckKERNEL Kernel,
- + IN gcskSECURE_CACHE_PTR Cache,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes
- + );
- +#endif
- +
- +gceSTATUS
- +gckHARDWARE_QueryIdle(
- + IN gckHARDWARE Hardware,
- + OUT gctBOOL_PTR IsIdle
- + );
- +
- +/******************************************************************************\
- +******************************* gckCONTEXT Object *******************************
- +\******************************************************************************/
- +
- +gceSTATUS
- +gckCONTEXT_Construct(
- + IN gckOS Os,
- + IN gckHARDWARE Hardware,
- + IN gctUINT32 ProcessID,
- + OUT gckCONTEXT * Context
- + );
- +
- +gceSTATUS
- +gckCONTEXT_Destroy(
- + IN gckCONTEXT Context
- + );
- +
- +gceSTATUS
- +gckCONTEXT_Update(
- + IN gckCONTEXT Context,
- + IN gctUINT32 ProcessID,
- + IN gcsSTATE_DELTA_PTR StateDelta
- + );
- +
- +#if gcdLINK_QUEUE_SIZE
- +void
- +gckLINKQUEUE_Enqueue(
- + IN gckLINKQUEUE LinkQueue,
- + IN gctUINT32 start,
- + IN gctUINT32 end
- + );
- +
- +void
- +gckLINKQUEUE_GetData(
- + IN gckLINKQUEUE LinkQueue,
- + IN gctUINT32 Index,
- + OUT gckLINKDATA * Data
- + );
- +#endif
- +
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* __gc_hal_kernel_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_heap.c linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_heap.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_heap.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_heap.c 2015-03-08 14:27:37.633684500 -0500
- @@ -0,0 +1,859 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +/**
- +** @file
- +** gckHEAP object for kernel HAL layer. The heap implemented here is an arena-
- +** based memory allocation. An arena-based memory heap allocates data quickly
- +** from specified arenas and reduces memory fragmentation.
- +**
- +*/
- +#include "gc_hal_kernel_precomp.h"
- +
- +#define _GC_OBJ_ZONE gcvZONE_HEAP
- +
- +/*******************************************************************************
- +***** Structures ***************************************************************
- +*******************************************************************************/
- +
- +#define gcdIN_USE ((gcskNODE_PTR) ~0)
- +
- +typedef struct _gcskNODE * gcskNODE_PTR;
- +typedef struct _gcskNODE
- +{
- + /* Number of byets in node. */
- + gctSIZE_T bytes;
- +
- + /* Pointer to next free node, or gcvNULL to mark the node as freed, or
- + ** gcdIN_USE to mark the node as used. */
- + gcskNODE_PTR next;
- +
- +#if gcmIS_DEBUG(gcdDEBUG_CODE)
- + /* Time stamp of allocation. */
- + gctUINT64 timeStamp;
- +#endif
- +}
- +gcskNODE;
- +
- +typedef struct _gcskHEAP * gcskHEAP_PTR;
- +typedef struct _gcskHEAP
- +{
- + /* Linked list. */
- + gcskHEAP_PTR next;
- + gcskHEAP_PTR prev;
- +
- + /* Heap size. */
- + gctSIZE_T size;
- +
- + /* Free list. */
- + gcskNODE_PTR freeList;
- +}
- +gcskHEAP;
- +
- +struct _gckHEAP
- +{
- + /* Object. */
- + gcsOBJECT object;
- +
- + /* Pointer to a gckOS object. */
- + gckOS os;
- +
- + /* Locking mutex. */
- + gctPOINTER mutex;
- +
- + /* Allocation parameters. */
- + gctSIZE_T allocationSize;
- +
- + /* Heap list. */
- + gcskHEAP_PTR heap;
- +#if gcmIS_DEBUG(gcdDEBUG_CODE)
- + gctUINT64 timeStamp;
- +#endif
- +
- +#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
- + /* Profile information. */
- + gctUINT32 allocCount;
- + gctUINT64 allocBytes;
- + gctUINT64 allocBytesMax;
- + gctUINT64 allocBytesTotal;
- + gctUINT32 heapCount;
- + gctUINT32 heapCountMax;
- + gctUINT64 heapMemory;
- + gctUINT64 heapMemoryMax;
- +#endif
- +};
- +
- +/*******************************************************************************
- +***** Static Support Functions *************************************************
- +*******************************************************************************/
- +
- +#if gcmIS_DEBUG(gcdDEBUG_CODE)
- +static gctSIZE_T
- +_DumpHeap(
- + IN gcskHEAP_PTR Heap
- + )
- +{
- + gctPOINTER p;
- + gctSIZE_T leaked = 0;
- +
- + /* Start at first node. */
- + for (p = Heap + 1;;)
- + {
- + /* Convert the pointer. */
- + gcskNODE_PTR node = (gcskNODE_PTR) p;
- +
- + /* Check if this is a used node. */
- + if (node->next == gcdIN_USE)
- + {
- + /* Print the leaking node. */
- + gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_HEAP,
- + "Detected leaking: node=0x%x bytes=%lu timeStamp=%llu "
- + "(%08X %c%c%c%c)",
- + node, node->bytes, node->timeStamp,
- + ((gctUINT32_PTR) (node + 1))[0],
- + gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[0]),
- + gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[1]),
- + gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[2]),
- + gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[3]));
- +
- + /* Add leaking byte count. */
- + leaked += node->bytes;
- + }
- +
- + /* Test for end of heap. */
- + if (node->bytes == 0)
- + {
- + break;
- + }
- +
- + else
- + {
- + /* Move to next node. */
- + p = (gctUINT8_PTR) node + node->bytes;
- + }
- + }
- +
- + /* Return the number of leaked bytes. */
- + return leaked;
- +}
- +#endif
- +
- +static gceSTATUS
- +_CompactKernelHeap(
- + IN gckHEAP Heap
- + )
- +{
- + gcskHEAP_PTR heap, next;
- + gctPOINTER p;
- + gcskHEAP_PTR freeList = gcvNULL;
- +
- + gcmkHEADER_ARG("Heap=0x%x", Heap);
- +
- + /* Walk all the heaps. */
- + for (heap = Heap->heap; heap != gcvNULL; heap = next)
- + {
- + gcskNODE_PTR lastFree = gcvNULL;
- +
- + /* Zero out the free list. */
- + heap->freeList = gcvNULL;
- +
- + /* Start at the first node. */
- + for (p = (gctUINT8_PTR) (heap + 1);;)
- + {
- + /* Convert the pointer. */
- + gcskNODE_PTR node = (gcskNODE_PTR) p;
- +
- + gcmkASSERT(p <= (gctPOINTER) ((gctUINT8_PTR) (heap + 1) + heap->size));
- +
- + /* Test if this node not used. */
- + if (node->next != gcdIN_USE)
- + {
- + /* Test if this is the end of the heap. */
- + if (node->bytes == 0)
- + {
- + break;
- + }
- +
- + /* Test of this is the first free node. */
- + else if (lastFree == gcvNULL)
- + {
- + /* Initialzie the free list. */
- + heap->freeList = node;
- + lastFree = node;
- + }
- +
- + else
- + {
- + /* Test if this free node is contiguous with the previous
- + ** free node. */
- + if ((gctUINT8_PTR) lastFree + lastFree->bytes == p)
- + {
- + /* Just increase the size of the previous free node. */
- + lastFree->bytes += node->bytes;
- + }
- + else
- + {
- + /* Add to linked list. */
- + lastFree->next = node;
- + lastFree = node;
- + }
- + }
- + }
- +
- + /* Move to next node. */
- + p = (gctUINT8_PTR) node + node->bytes;
- + }
- +
- + /* Mark the end of the chain. */
- + if (lastFree != gcvNULL)
- + {
- + lastFree->next = gcvNULL;
- + }
- +
- + /* Get next heap. */
- + next = heap->next;
- +
- + /* Check if the entire heap is free. */
- + if ((heap->freeList != gcvNULL)
- + && (heap->freeList->bytes == heap->size - gcmSIZEOF(gcskNODE))
- + )
- + {
- + /* Remove the heap from the linked list. */
- + if (heap->prev == gcvNULL)
- + {
- + Heap->heap = next;
- + }
- + else
- + {
- + heap->prev->next = next;
- + }
- +
- + if (heap->next != gcvNULL)
- + {
- + heap->next->prev = heap->prev;
- + }
- +
- +#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
- + /* Update profiling. */
- + Heap->heapCount -= 1;
- + Heap->heapMemory -= heap->size + gcmSIZEOF(gcskHEAP);
- +#endif
- +
- + /* Add this heap to the list of heaps that need to be freed. */
- + heap->next = freeList;
- + freeList = heap;
- + }
- + }
- +
- + if (freeList != gcvNULL)
- + {
- + /* Release the mutex, remove any chance for a dead lock. */
- + gcmkVERIFY_OK(
- + gckOS_ReleaseMutex(Heap->os, Heap->mutex));
- +
- + /* Free all heaps in the free list. */
- + for (heap = freeList; heap != gcvNULL; heap = next)
- + {
- + /* Get pointer to the next heap. */
- + next = heap->next;
- +
- + /* Free the heap. */
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
- + "Freeing heap 0x%x (%lu bytes)",
- + heap, heap->size + gcmSIZEOF(gcskHEAP));
- + gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
- + }
- +
- + /* Acquire the mutex again. */
- + gcmkVERIFY_OK(
- + gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +***** gckHEAP API Code *********************************************************
- +*******************************************************************************/
- +
- +/*******************************************************************************
- +**
- +** gckHEAP_Construct
- +**
- +** Construct a new gckHEAP object.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** gctSIZE_T AllocationSize
- +** Minimum size per arena.
- +**
- +** OUTPUT:
- +**
- +** gckHEAP * Heap
- +** Pointer to a variable that will hold the pointer to the gckHEAP
- +** object.
- +*/
- +gceSTATUS
- +gckHEAP_Construct(
- + IN gckOS Os,
- + IN gctSIZE_T AllocationSize,
- + OUT gckHEAP * Heap
- + )
- +{
- + gceSTATUS status;
- + gckHEAP heap = gcvNULL;
- + gctPOINTER pointer = gcvNULL;
- +
- + gcmkHEADER_ARG("Os=0x%x AllocationSize=%lu", Os, AllocationSize);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Heap != gcvNULL);
- +
- + /* Allocate the gckHEAP object. */
- + gcmkONERROR(gckOS_AllocateMemory(Os,
- + gcmSIZEOF(struct _gckHEAP),
- + &pointer));
- +
- + heap = pointer;
- +
- + /* Initialize the gckHEAP object. */
- + heap->object.type = gcvOBJ_HEAP;
- + heap->os = Os;
- + heap->allocationSize = AllocationSize;
- + heap->heap = gcvNULL;
- +#if gcmIS_DEBUG(gcdDEBUG_CODE)
- + heap->timeStamp = 0;
- +#endif
- +
- +#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
- + /* Zero the counters. */
- + heap->allocCount = 0;
- + heap->allocBytes = 0;
- + heap->allocBytesMax = 0;
- + heap->allocBytesTotal = 0;
- + heap->heapCount = 0;
- + heap->heapCountMax = 0;
- + heap->heapMemory = 0;
- + heap->heapMemoryMax = 0;
- +#endif
- +
- + /* Create the mutex. */
- + gcmkONERROR(gckOS_CreateMutex(Os, &heap->mutex));
- +
- + /* Return the pointer to the gckHEAP object. */
- + *Heap = heap;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Heap=0x%x", *Heap);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Roll back. */
- + if (heap != gcvNULL)
- + {
- + /* Free the heap structure. */
- + gcmkVERIFY_OK(gckOS_FreeMemory(Os, heap));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHEAP_Destroy
- +**
- +** Destroy a gckHEAP object.
- +**
- +** INPUT:
- +**
- +** gckHEAP Heap
- +** Pointer to a gckHEAP object to destroy.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckHEAP_Destroy(
- + IN gckHEAP Heap
- + )
- +{
- + gcskHEAP_PTR heap;
- +#if gcmIS_DEBUG(gcdDEBUG_CODE)
- + gctSIZE_T leaked = 0;
- +#endif
- +
- + gcmkHEADER_ARG("Heap=0x%x", Heap);
- +
- + for (heap = Heap->heap; heap != gcvNULL; heap = Heap->heap)
- + {
- + /* Unlink heap from linked list. */
- + Heap->heap = heap->next;
- +
- +#if gcmIS_DEBUG(gcdDEBUG_CODE)
- + /* Check for leaked memory. */
- + leaked += _DumpHeap(heap);
- +#endif
- +
- + /* Free the heap. */
- + gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
- + }
- +
- + /* Free the mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Heap->os, Heap->mutex));
- +
- + /* Free the heap structure. */
- + gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, Heap));
- +
- + /* Success. */
- +#if gcmIS_DEBUG(gcdDEBUG_CODE)
- + gcmkFOOTER_ARG("leaked=%lu", leaked);
- +#else
- + gcmkFOOTER_NO();
- +#endif
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHEAP_Allocate
- +**
- +** Allocate data from the heap.
- +**
- +** INPUT:
- +**
- +** gckHEAP Heap
- +** Pointer to a gckHEAP object.
- +**
- +** IN gctSIZE_T Bytes
- +** Number of byte to allocate.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * Memory
- +** Pointer to a variable that will hold the address of the allocated
- +** memory.
- +*/
- +gceSTATUS
- +gckHEAP_Allocate(
- + IN gckHEAP Heap,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER * Memory
- + )
- +{
- + gctBOOL acquired = gcvFALSE;
- + gcskHEAP_PTR heap;
- + gceSTATUS status;
- + gctSIZE_T bytes;
- + gcskNODE_PTR node, used, prevFree = gcvNULL;
- + gctPOINTER memory = gcvNULL;
- +
- + gcmkHEADER_ARG("Heap=0x%x Bytes=%lu", Heap, Bytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- + gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
- +
- + /* Determine number of bytes required for a node. */
- + bytes = gcmALIGN(Bytes + gcmSIZEOF(gcskNODE), 8);
- +
- + /* Acquire the mutex. */
- + gcmkONERROR(
- + gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
- +
- + acquired = gcvTRUE;
- +
- + /* Check if this allocation is bigger than the default allocation size. */
- + if (bytes > Heap->allocationSize - gcmSIZEOF(gcskHEAP) - gcmSIZEOF(gcskNODE))
- + {
- + /* Adjust allocation size. */
- + Heap->allocationSize = bytes * 2;
- + }
- +
- + else if (Heap->heap != gcvNULL)
- + {
- + gctINT i;
- +
- + /* 2 retries, since we might need to compact. */
- + for (i = 0; i < 2; ++i)
- + {
- + /* Walk all the heaps. */
- + for (heap = Heap->heap; heap != gcvNULL; heap = heap->next)
- + {
- + /* Check if this heap has enough bytes to hold the request. */
- + if (bytes <= heap->size - gcmSIZEOF(gcskNODE))
- + {
- + prevFree = gcvNULL;
- +
- + /* Walk the chain of free nodes. */
- + for (node = heap->freeList;
- + node != gcvNULL;
- + node = node->next
- + )
- + {
- + gcmkASSERT(node->next != gcdIN_USE);
- +
- + /* Check if this free node has enough bytes. */
- + if (node->bytes >= bytes)
- + {
- + /* Use the node. */
- + goto UseNode;
- + }
- +
- + /* Save current free node for linked list management. */
- + prevFree = node;
- + }
- + }
- + }
- +
- + if (i == 0)
- + {
- + /* Compact the heap. */
- + gcmkVERIFY_OK(_CompactKernelHeap(Heap));
- +
- +#if gcmIS_DEBUG(gcdDEBUG_CODE)
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
- + "===== KERNEL HEAP =====");
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
- + "Number of allocations : %12u",
- + Heap->allocCount);
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
- + "Number of bytes allocated : %12llu",
- + Heap->allocBytes);
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
- + "Maximum allocation size : %12llu",
- + Heap->allocBytesMax);
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
- + "Total number of bytes allocated : %12llu",
- + Heap->allocBytesTotal);
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
- + "Number of heaps : %12u",
- + Heap->heapCount);
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
- + "Heap memory in bytes : %12llu",
- + Heap->heapMemory);
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
- + "Maximum number of heaps : %12u",
- + Heap->heapCountMax);
- + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
- + "Maximum heap memory in bytes : %12llu",
- + Heap->heapMemoryMax);
- +#endif
- + }
- + }
- + }
- +
- + /* Release the mutex. */
- + gcmkONERROR(
- + gckOS_ReleaseMutex(Heap->os, Heap->mutex));
- +
- + acquired = gcvFALSE;
- +
- + /* Allocate a new heap. */
- + gcmkONERROR(
- + gckOS_AllocateMemory(Heap->os,
- + Heap->allocationSize,
- + &memory));
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
- + "Allocated heap 0x%x (%lu bytes)",
- + memory, Heap->allocationSize);
- +
- + /* Acquire the mutex. */
- + gcmkONERROR(
- + gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
- +
- + acquired = gcvTRUE;
- +
- + /* Use the allocated memory as the heap. */
- + heap = (gcskHEAP_PTR) memory;
- +
- + /* Insert this heap to the head of the chain. */
- + heap->next = Heap->heap;
- + heap->prev = gcvNULL;
- + heap->size = Heap->allocationSize - gcmSIZEOF(gcskHEAP);
- +
- + if (heap->next != gcvNULL)
- + {
- + heap->next->prev = heap;
- + }
- + Heap->heap = heap;
- +
- + /* Mark the end of the heap. */
- + node = (gcskNODE_PTR) ( (gctUINT8_PTR) heap
- + + Heap->allocationSize
- + - gcmSIZEOF(gcskNODE)
- + );
- + node->bytes = 0;
- + node->next = gcvNULL;
- +
- + /* Create a free list. */
- + node = (gcskNODE_PTR) (heap + 1);
- + heap->freeList = node;
- +
- + /* Initialize the free list. */
- + node->bytes = heap->size - gcmSIZEOF(gcskNODE);
- + node->next = gcvNULL;
- +
- + /* No previous free. */
- + prevFree = gcvNULL;
- +
- +#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
- + /* Update profiling. */
- + Heap->heapCount += 1;
- + Heap->heapMemory += Heap->allocationSize;
- +
- + if (Heap->heapCount > Heap->heapCountMax)
- + {
- + Heap->heapCountMax = Heap->heapCount;
- + }
- + if (Heap->heapMemory > Heap->heapMemoryMax)
- + {
- + Heap->heapMemoryMax = Heap->heapMemory;
- + }
- +#endif
- +
- +UseNode:
- + /* Verify some stuff. */
- + gcmkASSERT(heap != gcvNULL);
- + gcmkASSERT(node != gcvNULL);
- + gcmkASSERT(node->bytes >= bytes);
- +
- + if (heap->prev != gcvNULL)
- + {
- + /* Unlink the heap from the linked list. */
- + heap->prev->next = heap->next;
- + if (heap->next != gcvNULL)
- + {
- + heap->next->prev = heap->prev;
- + }
- +
- + /* Move the heap to the front of the list. */
- + heap->next = Heap->heap;
- + heap->prev = gcvNULL;
- + Heap->heap = heap;
- + heap->next->prev = heap;
- + }
- +
- + /* Check if there is enough free space left after usage for another free
- + ** node. */
- + if (node->bytes - bytes >= gcmSIZEOF(gcskNODE))
- + {
- + /* Allocated used space from the back of the free list. */
- + used = (gcskNODE_PTR) ((gctUINT8_PTR) node + node->bytes - bytes);
- +
- + /* Adjust the number of free bytes. */
- + node->bytes -= bytes;
- + gcmkASSERT(node->bytes >= gcmSIZEOF(gcskNODE));
- + }
- + else
- + {
- + /* Remove this free list from the chain. */
- + if (prevFree == gcvNULL)
- + {
- + heap->freeList = node->next;
- + }
- + else
- + {
- + prevFree->next = node->next;
- + }
- +
- + /* Consume the entire free node. */
- + used = (gcskNODE_PTR) node;
- + bytes = node->bytes;
- + }
- +
- + /* Mark node as used. */
- + used->bytes = bytes;
- + used->next = gcdIN_USE;
- +#if gcmIS_DEBUG(gcdDEBUG_CODE)
- + used->timeStamp = ++Heap->timeStamp;
- +#endif
- +
- +#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
- + /* Update profile counters. */
- + Heap->allocCount += 1;
- + Heap->allocBytes += bytes;
- + Heap->allocBytesMax = gcmMAX(Heap->allocBytes, Heap->allocBytesMax);
- + Heap->allocBytesTotal += bytes;
- +#endif
- +
- + /* Release the mutex. */
- + gcmkVERIFY_OK(
- + gckOS_ReleaseMutex(Heap->os, Heap->mutex));
- +
- + /* Return pointer to memory. */
- + *Memory = used + 1;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + /* Release the mutex. */
- + gcmkVERIFY_OK(
- + gckOS_ReleaseMutex(Heap->os, Heap->mutex));
- + }
- +
- + if (memory != gcvNULL)
- + {
- + /* Free the heap memory. */
- + gckOS_FreeMemory(Heap->os, memory);
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckHEAP_Free
- +**
- +** Free allocated memory from the heap.
- +**
- +** INPUT:
- +**
- +** gckHEAP Heap
- +** Pointer to a gckHEAP object.
- +**
- +** IN gctPOINTER Memory
- +** Pointer to memory to free.
- +**
- +** OUTPUT:
- +**
- +** NOTHING.
- +*/
- +gceSTATUS
- +gckHEAP_Free(
- + IN gckHEAP Heap,
- + IN gctPOINTER Memory
- + )
- +{
- + gcskNODE_PTR node;
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Heap=0x%x Memory=0x%x", Heap, Memory);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
- + gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
- +
- + /* Acquire the mutex. */
- + gcmkONERROR(
- + gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
- +
- + /* Pointer to structure. */
- + node = (gcskNODE_PTR) Memory - 1;
- +
- + /* Mark the node as freed. */
- + node->next = gcvNULL;
- +
- +#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
- + /* Update profile counters. */
- + Heap->allocBytes -= node->bytes;
- +#endif
- +
- + /* Release the mutex. */
- + gcmkVERIFY_OK(
- + gckOS_ReleaseMutex(Heap->os, Heap->mutex));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +#if VIVANTE_PROFILER
- +gceSTATUS
- +gckHEAP_ProfileStart(
- + IN gckHEAP Heap
- + )
- +{
- + gcmkHEADER_ARG("Heap=0x%x", Heap);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
- +
- + /* Zero the counters. */
- + Heap->allocCount = 0;
- + Heap->allocBytes = 0;
- + Heap->allocBytesMax = 0;
- + Heap->allocBytesTotal = 0;
- + Heap->heapCount = 0;
- + Heap->heapCountMax = 0;
- + Heap->heapMemory = 0;
- + Heap->heapMemoryMax = 0;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckHEAP_ProfileEnd(
- + IN gckHEAP Heap,
- + IN gctCONST_STRING Title
- + )
- +{
- + gcmkHEADER_ARG("Heap=0x%x Title=0x%x", Heap, Title);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
- + gcmkVERIFY_ARGUMENT(Title != gcvNULL);
- +
- + gcmkPRINT("");
- + gcmkPRINT("=====[ HEAP - %s ]=====", Title);
- + gcmkPRINT("Number of allocations : %12u", Heap->allocCount);
- + gcmkPRINT("Number of bytes allocated : %12llu", Heap->allocBytes);
- + gcmkPRINT("Maximum allocation size : %12llu", Heap->allocBytesMax);
- + gcmkPRINT("Total number of bytes allocated : %12llu", Heap->allocBytesTotal);
- + gcmkPRINT("Number of heaps : %12u", Heap->heapCount);
- + gcmkPRINT("Heap memory in bytes : %12llu", Heap->heapMemory);
- + gcmkPRINT("Maximum number of heaps : %12u", Heap->heapCountMax);
- + gcmkPRINT("Maximum heap memory in bytes : %12llu", Heap->heapMemoryMax);
- + gcmkPRINT("==============================================");
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +#endif /* VIVANTE_PROFILER */
- +
- +/*******************************************************************************
- +***** Test Code ****************************************************************
- +*******************************************************************************/
- +
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_interrupt_vg.c linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_interrupt_vg.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_interrupt_vg.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_interrupt_vg.c 2015-03-08 14:27:37.637684501 -0500
- @@ -0,0 +1,877 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal_kernel_precomp.h"
- +
- +#if gcdENABLE_VG
- +
- +/******************************************************************************\
- +*********************** Support Functions and Definitions **********************
- +\******************************************************************************/
- +
- +/* Interruot statistics will be accumulated if not zero. */
- +#define gcmENABLE_INTERRUPT_STATISTICS 0
- +
- +#define _GC_OBJ_ZONE gcvZONE_INTERRUPT
- +
- +/* Object structure. */
- +struct _gckVGINTERRUPT
- +{
- + /* Object. */
- + gcsOBJECT object;
- +
- + /* gckVGKERNEL pointer. */
- + gckVGKERNEL kernel;
- +
- + /* gckOS pointer. */
- + gckOS os;
- +
- + /* Interrupt handlers. */
- + gctINTERRUPT_HANDLER handlers[32];
- +
- + /* Main interrupt handler thread. */
- + gctTHREAD handler;
- + gctBOOL terminate;
- +
- + /* Interrupt FIFO. */
- + gctSEMAPHORE fifoValid;
- + gctUINT32 fifo[256];
- + gctUINT fifoItems;
- + gctUINT8 head;
- + gctUINT8 tail;
- +
- + /* Interrupt statistics. */
- +#if gcmENABLE_INTERRUPT_STATISTICS
- + gctUINT maxFifoItems;
- + gctUINT fifoOverflow;
- + gctUINT maxSimultaneous;
- + gctUINT multipleCount;
- +#endif
- +};
- +
- +
- +/*******************************************************************************
- +**
- +** _ProcessInterrupt
- +**
- +** The interrupt processor.
- +**
- +** INPUT:
- +**
- +** ThreadParameter
- +** Pointer to the gckVGINTERRUPT object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +#if gcmENABLE_INTERRUPT_STATISTICS
- +static void
- +_ProcessInterrupt(
- + gckVGINTERRUPT Interrupt,
- + gctUINT_PTR TriggeredCount
- + )
- +#else
- +static void
- +_ProcessInterrupt(
- + gckVGINTERRUPT Interrupt
- + )
- +#endif
- +{
- + gceSTATUS status;
- + gctUINT32 triggered;
- + gctUINT i;
- +
- + /* Advance to the next entry. */
- + Interrupt->tail += 1;
- + Interrupt->fifoItems -= 1;
- +
- + /* Get the interrupt value. */
- + triggered = Interrupt->fifo[Interrupt->tail];
- + gcmkASSERT(triggered != 0);
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + "%s: triggered=0x%08X\n",
- + __FUNCTION__,
- + triggered
- + );
- +
- + /* Walk through all possible interrupts. */
- + for (i = 0; i < gcmSIZEOF(Interrupt->handlers); i += 1)
- + {
- + /* Test if interrupt happened. */
- + if ((triggered & 1) == 1)
- + {
- +#if gcmENABLE_INTERRUPT_STATISTICS
- + if (TriggeredCount != gcvNULL)
- + {
- + (* TriggeredCount) += 1;
- + }
- +#endif
- +
- + /* Make sure we have valid handler. */
- + if (Interrupt->handlers[i] == gcvNULL)
- + {
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s: Interrupt %d isn't registered.\n",
- + __FUNCTION__, i
- + );
- + }
- + else
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + "%s: interrupt=%d\n",
- + __FUNCTION__,
- + i
- + );
- +
- + /* Call the handler. */
- + status = Interrupt->handlers[i] (Interrupt->kernel);
- +
- + if (gcmkIS_ERROR(status))
- + {
- + /* Failed to signal the semaphore. */
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s: Error %d incrementing the semaphore #%d.\n",
- + __FUNCTION__, status, i
- + );
- + }
- + }
- + }
- +
- + /* Next interrupt. */
- + triggered >>= 1;
- +
- + /* No more interrupts to handle? */
- + if (triggered == 0)
- + {
- + break;
- + }
- + }
- +}
- +
- +
- +/*******************************************************************************
- +**
- +** _MainInterruptHandler
- +**
- +** The main interrupt thread serves the interrupt FIFO and calls registered
- +** handlers for the interrupts that occured. The handlers are called in the
- +** sequence interrupts occured with the exception when multiple interrupts
- +** occured at the same time. In that case the handler calls are "sorted" by
- +** the interrupt number therefore giving the interrupts with lower numbers
- +** higher priority.
- +**
- +** INPUT:
- +**
- +** ThreadParameter
- +** Pointer to the gckVGINTERRUPT object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +static gctTHREADFUNCRESULT gctTHREADFUNCTYPE
- +_MainInterruptHandler(
- + gctTHREADFUNCPARAMETER ThreadParameter
- + )
- +{
- + gceSTATUS status;
- + gckVGINTERRUPT interrupt;
- +
- +#if gcmENABLE_INTERRUPT_STATISTICS
- + gctUINT count;
- +#endif
- +
- + /* Cast the object. */
- + interrupt = (gckVGINTERRUPT) ThreadParameter;
- +
- + /* Enter the loop. */
- + while (gcvTRUE)
- + {
- + /* Wait for an interrupt. */
- + status = gckOS_DecrementSemaphore(interrupt->os, interrupt->fifoValid);
- +
- + /* Error? */
- + if (gcmkIS_ERROR(status))
- + {
- + break;
- + }
- +
- + /* System termination request? */
- + if (status == gcvSTATUS_TERMINATE)
- + {
- + break;
- + }
- +
- + /* Driver is shutting down? */
- + if (interrupt->terminate)
- + {
- + break;
- + }
- +
- +#if gcmENABLE_INTERRUPT_STATISTICS
- + /* Reset triggered count. */
- + count = 0;
- +
- + /* Process the interrupt. */
- + _ProcessInterrupt(interrupt, &count);
- +
- + /* Update conters. */
- + if (count > interrupt->maxSimultaneous)
- + {
- + interrupt->maxSimultaneous = count;
- + }
- +
- + if (count > 1)
- + {
- + interrupt->multipleCount += 1;
- + }
- +#else
- + /* Process the interrupt. */
- + _ProcessInterrupt(interrupt);
- +#endif
- + }
- +
- + return 0;
- +}
- +
- +
- +/*******************************************************************************
- +**
- +** _StartInterruptHandler / _StopInterruptHandler
- +**
- +** Main interrupt handler routine control.
- +**
- +** INPUT:
- +**
- +** ThreadParameter
- +** Pointer to the gckVGINTERRUPT object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +static gceSTATUS
- +_StartInterruptHandler(
- + gckVGINTERRUPT Interrupt
- + )
- +{
- + gceSTATUS status, last;
- +
- + do
- + {
- + /* Objects must not be already created. */
- + gcmkASSERT(Interrupt->fifoValid == gcvNULL);
- + gcmkASSERT(Interrupt->handler == gcvNULL);
- +
- + /* Reset the termination request. */
- + Interrupt->terminate = gcvFALSE;
- +
- +#if !gcdENABLE_INFINITE_SPEED_HW
- + /* Construct the fifo semaphore. */
- + gcmkERR_BREAK(gckOS_CreateSemaphoreVG(
- + Interrupt->os, &Interrupt->fifoValid
- + ));
- +
- + /* Start the interrupt handler thread. */
- + gcmkERR_BREAK(gckOS_StartThread(
- + Interrupt->os,
- + _MainInterruptHandler,
- + Interrupt,
- + &Interrupt->handler
- + ));
- +#endif
- +
- + /* Success. */
- + return gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + /* Roll back. */
- + if (Interrupt->fifoValid != gcvNULL)
- + {
- + gcmkCHECK_STATUS(gckOS_DestroySemaphore(
- + Interrupt->os, Interrupt->fifoValid
- + ));
- +
- + Interrupt->fifoValid = gcvNULL;
- + }
- +
- + /* Return the status. */
- + return status;
- +}
- +
- +static gceSTATUS
- +_StopInterruptHandler(
- + gckVGINTERRUPT Interrupt
- + )
- +{
- + gceSTATUS status;
- +
- + do
- + {
- + /* Does the thread exist? */
- + if (Interrupt->handler == gcvNULL)
- + {
- + /* The semaphore must be NULL as well. */
- + gcmkASSERT(Interrupt->fifoValid == gcvNULL);
- +
- + /* Success. */
- + status = gcvSTATUS_OK;
- + break;
- + }
- +
- + /* The semaphore must exist as well. */
- + gcmkASSERT(Interrupt->fifoValid != gcvNULL);
- +
- + /* Set the termination request. */
- + Interrupt->terminate = gcvTRUE;
- +
- + /* Unlock the thread. */
- + gcmkERR_BREAK(gckOS_IncrementSemaphore(
- + Interrupt->os, Interrupt->fifoValid
- + ));
- +
- + /* Wait until the thread quits. */
- + gcmkERR_BREAK(gckOS_StopThread(
- + Interrupt->os,
- + Interrupt->handler
- + ));
- +
- + /* Destroy the semaphore. */
- + gcmkERR_BREAK(gckOS_DestroySemaphore(
- + Interrupt->os, Interrupt->fifoValid
- + ));
- +
- + /* Reset handles. */
- + Interrupt->handler = gcvNULL;
- + Interrupt->fifoValid = gcvNULL;
- + }
- + while (gcvFALSE);
- +
- + /* Return the status. */
- + return status;
- +}
- +
- +
- +/******************************************************************************\
- +***************************** Interrupt Object API *****************************
- +\******************************************************************************/
- +
- +/*******************************************************************************
- +**
- +** gckVGINTERRUPT_Construct
- +**
- +** Construct an interrupt object.
- +**
- +** INPUT:
- +**
- +** Kernel
- +** Pointer to the gckVGKERNEL object.
- +**
- +** OUTPUT:
- +**
- +** Interrupt
- +** Pointer to the new gckVGINTERRUPT object.
- +*/
- +
- +gceSTATUS
- +gckVGINTERRUPT_Construct(
- + IN gckVGKERNEL Kernel,
- + OUT gckVGINTERRUPT * Interrupt
- + )
- +{
- + gceSTATUS status;
- + gckVGINTERRUPT interrupt = gcvNULL;
- +
- + gcmkHEADER_ARG("Kernel=0x%x Interrupt=0x%x", Kernel, Interrupt);
- +
- + /* Verify argeuments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(Interrupt != gcvNULL);
- +
- + do
- + {
- + /* Allocate the gckVGINTERRUPT structure. */
- + gcmkERR_BREAK(gckOS_Allocate(
- + Kernel->os,
- + gcmSIZEOF(struct _gckVGINTERRUPT),
- + (gctPOINTER *) &interrupt
- + ));
- +
- + /* Reset the object data. */
- + gcmkVERIFY_OK(gckOS_ZeroMemory(
- + interrupt, gcmSIZEOF(struct _gckVGINTERRUPT)
- + ));
- +
- + /* Initialize the object. */
- + interrupt->object.type = gcvOBJ_INTERRUPT;
- +
- + /* Initialize the object pointers. */
- + interrupt->kernel = Kernel;
- + interrupt->os = Kernel->os;
- +
- + /* Initialize the current FIFO position. */
- + interrupt->head = (gctUINT8)~0;
- + interrupt->tail = (gctUINT8)~0;
- +
- + /* Start the thread. */
- + gcmkERR_BREAK(_StartInterruptHandler(interrupt));
- +
- + /* Return interrupt object. */
- + *Interrupt = interrupt;
- +
- + gcmkFOOTER_ARG("*Interrup=0x%x", *Interrupt);
- + /* Success. */
- + return gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + /* Roll back. */
- + if (interrupt != gcvNULL)
- + {
- + /* Free the gckVGINTERRUPT structure. */
- + gcmkVERIFY_OK(gckOS_Free(interrupt->os, interrupt));
- + }
- +
- + gcmkFOOTER();
- +
- + /* Return the status. */
- + return status;
- +}
- +
- +
- +/*******************************************************************************
- +**
- +** gckVGINTERRUPT_Destroy
- +**
- +** Destroy an interrupt object.
- +**
- +** INPUT:
- +**
- +** Interrupt
- +** Pointer to the gckVGINTERRUPT object to destroy.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +gceSTATUS
- +gckVGINTERRUPT_Destroy(
- + IN gckVGINTERRUPT Interrupt
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
- +
- + do
- + {
- + /* Stop the interrupt thread. */
- + gcmkERR_BREAK(_StopInterruptHandler(Interrupt));
- +
- + /* Mark the object as unknown. */
- + Interrupt->object.type = gcvOBJ_UNKNOWN;
- +
- + /* Free the gckVGINTERRUPT structure. */
- + gcmkERR_BREAK(gckOS_Free(Interrupt->os, Interrupt));
- + }
- + while (gcvFALSE);
- +
- + gcmkFOOTER();
- +
- + /* Return the status. */
- + return status;
- +}
- +
- +
- +/*******************************************************************************
- +**
- +** gckVGINTERRUPT_DumpState
- +**
- +** Print the current state of the interrupt manager.
- +**
- +** INPUT:
- +**
- +** Interrupt
- +** Pointer to a gckVGINTERRUPT object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +#if gcvDEBUG
- +gceSTATUS
- +gckVGINTERRUPT_DumpState(
- + IN gckVGINTERRUPT Interrupt
- + )
- +{
- + gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
- +
- + /* Print the header. */
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + "%s: INTERRUPT OBJECT STATUS\n",
- + __FUNCTION__
- + );
- +
- + /* Print statistics. */
- +#if gcmENABLE_INTERRUPT_STATISTICS
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + " Maximum number of FIFO items accumulated at a single time: %d\n",
- + Interrupt->maxFifoItems
- + );
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + " Interrupt FIFO overflow happened times: %d\n",
- + Interrupt->fifoOverflow
- + );
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + " Maximum number of interrupts simultaneously generated: %d\n",
- + Interrupt->maxSimultaneous
- + );
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + " Number of times when there were multiple interrupts generated: %d\n",
- + Interrupt->multipleCount
- + );
- +#endif
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + " The current number of entries in the FIFO: %d\n",
- + Interrupt->fifoItems
- + );
- +
- + /* Print the FIFO contents. */
- + if (Interrupt->fifoItems != 0)
- + {
- + gctUINT8 index;
- + gctUINT8 last;
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + " FIFO current contents:\n"
- + );
- +
- + /* Get the current pointers. */
- + index = Interrupt->tail;
- + last = Interrupt->head;
- +
- + while (index != last)
- + {
- + /* Advance to the next entry. */
- + index += 1;
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
- + " %d: 0x%08X\n",
- + index, Interrupt->fifo[index]
- + );
- + }
- + }
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +#endif
- +
- +
- +/*******************************************************************************
- +**
- +** gckVGINTERRUPT_Enable
- +**
- +** Enable the specified interrupt.
- +**
- +** INPUT:
- +**
- +** Interrupt
- +** Pointer to a gckVGINTERRUPT object.
- +**
- +** Id
- +** Pointer to the variable that holds the interrupt number to be
- +** registered in range 0..31.
- +** If the value is less then 0, gckVGINTERRUPT_Enable will attempt
- +** to find an unused interrupt. If such interrupt is found, the number
- +** will be assigned to the variable if the functuion call succeedes.
- +**
- +** Handler
- +** Pointer to the handler to register for the interrupt.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +gceSTATUS
- +gckVGINTERRUPT_Enable(
- + IN gckVGINTERRUPT Interrupt,
- + IN OUT gctINT32_PTR Id,
- + IN gctINTERRUPT_HANDLER Handler
- + )
- +{
- + gceSTATUS status;
- + gctINT32 i;
- +
- + gcmkHEADER_ARG("Interrupt=0x%x Id=0x%x Handler=0x%x", Interrupt, Id, Handler);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
- + gcmkVERIFY_ARGUMENT(Id != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Handler != gcvNULL);
- +
- + do
- + {
- + /* See if we need to allocate an ID. */
- + if (*Id < 0)
- + {
- + /* Find the first unused interrupt handler. */
- + for (i = 0; i < gcmCOUNTOF(Interrupt->handlers); ++i)
- + {
- + if (Interrupt->handlers[i] == gcvNULL)
- + {
- + break;
- + }
- + }
- +
- + /* No unused innterrupts? */
- + if (i == gcmCOUNTOF(Interrupt->handlers))
- + {
- + status = gcvSTATUS_OUT_OF_RESOURCES;
- + break;
- + }
- +
- + /* Update the interrupt ID. */
- + *Id = i;
- + }
- +
- + /* Make sure the ID is in range. */
- + else if (*Id >= gcmCOUNTOF(Interrupt->handlers))
- + {
- + status = gcvSTATUS_INVALID_ARGUMENT;
- + break;
- + }
- +
- + /* Set interrupt handler. */
- + Interrupt->handlers[*Id] = Handler;
- +
- + /* Success. */
- + status = gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + gcmkFOOTER();
- + /* Return the status. */
- + return status;
- +}
- +
- +
- +/*******************************************************************************
- +**
- +** gckVGINTERRUPT_Disable
- +**
- +** Disable the specified interrupt.
- +**
- +** INPUT:
- +**
- +** Interrupt
- +** Pointer to a gckVGINTERRUPT object.
- +**
- +** Id
- +** Interrupt number to be disabled in range 0..31.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +gceSTATUS
- +gckVGINTERRUPT_Disable(
- + IN gckVGINTERRUPT Interrupt,
- + IN gctINT32 Id
- + )
- +{
- + gcmkHEADER_ARG("Interrupt=0x%x Id=0x%x", Interrupt, Id);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
- + gcmkVERIFY_ARGUMENT((Id >= 0) && (Id < gcmCOUNTOF(Interrupt->handlers)));
- +
- + /* Reset interrupt handler. */
- + Interrupt->handlers[Id] = gcvNULL;
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +
- +/*******************************************************************************
- +**
- +** gckVGINTERRUPT_Enque
- +**
- +** Read the interrupt status register and put the value in the interrupt FIFO.
- +**
- +** INPUT:
- +**
- +** Interrupt
- +** Pointer to a gckVGINTERRUPT object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +
- +#ifndef __QNXNTO__
- +gceSTATUS
- +gckVGINTERRUPT_Enque(
- + IN gckVGINTERRUPT Interrupt
- + )
- +#else
- +gceSTATUS
- +gckVGINTERRUPT_Enque(
- + IN gckVGINTERRUPT Interrupt,
- + OUT gckOS *Os,
- + OUT gctSEMAPHORE *Semaphore
- + )
- +#endif
- +{
- + gceSTATUS status;
- + gctUINT32 triggered;
- +
- + gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
- +
- +#ifdef __QNXNTO__
- + *Os = gcvNULL;
- + *Semaphore = gcvNULL;
- +#endif
- +
- + do
- + {
- + /* Read interrupt status register. */
- + gcmkERR_BREAK(gckVGHARDWARE_ReadInterrupt(
- + Interrupt->kernel->hardware, &triggered
- + ));
- +
- + /* Mask out TS overflow interrupt */
- + triggered &= 0xfffffffe;
- +
- + /* No interrupts to process? */
- + if (triggered == 0)
- + {
- + status = gcvSTATUS_NOT_OUR_INTERRUPT;
- + break;
- + }
- +
- + /* FIFO overflow? */
- + if (Interrupt->fifoItems == gcmCOUNTOF(Interrupt->fifo))
- + {
- +#if gcmENABLE_INTERRUPT_STATISTICS
- + Interrupt->fifoOverflow += 1;
- +#endif
- +
- + /* OR the interrupt with the last value in the FIFO. */
- + Interrupt->fifo[Interrupt->head] |= triggered;
- +
- + /* Success (kind of). */
- + status = gcvSTATUS_OK;
- + }
- + else
- + {
- + /* Advance to the next entry. */
- + Interrupt->head += 1;
- + Interrupt->fifoItems += 1;
- +
- +#if gcmENABLE_INTERRUPT_STATISTICS
- + if (Interrupt->fifoItems > Interrupt->maxFifoItems)
- + {
- + Interrupt->maxFifoItems = Interrupt->fifoItems;
- + }
- +#endif
- +
- + /* Set the new value. */
- + Interrupt->fifo[Interrupt->head] = triggered;
- +
- +#ifndef __QNXNTO__
- + /* Increment the FIFO semaphore. */
- + gcmkERR_BREAK(gckOS_IncrementSemaphore(
- + Interrupt->os, Interrupt->fifoValid
- + ));
- +#else
- + *Os = Interrupt->os;
- + *Semaphore = Interrupt->fifoValid;
- +#endif
- +
- + /* Windows kills our threads prematurely when the application
- + exists. Verify here that the thread is still alive. */
- + status = gckOS_VerifyThread(Interrupt->os, Interrupt->handler);
- +
- + /* Has the thread been prematurely terminated? */
- + if (status != gcvSTATUS_OK)
- + {
- + /* Process all accumulated interrupts. */
- + while (Interrupt->head != Interrupt->tail)
- + {
- +#if gcmENABLE_INTERRUPT_STATISTICS
- + /* Process the interrupt. */
- + _ProcessInterrupt(Interrupt, gcvNULL);
- +#else
- + /* Process the interrupt. */
- + _ProcessInterrupt(Interrupt);
- +#endif
- + }
- +
- + /* Set success. */
- + status = gcvSTATUS_OK;
- + }
- + }
- + }
- + while (gcvFALSE);
- +
- + gcmkFOOTER();
- + /* Return status. */
- + return status;
- +}
- +
- +#endif /* gcdENABLE_VG */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c 2015-03-08 14:27:37.637684501 -0500
- @@ -0,0 +1,1982 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal_kernel_precomp.h"
- +
- +#define _GC_OBJ_ZONE gcvZONE_MMU
- +
- +typedef enum _gceMMU_TYPE
- +{
- + gcvMMU_USED = (0 << 4),
- + gcvMMU_SINGLE = (1 << 4),
- + gcvMMU_FREE = (2 << 4),
- +}
- +gceMMU_TYPE;
- +
- +#define gcmENTRY_TYPE(x) (x & 0xF0)
- +
- +#define gcdMMU_TABLE_DUMP 0
- +
- +#define gcdUSE_MMU_EXCEPTION 0
- +
- +/*
- + gcdMMU_CLEAR_VALUE
- +
- + The clear value for the entry of the old MMU.
- +*/
- +#ifndef gcdMMU_CLEAR_VALUE
- +# define gcdMMU_CLEAR_VALUE 0x00000ABC
- +#endif
- +
- +/* VIV: Start GPU address for gcvSURF_VERTEX. */
- +#define gcdVERTEX_START (128 << 10)
- +
- +typedef struct _gcsMMU_STLB *gcsMMU_STLB_PTR;
- +
- +typedef struct _gcsMMU_STLB
- +{
- + gctPHYS_ADDR physical;
- + gctUINT32_PTR logical;
- + gctSIZE_T size;
- + gctUINT32 physBase;
- + gctSIZE_T pageCount;
- + gctUINT32 mtlbIndex;
- + gctUINT32 mtlbEntryNum;
- + gcsMMU_STLB_PTR next;
- +} gcsMMU_STLB;
- +
- +#if gcdSHARED_PAGETABLE
- +typedef struct _gcsSharedPageTable * gcsSharedPageTable_PTR;
- +typedef struct _gcsSharedPageTable
- +{
- + /* Shared gckMMU object. */
- + gckMMU mmu;
- +
- + /* Hardwares which use this shared pagetable. */
- + gckHARDWARE hardwares[gcdMAX_GPU_COUNT];
- +
- + /* Number of cores use this shared pagetable. */
- + gctUINT32 reference;
- +}
- +gcsSharedPageTable;
- +
- +static gcsSharedPageTable_PTR sharedPageTable = gcvNULL;
- +#endif
- +
- +#if gcdMIRROR_PAGETABLE
- +typedef struct _gcsMirrorPageTable * gcsMirrorPageTable_PTR;
- +typedef struct _gcsMirrorPageTable
- +{
- + /* gckMMU objects. */
- + gckMMU mmus[gcdMAX_GPU_COUNT];
- +
- + /* Hardwares which use this shared pagetable. */
- + gckHARDWARE hardwares[gcdMAX_GPU_COUNT];
- +
- + /* Number of cores use this shared pagetable. */
- + gctUINT32 reference;
- +}
- +gcsMirrorPageTable;
- +
- +static gcsMirrorPageTable_PTR mirrorPageTable = gcvNULL;
- +static gctPOINTER mirrorPageTableMutex = gcvNULL;
- +#endif
- +
- +typedef struct _gcsDynamicSpaceNode * gcsDynamicSpaceNode_PTR;
- +typedef struct _gcsDynamicSpaceNode
- +{
- + gctUINT32 start;
- + gctINT32 entries;
- +}
- +gcsDynamicSpaceNode;
- +
- +static void
- +_WritePageEntry(
- + IN gctUINT32_PTR PageEntry,
- + IN gctUINT32 EntryValue
- + )
- +{
- + static gctUINT16 data = 0xff00;
- +
- + if (*(gctUINT8 *)&data == 0xff)
- + {
- + *PageEntry = gcmSWAB32(EntryValue);
- + }
- + else
- + {
- + *PageEntry = EntryValue;
- + }
- +}
- +
- +static gctUINT32
- +_ReadPageEntry(
- + IN gctUINT32_PTR PageEntry
- + )
- +{
- + static gctUINT16 data = 0xff00;
- + gctUINT32 entryValue;
- +
- + if (*(gctUINT8 *)&data == 0xff)
- + {
- + entryValue = *PageEntry;
- + return gcmSWAB32(entryValue);
- + }
- + else
- + {
- + return *PageEntry;
- + }
- +}
- +
- +static gceSTATUS
- +_FillPageTable(
- + IN gctUINT32_PTR PageTable,
- + IN gctUINT32 PageCount,
- + IN gctUINT32 EntryValue
- +)
- +{
- + gctUINT i;
- +
- + for (i = 0; i < PageCount; i++)
- + {
- + _WritePageEntry(PageTable + i, EntryValue);
- + }
- +
- + return gcvSTATUS_OK;
- +}
- +
- +static gceSTATUS
- +_Link(
- + IN gckMMU Mmu,
- + IN gctUINT32 Index,
- + IN gctUINT32 Next
- + )
- +{
- + if (Index >= Mmu->pageTableEntries)
- + {
- + /* Just move heap pointer. */
- + Mmu->heapList = Next;
- + }
- + else
- + {
- + /* Address page table. */
- + gctUINT32_PTR pageTable = Mmu->pageTableLogical;
- +
- + /* Dispatch on node type. */
- + switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[Index])))
- + {
- + case gcvMMU_SINGLE:
- + /* Set single index. */
- + _WritePageEntry(&pageTable[Index], (Next << 8) | gcvMMU_SINGLE);
- + break;
- +
- + case gcvMMU_FREE:
- + /* Set index. */
- + _WritePageEntry(&pageTable[Index + 1], Next);
- + break;
- +
- + default:
- + gcmkFATAL("MMU table correcupted at index %u!", Index);
- + return gcvSTATUS_HEAP_CORRUPTED;
- + }
- + }
- +
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +static gceSTATUS
- +_AddFree(
- + IN gckMMU Mmu,
- + IN gctUINT32 Index,
- + IN gctUINT32 Node,
- + IN gctUINT32 Count
- + )
- +{
- + gctUINT32_PTR pageTable = Mmu->pageTableLogical;
- +
- + if (Count == 1)
- + {
- + /* Initialize a single page node. */
- + _WritePageEntry(pageTable + Node, (~((1U<<8)-1)) | gcvMMU_SINGLE);
- + }
- + else
- + {
- + /* Initialize the node. */
- + _WritePageEntry(pageTable + Node + 0, (Count << 8) | gcvMMU_FREE);
- + _WritePageEntry(pageTable + Node + 1, ~0U);
- + }
- +
- + /* Append the node. */
- + return _Link(Mmu, Index, Node);
- +}
- +
- +static gceSTATUS
- +_Collect(
- + IN gckMMU Mmu
- + )
- +{
- + gctUINT32_PTR pageTable = Mmu->pageTableLogical;
- + gceSTATUS status;
- + gctUINT32 i, previous, start = 0, count = 0;
- +
- + previous = Mmu->heapList = ~0U;
- + Mmu->freeNodes = gcvFALSE;
- +
- + /* Walk the entire page table. */
- + for (i = 0; i < Mmu->pageTableEntries; ++i)
- + {
- + /* Dispatch based on type of page. */
- + switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[i])))
- + {
- + case gcvMMU_USED:
- + /* Used page, so close any open node. */
- + if (count > 0)
- + {
- + /* Add the node. */
- + gcmkONERROR(_AddFree(Mmu, previous, start, count));
- +
- + /* Reset the node. */
- + previous = start;
- + count = 0;
- + }
- + break;
- +
- + case gcvMMU_SINGLE:
- + /* Single free node. */
- + if (count++ == 0)
- + {
- + /* Start a new node. */
- + start = i;
- + }
- + break;
- +
- + case gcvMMU_FREE:
- + /* A free node. */
- + if (count == 0)
- + {
- + /* Start a new node. */
- + start = i;
- + }
- +
- + /* Advance the count. */
- + count += _ReadPageEntry(&pageTable[i]) >> 8;
- +
- + /* Advance the index into the page table. */
- + i += (_ReadPageEntry(&pageTable[i]) >> 8) - 1;
- + break;
- +
- + default:
- + gcmkFATAL("MMU page table correcupted at index %u!", i);
- + return gcvSTATUS_HEAP_CORRUPTED;
- + }
- + }
- +
- + /* See if we have an open node left. */
- + if (count > 0)
- + {
- + /* Add the node to the list. */
- + gcmkONERROR(_AddFree(Mmu, previous, start, count));
- + }
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_MMU,
- + "Performed a garbage collection of the MMU heap.");
- +
- + /* Success. */
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the staus. */
- + return status;
- +}
- +
- +static gctUINT32
- +_SetPage(gctUINT32 PageAddress)
- +{
- + return PageAddress
- + /* writable */
- + | (1 << 2)
- + /* Ignore exception */
- + | (0 << 1)
- + /* Present */
- + | (1 << 0);
- +}
- +
- +static gceSTATUS
- +_FillFlatMapping(
- + IN gckMMU Mmu,
- + IN gctUINT32 PhysBase,
- + OUT gctSIZE_T Size
- + )
- +{
- + gceSTATUS status;
- + gctBOOL mutex = gcvFALSE;
- + gcsMMU_STLB_PTR head = gcvNULL, pre = gcvNULL;
- + gctUINT32 start = PhysBase & (~gcdMMU_PAGE_64K_MASK);
- + gctUINT32 end = (PhysBase + Size - 1) & (~gcdMMU_PAGE_64K_MASK);
- + gctUINT32 mStart = start >> gcdMMU_MTLB_SHIFT;
- + gctUINT32 mEnd = end >> gcdMMU_MTLB_SHIFT;
- + gctUINT32 sStart = (start & gcdMMU_STLB_64K_MASK) >> gcdMMU_STLB_64K_SHIFT;
- + gctUINT32 sEnd = (end & gcdMMU_STLB_64K_MASK) >> gcdMMU_STLB_64K_SHIFT;
- +
- + /* Grab the mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
- + mutex = gcvTRUE;
- +
- + while (mStart <= mEnd)
- + {
- + gcmkASSERT(mStart < gcdMMU_MTLB_ENTRY_NUM);
- + if (*(Mmu->mtlbLogical + mStart) == 0)
- + {
- + gcsMMU_STLB_PTR stlb;
- + gctPOINTER pointer = gcvNULL;
- + gctUINT32 last = (mStart == mEnd) ? sEnd : (gcdMMU_STLB_64K_ENTRY_NUM - 1);
- +
- + gcmkONERROR(gckOS_Allocate(Mmu->os, sizeof(struct _gcsMMU_STLB), &pointer));
- + stlb = pointer;
- +
- + stlb->mtlbEntryNum = 0;
- + stlb->next = gcvNULL;
- + stlb->physical = gcvNULL;
- + stlb->logical = gcvNULL;
- + stlb->size = gcdMMU_STLB_64K_SIZE;
- + stlb->pageCount = 0;
- +
- + if (pre == gcvNULL)
- + {
- + pre = head = stlb;
- + }
- + else
- + {
- + gcmkASSERT(pre->next == gcvNULL);
- + pre->next = stlb;
- + pre = stlb;
- + }
- +
- + gcmkONERROR(
- + gckOS_AllocateContiguous(Mmu->os,
- + gcvFALSE,
- + &stlb->size,
- + &stlb->physical,
- + (gctPOINTER)&stlb->logical));
- +
- + gcmkONERROR(gckOS_ZeroMemory(stlb->logical, stlb->size));
- +
- + gcmkONERROR(gckOS_GetPhysicalAddress(
- + Mmu->os,
- + stlb->logical,
- + &stlb->physBase));
- +
- + if (stlb->physBase & (gcdMMU_STLB_64K_SIZE - 1))
- + {
- + gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
- + }
- +
- + _WritePageEntry(Mmu->mtlbLogical + mStart,
- + stlb->physBase
- + /* 64KB page size */
- + | (1 << 2)
- + /* Ignore exception */
- + | (0 << 1)
- + /* Present */
- + | (1 << 0)
- + );
- +#if gcdMMU_TABLE_DUMP
- + gckOS_Print("%s(%d): insert MTLB[%d]: %08x\n",
- + __FUNCTION__, __LINE__,
- + mStart,
- + _ReadPageEntry(Mmu->mtlbLogical + mStart));
- +#endif
- +
- + stlb->mtlbIndex = mStart;
- + stlb->mtlbEntryNum = 1;
- +#if gcdMMU_TABLE_DUMP
- + gckOS_Print("%s(%d): STLB: logical:%08x -> physical:%08x\n",
- + __FUNCTION__, __LINE__,
- + stlb->logical,
- + stlb->physBase);
- +#endif
- +
- + while (sStart <= last)
- + {
- + gcmkASSERT(!(start & gcdMMU_PAGE_64K_MASK));
- + _WritePageEntry(stlb->logical + sStart, _SetPage(start));
- +#if gcdMMU_TABLE_DUMP
- + gckOS_Print("%s(%d): insert STLB[%d]: %08x\n",
- + __FUNCTION__, __LINE__,
- + sStart,
- + _ReadPageEntry(stlb->logical + sStart));
- +#endif
- + /* next page. */
- + start += gcdMMU_PAGE_64K_SIZE;
- + sStart++;
- + stlb->pageCount++;
- + }
- +
- + sStart = 0;
- + ++mStart;
- + }
- + else
- + {
- + gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
- + }
- + }
- +
- + /* Insert the stlb into staticSTLB. */
- + if (Mmu->staticSTLB == gcvNULL)
- + {
- + Mmu->staticSTLB = head;
- + }
- + else
- + {
- + gcmkASSERT(pre == gcvNULL);
- + gcmkASSERT(pre->next == gcvNULL);
- + pre->next = Mmu->staticSTLB;
- + Mmu->staticSTLB = head;
- + }
- +
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
- +
- + return gcvSTATUS_OK;
- +
- +OnError:
- +
- + /* Roll back. */
- + while (head != gcvNULL)
- + {
- + pre = head;
- + head = head->next;
- +
- + if (pre->physical != gcvNULL)
- + {
- + gcmkVERIFY_OK(
- + gckOS_FreeContiguous(Mmu->os,
- + pre->physical,
- + pre->logical,
- + pre->size));
- + }
- +
- + if (pre->mtlbEntryNum != 0)
- + {
- + gcmkASSERT(pre->mtlbEntryNum == 1);
- + _WritePageEntry(Mmu->mtlbLogical + pre->mtlbIndex, 0);
- + }
- +
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, pre));
- + }
- +
- + if (mutex)
- + {
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
- + }
- +
- + return status;
- +}
- +
- +static gceSTATUS
- +_FindDynamicSpace(
- + IN gckMMU Mmu,
- + OUT gcsDynamicSpaceNode_PTR *Array,
- + OUT gctINT * Size
- + )
- +{
- + gceSTATUS status = gcvSTATUS_OK;
- + gctPOINTER pointer = gcvNULL;
- + gcsDynamicSpaceNode_PTR array = gcvNULL;
- + gctINT size = 0;
- + gctINT i = 0, nodeStart = -1, nodeEntries = 0;
- +
- + /* Allocate memory for the array. */
- + gcmkONERROR(gckOS_Allocate(Mmu->os,
- + gcmSIZEOF(*array) * (gcdMMU_MTLB_ENTRY_NUM / 2),
- + &pointer));
- +
- + array = (gcsDynamicSpaceNode_PTR)pointer;
- +
- + /* Loop all the entries. */
- + while (i < gcdMMU_MTLB_ENTRY_NUM)
- + {
- + if (!Mmu->mtlbLogical[i])
- + {
- + if (nodeStart < 0)
- + {
- + /* This is the first entry of the dynamic space. */
- + nodeStart = i;
- + nodeEntries = 1;
- + }
- + else
- + {
- + /* Other entries of the dynamic space. */
- + nodeEntries++;
- + }
- + }
- + else if (nodeStart >= 0)
- + {
- + /* Save the previous node. */
- + array[size].start = nodeStart;
- + array[size].entries = nodeEntries;
- + size++;
- +
- + /* Reset the start. */
- + nodeStart = -1;
- + nodeEntries = 0;
- + }
- +
- + i++;
- + }
- +
- + /* Save the previous node. */
- + if (nodeStart >= 0)
- + {
- + array[size].start = nodeStart;
- + array[size].entries = nodeEntries;
- + size++;
- + }
- +
- +#if gcdMMU_TABLE_DUMP
- + for (i = 0; i < size; i++)
- + {
- + gckOS_Print("%s(%d): [%d]: start=%d, entries=%d.\n",
- + __FUNCTION__, __LINE__,
- + i,
- + array[i].start,
- + array[i].entries);
- + }
- +#endif
- +
- + *Array = array;
- + *Size = size;
- +
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (pointer != gcvNULL)
- + {
- + gckOS_Free(Mmu->os, pointer);
- + }
- +
- + return status;
- +}
- +
- +static gceSTATUS
- +_SetupDynamicSpace(
- + IN gckMMU Mmu
- + )
- +{
- + gceSTATUS status;
- + gcsDynamicSpaceNode_PTR nodeArray = gcvNULL;
- + gctINT i, nodeArraySize = 0;
- + gctUINT32 physical;
- + gctINT numEntries = 0;
- + gctUINT32_PTR pageTable;
- + gctBOOL acquired = gcvFALSE;
- +
- + /* Find all the dynamic address space. */
- + gcmkONERROR(_FindDynamicSpace(Mmu, &nodeArray, &nodeArraySize));
- +
- + /* TODO: We only use the largest one for now. */
- + for (i = 0; i < nodeArraySize; i++)
- + {
- + if (nodeArray[i].entries > numEntries)
- + {
- + Mmu->dynamicMappingStart = nodeArray[i].start;
- + numEntries = nodeArray[i].entries;
- + }
- + }
- +
- + gckOS_Free(Mmu->os, (gctPOINTER)nodeArray);
- +
- + Mmu->pageTableSize = numEntries * 4096;
- +
- + Mmu->pageTableEntries = Mmu->pageTableSize / gcmSIZEOF(gctUINT32);
- +
- + /* Construct Slave TLB. */
- + gcmkONERROR(gckOS_AllocateContiguous(Mmu->os,
- + gcvFALSE,
- + &Mmu->pageTableSize,
- + &Mmu->pageTablePhysical,
- + (gctPOINTER)&Mmu->pageTableLogical));
- +
- +#if gcdUSE_MMU_EXCEPTION
- + gcmkONERROR(_FillPageTable(Mmu->pageTableLogical,
- + Mmu->pageTableEntries,
- + /* Enable exception */
- + 1 << 1));
- +#else
- + /* Invalidate all entries. */
- + gcmkONERROR(gckOS_ZeroMemory(Mmu->pageTableLogical,
- + Mmu->pageTableSize));
- +#endif
- +
- + /* Initilization. */
- + pageTable = Mmu->pageTableLogical;
- + _WritePageEntry(pageTable, (Mmu->pageTableEntries << 8) | gcvMMU_FREE);
- + _WritePageEntry(pageTable + 1, ~0U);
- + Mmu->heapList = 0;
- + Mmu->freeNodes = gcvFALSE;
- +
- + gcmkONERROR(gckOS_GetPhysicalAddress(Mmu->os,
- + Mmu->pageTableLogical,
- + &physical));
- +
- + /* Grab the mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + /* Map to Master TLB. */
- + for (i = (gctINT)Mmu->dynamicMappingStart;
- + i < (gctINT)Mmu->dynamicMappingStart + numEntries;
- + i++)
- + {
- + _WritePageEntry(Mmu->mtlbLogical + i,
- + physical
- + /* 4KB page size */
- + | (0 << 2)
- + /* Ignore exception */
- + | (0 << 1)
- + /* Present */
- + | (1 << 0)
- + );
- +#if gcdMMU_TABLE_DUMP
- + gckOS_Print("%s(%d): insert MTLB[%d]: %08x\n",
- + __FUNCTION__, __LINE__,
- + i,
- + _ReadPageEntry(Mmu->mtlbLogical + i));
- +#endif
- + physical += gcdMMU_STLB_4K_SIZE;
- + }
- +
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
- +
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (Mmu->pageTableLogical)
- + {
- + /* Free the page table. */
- + gcmkVERIFY_OK(
- + gckOS_FreeContiguous(Mmu->os,
- + Mmu->pageTablePhysical,
- + (gctPOINTER) Mmu->pageTableLogical,
- + Mmu->pageTableSize));
- + }
- +
- + if (acquired)
- + {
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
- + }
- +
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** _Construct
- +**
- +** Construct a new gckMMU object.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gctSIZE_T MmuSize
- +** Number of bytes for the page table.
- +**
- +** OUTPUT:
- +**
- +** gckMMU * Mmu
- +** Pointer to a variable that receives the gckMMU object pointer.
- +*/
- +gceSTATUS
- +_Construct(
- + IN gckKERNEL Kernel,
- + IN gctSIZE_T MmuSize,
- + OUT gckMMU * Mmu
- + )
- +{
- + gckOS os;
- + gckHARDWARE hardware;
- + gceSTATUS status;
- + gckMMU mmu = gcvNULL;
- + gctUINT32_PTR pageTable;
- + gctPOINTER pointer = gcvNULL;
- +
- + gcmkHEADER_ARG("Kernel=0x%x MmuSize=%lu", Kernel, MmuSize);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(MmuSize > 0);
- + gcmkVERIFY_ARGUMENT(Mmu != gcvNULL);
- +
- + /* Extract the gckOS object pointer. */
- + os = Kernel->os;
- + gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
- +
- + /* Extract the gckHARDWARE object pointer. */
- + hardware = Kernel->hardware;
- + gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
- +
- + /* Allocate memory for the gckMMU object. */
- + gcmkONERROR(gckOS_Allocate(os, sizeof(struct _gckMMU), &pointer));
- +
- + mmu = pointer;
- +
- + /* Initialize the gckMMU object. */
- + mmu->object.type = gcvOBJ_MMU;
- + mmu->os = os;
- + mmu->hardware = hardware;
- + mmu->pageTableMutex = gcvNULL;
- + mmu->pageTableLogical = gcvNULL;
- + mmu->mtlbLogical = gcvNULL;
- + mmu->staticSTLB = gcvNULL;
- + mmu->enabled = gcvFALSE;
- +#ifdef __QNXNTO__
- + mmu->nodeList = gcvNULL;
- + mmu->nodeMutex = gcvNULL;
- +#endif
- +
- + /* Create the page table mutex. */
- + gcmkONERROR(gckOS_CreateMutex(os, &mmu->pageTableMutex));
- +
- +#ifdef __QNXNTO__
- + /* Create the node list mutex. */
- + gcmkONERROR(gckOS_CreateMutex(os, &mmu->nodeMutex));
- +#endif
- +
- + if (hardware->mmuVersion == 0)
- + {
- + mmu->pageTableSize = MmuSize;
- +
- + gcmkONERROR(
- + gckOS_AllocateContiguous(os,
- + gcvFALSE,
- + &mmu->pageTableSize,
- + &mmu->pageTablePhysical,
- + &pointer));
- +
- + mmu->pageTableLogical = pointer;
- +
- + /* Compute number of entries in page table. */
- + mmu->pageTableEntries = mmu->pageTableSize / sizeof(gctUINT32);
- +
- + /* Mark all pages as free. */
- + pageTable = mmu->pageTableLogical;
- +
- +#if gcdMMU_CLEAR_VALUE
- + _FillPageTable(pageTable, mmu->pageTableEntries, gcdMMU_CLEAR_VALUE);
- +#endif
- +
- + _WritePageEntry(pageTable, (mmu->pageTableEntries << 8) | gcvMMU_FREE);
- + _WritePageEntry(pageTable + 1, ~0U);
- + mmu->heapList = 0;
- + mmu->freeNodes = gcvFALSE;
- +
- + /* Set page table address. */
- + gcmkONERROR(
- + gckHARDWARE_SetMMU(hardware, (gctPOINTER) mmu->pageTableLogical));
- + }
- + else
- + {
- + /* Allocate the 4K mode MTLB table. */
- + mmu->mtlbSize = gcdMMU_MTLB_SIZE + 64;
- +
- + gcmkONERROR(
- + gckOS_AllocateContiguous(os,
- + gcvFALSE,
- + &mmu->mtlbSize,
- + &mmu->mtlbPhysical,
- + &pointer));
- +
- + mmu->mtlbLogical = pointer;
- +
- + /* Invalid all the entries. */
- + gcmkONERROR(
- + gckOS_ZeroMemory(pointer, mmu->mtlbSize));
- + }
- +
- + /* Return the gckMMU object pointer. */
- + *Mmu = mmu;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Mmu=0x%x", *Mmu);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Roll back. */
- + if (mmu != gcvNULL)
- + {
- + if (mmu->pageTableLogical != gcvNULL)
- + {
- + /* Free the page table. */
- + gcmkVERIFY_OK(
- + gckOS_FreeContiguous(os,
- + mmu->pageTablePhysical,
- + (gctPOINTER) mmu->pageTableLogical,
- + mmu->pageTableSize));
- +
- + }
- +
- + if (mmu->mtlbLogical != gcvNULL)
- + {
- + gcmkVERIFY_OK(
- + gckOS_FreeContiguous(os,
- + mmu->mtlbPhysical,
- + (gctPOINTER) mmu->mtlbLogical,
- + mmu->mtlbSize));
- + }
- +
- + if (mmu->pageTableMutex != gcvNULL)
- + {
- + /* Delete the mutex. */
- + gcmkVERIFY_OK(
- + gckOS_DeleteMutex(os, mmu->pageTableMutex));
- + }
- +
- +#ifdef __QNXNTO__
- + if (mmu->nodeMutex != gcvNULL)
- + {
- + /* Delete the mutex. */
- + gcmkVERIFY_OK(
- + gckOS_DeleteMutex(os, mmu->nodeMutex));
- + }
- +#endif
- +
- + /* Mark the gckMMU object as unknown. */
- + mmu->object.type = gcvOBJ_UNKNOWN;
- +
- + /* Free the allocates memory. */
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, mmu));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** _Destroy
- +**
- +** Destroy a gckMMU object.
- +**
- +** INPUT:
- +**
- +** gckMMU Mmu
- +** Pointer to an gckMMU object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +_Destroy(
- + IN gckMMU Mmu
- + )
- +{
- +#ifdef __QNXNTO__
- + gcuVIDMEM_NODE_PTR node, next;
- +#endif
- +
- + gcmkHEADER_ARG("Mmu=0x%x", Mmu);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
- +
- +#ifdef __QNXNTO__
- + /* Free all associated virtual memory. */
- + for (node = Mmu->nodeList; node != gcvNULL; node = next)
- + {
- + next = node->Virtual.next;
- + gcmkVERIFY_OK(gckVIDMEM_Free(node));
- + }
- +#endif
- +
- + while (Mmu->staticSTLB != gcvNULL)
- + {
- + gcsMMU_STLB_PTR pre = Mmu->staticSTLB;
- + Mmu->staticSTLB = pre->next;
- +
- + if (pre->physical != gcvNULL)
- + {
- + gcmkVERIFY_OK(
- + gckOS_FreeContiguous(Mmu->os,
- + pre->physical,
- + pre->logical,
- + pre->size));
- + }
- +
- + if (pre->mtlbEntryNum != 0)
- + {
- + gcmkASSERT(pre->mtlbEntryNum == 1);
- + _WritePageEntry(Mmu->mtlbLogical + pre->mtlbIndex, 0);
- +#if gcdMMU_TABLE_DUMP
- + gckOS_Print("%s(%d): clean MTLB[%d]\n",
- + __FUNCTION__, __LINE__,
- + pre->mtlbIndex);
- +#endif
- + }
- +
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, pre));
- + }
- +
- + if (Mmu->hardware->mmuVersion != 0)
- + {
- + gcmkVERIFY_OK(
- + gckOS_FreeContiguous(Mmu->os,
- + Mmu->mtlbPhysical,
- + (gctPOINTER) Mmu->mtlbLogical,
- + Mmu->mtlbSize));
- + }
- +
- + /* Free the page table. */
- + gcmkVERIFY_OK(
- + gckOS_FreeContiguous(Mmu->os,
- + Mmu->pageTablePhysical,
- + (gctPOINTER) Mmu->pageTableLogical,
- + Mmu->pageTableSize));
- +
- +#ifdef __QNXNTO__
- + /* Delete the node list mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Mmu->os, Mmu->nodeMutex));
- +#endif
- +
- + /* Delete the page table mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Mmu->os, Mmu->pageTableMutex));
- +
- + /* Mark the gckMMU object as unknown. */
- + Mmu->object.type = gcvOBJ_UNKNOWN;
- +
- + /* Free the gckMMU object. */
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, Mmu));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +** _AdjstIndex
- +**
- +** Adjust the index from which we search for a usable node to make sure
- +** index allocated is greater than Start.
- +*/
- +gceSTATUS
- +_AdjustIndex(
- + IN gckMMU Mmu,
- + IN gctUINT32 Index,
- + IN gctUINT32 PageCount,
- + IN gctUINT32 Start,
- + OUT gctUINT32 * IndexAdjusted
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 index = Index;
- + gctUINT32_PTR map = Mmu->pageTableLogical;
- +
- + gcmkHEADER();
- +
- + for (; index < Mmu->pageTableEntries;)
- + {
- + gctUINT32 result = 0;
- + gctUINT32 nodeSize = 0;
- +
- + if (index >= Start)
- + {
- + break;
- + }
- +
- + switch (gcmENTRY_TYPE(map[index]))
- + {
- + case gcvMMU_SINGLE:
- + nodeSize = 1;
- + break;
- +
- + case gcvMMU_FREE:
- + nodeSize = map[index] >> 8;
- + break;
- +
- + default:
- + gcmkFATAL("MMU table correcupted at index %u!", index);
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +
- + if (nodeSize > PageCount)
- + {
- + result = index + (nodeSize - PageCount);
- +
- + if (result >= Start)
- + {
- + break;
- + }
- + }
- +
- + switch (gcmENTRY_TYPE(map[index]))
- + {
- + case gcvMMU_SINGLE:
- + index = map[index] >> 8;
- + break;
- +
- + case gcvMMU_FREE:
- + index = map[index + 1];
- + break;
- +
- + default:
- + gcmkFATAL("MMU table correcupted at index %u!", index);
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- + }
- +
- + *IndexAdjusted = index;
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckMMU_Construct(
- + IN gckKERNEL Kernel,
- + IN gctSIZE_T MmuSize,
- + OUT gckMMU * Mmu
- + )
- +{
- +#if gcdSHARED_PAGETABLE
- + gceSTATUS status;
- + gctPOINTER pointer;
- +
- + gcmkHEADER_ARG("Kernel=0x%08x", Kernel);
- +
- + if (sharedPageTable == gcvNULL)
- + {
- + gcmkONERROR(
- + gckOS_Allocate(Kernel->os,
- + sizeof(struct _gcsSharedPageTable),
- + &pointer));
- + sharedPageTable = pointer;
- +
- + gcmkONERROR(
- + gckOS_ZeroMemory(sharedPageTable,
- + sizeof(struct _gcsSharedPageTable)));
- +
- + gcmkONERROR(_Construct(Kernel, MmuSize, &sharedPageTable->mmu));
- + }
- + else if (Kernel->hardware->mmuVersion == 0)
- + {
- + /* Set page table address. */
- + gcmkONERROR(
- + gckHARDWARE_SetMMU(Kernel->hardware, (gctPOINTER) sharedPageTable->mmu->pageTableLogical));
- + }
- +
- + *Mmu = sharedPageTable->mmu;
- +
- + sharedPageTable->hardwares[sharedPageTable->reference] = Kernel->hardware;
- +
- + sharedPageTable->reference++;
- +
- + gcmkFOOTER_ARG("sharedPageTable->reference=%lu", sharedPageTable->reference);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (sharedPageTable)
- + {
- + if (sharedPageTable->mmu)
- + {
- + gcmkVERIFY_OK(gckMMU_Destroy(sharedPageTable->mmu));
- + }
- +
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, sharedPageTable));
- + }
- +
- + gcmkFOOTER();
- + return status;
- +#elif gcdMIRROR_PAGETABLE
- + gceSTATUS status;
- + gctPOINTER pointer;
- +
- + gcmkHEADER_ARG("Kernel=0x%08x", Kernel);
- +
- + if (mirrorPageTable == gcvNULL)
- + {
- + gcmkONERROR(
- + gckOS_Allocate(Kernel->os,
- + sizeof(struct _gcsMirrorPageTable),
- + &pointer));
- + mirrorPageTable = pointer;
- +
- + gcmkONERROR(
- + gckOS_ZeroMemory(mirrorPageTable,
- + sizeof(struct _gcsMirrorPageTable)));
- +
- + gcmkONERROR(
- + gckOS_CreateMutex(Kernel->os, &mirrorPageTableMutex));
- + }
- +
- + gcmkONERROR(_Construct(Kernel, MmuSize, Mmu));
- +
- + mirrorPageTable->mmus[mirrorPageTable->reference] = *Mmu;
- +
- + mirrorPageTable->hardwares[mirrorPageTable->reference] = Kernel->hardware;
- +
- + mirrorPageTable->reference++;
- +
- + gcmkFOOTER_ARG("mirrorPageTable->reference=%lu", mirrorPageTable->reference);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (mirrorPageTable && mirrorPageTable->reference == 0)
- + {
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, mirrorPageTable));
- + }
- +
- + gcmkFOOTER();
- + return status;
- +#else
- + return _Construct(Kernel, MmuSize, Mmu);
- +#endif
- +}
- +
- +gceSTATUS
- +gckMMU_Destroy(
- + IN gckMMU Mmu
- + )
- +{
- +#if gcdSHARED_PAGETABLE
- + sharedPageTable->reference--;
- +
- + if (sharedPageTable->reference == 0)
- + {
- + if (sharedPageTable->mmu)
- + {
- + gcmkVERIFY_OK(_Destroy(Mmu));
- + }
- +
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, sharedPageTable));
- + }
- +
- + return gcvSTATUS_OK;
- +#elif gcdMIRROR_PAGETABLE
- + mirrorPageTable->reference--;
- +
- + if (mirrorPageTable->reference == 0)
- + {
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, mirrorPageTable));
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, mirrorPageTableMutex));
- + }
- +
- + return _Destroy(Mmu);
- +#else
- + return _Destroy(Mmu);
- +#endif
- +}
- +
- +/*******************************************************************************
- +**
- +** gckMMU_AllocatePages
- +**
- +** Allocate pages inside the page table.
- +**
- +** INPUT:
- +**
- +** gckMMU Mmu
- +** Pointer to an gckMMU object.
- +**
- +** gctSIZE_T PageCount
- +** Number of pages to allocate.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * PageTable
- +** Pointer to a variable that receives the base address of the page
- +** table.
- +**
- +** gctUINT32 * Address
- +** Pointer to a variable that receives the hardware specific address.
- +*/
- +gceSTATUS
- +_AllocatePages(
- + IN gckMMU Mmu,
- + IN gctSIZE_T PageCount,
- + IN gceSURF_TYPE Type,
- + OUT gctPOINTER * PageTable,
- + OUT gctUINT32 * Address
- + )
- +{
- + gceSTATUS status;
- + gctBOOL mutex = gcvFALSE;
- + gctUINT32 index = 0, previous = ~0U, left;
- + gctUINT32_PTR pageTable;
- + gctBOOL gotIt;
- + gctUINT32 address;
- +
- + gcmkHEADER_ARG("Mmu=0x%x PageCount=%lu", Mmu, PageCount);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
- + gcmkVERIFY_ARGUMENT(PageCount > 0);
- + gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
- +
- + if (PageCount > Mmu->pageTableEntries)
- + {
- + gcmkPRINT("[galcore]: %s(%d): Run out of free page entry.",
- + __FUNCTION__, __LINE__);
- +
- + /* Not enough pages avaiable. */
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +
- + /* Grab the mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
- + mutex = gcvTRUE;
- +
- + /* Cast pointer to page table. */
- + for (pageTable = Mmu->pageTableLogical, gotIt = gcvFALSE; !gotIt;)
- + {
- + index = Mmu->heapList;
- +
- + if ((Mmu->hardware->mmuVersion == 0) && (Type == gcvSURF_VERTEX))
- + {
- + gcmkONERROR(_AdjustIndex(
- + Mmu,
- + index,
- + PageCount,
- + gcdVERTEX_START / gcmSIZEOF(gctUINT32),
- + &index
- + ));
- + }
- +
- + /* Walk the heap list. */
- + for (; !gotIt && (index < Mmu->pageTableEntries);)
- + {
- + /* Check the node type. */
- + switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[index])))
- + {
- + case gcvMMU_SINGLE:
- + /* Single odes are valid if we only need 1 page. */
- + if (PageCount == 1)
- + {
- + gotIt = gcvTRUE;
- + }
- + else
- + {
- + /* Move to next node. */
- + previous = index;
- + index = _ReadPageEntry(&pageTable[index]) >> 8;
- + }
- + break;
- +
- + case gcvMMU_FREE:
- + /* Test if the node has enough space. */
- + if (PageCount <= (_ReadPageEntry(&pageTable[index]) >> 8))
- + {
- + gotIt = gcvTRUE;
- + }
- + else
- + {
- + /* Move to next node. */
- + previous = index;
- + index = _ReadPageEntry(&pageTable[index + 1]);
- + }
- + break;
- +
- + default:
- + gcmkFATAL("MMU table correcupted at index %u!", index);
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- + }
- +
- + /* Test if we are out of memory. */
- + if (index >= Mmu->pageTableEntries)
- + {
- + if (Mmu->freeNodes)
- + {
- + /* Time to move out the trash! */
- + gcmkONERROR(_Collect(Mmu));
- + }
- + else
- + {
- + gcmkPRINT("[galcore]: %s(%d): Run out of free page entry.",
- + __FUNCTION__, __LINE__);
- +
- + /* Out of resources. */
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- + }
- + }
- +
- + switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[index])))
- + {
- + case gcvMMU_SINGLE:
- + /* Unlink single node from free list. */
- + gcmkONERROR(
- + _Link(Mmu, previous, _ReadPageEntry(&pageTable[index]) >> 8));
- + break;
- +
- + case gcvMMU_FREE:
- + /* Check how many pages will be left. */
- + left = (_ReadPageEntry(&pageTable[index]) >> 8) - PageCount;
- + switch (left)
- + {
- + case 0:
- + /* The entire node is consumed, just unlink it. */
- + gcmkONERROR(
- + _Link(Mmu, previous, _ReadPageEntry(&pageTable[index + 1])));
- + break;
- +
- + case 1:
- + /* One page will remain. Convert the node to a single node and
- + ** advance the index. */
- + _WritePageEntry(&pageTable[index], (_ReadPageEntry(&pageTable[index + 1]) << 8) | gcvMMU_SINGLE);
- + index ++;
- + break;
- +
- + default:
- + /* Enough pages remain for a new node. However, we will just adjust
- + ** the size of the current node and advance the index. */
- + _WritePageEntry(&pageTable[index], (left << 8) | gcvMMU_FREE);
- + index += left;
- + break;
- + }
- + break;
- + }
- +
- + /* Mark node as used. */
- + gcmkONERROR(_FillPageTable(&pageTable[index], PageCount, gcvMMU_USED));
- +
- + /* Return pointer to page table. */
- + *PageTable = &pageTable[index];
- +
- + /* Build virtual address. */
- + if (Mmu->hardware->mmuVersion == 0)
- + {
- + gcmkONERROR(
- + gckHARDWARE_BuildVirtualAddress(Mmu->hardware, index, 0, &address));
- + }
- + else
- + {
- + gctUINT32 masterOffset = index / gcdMMU_STLB_4K_ENTRY_NUM
- + + Mmu->dynamicMappingStart;
- + gctUINT32 slaveOffset = index % gcdMMU_STLB_4K_ENTRY_NUM;
- +
- + address = (masterOffset << gcdMMU_MTLB_SHIFT)
- + | (slaveOffset << gcdMMU_STLB_4K_SHIFT);
- + }
- +
- + if (Address != gcvNULL)
- + {
- + *Address = address;
- + }
- +
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*PageTable=0x%x *Address=%08x",
- + *PageTable, gcmOPT_VALUE(Address));
- + return gcvSTATUS_OK;
- +
- +OnError:
- +
- + if (mutex)
- + {
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckMMU_FreePages
- +**
- +** Free pages inside the page table.
- +**
- +** INPUT:
- +**
- +** gckMMU Mmu
- +** Pointer to an gckMMU object.
- +**
- +** gctPOINTER PageTable
- +** Base address of the page table to free.
- +**
- +** gctSIZE_T PageCount
- +** Number of pages to free.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +_FreePages(
- + IN gckMMU Mmu,
- + IN gctPOINTER PageTable,
- + IN gctSIZE_T PageCount
- + )
- +{
- + gctUINT32_PTR pageTable;
- + gceSTATUS status;
- + gctBOOL acquired = gcvFALSE;
- +
- + gcmkHEADER_ARG("Mmu=0x%x PageTable=0x%x PageCount=%lu",
- + Mmu, PageTable, PageCount);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
- + gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
- + gcmkVERIFY_ARGUMENT(PageCount > 0);
- +
- + /* Convert the pointer. */
- + pageTable = (gctUINT32_PTR) PageTable;
- +
- + gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- +#if gcdMMU_CLEAR_VALUE
- + if (Mmu->hardware->mmuVersion == 0)
- + {
- + _FillPageTable(pageTable, PageCount, gcdMMU_CLEAR_VALUE);
- + }
- +#endif
- +
- + if (PageCount == 1)
- + {
- + /* Single page node. */
- + _WritePageEntry(pageTable,
- + (~((1U<<8)-1)) | gcvMMU_SINGLE
- +#if gcdUSE_MMU_EXCEPTION
- + /* Enable exception */
- + | 1 << 1
- +#endif
- + );
- + }
- + else
- + {
- + /* Mark the node as free. */
- + _WritePageEntry(pageTable,
- + (PageCount << 8) | gcvMMU_FREE
- +#if gcdUSE_MMU_EXCEPTION
- + /* Enable exception */
- + | 1 << 1
- +#endif
- + );
- + _WritePageEntry(pageTable + 1, ~0U);
- +
- +#if gcdUSE_MMU_EXCEPTION
- + /* Enable exception */
- + gcmkVERIFY_OK(_FillPageTable(pageTable + 2, PageCount - 2, 1 << 1));
- +#endif
- + }
- +
- + /* We have free nodes. */
- + Mmu->freeNodes = gcvTRUE;
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
- + acquired = gcvFALSE;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckMMU_AllocatePages(
- + IN gckMMU Mmu,
- + IN gctSIZE_T PageCount,
- + OUT gctPOINTER * PageTable,
- + OUT gctUINT32 * Address
- + )
- +{
- + return gckMMU_AllocatePagesEx(
- + Mmu, PageCount, gcvSURF_UNKNOWN, PageTable, Address);
- +}
- +
- +gceSTATUS
- +gckMMU_AllocatePagesEx(
- + IN gckMMU Mmu,
- + IN gctSIZE_T PageCount,
- + IN gceSURF_TYPE Type,
- + OUT gctPOINTER * PageTable,
- + OUT gctUINT32 * Address
- + )
- +{
- +#if gcdMIRROR_PAGETABLE
- + gceSTATUS status;
- + gctPOINTER pageTable;
- + gctUINT32 address;
- + gctINT i;
- + gckMMU mmu;
- + gctBOOL acquired = gcvFALSE;
- + gctBOOL allocated = gcvFALSE;
- +
- + gckOS_AcquireMutex(Mmu->os, mirrorPageTableMutex, gcvINFINITE);
- + acquired = gcvTRUE;
- +
- + /* Allocate page table for current MMU. */
- + for (i = 0; i < (gctINT)mirrorPageTable->reference; i++)
- + {
- + if (Mmu == mirrorPageTable->mmus[i])
- + {
- + gcmkONERROR(_AllocatePages(Mmu, PageCount, Type, PageTable, Address));
- + allocated = gcvTRUE;
- + }
- + }
- +
- + /* Allocate page table for other MMUs. */
- + for (i = 0; i < (gctINT)mirrorPageTable->reference; i++)
- + {
- + mmu = mirrorPageTable->mmus[i];
- +
- + if (Mmu != mmu)
- + {
- + gcmkONERROR(_AllocatePages(mmu, PageCount, Type, &pageTable, &address));
- + gcmkASSERT(address == *Address);
- + }
- + }
- +
- + gckOS_ReleaseMutex(Mmu->os, mirrorPageTableMutex);
- + acquired = gcvFALSE;
- +
- + return gcvSTATUS_OK;
- +OnError:
- +
- + if (allocated)
- + {
- + /* Page tables for multiple GPU always keep the same. So it is impossible
- + * the fist one allocates successfully but others fail.
- + */
- + gcmkASSERT(0);
- + }
- +
- + if (acquired)
- + {
- + gckOS_ReleaseMutex(Mmu->os, mirrorPageTableMutex);
- + }
- +
- + return status;
- +#else
- + return _AllocatePages(Mmu, PageCount, Type, PageTable, Address);
- +#endif
- +}
- +
- +gceSTATUS
- +gckMMU_FreePages(
- + IN gckMMU Mmu,
- + IN gctPOINTER PageTable,
- + IN gctSIZE_T PageCount
- + )
- +{
- +#if gcdMIRROR_PAGETABLE
- + gctINT i;
- + gctUINT32 offset;
- + gckMMU mmu;
- +
- + gckOS_AcquireMutex(Mmu->os, mirrorPageTableMutex, gcvINFINITE);
- +
- + gcmkVERIFY_OK(_FreePages(Mmu, PageTable, PageCount));
- +
- + offset = (gctUINT32)PageTable - (gctUINT32)Mmu->pageTableLogical;
- +
- + for (i = 0; i < (gctINT)mirrorPageTable->reference; i++)
- + {
- + mmu = mirrorPageTable->mmus[i];
- +
- + if (mmu != Mmu)
- + {
- + gcmkVERIFY_OK(_FreePages(mmu, mmu->pageTableLogical + offset/4, PageCount));
- + }
- + }
- +
- + gckOS_ReleaseMutex(Mmu->os, mirrorPageTableMutex);
- +
- + return gcvSTATUS_OK;
- +#else
- + return _FreePages(Mmu, PageTable, PageCount);
- +#endif
- +}
- +
- +gceSTATUS
- +gckMMU_Enable(
- + IN gckMMU Mmu,
- + IN gctUINT32 PhysBaseAddr,
- + IN gctUINT32 PhysSize
- + )
- +{
- + gceSTATUS status;
- +#if gcdSHARED_PAGETABLE
- + gckHARDWARE hardware;
- + gctINT i;
- +#endif
- +
- + gcmkHEADER_ARG("Mmu=0x%x", Mmu);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
- +
- +#if gcdSHARED_PAGETABLE
- + if (Mmu->enabled)
- + {
- + gcmkFOOTER_ARG("Status=%d", gcvSTATUS_SKIP);
- + return gcvSTATUS_SKIP;
- + }
- +#endif
- +
- + if (Mmu->hardware->mmuVersion == 0)
- + {
- + /* Success. */
- + gcmkFOOTER_ARG("Status=%d", gcvSTATUS_SKIP);
- + return gcvSTATUS_SKIP;
- + }
- + else
- + {
- + if (PhysSize != 0)
- + {
- + gcmkONERROR(_FillFlatMapping(
- + Mmu,
- + PhysBaseAddr,
- + PhysSize
- + ));
- + }
- +
- + gcmkONERROR(_SetupDynamicSpace(Mmu));
- +
- +#if gcdSHARED_PAGETABLE
- + for(i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + hardware = sharedPageTable->hardwares[i];
- + if (hardware != gcvNULL)
- + {
- + gcmkONERROR(
- + gckHARDWARE_SetMMUv2(
- + hardware,
- + gcvTRUE,
- + Mmu->mtlbLogical,
- + gcvMMU_MODE_4K,
- + (gctUINT8_PTR)Mmu->mtlbLogical + gcdMMU_MTLB_SIZE,
- + gcvFALSE
- + ));
- + }
- + }
- +#else
- + gcmkONERROR(
- + gckHARDWARE_SetMMUv2(
- + Mmu->hardware,
- + gcvTRUE,
- + Mmu->mtlbLogical,
- + gcvMMU_MODE_4K,
- + (gctUINT8_PTR)Mmu->mtlbLogical + gcdMMU_MTLB_SIZE,
- + gcvFALSE
- + ));
- +#endif
- +
- + Mmu->enabled = gcvTRUE;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckMMU_SetPage(
- + IN gckMMU Mmu,
- + IN gctUINT32 PageAddress,
- + IN gctUINT32 *PageEntry
- + )
- +{
- +#if gcdMIRROR_PAGETABLE
- + gctUINT32_PTR pageEntry;
- + gctINT i;
- + gckMMU mmu;
- + gctUINT32 offset = (gctUINT32)PageEntry - (gctUINT32)Mmu->pageTableLogical;
- +#endif
- +
- + gctUINT32 data;
- + gcmkHEADER_ARG("Mmu=0x%x", Mmu);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
- + gcmkVERIFY_ARGUMENT(PageEntry != gcvNULL);
- + gcmkVERIFY_ARGUMENT(!(PageAddress & 0xFFF));
- +
- + if (Mmu->hardware->mmuVersion == 0)
- + {
- + data = PageAddress;
- + }
- + else
- + {
- + data = _SetPage(PageAddress);
- + }
- +
- + _WritePageEntry(PageEntry, data);
- +
- +#if gcdMIRROR_PAGETABLE
- + for (i = 0; i < (gctINT)mirrorPageTable->reference; i++)
- + {
- + mmu = mirrorPageTable->mmus[i];
- +
- + if (mmu != Mmu)
- + {
- + pageEntry = mmu->pageTableLogical + offset / 4;
- +
- + if (mmu->hardware->mmuVersion == 0)
- + {
- + _WritePageEntry(pageEntry, PageAddress);
- + }
- + else
- + {
- + _WritePageEntry(pageEntry, _SetPage(PageAddress));
- + }
- + }
- +
- + }
- +#endif
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +#ifdef __QNXNTO__
- +gceSTATUS
- +gckMMU_InsertNode(
- + IN gckMMU Mmu,
- + IN gcuVIDMEM_NODE_PTR Node)
- +{
- + gceSTATUS status;
- + gctBOOL mutex = gcvFALSE;
- +
- + gcmkHEADER_ARG("Mmu=0x%x Node=0x%x", Mmu, Node);
- +
- + gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
- +
- + gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->nodeMutex, gcvINFINITE));
- + mutex = gcvTRUE;
- +
- + Node->Virtual.next = Mmu->nodeList;
- + Mmu->nodeList = Node;
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
- +
- + gcmkFOOTER();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (mutex)
- + {
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckMMU_RemoveNode(
- + IN gckMMU Mmu,
- + IN gcuVIDMEM_NODE_PTR Node)
- +{
- + gceSTATUS status;
- + gctBOOL mutex = gcvFALSE;
- + gcuVIDMEM_NODE_PTR *iter;
- +
- + gcmkHEADER_ARG("Mmu=0x%x Node=0x%x", Mmu, Node);
- +
- + gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
- +
- + gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->nodeMutex, gcvINFINITE));
- + mutex = gcvTRUE;
- +
- + for (iter = &Mmu->nodeList; *iter; iter = &(*iter)->Virtual.next)
- + {
- + if (*iter == Node)
- + {
- + *iter = Node->Virtual.next;
- + break;
- + }
- + }
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
- +
- + gcmkFOOTER();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (mutex)
- + {
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckMMU_FreeHandleMemory(
- + IN gckKERNEL Kernel,
- + IN gckMMU Mmu,
- + IN gctUINT32 Pid
- + )
- +{
- + gceSTATUS status;
- + gctBOOL acquired = gcvFALSE;
- + gcuVIDMEM_NODE_PTR curr, next;
- +
- + gcmkHEADER_ARG("Kernel=0x%x, Mmu=0x%x Pid=%u", Kernel, Mmu, Pid);
- +
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
- +
- + gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->nodeMutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + for (curr = Mmu->nodeList; curr != gcvNULL; curr = next)
- + {
- + next = curr->Virtual.next;
- +
- + if (curr->Virtual.processID == Pid)
- + {
- + while (curr->Virtual.unlockPendings[Kernel->core] == 0 && curr->Virtual.lockeds[Kernel->core] > 0)
- + {
- + gcmkONERROR(gckVIDMEM_Unlock(Kernel, curr, gcvSURF_TYPE_UNKNOWN, gcvNULL));
- + }
- +
- + gcmkVERIFY_OK(gckVIDMEM_Free(curr));
- + }
- + }
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
- +
- + gcmkFOOTER();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +#endif
- +
- +gceSTATUS
- +gckMMU_Flush(
- + IN gckMMU Mmu
- + )
- +{
- + gckHARDWARE hardware;
- +#if gcdSHARED_PAGETABLE
- + gctINT i;
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- +#if gcdENABLE_VG
- + if (i == gcvCORE_VG)
- + {
- + continue;
- + }
- +#endif
- + hardware = sharedPageTable->hardwares[i];
- + if (hardware)
- + {
- + /* Notify cores who use this page table. */
- + gcmkVERIFY_OK(
- + gckOS_AtomSet(hardware->os, hardware->pageTableDirty, 1));
- + }
- + }
- +#elif gcdMIRROR_PAGETABLE
- + gctINT i;
- + for (i = 0; i < mirrorPageTable->reference; i++)
- + {
- + hardware = mirrorPageTable->hardwares[i];
- +
- + /* Notify cores who use this page table. */
- + gcmkVERIFY_OK(
- + gckOS_AtomSet(hardware->os, hardware->pageTableDirty, 1));
- + }
- +#else
- + hardware = Mmu->hardware;
- + gcmkVERIFY_OK(
- + gckOS_AtomSet(hardware->os, hardware->pageTableDirty, 1));
- +#endif
- +
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckMMU_DumpPageTableEntry(
- + IN gckMMU Mmu,
- + IN gctUINT32 Address
- + )
- +{
- + gctUINT32_PTR pageTable;
- + gctUINT32 index;
- + gctUINT32 mtlb, stlb;
- +
- + gcmkHEADER_ARG("Mmu=0x%08X Address=0x%08X", Mmu, Address);
- + gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
- +
- + gcmkASSERT(Mmu->hardware->mmuVersion > 0);
- +
- + mtlb = (Address & gcdMMU_MTLB_MASK) >> gcdMMU_MTLB_SHIFT;
- + stlb = (Address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
- +
- + if (Address >= 0x80000000)
- + {
- + pageTable = Mmu->pageTableLogical;
- +
- + index = (mtlb - Mmu->dynamicMappingStart)
- + * gcdMMU_STLB_4K_ENTRY_NUM
- + + stlb;
- +
- + gcmkPRINT(" Page table entry = 0x%08X", _ReadPageEntry(pageTable + index));
- + }
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/******************************************************************************
- +****************************** T E S T C O D E ******************************
- +******************************************************************************/
- +
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu_vg.c linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu_vg.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu_vg.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu_vg.c 2015-03-08 14:27:37.637684501 -0500
- @@ -0,0 +1,522 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal_kernel_precomp.h"
- +
- +#if gcdENABLE_VG
- +
- +#define _GC_OBJ_ZONE gcvZONE_MMU
- +
- +/*******************************************************************************
- +**
- +** gckVGMMU_Construct
- +**
- +** Construct a new gckVGMMU object.
- +**
- +** INPUT:
- +**
- +** gckVGKERNEL Kernel
- +** Pointer to an gckVGKERNEL object.
- +**
- +** gctSIZE_T MmuSize
- +** Number of bytes for the page table.
- +**
- +** OUTPUT:
- +**
- +** gckVGMMU * Mmu
- +** Pointer to a variable that receives the gckVGMMU object pointer.
- +*/
- +gceSTATUS gckVGMMU_Construct(
- + IN gckVGKERNEL Kernel,
- + IN gctSIZE_T MmuSize,
- + OUT gckVGMMU * Mmu
- + )
- +{
- + gckOS os;
- + gckVGHARDWARE hardware;
- + gceSTATUS status;
- + gckVGMMU mmu;
- + gctUINT32 * pageTable;
- + gctUINT32 i;
- +
- + gcmkHEADER_ARG("Kernel=0x%x MmuSize=0x%x Mmu=0x%x", Kernel, MmuSize, Mmu);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(MmuSize > 0);
- + gcmkVERIFY_ARGUMENT(Mmu != gcvNULL);
- +
- + /* Extract the gckOS object pointer. */
- + os = Kernel->os;
- + gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
- +
- + /* Extract the gckVGHARDWARE object pointer. */
- + hardware = Kernel->hardware;
- + gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
- +
- + /* Allocate memory for the gckVGMMU object. */
- + status = gckOS_Allocate(os, sizeof(struct _gckVGMMU), (gctPOINTER *) &mmu);
- +
- + if (status < 0)
- + {
- + /* Error. */
- + gcmkFATAL(
- + "%s(%d): could not allocate gckVGMMU object.",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkFOOTER();
- + return status;
- + }
- +
- + /* Initialize the gckVGMMU object. */
- + mmu->object.type = gcvOBJ_MMU;
- + mmu->os = os;
- + mmu->hardware = hardware;
- +
- + /* Create the mutex. */
- + status = gckOS_CreateMutex(os, &mmu->mutex);
- +
- + if (status < 0)
- + {
- + /* Roll back. */
- + mmu->object.type = gcvOBJ_UNKNOWN;
- + gcmkVERIFY_OK(gckOS_Free(os, mmu));
- +
- + gcmkFOOTER();
- + /* Error. */
- + return status;
- + }
- +
- + /* Allocate the page table. */
- + mmu->pageTableSize = MmuSize;
- + status = gckOS_AllocateContiguous(os,
- + gcvFALSE,
- + &mmu->pageTableSize,
- + &mmu->pageTablePhysical,
- + &mmu->pageTableLogical);
- +
- + if (status < 0)
- + {
- + /* Roll back. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(os, mmu->mutex));
- +
- + mmu->object.type = gcvOBJ_UNKNOWN;
- + gcmkVERIFY_OK(gckOS_Free(os, mmu));
- +
- + /* Error. */
- + gcmkFATAL(
- + "%s(%d): could not allocate page table.",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkFOOTER();
- + return status;
- + }
- +
- + /* Compute number of entries in page table. */
- + mmu->entryCount = mmu->pageTableSize / sizeof(gctUINT32);
- + mmu->entry = 0;
- +
- + /* Mark the entire page table as available. */
- + pageTable = (gctUINT32 *) mmu->pageTableLogical;
- + for (i = 0; i < mmu->entryCount; i++)
- + {
- + pageTable[i] = (gctUINT32)~0;
- + }
- +
- + /* Set page table address. */
- + status = gckVGHARDWARE_SetMMU(hardware, mmu->pageTableLogical);
- +
- + if (status < 0)
- + {
- + /* Free the page table. */
- + gcmkVERIFY_OK(gckOS_FreeContiguous(mmu->os,
- + mmu->pageTablePhysical,
- + mmu->pageTableLogical,
- + mmu->pageTableSize));
- +
- + /* Roll back. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(os, mmu->mutex));
- +
- + mmu->object.type = gcvOBJ_UNKNOWN;
- + gcmkVERIFY_OK(gckOS_Free(os, mmu));
- +
- + /* Error. */
- + gcmkFATAL(
- + "%s(%d): could not program page table.",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkFOOTER();
- + return status;
- + }
- +
- + /* Return the gckVGMMU object pointer. */
- + *Mmu = mmu;
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_MMU,
- + "%s(%d): %u entries at %p.(0x%08X)\n",
- + __FUNCTION__, __LINE__,
- + mmu->entryCount,
- + mmu->pageTableLogical,
- + mmu->pageTablePhysical
- + );
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGMMU_Destroy
- +**
- +** Destroy a nAQMMU object.
- +**
- +** INPUT:
- +**
- +** gckVGMMU Mmu
- +** Pointer to an gckVGMMU object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS gckVGMMU_Destroy(
- + IN gckVGMMU Mmu
- + )
- +{
- + gcmkHEADER_ARG("Mmu=0x%x", Mmu);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
- +
- + /* Free the page table. */
- + gcmkVERIFY_OK(gckOS_FreeContiguous(Mmu->os,
- + Mmu->pageTablePhysical,
- + Mmu->pageTableLogical,
- + Mmu->pageTableSize));
- +
- + /* Roll back. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Mmu->os, Mmu->mutex));
- +
- + /* Mark the gckVGMMU object as unknown. */
- + Mmu->object.type = gcvOBJ_UNKNOWN;
- +
- + /* Free the gckVGMMU object. */
- + gcmkVERIFY_OK(gckOS_Free(Mmu->os, Mmu));
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGMMU_AllocatePages
- +**
- +** Allocate pages inside the page table.
- +**
- +** INPUT:
- +**
- +** gckVGMMU Mmu
- +** Pointer to an gckVGMMU object.
- +**
- +** gctSIZE_T PageCount
- +** Number of pages to allocate.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * PageTable
- +** Pointer to a variable that receives the base address of the page
- +** table.
- +**
- +** gctUINT32 * Address
- +** Pointer to a variable that receives the hardware specific address.
- +*/
- +gceSTATUS gckVGMMU_AllocatePages(
- + IN gckVGMMU Mmu,
- + IN gctSIZE_T PageCount,
- + OUT gctPOINTER * PageTable,
- + OUT gctUINT32 * Address
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 tail, index, i;
- + gctUINT32 * table;
- + gctBOOL allocated = gcvFALSE;
- +
- + gcmkHEADER_ARG("Mmu=0x%x PageCount=0x%x PageTable=0x%x Address=0x%x",
- + Mmu, PageCount, PageTable, Address);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
- + gcmkVERIFY_ARGUMENT(PageCount > 0);
- + gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Address != gcvNULL);
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_MMU,
- + "%s(%d): %u pages.\n",
- + __FUNCTION__, __LINE__,
- + PageCount
- + );
- +
- + if (PageCount > Mmu->entryCount)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_MMU,
- + "%s(%d): page table too small for %u pages.\n",
- + __FUNCTION__, __LINE__,
- + PageCount
- + );
- +
- + gcmkFOOTER_NO();
- + /* Not enough pages avaiable. */
- + return gcvSTATUS_OUT_OF_RESOURCES;
- + }
- +
- + /* Grab the mutex. */
- + status = gckOS_AcquireMutex(Mmu->os, Mmu->mutex, gcvINFINITE);
- +
- + if (status < 0)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_MMU,
- + "%s(%d): could not acquire mutex.\n"
- + ,__FUNCTION__, __LINE__
- + );
- +
- + gcmkFOOTER();
- + /* Error. */
- + return status;
- + }
- +
- + /* Compute the tail for this allocation. */
- + tail = Mmu->entryCount - PageCount;
- +
- + /* Walk all entries until we find enough slots. */
- + for (index = Mmu->entry; index <= tail;)
- + {
- + /* Access page table. */
- + table = (gctUINT32 *) Mmu->pageTableLogical + index;
- +
- + /* See if all slots are available. */
- + for (i = 0; i < PageCount; i++, table++)
- + {
- + if (*table != ~0)
- + {
- + /* Start from next slot. */
- + index += i + 1;
- + break;
- + }
- + }
- +
- + if (i == PageCount)
- + {
- + /* Bail out if we have enough page entries. */
- + allocated = gcvTRUE;
- + break;
- + }
- + }
- +
- + if (!allocated)
- + {
- + if (status >= 0)
- + {
- + /* Walk all entries until we find enough slots. */
- + for (index = 0; index <= tail;)
- + {
- + /* Access page table. */
- + table = (gctUINT32 *) Mmu->pageTableLogical + index;
- +
- + /* See if all slots are available. */
- + for (i = 0; i < PageCount; i++, table++)
- + {
- + if (*table != ~0)
- + {
- + /* Start from next slot. */
- + index += i + 1;
- + break;
- + }
- + }
- +
- + if (i == PageCount)
- + {
- + /* Bail out if we have enough page entries. */
- + allocated = gcvTRUE;
- + break;
- + }
- + }
- + }
- + }
- +
- + if (!allocated && (status >= 0))
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_MMU,
- + "%s(%d): not enough free pages for %u pages.\n",
- + __FUNCTION__, __LINE__,
- + PageCount
- + );
- +
- + /* Not enough empty slots available. */
- + status = gcvSTATUS_OUT_OF_RESOURCES;
- + }
- +
- + if (status >= 0)
- + {
- + /* Build virtual address. */
- + status = gckVGHARDWARE_BuildVirtualAddress(Mmu->hardware,
- + index,
- + 0,
- + Address);
- +
- + if (status >= 0)
- + {
- + /* Update current entry into page table. */
- + Mmu->entry = index + PageCount;
- +
- + /* Return pointer to page table. */
- + *PageTable = (gctUINT32 *) Mmu->pageTableLogical + index;
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_MMU,
- + "%s(%d): allocated %u pages at index %u (0x%08X) @ %p.\n",
- + __FUNCTION__, __LINE__,
- + PageCount,
- + index,
- + *Address,
- + *PageTable
- + );
- + }
- + }
- +
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->mutex));
- + gcmkFOOTER();
- +
- + /* Return status. */
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVGMMU_FreePages
- +**
- +** Free pages inside the page table.
- +**
- +** INPUT:
- +**
- +** gckVGMMU Mmu
- +** Pointer to an gckVGMMU object.
- +**
- +** gctPOINTER PageTable
- +** Base address of the page table to free.
- +**
- +** gctSIZE_T PageCount
- +** Number of pages to free.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS gckVGMMU_FreePages(
- + IN gckVGMMU Mmu,
- + IN gctPOINTER PageTable,
- + IN gctSIZE_T PageCount
- + )
- +{
- + gctUINT32 * table;
- +
- + gcmkHEADER_ARG("Mmu=0x%x PageTable=0x%x PageCount=0x%x",
- + Mmu, PageTable, PageCount);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
- + gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
- + gcmkVERIFY_ARGUMENT(PageCount > 0);
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_MMU,
- + "%s(%d): freeing %u pages at index %u @ %p.\n",
- + __FUNCTION__, __LINE__,
- + PageCount,
- + ((gctUINT32 *) PageTable - (gctUINT32 *) Mmu->pageTableLogical),
- + PageTable
- + );
- +
- + /* Convert pointer. */
- + table = (gctUINT32 *) PageTable;
- +
- + /* Mark the page table entries as available. */
- + while (PageCount-- > 0)
- + {
- + *table++ = (gctUINT32)~0;
- + }
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckVGMMU_SetPage(
- + IN gckVGMMU Mmu,
- + IN gctUINT32 PageAddress,
- + IN gctUINT32 *PageEntry
- + )
- +{
- + gcmkHEADER_ARG("Mmu=0x%x", Mmu);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
- + gcmkVERIFY_ARGUMENT(PageEntry != gcvNULL);
- + gcmkVERIFY_ARGUMENT(!(PageAddress & 0xFFF));
- +
- + *PageEntry = PageAddress;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckVGMMU_Flush(
- + IN gckVGMMU Mmu
- + )
- +{
- + gckVGHARDWARE hardware;
- +
- + gcmkHEADER_ARG("Mmu=0x%x", Mmu);
- +
- + hardware = Mmu->hardware;
- + gcmkVERIFY_OK(
- + gckOS_AtomSet(hardware->os, hardware->pageTableDirty, 1));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +#endif /* gcdENABLE_VG */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_power.c linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_power.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_power.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_power.c 2015-03-08 14:27:37.637684501 -0500
- @@ -0,0 +1,347 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal_kernel_precomp.h"
- +
- +#define _GC_OBJ_ZONE gcvZONE_POWER
- +
- +/******************************************************************************\
- +************************ Dynamic Voltage Frequency Setting *********************
- +\******************************************************************************/
- +#if gcdDVFS
- +static gctUINT32
- +_GetLoadHistory(
- + IN gckDVFS Dvfs,
- + IN gctUINT32 Select,
- + IN gctUINT32 Index
- +)
- +{
- + return Dvfs->loads[Index];
- +}
- +
- +static void
- +_IncreaseScale(
- + IN gckDVFS Dvfs,
- + IN gctUINT32 Load,
- + OUT gctUINT8 *Scale
- + )
- +{
- + if (Dvfs->currentScale < 32)
- + {
- + *Scale = Dvfs->currentScale + 8;
- + }
- + else
- + {
- + *Scale = Dvfs->currentScale + 8;
- + *Scale = gcmMIN(64, *Scale);
- + }
- +}
- +
- +static void
- +_RecordFrequencyHistory(
- + gckDVFS Dvfs,
- + gctUINT32 Frequency
- + )
- +{
- + gctUINT32 i = 0;
- +
- + struct _FrequencyHistory *history = Dvfs->frequencyHistory;
- +
- + for (i = 0; i < 16; i++)
- + {
- + if (history->frequency == Frequency)
- + {
- + break;
- + }
- +
- + if (history->frequency == 0)
- + {
- + history->frequency = Frequency;
- + break;
- + }
- +
- + history++;
- + }
- +
- + if (i < 16)
- + {
- + history->count++;
- + }
- +}
- +
- +static gctUINT32
- +_GetFrequencyHistory(
- + gckDVFS Dvfs,
- + gctUINT32 Frequency
- + )
- +{
- + gctUINT32 i = 0;
- +
- + struct _FrequencyHistory * history = Dvfs->frequencyHistory;
- +
- + for (i = 0; i < 16; i++)
- + {
- + if (history->frequency == Frequency)
- + {
- + break;
- + }
- +
- + history++;
- + }
- +
- + if (i < 16)
- + {
- + return history->count;
- + }
- +
- + return 0;
- +}
- +
- +static void
- +_Policy(
- + IN gckDVFS Dvfs,
- + IN gctUINT32 Load,
- + OUT gctUINT8 *Scale
- + )
- +{
- + gctUINT8 load[4], nextLoad;
- + gctUINT8 scale;
- +
- + /* Last 4 history. */
- + load[0] = (Load & 0xFF);
- + load[1] = (Load & 0xFF00) >> 8;
- + load[2] = (Load & 0xFF0000) >> 16;
- + load[3] = (Load & 0xFF000000) >> 24;
- +
- + /* Determine target scale. */
- + if (load[0] > 54)
- + {
- + _IncreaseScale(Dvfs, Load, &scale);
- + }
- + else
- + {
- + nextLoad = (load[0] + load[1] + load[2] + load[3])/4;
- +
- + scale = Dvfs->currentScale * (nextLoad) / 54;
- +
- + scale = gcmMAX(1, scale);
- + scale = gcmMIN(64, scale);
- + }
- +
- + Dvfs->totalConfig++;
- +
- + Dvfs->loads[(load[0]-1)/8]++;
- +
- + *Scale = scale;
- +
- +
- + if (Dvfs->totalConfig % 100 == 0)
- + {
- + gcmkPRINT("=======================================================");
- + gcmkPRINT("GPU Load: %-8d %-8d %-8d %-8d %-8d %-8d %-8d %-8d",
- + 8, 16, 24, 32, 40, 48, 56, 64);
- + gcmkPRINT(" %-8d %-8d %-8d %-8d %-8d %-8d %-8d %-8d",
- + _GetLoadHistory(Dvfs,2, 0),
- + _GetLoadHistory(Dvfs,2, 1),
- + _GetLoadHistory(Dvfs,2, 2),
- + _GetLoadHistory(Dvfs,2, 3),
- + _GetLoadHistory(Dvfs,2, 4),
- + _GetLoadHistory(Dvfs,2, 5),
- + _GetLoadHistory(Dvfs,2, 6),
- + _GetLoadHistory(Dvfs,2, 7)
- + );
- +
- + gcmkPRINT("Frequency(MHz) %-8d %-8d %-8d %-8d %-8d",
- + 58, 120, 240, 360, 480);
- + gcmkPRINT(" %-8d %-8d %-8d %-8d %-8d",
- + _GetFrequencyHistory(Dvfs, 58),
- + _GetFrequencyHistory(Dvfs,120),
- + _GetFrequencyHistory(Dvfs,240),
- + _GetFrequencyHistory(Dvfs,360),
- + _GetFrequencyHistory(Dvfs,480)
- + );
- + }
- +}
- +
- +static void
- +_TimerFunction(
- + gctPOINTER Data
- + )
- +{
- + gceSTATUS status;
- + gckDVFS dvfs = (gckDVFS) Data;
- + gckHARDWARE hardware = dvfs->hardware;
- + gctUINT32 value;
- + gctUINT32 frequency;
- + gctUINT8 scale;
- + gctUINT32 t1, t2, consumed;
- +
- + gckOS_GetTicks(&t1);
- +
- + gcmkONERROR(gckHARDWARE_QueryLoad(hardware, &value));
- +
- + /* determine target sacle. */
- + _Policy(dvfs, value, &scale);
- +
- + /* Set frequency and voltage. */
- + gcmkONERROR(gckOS_SetGPUFrequency(hardware->os, hardware->core, scale));
- +
- + /* Query real frequency. */
- + gcmkONERROR(
- + gckOS_QueryGPUFrequency(hardware->os,
- + hardware->core,
- + &frequency,
- + &dvfs->currentScale));
- +
- + _RecordFrequencyHistory(dvfs, frequency);
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_POWER,
- + "Current frequency = %d",
- + frequency);
- +
- + /* Set period. */
- + gcmkONERROR(gckHARDWARE_SetDVFSPeroid(hardware, frequency));
- +
- +OnError:
- + /* Determine next querying time. */
- + gckOS_GetTicks(&t2);
- +
- + consumed = gcmMIN(((long)t2 - (long)t1), 5);
- +
- + if (dvfs->stop == gcvFALSE)
- + {
- + gcmkVERIFY_OK(gckOS_StartTimer(hardware->os,
- + dvfs->timer,
- + dvfs->pollingTime - consumed));
- + }
- +
- + return;
- +}
- +
- +gceSTATUS
- +gckDVFS_Construct(
- + IN gckHARDWARE Hardware,
- + OUT gckDVFS * Dvfs
- + )
- +{
- + gceSTATUS status;
- + gctPOINTER pointer;
- + gckDVFS dvfs = gcvNULL;
- + gckOS os = Hardware->os;
- +
- + gcmkHEADER_ARG("Hardware=0x%X", Hardware);
- +
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- + gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
- +
- + /* Allocate a gckDVFS manager. */
- + gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct _gckDVFS), &pointer));
- +
- + gckOS_ZeroMemory(pointer, gcmSIZEOF(struct _gckDVFS));
- +
- + dvfs = pointer;
- +
- + /* Initialization. */
- + dvfs->hardware = Hardware;
- + dvfs->pollingTime = gcdDVFS_POLLING_TIME;
- + dvfs->os = Hardware->os;
- + dvfs->currentScale = 64;
- +
- + /* Create a polling timer. */
- + gcmkONERROR(gckOS_CreateTimer(os, _TimerFunction, pointer, &dvfs->timer));
- +
- + /* Initialize frequency and voltage adjustment helper. */
- + gcmkONERROR(gckOS_PrepareGPUFrequency(os, Hardware->core));
- +
- + /* Return result. */
- + *Dvfs = dvfs;
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Roll back. */
- + if (dvfs)
- + {
- + if (dvfs->timer)
- + {
- + gcmkVERIFY_OK(gckOS_DestroyTimer(os, dvfs->timer));
- + }
- +
- + gcmkOS_SAFE_FREE(os, dvfs);
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckDVFS_Destroy(
- + IN gckDVFS Dvfs
- + )
- +{
- + gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
- + gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
- +
- + /* Deinitialize helper fuunction. */
- + gcmkVERIFY_OK(gckOS_FinishGPUFrequency(Dvfs->os, Dvfs->hardware->core));
- +
- + /* DestroyTimer. */
- + gcmkVERIFY_OK(gckOS_DestroyTimer(Dvfs->os, Dvfs->timer));
- +
- + gcmkOS_SAFE_FREE(Dvfs->os, Dvfs);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckDVFS_Start(
- + IN gckDVFS Dvfs
- + )
- +{
- + gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
- + gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
- +
- + gckHARDWARE_InitDVFS(Dvfs->hardware);
- +
- + Dvfs->stop = gcvFALSE;
- +
- + gckOS_StartTimer(Dvfs->os, Dvfs->timer, Dvfs->pollingTime);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckDVFS_Stop(
- + IN gckDVFS Dvfs
- + )
- +{
- + gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
- + gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
- +
- + Dvfs->stop = gcvTRUE;
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +#endif
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_precomp.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_precomp.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_precomp.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_precomp.h 2015-03-08 14:27:37.637684501 -0500
- @@ -0,0 +1,29 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_kernel_precomp_h_
- +#define __gc_hal_kernel_precomp_h_
- +
- +#include "gc_hal.h"
- +#include "gc_hal_driver.h"
- +#include "gc_hal_kernel.h"
- +
- +#endif /* __gc_hal_kernel_precomp_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c 2015-03-08 14:27:37.637684501 -0500
- @@ -0,0 +1,895 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal_kernel_precomp.h"
- +
- +#if gcdENABLE_VG
- +
- +#define ENABLE_VG_TRY_VIRTUAL_MEMORY 0
- +
- +#define _GC_OBJ_ZONE gcvZONE_VG
- +
- +/******************************************************************************\
- +******************************* gckKERNEL API Code ******************************
- +\******************************************************************************/
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_Construct
- +**
- +** Construct a new gckKERNEL object.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** IN gctPOINTER Context
- +** Pointer to a driver defined context.
- +**
- +** OUTPUT:
- +**
- +** gckKERNEL * Kernel
- +** Pointer to a variable that will hold the pointer to the gckKERNEL
- +** object.
- +*/
- +gceSTATUS gckVGKERNEL_Construct(
- + IN gckOS Os,
- + IN gctPOINTER Context,
- + IN gckKERNEL inKernel,
- + OUT gckVGKERNEL * Kernel
- + )
- +{
- + gceSTATUS status;
- + gckVGKERNEL kernel = gcvNULL;
- +
- + gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os, Context);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
- +
- + do
- + {
- + /* Allocate the gckKERNEL object. */
- + gcmkERR_BREAK(gckOS_Allocate(
- + Os,
- + sizeof(struct _gckVGKERNEL),
- + (gctPOINTER *) &kernel
- + ));
- +
- + /* Initialize the gckKERNEL object. */
- + kernel->object.type = gcvOBJ_KERNEL;
- + kernel->os = Os;
- + kernel->context = Context;
- + kernel->hardware = gcvNULL;
- + kernel->interrupt = gcvNULL;
- + kernel->command = gcvNULL;
- + kernel->mmu = gcvNULL;
- + kernel->kernel = inKernel;
- +
- + /* Construct the gckVGHARDWARE object. */
- + gcmkERR_BREAK(gckVGHARDWARE_Construct(
- + Os, &kernel->hardware
- + ));
- +
- + /* Set pointer to gckKERNEL object in gckVGHARDWARE object. */
- + kernel->hardware->kernel = kernel;
- +
- + /* Construct the gckVGINTERRUPT object. */
- + gcmkERR_BREAK(gckVGINTERRUPT_Construct(
- + kernel, &kernel->interrupt
- + ));
- +
- + /* Construct the gckVGCOMMAND object. */
- + gcmkERR_BREAK(gckVGCOMMAND_Construct(
- + kernel, gcmKB2BYTES(8), gcmKB2BYTES(2), &kernel->command
- + ));
- +
- + /* Construct the gckVGMMU object. */
- + gcmkERR_BREAK(gckVGMMU_Construct(
- + kernel, gcmKB2BYTES(32), &kernel->mmu
- + ));
- +
- + /* Return pointer to the gckKERNEL object. */
- + *Kernel = kernel;
- +
- + gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
- + /* Success. */
- + return gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + /* Roll back. */
- + if (kernel != gcvNULL)
- + {
- + if (kernel->mmu != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckVGMMU_Destroy(kernel->mmu));
- + }
- +
- + if (kernel->command != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckVGCOMMAND_Destroy(kernel->command));
- + }
- +
- + if (kernel->interrupt != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckVGINTERRUPT_Destroy(kernel->interrupt));
- + }
- +
- + if (kernel->hardware != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckVGHARDWARE_Destroy(kernel->hardware));
- + }
- +
- + gcmkVERIFY_OK(gckOS_Free(Os, kernel));
- + }
- +
- + gcmkFOOTER();
- + /* Return status. */
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_Destroy
- +**
- +** Destroy an gckKERNEL object.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object to destroy.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS gckVGKERNEL_Destroy(
- + IN gckVGKERNEL Kernel
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Kernel=0x%x", Kernel);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- +
- + do
- + {
- + /* Destroy the gckVGMMU object. */
- + if (Kernel->mmu != gcvNULL)
- + {
- + gcmkERR_BREAK(gckVGMMU_Destroy(Kernel->mmu));
- + Kernel->mmu = gcvNULL;
- + }
- +
- + /* Destroy the gckVGCOMMAND object. */
- + if (Kernel->command != gcvNULL)
- + {
- + gcmkERR_BREAK(gckVGCOMMAND_Destroy(Kernel->command));
- + Kernel->command = gcvNULL;
- + }
- +
- + /* Destroy the gckVGINTERRUPT object. */
- + if (Kernel->interrupt != gcvNULL)
- + {
- + gcmkERR_BREAK(gckVGINTERRUPT_Destroy(Kernel->interrupt));
- + Kernel->interrupt = gcvNULL;
- + }
- +
- + /* Destroy the gckVGHARDWARE object. */
- + if (Kernel->hardware != gcvNULL)
- + {
- + gcmkERR_BREAK(gckVGHARDWARE_Destroy(Kernel->hardware));
- + Kernel->hardware = gcvNULL;
- + }
- +
- + /* Mark the gckKERNEL object as unknown. */
- + Kernel->object.type = gcvOBJ_UNKNOWN;
- +
- + /* Free the gckKERNEL object. */
- + gcmkERR_BREAK(gckOS_Free(Kernel->os, Kernel));
- + }
- + while (gcvFALSE);
- +
- + gcmkFOOTER();
- +
- + /* Return status. */
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_AllocateLinearMemory
- +**
- +** Function walks all required memory pools and allocates the requested
- +** amount of video memory.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gcePOOL * Pool
- +** Pointer the desired memory pool.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes to allocate.
- +**
- +** gctSIZE_T Alignment
- +** Required buffer alignment.
- +**
- +** gceSURF_TYPE Type
- +** Surface type.
- +**
- +** OUTPUT:
- +**
- +** gcePOOL * Pool
- +** Pointer to the actual pool where the memory was allocated.
- +**
- +** gcuVIDMEM_NODE_PTR * Node
- +** Allocated node.
- +*/
- +gceSTATUS
- +gckKERNEL_AllocateLinearMemory(
- + IN gckKERNEL Kernel,
- + IN OUT gcePOOL * Pool,
- + IN gctSIZE_T Bytes,
- + IN gctSIZE_T Alignment,
- + IN gceSURF_TYPE Type,
- + OUT gcuVIDMEM_NODE_PTR * Node
- + )
- +{
- + gcePOOL pool;
- + gceSTATUS status;
- + gckVIDMEM videoMemory;
- +
- + /* Get initial pool. */
- + switch (pool = *Pool)
- + {
- + case gcvPOOL_DEFAULT:
- + case gcvPOOL_LOCAL:
- + pool = gcvPOOL_LOCAL_INTERNAL;
- + break;
- +
- + case gcvPOOL_UNIFIED:
- + pool = gcvPOOL_SYSTEM;
- + break;
- +
- + default:
- + break;
- + }
- +
- + do
- + {
- + /* Verify the number of bytes to allocate. */
- + if (Bytes == 0)
- + {
- + status = gcvSTATUS_INVALID_ARGUMENT;
- + break;
- + }
- +
- + if (pool == gcvPOOL_VIRTUAL)
- + {
- + /* Create a gcuVIDMEM_NODE for virtual memory. */
- + gcmkERR_BREAK(gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, Node));
- +
- + /* Success. */
- + break;
- + }
- +
- + else
- + {
- + /* Get pointer to gckVIDMEM object for pool. */
- + status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory);
- +
- + if (status == gcvSTATUS_OK)
- + {
- + if(*Pool == gcvPOOL_SYSTEM)
- + Type |= gcvSURF_VG;
- + /* Allocate memory. */
- + status = gckVIDMEM_AllocateLinear(videoMemory,
- + Bytes,
- + Alignment,
- + Type,
- + Node);
- +
- + if (status == gcvSTATUS_OK)
- + {
- + /* Memory allocated. */
- + break;
- + }
- + }
- + }
- +
- + if (pool == gcvPOOL_LOCAL_INTERNAL)
- + {
- + /* Advance to external memory. */
- + pool = gcvPOOL_LOCAL_EXTERNAL;
- + }
- + else if (pool == gcvPOOL_LOCAL_EXTERNAL)
- + {
- + /* Advance to contiguous system memory. */
- + pool = gcvPOOL_SYSTEM;
- + }
- + else if (pool == gcvPOOL_SYSTEM)
- + {
- + /* Advance to virtual memory. */
- +#if ENABLE_VG_TRY_VIRTUAL_MEMORY
- + pool = gcvPOOL_VIRTUAL;
- +#else
- + /*VG non-contiguous memory support is not ready yet, disable it temporary*/
- + status = gcvSTATUS_OUT_OF_MEMORY;
- + break;
- +#endif
- + }
- + else
- + {
- + /* Out of pools. */
- + status = gcvSTATUS_OUT_OF_MEMORY;
- + break;
- + }
- + }
- + /* Loop only for multiple selection pools. */
- + while ((*Pool == gcvPOOL_DEFAULT)
- + || (*Pool == gcvPOOL_LOCAL)
- + || (*Pool == gcvPOOL_UNIFIED)
- + );
- +
- + if (gcmIS_SUCCESS(status))
- + {
- + /* Return pool used for allocation. */
- + *Pool = pool;
- + }
- +
- + /* Return status. */
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_Dispatch
- +**
- +** Dispatch a command received from the user HAL layer.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gcsHAL_INTERFACE * Interface
- +** Pointer to a gcsHAL_INTERFACE structure that defines the command to
- +** be dispatched.
- +**
- +** OUTPUT:
- +**
- +** gcsHAL_INTERFACE * Interface
- +** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
- +** returned.
- +*/
- +gceSTATUS gckVGKERNEL_Dispatch(
- + IN gckKERNEL Kernel,
- + IN gctBOOL FromUser,
- + IN OUT gcsHAL_INTERFACE * Interface
- + )
- +{
- + gceSTATUS status;
- + gcsHAL_INTERFACE * kernelInterface = Interface;
- + gcuVIDMEM_NODE_PTR node;
- + gctUINT32 processID;
- + gckKERNEL kernel = Kernel;
- + gctPOINTER info = gcvNULL;
- + gctPHYS_ADDR physical = gcvNULL;
- + gctPOINTER logical = gcvNULL;
- + gctSIZE_T bytes = 0;
- +
- + gcmkHEADER_ARG("Kernel=0x%x Interface=0x%x ", Kernel, Interface);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
- +
- + gcmkONERROR(gckOS_GetProcessID(&processID));
- +
- + /* Dispatch on command. */
- + switch (Interface->command)
- + {
- + case gcvHAL_QUERY_VIDEO_MEMORY:
- + /* Query video memory size. */
- + gcmkERR_BREAK(gckKERNEL_QueryVideoMemory(
- + Kernel, kernelInterface
- + ));
- + break;
- +
- + case gcvHAL_QUERY_CHIP_IDENTITY:
- + /* Query chip identity. */
- + gcmkERR_BREAK(gckVGHARDWARE_QueryChipIdentity(
- + Kernel->vg->hardware,
- + &kernelInterface->u.QueryChipIdentity.chipModel,
- + &kernelInterface->u.QueryChipIdentity.chipRevision,
- + &kernelInterface->u.QueryChipIdentity.chipFeatures,
- + &kernelInterface->u.QueryChipIdentity.chipMinorFeatures,
- + &kernelInterface->u.QueryChipIdentity.chipMinorFeatures2
- + ));
- + break;
- +
- + case gcvHAL_QUERY_COMMAND_BUFFER:
- + /* Query command buffer information. */
- + gcmkERR_BREAK(gckKERNEL_QueryCommandBuffer(
- + Kernel,
- + &kernelInterface->u.QueryCommandBuffer.information
- + ));
- + break;
- + case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
- + bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes;
- + /* Allocate non-paged memory. */
- + gcmkERR_BREAK(gckOS_AllocateContiguous(
- + Kernel->os,
- + gcvTRUE,
- + &bytes,
- + &physical,
- + &logical
- + ));
- +
- + kernelInterface->u.AllocateNonPagedMemory.bytes = bytes;
- + kernelInterface->u.AllocateNonPagedMemory.logical = gcmPTR_TO_UINT64(logical);
- + kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
- + break;
- +
- + case gcvHAL_FREE_NON_PAGED_MEMORY:
- + physical = gcmNAME_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.physical);
- +
- + /* Unmap user logical out of physical memory first. */
- + gcmkERR_BREAK(gckOS_UnmapUserLogical(
- + Kernel->os,
- + physical,
- + (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
- + gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
- + ));
- +
- + /* Free non-paged memory. */
- + gcmkERR_BREAK(gckOS_FreeNonPagedMemory(
- + Kernel->os,
- + (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
- + physical,
- + gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
- + ));
- +
- + gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
- + break;
- +
- + case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
- + bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes;
- + /* Allocate contiguous memory. */
- + gcmkERR_BREAK(gckOS_AllocateContiguous(
- + Kernel->os,
- + gcvTRUE,
- + &bytes,
- + &physical,
- + &logical
- + ));
- +
- + kernelInterface->u.AllocateNonPagedMemory.bytes = bytes;
- + kernelInterface->u.AllocateNonPagedMemory.logical = gcmPTR_TO_UINT64(logical);
- + kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
- + break;
- +
- + case gcvHAL_FREE_CONTIGUOUS_MEMORY:
- + physical = gcmNAME_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.physical);
- + /* Unmap user logical out of physical memory first. */
- + gcmkERR_BREAK(gckOS_UnmapUserLogical(
- + Kernel->os,
- + physical,
- + (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
- + gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
- + ));
- +
- + /* Free contiguous memory. */
- + gcmkERR_BREAK(gckOS_FreeContiguous(
- + Kernel->os,
- + physical,
- + gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical),
- + (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes
- + ));
- +
- + gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
- + break;
- +
- + case gcvHAL_ALLOCATE_VIDEO_MEMORY:
- + {
- + gctSIZE_T bytes;
- + gctUINT32 bitsPerPixel;
- + gctUINT32 bits;
- +
- + /* Align width and height to tiles. */
- + gcmkERR_BREAK(gckVGHARDWARE_AlignToTile(
- + Kernel->vg->hardware,
- + kernelInterface->u.AllocateVideoMemory.type,
- + &kernelInterface->u.AllocateVideoMemory.width,
- + &kernelInterface->u.AllocateVideoMemory.height
- + ));
- +
- + /* Convert format into bytes per pixel and bytes per tile. */
- + gcmkERR_BREAK(gckVGHARDWARE_ConvertFormat(
- + Kernel->vg->hardware,
- + kernelInterface->u.AllocateVideoMemory.format,
- + &bitsPerPixel,
- + gcvNULL
- + ));
- +
- + /* Compute number of bits for the allocation. */
- + bits
- + = kernelInterface->u.AllocateVideoMemory.width
- + * kernelInterface->u.AllocateVideoMemory.height
- + * kernelInterface->u.AllocateVideoMemory.depth
- + * bitsPerPixel;
- +
- + /* Compute number of bytes for the allocation. */
- + bytes = gcmALIGN(bits, 8) / 8;
- +
- + /* Allocate memory. */
- + gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
- + Kernel,
- + &kernelInterface->u.AllocateVideoMemory.pool,
- + bytes,
- + 64,
- + kernelInterface->u.AllocateVideoMemory.type,
- + &node
- + ));
- +
- + kernelInterface->u.AllocateVideoMemory.node = gcmPTR_TO_UINT64(node);
- + }
- + break;
- +
- + case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
- + /* Allocate memory. */
- + gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
- + Kernel,
- + &kernelInterface->u.AllocateLinearVideoMemory.pool,
- + kernelInterface->u.AllocateLinearVideoMemory.bytes,
- + kernelInterface->u.AllocateLinearVideoMemory.alignment,
- + kernelInterface->u.AllocateLinearVideoMemory.type,
- + &node
- + ));
- +
- + gcmkERR_BREAK(gckKERNEL_AddProcessDB(Kernel,
- + processID, gcvDB_VIDEO_MEMORY,
- + node,
- + gcvNULL,
- + kernelInterface->u.AllocateLinearVideoMemory.bytes
- + ));
- +
- + kernelInterface->u.AllocateLinearVideoMemory.node = gcmPTR_TO_UINT64(node);
- + break;
- +
- + case gcvHAL_FREE_VIDEO_MEMORY:
- + node = gcmUINT64_TO_PTR(Interface->u.FreeVideoMemory.node);
- +#ifdef __QNXNTO__
- + /* Unmap the video memory */
- +
- + if ((node->VidMem.memory->object.type == gcvOBJ_VIDMEM) &&
- + (node->VidMem.logical != gcvNULL))
- + {
- + gckKERNEL_UnmapVideoMemory(Kernel,
- + node->VidMem.logical,
- + processID,
- + node->VidMem.bytes);
- + node->VidMem.logical = gcvNULL;
- + }
- +#endif /* __QNXNTO__ */
- +
- + /* Free video memory. */
- + gcmkERR_BREAK(gckVIDMEM_Free(
- + node
- + ));
- +
- + gcmkERR_BREAK(gckKERNEL_RemoveProcessDB(
- + Kernel,
- + processID, gcvDB_VIDEO_MEMORY,
- + node
- + ));
- +
- + break;
- +
- + case gcvHAL_MAP_MEMORY:
- + /* Map memory. */
- + gcmkERR_BREAK(gckKERNEL_MapMemory(
- + Kernel,
- + gcmINT2PTR(kernelInterface->u.MapMemory.physical),
- + (gctSIZE_T) kernelInterface->u.MapMemory.bytes,
- + &logical
- + ));
- + kernelInterface->u.MapMemory.logical = gcmPTR_TO_UINT64(logical);
- + break;
- +
- + case gcvHAL_UNMAP_MEMORY:
- + /* Unmap memory. */
- + gcmkERR_BREAK(gckKERNEL_UnmapMemory(
- + Kernel,
- + gcmINT2PTR(kernelInterface->u.MapMemory.physical),
- + (gctSIZE_T) kernelInterface->u.MapMemory.bytes,
- + gcmUINT64_TO_PTR(kernelInterface->u.MapMemory.logical)
- + ));
- + break;
- +
- + case gcvHAL_MAP_USER_MEMORY:
- + /* Map user memory to DMA. */
- + gcmkERR_BREAK(gckOS_MapUserMemory(
- + Kernel->os,
- + gcvCORE_VG,
- + gcmUINT64_TO_PTR(kernelInterface->u.MapUserMemory.memory),
- + kernelInterface->u.MapUserMemory.physical,
- + (gctSIZE_T) kernelInterface->u.MapUserMemory.size,
- + &info,
- + &kernelInterface->u.MapUserMemory.address
- + ));
- +
- + kernelInterface->u.MapUserMemory.info = gcmPTR_TO_NAME(info);
- + break;
- +
- + case gcvHAL_UNMAP_USER_MEMORY:
- + /* Unmap user memory. */
- + gcmkERR_BREAK(gckOS_UnmapUserMemory(
- + Kernel->os,
- + gcvCORE_VG,
- + gcmUINT64_TO_PTR(kernelInterface->u.UnmapUserMemory.memory),
- + (gctSIZE_T) kernelInterface->u.UnmapUserMemory.size,
- + gcmNAME_TO_PTR(kernelInterface->u.UnmapUserMemory.info),
- + kernelInterface->u.UnmapUserMemory.address
- + ));
- + gcmRELEASE_NAME(kernelInterface->u.UnmapUserMemory.info);
- + break;
- + case gcvHAL_LOCK_VIDEO_MEMORY:
- + node = gcmUINT64_TO_PTR(Interface->u.LockVideoMemory.node);
- +
- + /* Lock video memory. */
- + gcmkERR_BREAK(
- + gckVIDMEM_Lock(Kernel,
- + node,
- + gcvFALSE,
- + &Interface->u.LockVideoMemory.address));
- +
- + if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
- + {
- + /* Map video memory address into user space. */
- +#ifdef __QNXNTO__
- + if (node->VidMem.logical == gcvNULL)
- + {
- + gcmkONERROR(
- + gckKERNEL_MapVideoMemory(Kernel,
- + FromUser,
- + Interface->u.LockVideoMemory.address,
- + processID,
- + node->VidMem.bytes,
- + &node->VidMem.logical));
- + }
- +
- + Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(node->VidMem.logical);
- +#else
- + gcmkERR_BREAK(
- + gckKERNEL_MapVideoMemoryEx(Kernel,
- + gcvCORE_VG,
- + FromUser,
- + Interface->u.LockVideoMemory.address,
- + &logical));
- + Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(logical);
- +#endif
- + }
- + else
- + {
- + Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(node->Virtual.logical);
- +
- + /* Success. */
- + status = gcvSTATUS_OK;
- + }
- +
- +#if gcdSECURE_USER
- + /* Return logical address as physical address. */
- + Interface->u.LockVideoMemory.address =
- + (gctUINT32)(Interface->u.LockVideoMemory.memory);
- +#endif
- + gcmkERR_BREAK(
- + gckKERNEL_AddProcessDB(Kernel,
- + processID, gcvDB_VIDEO_MEMORY_LOCKED,
- + node,
- + gcvNULL,
- + 0));
- + break;
- +
- + case gcvHAL_UNLOCK_VIDEO_MEMORY:
- + /* Unlock video memory. */
- + node = gcmUINT64_TO_PTR(Interface->u.UnlockVideoMemory.node);
- +
- +#if gcdSECURE_USER
- + /* Save node information before it disappears. */
- + if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
- + {
- + logical = gcvNULL;
- + bytes = 0;
- + }
- + else
- + {
- + logical = node->Virtual.logical;
- + bytes = node->Virtual.bytes;
- + }
- +#endif
- +
- + /* Unlock video memory. */
- + gcmkERR_BREAK(
- + gckVIDMEM_Unlock(Kernel,
- + node,
- + Interface->u.UnlockVideoMemory.type,
- + &Interface->u.UnlockVideoMemory.asynchroneous));
- +
- +#if gcdSECURE_USER
- + /* Flush the translation cache for virtual surfaces. */
- + if (logical != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(Kernel,
- + cache,
- + logical,
- + bytes));
- + }
- +#endif
- +
- + if (Interface->u.UnlockVideoMemory.asynchroneous == gcvFALSE)
- + {
- + /* There isn't a event to unlock this node, remove record now */
- + gcmkERR_BREAK(
- + gckKERNEL_RemoveProcessDB(Kernel,
- + processID, gcvDB_VIDEO_MEMORY_LOCKED,
- + node));
- + }
- +
- + break;
- + case gcvHAL_USER_SIGNAL:
- +#if !USE_NEW_LINUX_SIGNAL
- + /* Dispatch depends on the user signal subcommands. */
- + switch(Interface->u.UserSignal.command)
- + {
- + case gcvUSER_SIGNAL_CREATE:
- + /* Create a signal used in the user space. */
- + gcmkERR_BREAK(
- + gckOS_CreateUserSignal(Kernel->os,
- + Interface->u.UserSignal.manualReset,
- + &Interface->u.UserSignal.id));
- +
- + gcmkVERIFY_OK(
- + gckKERNEL_AddProcessDB(Kernel,
- + processID, gcvDB_SIGNAL,
- + gcmINT2PTR(Interface->u.UserSignal.id),
- + gcvNULL,
- + 0));
- + break;
- +
- + case gcvUSER_SIGNAL_DESTROY:
- + /* Destroy the signal. */
- + gcmkERR_BREAK(
- + gckOS_DestroyUserSignal(Kernel->os,
- + Interface->u.UserSignal.id));
- +
- + gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
- + Kernel,
- + processID, gcvDB_SIGNAL,
- + gcmINT2PTR(Interface->u.UserSignal.id)));
- + break;
- +
- + case gcvUSER_SIGNAL_SIGNAL:
- + /* Signal the signal. */
- + gcmkERR_BREAK(
- + gckOS_SignalUserSignal(Kernel->os,
- + Interface->u.UserSignal.id,
- + Interface->u.UserSignal.state));
- + break;
- +
- + case gcvUSER_SIGNAL_WAIT:
- + /* Wait on the signal. */
- + status = gckOS_WaitUserSignal(Kernel->os,
- + Interface->u.UserSignal.id,
- + Interface->u.UserSignal.wait);
- + break;
- +
- + default:
- + /* Invalid user signal command. */
- + gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +#endif
- + break;
- +
- + case gcvHAL_COMMIT:
- + /* Commit a command and context buffer. */
- + gcmkERR_BREAK(gckVGCOMMAND_Commit(
- + Kernel->vg->command,
- + gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.context),
- + gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.queue),
- + kernelInterface->u.VGCommit.entryCount,
- + gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.taskTable)
- + ));
- + break;
- + case gcvHAL_VERSION:
- + kernelInterface->u.Version.major = gcvVERSION_MAJOR;
- + kernelInterface->u.Version.minor = gcvVERSION_MINOR;
- + kernelInterface->u.Version.patch = gcvVERSION_PATCH;
- + kernelInterface->u.Version.build = gcvVERSION_BUILD;
- + status = gcvSTATUS_OK;
- + break;
- +
- + case gcvHAL_GET_BASE_ADDRESS:
- + /* Get base address. */
- + gcmkERR_BREAK(
- + gckOS_GetBaseAddress(Kernel->os,
- + &kernelInterface->u.GetBaseAddress.baseAddress));
- + break;
- + default:
- + /* Invalid command. */
- + status = gcvSTATUS_INVALID_ARGUMENT;
- + }
- +
- +OnError:
- + /* Save status. */
- + kernelInterface->status = status;
- +
- + gcmkFOOTER();
- +
- + /* Return the status. */
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_QueryCommandBuffer
- +**
- +** Query command buffer attributes.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckVGHARDWARE object.
- +**
- +** OUTPUT:
- +**
- +** gcsCOMMAND_BUFFER_INFO_PTR Information
- +** Pointer to the information structure to receive buffer attributes.
- +*/
- +gceSTATUS
- +gckKERNEL_QueryCommandBuffer(
- + IN gckKERNEL Kernel,
- + OUT gcsCOMMAND_BUFFER_INFO_PTR Information
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Kernel=0x%x *Pool=0x%x",
- + Kernel, Information);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- +
- + /* Get the information. */
- + status = gckVGCOMMAND_QueryCommandBuffer(Kernel->vg->command, Information);
- +
- + gcmkFOOTER();
- + /* Return status. */
- + return status;
- +}
- +
- +#endif /* gcdENABLE_VG */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.h 2015-03-08 14:27:37.637684501 -0500
- @@ -0,0 +1,85 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_kernel_vg_h_
- +#define __gc_hal_kernel_vg_h_
- +
- +#include "gc_hal.h"
- +#include "gc_hal_driver.h"
- +#include "gc_hal_kernel_hardware.h"
- +
- +/******************************************************************************\
- +********************************** Structures **********************************
- +\******************************************************************************/
- +
- +/* gckKERNEL object. */
- +struct _gckVGKERNEL
- +{
- + /* Object. */
- + gcsOBJECT object;
- +
- + /* Pointer to gckOS object. */
- + gckOS os;
- +
- + /* Pointer to gckHARDWARE object. */
- + gckVGHARDWARE hardware;
- +
- + /* Pointer to gckINTERRUPT object. */
- + gckVGINTERRUPT interrupt;
- +
- + /* Pointer to gckCOMMAND object. */
- + gckVGCOMMAND command;
- +
- + /* Pointer to context. */
- + gctPOINTER context;
- +
- + /* Pointer to gckMMU object. */
- + gckVGMMU mmu;
- +
- + gckKERNEL kernel;
- +};
- +
- +/* gckMMU object. */
- +struct _gckVGMMU
- +{
- + /* The object. */
- + gcsOBJECT object;
- +
- + /* Pointer to gckOS object. */
- + gckOS os;
- +
- + /* Pointer to gckHARDWARE object. */
- + gckVGHARDWARE hardware;
- +
- + /* The page table mutex. */
- + gctPOINTER mutex;
- +
- + /* Page table information. */
- + gctSIZE_T pageTableSize;
- + gctPHYS_ADDR pageTablePhysical;
- + gctPOINTER pageTableLogical;
- +
- + /* Allocation index. */
- + gctUINT32 entryCount;
- + gctUINT32 entry;
- +};
- +
- +#endif /* __gc_hal_kernel_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c 2015-03-08 14:27:37.637684501 -0500
- @@ -0,0 +1,2264 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal_kernel_precomp.h"
- +
- +#define _GC_OBJ_ZONE gcvZONE_VIDMEM
- +
- +/******************************************************************************\
- +******************************* Private Functions ******************************
- +\******************************************************************************/
- +
- +/*******************************************************************************
- +**
- +** _Split
- +**
- +** Split a node on the required byte boundary.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gcuVIDMEM_NODE_PTR Node
- +** Pointer to the node to split.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes to keep in the node.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +**
- +** RETURNS:
- +**
- +** gctBOOL
- +** gcvTRUE if the node was split successfully, or gcvFALSE if there is an
- +** error.
- +**
- +*/
- +static gctBOOL
- +_Split(
- + IN gckOS Os,
- + IN gcuVIDMEM_NODE_PTR Node,
- + IN gctSIZE_T Bytes
- + )
- +{
- + gcuVIDMEM_NODE_PTR node;
- + gctPOINTER pointer = gcvNULL;
- +
- + /* Make sure the byte boundary makes sense. */
- + if ((Bytes <= 0) || (Bytes > Node->VidMem.bytes))
- + {
- + return gcvFALSE;
- + }
- +
- + /* Allocate a new gcuVIDMEM_NODE object. */
- + if (gcmIS_ERROR(gckOS_Allocate(Os,
- + gcmSIZEOF(gcuVIDMEM_NODE),
- + &pointer)))
- + {
- + /* Error. */
- + return gcvFALSE;
- + }
- +
- + node = pointer;
- +
- + /* Initialize gcuVIDMEM_NODE structure. */
- + node->VidMem.offset = Node->VidMem.offset + Bytes;
- + node->VidMem.bytes = Node->VidMem.bytes - Bytes;
- + node->VidMem.alignment = 0;
- + node->VidMem.locked = 0;
- + node->VidMem.memory = Node->VidMem.memory;
- + node->VidMem.pool = Node->VidMem.pool;
- + node->VidMem.physical = Node->VidMem.physical;
- +#ifdef __QNXNTO__
- +#if gcdUSE_VIDMEM_PER_PID
- + gcmkASSERT(Node->VidMem.physical != 0);
- + gcmkASSERT(Node->VidMem.logical != gcvNULL);
- + node->VidMem.processID = Node->VidMem.processID;
- + node->VidMem.physical = Node->VidMem.physical + Bytes;
- + node->VidMem.logical = Node->VidMem.logical + Bytes;
- +#else
- + node->VidMem.processID = 0;
- + node->VidMem.logical = gcvNULL;
- +#endif
- +#endif
- +
- + /* Insert node behind specified node. */
- + node->VidMem.next = Node->VidMem.next;
- + node->VidMem.prev = Node;
- + Node->VidMem.next = node->VidMem.next->VidMem.prev = node;
- +
- + /* Insert free node behind specified node. */
- + node->VidMem.nextFree = Node->VidMem.nextFree;
- + node->VidMem.prevFree = Node;
- + Node->VidMem.nextFree = node->VidMem.nextFree->VidMem.prevFree = node;
- +
- + /* Adjust size of specified node. */
- + Node->VidMem.bytes = Bytes;
- +
- + /* Success. */
- + return gcvTRUE;
- +}
- +
- +/*******************************************************************************
- +**
- +** _Merge
- +**
- +** Merge two adjacent nodes together.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gcuVIDMEM_NODE_PTR Node
- +** Pointer to the first of the two nodes to merge.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +**
- +*/
- +static gceSTATUS
- +_Merge(
- + IN gckOS Os,
- + IN gcuVIDMEM_NODE_PTR Node
- + )
- +{
- + gcuVIDMEM_NODE_PTR node;
- + gceSTATUS status;
- +
- + /* Save pointer to next node. */
- + node = Node->VidMem.next;
- +#if gcdUSE_VIDMEM_PER_PID
- + /* Check if the nodes are adjacent physically. */
- + if ( ((Node->VidMem.physical + Node->VidMem.bytes) != node->VidMem.physical) ||
- + ((Node->VidMem.logical + Node->VidMem.bytes) != node->VidMem.logical) )
- + {
- + /* Can't merge. */
- + return gcvSTATUS_OK;
- + }
- +#else
- +
- + /* This is a good time to make sure the heap is not corrupted. */
- + if (Node->VidMem.offset + Node->VidMem.bytes != node->VidMem.offset)
- + {
- + /* Corrupted heap. */
- + gcmkASSERT(
- + Node->VidMem.offset + Node->VidMem.bytes == node->VidMem.offset);
- + return gcvSTATUS_HEAP_CORRUPTED;
- + }
- +#endif
- +
- + /* Adjust byte count. */
- + Node->VidMem.bytes += node->VidMem.bytes;
- +
- + /* Unlink next node from linked list. */
- + Node->VidMem.next = node->VidMem.next;
- + Node->VidMem.nextFree = node->VidMem.nextFree;
- +
- + Node->VidMem.next->VidMem.prev =
- + Node->VidMem.nextFree->VidMem.prevFree = Node;
- +
- + /* Free next node. */
- + status = gcmkOS_SAFE_FREE(Os, node);
- + return status;
- +}
- +
- +/******************************************************************************\
- +******************************* gckVIDMEM API Code ******************************
- +\******************************************************************************/
- +
- +/*******************************************************************************
- +**
- +** gckVIDMEM_ConstructVirtual
- +**
- +** Construct a new gcuVIDMEM_NODE union for virtual memory.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gctSIZE_T Bytes
- +** Number of byte to allocate.
- +**
- +** OUTPUT:
- +**
- +** gcuVIDMEM_NODE_PTR * Node
- +** Pointer to a variable that receives the gcuVIDMEM_NODE union pointer.
- +*/
- +gceSTATUS
- +gckVIDMEM_ConstructVirtual(
- + IN gckKERNEL Kernel,
- + IN gctBOOL Contiguous,
- + IN gctSIZE_T Bytes,
- + OUT gcuVIDMEM_NODE_PTR * Node
- + )
- +{
- + gckOS os;
- + gceSTATUS status;
- + gcuVIDMEM_NODE_PTR node = gcvNULL;
- + gctPOINTER pointer = gcvNULL;
- + gctINT i;
- +
- + gcmkHEADER_ARG("Kernel=0x%x Contiguous=%d Bytes=%lu", Kernel, Contiguous, Bytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- + gcmkVERIFY_ARGUMENT(Node != gcvNULL);
- +
- + /* Extract the gckOS object pointer. */
- + os = Kernel->os;
- + gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
- +
- + /* Allocate an gcuVIDMEM_NODE union. */
- + gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcuVIDMEM_NODE), &pointer));
- +
- + node = pointer;
- +
- + /* Initialize gcuVIDMEM_NODE union for virtual memory. */
- + node->Virtual.kernel = Kernel;
- + node->Virtual.contiguous = Contiguous;
- + node->Virtual.logical = gcvNULL;
- +
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + node->Virtual.lockeds[i] = 0;
- + node->Virtual.pageTables[i] = gcvNULL;
- + node->Virtual.lockKernels[i] = gcvNULL;
- + }
- +
- + node->Virtual.mutex = gcvNULL;
- +
- + gcmkONERROR(gckOS_GetProcessID(&node->Virtual.processID));
- +
- +#ifdef __QNXNTO__
- + node->Virtual.next = gcvNULL;
- + node->Virtual.freePending = gcvFALSE;
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + node->Virtual.unlockPendings[i] = gcvFALSE;
- + }
- +#endif
- +
- + node->Virtual.freed = gcvFALSE;
- +
- + gcmkONERROR(gckOS_ZeroMemory(&node->Virtual.sharedInfo, gcmSIZEOF(gcsVIDMEM_NODE_SHARED_INFO)));
- +
- + /* Create the mutex. */
- + gcmkONERROR(
- + gckOS_CreateMutex(os, &node->Virtual.mutex));
- +
- + /* Allocate the virtual memory. */
- + gcmkONERROR(
- + gckOS_AllocatePagedMemoryEx(os,
- + node->Virtual.contiguous,
- + node->Virtual.bytes = Bytes,
- + &node->Virtual.physical));
- +
- +#ifdef __QNXNTO__
- + /* Register. */
- +#if gcdENABLE_VG
- + if (Kernel->core != gcvCORE_VG)
- +#endif
- + {
- + gckMMU_InsertNode(Kernel->mmu, node);
- + }
- +#endif
- +
- + /* Return pointer to the gcuVIDMEM_NODE union. */
- + *Node = node;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
- + "Created virtual node 0x%x for %u bytes @ 0x%x",
- + node, Bytes, node->Virtual.physical);
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Node=0x%x", *Node);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Roll back. */
- + if (node != gcvNULL)
- + {
- + if (node->Virtual.mutex != gcvNULL)
- + {
- + /* Destroy the mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(os, node->Virtual.mutex));
- + }
- +
- + /* Free the structure. */
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, node));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVIDMEM_DestroyVirtual
- +**
- +** Destroy an gcuVIDMEM_NODE union for virtual memory.
- +**
- +** INPUT:
- +**
- +** gcuVIDMEM_NODE_PTR Node
- +** Pointer to a gcuVIDMEM_NODE union.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckVIDMEM_DestroyVirtual(
- + IN gcuVIDMEM_NODE_PTR Node
- + )
- +{
- + gckOS os;
- + gctINT i;
- +
- + gcmkHEADER_ARG("Node=0x%x", Node);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Node->Virtual.kernel, gcvOBJ_KERNEL);
- +
- + /* Extact the gckOS object pointer. */
- + os = Node->Virtual.kernel->os;
- + gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
- +
- +#ifdef __QNXNTO__
- + /* Unregister. */
- +#if gcdENABLE_VG
- + if (Node->Virtual.kernel->core != gcvCORE_VG)
- +#endif
- + {
- + gcmkVERIFY_OK(
- + gckMMU_RemoveNode(Node->Virtual.kernel->mmu, Node));
- + }
- +#endif
- +
- + /* Delete the mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(os, Node->Virtual.mutex));
- +
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + if (Node->Virtual.pageTables[i] != gcvNULL)
- + {
- +#if gcdENABLE_VG
- + if (i == gcvCORE_VG)
- + {
- + /* Free the pages. */
- + gcmkVERIFY_OK(gckVGMMU_FreePages(Node->Virtual.lockKernels[i]->vg->mmu,
- + Node->Virtual.pageTables[i],
- + Node->Virtual.pageCount));
- + }
- + else
- +#endif
- + {
- + /* Free the pages. */
- + gcmkVERIFY_OK(gckMMU_FreePages(Node->Virtual.lockKernels[i]->mmu,
- + Node->Virtual.pageTables[i],
- + Node->Virtual.pageCount));
- + }
- + }
- + }
- +
- + /* Delete the gcuVIDMEM_NODE union. */
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, Node));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVIDMEM_Construct
- +**
- +** Construct a new gckVIDMEM object.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctUINT32 BaseAddress
- +** Base address for the video memory heap.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes in the video memory heap.
- +**
- +** gctSIZE_T Threshold
- +** Minimum number of bytes beyond am allocation before the node is
- +** split. Can be used as a minimum alignment requirement.
- +**
- +** gctSIZE_T BankSize
- +** Number of bytes per physical memory bank. Used by bank
- +** optimization.
- +**
- +** OUTPUT:
- +**
- +** gckVIDMEM * Memory
- +** Pointer to a variable that will hold the pointer to the gckVIDMEM
- +** object.
- +*/
- +gceSTATUS
- +gckVIDMEM_Construct(
- + IN gckOS Os,
- + IN gctUINT32 BaseAddress,
- + IN gctSIZE_T Bytes,
- + IN gctSIZE_T Threshold,
- + IN gctSIZE_T BankSize,
- + OUT gckVIDMEM * Memory
- + )
- +{
- + gckVIDMEM memory = gcvNULL;
- + gceSTATUS status;
- + gcuVIDMEM_NODE_PTR node;
- + gctINT i, banks = 0;
- + gctPOINTER pointer = gcvNULL;
- +
- + gcmkHEADER_ARG("Os=0x%x BaseAddress=%08x Bytes=%lu Threshold=%lu "
- + "BankSize=%lu",
- + Os, BaseAddress, Bytes, Threshold, BankSize);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- + gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
- +
- + /* Allocate the gckVIDMEM object. */
- + gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(struct _gckVIDMEM), &pointer));
- +
- + memory = pointer;
- +
- + /* Initialize the gckVIDMEM object. */
- + memory->object.type = gcvOBJ_VIDMEM;
- + memory->os = Os;
- +
- + /* Set video memory heap information. */
- + memory->baseAddress = BaseAddress;
- + memory->bytes = Bytes;
- + memory->freeBytes = Bytes;
- + memory->threshold = Threshold;
- + memory->mutex = gcvNULL;
- +#if gcdUSE_VIDMEM_PER_PID
- + gcmkONERROR(gckOS_GetProcessID(&memory->pid));
- +#endif
- +
- + BaseAddress = 0;
- +
- + /* Walk all possible banks. */
- + for (i = 0; i < gcmCOUNTOF(memory->sentinel); ++i)
- + {
- + gctSIZE_T bytes;
- +
- + if (BankSize == 0)
- + {
- + /* Use all bytes for the first bank. */
- + bytes = Bytes;
- + }
- + else
- + {
- + /* Compute number of bytes for this bank. */
- + bytes = gcmALIGN(BaseAddress + 1, BankSize) - BaseAddress;
- +
- + if (bytes > Bytes)
- + {
- + /* Make sure we don't exceed the total number of bytes. */
- + bytes = Bytes;
- + }
- + }
- +
- + if (bytes == 0)
- + {
- + /* Mark heap is not used. */
- + memory->sentinel[i].VidMem.next =
- + memory->sentinel[i].VidMem.prev =
- + memory->sentinel[i].VidMem.nextFree =
- + memory->sentinel[i].VidMem.prevFree = gcvNULL;
- + continue;
- + }
- +
- + /* Allocate one gcuVIDMEM_NODE union. */
- + gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcuVIDMEM_NODE), &pointer));
- +
- + node = pointer;
- +
- + /* Initialize gcuVIDMEM_NODE union. */
- + node->VidMem.memory = memory;
- +
- + node->VidMem.next =
- + node->VidMem.prev =
- + node->VidMem.nextFree =
- + node->VidMem.prevFree = &memory->sentinel[i];
- +
- + node->VidMem.offset = BaseAddress;
- + node->VidMem.bytes = bytes;
- + node->VidMem.alignment = 0;
- + node->VidMem.physical = 0;
- + node->VidMem.pool = gcvPOOL_UNKNOWN;
- +
- + node->VidMem.locked = 0;
- +
- +#if gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
- + node->VidMem.kernelVirtual = gcvNULL;
- +#endif
- +
- + gcmkONERROR(gckOS_ZeroMemory(&node->VidMem.sharedInfo, gcmSIZEOF(gcsVIDMEM_NODE_SHARED_INFO)));
- +
- +#ifdef __QNXNTO__
- +#if gcdUSE_VIDMEM_PER_PID
- + node->VidMem.processID = memory->pid;
- + node->VidMem.physical = memory->baseAddress + BaseAddress;
- + gcmkONERROR(gckOS_GetLogicalAddressProcess(Os,
- + node->VidMem.processID,
- + node->VidMem.physical,
- + &node->VidMem.logical));
- +#else
- + node->VidMem.processID = 0;
- + node->VidMem.logical = gcvNULL;
- +#endif
- +#endif
- +
- + /* Initialize the linked list of nodes. */
- + memory->sentinel[i].VidMem.next =
- + memory->sentinel[i].VidMem.prev =
- + memory->sentinel[i].VidMem.nextFree =
- + memory->sentinel[i].VidMem.prevFree = node;
- +
- + /* Mark sentinel. */
- + memory->sentinel[i].VidMem.bytes = 0;
- +
- + /* Adjust address for next bank. */
- + BaseAddress += bytes;
- + Bytes -= bytes;
- + banks ++;
- + }
- +
- + /* Assign all the bank mappings. */
- + memory->mapping[gcvSURF_RENDER_TARGET] = banks - 1;
- + memory->mapping[gcvSURF_BITMAP] = banks - 1;
- + if (banks > 1) --banks;
- + memory->mapping[gcvSURF_DEPTH] = banks - 1;
- + memory->mapping[gcvSURF_HIERARCHICAL_DEPTH] = banks - 1;
- + if (banks > 1) --banks;
- + memory->mapping[gcvSURF_TEXTURE] = banks - 1;
- + if (banks > 1) --banks;
- + memory->mapping[gcvSURF_VERTEX] = banks - 1;
- + if (banks > 1) --banks;
- + memory->mapping[gcvSURF_INDEX] = banks - 1;
- + if (banks > 1) --banks;
- + memory->mapping[gcvSURF_TILE_STATUS] = banks - 1;
- + if (banks > 1) --banks;
- + memory->mapping[gcvSURF_TYPE_UNKNOWN] = 0;
- +
- +#if gcdENABLE_VG
- + memory->mapping[gcvSURF_IMAGE] = 0;
- + memory->mapping[gcvSURF_MASK] = 0;
- + memory->mapping[gcvSURF_SCISSOR] = 0;
- +#endif
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
- + "[GALCORE] INDEX: bank %d",
- + memory->mapping[gcvSURF_INDEX]);
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
- + "[GALCORE] VERTEX: bank %d",
- + memory->mapping[gcvSURF_VERTEX]);
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
- + "[GALCORE] TEXTURE: bank %d",
- + memory->mapping[gcvSURF_TEXTURE]);
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
- + "[GALCORE] RENDER_TARGET: bank %d",
- + memory->mapping[gcvSURF_RENDER_TARGET]);
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
- + "[GALCORE] DEPTH: bank %d",
- + memory->mapping[gcvSURF_DEPTH]);
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
- + "[GALCORE] TILE_STATUS: bank %d",
- + memory->mapping[gcvSURF_TILE_STATUS]);
- +
- + /* Allocate the mutex. */
- + gcmkONERROR(gckOS_CreateMutex(Os, &memory->mutex));
- +
- + /* Return pointer to the gckVIDMEM object. */
- + *Memory = memory;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Roll back. */
- + if (memory != gcvNULL)
- + {
- + if (memory->mutex != gcvNULL)
- + {
- + /* Delete the mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Os, memory->mutex));
- + }
- +
- + for (i = 0; i < banks; ++i)
- + {
- + /* Free the heap. */
- + gcmkASSERT(memory->sentinel[i].VidMem.next != gcvNULL);
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, memory->sentinel[i].VidMem.next));
- + }
- +
- + /* Free the object. */
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, memory));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVIDMEM_Destroy
- +**
- +** Destroy an gckVIDMEM object.
- +**
- +** INPUT:
- +**
- +** gckVIDMEM Memory
- +** Pointer to an gckVIDMEM object to destroy.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckVIDMEM_Destroy(
- + IN gckVIDMEM Memory
- + )
- +{
- + gcuVIDMEM_NODE_PTR node, next;
- + gctINT i;
- +
- + gcmkHEADER_ARG("Memory=0x%x", Memory);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
- +
- + /* Walk all sentinels. */
- + for (i = 0; i < gcmCOUNTOF(Memory->sentinel); ++i)
- + {
- + /* Bail out of the heap is not used. */
- + if (Memory->sentinel[i].VidMem.next == gcvNULL)
- + {
- + break;
- + }
- +
- + /* Walk all the nodes until we reach the sentinel. */
- + for (node = Memory->sentinel[i].VidMem.next;
- + node->VidMem.bytes != 0;
- + node = next)
- + {
- + /* Save pointer to the next node. */
- + next = node->VidMem.next;
- +
- + /* Free the node. */
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Memory->os, node));
- + }
- + }
- +
- + /* Free the mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Memory->os, Memory->mutex));
- +
- + /* Mark the object as unknown. */
- + Memory->object.type = gcvOBJ_UNKNOWN;
- +
- + /* Free the gckVIDMEM object. */
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Memory->os, Memory));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVIDMEM_Allocate
- +**
- +** Allocate rectangular memory from the gckVIDMEM object.
- +**
- +** INPUT:
- +**
- +** gckVIDMEM Memory
- +** Pointer to an gckVIDMEM object.
- +**
- +** gctUINT Width
- +** Width of rectangle to allocate. Make sure the width is properly
- +** aligned.
- +**
- +** gctUINT Height
- +** Height of rectangle to allocate. Make sure the height is properly
- +** aligned.
- +**
- +** gctUINT Depth
- +** Depth of rectangle to allocate. This equals to the number of
- +** rectangles to allocate contiguously (i.e., for cubic maps and volume
- +** textures).
- +**
- +** gctUINT BytesPerPixel
- +** Number of bytes per pixel.
- +**
- +** gctUINT32 Alignment
- +** Byte alignment for allocation.
- +**
- +** gceSURF_TYPE Type
- +** Type of surface to allocate (use by bank optimization).
- +**
- +** OUTPUT:
- +**
- +** gcuVIDMEM_NODE_PTR * Node
- +** Pointer to a variable that will hold the allocated memory node.
- +*/
- +gceSTATUS
- +gckVIDMEM_Allocate(
- + IN gckVIDMEM Memory,
- + IN gctUINT Width,
- + IN gctUINT Height,
- + IN gctUINT Depth,
- + IN gctUINT BytesPerPixel,
- + IN gctUINT32 Alignment,
- + IN gceSURF_TYPE Type,
- + OUT gcuVIDMEM_NODE_PTR * Node
- + )
- +{
- + gctSIZE_T bytes;
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Memory=0x%x Width=%u Height=%u Depth=%u BytesPerPixel=%u "
- + "Alignment=%u Type=%d",
- + Memory, Width, Height, Depth, BytesPerPixel, Alignment,
- + Type);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
- + gcmkVERIFY_ARGUMENT(Width > 0);
- + gcmkVERIFY_ARGUMENT(Height > 0);
- + gcmkVERIFY_ARGUMENT(Depth > 0);
- + gcmkVERIFY_ARGUMENT(BytesPerPixel > 0);
- + gcmkVERIFY_ARGUMENT(Node != gcvNULL);
- +
- + /* Compute linear size. */
- + bytes = Width * Height * Depth * BytesPerPixel;
- +
- + /* Allocate through linear function. */
- + gcmkONERROR(
- + gckVIDMEM_AllocateLinear(Memory, bytes, Alignment, Type, Node));
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Node=0x%x", *Node);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +#if gcdENABLE_BANK_ALIGNMENT
- +
- +#if !gcdBANK_BIT_START
- +#error gcdBANK_BIT_START not defined.
- +#endif
- +
- +#if !gcdBANK_BIT_END
- +#error gcdBANK_BIT_END not defined.
- +#endif
- +/*******************************************************************************
- +** _GetSurfaceBankAlignment
- +**
- +** Return the required offset alignment required to the make BaseAddress
- +** aligned properly.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to gcoOS object.
- +**
- +** gceSURF_TYPE Type
- +** Type of allocation.
- +**
- +** gctUINT32 BaseAddress
- +** Base address of current video memory node.
- +**
- +** OUTPUT:
- +**
- +** gctUINT32_PTR AlignmentOffset
- +** Pointer to a variable that will hold the number of bytes to skip in
- +** the current video memory node in order to make the alignment bank
- +** aligned.
- +*/
- +static gceSTATUS
- +_GetSurfaceBankAlignment(
- + IN gceSURF_TYPE Type,
- + IN gctUINT32 BaseAddress,
- + OUT gctUINT32_PTR AlignmentOffset
- + )
- +{
- + gctUINT32 bank;
- + /* To retrieve the bank. */
- + static const gctUINT32 bankMask = (0xFFFFFFFF << gcdBANK_BIT_START)
- + ^ (0xFFFFFFFF << (gcdBANK_BIT_END + 1));
- +
- + /* To retrieve the bank and all the lower bytes. */
- + static const gctUINT32 byteMask = ~(0xFFFFFFFF << (gcdBANK_BIT_END + 1));
- +
- + gcmkHEADER_ARG("Type=%d BaseAddress=0x%x ", Type, BaseAddress);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_ARGUMENT(AlignmentOffset != gcvNULL);
- +
- + switch (Type)
- + {
- + case gcvSURF_RENDER_TARGET:
- + bank = (BaseAddress & bankMask) >> (gcdBANK_BIT_START);
- +
- + /* Align to the first bank. */
- + *AlignmentOffset = (bank == 0) ?
- + 0 :
- + ((1 << (gcdBANK_BIT_END + 1)) + 0) - (BaseAddress & byteMask);
- + break;
- +
- + case gcvSURF_DEPTH:
- + bank = (BaseAddress & bankMask) >> (gcdBANK_BIT_START);
- +
- + /* Align to the third bank. */
- + *AlignmentOffset = (bank == 2) ?
- + 0 :
- + ((1 << (gcdBANK_BIT_END + 1)) + (2 << gcdBANK_BIT_START)) - (BaseAddress & byteMask);
- +
- + /* Add a channel offset at the channel bit. */
- + *AlignmentOffset += (1 << gcdBANK_CHANNEL_BIT);
- + break;
- +
- + default:
- + /* no alignment needed. */
- + *AlignmentOffset = 0;
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER_ARG("*AlignmentOffset=%u", *AlignmentOffset);
- + return gcvSTATUS_OK;
- +}
- +#endif
- +
- +static gcuVIDMEM_NODE_PTR
- +_FindNode(
- + IN gckVIDMEM Memory,
- + IN gctINT Bank,
- + IN gctSIZE_T Bytes,
- + IN gceSURF_TYPE Type,
- + IN OUT gctUINT32_PTR Alignment
- + )
- +{
- + gcuVIDMEM_NODE_PTR node;
- + gctUINT32 alignment;
- +
- +#if gcdENABLE_BANK_ALIGNMENT
- + gctUINT32 bankAlignment;
- + gceSTATUS status;
- +#endif
- +
- + if (Memory->sentinel[Bank].VidMem.nextFree == gcvNULL)
- + {
- + /* No free nodes left. */
- + return gcvNULL;
- + }
- +
- +#if gcdENABLE_BANK_ALIGNMENT
- + /* Walk all free nodes until we have one that is big enough or we have
- + ** reached the sentinel. */
- + for (node = Memory->sentinel[Bank].VidMem.nextFree;
- + node->VidMem.bytes != 0;
- + node = node->VidMem.nextFree)
- + {
- + gcmkONERROR(_GetSurfaceBankAlignment(
- + Type,
- + node->VidMem.memory->baseAddress + node->VidMem.offset,
- + &bankAlignment));
- +
- + bankAlignment = gcmALIGN(bankAlignment, *Alignment);
- +
- + /* Compute number of bytes to skip for alignment. */
- + alignment = (*Alignment == 0)
- + ? 0
- + : (*Alignment - (node->VidMem.offset % *Alignment));
- +
- + if (alignment == *Alignment)
- + {
- + /* Node is already aligned. */
- + alignment = 0;
- + }
- +
- + if (node->VidMem.bytes >= Bytes + alignment + bankAlignment)
- + {
- + /* This node is big enough. */
- + *Alignment = alignment + bankAlignment;
- + return node;
- + }
- + }
- +#endif
- +
- + /* Walk all free nodes until we have one that is big enough or we have
- + reached the sentinel. */
- + for (node = Memory->sentinel[Bank].VidMem.nextFree;
- + node->VidMem.bytes != 0;
- + node = node->VidMem.nextFree)
- + {
- +
- + gctINT modulo = gckMATH_ModuloInt(node->VidMem.offset, *Alignment);
- +
- + /* Compute number of bytes to skip for alignment. */
- + alignment = (*Alignment == 0) ? 0 : (*Alignment - modulo);
- +
- + if (alignment == *Alignment)
- + {
- + /* Node is already aligned. */
- + alignment = 0;
- + }
- +
- + if (node->VidMem.bytes >= Bytes + alignment)
- + {
- + /* This node is big enough. */
- + *Alignment = alignment;
- + return node;
- + }
- + }
- +
- +#if gcdENABLE_BANK_ALIGNMENT
- +OnError:
- +#endif
- + /* Not enough memory. */
- + return gcvNULL;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVIDMEM_AllocateLinear
- +**
- +** Allocate linear memory from the gckVIDMEM object.
- +**
- +** INPUT:
- +**
- +** gckVIDMEM Memory
- +** Pointer to an gckVIDMEM object.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes to allocate.
- +**
- +** gctUINT32 Alignment
- +** Byte alignment for allocation.
- +**
- +** gceSURF_TYPE Type
- +** Type of surface to allocate (use by bank optimization).
- +**
- +** OUTPUT:
- +**
- +** gcuVIDMEM_NODE_PTR * Node
- +** Pointer to a variable that will hold the allocated memory node.
- +*/
- +gceSTATUS
- +gckVIDMEM_AllocateLinear(
- + IN gckVIDMEM Memory,
- + IN gctSIZE_T Bytes,
- + IN gctUINT32 Alignment,
- + IN gceSURF_TYPE Type,
- + OUT gcuVIDMEM_NODE_PTR * Node
- + )
- +{
- + gceSTATUS status;
- + gcuVIDMEM_NODE_PTR node;
- + gctUINT32 alignment;
- + gctINT bank, i;
- + gctBOOL acquired = gcvFALSE;
- +#if gcdSMALL_BLOCK_SIZE
- + gctBOOL force_allocate = (Type == gcvSURF_TILE_STATUS) || (Type & gcvSURF_VG);
- +#endif
- +
- + gcmkHEADER_ARG("Memory=0x%x Bytes=%lu Alignment=%u Type=%d",
- + Memory, Bytes, Alignment, Type);
- +
- + Type &= ~gcvSURF_VG;
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- + gcmkVERIFY_ARGUMENT(Node != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Type < gcvSURF_NUM_TYPES);
- +
- + /* Acquire the mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(Memory->os, Memory->mutex, gcvINFINITE));
- +
- + acquired = gcvTRUE;
- +#if !gcdUSE_VIDMEM_PER_PID
- +
- + if (Bytes > Memory->freeBytes)
- + {
- + /* Not enough memory. */
- + status = gcvSTATUS_OUT_OF_MEMORY;
- + goto OnError;
- + }
- +#endif
- +
- +#if gcdSMALL_BLOCK_SIZE
- + if ((!force_allocate) && (Memory->freeBytes < (Memory->bytes/gcdRATIO_FOR_SMALL_MEMORY))
- + && (Bytes >= gcdSMALL_BLOCK_SIZE)
- + )
- + {
- + /* The left memory is for small memory.*/
- + status = gcvSTATUS_OUT_OF_MEMORY;
- + goto OnError;
- + }
- +#endif
- +
- + /* Find the default bank for this surface type. */
- + gcmkASSERT((gctINT) Type < gcmCOUNTOF(Memory->mapping));
- + bank = Memory->mapping[Type];
- + alignment = Alignment;
- +
- +#if gcdUSE_VIDMEM_PER_PID
- + if (Bytes <= Memory->freeBytes)
- + {
- +#endif
- + /* Find a free node in the default bank. */
- + node = _FindNode(Memory, bank, Bytes, Type, &alignment);
- +
- + /* Out of memory? */
- + if (node == gcvNULL)
- + {
- + /* Walk all lower banks. */
- + for (i = bank - 1; i >= 0; --i)
- + {
- + /* Find a free node inside the current bank. */
- + node = _FindNode(Memory, i, Bytes, Type, &alignment);
- + if (node != gcvNULL)
- + {
- + break;
- + }
- + }
- + }
- +
- + if (node == gcvNULL)
- + {
- + /* Walk all upper banks. */
- + for (i = bank + 1; i < gcmCOUNTOF(Memory->sentinel); ++i)
- + {
- + if (Memory->sentinel[i].VidMem.nextFree == gcvNULL)
- + {
- + /* Abort when we reach unused banks. */
- + break;
- + }
- +
- + /* Find a free node inside the current bank. */
- + node = _FindNode(Memory, i, Bytes, Type, &alignment);
- + if (node != gcvNULL)
- + {
- + break;
- + }
- + }
- + }
- +#if gcdUSE_VIDMEM_PER_PID
- + }
- +#endif
- +
- + if (node == gcvNULL)
- + {
- + /* Out of memory. */
- +#if gcdUSE_VIDMEM_PER_PID
- + /* Allocate more memory from shared pool. */
- + gctSIZE_T bytes;
- + gctPHYS_ADDR physical_temp;
- + gctUINT32 physical;
- + gctPOINTER logical;
- +
- + bytes = gcmALIGN(Bytes, gcdUSE_VIDMEM_PER_PID_SIZE);
- +
- + gcmkONERROR(gckOS_AllocateContiguous(Memory->os,
- + gcvTRUE,
- + &bytes,
- + &physical_temp,
- + &logical));
- +
- + /* physical address is returned as 0 for user space. workaround. */
- + if (physical_temp == gcvNULL)
- + {
- + gcmkONERROR(gckOS_GetPhysicalAddress(Memory->os, logical, &physical));
- + }
- +
- + /* Allocate one gcuVIDMEM_NODE union. */
- + gcmkONERROR(
- + gckOS_Allocate(Memory->os,
- + gcmSIZEOF(gcuVIDMEM_NODE),
- + (gctPOINTER *) &node));
- +
- + /* Initialize gcuVIDMEM_NODE union. */
- + node->VidMem.memory = Memory;
- +
- + node->VidMem.offset = 0;
- + node->VidMem.bytes = bytes;
- + node->VidMem.alignment = 0;
- + node->VidMem.physical = physical;
- + node->VidMem.pool = gcvPOOL_UNKNOWN;
- +
- + node->VidMem.locked = 0;
- +
- +#ifdef __QNXNTO__
- + gcmkONERROR(gckOS_GetProcessID(&node->VidMem.processID));
- + node->VidMem.logical = logical;
- + gcmkASSERT(logical != gcvNULL);
- +#endif
- +
- + /* Insert node behind sentinel node. */
- + node->VidMem.next = Memory->sentinel[bank].VidMem.next;
- + node->VidMem.prev = &Memory->sentinel[bank];
- + Memory->sentinel[bank].VidMem.next = node->VidMem.next->VidMem.prev = node;
- +
- + /* Insert free node behind sentinel node. */
- + node->VidMem.nextFree = Memory->sentinel[bank].VidMem.nextFree;
- + node->VidMem.prevFree = &Memory->sentinel[bank];
- + Memory->sentinel[bank].VidMem.nextFree = node->VidMem.nextFree->VidMem.prevFree = node;
- +
- + Memory->freeBytes += bytes;
- +#else
- + status = gcvSTATUS_OUT_OF_MEMORY;
- + goto OnError;
- +#endif
- + }
- +
- + /* Do we have an alignment? */
- + if (alignment > 0)
- + {
- + /* Split the node so it is aligned. */
- + if (_Split(Memory->os, node, alignment))
- + {
- + /* Successful split, move to aligned node. */
- + node = node->VidMem.next;
- +
- + /* Remove alignment. */
- + alignment = 0;
- + }
- + }
- +
- + /* Do we have enough memory after the allocation to split it? */
- + if (node->VidMem.bytes - Bytes > Memory->threshold)
- + {
- + /* Adjust the node size. */
- + _Split(Memory->os, node, Bytes);
- + }
- +
- + /* Remove the node from the free list. */
- + node->VidMem.prevFree->VidMem.nextFree = node->VidMem.nextFree;
- + node->VidMem.nextFree->VidMem.prevFree = node->VidMem.prevFree;
- + node->VidMem.nextFree =
- + node->VidMem.prevFree = gcvNULL;
- +
- + /* Fill in the information. */
- + node->VidMem.alignment = alignment;
- + node->VidMem.memory = Memory;
- +#ifdef __QNXNTO__
- +#if !gcdUSE_VIDMEM_PER_PID
- + node->VidMem.logical = gcvNULL;
- + gcmkONERROR(gckOS_GetProcessID(&node->VidMem.processID));
- +#else
- + gcmkASSERT(node->VidMem.logical != gcvNULL);
- +#endif
- +#endif
- +
- + /* Adjust the number of free bytes. */
- + Memory->freeBytes -= node->VidMem.bytes;
- +
- + node->VidMem.freePending = gcvFALSE;
- +
- +#if gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
- + node->VidMem.kernelVirtual = gcvNULL;
- +#endif
- +
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
- +
- + /* Return the pointer to the node. */
- + *Node = node;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
- + "Allocated %u bytes @ 0x%x [0x%08X]",
- + node->VidMem.bytes, node, node->VidMem.offset);
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Node=0x%x", *Node);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVIDMEM_Free
- +**
- +** Free an allocated video memory node.
- +**
- +** INPUT:
- +**
- +** gcuVIDMEM_NODE_PTR Node
- +** Pointer to a gcuVIDMEM_NODE object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckVIDMEM_Free(
- + IN gcuVIDMEM_NODE_PTR Node
- + )
- +{
- + gceSTATUS status;
- + gckKERNEL kernel = gcvNULL;
- + gckVIDMEM memory = gcvNULL;
- + gcuVIDMEM_NODE_PTR node;
- + gctBOOL mutexAcquired = gcvFALSE;
- + gckOS os = gcvNULL;
- + gctBOOL acquired = gcvFALSE;
- + gctINT32 i, totalLocked;
- +
- + gcmkHEADER_ARG("Node=0x%x", Node);
- +
- + /* Verify the arguments. */
- + if ((Node == gcvNULL)
- + || (Node->VidMem.memory == gcvNULL)
- + )
- + {
- + /* Invalid object. */
- + gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
- + }
- +
- + /**************************** Video Memory ********************************/
- +
- + if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
- + {
- + if (Node->VidMem.locked > 0)
- + {
- + /* Client still has a lock, defer free op 'till when lock reaches 0. */
- + Node->VidMem.freePending = gcvTRUE;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
- + "Node 0x%x is locked (%d)... deferring free.",
- + Node, Node->VidMem.locked);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- +
- + /* Extract pointer to gckVIDMEM object owning the node. */
- + memory = Node->VidMem.memory;
- +
- + /* Acquire the mutex. */
- + gcmkONERROR(
- + gckOS_AcquireMutex(memory->os, memory->mutex, gcvINFINITE));
- +
- + mutexAcquired = gcvTRUE;
- +
- +#ifdef __QNXNTO__
- +#if !gcdUSE_VIDMEM_PER_PID
- + /* Reset. */
- + Node->VidMem.processID = 0;
- + Node->VidMem.logical = gcvNULL;
- +#endif
- +
- + /* Don't try to re-free an already freed node. */
- + if ((Node->VidMem.nextFree == gcvNULL)
- + && (Node->VidMem.prevFree == gcvNULL)
- + )
- +#endif
- + {
- +#if gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
- + if (Node->VidMem.kernelVirtual)
- + {
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
- + "%s(%d) Unmap %x from kernel space.",
- + __FUNCTION__, __LINE__,
- + Node->VidMem.kernelVirtual);
- +
- + gcmkVERIFY_OK(
- + gckOS_UnmapPhysical(memory->os,
- + Node->VidMem.kernelVirtual,
- + Node->VidMem.bytes));
- +
- + Node->VidMem.kernelVirtual = gcvNULL;
- + }
- +#endif
- +
- + /* Check if Node is already freed. */
- + if (Node->VidMem.nextFree)
- + {
- + /* Node is alread freed. */
- + gcmkONERROR(gcvSTATUS_INVALID_DATA);
- + }
- +
- + /* Update the number of free bytes. */
- + memory->freeBytes += Node->VidMem.bytes;
- +
- + /* Find the next free node. */
- + for (node = Node->VidMem.next;
- + node != gcvNULL && node->VidMem.nextFree == gcvNULL;
- + node = node->VidMem.next) ;
- +
- + /* Insert this node in the free list. */
- + Node->VidMem.nextFree = node;
- + Node->VidMem.prevFree = node->VidMem.prevFree;
- +
- + Node->VidMem.prevFree->VidMem.nextFree =
- + node->VidMem.prevFree = Node;
- +
- + /* Is the next node a free node and not the sentinel? */
- + if ((Node->VidMem.next == Node->VidMem.nextFree)
- + && (Node->VidMem.next->VidMem.bytes != 0)
- + )
- + {
- + /* Merge this node with the next node. */
- + gcmkONERROR(_Merge(memory->os, node = Node));
- + gcmkASSERT(node->VidMem.nextFree != node);
- + gcmkASSERT(node->VidMem.prevFree != node);
- + }
- +
- + /* Is the previous node a free node and not the sentinel? */
- + if ((Node->VidMem.prev == Node->VidMem.prevFree)
- + && (Node->VidMem.prev->VidMem.bytes != 0)
- + )
- + {
- + /* Merge this node with the previous node. */
- + gcmkONERROR(_Merge(memory->os, node = Node->VidMem.prev));
- + gcmkASSERT(node->VidMem.nextFree != node);
- + gcmkASSERT(node->VidMem.prevFree != node);
- + }
- + }
- +
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(memory->os, memory->mutex));
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
- + "Node 0x%x is freed.",
- + Node);
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- +
- + /*************************** Virtual Memory *******************************/
- +
- + /* Get gckKERNEL object. */
- + kernel = Node->Virtual.kernel;
- +
- + /* Verify the gckKERNEL object pointer. */
- + gcmkVERIFY_OBJECT(kernel, gcvOBJ_KERNEL);
- +
- + /* Get the gckOS object pointer. */
- + os = kernel->os;
- + gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
- +
- + /* Grab the mutex. */
- + gcmkONERROR(
- + gckOS_AcquireMutex(os, Node->Virtual.mutex, gcvINFINITE));
- +
- + acquired = gcvTRUE;
- +
- + for (i = 0, totalLocked = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + totalLocked += Node->Virtual.lockeds[i];
- + }
- +
- + if (totalLocked > 0)
- + {
- + gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_VIDMEM,
- + "gckVIDMEM_Free: Virtual node 0x%x is locked (%d)",
- + Node, totalLocked);
- +
- + /* Set Flag */
- + Node->Virtual.freed = gcvTRUE;
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
- + }
- + else
- + {
- + /* Free the virtual memory. */
- + gcmkVERIFY_OK(gckOS_FreePagedMemory(kernel->os,
- + Node->Virtual.physical,
- + Node->Virtual.bytes));
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
- +
- + /* Destroy the gcuVIDMEM_NODE union. */
- + gcmkVERIFY_OK(gckVIDMEM_DestroyVirtual(Node));
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (mutexAcquired)
- + {
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(
- + memory->os, memory->mutex
- + ));
- + }
- +
- + if (acquired)
- + {
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +
- +#ifdef __QNXNTO__
- +/*******************************************************************************
- +**
- +** gcoVIDMEM_FreeHandleMemory
- +**
- +** Free all allocated video memory nodes for a handle.
- +**
- +** INPUT:
- +**
- +** gcoVIDMEM Memory
- +** Pointer to an gcoVIDMEM object..
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckVIDMEM_FreeHandleMemory(
- + IN gckKERNEL Kernel,
- + IN gckVIDMEM Memory,
- + IN gctUINT32 Pid
- + )
- +{
- + gceSTATUS status;
- + gctBOOL mutex = gcvFALSE;
- + gcuVIDMEM_NODE_PTR node;
- + gctINT i;
- + gctUINT32 nodeCount = 0, byteCount = 0;
- + gctBOOL again;
- +
- + gcmkHEADER_ARG("Kernel=0x%x, Memory=0x%x Pid=0x%u", Kernel, Memory, Pid);
- +
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
- +
- + gcmkONERROR(gckOS_AcquireMutex(Memory->os, Memory->mutex, gcvINFINITE));
- + mutex = gcvTRUE;
- +
- + /* Walk all sentinels. */
- + for (i = 0; i < gcmCOUNTOF(Memory->sentinel); ++i)
- + {
- + /* Bail out of the heap if it is not used. */
- + if (Memory->sentinel[i].VidMem.next == gcvNULL)
- + {
- + break;
- + }
- +
- + do
- + {
- + again = gcvFALSE;
- +
- + /* Walk all the nodes until we reach the sentinel. */
- + for (node = Memory->sentinel[i].VidMem.next;
- + node->VidMem.bytes != 0;
- + node = node->VidMem.next)
- + {
- + /* Free the node if it was allocated by Handle. */
- + if (node->VidMem.processID == Pid)
- + {
- + /* Unlock video memory. */
- + while (node->VidMem.locked > 0)
- + {
- + gckVIDMEM_Unlock(Kernel, node, gcvSURF_TYPE_UNKNOWN, gcvNULL);
- + }
- +
- + nodeCount++;
- + byteCount += node->VidMem.bytes;
- +
- + /* Free video memory. */
- + gcmkVERIFY_OK(gckVIDMEM_Free(node));
- +
- + /*
- + * Freeing may cause a merge which will invalidate our iteration.
- + * Don't be clever, just restart.
- + */
- + again = gcvTRUE;
- +
- + break;
- + }
- +#if gcdUSE_VIDMEM_PER_PID
- + else
- + {
- + gcmkASSERT(node->VidMem.processID == Pid);
- + }
- +#endif
- + }
- + }
- + while (again);
- + }
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
- + gcmkFOOTER();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (mutex)
- + {
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +#endif
- +
- +/*******************************************************************************
- +**
- +** _NeedVirtualMapping
- +**
- +** Whether setup GPU page table for video node.
- +**
- +** INPUT:
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gcuVIDMEM_NODE_PTR Node
- +** Pointer to a gcuVIDMEM_NODE union.
- +**
- +** gceCORE Core
- +** Id of current GPU.
- +**
- +** OUTPUT:
- +** gctBOOL * NeedMapping
- +** A pointer hold the result whether Node should be mapping.
- +*/
- +static gceSTATUS
- +_NeedVirtualMapping(
- + IN gckKERNEL Kernel,
- + IN gceCORE Core,
- + IN gcuVIDMEM_NODE_PTR Node,
- + OUT gctBOOL * NeedMapping
- +)
- +{
- + gceSTATUS status;
- + gctUINT32 phys;
- + gctUINT32 end;
- + gcePOOL pool;
- + gctUINT32 offset;
- + gctUINT32 baseAddress;
- +
- + gcmkHEADER_ARG("Node=0x%X", Node);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Node != gcvNULL);
- + gcmkVERIFY_ARGUMENT(NeedMapping != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Core < gcdMAX_GPU_COUNT);
- +
- + if (Node->Virtual.contiguous)
- + {
- +#if gcdENABLE_VG
- + if (Core == gcvCORE_VG)
- + {
- + *NeedMapping = gcvFALSE;
- + }
- + else
- +#endif
- + {
- + /* Convert logical address into a physical address. */
- + gcmkONERROR(
- + gckOS_GetPhysicalAddress(Kernel->os, Node->Virtual.logical, &phys));
- +
- + gcmkONERROR(gckOS_GetBaseAddress(Kernel->os, &baseAddress));
- +
- + gcmkASSERT(phys >= baseAddress);
- +
- + /* Subtract baseAddress to get a GPU address used for programming. */
- + phys -= baseAddress;
- +
- + /* If part of region is belong to gcvPOOL_VIRTUAL,
- + ** whole region has to be mapped. */
- + end = phys + Node->Virtual.bytes - 1;
- +
- + gcmkONERROR(gckHARDWARE_SplitMemory(
- + Kernel->hardware, end, &pool, &offset
- + ));
- +
- + *NeedMapping = (pool == gcvPOOL_VIRTUAL);
- + }
- + }
- + else
- + {
- + *NeedMapping = gcvTRUE;
- + }
- +
- + gcmkFOOTER_ARG("*NeedMapping=%d", *NeedMapping);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVIDMEM_Lock
- +**
- +** Lock a video memory node and return its hardware specific address.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gcuVIDMEM_NODE_PTR Node
- +** Pointer to a gcuVIDMEM_NODE union.
- +**
- +** OUTPUT:
- +**
- +** gctUINT32 * Address
- +** Pointer to a variable that will hold the hardware specific address.
- +*/
- +gceSTATUS
- +gckVIDMEM_Lock(
- + IN gckKERNEL Kernel,
- + IN gcuVIDMEM_NODE_PTR Node,
- + IN gctBOOL Cacheable,
- + OUT gctUINT32 * Address
- + )
- +{
- + gceSTATUS status;
- + gctBOOL acquired = gcvFALSE;
- + gctBOOL locked = gcvFALSE;
- + gckOS os = gcvNULL;
- + gctBOOL needMapping;
- + gctUINT32 baseAddress;
- +
- + gcmkHEADER_ARG("Node=0x%x", Node);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_ARGUMENT(Address != gcvNULL);
- +
- + if ((Node == gcvNULL)
- + || (Node->VidMem.memory == gcvNULL)
- + )
- + {
- + /* Invalid object. */
- + gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
- + }
- +
- + /**************************** Video Memory ********************************/
- +
- + if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
- + {
- + if (Cacheable == gcvTRUE)
- + {
- + gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
- + }
- +
- + /* Increment the lock count. */
- + Node->VidMem.locked ++;
- +
- + /* Return the physical address of the node. */
- +#if !gcdUSE_VIDMEM_PER_PID
- + *Address = Node->VidMem.memory->baseAddress
- + + Node->VidMem.offset
- + + Node->VidMem.alignment;
- +#else
- + *Address = Node->VidMem.physical;
- +#endif
- +
- + /* Get hardware specific address. */
- +#if gcdENABLE_VG
- + if (Kernel->vg == gcvNULL)
- +#endif
- + {
- + if (Kernel->hardware->mmuVersion == 0)
- + {
- + /* Convert physical to GPU address for old mmu. */
- + gcmkONERROR(gckOS_GetBaseAddress(Kernel->os, &baseAddress));
- + gcmkASSERT(*Address > baseAddress);
- + *Address -= baseAddress;
- + }
- + }
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
- + "Locked node 0x%x (%d) @ 0x%08X",
- + Node,
- + Node->VidMem.locked,
- + *Address);
- + }
- +
- + /*************************** Virtual Memory *******************************/
- +
- + else
- + {
- + /* Verify the gckKERNEL object pointer. */
- + gcmkVERIFY_OBJECT(Node->Virtual.kernel, gcvOBJ_KERNEL);
- +
- + /* Extract the gckOS object pointer. */
- + os = Node->Virtual.kernel->os;
- + gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
- +
- + /* Grab the mutex. */
- + gcmkONERROR(gckOS_AcquireMutex(os, Node->Virtual.mutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- +#if gcdPAGED_MEMORY_CACHEABLE
- + /* Force video memory cacheable. */
- + Cacheable = gcvTRUE;
- +#endif
- +
- + gcmkONERROR(
- + gckOS_LockPages(os,
- + Node->Virtual.physical,
- + Node->Virtual.bytes,
- + Cacheable,
- + &Node->Virtual.logical,
- + &Node->Virtual.pageCount));
- +
- + /* Increment the lock count. */
- + if (Node->Virtual.lockeds[Kernel->core] ++ == 0)
- + {
- + /* Is this node pending for a final unlock? */
- +#ifdef __QNXNTO__
- + if (!Node->Virtual.contiguous && Node->Virtual.unlockPendings[Kernel->core])
- + {
- + /* Make sure we have a page table. */
- + gcmkASSERT(Node->Virtual.pageTables[Kernel->core] != gcvNULL);
- +
- + /* Remove pending unlock. */
- + Node->Virtual.unlockPendings[Kernel->core] = gcvFALSE;
- + }
- +
- + /* First lock - create a page table. */
- + gcmkASSERT(Node->Virtual.pageTables[Kernel->core] == gcvNULL);
- +
- + /* Make sure we mark our node as not flushed. */
- + Node->Virtual.unlockPendings[Kernel->core] = gcvFALSE;
- +#endif
- +
- + locked = gcvTRUE;
- +
- + gcmkONERROR(_NeedVirtualMapping(Kernel, Kernel->core, Node, &needMapping));
- +
- + if (needMapping == gcvFALSE)
- + {
- + /* Get hardware specific address. */
- +#if gcdENABLE_VG
- + if (Kernel->vg != gcvNULL)
- + {
- + gcmkONERROR(gckVGHARDWARE_ConvertLogical(Kernel->vg->hardware,
- + Node->Virtual.logical,
- + &Node->Virtual.addresses[Kernel->core]));
- + }
- + else
- +#endif
- + {
- + gcmkONERROR(gckHARDWARE_ConvertLogical(Kernel->hardware,
- + Node->Virtual.logical,
- + &Node->Virtual.addresses[Kernel->core]));
- + }
- + }
- + else
- + {
- +#if gcdENABLE_VG
- + if (Kernel->vg != gcvNULL)
- + {
- + /* Allocate pages inside the MMU. */
- + gcmkONERROR(
- + gckVGMMU_AllocatePages(Kernel->vg->mmu,
- + Node->Virtual.pageCount,
- + &Node->Virtual.pageTables[Kernel->core],
- + &Node->Virtual.addresses[Kernel->core]));
- + }
- + else
- +#endif
- + {
- + /* Allocate pages inside the MMU. */
- + gcmkONERROR(
- + gckMMU_AllocatePagesEx(Kernel->mmu,
- + Node->Virtual.pageCount,
- + Node->Virtual.type,
- + &Node->Virtual.pageTables[Kernel->core],
- + &Node->Virtual.addresses[Kernel->core]));
- + }
- +
- + Node->Virtual.lockKernels[Kernel->core] = Kernel;
- +
- + /* Map the pages. */
- +#ifdef __QNXNTO__
- + gcmkONERROR(
- + gckOS_MapPagesEx(os,
- + Kernel->core,
- + Node->Virtual.physical,
- + Node->Virtual.logical,
- + Node->Virtual.pageCount,
- + Node->Virtual.pageTables[Kernel->core]));
- +#else
- + gcmkONERROR(
- + gckOS_MapPagesEx(os,
- + Kernel->core,
- + Node->Virtual.physical,
- + Node->Virtual.pageCount,
- + Node->Virtual.pageTables[Kernel->core]));
- +#endif
- +
- +#if gcdENABLE_VG
- + if (Kernel->core == gcvCORE_VG)
- + {
- + gcmkONERROR(gckVGMMU_Flush(Kernel->vg->mmu));
- + }
- + else
- +#endif
- + {
- + gcmkONERROR(gckMMU_Flush(Kernel->mmu));
- + }
- + }
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
- + "Mapped virtual node 0x%x to 0x%08X",
- + Node,
- + Node->Virtual.addresses[Kernel->core]);
- + }
- +
- + /* Return hardware address. */
- + *Address = Node->Virtual.addresses[Kernel->core];
- +
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Address=%08x", *Address);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (locked)
- + {
- + if (Node->Virtual.pageTables[Kernel->core] != gcvNULL)
- + {
- +#if gcdENABLE_VG
- + if (Kernel->vg != gcvNULL)
- + {
- + /* Free the pages from the MMU. */
- + gcmkVERIFY_OK(
- + gckVGMMU_FreePages(Kernel->vg->mmu,
- + Node->Virtual.pageTables[Kernel->core],
- + Node->Virtual.pageCount));
- + }
- + else
- +#endif
- + {
- + /* Free the pages from the MMU. */
- + gcmkVERIFY_OK(
- + gckMMU_FreePages(Kernel->mmu,
- + Node->Virtual.pageTables[Kernel->core],
- + Node->Virtual.pageCount));
- + }
- + Node->Virtual.pageTables[Kernel->core] = gcvNULL;
- + Node->Virtual.lockKernels[Kernel->core] = gcvNULL;
- + }
- +
- + /* Unlock the pages. */
- + gcmkVERIFY_OK(
- + gckOS_UnlockPages(os,
- + Node->Virtual.physical,
- + Node->Virtual.bytes,
- + Node->Virtual.logical
- + ));
- +
- + Node->Virtual.lockeds[Kernel->core]--;
- + }
- +
- + if (acquired)
- + {
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckVIDMEM_Unlock
- +**
- +** Unlock a video memory node.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gcuVIDMEM_NODE_PTR Node
- +** Pointer to a locked gcuVIDMEM_NODE union.
- +**
- +** gceSURF_TYPE Type
- +** Type of surface to unlock.
- +**
- +** gctBOOL * Asynchroneous
- +** Pointer to a variable specifying whether the surface should be
- +** unlocked asynchroneously or not.
- +**
- +** OUTPUT:
- +**
- +** gctBOOL * Asynchroneous
- +** Pointer to a variable receiving the number of bytes used in the
- +** command buffer specified by 'Commands'. If gcvNULL, there is no
- +** command buffer.
- +*/
- +gceSTATUS
- +gckVIDMEM_Unlock(
- + IN gckKERNEL Kernel,
- + IN gcuVIDMEM_NODE_PTR Node,
- + IN gceSURF_TYPE Type,
- + IN OUT gctBOOL * Asynchroneous
- + )
- +{
- + gceSTATUS status;
- + gckHARDWARE hardware;
- + gctPOINTER buffer;
- + gctSIZE_T requested, bufferSize;
- + gckCOMMAND command = gcvNULL;
- + gceKERNEL_FLUSH flush;
- + gckOS os = gcvNULL;
- + gctBOOL acquired = gcvFALSE;
- + gctBOOL commitEntered = gcvFALSE;
- + gctINT32 i, totalLocked;
- +
- + gcmkHEADER_ARG("Node=0x%x Type=%d *Asynchroneous=%d",
- + Node, Type, gcmOPT_VALUE(Asynchroneous));
- +
- + /* Verify the arguments. */
- + if ((Node == gcvNULL)
- + || (Node->VidMem.memory == gcvNULL)
- + )
- + {
- + /* Invalid object. */
- + gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
- + }
- +
- + /**************************** Video Memory ********************************/
- +
- + if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
- + {
- + if (Node->VidMem.locked <= 0)
- + {
- + /* The surface was not locked. */
- + status = gcvSTATUS_MEMORY_UNLOCKED;
- + goto OnError;
- + }
- +
- + /* Decrement the lock count. */
- + Node->VidMem.locked --;
- +
- + if (Asynchroneous != gcvNULL)
- + {
- + /* No need for any events. */
- + *Asynchroneous = gcvFALSE;
- + }
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
- + "Unlocked node 0x%x (%d)",
- + Node,
- + Node->VidMem.locked);
- +
- +#ifdef __QNXNTO__
- + /* Unmap the video memory */
- + if ((Node->VidMem.locked == 0) && (Node->VidMem.logical != gcvNULL))
- + {
- + if (Kernel->core == gcvCORE_VG)
- + {
- + gckKERNEL_UnmapVideoMemory(Kernel,
- + Node->VidMem.logical,
- + Node->VidMem.processID,
- + Node->VidMem.bytes);
- + Node->VidMem.logical = gcvNULL;
- + }
- + }
- +#endif /* __QNXNTO__ */
- +
- + if (Node->VidMem.freePending && (Node->VidMem.locked == 0))
- + {
- + /* Client has unlocked node previously attempted to be freed by compositor. Free now. */
- + Node->VidMem.freePending = gcvFALSE;
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
- + "Deferred-freeing Node 0x%x.",
- + Node);
- + gcmkONERROR(gckVIDMEM_Free(Node));
- + }
- + }
- +
- + /*************************** Virtual Memory *******************************/
- +
- + else
- + {
- + /* Verify the gckHARDWARE object pointer. */
- + hardware = Kernel->hardware;
- + gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
- +
- + /* Verify the gckCOMMAND object pointer. */
- + command = Kernel->command;
- + gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
- +
- + /* Get the gckOS object pointer. */
- + os = Kernel->os;
- + gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
- +
- + /* Grab the mutex. */
- + gcmkONERROR(
- + gckOS_AcquireMutex(os, Node->Virtual.mutex, gcvINFINITE));
- +
- + acquired = gcvTRUE;
- +
- + if (Asynchroneous == gcvNULL)
- + {
- + if (Node->Virtual.lockeds[Kernel->core] == 0)
- + {
- + status = gcvSTATUS_MEMORY_UNLOCKED;
- + goto OnError;
- + }
- +
- + /* Decrement lock count. */
- + -- Node->Virtual.lockeds[Kernel->core];
- +
- + /* See if we can unlock the resources. */
- + if (Node->Virtual.lockeds[Kernel->core] == 0)
- + {
- + /* Free the page table. */
- + if (Node->Virtual.pageTables[Kernel->core] != gcvNULL)
- + {
- +#if gcdENABLE_VG
- + if (Kernel->vg != gcvNULL)
- + {
- + gcmkONERROR(
- + gckVGMMU_FreePages(Kernel->vg->mmu,
- + Node->Virtual.pageTables[Kernel->core],
- + Node->Virtual.pageCount));
- + }
- + else
- +#endif
- + {
- + gcmkONERROR(
- + gckMMU_FreePages(Kernel->mmu,
- + Node->Virtual.pageTables[Kernel->core],
- + Node->Virtual.pageCount));
- + }
- + /* Mark page table as freed. */
- + Node->Virtual.pageTables[Kernel->core] = gcvNULL;
- + Node->Virtual.lockKernels[Kernel->core] = gcvNULL;
- + }
- +
- +#ifdef __QNXNTO__
- + /* Mark node as unlocked. */
- + Node->Virtual.unlockPendings[Kernel->core] = gcvFALSE;
- +#endif
- + }
- +
- + for (i = 0, totalLocked = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + totalLocked += Node->Virtual.lockeds[i];
- + }
- +
- + if (totalLocked == 0)
- + {
- + /* Owner have already freed this node
- + ** and we are the last one to unlock, do
- + ** real free */
- + if (Node->Virtual.freed)
- + {
- + /* Free the virtual memory. */
- + gcmkVERIFY_OK(gckOS_FreePagedMemory(Kernel->os,
- + Node->Virtual.physical,
- + Node->Virtual.bytes));
- +
- + /* Release mutex before node is destroyed */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
- +
- + acquired = gcvFALSE;
- +
- + /* Destroy the gcuVIDMEM_NODE union. */
- + gcmkVERIFY_OK(gckVIDMEM_DestroyVirtual(Node));
- +
- + /* Node has been destroyed, so we should not touch it any more */
- + gcmkFOOTER();
- + return gcvSTATUS_OK;
- + }
- + }
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
- + "Unmapped virtual node 0x%x from 0x%08X",
- + Node, Node->Virtual.addresses[Kernel->core]);
- +
- + }
- +
- + else
- + {
- + /* If we need to unlock a node from virtual memory we have to be
- + ** very carefull. If the node is still inside the caches we
- + ** might get a bus error later if the cache line needs to be
- + ** replaced. So - we have to flush the caches before we do
- + ** anything. */
- +
- + /* gckCommand_EnterCommit() can't be called in interrupt handler because
- + ** of a dead lock situation:
- + ** process call Command_Commit(), and acquire Command->mutexQueue in
- + ** gckCOMMAND_EnterCommit(). Then it will wait for a signal which depends
- + ** on interrupt handler to generate, if interrupt handler enter
- + ** gckCommand_EnterCommit(), process will never get the signal. */
- +
- + /* So, flush cache when we still in process context, and then ask caller to
- + ** schedule a event. */
- +
- + gcmkONERROR(
- + gckOS_UnlockPages(os,
- + Node->Virtual.physical,
- + Node->Virtual.bytes,
- + Node->Virtual.logical));
- +
- + if (!Node->Virtual.contiguous
- + && (Node->Virtual.lockeds[Kernel->core] == 1)
- +#if gcdENABLE_VG
- + && (Kernel->vg == gcvNULL)
- +#endif
- + )
- + {
- + if (Type == gcvSURF_BITMAP)
- + {
- + /* Flush 2D cache. */
- + flush = gcvFLUSH_2D;
- + }
- + else if (Type == gcvSURF_RENDER_TARGET)
- + {
- + /* Flush color cache. */
- + flush = gcvFLUSH_COLOR;
- + }
- + else if (Type == gcvSURF_DEPTH)
- + {
- + /* Flush depth cache. */
- + flush = gcvFLUSH_DEPTH;
- + }
- + else
- + {
- + /* No flush required. */
- + flush = (gceKERNEL_FLUSH) 0;
- + }
- + if(hardware)
- + {
- + gcmkONERROR(
- + gckHARDWARE_Flush(hardware, flush, gcvNULL, &requested));
- +
- + if (requested != 0)
- + {
- + /* Acquire the command queue. */
- + gcmkONERROR(gckCOMMAND_EnterCommit(command, gcvFALSE));
- + commitEntered = gcvTRUE;
- +
- + gcmkONERROR(gckCOMMAND_Reserve(
- + command, requested, &buffer, &bufferSize
- + ));
- +
- + gcmkONERROR(gckHARDWARE_Flush(
- + hardware, flush, buffer, &bufferSize
- + ));
- +
- + /* Mark node as pending. */
- +#ifdef __QNXNTO__
- + Node->Virtual.unlockPendings[Kernel->core] = gcvTRUE;
- +#endif
- +
- + gcmkONERROR(gckCOMMAND_Execute(command, requested));
- +
- + /* Release the command queue. */
- + gcmkONERROR(gckCOMMAND_ExitCommit(command, gcvFALSE));
- + commitEntered = gcvFALSE;
- + }
- + }
- + else
- + {
- + gckOS_Print("Hardware already is freed.\n");
- + }
- + }
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
- + "Scheduled unlock for virtual node 0x%x",
- + Node);
- +
- + /* Schedule the surface to be unlocked. */
- + *Asynchroneous = gcvTRUE;
- + }
- +
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
- +
- + acquired = gcvFALSE;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Asynchroneous=%d", gcmOPT_VALUE(Asynchroneous));
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (commitEntered)
- + {
- + /* Release the command queue mutex. */
- + gcmkVERIFY_OK(gckCOMMAND_ExitCommit(command, gcvFALSE));
- + }
- +
- + if (acquired)
- + {
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h 2015-03-08 14:27:37.641684501 -0500
- @@ -0,0 +1,3896 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_base_h_
- +#define __gc_hal_base_h_
- +
- +#include "gc_hal_enum.h"
- +#include "gc_hal_types.h"
- +
- +#include "gc_hal_dump.h"
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +/******************************************************************************\
- +****************************** Object Declarations *****************************
- +\******************************************************************************/
- +
- +typedef struct _gckOS * gckOS;
- +typedef struct _gcoHAL * gcoHAL;
- +typedef struct _gcoOS * gcoOS;
- +typedef struct _gco2D * gco2D;
- +
- +#ifndef VIVANTE_NO_3D
- +typedef struct _gco3D * gco3D;
- +#endif
- +
- +typedef struct _gcoSURF * gcoSURF;
- +typedef struct _gcsSURF_INFO * gcsSURF_INFO_PTR;
- +typedef struct _gcsSURF_NODE * gcsSURF_NODE_PTR;
- +typedef struct _gcsSURF_FORMAT_INFO * gcsSURF_FORMAT_INFO_PTR;
- +typedef struct _gcsPOINT * gcsPOINT_PTR;
- +typedef struct _gcsSIZE * gcsSIZE_PTR;
- +typedef struct _gcsRECT * gcsRECT_PTR;
- +typedef struct _gcsBOUNDARY * gcsBOUNDARY_PTR;
- +typedef struct _gcoDUMP * gcoDUMP;
- +typedef struct _gcoHARDWARE * gcoHARDWARE;
- +typedef union _gcuVIDMEM_NODE * gcuVIDMEM_NODE_PTR;
- +
- +typedef struct gcsATOM * gcsATOM_PTR;
- +
- +#if gcdENABLE_VG
- +typedef struct _gcoVG * gcoVG;
- +typedef struct _gcsCOMPLETION_SIGNAL * gcsCOMPLETION_SIGNAL_PTR;
- +typedef struct _gcsCONTEXT_MAP * gcsCONTEXT_MAP_PTR;
- +#else
- +typedef void * gcoVG;
- +#endif
- +
- +#if gcdSYNC
- +typedef struct _gcoFENCE * gcoFENCE;
- +typedef struct _gcsSYNC_CONTEXT * gcsSYNC_CONTEXT_PTR;
- +#endif
- +
- +typedef struct _gcoOS_SymbolsList gcoOS_SymbolsList;
- +
- +/******************************************************************************\
- +******************************* Process local storage *************************
- +\******************************************************************************/
- +typedef struct _gcsPLS * gcsPLS_PTR;
- +
- +typedef void (* gctPLS_DESTRUCTOR) (
- + gcsPLS_PTR
- + );
- +
- +typedef struct _gcsPLS
- +{
- + /* Global objects. */
- + gcoOS os;
- + gcoHAL hal;
- +
- + /* Internal memory pool. */
- + gctSIZE_T internalSize;
- + gctPHYS_ADDR internalPhysical;
- + gctPOINTER internalLogical;
- +
- + /* External memory pool. */
- + gctSIZE_T externalSize;
- + gctPHYS_ADDR externalPhysical;
- + gctPOINTER externalLogical;
- +
- + /* Contiguous memory pool. */
- + gctSIZE_T contiguousSize;
- + gctPHYS_ADDR contiguousPhysical;
- + gctPOINTER contiguousLogical;
- +
- + /* EGL-specific process-wide objects. */
- + gctPOINTER eglDisplayInfo;
- + gctPOINTER eglSurfaceInfo;
- + gceSURF_FORMAT eglConfigFormat;
- +
- + /* PorcessID of the constrcutor process */
- + gctUINT32 processID;
- +#if gcdFORCE_GAL_LOAD_TWICE
- + /* ThreadID of the constrcutor process. */
- + gctSIZE_T threadID;
- + /* Flag for calling module destructor. */
- + gctBOOL exiting;
- +#endif
- +
- + /* Reference count for destructor. */
- + gcsATOM_PTR reference;
- + gctBOOL bKFS;
- +#if gcdUSE_NPOT_PATCH
- + gctBOOL bNeedSupportNP2Texture;
- +#endif
- +
- + /* Destructor for eglDisplayInfo. */
- + gctPLS_DESTRUCTOR destructor;
- +}
- +gcsPLS;
- +
- +extern gcsPLS gcPLS;
- +
- +/******************************************************************************\
- +******************************* Thread local storage *************************
- +\******************************************************************************/
- +
- +typedef struct _gcsTLS * gcsTLS_PTR;
- +
- +typedef void (* gctTLS_DESTRUCTOR) (
- + gcsTLS_PTR
- + );
- +
- +typedef struct _gcsTLS
- +{
- + gceHARDWARE_TYPE currentType;
- + gcoHARDWARE hardware;
- + /* Only for separated 3D and 2D */
- + gcoHARDWARE hardware2D;
- +#if gcdENABLE_VG
- + gcoVGHARDWARE vg;
- + gcoVG engineVG;
- +#endif /* gcdENABLE_VG */
- + gctPOINTER context;
- + gctTLS_DESTRUCTOR destructor;
- + gctBOOL ProcessExiting;
- +
- +#ifndef VIVANTE_NO_3D
- + gco3D engine3D;
- +#endif
- +#if gcdSYNC
- + gctBOOL fenceEnable;
- +#endif
- + gco2D engine2D;
- + gctBOOL copied;
- +
- +#if gcdFORCE_GAL_LOAD_TWICE
- + /* libGAL.so handle */
- + gctHANDLE handle;
- +#endif
- +}
- +gcsTLS;
- +
- +/******************************************************************************\
- +********************************* Enumerations *********************************
- +\******************************************************************************/
- +
- +typedef enum _gcePLS_VALUE
- +{
- + gcePLS_VALUE_EGL_DISPLAY_INFO,
- + gcePLS_VALUE_EGL_SURFACE_INFO,
- + gcePLS_VALUE_EGL_CONFIG_FORMAT_INFO,
- + gcePLS_VALUE_EGL_DESTRUCTOR_INFO,
- +}
- +gcePLS_VALUE;
- +
- +/* Video memory pool type. */
- +typedef enum _gcePOOL
- +{
- + gcvPOOL_UNKNOWN = 0,
- + gcvPOOL_DEFAULT,
- + gcvPOOL_LOCAL,
- + gcvPOOL_LOCAL_INTERNAL,
- + gcvPOOL_LOCAL_EXTERNAL,
- + gcvPOOL_UNIFIED,
- + gcvPOOL_SYSTEM,
- + gcvPOOL_VIRTUAL,
- + gcvPOOL_USER,
- + gcvPOOL_CONTIGUOUS,
- + gcvPOOL_DEFAULT_FORCE_CONTIGUOUS,
- + gcvPOOL_DEFAULT_FORCE_CONTIGUOUS_CACHEABLE,
- +
- + gcvPOOL_NUMBER_OF_POOLS
- +}
- +gcePOOL;
- +
- +#ifndef VIVANTE_NO_3D
- +/* Blending functions. */
- +typedef enum _gceBLEND_FUNCTION
- +{
- + gcvBLEND_ZERO,
- + gcvBLEND_ONE,
- + gcvBLEND_SOURCE_COLOR,
- + gcvBLEND_INV_SOURCE_COLOR,
- + gcvBLEND_SOURCE_ALPHA,
- + gcvBLEND_INV_SOURCE_ALPHA,
- + gcvBLEND_TARGET_COLOR,
- + gcvBLEND_INV_TARGET_COLOR,
- + gcvBLEND_TARGET_ALPHA,
- + gcvBLEND_INV_TARGET_ALPHA,
- + gcvBLEND_SOURCE_ALPHA_SATURATE,
- + gcvBLEND_CONST_COLOR,
- + gcvBLEND_INV_CONST_COLOR,
- + gcvBLEND_CONST_ALPHA,
- + gcvBLEND_INV_CONST_ALPHA,
- +}
- +gceBLEND_FUNCTION;
- +
- +/* Blending modes. */
- +typedef enum _gceBLEND_MODE
- +{
- + gcvBLEND_ADD,
- + gcvBLEND_SUBTRACT,
- + gcvBLEND_REVERSE_SUBTRACT,
- + gcvBLEND_MIN,
- + gcvBLEND_MAX,
- +}
- +gceBLEND_MODE;
- +
- +/* API flags. */
- +typedef enum _gceAPI
- +{
- + gcvAPI_D3D = 0x1,
- + gcvAPI_OPENGL = 0x2,
- + gcvAPI_OPENVG = 0x3,
- + gcvAPI_OPENCL = 0x4,
- +}
- +gceAPI;
- +
- +/* Depth modes. */
- +typedef enum _gceDEPTH_MODE
- +{
- + gcvDEPTH_NONE,
- + gcvDEPTH_Z,
- + gcvDEPTH_W,
- +}
- +gceDEPTH_MODE;
- +#endif /* VIVANTE_NO_3D */
- +
- +typedef enum _gceWHERE
- +{
- + gcvWHERE_COMMAND,
- + gcvWHERE_RASTER,
- + gcvWHERE_PIXEL,
- +}
- +gceWHERE;
- +
- +typedef enum _gceHOW
- +{
- + gcvHOW_SEMAPHORE = 0x1,
- + gcvHOW_STALL = 0x2,
- + gcvHOW_SEMAPHORE_STALL = 0x3,
- +}
- +gceHOW;
- +
- +typedef enum _gceSignalHandlerType
- +{
- + gcvHANDLE_SIGFPE_WHEN_SIGNAL_CODE_IS_0 = 0x1,
- +}
- +gceSignalHandlerType;
- +
- +
- +#if gcdENABLE_VG
- +/* gcsHAL_Limits*/
- +typedef struct _gcsHAL_LIMITS
- +{
- + /* chip info */
- + gceCHIPMODEL chipModel;
- + gctUINT32 chipRevision;
- + gctUINT32 featureCount;
- + gctUINT32 *chipFeatures;
- +
- + /* target caps */
- + gctUINT32 maxWidth;
- + gctUINT32 maxHeight;
- + gctUINT32 multiTargetCount;
- + gctUINT32 maxSamples;
- +
- +}gcsHAL_LIMITS;
- +#endif
- +
- +/******************************************************************************\
- +*********** Generic Memory Allocation Optimization Using Containers ************
- +\******************************************************************************/
- +
- +/* Generic container definition. */
- +typedef struct _gcsCONTAINER_LINK * gcsCONTAINER_LINK_PTR;
- +typedef struct _gcsCONTAINER_LINK
- +{
- + /* Points to the next container. */
- + gcsCONTAINER_LINK_PTR next;
- +}
- +gcsCONTAINER_LINK;
- +
- +typedef struct _gcsCONTAINER_RECORD * gcsCONTAINER_RECORD_PTR;
- +typedef struct _gcsCONTAINER_RECORD
- +{
- + gcsCONTAINER_RECORD_PTR prev;
- + gcsCONTAINER_RECORD_PTR next;
- +}
- +gcsCONTAINER_RECORD;
- +
- +typedef struct _gcsCONTAINER * gcsCONTAINER_PTR;
- +typedef struct _gcsCONTAINER
- +{
- + gctUINT containerSize;
- + gctUINT recordSize;
- + gctUINT recordCount;
- + gcsCONTAINER_LINK_PTR containers;
- + gcsCONTAINER_RECORD freeList;
- + gcsCONTAINER_RECORD allocList;
- +}
- +gcsCONTAINER;
- +
- +gceSTATUS
- +gcsCONTAINER_Construct(
- + IN gcsCONTAINER_PTR Container,
- + gctUINT RecordsPerContainer,
- + gctUINT RecordSize
- + );
- +
- +gceSTATUS
- +gcsCONTAINER_Destroy(
- + IN gcsCONTAINER_PTR Container
- + );
- +
- +gceSTATUS
- +gcsCONTAINER_AllocateRecord(
- + IN gcsCONTAINER_PTR Container,
- + OUT gctPOINTER * Record
- + );
- +
- +gceSTATUS
- +gcsCONTAINER_FreeRecord(
- + IN gcsCONTAINER_PTR Container,
- + IN gctPOINTER Record
- + );
- +
- +gceSTATUS
- +gcsCONTAINER_FreeAll(
- + IN gcsCONTAINER_PTR Container
- + );
- +
- +/******************************************************************************\
- +********************************* gcoHAL Object *********************************
- +\******************************************************************************/
- +
- +/* Construct a new gcoHAL object. */
- +gceSTATUS
- +gcoHAL_Construct(
- + IN gctPOINTER Context,
- + IN gcoOS Os,
- + OUT gcoHAL * Hal
- + );
- +
- +/* Destroy an gcoHAL object. */
- +gceSTATUS
- +gcoHAL_Destroy(
- + IN gcoHAL Hal
- + );
- +
- +/* Get pointer to gco2D object. */
- +gceSTATUS
- +gcoHAL_Get2DEngine(
- + IN gcoHAL Hal,
- + OUT gco2D * Engine
- + );
- +
- +gceSTATUS
- +gcoHAL_SetFscaleValue(
- + IN gctUINT FscaleValue
- + );
- +
- +gceSTATUS
- +gcoHAL_GetFscaleValue(
- + OUT gctUINT * FscaleValue,
- + OUT gctUINT * MinFscaleValue,
- + OUT gctUINT * MaxFscaleValue
- + );
- +
- +gceSTATUS
- +gcoHAL_SetBltNP2Texture(
- + gctBOOL enable
- + );
- +
- +#ifndef VIVANTE_NO_3D
- +/* Get pointer to gco3D object. */
- +gceSTATUS
- +gcoHAL_Get3DEngine(
- + IN gcoHAL Hal,
- + OUT gco3D * Engine
- + );
- +
- +gceSTATUS
- +gcoHAL_Query3DEngine(
- + IN gcoHAL Hal,
- + OUT gco3D * Engine
- + );
- +
- +gceSTATUS
- +gcoHAL_Set3DEngine(
- + IN gcoHAL Hal,
- + IN gco3D Engine
- + );
- +
- +gceSTATUS
- +gcoHAL_Get3DHardware(
- + IN gcoHAL Hal,
- + OUT gcoHARDWARE * Hardware
- + );
- +
- +gceSTATUS
- +gcoHAL_Set3DHardware(
- + IN gcoHAL Hal,
- + IN gcoHARDWARE Hardware
- + );
- +
- +
- +#endif /* VIVANTE_NO_3D */
- +
- +/* Verify whether the specified feature is available in hardware. */
- +gceSTATUS
- +gcoHAL_IsFeatureAvailable(
- + IN gcoHAL Hal,
- + IN gceFEATURE Feature
- + );
- +
- +/* Query the identity of the hardware. */
- +gceSTATUS
- +gcoHAL_QueryChipIdentity(
- + IN gcoHAL Hal,
- + OUT gceCHIPMODEL* ChipModel,
- + OUT gctUINT32* ChipRevision,
- + OUT gctUINT32* ChipFeatures,
- + OUT gctUINT32* ChipMinorFeatures
- + );
- +
- +/* Query the minor features of the hardware. */
- +gceSTATUS gcoHAL_QueryChipMinorFeatures(
- + IN gcoHAL Hal,
- + OUT gctUINT32* NumFeatures,
- + OUT gctUINT32* ChipMinorFeatures
- + );
- +
- +/* Query the amount of video memory. */
- +gceSTATUS
- +gcoHAL_QueryVideoMemory(
- + IN gcoHAL Hal,
- + OUT gctPHYS_ADDR * InternalAddress,
- + OUT gctSIZE_T * InternalSize,
- + OUT gctPHYS_ADDR * ExternalAddress,
- + OUT gctSIZE_T * ExternalSize,
- + OUT gctPHYS_ADDR * ContiguousAddress,
- + OUT gctSIZE_T * ContiguousSize
- + );
- +
- +/* Map video memory. */
- +gceSTATUS
- +gcoHAL_MapMemory(
- + IN gcoHAL Hal,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T NumberOfBytes,
- + OUT gctPOINTER * Logical
- + );
- +
- +/* Unmap video memory. */
- +gceSTATUS
- +gcoHAL_UnmapMemory(
- + IN gcoHAL Hal,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T NumberOfBytes,
- + IN gctPOINTER Logical
- + );
- +
- +/* Schedule an unmap of a buffer mapped through its physical address. */
- +gceSTATUS
- +gcoHAL_ScheduleUnmapMemory(
- + IN gcoHAL Hal,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T NumberOfBytes,
- + IN gctPOINTER Logical
- + );
- +
- +/* Map user memory. */
- +gceSTATUS
- +gcoHAL_MapUserMemory(
- + IN gctPOINTER Logical,
- + IN gctUINT32 Physical,
- + IN gctSIZE_T Size,
- + OUT gctPOINTER * Info,
- + OUT gctUINT32_PTR GPUAddress
- + );
- +
- +/* Unmap user memory. */
- +gceSTATUS
- +gcoHAL_UnmapUserMemory(
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Size,
- + IN gctPOINTER Info,
- + IN gctUINT32 GPUAddress
- + );
- +
- +/* Schedule an unmap of a user buffer using event mechanism. */
- +gceSTATUS
- +gcoHAL_ScheduleUnmapUserMemory(
- + IN gcoHAL Hal,
- + IN gctPOINTER Info,
- + IN gctSIZE_T Size,
- + IN gctUINT32 Address,
- + IN gctPOINTER Memory
- + );
- +
- +/* Commit the current command buffer. */
- +gceSTATUS
- +gcoHAL_Commit(
- + IN gcoHAL Hal,
- + IN gctBOOL Stall
- + );
- +
- +/* Query the tile capabilities. */
- +gceSTATUS
- +gcoHAL_QueryTiled(
- + IN gcoHAL Hal,
- + OUT gctINT32 * TileWidth2D,
- + OUT gctINT32 * TileHeight2D,
- + OUT gctINT32 * TileWidth3D,
- + OUT gctINT32 * TileHeight3D
- + );
- +
- +gceSTATUS
- +gcoHAL_Compact(
- + IN gcoHAL Hal
- + );
- +
- +#if VIVANTE_PROFILER
- +gceSTATUS
- +gcoHAL_ProfileStart(
- + IN gcoHAL Hal
- + );
- +
- +gceSTATUS
- +gcoHAL_ProfileEnd(
- + IN gcoHAL Hal,
- + IN gctCONST_STRING Title
- + );
- +#endif
- +
- +/* Power Management */
- +gceSTATUS
- +gcoHAL_SetPowerManagementState(
- + IN gcoHAL Hal,
- + IN gceCHIPPOWERSTATE State
- + );
- +
- +gceSTATUS
- +gcoHAL_QueryPowerManagementState(
- + IN gcoHAL Hal,
- + OUT gceCHIPPOWERSTATE *State
- + );
- +
- +/* Set the filter type for filter blit. */
- +gceSTATUS
- +gcoHAL_SetFilterType(
- + IN gcoHAL Hal,
- + IN gceFILTER_TYPE FilterType
- + );
- +
- +gceSTATUS
- +gcoHAL_GetDump(
- + IN gcoHAL Hal,
- + OUT gcoDUMP * Dump
- + );
- +
- +/* Call the kernel HAL layer. */
- +gceSTATUS
- +gcoHAL_Call(
- + IN gcoHAL Hal,
- + IN OUT gcsHAL_INTERFACE_PTR Interface
- + );
- +
- +gceSTATUS
- +gcoHAL_GetPatchID(
- + IN gcoHAL Hal,
- + OUT gcePATCH_ID * PatchID
- + );
- +
- +/* Schedule an event. */
- +gceSTATUS
- +gcoHAL_ScheduleEvent(
- + IN gcoHAL Hal,
- + IN OUT gcsHAL_INTERFACE_PTR Interface
- + );
- +
- +/* Destroy a surface. */
- +gceSTATUS
- +gcoHAL_DestroySurface(
- + IN gcoHAL Hal,
- + IN gcoSURF Surface
- + );
- +
- +/* Request a start/stop timestamp. */
- +gceSTATUS
- +gcoHAL_SetTimer(
- + IN gcoHAL Hal,
- + IN gctUINT32 Index,
- + IN gctBOOL Start
- + );
- +
- +/* Get Time delta from a Timer in microseconds. */
- +gceSTATUS
- +gcoHAL_GetTimerTime(
- + IN gcoHAL Hal,
- + IN gctUINT32 Timer,
- + OUT gctINT32_PTR TimeDelta
- + );
- +
- +/* set timeout value. */
- +gceSTATUS
- +gcoHAL_SetTimeOut(
- + IN gcoHAL Hal,
- + IN gctUINT32 timeOut
- + );
- +
- +gceSTATUS
- +gcoHAL_SetHardwareType(
- + IN gcoHAL Hal,
- + IN gceHARDWARE_TYPE HardwardType
- + );
- +
- +gceSTATUS
- +gcoHAL_GetHardwareType(
- + IN gcoHAL Hal,
- + OUT gceHARDWARE_TYPE * HardwardType
- + );
- +
- +gceSTATUS
- +gcoHAL_QueryChipCount(
- + IN gcoHAL Hal,
- + OUT gctINT32 * Count
- + );
- +
- +gceSTATUS
- +gcoHAL_QuerySeparated3D2D(
- + IN gcoHAL Hal
- + );
- +
- +gceSTATUS
- +gcoHAL_QuerySpecialHint(
- + IN gceSPECIAL_HINT Hint
- + );
- +
- +gceSTATUS
- +gcoHAL_SetSpecialHintData(
- + IN gcoHARDWARE Hardware
- + );
- +
- +/* Get pointer to gcoVG object. */
- +gceSTATUS
- +gcoHAL_GetVGEngine(
- + IN gcoHAL Hal,
- + OUT gcoVG * Engine
- + );
- +
- +#if gcdENABLE_VG
- +gceSTATUS
- +gcoHAL_QueryChipLimits(
- + IN gcoHAL Hal,
- + IN gctINT32 Chip,
- + OUT gcsHAL_LIMITS *Limits);
- +
- +gceSTATUS
- +gcoHAL_QueryChipFeature(
- + IN gcoHAL Hal,
- + IN gctINT32 Chip,
- + IN gceFEATURE Feature);
- +
- +#endif
- +/******************************************************************************\
- +********************************** gcoOS Object *********************************
- +\******************************************************************************/
- +
- +/* Get PLS value for given key */
- +gctPOINTER
- +gcoOS_GetPLSValue(
- + IN gcePLS_VALUE key
- + );
- +
- +/* Set PLS value of a given key */
- +void
- +gcoOS_SetPLSValue(
- + IN gcePLS_VALUE key,
- + OUT gctPOINTER value
- + );
- +
- +/* Get access to the thread local storage. */
- +gceSTATUS
- +gcoOS_GetTLS(
- + OUT gcsTLS_PTR * TLS
- + );
- +
- + /* Copy the TLS from a source thread. */
- + gceSTATUS gcoOS_CopyTLS(IN gcsTLS_PTR Source);
- +
- +/* Destroy the objects associated with the current thread. */
- +void
- +gcoOS_FreeThreadData(
- + IN gctBOOL ProcessExiting
- + );
- +
- +/* Construct a new gcoOS object. */
- +gceSTATUS
- +gcoOS_Construct(
- + IN gctPOINTER Context,
- + OUT gcoOS * Os
- + );
- +
- +/* Destroy an gcoOS object. */
- +gceSTATUS
- +gcoOS_Destroy(
- + IN gcoOS Os
- + );
- +
- +/* Get the base address for the physical memory. */
- +gceSTATUS
- +gcoOS_GetBaseAddress(
- + IN gcoOS Os,
- + OUT gctUINT32_PTR BaseAddress
- + );
- +
- +/* Allocate memory from the heap. */
- +gceSTATUS
- +gcoOS_Allocate(
- + IN gcoOS Os,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER * Memory
- + );
- +
- +/* Get allocated memory size. */
- +gceSTATUS
- +gcoOS_GetMemorySize(
- + IN gcoOS Os,
- + IN gctPOINTER Memory,
- + OUT gctSIZE_T_PTR MemorySize
- + );
- +
- +/* Free allocated memory. */
- +gceSTATUS
- +gcoOS_Free(
- + IN gcoOS Os,
- + IN gctPOINTER Memory
- + );
- +
- +/* Allocate memory. */
- +gceSTATUS
- +gcoOS_AllocateMemory(
- + IN gcoOS Os,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER * Memory
- + );
- +
- +/* Free memory. */
- +gceSTATUS
- +gcoOS_FreeMemory(
- + IN gcoOS Os,
- + IN gctPOINTER Memory
- + );
- +
- +/* Allocate contiguous memory. */
- +gceSTATUS
- +gcoOS_AllocateContiguous(
- + IN gcoOS Os,
- + IN gctBOOL InUserSpace,
- + IN OUT gctSIZE_T * Bytes,
- + OUT gctPHYS_ADDR * Physical,
- + OUT gctPOINTER * Logical
- + );
- +
- +/* Free contiguous memory. */
- +gceSTATUS
- +gcoOS_FreeContiguous(
- + IN gcoOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes
- + );
- +
- +/* Allocate video memory. */
- +gceSTATUS
- +gcoOS_AllocateVideoMemory(
- + IN gcoOS Os,
- + IN gctBOOL InUserSpace,
- + IN gctBOOL InCacheable,
- + IN OUT gctSIZE_T * Bytes,
- + OUT gctUINT32 * Physical,
- + OUT gctPOINTER * Logical,
- + OUT gctPOINTER * Handle
- + );
- +
- +/* Free video memory. */
- +gceSTATUS
- +gcoOS_FreeVideoMemory(
- + IN gcoOS Os,
- + IN gctPOINTER Handle
- + );
- +
- +gceSTATUS
- +gcoSURF_GetBankOffsetBytes(
- + IN gcoSURF Surfce,
- + IN gceSURF_TYPE Type,
- + IN gctUINT32 Stride,
- + IN gctUINT32_PTR Bytes
- + );
- +
- +/* Map user memory. */
- +gceSTATUS
- +gcoOS_MapUserMemory(
- + IN gcoOS Os,
- + IN gctPOINTER Memory,
- + IN gctSIZE_T Size,
- + OUT gctPOINTER * Info,
- + OUT gctUINT32_PTR Address
- + );
- +
- +/* Map user memory. */
- +gceSTATUS
- +gcoOS_MapUserMemoryEx(
- + IN gcoOS Os,
- + IN gctPOINTER Memory,
- + IN gctUINT32 Physical,
- + IN gctSIZE_T Size,
- + OUT gctPOINTER * Info,
- + OUT gctUINT32_PTR Address
- + );
- +
- +/* Unmap user memory. */
- +gceSTATUS
- +gcoOS_UnmapUserMemory(
- + IN gcoOS Os,
- + IN gctPOINTER Memory,
- + IN gctSIZE_T Size,
- + IN gctPOINTER Info,
- + IN gctUINT32 Address
- + );
- +
- +/* Device I/O Control call to the kernel HAL layer. */
- +gceSTATUS
- +gcoOS_DeviceControl(
- + IN gcoOS Os,
- + IN gctUINT32 IoControlCode,
- + IN gctPOINTER InputBuffer,
- + IN gctSIZE_T InputBufferSize,
- + IN gctPOINTER OutputBuffer,
- + IN gctSIZE_T OutputBufferSize
- + );
- +
- +/* Allocate non paged memory. */
- +gceSTATUS
- +gcoOS_AllocateNonPagedMemory(
- + IN gcoOS Os,
- + IN gctBOOL InUserSpace,
- + IN OUT gctSIZE_T * Bytes,
- + OUT gctPHYS_ADDR * Physical,
- + OUT gctPOINTER * Logical
- + );
- +
- +/* Free non paged memory. */
- +gceSTATUS
- +gcoOS_FreeNonPagedMemory(
- + IN gcoOS Os,
- + IN gctSIZE_T Bytes,
- + IN gctPHYS_ADDR Physical,
- + IN gctPOINTER Logical
- + );
- +
- +#define gcmOS_SAFE_FREE(os, mem) \
- + gcoOS_Free(os, mem); \
- + mem = gcvNULL
- +
- +#define gcmkOS_SAFE_FREE(os, mem) \
- + gckOS_Free(os, mem); \
- + mem = gcvNULL
- +
- +typedef enum _gceFILE_MODE
- +{
- + gcvFILE_CREATE = 0,
- + gcvFILE_APPEND,
- + gcvFILE_READ,
- + gcvFILE_CREATETEXT,
- + gcvFILE_APPENDTEXT,
- + gcvFILE_READTEXT,
- +}
- +gceFILE_MODE;
- +
- +/* Open a file. */
- +gceSTATUS
- +gcoOS_Open(
- + IN gcoOS Os,
- + IN gctCONST_STRING FileName,
- + IN gceFILE_MODE Mode,
- + OUT gctFILE * File
- + );
- +
- +/* Close a file. */
- +gceSTATUS
- +gcoOS_Close(
- + IN gcoOS Os,
- + IN gctFILE File
- + );
- +
- +/* Read data from a file. */
- +gceSTATUS
- +gcoOS_Read(
- + IN gcoOS Os,
- + IN gctFILE File,
- + IN gctSIZE_T ByteCount,
- + IN gctPOINTER Data,
- + OUT gctSIZE_T * ByteRead
- + );
- +
- +/* Write data to a file. */
- +gceSTATUS
- +gcoOS_Write(
- + IN gcoOS Os,
- + IN gctFILE File,
- + IN gctSIZE_T ByteCount,
- + IN gctCONST_POINTER Data
- + );
- +
- +/* Flush data to a file. */
- +gceSTATUS
- +gcoOS_Flush(
- + IN gcoOS Os,
- + IN gctFILE File
- + );
- +
- +/* Close a file descriptor. */
- +gceSTATUS
- +gcoOS_CloseFD(
- + IN gcoOS Os,
- + IN gctINT FD
- + );
- +
- +/* Dup file descriptor to another. */
- +gceSTATUS
- +gcoOS_DupFD(
- + IN gcoOS Os,
- + IN gctINT FD,
- + OUT gctINT * FD2
- + );
- +
- +/* Create an endpoint for communication. */
- +gceSTATUS
- +gcoOS_Socket(
- + IN gcoOS Os,
- + IN gctINT Domain,
- + IN gctINT Type,
- + IN gctINT Protocol,
- + OUT gctINT *SockFd
- + );
- +
- +/* Close a socket. */
- +gceSTATUS
- +gcoOS_CloseSocket(
- + IN gcoOS Os,
- + IN gctINT SockFd
- + );
- +
- +/* Initiate a connection on a socket. */
- +gceSTATUS
- +gcoOS_Connect(
- + IN gcoOS Os,
- + IN gctINT SockFd,
- + IN gctCONST_POINTER HostName,
- + IN gctUINT Port);
- +
- +/* Shut down part of connection on a socket. */
- +gceSTATUS
- +gcoOS_Shutdown(
- + IN gcoOS Os,
- + IN gctINT SockFd,
- + IN gctINT How
- + );
- +
- +/* Send a message on a socket. */
- +gceSTATUS
- +gcoOS_Send(
- + IN gcoOS Os,
- + IN gctINT SockFd,
- + IN gctSIZE_T ByteCount,
- + IN gctCONST_POINTER Data,
- + IN gctINT Flags
- + );
- +
- +/* Initiate a connection on a socket. */
- +gceSTATUS
- +gcoOS_WaitForSend(
- + IN gcoOS Os,
- + IN gctINT SockFd,
- + IN gctINT Seconds,
- + IN gctINT MicroSeconds);
- +
- +/* Get environment variable value. */
- +gceSTATUS
- +gcoOS_GetEnv(
- + IN gcoOS Os,
- + IN gctCONST_STRING VarName,
- + OUT gctSTRING * Value
- + );
- +
- +/* Set environment variable value. */
- +gceSTATUS
- +gcoOS_SetEnv(
- + IN gcoOS Os,
- + IN gctCONST_STRING VarName,
- + IN gctSTRING Value
- + );
- +
- +/* Get current working directory. */
- +gceSTATUS
- +gcoOS_GetCwd(
- + IN gcoOS Os,
- + IN gctINT SizeInBytes,
- + OUT gctSTRING Buffer
- + );
- +
- +/* Get file status info. */
- +gceSTATUS
- +gcoOS_Stat(
- + IN gcoOS Os,
- + IN gctCONST_STRING FileName,
- + OUT gctPOINTER Buffer
- + );
- +
- +typedef enum _gceFILE_WHENCE
- +{
- + gcvFILE_SEEK_SET,
- + gcvFILE_SEEK_CUR,
- + gcvFILE_SEEK_END
- +}
- +gceFILE_WHENCE;
- +
- +/* Set the current position of a file. */
- +gceSTATUS
- +gcoOS_Seek(
- + IN gcoOS Os,
- + IN gctFILE File,
- + IN gctUINT32 Offset,
- + IN gceFILE_WHENCE Whence
- + );
- +
- +/* Set the current position of a file. */
- +gceSTATUS
- +gcoOS_SetPos(
- + IN gcoOS Os,
- + IN gctFILE File,
- + IN gctUINT32 Position
- + );
- +
- +/* Get the current position of a file. */
- +gceSTATUS
- +gcoOS_GetPos(
- + IN gcoOS Os,
- + IN gctFILE File,
- + OUT gctUINT32 * Position
- + );
- +
- +/* Same as strstr. */
- +gceSTATUS
- +gcoOS_StrStr(
- + IN gctCONST_STRING String,
- + IN gctCONST_STRING SubString,
- + OUT gctSTRING * Output
- + );
- +
- +/* Find the last occurance of a character inside a string. */
- +gceSTATUS
- +gcoOS_StrFindReverse(
- + IN gctCONST_STRING String,
- + IN gctINT8 Character,
- + OUT gctSTRING * Output
- + );
- +
- +gceSTATUS
- +gcoOS_StrDup(
- + IN gcoOS Os,
- + IN gctCONST_STRING String,
- + OUT gctSTRING * Target
- + );
- +
- +/* Copy a string. */
- +gceSTATUS
- +gcoOS_StrCopySafe(
- + IN gctSTRING Destination,
- + IN gctSIZE_T DestinationSize,
- + IN gctCONST_STRING Source
- + );
- +
- +/* Append a string. */
- +gceSTATUS
- +gcoOS_StrCatSafe(
- + IN gctSTRING Destination,
- + IN gctSIZE_T DestinationSize,
- + IN gctCONST_STRING Source
- + );
- +
- +/* Compare two strings. */
- +gceSTATUS
- +gcoOS_StrCmp(
- + IN gctCONST_STRING String1,
- + IN gctCONST_STRING String2
- + );
- +
- +/* Compare characters of two strings. */
- +gceSTATUS
- +gcoOS_StrNCmp(
- + IN gctCONST_STRING String1,
- + IN gctCONST_STRING String2,
- + IN gctSIZE_T Count
- + );
- +
- +/* Convert string to float. */
- +gceSTATUS
- +gcoOS_StrToFloat(
- + IN gctCONST_STRING String,
- + OUT gctFLOAT * Float
- + );
- +
- +/* Convert hex string to integer. */
- +gceSTATUS
- +gcoOS_HexStrToInt(
- + IN gctCONST_STRING String,
- + OUT gctINT * Int
- + );
- +
- +/* Convert hex string to float. */
- +gceSTATUS
- +gcoOS_HexStrToFloat(
- + IN gctCONST_STRING String,
- + OUT gctFLOAT * Float
- + );
- +
- +/* Convert string to integer. */
- +gceSTATUS
- +gcoOS_StrToInt(
- + IN gctCONST_STRING String,
- + OUT gctINT * Int
- + );
- +
- +gceSTATUS
- +gcoOS_MemCmp(
- + IN gctCONST_POINTER Memory1,
- + IN gctCONST_POINTER Memory2,
- + IN gctSIZE_T Bytes
- + );
- +
- +gceSTATUS
- +gcoOS_PrintStrSafe(
- + OUT gctSTRING String,
- + IN gctSIZE_T StringSize,
- + IN OUT gctUINT * Offset,
- + IN gctCONST_STRING Format,
- + ...
- + );
- +
- +gceSTATUS
- +gcoOS_LoadLibrary(
- + IN gcoOS Os,
- + IN gctCONST_STRING Library,
- + OUT gctHANDLE * Handle
- + );
- +
- +gceSTATUS
- +gcoOS_FreeLibrary(
- + IN gcoOS Os,
- + IN gctHANDLE Handle
- + );
- +
- +gceSTATUS
- +gcoOS_GetProcAddress(
- + IN gcoOS Os,
- + IN gctHANDLE Handle,
- + IN gctCONST_STRING Name,
- + OUT gctPOINTER * Function
- + );
- +
- +gceSTATUS
- +gcoOS_Compact(
- + IN gcoOS Os
- + );
- +
- +gceSTATUS
- +gcoOS_AddSignalHandler (
- + IN gceSignalHandlerType SignalHandlerType
- + );
- +
- +#if VIVANTE_PROFILER
- +gceSTATUS
- +gcoOS_ProfileStart(
- + IN gcoOS Os
- + );
- +
- +gceSTATUS
- +gcoOS_ProfileEnd(
- + IN gcoOS Os,
- + IN gctCONST_STRING Title
- + );
- +
- +gceSTATUS
- +gcoOS_SetProfileSetting(
- + IN gcoOS Os,
- + IN gctBOOL Enable,
- + IN gctCONST_STRING FileName
- + );
- +#endif
- +
- +gctBOOL
- +gcoOS_IsNeededSupportNP2Texture(
- + IN gctCHAR* ProcName
- + );
- +
- +/* Query the video memory. */
- +gceSTATUS
- +gcoOS_QueryVideoMemory(
- + IN gcoOS Os,
- + OUT gctPHYS_ADDR * InternalAddress,
- + OUT gctSIZE_T * InternalSize,
- + OUT gctPHYS_ADDR * ExternalAddress,
- + OUT gctSIZE_T * ExternalSize,
- + OUT gctPHYS_ADDR * ContiguousAddress,
- + OUT gctSIZE_T * ContiguousSize
- + );
- +
- +/* Detect if the process is the executable specified. */
- +gceSTATUS
- +gcoOS_DetectProcessByNamePid(
- + IN gctCONST_STRING Name,
- + IN gctHANDLE Pid
- + );
- +
- +/* Detect if the current process is the executable specified. */
- +gceSTATUS
- +gcoOS_DetectProcessByName(
- + IN gctCONST_STRING Name
- + );
- +
- +gceSTATUS
- +gcoOS_DetectProcessByEncryptedName(
- + IN gctCONST_STRING Name
- + );
- +
- +#if defined(ANDROID)
- +gceSTATUS
- +gcoOS_DetectProgrameByEncryptedSymbols(
- + IN gcoOS_SymbolsList Symbols
- + );
- +#endif
- +
- +/*----------------------------------------------------------------------------*/
- +/*----- Atoms ----------------------------------------------------------------*/
- +
- +/* Construct an atom. */
- +gceSTATUS
- +gcoOS_AtomConstruct(
- + IN gcoOS Os,
- + OUT gcsATOM_PTR * Atom
- + );
- +
- +/* Destroy an atom. */
- +gceSTATUS
- +gcoOS_AtomDestroy(
- + IN gcoOS Os,
- + IN gcsATOM_PTR Atom
- + );
- +
- +/* Increment an atom. */
- +gceSTATUS
- +gcoOS_AtomIncrement(
- + IN gcoOS Os,
- + IN gcsATOM_PTR Atom,
- + OUT gctINT32_PTR OldValue
- + );
- +
- +/* Decrement an atom. */
- +gceSTATUS
- +gcoOS_AtomDecrement(
- + IN gcoOS Os,
- + IN gcsATOM_PTR Atom,
- + OUT gctINT32_PTR OldValue
- + );
- +
- +gctHANDLE
- +gcoOS_GetCurrentProcessID(
- + void
- + );
- +
- +gctHANDLE
- +gcoOS_GetCurrentThreadID(
- + void
- + );
- +
- +/*----------------------------------------------------------------------------*/
- +/*----- Time -----------------------------------------------------------------*/
- +
- +/* Get the number of milliseconds since the system started. */
- +gctUINT32
- +gcoOS_GetTicks(
- + void
- + );
- +
- +/* Get time in microseconds. */
- +gceSTATUS
- +gcoOS_GetTime(
- + gctUINT64_PTR Time
- + );
- +
- +/* Get CPU usage in microseconds. */
- +gceSTATUS
- +gcoOS_GetCPUTime(
- + gctUINT64_PTR CPUTime
- + );
- +
- +/* Get memory usage. */
- +gceSTATUS
- +gcoOS_GetMemoryUsage(
- + gctUINT32_PTR MaxRSS,
- + gctUINT32_PTR IxRSS,
- + gctUINT32_PTR IdRSS,
- + gctUINT32_PTR IsRSS
- + );
- +
- +/* Delay a number of microseconds. */
- +gceSTATUS
- +gcoOS_Delay(
- + IN gcoOS Os,
- + IN gctUINT32 Delay
- + );
- +
- +/*----------------------------------------------------------------------------*/
- +/*----- Threads --------------------------------------------------------------*/
- +
- +#ifdef _WIN32
- +/* Cannot include windows.h here becuase "near" and "far"
- + * which are used in gcsDEPTH_INFO, are defined to nothing in WinDef.h.
- + * So, use the real value of DWORD and WINAPI, instead.
- + * DWORD is unsigned long, and WINAPI is __stdcall.
- + * If these two are change in WinDef.h, the following two typdefs
- + * need to be changed, too.
- + */
- +typedef unsigned long gctTHREAD_RETURN;
- +typedef unsigned long (__stdcall * gcTHREAD_ROUTINE)(void * Argument);
- +#else
- +typedef void * gctTHREAD_RETURN;
- +typedef void * (* gcTHREAD_ROUTINE)(void *);
- +#endif
- +
- +/* Create a new thread. */
- +gceSTATUS
- +gcoOS_CreateThread(
- + IN gcoOS Os,
- + IN gcTHREAD_ROUTINE Worker,
- + IN gctPOINTER Argument,
- + OUT gctPOINTER * Thread
- + );
- +
- +/* Close a thread. */
- +gceSTATUS
- +gcoOS_CloseThread(
- + IN gcoOS Os,
- + IN gctPOINTER Thread
- + );
- +
- +/*----------------------------------------------------------------------------*/
- +/*----- Mutexes --------------------------------------------------------------*/
- +
- +/* Create a new mutex. */
- +gceSTATUS
- +gcoOS_CreateMutex(
- + IN gcoOS Os,
- + OUT gctPOINTER * Mutex
- + );
- +
- +/* Delete a mutex. */
- +gceSTATUS
- +gcoOS_DeleteMutex(
- + IN gcoOS Os,
- + IN gctPOINTER Mutex
- + );
- +
- +/* Acquire a mutex. */
- +gceSTATUS
- +gcoOS_AcquireMutex(
- + IN gcoOS Os,
- + IN gctPOINTER Mutex,
- + IN gctUINT32 Timeout
- + );
- +
- +/* Release a mutex. */
- +gceSTATUS
- +gcoOS_ReleaseMutex(
- + IN gcoOS Os,
- + IN gctPOINTER Mutex
- + );
- +
- +/*----------------------------------------------------------------------------*/
- +/*----- Signals --------------------------------------------------------------*/
- +
- +/* Create a signal. */
- +gceSTATUS
- +gcoOS_CreateSignal(
- + IN gcoOS Os,
- + IN gctBOOL ManualReset,
- + OUT gctSIGNAL * Signal
- + );
- +
- +/* Destroy a signal. */
- +gceSTATUS
- +gcoOS_DestroySignal(
- + IN gcoOS Os,
- + IN gctSIGNAL Signal
- + );
- +
- +/* Signal a signal. */
- +gceSTATUS
- +gcoOS_Signal(
- + IN gcoOS Os,
- + IN gctSIGNAL Signal,
- + IN gctBOOL State
- + );
- +
- +/* Wait for a signal. */
- +gceSTATUS
- +gcoOS_WaitSignal(
- + IN gcoOS Os,
- + IN gctSIGNAL Signal,
- + IN gctUINT32 Wait
- + );
- +
- +/* Map a signal from another process */
- +gceSTATUS
- +gcoOS_MapSignal(
- + IN gctSIGNAL RemoteSignal,
- + OUT gctSIGNAL * LocalSignal
- + );
- +
- +/* Unmap a signal mapped from another process */
- +gceSTATUS
- +gcoOS_UnmapSignal(
- + IN gctSIGNAL Signal
- + );
- +
- +/*----------------------------------------------------------------------------*/
- +/*----- Android Native Fence -------------------------------------------------*/
- +
- +/* Create sync point. */
- +gceSTATUS
- +gcoOS_CreateSyncPoint(
- + IN gcoOS Os,
- + OUT gctSYNC_POINT * SyncPoint
- + );
- +
- +/* Destroy sync point. */
- +gceSTATUS
- +gcoOS_DestroySyncPoint(
- + IN gcoOS Os,
- + IN gctSYNC_POINT SyncPoint
- + );
- +
- +/* Create native fence. */
- +gceSTATUS
- +gcoOS_CreateNativeFence(
- + IN gcoOS Os,
- + IN gctSYNC_POINT SyncPoint,
- + OUT gctINT * FenceFD
- + );
- +
- +/* Wait on native fence. */
- +gceSTATUS
- +gcoOS_WaitNativeFence(
- + IN gcoOS Os,
- + IN gctINT FenceFD,
- + IN gctUINT32 Timeout
- + );
- +
- +/*----------------------------------------------------------------------------*/
- +/*----- Memory Access and Cache ----------------------------------------------*/
- +
- +/* Write a register. */
- +gceSTATUS
- +gcoOS_WriteRegister(
- + IN gcoOS Os,
- + IN gctUINT32 Address,
- + IN gctUINT32 Data
- + );
- +
- +/* Read a register. */
- +gceSTATUS
- +gcoOS_ReadRegister(
- + IN gcoOS Os,
- + IN gctUINT32 Address,
- + OUT gctUINT32 * Data
- + );
- +
- +gceSTATUS
- +gcoOS_CacheClean(
- + IN gcoOS Os,
- + IN gctUINT64 Node,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes
- + );
- +
- +gceSTATUS
- +gcoOS_CacheFlush(
- + IN gcoOS Os,
- + IN gctUINT64 Node,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes
- + );
- +
- +gceSTATUS
- +gcoOS_CacheInvalidate(
- + IN gcoOS Os,
- + IN gctUINT64 Node,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes
- + );
- +
- +gceSTATUS
- +gcoOS_MemoryBarrier(
- + IN gcoOS Os,
- + IN gctPOINTER Logical
- + );
- +
- +
- +/*----------------------------------------------------------------------------*/
- +/*----- Profile --------------------------------------------------------------*/
- +
- +gceSTATUS
- +gckOS_GetProfileTick(
- + OUT gctUINT64_PTR Tick
- + );
- +
- +gceSTATUS
- +gckOS_QueryProfileTickRate(
- + OUT gctUINT64_PTR TickRate
- + );
- +
- +gctUINT32
- +gckOS_ProfileToMS(
- + IN gctUINT64 Ticks
- + );
- +
- +gceSTATUS
- +gcoOS_GetProfileTick(
- + OUT gctUINT64_PTR Tick
- + );
- +
- +gceSTATUS
- +gcoOS_QueryProfileTickRate(
- + OUT gctUINT64_PTR TickRate
- + );
- +
- +#define _gcmPROFILE_INIT(prefix, freq, start) \
- + do { \
- + prefix ## OS_QueryProfileTickRate(&(freq)); \
- + prefix ## OS_GetProfileTick(&(start)); \
- + } while (gcvFALSE)
- +
- +#define _gcmPROFILE_QUERY(prefix, start, ticks) \
- + do { \
- + prefix ## OS_GetProfileTick(&(ticks)); \
- + (ticks) = ((ticks) > (start)) ? ((ticks) - (start)) \
- + : (~0ull - (start) + (ticks) + 1); \
- + } while (gcvFALSE)
- +
- +#if gcdENABLE_PROFILING
- +# define gcmkPROFILE_INIT(freq, start) _gcmPROFILE_INIT(gck, freq, start)
- +# define gcmkPROFILE_QUERY(start, ticks) _gcmPROFILE_QUERY(gck, start, ticks)
- +# define gcmPROFILE_INIT(freq, start) _gcmPROFILE_INIT(gco, freq, start)
- +# define gcmPROFILE_QUERY(start, ticks) _gcmPROFILE_QUERY(gco, start, ticks)
- +# define gcmPROFILE_ONLY(x) x
- +# define gcmPROFILE_ELSE(x) do { } while (gcvFALSE)
- +# define gcmPROFILE_DECLARE_ONLY(x) x
- +# define gcmPROFILE_DECLARE_ELSE(x) typedef x
- +#else
- +# define gcmkPROFILE_INIT(start, freq) do { } while (gcvFALSE)
- +# define gcmkPROFILE_QUERY(start, ticks) do { } while (gcvFALSE)
- +# define gcmPROFILE_INIT(start, freq) do { } while (gcvFALSE)
- +# define gcmPROFILE_QUERY(start, ticks) do { } while (gcvFALSE)
- +# define gcmPROFILE_ONLY(x) do { } while (gcvFALSE)
- +# define gcmPROFILE_ELSE(x) x
- +# define gcmPROFILE_DECLARE_ONLY(x) do { } while (gcvFALSE)
- +# define gcmPROFILE_DECLARE_ELSE(x) x
- +#endif
- +
- +/*******************************************************************************
- +** gcoMATH object
- +*/
- +
- +#define gcdPI 3.14159265358979323846f
- +
- +/* Kernel. */
- +gctINT
- +gckMATH_ModuloInt(
- + IN gctINT X,
- + IN gctINT Y
- + );
- +
- +/* User. */
- +gctUINT32
- +gcoMATH_Log2in5dot5(
- + IN gctINT X
- + );
- +
- +
- +gctFLOAT
- +gcoMATH_UIntAsFloat(
- + IN gctUINT32 X
- + );
- +
- +gctUINT32
- +gcoMATH_FloatAsUInt(
- + IN gctFLOAT X
- + );
- +
- +gctBOOL
- +gcoMATH_CompareEqualF(
- + IN gctFLOAT X,
- + IN gctFLOAT Y
- + );
- +
- +gctUINT16
- +gcoMATH_UInt8AsFloat16(
- + IN gctUINT8 X
- + );
- +
- +/******************************************************************************\
- +**************************** Coordinate Structures *****************************
- +\******************************************************************************/
- +
- +typedef struct _gcsPOINT
- +{
- + gctINT32 x;
- + gctINT32 y;
- +}
- +gcsPOINT;
- +
- +typedef struct _gcsSIZE
- +{
- + gctINT32 width;
- + gctINT32 height;
- +}
- +gcsSIZE;
- +
- +typedef struct _gcsRECT
- +{
- + gctINT32 left;
- + gctINT32 top;
- + gctINT32 right;
- + gctINT32 bottom;
- +}
- +gcsRECT;
- +
- +typedef union _gcsPIXEL
- +{
- + struct
- + {
- + gctFLOAT r, g, b, a;
- + gctFLOAT d, s;
- + } pf;
- +
- + struct
- + {
- + gctINT32 r, g, b, a;
- + gctINT32 d, s;
- + } pi;
- +
- + struct
- + {
- + gctUINT32 r, g, b, a;
- + gctUINT32 d, s;
- + } pui;
- +
- +} gcsPIXEL;
- +
- +
- +/******************************************************************************\
- +********************************* gcoSURF Object ********************************
- +\******************************************************************************/
- +
- +/*----------------------------------------------------------------------------*/
- +/*------------------------------- gcoSURF Common ------------------------------*/
- +
- +/* Color format classes. */
- +typedef enum _gceFORMAT_CLASS
- +{
- + gcvFORMAT_CLASS_RGBA = 4500,
- + gcvFORMAT_CLASS_YUV,
- + gcvFORMAT_CLASS_INDEX,
- + gcvFORMAT_CLASS_LUMINANCE,
- + gcvFORMAT_CLASS_BUMP,
- + gcvFORMAT_CLASS_DEPTH,
- +}
- +gceFORMAT_CLASS;
- +
- +/* Special enums for width field in gcsFORMAT_COMPONENT. */
- +typedef enum _gceCOMPONENT_CONTROL
- +{
- + gcvCOMPONENT_NOTPRESENT = 0x00,
- + gcvCOMPONENT_DONTCARE = 0x80,
- + gcvCOMPONENT_WIDTHMASK = 0x7F,
- + gcvCOMPONENT_ODD = 0x80
- +}
- +gceCOMPONENT_CONTROL;
- +
- +/* Color format component parameters. */
- +typedef struct _gcsFORMAT_COMPONENT
- +{
- + gctUINT8 start;
- + gctUINT8 width;
- +}
- +gcsFORMAT_COMPONENT;
- +
- +/* RGBA color format class. */
- +typedef struct _gcsFORMAT_CLASS_TYPE_RGBA
- +{
- + gcsFORMAT_COMPONENT alpha;
- + gcsFORMAT_COMPONENT red;
- + gcsFORMAT_COMPONENT green;
- + gcsFORMAT_COMPONENT blue;
- +}
- +gcsFORMAT_CLASS_TYPE_RGBA;
- +
- +/* YUV color format class. */
- +typedef struct _gcsFORMAT_CLASS_TYPE_YUV
- +{
- + gcsFORMAT_COMPONENT y;
- + gcsFORMAT_COMPONENT u;
- + gcsFORMAT_COMPONENT v;
- +}
- +gcsFORMAT_CLASS_TYPE_YUV;
- +
- +/* Index color format class. */
- +typedef struct _gcsFORMAT_CLASS_TYPE_INDEX
- +{
- + gcsFORMAT_COMPONENT value;
- +}
- +gcsFORMAT_CLASS_TYPE_INDEX;
- +
- +/* Luminance color format class. */
- +typedef struct _gcsFORMAT_CLASS_TYPE_LUMINANCE
- +{
- + gcsFORMAT_COMPONENT alpha;
- + gcsFORMAT_COMPONENT value;
- +}
- +gcsFORMAT_CLASS_TYPE_LUMINANCE;
- +
- +/* Bump map color format class. */
- +typedef struct _gcsFORMAT_CLASS_TYPE_BUMP
- +{
- + gcsFORMAT_COMPONENT alpha;
- + gcsFORMAT_COMPONENT l;
- + gcsFORMAT_COMPONENT v;
- + gcsFORMAT_COMPONENT u;
- + gcsFORMAT_COMPONENT q;
- + gcsFORMAT_COMPONENT w;
- +}
- +gcsFORMAT_CLASS_TYPE_BUMP;
- +
- +/* Depth and stencil format class. */
- +typedef struct _gcsFORMAT_CLASS_TYPE_DEPTH
- +{
- + gcsFORMAT_COMPONENT depth;
- + gcsFORMAT_COMPONENT stencil;
- +}
- +gcsFORMAT_CLASS_TYPE_DEPTH;
- +
- +/* Format parameters. */
- +typedef struct _gcsSURF_FORMAT_INFO
- +{
- + /* Format code and class. */
- + gceSURF_FORMAT format;
- + gceFORMAT_CLASS fmtClass;
- +
- + /* The size of one pixel in bits. */
- + gctUINT8 bitsPerPixel;
- +
- + /* Component swizzle. */
- + gceSURF_SWIZZLE swizzle;
- +
- + /* Some formats have two neighbour pixels interleaved together. */
- + /* To describe such format, set the flag to 1 and add another */
- + /* like this one describing the odd pixel format. */
- + gctUINT8 interleaved;
- +
- + /* Format components. */
- + union
- + {
- + gcsFORMAT_CLASS_TYPE_BUMP bump;
- + gcsFORMAT_CLASS_TYPE_RGBA rgba;
- + gcsFORMAT_CLASS_TYPE_YUV yuv;
- + gcsFORMAT_CLASS_TYPE_LUMINANCE lum;
- + gcsFORMAT_CLASS_TYPE_INDEX index;
- + gcsFORMAT_CLASS_TYPE_DEPTH depth;
- + } u;
- +}
- +gcsSURF_FORMAT_INFO;
- +
- +/* Frame buffer information. */
- +typedef struct _gcsSURF_FRAMEBUFFER
- +{
- + gctPOINTER logical;
- + gctUINT width, height;
- + gctINT stride;
- + gceSURF_FORMAT format;
- +}
- +gcsSURF_FRAMEBUFFER;
- +
- +typedef struct _gcsVIDMEM_NODE_SHARED_INFO
- +{
- + gctBOOL tileStatusDisabled;
- + gcsPOINT SrcOrigin;
- + gcsPOINT DestOrigin;
- + gcsSIZE RectSize;
- + gctUINT32 clearValue;
- +}
- +gcsVIDMEM_NODE_SHARED_INFO;
- +
- +/* Generic pixel component descriptors. */
- +extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_XXX8;
- +extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_XX8X;
- +extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_X8XX;
- +extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_8XXX;
- +
- +typedef enum _gceORIENTATION
- +{
- + gcvORIENTATION_TOP_BOTTOM,
- + gcvORIENTATION_BOTTOM_TOP,
- +}
- +gceORIENTATION;
- +
- +
- +/* Construct a new gcoSURF object. */
- +gceSTATUS
- +gcoSURF_Construct(
- + IN gcoHAL Hal,
- + IN gctUINT Width,
- + IN gctUINT Height,
- + IN gctUINT Depth,
- + IN gceSURF_TYPE Type,
- + IN gceSURF_FORMAT Format,
- + IN gcePOOL Pool,
- + OUT gcoSURF * Surface
- + );
- +
- +/* Destroy an gcoSURF object. */
- +gceSTATUS
- +gcoSURF_Destroy(
- + IN gcoSURF Surface
- + );
- +
- +/* Map user-allocated surface. */
- +gceSTATUS
- +gcoSURF_MapUserSurface(
- + IN gcoSURF Surface,
- + IN gctUINT Alignment,
- + IN gctPOINTER Logical,
- + IN gctUINT32 Physical
- + );
- +
- +/* Query vid mem node info. */
- +gceSTATUS
- +gcoSURF_QueryVidMemNode(
- + IN gcoSURF Surface,
- + OUT gctUINT64 * Node,
- + OUT gcePOOL * Pool,
- + OUT gctUINT_PTR Bytes
- + );
- +
- +/* Set the color type of the surface. */
- +gceSTATUS
- +gcoSURF_SetColorType(
- + IN gcoSURF Surface,
- + IN gceSURF_COLOR_TYPE ColorType
- + );
- +
- +/* Get the color type of the surface. */
- +gceSTATUS
- +gcoSURF_GetColorType(
- + IN gcoSURF Surface,
- + OUT gceSURF_COLOR_TYPE *ColorType
- + );
- +
- +/* Set the surface ration angle. */
- +gceSTATUS
- +gcoSURF_SetRotation(
- + IN gcoSURF Surface,
- + IN gceSURF_ROTATION Rotation
- + );
- +
- +gceSTATUS
- +gcoSURF_SetPreRotation(
- + IN gcoSURF Surface,
- + IN gceSURF_ROTATION Rotation
- + );
- +
- +gceSTATUS
- +gcoSURF_GetPreRotation(
- + IN gcoSURF Surface,
- + IN gceSURF_ROTATION *Rotation
- + );
- +
- +gceSTATUS
- +gcoSURF_IsValid(
- + IN gcoSURF Surface
- + );
- +
- +#ifndef VIVANTE_NO_3D
- +/* Verify and return the state of the tile status mechanism. */
- +gceSTATUS
- +gcoSURF_IsTileStatusSupported(
- + IN gcoSURF Surface
- + );
- +
- +/* Process tile status for the specified surface. */
- +gceSTATUS
- +gcoSURF_SetTileStatus(
- + IN gcoSURF Surface
- + );
- +
- +/* Enable tile status for the specified surface. */
- +gceSTATUS
- +gcoSURF_EnableTileStatus(
- + IN gcoSURF Surface
- + );
- +
- +/* Disable tile status for the specified surface. */
- +gceSTATUS
- +gcoSURF_DisableTileStatus(
- + IN gcoSURF Surface,
- + IN gctBOOL Decompress
- + );
- +
- +gceSTATUS
- +gcoSURF_AlignResolveRect(
- + IN gcoSURF Surf,
- + IN gcsPOINT_PTR RectOrigin,
- + IN gcsPOINT_PTR RectSize,
- + OUT gcsPOINT_PTR AlignedOrigin,
- + OUT gcsPOINT_PTR AlignedSize
- + );
- +#endif /* VIVANTE_NO_3D */
- +
- +/* Get surface size. */
- +gceSTATUS
- +gcoSURF_GetSize(
- + IN gcoSURF Surface,
- + OUT gctUINT * Width,
- + OUT gctUINT * Height,
- + OUT gctUINT * Depth
- + );
- +
- +/* Get surface aligned sizes. */
- +gceSTATUS
- +gcoSURF_GetAlignedSize(
- + IN gcoSURF Surface,
- + OUT gctUINT * Width,
- + OUT gctUINT * Height,
- + OUT gctINT * Stride
- + );
- +
- +/* Get alignments. */
- +gceSTATUS
- +gcoSURF_GetAlignment(
- + IN gceSURF_TYPE Type,
- + IN gceSURF_FORMAT Format,
- + OUT gctUINT * AddressAlignment,
- + OUT gctUINT * XAlignment,
- + OUT gctUINT * YAlignment
- + );
- +
- +/* Get surface type and format. */
- +gceSTATUS
- +gcoSURF_GetFormat(
- + IN gcoSURF Surface,
- + OUT gceSURF_TYPE * Type,
- + OUT gceSURF_FORMAT * Format
- + );
- +
- +/* Get surface tiling. */
- +gceSTATUS
- +gcoSURF_GetTiling(
- + IN gcoSURF Surface,
- + OUT gceTILING * Tiling
- + );
- +
- +/* Lock the surface. */
- +gceSTATUS
- +gcoSURF_Lock(
- + IN gcoSURF Surface,
- + IN OUT gctUINT32 * Address,
- + IN OUT gctPOINTER * Memory
- + );
- +
- +/* Unlock the surface. */
- +gceSTATUS
- +gcoSURF_Unlock(
- + IN gcoSURF Surface,
- + IN gctPOINTER Memory
- + );
- +
- +/* Return pixel format parameters. */
- +gceSTATUS
- +gcoSURF_QueryFormat(
- + IN gceSURF_FORMAT Format,
- + OUT gcsSURF_FORMAT_INFO_PTR * Info
- + );
- +
- +/* Compute the color pixel mask. */
- +gceSTATUS
- +gcoSURF_ComputeColorMask(
- + IN gcsSURF_FORMAT_INFO_PTR Format,
- + OUT gctUINT32_PTR ColorMask
- + );
- +
- +/* Flush the surface. */
- +gceSTATUS
- +gcoSURF_Flush(
- + IN gcoSURF Surface
- + );
- +
- +/* Fill surface from it's tile status buffer. */
- +gceSTATUS
- +gcoSURF_FillFromTile(
- + IN gcoSURF Surface
- + );
- +
- +/* Check if surface needs a filler. */
- +gceSTATUS gcoSURF_NeedFiller(IN gcoSURF Surface);
- +
- +/* Fill surface with a value. */
- +gceSTATUS
- +gcoSURF_Fill(
- + IN gcoSURF Surface,
- + IN gcsPOINT_PTR Origin,
- + IN gcsSIZE_PTR Size,
- + IN gctUINT32 Value,
- + IN gctUINT32 Mask
- + );
- +
- +/* Alpha blend two surfaces together. */
- +gceSTATUS
- +gcoSURF_Blend(
- + IN gcoSURF SrcSurface,
- + IN gcoSURF DestSurface,
- + IN gcsPOINT_PTR SrcOrig,
- + IN gcsPOINT_PTR DestOrigin,
- + IN gcsSIZE_PTR Size,
- + IN gceSURF_BLEND_MODE Mode
- + );
- +
- +/* Create a new gcoSURF wrapper object. */
- +gceSTATUS
- +gcoSURF_ConstructWrapper(
- + IN gcoHAL Hal,
- + OUT gcoSURF * Surface
- + );
- +
- +/* Set the underlying buffer for the surface wrapper. */
- +gceSTATUS
- +gcoSURF_SetBuffer(
- + IN gcoSURF Surface,
- + IN gceSURF_TYPE Type,
- + IN gceSURF_FORMAT Format,
- + IN gctUINT Stride,
- + IN gctPOINTER Logical,
- + IN gctUINT32 Physical
- + );
- +
- +/* Set the underlying video buffer for the surface wrapper. */
- +gceSTATUS
- +gcoSURF_SetVideoBuffer(
- + IN gcoSURF Surface,
- + IN gceSURF_TYPE Type,
- + IN gceSURF_FORMAT Format,
- + IN gctUINT Width,
- + IN gctUINT Height,
- + IN gctUINT Stride,
- + IN gctPOINTER *LogicalPlane1,
- + IN gctUINT32 *PhysicalPlane1
- + );
- +
- +/* Set the size of the surface in pixels and map the underlying buffer. */
- +gceSTATUS
- +gcoSURF_SetWindow(
- + IN gcoSURF Surface,
- + IN gctUINT X,
- + IN gctUINT Y,
- + IN gctUINT Width,
- + IN gctUINT Height
- + );
- +
- +/* Set width/height alignment of the surface directly and calculate stride/size. This is only for dri backend now. Please be careful before use. */
- +gceSTATUS
- +gcoSURF_SetAlignment(
- + IN gcoSURF Surface,
- + IN gctUINT Width,
- + IN gctUINT Height
- + );
- +
- +/* Increase reference count of the surface. */
- +gceSTATUS
- +gcoSURF_ReferenceSurface(
- + IN gcoSURF Surface
- + );
- +
- +/* Get surface reference count. */
- +gceSTATUS
- +gcoSURF_QueryReferenceCount(
- + IN gcoSURF Surface,
- + OUT gctINT32 * ReferenceCount
- + );
- +
- +/* Set surface orientation. */
- +gceSTATUS
- +gcoSURF_SetOrientation(
- + IN gcoSURF Surface,
- + IN gceORIENTATION Orientation
- + );
- +
- +/* Query surface orientation. */
- +gceSTATUS
- +gcoSURF_QueryOrientation(
- + IN gcoSURF Surface,
- + OUT gceORIENTATION * Orientation
- + );
- +
- +gceSTATUS
- +gcoSURF_SetOffset(
- + IN gcoSURF Surface,
- + IN gctUINT Offset
- + );
- +
- +gceSTATUS
- +gcoSURF_GetOffset(
- + IN gcoSURF Surface,
- + OUT gctUINT *Offset
- + );
- +
- +gceSTATUS
- +gcoSURF_NODE_Cache(
- + IN gcsSURF_NODE_PTR Node,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes,
- + IN gceCACHEOPERATION Operation
- + );
- +
- +/* Perform CPU cache operation on surface */
- +gceSTATUS
- +gcoSURF_CPUCacheOperation(
- + IN gcoSURF Surface,
- + IN gceCACHEOPERATION Operation
- + );
- +
- +
- +gceSTATUS
- +gcoSURF_SetLinearResolveAddress(
- + IN gcoSURF Surface,
- + IN gctUINT32 Address,
- + IN gctPOINTER Memory
- + );
- +
- + gceSTATUS
- + gcoSURF_Swap(IN gcoSURF Surface1, IN gcoSURF Surface2);
- +
- +/******************************************************************************\
- +********************************* gcoDUMP Object ********************************
- +\******************************************************************************/
- +
- +/* Construct a new gcoDUMP object. */
- +gceSTATUS
- +gcoDUMP_Construct(
- + IN gcoOS Os,
- + IN gcoHAL Hal,
- + OUT gcoDUMP * Dump
- + );
- +
- +/* Destroy a gcoDUMP object. */
- +gceSTATUS
- +gcoDUMP_Destroy(
- + IN gcoDUMP Dump
- + );
- +
- +/* Enable/disable dumping. */
- +gceSTATUS
- +gcoDUMP_Control(
- + IN gcoDUMP Dump,
- + IN gctSTRING FileName
- + );
- +
- +gceSTATUS
- +gcoDUMP_IsEnabled(
- + IN gcoDUMP Dump,
- + OUT gctBOOL * Enabled
- + );
- +
- +/* Add surface. */
- +gceSTATUS
- +gcoDUMP_AddSurface(
- + IN gcoDUMP Dump,
- + IN gctINT32 Width,
- + IN gctINT32 Height,
- + IN gceSURF_FORMAT PixelFormat,
- + IN gctUINT32 Address,
- + IN gctSIZE_T ByteCount
- + );
- +
- +/* Mark the beginning of a frame. */
- +gceSTATUS
- +gcoDUMP_FrameBegin(
- + IN gcoDUMP Dump
- + );
- +
- +/* Mark the end of a frame. */
- +gceSTATUS
- +gcoDUMP_FrameEnd(
- + IN gcoDUMP Dump
- + );
- +
- +/* Dump data. */
- +gceSTATUS
- +gcoDUMP_DumpData(
- + IN gcoDUMP Dump,
- + IN gceDUMP_TAG Type,
- + IN gctUINT32 Address,
- + IN gctSIZE_T ByteCount,
- + IN gctCONST_POINTER Data
- + );
- +
- +/* Delete an address. */
- +gceSTATUS
- +gcoDUMP_Delete(
- + IN gcoDUMP Dump,
- + IN gctUINT32 Address
- + );
- +
- +/* Enable dump or not. */
- +gceSTATUS
- +gcoDUMP_SetDumpFlag(
- + IN gctBOOL DumpState
- + );
- +
- +/******************************************************************************\
- +******************************* gcsRECT Structure ******************************
- +\******************************************************************************/
- +
- +/* Initialize rectangle structure. */
- +gceSTATUS
- +gcsRECT_Set(
- + OUT gcsRECT_PTR Rect,
- + IN gctINT32 Left,
- + IN gctINT32 Top,
- + IN gctINT32 Right,
- + IN gctINT32 Bottom
- + );
- +
- +/* Return the width of the rectangle. */
- +gceSTATUS
- +gcsRECT_Width(
- + IN gcsRECT_PTR Rect,
- + OUT gctINT32 * Width
- + );
- +
- +/* Return the height of the rectangle. */
- +gceSTATUS
- +gcsRECT_Height(
- + IN gcsRECT_PTR Rect,
- + OUT gctINT32 * Height
- + );
- +
- +/* Ensure that top left corner is to the left and above the right bottom. */
- +gceSTATUS
- +gcsRECT_Normalize(
- + IN OUT gcsRECT_PTR Rect
- + );
- +
- +/* Compare two rectangles. */
- +gceSTATUS
- +gcsRECT_IsEqual(
- + IN gcsRECT_PTR Rect1,
- + IN gcsRECT_PTR Rect2,
- + OUT gctBOOL * Equal
- + );
- +
- +/* Compare the sizes of two rectangles. */
- +gceSTATUS
- +gcsRECT_IsOfEqualSize(
- + IN gcsRECT_PTR Rect1,
- + IN gcsRECT_PTR Rect2,
- + OUT gctBOOL * EqualSize
- + );
- +
- +gceSTATUS
- +gcsRECT_RelativeRotation(
- + IN gceSURF_ROTATION Orientation,
- + IN OUT gceSURF_ROTATION *Relation);
- +
- +gceSTATUS
- +
- +gcsRECT_Rotate(
- +
- + IN OUT gcsRECT_PTR Rect,
- +
- + IN gceSURF_ROTATION Rotation,
- +
- + IN gceSURF_ROTATION toRotation,
- +
- + IN gctINT32 SurfaceWidth,
- +
- + IN gctINT32 SurfaceHeight
- +
- + );
- +
- +/******************************************************************************\
- +**************************** gcsBOUNDARY Structure *****************************
- +\******************************************************************************/
- +
- +typedef struct _gcsBOUNDARY
- +{
- + gctINT x;
- + gctINT y;
- + gctINT width;
- + gctINT height;
- +}
- +gcsBOUNDARY;
- +
- +/******************************************************************************\
- +********************************* gcoHEAP Object ********************************
- +\******************************************************************************/
- +
- +typedef struct _gcoHEAP * gcoHEAP;
- +
- +/* Construct a new gcoHEAP object. */
- +gceSTATUS
- +gcoHEAP_Construct(
- + IN gcoOS Os,
- + IN gctSIZE_T AllocationSize,
- + OUT gcoHEAP * Heap
- + );
- +
- +/* Destroy an gcoHEAP object. */
- +gceSTATUS
- +gcoHEAP_Destroy(
- + IN gcoHEAP Heap
- + );
- +
- +/* Allocate memory. */
- +gceSTATUS
- +gcoHEAP_Allocate(
- + IN gcoHEAP Heap,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER * Node
- + );
- +
- +gceSTATUS
- +gcoHEAP_GetMemorySize(
- + IN gcoHEAP Heap,
- + IN gctPOINTER Memory,
- + OUT gctSIZE_T_PTR MemorySize
- + );
- +
- +/* Free memory. */
- +gceSTATUS
- +gcoHEAP_Free(
- + IN gcoHEAP Heap,
- + IN gctPOINTER Node
- + );
- +
- +#if (VIVANTE_PROFILER || gcdDEBUG)
- +/* Profile the heap. */
- +gceSTATUS
- +gcoHEAP_ProfileStart(
- + IN gcoHEAP Heap
- + );
- +
- +gceSTATUS
- +gcoHEAP_ProfileEnd(
- + IN gcoHEAP Heap,
- + IN gctCONST_STRING Title
- + );
- +#endif
- +
- +
- +/******************************************************************************\
- +******************************* Debugging Macros *******************************
- +\******************************************************************************/
- +
- +void
- +gcoOS_SetDebugLevel(
- + IN gctUINT32 Level
- + );
- +
- +void
- +gcoOS_GetDebugLevel(
- + OUT gctUINT32_PTR DebugLevel
- + );
- +
- +void
- +gcoOS_SetDebugZone(
- + IN gctUINT32 Zone
- + );
- +
- +void
- +gcoOS_GetDebugZone(
- + IN gctUINT32 Zone,
- + OUT gctUINT32_PTR DebugZone
- + );
- +
- +void
- +gcoOS_SetDebugLevelZone(
- + IN gctUINT32 Level,
- + IN gctUINT32 Zone
- + );
- +
- +void
- +gcoOS_SetDebugZones(
- + IN gctUINT32 Zones,
- + IN gctBOOL Enable
- + );
- +
- +void
- +gcoOS_SetDebugFile(
- + IN gctCONST_STRING FileName
- + );
- +
- +gctFILE
- +gcoOS_ReplaceDebugFile(
- + IN gctFILE fp
- + );
- +
- +/*******************************************************************************
- +**
- +** gcmFATAL
- +**
- +** Print a message to the debugger and execute a break point.
- +**
- +** ARGUMENTS:
- +**
- +** message Message.
- +** ... Optional arguments.
- +*/
- +
- +void
- +gckOS_DebugFatal(
- + IN gctCONST_STRING Message,
- + ...
- + );
- +
- +void
- +gcoOS_DebugFatal(
- + IN gctCONST_STRING Message,
- + ...
- + );
- +
- +#if gcmIS_DEBUG(gcdDEBUG_FATAL)
- +# define gcmFATAL gcoOS_DebugFatal
- +# define gcmkFATAL gckOS_DebugFatal
- +#elif gcdHAS_ELLIPSES
- +# define gcmFATAL(...)
- +# define gcmkFATAL(...)
- +#else
- + gcmINLINE static void
- + __dummy_fatal(
- + IN gctCONST_STRING Message,
- + ...
- + )
- + {
- + }
- +# define gcmFATAL __dummy_fatal
- +# define gcmkFATAL __dummy_fatal
- +#endif
- +
- +#define gcmENUM2TEXT(e) case e: return #e
- +
- +/*******************************************************************************
- +**
- +** gcmTRACE
- +**
- +** Print a message to the debugfer if the correct level has been set. In
- +** retail mode this macro does nothing.
- +**
- +** ARGUMENTS:
- +**
- +** level Level of message.
- +** message Message.
- +** ... Optional arguments.
- +*/
- +#define gcvLEVEL_NONE -1
- +#define gcvLEVEL_ERROR 0
- +#define gcvLEVEL_WARNING 1
- +#define gcvLEVEL_INFO 2
- +#define gcvLEVEL_VERBOSE 3
- +
- +void
- +gckOS_DebugTrace(
- + IN gctUINT32 Level,
- + IN gctCONST_STRING Message,
- + ...
- + );
- +
- +void
- +gckOS_DebugTraceN(
- + IN gctUINT32 Level,
- + IN gctUINT ArgumentSize,
- + IN gctCONST_STRING Message,
- + ...
- + );
- +
- +void
- +gcoOS_DebugTrace(
- + IN gctUINT32 Level,
- + IN gctCONST_STRING Message,
- + ...
- + );
- +
- +#if gcmIS_DEBUG(gcdDEBUG_TRACE)
- +# define gcmTRACE gcoOS_DebugTrace
- +# define gcmkTRACE gckOS_DebugTrace
- +# define gcmkTRACE_N gckOS_DebugTraceN
- +#elif gcdHAS_ELLIPSES
- +# define gcmTRACE(...)
- +# define gcmkTRACE(...)
- +# define gcmkTRACE_N(...)
- +#else
- + gcmINLINE static void
- + __dummy_trace(
- + IN gctUINT32 Level,
- + IN gctCONST_STRING Message,
- + ...
- + )
- + {
- + }
- +
- + gcmINLINE static void
- + __dummy_trace_n(
- + IN gctUINT32 Level,
- + IN gctUINT ArgumentSize,
- + IN gctCONST_STRING Message,
- + ...
- + )
- + {
- + }
- +
- +# define gcmTRACE __dummy_trace
- +# define gcmkTRACE __dummy_trace
- +# define gcmkTRACE_N __dummy_trace_n
- +#endif
- +
- +/* Zones common for kernel and user. */
- +#define gcvZONE_OS (1 << 0)
- +#define gcvZONE_HARDWARE (1 << 1)
- +#define gcvZONE_HEAP (1 << 2)
- +#define gcvZONE_SIGNAL (1 << 27)
- +
- +/* Kernel zones. */
- +#define gcvZONE_KERNEL (1 << 3)
- +#define gcvZONE_VIDMEM (1 << 4)
- +#define gcvZONE_COMMAND (1 << 5)
- +#define gcvZONE_DRIVER (1 << 6)
- +#define gcvZONE_CMODEL (1 << 7)
- +#define gcvZONE_MMU (1 << 8)
- +#define gcvZONE_EVENT (1 << 9)
- +#define gcvZONE_DEVICE (1 << 10)
- +#define gcvZONE_DATABASE (1 << 11)
- +#define gcvZONE_INTERRUPT (1 << 12)
- +#define gcvZONE_POWER (1 << 13)
- +
- +/* User zones. */
- +#define gcvZONE_HAL (1 << 3)
- +#define gcvZONE_BUFFER (1 << 4)
- +#define gcvZONE_CONTEXT (1 << 5)
- +#define gcvZONE_SURFACE (1 << 6)
- +#define gcvZONE_INDEX (1 << 7)
- +#define gcvZONE_STREAM (1 << 8)
- +#define gcvZONE_TEXTURE (1 << 9)
- +#define gcvZONE_2D (1 << 10)
- +#define gcvZONE_3D (1 << 11)
- +#define gcvZONE_COMPILER (1 << 12)
- +#define gcvZONE_MEMORY (1 << 13)
- +#define gcvZONE_STATE (1 << 14)
- +#define gcvZONE_AUX (1 << 15)
- +#define gcvZONE_VERTEX (1 << 16)
- +#define gcvZONE_CL (1 << 17)
- +#define gcvZONE_COMPOSITION (1 << 17)
- +#define gcvZONE_VG (1 << 18)
- +#define gcvZONE_IMAGE (1 << 19)
- +#define gcvZONE_UTILITY (1 << 20)
- +#define gcvZONE_PARAMETERS (1 << 21)
- +
- +/* API definitions. */
- +#define gcvZONE_API_HAL (1 << 28)
- +#define gcvZONE_API_EGL (2 << 28)
- +#define gcvZONE_API_ES11 (3 << 28)
- +#define gcvZONE_API_ES20 (4 << 28)
- +#define gcvZONE_API_VG11 (5 << 28)
- +#define gcvZONE_API_GL (6 << 28)
- +#define gcvZONE_API_DFB (7 << 28)
- +#define gcvZONE_API_GDI (8 << 28)
- +#define gcvZONE_API_D3D (9 << 28)
- +#define gcvZONE_API_ES30 (10 << 28)
- +
- +
- +#define gcmZONE_GET_API(zone) ((zone) >> 28)
- +/*Set gcdZONE_MASE like 0x0 | gcvZONE_API_EGL
- +will enable print EGL module debug info*/
- +#define gcdZONE_MASK 0x0FFFFFFF
- +
- +/* Handy zones. */
- +#define gcvZONE_NONE 0
- +#define gcvZONE_ALL 0x0FFFFFFF
- +
- +/*Dump API depth set 1 for API, 2 for API and API behavior*/
- +#define gcvDUMP_API_DEPTH 1
- +
- +/*******************************************************************************
- +**
- +** gcmTRACE_ZONE
- +**
- +** Print a message to the debugger if the correct level and zone has been
- +** set. In retail mode this macro does nothing.
- +**
- +** ARGUMENTS:
- +**
- +** Level Level of message.
- +** Zone Zone of message.
- +** Message Message.
- +** ... Optional arguments.
- +*/
- +
- +void
- +gckOS_DebugTraceZone(
- + IN gctUINT32 Level,
- + IN gctUINT32 Zone,
- + IN gctCONST_STRING Message,
- + ...
- + );
- +
- +void
- +gckOS_DebugTraceZoneN(
- + IN gctUINT32 Level,
- + IN gctUINT32 Zone,
- + IN gctUINT ArgumentSize,
- + IN gctCONST_STRING Message,
- + ...
- + );
- +
- +void
- +gcoOS_DebugTraceZone(
- + IN gctUINT32 Level,
- + IN gctUINT32 Zone,
- + IN gctCONST_STRING Message,
- + ...
- + );
- +
- +#if gcmIS_DEBUG(gcdDEBUG_TRACE)
- +# define gcmTRACE_ZONE gcoOS_DebugTraceZone
- +# define gcmkTRACE_ZONE gckOS_DebugTraceZone
- +# define gcmkTRACE_ZONE_N gckOS_DebugTraceZoneN
- +#elif gcdHAS_ELLIPSES
- +# define gcmTRACE_ZONE(...)
- +# define gcmkTRACE_ZONE(...)
- +# define gcmkTRACE_ZONE_N(...)
- +#else
- + gcmINLINE static void
- + __dummy_trace_zone(
- + IN gctUINT32 Level,
- + IN gctUINT32 Zone,
- + IN gctCONST_STRING Message,
- + ...
- + )
- + {
- + }
- +
- + gcmINLINE static void
- + __dummy_trace_zone_n(
- + IN gctUINT32 Level,
- + IN gctUINT32 Zone,
- + IN gctUINT ArgumentSize,
- + IN gctCONST_STRING Message,
- + ...
- + )
- + {
- + }
- +
- +# define gcmTRACE_ZONE __dummy_trace_zone
- +# define gcmkTRACE_ZONE __dummy_trace_zone
- +# define gcmkTRACE_ZONE_N __dummy_trace_zone_n
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gcmDEBUG_ONLY
- +**
- +** Execute a statement or function only in DEBUG mode.
- +**
- +** ARGUMENTS:
- +**
- +** f Statement or function to execute.
- +*/
- +#if gcmIS_DEBUG(gcdDEBUG_CODE)
- +# define gcmDEBUG_ONLY(f) f
- +#else
- +# define gcmDEBUG_ONLY(f)
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gcmSTACK_PUSH
- +** gcmSTACK_POP
- +** gcmSTACK_DUMP
- +**
- +** Push or pop a function with entry arguments on the trace stack.
- +**
- +** ARGUMENTS:
- +**
- +** Function Name of function.
- +** Line Line number.
- +** Text Optional text.
- +** ... Optional arguments for text.
- +*/
- +#if gcmIS_DEBUG(gcdDEBUG_STACK)
- + void
- + gcoOS_StackPush(
- + IN gctCONST_STRING Function,
- + IN gctINT Line,
- + IN gctCONST_STRING Text,
- + ...
- + );
- + void
- + gcoOS_StackPop(
- + IN gctCONST_STRING Function
- + );
- + void
- + gcoOS_StackDump(
- + void
- + );
- +# define gcmSTACK_PUSH gcoOS_StackPush
- +# define gcmSTACK_POP gcoOS_StackPop
- +# define gcmSTACK_DUMP gcoOS_StackDump
- +#elif gcdHAS_ELLIPSES
- +# define gcmSTACK_PUSH(...) do { } while (0)
- +# define gcmSTACK_POP(Function) do { } while (0)
- +# define gcmSTACK_DUMP() do { } while (0)
- +#else
- + gcmINLINE static void
- + __dummy_stack_push(
- + IN gctCONST_STRING Function,
- + IN gctINT Line,
- + IN gctCONST_STRING Text, ...
- + )
- + {
- + }
- +# define gcmSTACK_PUSH __dummy_stack_push
- +# define gcmSTACK_POP(Function) do { } while (0)
- +# define gcmSTACK_DUMP() do { } while (0)
- +#endif
- +
- +/******************************************************************************\
- +******************************** Logging Macros ********************************
- +\******************************************************************************/
- +
- +#define gcdHEADER_LEVEL gcvLEVEL_VERBOSE
- +
- +
- +#if gcdENABLE_PROFILING
- +void
- +gcoOS_ProfileDB(
- + IN gctCONST_STRING Function,
- + IN OUT gctBOOL_PTR Initialized
- + );
- +
- +#define gcmHEADER() \
- + static gctBOOL __profile__initialized__ = gcvFALSE; \
- + gcmSTACK_PUSH(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
- + gcoOS_ProfileDB(__FUNCTION__, &__profile__initialized__)
- +#define gcmHEADER_ARG(...) \
- + static gctBOOL __profile__initialized__ = gcvFALSE; \
- + gcmSTACK_PUSH(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
- + gcoOS_ProfileDB(__FUNCTION__, &__profile__initialized__)
- +#define gcmFOOTER() \
- + gcmSTACK_POP(__FUNCTION__); \
- + gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
- +#define gcmFOOTER_NO() \
- + gcmSTACK_POP(__FUNCTION__); \
- + gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
- +#define gcmFOOTER_ARG(...) \
- + gcmSTACK_POP(__FUNCTION__); \
- + gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
- +#define gcmFOOTER_KILL() \
- + gcmSTACK_POP(__FUNCTION__); \
- + gcoOS_ProfileDB(gcvNULL, gcvNULL)
- +
- +#else /* gcdENABLE_PROFILING */
- +
- +#if gcdHAS_ELLIPSES
- +#define gcmHEADER() \
- + gctINT8 __user__ = 1; \
- + gctINT8_PTR __user_ptr__ = &__user__; \
- + gcmSTACK_PUSH(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
- + gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
- + "++%s(%d)", __FUNCTION__, __LINE__)
- +#else
- + gcmINLINE static void
- + __dummy_header(void)
- + {
- + }
- +# define gcmHEADER __dummy_header
- +#endif
- +
- +#if gcdHAS_ELLIPSES
- +# define gcmHEADER_ARG(Text, ...) \
- + gctINT8 __user__ = 1; \
- + gctINT8_PTR __user_ptr__ = &__user__; \
- + gcmSTACK_PUSH(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
- + gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
- + "++%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__)
- +#else
- + gcmINLINE static void
- + __dummy_header_arg(
- + IN gctCONST_STRING Text,
- + ...
- + )
- + {
- + }
- +# define gcmHEADER_ARG __dummy_header_arg
- +#endif
- +
- +#if gcdHAS_ELLIPSES
- +# define gcmFOOTER() \
- + gcmSTACK_POP(__FUNCTION__); \
- + gcmPROFILE_ONLY(gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
- + "--%s(%d) [%llu,%llu]: status=%d(%s)", \
- + __FUNCTION__, __LINE__, \
- + __ticks__, __total__, \
- + status, gcoOS_DebugStatus2Name(status))); \
- + gcmPROFILE_ELSE(gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
- + "--%s(%d): status=%d(%s)", \
- + __FUNCTION__, __LINE__, \
- + status, gcoOS_DebugStatus2Name(status))); \
- + *__user_ptr__ -= 1
- +#else
- + gcmINLINE static void
- + __dummy_footer(void)
- + {
- + }
- +# define gcmFOOTER __dummy_footer
- +#endif
- +
- +#if gcdHAS_ELLIPSES
- +#define gcmFOOTER_NO() \
- + gcmSTACK_POP(__FUNCTION__); \
- + gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
- + "--%s(%d)", __FUNCTION__, __LINE__); \
- + *__user_ptr__ -= 1
- +#else
- + gcmINLINE static void
- + __dummy_footer_no(void)
- + {
- + }
- +# define gcmFOOTER_NO __dummy_footer_no
- +#endif
- +
- +#if gcdHAS_ELLIPSES
- +#define gcmFOOTER_KILL() \
- + gcmSTACK_POP(__FUNCTION__); \
- + gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
- + "--%s(%d)", __FUNCTION__, __LINE__); \
- + *__user_ptr__ -= 1
- +#else
- + gcmINLINE static void
- + __dummy_footer_kill(void)
- + {
- + }
- +# define gcmFOOTER_KILL __dummy_footer_kill
- +#endif
- +
- +#if gcdHAS_ELLIPSES
- +# define gcmFOOTER_ARG(Text, ...) \
- + gcmSTACK_POP(__FUNCTION__); \
- + gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
- + "--%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__); \
- + *__user_ptr__ -= 1
- +#else
- + gcmINLINE static void
- + __dummy_footer_arg(
- + IN gctCONST_STRING Text,
- + ...
- + )
- + {
- + }
- +# define gcmFOOTER_ARG __dummy_footer_arg
- +#endif
- +
- +#endif /* gcdENABLE_PROFILING */
- +
- +#if gcdHAS_ELLIPSES
- +#define gcmkHEADER() \
- + gctINT8 __kernel__ = 1; \
- + gctINT8_PTR __kernel_ptr__ = &__kernel__; \
- + gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
- + "++%s(%d)", __FUNCTION__, __LINE__)
- +#else
- + gcmINLINE static void
- + __dummy_kheader(void)
- + {
- + }
- +# define gcmkHEADER __dummy_kheader
- +#endif
- +
- +#if gcdHAS_ELLIPSES
- +# define gcmkHEADER_ARG(Text, ...) \
- + gctINT8 __kernel__ = 1; \
- + gctINT8_PTR __kernel_ptr__ = &__kernel__; \
- + gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
- + "++%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__)
- +#else
- + gcmINLINE static void
- + __dummy_kheader_arg(
- + IN gctCONST_STRING Text,
- + ...
- + )
- + {
- + }
- +# define gcmkHEADER_ARG __dummy_kheader_arg
- +#endif
- +
- +#if gcdHAS_ELLIPSES
- +#define gcmkFOOTER() \
- + gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
- + "--%s(%d): status=%d(%s)", \
- + __FUNCTION__, __LINE__, status, gckOS_DebugStatus2Name(status)); \
- + *__kernel_ptr__ -= 1
- +#else
- + gcmINLINE static void
- + __dummy_kfooter(void)
- + {
- + }
- +# define gcmkFOOTER __dummy_kfooter
- +#endif
- +
- +#if gcdHAS_ELLIPSES
- +#define gcmkFOOTER_NO() \
- + gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
- + "--%s(%d)", __FUNCTION__, __LINE__); \
- + *__kernel_ptr__ -= 1
- +#else
- + gcmINLINE static void
- + __dummy_kfooter_no(void)
- + {
- + }
- +# define gcmkFOOTER_NO __dummy_kfooter_no
- +#endif
- +
- +#if gcdHAS_ELLIPSES
- +# define gcmkFOOTER_ARG(Text, ...) \
- + gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
- + "--%s(%d): " Text, \
- + __FUNCTION__, __LINE__, __VA_ARGS__); \
- + *__kernel_ptr__ -= 1
- +#else
- + gcmINLINE static void
- + __dummy_kfooter_arg(
- + IN gctCONST_STRING Text,
- + ...
- + )
- + {
- + }
- +# define gcmkFOOTER_ARG __dummy_kfooter_arg
- +#endif
- +
- +#define gcmOPT_VALUE(ptr) (((ptr) == gcvNULL) ? 0 : *(ptr))
- +#define gcmOPT_VALUE_INDEX(ptr, index) (((ptr) == gcvNULL) ? 0 : ptr[index])
- +#define gcmOPT_POINTER(ptr) (((ptr) == gcvNULL) ? gcvNULL : *(ptr))
- +#define gcmOPT_STRING(ptr) (((ptr) == gcvNULL) ? "(nil)" : (ptr))
- +
- +void
- +gckOS_Print(
- + IN gctCONST_STRING Message,
- + ...
- + );
- +
- +void
- +gckOS_PrintN(
- + IN gctUINT ArgumentSize,
- + IN gctCONST_STRING Message,
- + ...
- + );
- +
- +void
- +gckOS_CopyPrint(
- + IN gctCONST_STRING Message,
- + ...
- + );
- +
- +void
- +gcoOS_Print(
- + IN gctCONST_STRING Message,
- + ...
- + );
- +
- +#define gcmPRINT gcoOS_Print
- +#define gcmkPRINT gckOS_Print
- +#define gcmkPRINT_N gckOS_PrintN
- +
- +#if gcdPRINT_VERSION
- +# define gcmPRINT_VERSION() do { \
- + _gcmPRINT_VERSION(gcm); \
- + gcmSTACK_DUMP(); \
- + } while (0)
- +# define gcmkPRINT_VERSION() _gcmPRINT_VERSION(gcmk)
- +# define _gcmPRINT_VERSION(prefix) \
- + prefix##TRACE(gcvLEVEL_ERROR, \
- + "Vivante HAL version %d.%d.%d build %d %s %s", \
- + gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, \
- + gcvVERSION_BUILD, gcvVERSION_DATE, gcvVERSION_TIME )
- +#else
- +# define gcmPRINT_VERSION() do { gcmSTACK_DUMP(); } while (gcvFALSE)
- +# define gcmkPRINT_VERSION() do { } while (gcvFALSE)
- +#endif
- +
- +typedef enum _gceDUMP_BUFFER
- +{
- + gceDUMP_BUFFER_CONTEXT,
- + gceDUMP_BUFFER_USER,
- + gceDUMP_BUFFER_KERNEL,
- + gceDUMP_BUFFER_LINK,
- + gceDUMP_BUFFER_WAITLINK,
- + gceDUMP_BUFFER_FROM_USER,
- +}
- +gceDUMP_BUFFER;
- +
- +void
- +gckOS_DumpBuffer(
- + IN gckOS Os,
- + IN gctPOINTER Buffer,
- + IN gctUINT Size,
- + IN gceDUMP_BUFFER Type,
- + IN gctBOOL CopyMessage
- + );
- +
- +#define gcmkDUMPBUFFER gckOS_DumpBuffer
- +
- +#if gcdDUMP_COMMAND
- +# define gcmkDUMPCOMMAND(Os, Buffer, Size, Type, CopyMessage) \
- + gcmkDUMPBUFFER(Os, Buffer, Size, Type, CopyMessage)
- +#else
- +# define gcmkDUMPCOMMAND(Os, Buffer, Size, Type, CopyMessage)
- +#endif
- +
- +#if gcmIS_DEBUG(gcdDEBUG_CODE)
- +
- +void
- +gckOS_DebugFlush(
- + gctCONST_STRING CallerName,
- + gctUINT LineNumber,
- + gctUINT32 DmaAddress
- + );
- +
- +# define gcmkDEBUGFLUSH(DmaAddress) \
- + gckOS_DebugFlush(__FUNCTION__, __LINE__, DmaAddress)
- +#else
- +# define gcmkDEBUGFLUSH(DmaAddress)
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gcmDUMP_FRAMERATE
- +**
- +** Print average frame rate
- +**
- +*/
- +#if gcdDUMP_FRAMERATE
- + gceSTATUS
- + gcfDumpFrameRate(
- + void
- + );
- +# define gcmDUMP_FRAMERATE gcfDumpFrameRate
- +#elif gcdHAS_ELLIPSES
- +# define gcmDUMP_FRAMERATE(...)
- +#else
- + gcmINLINE static void
- + __dummy_dump_frame_rate(
- + void
- + )
- + {
- + }
- +# define gcmDUMP_FRAMERATE __dummy_dump_frame_rate
- +#endif
- +
- +
- +/*******************************************************************************
- +**
- +** gcmDUMP
- +**
- +** Print a dump message.
- +**
- +** ARGUMENTS:
- +**
- +** gctSTRING Message.
- +**
- +** ... Optional arguments.
- +*/
- +#if gcdDUMP
- + gceSTATUS
- + gcfDump(
- + IN gcoOS Os,
- + IN gctCONST_STRING String,
- + ...
- + );
- +# define gcmDUMP gcfDump
- +#elif gcdHAS_ELLIPSES
- +# define gcmDUMP(...)
- +#else
- + gcmINLINE static void
- + __dummy_dump(
- + IN gcoOS Os,
- + IN gctCONST_STRING Message,
- + ...
- + )
- + {
- + }
- +# define gcmDUMP __dummy_dump
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gcmDUMP_DATA
- +**
- +** Add data to the dump.
- +**
- +** ARGUMENTS:
- +**
- +** gctSTRING Tag
- +** Tag for dump.
- +**
- +** gctPOINTER Logical
- +** Logical address of buffer.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes.
- +*/
- +
- +#if gcdDUMP || gcdDUMP_COMMAND
- + gceSTATUS
- + gcfDumpData(
- + IN gcoOS Os,
- + IN gctSTRING Tag,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes
- + );
- +# define gcmDUMP_DATA gcfDumpData
- +#elif gcdHAS_ELLIPSES
- +# define gcmDUMP_DATA(...)
- +#else
- + gcmINLINE static void
- + __dummy_dump_data(
- + IN gcoOS Os,
- + IN gctSTRING Tag,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes
- + )
- + {
- + }
- +# define gcmDUMP_DATA __dummy_dump_data
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gcmDUMP_BUFFER
- +**
- +** Print a buffer to the dump.
- +**
- +** ARGUMENTS:
- +**
- +** gctSTRING Tag
- +** Tag for dump.
- +**
- +** gctUINT32 Physical
- +** Physical address of buffer.
- +**
- +** gctPOINTER Logical
- +** Logical address of buffer.
- +**
- +** gctUINT32 Offset
- +** Offset into buffer.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes.
- +*/
- +
- +#if gcdDUMP || gcdDUMP_COMMAND
- +gceSTATUS
- +gcfDumpBuffer(
- + IN gcoOS Os,
- + IN gctSTRING Tag,
- + IN gctUINT32 Physical,
- + IN gctPOINTER Logical,
- + IN gctUINT32 Offset,
- + IN gctSIZE_T Bytes
- + );
- +# define gcmDUMP_BUFFER gcfDumpBuffer
- +#elif gcdHAS_ELLIPSES
- +# define gcmDUMP_BUFFER(...)
- +#else
- + gcmINLINE static void
- + __dummy_dump_buffer(
- + IN gcoOS Os,
- + IN gctSTRING Tag,
- + IN gctUINT32 Physical,
- + IN gctPOINTER Logical,
- + IN gctUINT32 Offset,
- + IN gctSIZE_T Bytes
- + )
- + {
- + }
- +# define gcmDUMP_BUFFER __dummy_dump_buffer
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gcmDUMP_API
- +**
- +** Print a dump message for a high level API prefixed by the function name.
- +**
- +** ARGUMENTS:
- +**
- +** gctSTRING Message.
- +**
- +** ... Optional arguments.
- +*/
- +gceSTATUS gcfDumpApi(IN gctCONST_STRING String, ...);
- +#if gcdDUMP_API
- +# define gcmDUMP_API gcfDumpApi
- +#elif gcdHAS_ELLIPSES
- +# define gcmDUMP_API(...)
- +#else
- + gcmINLINE static void
- + __dummy_dump_api(
- + IN gctCONST_STRING Message,
- + ...
- + )
- + {
- + }
- +# define gcmDUMP_API __dummy_dump_api
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gcmDUMP_API_ARRAY
- +**
- +** Print an array of data.
- +**
- +** ARGUMENTS:
- +**
- +** gctUINT32_PTR Pointer to array.
- +** gctUINT32 Size.
- +*/
- +gceSTATUS gcfDumpArray(IN gctCONST_POINTER Data, IN gctUINT32 Size);
- +#if gcdDUMP_API
- +# define gcmDUMP_API_ARRAY gcfDumpArray
- +#elif gcdHAS_ELLIPSES
- +# define gcmDUMP_API_ARRAY(...)
- +#else
- + gcmINLINE static void
- + __dummy_dump_api_array(
- + IN gctCONST_POINTER Data,
- + IN gctUINT32 Size
- + )
- + {
- + }
- +# define gcmDUMP_API_ARRAY __dummy_dump_api_array
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gcmDUMP_API_ARRAY_TOKEN
- +**
- +** Print an array of data terminated by a token.
- +**
- +** ARGUMENTS:
- +**
- +** gctUINT32_PTR Pointer to array.
- +** gctUINT32 Termination.
- +*/
- +gceSTATUS gcfDumpArrayToken(IN gctCONST_POINTER Data, IN gctUINT32 Termination);
- +#if gcdDUMP_API
- +# define gcmDUMP_API_ARRAY_TOKEN gcfDumpArrayToken
- +#elif gcdHAS_ELLIPSES
- +# define gcmDUMP_API_ARRAY_TOKEN(...)
- +#else
- + gcmINLINE static void
- + __dummy_dump_api_array_token(
- + IN gctCONST_POINTER Data,
- + IN gctUINT32 Termination
- + )
- + {
- + }
- +# define gcmDUMP_API_ARRAY_TOKEN __dummy_dump_api_array_token
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gcmDUMP_API_DATA
- +**
- +** Print an array of bytes.
- +**
- +** ARGUMENTS:
- +**
- +** gctCONST_POINTER Pointer to array.
- +** gctSIZE_T Size.
- +*/
- +gceSTATUS gcfDumpApiData(IN gctCONST_POINTER Data, IN gctSIZE_T Size);
- +#if gcdDUMP_API
- +# define gcmDUMP_API_DATA gcfDumpApiData
- +#elif gcdHAS_ELLIPSES
- +# define gcmDUMP_API_DATA(...)
- +#else
- + gcmINLINE static void
- + __dummy_dump_api_data(
- + IN gctCONST_POINTER Data,
- + IN gctSIZE_T Size
- + )
- + {
- + }
- +# define gcmDUMP_API_DATA __dummy_dump_api_data
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gcmTRACE_RELEASE
- +**
- +** Print a message to the shader debugger.
- +**
- +** ARGUMENTS:
- +**
- +** message Message.
- +** ... Optional arguments.
- +*/
- +
- +#define gcmTRACE_RELEASE gcoOS_DebugShaderTrace
- +
- +void
- +gcoOS_DebugShaderTrace(
- + IN gctCONST_STRING Message,
- + ...
- + );
- +
- +void
- +gcoOS_SetDebugShaderFiles(
- + IN gctCONST_STRING VSFileName,
- + IN gctCONST_STRING FSFileName
- + );
- +
- +void
- +gcoOS_SetDebugShaderFileType(
- + IN gctUINT32 ShaderType
- + );
- +
- +void
- +gcoOS_EnableDebugBuffer(
- + IN gctBOOL Enable
- + );
- +
- +/*******************************************************************************
- +**
- +** gcmBREAK
- +**
- +** Break into the debugger. In retail mode this macro does nothing.
- +**
- +** ARGUMENTS:
- +**
- +** None.
- +*/
- +
- +void
- +gcoOS_DebugBreak(
- + void
- + );
- +
- +void
- +gckOS_DebugBreak(
- + void
- + );
- +
- +#if gcmIS_DEBUG(gcdDEBUG_BREAK)
- +# define gcmBREAK gcoOS_DebugBreak
- +# define gcmkBREAK gckOS_DebugBreak
- +#else
- +# define gcmBREAK()
- +# define gcmkBREAK()
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gcmASSERT
- +**
- +** Evaluate an expression and break into the debugger if the expression
- +** evaluates to false. In retail mode this macro does nothing.
- +**
- +** ARGUMENTS:
- +**
- +** exp Expression to evaluate.
- +*/
- +#if gcmIS_DEBUG(gcdDEBUG_ASSERT)
- +# define _gcmASSERT(prefix, exp) \
- + do \
- + { \
- + if (!(exp)) \
- + { \
- + prefix##TRACE(gcvLEVEL_ERROR, \
- + #prefix "ASSERT at %s(%d)", \
- + __FUNCTION__, __LINE__); \
- + prefix##TRACE(gcvLEVEL_ERROR, \
- + "(%s)", #exp); \
- + prefix##BREAK(); \
- + } \
- + } \
- + while (gcvFALSE)
- +# define gcmASSERT(exp) _gcmASSERT(gcm, exp)
- +# define gcmkASSERT(exp) _gcmASSERT(gcmk, exp)
- +#else
- +# define gcmASSERT(exp)
- +# define gcmkASSERT(exp)
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gcmVERIFY
- +**
- +** Verify if an expression returns true. If the expression does not
- +** evaluates to true, an assertion will happen in debug mode.
- +**
- +** ARGUMENTS:
- +**
- +** exp Expression to evaluate.
- +*/
- +#if gcmIS_DEBUG(gcdDEBUG_ASSERT)
- +# define gcmVERIFY(exp) gcmASSERT(exp)
- +# define gcmkVERIFY(exp) gcmkASSERT(exp)
- +#else
- +# define gcmVERIFY(exp) exp
- +# define gcmkVERIFY(exp) exp
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gcmVERIFY_OK
- +**
- +** Verify a fucntion returns gcvSTATUS_OK. If the function does not return
- +** gcvSTATUS_OK, an assertion will happen in debug mode.
- +**
- +** ARGUMENTS:
- +**
- +** func Function to evaluate.
- +*/
- +
- +void
- +gcoOS_Verify(
- + IN gceSTATUS status
- + );
- +
- +void
- +gckOS_Verify(
- + IN gceSTATUS status
- + );
- +
- +#if gcmIS_DEBUG(gcdDEBUG_ASSERT)
- +# define gcmVERIFY_OK(func) \
- + do \
- + { \
- + gceSTATUS verifyStatus = func; \
- + gcoOS_Verify(verifyStatus); \
- + if (verifyStatus != gcvSTATUS_OK) \
- + { \
- + gcmTRACE( \
- + gcvLEVEL_ERROR, \
- + "gcmVERIFY_OK(%d): function returned %d", \
- + __LINE__, verifyStatus \
- + ); \
- + } \
- + gcmASSERT(verifyStatus == gcvSTATUS_OK); \
- + } \
- + while (gcvFALSE)
- +# define gcmkVERIFY_OK(func) \
- + do \
- + { \
- + gceSTATUS verifyStatus = func; \
- + if (verifyStatus != gcvSTATUS_OK) \
- + { \
- + gcmkTRACE( \
- + gcvLEVEL_ERROR, \
- + "gcmkVERIFY_OK(%d): function returned %d", \
- + __LINE__, verifyStatus \
- + ); \
- + } \
- + gckOS_Verify(verifyStatus); \
- + gcmkASSERT(verifyStatus == gcvSTATUS_OK); \
- + } \
- + while (gcvFALSE)
- +#else
- +# define gcmVERIFY_OK(func) func
- +# define gcmkVERIFY_OK(func) func
- +#endif
- +
- +gctCONST_STRING
- +gcoOS_DebugStatus2Name(
- + gceSTATUS status
- + );
- +
- +gctCONST_STRING
- +gckOS_DebugStatus2Name(
- + gceSTATUS status
- + );
- +
- +/*******************************************************************************
- +**
- +** gcmERR_BREAK
- +**
- +** Executes a break statement on error.
- +**
- +** ASSUMPTIONS:
- +**
- +** 'status' variable of gceSTATUS type must be defined.
- +**
- +** ARGUMENTS:
- +**
- +** func Function to evaluate.
- +*/
- +#define _gcmERR_BREAK(prefix, func) \
- + status = func; \
- + if (gcmIS_ERROR(status)) \
- + { \
- + prefix##PRINT_VERSION(); \
- + prefix##TRACE(gcvLEVEL_ERROR, \
- + #prefix "ERR_BREAK: status=%d(%s) @ %s(%d)", \
- + status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
- + break; \
- + } \
- + do { } while (gcvFALSE)
- +#define _gcmkERR_BREAK(prefix, func) \
- + status = func; \
- + if (gcmIS_ERROR(status)) \
- + { \
- + prefix##PRINT_VERSION(); \
- + prefix##TRACE(gcvLEVEL_ERROR, \
- + #prefix "ERR_BREAK: status=%d(%s) @ %s(%d)", \
- + status, gckOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
- + break; \
- + } \
- + do { } while (gcvFALSE)
- +#define gcmERR_BREAK(func) _gcmERR_BREAK(gcm, func)
- +#define gcmkERR_BREAK(func) _gcmkERR_BREAK(gcmk, func)
- +
- +/*******************************************************************************
- +**
- +** gcmERR_RETURN
- +**
- +** Executes a return on error.
- +**
- +** ASSUMPTIONS:
- +**
- +** 'status' variable of gceSTATUS type must be defined.
- +**
- +** ARGUMENTS:
- +**
- +** func Function to evaluate.
- +*/
- +#define _gcmERR_RETURN(prefix, func) \
- + status = func; \
- + if (gcmIS_ERROR(status)) \
- + { \
- + prefix##PRINT_VERSION(); \
- + prefix##TRACE(gcvLEVEL_ERROR, \
- + #prefix "ERR_RETURN: status=%d(%s) @ %s(%d)", \
- + status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
- + prefix##FOOTER(); \
- + return status; \
- + } \
- + do { } while (gcvFALSE)
- +#define _gcmkERR_RETURN(prefix, func) \
- + status = func; \
- + if (gcmIS_ERROR(status)) \
- + { \
- + prefix##PRINT_VERSION(); \
- + prefix##TRACE(gcvLEVEL_ERROR, \
- + #prefix "ERR_RETURN: status=%d(%s) @ %s(%d)", \
- + status, gckOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
- + prefix##FOOTER(); \
- + return status; \
- + } \
- + do { } while (gcvFALSE)
- +#define gcmERR_RETURN(func) _gcmERR_RETURN(gcm, func)
- +#define gcmkERR_RETURN(func) _gcmkERR_RETURN(gcmk, func)
- +
- +
- +/*******************************************************************************
- +**
- +** gcmONERROR
- +**
- +** Jump to the error handler in case there is an error.
- +**
- +** ASSUMPTIONS:
- +**
- +** 'status' variable of gceSTATUS type must be defined.
- +**
- +** ARGUMENTS:
- +**
- +** func Function to evaluate.
- +*/
- +#define _gcmONERROR(prefix, func) \
- + do \
- + { \
- + status = func; \
- + if (gcmIS_ERROR(status)) \
- + { \
- + prefix##PRINT_VERSION(); \
- + prefix##TRACE(gcvLEVEL_ERROR, \
- + #prefix "ONERROR: status=%d(%s) @ %s(%d)", \
- + status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
- + goto OnError; \
- + } \
- + } \
- + while (gcvFALSE)
- +#define _gcmkONERROR(prefix, func) \
- + do \
- + { \
- + status = func; \
- + if (gcmIS_ERROR(status)) \
- + { \
- + prefix##PRINT_VERSION(); \
- + prefix##TRACE(gcvLEVEL_ERROR, \
- + #prefix "ONERROR: status=%d(%s) @ %s(%d)", \
- + status, gckOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
- + goto OnError; \
- + } \
- + } \
- + while (gcvFALSE)
- +#define gcmONERROR(func) _gcmONERROR(gcm, func)
- +#define gcmkONERROR(func) _gcmkONERROR(gcmk, func)
- +
- +/*******************************************************************************
- +**
- +** gcmVERIFY_LOCK
- +**
- +** Verifies whether the surface is locked.
- +**
- +** ARGUMENTS:
- +**
- +** surfaceInfo Pointer to the surface iniformational structure.
- +*/
- +#define gcmVERIFY_LOCK(surfaceInfo) \
- + if (!surfaceInfo->node.valid) \
- + { \
- + gcmONERROR(gcvSTATUS_MEMORY_UNLOCKED); \
- + } \
- +
- +/*******************************************************************************
- +**
- +** gcmVERIFY_NODE_LOCK
- +**
- +** Verifies whether the surface node is locked.
- +**
- +** ARGUMENTS:
- +**
- +** surfaceInfo Pointer to the surface iniformational structure.
- +*/
- +#define gcmVERIFY_NODE_LOCK(surfaceNode) \
- + if (!(surfaceNode)->valid) \
- + { \
- + status = gcvSTATUS_MEMORY_UNLOCKED; \
- + break; \
- + } \
- + do { } while (gcvFALSE)
- +
- +/*******************************************************************************
- +**
- +** gcmBADOBJECT_BREAK
- +**
- +** Executes a break statement on bad object.
- +**
- +** ARGUMENTS:
- +**
- +** obj Object to test.
- +** t Expected type of the object.
- +*/
- +#define gcmBADOBJECT_BREAK(obj, t) \
- + if ((obj == gcvNULL) \
- + || (((gcsOBJECT *)(obj))->type != t) \
- + ) \
- + { \
- + status = gcvSTATUS_INVALID_OBJECT; \
- + break; \
- + } \
- + do { } while (gcvFALSE)
- +
- +/*******************************************************************************
- +**
- +** gcmCHECK_STATUS
- +**
- +** Executes a break statement on error.
- +**
- +** ASSUMPTIONS:
- +**
- +** 'status' variable of gceSTATUS type must be defined.
- +**
- +** ARGUMENTS:
- +**
- +** func Function to evaluate.
- +*/
- +#define _gcmCHECK_STATUS(prefix, func) \
- + do \
- + { \
- + last = func; \
- + if (gcmIS_ERROR(last)) \
- + { \
- + prefix##TRACE(gcvLEVEL_ERROR, \
- + #prefix "CHECK_STATUS: status=%d(%s) @ %s(%d)", \
- + last, gcoOS_DebugStatus2Name(last), __FUNCTION__, __LINE__); \
- + status = last; \
- + } \
- + } \
- + while (gcvFALSE)
- +#define _gcmkCHECK_STATUS(prefix, func) \
- + do \
- + { \
- + last = func; \
- + if (gcmIS_ERROR(last)) \
- + { \
- + prefix##TRACE(gcvLEVEL_ERROR, \
- + #prefix "CHECK_STATUS: status=%d(%s) @ %s(%d)", \
- + last, gckOS_DebugStatus2Name(last), __FUNCTION__, __LINE__); \
- + status = last; \
- + } \
- + } \
- + while (gcvFALSE)
- +#define gcmCHECK_STATUS(func) _gcmCHECK_STATUS(gcm, func)
- +#define gcmkCHECK_STATUS(func) _gcmkCHECK_STATUS(gcmk, func)
- +
- +/*******************************************************************************
- +**
- +** gcmVERIFY_ARGUMENT
- +**
- +** Assert if an argument does not apply to the specified expression. If
- +** the argument evaluates to false, gcvSTATUS_INVALID_ARGUMENT will be
- +** returned from the current function. In retail mode this macro does
- +** nothing.
- +**
- +** ARGUMENTS:
- +**
- +** arg Argument to evaluate.
- +*/
- +# define _gcmVERIFY_ARGUMENT(prefix, arg) \
- + do \
- + { \
- + if (!(arg)) \
- + { \
- + prefix##TRACE(gcvLEVEL_ERROR, #prefix "VERIFY_ARGUMENT failed:"); \
- + prefix##ASSERT(arg); \
- + prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT); \
- + return gcvSTATUS_INVALID_ARGUMENT; \
- + } \
- + } \
- + while (gcvFALSE)
- +# define gcmVERIFY_ARGUMENT(arg) _gcmVERIFY_ARGUMENT(gcm, arg)
- +# define gcmkVERIFY_ARGUMENT(arg) _gcmVERIFY_ARGUMENT(gcmk, arg)
- +
- +/*******************************************************************************
- +**
- +** gcmDEBUG_VERIFY_ARGUMENT
- +**
- +** Works just like gcmVERIFY_ARGUMENT, but is only valid in debug mode.
- +** Use this to verify arguments inside non-public API functions.
- +*/
- +#if gcdDEBUG
- +# define gcmDEBUG_VERIFY_ARGUMENT(arg) _gcmVERIFY_ARGUMENT(gcm, arg)
- +# define gcmkDEBUG_VERIFY_ARGUMENT(arg) _gcmkVERIFY_ARGUMENT(gcm, arg)
- +#else
- +# define gcmDEBUG_VERIFY_ARGUMENT(arg)
- +# define gcmkDEBUG_VERIFY_ARGUMENT(arg)
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gcmVERIFY_ARGUMENT_RETURN
- +**
- +** Assert if an argument does not apply to the specified expression. If
- +** the argument evaluates to false, gcvSTATUS_INVALID_ARGUMENT will be
- +** returned from the current function. In retail mode this macro does
- +** nothing.
- +**
- +** ARGUMENTS:
- +**
- +** arg Argument to evaluate.
- +*/
- +# define _gcmVERIFY_ARGUMENT_RETURN(prefix, arg, value) \
- + do \
- + { \
- + if (!(arg)) \
- + { \
- + prefix##TRACE(gcvLEVEL_ERROR, \
- + #prefix "gcmVERIFY_ARGUMENT_RETURN failed:"); \
- + prefix##ASSERT(arg); \
- + prefix##FOOTER_ARG("value=%d", value); \
- + return value; \
- + } \
- + } \
- + while (gcvFALSE)
- +# define gcmVERIFY_ARGUMENT_RETURN(arg, value) \
- + _gcmVERIFY_ARGUMENT_RETURN(gcm, arg, value)
- +# define gcmkVERIFY_ARGUMENT_RETURN(arg, value) \
- + _gcmVERIFY_ARGUMENT_RETURN(gcmk, arg, value)
- +
- +#define MAX_LOOP_COUNT 0x7FFFFFFF
- +
- +/******************************************************************************\
- +****************************** User Debug Option ******************************
- +\******************************************************************************/
- +
- +/* User option. */
- +typedef enum _gceDEBUG_MSG
- +{
- + gcvDEBUG_MSG_NONE,
- + gcvDEBUG_MSG_ERROR,
- + gcvDEBUG_MSG_WARNING
- +}
- +gceDEBUG_MSG;
- +
- +typedef struct _gcsUSER_DEBUG_OPTION
- +{
- + gceDEBUG_MSG debugMsg;
- +}
- +gcsUSER_DEBUG_OPTION;
- +
- +gcsUSER_DEBUG_OPTION *
- +gcGetUserDebugOption(
- + void
- + );
- +
- +struct _gcoOS_SymbolsList
- +{
- + gcePATCH_ID patchId;
- + const char * symList[10];
- +};
- +
- +#if gcdHAS_ELLIPSES
- +#define gcmUSER_DEBUG_MSG(level, ...) \
- + do \
- + { \
- + if (level <= gcGetUserDebugOption()->debugMsg) \
- + { \
- + gcoOS_Print(__VA_ARGS__); \
- + } \
- + } while (gcvFALSE)
- +
- +#define gcmUSER_DEBUG_ERROR_MSG(...) gcmUSER_DEBUG_MSG(gcvDEBUG_MSG_ERROR, "Error: " __VA_ARGS__)
- +#define gcmUSER_DEBUG_WARNING_MSG(...) gcmUSER_DEBUG_MSG(gcvDEBUG_MSG_WARNING, "Warring: " __VA_ARGS__)
- +#else
- +#define gcmUSER_DEBUG_MSG
- +#define gcmUSER_DEBUG_ERROR_MSG
- +#define gcmUSER_DEBUG_WARNING_MSG
- +#endif
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* __gc_hal_base_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h 2015-03-08 14:27:37.641684501 -0500
- @@ -0,0 +1,4298 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +/*
- +** Include file the defines the front- and back-end compilers, as well as the
- +** objects they use.
- +*/
- +
- +#ifndef __gc_hal_compiler_h_
- +#define __gc_hal_compiler_h_
- +
- +#ifndef VIVANTE_NO_3D
- +#include "gc_hal_types.h"
- +#include "gc_hal_engine.h"
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +#ifndef GC_ENABLE_LOADTIME_OPT
- +#define GC_ENABLE_LOADTIME_OPT 1
- +#endif
- +
- +#define TEMP_OPT_CONSTANT_TEXLD_COORD 0
- +
- +#define TEMP_SHADER_PATCH 1
- +
- +#define TEMP_INLINE_ALL_EXPANSION 1
- +/******************************* IR VERSION ******************/
- +#define gcdSL_IR_VERSION gcmCC('\0','\0','\0','\1')
- +
- +/******************************************************************************\
- +|******************************* SHADER LANGUAGE ******************************|
- +\******************************************************************************/
- +
- + /* allocator/deallocator function pointer */
- +typedef gceSTATUS (*gctAllocatorFunc)(
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER * Memory
- + );
- +
- +typedef gceSTATUS (*gctDeallocatorFunc)(
- + IN gctPOINTER Memory
- + );
- +
- +typedef gctBOOL (*compareFunc) (
- + IN void * data,
- + IN void * key
- + );
- +
- +typedef struct _gcsListNode gcsListNode;
- +struct _gcsListNode
- +{
- + gcsListNode * next;
- + void * data;
- +};
- +
- +typedef struct _gcsAllocator
- +{
- + gctAllocatorFunc allocate;
- + gctDeallocatorFunc deallocate;
- +} gcsAllocator;
- +
- +/* simple map structure */
- +typedef struct _SimpleMap SimpleMap;
- +struct _SimpleMap
- +{
- + gctUINT32 key;
- + gctUINT32 val;
- + SimpleMap *next;
- + gcsAllocator *allocator;
- +
- +};
- +
- +/* SimpleMap Operations */
- +/* return -1 if not found, otherwise return the mapped value */
- +gctUINT32
- +gcSimpleMap_Find(
- + IN SimpleMap *Map,
- + IN gctUINT32 Key
- + );
- +
- +gceSTATUS
- +gcSimpleMap_Destory(
- + IN SimpleMap * Map,
- + IN gcsAllocator * Allocator
- + );
- +
- +/* Add a pair <Key, Val> to the Map head, the user should be aware that the
- + * map pointer is always changed when adding a new node :
- + *
- + * gcSimpleMap_AddNode(&theMap, key, val, allocator);
- + *
- + */
- +gceSTATUS
- +gcSimpleMap_AddNode(
- + IN SimpleMap ** Map,
- + IN gctUINT32 Key,
- + IN gctUINT32 Val,
- + IN gcsAllocator * Allocator
- + );
- +
- +/* gcsList data structure and related operations */
- +typedef struct _gcsList
- +{
- + gcsListNode *head;
- + gcsListNode *tail;
- + gctINT count;
- + gcsAllocator *allocator;
- +} gcsList;
- +
- +/* List operations */
- +void
- +gcList_Init(
- + IN gcsList *list,
- + IN gcsAllocator *allocator
- + );
- +
- +gceSTATUS
- +gcList_CreateNode(
- + IN void * Data,
- + IN gctAllocatorFunc Allocator,
- + OUT gcsListNode ** ListNode
- + );
- +
- +gceSTATUS
- +gcList_Clean(
- + IN gcsList * List,
- + IN gctBOOL FreeData
- + );
- +
- +gcsListNode *
- +gcList_FindNode(
- + IN gcsList * List,
- + IN void * Key,
- + IN compareFunc compare
- + );
- +
- +gceSTATUS
- +gcList_AddNode(
- + IN gcsList * List,
- + IN void * Data
- + );
- +
- +gceSTATUS
- +gcList_RemoveNode(
- + IN gcsList * List,
- + IN gcsListNode * Node
- + );
- +
- +/* link list structure for code list */
- +typedef gcsList gcsCodeList;
- +typedef gcsCodeList * gctCodeList;
- +typedef gcsListNode gcsCodeListNode;
- +
- +/* Possible shader language opcodes. */
- +typedef enum _gcSL_OPCODE
- +{
- + gcSL_NOP, /* 0x00 */
- + gcSL_MOV, /* 0x01 */
- + gcSL_SAT, /* 0x02 */
- + gcSL_DP3, /* 0x03 */
- + gcSL_DP4, /* 0x04 */
- + gcSL_ABS, /* 0x05 */
- + gcSL_JMP, /* 0x06 */
- + gcSL_ADD, /* 0x07 */
- + gcSL_MUL, /* 0x08 */
- + gcSL_RCP, /* 0x09 */
- + gcSL_SUB, /* 0x0A */
- + gcSL_KILL, /* 0x0B */
- + gcSL_TEXLD, /* 0x0C */
- + gcSL_CALL, /* 0x0D */
- + gcSL_RET, /* 0x0E */
- + gcSL_NORM, /* 0x0F */
- + gcSL_MAX, /* 0x10 */
- + gcSL_MIN, /* 0x11 */
- + gcSL_POW, /* 0x12 */
- + gcSL_RSQ, /* 0x13 */
- + gcSL_LOG, /* 0x14 */
- + gcSL_FRAC, /* 0x15 */
- + gcSL_FLOOR, /* 0x16 */
- + gcSL_CEIL, /* 0x17 */
- + gcSL_CROSS, /* 0x18 */
- + gcSL_TEXLDP, /* 0x19 */
- + gcSL_TEXBIAS, /* 0x1A */
- + gcSL_TEXGRAD, /* 0x1B */
- + gcSL_TEXLOD, /* 0x1C */
- + gcSL_SIN, /* 0x1D */
- + gcSL_COS, /* 0x1E */
- + gcSL_TAN, /* 0x1F */
- + gcSL_EXP, /* 0x20 */
- + gcSL_SIGN, /* 0x21 */
- + gcSL_STEP, /* 0x22 */
- + gcSL_SQRT, /* 0x23 */
- + gcSL_ACOS, /* 0x24 */
- + gcSL_ASIN, /* 0x25 */
- + gcSL_ATAN, /* 0x26 */
- + gcSL_SET, /* 0x27 */
- + gcSL_DSX, /* 0x28 */
- + gcSL_DSY, /* 0x29 */
- + gcSL_FWIDTH, /* 0x2A */
- + gcSL_DIV, /* 0x2B */
- + gcSL_MOD, /* 0x2C */
- + gcSL_AND_BITWISE, /* 0x2D */
- + gcSL_OR_BITWISE, /* 0x2E */
- + gcSL_XOR_BITWISE, /* 0x2F */
- + gcSL_NOT_BITWISE, /* 0x30 */
- + gcSL_LSHIFT, /* 0x31 */
- + gcSL_RSHIFT, /* 0x32 */
- + gcSL_ROTATE, /* 0x33 */
- + gcSL_BITSEL, /* 0x34 */
- + gcSL_LEADZERO, /* 0x35 */
- + gcSL_LOAD, /* 0x36 */
- + gcSL_STORE, /* 0x37 */
- + gcSL_BARRIER, /* 0x38 */
- + gcSL_STORE1, /* 0x39 */
- + gcSL_ATOMADD, /* 0x3A */
- + gcSL_ATOMSUB, /* 0x3B */
- + gcSL_ATOMXCHG, /* 0x3C */
- + gcSL_ATOMCMPXCHG, /* 0x3D */
- + gcSL_ATOMMIN, /* 0x3E */
- + gcSL_ATOMMAX, /* 0x3F */
- + gcSL_ATOMOR, /* 0x40 */
- + gcSL_ATOMAND, /* 0x41 */
- + gcSL_ATOMXOR, /* 0x42 */
- + /*gcSL_UNUSED, 0x43 */
- + /*gcSL_UNUSED, 0x44 */
- + /*gcSL_UNUSED, 0x45 */
- + /*gcSL_UNUSED, 0x46 */
- + /*gcSL_UNUSED, 0x47 */
- + /*gcSL_UNUSED, 0x48 */
- + /*gcSL_UNUSED, 0x49 */
- + /*gcSL_UNUSED, 0x4A */
- + /*gcSL_UNUSED, 0x4B */
- + /*gcSL_UNUSED, 0x4C */
- + /*gcSL_UNUSED, 0x4D */
- + /*gcSL_UNUSED, 0x4E */
- + /*gcSL_UNUSED, 0x4F */
- + /*gcSL_UNUSED, 0x50 */
- + /*gcSL_UNUSED, 0x51 */
- + /*gcSL_UNUSED, 0x52 */
- + gcSL_ADDLO = 0x53, /* 0x53 */ /* Float only. */
- + gcSL_MULLO, /* 0x54 */ /* Float only. */
- + gcSL_CONV, /* 0x55 */
- + gcSL_GETEXP, /* 0x56 */
- + gcSL_GETMANT, /* 0x57 */
- + gcSL_MULHI, /* 0x58 */ /* Integer only. */
- + gcSL_CMP, /* 0x59 */
- + gcSL_I2F, /* 0x5A */
- + gcSL_F2I, /* 0x5B */
- + gcSL_ADDSAT, /* 0x5C */ /* Integer only. */
- + gcSL_SUBSAT, /* 0x5D */ /* Integer only. */
- + gcSL_MULSAT, /* 0x5E */ /* Integer only. */
- + gcSL_DP2, /* 0x5F */
- + gcSL_MAXOPCODE
- +}
- +gcSL_OPCODE;
- +
- +typedef enum _gcSL_FORMAT
- +{
- + gcSL_FLOAT = 0, /* 0 */
- + gcSL_INTEGER = 1, /* 1 */
- + gcSL_INT32 = 1, /* 1 */
- + gcSL_BOOLEAN = 2, /* 2 */
- + gcSL_UINT32 = 3, /* 3 */
- + gcSL_INT8, /* 4 */
- + gcSL_UINT8, /* 5 */
- + gcSL_INT16, /* 6 */
- + gcSL_UINT16, /* 7 */
- + gcSL_INT64, /* 8 */ /* Reserved for future enhancement. */
- + gcSL_UINT64, /* 9 */ /* Reserved for future enhancement. */
- + gcSL_INT128, /* 10 */ /* Reserved for future enhancement. */
- + gcSL_UINT128, /* 11 */ /* Reserved for future enhancement. */
- + gcSL_FLOAT16, /* 12 */
- + gcSL_FLOAT64, /* 13 */ /* Reserved for future enhancement. */
- + gcSL_FLOAT128, /* 14 */ /* Reserved for future enhancement. */
- +}
- +gcSL_FORMAT;
- +
- +/* Destination write enable bits. */
- +typedef enum _gcSL_ENABLE
- +{
- + gcSL_ENABLE_NONE = 0x0, /* none is enabled, error/uninitialized state */
- + gcSL_ENABLE_X = 0x1,
- + gcSL_ENABLE_Y = 0x2,
- + gcSL_ENABLE_Z = 0x4,
- + gcSL_ENABLE_W = 0x8,
- + /* Combinations. */
- + gcSL_ENABLE_XY = gcSL_ENABLE_X | gcSL_ENABLE_Y,
- + gcSL_ENABLE_XYZ = gcSL_ENABLE_X | gcSL_ENABLE_Y | gcSL_ENABLE_Z,
- + gcSL_ENABLE_XYZW = gcSL_ENABLE_X | gcSL_ENABLE_Y | gcSL_ENABLE_Z | gcSL_ENABLE_W,
- + gcSL_ENABLE_XYW = gcSL_ENABLE_X | gcSL_ENABLE_Y | gcSL_ENABLE_W,
- + gcSL_ENABLE_XZ = gcSL_ENABLE_X | gcSL_ENABLE_Z,
- + gcSL_ENABLE_XZW = gcSL_ENABLE_X | gcSL_ENABLE_Z | gcSL_ENABLE_W,
- + gcSL_ENABLE_XW = gcSL_ENABLE_X | gcSL_ENABLE_W,
- + gcSL_ENABLE_YZ = gcSL_ENABLE_Y | gcSL_ENABLE_Z,
- + gcSL_ENABLE_YZW = gcSL_ENABLE_Y | gcSL_ENABLE_Z | gcSL_ENABLE_W,
- + gcSL_ENABLE_YW = gcSL_ENABLE_Y | gcSL_ENABLE_W,
- + gcSL_ENABLE_ZW = gcSL_ENABLE_Z | gcSL_ENABLE_W,
- +}
- +gcSL_ENABLE;
- +
- +/* Possible indices. */
- +typedef enum _gcSL_INDEXED
- +{
- + gcSL_NOT_INDEXED, /* 0 */
- + gcSL_INDEXED_X, /* 1 */
- + gcSL_INDEXED_Y, /* 2 */
- + gcSL_INDEXED_Z, /* 3 */
- + gcSL_INDEXED_W, /* 4 */
- +}
- +gcSL_INDEXED;
- +
- +/* Opcode conditions. */
- +typedef enum _gcSL_CONDITION
- +{
- + gcSL_ALWAYS, /* 0x0 */
- + gcSL_NOT_EQUAL, /* 0x1 */
- + gcSL_LESS_OR_EQUAL, /* 0x2 */
- + gcSL_LESS, /* 0x3 */
- + gcSL_EQUAL, /* 0x4 */
- + gcSL_GREATER, /* 0x5 */
- + gcSL_GREATER_OR_EQUAL, /* 0x6 */
- + gcSL_AND, /* 0x7 */
- + gcSL_OR, /* 0x8 */
- + gcSL_XOR, /* 0x9 */
- + gcSL_NOT_ZERO, /* 0xA */
- +}
- +gcSL_CONDITION;
- +
- +/* Possible source operand types. */
- +typedef enum _gcSL_TYPE
- +{
- + gcSL_NONE, /* 0x0 */
- + gcSL_TEMP, /* 0x1 */
- + gcSL_ATTRIBUTE, /* 0x2 */
- + gcSL_UNIFORM, /* 0x3 */
- + gcSL_SAMPLER, /* 0x4 */
- + gcSL_CONSTANT, /* 0x5 */
- + gcSL_OUTPUT, /* 0x6 */
- + gcSL_PHYSICAL, /* 0x7 */
- +}
- +gcSL_TYPE;
- +
- +/* Swizzle generator macro. */
- +#define gcmSWIZZLE(Component1, Component2, Component3, Component4) \
- +( \
- + (gcSL_SWIZZLE_ ## Component1 << 0) | \
- + (gcSL_SWIZZLE_ ## Component2 << 2) | \
- + (gcSL_SWIZZLE_ ## Component3 << 4) | \
- + (gcSL_SWIZZLE_ ## Component4 << 6) \
- +)
- +
- +#define gcmExtractSwizzle(Swizzle, Index) \
- + ((gcSL_SWIZZLE) ((((Swizzle) >> (Index * 2)) & 0x3)))
- +
- +#define gcmComposeSwizzle(SwizzleX, SwizzleY, SwizzleZ, SwizzleW) \
- +( \
- + ((SwizzleX) << 0) | \
- + ((SwizzleY) << 2) | \
- + ((SwizzleZ) << 4) | \
- + ((SwizzleW) << 6) \
- +)
- +
- +/* Possible swizzle values. */
- +typedef enum _gcSL_SWIZZLE
- +{
- + gcSL_SWIZZLE_X, /* 0x0 */
- + gcSL_SWIZZLE_Y, /* 0x1 */
- + gcSL_SWIZZLE_Z, /* 0x2 */
- + gcSL_SWIZZLE_W, /* 0x3 */
- + /* Combinations. */
- + gcSL_SWIZZLE_XXXX = gcmSWIZZLE(X, X, X, X),
- + gcSL_SWIZZLE_YYYY = gcmSWIZZLE(Y, Y, Y, Y),
- + gcSL_SWIZZLE_ZZZZ = gcmSWIZZLE(Z, Z, Z, Z),
- + gcSL_SWIZZLE_WWWW = gcmSWIZZLE(W, W, W, W),
- + gcSL_SWIZZLE_XYYY = gcmSWIZZLE(X, Y, Y, Y),
- + gcSL_SWIZZLE_XZZZ = gcmSWIZZLE(X, Z, Z, Z),
- + gcSL_SWIZZLE_XWWW = gcmSWIZZLE(X, W, W, W),
- + gcSL_SWIZZLE_YZZZ = gcmSWIZZLE(Y, Z, Z, Z),
- + gcSL_SWIZZLE_YWWW = gcmSWIZZLE(Y, W, W, W),
- + gcSL_SWIZZLE_ZWWW = gcmSWIZZLE(Z, W, W, W),
- + gcSL_SWIZZLE_XYZZ = gcmSWIZZLE(X, Y, Z, Z),
- + gcSL_SWIZZLE_XYWW = gcmSWIZZLE(X, Y, W, W),
- + gcSL_SWIZZLE_XZWW = gcmSWIZZLE(X, Z, W, W),
- + gcSL_SWIZZLE_YZWW = gcmSWIZZLE(Y, Z, W, W),
- + gcSL_SWIZZLE_XXYZ = gcmSWIZZLE(X, X, Y, Z),
- + gcSL_SWIZZLE_XYZW = gcmSWIZZLE(X, Y, Z, W),
- + gcSL_SWIZZLE_XYXY = gcmSWIZZLE(X, Y, X, Y),
- + gcSL_SWIZZLE_YYZZ = gcmSWIZZLE(Y, Y, Z, Z),
- + gcSL_SWIZZLE_YYWW = gcmSWIZZLE(Y, Y, W, W),
- + gcSL_SWIZZLE_ZZZW = gcmSWIZZLE(Z, Z, Z, W),
- + gcSL_SWIZZLE_XZZW = gcmSWIZZLE(X, Z, Z, W),
- + gcSL_SWIZZLE_YYZW = gcmSWIZZLE(Y, Y, Z, W),
- +
- + gcSL_SWIZZLE_INVALID = 0x7FFFFFFF
- +}
- +gcSL_SWIZZLE;
- +
- +typedef enum _gcSL_COMPONENT
- +{
- + gcSL_COMPONENT_X, /* 0x0 */
- + gcSL_COMPONENT_Y, /* 0x1 */
- + gcSL_COMPONENT_Z, /* 0x2 */
- + gcSL_COMPONENT_W, /* 0x3 */
- + gcSL_COMPONENT_COUNT /* 0x4 */
- +} gcSL_COMPONENT;
- +
- +#define gcmIsComponentEnabled(Enable, Component) (((Enable) & (1 << (Component))) != 0)
- +
- +/******************************************************************************\
- +|*********************************** SHADERS **********************************|
- +\******************************************************************************/
- +
- +/* Shader types. */
- +typedef enum _gcSHADER_KIND {
- + gcSHADER_TYPE_UNKNOWN = 0,
- + gcSHADER_TYPE_VERTEX,
- + gcSHADER_TYPE_FRAGMENT,
- + gcSHADER_TYPE_CL,
- + gcSHADER_TYPE_PRECOMPILED,
- + gcSHADER_KIND_COUNT
- +} gcSHADER_KIND;
- +
- +typedef enum _gcGL_DRIVER_VERSION {
- + gcGL_DRIVER_ES11, /* OpenGL ES 1.1 */
- + gcGL_DRIVER_ES20, /* OpenGL ES 2.0 */
- + gcGL_DRIVER_ES30 /* OpenGL ES 3.0 */
- +} gcGL_DRIVER_VERSION;
- +
- +/* gcSHADER objects. */
- +typedef struct _gcSHADER * gcSHADER;
- +typedef struct _gcATTRIBUTE * gcATTRIBUTE;
- +typedef struct _gcUNIFORM * gcUNIFORM;
- +typedef struct _gcOUTPUT * gcOUTPUT;
- +typedef struct _gcsFUNCTION * gcFUNCTION;
- +typedef struct _gcsKERNEL_FUNCTION * gcKERNEL_FUNCTION;
- +typedef struct _gcsHINT * gcsHINT_PTR;
- +typedef struct _gcSHADER_PROFILER * gcSHADER_PROFILER;
- +typedef struct _gcVARIABLE * gcVARIABLE;
- +
- +struct _gcsHINT
- +{
- + /* Numbr of data transfers for Vertex Shader output. */
- + gctUINT32 vsOutputCount;
- +
- + /* Flag whether the VS has point size or not. */
- + gctBOOL vsHasPointSize;
- +
- +#if gcdUSE_WCLIP_PATCH
- + /* Flag whether the VS gl_position.z depends on gl_position.w
- + it's a hint for wclipping */
- + gctBOOL vsPositionZDependsOnW;
- +#endif
- +
- + gctBOOL clipW;
- +
- + /* Flag whether or not the shader has a KILL instruction. */
- + gctBOOL hasKill;
- +
- + /* Element count. */
- + gctUINT32 elementCount;
- +
- + /* Component count. */
- + gctUINT32 componentCount;
- +
- + /* Number of data transfers for Fragment Shader input. */
- + gctUINT32 fsInputCount;
- +
- + /* Maximum number of temporary registers used in FS. */
- + gctUINT32 fsMaxTemp;
- +
- + /* Maximum number of temporary registers used in VS. */
- + gctUINT32 vsMaxTemp;
- +
- + /* Balance minimum. */
- + gctUINT32 balanceMin;
- +
- + /* Balance maximum. */
- + gctUINT32 balanceMax;
- +
- + /* Auto-shift balancing. */
- + gctBOOL autoShift;
- +
- + /* Flag whether the PS outputs the depth value or not. */
- + gctBOOL psHasFragDepthOut;
- +
- + /* Flag whether the ThreadWalker is in PS. */
- + gctBOOL threadWalkerInPS;
- +
- + /* HW reg number for position of VS */
- + gctUINT32 hwRegNoOfSIVPos;
- +
- +#if gcdALPHA_KILL_IN_SHADER
- + /* States to set when alpha kill is enabled. */
- + gctUINT32 killStateAddress;
- + gctUINT32 alphaKillStateValue;
- + gctUINT32 colorKillStateValue;
- +
- + /* Shader instructiuon. */
- + gctUINT32 killInstructionAddress;
- + gctUINT32 alphaKillInstruction[3];
- + gctUINT32 colorKillInstruction[3];
- +#endif
- +
- +#if TEMP_SHADER_PATCH
- + gctUINT32 pachedShaderIdentifier;
- +#endif
- +};
- +
- +#if TEMP_SHADER_PATCH
- +#define INVALID_SHADER_IDENTIFIER 0xFFFFFFFF
- +#endif
- +
- +/* gcSHADER_TYPE enumeration. */
- +typedef enum _gcSHADER_TYPE
- +{
- + gcSHADER_FLOAT_X1 = 0, /* 0x00 */
- + gcSHADER_FLOAT_X2, /* 0x01 */
- + gcSHADER_FLOAT_X3, /* 0x02 */
- + gcSHADER_FLOAT_X4, /* 0x03 */
- + gcSHADER_FLOAT_2X2, /* 0x04 */
- + gcSHADER_FLOAT_3X3, /* 0x05 */
- + gcSHADER_FLOAT_4X4, /* 0x06 */
- + gcSHADER_BOOLEAN_X1, /* 0x07 */
- + gcSHADER_BOOLEAN_X2, /* 0x08 */
- + gcSHADER_BOOLEAN_X3, /* 0x09 */
- + gcSHADER_BOOLEAN_X4, /* 0x0A */
- + gcSHADER_INTEGER_X1, /* 0x0B */
- + gcSHADER_INTEGER_X2, /* 0x0C */
- + gcSHADER_INTEGER_X3, /* 0x0D */
- + gcSHADER_INTEGER_X4, /* 0x0E */
- + gcSHADER_SAMPLER_1D, /* 0x0F */
- + gcSHADER_SAMPLER_2D, /* 0x10 */
- + gcSHADER_SAMPLER_3D, /* 0x11 */
- + gcSHADER_SAMPLER_CUBIC, /* 0x12 */
- + gcSHADER_FIXED_X1, /* 0x13 */
- + gcSHADER_FIXED_X2, /* 0x14 */
- + gcSHADER_FIXED_X3, /* 0x15 */
- + gcSHADER_FIXED_X4, /* 0x16 */
- + gcSHADER_IMAGE_2D, /* 0x17 */ /* For OCL. */
- + gcSHADER_IMAGE_3D, /* 0x18 */ /* For OCL. */
- + gcSHADER_SAMPLER, /* 0x19 */ /* For OCL. */
- + gcSHADER_FLOAT_2X3, /* 0x1A */
- + gcSHADER_FLOAT_2X4, /* 0x1B */
- + gcSHADER_FLOAT_3X2, /* 0x1C */
- + gcSHADER_FLOAT_3X4, /* 0x1D */
- + gcSHADER_FLOAT_4X2, /* 0x1E */
- + gcSHADER_FLOAT_4X3, /* 0x1F */
- + gcSHADER_ISAMPLER_2D, /* 0x20 */
- + gcSHADER_ISAMPLER_3D, /* 0x21 */
- + gcSHADER_ISAMPLER_CUBIC, /* 0x22 */
- + gcSHADER_USAMPLER_2D, /* 0x23 */
- + gcSHADER_USAMPLER_3D, /* 0x24 */
- + gcSHADER_USAMPLER_CUBIC, /* 0x25 */
- + gcSHADER_SAMPLER_EXTERNAL_OES, /* 0x26 */
- +
- + gcSHADER_UINT_X1, /* 0x27 */
- + gcSHADER_UINT_X2, /* 0x28 */
- + gcSHADER_UINT_X3, /* 0x29 */
- + gcSHADER_UINT_X4, /* 0x2A */
- +
- + gcSHADER_UNKONWN_TYPE, /* do not add type after this */
- + gcSHADER_TYPE_COUNT /* must to change gcvShaderTypeInfo at the
- + * same time if you add any new type! */}
- +gcSHADER_TYPE;
- +
- +typedef enum _gcSHADER_TYPE_KIND
- +{
- + gceTK_UNKOWN,
- + gceTK_FLOAT,
- + gceTK_INT,
- + gceTK_UINT,
- + gceTK_BOOL,
- + gceTK_FIXED,
- + gceTK_SAMPLER,
- + gceTK_IMAGE,
- + gceTK_OTHER
- +} gcSHADER_TYPE_KIND;
- +
- +typedef struct _gcSHADER_TYPEINFO
- +{
- + gcSHADER_TYPE type; /* e.g. gcSHADER_FLOAT_2X4 */
- + gctINT components; /* e.g. 4 components */
- + gctINT rows; /* e.g. 2 rows */
- + gcSHADER_TYPE componentType; /* e.g. gcSHADER_FLOAT_X4 */
- + gcSHADER_TYPE_KIND kind; /* e.g. gceTK_FLOAT */
- + gctCONST_STRING name; /* e.g. "FLOAT_2X4" */
- +} gcSHADER_TYPEINFO;
- +
- +extern gcSHADER_TYPEINFO gcvShaderTypeInfo[];
- +
- +#define gcmType_Comonents(Type) (gcvShaderTypeInfo[Type].components)
- +#define gcmType_Rows(Type) (gcvShaderTypeInfo[Type].rows)
- +#define gcmType_ComonentType(Type) (gcvShaderTypeInfo[Type].componentType)
- +#define gcmType_Kind(Type) (gcvShaderTypeInfo[Type].kind)
- +#define gcmType_Name(Type) (gcvShaderTypeInfo[Type].name)
- +
- +#define gcmType_isMatrix(type) (gcmType_Rows(type) > 1)
- +
- +typedef enum _gcSHADER_VAR_CATEGORY
- +{
- + gcSHADER_VAR_CATEGORY_NORMAL = 0, /* primitive type and its array */
- + gcSHADER_VAR_CATEGORY_STRUCT = 1 /* structure */
- +}
- +gcSHADER_VAR_CATEGORY;
- +
- +typedef enum _gceTYPE_QUALIFIER
- +{
- + gcvTYPE_QUALIFIER_NONE = 0x0, /* unqualified */
- + gcvTYPE_QUALIFIER_VOLATILE = 0x1, /* volatile */
- +}gceTYPE_QUALIFIER;
- +
- +typedef gctUINT16 gctTYPE_QUALIFIER;
- +
- +#if GC_ENABLE_LOADTIME_OPT
- +typedef struct _gcSHADER_TYPE_INFO
- +{
- + gcSHADER_TYPE type; /* eg. gcSHADER_FLOAT_2X3 is the type */
- + gctCONST_STRING name; /* the name of the type: "gcSHADER_FLOAT_2X3" */
- + gcSHADER_TYPE baseType; /* its base type is gcSHADER_FLOAT_2 */
- + gctINT components; /* it has 2 components */
- + gctINT rows; /* and 3 rows */
- + gctINT size; /* the size in byte */
- +} gcSHADER_TYPE_INFO;
- +
- +extern gcSHADER_TYPE_INFO shader_type_info[];
- +
- +enum gceLTCDumpOption {
- + gceLTC_DUMP_UNIFORM = 0x0001,
- + gceLTC_DUMP_EVALUATION = 0x0002,
- + gceLTC_DUMP_EXPESSION = 0x0004,
- + gceLTC_DUMP_COLLECTING = 0x0008,
- +};
- +
- +gctBOOL gcDumpOption(gctINT Opt);
- +
- +#endif /* GC_ENABLE_LOADTIME_OPT */
- +
- +#define IS_MATRIX_TYPE(type) \
- + (((type >= gcSHADER_FLOAT_2X2) && (type <= gcSHADER_FLOAT_4X4)) || \
- + ((type >= gcSHADER_FLOAT_2X3) && (type <= gcSHADER_FLOAT_4X3)))
- +
- +/* gcSHADER_PRECISION enumeration. */
- +typedef enum _gcSHADER_PRECISION
- +{
- + gcSHADER_PRECISION_DEFAULT, /* 0x00 */
- + gcSHADER_PRECISION_HIGH, /* 0x01 */
- + gcSHADER_PRECISION_MEDIUM, /* 0x02 */
- + gcSHADER_PRECISION_LOW, /* 0x03 */
- +}
- +gcSHADER_PRECISION;
- +
- +/* Shader flags. */
- +typedef enum _gceSHADER_FLAGS
- +{
- + gcvSHADER_NO_OPTIMIZATION = 0x00,
- + gcvSHADER_DEAD_CODE = 0x01,
- + gcvSHADER_RESOURCE_USAGE = 0x02,
- + gcvSHADER_OPTIMIZER = 0x04,
- + gcvSHADER_USE_GL_Z = 0x08,
- + /*
- + The GC family of GPU cores model GC860 and under require the Z
- + to be from 0 <= z <= w.
- + However, OpenGL specifies the Z to be from -w <= z <= w. So we
- + have to a conversion here:
- +
- + z = (z + w) / 2.
- +
- + So here we append two instructions to the vertex shader.
- + */
- + gcvSHADER_USE_GL_POSITION = 0x10,
- + gcvSHADER_USE_GL_FACE = 0x20,
- + gcvSHADER_USE_GL_POINT_COORD = 0x40,
- + gcvSHADER_LOADTIME_OPTIMIZER = 0x80,
- +#if gcdALPHA_KILL_IN_SHADER
- + gcvSHADER_USE_ALPHA_KILL = 0x100,
- +#endif
- +
- +#if gcdPRE_ROTATION && (ANDROID_SDK_VERSION >= 14)
- + gcvSHADER_VS_PRE_ROTATION = 0x200,
- +#endif
- +
- +#if TEMP_INLINE_ALL_EXPANSION
- + gcvSHADER_INLINE_ALL_EXPANSION = 0x400,
- +#endif
- +}
- +gceSHADER_FLAGS;
- +
- +gceSTATUS
- +gcSHADER_CheckClipW(
- + IN gctCONST_STRING VertexSource,
- + IN gctCONST_STRING FragmentSource,
- + OUT gctBOOL * clipW);
- +
- +/*******************************************************************************
- +** gcSHADER_GetUniformVectorCount
- +**
- +** Get the number of vectors used by uniforms for this shader.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Count
- +** Pointer to a variable receiving the number of vectors.
- +*/
- +gceSTATUS
- +gcSHADER_GetUniformVectorCount(
- + IN gcSHADER Shader,
- + OUT gctSIZE_T * Count
- + );
- +
- +/*******************************************************************************
- +** gcOptimizer Data Structures
- +*******************************************************************************/
- +typedef enum _gceSHADER_OPTIMIZATION
- +{
- + /* No optimization. */
- + gcvOPTIMIZATION_NONE,
- +
- + /* Flow graph construction. */
- + gcvOPTIMIZATION_CONSTRUCTION = 1 << 0,
- +
- + /* Dead code elimination. */
- + gcvOPTIMIZATION_DEAD_CODE = 1 << 1,
- +
- + /* Redundant move instruction elimination. */
- + gcvOPTIMIZATION_REDUNDANT_MOVE = 1 << 2,
- +
- + /* Inline expansion. */
- + gcvOPTIMIZATION_INLINE_EXPANSION = 1 << 3,
- +
- + /* Constant propagation. */
- + gcvOPTIMIZATION_CONSTANT_PROPAGATION = 1 << 4,
- +
- + /* Redundant bounds/checking elimination. */
- + gcvOPTIMIZATION_REDUNDANT_CHECKING = 1 << 5,
- +
- + /* Loop invariant movement. */
- + gcvOPTIMIZATION_LOOP_INVARIANT = 1 << 6,
- +
- + /* Induction variable removal. */
- + gcvOPTIMIZATION_INDUCTION_VARIABLE = 1 << 7,
- +
- + /* Common subexpression elimination. */
- + gcvOPTIMIZATION_COMMON_SUBEXPRESSION = 1 << 8,
- +
- + /* Control flow/banch optimization. */
- + gcvOPTIMIZATION_CONTROL_FLOW = 1 << 9,
- +
- + /* Vector component operation merge. */
- + gcvOPTIMIZATION_VECTOR_INSTRUCTION_MERGE = 1 << 10,
- +
- + /* Algebra simplificaton. */
- + gcvOPTIMIZATION_ALGEBRAIC_SIMPLIFICATION = 1 << 11,
- +
- + /* Pattern matching and replacing. */
- + gcvOPTIMIZATION_PATTERN_MATCHING = 1 << 12,
- +
- + /* Interprocedural constant propagation. */
- + gcvOPTIMIZATION_IP_CONSTANT_PROPAGATION = 1 << 13,
- +
- + /* Interprecedural register optimization. */
- + gcvOPTIMIZATION_IP_REGISTRATION = 1 << 14,
- +
- + /* Optimization option number. */
- + gcvOPTIMIZATION_OPTION_NUMBER = 1 << 15,
- +
- + /* Loadtime constant. */
- + gcvOPTIMIZATION_LOADTIME_CONSTANT = 1 << 16,
- +
- + /* MAD instruction optimization. */
- + gcvOPTIMIZATION_MAD_INSTRUCTION = 1 << 17,
- +
- + /* Special optimization for LOAD SW workaround. */
- + gcvOPTIMIZATION_LOAD_SW_WORKAROUND = 1 << 18,
- +
- + /* move code into conditional block if possile */
- + gcvOPTIMIZATION_CONDITIONALIZE = 1 << 19,
- +
- + /* expriemental: power optimization mode
- + 1. add extra dummy texld to tune performance
- + 2. insert NOP after high power instrucitons
- + 3. split high power vec3/vec4 instruciton to vec2/vec1 operation
- + 4. ...
- + */
- + gcvOPTIMIZATION_POWER_OPTIMIZATION = 1 << 20,
- +
- + /* optimize varying packing */
- + gcvOPTIMIZATION_VARYINGPACKING = 1 << 22,
- +
- +#if TEMP_INLINE_ALL_EXPANSION
- + gcvOPTIMIZATION_INLINE_ALL_EXPANSION = 1 << 23,
- +#endif
- +
- + /* Full optimization. */
- + /* Note that gcvOPTIMIZATION_LOAD_SW_WORKAROUND is off. */
- + gcvOPTIMIZATION_FULL = 0x7FFFFFFF &
- + ~gcvOPTIMIZATION_LOAD_SW_WORKAROUND &
- + ~gcvOPTIMIZATION_INLINE_ALL_EXPANSION &
- + ~gcvOPTIMIZATION_POWER_OPTIMIZATION,
- +
- + /* Optimization Unit Test flag. */
- + gcvOPTIMIZATION_UNIT_TEST = 1 << 31
- +}
- +gceSHADER_OPTIMIZATION;
- +
- +typedef enum _gceOPTIMIZATION_VaryingPaking
- +{
- + gcvOPTIMIZATION_VARYINGPACKING_NONE = 0,
- + gcvOPTIMIZATION_VARYINGPACKING_NOSPLIT,
- + gcvOPTIMIZATION_VARYINGPACKING_SPLIT
- +} gceOPTIMIZATION_VaryingPaking;
- +
- +typedef struct _gcOPTIMIZER_OPTION
- +{
- + gceSHADER_OPTIMIZATION optFlags;
- +
- + /* debug & dump options:
- +
- + VC_OPTION=-DUMP:SRC:OPT|:OPTV|:CG|:CGV:|ALL|ALLV
- +
- + SRC: dump shader source code
- + OPT: dump incoming and final IR
- + OPTV: dump result IR in each optimization phase
- + CG: dump generated machine code
- + CGV: dump BE tree and optimization detail
- +
- + ALL = SRC|OPT|CG
- + ALLV = SRC|OPT|OPTV|CG|CGV
- + */
- + gctBOOL dumpShaderSource; /* dump shader source code */
- + gctBOOL dumpOptimizer; /* dump incoming and final IR */
- + gctBOOL dumpOptimizerVerbose; /* dump result IR in each optimization phase */
- + gctBOOL dumpBEGenertedCode; /* dump generated machine code */
- + gctBOOL dumpBEVerbose; /* dump BE tree and optimization detail */
- + gctBOOL dumpBEFinalIR; /* dump BE final IR */
- +
- + /* Code generation */
- +
- + /* Varying Packing:
- +
- + VC_OPTION=-PACKVARYING:[0-2]|:T[-]m[,n]|:LshaderIdx,min,max
- +
- + 0: turn off varying packing
- + 1: pack varyings, donot split any varying
- + 2: pack varyings, may split to make fully packed output
- +
- + Tm: only packing shader pair which vertex shader id is m
- + Tm,n: only packing shader pair which vertex shader id
- + is in range of [m, n]
- + T-m: do not packing shader pair which vertex shader id is m
- + T-m,n: do not packing shader pair which vertex shader id
- + is in range of [m, n]
- +
- + LshaderIdx,min,max : set load balance (min, max) for shaderIdx
- + if shaderIdx is -1, all shaders are impacted
- + newMin = origMin * (min/100.);
- + newMax = origMax * (max/100.);
- + */
- + gceOPTIMIZATION_VaryingPaking packVarying;
- + gctINT _triageStart;
- + gctINT _triageEnd;
- + gctINT _loadBalanceShaderIdx;
- + gctINT _loadBalanceMin;
- + gctINT _loadBalanceMax;
- +
- + /* Do not generate immdeiate
- +
- + VC_OPTION=-NOIMM
- +
- + Force generate immediate even the machine model don't support it,
- + for testing purpose only
- +
- + VC_OPTION=-FORCEIMM
- + */
- + gctBOOL noImmediate;
- + gctBOOL forceImmediate;
- +
- + /* Power reduction mode options */
- + gctBOOL needPowerOptimization;
- +
- + /* Patch TEXLD instruction by adding dummy texld
- + (can be used to tune GPU power usage):
- + for every TEXLD we seen, add n dummy TEXLD
- +
- + it can be enabled by environment variable:
- +
- + VC_OPTION=-PATCH_TEXLD:M:N
- +
- + (for each M texld, add N dummy texld)
- + */
- + gctINT patchEveryTEXLDs;
- + gctINT patchDummyTEXLDs;
- +
- + /* Insert NOP after high power consumption instructions
- +
- + VC_OPTION="-INSERTNOP:MUL:MULLO:DP3:DP4:SEENTEXLD"
- + */
- + gctBOOL insertNOP;
- + gctBOOL insertNOPAfterMUL;
- + gctBOOL insertNOPAfterMULLO;
- + gctBOOL insertNOPAfterDP3;
- + gctBOOL insertNOPAfterDP4;
- + gctBOOL insertNOPOnlyWhenTexldSeen;
- +
- + /* split MAD to MUL and ADD:
- +
- + VC_OPTION=-SPLITMAD
- + */
- + gctBOOL splitMAD;
- +
- + /* Convert vect3/vec4 operations to multiple vec2/vec1 operations
- +
- + VC_OPTION=-SPLITVEC:MUL:MULLO:DP3:DP4
- + */
- + gctBOOL splitVec;
- + gctBOOL splitVec4MUL;
- + gctBOOL splitVec4MULLO;
- + gctBOOL splitVec4DP3;
- + gctBOOL splitVec4DP4;
- +
- + /* turn/off features:
- +
- + VC_OPTION=-F:n,[0|1]
- + Note: n must be decimal number
- + */
- + gctUINT featureBits;
- +
- + /* inline level (default 2 at O1):
- +
- + VC_OPTION=-INLINELEVEL:[0-3]
- + 0: no inline
- + 1: only inline the function only called once or small function
- + 2: inline functions be called less than 5 times or medium size function
- + 3: inline everything possible
- + */
- + gctUINT inlineLevel;
- +} gcOPTIMIZER_OPTION;
- +
- +extern gcOPTIMIZER_OPTION theOptimizerOption;
- +#define gcmGetOptimizerOption() gcGetOptimizerOption()
- +
- +#define gcmOPT_DUMP_SHADER_SRC() \
- + (gcmGetOptimizerOption()->dumpShaderSource != 0)
- +#define gcmOPT_DUMP_OPTIMIZER() \
- + (gcmGetOptimizerOption()->dumpOptimizer != 0 || \
- + gcmOPT_DUMP_OPTIMIZER_VERBOSE() )
- +#define gcmOPT_DUMP_OPTIMIZER_VERBOSE() \
- + (gcmGetOptimizerOption()->dumpOptimizerVerbose != 0)
- +#define gcmOPT_DUMP_CODEGEN() \
- + (gcmGetOptimizerOption()->dumpBEGenertedCode != 0 || \
- + gcmOPT_DUMP_CODEGEN_VERBOSE() )
- +#define gcmOPT_DUMP_CODEGEN_VERBOSE() \
- + (gcmGetOptimizerOption()->dumpBEVerbose != 0)
- +#define gcmOPT_DUMP_FINAL_IR() \
- + (gcmGetOptimizerOption()->dumpBEFinalIR != 0)
- +
- +#define gcmOPT_SET_DUMP_SHADER_SRC(v) \
- + gcmGetOptimizerOption()->dumpShaderSource = (v)
- +
- +#define gcmOPT_PATCH_TEXLD() (gcmGetOptimizerOption()->patchDummyTEXLDs != 0)
- +#define gcmOPT_INSERT_NOP() (gcmGetOptimizerOption()->insertNOP == gcvTRUE)
- +#define gcmOPT_SPLITMAD() (gcmGetOptimizerOption()->splitMAD == gcvTRUE)
- +#define gcmOPT_SPLITVEC() (gcmGetOptimizerOption()->splitVec == gcvTRUE)
- +
- +#define gcmOPT_NOIMMEDIATE() (gcmGetOptimizerOption()->noImmediate == gcvTRUE)
- +#define gcmOPT_FORCEIMMEDIATE() (gcmGetOptimizerOption()->forceImmediate == gcvTRUE)
- +
- +#define gcmOPT_PACKVARYING() (gcmGetOptimizerOption()->packVarying)
- +#define gcmOPT_PACKVARYING_triageStart() (gcmGetOptimizerOption()->_triageStart)
- +#define gcmOPT_PACKVARYING_triageEnd() (gcmGetOptimizerOption()->_triageEnd)
- +
- +#define gcmOPT_INLINELEVEL() (gcmGetOptimizerOption()->inlineLevel)
- +
- +/* Setters */
- +#define gcmOPT_SetPatchTexld(m,n) (gcmGetOptimizerOption()->patchEveryTEXLDs = (m),\
- + gcmGetOptimizerOption()->patchDummyTEXLDs = (n))
- +#define gcmOPT_SetSplitVecMUL() (gcmGetOptimizerOption()->splitVec = gcvTRUE, \
- + gcmGetOptimizerOption()->splitVec4MUL = gcvTRUE)
- +#define gcmOPT_SetSplitVecMULLO() (gcmGetOptimizerOption()->splitVec = gcvTRUE, \
- + gcmGetOptimizerOption()->splitVec4MULLO = gcvTRUE)
- +#define gcmOPT_SetSplitVecDP3() (gcmGetOptimizerOption()->splitVec = gcvTRUE, \
- + gcmGetOptimizerOption()->splitVec4DP3 = gcvTRUE)
- +#define gcmOPT_SetSplitVecDP4() (gcmGetOptimizerOption()->splitVec = gcvTRUE, \
- + gcmGetOptimizerOption()->splitVec4DP4 = gcvTRUE)
- +
- +#define gcmOPT_SetPackVarying(v) (gcmGetOptimizerOption()->packVarying = v)
- +
- +#define FB_LIVERANGE_FIX1 0x0001
- +
- +
- +#define PredefinedDummySamplerId 8
- +
- +/* Function argument qualifier */
- +typedef enum _gceINPUT_OUTPUT
- +{
- + gcvFUNCTION_INPUT,
- + gcvFUNCTION_OUTPUT,
- + gcvFUNCTION_INOUT
- +}
- +gceINPUT_OUTPUT;
- +
- +/* Kernel function property flags. */
- +typedef enum _gcePROPERTY_FLAGS
- +{
- + gcvPROPERTY_REQD_WORK_GRP_SIZE = 0x01
- +}
- +gceKERNEL_FUNCTION_PROPERTY_FLAGS;
- +
- +/* Uniform flags. */
- +typedef enum _gceUNIFORM_FLAGS
- +{
- + gcvUNIFORM_KERNEL_ARG = 0x01,
- + gcvUNIFORM_KERNEL_ARG_LOCAL = 0x02,
- + gcvUNIFORM_KERNEL_ARG_SAMPLER = 0x04,
- + gcvUNIFORM_LOCAL_ADDRESS_SPACE = 0x08,
- + gcvUNIFORM_PRIVATE_ADDRESS_SPACE = 0x10,
- + gcvUNIFORM_CONSTANT_ADDRESS_SPACE = 0x20,
- + gcvUNIFORM_GLOBAL_SIZE = 0x40,
- + gcvUNIFORM_LOCAL_SIZE = 0x80,
- + gcvUNIFORM_NUM_GROUPS = 0x100,
- + gcvUNIFORM_GLOBAL_OFFSET = 0x200,
- + gcvUNIFORM_WORK_DIM = 0x400,
- + gcvUNIFORM_KERNEL_ARG_CONSTANT = 0x800,
- + gcvUNIFORM_KERNEL_ARG_LOCAL_MEM_SIZE = 0x1000,
- + gcvUNIFORM_KERNEL_ARG_PRIVATE = 0x2000,
- + gcvUNIFORM_LOADTIME_CONSTANT = 0x4000,
- + gcvUNIFORM_IS_ARRAY = 0x8000,
- +}
- +gceUNIFORM_FLAGS;
- +
- +#define gcdUNIFORM_KERNEL_ARG_MASK (gcvUNIFORM_KERNEL_ARG | \
- + gcvUNIFORM_KERNEL_ARG_LOCAL | \
- + gcvUNIFORM_KERNEL_ARG_SAMPLER | \
- + gcvUNIFORM_KERNEL_ARG_PRIVATE | \
- + gcvUNIFORM_KERNEL_ARG_CONSTANT)
- +
- +typedef enum _gceVARIABLE_UPDATE_FLAGS
- +{
- + gcvVARIABLE_UPDATE_NOUPDATE = 0,
- + gcvVARIABLE_UPDATE_TEMPREG,
- + gcvVARIABLE_UPDATE_TYPE_QUALIFIER,
- +}gceVARIABLE_UPDATE_FLAGS;
- +
- +typedef struct _gcMACHINE_INST
- +{
- + gctUINT state0;
- + gctUINT state1;
- + gctUINT state2;
- + gctUINT state3;
- +}gcMACHINE_INST, *gcMACHINE_INST_PTR;
- +
- +typedef struct _gcMACHINECODE
- +{
- + gcMACHINE_INST_PTR pCode; /* machine code */
- + gctUINT instCount; /* 128-bit count */
- + gctUINT maxConstRegNo;
- + gctUINT maxTempRegNo;
- + gctUINT endPCOfMainRoutine;
- +}gcMACHINECODE, *gcMACHINECODE_PTR;
- +
- +typedef enum NP2_ADDRESS_MODE
- +{
- + NP2_ADDRESS_MODE_CLAMP = 0,
- + NP2_ADDRESS_MODE_REPEAT = 1,
- + NP2_ADDRESS_MODE_MIRROR = 2
- +}NP2_ADDRESS_MODE;
- +
- +typedef struct _gcNPOT_PATCH_PARAM
- +{
- + gctINT samplerSlot;
- + NP2_ADDRESS_MODE addressMode[3];
- + gctINT texDimension; /* 2 or 3 */
- +}gcNPOT_PATCH_PARAM, *gcNPOT_PATCH_PARAM_PTR;
- +
- +typedef struct _gcZBIAS_PATCH_PARAM
- +{
- + /* Driver uses this to program uniform that designating zbias */
- + gctINT uniformAddr;
- + gctINT channel;
- +}gcZBIAS_PATCH_PARAM, *gcZBIAS_PATCH_PARAM_PTR;
- +
- +void
- +gcGetOptionFromEnv(
- + IN OUT gcOPTIMIZER_OPTION * Option
- + );
- +
- +void
- +gcSetOptimizerOption(
- + IN gceSHADER_FLAGS Flags
- + );
- +
- +gcOPTIMIZER_OPTION *
- +gcGetOptimizerOption();
- +
- +/*******************************************************************************
- +** gcSHADER_SetCompilerVersion
- +**
- +** Set the compiler version of a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to gcSHADER object
- +**
- +** gctINT *Version
- +** Pointer to a two word version
- +*/
- +gceSTATUS
- +gcSHADER_SetCompilerVersion(
- + IN gcSHADER Shader,
- + IN gctUINT32 *Version
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_GetCompilerVersion
- +**
- +** Get the compiler version of a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** OUTPUT:
- +**
- +** gctUINT32_PTR *CompilerVersion.
- +** Pointer to holder of returned compilerVersion pointer
- +*/
- +gceSTATUS
- +gcSHADER_GetCompilerVersion(
- + IN gcSHADER Shader,
- + OUT gctUINT32_PTR *CompilerVersion
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_GetType
- +**
- +** Get the gcSHADER object's type.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** OUTPUT:
- +**
- +** gctINT *Type.
- +** Pointer to return shader type.
- +*/
- +gceSTATUS
- +gcSHADER_GetType(
- + IN gcSHADER Shader,
- + OUT gctINT *Type
- + );
- +
- +gctUINT
- +gcSHADER_NextId();
- +/*******************************************************************************
- +** gcSHADER_Construct
- +********************************************************************************
- +**
- +** Construct a new gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcoOS Hal
- +** Pointer to an gcoHAL object.
- +**
- +** gctINT ShaderType
- +** Type of gcSHADER object to cerate. 'ShaderType' can be one of the
- +** following:
- +**
- +** gcSHADER_TYPE_VERTEX Vertex shader.
- +** gcSHADER_TYPE_FRAGMENT Fragment shader.
- +**
- +** OUTPUT:
- +**
- +** gcSHADER * Shader
- +** Pointer to a variable receiving the gcSHADER object pointer.
- +*/
- +gceSTATUS
- +gcSHADER_Construct(
- + IN gcoHAL Hal,
- + IN gctINT ShaderType,
- + OUT gcSHADER * Shader
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_Destroy
- +********************************************************************************
- +**
- +** Destroy a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_Destroy(
- + IN gcSHADER Shader
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_Copy
- +********************************************************************************
- +**
- +** Copy a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gcSHADER Source
- +** Pointer to a gcSHADER object that will be copied.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_Copy(
- + IN gcSHADER Shader,
- + IN gcSHADER Source
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_LoadHeader
- +**
- +** Load a gcSHADER object from a binary buffer. The binary buffer is layed out
- +** as follows:
- +** // Six word header
- +** // Signature, must be 'S','H','D','R'.
- +** gctINT8 signature[4];
- +** gctUINT32 binFileVersion;
- +** gctUINT32 compilerVersion[2];
- +** gctUINT32 gcSLVersion;
- +** gctUINT32 binarySize;
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +** Shader type will be returned if type in shader object is not gcSHADER_TYPE_PRECOMPILED
- +**
- +** gctPOINTER Buffer
- +** Pointer to a binary buffer containing the shader data to load.
- +**
- +** gctSIZE_T BufferSize
- +** Number of bytes inside the binary buffer pointed to by 'Buffer'.
- +**
- +** OUTPUT:
- +** nothing
- +**
- +*/
- +gceSTATUS
- +gcSHADER_LoadHeader(
- + IN gcSHADER Shader,
- + IN gctPOINTER Buffer,
- + IN gctSIZE_T BufferSize,
- + OUT gctUINT32 * ShaderVersion
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_LoadKernel
- +**
- +** Load a kernel function given by name into gcSHADER object
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctSTRING KernelName
- +** Pointer to a kernel function name
- +**
- +** OUTPUT:
- +** nothing
- +**
- +*/
- +gceSTATUS
- +gcSHADER_LoadKernel(
- + IN gcSHADER Shader,
- + IN gctSTRING KernelName
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_Load
- +********************************************************************************
- +**
- +** Load a gcSHADER object from a binary buffer.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctPOINTER Buffer
- +** Pointer to a binary buffer containg the shader data to load.
- +**
- +** gctSIZE_T BufferSize
- +** Number of bytes inside the binary buffer pointed to by 'Buffer'.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_Load(
- + IN gcSHADER Shader,
- + IN gctPOINTER Buffer,
- + IN gctSIZE_T BufferSize
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_Save
- +********************************************************************************
- +**
- +** Save a gcSHADER object to a binary buffer.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctPOINTER Buffer
- +** Pointer to a binary buffer to be used as storage for the gcSHADER
- +** object. If 'Buffer' is gcvNULL, the gcSHADER object will not be saved,
- +** but the number of bytes required to hold the binary output for the
- +** gcSHADER object will be returned.
- +**
- +** gctSIZE_T * BufferSize
- +** Pointer to a variable holding the number of bytes allocated in
- +** 'Buffer'. Only valid if 'Buffer' is not gcvNULL.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * BufferSize
- +** Pointer to a variable receiving the number of bytes required to hold
- +** the binary form of the gcSHADER object.
- +*/
- +gceSTATUS
- +gcSHADER_Save(
- + IN gcSHADER Shader,
- + IN gctPOINTER Buffer,
- + IN OUT gctSIZE_T * BufferSize
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_LoadEx
- +********************************************************************************
- +**
- +** Load a gcSHADER object from a binary buffer.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctPOINTER Buffer
- +** Pointer to a binary buffer containg the shader data to load.
- +**
- +** gctSIZE_T BufferSize
- +** Number of bytes inside the binary buffer pointed to by 'Buffer'.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_LoadEx(
- + IN gcSHADER Shader,
- + IN gctPOINTER Buffer,
- + IN gctSIZE_T BufferSize
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_SaveEx
- +********************************************************************************
- +**
- +** Save a gcSHADER object to a binary buffer.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctPOINTER Buffer
- +** Pointer to a binary buffer to be used as storage for the gcSHADER
- +** object. If 'Buffer' is gcvNULL, the gcSHADER object will not be saved,
- +** but the number of bytes required to hold the binary output for the
- +** gcSHADER object will be returned.
- +**
- +** gctSIZE_T * BufferSize
- +** Pointer to a variable holding the number of bytes allocated in
- +** 'Buffer'. Only valid if 'Buffer' is not gcvNULL.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * BufferSize
- +** Pointer to a variable receiving the number of bytes required to hold
- +** the binary form of the gcSHADER object.
- +*/
- +gceSTATUS
- +gcSHADER_SaveEx(
- + IN gcSHADER Shader,
- + IN gctPOINTER Buffer,
- + IN OUT gctSIZE_T * BufferSize
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_ReallocateAttributes
- +**
- +** Reallocate an array of pointers to gcATTRIBUTE objects.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctSIZE_T Count
- +** Array count to reallocate. 'Count' must be at least 1.
- +*/
- +gceSTATUS
- +gcSHADER_ReallocateAttributes(
- + IN gcSHADER Shader,
- + IN gctSIZE_T Count
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddAttribute
- +********************************************************************************
- +**
- +** Add an attribute to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctCONST_STRING Name
- +** Name of the attribute to add.
- +**
- +** gcSHADER_TYPE Type
- +** Type of the attribute to add.
- +**
- +** gctSIZE_T Length
- +** Array length of the attribute to add. 'Length' must be at least 1.
- +**
- +** gctBOOL IsTexture
- +** gcvTRUE if the attribute is used as a texture coordinate, gcvFALSE if not.
- +**
- +** OUTPUT:
- +**
- +** gcATTRIBUTE * Attribute
- +** Pointer to a variable receiving the gcATTRIBUTE object pointer.
- +*/
- +gceSTATUS
- +gcSHADER_AddAttribute(
- + IN gcSHADER Shader,
- + IN gctCONST_STRING Name,
- + IN gcSHADER_TYPE Type,
- + IN gctSIZE_T Length,
- + IN gctBOOL IsTexture,
- + OUT gcATTRIBUTE * Attribute
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_GetAttributeCount
- +********************************************************************************
- +**
- +** Get the number of attributes for this shader.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Count
- +** Pointer to a variable receiving the number of attributes.
- +*/
- +gceSTATUS
- +gcSHADER_GetAttributeCount(
- + IN gcSHADER Shader,
- + OUT gctSIZE_T * Count
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_GetAttribute
- +********************************************************************************
- +**
- +** Get the gcATTRIBUTE object poniter for an indexed attribute for this shader.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctUINT Index
- +** Index of the attribute to retrieve.
- +**
- +** OUTPUT:
- +**
- +** gcATTRIBUTE * Attribute
- +** Pointer to a variable receiving the gcATTRIBUTE object pointer.
- +*/
- +gceSTATUS
- +gcSHADER_GetAttribute(
- + IN gcSHADER Shader,
- + IN gctUINT Index,
- + OUT gcATTRIBUTE * Attribute
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_ReallocateUniforms
- +**
- +** Reallocate an array of pointers to gcUNIFORM objects.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctSIZE_T Count
- +** Array count to reallocate. 'Count' must be at least 1.
- +*/
- +gceSTATUS
- +gcSHADER_ReallocateUniforms(
- + IN gcSHADER Shader,
- + IN gctSIZE_T Count
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddUniform
- +********************************************************************************
- +**
- +** Add an uniform to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctCONST_STRING Name
- +** Name of the uniform to add.
- +**
- +** gcSHADER_TYPE Type
- +** Type of the uniform to add.
- +**
- +** gctSIZE_T Length
- +** Array length of the uniform to add. 'Length' must be at least 1.
- +**
- +** OUTPUT:
- +**
- +** gcUNIFORM * Uniform
- +** Pointer to a variable receiving the gcUNIFORM object pointer.
- +*/
- +gceSTATUS
- +gcSHADER_AddUniform(
- + IN gcSHADER Shader,
- + IN gctCONST_STRING Name,
- + IN gcSHADER_TYPE Type,
- + IN gctSIZE_T Length,
- + OUT gcUNIFORM * Uniform
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddPreRotationUniform
- +********************************************************************************
- +**
- +** Add an uniform to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctCONST_STRING Name
- +** Name of the uniform to add.
- +**
- +** gcSHADER_TYPE Type
- +** Type of the uniform to add.
- +**
- +** gctSIZE_T Length
- +** Array length of the uniform to add. 'Length' must be at least 1.
- +**
- +** gctINT col
- +** Which uniform.
- +**
- +** OUTPUT:
- +**
- +** gcUNIFORM * Uniform
- +** Pointer to a variable receiving the gcUNIFORM object pointer.
- +*/
- +gceSTATUS
- +gcSHADER_AddPreRotationUniform(
- + IN gcSHADER Shader,
- + IN gctCONST_STRING Name,
- + IN gcSHADER_TYPE Type,
- + IN gctSIZE_T Length,
- + IN gctINT col,
- + OUT gcUNIFORM * Uniform
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddUniformEx
- +********************************************************************************
- +**
- +** Add an uniform to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctCONST_STRING Name
- +** Name of the uniform to add.
- +**
- +** gcSHADER_TYPE Type
- +** Type of the uniform to add.
- +**
- +** gcSHADER_PRECISION precision
- +** Precision of the uniform to add.
- +**
- +** gctSIZE_T Length
- +** Array length of the uniform to add. 'Length' must be at least 1.
- +**
- +** OUTPUT:
- +**
- +** gcUNIFORM * Uniform
- +** Pointer to a variable receiving the gcUNIFORM object pointer.
- +*/
- +gceSTATUS
- +gcSHADER_AddUniformEx(
- + IN gcSHADER Shader,
- + IN gctCONST_STRING Name,
- + IN gcSHADER_TYPE Type,
- + IN gcSHADER_PRECISION precision,
- + IN gctSIZE_T Length,
- + OUT gcUNIFORM * Uniform
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddUniformEx1
- +********************************************************************************
- +**
- +** Add an uniform to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctCONST_STRING Name
- +** Name of the uniform to add.
- +**
- +** gcSHADER_TYPE Type
- +** Type of the uniform to add.
- +**
- +** gcSHADER_PRECISION precision
- +** Precision of the uniform to add.
- +**
- +** gctSIZE_T Length
- +** Array length of the uniform to add. 'Length' must be at least 1.
- +**
- +** gcSHADER_VAR_CATEGORY varCategory
- +** Variable category, normal or struct.
- +**
- +** gctUINT16 numStructureElement
- +** If struct, its element number.
- +**
- +** gctINT16 parent
- +** If struct, parent index in gcSHADER.variables.
- +**
- +** gctINT16 prevSibling
- +** If struct, previous sibling index in gcSHADER.variables.
- +**
- +** OUTPUT:
- +**
- +** gcUNIFORM * Uniform
- +** Pointer to a variable receiving the gcUNIFORM object pointer.
- +**
- +** gctINT16* ThisUniformIndex
- +** Returned value about uniform index in gcSHADER.
- +*/
- +gceSTATUS
- +gcSHADER_AddUniformEx1(
- + IN gcSHADER Shader,
- + IN gctCONST_STRING Name,
- + IN gcSHADER_TYPE Type,
- + IN gcSHADER_PRECISION precision,
- + IN gctSIZE_T Length,
- + IN gctINT IsArray,
- + IN gcSHADER_VAR_CATEGORY varCategory,
- + IN gctUINT16 numStructureElement,
- + IN gctINT16 parent,
- + IN gctINT16 prevSibling,
- + OUT gctINT16* ThisUniformIndex,
- + OUT gcUNIFORM * Uniform
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_GetUniformCount
- +********************************************************************************
- +**
- +** Get the number of uniforms for this shader.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Count
- +** Pointer to a variable receiving the number of uniforms.
- +*/
- +gceSTATUS
- +gcSHADER_GetUniformCount(
- + IN gcSHADER Shader,
- + OUT gctSIZE_T * Count
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_GetPreRotationUniform
- +********************************************************************************
- +**
- +** Get the preRotate Uniform.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** OUTPUT:
- +**
- +** gcUNIFORM ** pUniform
- +** Pointer to a preRotation uniforms array.
- +*/
- +gceSTATUS
- +gcSHADER_GetPreRotationUniform(
- + IN gcSHADER Shader,
- + OUT gcUNIFORM ** pUniform
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_GetUniform
- +********************************************************************************
- +**
- +** Get the gcUNIFORM object pointer for an indexed uniform for this shader.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctUINT Index
- +** Index of the uniform to retrieve.
- +**
- +** OUTPUT:
- +**
- +** gcUNIFORM * Uniform
- +** Pointer to a variable receiving the gcUNIFORM object pointer.
- +*/
- +gceSTATUS
- +gcSHADER_GetUniform(
- + IN gcSHADER Shader,
- + IN gctUINT Index,
- + OUT gcUNIFORM * Uniform
- + );
- +
- +
- +/*******************************************************************************
- +** gcSHADER_GetUniformIndexingRange
- +********************************************************************************
- +**
- +** Get the gcUNIFORM object pointer for an indexed uniform for this shader.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctINT uniformIndex
- +** Index of the start uniform.
- +**
- +** gctINT offset
- +** Offset to indexing.
- +**
- +** OUTPUT:
- +**
- +** gctINT * LastUniformIndex
- +** Pointer to index of last uniform in indexing range.
- +**
- +** gctINT * OffsetUniformIndex
- +** Pointer to index of uniform that indexing at offset.
- +**
- +** gctINT * DeviationInOffsetUniform
- +** Pointer to offset in uniform picked up.
- +*/
- +gceSTATUS
- +gcSHADER_GetUniformIndexingRange(
- + IN gcSHADER Shader,
- + IN gctINT uniformIndex,
- + IN gctINT offset,
- + OUT gctINT * LastUniformIndex,
- + OUT gctINT * OffsetUniformIndex,
- + OUT gctINT * DeviationInOffsetUniform
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_GetKernelFucntion
- +**
- +** Get the gcKERNEL_FUNCTION object pointer for an indexed kernel function for this shader.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctUINT Index
- +** Index of kernel function to retreive the name for.
- +**
- +** OUTPUT:
- +**
- +** gcKERNEL_FUNCTION * KernelFunction
- +** Pointer to a variable receiving the gcKERNEL_FUNCTION object pointer.
- +*/
- +gceSTATUS
- +gcSHADER_GetKernelFunction(
- + IN gcSHADER Shader,
- + IN gctUINT Index,
- + OUT gcKERNEL_FUNCTION * KernelFunction
- + );
- +
- +gceSTATUS
- +gcSHADER_GetKernelFunctionByName(
- + IN gcSHADER Shader,
- + IN gctSTRING KernelName,
- + OUT gcKERNEL_FUNCTION * KernelFunction
- + );
- +/*******************************************************************************
- +** gcSHADER_GetKernelFunctionCount
- +**
- +** Get the number of kernel functions for this shader.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Count
- +** Pointer to a variable receiving the number of kernel functions.
- +*/
- +gceSTATUS
- +gcSHADER_GetKernelFunctionCount(
- + IN gcSHADER Shader,
- + OUT gctSIZE_T * Count
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_ReallocateOutputs
- +**
- +** Reallocate an array of pointers to gcOUTPUT objects.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctSIZE_T Count
- +** Array count to reallocate. 'Count' must be at least 1.
- +*/
- +gceSTATUS
- +gcSHADER_ReallocateOutputs(
- + IN gcSHADER Shader,
- + IN gctSIZE_T Count
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddOutput
- +********************************************************************************
- +**
- +** Add an output to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctCONST_STRING Name
- +** Name of the output to add.
- +**
- +** gcSHADER_TYPE Type
- +** Type of the output to add.
- +**
- +** gctSIZE_T Length
- +** Array length of the output to add. 'Length' must be at least 1.
- +**
- +** gctUINT16 TempRegister
- +** Temporary register index that holds the output value.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_AddOutput(
- + IN gcSHADER Shader,
- + IN gctCONST_STRING Name,
- + IN gcSHADER_TYPE Type,
- + IN gctSIZE_T Length,
- + IN gctUINT16 TempRegister
- + );
- +
- +gceSTATUS
- +gcSHADER_AddOutputIndexed(
- + IN gcSHADER Shader,
- + IN gctCONST_STRING Name,
- + IN gctSIZE_T Index,
- + IN gctUINT16 TempIndex
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_GetOutputCount
- +********************************************************************************
- +**
- +** Get the number of outputs for this shader.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Count
- +** Pointer to a variable receiving the number of outputs.
- +*/
- +gceSTATUS
- +gcSHADER_GetOutputCount(
- + IN gcSHADER Shader,
- + OUT gctSIZE_T * Count
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_GetOutput
- +********************************************************************************
- +**
- +** Get the gcOUTPUT object pointer for an indexed output for this shader.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctUINT Index
- +** Index of output to retrieve.
- +**
- +** OUTPUT:
- +**
- +** gcOUTPUT * Output
- +** Pointer to a variable receiving the gcOUTPUT object pointer.
- +*/
- +gceSTATUS
- +gcSHADER_GetOutput(
- + IN gcSHADER Shader,
- + IN gctUINT Index,
- + OUT gcOUTPUT * Output
- + );
- +
- +
- +/*******************************************************************************
- +** gcSHADER_GetOutputByName
- +********************************************************************************
- +**
- +** Get the gcOUTPUT object pointer for this shader by output name.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctSTRING name
- +** Name of output to retrieve.
- +**
- +** gctSIZE_T nameLength
- +** Length of name to retrieve
- +**
- +** OUTPUT:
- +**
- +** gcOUTPUT * Output
- +** Pointer to a variable receiving the gcOUTPUT object pointer.
- +*/
- +gceSTATUS
- +gcSHADER_GetOutputByName(
- + IN gcSHADER Shader,
- + IN gctSTRING name,
- + IN gctSIZE_T nameLength,
- + OUT gcOUTPUT * Output
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_ReallocateVariables
- +**
- +** Reallocate an array of pointers to gcVARIABLE objects.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctSIZE_T Count
- +** Array count to reallocate. 'Count' must be at least 1.
- +*/
- +gceSTATUS
- +gcSHADER_ReallocateVariables(
- + IN gcSHADER Shader,
- + IN gctSIZE_T Count
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddVariable
- +********************************************************************************
- +**
- +** Add a variable to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctCONST_STRING Name
- +** Name of the variable to add.
- +**
- +** gcSHADER_TYPE Type
- +** Type of the variable to add.
- +**
- +** gctSIZE_T Length
- +** Array length of the variable to add. 'Length' must be at least 1.
- +**
- +** gctUINT16 TempRegister
- +** Temporary register index that holds the variable value.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_AddVariable(
- + IN gcSHADER Shader,
- + IN gctCONST_STRING Name,
- + IN gcSHADER_TYPE Type,
- + IN gctSIZE_T Length,
- + IN gctUINT16 TempRegister
- + );
- +
- +
- +/*******************************************************************************
- +** gcSHADER_AddVariableEx
- +********************************************************************************
- +**
- +** Add a variable to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctCONST_STRING Name
- +** Name of the variable to add.
- +**
- +** gcSHADER_TYPE Type
- +** Type of the variable to add.
- +**
- +** gctSIZE_T Length
- +** Array length of the variable to add. 'Length' must be at least 1.
- +**
- +** gctUINT16 TempRegister
- +** Temporary register index that holds the variable value.
- +**
- +** gcSHADER_VAR_CATEGORY varCategory
- +** Variable category, normal or struct.
- +**
- +** gctUINT16 numStructureElement
- +** If struct, its element number.
- +**
- +** gctINT16 parent
- +** If struct, parent index in gcSHADER.variables.
- +**
- +** gctINT16 prevSibling
- +** If struct, previous sibling index in gcSHADER.variables.
- +**
- +** OUTPUT:
- +**
- +** gctINT16* ThisVarIndex
- +** Returned value about variable index in gcSHADER.
- +*/
- +gceSTATUS
- +gcSHADER_AddVariableEx(
- + IN gcSHADER Shader,
- + IN gctCONST_STRING Name,
- + IN gcSHADER_TYPE Type,
- + IN gctSIZE_T Length,
- + IN gctUINT16 TempRegister,
- + IN gcSHADER_VAR_CATEGORY varCategory,
- + IN gctUINT16 numStructureElement,
- + IN gctINT16 parent,
- + IN gctINT16 prevSibling,
- + OUT gctINT16* ThisVarIndex
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_UpdateVariable
- +********************************************************************************
- +**
- +** Update a variable to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctUINT Index
- +** Index of variable to retrieve.
- +**
- +** gceVARIABLE_UPDATE_FLAGS flag
- +** Flag which property of variable will be updated.
- +**
- +** gctUINT newValue
- +** New value to update.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_UpdateVariable(
- + IN gcSHADER Shader,
- + IN gctUINT Index,
- + IN gceVARIABLE_UPDATE_FLAGS flag,
- + IN gctUINT newValue
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_GetVariableCount
- +********************************************************************************
- +**
- +** Get the number of variables for this shader.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Count
- +** Pointer to a variable receiving the number of variables.
- +*/
- +gceSTATUS
- +gcSHADER_GetVariableCount(
- + IN gcSHADER Shader,
- + OUT gctSIZE_T * Count
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_GetVariable
- +********************************************************************************
- +**
- +** Get the gcVARIABLE object pointer for an indexed variable for this shader.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctUINT Index
- +** Index of variable to retrieve.
- +**
- +** OUTPUT:
- +**
- +** gcVARIABLE * Variable
- +** Pointer to a variable receiving the gcVARIABLE object pointer.
- +*/
- +gceSTATUS
- +gcSHADER_GetVariable(
- + IN gcSHADER Shader,
- + IN gctUINT Index,
- + OUT gcVARIABLE * Variable
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_GetVariableIndexingRange
- +********************************************************************************
- +**
- +** Get the gcVARIABLE indexing range.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gcVARIABLE variable
- +** Start variable.
- +**
- +** gctBOOL whole
- +** Indicate whether maximum indexing range is queried
- +**
- +** OUTPUT:
- +**
- +** gctUINT *Start
- +** Pointer to range start (temp register index).
- +**
- +** gctUINT *End
- +** Pointer to range end (temp register index).
- +*/
- +gceSTATUS
- +gcSHADER_GetVariableIndexingRange(
- + IN gcSHADER Shader,
- + IN gcVARIABLE variable,
- + IN gctBOOL whole,
- + OUT gctUINT *Start,
- + OUT gctUINT *End
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddOpcode
- +********************************************************************************
- +**
- +** Add an opcode to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gcSL_OPCODE Opcode
- +** Opcode to add.
- +**
- +** gctUINT16 TempRegister
- +** Temporary register index that acts as the target of the opcode.
- +**
- +** gctUINT8 Enable
- +** Write enable bits for the temporary register that acts as the target
- +** of the opcode.
- +**
- +** gcSL_FORMAT Format
- +** Format of the temporary register.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_AddOpcode(
- + IN gcSHADER Shader,
- + IN gcSL_OPCODE Opcode,
- + IN gctUINT16 TempRegister,
- + IN gctUINT8 Enable,
- + IN gcSL_FORMAT Format
- + );
- +
- +gceSTATUS
- +gcSHADER_AddOpcode2(
- + IN gcSHADER Shader,
- + IN gcSL_OPCODE Opcode,
- + IN gcSL_CONDITION Condition,
- + IN gctUINT16 TempRegister,
- + IN gctUINT8 Enable,
- + IN gcSL_FORMAT Format
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddOpcodeIndexed
- +********************************************************************************
- +**
- +** Add an opcode to a gcSHADER object that writes to an dynamically indexed
- +** target.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gcSL_OPCODE Opcode
- +** Opcode to add.
- +**
- +** gctUINT16 TempRegister
- +** Temporary register index that acts as the target of the opcode.
- +**
- +** gctUINT8 Enable
- +** Write enable bits for the temporary register that acts as the
- +** target of the opcode.
- +**
- +** gcSL_INDEXED Mode
- +** Location of the dynamic index inside the temporary register. Valid
- +** values can be:
- +**
- +** gcSL_INDEXED_X - Use x component of the temporary register.
- +** gcSL_INDEXED_Y - Use y component of the temporary register.
- +** gcSL_INDEXED_Z - Use z component of the temporary register.
- +** gcSL_INDEXED_W - Use w component of the temporary register.
- +**
- +** gctUINT16 IndexRegister
- +** Temporary register index that holds the dynamic index.
- +**
- +** gcSL_FORMAT Format
- +** Format of the temporary register.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_AddOpcodeIndexed(
- + IN gcSHADER Shader,
- + IN gcSL_OPCODE Opcode,
- + IN gctUINT16 TempRegister,
- + IN gctUINT8 Enable,
- + IN gcSL_INDEXED Mode,
- + IN gctUINT16 IndexRegister,
- + IN gcSL_FORMAT Format
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddOpcodeConditionIndexed
- +**
- +** Add an opcode to a gcSHADER object that writes to an dynamically indexed
- +** target.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gcSL_OPCODE Opcode
- +** Opcode to add.
- +**
- +** gcSL_CONDITION Condition
- +** Condition to check.
- +**
- +** gctUINT16 TempRegister
- +** Temporary register index that acts as the target of the opcode.
- +**
- +** gctUINT8 Enable
- +** Write enable bits for the temporary register that acts as the
- +** target of the opcode.
- +**
- +** gcSL_INDEXED Indexed
- +** Location of the dynamic index inside the temporary register. Valid
- +** values can be:
- +**
- +** gcSL_INDEXED_X - Use x component of the temporary register.
- +** gcSL_INDEXED_Y - Use y component of the temporary register.
- +** gcSL_INDEXED_Z - Use z component of the temporary register.
- +** gcSL_INDEXED_W - Use w component of the temporary register.
- +**
- +** gctUINT16 IndexRegister
- +** Temporary register index that holds the dynamic index.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_AddOpcodeConditionIndexed(
- + IN gcSHADER Shader,
- + IN gcSL_OPCODE Opcode,
- + IN gcSL_CONDITION Condition,
- + IN gctUINT16 TempRegister,
- + IN gctUINT8 Enable,
- + IN gcSL_INDEXED Indexed,
- + IN gctUINT16 IndexRegister,
- + IN gcSL_FORMAT Format
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddOpcodeConditional
- +********************************************************************************
- +**
- +** Add an conditional opcode to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gcSL_OPCODE Opcode
- +** Opcode to add.
- +**
- +** gcSL_CONDITION Condition
- +** Condition that needs to evaluate to gcvTRUE in order for the opcode to
- +** execute.
- +**
- +** gctUINT Label
- +** Target label if 'Condition' evaluates to gcvTRUE.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_AddOpcodeConditional(
- + IN gcSHADER Shader,
- + IN gcSL_OPCODE Opcode,
- + IN gcSL_CONDITION Condition,
- + IN gctUINT Label
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddOpcodeConditionalFormatted
- +**
- +** Add an conditional jump or call opcode to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gcSL_OPCODE Opcode
- +** Opcode to add.
- +**
- +** gcSL_CONDITION Condition
- +** Condition that needs to evaluate to gcvTRUE in order for the opcode to
- +** execute.
- +**
- +** gcSL_FORMAT Format
- +** Format of conditional operands
- +**
- +** gctUINT Label
- +** Target label if 'Condition' evaluates to gcvTRUE.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_AddOpcodeConditionalFormatted(
- + IN gcSHADER Shader,
- + IN gcSL_OPCODE Opcode,
- + IN gcSL_CONDITION Condition,
- + IN gcSL_FORMAT Format,
- + IN gctUINT Label
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddOpcodeConditionalFormattedEnable
- +**
- +** Add an conditional jump or call opcode to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gcSL_OPCODE Opcode
- +** Opcode to add.
- +**
- +** gcSL_CONDITION Condition
- +** Condition that needs to evaluate to gcvTRUE in order for the opcode to
- +** execute.
- +**
- +** gcSL_FORMAT Format
- +** Format of conditional operands
- +**
- +** gctUINT8 Enable
- +** Write enable value for the target of the opcode.
- +**
- +** gctUINT Label
- +** Target label if 'Condition' evaluates to gcvTRUE.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_AddOpcodeConditionalFormattedEnable(
- + IN gcSHADER Shader,
- + IN gcSL_OPCODE Opcode,
- + IN gcSL_CONDITION Condition,
- + IN gcSL_FORMAT Format,
- + IN gctUINT8 Enable,
- + IN gctUINT Label
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddLabel
- +********************************************************************************
- +**
- +** Define a label at the current instruction of a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctUINT Label
- +** Label to define.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_AddLabel(
- + IN gcSHADER Shader,
- + IN gctUINT Label
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddSource
- +********************************************************************************
- +**
- +** Add a source operand to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gcSL_TYPE Type
- +** Type of the source operand.
- +**
- +** gctUINT16 SourceIndex
- +** Index of the source operand.
- +**
- +** gctUINT8 Swizzle
- +** x, y, z, and w swizzle values packed into one 8-bit value.
- +**
- +** gcSL_FORMAT Format
- +** Format of the source operand.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_AddSource(
- + IN gcSHADER Shader,
- + IN gcSL_TYPE Type,
- + IN gctUINT16 SourceIndex,
- + IN gctUINT8 Swizzle,
- + IN gcSL_FORMAT Format
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddSourceIndexed
- +********************************************************************************
- +**
- +** Add a dynamically indexed source operand to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gcSL_TYPE Type
- +** Type of the source operand.
- +**
- +** gctUINT16 SourceIndex
- +** Index of the source operand.
- +**
- +** gctUINT8 Swizzle
- +** x, y, z, and w swizzle values packed into one 8-bit value.
- +**
- +** gcSL_INDEXED Mode
- +** Addressing mode for the index.
- +**
- +** gctUINT16 IndexRegister
- +** Temporary register index that holds the dynamic index.
- +**
- +** gcSL_FORMAT Format
- +** Format of the source operand.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_AddSourceIndexed(
- + IN gcSHADER Shader,
- + IN gcSL_TYPE Type,
- + IN gctUINT16 SourceIndex,
- + IN gctUINT8 Swizzle,
- + IN gcSL_INDEXED Mode,
- + IN gctUINT16 IndexRegister,
- + IN gcSL_FORMAT Format
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddSourceAttribute
- +********************************************************************************
- +**
- +** Add an attribute as a source operand to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gcATTRIBUTE Attribute
- +** Pointer to a gcATTRIBUTE object.
- +**
- +** gctUINT8 Swizzle
- +** x, y, z, and w swizzle values packed into one 8-bit value.
- +**
- +** gctINT Index
- +** Static index into the attribute in case the attribute is a matrix
- +** or array.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_AddSourceAttribute(
- + IN gcSHADER Shader,
- + IN gcATTRIBUTE Attribute,
- + IN gctUINT8 Swizzle,
- + IN gctINT Index
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddSourceAttributeIndexed
- +********************************************************************************
- +**
- +** Add an indexed attribute as a source operand to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gcATTRIBUTE Attribute
- +** Pointer to a gcATTRIBUTE object.
- +**
- +** gctUINT8 Swizzle
- +** x, y, z, and w swizzle values packed into one 8-bit value.
- +**
- +** gctINT Index
- +** Static index into the attribute in case the attribute is a matrix
- +** or array.
- +**
- +** gcSL_INDEXED Mode
- +** Addressing mode of the dynamic index.
- +**
- +** gctUINT16 IndexRegister
- +** Temporary register index that holds the dynamic index.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_AddSourceAttributeIndexed(
- + IN gcSHADER Shader,
- + IN gcATTRIBUTE Attribute,
- + IN gctUINT8 Swizzle,
- + IN gctINT Index,
- + IN gcSL_INDEXED Mode,
- + IN gctUINT16 IndexRegister
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddSourceUniform
- +********************************************************************************
- +**
- +** Add a uniform as a source operand to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gcUNIFORM Uniform
- +** Pointer to a gcUNIFORM object.
- +**
- +** gctUINT8 Swizzle
- +** x, y, z, and w swizzle values packed into one 8-bit value.
- +**
- +** gctINT Index
- +** Static index into the uniform in case the uniform is a matrix or
- +** array.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_AddSourceUniform(
- + IN gcSHADER Shader,
- + IN gcUNIFORM Uniform,
- + IN gctUINT8 Swizzle,
- + IN gctINT Index
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddSourceUniformIndexed
- +********************************************************************************
- +**
- +** Add an indexed uniform as a source operand to a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gcUNIFORM Uniform
- +** Pointer to a gcUNIFORM object.
- +**
- +** gctUINT8 Swizzle
- +** x, y, z, and w swizzle values packed into one 8-bit value.
- +**
- +** gctINT Index
- +** Static index into the uniform in case the uniform is a matrix or
- +** array.
- +**
- +** gcSL_INDEXED Mode
- +** Addressing mode of the dynamic index.
- +**
- +** gctUINT16 IndexRegister
- +** Temporary register index that holds the dynamic index.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_AddSourceUniformIndexed(
- + IN gcSHADER Shader,
- + IN gcUNIFORM Uniform,
- + IN gctUINT8 Swizzle,
- + IN gctINT Index,
- + IN gcSL_INDEXED Mode,
- + IN gctUINT16 IndexRegister
- + );
- +
- +gceSTATUS
- +gcSHADER_AddSourceSamplerIndexed(
- + IN gcSHADER Shader,
- + IN gctUINT8 Swizzle,
- + IN gcSL_INDEXED Mode,
- + IN gctUINT16 IndexRegister
- + );
- +
- +gceSTATUS
- +gcSHADER_AddSourceAttributeFormatted(
- + IN gcSHADER Shader,
- + IN gcATTRIBUTE Attribute,
- + IN gctUINT8 Swizzle,
- + IN gctINT Index,
- + IN gcSL_FORMAT Format
- + );
- +
- +gceSTATUS
- +gcSHADER_AddSourceAttributeIndexedFormatted(
- + IN gcSHADER Shader,
- + IN gcATTRIBUTE Attribute,
- + IN gctUINT8 Swizzle,
- + IN gctINT Index,
- + IN gcSL_INDEXED Mode,
- + IN gctUINT16 IndexRegister,
- + IN gcSL_FORMAT Format
- + );
- +
- +gceSTATUS
- +gcSHADER_AddSourceUniformFormatted(
- + IN gcSHADER Shader,
- + IN gcUNIFORM Uniform,
- + IN gctUINT8 Swizzle,
- + IN gctINT Index,
- + IN gcSL_FORMAT Format
- + );
- +
- +gceSTATUS
- +gcSHADER_AddSourceUniformIndexedFormatted(
- + IN gcSHADER Shader,
- + IN gcUNIFORM Uniform,
- + IN gctUINT8 Swizzle,
- + IN gctINT Index,
- + IN gcSL_INDEXED Mode,
- + IN gctUINT16 IndexRegister,
- + IN gcSL_FORMAT Format
- + );
- +
- +gceSTATUS
- +gcSHADER_AddSourceSamplerIndexedFormatted(
- + IN gcSHADER Shader,
- + IN gctUINT8 Swizzle,
- + IN gcSL_INDEXED Mode,
- + IN gctUINT16 IndexRegister,
- + IN gcSL_FORMAT Format
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddSourceConstant
- +********************************************************************************
- +**
- +** Add a constant floating point value as a source operand to a gcSHADER
- +** object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctFLOAT Constant
- +** Floating point constant.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_AddSourceConstant(
- + IN gcSHADER Shader,
- + IN gctFLOAT Constant
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_AddSourceConstantFormatted
- +********************************************************************************
- +**
- +** Add a constant value as a source operand to a gcSHADER
- +** object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** void * Constant
- +** Pointer to constant.
- +**
- +** gcSL_FORMAT Format
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_AddSourceConstantFormatted(
- + IN gcSHADER Shader,
- + IN void *Constant,
- + IN gcSL_FORMAT Format
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_Pack
- +********************************************************************************
- +**
- +** Pack a dynamically created gcSHADER object by trimming the allocated arrays
- +** and resolving all the labeling.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_Pack(
- + IN gcSHADER Shader
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_SetOptimizationOption
- +********************************************************************************
- +**
- +** Set optimization option of a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctUINT OptimizationOption
- +** Optimization option. Can be one of the following:
- +**
- +** 0 - No optimization.
- +** 1 - Full optimization.
- +** Other value - For optimizer testing.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcSHADER_SetOptimizationOption(
- + IN gcSHADER Shader,
- + IN gctUINT OptimizationOption
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_ReallocateFunctions
- +**
- +** Reallocate an array of pointers to gcFUNCTION objects.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctSIZE_T Count
- +** Array count to reallocate. 'Count' must be at least 1.
- +*/
- +gceSTATUS
- +gcSHADER_ReallocateFunctions(
- + IN gcSHADER Shader,
- + IN gctSIZE_T Count
- + );
- +
- +gceSTATUS
- +gcSHADER_AddFunction(
- + IN gcSHADER Shader,
- + IN gctCONST_STRING Name,
- + OUT gcFUNCTION * Function
- + );
- +
- +gceSTATUS
- +gcSHADER_ReallocateKernelFunctions(
- + IN gcSHADER Shader,
- + IN gctSIZE_T Count
- + );
- +
- +gceSTATUS
- +gcSHADER_AddKernelFunction(
- + IN gcSHADER Shader,
- + IN gctCONST_STRING Name,
- + OUT gcKERNEL_FUNCTION * KernelFunction
- + );
- +
- +gceSTATUS
- +gcSHADER_BeginFunction(
- + IN gcSHADER Shader,
- + IN gcFUNCTION Function
- + );
- +
- +gceSTATUS
- +gcSHADER_EndFunction(
- + IN gcSHADER Shader,
- + IN gcFUNCTION Function
- + );
- +
- +gceSTATUS
- +gcSHADER_BeginKernelFunction(
- + IN gcSHADER Shader,
- + IN gcKERNEL_FUNCTION KernelFunction
- + );
- +
- +gceSTATUS
- +gcSHADER_EndKernelFunction(
- + IN gcSHADER Shader,
- + IN gcKERNEL_FUNCTION KernelFunction,
- + IN gctSIZE_T LocalMemorySize
- + );
- +
- +gceSTATUS
- +gcSHADER_SetMaxKernelFunctionArgs(
- + IN gcSHADER Shader,
- + IN gctUINT32 MaxKernelFunctionArgs
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_SetConstantMemorySize
- +**
- +** Set the constant memory address space size of a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctSIZE_T ConstantMemorySize
- +** Constant memory size in bytes
- +**
- +** gctCHAR *ConstantMemoryBuffer
- +** Constant memory buffer
- +*/
- +gceSTATUS
- +gcSHADER_SetConstantMemorySize(
- + IN gcSHADER Shader,
- + IN gctSIZE_T ConstantMemorySize,
- + IN gctCHAR * ConstantMemoryBuffer
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_GetConstantMemorySize
- +**
- +** Set the constant memory address space size of a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * ConstantMemorySize
- +** Pointer to a variable receiving constant memory size in bytes
- +**
- +** gctCHAR **ConstantMemoryBuffer.
- +** Pointer to a variable for returned shader constant memory buffer.
- +*/
- +gceSTATUS
- +gcSHADER_GetConstantMemorySize(
- + IN gcSHADER Shader,
- + OUT gctSIZE_T * ConstantMemorySize,
- + OUT gctCHAR ** ConstantMemoryBuffer
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_SetPrivateMemorySize
- +**
- +** Set the private memory address space size of a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctSIZE_T PrivateMemorySize
- +** Private memory size in bytes
- +*/
- +gceSTATUS
- +gcSHADER_SetPrivateMemorySize(
- + IN gcSHADER Shader,
- + IN gctSIZE_T PrivateMemorySize
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_GetPrivateMemorySize
- +**
- +** Set the private memory address space size of a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * PrivateMemorySize
- +** Pointer to a variable receiving private memory size in bytes
- +*/
- +gceSTATUS
- +gcSHADER_GetPrivateMemorySize(
- + IN gcSHADER Shader,
- + OUT gctSIZE_T * PrivateMemorySize
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_SetLocalMemorySize
- +**
- +** Set the local memory address space size of a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** gctSIZE_T LocalMemorySize
- +** Local memory size in bytes
- +*/
- +gceSTATUS
- +gcSHADER_SetLocalMemorySize(
- + IN gcSHADER Shader,
- + IN gctSIZE_T LocalMemorySize
- + );
- +
- +/*******************************************************************************
- +** gcSHADER_GetLocalMemorySize
- +**
- +** Set the local memory address space size of a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * LocalMemorySize
- +** Pointer to a variable receiving lcoal memory size in bytes
- +*/
- +gceSTATUS
- +gcSHADER_GetLocalMemorySize(
- + IN gcSHADER Shader,
- + OUT gctSIZE_T * LocalMemorySize
- + );
- +
- +
- +/*******************************************************************************
- +** gcSHADER_CheckValidity
- +**
- +** Check validity for a gcSHADER object.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object.
- +**
- +*/
- +gceSTATUS
- +gcSHADER_CheckValidity(
- + IN gcSHADER Shader
- + );
- +
- +#if gcdUSE_WCLIP_PATCH
- +gceSTATUS
- +gcATTRIBUTE_IsPosition(
- + IN gcATTRIBUTE Attribute,
- + OUT gctBOOL * IsPosition
- + );
- +#endif
- +
- +/*******************************************************************************
- +** gcATTRIBUTE_GetType
- +********************************************************************************
- +**
- +** Get the type and array length of a gcATTRIBUTE object.
- +**
- +** INPUT:
- +**
- +** gcATTRIBUTE Attribute
- +** Pointer to a gcATTRIBUTE object.
- +**
- +** OUTPUT:
- +**
- +** gcSHADER_TYPE * Type
- +** Pointer to a variable receiving the type of the attribute. 'Type'
- +** can be gcvNULL, in which case no type will be returned.
- +**
- +** gctSIZE_T * ArrayLength
- +** Pointer to a variable receiving the length of the array if the
- +** attribute was declared as an array. If the attribute was not
- +** declared as an array, the array length will be 1. 'ArrayLength' can
- +** be gcvNULL, in which case no array length will be returned.
- +*/
- +gceSTATUS
- +gcATTRIBUTE_GetType(
- + IN gcATTRIBUTE Attribute,
- + OUT gcSHADER_TYPE * Type,
- + OUT gctSIZE_T * ArrayLength
- + );
- +
- +/*******************************************************************************
- +** gcATTRIBUTE_GetName
- +********************************************************************************
- +**
- +** Get the name of a gcATTRIBUTE object.
- +**
- +** INPUT:
- +**
- +** gcATTRIBUTE Attribute
- +** Pointer to a gcATTRIBUTE object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Length
- +** Pointer to a variable receiving the length of the attribute name.
- +** 'Length' can be gcvNULL, in which case no length will be returned.
- +**
- +** gctCONST_STRING * Name
- +** Pointer to a variable receiving the pointer to the attribute name.
- +** 'Name' can be gcvNULL, in which case no name will be returned.
- +*/
- +gceSTATUS
- +gcATTRIBUTE_GetName(
- + IN gcATTRIBUTE Attribute,
- + OUT gctSIZE_T * Length,
- + OUT gctCONST_STRING * Name
- + );
- +
- +/*******************************************************************************
- +** gcATTRIBUTE_IsEnabled
- +********************************************************************************
- +**
- +** Query the enabled state of a gcATTRIBUTE object.
- +**
- +** INPUT:
- +**
- +** gcATTRIBUTE Attribute
- +** Pointer to a gcATTRIBUTE object.
- +**
- +** OUTPUT:
- +**
- +** gctBOOL * Enabled
- +** Pointer to a variable receiving the enabled state of the attribute.
- +*/
- +gceSTATUS
- +gcATTRIBUTE_IsEnabled(
- + IN gcATTRIBUTE Attribute,
- + OUT gctBOOL * Enabled
- + );
- +
- +/*******************************************************************************
- +** gcUNIFORM_GetType
- +********************************************************************************
- +**
- +** Get the type and array length of a gcUNIFORM object.
- +**
- +** INPUT:
- +**
- +** gcUNIFORM Uniform
- +** Pointer to a gcUNIFORM object.
- +**
- +** OUTPUT:
- +**
- +** gcSHADER_TYPE * Type
- +** Pointer to a variable receiving the type of the uniform. 'Type' can
- +** be gcvNULL, in which case no type will be returned.
- +**
- +** gctSIZE_T * ArrayLength
- +** Pointer to a variable receiving the length of the array if the
- +** uniform was declared as an array. If the uniform was not declared
- +** as an array, the array length will be 1. 'ArrayLength' can be gcvNULL,
- +** in which case no array length will be returned.
- +*/
- +gceSTATUS
- +gcUNIFORM_GetType(
- + IN gcUNIFORM Uniform,
- + OUT gcSHADER_TYPE * Type,
- + OUT gctSIZE_T * ArrayLength
- + );
- +
- +/*******************************************************************************
- +** gcUNIFORM_GetTypeEx
- +********************************************************************************
- +**
- +** Get the type and array length of a gcUNIFORM object.
- +**
- +** INPUT:
- +**
- +** gcUNIFORM Uniform
- +** Pointer to a gcUNIFORM object.
- +**
- +** OUTPUT:
- +**
- +** gcSHADER_TYPE * Type
- +** Pointer to a variable receiving the type of the uniform. 'Type' can
- +** be gcvNULL, in which case no type will be returned.
- +**
- +** gcSHADER_PRECISION * Precision
- +** Pointer to a variable receiving the precision of the uniform. 'Precision' can
- +** be gcvNULL, in which case no type will be returned.
- +**
- +** gctSIZE_T * ArrayLength
- +** Pointer to a variable receiving the length of the array if the
- +** uniform was declared as an array. If the uniform was not declared
- +** as an array, the array length will be 1. 'ArrayLength' can be gcvNULL,
- +** in which case no array length will be returned.
- +*/
- +gceSTATUS
- +gcUNIFORM_GetTypeEx(
- + IN gcUNIFORM Uniform,
- + OUT gcSHADER_TYPE * Type,
- + OUT gcSHADER_PRECISION * Precision,
- + OUT gctSIZE_T * ArrayLength
- + );
- +
- +/*******************************************************************************
- +** gcUNIFORM_GetFlags
- +********************************************************************************
- +**
- +** Get the flags of a gcUNIFORM object.
- +**
- +** INPUT:
- +**
- +** gcUNIFORM Uniform
- +** Pointer to a gcUNIFORM object.
- +**
- +** OUTPUT:
- +**
- +** gceUNIFORM_FLAGS * Flags
- +** Pointer to a variable receiving the flags of the uniform.
- +**
- +*/
- +gceSTATUS
- +gcUNIFORM_GetFlags(
- + IN gcUNIFORM Uniform,
- + OUT gceUNIFORM_FLAGS * Flags
- + );
- +
- +/*******************************************************************************
- +** gcUNIFORM_SetFlags
- +********************************************************************************
- +**
- +** Set the flags of a gcUNIFORM object.
- +**
- +** INPUT:
- +**
- +** gcUNIFORM Uniform
- +** Pointer to a gcUNIFORM object.
- +**
- +** gceUNIFORM_FLAGS Flags
- +** Flags of the uniform to be set.
- +**
- +** OUTPUT:
- +** Nothing.
- +**
- +*/
- +gceSTATUS
- +gcUNIFORM_SetFlags(
- + IN gcUNIFORM Uniform,
- + IN gceUNIFORM_FLAGS Flags
- + );
- +
- +/*******************************************************************************
- +** gcUNIFORM_GetName
- +********************************************************************************
- +**
- +** Get the name of a gcUNIFORM object.
- +**
- +** INPUT:
- +**
- +** gcUNIFORM Uniform
- +** Pointer to a gcUNIFORM object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Length
- +** Pointer to a variable receiving the length of the uniform name.
- +** 'Length' can be gcvNULL, in which case no length will be returned.
- +**
- +** gctCONST_STRING * Name
- +** Pointer to a variable receiving the pointer to the uniform name.
- +** 'Name' can be gcvNULL, in which case no name will be returned.
- +*/
- +gceSTATUS
- +gcUNIFORM_GetName(
- + IN gcUNIFORM Uniform,
- + OUT gctSIZE_T * Length,
- + OUT gctCONST_STRING * Name
- + );
- +
- +/*******************************************************************************
- +** gcUNIFORM_GetSampler
- +********************************************************************************
- +**
- +** Get the physical sampler number for a sampler gcUNIFORM object.
- +**
- +** INPUT:
- +**
- +** gcUNIFORM Uniform
- +** Pointer to a gcUNIFORM object.
- +**
- +** OUTPUT:
- +**
- +** gctUINT32 * Sampler
- +** Pointer to a variable receiving the physical sampler.
- +*/
- +gceSTATUS
- +gcUNIFORM_GetSampler(
- + IN gcUNIFORM Uniform,
- + OUT gctUINT32 * Sampler
- + );
- +
- +/*******************************************************************************
- +** gcUNIFORM_GetFormat
- +**
- +** Get the type and array length of a gcUNIFORM object.
- +**
- +** INPUT:
- +**
- +** gcUNIFORM Uniform
- +** Pointer to a gcUNIFORM object.
- +**
- +** OUTPUT:
- +**
- +** gcSL_FORMAT * Format
- +** Pointer to a variable receiving the format of element of the uniform.
- +** 'Type' can be gcvNULL, in which case no type will be returned.
- +**
- +** gctBOOL * IsPointer
- +** Pointer to a variable receiving the state wheter the uniform is a pointer.
- +** 'IsPointer' can be gcvNULL, in which case no array length will be returned.
- +*/
- +gceSTATUS
- +gcUNIFORM_GetFormat(
- + IN gcUNIFORM Uniform,
- + OUT gcSL_FORMAT * Format,
- + OUT gctBOOL * IsPointer
- + );
- +
- +/*******************************************************************************
- +** gcUNIFORM_SetFormat
- +**
- +** Set the format and isPointer of a uniform.
- +**
- +** INPUT:
- +**
- +** gcUNIFORM Uniform
- +** Pointer to a gcUNIFORM object.
- +**
- +** gcSL_FORMAT Format
- +** Format of element of the uniform shaderType.
- +**
- +** gctBOOL IsPointer
- +** Wheter the uniform is a pointer.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcUNIFORM_SetFormat(
- + IN gcUNIFORM Uniform,
- + IN gcSL_FORMAT Format,
- + IN gctBOOL IsPointer
- + );
- +
- +/*******************************************************************************
- +** gcUNIFORM_SetValue
- +********************************************************************************
- +**
- +** Set the value of a uniform in integer.
- +**
- +** INPUT:
- +**
- +** gcUNIFORM Uniform
- +** Pointer to a gcUNIFORM object.
- +**
- +** gctSIZE_T Count
- +** Number of entries to program if the uniform has been declared as an
- +** array.
- +**
- +** const gctINT * Value
- +** Pointer to a buffer holding the integer values for the uniform.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcUNIFORM_SetValue(
- + IN gcUNIFORM Uniform,
- + IN gctSIZE_T Count,
- + IN const gctINT * Value
- + );
- +
- +/*******************************************************************************
- +** gcUNIFORM_SetValueX
- +********************************************************************************
- +**
- +** Set the value of a uniform in fixed point.
- +**
- +** INPUT:
- +**
- +** gcUNIFORM Uniform
- +** Pointer to a gcUNIFORM object.
- +**
- +** gctSIZE_T Count
- +** Number of entries to program if the uniform has been declared as an
- +** array.
- +**
- +** const gctFIXED_POINT * Value
- +** Pointer to a buffer holding the fixed point values for the uniform.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcUNIFORM_SetValueX(
- + IN gcUNIFORM Uniform,
- + IN gctSIZE_T Count,
- + IN gctFIXED_POINT * Value
- + );
- +
- +/*******************************************************************************
- +** gcUNIFORM_SetValueF
- +********************************************************************************
- +**
- +** Set the value of a uniform in floating point.
- +**
- +** INPUT:
- +**
- +** gcUNIFORM Uniform
- +** Pointer to a gcUNIFORM object.
- +**
- +** gctSIZE_T Count
- +** Number of entries to program if the uniform has been declared as an
- +** array.
- +**
- +** const gctFLOAT * Value
- +** Pointer to a buffer holding the floating point values for the
- +** uniform.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcUNIFORM_SetValueF(
- + IN gcUNIFORM Uniform,
- + IN gctSIZE_T Count,
- + IN const gctFLOAT * Value
- + );
- +
- +/*******************************************************************************
- +** gcUNIFORM_ProgramF
- +**
- +** Set the value of a uniform in floating point.
- +**
- +** INPUT:
- +**
- +** gctUINT32 Address
- +** Address of Uniform.
- +**
- +** gctSIZE_T Row/Col
- +**
- +** const gctFLOAT * Value
- +** Pointer to a buffer holding the floating point values for the
- +** uniform.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gcUNIFORM_ProgramF(
- + IN gctUINT32 Address,
- + IN gctSIZE_T Row,
- + IN gctSIZE_T Col,
- + IN const gctFLOAT * Value
- + );
- +
- +/*******************************************************************************
- +** gcUNIFORM_GetModelViewProjMatrix
- +********************************************************************************
- +**
- +** Get the value of uniform modelViewProjMatrix ID if present.
- +**
- +** INPUT:
- +**
- +** gcUNIFORM Uniform
- +** Pointer to a gcUNIFORM object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gctUINT
- +gcUNIFORM_GetModelViewProjMatrix(
- + IN gcUNIFORM Uniform
- + );
- +
- +/*******************************************************************************
- +** gcOUTPUT_GetType
- +********************************************************************************
- +**
- +** Get the type and array length of a gcOUTPUT object.
- +**
- +** INPUT:
- +**
- +** gcOUTPUT Output
- +** Pointer to a gcOUTPUT object.
- +**
- +** OUTPUT:
- +**
- +** gcSHADER_TYPE * Type
- +** Pointer to a variable receiving the type of the output. 'Type' can
- +** be gcvNULL, in which case no type will be returned.
- +**
- +** gctSIZE_T * ArrayLength
- +** Pointer to a variable receiving the length of the array if the
- +** output was declared as an array. If the output was not declared
- +** as an array, the array length will be 1. 'ArrayLength' can be gcvNULL,
- +** in which case no array length will be returned.
- +*/
- +gceSTATUS
- +gcOUTPUT_GetType(
- + IN gcOUTPUT Output,
- + OUT gcSHADER_TYPE * Type,
- + OUT gctSIZE_T * ArrayLength
- + );
- +
- +/*******************************************************************************
- +** gcOUTPUT_GetIndex
- +********************************************************************************
- +**
- +** Get the index of a gcOUTPUT object.
- +**
- +** INPUT:
- +**
- +** gcOUTPUT Output
- +** Pointer to a gcOUTPUT object.
- +**
- +** OUTPUT:
- +**
- +** gctUINT * Index
- +** Pointer to a variable receiving the temporary register index of the
- +** output. 'Index' can be gcvNULL,. in which case no index will be
- +** returned.
- +*/
- +gceSTATUS
- +gcOUTPUT_GetIndex(
- + IN gcOUTPUT Output,
- + OUT gctUINT * Index
- + );
- +
- +/*******************************************************************************
- +** gcOUTPUT_GetName
- +********************************************************************************
- +**
- +** Get the name of a gcOUTPUT object.
- +**
- +** INPUT:
- +**
- +** gcOUTPUT Output
- +** Pointer to a gcOUTPUT object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Length
- +** Pointer to a variable receiving the length of the output name.
- +** 'Length' can be gcvNULL, in which case no length will be returned.
- +**
- +** gctCONST_STRING * Name
- +** Pointer to a variable receiving the pointer to the output name.
- +** 'Name' can be gcvNULL, in which case no name will be returned.
- +*/
- +gceSTATUS
- +gcOUTPUT_GetName(
- + IN gcOUTPUT Output,
- + OUT gctSIZE_T * Length,
- + OUT gctCONST_STRING * Name
- + );
- +
- +/*******************************************************************************
- +*********************************************************** F U N C T I O N S **
- +*******************************************************************************/
- +
- +/*******************************************************************************
- +** gcFUNCTION_ReallocateArguments
- +**
- +** Reallocate an array of gcsFUNCTION_ARGUMENT objects.
- +**
- +** INPUT:
- +**
- +** gcFUNCTION Function
- +** Pointer to a gcFUNCTION object.
- +**
- +** gctSIZE_T Count
- +** Array count to reallocate. 'Count' must be at least 1.
- +*/
- +gceSTATUS
- +gcFUNCTION_ReallocateArguments(
- + IN gcFUNCTION Function,
- + IN gctSIZE_T Count
- + );
- +
- +gceSTATUS
- +gcFUNCTION_AddArgument(
- + IN gcFUNCTION Function,
- + IN gctUINT16 TempIndex,
- + IN gctUINT8 Enable,
- + IN gctUINT8 Qualifier
- + );
- +
- +gceSTATUS
- +gcFUNCTION_GetArgument(
- + IN gcFUNCTION Function,
- + IN gctUINT16 Index,
- + OUT gctUINT16_PTR Temp,
- + OUT gctUINT8_PTR Enable,
- + OUT gctUINT8_PTR Swizzle
- + );
- +
- +gceSTATUS
- +gcFUNCTION_GetLabel(
- + IN gcFUNCTION Function,
- + OUT gctUINT_PTR Label
- + );
- +
- +/*******************************************************************************
- +************************* K E R N E L P R O P E R T Y F U N C T I O N S **
- +*******************************************************************************/
- +/*******************************************************************************/
- +gceSTATUS
- +gcKERNEL_FUNCTION_AddKernelFunctionProperties(
- + IN gcKERNEL_FUNCTION KernelFunction,
- + IN gctINT propertyType,
- + IN gctSIZE_T propertySize,
- + IN gctINT * values
- + );
- +
- +gceSTATUS
- +gcKERNEL_FUNCTION_GetPropertyCount(
- + IN gcKERNEL_FUNCTION KernelFunction,
- + OUT gctSIZE_T * Count
- + );
- +
- +gceSTATUS
- +gcKERNEL_FUNCTION_GetProperty(
- + IN gcKERNEL_FUNCTION KernelFunction,
- + IN gctUINT Index,
- + OUT gctSIZE_T * propertySize,
- + OUT gctINT * propertyType,
- + OUT gctINT * propertyValues
- + );
- +
- +
- +/*******************************************************************************
- +*******************************I M A G E S A M P L E R F U N C T I O N S **
- +*******************************************************************************/
- +/*******************************************************************************
- +** gcKERNEL_FUNCTION_ReallocateImageSamplers
- +**
- +** Reallocate an array of pointers to image sampler pair.
- +**
- +** INPUT:
- +**
- +** gcKERNEL_FUNCTION KernelFunction
- +** Pointer to a gcKERNEL_FUNCTION object.
- +**
- +** gctSIZE_T Count
- +** Array count to reallocate. 'Count' must be at least 1.
- +*/
- +gceSTATUS
- +gcKERNEL_FUNCTION_ReallocateImageSamplers(
- + IN gcKERNEL_FUNCTION KernelFunction,
- + IN gctSIZE_T Count
- + );
- +
- +gceSTATUS
- +gcKERNEL_FUNCTION_AddImageSampler(
- + IN gcKERNEL_FUNCTION KernelFunction,
- + IN gctUINT8 ImageNum,
- + IN gctBOOL IsConstantSamplerType,
- + IN gctUINT32 SamplerType
- + );
- +
- +gceSTATUS
- +gcKERNEL_FUNCTION_GetImageSamplerCount(
- + IN gcKERNEL_FUNCTION KernelFunction,
- + OUT gctSIZE_T * Count
- + );
- +
- +gceSTATUS
- +gcKERNEL_FUNCTION_GetImageSampler(
- + IN gcKERNEL_FUNCTION KernelFunction,
- + IN gctUINT Index,
- + OUT gctUINT8 *ImageNum,
- + OUT gctBOOL *IsConstantSamplerType,
- + OUT gctUINT32 *SamplerType
- + );
- +
- +/*******************************************************************************
- +*********************************************K E R N E L F U N C T I O N S **
- +*******************************************************************************/
- +
- +/*******************************************************************************
- +** gcKERNEL_FUNCTION_ReallocateArguments
- +**
- +** Reallocate an array of gcsFUNCTION_ARGUMENT objects.
- +**
- +** INPUT:
- +**
- +** gcKERNEL_FUNCTION Function
- +** Pointer to a gcKERNEL_FUNCTION object.
- +**
- +** gctSIZE_T Count
- +** Array count to reallocate. 'Count' must be at least 1.
- +*/
- +gceSTATUS
- +gcKERNEL_FUNCTION_ReallocateArguments(
- + IN gcKERNEL_FUNCTION Function,
- + IN gctSIZE_T Count
- + );
- +
- +gceSTATUS
- +gcKERNEL_FUNCTION_AddArgument(
- + IN gcKERNEL_FUNCTION Function,
- + IN gctUINT16 TempIndex,
- + IN gctUINT8 Enable,
- + IN gctUINT8 Qualifier
- + );
- +
- +gceSTATUS
- +gcKERNEL_FUNCTION_GetArgument(
- + IN gcKERNEL_FUNCTION Function,
- + IN gctUINT16 Index,
- + OUT gctUINT16_PTR Temp,
- + OUT gctUINT8_PTR Enable,
- + OUT gctUINT8_PTR Swizzle
- + );
- +
- +gceSTATUS
- +gcKERNEL_FUNCTION_GetLabel(
- + IN gcKERNEL_FUNCTION Function,
- + OUT gctUINT_PTR Label
- + );
- +
- +gceSTATUS
- +gcKERNEL_FUNCTION_GetName(
- + IN gcKERNEL_FUNCTION KernelFunction,
- + OUT gctSIZE_T * Length,
- + OUT gctCONST_STRING * Name
- + );
- +
- +gceSTATUS
- +gcKERNEL_FUNCTION_ReallocateUniformArguments(
- + IN gcKERNEL_FUNCTION KernelFunction,
- + IN gctSIZE_T Count
- + );
- +
- +gceSTATUS
- +gcKERNEL_FUNCTION_AddUniformArgument(
- + IN gcKERNEL_FUNCTION KernelFunction,
- + IN gctCONST_STRING Name,
- + IN gcSHADER_TYPE Type,
- + IN gctSIZE_T Length,
- + OUT gcUNIFORM * UniformArgument
- + );
- +
- +gceSTATUS
- +gcKERNEL_FUNCTION_GetUniformArgumentCount(
- + IN gcKERNEL_FUNCTION KernelFunction,
- + OUT gctSIZE_T * Count
- + );
- +
- +gceSTATUS
- +gcKERNEL_FUNCTION_GetUniformArgument(
- + IN gcKERNEL_FUNCTION KernelFunction,
- + IN gctUINT Index,
- + OUT gcUNIFORM * UniformArgument
- + );
- +
- +gceSTATUS
- +gcKERNEL_FUNCTION_SetCodeEnd(
- + IN gcKERNEL_FUNCTION KernelFunction
- + );
- +
- +/*******************************************************************************
- +** gcCompileShader
- +********************************************************************************
- +**
- +** Compile a shader.
- +**
- +** INPUT:
- +**
- +** gcoOS Hal
- +** Pointer to an gcoHAL object.
- +**
- +** gctINT ShaderType
- +** Shader type to compile. Can be one of the following values:
- +**
- +** gcSHADER_TYPE_VERTEX
- +** Compile a vertex shader.
- +**
- +** gcSHADER_TYPE_FRAGMENT
- +** Compile a fragment shader.
- +**
- +** gctSIZE_T SourceSize
- +** Size of the source buffer in bytes.
- +**
- +** gctCONST_STRING Source
- +** Pointer to the buffer containing the shader source code.
- +**
- +** OUTPUT:
- +**
- +** gcSHADER * Binary
- +** Pointer to a variable receiving the pointer to a gcSHADER object
- +** containg the compiled shader code.
- +**
- +** gctSTRING * Log
- +** Pointer to a variable receiving a string pointer containging the
- +** compile log.
- +*/
- +gceSTATUS
- +gcCompileShader(
- + IN gcoHAL Hal,
- + IN gctINT ShaderType,
- + IN gctSIZE_T SourceSize,
- + IN gctCONST_STRING Source,
- + OUT gcSHADER * Binary,
- + OUT gctSTRING * Log
- + );
- +
- +/*******************************************************************************
- +** gcOptimizeShader
- +********************************************************************************
- +**
- +** Optimize a shader.
- +**
- +** INPUT:
- +**
- +** gcSHADER Shader
- +** Pointer to a gcSHADER object holding information about the compiled
- +** shader.
- +**
- +** gctFILE LogFile
- +** Pointer to an open FILE object.
- +*/
- +gceSTATUS
- +gcOptimizeShader(
- + IN gcSHADER Shader,
- + IN gctFILE LogFile
- + );
- +
- +/*******************************************************************************
- +** gcLinkShaders
- +********************************************************************************
- +**
- +** Link two shaders and generate a harwdare specific state buffer by compiling
- +** the compiler generated code through the resource allocator and code
- +** generator.
- +**
- +** INPUT:
- +**
- +** gcSHADER VertexShader
- +** Pointer to a gcSHADER object holding information about the compiled
- +** vertex shader.
- +**
- +** gcSHADER FragmentShader
- +** Pointer to a gcSHADER object holding information about the compiled
- +** fragment shader.
- +**
- +** gceSHADER_FLAGS Flags
- +** Compiler flags. Can be any of the following:
- +**
- +** gcvSHADER_DEAD_CODE - Dead code elimination.
- +** gcvSHADER_RESOURCE_USAGE - Resource usage optimizaion.
- +** gcvSHADER_OPTIMIZER - Full optimization.
- +** gcvSHADER_USE_GL_Z - Use OpenGL ES Z coordinate.
- +** gcvSHADER_USE_GL_POSITION - Use OpenGL ES gl_Position.
- +** gcvSHADER_USE_GL_FACE - Use OpenGL ES gl_FaceForward.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * StateBufferSize
- +** Pointer to a variable receicing the number of bytes in the buffer
- +** returned in 'StateBuffer'.
- +**
- +** gctPOINTER * StateBuffer
- +** Pointer to a variable receiving a buffer pointer that contains the
- +** states required to download the shaders into the hardware.
- +**
- +** gcsHINT_PTR * Hints
- +** Pointer to a variable receiving a gcsHINT structure pointer that
- +** contains information required when loading the shader states.
- +*/
- +gceSTATUS
- +gcLinkShaders(
- + IN gcSHADER VertexShader,
- + IN gcSHADER FragmentShader,
- + IN gceSHADER_FLAGS Flags,
- + OUT gctSIZE_T * StateBufferSize,
- + OUT gctPOINTER * StateBuffer,
- + OUT gcsHINT_PTR * Hints,
- + OUT gcMACHINECODE_PTR *ppVsMachineCode,
- + OUT gcMACHINECODE_PTR *ppFsMachineCode
- + );
- +
- +/*******************************************************************************
- +** gcLoadShaders
- +********************************************************************************
- +**
- +** Load a pre-compiled and pre-linked shader program into the hardware.
- +**
- +** INPUT:
- +**
- +** gcoHAL Hal
- +** Pointer to a gcoHAL object.
- +**
- +** gctSIZE_T StateBufferSize
- +** The number of bytes in the 'StateBuffer'.
- +**
- +** gctPOINTER StateBuffer
- +** Pointer to the states that make up the shader program.
- +**
- +** gcsHINT_PTR Hints
- +** Pointer to a gcsHINT structure that contains information required
- +** when loading the shader states.
- +*/
- +gceSTATUS
- +gcLoadShaders(
- + IN gcoHAL Hal,
- + IN gctSIZE_T StateBufferSize,
- + IN gctPOINTER StateBuffer,
- + IN gcsHINT_PTR Hints
- + );
- +
- +gceSTATUS
- +gcRecompileShaders(
- + IN gcoHAL Hal,
- + IN gcMACHINECODE_PTR pVsMachineCode,
- + IN gcMACHINECODE_PTR pPsMachineCode,
- + /*Recompile variables*/
- + IN OUT gctPOINTER *ppRecompileStateBuffer,
- + IN OUT gctSIZE_T *pRecompileStateBufferSize,
- + IN OUT gcsHINT_PTR *ppRecompileHints,
- + /* natvie state*/
- + IN gctPOINTER pNativeStateBuffer,
- + IN gctSIZE_T nativeStateBufferSize,
- + IN gcsHINT_PTR pNativeHints,
- + /* npt info */
- + IN gctUINT32 Samplers,
- + IN gctUINT32 *SamplerWrapS,
- + IN gctUINT32 *SamplerWrapT
- + );
- +
- +gceSTATUS
- +gcRecompileDepthBias(
- + IN gcoHAL Hal,
- + IN gcMACHINECODE_PTR pVsMachineCode,
- + /*Recompile variables*/
- + IN OUT gctPOINTER *ppRecompileStateBuffer,
- + IN OUT gctSIZE_T *pRecompileStateBufferSize,
- + IN OUT gcsHINT_PTR *ppRecompileHints,
- + /* natvie state*/
- + IN gctPOINTER pNativeStateBuffer,
- + IN gctSIZE_T nativeStateBufferSize,
- + IN gcsHINT_PTR pNativeHints,
- + OUT gctINT * uniformAddr,
- + OUT gctINT * uniformChannel
- + );
- +
- +/*******************************************************************************
- +** gcSaveProgram
- +********************************************************************************
- +**
- +** Save pre-compiled shaders and pre-linked programs to a binary file.
- +**
- +** INPUT:
- +**
- +** gcSHADER VertexShader
- +** Pointer to vertex shader object.
- +**
- +** gcSHADER FragmentShader
- +** Pointer to fragment shader object.
- +**
- +** gctSIZE_T ProgramBufferSize
- +** Number of bytes in 'ProgramBuffer'.
- +**
- +** gctPOINTER ProgramBuffer
- +** Pointer to buffer containing the program states.
- +**
- +** gcsHINT_PTR Hints
- +** Pointer to HINTS structure for program states.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * Binary
- +** Pointer to a variable receiving the binary data to be saved.
- +**
- +** gctSIZE_T * BinarySize
- +** Pointer to a variable receiving the number of bytes inside 'Binary'.
- +*/
- +gceSTATUS
- +gcSaveProgram(
- + IN gcSHADER VertexShader,
- + IN gcSHADER FragmentShader,
- + IN gctSIZE_T ProgramBufferSize,
- + IN gctPOINTER ProgramBuffer,
- + IN gcsHINT_PTR Hints,
- + OUT gctPOINTER * Binary,
- + OUT gctSIZE_T * BinarySize
- + );
- +
- +/*******************************************************************************
- +** gcLoadProgram
- +********************************************************************************
- +**
- +** Load pre-compiled shaders and pre-linked programs from a binary file.
- +**
- +** INPUT:
- +**
- +** gctPOINTER Binary
- +** Pointer to the binary data loaded.
- +**
- +** gctSIZE_T BinarySize
- +** Number of bytes in 'Binary'.
- +**
- +** OUTPUT:
- +**
- +** gcSHADER VertexShader
- +** Pointer to a vertex shader object.
- +**
- +** gcSHADER FragmentShader
- +** Pointer to a fragment shader object.
- +**
- +** gctSIZE_T * ProgramBufferSize
- +** Pointer to a variable receicing the number of bytes in the buffer
- +** returned in 'ProgramBuffer'.
- +**
- +** gctPOINTER * ProgramBuffer
- +** Pointer to a variable receiving a buffer pointer that contains the
- +** states required to download the shaders into the hardware.
- +**
- +** gcsHINT_PTR * Hints
- +** Pointer to a variable receiving a gcsHINT structure pointer that
- +** contains information required when loading the shader states.
- +*/
- +gceSTATUS
- +gcLoadProgram(
- + IN gctPOINTER Binary,
- + IN gctSIZE_T BinarySize,
- + OUT gcSHADER VertexShader,
- + OUT gcSHADER FragmentShader,
- + OUT gctSIZE_T * ProgramBufferSize,
- + OUT gctPOINTER * ProgramBuffer,
- + OUT gcsHINT_PTR * Hints
- + );
- +
- +/*******************************************************************************
- +** gcCompileKernel
- +********************************************************************************
- +**
- +** Compile a OpenCL kernel shader.
- +**
- +** INPUT:
- +**
- +** gcoOS Hal
- +** Pointer to an gcoHAL object.
- +**
- +** gctSIZE_T SourceSize
- +** Size of the source buffer in bytes.
- +**
- +** gctCONST_STRING Source
- +** Pointer to the buffer containing the shader source code.
- +**
- +** OUTPUT:
- +**
- +** gcSHADER * Binary
- +** Pointer to a variable receiving the pointer to a gcSHADER object
- +** containg the compiled shader code.
- +**
- +** gctSTRING * Log
- +** Pointer to a variable receiving a string pointer containging the
- +** compile log.
- +*/
- +gceSTATUS
- +gcCompileKernel(
- + IN gcoHAL Hal,
- + IN gctSIZE_T SourceSize,
- + IN gctCONST_STRING Source,
- + IN gctCONST_STRING Options,
- + OUT gcSHADER * Binary,
- + OUT gctSTRING * Log
- + );
- +
- +/*******************************************************************************
- +** gcLinkKernel
- +********************************************************************************
- +**
- +** Link OpenCL kernel and generate a harwdare specific state buffer by compiling
- +** the compiler generated code through the resource allocator and code
- +** generator.
- +**
- +** INPUT:
- +**
- +** gcSHADER Kernel
- +** Pointer to a gcSHADER object holding information about the compiled
- +** OpenCL kernel.
- +**
- +** gceSHADER_FLAGS Flags
- +** Compiler flags. Can be any of the following:
- +**
- +** gcvSHADER_DEAD_CODE - Dead code elimination.
- +** gcvSHADER_RESOURCE_USAGE - Resource usage optimizaion.
- +** gcvSHADER_OPTIMIZER - Full optimization.
- +** gcvSHADER_USE_GL_Z - Use OpenGL ES Z coordinate.
- +** gcvSHADER_USE_GL_POSITION - Use OpenGL ES gl_Position.
- +** gcvSHADER_USE_GL_FACE - Use OpenGL ES gl_FaceForward.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * StateBufferSize
- +** Pointer to a variable receiving the number of bytes in the buffer
- +** returned in 'StateBuffer'.
- +**
- +** gctPOINTER * StateBuffer
- +** Pointer to a variable receiving a buffer pointer that contains the
- +** states required to download the shaders into the hardware.
- +**
- +** gcsHINT_PTR * Hints
- +** Pointer to a variable receiving a gcsHINT structure pointer that
- +** contains information required when loading the shader states.
- +*/
- +gceSTATUS
- +gcLinkKernel(
- + IN gcSHADER Kernel,
- + IN gceSHADER_FLAGS Flags,
- + OUT gctSIZE_T * StateBufferSize,
- + OUT gctPOINTER * StateBuffer,
- + OUT gcsHINT_PTR * Hints
- + );
- +
- +/*******************************************************************************
- +** gcLoadKernel
- +********************************************************************************
- +**
- +** Load a pre-compiled and pre-linked kernel program into the hardware.
- +**
- +** INPUT:
- +**
- +** gctSIZE_T StateBufferSize
- +** The number of bytes in the 'StateBuffer'.
- +**
- +** gctPOINTER StateBuffer
- +** Pointer to the states that make up the shader program.
- +**
- +** gcsHINT_PTR Hints
- +** Pointer to a gcsHINT structure that contains information required
- +** when loading the shader states.
- +*/
- +gceSTATUS
- +gcLoadKernel(
- + IN gctSIZE_T StateBufferSize,
- + IN gctPOINTER StateBuffer,
- + IN gcsHINT_PTR Hints
- + );
- +
- +gceSTATUS
- +gcInvokeThreadWalker(
- + IN gcsTHREAD_WALKER_INFO_PTR Info
- + );
- +
- +void
- +gcTYPE_GetTypeInfo(
- + IN gcSHADER_TYPE Type,
- + OUT gctINT * Components,
- + OUT gctINT * Rows,
- + OUT gctCONST_STRING * Name
- + );
- +
- +gctBOOL
- +gcOPT_doVaryingPackingForShader(
- + IN gcSHADER Shader
- + );
- +
- +gceSTATUS
- +gcSHADER_PatchNPOTForMachineCode(
- + IN gcSHADER_KIND shaderType,
- + IN gcMACHINECODE_PTR pMachineCode,
- + IN gcNPOT_PATCH_PARAM_PTR pPatchParam,
- + IN gctUINT countOfPatchParam,
- + IN gctUINT hwSupportedInstCount,
- + OUT gctPOINTER* ppCmdBuffer,
- + OUT gctUINT32* pByteSizeOfCmdBuffer,
- + IN OUT gcsHINT_PTR pHints /* User needs copy original hints to this one, then passed this one in */
- + );
- +
- +gceSTATUS
- +gcSHADER_PatchZBiasForMachineCodeVS(
- + IN gcMACHINECODE_PTR pMachineCode,
- + IN OUT gcZBIAS_PATCH_PARAM_PTR pPatchParam,
- + IN gctUINT hwSupportedInstCount,
- + OUT gctPOINTER* ppCmdBuffer,
- + OUT gctUINT32* pByteSizeOfCmdBuffer,
- + IN OUT gcsHINT_PTR pHints /* User needs copy original hints to this one, then passed this one in */
- + );
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* VIVANTE_NO_3D */
- +#endif /* __gc_hal_compiler_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h 2015-03-08 14:27:37.641684501 -0500
- @@ -0,0 +1,1051 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_driver_h_
- +#define __gc_hal_driver_h_
- +
- +#include "gc_hal_enum.h"
- +#include "gc_hal_types.h"
- +
- +#if gcdENABLE_VG
- +#include "gc_hal_driver_vg.h"
- +#endif
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +/******************************************************************************\
- +******************************* I/O Control Codes ******************************
- +\******************************************************************************/
- +
- +#define gcvHAL_CLASS "galcore"
- +#define IOCTL_GCHAL_INTERFACE 30000
- +#define IOCTL_GCHAL_KERNEL_INTERFACE 30001
- +#define IOCTL_GCHAL_TERMINATE 30002
- +
- +/******************************************************************************\
- +********************************* Command Codes ********************************
- +\******************************************************************************/
- +
- +typedef enum _gceHAL_COMMAND_CODES
- +{
- + /* Generic query. */
- + gcvHAL_QUERY_VIDEO_MEMORY,
- + gcvHAL_QUERY_CHIP_IDENTITY,
- +
- + /* Contiguous memory. */
- + gcvHAL_ALLOCATE_NON_PAGED_MEMORY,
- + gcvHAL_FREE_NON_PAGED_MEMORY,
- + gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY,
- + gcvHAL_FREE_CONTIGUOUS_MEMORY,
- +
- + /* Video memory allocation. */
- + gcvHAL_ALLOCATE_VIDEO_MEMORY, /* Enforced alignment. */
- + gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY, /* No alignment. */
- + gcvHAL_FREE_VIDEO_MEMORY,
- +
- + /* Physical-to-logical mapping. */
- + gcvHAL_MAP_MEMORY,
- + gcvHAL_UNMAP_MEMORY,
- +
- + /* Logical-to-physical mapping. */
- + gcvHAL_MAP_USER_MEMORY,
- + gcvHAL_UNMAP_USER_MEMORY,
- +
- + /* Surface lock/unlock. */
- + gcvHAL_LOCK_VIDEO_MEMORY,
- + gcvHAL_UNLOCK_VIDEO_MEMORY,
- +
- + /* Event queue. */
- + gcvHAL_EVENT_COMMIT,
- +
- + gcvHAL_USER_SIGNAL,
- + gcvHAL_SIGNAL,
- + gcvHAL_WRITE_DATA,
- +
- + gcvHAL_COMMIT,
- + gcvHAL_STALL,
- +
- + gcvHAL_READ_REGISTER,
- + gcvHAL_WRITE_REGISTER,
- +
- + gcvHAL_GET_PROFILE_SETTING,
- + gcvHAL_SET_PROFILE_SETTING,
- +
- + gcvHAL_READ_ALL_PROFILE_REGISTERS,
- + gcvHAL_PROFILE_REGISTERS_2D,
- +#if VIVANTE_PROFILER_PERDRAW
- + gcvHAL_READ_PROFILER_REGISTER_SETTING,
- +#endif
- +
- + /* Power management. */
- + gcvHAL_SET_POWER_MANAGEMENT_STATE,
- + gcvHAL_QUERY_POWER_MANAGEMENT_STATE,
- +
- + gcvHAL_GET_BASE_ADDRESS,
- +
- + gcvHAL_SET_IDLE, /* reserved */
- +
- + /* Queries. */
- + gcvHAL_QUERY_KERNEL_SETTINGS,
- +
- + /* Reset. */
- + gcvHAL_RESET,
- +
- + /* Map physical address into handle. */
- + gcvHAL_MAP_PHYSICAL,
- +
- + /* Debugger stuff. */
- + gcvHAL_DEBUG,
- +
- + /* Cache stuff. */
- + gcvHAL_CACHE,
- +
- + /* TimeStamp */
- + gcvHAL_TIMESTAMP,
- +
- + /* Database. */
- + gcvHAL_DATABASE,
- +
- + /* Version. */
- + gcvHAL_VERSION,
- +
- + /* Chip info */
- + gcvHAL_CHIP_INFO,
- +
- + /* Process attaching/detaching. */
- + gcvHAL_ATTACH,
- + gcvHAL_DETACH,
- +
- + /* Composition. */
- + gcvHAL_COMPOSE,
- +
- + /* Set timeOut value */
- + gcvHAL_SET_TIMEOUT,
- +
- + /* Frame database. */
- + gcvHAL_GET_FRAME_INFO,
- +
- + /* Shared info for each process */
- + gcvHAL_GET_SHARED_INFO,
- + gcvHAL_SET_SHARED_INFO,
- + gcvHAL_QUERY_COMMAND_BUFFER,
- +
- + gcvHAL_COMMIT_DONE,
- +
- + /* GPU and event dump */
- + gcvHAL_DUMP_GPU_STATE,
- + gcvHAL_DUMP_EVENT,
- +
- + /* Virtual command buffer. */
- + gcvHAL_ALLOCATE_VIRTUAL_COMMAND_BUFFER,
- + gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER,
- +
- + /* FSCALE_VAL. */
- + gcvHAL_SET_FSCALE_VALUE,
- + gcvHAL_GET_FSCALE_VALUE,
- +
- + /* Reset time stamp. */
- + gcvHAL_QUERY_RESET_TIME_STAMP,
- +
- + /* Sync point operations. */
- + gcvHAL_SYNC_POINT,
- +
- + /* Create native fence and return its fd. */
- + gcvHAL_CREATE_NATIVE_FENCE,
- +
- + /* Video memory database */
- + gcvHAL_VIDMEM_DATABASE,
- +}
- +gceHAL_COMMAND_CODES;
- +
- +/******************************************************************************\
- +****************************** Interface Structure *****************************
- +\******************************************************************************/
- +
- +#define gcdMAX_PROFILE_FILE_NAME 128
- +
- +/* Kernel settings. */
- +typedef struct _gcsKERNEL_SETTINGS
- +{
- + /* Used RealTime signal between kernel and user. */
- + gctINT signal;
- +}
- +gcsKERNEL_SETTINGS;
- +
- +
- +/* gcvHAL_QUERY_CHIP_IDENTITY */
- +typedef struct _gcsHAL_QUERY_CHIP_IDENTITY * gcsHAL_QUERY_CHIP_IDENTITY_PTR;
- +typedef struct _gcsHAL_QUERY_CHIP_IDENTITY
- +{
- +
- + /* Chip model. */
- + gceCHIPMODEL chipModel;
- +
- + /* Revision value.*/
- + gctUINT32 chipRevision;
- +
- + /* Supported feature fields. */
- + gctUINT32 chipFeatures;
- +
- + /* Supported minor feature fields. */
- + gctUINT32 chipMinorFeatures;
- +
- + /* Supported minor feature 1 fields. */
- + gctUINT32 chipMinorFeatures1;
- +
- + /* Supported minor feature 2 fields. */
- + gctUINT32 chipMinorFeatures2;
- +
- + /* Supported minor feature 3 fields. */
- + gctUINT32 chipMinorFeatures3;
- +
- + /* Supported minor feature 4 fields. */
- + gctUINT32 chipMinorFeatures4;
- +
- + /* Number of streams supported. */
- + gctUINT32 streamCount;
- +
- + /* Total number of temporary registers per thread. */
- + gctUINT32 registerMax;
- +
- + /* Maximum number of threads. */
- + gctUINT32 threadCount;
- +
- + /* Number of shader cores. */
- + gctUINT32 shaderCoreCount;
- +
- + /* Size of the vertex cache. */
- + gctUINT32 vertexCacheSize;
- +
- + /* Number of entries in the vertex output buffer. */
- + gctUINT32 vertexOutputBufferSize;
- +
- + /* Number of pixel pipes. */
- + gctUINT32 pixelPipes;
- +
- + /* Number of instructions. */
- + gctUINT32 instructionCount;
- +
- + /* Number of constants. */
- + gctUINT32 numConstants;
- +
- + /* Buffer size */
- + gctUINT32 bufferSize;
- +
- + /* Number of varyings */
- + gctUINT32 varyingsCount;
- +
- + /* Supertile layout style in hardware */
- + gctUINT32 superTileMode;
- +
- + /* Special control bits for 2D chip. */
- + gctUINT32 chip2DControl;
- +}
- +gcsHAL_QUERY_CHIP_IDENTITY;
- +
- +/* gcvHAL_COMPOSE. */
- +typedef struct _gcsHAL_COMPOSE * gcsHAL_COMPOSE_PTR;
- +typedef struct _gcsHAL_COMPOSE
- +{
- + /* Composition state buffer. */
- + gctUINT64 physical;
- + gctUINT64 logical;
- + gctUINT offset;
- + gctUINT size;
- +
- + /* Composition end signal. */
- + gctUINT64 process;
- + gctUINT64 signal;
- +
- + /* User signals. */
- + gctUINT64 userProcess;
- + gctUINT64 userSignal1;
- + gctUINT64 userSignal2;
- +
- +#if defined(__QNXNTO__)
- + /* Client pulse side-channel connection ID. */
- + gctINT32 coid;
- +
- + /* Set by server. */
- + gctINT32 rcvid;
- +#endif
- +}
- +gcsHAL_COMPOSE;
- +
- +
- +typedef struct _gcsHAL_INTERFACE
- +{
- + /* Command code. */
- + gceHAL_COMMAND_CODES command;
- +
- + /* Hardware type. */
- + gceHARDWARE_TYPE hardwareType;
- +
- + /* Status value. */
- + gceSTATUS status;
- +
- + /* Handle to this interface channel. */
- + gctUINT64 handle;
- +
- + /* Pid of the client. */
- + gctUINT32 pid;
- +
- + /* Union of command structures. */
- + union _u
- + {
- + /* gcvHAL_GET_BASE_ADDRESS */
- + struct _gcsHAL_GET_BASE_ADDRESS
- + {
- + /* Physical memory address of internal memory. */
- + OUT gctUINT32 baseAddress;
- + }
- + GetBaseAddress;
- +
- + /* gcvHAL_QUERY_VIDEO_MEMORY */
- + struct _gcsHAL_QUERY_VIDEO_MEMORY
- + {
- + /* Physical memory address of internal memory. Just a name. */
- + OUT gctUINT32 internalPhysical;
- +
- + /* Size in bytes of internal memory. */
- + OUT gctUINT64 internalSize;
- +
- + /* Physical memory address of external memory. Just a name. */
- + OUT gctUINT32 externalPhysical;
- +
- + /* Size in bytes of external memory.*/
- + OUT gctUINT64 externalSize;
- +
- + /* Physical memory address of contiguous memory. Just a name. */
- + OUT gctUINT32 contiguousPhysical;
- +
- + /* Size in bytes of contiguous memory.*/
- + OUT gctUINT64 contiguousSize;
- + }
- + QueryVideoMemory;
- +
- + /* gcvHAL_QUERY_CHIP_IDENTITY */
- + gcsHAL_QUERY_CHIP_IDENTITY QueryChipIdentity;
- +
- + /* gcvHAL_MAP_MEMORY */
- + struct _gcsHAL_MAP_MEMORY
- + {
- + /* Physical memory address to map. Just a name on Linux/Qnx. */
- + IN gctUINT32 physical;
- +
- + /* Number of bytes in physical memory to map. */
- + IN gctUINT64 bytes;
- +
- + /* Address of mapped memory. */
- + OUT gctUINT64 logical;
- + }
- + MapMemory;
- +
- + /* gcvHAL_UNMAP_MEMORY */
- + struct _gcsHAL_UNMAP_MEMORY
- + {
- + /* Physical memory address to unmap. Just a name on Linux/Qnx. */
- + IN gctUINT32 physical;
- +
- + /* Number of bytes in physical memory to unmap. */
- + IN gctUINT64 bytes;
- +
- + /* Address of mapped memory to unmap. */
- + IN gctUINT64 logical;
- + }
- + UnmapMemory;
- +
- + /* gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY */
- + struct _gcsHAL_ALLOCATE_LINEAR_VIDEO_MEMORY
- + {
- + /* Number of bytes to allocate. */
- + IN OUT gctUINT bytes;
- +
- + /* Buffer alignment. */
- + IN gctUINT alignment;
- +
- + /* Type of allocation. */
- + IN gceSURF_TYPE type;
- +
- + /* Memory pool to allocate from. */
- + IN OUT gcePOOL pool;
- +
- + /* Allocated video memory in gcuVIDMEM_NODE. */
- + OUT gctUINT64 node;
- + }
- + AllocateLinearVideoMemory;
- +
- + /* gcvHAL_ALLOCATE_VIDEO_MEMORY */
- + struct _gcsHAL_ALLOCATE_VIDEO_MEMORY
- + {
- + /* Width of rectangle to allocate. */
- + IN OUT gctUINT width;
- +
- + /* Height of rectangle to allocate. */
- + IN OUT gctUINT height;
- +
- + /* Depth of rectangle to allocate. */
- + IN gctUINT depth;
- +
- + /* Format rectangle to allocate in gceSURF_FORMAT. */
- + IN gceSURF_FORMAT format;
- +
- + /* Type of allocation. */
- + IN gceSURF_TYPE type;
- +
- + /* Memory pool to allocate from. */
- + IN OUT gcePOOL pool;
- +
- + /* Allocated video memory in gcuVIDMEM_NODE. */
- + OUT gctUINT64 node;
- + }
- + AllocateVideoMemory;
- +
- + /* gcvHAL_FREE_VIDEO_MEMORY */
- + struct _gcsHAL_FREE_VIDEO_MEMORY
- + {
- + /* Allocated video memory in gcuVIDMEM_NODE. */
- + IN gctUINT64 node;
- +
- +#ifdef __QNXNTO__
- +/* TODO: This is part of the unlock - why is it here? */
- + /* Mapped logical address to unmap in user space. */
- + OUT gctUINT64 memory;
- +
- + /* Number of bytes to allocated. */
- + OUT gctUINT64 bytes;
- +#endif
- + }
- + FreeVideoMemory;
- +
- + /* gcvHAL_LOCK_VIDEO_MEMORY */
- + struct _gcsHAL_LOCK_VIDEO_MEMORY
- + {
- + /* Allocated video memory gcuVIDMEM_NODE gcuVIDMEM_NODE. */
- + IN gctUINT64 node;
- +
- + /* Cache configuration. */
- + /* Only gcvPOOL_CONTIGUOUS and gcvPOOL_VIRUTAL
- + ** can be configured */
- + IN gctBOOL cacheable;
- +
- + /* Hardware specific address. */
- + OUT gctUINT32 address;
- +
- + /* Mapped logical address. */
- + OUT gctUINT64 memory;
- + }
- + LockVideoMemory;
- +
- + /* gcvHAL_UNLOCK_VIDEO_MEMORY */
- + struct _gcsHAL_UNLOCK_VIDEO_MEMORY
- + {
- + /* Allocated video memory in gcuVIDMEM_NODE. */
- + IN gctUINT64 node;
- +
- + /* Type of surface. */
- + IN gceSURF_TYPE type;
- +
- + /* Flag to unlock surface asynchroneously. */
- + IN OUT gctBOOL asynchroneous;
- + }
- + UnlockVideoMemory;
- +
- + /* gcvHAL_ALLOCATE_NON_PAGED_MEMORY */
- + struct _gcsHAL_ALLOCATE_NON_PAGED_MEMORY
- + {
- + /* Number of bytes to allocate. */
- + IN OUT gctUINT64 bytes;
- +
- + /* Physical address of allocation. Just a name. */
- + OUT gctUINT32 physical;
- +
- + /* Logical address of allocation. */
- + OUT gctUINT64 logical;
- + }
- + AllocateNonPagedMemory;
- +
- + /* gcvHAL_FREE_NON_PAGED_MEMORY */
- + struct _gcsHAL_FREE_NON_PAGED_MEMORY
- + {
- + /* Number of bytes allocated. */
- + IN gctUINT64 bytes;
- +
- + /* Physical address of allocation. Just a name. */
- + IN gctUINT32 physical;
- +
- + /* Logical address of allocation. */
- + IN gctUINT64 logical;
- + }
- + FreeNonPagedMemory;
- +
- + /* gcvHAL_ALLOCATE_NON_PAGED_MEMORY */
- + struct _gcsHAL_ALLOCATE_VIRTUAL_COMMAND_BUFFER
- + {
- + /* Number of bytes to allocate. */
- + IN OUT gctUINT64 bytes;
- +
- + /* Physical address of allocation. Just a name. */
- + OUT gctUINT32 physical;
- +
- + /* Logical address of allocation. */
- + OUT gctUINT64 logical;
- + }
- + AllocateVirtualCommandBuffer;
- +
- + /* gcvHAL_FREE_NON_PAGED_MEMORY */
- + struct _gcsHAL_FREE_VIRTUAL_COMMAND_BUFFER
- + {
- + /* Number of bytes allocated. */
- + IN gctUINT64 bytes;
- +
- + /* Physical address of allocation. Just a name. */
- + IN gctUINT32 physical;
- +
- + /* Logical address of allocation. */
- + IN gctUINT64 logical;
- + }
- + FreeVirtualCommandBuffer;
- +
- + /* gcvHAL_EVENT_COMMIT. */
- + struct _gcsHAL_EVENT_COMMIT
- + {
- + /* Event queue in gcsQUEUE. */
- + IN gctUINT64 queue;
- + }
- + Event;
- +
- + /* gcvHAL_COMMIT */
- + struct _gcsHAL_COMMIT
- + {
- + /* Context buffer object gckCONTEXT. */
- + IN gctUINT64 context;
- +
- + /* Command buffer gcoCMDBUF. */
- + IN gctUINT64 commandBuffer;
- +
- + /* State delta buffer in gcsSTATE_DELTA. */
- + gctUINT64 delta;
- +
- + /* Event queue in gcsQUEUE. */
- + IN gctUINT64 queue;
- + }
- + Commit;
- +
- + /* gcvHAL_MAP_USER_MEMORY */
- + struct _gcsHAL_MAP_USER_MEMORY
- + {
- + /* Base address of user memory to map. */
- + IN gctUINT64 memory;
- +
- + /* Physical address of user memory to map. */
- + IN gctUINT32 physical;
- +
- + /* Size of user memory in bytes to map. */
- + IN gctUINT64 size;
- +
- + /* Info record required by gcvHAL_UNMAP_USER_MEMORY. Just a name. */
- + OUT gctUINT32 info;
- +
- + /* Physical address of mapped memory. */
- + OUT gctUINT32 address;
- + }
- + MapUserMemory;
- +
- + /* gcvHAL_UNMAP_USER_MEMORY */
- + struct _gcsHAL_UNMAP_USER_MEMORY
- + {
- + /* Base address of user memory to unmap. */
- + IN gctUINT64 memory;
- +
- + /* Size of user memory in bytes to unmap. */
- + IN gctUINT64 size;
- +
- + /* Info record returned by gcvHAL_MAP_USER_MEMORY. Just a name. */
- + IN gctUINT32 info;
- +
- + /* Physical address of mapped memory as returned by
- + gcvHAL_MAP_USER_MEMORY. */
- + IN gctUINT32 address;
- + }
- + UnmapUserMemory;
- +#if !USE_NEW_LINUX_SIGNAL
- + /* gcsHAL_USER_SIGNAL */
- + struct _gcsHAL_USER_SIGNAL
- + {
- + /* Command. */
- + gceUSER_SIGNAL_COMMAND_CODES command;
- +
- + /* Signal ID. */
- + IN OUT gctINT id;
- +
- + /* Reset mode. */
- + IN gctBOOL manualReset;
- +
- + /* Wait timedout. */
- + IN gctUINT32 wait;
- +
- + /* State. */
- + IN gctBOOL state;
- + }
- + UserSignal;
- +#endif
- +
- + /* gcvHAL_SIGNAL. */
- + struct _gcsHAL_SIGNAL
- + {
- + /* Signal handle to signal gctSIGNAL. */
- + IN gctUINT64 signal;
- +
- + /* Reserved gctSIGNAL. */
- + IN gctUINT64 auxSignal;
- +
- + /* Process owning the signal gctHANDLE. */
- + IN gctUINT64 process;
- +
- +#if defined(__QNXNTO__)
- + /* Client pulse side-channel connection ID. Set by client in gcoOS_CreateSignal. */
- + IN gctINT32 coid;
- +
- + /* Set by server. */
- + IN gctINT32 rcvid;
- +#endif
- + /* Event generated from where of pipeline */
- + IN gceKERNEL_WHERE fromWhere;
- + }
- + Signal;
- +
- + /* gcvHAL_WRITE_DATA. */
- + struct _gcsHAL_WRITE_DATA
- + {
- + /* Address to write data to. */
- + IN gctUINT32 address;
- +
- + /* Data to write. */
- + IN gctUINT32 data;
- + }
- + WriteData;
- +
- + /* gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY */
- + struct _gcsHAL_ALLOCATE_CONTIGUOUS_MEMORY
- + {
- + /* Number of bytes to allocate. */
- + IN OUT gctUINT64 bytes;
- +
- + /* Hardware address of allocation. */
- + OUT gctUINT32 address;
- +
- + /* Physical address of allocation. Just a name. */
- + OUT gctUINT32 physical;
- +
- + /* Logical address of allocation. */
- + OUT gctUINT64 logical;
- + }
- + AllocateContiguousMemory;
- +
- + /* gcvHAL_FREE_CONTIGUOUS_MEMORY */
- + struct _gcsHAL_FREE_CONTIGUOUS_MEMORY
- + {
- + /* Number of bytes allocated. */
- + IN gctUINT64 bytes;
- +
- + /* Physical address of allocation. Just a name. */
- + IN gctUINT32 physical;
- +
- + /* Logical address of allocation. */
- + IN gctUINT64 logical;
- + }
- + FreeContiguousMemory;
- +
- + /* gcvHAL_READ_REGISTER */
- + struct _gcsHAL_READ_REGISTER
- + {
- + /* Logical address of memory to write data to. */
- + IN gctUINT32 address;
- +
- + /* Data read. */
- + OUT gctUINT32 data;
- + }
- + ReadRegisterData;
- +
- + /* gcvHAL_WRITE_REGISTER */
- + struct _gcsHAL_WRITE_REGISTER
- + {
- + /* Logical address of memory to write data to. */
- + IN gctUINT32 address;
- +
- + /* Data read. */
- + IN gctUINT32 data;
- + }
- + WriteRegisterData;
- +
- +#if VIVANTE_PROFILER
- + /* gcvHAL_GET_PROFILE_SETTING */
- + struct _gcsHAL_GET_PROFILE_SETTING
- + {
- + /* Enable profiling */
- + OUT gctBOOL enable;
- +
- + /* The profile file name */
- + OUT gctCHAR fileName[gcdMAX_PROFILE_FILE_NAME];
- + }
- + GetProfileSetting;
- +
- + /* gcvHAL_SET_PROFILE_SETTING */
- + struct _gcsHAL_SET_PROFILE_SETTING
- + {
- + /* Enable profiling */
- + IN gctBOOL enable;
- +
- + /* The profile file name */
- + IN gctCHAR fileName[gcdMAX_PROFILE_FILE_NAME];
- + }
- + SetProfileSetting;
- +
- +#if VIVANTE_PROFILER_PERDRAW
- + /* gcvHAL_READ_PROFILER_REGISTER_SETTING */
- + struct _gcsHAL_READ_PROFILER_REGISTER_SETTING
- + {
- + /*Should Clear Register*/
- + IN gctBOOL bclear;
- + }
- + SetProfilerRegisterClear;
- +#endif
- +
- + /* gcvHAL_READ_ALL_PROFILE_REGISTERS */
- + struct _gcsHAL_READ_ALL_PROFILE_REGISTERS
- + {
- +#if VIVANTE_PROFILER_CONTEXT
- + /* Context buffer object gckCONTEXT. Just a name. */
- + IN gctUINT32 context;
- +#endif
- + /* Data read. */
- + OUT gcsPROFILER_COUNTERS counters;
- + }
- + RegisterProfileData;
- +
- + /* gcvHAL_PROFILE_REGISTERS_2D */
- + struct _gcsHAL_PROFILE_REGISTERS_2D
- + {
- + /* Data read in gcs2D_PROFILE. */
- + OUT gctUINT64 hwProfile2D;
- + }
- + RegisterProfileData2D;
- +#endif
- + /* Power management. */
- + /* gcvHAL_SET_POWER_MANAGEMENT_STATE */
- + struct _gcsHAL_SET_POWER_MANAGEMENT
- + {
- + /* Data read. */
- + IN gceCHIPPOWERSTATE state;
- + }
- + SetPowerManagement;
- +
- + /* gcvHAL_QUERY_POWER_MANAGEMENT_STATE */
- + struct _gcsHAL_QUERY_POWER_MANAGEMENT
- + {
- + /* Data read. */
- + OUT gceCHIPPOWERSTATE state;
- +
- + /* Idle query. */
- + OUT gctBOOL isIdle;
- + }
- + QueryPowerManagement;
- +
- + /* gcvHAL_QUERY_KERNEL_SETTINGS */
- + struct _gcsHAL_QUERY_KERNEL_SETTINGS
- + {
- + /* Settings.*/
- + OUT gcsKERNEL_SETTINGS settings;
- + }
- + QueryKernelSettings;
- +
- + /* gcvHAL_MAP_PHYSICAL */
- + struct _gcsHAL_MAP_PHYSICAL
- + {
- + /* gcvTRUE to map, gcvFALSE to unmap. */
- + IN gctBOOL map;
- +
- + /* Physical address. */
- + IN OUT gctUINT64 physical;
- + }
- + MapPhysical;
- +
- + /* gcvHAL_DEBUG */
- + struct _gcsHAL_DEBUG
- + {
- + /* If gcvTRUE, set the debug information. */
- + IN gctBOOL set;
- + IN gctUINT32 level;
- + IN gctUINT32 zones;
- + IN gctBOOL enable;
- +
- + IN gceDEBUG_MESSAGE_TYPE type;
- + IN gctUINT32 messageSize;
- +
- + /* Message to print if not empty. */
- + IN gctCHAR message[80];
- + }
- + Debug;
- +
- + /* gcvHAL_CACHE */
- + struct _gcsHAL_CACHE
- + {
- + IN gceCACHEOPERATION operation;
- + /* gctHANDLE */
- + IN gctUINT64 process;
- + IN gctUINT64 logical;
- + IN gctUINT64 bytes;
- + /* gcuVIDMEM_NODE_PTR */
- + IN gctUINT64 node;
- + }
- + Cache;
- +
- + /* gcvHAL_TIMESTAMP */
- + struct _gcsHAL_TIMESTAMP
- + {
- + /* Timer select. */
- + IN gctUINT32 timer;
- +
- + /* Timer request type (0-stop, 1-start, 2-send delta). */
- + IN gctUINT32 request;
- +
- + /* Result of delta time in microseconds. */
- + OUT gctINT32 timeDelta;
- + }
- + TimeStamp;
- +
- + /* gcvHAL_DATABASE */
- + struct _gcsHAL_DATABASE
- + {
- + /* Set to gcvTRUE if you want to query a particular process ID.
- + ** Set to gcvFALSE to query the last detached process. */
- + IN gctBOOL validProcessID;
- +
- + /* Process ID to query. */
- + IN gctUINT32 processID;
- +
- + /* Information. */
- + OUT gcuDATABASE_INFO vidMem;
- + OUT gcuDATABASE_INFO nonPaged;
- + OUT gcuDATABASE_INFO contiguous;
- + OUT gcuDATABASE_INFO gpuIdle;
- + }
- + Database;
- +
- + /* gcvHAL_VIDMEM_DATABASE */
- + struct _gcsHAL_VIDMEM_DATABASE
- + {
- + /* Set to gcvTRUE if you want to query a particular process ID.
- + ** Set to gcvFALSE to query the last detached process. */
- + IN gctBOOL validProcessID;
- +
- + /* Process ID to query. */
- + IN gctUINT32 processID;
- +
- + /* Information. */
- + OUT gcuDATABASE_INFO vidMemResv;
- + OUT gcuDATABASE_INFO vidMemCont;
- + OUT gcuDATABASE_INFO vidMemVirt;
- + }
- + VidMemDatabase;
- +
- + /* gcvHAL_VERSION */
- + struct _gcsHAL_VERSION
- + {
- + /* Major version: N.n.n. */
- + OUT gctINT32 major;
- +
- + /* Minor version: n.N.n. */
- + OUT gctINT32 minor;
- +
- + /* Patch version: n.n.N. */
- + OUT gctINT32 patch;
- +
- + /* Build version. */
- + OUT gctUINT32 build;
- + }
- + Version;
- +
- + /* gcvHAL_CHIP_INFO */
- + struct _gcsHAL_CHIP_INFO
- + {
- + /* Chip count. */
- + OUT gctINT32 count;
- +
- + /* Chip types. */
- + OUT gceHARDWARE_TYPE types[gcdCHIP_COUNT];
- + }
- + ChipInfo;
- +
- + /* gcvHAL_ATTACH */
- + struct _gcsHAL_ATTACH
- + {
- + /* Context buffer object gckCONTEXT. Just a name. */
- + OUT gctUINT32 context;
- +
- + /* Number of states in the buffer. */
- + OUT gctUINT64 stateCount;
- + }
- + Attach;
- +
- + /* gcvHAL_DETACH */
- + struct _gcsHAL_DETACH
- + {
- + /* Context buffer object gckCONTEXT. Just a name. */
- + IN gctUINT32 context;
- + }
- + Detach;
- +
- + /* gcvHAL_COMPOSE. */
- + gcsHAL_COMPOSE Compose;
- +
- + /* gcvHAL_GET_FRAME_INFO. */
- + struct _gcsHAL_GET_FRAME_INFO
- + {
- + /* gcsHAL_FRAME_INFO* */
- + OUT gctUINT64 frameInfo;
- + }
- + GetFrameInfo;
- +
- + /* gcvHAL_SET_TIME_OUT. */
- + struct _gcsHAL_SET_TIMEOUT
- + {
- + gctUINT32 timeOut;
- + }
- + SetTimeOut;
- +
- +#if gcdENABLE_VG
- + /* gcvHAL_COMMIT */
- + struct _gcsHAL_VGCOMMIT
- + {
- + /* Context buffer in gcsVGCONTEXT. */
- + IN gctUINT64 context;
- +
- + /* Command queue in gcsVGCMDQUEUE. */
- + IN gctUINT64 queue;
- +
- + /* Number of entries in the queue. */
- + IN gctUINT entryCount;
- +
- + /* Task table in gcsTASK_MASTER_TABLE. */
- + IN gctUINT64 taskTable;
- + }
- + VGCommit;
- +
- + /* gcvHAL_QUERY_COMMAND_BUFFER */
- + struct _gcsHAL_QUERY_COMMAND_BUFFER
- + {
- + /* Command buffer attributes. */
- + OUT gcsCOMMAND_BUFFER_INFO information;
- + }
- + QueryCommandBuffer;
- +
- +#endif
- +
- + struct _gcsHAL_GET_SHARED_INFO
- + {
- + /* Process id. */
- + IN gctUINT32 pid;
- +
- + /* Data id. */
- + IN gctUINT32 dataId;
- +
- + /* Data size. */
- + IN gctSIZE_T bytes;
- +
- + /* Pointer to save the shared data. */
- + OUT gctPOINTER data;
- + }
- + GetSharedInfo;
- +
- + struct _gcsHAL_SET_SHARED_INFO
- + {
- + /* Data id. */
- + IN gctUINT32 dataId;
- +
- + /* Data to be shared. */
- + IN gctPOINTER data;
- +
- + /* Data size. */
- + IN gctSIZE_T bytes;
- + }
- + SetSharedInfo;
- +
- + struct _gcsHAL_SET_FSCALE_VALUE
- + {
- + IN gctUINT value;
- + }
- + SetFscaleValue;
- +
- + struct _gcsHAL_GET_FSCALE_VALUE
- + {
- + OUT gctUINT value;
- + OUT gctUINT minValue;
- + OUT gctUINT maxValue;
- + }
- + GetFscaleValue;
- +
- + struct _gcsHAL_QUERY_RESET_TIME_STAMP
- + {
- + OUT gctUINT64 timeStamp;
- + }
- + QueryResetTimeStamp;
- +
- + struct _gcsHAL_SYNC_POINT
- + {
- + /* Command. */
- + gceSYNC_POINT_COMMAND_CODES command;
- +
- + /* Sync point. */
- + IN OUT gctUINT64 syncPoint;
- +
- + /* From where. */
- + IN gceKERNEL_WHERE fromWhere;
- +
- + /* Signaled state. */
- + OUT gctBOOL state;
- + }
- + SyncPoint;
- +
- + struct _gcsHAL_CREATE_NATIVE_FENCE
- + {
- + /* Signal id to dup. */
- + IN gctUINT64 syncPoint;
- +
- + /* Native fence file descriptor. */
- + OUT gctINT fenceFD;
- +
- + }
- + CreateNativeFence;
- + }
- + u;
- +}
- +gcsHAL_INTERFACE;
- +
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* __gc_hal_driver_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver_vg.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver_vg.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver_vg.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver_vg.h 2015-03-08 14:27:37.641684501 -0500
- @@ -0,0 +1,270 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_driver_vg_h_
- +#define __gc_hal_driver_vg_h_
- +
- +
- +
- +#include "gc_hal_types.h"
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +/******************************************************************************\
- +******************************* I/O Control Codes ******************************
- +\******************************************************************************/
- +
- +#define gcvHAL_CLASS "galcore"
- +#define IOCTL_GCHAL_INTERFACE 30000
- +
- +/******************************************************************************\
- +********************************* Command Codes ********************************
- +\******************************************************************************/
- +
- +/******************************************************************************\
- +********************* Command buffer information structure. ********************
- +\******************************************************************************/
- +
- +typedef struct _gcsCOMMAND_BUFFER_INFO * gcsCOMMAND_BUFFER_INFO_PTR;
- +typedef struct _gcsCOMMAND_BUFFER_INFO
- +{
- + /* FE command buffer interrupt ID. */
- + gctINT32 feBufferInt;
- +
- + /* TS overflow interrupt ID. */
- + gctINT32 tsOverflowInt;
- +
- + /* Alignment and mask for the buffer address. */
- + gctUINT addressMask;
- + gctSIZE_T addressAlignment;
- +
- + /* Alignment for each command. */
- + gctSIZE_T commandAlignment;
- +
- + /* Number of bytes required by the STATE command. */
- + gctSIZE_T stateCommandSize;
- +
- + /* Number of bytes required by the RESTART command. */
- + gctSIZE_T restartCommandSize;
- +
- + /* Number of bytes required by the FETCH command. */
- + gctSIZE_T fetchCommandSize;
- +
- + /* Number of bytes required by the CALL command. */
- + gctSIZE_T callCommandSize;
- +
- + /* Number of bytes required by the RETURN command. */
- + gctSIZE_T returnCommandSize;
- +
- + /* Number of bytes required by the EVENT command. */
- + gctSIZE_T eventCommandSize;
- +
- + /* Number of bytes required by the END command. */
- + gctSIZE_T endCommandSize;
- +
- + /* Number of bytes reserved at the tail of a static command buffer. */
- + gctSIZE_T staticTailSize;
- +
- + /* Number of bytes reserved at the tail of a dynamic command buffer. */
- + gctSIZE_T dynamicTailSize;
- +}
- +gcsCOMMAND_BUFFER_INFO;
- +
- +/******************************************************************************\
- +******************************** Task Structures *******************************
- +\******************************************************************************/
- +
- +typedef enum _gceTASK
- +{
- + gcvTASK_LINK,
- + gcvTASK_CLUSTER,
- + gcvTASK_INCREMENT,
- + gcvTASK_DECREMENT,
- + gcvTASK_SIGNAL,
- + gcvTASK_LOCKDOWN,
- + gcvTASK_UNLOCK_VIDEO_MEMORY,
- + gcvTASK_FREE_VIDEO_MEMORY,
- + gcvTASK_FREE_CONTIGUOUS_MEMORY,
- + gcvTASK_UNMAP_USER_MEMORY
- +}
- +gceTASK;
- +
- +typedef struct _gcsTASK_HEADER * gcsTASK_HEADER_PTR;
- +typedef struct _gcsTASK_HEADER
- +{
- + /* Task ID. */
- + IN gceTASK id;
- +}
- +gcsTASK_HEADER;
- +
- +typedef struct _gcsTASK_LINK * gcsTASK_LINK_PTR;
- +typedef struct _gcsTASK_LINK
- +{
- + /* Task ID (gcvTASK_LINK). */
- + IN gceTASK id;
- +
- + /* Pointer to the next task container. */
- + IN gctPOINTER cotainer;
- +
- + /* Pointer to the next task from the next task container. */
- + IN gcsTASK_HEADER_PTR task;
- +}
- +gcsTASK_LINK;
- +
- +typedef struct _gcsTASK_CLUSTER * gcsTASK_CLUSTER_PTR;
- +typedef struct _gcsTASK_CLUSTER
- +{
- + /* Task ID (gcvTASK_CLUSTER). */
- + IN gceTASK id;
- +
- + /* Number of tasks in the cluster. */
- + IN gctUINT taskCount;
- +}
- +gcsTASK_CLUSTER;
- +
- +typedef struct _gcsTASK_INCREMENT * gcsTASK_INCREMENT_PTR;
- +typedef struct _gcsTASK_INCREMENT
- +{
- + /* Task ID (gcvTASK_INCREMENT). */
- + IN gceTASK id;
- +
- + /* Address of the variable to increment. */
- + IN gctUINT32 address;
- +}
- +gcsTASK_INCREMENT;
- +
- +typedef struct _gcsTASK_DECREMENT * gcsTASK_DECREMENT_PTR;
- +typedef struct _gcsTASK_DECREMENT
- +{
- + /* Task ID (gcvTASK_DECREMENT). */
- + IN gceTASK id;
- +
- + /* Address of the variable to decrement. */
- + IN gctUINT32 address;
- +}
- +gcsTASK_DECREMENT;
- +
- +typedef struct _gcsTASK_SIGNAL * gcsTASK_SIGNAL_PTR;
- +typedef struct _gcsTASK_SIGNAL
- +{
- + /* Task ID (gcvTASK_SIGNAL). */
- + IN gceTASK id;
- +
- + /* Process owning the signal. */
- + IN gctHANDLE process;
- +
- + /* Signal handle to signal. */
- + IN gctSIGNAL signal;
- +
- +#if defined(__QNXNTO__)
- + IN gctINT32 coid;
- + IN gctINT32 rcvid;
- +#endif
- +}
- +gcsTASK_SIGNAL;
- +
- +typedef struct _gcsTASK_LOCKDOWN * gcsTASK_LOCKDOWN_PTR;
- +typedef struct _gcsTASK_LOCKDOWN
- +{
- + /* Task ID (gcvTASK_LOCKDOWN). */
- + IN gceTASK id;
- +
- + /* Address of the user space counter. */
- + IN gctUINT32 userCounter;
- +
- + /* Address of the kernel space counter. */
- + IN gctUINT32 kernelCounter;
- +
- + /* Process owning the signal. */
- + IN gctHANDLE process;
- +
- + /* Signal handle to signal. */
- + IN gctSIGNAL signal;
- +}
- +gcsTASK_LOCKDOWN;
- +
- +typedef struct _gcsTASK_UNLOCK_VIDEO_MEMORY * gcsTASK_UNLOCK_VIDEO_MEMORY_PTR;
- +typedef struct _gcsTASK_UNLOCK_VIDEO_MEMORY
- +{
- + /* Task ID (gcvTASK_UNLOCK_VIDEO_MEMORY). */
- + IN gceTASK id;
- +
- + /* Allocated video memory. */
- + IN gctUINT64 node;
- +}
- +gcsTASK_UNLOCK_VIDEO_MEMORY;
- +
- +typedef struct _gcsTASK_FREE_VIDEO_MEMORY * gcsTASK_FREE_VIDEO_MEMORY_PTR;
- +typedef struct _gcsTASK_FREE_VIDEO_MEMORY
- +{
- + /* Task ID (gcvTASK_FREE_VIDEO_MEMORY). */
- + IN gceTASK id;
- +
- + /* Allocated video memory. */
- + IN gctUINT64 node;
- +}
- +gcsTASK_FREE_VIDEO_MEMORY;
- +
- +typedef struct _gcsTASK_FREE_CONTIGUOUS_MEMORY * gcsTASK_FREE_CONTIGUOUS_MEMORY_PTR;
- +typedef struct _gcsTASK_FREE_CONTIGUOUS_MEMORY
- +{
- + /* Task ID (gcvTASK_FREE_CONTIGUOUS_MEMORY). */
- + IN gceTASK id;
- +
- + /* Number of bytes allocated. */
- + IN gctSIZE_T bytes;
- +
- + /* Physical address of allocation. */
- + IN gctPHYS_ADDR physical;
- +
- + /* Logical address of allocation. */
- + IN gctPOINTER logical;
- +}
- +gcsTASK_FREE_CONTIGUOUS_MEMORY;
- +
- +typedef struct _gcsTASK_UNMAP_USER_MEMORY * gcsTASK_UNMAP_USER_MEMORY_PTR;
- +typedef struct _gcsTASK_UNMAP_USER_MEMORY
- +{
- + /* Task ID (gcvTASK_UNMAP_USER_MEMORY). */
- + IN gceTASK id;
- +
- + /* Base address of user memory to unmap. */
- + IN gctPOINTER memory;
- +
- + /* Size of user memory in bytes to unmap. */
- + IN gctSIZE_T size;
- +
- + /* Info record returned by gcvHAL_MAP_USER_MEMORY. */
- + IN gctPOINTER info;
- +
- + /* Physical address of mapped memory as returned by
- + gcvHAL_MAP_USER_MEMORY. */
- + IN gctUINT32 address;
- +}
- +gcsTASK_UNMAP_USER_MEMORY;
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* __gc_hal_driver_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_dump.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_dump.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_dump.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_dump.h 2015-03-08 14:27:37.645684500 -0500
- @@ -0,0 +1,88 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_dump_h_
- +#define __gc_hal_dump_h_
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +/*
- +** FILE LAYOUT:
- +**
- +** gcsDUMP_FILE structure
- +**
- +** gcsDUMP_DATA frame
- +** gcsDUMP_DATA or gcDUMP_DATA_SIZE records rendingring the frame
- +** gctUINT8 data[length]
- +*/
- +
- +#define gcvDUMP_FILE_SIGNATURE gcmCC('g','c','D','B')
- +
- +typedef struct _gcsDUMP_FILE
- +{
- + gctUINT32 signature; /* File signature */
- + gctSIZE_T length; /* Length of file */
- + gctUINT32 frames; /* Number of frames in file */
- +}
- +gcsDUMP_FILE;
- +
- +typedef enum _gceDUMP_TAG
- +{
- + gcvTAG_SURFACE = gcmCC('s','u','r','f'),
- + gcvTAG_FRAME = gcmCC('f','r','m',' '),
- + gcvTAG_COMMAND = gcmCC('c','m','d',' '),
- + gcvTAG_INDEX = gcmCC('i','n','d','x'),
- + gcvTAG_STREAM = gcmCC('s','t','r','m'),
- + gcvTAG_TEXTURE = gcmCC('t','e','x','t'),
- + gcvTAG_RENDER_TARGET = gcmCC('r','n','d','r'),
- + gcvTAG_DEPTH = gcmCC('z','b','u','f'),
- + gcvTAG_RESOLVE = gcmCC('r','s','l','v'),
- + gcvTAG_DELETE = gcmCC('d','e','l',' '),
- +}
- +gceDUMP_TAG;
- +
- +typedef struct _gcsDUMP_SURFACE
- +{
- + gceDUMP_TAG type; /* Type of record. */
- + gctUINT32 address; /* Address of the surface. */
- + gctINT16 width; /* Width of surface. */
- + gctINT16 height; /* Height of surface. */
- + gceSURF_FORMAT format; /* Surface pixel format. */
- + gctSIZE_T length; /* Number of bytes inside the surface. */
- +}
- +gcsDUMP_SURFACE;
- +
- +typedef struct _gcsDUMP_DATA
- +{
- + gceDUMP_TAG type; /* Type of record. */
- + gctSIZE_T length; /* Number of bytes of data. */
- + gctUINT32 address; /* Address for the data. */
- +}
- +gcsDUMP_DATA;
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* __gc_hal_dump_h_ */
- +
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h 2015-03-08 14:27:37.645684500 -0500
- @@ -0,0 +1,627 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_eglplatform_h_
- +#define __gc_hal_eglplatform_h_
- +
- +/* Include VDK types. */
- +#include "gc_hal_types.h"
- +#include "gc_hal_base.h"
- +#include "gc_hal_eglplatform_type.h"
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +
- +#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
- +/* Win32 and Windows CE platforms. */
- +#include <windows.h>
- +typedef HDC HALNativeDisplayType;
- +typedef HWND HALNativeWindowType;
- +typedef HBITMAP HALNativePixmapType;
- +
- +typedef struct __BITFIELDINFO{
- + BITMAPINFO bmi;
- + RGBQUAD bmiColors[2];
- +} BITFIELDINFO;
- +
- +#elif defined(LINUX) && defined(EGL_API_DFB) && !defined(__APPLE__)
- +#include <directfb.h>
- +typedef struct _DFBDisplay * HALNativeDisplayType;
- +typedef struct _DFBWindow * HALNativeWindowType;
- +typedef struct _DFBPixmap * HALNativePixmapType;
- +
- +#elif defined(LINUX) && defined(EGL_API_FB) && !defined(__APPLE__)
- +
- +#if defined(EGL_API_WL)
- +/* Wayland platform. */
- +#include "wayland-server.h"
- +#include <wayland-egl.h>
- +
- +#define WL_EGL_NUM_BACKBUFFERS 3
- +
- +typedef struct _gcsWL_VIV_BUFFER
- +{
- + struct wl_resource *wl_buffer;
- + gcoSURF surface;
- + gctINT32 width, height;
- +} gcsWL_VIV_BUFFER;
- +
- +typedef struct _gcsWL_EGL_DISPLAY
- +{
- + struct wl_display* wl_display;
- + struct wl_viv* wl_viv;
- + struct wl_registry *registry;
- + struct wl_event_queue *wl_queue;
- +} gcsWL_EGL_DISPLAY;
- +
- +typedef struct _gcsWL_EGL_BUFFER_INFO
- +{
- + gctINT32 width;
- + gctINT32 height;
- + gctINT32 stride;
- + gceSURF_FORMAT format;
- + gcuVIDMEM_NODE_PTR node;
- + gcePOOL pool;
- + gctUINT bytes;
- + gcoSURF surface;
- + gcoSURF attached_surface;
- + gctINT32 invalidate;
- + gctBOOL locked;
- +} gcsWL_EGL_BUFFER_INFO;
- +
- +typedef struct _gcsWL_EGL_BUFFER
- +{
- + struct wl_buffer* wl_buffer;
- + gcsWL_EGL_BUFFER_INFO info;
- +} gcsWL_EGL_BUFFER;
- +
- +typedef struct _gcsWL_EGL_WINDOW_INFO
- +{
- + gctINT32 dx;
- + gctINT32 dy;
- + gctUINT width;
- + gctUINT height;
- + gctINT32 attached_width;
- + gctINT32 attached_height;
- + gceSURF_FORMAT format;
- + gctUINT bpp;
- +} gcsWL_EGL_WINDOW_INFO;
- +
- +struct wl_egl_window
- +{
- + gcsWL_EGL_DISPLAY* display;
- + gcsWL_EGL_BUFFER backbuffers[WL_EGL_NUM_BACKBUFFERS];
- + gcsWL_EGL_WINDOW_INFO info;
- + gctUINT current;
- + struct wl_surface* surface;
- + struct wl_callback* frame_callback;
- +};
- +
- +typedef void* HALNativeDisplayType;
- +typedef void* HALNativeWindowType;
- +typedef void* HALNativePixmapType;
- +#else
- +/* Linux platform for FBDEV. */
- +typedef struct _FBDisplay * HALNativeDisplayType;
- +typedef struct _FBWindow * HALNativeWindowType;
- +typedef struct _FBPixmap * HALNativePixmapType;
- +#endif
- +#elif defined(__ANDROID__) || defined(ANDROID)
- +
- +struct egl_native_pixmap_t;
- +
- +#if ANDROID_SDK_VERSION >= 9
- + #include <android/native_window.h>
- +
- + typedef struct ANativeWindow* HALNativeWindowType;
- + typedef struct egl_native_pixmap_t* HALNativePixmapType;
- + typedef void* HALNativeDisplayType;
- +#else
- + struct android_native_window_t;
- + typedef struct android_native_window_t* HALNativeWindowType;
- + typedef struct egl_native_pixmap_t * HALNativePixmapType;
- + typedef void* HALNativeDisplayType;
- +#endif
- +
- +#elif defined(LINUX) || defined(__APPLE__)
- +/* X11 platform. */
- +#include <X11/Xlib.h>
- +#include <X11/Xutil.h>
- +
- +typedef Display * HALNativeDisplayType;
- +typedef Window HALNativeWindowType;
- +
- +#ifdef CUSTOM_PIXMAP
- +typedef void * HALNativePixmapType;
- +#else
- +typedef Pixmap HALNativePixmapType;
- +#endif /* CUSTOM_PIXMAP */
- +
- +/* Rename some badly named X defines. */
- +#ifdef Status
- +# define XStatus int
- +# undef Status
- +#endif
- +#ifdef Always
- +# define XAlways 2
- +# undef Always
- +#endif
- +#ifdef CurrentTime
- +# undef CurrentTime
- +# define XCurrentTime 0
- +#endif
- +
- +#elif defined(__QNXNTO__)
- +#include <screen/screen.h>
- +
- +/* VOID */
- +typedef int HALNativeDisplayType;
- +typedef screen_window_t HALNativeWindowType;
- +typedef screen_pixmap_t HALNativePixmapType;
- +
- +#else
- +
- +#error "Platform not recognized"
- +
- +/* VOID */
- +typedef void * HALNativeDisplayType;
- +typedef void * HALNativeWindowType;
- +typedef void * HALNativePixmapType;
- +
- +#endif
- +
- +/* define DUMMY according to the system */
- +#if defined(EGL_API_WL)
- +# define WL_DUMMY (31415926)
- +# define EGL_DUMMY WL_DUMMY
- +#elif defined(__ANDROID__) || defined(ANDROID)
- +# define ANDROID_DUMMY (31415926)
- +# define EGL_DUMMY ANDROID_DUMMY
- +#else
- +# define EGL_DUMMY (31415926)
- +#endif
- +
- +/*******************************************************************************
- +** Display. ********************************************************************
- +*/
- +
- +gceSTATUS
- +gcoOS_GetDisplay(
- + OUT HALNativeDisplayType * Display,
- + IN gctPOINTER Context
- + );
- +
- +gceSTATUS
- +gcoOS_GetDisplayByIndex(
- + IN gctINT DisplayIndex,
- + OUT HALNativeDisplayType * Display,
- + IN gctPOINTER Context
- + );
- +
- +gceSTATUS
- +gcoOS_GetDisplayInfo(
- + IN HALNativeDisplayType Display,
- + OUT gctINT * Width,
- + OUT gctINT * Height,
- + OUT gctSIZE_T * Physical,
- + OUT gctINT * Stride,
- + OUT gctINT * BitsPerPixel
- + );
- +
- +
- +
- +gceSTATUS
- +gcoOS_GetDisplayInfoEx(
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window,
- + IN gctUINT DisplayInfoSize,
- + OUT halDISPLAY_INFO * DisplayInfo
- + );
- +
- +gceSTATUS
- +gcoOS_GetNextDisplayInfoExByIndex(
- + IN gctINT Index,
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window,
- + IN gctUINT DisplayInfoSize,
- + OUT halDISPLAY_INFO * DisplayInfo
- + );
- +
- +gceSTATUS
- +gcoOS_GetDisplayVirtual(
- + IN HALNativeDisplayType Display,
- + OUT gctINT * Width,
- + OUT gctINT * Height
- + );
- +
- +gceSTATUS
- +gcoOS_GetDisplayBackbuffer(
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window,
- + OUT gctPOINTER * context,
- + OUT gcoSURF * surface,
- + OUT gctUINT * Offset,
- + OUT gctINT * X,
- + OUT gctINT * Y
- + );
- +
- +gceSTATUS
- +gcoOS_SetDisplayVirtual(
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window,
- + IN gctUINT Offset,
- + IN gctINT X,
- + IN gctINT Y
- + );
- +
- +gceSTATUS
- +gcoOS_SetDisplayVirtualEx(
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window,
- + IN gctPOINTER Context,
- + IN gcoSURF Surface,
- + IN gctUINT Offset,
- + IN gctINT X,
- + IN gctINT Y
- + );
- +
- +gceSTATUS
- +gcoOS_SetSwapInterval(
- + IN HALNativeDisplayType Display,
- + IN gctINT Interval
- +);
- +
- +gceSTATUS
- +gcoOS_GetSwapInterval(
- + IN HALNativeDisplayType Display,
- + IN gctINT_PTR Min,
- + IN gctINT_PTR Max
- +);
- +
- +gceSTATUS
- +gcoOS_DisplayBufferRegions(
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window,
- + IN gctINT NumRects,
- + IN gctINT_PTR Rects
- + );
- +
- +gceSTATUS
- +gcoOS_DestroyDisplay(
- + IN HALNativeDisplayType Display
- + );
- +
- +gceSTATUS
- +gcoOS_InitLocalDisplayInfo(
- + IN HALNativeDisplayType Display,
- + IN OUT gctPOINTER * localDisplay
- + );
- +
- +gceSTATUS
- +gcoOS_DeinitLocalDisplayInfo(
- + IN HALNativeDisplayType Display,
- + IN OUT gctPOINTER * localDisplay
- + );
- +
- +gceSTATUS
- +gcoOS_GetDisplayInfoEx2(
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window,
- + IN gctPOINTER localDisplay,
- + IN gctUINT DisplayInfoSize,
- + OUT halDISPLAY_INFO * DisplayInfo
- + );
- +
- +gceSTATUS
- +gcoOS_GetDisplayBackbufferEx(
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window,
- + IN gctPOINTER localDisplay,
- + OUT gctPOINTER * context,
- + OUT gcoSURF * surface,
- + OUT gctUINT * Offset,
- + OUT gctINT * X,
- + OUT gctINT * Y
- + );
- +
- +gceSTATUS
- +gcoOS_IsValidDisplay(
- + IN HALNativeDisplayType Display
- + );
- +
- +gceSTATUS
- +gcoOS_GetNativeVisualId(
- + IN HALNativeDisplayType Display,
- + OUT gctINT* nativeVisualId
- + );
- +
- +gctBOOL
- +gcoOS_SynchronousFlip(
- + IN HALNativeDisplayType Display
- + );
- +
- +/*******************************************************************************
- +** Windows. ********************************************************************
- +*/
- +
- +gceSTATUS
- +gcoOS_CreateWindow(
- + IN HALNativeDisplayType Display,
- + IN gctINT X,
- + IN gctINT Y,
- + IN gctINT Width,
- + IN gctINT Height,
- + OUT HALNativeWindowType * Window
- + );
- +
- +gceSTATUS
- +gcoOS_GetWindowInfo(
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window,
- + OUT gctINT * X,
- + OUT gctINT * Y,
- + OUT gctINT * Width,
- + OUT gctINT * Height,
- + OUT gctINT * BitsPerPixel,
- + OUT gctUINT * Offset
- + );
- +
- +gceSTATUS
- +gcoOS_DestroyWindow(
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window
- + );
- +
- +gceSTATUS
- +gcoOS_DrawImage(
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window,
- + IN gctINT Left,
- + IN gctINT Top,
- + IN gctINT Right,
- + IN gctINT Bottom,
- + IN gctINT Width,
- + IN gctINT Height,
- + IN gctINT BitsPerPixel,
- + IN gctPOINTER Bits
- + );
- +
- +gceSTATUS
- +gcoOS_GetImage(
- + IN HALNativeWindowType Window,
- + IN gctINT Left,
- + IN gctINT Top,
- + IN gctINT Right,
- + IN gctINT Bottom,
- + OUT gctINT * BitsPerPixel,
- + OUT gctPOINTER * Bits
- + );
- +
- +gceSTATUS
- +gcoOS_GetWindowInfoEx(
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window,
- + OUT gctINT * X,
- + OUT gctINT * Y,
- + OUT gctINT * Width,
- + OUT gctINT * Height,
- + OUT gctINT * BitsPerPixel,
- + OUT gctUINT * Offset,
- + OUT gceSURF_FORMAT * Format
- + );
- +
- +gceSTATUS
- +gcoOS_DrawImageEx(
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window,
- + IN gctINT Left,
- + IN gctINT Top,
- + IN gctINT Right,
- + IN gctINT Bottom,
- + IN gctINT Width,
- + IN gctINT Height,
- + IN gctINT BitsPerPixel,
- + IN gctPOINTER Bits,
- + IN gceSURF_FORMAT Format
- + );
- +
- +/*******************************************************************************
- +** Pixmaps. ********************************************************************
- +*/
- +
- +gceSTATUS
- +gcoOS_CreatePixmap(
- + IN HALNativeDisplayType Display,
- + IN gctINT Width,
- + IN gctINT Height,
- + IN gctINT BitsPerPixel,
- + OUT HALNativePixmapType * Pixmap
- + );
- +
- +gceSTATUS
- +gcoOS_GetPixmapInfo(
- + IN HALNativeDisplayType Display,
- + IN HALNativePixmapType Pixmap,
- + OUT gctINT * Width,
- + OUT gctINT * Height,
- + OUT gctINT * BitsPerPixel,
- + OUT gctINT * Stride,
- + OUT gctPOINTER * Bits
- + );
- +
- +gceSTATUS
- +gcoOS_DrawPixmap(
- + IN HALNativeDisplayType Display,
- + IN HALNativePixmapType Pixmap,
- + IN gctINT Left,
- + IN gctINT Top,
- + IN gctINT Right,
- + IN gctINT Bottom,
- + IN gctINT Width,
- + IN gctINT Height,
- + IN gctINT BitsPerPixel,
- + IN gctPOINTER Bits
- + );
- +
- +gceSTATUS
- +gcoOS_DestroyPixmap(
- + IN HALNativeDisplayType Display,
- + IN HALNativePixmapType Pixmap
- + );
- +
- +gceSTATUS
- +gcoOS_GetPixmapInfoEx(
- + IN HALNativeDisplayType Display,
- + IN HALNativePixmapType Pixmap,
- + OUT gctINT * Width,
- + OUT gctINT * Height,
- + OUT gctINT * BitsPerPixel,
- + OUT gctINT * Stride,
- + OUT gctPOINTER * Bits,
- + OUT gceSURF_FORMAT * Format
- + );
- +
- +gceSTATUS
- +gcoOS_CopyPixmapBits(
- + IN HALNativeDisplayType Display,
- + IN HALNativePixmapType Pixmap,
- + IN gctUINT DstWidth,
- + IN gctUINT DstHeight,
- + IN gctINT DstStride,
- + IN gceSURF_FORMAT DstFormat,
- + OUT gctPOINTER DstBits
- + );
- +
- +/*******************************************************************************
- +** OS relative. ****************************************************************
- +*/
- +gceSTATUS
- +gcoOS_LoadEGLLibrary(
- + OUT gctHANDLE * Handle
- + );
- +
- +gceSTATUS
- +gcoOS_FreeEGLLibrary(
- + IN gctHANDLE Handle
- + );
- +
- +gceSTATUS
- +gcoOS_ShowWindow(
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window
- + );
- +
- +gceSTATUS
- +gcoOS_HideWindow(
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window
- + );
- +
- +gceSTATUS
- +gcoOS_SetWindowTitle(
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window,
- + IN gctCONST_STRING Title
- + );
- +
- +gceSTATUS
- +gcoOS_CapturePointer(
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window
- + );
- +
- +gceSTATUS
- +gcoOS_GetEvent(
- + IN HALNativeDisplayType Display,
- + IN HALNativeWindowType Window,
- + OUT halEvent * Event
- + );
- +
- +gceSTATUS
- +gcoOS_CreateClientBuffer(
- + IN gctINT Width,
- + IN gctINT Height,
- + IN gctINT Format,
- + IN gctINT Type,
- + OUT gctPOINTER * ClientBuffer
- + );
- +
- +gceSTATUS
- +gcoOS_GetClientBufferInfo(
- + IN gctPOINTER ClientBuffer,
- + OUT gctINT * Width,
- + OUT gctINT * Height,
- + OUT gctINT * Stride,
- + OUT gctPOINTER * Bits
- + );
- +
- +gceSTATUS
- +gcoOS_DestroyClientBuffer(
- + IN gctPOINTER ClientBuffer
- + );
- +
- +gceSTATUS
- +gcoOS_DestroyContext(
- + IN gctPOINTER Display,
- + IN gctPOINTER Context
- + );
- +
- +gceSTATUS
- +gcoOS_CreateContext(
- + IN gctPOINTER LocalDisplay,
- + IN gctPOINTER Context
- + );
- +
- +gceSTATUS
- +gcoOS_MakeCurrent(
- + IN gctPOINTER LocalDisplay,
- + IN HALNativeWindowType DrawDrawable,
- + IN HALNativeWindowType ReadDrawable,
- + IN gctPOINTER Context,
- + IN gcoSURF ResolveTarget
- + );
- +
- +gceSTATUS
- +gcoOS_CreateDrawable(
- + IN gctPOINTER LocalDisplay,
- + IN HALNativeWindowType Drawable
- + );
- +
- +gceSTATUS
- +gcoOS_DestroyDrawable(
- + IN gctPOINTER LocalDisplay,
- + IN HALNativeWindowType Drawable
- + );
- +gceSTATUS
- +gcoOS_SwapBuffers(
- + IN gctPOINTER LocalDisplay,
- + IN HALNativeWindowType Drawable,
- + IN gcoSURF RenderTarget,
- + IN gcoSURF ResolveTarget,
- + IN gctPOINTER ResolveBits,
- + OUT gctUINT *Width,
- + OUT gctUINT *Height
- + );
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* __gc_hal_eglplatform_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform_type.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform_type.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform_type.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform_type.h 2015-03-08 14:27:37.645684500 -0500
- @@ -0,0 +1,286 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_eglplatform_type_h_
- +#define __gc_hal_eglplatform_type_h_
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +/*******************************************************************************
- +** Events. *********************************************************************
- +*/
- +
- +typedef enum _halEventType
- +{
- + /* Keyboard event. */
- + HAL_KEYBOARD,
- +
- + /* Mouse move event. */
- + HAL_POINTER,
- +
- + /* Mouse button event. */
- + HAL_BUTTON,
- +
- + /* Application close event. */
- + HAL_CLOSE,
- +
- + /* Application window has been updated. */
- + HAL_WINDOW_UPDATE
- +}
- +halEventType;
- +
- +/* Scancodes for keyboard. */
- +typedef enum _halKeys
- +{
- + HAL_UNKNOWN = -1,
- +
- + HAL_BACKSPACE = 0x08,
- + HAL_TAB,
- + HAL_ENTER = 0x0D,
- + HAL_ESCAPE = 0x1B,
- +
- + HAL_SPACE = 0x20,
- + HAL_SINGLEQUOTE = 0x27,
- + HAL_PAD_ASTERISK = 0x2A,
- + HAL_COMMA = 0x2C,
- + HAL_HYPHEN,
- + HAL_PERIOD,
- + HAL_SLASH,
- + HAL_0,
- + HAL_1,
- + HAL_2,
- + HAL_3,
- + HAL_4,
- + HAL_5,
- + HAL_6,
- + HAL_7,
- + HAL_8,
- + HAL_9,
- + HAL_SEMICOLON = 0x3B,
- + HAL_EQUAL = 0x3D,
- + HAL_A = 0x41,
- + HAL_B,
- + HAL_C,
- + HAL_D,
- + HAL_E,
- + HAL_F,
- + HAL_G,
- + HAL_H,
- + HAL_I,
- + HAL_J,
- + HAL_K,
- + HAL_L,
- + HAL_M,
- + HAL_N,
- + HAL_O,
- + HAL_P,
- + HAL_Q,
- + HAL_R,
- + HAL_S,
- + HAL_T,
- + HAL_U,
- + HAL_V,
- + HAL_W,
- + HAL_X,
- + HAL_Y,
- + HAL_Z,
- + HAL_LBRACKET,
- + HAL_BACKSLASH,
- + HAL_RBRACKET,
- + HAL_BACKQUOTE = 0x60,
- +
- + HAL_F1 = 0x80,
- + HAL_F2,
- + HAL_F3,
- + HAL_F4,
- + HAL_F5,
- + HAL_F6,
- + HAL_F7,
- + HAL_F8,
- + HAL_F9,
- + HAL_F10,
- + HAL_F11,
- + HAL_F12,
- +
- + HAL_LCTRL,
- + HAL_RCTRL,
- + HAL_LSHIFT,
- + HAL_RSHIFT,
- + HAL_LALT,
- + HAL_RALT,
- + HAL_CAPSLOCK,
- + HAL_NUMLOCK,
- + HAL_SCROLLLOCK,
- + HAL_PAD_0,
- + HAL_PAD_1,
- + HAL_PAD_2,
- + HAL_PAD_3,
- + HAL_PAD_4,
- + HAL_PAD_5,
- + HAL_PAD_6,
- + HAL_PAD_7,
- + HAL_PAD_8,
- + HAL_PAD_9,
- + HAL_PAD_HYPHEN,
- + HAL_PAD_PLUS,
- + HAL_PAD_SLASH,
- + HAL_PAD_PERIOD,
- + HAL_PAD_ENTER,
- + HAL_SYSRQ,
- + HAL_PRNTSCRN,
- + HAL_BREAK,
- + HAL_UP,
- + HAL_LEFT,
- + HAL_RIGHT,
- + HAL_DOWN,
- + HAL_HOME,
- + HAL_END,
- + HAL_PGUP,
- + HAL_PGDN,
- + HAL_INSERT,
- + HAL_DELETE,
- + HAL_LWINDOW,
- + HAL_RWINDOW,
- + HAL_MENU,
- + HAL_POWER,
- + HAL_SLEEP,
- + HAL_WAKE
- +}
- +halKeys;
- +
- +/* Structure that defined keyboard mapping. */
- +typedef struct _halKeyMap
- +{
- + /* Normal key. */
- + halKeys normal;
- +
- + /* Extended key. */
- + halKeys extended;
- +}
- +halKeyMap;
- +
- +/* Event structure. */
- +typedef struct _halEvent
- +{
- + /* Event type. */
- + halEventType type;
- +
- + /* Event data union. */
- + union _halEventData
- + {
- + /* Event data for keyboard. */
- + struct _halKeyboard
- + {
- + /* Scancode. */
- + halKeys scancode;
- +
- + /* ASCII characte of the key pressed. */
- + char key;
- +
- + /* Flag whether the key was pressed (1) or released (0). */
- + char pressed;
- + }
- + keyboard;
- +
- + /* Event data for pointer. */
- + struct _halPointer
- + {
- + /* Current pointer coordinate. */
- + int x;
- + int y;
- + }
- + pointer;
- +
- + /* Event data for mouse buttons. */
- + struct _halButton
- + {
- + /* Left button state. */
- + int left;
- +
- + /* Middle button state. */
- + int middle;
- +
- + /* Right button state. */
- + int right;
- +
- + /* Current pointer coordinate. */
- + int x;
- + int y;
- + }
- + button;
- + }
- + data;
- +}
- +halEvent;
- +
- +/* VFK_DISPLAY_INFO structure defining information returned by
- + vdkGetDisplayInfoEx. */
- +typedef struct _halDISPLAY_INFO
- +{
- + /* The size of the display in pixels. */
- + int width;
- + int height;
- +
- + /* The stride of the dispay. -1 is returned if the stride is not known
- + ** for the specified display.*/
- + int stride;
- +
- + /* The color depth of the display in bits per pixel. */
- + int bitsPerPixel;
- +
- + /* The logical pointer to the display memory buffer. NULL is returned
- + ** if the pointer is not known for the specified display. */
- + void * logical;
- +
- + /* The physical address of the display memory buffer. ~0 is returned
- + ** if the address is not known for the specified display. */
- + unsigned long physical;
- +
- + int wrapFB; /* true if compositor, false otherwise. */
- +
- +#ifndef __QNXNTO__
- + /* 355_FB_MULTI_BUFFER */
- + int multiBuffer;
- + int backBufferY;
- +#endif
- +
- + /* The color info of the display. */
- + unsigned int alphaLength;
- + unsigned int alphaOffset;
- + unsigned int redLength;
- + unsigned int redOffset;
- + unsigned int greenLength;
- + unsigned int greenOffset;
- + unsigned int blueLength;
- + unsigned int blueOffset;
- +
- + /* Display flip support. */
- + int flip;
- +}
- +halDISPLAY_INFO;
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* __gc_hal_eglplatform_type_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h 2015-03-08 14:27:37.645684500 -0500
- @@ -0,0 +1,2053 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_engine_h_
- +#define __gc_hal_engine_h_
- +
- +#ifndef VIVANTE_NO_3D
- +#include "gc_hal_types.h"
- +#include "gc_hal_enum.h"
- +
- +#if gcdENABLE_VG
- +#include "gc_hal_engine_vg.h"
- +#endif
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +/******************************************************************************\
- +****************************** Object Declarations *****************************
- +\******************************************************************************/
- +
- +typedef struct _gcoSTREAM * gcoSTREAM;
- +typedef struct _gcoVERTEX * gcoVERTEX;
- +typedef struct _gcoTEXTURE * gcoTEXTURE;
- +typedef struct _gcoINDEX * gcoINDEX;
- +typedef struct _gcsVERTEX_ATTRIBUTES * gcsVERTEX_ATTRIBUTES_PTR;
- +typedef struct _gcoVERTEXARRAY * gcoVERTEXARRAY;
- +
- +#define gcdATTRIBUTE_COUNT 16
- +
- +/******************************************************************************\
- +********************************* Enumerations *********************************
- +\******************************************************************************/
- +
- +/* Shading format. */
- +typedef enum _gceSHADING
- +{
- + gcvSHADING_SMOOTH,
- + gcvSHADING_FLAT_D3D,
- + gcvSHADING_FLAT_OPENGL,
- +}
- +gceSHADING;
- +
- +/* Culling modes. */
- +typedef enum _gceCULL
- +{
- + gcvCULL_NONE,
- + gcvCULL_CCW,
- + gcvCULL_CW,
- +}
- +gceCULL;
- +
- +/* Fill modes. */
- +typedef enum _gceFILL
- +{
- + gcvFILL_POINT,
- + gcvFILL_WIRE_FRAME,
- + gcvFILL_SOLID,
- +}
- +gceFILL;
- +
- +/* Compare modes. */
- +typedef enum _gceCOMPARE
- +{
- + gcvCOMPARE_NEVER,
- + gcvCOMPARE_NOT_EQUAL,
- + gcvCOMPARE_LESS,
- + gcvCOMPARE_LESS_OR_EQUAL,
- + gcvCOMPARE_EQUAL,
- + gcvCOMPARE_GREATER,
- + gcvCOMPARE_GREATER_OR_EQUAL,
- + gcvCOMPARE_ALWAYS,
- + gcvCOMPARE_INVALID = -1
- +}
- +gceCOMPARE;
- +
- +/* Stencil modes. */
- +typedef enum _gceSTENCIL_MODE
- +{
- + gcvSTENCIL_NONE,
- + gcvSTENCIL_SINGLE_SIDED,
- + gcvSTENCIL_DOUBLE_SIDED,
- +}
- +gceSTENCIL_MODE;
- +
- +/* Stencil operations. */
- +typedef enum _gceSTENCIL_OPERATION
- +{
- + gcvSTENCIL_KEEP,
- + gcvSTENCIL_REPLACE,
- + gcvSTENCIL_ZERO,
- + gcvSTENCIL_INVERT,
- + gcvSTENCIL_INCREMENT,
- + gcvSTENCIL_DECREMENT,
- + gcvSTENCIL_INCREMENT_SATURATE,
- + gcvSTENCIL_DECREMENT_SATURATE,
- + gcvSTENCIL_OPERATION_INVALID = -1
- +}
- +gceSTENCIL_OPERATION;
- +
- +/* Stencil selection. */
- +typedef enum _gceSTENCIL_WHERE
- +{
- + gcvSTENCIL_FRONT,
- + gcvSTENCIL_BACK,
- +}
- +gceSTENCIL_WHERE;
- +
- +/* Texture addressing selection. */
- +typedef enum _gceTEXTURE_WHICH
- +{
- + gcvTEXTURE_S,
- + gcvTEXTURE_T,
- + gcvTEXTURE_R,
- +}
- +gceTEXTURE_WHICH;
- +
- +/* Texture addressing modes. */
- +typedef enum _gceTEXTURE_ADDRESSING
- +{
- + gcvTEXTURE_WRAP,
- + gcvTEXTURE_CLAMP,
- + gcvTEXTURE_BORDER,
- + gcvTEXTURE_MIRROR,
- + gcvTEXTURE_MIRROR_ONCE,
- +}
- +gceTEXTURE_ADDRESSING;
- +
- +/* Texture filters. */
- +typedef enum _gceTEXTURE_FILTER
- +{
- + gcvTEXTURE_NONE,
- + gcvTEXTURE_POINT,
- + gcvTEXTURE_LINEAR,
- + gcvTEXTURE_ANISOTROPIC,
- +}
- +gceTEXTURE_FILTER;
- +
- +/* Primitive types. */
- +typedef enum _gcePRIMITIVE
- +{
- + gcvPRIMITIVE_POINT_LIST,
- + gcvPRIMITIVE_LINE_LIST,
- + gcvPRIMITIVE_LINE_STRIP,
- + gcvPRIMITIVE_LINE_LOOP,
- + gcvPRIMITIVE_TRIANGLE_LIST,
- + gcvPRIMITIVE_TRIANGLE_STRIP,
- + gcvPRIMITIVE_TRIANGLE_FAN,
- + gcvPRIMITIVE_RECTANGLE,
- +}
- +gcePRIMITIVE;
- +
- +/* Index types. */
- +typedef enum _gceINDEX_TYPE
- +{
- + gcvINDEX_8,
- + gcvINDEX_16,
- + gcvINDEX_32,
- +}
- +gceINDEX_TYPE;
- +
- +/******************************************************************************\
- +********************************* gcoHAL Object *********************************
- +\******************************************************************************/
- +
- +/* Query the target capabilities. */
- +gceSTATUS
- +gcoHAL_QueryTargetCaps(
- + IN gcoHAL Hal,
- + OUT gctUINT * MaxWidth,
- + OUT gctUINT * MaxHeight,
- + OUT gctUINT * MultiTargetCount,
- + OUT gctUINT * MaxSamples
- + );
- +
- +gceSTATUS
- +gcoHAL_SetDepthOnly(
- + IN gcoHAL Hal,
- + IN gctBOOL Enable
- + );
- +
- +gceSTATUS
- +gcoHAL_QueryShaderCaps(
- + IN gcoHAL Hal,
- + OUT gctUINT * VertexUniforms,
- + OUT gctUINT * FragmentUniforms,
- + OUT gctUINT * Varyings
- + );
- +
- +gceSTATUS
- +gcoHAL_QueryTextureCaps(
- + IN gcoHAL Hal,
- + OUT gctUINT * MaxWidth,
- + OUT gctUINT * MaxHeight,
- + OUT gctUINT * MaxDepth,
- + OUT gctBOOL * Cubic,
- + OUT gctBOOL * NonPowerOfTwo,
- + OUT gctUINT * VertexSamplers,
- + OUT gctUINT * PixelSamplers
- + );
- +
- +gceSTATUS
- +gcoHAL_QueryTextureMaxAniso(
- + IN gcoHAL Hal,
- + OUT gctUINT * MaxAnisoValue
- + );
- +
- +gceSTATUS
- +gcoHAL_QueryStreamCaps(
- + IN gcoHAL Hal,
- + OUT gctUINT32 * MaxAttributes,
- + OUT gctUINT32 * MaxStreamSize,
- + OUT gctUINT32 * NumberOfStreams,
- + OUT gctUINT32 * Alignment
- + );
- +
- +/******************************************************************************\
- +********************************* gcoSURF Object ********************************
- +\******************************************************************************/
- +
- +/*----------------------------------------------------------------------------*/
- +/*--------------------------------- gcoSURF 3D --------------------------------*/
- +
- +/* Copy surface. */
- +gceSTATUS
- +gcoSURF_Copy(
- + IN gcoSURF Surface,
- + IN gcoSURF Source
- + );
- +
- +/* Clear surface. */
- +gceSTATUS
- +gcoSURF_Clear(
- + IN gcoSURF Surface,
- + IN gctUINT Flags
- + );
- +
- +/* Set number of samples for a gcoSURF object. */
- +gceSTATUS
- +gcoSURF_SetSamples(
- + IN gcoSURF Surface,
- + IN gctUINT Samples
- + );
- +
- +/* Get the number of samples per pixel. */
- +gceSTATUS
- +gcoSURF_GetSamples(
- + IN gcoSURF Surface,
- + OUT gctUINT_PTR Samples
- + );
- +
- +/* Clear rectangular surface. */
- +gceSTATUS
- +gcoSURF_ClearRect(
- + IN gcoSURF Surface,
- + IN gctINT Left,
- + IN gctINT Top,
- + IN gctINT Right,
- + IN gctINT Bottom,
- + IN gctUINT Flags
- + );
- +
- +/* TO BE REMOVED */
- + gceSTATUS
- + depr_gcoSURF_Resolve(
- + IN gcoSURF SrcSurface,
- + IN gcoSURF DestSurface,
- + IN gctUINT32 DestAddress,
- + IN gctPOINTER DestBits,
- + IN gctINT DestStride,
- + IN gceSURF_TYPE DestType,
- + IN gceSURF_FORMAT DestFormat,
- + IN gctUINT DestWidth,
- + IN gctUINT DestHeight
- + );
- +
- + gceSTATUS
- + depr_gcoSURF_ResolveRect(
- + IN gcoSURF SrcSurface,
- + IN gcoSURF DestSurface,
- + IN gctUINT32 DestAddress,
- + IN gctPOINTER DestBits,
- + IN gctINT DestStride,
- + IN gceSURF_TYPE DestType,
- + IN gceSURF_FORMAT DestFormat,
- + IN gctUINT DestWidth,
- + IN gctUINT DestHeight,
- + IN gcsPOINT_PTR SrcOrigin,
- + IN gcsPOINT_PTR DestOrigin,
- + IN gcsPOINT_PTR RectSize
- + );
- +
- +/* Resample surface. */
- +gceSTATUS
- +gcoSURF_Resample(
- + IN gcoSURF SrcSurface,
- + IN gcoSURF DestSurface
- + );
- +
- +/* Resolve surface. */
- +gceSTATUS
- +gcoSURF_Resolve(
- + IN gcoSURF SrcSurface,
- + IN gcoSURF DestSurface
- + );
- +
- +gceSTATUS
- +gcoSURF_IsHWResolveable(
- + IN gcoSURF SrcSurface,
- + IN gcoSURF DestSurface,
- + IN gcsPOINT_PTR SrcOrigin,
- + IN gcsPOINT_PTR DestOrigin,
- + IN gcsPOINT_PTR RectSize
- + );
- +
- +/* Resolve rectangular area of a surface. */
- +gceSTATUS
- +gcoSURF_ResolveRect(
- + IN gcoSURF SrcSurface,
- + IN gcoSURF DestSurface,
- + IN gcsPOINT_PTR SrcOrigin,
- + IN gcsPOINT_PTR DestOrigin,
- + IN gcsPOINT_PTR RectSize
- + );
- +
- +/* Set surface resolvability. */
- +gceSTATUS
- +gcoSURF_SetResolvability(
- + IN gcoSURF Surface,
- + IN gctBOOL Resolvable
- + );
- +
- +gceSTATUS
- +gcoSURF_IsRenderable(
- + IN gcoSURF Surface
- + );
- +
- +gceSTATUS
- +gcoSURF_IsFormatRenderableAsRT(
- + IN gcoSURF Surface
- + );
- +
- +#if gcdSYNC
- +gceSTATUS
- +gcoSURF_GetFence(
- + IN gcoSURF Surface
- + );
- +gceSTATUS
- +gcoSURF_WaitFence(
- + IN gcoSURF Surface
- + );
- +
- +gceSTATUS
- +gcoSTREAM_GetFence(
- + IN gcoSTREAM stream
- + );
- +
- +gceSTATUS
- +gcoSTREAM_WaitFence(
- + IN gcoSTREAM stream
- + );
- +
- +gceSTATUS
- +gcoINDEX_GetFence(
- + IN gcoINDEX index
- + );
- +
- +gceSTATUS
- +gcoINDEX_WaitFence(
- + IN gcoINDEX index
- + );
- +#endif
- +
- +/******************************************************************************\
- +******************************** gcoINDEX Object *******************************
- +\******************************************************************************/
- +
- +/* Construct a new gcoINDEX object. */
- +gceSTATUS
- +gcoINDEX_Construct(
- + IN gcoHAL Hal,
- + OUT gcoINDEX * Index
- + );
- +
- +/* Destroy a gcoINDEX object. */
- +gceSTATUS
- +gcoINDEX_Destroy(
- + IN gcoINDEX Index
- + );
- +
- +/* Lock index in memory. */
- +gceSTATUS
- +gcoINDEX_Lock(
- + IN gcoINDEX Index,
- + OUT gctUINT32 * Address,
- + OUT gctPOINTER * Memory
- + );
- +
- +/* Unlock index that was previously locked with gcoINDEX_Lock. */
- +gceSTATUS
- +gcoINDEX_Unlock(
- + IN gcoINDEX Index
- + );
- +
- +/* Upload index data into the memory. */
- +gceSTATUS
- +gcoINDEX_Load(
- + IN gcoINDEX Index,
- + IN gceINDEX_TYPE IndexType,
- + IN gctUINT32 IndexCount,
- + IN gctPOINTER IndexBuffer
- + );
- +
- +/* Bind an index object to the hardware. */
- +gceSTATUS
- +gcoINDEX_Bind(
- + IN gcoINDEX Index,
- + IN gceINDEX_TYPE Type
- + );
- +
- +/* Bind an index object to the hardware. */
- +gceSTATUS
- +gcoINDEX_BindOffset(
- + IN gcoINDEX Index,
- + IN gceINDEX_TYPE Type,
- + IN gctUINT32 Offset
- + );
- +
- +/* Free existing index buffer. */
- +gceSTATUS
- +gcoINDEX_Free(
- + IN gcoINDEX Index
- + );
- +
- +/* Upload data into an index buffer. */
- +gceSTATUS
- +gcoINDEX_Upload(
- + IN gcoINDEX Index,
- + IN gctCONST_POINTER Buffer,
- + IN gctSIZE_T Bytes
- + );
- +
- +/* Upload data into an index buffer starting at an offset. */
- +gceSTATUS
- +gcoINDEX_UploadOffset(
- + IN gcoINDEX Index,
- + IN gctUINT32 Offset,
- + IN gctCONST_POINTER Buffer,
- + IN gctSIZE_T Bytes
- + );
- +
- +/*Merge index2 to index1 from 0, index2 must subset of inex1*/
- +gceSTATUS
- +gcoINDEX_Merge(
- + IN gcoINDEX Index1,
- + IN gcoINDEX Index2
- + );
- +
- +/*check if index buffer is enough for this draw*/
- +gctBOOL
- +gcoINDEX_CheckRange(
- + IN gcoINDEX Index,
- + IN gceINDEX_TYPE Type,
- + IN gctINT Count,
- + IN gctUINT32 Indices
- + );
- +
- +/* Query the index capabilities. */
- +gceSTATUS
- +gcoINDEX_QueryCaps(
- + OUT gctBOOL * Index8,
- + OUT gctBOOL * Index16,
- + OUT gctBOOL * Index32,
- + OUT gctUINT * MaxIndex
- + );
- +
- +/* Determine the index range in the current index buffer. */
- +gceSTATUS
- +gcoINDEX_GetIndexRange(
- + IN gcoINDEX Index,
- + IN gceINDEX_TYPE Type,
- + IN gctUINT32 Offset,
- + IN gctUINT32 Count,
- + OUT gctUINT32 * MinimumIndex,
- + OUT gctUINT32 * MaximumIndex
- + );
- +
- +/* Dynamic buffer management. */
- +gceSTATUS
- +gcoINDEX_SetDynamic(
- + IN gcoINDEX Index,
- + IN gctSIZE_T Bytes,
- + IN gctUINT Buffers
- + );
- +
- +gceSTATUS
- +gcoINDEX_UploadDynamic(
- + IN gcoINDEX Index,
- + IN gctCONST_POINTER Data,
- + IN gctSIZE_T Bytes
- + );
- +
- +/******************************************************************************\
- +********************************** gco3D Object *********************************
- +\******************************************************************************/
- +
- +/* Clear flags. */
- +typedef enum _gceCLEAR
- +{
- + gcvCLEAR_COLOR = 0x1,
- + gcvCLEAR_DEPTH = 0x2,
- + gcvCLEAR_STENCIL = 0x4,
- + gcvCLEAR_HZ = 0x8,
- + gcvCLEAR_HAS_VAA = 0x10,
- +}
- +gceCLEAR;
- +
- +/* Blending targets. */
- +typedef enum _gceBLEND_UNIT
- +{
- + gcvBLEND_SOURCE,
- + gcvBLEND_TARGET,
- +}
- +gceBLEND_UNIT;
- +
- +/* Construct a new gco3D object. */
- +gceSTATUS
- +gco3D_Construct(
- + IN gcoHAL Hal,
- + OUT gco3D * Engine
- + );
- +
- +/* Destroy an gco3D object. */
- +gceSTATUS
- +gco3D_Destroy(
- + IN gco3D Engine
- + );
- +
- +/* Set 3D API type. */
- +gceSTATUS
- +gco3D_SetAPI(
- + IN gco3D Engine,
- + IN gceAPI ApiType
- + );
- +
- +/* Set render target. */
- +gceSTATUS
- +gco3D_SetTarget(
- + IN gco3D Engine,
- + IN gcoSURF Surface
- + );
- +
- +/* Unset render target. */
- +gceSTATUS
- +gco3D_UnsetTarget(
- + IN gco3D Engine,
- + IN gcoSURF Surface
- + );
- +
- +/* Set depth buffer. */
- +gceSTATUS
- +gco3D_SetDepth(
- + IN gco3D Engine,
- + IN gcoSURF Surface
- + );
- +
- +/* Unset depth buffer. */
- +gceSTATUS
- +gco3D_UnsetDepth(
- + IN gco3D Engine,
- + IN gcoSURF Surface
- + );
- +
- +/* Set viewport. */
- +gceSTATUS
- +gco3D_SetViewport(
- + IN gco3D Engine,
- + IN gctINT32 Left,
- + IN gctINT32 Top,
- + IN gctINT32 Right,
- + IN gctINT32 Bottom
- + );
- +
- +/* Set scissors. */
- +gceSTATUS
- +gco3D_SetScissors(
- + IN gco3D Engine,
- + IN gctINT32 Left,
- + IN gctINT32 Top,
- + IN gctINT32 Right,
- + IN gctINT32 Bottom
- + );
- +
- +/* Set clear color. */
- +gceSTATUS
- +gco3D_SetClearColor(
- + IN gco3D Engine,
- + IN gctUINT8 Red,
- + IN gctUINT8 Green,
- + IN gctUINT8 Blue,
- + IN gctUINT8 Alpha
- + );
- +
- +/* Set fixed point clear color. */
- +gceSTATUS
- +gco3D_SetClearColorX(
- + IN gco3D Engine,
- + IN gctFIXED_POINT Red,
- + IN gctFIXED_POINT Green,
- + IN gctFIXED_POINT Blue,
- + IN gctFIXED_POINT Alpha
- + );
- +
- +/* Set floating point clear color. */
- +gceSTATUS
- +gco3D_SetClearColorF(
- + IN gco3D Engine,
- + IN gctFLOAT Red,
- + IN gctFLOAT Green,
- + IN gctFLOAT Blue,
- + IN gctFLOAT Alpha
- + );
- +
- +/* Set fixed point clear depth. */
- +gceSTATUS
- +gco3D_SetClearDepthX(
- + IN gco3D Engine,
- + IN gctFIXED_POINT Depth
- + );
- +
- +/* Set floating point clear depth. */
- +gceSTATUS
- +gco3D_SetClearDepthF(
- + IN gco3D Engine,
- + IN gctFLOAT Depth
- + );
- +
- +/* Set clear stencil. */
- +gceSTATUS
- +gco3D_SetClearStencil(
- + IN gco3D Engine,
- + IN gctUINT32 Stencil
- + );
- +
- +/* Clear a Rect sub-surface. */
- +gceSTATUS
- +gco3D_ClearRect(
- + IN gco3D Engine,
- + IN gctUINT32 Address,
- + IN gctPOINTER Memory,
- + IN gctUINT32 Stride,
- + IN gceSURF_FORMAT Format,
- + IN gctINT32 Left,
- + IN gctINT32 Top,
- + IN gctINT32 Right,
- + IN gctINT32 Bottom,
- + IN gctUINT32 Width,
- + IN gctUINT32 Height,
- + IN gctUINT32 Flags
- + );
- +
- +/* Clear surface. */
- +gceSTATUS
- +gco3D_Clear(
- + IN gco3D Engine,
- + IN gctUINT32 Address,
- + IN gctUINT32 Stride,
- + IN gceSURF_FORMAT Format,
- + IN gctUINT32 Width,
- + IN gctUINT32 Height,
- + IN gctUINT32 Flags
- + );
- +
- +
- +/* Clear tile status. */
- +gceSTATUS
- +gco3D_ClearTileStatus(
- + IN gco3D Engine,
- + IN gcsSURF_INFO_PTR Surface,
- + IN gctUINT32 TileStatusAddress,
- + IN gctUINT32 Flags
- + );
- +
- +/* Set shading mode. */
- +gceSTATUS
- +gco3D_SetShading(
- + IN gco3D Engine,
- + IN gceSHADING Shading
- + );
- +
- +/* Set blending mode. */
- +gceSTATUS
- +gco3D_EnableBlending(
- + IN gco3D Engine,
- + IN gctBOOL Enable
- + );
- +
- +/* Set blending function. */
- +gceSTATUS
- +gco3D_SetBlendFunction(
- + IN gco3D Engine,
- + IN gceBLEND_UNIT Unit,
- + IN gceBLEND_FUNCTION FunctionRGB,
- + IN gceBLEND_FUNCTION FunctionAlpha
- + );
- +
- +/* Set blending mode. */
- +gceSTATUS
- +gco3D_SetBlendMode(
- + IN gco3D Engine,
- + IN gceBLEND_MODE ModeRGB,
- + IN gceBLEND_MODE ModeAlpha
- + );
- +
- +/* Set blending color. */
- +gceSTATUS
- +gco3D_SetBlendColor(
- + IN gco3D Engine,
- + IN gctUINT Red,
- + IN gctUINT Green,
- + IN gctUINT Blue,
- + IN gctUINT Alpha
- + );
- +
- +/* Set fixed point blending color. */
- +gceSTATUS
- +gco3D_SetBlendColorX(
- + IN gco3D Engine,
- + IN gctFIXED_POINT Red,
- + IN gctFIXED_POINT Green,
- + IN gctFIXED_POINT Blue,
- + IN gctFIXED_POINT Alpha
- + );
- +
- +/* Set floating point blending color. */
- +gceSTATUS
- +gco3D_SetBlendColorF(
- + IN gco3D Engine,
- + IN gctFLOAT Red,
- + IN gctFLOAT Green,
- + IN gctFLOAT Blue,
- + IN gctFLOAT Alpha
- + );
- +
- +/* Set culling mode. */
- +gceSTATUS
- +gco3D_SetCulling(
- + IN gco3D Engine,
- + IN gceCULL Mode
- + );
- +
- +/* Enable point size */
- +gceSTATUS
- +gco3D_SetPointSizeEnable(
- + IN gco3D Engine,
- + IN gctBOOL Enable
- + );
- +
- +/* Set point sprite */
- +gceSTATUS
- +gco3D_SetPointSprite(
- + IN gco3D Engine,
- + IN gctBOOL Enable
- + );
- +
- +/* Set fill mode. */
- +gceSTATUS
- +gco3D_SetFill(
- + IN gco3D Engine,
- + IN gceFILL Mode
- + );
- +
- +/* Set depth compare mode. */
- +gceSTATUS
- +gco3D_SetDepthCompare(
- + IN gco3D Engine,
- + IN gceCOMPARE Compare
- + );
- +
- +/* Enable depth writing. */
- +gceSTATUS
- +gco3D_EnableDepthWrite(
- + IN gco3D Engine,
- + IN gctBOOL Enable
- + );
- +
- +/* Set depth mode. */
- +gceSTATUS
- +gco3D_SetDepthMode(
- + IN gco3D Engine,
- + IN gceDEPTH_MODE Mode
- + );
- +
- +/* Set depth range. */
- +gceSTATUS
- +gco3D_SetDepthRangeX(
- + IN gco3D Engine,
- + IN gceDEPTH_MODE Mode,
- + IN gctFIXED_POINT Near,
- + IN gctFIXED_POINT Far
- + );
- +
- +/* Set depth range. */
- +gceSTATUS
- +gco3D_SetDepthRangeF(
- + IN gco3D Engine,
- + IN gceDEPTH_MODE Mode,
- + IN gctFLOAT Near,
- + IN gctFLOAT Far
- + );
- +
- +/* Set last pixel enable */
- +gceSTATUS
- +gco3D_SetLastPixelEnable(
- + IN gco3D Engine,
- + IN gctBOOL Enable
- + );
- +
- +/* Set depth Bias and Scale */
- +gceSTATUS
- +gco3D_SetDepthScaleBiasX(
- + IN gco3D Engine,
- + IN gctFIXED_POINT DepthScale,
- + IN gctFIXED_POINT DepthBias
- + );
- +
- +gceSTATUS
- +gco3D_SetDepthScaleBiasF(
- + IN gco3D Engine,
- + IN gctFLOAT DepthScale,
- + IN gctFLOAT DepthBias
- + );
- +
- +/* Set depth near and far clipping plane. */
- +gceSTATUS
- +gco3D_SetDepthPlaneF(
- + IN gco3D Engine,
- + IN gctFLOAT Near,
- + IN gctFLOAT Far
- + );
- +
- +/* Enable or disable dithering. */
- +gceSTATUS
- +gco3D_EnableDither(
- + IN gco3D Engine,
- + IN gctBOOL Enable
- + );
- +
- +/* Set color write enable bits. */
- +gceSTATUS
- +gco3D_SetColorWrite(
- + IN gco3D Engine,
- + IN gctUINT8 Enable
- + );
- +
- +/* Enable or disable early depth. */
- +gceSTATUS
- +gco3D_SetEarlyDepth(
- + IN gco3D Engine,
- + IN gctBOOL Enable
- + );
- +
- +/* Enable or disable all early depth operations. */
- +gceSTATUS
- +gco3D_SetAllEarlyDepthModes(
- + IN gco3D Engine,
- + IN gctBOOL Disable
- + );
- +
- +/* Switch dynamic early mode */
- +gceSTATUS
- +gco3D_SwitchDynamicEarlyDepthMode(
- + IN gco3D Engine
- + );
- +
- +/* Set dynamic early mode */
- +gceSTATUS
- +gco3D_DisableDynamicEarlyDepthMode(
- + IN gco3D Engine,
- + IN gctBOOL Disable
- + );
- +
- +/* Enable or disable depth-only mode. */
- +gceSTATUS
- +gco3D_SetDepthOnly(
- + IN gco3D Engine,
- + IN gctBOOL Enable
- + );
- +
- +typedef struct _gcsSTENCIL_INFO * gcsSTENCIL_INFO_PTR;
- +typedef struct _gcsSTENCIL_INFO
- +{
- + gceSTENCIL_MODE mode;
- +
- + gctUINT8 maskFront;
- + gctUINT8 maskBack;
- + gctUINT8 writeMaskFront;
- + gctUINT8 writeMaskBack;
- +
- + gctUINT8 referenceFront;
- +
- + gceCOMPARE compareFront;
- + gceSTENCIL_OPERATION passFront;
- + gceSTENCIL_OPERATION failFront;
- + gceSTENCIL_OPERATION depthFailFront;
- +
- + gctUINT8 referenceBack;
- + gceCOMPARE compareBack;
- + gceSTENCIL_OPERATION passBack;
- + gceSTENCIL_OPERATION failBack;
- + gceSTENCIL_OPERATION depthFailBack;
- +}
- +gcsSTENCIL_INFO;
- +
- +/* Set stencil mode. */
- +gceSTATUS
- +gco3D_SetStencilMode(
- + IN gco3D Engine,
- + IN gceSTENCIL_MODE Mode
- + );
- +
- +/* Set stencil mask. */
- +gceSTATUS
- +gco3D_SetStencilMask(
- + IN gco3D Engine,
- + IN gctUINT8 Mask
- + );
- +
- +/* Set stencil back mask. */
- +gceSTATUS
- +gco3D_SetStencilMaskBack(
- + IN gco3D Engine,
- + IN gctUINT8 Mask
- + );
- +
- +/* Set stencil write mask. */
- +gceSTATUS
- +gco3D_SetStencilWriteMask(
- + IN gco3D Engine,
- + IN gctUINT8 Mask
- + );
- +
- +/* Set stencil back write mask. */
- +gceSTATUS
- +gco3D_SetStencilWriteMaskBack(
- + IN gco3D Engine,
- + IN gctUINT8 Mask
- + );
- +
- +/* Set stencil reference. */
- +gceSTATUS
- +gco3D_SetStencilReference(
- + IN gco3D Engine,
- + IN gctUINT8 Reference,
- + IN gctBOOL Front
- + );
- +
- +/* Set stencil compare. */
- +gceSTATUS
- +gco3D_SetStencilCompare(
- + IN gco3D Engine,
- + IN gceSTENCIL_WHERE Where,
- + IN gceCOMPARE Compare
- + );
- +
- +/* Set stencil operation on pass. */
- +gceSTATUS
- +gco3D_SetStencilPass(
- + IN gco3D Engine,
- + IN gceSTENCIL_WHERE Where,
- + IN gceSTENCIL_OPERATION Operation
- + );
- +
- +/* Set stencil operation on fail. */
- +gceSTATUS
- +gco3D_SetStencilFail(
- + IN gco3D Engine,
- + IN gceSTENCIL_WHERE Where,
- + IN gceSTENCIL_OPERATION Operation
- + );
- +
- +/* Set stencil operation on depth fail. */
- +gceSTATUS
- +gco3D_SetStencilDepthFail(
- + IN gco3D Engine,
- + IN gceSTENCIL_WHERE Where,
- + IN gceSTENCIL_OPERATION Operation
- + );
- +
- +/* Set all stencil states in one blow. */
- +gceSTATUS
- +gco3D_SetStencilAll(
- + IN gco3D Engine,
- + IN gcsSTENCIL_INFO_PTR Info
- + );
- +
- +typedef struct _gcsALPHA_INFO * gcsALPHA_INFO_PTR;
- +typedef struct _gcsALPHA_INFO
- +{
- + /* Alpha test states. */
- + gctBOOL test;
- + gceCOMPARE compare;
- + gctUINT8 reference;
- + gctFLOAT floatReference;
- +
- + /* Alpha blending states. */
- + gctBOOL blend;
- +
- + gceBLEND_FUNCTION srcFuncColor;
- + gceBLEND_FUNCTION srcFuncAlpha;
- + gceBLEND_FUNCTION trgFuncColor;
- + gceBLEND_FUNCTION trgFuncAlpha;
- +
- + gceBLEND_MODE modeColor;
- + gceBLEND_MODE modeAlpha;
- +
- + gctUINT32 color;
- +}
- +gcsALPHA_INFO;
- +
- +/* Enable or disable alpha test. */
- +gceSTATUS
- +gco3D_SetAlphaTest(
- + IN gco3D Engine,
- + IN gctBOOL Enable
- + );
- +
- +/* Set alpha test compare. */
- +gceSTATUS
- +gco3D_SetAlphaCompare(
- + IN gco3D Engine,
- + IN gceCOMPARE Compare
- + );
- +
- +/* Set alpha test reference in unsigned integer. */
- +gceSTATUS
- +gco3D_SetAlphaReference(
- + IN gco3D Engine,
- + IN gctUINT8 Reference,
- + IN gctFLOAT FloatReference
- + );
- +
- +/* Set alpha test reference in fixed point. */
- +gceSTATUS
- +gco3D_SetAlphaReferenceX(
- + IN gco3D Engine,
- + IN gctFIXED_POINT Reference
- + );
- +
- +/* Set alpha test reference in floating point. */
- +gceSTATUS
- +gco3D_SetAlphaReferenceF(
- + IN gco3D Engine,
- + IN gctFLOAT Reference
- + );
- +
- +/* Enable/Disable anti-alias line. */
- +gceSTATUS
- +gco3D_SetAntiAliasLine(
- + IN gco3D Engine,
- + IN gctBOOL Enable
- + );
- +
- +/* Set texture slot for anti-alias line. */
- +gceSTATUS
- +gco3D_SetAALineTexSlot(
- + IN gco3D Engine,
- + IN gctUINT TexSlot
- + );
- +
- +/* Set anti-alias line width scale. */
- +gceSTATUS
- +gco3D_SetAALineWidth(
- + IN gco3D Engine,
- + IN gctFLOAT Width
- + );
- +
- +/* Draw a number of primitives. */
- +gceSTATUS
- +gco3D_DrawPrimitives(
- + IN gco3D Engine,
- + IN gcePRIMITIVE Type,
- + IN gctINT StartVertex,
- + IN gctSIZE_T PrimitiveCount
- + );
- +
- +gceSTATUS
- +gco3D_DrawPrimitivesCount(
- + IN gco3D Engine,
- + IN gcePRIMITIVE Type,
- + IN gctINT* StartVertex,
- + IN gctSIZE_T* VertexCount,
- + IN gctSIZE_T PrimitiveCount
- + );
- +
- +
- +/* Draw a number of primitives using offsets. */
- +gceSTATUS
- +gco3D_DrawPrimitivesOffset(
- + IN gco3D Engine,
- + IN gcePRIMITIVE Type,
- + IN gctINT32 StartOffset,
- + IN gctSIZE_T PrimitiveCount
- + );
- +
- +/* Draw a number of indexed primitives. */
- +gceSTATUS
- +gco3D_DrawIndexedPrimitives(
- + IN gco3D Engine,
- + IN gcePRIMITIVE Type,
- + IN gctINT BaseVertex,
- + IN gctINT StartIndex,
- + IN gctSIZE_T PrimitiveCount
- + );
- +
- +/* Draw a number of indexed primitives using offsets. */
- +gceSTATUS
- +gco3D_DrawIndexedPrimitivesOffset(
- + IN gco3D Engine,
- + IN gcePRIMITIVE Type,
- + IN gctINT32 BaseOffset,
- + IN gctINT32 StartOffset,
- + IN gctSIZE_T PrimitiveCount
- + );
- +
- +/* Enable or disable anti-aliasing. */
- +gceSTATUS
- +gco3D_SetAntiAlias(
- + IN gco3D Engine,
- + IN gctBOOL Enable
- + );
- +
- +/* Write data into the command buffer. */
- +gceSTATUS
- +gco3D_WriteBuffer(
- + IN gco3D Engine,
- + IN gctCONST_POINTER Data,
- + IN gctSIZE_T Bytes,
- + IN gctBOOL Aligned
- + );
- +
- +/* Send sempahore and stall until sempahore is signalled. */
- +gceSTATUS
- +gco3D_Semaphore(
- + IN gco3D Engine,
- + IN gceWHERE From,
- + IN gceWHERE To,
- + IN gceHOW How);
- +
- +/* Set the subpixels center. */
- +gceSTATUS
- +gco3D_SetCentroids(
- + IN gco3D Engine,
- + IN gctUINT32 Index,
- + IN gctPOINTER Centroids
- + );
- +
- +gceSTATUS
- +gco3D_SetLogicOp(
- + IN gco3D Engine,
- + IN gctUINT8 Rop
- + );
- +
- +/* OCL thread walker information. */
- +typedef struct _gcsTHREAD_WALKER_INFO * gcsTHREAD_WALKER_INFO_PTR;
- +typedef struct _gcsTHREAD_WALKER_INFO
- +{
- + gctUINT32 dimensions;
- + gctUINT32 traverseOrder;
- + gctUINT32 enableSwathX;
- + gctUINT32 enableSwathY;
- + gctUINT32 enableSwathZ;
- + gctUINT32 swathSizeX;
- + gctUINT32 swathSizeY;
- + gctUINT32 swathSizeZ;
- + gctUINT32 valueOrder;
- +
- + gctUINT32 globalSizeX;
- + gctUINT32 globalOffsetX;
- + gctUINT32 globalSizeY;
- + gctUINT32 globalOffsetY;
- + gctUINT32 globalSizeZ;
- + gctUINT32 globalOffsetZ;
- +
- + gctUINT32 workGroupSizeX;
- + gctUINT32 workGroupCountX;
- + gctUINT32 workGroupSizeY;
- + gctUINT32 workGroupCountY;
- + gctUINT32 workGroupSizeZ;
- + gctUINT32 workGroupCountZ;
- +
- + gctUINT32 threadAllocation;
- +}
- +gcsTHREAD_WALKER_INFO;
- +
- +/* Start OCL thread walker. */
- +gceSTATUS
- +gco3D_InvokeThreadWalker(
- + IN gco3D Engine,
- + IN gcsTHREAD_WALKER_INFO_PTR Info
- + );
- +
- +/* Set w clip and w plane limit value. */
- +gceSTATUS
- +gco3D_SetWClipEnable(
- + IN gco3D Engine,
- + IN gctBOOL Enable
- + );
- +
- +gceSTATUS
- +gco3D_GetWClipEnable(
- + IN gco3D Engine,
- + OUT gctBOOL * Enable
- + );
- +
- +gceSTATUS
- +gco3D_SetWPlaneLimitF(
- + IN gco3D Engine,
- + IN gctFLOAT Value
- + );
- +
- +gceSTATUS
- +gco3D_SetWPlaneLimitX(
- + IN gco3D Engine,
- + IN gctFIXED_POINT Value
- + );
- +
- +
- +gceSTATUS
- +gco3D_SetWPlaneLimit(
- + IN gco3D Engine,
- + IN gctFLOAT Value
- + );
- +
- +/*----------------------------------------------------------------------------*/
- +/*-------------------------- gco3D Fragment Processor ------------------------*/
- +
- +/* Set the fragment processor configuration. */
- +gceSTATUS
- +gco3D_SetFragmentConfiguration(
- + IN gco3D Engine,
- + IN gctBOOL ColorFromStream,
- + IN gctBOOL EnableFog,
- + IN gctBOOL EnableSmoothPoint,
- + IN gctUINT32 ClipPlanes
- + );
- +
- +/* Enable/disable texture stage operation. */
- +gceSTATUS
- +gco3D_EnableTextureStage(
- + IN gco3D Engine,
- + IN gctINT Stage,
- + IN gctBOOL Enable
- + );
- +
- +/* Program the channel enable masks for the color texture function. */
- +gceSTATUS
- +gco3D_SetTextureColorMask(
- + IN gco3D Engine,
- + IN gctINT Stage,
- + IN gctBOOL ColorEnabled,
- + IN gctBOOL AlphaEnabled
- + );
- +
- +/* Program the channel enable masks for the alpha texture function. */
- +gceSTATUS
- +gco3D_SetTextureAlphaMask(
- + IN gco3D Engine,
- + IN gctINT Stage,
- + IN gctBOOL ColorEnabled,
- + IN gctBOOL AlphaEnabled
- + );
- +
- +/* Program the constant fragment color. */
- +gceSTATUS
- +gco3D_SetFragmentColorX(
- + IN gco3D Engine,
- + IN gctFIXED_POINT Red,
- + IN gctFIXED_POINT Green,
- + IN gctFIXED_POINT Blue,
- + IN gctFIXED_POINT Alpha
- + );
- +
- +gceSTATUS
- +gco3D_SetFragmentColorF(
- + IN gco3D Engine,
- + IN gctFLOAT Red,
- + IN gctFLOAT Green,
- + IN gctFLOAT Blue,
- + IN gctFLOAT Alpha
- + );
- +
- +/* Program the constant fog color. */
- +gceSTATUS
- +gco3D_SetFogColorX(
- + IN gco3D Engine,
- + IN gctFIXED_POINT Red,
- + IN gctFIXED_POINT Green,
- + IN gctFIXED_POINT Blue,
- + IN gctFIXED_POINT Alpha
- + );
- +
- +gceSTATUS
- +gco3D_SetFogColorF(
- + IN gco3D Engine,
- + IN gctFLOAT Red,
- + IN gctFLOAT Green,
- + IN gctFLOAT Blue,
- + IN gctFLOAT Alpha
- + );
- +
- +/* Program the constant texture color. */
- +gceSTATUS
- +gco3D_SetTetxureColorX(
- + IN gco3D Engine,
- + IN gctINT Stage,
- + IN gctFIXED_POINT Red,
- + IN gctFIXED_POINT Green,
- + IN gctFIXED_POINT Blue,
- + IN gctFIXED_POINT Alpha
- + );
- +
- +gceSTATUS
- +gco3D_SetTetxureColorF(
- + IN gco3D Engine,
- + IN gctINT Stage,
- + IN gctFLOAT Red,
- + IN gctFLOAT Green,
- + IN gctFLOAT Blue,
- + IN gctFLOAT Alpha
- + );
- +
- +/* Configure color texture function. */
- +gceSTATUS
- +gco3D_SetColorTextureFunction(
- + IN gco3D Engine,
- + IN gctINT Stage,
- + IN gceTEXTURE_FUNCTION Function,
- + IN gceTEXTURE_SOURCE Source0,
- + IN gceTEXTURE_CHANNEL Channel0,
- + IN gceTEXTURE_SOURCE Source1,
- + IN gceTEXTURE_CHANNEL Channel1,
- + IN gceTEXTURE_SOURCE Source2,
- + IN gceTEXTURE_CHANNEL Channel2,
- + IN gctINT Scale
- + );
- +
- +/* Configure alpha texture function. */
- +gceSTATUS
- +gco3D_SetAlphaTextureFunction(
- + IN gco3D Engine,
- + IN gctINT Stage,
- + IN gceTEXTURE_FUNCTION Function,
- + IN gceTEXTURE_SOURCE Source0,
- + IN gceTEXTURE_CHANNEL Channel0,
- + IN gceTEXTURE_SOURCE Source1,
- + IN gceTEXTURE_CHANNEL Channel1,
- + IN gceTEXTURE_SOURCE Source2,
- + IN gceTEXTURE_CHANNEL Channel2,
- + IN gctINT Scale
- + );
- +
- +/* Invoke OCL thread walker. */
- +gceSTATUS
- +gcoHARDWARE_InvokeThreadWalker(
- + IN gcsTHREAD_WALKER_INFO_PTR Info
- + );
- +
- +/******************************************************************************\
- +******************************* gcoTEXTURE Object *******************************
- +\******************************************************************************/
- +
- +/* Cube faces. */
- +typedef enum _gceTEXTURE_FACE
- +{
- + gcvFACE_NONE,
- + gcvFACE_POSITIVE_X,
- + gcvFACE_NEGATIVE_X,
- + gcvFACE_POSITIVE_Y,
- + gcvFACE_NEGATIVE_Y,
- + gcvFACE_POSITIVE_Z,
- + gcvFACE_NEGATIVE_Z,
- +}
- +gceTEXTURE_FACE;
- +
- +#if gcdFORCE_MIPMAP
- +typedef enum
- +{
- + gcvForceMipDisabled = 0,
- + gcvForceMipEnable = 1,
- + gcvForceMipGenerated = 2,
- + gcvForceMipNever = 3,
- +}gceFORCE_MIPMAP;
- +#endif
- +
- +typedef struct _gcsTEXTURE
- +{
- + /* Addressing modes. */
- + gceTEXTURE_ADDRESSING s;
- + gceTEXTURE_ADDRESSING t;
- + gceTEXTURE_ADDRESSING r;
- +
- + /* Border color. */
- + gctUINT8 border[4];
- +
- + /* Filters. */
- + gceTEXTURE_FILTER minFilter;
- + gceTEXTURE_FILTER magFilter;
- + gceTEXTURE_FILTER mipFilter;
- + gctUINT anisoFilter;
- + gctBOOL forceTopLevel;
- + gctBOOL autoMipmap;
- +#if gcdFORCE_MIPMAP
- + gceFORCE_MIPMAP forceMipmap;
- +#endif
- + /* Level of detail. */
- + gctFIXED_POINT lodBias;
- + gctFIXED_POINT lodMin;
- + gctFIXED_POINT lodMax;
- +}
- +gcsTEXTURE, * gcsTEXTURE_PTR;
- +
- +/* Construct a new gcoTEXTURE object. */
- +gceSTATUS
- +gcoTEXTURE_Construct(
- + IN gcoHAL Hal,
- + OUT gcoTEXTURE * Texture
- + );
- +
- +/* Construct a new sized gcoTEXTURE object. */
- +gceSTATUS
- +gcoTEXTURE_ConstructSized(
- + IN gcoHAL Hal,
- + IN gceSURF_FORMAT Format,
- + IN gctUINT Width,
- + IN gctUINT Height,
- + IN gctUINT Depth,
- + IN gctUINT Faces,
- + IN gctUINT MipMapCount,
- + IN gcePOOL Pool,
- + OUT gcoTEXTURE * Texture
- + );
- +
- +/* Destroy an gcoTEXTURE object. */
- +gceSTATUS
- +gcoTEXTURE_Destroy(
- + IN gcoTEXTURE Texture
- + );
- +#if gcdFORCE_MIPMAP
- +gceSTATUS
- +gcoTEXTURE_DestroyForceMipmap(
- + IN gcoTEXTURE Texture
- + );
- +
- +gceSTATUS
- +gcoTEXTURE_GetMipLevels(
- + IN gcoTEXTURE Texture,
- + OUT gctINT * levels
- + );
- +#endif
- +/* Replace a mipmap in gcoTEXTURE object. */
- +gceSTATUS
- +gcoTEXTURE_ReplaceMipMap(
- + IN gcoTEXTURE Texture,
- + IN gctUINT Level,
- + IN gctUINT Width,
- + IN gctUINT Height,
- + IN gctINT imageFormat,
- + IN gceSURF_FORMAT Format,
- + IN gctUINT Depth,
- + IN gctUINT Faces,
- + IN gcePOOL Pool
- + );
- +
- +/* Upload data to an gcoTEXTURE object. */
- +gceSTATUS
- +gcoTEXTURE_Upload(
- + IN gcoTEXTURE Texture,
- + IN gceTEXTURE_FACE Face,
- + IN gctUINT Width,
- + IN gctUINT Height,
- + IN gctUINT Slice,
- + IN gctCONST_POINTER Memory,
- + IN gctINT Stride,
- + IN gceSURF_FORMAT Format
- + );
- +
- +/* Upload data to an gcoTEXTURE object. */
- +gceSTATUS
- +gcoTEXTURE_UploadSub(
- + IN gcoTEXTURE Texture,
- + IN gctUINT MipMap,
- + IN gceTEXTURE_FACE Face,
- + IN gctUINT X,
- + IN gctUINT Y,
- + IN gctUINT Width,
- + IN gctUINT Height,
- + IN gctUINT Slice,
- + IN gctCONST_POINTER Memory,
- + IN gctINT Stride,
- + IN gceSURF_FORMAT Format
- + );
- +
- +/* Upload YUV data to an gcoTEXTURE object. */
- +gceSTATUS
- +gcoTEXTURE_UploadYUV(
- + IN gcoTEXTURE Texture,
- + IN gceTEXTURE_FACE Face,
- + IN gctUINT Width,
- + IN gctUINT Height,
- + IN gctUINT Slice,
- + IN gctPOINTER Memory[3],
- + IN gctINT Stride[3],
- + IN gceSURF_FORMAT Format
- + );
- +
- +/* Upload compressed data to an gcoTEXTURE object. */
- +gceSTATUS
- +gcoTEXTURE_UploadCompressed(
- + IN gcoTEXTURE Texture,
- + IN gceTEXTURE_FACE Face,
- + IN gctUINT Width,
- + IN gctUINT Height,
- + IN gctUINT Slice,
- + IN gctCONST_POINTER Memory,
- + IN gctSIZE_T Bytes
- + );
- +
- +/* Upload compressed sub data to an gcoTEXTURE object. */
- +gceSTATUS
- +gcoTEXTURE_UploadCompressedSub(
- + IN gcoTEXTURE Texture,
- + IN gctUINT MipMap,
- + IN gceTEXTURE_FACE Face,
- + IN gctUINT XOffset,
- + IN gctUINT YOffset,
- + IN gctUINT Width,
- + IN gctUINT Height,
- + IN gctUINT Slice,
- + IN gctCONST_POINTER Memory,
- + IN gctSIZE_T Size
- + );
- +
- +/* GetImageFormat of texture. */
- +gceSTATUS
- +gcoTEXTURE_GetImageFormat(
- + IN gcoTEXTURE Texture,
- + IN gctUINT MipMap,
- + OUT gctINT * ImageFormat
- + );
- +
- +/* Get gcoSURF object for a mipmap level. */
- +gceSTATUS
- +gcoTEXTURE_GetMipMap(
- + IN gcoTEXTURE Texture,
- + IN gctUINT MipMap,
- + OUT gcoSURF * Surface
- + );
- +
- +/* Get gcoSURF object for a mipmap level and face offset. */
- +gceSTATUS
- +gcoTEXTURE_GetMipMapFace(
- + IN gcoTEXTURE Texture,
- + IN gctUINT MipMap,
- + IN gceTEXTURE_FACE Face,
- + OUT gcoSURF * Surface,
- + OUT gctUINT32_PTR Offset
- + );
- +
- +gceSTATUS
- +gcoTEXTURE_AddMipMap(
- + IN gcoTEXTURE Texture,
- + IN gctINT Level,
- + IN gctINT imageFormat,
- + IN gceSURF_FORMAT Format,
- + IN gctUINT Width,
- + IN gctUINT Height,
- + IN gctUINT Depth,
- + IN gctUINT Faces,
- + IN gcePOOL Pool,
- + OUT gcoSURF * Surface
- + );
- +
- +gceSTATUS
- +gcoTEXTURE_AddMipMapFromClient(
- + IN gcoTEXTURE Texture,
- + IN gctINT Level,
- + IN gcoSURF Surface
- + );
- +
- +gceSTATUS
- +gcoTEXTURE_AddMipMapFromSurface(
- + IN gcoTEXTURE Texture,
- + IN gctINT Level,
- + IN gcoSURF Surface
- + );
- +
- +gceSTATUS
- +gcoTEXTURE_SetMaxLevel(
- + IN gcoTEXTURE Texture,
- + IN gctUINT Levels
- + );
- +
- +gceSTATUS
- +gcoTEXTURE_SetEndianHint(
- + IN gcoTEXTURE Texture,
- + IN gceENDIAN_HINT EndianHint
- + );
- +
- +gceSTATUS
- +gcoTEXTURE_Disable(
- + IN gcoHAL Hal,
- + IN gctINT Sampler
- + );
- +
- +gceSTATUS
- +gcoTEXTURE_Flush(
- + IN gcoTEXTURE Texture
- + );
- +
- +gceSTATUS
- +gcoTEXTURE_QueryCaps(
- + IN gcoHAL Hal,
- + OUT gctUINT * MaxWidth,
- + OUT gctUINT * MaxHeight,
- + OUT gctUINT * MaxDepth,
- + OUT gctBOOL * Cubic,
- + OUT gctBOOL * NonPowerOfTwo,
- + OUT gctUINT * VertexSamplers,
- + OUT gctUINT * PixelSamplers
- + );
- +
- +gceSTATUS
- +gcoTEXTURE_GetTiling(
- + IN gcoTEXTURE Texture,
- + IN gctINT preferLevel,
- + OUT gceTILING * Tiling
- + );
- +
- +gceSTATUS
- +gcoTEXTURE_GetClosestFormat(
- + IN gcoHAL Hal,
- + IN gceSURF_FORMAT InFormat,
- + OUT gceSURF_FORMAT* OutFormat
- + );
- +
- +gceSTATUS
- +gcoTEXTURE_RenderIntoMipMap(
- + IN gcoTEXTURE Texture,
- + IN gctINT Level
- + );
- +
- +gceSTATUS
- +gcoTEXTURE_IsRenderable(
- + IN gcoTEXTURE Texture,
- + IN gctUINT Level
- + );
- +
- +gceSTATUS
- +gcoTEXTURE_IsRenderableEx(
- + IN gcoTEXTURE Texture,
- + IN gctUINT Level
- + );
- +
- +gceSTATUS
- +gcoTEXTURE_IsComplete(
- + IN gcoTEXTURE Texture,
- + IN gctINT MaxLevel
- + );
- +
- +gceSTATUS
- +gcoTEXTURE_BindTexture(
- + IN gcoTEXTURE Texture,
- + IN gctINT Target,
- + IN gctINT Sampler,
- + IN gcsTEXTURE_PTR Info
- + );
- +
- +/******************************************************************************\
- +******************************* gcoSTREAM Object ******************************
- +\******************************************************************************/
- +
- +typedef enum _gceVERTEX_FORMAT
- +{
- + gcvVERTEX_BYTE,
- + gcvVERTEX_UNSIGNED_BYTE,
- + gcvVERTEX_SHORT,
- + gcvVERTEX_UNSIGNED_SHORT,
- + gcvVERTEX_INT,
- + gcvVERTEX_UNSIGNED_INT,
- + gcvVERTEX_FIXED,
- + gcvVERTEX_HALF,
- + gcvVERTEX_FLOAT,
- + gcvVERTEX_UNSIGNED_INT_10_10_10_2,
- + gcvVERTEX_INT_10_10_10_2,
- +}
- +gceVERTEX_FORMAT;
- +
- +gceSTATUS
- +gcoSTREAM_Construct(
- + IN gcoHAL Hal,
- + OUT gcoSTREAM * Stream
- + );
- +
- +gceSTATUS
- +gcoSTREAM_Destroy(
- + IN gcoSTREAM Stream
- + );
- +
- +gceSTATUS
- +gcoSTREAM_Upload(
- + IN gcoSTREAM Stream,
- + IN gctCONST_POINTER Buffer,
- + IN gctUINT32 Offset,
- + IN gctSIZE_T Bytes,
- + IN gctBOOL Dynamic
- + );
- +
- +gceSTATUS
- +gcoSTREAM_SetStride(
- + IN gcoSTREAM Stream,
- + IN gctUINT32 Stride
- + );
- +
- +gceSTATUS
- +gcoSTREAM_Lock(
- + IN gcoSTREAM Stream,
- + OUT gctPOINTER * Logical,
- + OUT gctUINT32 * Physical
- + );
- +
- +gceSTATUS
- +gcoSTREAM_Unlock(
- + IN gcoSTREAM Stream
- + );
- +
- +gceSTATUS
- +gcoSTREAM_Reserve(
- + IN gcoSTREAM Stream,
- + IN gctSIZE_T Bytes
- + );
- +
- +gceSTATUS
- +gcoSTREAM_Flush(
- + IN gcoSTREAM Stream
- + );
- +
- +/* Dynamic buffer API. */
- +gceSTATUS
- +gcoSTREAM_SetDynamic(
- + IN gcoSTREAM Stream,
- + IN gctSIZE_T Bytes,
- + IN gctUINT Buffers
- + );
- +
- +typedef struct _gcsSTREAM_INFO
- +{
- + gctUINT index;
- + gceVERTEX_FORMAT format;
- + gctBOOL normalized;
- + gctUINT components;
- + gctSIZE_T size;
- + gctCONST_POINTER data;
- + gctUINT stride;
- +}
- +gcsSTREAM_INFO, * gcsSTREAM_INFO_PTR;
- +
- +gceSTATUS
- +gcoSTREAM_UploadDynamic(
- + IN gcoSTREAM Stream,
- + IN gctUINT VertexCount,
- + IN gctUINT InfoCount,
- + IN gcsSTREAM_INFO_PTR Info,
- + IN gcoVERTEX Vertex
- + );
- +
- +gceSTATUS
- +gcoSTREAM_CPUCacheOperation(
- + IN gcoSTREAM Stream,
- + IN gceCACHEOPERATION Operation
- + );
- +
- +/******************************************************************************\
- +******************************** gcoVERTEX Object ******************************
- +\******************************************************************************/
- +
- +typedef struct _gcsVERTEX_ATTRIBUTES
- +{
- + gceVERTEX_FORMAT format;
- + gctBOOL normalized;
- + gctUINT32 components;
- + gctSIZE_T size;
- + gctUINT32 stream;
- + gctUINT32 offset;
- + gctUINT32 stride;
- +}
- +gcsVERTEX_ATTRIBUTES;
- +
- +gceSTATUS
- +gcoVERTEX_Construct(
- + IN gcoHAL Hal,
- + OUT gcoVERTEX * Vertex
- + );
- +
- +gceSTATUS
- +gcoVERTEX_Destroy(
- + IN gcoVERTEX Vertex
- + );
- +
- +gceSTATUS
- +gcoVERTEX_Reset(
- + IN gcoVERTEX Vertex
- + );
- +
- +gceSTATUS
- +gcoVERTEX_EnableAttribute(
- + IN gcoVERTEX Vertex,
- + IN gctUINT32 Index,
- + IN gceVERTEX_FORMAT Format,
- + IN gctBOOL Normalized,
- + IN gctUINT32 Components,
- + IN gcoSTREAM Stream,
- + IN gctUINT32 Offset,
- + IN gctUINT32 Stride
- + );
- +
- +gceSTATUS
- +gcoVERTEX_DisableAttribute(
- + IN gcoVERTEX Vertex,
- + IN gctUINT32 Index
- + );
- +
- +gceSTATUS
- +gcoVERTEX_Bind(
- + IN gcoVERTEX Vertex
- + );
- +
- +/*******************************************************************************
- +***** gcoVERTEXARRAY Object ***************************************************/
- +
- +typedef struct _gcsVERTEXARRAY
- +{
- + /* Enabled. */
- + gctBOOL enable;
- +
- + /* Number of components. */
- + gctINT size;
- +
- + /* Attribute format. */
- + gceVERTEX_FORMAT format;
- +
- + /* Flag whether the attribute is normalized or not. */
- + gctBOOL normalized;
- +
- + /* Stride of the component. */
- + gctUINT stride;
- +
- + /* Pointer to the attribute data. */
- + gctCONST_POINTER pointer;
- +
- + /* Stream object owning the attribute data. */
- + gcoSTREAM stream;
- +
- + /* Generic values for attribute. */
- + gctFLOAT genericValue[4];
- +
- + /* Generic size for attribute. */
- + gctINT genericSize;
- +
- + /* Vertex shader linkage. */
- + gctUINT linkage;
- +
- +#if gcdUSE_WCLIP_PATCH
- + gctBOOL isPosition;
- +#endif
- +}
- +gcsVERTEXARRAY,
- +* gcsVERTEXARRAY_PTR;
- +
- +gceSTATUS
- +gcoVERTEXARRAY_Construct(
- + IN gcoHAL Hal,
- + OUT gcoVERTEXARRAY * Vertex
- + );
- +
- +gceSTATUS
- +gcoVERTEXARRAY_Destroy(
- + IN gcoVERTEXARRAY Vertex
- + );
- +
- +gceSTATUS
- +gcoVERTEXARRAY_Bind(
- + IN gcoVERTEXARRAY Vertex,
- + IN gctUINT32 EnableBits,
- + IN gcsVERTEXARRAY_PTR VertexArray,
- + IN gctUINT First,
- + IN gctSIZE_T Count,
- + IN gceINDEX_TYPE IndexType,
- + IN gcoINDEX IndexObject,
- + IN gctPOINTER IndexMemory,
- + IN OUT gcePRIMITIVE * PrimitiveType,
- +#if gcdUSE_WCLIP_PATCH
- + IN OUT gctUINT * PrimitiveCount,
- + IN OUT gctFLOAT * wLimitRms,
- + IN OUT gctBOOL * wLimitDirty
- +#else
- + IN OUT gctUINT * PrimitiveCount
- +#endif
- + );
- +
- +gctUINT
- +gcoVERTEXARRAY_GetMaxStream(
- + IN gcoVERTEXARRAY Vertex
- +);
- +
- +gceSTATUS
- +gcoVERTEXARRAY_SetMaxStream(
- + IN gcoVERTEXARRAY Vertex,
- + gctUINT maxStreams
- +);
- +/*******************************************************************************
- +***** Composition *************************************************************/
- +
- +typedef enum _gceCOMPOSITION
- +{
- + gcvCOMPOSE_CLEAR = 1,
- + gcvCOMPOSE_BLUR,
- + gcvCOMPOSE_DIM,
- + gcvCOMPOSE_LAYER
- +}
- +gceCOMPOSITION;
- +
- +typedef struct _gcsCOMPOSITION * gcsCOMPOSITION_PTR;
- +typedef struct _gcsCOMPOSITION
- +{
- + /* Structure size. */
- + gctUINT structSize;
- +
- + /* Composition operation. */
- + gceCOMPOSITION operation;
- +
- + /* Layer to be composed. */
- + gcoSURF layer;
- +
- + /* Source and target coordinates. */
- + gcsRECT srcRect;
- + gcsRECT trgRect;
- +
- + /* Target rectangle */
- + gcsPOINT v0;
- + gcsPOINT v1;
- + gcsPOINT v2;
- +
- + /* Blending parameters. */
- + gctBOOL enableBlending;
- + gctBOOL premultiplied;
- + gctUINT8 alphaValue;
- +
- + /* Clear color. */
- + gctFLOAT r;
- + gctFLOAT g;
- + gctFLOAT b;
- + gctFLOAT a;
- +}
- +gcsCOMPOSITION;
- +
- +gceSTATUS
- +gco3D_ProbeComposition(
- + gctBOOL ResetIfEmpty
- + );
- +
- +gceSTATUS
- +gco3D_CompositionBegin(
- + void
- + );
- +
- +gceSTATUS
- +gco3D_ComposeLayer(
- + IN gcsCOMPOSITION_PTR Layer
- + );
- +
- +gceSTATUS
- +gco3D_CompositionSignals(
- + IN gctHANDLE Process,
- + IN gctSIGNAL Signal1,
- + IN gctSIGNAL Signal2
- + );
- +
- +gceSTATUS
- +gco3D_CompositionEnd(
- + IN gcoSURF Target,
- + IN gctBOOL Synchronous
- + );
- +
- +/* Frame Database */
- +gceSTATUS
- +gcoHAL_AddFrameDB(
- + void
- + );
- +
- +gceSTATUS
- +gcoHAL_DumpFrameDB(
- + gctCONST_STRING Filename OPTIONAL
- + );
- +
- +gceSTATUS
- +gcoHAL_GetSharedInfo(
- + IN gctUINT32 Pid,
- + IN gctUINT32 DataId,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER Data
- + );
- +
- +gceSTATUS
- +gcoHAL_SetSharedInfo(
- + IN gctUINT32 DataId,
- + IN gctPOINTER Data,
- + IN gctSIZE_T Bytes
- + );
- +
- +#if VIVANTE_PROFILER_CONTEXT
- +gceSTATUS
- +gcoHARDWARE_GetContext(
- + IN gcoHARDWARE Hardware,
- + OUT gctUINT32 * Context
- + );
- +#endif
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* VIVANTE_NO_3D */
- +#endif /* __gc_hal_engine_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine_vg.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine_vg.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine_vg.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine_vg.h 2015-03-08 14:27:37.645684500 -0500
- @@ -0,0 +1,904 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_engine_vg_h_
- +#define __gc_hal_engine_vg_h_
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +#include "gc_hal_types.h"
- +
- +/******************************************************************************\
- +******************************** VG Enumerations *******************************
- +\******************************************************************************/
- +
- +/**
- +** @ingroup gcoVG
- +**
- +** @brief Tiling mode for painting and imagig.
- +**
- +** This enumeration defines the tiling modes supported by the HAL. This is
- +** in fact a one-to-one mapping of the OpenVG 1.1 tile modes.
- +*/
- +typedef enum _gceTILE_MODE
- +{
- + gcvTILE_FILL,
- + gcvTILE_PAD,
- + gcvTILE_REPEAT,
- + gcvTILE_REFLECT
- +}
- +gceTILE_MODE;
- +
- +/******************************************************************************/
- +/** @ingroup gcoVG
- +**
- +** @brief The different paint modes.
- +**
- +** This enumeration lists the available paint modes.
- +*/
- +typedef enum _gcePAINT_TYPE
- +{
- + /** Solid color. */
- + gcvPAINT_MODE_SOLID,
- +
- + /** Linear gradient. */
- + gcvPAINT_MODE_LINEAR,
- +
- + /** Radial gradient. */
- + gcvPAINT_MODE_RADIAL,
- +
- + /** Pattern. */
- + gcvPAINT_MODE_PATTERN,
- +
- + /** Mode count. */
- + gcvPAINT_MODE_COUNT
- +}
- +gcePAINT_TYPE;
- +
- +/**
- +** @ingroup gcoVG
- +**
- +** @brief Types of path data supported by HAL.
- +**
- +** This enumeration defines the types of path data supported by the HAL.
- +** This is in fact a one-to-one mapping of the OpenVG 1.1 path types.
- +*/
- +typedef enum _gcePATHTYPE
- +{
- + gcePATHTYPE_UNKNOWN = -1,
- + gcePATHTYPE_INT8,
- + gcePATHTYPE_INT16,
- + gcePATHTYPE_INT32,
- + gcePATHTYPE_FLOAT
- +}
- +gcePATHTYPE;
- +
- +/**
- +** @ingroup gcoVG
- +**
- +** @brief Supported path segment commands.
- +**
- +** This enumeration defines the path segment commands supported by the HAL.
- +*/
- +typedef enum _gceVGCMD
- +{
- + gcvVGCMD_END, /* 0: GCCMD_TS_OPCODE_END */
- + gcvVGCMD_CLOSE, /* 1: GCCMD_TS_OPCODE_CLOSE */
- + gcvVGCMD_MOVE, /* 2: GCCMD_TS_OPCODE_MOVE */
- + gcvVGCMD_MOVE_REL, /* 3: GCCMD_TS_OPCODE_MOVE_REL */
- + gcvVGCMD_LINE, /* 4: GCCMD_TS_OPCODE_LINE */
- + gcvVGCMD_LINE_REL, /* 5: GCCMD_TS_OPCODE_LINE_REL */
- + gcvVGCMD_QUAD, /* 6: GCCMD_TS_OPCODE_QUADRATIC */
- + gcvVGCMD_QUAD_REL, /* 7: GCCMD_TS_OPCODE_QUADRATIC_REL */
- + gcvVGCMD_CUBIC, /* 8: GCCMD_TS_OPCODE_CUBIC */
- + gcvVGCMD_CUBIC_REL, /* 9: GCCMD_TS_OPCODE_CUBIC_REL */
- + gcvVGCMD_BREAK, /* 10: GCCMD_TS_OPCODE_BREAK */
- + gcvVGCMD_HLINE, /* 11: ******* R E S E R V E D *******/
- + gcvVGCMD_HLINE_REL, /* 12: ******* R E S E R V E D *******/
- + gcvVGCMD_VLINE, /* 13: ******* R E S E R V E D *******/
- + gcvVGCMD_VLINE_REL, /* 14: ******* R E S E R V E D *******/
- + gcvVGCMD_SQUAD, /* 15: ******* R E S E R V E D *******/
- + gcvVGCMD_SQUAD_REL, /* 16: ******* R E S E R V E D *******/
- + gcvVGCMD_SCUBIC, /* 17: ******* R E S E R V E D *******/
- + gcvVGCMD_SCUBIC_REL, /* 18: ******* R E S E R V E D *******/
- + gcvVGCMD_SCCWARC, /* 19: ******* R E S E R V E D *******/
- + gcvVGCMD_SCCWARC_REL, /* 20: ******* R E S E R V E D *******/
- + gcvVGCMD_SCWARC, /* 21: ******* R E S E R V E D *******/
- + gcvVGCMD_SCWARC_REL, /* 22: ******* R E S E R V E D *******/
- + gcvVGCMD_LCCWARC, /* 23: ******* R E S E R V E D *******/
- + gcvVGCMD_LCCWARC_REL, /* 24: ******* R E S E R V E D *******/
- + gcvVGCMD_LCWARC, /* 25: ******* R E S E R V E D *******/
- + gcvVGCMD_LCWARC_REL, /* 26: ******* R E S E R V E D *******/
- +
- + /* The width of the command recognized by the hardware on bits. */
- + gcvVGCMD_WIDTH = 5,
- +
- + /* Hardware command mask. */
- + gcvVGCMD_MASK = (1 << gcvVGCMD_WIDTH) - 1,
- +
- + /* Command modifiers. */
- + gcvVGCMD_H_MOD = 1 << gcvVGCMD_WIDTH, /* = 32 */
- + gcvVGCMD_V_MOD = 2 << gcvVGCMD_WIDTH, /* = 64 */
- + gcvVGCMD_S_MOD = 3 << gcvVGCMD_WIDTH, /* = 96 */
- + gcvVGCMD_ARC_MOD = 4 << gcvVGCMD_WIDTH, /* = 128 */
- +
- + /* Emulated LINE commands. */
- + gcvVGCMD_HLINE_EMUL = gcvVGCMD_H_MOD | gcvVGCMD_LINE, /* = 36 */
- + gcvVGCMD_HLINE_EMUL_REL = gcvVGCMD_H_MOD | gcvVGCMD_LINE_REL, /* = 37 */
- + gcvVGCMD_VLINE_EMUL = gcvVGCMD_V_MOD | gcvVGCMD_LINE, /* = 68 */
- + gcvVGCMD_VLINE_EMUL_REL = gcvVGCMD_V_MOD | gcvVGCMD_LINE_REL, /* = 69 */
- +
- + /* Emulated SMOOTH commands. */
- + gcvVGCMD_SQUAD_EMUL = gcvVGCMD_S_MOD | gcvVGCMD_QUAD, /* = 102 */
- + gcvVGCMD_SQUAD_EMUL_REL = gcvVGCMD_S_MOD | gcvVGCMD_QUAD_REL, /* = 103 */
- + gcvVGCMD_SCUBIC_EMUL = gcvVGCMD_S_MOD | gcvVGCMD_CUBIC, /* = 104 */
- + gcvVGCMD_SCUBIC_EMUL_REL = gcvVGCMD_S_MOD | gcvVGCMD_CUBIC_REL, /* = 105 */
- +
- + /* Emulation ARC commands. */
- + gcvVGCMD_ARC_LINE = gcvVGCMD_ARC_MOD | gcvVGCMD_LINE, /* = 132 */
- + gcvVGCMD_ARC_LINE_REL = gcvVGCMD_ARC_MOD | gcvVGCMD_LINE_REL, /* = 133 */
- + gcvVGCMD_ARC_QUAD = gcvVGCMD_ARC_MOD | gcvVGCMD_QUAD, /* = 134 */
- + gcvVGCMD_ARC_QUAD_REL = gcvVGCMD_ARC_MOD | gcvVGCMD_QUAD_REL /* = 135 */
- +}
- +gceVGCMD;
- +typedef enum _gceVGCMD * gceVGCMD_PTR;
- +
- +/**
- +** @ingroup gcoVG
- +**
- +** @brief Blending modes supported by the HAL.
- +**
- +** This enumeration defines the blending modes supported by the HAL. This is
- +** in fact a one-to-one mapping of the OpenVG 1.1 blending modes.
- +*/
- +typedef enum _gceVG_BLEND
- +{
- + gcvVG_BLEND_SRC,
- + gcvVG_BLEND_SRC_OVER,
- + gcvVG_BLEND_DST_OVER,
- + gcvVG_BLEND_SRC_IN,
- + gcvVG_BLEND_DST_IN,
- + gcvVG_BLEND_MULTIPLY,
- + gcvVG_BLEND_SCREEN,
- + gcvVG_BLEND_DARKEN,
- + gcvVG_BLEND_LIGHTEN,
- + gcvVG_BLEND_ADDITIVE,
- + gcvVG_BLEND_SUBTRACT,
- + gcvVG_BLEND_FILTER
- +}
- +gceVG_BLEND;
- +
- +/**
- +** @ingroup gcoVG
- +**
- +** @brief Image modes supported by the HAL.
- +**
- +** This enumeration defines the image modes supported by the HAL. This is
- +** in fact a one-to-one mapping of the OpenVG 1.1 image modes with the addition
- +** of NO IMAGE.
- +*/
- +typedef enum _gceVG_IMAGE
- +{
- + gcvVG_IMAGE_NONE,
- + gcvVG_IMAGE_NORMAL,
- + gcvVG_IMAGE_MULTIPLY,
- + gcvVG_IMAGE_STENCIL,
- + gcvVG_IMAGE_FILTER
- +}
- +gceVG_IMAGE;
- +
- +/**
- +** @ingroup gcoVG
- +**
- +** @brief Filter mode patterns and imaging.
- +**
- +** This enumeration defines the filter modes supported by the HAL.
- +*/
- +typedef enum _gceIMAGE_FILTER
- +{
- + gcvFILTER_POINT,
- + gcvFILTER_LINEAR,
- + gcvFILTER_BI_LINEAR
- +}
- +gceIMAGE_FILTER;
- +
- +/**
- +** @ingroup gcoVG
- +**
- +** @brief Primitive modes supported by the HAL.
- +**
- +** This enumeration defines the primitive modes supported by the HAL.
- +*/
- +typedef enum _gceVG_PRIMITIVE
- +{
- + gcvVG_SCANLINE,
- + gcvVG_RECTANGLE,
- + gcvVG_TESSELLATED,
- + gcvVG_TESSELLATED_TILED
- +}
- +gceVG_PRIMITIVE;
- +
- +/**
- +** @ingroup gcoVG
- +**
- +** @brief Rendering quality modes supported by the HAL.
- +**
- +** This enumeration defines the rendering quality modes supported by the HAL.
- +*/
- +typedef enum _gceRENDER_QUALITY
- +{
- + gcvVG_NONANTIALIASED,
- + gcvVG_2X2_MSAA,
- + gcvVG_2X4_MSAA,
- + gcvVG_4X4_MSAA
- +}
- +gceRENDER_QUALITY;
- +
- +/**
- +** @ingroup gcoVG
- +**
- +** @brief Fill rules supported by the HAL.
- +**
- +** This enumeration defines the fill rules supported by the HAL.
- +*/
- +typedef enum _gceFILL_RULE
- +{
- + gcvVG_EVEN_ODD,
- + gcvVG_NON_ZERO
- +}
- +gceFILL_RULE;
- +
- +/**
- +** @ingroup gcoVG
- +**
- +** @brief Cap styles supported by the HAL.
- +**
- +** This enumeration defines the cap styles supported by the HAL.
- +*/
- +typedef enum _gceCAP_STYLE
- +{
- + gcvCAP_BUTT,
- + gcvCAP_ROUND,
- + gcvCAP_SQUARE
- +}
- +gceCAP_STYLE;
- +
- +/**
- +** @ingroup gcoVG
- +**
- +** @brief Join styles supported by the HAL.
- +**
- +** This enumeration defines the join styles supported by the HAL.
- +*/
- +typedef enum _gceJOIN_STYLE
- +{
- + gcvJOIN_MITER,
- + gcvJOIN_ROUND,
- + gcvJOIN_BEVEL
- +}
- +gceJOIN_STYLE;
- +
- +/**
- +** @ingroup gcoVG
- +**
- +** @brief Channel mask values.
- +**
- +** This enumeration defines the values for channel mask used in image
- +** filtering.
- +*/
- +
- +/* Base values for channel mask definitions. */
- +#define gcvCHANNEL_X (0)
- +#define gcvCHANNEL_R (1 << 0)
- +#define gcvCHANNEL_G (1 << 1)
- +#define gcvCHANNEL_B (1 << 2)
- +#define gcvCHANNEL_A (1 << 3)
- +
- +typedef enum _gceCHANNEL
- +{
- + gcvCHANNEL_XXXX = (gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_X),
- + gcvCHANNEL_XXXA = (gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_A),
- + gcvCHANNEL_XXBX = (gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_B | gcvCHANNEL_X),
- + gcvCHANNEL_XXBA = (gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_B | gcvCHANNEL_A),
- +
- + gcvCHANNEL_XGXX = (gcvCHANNEL_X | gcvCHANNEL_G | gcvCHANNEL_X | gcvCHANNEL_X),
- + gcvCHANNEL_XGXA = (gcvCHANNEL_X | gcvCHANNEL_G | gcvCHANNEL_X | gcvCHANNEL_A),
- + gcvCHANNEL_XGBX = (gcvCHANNEL_X | gcvCHANNEL_G | gcvCHANNEL_B | gcvCHANNEL_X),
- + gcvCHANNEL_XGBA = (gcvCHANNEL_X | gcvCHANNEL_G | gcvCHANNEL_B | gcvCHANNEL_A),
- +
- + gcvCHANNEL_RXXX = (gcvCHANNEL_R | gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_X),
- + gcvCHANNEL_RXXA = (gcvCHANNEL_R | gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_A),
- + gcvCHANNEL_RXBX = (gcvCHANNEL_R | gcvCHANNEL_X | gcvCHANNEL_B | gcvCHANNEL_X),
- + gcvCHANNEL_RXBA = (gcvCHANNEL_R | gcvCHANNEL_X | gcvCHANNEL_B | gcvCHANNEL_A),
- +
- + gcvCHANNEL_RGXX = (gcvCHANNEL_R | gcvCHANNEL_G | gcvCHANNEL_X | gcvCHANNEL_X),
- + gcvCHANNEL_RGXA = (gcvCHANNEL_R | gcvCHANNEL_G | gcvCHANNEL_X | gcvCHANNEL_A),
- + gcvCHANNEL_RGBX = (gcvCHANNEL_R | gcvCHANNEL_G | gcvCHANNEL_B | gcvCHANNEL_X),
- + gcvCHANNEL_RGBA = (gcvCHANNEL_R | gcvCHANNEL_G | gcvCHANNEL_B | gcvCHANNEL_A),
- +}
- +gceCHANNEL;
- +
- +/******************************************************************************\
- +******************************** VG Structures *******************************
- +\******************************************************************************/
- +
- +/**
- +** @ingroup gcoVG
- +**
- +** @brief Definition of the color ramp used by the gradient paints.
- +**
- +** The gcsCOLOR_RAMP structure defines the layout of one single color inside
- +** a color ramp which is used by gradient paints.
- +*/
- +typedef struct _gcsCOLOR_RAMP
- +{
- + /** Value for the color stop. */
- + gctFLOAT stop;
- +
- + /** Red color channel value for the color stop. */
- + gctFLOAT red;
- +
- + /** Green color channel value for the color stop. */
- + gctFLOAT green;
- +
- + /** Blue color channel value for the color stop. */
- + gctFLOAT blue;
- +
- + /** Alpha color channel value for the color stop. */
- + gctFLOAT alpha;
- +}
- +gcsCOLOR_RAMP, * gcsCOLOR_RAMP_PTR;
- +
- +/**
- +** @ingroup gcoVG
- +**
- +** @brief Definition of the color ramp used by the gradient paints in fixed form.
- +**
- +** The gcsCOLOR_RAMP structure defines the layout of one single color inside
- +** a color ramp which is used by gradient paints.
- +*/
- +typedef struct _gcsFIXED_COLOR_RAMP
- +{
- + /** Value for the color stop. */
- + gctFIXED_POINT stop;
- +
- + /** Red color channel value for the color stop. */
- + gctFIXED_POINT red;
- +
- + /** Green color channel value for the color stop. */
- + gctFIXED_POINT green;
- +
- + /** Blue color channel value for the color stop. */
- + gctFIXED_POINT blue;
- +
- + /** Alpha color channel value for the color stop. */
- + gctFIXED_POINT alpha;
- +}
- +gcsFIXED_COLOR_RAMP, * gcsFIXED_COLOR_RAMP_PTR;
- +
- +
- +/**
- +** @ingroup gcoVG
- +**
- +** @brief Rectangle structure used by the gcoVG object.
- +**
- +** This structure defines the layout of a rectangle. Make sure width and
- +** height are larger than 0.
- +*/
- +typedef struct _gcsVG_RECT * gcsVG_RECT_PTR;
- +typedef struct _gcsVG_RECT
- +{
- + /** Left location of the rectangle. */
- + gctINT x;
- +
- + /** Top location of the rectangle. */
- + gctINT y;
- +
- + /** Width of the rectangle. */
- + gctINT width;
- +
- + /** Height of the rectangle. */
- + gctINT height;
- +}
- +gcsVG_RECT;
- +
- +/**
- +** @ingroup gcoVG
- +**
- +** @brief Path command buffer attribute structure.
- +**
- +** The gcsPATH_BUFFER_INFO structure contains the specifics about
- +** the layout of the path data command buffer.
- +*/
- +typedef struct _gcsPATH_BUFFER_INFO * gcsPATH_BUFFER_INFO_PTR;
- +typedef struct _gcsPATH_BUFFER_INFO
- +{
- + gctUINT reservedForHead;
- + gctUINT reservedForTail;
- +}
- +gcsPATH_BUFFER_INFO;
- +
- +/**
- +** @ingroup gcoVG
- +**
- +** @brief Definition of the path data container structure.
- +**
- +** The gcsPATH structure defines the layout of the path data container.
- +*/
- +typedef struct _gcsPATH_DATA * gcsPATH_DATA_PTR;
- +typedef struct _gcsPATH_DATA
- +{
- + /* Data container in command buffer format. */
- + gcsCMDBUFFER data;
- +
- + /* Path data type. */
- + gcePATHTYPE dataType;
- +}
- +gcsPATH_DATA;
- +
- +
- +/******************************************************************************\
- +********************************* gcoHAL Object ********************************
- +\******************************************************************************/
- +
- +/* Query path data storage attributes. */
- +gceSTATUS
- +gcoHAL_QueryPathStorage(
- + IN gcoHAL Hal,
- + OUT gcsPATH_BUFFER_INFO_PTR Information
- + );
- +
- +/* Associate a completion signal with the command buffer. */
- +gceSTATUS
- +gcoHAL_AssociateCompletion(
- + IN gcoHAL Hal,
- + IN gcsPATH_DATA_PTR PathData
- + );
- +
- +/* Release the current command buffer completion signal. */
- +gceSTATUS
- +gcoHAL_DeassociateCompletion(
- + IN gcoHAL Hal,
- + IN gcsPATH_DATA_PTR PathData
- + );
- +
- +/* Verify whether the command buffer is still in use. */
- +gceSTATUS
- +gcoHAL_CheckCompletion(
- + IN gcoHAL Hal,
- + IN gcsPATH_DATA_PTR PathData
- + );
- +
- +/* Wait until the command buffer is no longer in use. */
- +gceSTATUS
- +gcoHAL_WaitCompletion(
- + IN gcoHAL Hal,
- + IN gcsPATH_DATA_PTR PathData
- + );
- +
- +/* Flush the pixel cache. */
- +gceSTATUS
- +gcoHAL_Flush(
- + IN gcoHAL Hal
- + );
- +
- +/* Split a harwdare address into pool and offset. */
- +gceSTATUS
- +gcoHAL_SplitAddress(
- + IN gcoHAL Hal,
- + IN gctUINT32 Address,
- + OUT gcePOOL * Pool,
- + OUT gctUINT32 * Offset
- + );
- +
- +/* Combine pool and offset into a harwdare address. */
- +gceSTATUS
- +gcoHAL_CombineAddress(
- + IN gcoHAL Hal,
- + IN gcePOOL Pool,
- + IN gctUINT32 Offset,
- + OUT gctUINT32 * Address
- + );
- +
- +/* Schedule to free linear video memory allocated. */
- +gceSTATUS
- +gcoHAL_ScheduleVideoMemory(
- + IN gcoHAL Hal,
- + IN gctUINT64 Node
- + );
- +
- +/* Free linear video memory allocated with gcoHAL_AllocateLinearVideoMemory. */
- +gceSTATUS
- +gcoHAL_FreeVideoMemory(
- + IN gcoHAL Hal,
- + IN gctUINT64 Node
- + );
- +
- +/* Query command buffer attributes. */
- +gceSTATUS
- +gcoHAL_QueryCommandBuffer(
- + IN gcoHAL Hal,
- + OUT gcsCOMMAND_BUFFER_INFO_PTR Information
- + );
- +/* Allocate and lock linear video memory. */
- +gceSTATUS
- +gcoHAL_AllocateLinearVideoMemory(
- + IN gcoHAL Hal,
- + IN gctUINT Size,
- + IN gctUINT Alignment,
- + IN gcePOOL Pool,
- + OUT gctUINT64 * Node,
- + OUT gctUINT32 * Address,
- + OUT gctPOINTER * Memory
- + );
- +
- +/* Align the specified size accordingly to the hardware requirements. */
- +gceSTATUS
- +gcoHAL_GetAlignedSurfaceSize(
- + IN gcoHAL Hal,
- + IN gceSURF_TYPE Type,
- + IN OUT gctUINT32_PTR Width,
- + IN OUT gctUINT32_PTR Height
- + );
- +
- +gceSTATUS
- +gcoHAL_ReserveTask(
- + IN gcoHAL Hal,
- + IN gceBLOCK Block,
- + IN gctUINT TaskCount,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER * Memory
- + );
- +/******************************************************************************\
- +********************************** gcoVG Object ********************************
- +\******************************************************************************/
- +
- +/** @defgroup gcoVG gcoVG
- +**
- +** The gcoVG object abstracts the VG hardware pipe.
- +*/
- +
- +gctBOOL
- +gcoVG_IsMaskSupported(
- + IN gceSURF_FORMAT Format
- + );
- +
- +gctBOOL
- +gcoVG_IsTargetSupported(
- + IN gceSURF_FORMAT Format
- + );
- +
- +gctBOOL
- +gcoVG_IsImageSupported(
- + IN gceSURF_FORMAT Format
- + );
- +
- +gctUINT8 gcoVG_PackColorComponent(
- + gctFLOAT Value
- + );
- +
- +gceSTATUS
- +gcoVG_Construct(
- + IN gcoHAL Hal,
- + OUT gcoVG * Vg
- + );
- +
- +gceSTATUS
- +gcoVG_Destroy(
- + IN gcoVG Vg
- + );
- +
- +gceSTATUS
- +gcoVG_SetTarget(
- + IN gcoVG Vg,
- + IN gcoSURF Target
- + );
- +
- +gceSTATUS
- +gcoVG_UnsetTarget(
- + IN gcoVG Vg,
- + IN gcoSURF Surface
- + );
- +
- +gceSTATUS
- +gcoVG_SetUserToSurface(
- + IN gcoVG Vg,
- + IN gctFLOAT UserToSurface[9]
- + );
- +
- +gceSTATUS
- +gcoVG_SetSurfaceToImage(
- + IN gcoVG Vg,
- + IN gctFLOAT SurfaceToImage[9]
- + );
- +
- +gceSTATUS
- +gcoVG_EnableMask(
- + IN gcoVG Vg,
- + IN gctBOOL Enable
- + );
- +
- +gceSTATUS
- +gcoVG_SetMask(
- + IN gcoVG Vg,
- + IN gcoSURF Mask
- + );
- +
- +gceSTATUS
- +gcoVG_UnsetMask(
- + IN gcoVG Vg,
- + IN gcoSURF Surface
- + );
- +
- +gceSTATUS
- +gcoVG_FlushMask(
- + IN gcoVG Vg
- + );
- +
- +gceSTATUS
- +gcoVG_EnableScissor(
- + IN gcoVG Vg,
- + IN gctBOOL Enable
- + );
- +
- +gceSTATUS
- +gcoVG_SetScissor(
- + IN gcoVG Vg,
- + IN gctSIZE_T RectangleCount,
- + IN gcsVG_RECT_PTR Rectangles
- + );
- +
- +gceSTATUS
- +gcoVG_EnableColorTransform(
- + IN gcoVG Vg,
- + IN gctBOOL Enable
- + );
- +
- +gceSTATUS
- +gcoVG_SetColorTransform(
- + IN gcoVG Vg,
- + IN gctFLOAT ColorTransform[8]
- + );
- +
- +gceSTATUS
- +gcoVG_SetTileFillColor(
- + IN gcoVG Vg,
- + IN gctFLOAT Red,
- + IN gctFLOAT Green,
- + IN gctFLOAT Blue,
- + IN gctFLOAT Alpha
- + );
- +
- +gceSTATUS
- +gcoVG_SetSolidPaint(
- + IN gcoVG Vg,
- + IN gctUINT8 Red,
- + IN gctUINT8 Green,
- + IN gctUINT8 Blue,
- + IN gctUINT8 Alpha
- + );
- +
- +gceSTATUS
- +gcoVG_SetLinearPaint(
- + IN gcoVG Vg,
- + IN gctFLOAT Constant,
- + IN gctFLOAT StepX,
- + IN gctFLOAT StepY
- + );
- +
- +gceSTATUS
- +gcoVG_SetRadialPaint(
- + IN gcoVG Vg,
- + IN gctFLOAT LinConstant,
- + IN gctFLOAT LinStepX,
- + IN gctFLOAT LinStepY,
- + IN gctFLOAT RadConstant,
- + IN gctFLOAT RadStepX,
- + IN gctFLOAT RadStepY,
- + IN gctFLOAT RadStepXX,
- + IN gctFLOAT RadStepYY,
- + IN gctFLOAT RadStepXY
- + );
- +
- +gceSTATUS
- +gcoVG_SetPatternPaint(
- + IN gcoVG Vg,
- + IN gctFLOAT UConstant,
- + IN gctFLOAT UStepX,
- + IN gctFLOAT UStepY,
- + IN gctFLOAT VConstant,
- + IN gctFLOAT VStepX,
- + IN gctFLOAT VStepY,
- + IN gctBOOL Linear
- + );
- +
- +gceSTATUS
- +gcoVG_SetColorRamp(
- + IN gcoVG Vg,
- + IN gcoSURF ColorRamp,
- + IN gceTILE_MODE ColorRampSpreadMode
- + );
- +
- +gceSTATUS
- +gcoVG_SetPattern(
- + IN gcoVG Vg,
- + IN gcoSURF Pattern,
- + IN gceTILE_MODE TileMode,
- + IN gceIMAGE_FILTER Filter
- + );
- +
- +gceSTATUS
- +gcoVG_SetImageMode(
- + IN gcoVG Vg,
- + IN gceVG_IMAGE Mode
- + );
- +
- +gceSTATUS
- +gcoVG_SetBlendMode(
- + IN gcoVG Vg,
- + IN gceVG_BLEND Mode
- + );
- +
- +gceSTATUS
- +gcoVG_SetRenderingQuality(
- + IN gcoVG Vg,
- + IN gceRENDER_QUALITY Quality
- + );
- +
- +gceSTATUS
- +gcoVG_SetFillRule(
- + IN gcoVG Vg,
- + IN gceFILL_RULE FillRule
- + );
- +
- +gceSTATUS
- +gcoVG_FinalizePath(
- + IN gcoVG Vg,
- + IN gcsPATH_DATA_PTR PathData
- + );
- +
- +gceSTATUS
- +gcoVG_Clear(
- + IN gcoVG Vg,
- + IN gctINT X,
- + IN gctINT Y,
- + IN gctINT Width,
- + IN gctINT Height
- + );
- +
- +gceSTATUS
- +gcoVG_DrawPath(
- + IN gcoVG Vg,
- + IN gcsPATH_DATA_PTR PathData,
- + IN gctFLOAT Scale,
- + IN gctFLOAT Bias,
- + IN gctBOOL SoftwareTesselation
- + );
- +
- +gceSTATUS
- +gcoVG_DrawImage(
- + IN gcoVG Vg,
- + IN gcoSURF Source,
- + IN gcsPOINT_PTR SourceOrigin,
- + IN gcsPOINT_PTR TargetOrigin,
- + IN gcsSIZE_PTR SourceSize,
- + IN gctINT SourceX,
- + IN gctINT SourceY,
- + IN gctINT TargetX,
- + IN gctINT TargetY,
- + IN gctINT Width,
- + IN gctINT Height,
- + IN gctBOOL Mask
- + );
- +
- +gceSTATUS
- +gcoVG_TesselateImage(
- + IN gcoVG Vg,
- + IN gcoSURF Image,
- + IN gcsVG_RECT_PTR Rectangle,
- + IN gceIMAGE_FILTER Filter,
- + IN gctBOOL Mask,
- + IN gctBOOL SoftwareTesselation
- + );
- +
- +gceSTATUS
- +gcoVG_Blit(
- + IN gcoVG Vg,
- + IN gcoSURF Source,
- + IN gcoSURF Target,
- + IN gcsVG_RECT_PTR SrcRect,
- + IN gcsVG_RECT_PTR TrgRect,
- + IN gceIMAGE_FILTER Filter,
- + IN gceVG_BLEND Mode
- + );
- +
- +gceSTATUS
- +gcoVG_ColorMatrix(
- + IN gcoVG Vg,
- + IN gcoSURF Source,
- + IN gcoSURF Target,
- + IN const gctFLOAT * Matrix,
- + IN gceCHANNEL ColorChannels,
- + IN gctBOOL FilterLinear,
- + IN gctBOOL FilterPremultiplied,
- + IN gcsPOINT_PTR SourceOrigin,
- + IN gcsPOINT_PTR TargetOrigin,
- + IN gctINT Width,
- + IN gctINT Height
- + );
- +
- +gceSTATUS
- +gcoVG_SeparableConvolve(
- + IN gcoVG Vg,
- + IN gcoSURF Source,
- + IN gcoSURF Target,
- + IN gctINT KernelWidth,
- + IN gctINT KernelHeight,
- + IN gctINT ShiftX,
- + IN gctINT ShiftY,
- + IN const gctINT16 * KernelX,
- + IN const gctINT16 * KernelY,
- + IN gctFLOAT Scale,
- + IN gctFLOAT Bias,
- + IN gceTILE_MODE TilingMode,
- + IN gctFLOAT_PTR FillColor,
- + IN gceCHANNEL ColorChannels,
- + IN gctBOOL FilterLinear,
- + IN gctBOOL FilterPremultiplied,
- + IN gcsPOINT_PTR SourceOrigin,
- + IN gcsPOINT_PTR TargetOrigin,
- + IN gcsSIZE_PTR SourceSize,
- + IN gctINT Width,
- + IN gctINT Height
- + );
- +
- +gceSTATUS
- +gcoVG_GaussianBlur(
- + IN gcoVG Vg,
- + IN gcoSURF Source,
- + IN gcoSURF Target,
- + IN gctFLOAT StdDeviationX,
- + IN gctFLOAT StdDeviationY,
- + IN gceTILE_MODE TilingMode,
- + IN gctFLOAT_PTR FillColor,
- + IN gceCHANNEL ColorChannels,
- + IN gctBOOL FilterLinear,
- + IN gctBOOL FilterPremultiplied,
- + IN gcsPOINT_PTR SourceOrigin,
- + IN gcsPOINT_PTR TargetOrigin,
- + IN gcsSIZE_PTR SourceSize,
- + IN gctINT Width,
- + IN gctINT Height
- + );
- +
- +gceSTATUS
- +gcoVG_EnableDither(
- + IN gcoVG Vg,
- + IN gctBOOL Enable
- + );
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* __gc_hal_vg_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h 2015-03-08 14:27:37.645684500 -0500
- @@ -0,0 +1,965 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_enum_h_
- +#define __gc_hal_enum_h_
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +/* Chip models. */
- +typedef enum _gceCHIPMODEL
- +{
- + gcv300 = 0x0300,
- + gcv320 = 0x0320,
- + gcv350 = 0x0350,
- + gcv355 = 0x0355,
- + gcv400 = 0x0400,
- + gcv410 = 0x0410,
- + gcv420 = 0x0420,
- + gcv450 = 0x0450,
- + gcv500 = 0x0500,
- + gcv530 = 0x0530,
- + gcv600 = 0x0600,
- + gcv700 = 0x0700,
- + gcv800 = 0x0800,
- + gcv860 = 0x0860,
- + gcv880 = 0x0880,
- + gcv1000 = 0x1000,
- + gcv2000 = 0x2000,
- + gcv2100 = 0x2100,
- + gcv4000 = 0x4000,
- +}
- +gceCHIPMODEL;
- +
- +/* Chip features. */
- +typedef enum _gceFEATURE
- +{
- + gcvFEATURE_PIPE_2D = 0,
- + gcvFEATURE_PIPE_3D,
- + gcvFEATURE_PIPE_VG,
- + gcvFEATURE_DC,
- + gcvFEATURE_HIGH_DYNAMIC_RANGE,
- + gcvFEATURE_MODULE_CG,
- + gcvFEATURE_MIN_AREA,
- + gcvFEATURE_BUFFER_INTERLEAVING,
- + gcvFEATURE_BYTE_WRITE_2D,
- + gcvFEATURE_ENDIANNESS_CONFIG,
- + gcvFEATURE_DUAL_RETURN_BUS,
- + gcvFEATURE_DEBUG_MODE,
- + gcvFEATURE_YUY2_RENDER_TARGET,
- + gcvFEATURE_FRAGMENT_PROCESSOR,
- + gcvFEATURE_2DPE20,
- + gcvFEATURE_FAST_CLEAR,
- + gcvFEATURE_YUV420_TILER,
- + gcvFEATURE_YUY2_AVERAGING,
- + gcvFEATURE_FLIP_Y,
- + gcvFEATURE_EARLY_Z,
- + gcvFEATURE_Z_COMPRESSION,
- + gcvFEATURE_MSAA,
- + gcvFEATURE_SPECIAL_ANTI_ALIASING,
- + gcvFEATURE_SPECIAL_MSAA_LOD,
- + gcvFEATURE_422_TEXTURE_COMPRESSION,
- + gcvFEATURE_DXT_TEXTURE_COMPRESSION,
- + gcvFEATURE_ETC1_TEXTURE_COMPRESSION,
- + gcvFEATURE_CORRECT_TEXTURE_CONVERTER,
- + gcvFEATURE_TEXTURE_8K,
- + gcvFEATURE_SCALER,
- + gcvFEATURE_YUV420_SCALER,
- + gcvFEATURE_SHADER_HAS_W,
- + gcvFEATURE_SHADER_HAS_SIGN,
- + gcvFEATURE_SHADER_HAS_FLOOR,
- + gcvFEATURE_SHADER_HAS_CEIL,
- + gcvFEATURE_SHADER_HAS_SQRT,
- + gcvFEATURE_SHADER_HAS_TRIG,
- + gcvFEATURE_VAA,
- + gcvFEATURE_HZ,
- + gcvFEATURE_CORRECT_STENCIL,
- + gcvFEATURE_VG20,
- + gcvFEATURE_VG_FILTER,
- + gcvFEATURE_VG21,
- + gcvFEATURE_VG_DOUBLE_BUFFER,
- + gcvFEATURE_MC20,
- + gcvFEATURE_SUPER_TILED,
- + gcvFEATURE_2D_FILTERBLIT_PLUS_ALPHABLEND,
- + gcvFEATURE_2D_DITHER,
- + gcvFEATURE_2D_A8_TARGET,
- + gcvFEATURE_2D_FILTERBLIT_FULLROTATION,
- + gcvFEATURE_2D_BITBLIT_FULLROTATION,
- + gcvFEATURE_WIDE_LINE,
- + gcvFEATURE_FC_FLUSH_STALL,
- + gcvFEATURE_FULL_DIRECTFB,
- + gcvFEATURE_HALF_FLOAT_PIPE,
- + gcvFEATURE_LINE_LOOP,
- + gcvFEATURE_2D_YUV_BLIT,
- + gcvFEATURE_2D_TILING,
- + gcvFEATURE_NON_POWER_OF_TWO,
- + gcvFEATURE_3D_TEXTURE,
- + gcvFEATURE_TEXTURE_ARRAY,
- + gcvFEATURE_TILE_FILLER,
- + gcvFEATURE_LOGIC_OP,
- + gcvFEATURE_COMPOSITION,
- + gcvFEATURE_MIXED_STREAMS,
- + gcvFEATURE_2D_MULTI_SOURCE_BLT,
- + gcvFEATURE_END_EVENT,
- + gcvFEATURE_VERTEX_10_10_10_2,
- + gcvFEATURE_TEXTURE_10_10_10_2,
- + gcvFEATURE_TEXTURE_ANISOTROPIC_FILTERING,
- + gcvFEATURE_TEXTURE_FLOAT_HALF_FLOAT,
- + gcvFEATURE_2D_ROTATION_STALL_FIX,
- + gcvFEATURE_2D_MULTI_SOURCE_BLT_EX,
- + gcvFEATURE_BUG_FIXES10,
- + gcvFEATURE_2D_MINOR_TILING,
- + /* Supertiled compressed textures are supported. */
- + gcvFEATURE_TEX_COMPRRESSION_SUPERTILED,
- + gcvFEATURE_FAST_MSAA,
- + gcvFEATURE_BUG_FIXED_INDEXED_TRIANGLE_STRIP,
- + gcvFEATURE_TEXTURE_TILED_READ,
- + gcvFEATURE_DEPTH_BIAS_FIX,
- + gcvFEATURE_RECT_PRIMITIVE,
- + gcvFEATURE_BUG_FIXES11,
- + gcvFEATURE_SUPERTILED_TEXTURE,
- + gcvFEATURE_2D_NO_COLORBRUSH_INDEX8,
- + gcvFEATURE_RS_YUV_TARGET,
- + gcvFEATURE_2D_FC_SOURCE,
- + gcvFEATURE_PE_DITHER_FIX,
- + gcvFEATURE_2D_YUV_SEPARATE_STRIDE,
- + gcvFEATURE_FRUSTUM_CLIP_FIX,
- + gcvFEATURE_TEXTURE_LINEAR,
- + gcvFEATURE_TEXTURE_YUV_ASSEMBLER,
- + gcvFEATURE_SHADER_HAS_INSTRUCTION_CACHE,
- + gcvFEATURE_DYNAMIC_FREQUENCY_SCALING,
- + gcvFEATURE_BUGFIX15,
- + gcvFEATURE_2D_GAMMA,
- + gcvFEATURE_2D_COLOR_SPACE_CONVERSION,
- + gcvFEATURE_2D_SUPER_TILE_VERSION,
- + gcvFEATURE_2D_MIRROR_EXTENSION,
- + gcvFEATURE_2D_SUPER_TILE_V1,
- + gcvFEATURE_2D_SUPER_TILE_V2,
- + gcvFEATURE_2D_SUPER_TILE_V3,
- + gcvFEATURE_2D_MULTI_SOURCE_BLT_EX2,
- + gcvFEATURE_ELEMENT_INDEX_UINT,
- + gcvFEATURE_2D_COMPRESSION,
- + gcvFEATURE_2D_OPF_YUV_OUTPUT,
- + gcvFEATURE_2D_MULTI_SRC_BLT_TO_UNIFIED_DST_RECT,
- + gcvFEATURE_2D_YUV_MODE,
- + gcvFEATURE_DECOMPRESS_Z16,
- + gcvFEATURE_LINEAR_RENDER_TARGET,
- + gcvFEATURE_BUG_FIXES8,
- + gcvFEATURE_HALTI2,
- + gcvFEATURE_MMU,
- +}
- +gceFEATURE;
- +
- +/* Chip Power Status. */
- +typedef enum _gceCHIPPOWERSTATE
- +{
- + gcvPOWER_ON = 0,
- + gcvPOWER_OFF,
- + gcvPOWER_IDLE,
- + gcvPOWER_SUSPEND,
- + gcvPOWER_SUSPEND_ATPOWERON,
- + gcvPOWER_OFF_ATPOWERON,
- + gcvPOWER_IDLE_BROADCAST,
- + gcvPOWER_SUSPEND_BROADCAST,
- + gcvPOWER_OFF_BROADCAST,
- + gcvPOWER_OFF_RECOVERY,
- + gcvPOWER_OFF_TIMEOUT,
- + gcvPOWER_ON_AUTO
- +}
- +gceCHIPPOWERSTATE;
- +
- +/* CPU cache operations */
- +typedef enum _gceCACHEOPERATION
- +{
- + gcvCACHE_CLEAN = 0x01,
- + gcvCACHE_INVALIDATE = 0x02,
- + gcvCACHE_FLUSH = gcvCACHE_CLEAN | gcvCACHE_INVALIDATE,
- + gcvCACHE_MEMORY_BARRIER = 0x04
- +}
- +gceCACHEOPERATION;
- +
- +/* Surface types. */
- +typedef enum _gceSURF_TYPE
- +{
- + gcvSURF_TYPE_UNKNOWN = 0,
- + gcvSURF_INDEX,
- + gcvSURF_VERTEX,
- + gcvSURF_TEXTURE,
- + gcvSURF_RENDER_TARGET,
- + gcvSURF_DEPTH,
- + gcvSURF_BITMAP,
- + gcvSURF_TILE_STATUS,
- + gcvSURF_IMAGE,
- + gcvSURF_MASK,
- + gcvSURF_SCISSOR,
- + gcvSURF_HIERARCHICAL_DEPTH,
- + gcvSURF_NUM_TYPES, /* Make sure this is the last one! */
- +
- + /* Combinations. */
- + gcvSURF_NO_TILE_STATUS = 0x100,
- + gcvSURF_NO_VIDMEM = 0x200, /* Used to allocate surfaces with no underlying vidmem node.
- + In Android, vidmem node is allocated by another process. */
- + gcvSURF_CACHEABLE = 0x400, /* Used to allocate a cacheable surface */
- + gcvSURF_FLIP = 0x800, /* The Resolve Target the will been flip resolve from RT */
- + gcvSURF_TILE_STATUS_DIRTY = 0x1000, /* Init tile status to all dirty */
- +
- + gcvSURF_LINEAR = 0x2000,
- + gcvSURF_VG = 0x4000,
- +
- + gcvSURF_TEXTURE_LINEAR = gcvSURF_TEXTURE
- + | gcvSURF_LINEAR,
- +
- + gcvSURF_RENDER_TARGET_NO_TILE_STATUS = gcvSURF_RENDER_TARGET
- + | gcvSURF_NO_TILE_STATUS,
- +
- + gcvSURF_RENDER_TARGET_TS_DIRTY = gcvSURF_RENDER_TARGET
- + | gcvSURF_TILE_STATUS_DIRTY,
- +
- + gcvSURF_DEPTH_NO_TILE_STATUS = gcvSURF_DEPTH
- + | gcvSURF_NO_TILE_STATUS,
- +
- + gcvSURF_DEPTH_TS_DIRTY = gcvSURF_DEPTH
- + | gcvSURF_TILE_STATUS_DIRTY,
- +
- + /* Supported surface types with no vidmem node. */
- + gcvSURF_BITMAP_NO_VIDMEM = gcvSURF_BITMAP
- + | gcvSURF_NO_VIDMEM,
- +
- + gcvSURF_TEXTURE_NO_VIDMEM = gcvSURF_TEXTURE
- + | gcvSURF_NO_VIDMEM,
- +
- + /* Cacheable surface types with no vidmem node. */
- + gcvSURF_CACHEABLE_BITMAP_NO_VIDMEM = gcvSURF_BITMAP_NO_VIDMEM
- + | gcvSURF_CACHEABLE,
- +
- + gcvSURF_CACHEABLE_BITMAP = gcvSURF_BITMAP
- + | gcvSURF_CACHEABLE,
- +
- + gcvSURF_FLIP_BITMAP = gcvSURF_BITMAP
- + | gcvSURF_FLIP,
- +}
- +gceSURF_TYPE;
- +
- +typedef enum _gceSURF_USAGE
- +{
- + gcvSURF_USAGE_UNKNOWN,
- + gcvSURF_USAGE_RESOLVE_AFTER_CPU,
- + gcvSURF_USAGE_RESOLVE_AFTER_3D
- +}
- +gceSURF_USAGE;
- +
- +typedef enum _gceSURF_COLOR_TYPE
- +{
- + gcvSURF_COLOR_UNKNOWN = 0,
- + gcvSURF_COLOR_LINEAR = 0x01,
- + gcvSURF_COLOR_ALPHA_PRE = 0x02,
- +}
- +gceSURF_COLOR_TYPE;
- +
- +/* Rotation. */
- +typedef enum _gceSURF_ROTATION
- +{
- + gcvSURF_0_DEGREE = 0,
- + gcvSURF_90_DEGREE,
- + gcvSURF_180_DEGREE,
- + gcvSURF_270_DEGREE,
- + gcvSURF_FLIP_X,
- + gcvSURF_FLIP_Y,
- +
- + gcvSURF_POST_FLIP_X = 0x40000000,
- + gcvSURF_POST_FLIP_Y = 0x80000000,
- +}
- +gceSURF_ROTATION;
- +
- +typedef enum _gceMIPMAP_IMAGE_FORMAT
- +{
- + gcvUNKNOWN_MIPMAP_IMAGE_FORMAT = -2
- +}
- +gceMIPMAP_IMAGE_FORMAT;
- +
- +
- +/* Surface formats. */
- +typedef enum _gceSURF_FORMAT
- +{
- + /* Unknown format. */
- + gcvSURF_UNKNOWN = 0,
- +
- + /* Palettized formats. */
- + gcvSURF_INDEX1 = 100,
- + gcvSURF_INDEX4,
- + gcvSURF_INDEX8,
- +
- + /* RGB formats. */
- + gcvSURF_A2R2G2B2 = 200,
- + gcvSURF_R3G3B2,
- + gcvSURF_A8R3G3B2,
- + gcvSURF_X4R4G4B4,
- + gcvSURF_A4R4G4B4,
- + gcvSURF_R4G4B4A4,
- + gcvSURF_X1R5G5B5,
- + gcvSURF_A1R5G5B5,
- + gcvSURF_R5G5B5A1,
- + gcvSURF_R5G6B5,
- + gcvSURF_R8G8B8,
- + gcvSURF_X8R8G8B8,
- + gcvSURF_A8R8G8B8,
- + gcvSURF_R8G8B8A8,
- + gcvSURF_G8R8G8B8,
- + gcvSURF_R8G8B8G8,
- + gcvSURF_X2R10G10B10,
- + gcvSURF_A2R10G10B10,
- + gcvSURF_X12R12G12B12,
- + gcvSURF_A12R12G12B12,
- + gcvSURF_X16R16G16B16,
- + gcvSURF_A16R16G16B16,
- + gcvSURF_A32R32G32B32,
- + gcvSURF_R8G8B8X8,
- + gcvSURF_R5G5B5X1,
- + gcvSURF_R4G4B4X4,
- +
- + /* BGR formats. */
- + gcvSURF_A4B4G4R4 = 300,
- + gcvSURF_A1B5G5R5,
- + gcvSURF_B5G6R5,
- + gcvSURF_B8G8R8,
- + gcvSURF_B16G16R16,
- + gcvSURF_X8B8G8R8,
- + gcvSURF_A8B8G8R8,
- + gcvSURF_A2B10G10R10,
- + gcvSURF_X16B16G16R16,
- + gcvSURF_A16B16G16R16,
- + gcvSURF_B32G32R32,
- + gcvSURF_X32B32G32R32,
- + gcvSURF_A32B32G32R32,
- + gcvSURF_B4G4R4A4,
- + gcvSURF_B5G5R5A1,
- + gcvSURF_B8G8R8X8,
- + gcvSURF_B8G8R8A8,
- + gcvSURF_X4B4G4R4,
- + gcvSURF_X1B5G5R5,
- + gcvSURF_B4G4R4X4,
- + gcvSURF_B5G5R5X1,
- + gcvSURF_X2B10G10R10,
- +
- + /* Compressed formats. */
- + gcvSURF_DXT1 = 400,
- + gcvSURF_DXT2,
- + gcvSURF_DXT3,
- + gcvSURF_DXT4,
- + gcvSURF_DXT5,
- + gcvSURF_CXV8U8,
- + gcvSURF_ETC1,
- + gcvSURF_R11_EAC,
- + gcvSURF_SIGNED_R11_EAC,
- + gcvSURF_RG11_EAC,
- + gcvSURF_SIGNED_RG11_EAC,
- + gcvSURF_RGB8_ETC2,
- + gcvSURF_SRGB8_ETC2,
- + gcvSURF_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
- + gcvSURF_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
- + gcvSURF_RGBA8_ETC2_EAC,
- + gcvSURF_SRGB8_ALPHA8_ETC2_EAC,
- +
- + /* YUV formats. */
- + gcvSURF_YUY2 = 500,
- + gcvSURF_UYVY,
- + gcvSURF_YV12,
- + gcvSURF_I420,
- + gcvSURF_NV12,
- + gcvSURF_NV21,
- + gcvSURF_NV16,
- + gcvSURF_NV61,
- + gcvSURF_YVYU,
- + gcvSURF_VYUY,
- +
- + /* Depth formats. */
- + gcvSURF_D16 = 600,
- + gcvSURF_D24S8,
- + gcvSURF_D32,
- + gcvSURF_D24X8,
- +
- + /* Alpha formats. */
- + gcvSURF_A4 = 700,
- + gcvSURF_A8,
- + gcvSURF_A12,
- + gcvSURF_A16,
- + gcvSURF_A32,
- + gcvSURF_A1,
- +
- + /* Luminance formats. */
- + gcvSURF_L4 = 800,
- + gcvSURF_L8,
- + gcvSURF_L12,
- + gcvSURF_L16,
- + gcvSURF_L32,
- + gcvSURF_L1,
- +
- + /* Alpha/Luminance formats. */
- + gcvSURF_A4L4 = 900,
- + gcvSURF_A2L6,
- + gcvSURF_A8L8,
- + gcvSURF_A4L12,
- + gcvSURF_A12L12,
- + gcvSURF_A16L16,
- +
- + /* Bump formats. */
- + gcvSURF_L6V5U5 = 1000,
- + gcvSURF_V8U8,
- + gcvSURF_X8L8V8U8,
- + gcvSURF_Q8W8V8U8,
- + gcvSURF_A2W10V10U10,
- + gcvSURF_V16U16,
- + gcvSURF_Q16W16V16U16,
- +
- + /* R/RG/RA formats. */
- + gcvSURF_R8 = 1100,
- + gcvSURF_X8R8,
- + gcvSURF_G8R8,
- + gcvSURF_X8G8R8,
- + gcvSURF_A8R8,
- + gcvSURF_R16,
- + gcvSURF_X16R16,
- + gcvSURF_G16R16,
- + gcvSURF_X16G16R16,
- + gcvSURF_A16R16,
- + gcvSURF_R32,
- + gcvSURF_X32R32,
- + gcvSURF_G32R32,
- + gcvSURF_X32G32R32,
- + gcvSURF_A32R32,
- + gcvSURF_RG16,
- +
- + /* Floating point formats. */
- + gcvSURF_R16F = 1200,
- + gcvSURF_X16R16F,
- + gcvSURF_G16R16F,
- + gcvSURF_X16G16R16F,
- + gcvSURF_B16G16R16F,
- + gcvSURF_X16B16G16R16F,
- + gcvSURF_A16B16G16R16F,
- + gcvSURF_R32F,
- + gcvSURF_X32R32F,
- + gcvSURF_G32R32F,
- + gcvSURF_X32G32R32F,
- + gcvSURF_B32G32R32F,
- + gcvSURF_X32B32G32R32F,
- + gcvSURF_A32B32G32R32F,
- + gcvSURF_A16F,
- + gcvSURF_L16F,
- + gcvSURF_A16L16F,
- + gcvSURF_A16R16F,
- + gcvSURF_A32F,
- + gcvSURF_L32F,
- + gcvSURF_A32L32F,
- + gcvSURF_A32R32F,
- +
- +}
- +gceSURF_FORMAT;
- +
- +/* Pixel swizzle modes. */
- +typedef enum _gceSURF_SWIZZLE
- +{
- + gcvSURF_NOSWIZZLE = 0,
- + gcvSURF_ARGB,
- + gcvSURF_ABGR,
- + gcvSURF_RGBA,
- + gcvSURF_BGRA
- +}
- +gceSURF_SWIZZLE;
- +
- +/* Transparency modes. */
- +typedef enum _gceSURF_TRANSPARENCY
- +{
- + /* Valid only for PE 1.0 */
- + gcvSURF_OPAQUE = 0,
- + gcvSURF_SOURCE_MATCH,
- + gcvSURF_SOURCE_MASK,
- + gcvSURF_PATTERN_MASK,
- +}
- +gceSURF_TRANSPARENCY;
- +
- +/* Surface Alignment. */
- +typedef enum _gceSURF_ALIGNMENT
- +{
- + gcvSURF_FOUR = 0,
- + gcvSURF_SIXTEEN,
- + gcvSURF_SUPER_TILED,
- + gcvSURF_SPLIT_TILED,
- + gcvSURF_SPLIT_SUPER_TILED,
- +}
- +gceSURF_ALIGNMENT;
- +
- +
- +/* Surface Addressing. */
- +typedef enum _gceSURF_ADDRESSING
- +{
- + gcvSURF_NO_STRIDE_TILED = 0,
- + gcvSURF_NO_STRIDE_LINEAR,
- + gcvSURF_STRIDE_TILED,
- + gcvSURF_STRIDE_LINEAR
- +}
- +gceSURF_ADDRESSING;
- +
- +/* Transparency modes. */
- +typedef enum _gce2D_TRANSPARENCY
- +{
- + /* Valid only for PE 2.0 */
- + gcv2D_OPAQUE = 0,
- + gcv2D_KEYED,
- + gcv2D_MASKED
- +}
- +gce2D_TRANSPARENCY;
- +
- +/* Mono packing modes. */
- +typedef enum _gceSURF_MONOPACK
- +{
- + gcvSURF_PACKED8 = 0,
- + gcvSURF_PACKED16,
- + gcvSURF_PACKED32,
- + gcvSURF_UNPACKED,
- +}
- +gceSURF_MONOPACK;
- +
- +/* Blending modes. */
- +typedef enum _gceSURF_BLEND_MODE
- +{
- + /* Porter-Duff blending modes. */
- + /* Fsrc Fdst */
- + gcvBLEND_CLEAR = 0, /* 0 0 */
- + gcvBLEND_SRC, /* 1 0 */
- + gcvBLEND_DST, /* 0 1 */
- + gcvBLEND_SRC_OVER_DST, /* 1 1 - Asrc */
- + gcvBLEND_DST_OVER_SRC, /* 1 - Adst 1 */
- + gcvBLEND_SRC_IN_DST, /* Adst 0 */
- + gcvBLEND_DST_IN_SRC, /* 0 Asrc */
- + gcvBLEND_SRC_OUT_DST, /* 1 - Adst 0 */
- + gcvBLEND_DST_OUT_SRC, /* 0 1 - Asrc */
- + gcvBLEND_SRC_ATOP_DST, /* Adst 1 - Asrc */
- + gcvBLEND_DST_ATOP_SRC, /* 1 - Adst Asrc */
- + gcvBLEND_SRC_XOR_DST, /* 1 - Adst 1 - Asrc */
- +
- + /* Special blending modes. */
- + gcvBLEND_SET, /* DST = 1 */
- + gcvBLEND_SUB /* DST = DST * (1 - SRC) */
- +}
- +gceSURF_BLEND_MODE;
- +
- +/* Per-pixel alpha modes. */
- +typedef enum _gceSURF_PIXEL_ALPHA_MODE
- +{
- + gcvSURF_PIXEL_ALPHA_STRAIGHT = 0,
- + gcvSURF_PIXEL_ALPHA_INVERSED
- +}
- +gceSURF_PIXEL_ALPHA_MODE;
- +
- +/* Global alpha modes. */
- +typedef enum _gceSURF_GLOBAL_ALPHA_MODE
- +{
- + gcvSURF_GLOBAL_ALPHA_OFF = 0,
- + gcvSURF_GLOBAL_ALPHA_ON,
- + gcvSURF_GLOBAL_ALPHA_SCALE
- +}
- +gceSURF_GLOBAL_ALPHA_MODE;
- +
- +/* Color component modes for alpha blending. */
- +typedef enum _gceSURF_PIXEL_COLOR_MODE
- +{
- + gcvSURF_COLOR_STRAIGHT = 0,
- + gcvSURF_COLOR_MULTIPLY
- +}
- +gceSURF_PIXEL_COLOR_MODE;
- +
- +/* Color component modes for alpha blending. */
- +typedef enum _gce2D_PIXEL_COLOR_MULTIPLY_MODE
- +{
- + gcv2D_COLOR_MULTIPLY_DISABLE = 0,
- + gcv2D_COLOR_MULTIPLY_ENABLE
- +}
- +gce2D_PIXEL_COLOR_MULTIPLY_MODE;
- +
- +/* Color component modes for alpha blending. */
- +typedef enum _gce2D_GLOBAL_COLOR_MULTIPLY_MODE
- +{
- + gcv2D_GLOBAL_COLOR_MULTIPLY_DISABLE = 0,
- + gcv2D_GLOBAL_COLOR_MULTIPLY_ALPHA,
- + gcv2D_GLOBAL_COLOR_MULTIPLY_COLOR
- +}
- +gce2D_GLOBAL_COLOR_MULTIPLY_MODE;
- +
- +/* Alpha blending factor modes. */
- +typedef enum _gceSURF_BLEND_FACTOR_MODE
- +{
- + gcvSURF_BLEND_ZERO = 0,
- + gcvSURF_BLEND_ONE,
- + gcvSURF_BLEND_STRAIGHT,
- + gcvSURF_BLEND_INVERSED,
- + gcvSURF_BLEND_COLOR,
- + gcvSURF_BLEND_COLOR_INVERSED,
- + gcvSURF_BLEND_SRC_ALPHA_SATURATED,
- + gcvSURF_BLEND_STRAIGHT_NO_CROSS,
- + gcvSURF_BLEND_INVERSED_NO_CROSS,
- + gcvSURF_BLEND_COLOR_NO_CROSS,
- + gcvSURF_BLEND_COLOR_INVERSED_NO_CROSS,
- + gcvSURF_BLEND_SRC_ALPHA_SATURATED_CROSS
- +}
- +gceSURF_BLEND_FACTOR_MODE;
- +
- +/* Alpha blending porter duff rules. */
- +typedef enum _gce2D_PORTER_DUFF_RULE
- +{
- + gcvPD_CLEAR = 0,
- + gcvPD_SRC,
- + gcvPD_SRC_OVER,
- + gcvPD_DST_OVER,
- + gcvPD_SRC_IN,
- + gcvPD_DST_IN,
- + gcvPD_SRC_OUT,
- + gcvPD_DST_OUT,
- + gcvPD_SRC_ATOP,
- + gcvPD_DST_ATOP,
- + gcvPD_ADD,
- + gcvPD_XOR,
- + gcvPD_DST
- +}
- +gce2D_PORTER_DUFF_RULE;
- +
- +/* Alpha blending factor modes. */
- +typedef enum _gce2D_YUV_COLOR_MODE
- +{
- + gcv2D_YUV_601= 0,
- + gcv2D_YUV_709,
- + gcv2D_YUV_USER_DEFINED,
- + gcv2D_YUV_USER_DEFINED_CLAMP,
- +
- + /* Default setting is for src. gcv2D_YUV_DST
- + can be ORed to set dst.
- + */
- + gcv2D_YUV_DST = 0x80000000,
- +}
- +gce2D_YUV_COLOR_MODE;
- +
- +typedef enum _gce2D_COMMAND
- +{
- + gcv2D_CLEAR = 0,
- + gcv2D_LINE,
- + gcv2D_BLT,
- + gcv2D_STRETCH,
- + gcv2D_HOR_FILTER,
- + gcv2D_VER_FILTER,
- + gcv2D_MULTI_SOURCE_BLT,
- +}
- +gce2D_COMMAND;
- +
- +typedef enum _gce2D_TILE_STATUS_CONFIG
- +{
- + gcv2D_TSC_DISABLE = 0,
- + gcv2D_TSC_ENABLE = 0x00000001,
- + gcv2D_TSC_COMPRESSED = 0x00000002,
- + gcv2D_TSC_DOWN_SAMPLER = 0x00000004,
- + gcv2D_TSC_2D_COMPRESSED = 0x00000008,
- +}
- +gce2D_TILE_STATUS_CONFIG;
- +
- +typedef enum _gce2D_QUERY
- +{
- + gcv2D_QUERY_RGB_ADDRESS_MIN_ALIGN = 0,
- + gcv2D_QUERY_RGB_STRIDE_MIN_ALIGN,
- + gcv2D_QUERY_YUV_ADDRESS_MIN_ALIGN,
- + gcv2D_QUERY_YUV_STRIDE_MIN_ALIGN,
- +}
- +gce2D_QUERY;
- +
- +typedef enum _gce2D_SUPER_TILE_VERSION
- +{
- + gcv2D_SUPER_TILE_VERSION_V1 = 1,
- + gcv2D_SUPER_TILE_VERSION_V2 = 2,
- + gcv2D_SUPER_TILE_VERSION_V3 = 3,
- +}
- +gce2D_SUPER_TILE_VERSION;
- +
- +typedef enum _gce2D_STATE
- +{
- + gcv2D_STATE_SPECIAL_FILTER_MIRROR_MODE = 1,
- + gcv2D_STATE_SUPER_TILE_VERSION,
- + gcv2D_STATE_EN_GAMMA,
- + gcv2D_STATE_DE_GAMMA,
- + gcv2D_STATE_MULTI_SRC_BLIT_UNIFIED_DST_RECT,
- + gcv2D_STATE_XRGB_ENABLE,
- +
- + gcv2D_STATE_ARRAY_EN_GAMMA = 0x10001,
- + gcv2D_STATE_ARRAY_DE_GAMMA,
- + gcv2D_STATE_ARRAY_CSC_YUV_TO_RGB,
- + gcv2D_STATE_ARRAY_CSC_RGB_TO_YUV,
- +}
- +gce2D_STATE;
- +
- +#ifndef VIVANTE_NO_3D
- +/* Texture functions. */
- +typedef enum _gceTEXTURE_FUNCTION
- +{
- + gcvTEXTURE_DUMMY = 0,
- + gcvTEXTURE_REPLACE = 0,
- + gcvTEXTURE_MODULATE,
- + gcvTEXTURE_ADD,
- + gcvTEXTURE_ADD_SIGNED,
- + gcvTEXTURE_INTERPOLATE,
- + gcvTEXTURE_SUBTRACT,
- + gcvTEXTURE_DOT3
- +}
- +gceTEXTURE_FUNCTION;
- +
- +/* Texture sources. */
- +typedef enum _gceTEXTURE_SOURCE
- +{
- + gcvCOLOR_FROM_TEXTURE = 0,
- + gcvCOLOR_FROM_CONSTANT_COLOR,
- + gcvCOLOR_FROM_PRIMARY_COLOR,
- + gcvCOLOR_FROM_PREVIOUS_COLOR
- +}
- +gceTEXTURE_SOURCE;
- +
- +/* Texture source channels. */
- +typedef enum _gceTEXTURE_CHANNEL
- +{
- + gcvFROM_COLOR = 0,
- + gcvFROM_ONE_MINUS_COLOR,
- + gcvFROM_ALPHA,
- + gcvFROM_ONE_MINUS_ALPHA
- +}
- +gceTEXTURE_CHANNEL;
- +#endif /* VIVANTE_NO_3D */
- +
- +/* Filter types. */
- +typedef enum _gceFILTER_TYPE
- +{
- + gcvFILTER_SYNC = 0,
- + gcvFILTER_BLUR,
- + gcvFILTER_USER
- +}
- +gceFILTER_TYPE;
- +
- +/* Filter pass types. */
- +typedef enum _gceFILTER_PASS_TYPE
- +{
- + gcvFILTER_HOR_PASS = 0,
- + gcvFILTER_VER_PASS
- +}
- +gceFILTER_PASS_TYPE;
- +
- +/* Endian hints. */
- +typedef enum _gceENDIAN_HINT
- +{
- + gcvENDIAN_NO_SWAP = 0,
- + gcvENDIAN_SWAP_WORD,
- + gcvENDIAN_SWAP_DWORD
- +}
- +gceENDIAN_HINT;
- +
- +/* Tiling modes. */
- +typedef enum _gceTILING
- +{
- + gcvLINEAR = 0,
- + gcvTILED,
- + gcvSUPERTILED,
- + gcvMULTI_TILED,
- + gcvMULTI_SUPERTILED,
- + gcvMINORTILED,
- +}
- +gceTILING;
- +
- +/* 2D pattern type. */
- +typedef enum _gce2D_PATTERN
- +{
- + gcv2D_PATTERN_SOLID = 0,
- + gcv2D_PATTERN_MONO,
- + gcv2D_PATTERN_COLOR,
- + gcv2D_PATTERN_INVALID
- +}
- +gce2D_PATTERN;
- +
- +/* 2D source type. */
- +typedef enum _gce2D_SOURCE
- +{
- + gcv2D_SOURCE_MASKED = 0,
- + gcv2D_SOURCE_MONO,
- + gcv2D_SOURCE_COLOR,
- + gcv2D_SOURCE_INVALID
- +}
- +gce2D_SOURCE;
- +
- +/* Pipes. */
- +typedef enum _gcePIPE_SELECT
- +{
- + gcvPIPE_INVALID = ~0,
- + gcvPIPE_3D = 0,
- + gcvPIPE_2D
- +}
- +gcePIPE_SELECT;
- +
- +/* Hardware type. */
- +typedef enum _gceHARDWARE_TYPE
- +{
- + gcvHARDWARE_INVALID = 0x00,
- + gcvHARDWARE_3D = 0x01,
- + gcvHARDWARE_2D = 0x02,
- + gcvHARDWARE_VG = 0x04,
- +
- + gcvHARDWARE_3D2D = gcvHARDWARE_3D | gcvHARDWARE_2D
- +}
- +gceHARDWARE_TYPE;
- +
- +#define gcdCHIP_COUNT 3
- +
- +typedef enum _gceMMU_MODE
- +{
- + gcvMMU_MODE_1K,
- + gcvMMU_MODE_4K,
- +} gceMMU_MODE;
- +
- +/* User signal command codes. */
- +typedef enum _gceUSER_SIGNAL_COMMAND_CODES
- +{
- + gcvUSER_SIGNAL_CREATE,
- + gcvUSER_SIGNAL_DESTROY,
- + gcvUSER_SIGNAL_SIGNAL,
- + gcvUSER_SIGNAL_WAIT,
- + gcvUSER_SIGNAL_MAP,
- + gcvUSER_SIGNAL_UNMAP,
- +}
- +gceUSER_SIGNAL_COMMAND_CODES;
- +
- +/* Sync point command codes. */
- +typedef enum _gceSYNC_POINT_COMMAND_CODES
- +{
- + gcvSYNC_POINT_CREATE,
- + gcvSYNC_POINT_DESTROY,
- + gcvSYNC_POINT_SIGNAL,
- +}
- +gceSYNC_POINT_COMMAND_CODES;
- +
- +/* Event locations. */
- +typedef enum _gceKERNEL_WHERE
- +{
- + gcvKERNEL_COMMAND,
- + gcvKERNEL_VERTEX,
- + gcvKERNEL_TRIANGLE,
- + gcvKERNEL_TEXTURE,
- + gcvKERNEL_PIXEL,
- +}
- +gceKERNEL_WHERE;
- +
- +#if gcdENABLE_VG
- +/* Hardware blocks. */
- +typedef enum _gceBLOCK
- +{
- + gcvBLOCK_COMMAND,
- + gcvBLOCK_TESSELLATOR,
- + gcvBLOCK_TESSELLATOR2,
- + gcvBLOCK_TESSELLATOR3,
- + gcvBLOCK_RASTER,
- + gcvBLOCK_VG,
- + gcvBLOCK_VG2,
- + gcvBLOCK_VG3,
- + gcvBLOCK_PIXEL,
- +
- + /* Number of defined blocks. */
- + gcvBLOCK_COUNT
- +}
- +gceBLOCK;
- +#endif
- +
- +/* gcdDUMP message type. */
- +typedef enum _gceDEBUG_MESSAGE_TYPE
- +{
- + gcvMESSAGE_TEXT,
- + gcvMESSAGE_DUMP
- +}
- +gceDEBUG_MESSAGE_TYPE;
- +
- +typedef enum _gceSPECIAL_HINT
- +{
- + gceSPECIAL_HINT0,
- + gceSPECIAL_HINT1,
- + gceSPECIAL_HINT2,
- + gceSPECIAL_HINT3,
- + /* For disable dynamic stream/index */
- + gceSPECIAL_HINT4
- +}
- +gceSPECIAL_HINT;
- +
- +typedef enum _gceMACHINECODE
- +{
- + gcvMACHINECODE_HOVERJET0 = 0x0,
- + gcvMACHINECODE_HOVERJET1 ,
- +
- + gcvMACHINECODE_TAIJI0 ,
- + gcvMACHINECODE_TAIJI1 ,
- + gcvMACHINECODE_TAIJI2 ,
- +
- + gcvMACHINECODE_ANTUTU0 ,
- +
- + gcvMACHINECODE_GLB27_RELEASE_0,
- + gcvMACHINECODE_GLB27_RELEASE_1,
- +
- + gcvMACHINECODE_WAVESCAPE0 ,
- + gcvMACHINECODE_WAVESCAPE1 ,
- +
- + gcvMACHINECODE_NENAMARKV2_4_0 ,
- + gcvMACHINECODE_NENAMARKV2_4_1 ,
- +
- + gcvMACHINECODE_GLB25_RELEASE_0,
- + gcvMACHINECODE_GLB25_RELEASE_1,
- + gcvMACHINECODE_GLB25_RELEASE_2,
- +}
- +gceMACHINECODE;
- +
- +
- +/******************************************************************************\
- +****************************** Object Declarations *****************************
- +\******************************************************************************/
- +
- +typedef struct _gckCONTEXT * gckCONTEXT;
- +typedef struct _gcoCMDBUF * gcoCMDBUF;
- +typedef struct _gcsSTATE_DELTA * gcsSTATE_DELTA_PTR;
- +typedef struct _gcsQUEUE * gcsQUEUE_PTR;
- +typedef struct _gcoQUEUE * gcoQUEUE;
- +typedef struct _gcsHAL_INTERFACE * gcsHAL_INTERFACE_PTR;
- +typedef struct _gcs2D_PROFILE * gcs2D_PROFILE_PTR;
- +
- +#if gcdENABLE_VG
- +typedef struct _gcoVGHARDWARE * gcoVGHARDWARE;
- +typedef struct _gcoVGBUFFER * gcoVGBUFFER;
- +typedef struct _gckVGHARDWARE * gckVGHARDWARE;
- +typedef struct _gcsVGCONTEXT * gcsVGCONTEXT_PTR;
- +typedef struct _gcsVGCONTEXT_MAP * gcsVGCONTEXT_MAP_PTR;
- +typedef struct _gcsVGCMDQUEUE * gcsVGCMDQUEUE_PTR;
- +typedef struct _gcsTASK_MASTER_TABLE * gcsTASK_MASTER_TABLE_PTR;
- +typedef struct _gckVGKERNEL * gckVGKERNEL;
- +typedef void * gctTHREAD;
- +#endif
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* __gc_hal_enum_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h 2015-03-08 14:27:37.645684500 -0500
- @@ -0,0 +1,2661 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_h_
- +#define __gc_hal_h_
- +
- +#include "gc_hal_rename.h"
- +#include "gc_hal_types.h"
- +#include "gc_hal_enum.h"
- +#include "gc_hal_base.h"
- +#include "gc_hal_profiler.h"
- +#include "gc_hal_driver.h"
- +#ifndef VIVANTE_NO_3D
- +#include "gc_hal_statistics.h"
- +#endif
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +/******************************************************************************\
- +******************************* Alignment Macros *******************************
- +\******************************************************************************/
- +
- +#define gcmALIGN(n, align) \
- +( \
- + ((n) + ((align) - 1)) & ~((align) - 1) \
- +)
- +
- +#define gcmALIGN_BASE(n, align) \
- +( \
- + ((n) & ~((align) - 1)) \
- +)
- +
- +/******************************************************************************\
- +***************************** Element Count Macro *****************************
- +\******************************************************************************/
- +
- +#define gcmSIZEOF(a) \
- +( \
- + (gctSIZE_T) (sizeof(a)) \
- +)
- +
- +#define gcmCOUNTOF(a) \
- +( \
- + sizeof(a) / sizeof(a[0]) \
- +)
- +
- +/******************************************************************************\
- +********************************* Cast Macro **********************************
- +\******************************************************************************/
- +#define gcmNAME_TO_PTR(na) \
- + gckKERNEL_QueryPointerFromName(kernel, gcmALL_TO_UINT32(na))
- +
- +#define gcmPTR_TO_NAME(ptr) \
- + gckKERNEL_AllocateNameFromPointer(kernel, ptr)
- +
- +#define gcmRELEASE_NAME(na) \
- + gckKERNEL_DeleteName(kernel, gcmALL_TO_UINT32(na))
- +
- +#ifdef __LP64__
- +
- +#define gcmALL_TO_UINT32(t) \
- +( \
- + (gctUINT32) (gctUINTPTR_T) (t)\
- +)
- +
- +#define gcmPTR_TO_UINT64(p) \
- +( \
- + (gctUINT64) (p)\
- +)
- +
- +#define gcmUINT64_TO_PTR(u) \
- +( \
- + (gctPOINTER) (u)\
- +)
- +
- +#else /* 32 bit */
- +
- +#define gcmALL_TO_UINT32(t) \
- +( \
- + (gctUINT32) (t)\
- +)
- +
- +#define gcmPTR_TO_UINT64(p) \
- +( \
- + (gctUINT64) (gctUINTPTR_T) (p)\
- +)
- +
- +#define gcmUINT64_TO_PTR(u) \
- +( \
- + (gctPOINTER) (gctUINTPTR_T) (u)\
- +)
- +
- +#endif
- +
- +#define gcmUINT64_TO_TYPE(u, t) \
- +( \
- + (t) (gctUINTPTR_T) (u)\
- +)
- +
- +/******************************************************************************\
- +******************************** Useful Macro *********************************
- +\******************************************************************************/
- +
- +#define gcvINVALID_ADDRESS ~0U
- +
- +#define gcmGET_PRE_ROTATION(rotate) \
- + ((rotate) & (~(gcvSURF_POST_FLIP_X | gcvSURF_POST_FLIP_Y)))
- +
- +#define gcmGET_POST_ROTATION(rotate) \
- + ((rotate) & (gcvSURF_POST_FLIP_X | gcvSURF_POST_FLIP_Y))
- +
- +/******************************************************************************\
- +******************************** gcsOBJECT Object *******************************
- +\******************************************************************************/
- +
- +/* Type of objects. */
- +typedef enum _gceOBJECT_TYPE
- +{
- + gcvOBJ_UNKNOWN = 0,
- + gcvOBJ_2D = gcmCC('2','D',' ',' '),
- + gcvOBJ_3D = gcmCC('3','D',' ',' '),
- + gcvOBJ_ATTRIBUTE = gcmCC('A','T','T','R'),
- + gcvOBJ_BRUSHCACHE = gcmCC('B','R','U','$'),
- + gcvOBJ_BRUSHNODE = gcmCC('B','R','U','n'),
- + gcvOBJ_BRUSH = gcmCC('B','R','U','o'),
- + gcvOBJ_BUFFER = gcmCC('B','U','F','R'),
- + gcvOBJ_COMMAND = gcmCC('C','M','D',' '),
- + gcvOBJ_COMMANDBUFFER = gcmCC('C','M','D','B'),
- + gcvOBJ_CONTEXT = gcmCC('C','T','X','T'),
- + gcvOBJ_DEVICE = gcmCC('D','E','V',' '),
- + gcvOBJ_DUMP = gcmCC('D','U','M','P'),
- + gcvOBJ_EVENT = gcmCC('E','V','N','T'),
- + gcvOBJ_FUNCTION = gcmCC('F','U','N','C'),
- + gcvOBJ_HAL = gcmCC('H','A','L',' '),
- + gcvOBJ_HARDWARE = gcmCC('H','A','R','D'),
- + gcvOBJ_HEAP = gcmCC('H','E','A','P'),
- + gcvOBJ_INDEX = gcmCC('I','N','D','X'),
- + gcvOBJ_INTERRUPT = gcmCC('I','N','T','R'),
- + gcvOBJ_KERNEL = gcmCC('K','E','R','N'),
- + gcvOBJ_KERNEL_FUNCTION = gcmCC('K','F','C','N'),
- + gcvOBJ_MEMORYBUFFER = gcmCC('M','E','M','B'),
- + gcvOBJ_MMU = gcmCC('M','M','U',' '),
- + gcvOBJ_OS = gcmCC('O','S',' ',' '),
- + gcvOBJ_OUTPUT = gcmCC('O','U','T','P'),
- + gcvOBJ_PAINT = gcmCC('P','N','T',' '),
- + gcvOBJ_PATH = gcmCC('P','A','T','H'),
- + gcvOBJ_QUEUE = gcmCC('Q','U','E',' '),
- + gcvOBJ_SAMPLER = gcmCC('S','A','M','P'),
- + gcvOBJ_SHADER = gcmCC('S','H','D','R'),
- + gcvOBJ_STREAM = gcmCC('S','T','R','M'),
- + gcvOBJ_SURF = gcmCC('S','U','R','F'),
- + gcvOBJ_TEXTURE = gcmCC('T','X','T','R'),
- + gcvOBJ_UNIFORM = gcmCC('U','N','I','F'),
- + gcvOBJ_VARIABLE = gcmCC('V','A','R','I'),
- + gcvOBJ_VERTEX = gcmCC('V','R','T','X'),
- + gcvOBJ_VIDMEM = gcmCC('V','M','E','M'),
- + gcvOBJ_VG = gcmCC('V','G',' ',' '),
- +}
- +gceOBJECT_TYPE;
- +
- +/* gcsOBJECT object defintinon. */
- +typedef struct _gcsOBJECT
- +{
- + /* Type of an object. */
- + gceOBJECT_TYPE type;
- +}
- +gcsOBJECT;
- +
- +typedef struct _gckHARDWARE * gckHARDWARE;
- +
- +/* CORE flags. */
- +typedef enum _gceCORE
- +{
- + gcvCORE_MAJOR = 0x0,
- + gcvCORE_2D = 0x1,
- + gcvCORE_VG = 0x2
- +}
- +gceCORE;
- +
- +#define gcdMAX_GPU_COUNT 3
- +
- +/*******************************************************************************
- +**
- +** gcmVERIFY_OBJECT
- +**
- +** Assert if an object is invalid or is not of the specified type. If the
- +** object is invalid or not of the specified type, gcvSTATUS_INVALID_OBJECT
- +** will be returned from the current function. In retail mode this macro
- +** does nothing.
- +**
- +** ARGUMENTS:
- +**
- +** obj Object to test.
- +** t Expected type of the object.
- +*/
- +#if gcmIS_DEBUG(gcdDEBUG_TRACE)
- +#define _gcmVERIFY_OBJECT(prefix, obj, t) \
- + if ((obj) == gcvNULL) \
- + { \
- + prefix##TRACE(gcvLEVEL_ERROR, \
- + #prefix "VERIFY_OBJECT failed: NULL"); \
- + prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
- + gcmCC_PRINT(t)); \
- + prefix##ASSERT((obj) != gcvNULL); \
- + prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_OBJECT); \
- + return gcvSTATUS_INVALID_OBJECT; \
- + } \
- + else if (((gcsOBJECT*) (obj))->type != t) \
- + { \
- + prefix##TRACE(gcvLEVEL_ERROR, \
- + #prefix "VERIFY_OBJECT failed: %c%c%c%c", \
- + gcmCC_PRINT(((gcsOBJECT*) (obj))->type)); \
- + prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
- + gcmCC_PRINT(t)); \
- + prefix##ASSERT(((gcsOBJECT*)(obj))->type == t); \
- + prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_OBJECT); \
- + return gcvSTATUS_INVALID_OBJECT; \
- + }
- +
- +# define gcmVERIFY_OBJECT(obj, t) _gcmVERIFY_OBJECT(gcm, obj, t)
- +# define gcmkVERIFY_OBJECT(obj, t) _gcmVERIFY_OBJECT(gcmk, obj, t)
- +#else
- +# define gcmVERIFY_OBJECT(obj, t) do {} while (gcvFALSE)
- +# define gcmkVERIFY_OBJECT(obj, t) do {} while (gcvFALSE)
- +#endif
- +
- +/******************************************************************************/
- +/*VERIFY_OBJECT if special return expected*/
- +/******************************************************************************/
- +#ifndef EGL_API_ANDROID
- +# define _gcmVERIFY_OBJECT_RETURN(prefix, obj, t, retVal) \
- + do \
- + { \
- + if ((obj) == gcvNULL) \
- + { \
- + prefix##PRINT_VERSION(); \
- + prefix##TRACE(gcvLEVEL_ERROR, \
- + #prefix "VERIFY_OBJECT_RETURN failed: NULL"); \
- + prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
- + gcmCC_PRINT(t)); \
- + prefix##ASSERT((obj) != gcvNULL); \
- + prefix##FOOTER_ARG("retVal=%d", retVal); \
- + return retVal; \
- + } \
- + else if (((gcsOBJECT*) (obj))->type != t) \
- + { \
- + prefix##PRINT_VERSION(); \
- + prefix##TRACE(gcvLEVEL_ERROR, \
- + #prefix "VERIFY_OBJECT_RETURN failed: %c%c%c%c", \
- + gcmCC_PRINT(((gcsOBJECT*) (obj))->type)); \
- + prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
- + gcmCC_PRINT(t)); \
- + prefix##ASSERT(((gcsOBJECT*)(obj))->type == t); \
- + prefix##FOOTER_ARG("retVal=%d", retVal); \
- + return retVal; \
- + } \
- + } \
- + while (gcvFALSE)
- +# define gcmVERIFY_OBJECT_RETURN(obj, t, retVal) \
- + _gcmVERIFY_OBJECT_RETURN(gcm, obj, t, retVal)
- +# define gcmkVERIFY_OBJECT_RETURN(obj, t, retVal) \
- + _gcmVERIFY_OBJECT_RETURN(gcmk, obj, t, retVal)
- +#else
- +# define gcmVERIFY_OBJECT_RETURN(obj, t) do {} while (gcvFALSE)
- +# define gcmVERIFY_OBJECT_RETURN(obj, t) do {} while (gcvFALSE)
- +#endif
- +
- +/******************************************************************************\
- +********************************** gckOS Object *********************************
- +\******************************************************************************/
- +
- +/* Construct a new gckOS object. */
- +gceSTATUS
- +gckOS_Construct(
- + IN gctPOINTER Context,
- + OUT gckOS * Os
- + );
- +
- +/* Destroy an gckOS object. */
- +gceSTATUS
- +gckOS_Destroy(
- + IN gckOS Os
- + );
- +
- +/* Query the video memory. */
- +gceSTATUS
- +gckOS_QueryVideoMemory(
- + IN gckOS Os,
- + OUT gctPHYS_ADDR * InternalAddress,
- + OUT gctSIZE_T * InternalSize,
- + OUT gctPHYS_ADDR * ExternalAddress,
- + OUT gctSIZE_T * ExternalSize,
- + OUT gctPHYS_ADDR * ContiguousAddress,
- + OUT gctSIZE_T * ContiguousSize
- + );
- +
- +/* Allocate memory from the heap. */
- +gceSTATUS
- +gckOS_Allocate(
- + IN gckOS Os,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER * Memory
- + );
- +
- +/* Free allocated memory. */
- +gceSTATUS
- +gckOS_Free(
- + IN gckOS Os,
- + IN gctPOINTER Memory
- + );
- +
- +/* Wrapper for allocation memory.. */
- +gceSTATUS
- +gckOS_AllocateMemory(
- + IN gckOS Os,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER * Memory
- + );
- +
- +/* Wrapper for freeing memory. */
- +gceSTATUS
- +gckOS_FreeMemory(
- + IN gckOS Os,
- + IN gctPOINTER Memory
- + );
- +
- +/* Allocate paged memory. */
- +gceSTATUS
- +gckOS_AllocatePagedMemory(
- + IN gckOS Os,
- + IN gctSIZE_T Bytes,
- + OUT gctPHYS_ADDR * Physical
- + );
- +
- +/* Allocate paged memory. */
- +gceSTATUS
- +gckOS_AllocatePagedMemoryEx(
- + IN gckOS Os,
- + IN gctBOOL Contiguous,
- + IN gctSIZE_T Bytes,
- + OUT gctPHYS_ADDR * Physical
- + );
- +
- +/* Lock pages. */
- +gceSTATUS
- +gckOS_LockPages(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes,
- + IN gctBOOL Cacheable,
- + OUT gctPOINTER * Logical,
- + OUT gctSIZE_T * PageCount
- + );
- +
- +/* Map pages. */
- +gceSTATUS
- +gckOS_MapPages(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- +#ifdef __QNXNTO__
- + IN gctPOINTER Logical,
- +#endif
- + IN gctSIZE_T PageCount,
- + IN gctPOINTER PageTable
- + );
- +
- +/* Map pages. */
- +gceSTATUS
- +gckOS_MapPagesEx(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctPHYS_ADDR Physical,
- +#ifdef __QNXNTO__
- + IN gctPOINTER Logical,
- +#endif
- + IN gctSIZE_T PageCount,
- + IN gctPOINTER PageTable
- + );
- +
- +/* Unlock pages. */
- +gceSTATUS
- +gckOS_UnlockPages(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes,
- + IN gctPOINTER Logical
- + );
- +
- +/* Free paged memory. */
- +gceSTATUS
- +gckOS_FreePagedMemory(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes
- + );
- +
- +/* Allocate non-paged memory. */
- +gceSTATUS
- +gckOS_AllocateNonPagedMemory(
- + IN gckOS Os,
- + IN gctBOOL InUserSpace,
- + IN OUT gctSIZE_T * Bytes,
- + OUT gctPHYS_ADDR * Physical,
- + OUT gctPOINTER * Logical
- + );
- +
- +/* Free non-paged memory. */
- +gceSTATUS
- +gckOS_FreeNonPagedMemory(
- + IN gckOS Os,
- + IN gctSIZE_T Bytes,
- + IN gctPHYS_ADDR Physical,
- + IN gctPOINTER Logical
- + );
- +
- +/* Allocate contiguous memory. */
- +gceSTATUS
- +gckOS_AllocateContiguous(
- + IN gckOS Os,
- + IN gctBOOL InUserSpace,
- + IN OUT gctSIZE_T * Bytes,
- + OUT gctPHYS_ADDR * Physical,
- + OUT gctPOINTER * Logical
- + );
- +
- +/* Free contiguous memory. */
- +gceSTATUS
- +gckOS_FreeContiguous(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes
- + );
- +
- +/* Get the number fo bytes per page. */
- +gceSTATUS
- +gckOS_GetPageSize(
- + IN gckOS Os,
- + OUT gctSIZE_T * PageSize
- + );
- +
- +/* Get the physical address of a corresponding logical address. */
- +gceSTATUS
- +gckOS_GetPhysicalAddress(
- + IN gckOS Os,
- + IN gctPOINTER Logical,
- + OUT gctUINT32 * Address
- + );
- +
- +/* Get the physical address of a corresponding logical address. */
- +gceSTATUS
- +gckOS_GetPhysicalAddressProcess(
- + IN gckOS Os,
- + IN gctPOINTER Logical,
- + IN gctUINT32 ProcessID,
- + OUT gctUINT32 * Address
- + );
- +
- +/* Map physical memory. */
- +gceSTATUS
- +gckOS_MapPhysical(
- + IN gckOS Os,
- + IN gctUINT32 Physical,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER * Logical
- + );
- +
- +/* Unmap previously mapped physical memory. */
- +gceSTATUS
- +gckOS_UnmapPhysical(
- + IN gckOS Os,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes
- + );
- +
- +/* Read data from a hardware register. */
- +gceSTATUS
- +gckOS_ReadRegister(
- + IN gckOS Os,
- + IN gctUINT32 Address,
- + OUT gctUINT32 * Data
- + );
- +
- +/* Read data from a hardware register. */
- +gceSTATUS
- +gckOS_ReadRegisterEx(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctUINT32 Address,
- + OUT gctUINT32 * Data
- + );
- +
- +/* Write data to a hardware register. */
- +gceSTATUS
- +gckOS_WriteRegister(
- + IN gckOS Os,
- + IN gctUINT32 Address,
- + IN gctUINT32 Data
- + );
- +
- +/* Write data to a hardware register. */
- +gceSTATUS
- +gckOS_WriteRegisterEx(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctUINT32 Address,
- + IN gctUINT32 Data
- + );
- +
- +/* Write data to a 32-bit memory location. */
- +gceSTATUS
- +gckOS_WriteMemory(
- + IN gckOS Os,
- + IN gctPOINTER Address,
- + IN gctUINT32 Data
- + );
- +
- +/* Map physical memory into the process space. */
- +gceSTATUS
- +gckOS_MapMemory(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER * Logical
- + );
- +
- +/* Unmap physical memory from the specified process space. */
- +gceSTATUS
- +gckOS_UnmapMemoryEx(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes,
- + IN gctPOINTER Logical,
- + IN gctUINT32 PID
- + );
- +
- +/* Unmap physical memory from the process space. */
- +gceSTATUS
- +gckOS_UnmapMemory(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes,
- + IN gctPOINTER Logical
- + );
- +
- +/* Unmap user logical memory out of physical memory.
- + * This function is only supported in Linux currently.
- + */
- +gceSTATUS
- +gckOS_UnmapUserLogical(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes,
- + IN gctPOINTER Logical
- + );
- +
- +/* Create a new mutex. */
- +gceSTATUS
- +gckOS_CreateMutex(
- + IN gckOS Os,
- + OUT gctPOINTER * Mutex
- + );
- +
- +/* Delete a mutex. */
- +gceSTATUS
- +gckOS_DeleteMutex(
- + IN gckOS Os,
- + IN gctPOINTER Mutex
- + );
- +
- +/* Acquire a mutex. */
- +gceSTATUS
- +gckOS_AcquireMutex(
- + IN gckOS Os,
- + IN gctPOINTER Mutex,
- + IN gctUINT32 Timeout
- + );
- +
- +/* Release a mutex. */
- +gceSTATUS
- +gckOS_ReleaseMutex(
- + IN gckOS Os,
- + IN gctPOINTER Mutex
- + );
- +
- +/* Atomically exchange a pair of 32-bit values. */
- +gceSTATUS
- +gckOS_AtomicExchange(
- + IN gckOS Os,
- + IN OUT gctUINT32_PTR Target,
- + IN gctUINT32 NewValue,
- + OUT gctUINT32_PTR OldValue
- + );
- +
- +/* Atomically exchange a pair of pointers. */
- +gceSTATUS
- +gckOS_AtomicExchangePtr(
- + IN gckOS Os,
- + IN OUT gctPOINTER * Target,
- + IN gctPOINTER NewValue,
- + OUT gctPOINTER * OldValue
- + );
- +
- +#if gcdSMP
- +gceSTATUS
- +gckOS_AtomSetMask(
- + IN gctPOINTER Atom,
- + IN gctUINT32 Mask
- + );
- +
- +gceSTATUS
- +gckOS_AtomClearMask(
- + IN gctPOINTER Atom,
- + IN gctUINT32 Mask
- + );
- +#endif
- +
- +gceSTATUS
- +gckOS_DumpCallStack(
- + IN gckOS Os
- + );
- +
- +gceSTATUS
- +gckOS_GetProcessNameByPid(
- + IN gctINT Pid,
- + IN gctSIZE_T Length,
- + OUT gctUINT8_PTR String
- + );
- +
- +
- +
- +/*******************************************************************************
- +**
- +** gckOS_AtomConstruct
- +**
- +** Create an atom.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * Atom
- +** Pointer to a variable receiving the constructed atom.
- +*/
- +gceSTATUS
- +gckOS_AtomConstruct(
- + IN gckOS Os,
- + OUT gctPOINTER * Atom
- + );
- +
- +/*******************************************************************************
- +**
- +** gckOS_AtomDestroy
- +**
- +** Destroy an atom.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** gctPOINTER Atom
- +** Pointer to the atom to destroy.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_AtomDestroy(
- + IN gckOS Os,
- + OUT gctPOINTER Atom
- + );
- +
- +/*******************************************************************************
- +**
- +** gckOS_AtomGet
- +**
- +** Get the 32-bit value protected by an atom.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** gctPOINTER Atom
- +** Pointer to the atom.
- +**
- +** OUTPUT:
- +**
- +** gctINT32_PTR Value
- +** Pointer to a variable the receives the value of the atom.
- +*/
- +gceSTATUS
- +gckOS_AtomGet(
- + IN gckOS Os,
- + IN gctPOINTER Atom,
- + OUT gctINT32_PTR Value
- + );
- +
- +/*******************************************************************************
- +**
- +** gckOS_AtomSet
- +**
- +** Set the 32-bit value protected by an atom.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** gctPOINTER Atom
- +** Pointer to the atom.
- +**
- +** gctINT32 Value
- +** The value of the atom.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_AtomSet(
- + IN gckOS Os,
- + IN gctPOINTER Atom,
- + IN gctINT32 Value
- + );
- +
- +/*******************************************************************************
- +**
- +** gckOS_AtomIncrement
- +**
- +** Atomically increment the 32-bit integer value inside an atom.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** gctPOINTER Atom
- +** Pointer to the atom.
- +**
- +** OUTPUT:
- +**
- +** gctINT32_PTR Value
- +** Pointer to a variable the receives the original value of the atom.
- +*/
- +gceSTATUS
- +gckOS_AtomIncrement(
- + IN gckOS Os,
- + IN gctPOINTER Atom,
- + OUT gctINT32_PTR Value
- + );
- +
- +/*******************************************************************************
- +**
- +** gckOS_AtomDecrement
- +**
- +** Atomically decrement the 32-bit integer value inside an atom.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** gctPOINTER Atom
- +** Pointer to the atom.
- +**
- +** OUTPUT:
- +**
- +** gctINT32_PTR Value
- +** Pointer to a variable the receives the original value of the atom.
- +*/
- +gceSTATUS
- +gckOS_AtomDecrement(
- + IN gckOS Os,
- + IN gctPOINTER Atom,
- + OUT gctINT32_PTR Value
- + );
- +
- +/* Delay a number of microseconds. */
- +gceSTATUS
- +gckOS_Delay(
- + IN gckOS Os,
- + IN gctUINT32 Delay
- + );
- +
- +/* Get time in milliseconds. */
- +gceSTATUS
- +gckOS_GetTicks(
- + OUT gctUINT32_PTR Time
- + );
- +
- +/* Compare time value. */
- +gceSTATUS
- +gckOS_TicksAfter(
- + IN gctUINT32 Time1,
- + IN gctUINT32 Time2,
- + OUT gctBOOL_PTR IsAfter
- + );
- +
- +/* Get time in microseconds. */
- +gceSTATUS
- +gckOS_GetTime(
- + OUT gctUINT64_PTR Time
- + );
- +
- +/* Memory barrier. */
- +gceSTATUS
- +gckOS_MemoryBarrier(
- + IN gckOS Os,
- + IN gctPOINTER Address
- + );
- +
- +/* Map user pointer. */
- +gceSTATUS
- +gckOS_MapUserPointer(
- + IN gckOS Os,
- + IN gctPOINTER Pointer,
- + IN gctSIZE_T Size,
- + OUT gctPOINTER * KernelPointer
- + );
- +
- +/* Unmap user pointer. */
- +gceSTATUS
- +gckOS_UnmapUserPointer(
- + IN gckOS Os,
- + IN gctPOINTER Pointer,
- + IN gctSIZE_T Size,
- + IN gctPOINTER KernelPointer
- + );
- +
- +/*******************************************************************************
- +**
- +** gckOS_QueryNeedCopy
- +**
- +** Query whether the memory can be accessed or mapped directly or it has to be
- +** copied.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctUINT32 ProcessID
- +** Process ID of the current process.
- +**
- +** OUTPUT:
- +**
- +** gctBOOL_PTR NeedCopy
- +** Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
- +** gcvFALSE if the memory can be accessed or mapped dircetly.
- +*/
- +gceSTATUS
- +gckOS_QueryNeedCopy(
- + IN gckOS Os,
- + IN gctUINT32 ProcessID,
- + OUT gctBOOL_PTR NeedCopy
- + );
- +
- +/*******************************************************************************
- +**
- +** gckOS_CopyFromUserData
- +**
- +** Copy data from user to kernel memory.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPOINTER KernelPointer
- +** Pointer to kernel memory.
- +**
- +** gctPOINTER Pointer
- +** Pointer to user memory.
- +**
- +** gctSIZE_T Size
- +** Number of bytes to copy.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_CopyFromUserData(
- + IN gckOS Os,
- + IN gctPOINTER KernelPointer,
- + IN gctPOINTER Pointer,
- + IN gctSIZE_T Size
- + );
- +
- +/*******************************************************************************
- +**
- +** gckOS_CopyToUserData
- +**
- +** Copy data from kernel to user memory.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPOINTER KernelPointer
- +** Pointer to kernel memory.
- +**
- +** gctPOINTER Pointer
- +** Pointer to user memory.
- +**
- +** gctSIZE_T Size
- +** Number of bytes to copy.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_CopyToUserData(
- + IN gckOS Os,
- + IN gctPOINTER KernelPointer,
- + IN gctPOINTER Pointer,
- + IN gctSIZE_T Size
- + );
- +
- +#ifdef __QNXNTO__
- +/* Map user physical address. */
- +gceSTATUS
- +gckOS_MapUserPhysical(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Phys,
- + OUT gctPOINTER * KernelPointer
- + );
- +#endif
- +
- +gceSTATUS
- +gckOS_SuspendInterrupt(
- + IN gckOS Os
- + );
- +
- +gceSTATUS
- +gckOS_SuspendInterruptEx(
- + IN gckOS Os,
- + IN gceCORE Core
- + );
- +
- +gceSTATUS
- +gckOS_ResumeInterrupt(
- + IN gckOS Os
- + );
- +
- +gceSTATUS
- +gckOS_ResumeInterruptEx(
- + IN gckOS Os,
- + IN gceCORE Core
- + );
- +
- +/* Get the base address for the physical memory. */
- +gceSTATUS
- +gckOS_GetBaseAddress(
- + IN gckOS Os,
- + OUT gctUINT32_PTR BaseAddress
- + );
- +
- +/* Perform a memory copy. */
- +gceSTATUS
- +gckOS_MemCopy(
- + IN gctPOINTER Destination,
- + IN gctCONST_POINTER Source,
- + IN gctSIZE_T Bytes
- + );
- +
- +/* Zero memory. */
- +gceSTATUS
- +gckOS_ZeroMemory(
- + IN gctPOINTER Memory,
- + IN gctSIZE_T Bytes
- + );
- +
- +/* Device I/O control to the kernel HAL layer. */
- +gceSTATUS
- +gckOS_DeviceControl(
- + IN gckOS Os,
- + IN gctBOOL FromUser,
- + IN gctUINT32 IoControlCode,
- + IN gctPOINTER InputBuffer,
- + IN gctSIZE_T InputBufferSize,
- + OUT gctPOINTER OutputBuffer,
- + IN gctSIZE_T OutputBufferSize
- + );
- +
- +/*******************************************************************************
- +**
- +** gckOS_GetProcessID
- +**
- +** Get current process ID.
- +**
- +** INPUT:
- +**
- +** Nothing.
- +**
- +** OUTPUT:
- +**
- +** gctUINT32_PTR ProcessID
- +** Pointer to the variable that receives the process ID.
- +*/
- +gceSTATUS
- +gckOS_GetProcessID(
- + OUT gctUINT32_PTR ProcessID
- + );
- +
- +gceSTATUS
- +gckOS_GetCurrentProcessID(
- + OUT gctUINT32_PTR ProcessID
- + );
- +
- +/*******************************************************************************
- +**
- +** gckOS_GetThreadID
- +**
- +** Get current thread ID.
- +**
- +** INPUT:
- +**
- +** Nothing.
- +**
- +** OUTPUT:
- +**
- +** gctUINT32_PTR ThreadID
- +** Pointer to the variable that receives the thread ID.
- +*/
- +gceSTATUS
- +gckOS_GetThreadID(
- + OUT gctUINT32_PTR ThreadID
- + );
- +
- +/******************************************************************************\
- +********************************** Signal Object *********************************
- +\******************************************************************************/
- +
- +/* Create a signal. */
- +gceSTATUS
- +gckOS_CreateSignal(
- + IN gckOS Os,
- + IN gctBOOL ManualReset,
- + OUT gctSIGNAL * Signal
- + );
- +
- +/* Destroy a signal. */
- +gceSTATUS
- +gckOS_DestroySignal(
- + IN gckOS Os,
- + IN gctSIGNAL Signal
- + );
- +
- +/* Signal a signal. */
- +gceSTATUS
- +gckOS_Signal(
- + IN gckOS Os,
- + IN gctSIGNAL Signal,
- + IN gctBOOL State
- + );
- +
- +/* Wait for a signal. */
- +gceSTATUS
- +gckOS_WaitSignal(
- + IN gckOS Os,
- + IN gctSIGNAL Signal,
- + IN gctUINT32 Wait
- + );
- +
- +/* Map a user signal to the kernel space. */
- +gceSTATUS
- +gckOS_MapSignal(
- + IN gckOS Os,
- + IN gctSIGNAL Signal,
- + IN gctHANDLE Process,
- + OUT gctSIGNAL * MappedSignal
- + );
- +
- +/* Unmap a user signal */
- +gceSTATUS
- +gckOS_UnmapSignal(
- + IN gckOS Os,
- + IN gctSIGNAL Signal
- + );
- +
- +/* Map user memory. */
- +gceSTATUS
- +gckOS_MapUserMemory(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctPOINTER Memory,
- + IN gctUINT32 Physical,
- + IN gctSIZE_T Size,
- + OUT gctPOINTER * Info,
- + OUT gctUINT32_PTR Address
- + );
- +
- +/* Unmap user memory. */
- +gceSTATUS
- +gckOS_UnmapUserMemory(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctPOINTER Memory,
- + IN gctSIZE_T Size,
- + IN gctPOINTER Info,
- + IN gctUINT32 Address
- + );
- +
- +/******************************************************************************\
- +************************** Android Native Fence Sync ***************************
- +\******************************************************************************/
- +gceSTATUS
- +gckOS_CreateSyncTimeline(
- + IN gckOS Os,
- + OUT gctHANDLE * Timeline
- + );
- +
- +gceSTATUS
- +gckOS_DestroySyncTimeline(
- + IN gckOS Os,
- + IN gctHANDLE Timeline
- + );
- +
- +gceSTATUS
- +gckOS_CreateSyncPoint(
- + IN gckOS Os,
- + OUT gctSYNC_POINT * SyncPoint
- + );
- +
- +gceSTATUS
- +gckOS_ReferenceSyncPoint(
- + IN gckOS Os,
- + IN gctSYNC_POINT SyncPoint
- + );
- +
- +gceSTATUS
- +gckOS_DestroySyncPoint(
- + IN gckOS Os,
- + IN gctSYNC_POINT SyncPoint
- + );
- +
- +gceSTATUS
- +gckOS_SignalSyncPoint(
- + IN gckOS Os,
- + IN gctSYNC_POINT SyncPoint
- + );
- +
- +gceSTATUS
- +gckOS_QuerySyncPoint(
- + IN gckOS Os,
- + IN gctSYNC_POINT SyncPoint,
- + OUT gctBOOL_PTR State
- + );
- +
- +gceSTATUS
- +gckOS_CreateNativeFence(
- + IN gckOS Os,
- + IN gctHANDLE Timeline,
- + IN gctSYNC_POINT SyncPoint,
- + OUT gctINT * FenceFD
- + );
- +
- +#if !USE_NEW_LINUX_SIGNAL
- +/* Create signal to be used in the user space. */
- +gceSTATUS
- +gckOS_CreateUserSignal(
- + IN gckOS Os,
- + IN gctBOOL ManualReset,
- + OUT gctINT * SignalID
- + );
- +
- +/* Destroy signal used in the user space. */
- +gceSTATUS
- +gckOS_DestroyUserSignal(
- + IN gckOS Os,
- + IN gctINT SignalID
- + );
- +
- +/* Wait for signal used in the user space. */
- +gceSTATUS
- +gckOS_WaitUserSignal(
- + IN gckOS Os,
- + IN gctINT SignalID,
- + IN gctUINT32 Wait
- + );
- +
- +/* Signal a signal used in the user space. */
- +gceSTATUS
- +gckOS_SignalUserSignal(
- + IN gckOS Os,
- + IN gctINT SignalID,
- + IN gctBOOL State
- + );
- +#endif /* USE_NEW_LINUX_SIGNAL */
- +
- +/* Set a signal owned by a process. */
- +#if defined(__QNXNTO__)
- +gceSTATUS
- +gckOS_UserSignal(
- + IN gckOS Os,
- + IN gctSIGNAL Signal,
- + IN gctINT Recvid,
- + IN gctINT Coid
- + );
- +#else
- +gceSTATUS
- +gckOS_UserSignal(
- + IN gckOS Os,
- + IN gctSIGNAL Signal,
- + IN gctHANDLE Process
- + );
- +#endif
- +
- +/******************************************************************************\
- +** Cache Support
- +*/
- +
- +gceSTATUS
- +gckOS_CacheClean(
- + gckOS Os,
- + gctUINT32 ProcessID,
- + gctPHYS_ADDR Handle,
- + gctPOINTER Physical,
- + gctPOINTER Logical,
- + gctSIZE_T Bytes
- + );
- +
- +gceSTATUS
- +gckOS_CacheFlush(
- + gckOS Os,
- + gctUINT32 ProcessID,
- + gctPHYS_ADDR Handle,
- + gctPOINTER Physical,
- + gctPOINTER Logical,
- + gctSIZE_T Bytes
- + );
- +
- +gceSTATUS
- +gckOS_CacheInvalidate(
- + gckOS Os,
- + gctUINT32 ProcessID,
- + gctPHYS_ADDR Handle,
- + gctPOINTER Physical,
- + gctPOINTER Logical,
- + gctSIZE_T Bytes
- + );
- +
- +/******************************************************************************\
- +** Debug Support
- +*/
- +
- +void
- +gckOS_SetDebugLevel(
- + IN gctUINT32 Level
- + );
- +
- +void
- +gckOS_SetDebugZone(
- + IN gctUINT32 Zone
- + );
- +
- +void
- +gckOS_SetDebugLevelZone(
- + IN gctUINT32 Level,
- + IN gctUINT32 Zone
- + );
- +
- +void
- +gckOS_SetDebugZones(
- + IN gctUINT32 Zones,
- + IN gctBOOL Enable
- + );
- +
- +void
- +gckOS_SetDebugFile(
- + IN gctCONST_STRING FileName
- + );
- +
- +/*******************************************************************************
- +** Broadcast interface.
- +*/
- +
- +typedef enum _gceBROADCAST
- +{
- + /* GPU might be idle. */
- + gcvBROADCAST_GPU_IDLE,
- +
- + /* A commit is going to happen. */
- + gcvBROADCAST_GPU_COMMIT,
- +
- + /* GPU seems to be stuck. */
- + gcvBROADCAST_GPU_STUCK,
- +
- + /* First process gets attached. */
- + gcvBROADCAST_FIRST_PROCESS,
- +
- + /* Last process gets detached. */
- + gcvBROADCAST_LAST_PROCESS,
- +
- + /* AXI bus error. */
- + gcvBROADCAST_AXI_BUS_ERROR,
- +}
- +gceBROADCAST;
- +
- +gceSTATUS
- +gckOS_Broadcast(
- + IN gckOS Os,
- + IN gckHARDWARE Hardware,
- + IN gceBROADCAST Reason
- + );
- +
- +gceSTATUS
- +gckOS_BroadcastHurry(
- + IN gckOS Os,
- + IN gckHARDWARE Hardware,
- + IN gctUINT Urgency
- + );
- +
- +gceSTATUS
- +gckOS_BroadcastCalibrateSpeed(
- + IN gckOS Os,
- + IN gckHARDWARE Hardware,
- + IN gctUINT Idle,
- + IN gctUINT Time
- + );
- +
- +/*******************************************************************************
- +**
- +** gckOS_SetGPUPower
- +**
- +** Set the power of the GPU on or off.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.ß
- +**
- +** gckCORE Core
- +** GPU whose power is set.
- +**
- +** gctBOOL Clock
- +** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
- +**
- +** gctBOOL Power
- +** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_SetGPUPower(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctBOOL Clock,
- + IN gctBOOL Power
- + );
- +
- +gceSTATUS
- +gckOS_ResetGPU(
- + IN gckOS Os,
- + IN gceCORE Core
- + );
- +
- +gceSTATUS
- +gckOS_PrepareGPUFrequency(
- + IN gckOS Os,
- + IN gceCORE Core
- + );
- +
- +gceSTATUS
- +gckOS_FinishGPUFrequency(
- + IN gckOS Os,
- + IN gceCORE Core
- + );
- +
- +gceSTATUS
- +gckOS_QueryGPUFrequency(
- + IN gckOS Os,
- + IN gceCORE Core,
- + OUT gctUINT32 * Frequency,
- + OUT gctUINT8 * Scale
- + );
- +
- +gceSTATUS
- +gckOS_SetGPUFrequency(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctUINT8 Scale
- + );
- +
- +/*******************************************************************************
- +** Semaphores.
- +*/
- +
- +/* Create a new semaphore. */
- +gceSTATUS
- +gckOS_CreateSemaphore(
- + IN gckOS Os,
- + OUT gctPOINTER * Semaphore
- + );
- +
- +#if gcdENABLE_VG
- +gceSTATUS
- +gckOS_CreateSemaphoreVG(
- + IN gckOS Os,
- + OUT gctPOINTER * Semaphore
- + );
- +#endif
- +
- +/* Delete a semahore. */
- +gceSTATUS
- +gckOS_DestroySemaphore(
- + IN gckOS Os,
- + IN gctPOINTER Semaphore
- + );
- +
- +/* Acquire a semahore. */
- +gceSTATUS
- +gckOS_AcquireSemaphore(
- + IN gckOS Os,
- + IN gctPOINTER Semaphore
- + );
- +
- +/* Try to acquire a semahore. */
- +gceSTATUS
- +gckOS_TryAcquireSemaphore(
- + IN gckOS Os,
- + IN gctPOINTER Semaphore
- + );
- +
- +/* Release a semahore. */
- +gceSTATUS
- +gckOS_ReleaseSemaphore(
- + IN gckOS Os,
- + IN gctPOINTER Semaphore
- + );
- +
- +/*******************************************************************************
- +** Timer API.
- +*/
- +
- +typedef void (*gctTIMERFUNCTION)(gctPOINTER);
- +
- +/* Create a timer. */
- +gceSTATUS
- +gckOS_CreateTimer(
- + IN gckOS Os,
- + IN gctTIMERFUNCTION Function,
- + IN gctPOINTER Data,
- + OUT gctPOINTER * Timer
- + );
- +
- +/* Destory a timer. */
- +gceSTATUS
- +gckOS_DestroyTimer(
- + IN gckOS Os,
- + IN gctPOINTER Timer
- + );
- +
- +/* Start a timer. */
- +gceSTATUS
- +gckOS_StartTimer(
- + IN gckOS Os,
- + IN gctPOINTER Timer,
- + IN gctUINT32 Delay
- + );
- +
- +/* Stop a timer. */
- +gceSTATUS
- +gckOS_StopTimer(
- + IN gckOS Os,
- + IN gctPOINTER Timer
- + );
- +
- +/******************************************************************************\
- +********************************* gckHEAP Object ********************************
- +\******************************************************************************/
- +
- +typedef struct _gckHEAP * gckHEAP;
- +
- +/* Construct a new gckHEAP object. */
- +gceSTATUS
- +gckHEAP_Construct(
- + IN gckOS Os,
- + IN gctSIZE_T AllocationSize,
- + OUT gckHEAP * Heap
- + );
- +
- +/* Destroy an gckHEAP object. */
- +gceSTATUS
- +gckHEAP_Destroy(
- + IN gckHEAP Heap
- + );
- +
- +/* Allocate memory. */
- +gceSTATUS
- +gckHEAP_Allocate(
- + IN gckHEAP Heap,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER * Node
- + );
- +
- +/* Free memory. */
- +gceSTATUS
- +gckHEAP_Free(
- + IN gckHEAP Heap,
- + IN gctPOINTER Node
- + );
- +
- +/* Profile the heap. */
- +gceSTATUS
- +gckHEAP_ProfileStart(
- + IN gckHEAP Heap
- + );
- +
- +gceSTATUS
- +gckHEAP_ProfileEnd(
- + IN gckHEAP Heap,
- + IN gctCONST_STRING Title
- + );
- +
- +
- +/******************************************************************************\
- +******************************** gckVIDMEM Object ******************************
- +\******************************************************************************/
- +
- +typedef struct _gckVIDMEM * gckVIDMEM;
- +typedef struct _gckKERNEL * gckKERNEL;
- +typedef struct _gckDB * gckDB;
- +typedef struct _gckDVFS * gckDVFS;
- +
- +/* Construct a new gckVIDMEM object. */
- +gceSTATUS
- +gckVIDMEM_Construct(
- + IN gckOS Os,
- + IN gctUINT32 BaseAddress,
- + IN gctSIZE_T Bytes,
- + IN gctSIZE_T Threshold,
- + IN gctSIZE_T Banking,
- + OUT gckVIDMEM * Memory
- + );
- +
- +/* Destroy an gckVDIMEM object. */
- +gceSTATUS
- +gckVIDMEM_Destroy(
- + IN gckVIDMEM Memory
- + );
- +
- +/* Allocate rectangular memory. */
- +gceSTATUS
- +gckVIDMEM_Allocate(
- + IN gckVIDMEM Memory,
- + IN gctUINT Width,
- + IN gctUINT Height,
- + IN gctUINT Depth,
- + IN gctUINT BytesPerPixel,
- + IN gctUINT32 Alignment,
- + IN gceSURF_TYPE Type,
- + OUT gcuVIDMEM_NODE_PTR * Node
- + );
- +
- +/* Allocate linear memory. */
- +gceSTATUS
- +gckVIDMEM_AllocateLinear(
- + IN gckVIDMEM Memory,
- + IN gctSIZE_T Bytes,
- + IN gctUINT32 Alignment,
- + IN gceSURF_TYPE Type,
- + OUT gcuVIDMEM_NODE_PTR * Node
- + );
- +
- +/* Free memory. */
- +gceSTATUS
- +gckVIDMEM_Free(
- + IN gcuVIDMEM_NODE_PTR Node
- + );
- +
- +/* Lock memory. */
- +gceSTATUS
- +gckVIDMEM_Lock(
- + IN gckKERNEL Kernel,
- + IN gcuVIDMEM_NODE_PTR Node,
- + IN gctBOOL Cacheable,
- + OUT gctUINT32 * Address
- + );
- +
- +/* Unlock memory. */
- +gceSTATUS
- +gckVIDMEM_Unlock(
- + IN gckKERNEL Kernel,
- + IN gcuVIDMEM_NODE_PTR Node,
- + IN gceSURF_TYPE Type,
- + IN OUT gctBOOL * Asynchroneous
- + );
- +
- +/* Construct a gcuVIDMEM_NODE union for virtual memory. */
- +gceSTATUS
- +gckVIDMEM_ConstructVirtual(
- + IN gckKERNEL Kernel,
- + IN gctBOOL Contiguous,
- + IN gctSIZE_T Bytes,
- + OUT gcuVIDMEM_NODE_PTR * Node
- + );
- +
- +/* Destroy a gcuVIDMEM_NODE union for virtual memory. */
- +gceSTATUS
- +gckVIDMEM_DestroyVirtual(
- + IN gcuVIDMEM_NODE_PTR Node
- + );
- +
- +/******************************************************************************\
- +******************************** gckKERNEL Object ******************************
- +\******************************************************************************/
- +
- +struct _gcsHAL_INTERFACE;
- +
- +/* Notifications. */
- +typedef enum _gceNOTIFY
- +{
- + gcvNOTIFY_INTERRUPT,
- + gcvNOTIFY_COMMAND_QUEUE,
- +}
- +gceNOTIFY;
- +
- +/* Flush flags. */
- +typedef enum _gceKERNEL_FLUSH
- +{
- + gcvFLUSH_COLOR = 0x01,
- + gcvFLUSH_DEPTH = 0x02,
- + gcvFLUSH_TEXTURE = 0x04,
- + gcvFLUSH_2D = 0x08,
- + gcvFLUSH_ALL = gcvFLUSH_COLOR
- + | gcvFLUSH_DEPTH
- + | gcvFLUSH_TEXTURE
- + | gcvFLUSH_2D,
- +}
- +gceKERNEL_FLUSH;
- +
- +/* Construct a new gckKERNEL object. */
- +gceSTATUS
- +gckKERNEL_Construct(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctPOINTER Context,
- + IN gckDB SharedDB,
- + OUT gckKERNEL * Kernel
- + );
- +
- +/* Destroy an gckKERNEL object. */
- +gceSTATUS
- +gckKERNEL_Destroy(
- + IN gckKERNEL Kernel
- + );
- +
- +/* Dispatch a user-level command. */
- +gceSTATUS
- +gckKERNEL_Dispatch(
- + IN gckKERNEL Kernel,
- + IN gctBOOL FromUser,
- + IN OUT struct _gcsHAL_INTERFACE * Interface
- + );
- +
- +/* Query the video memory. */
- +gceSTATUS
- +gckKERNEL_QueryVideoMemory(
- + IN gckKERNEL Kernel,
- + OUT struct _gcsHAL_INTERFACE * Interface
- + );
- +
- +/* Lookup the gckVIDMEM object for a pool. */
- +gceSTATUS
- +gckKERNEL_GetVideoMemoryPool(
- + IN gckKERNEL Kernel,
- + IN gcePOOL Pool,
- + OUT gckVIDMEM * VideoMemory
- + );
- +
- +#if gcdUSE_VIDMEM_PER_PID
- +gceSTATUS
- +gckKERNEL_GetVideoMemoryPoolPid(
- + IN gckKERNEL Kernel,
- + IN gcePOOL Pool,
- + IN gctUINT32 Pid,
- + OUT gckVIDMEM * VideoMemory
- + );
- +
- +gceSTATUS
- +gckKERNEL_CreateVideoMemoryPoolPid(
- + IN gckKERNEL Kernel,
- + IN gcePOOL Pool,
- + IN gctUINT32 Pid,
- + OUT gckVIDMEM * VideoMemory
- + );
- +
- +gceSTATUS
- +gckKERNEL_RemoveVideoMemoryPoolPid(
- + IN gckKERNEL Kernel,
- + IN gckVIDMEM VideoMemory
- + );
- +#endif
- +
- +/* Map video memory. */
- +gceSTATUS
- +gckKERNEL_MapVideoMemory(
- + IN gckKERNEL Kernel,
- + IN gctBOOL InUserSpace,
- + IN gctUINT32 Address,
- +#ifdef __QNXNTO__
- + IN gctUINT32 Pid,
- + IN gctUINT32 Bytes,
- +#endif
- + OUT gctPOINTER * Logical
- + );
- +
- +/* Map video memory. */
- +gceSTATUS
- +gckKERNEL_MapVideoMemoryEx(
- + IN gckKERNEL Kernel,
- + IN gceCORE Core,
- + IN gctBOOL InUserSpace,
- + IN gctUINT32 Address,
- +#ifdef __QNXNTO__
- + IN gctUINT32 Pid,
- + IN gctUINT32 Bytes,
- +#endif
- + OUT gctPOINTER * Logical
- + );
- +
- +#ifdef __QNXNTO__
- +/* Unmap video memory. */
- +gceSTATUS
- +gckKERNEL_UnmapVideoMemory(
- + IN gckKERNEL Kernel,
- + IN gctPOINTER Logical,
- + IN gctUINT32 Pid,
- + IN gctUINT32 Bytes
- + );
- +#endif
- +
- +/* Map memory. */
- +gceSTATUS
- +gckKERNEL_MapMemory(
- + IN gckKERNEL Kernel,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER * Logical
- + );
- +
- +/* Unmap memory. */
- +gceSTATUS
- +gckKERNEL_UnmapMemory(
- + IN gckKERNEL Kernel,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes,
- + IN gctPOINTER Logical
- + );
- +
- +/* Notification of events. */
- +gceSTATUS
- +gckKERNEL_Notify(
- + IN gckKERNEL Kernel,
- + IN gceNOTIFY Notifcation,
- + IN gctBOOL Data
- + );
- +
- +gceSTATUS
- +gckKERNEL_QuerySettings(
- + IN gckKERNEL Kernel,
- + OUT gcsKERNEL_SETTINGS * Settings
- + );
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_Recovery
- +**
- +** Try to recover the GPU from a fatal error.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckKERNEL_Recovery(
- + IN gckKERNEL Kernel
- + );
- +
- +/* Set the value of timeout on HW operation. */
- +void
- +gckKERNEL_SetTimeOut(
- + IN gckKERNEL Kernel,
- + IN gctUINT32 timeOut
- + );
- +
- +/* Get access to the user data. */
- +gceSTATUS
- +gckKERNEL_OpenUserData(
- + IN gckKERNEL Kernel,
- + IN gctBOOL NeedCopy,
- + IN gctPOINTER StaticStorage,
- + IN gctPOINTER UserPointer,
- + IN gctSIZE_T Size,
- + OUT gctPOINTER * KernelPointer
- + );
- +
- +/* Release resources associated with the user data connection. */
- +gceSTATUS
- +gckKERNEL_CloseUserData(
- + IN gckKERNEL Kernel,
- + IN gctBOOL NeedCopy,
- + IN gctBOOL FlushData,
- + IN gctPOINTER UserPointer,
- + IN gctSIZE_T Size,
- + OUT gctPOINTER * KernelPointer
- + );
- +
- +gceSTATUS
- +gckDVFS_Construct(
- + IN gckHARDWARE Hardware,
- + OUT gckDVFS * Frequency
- + );
- +
- +gceSTATUS
- +gckDVFS_Destroy(
- + IN gckDVFS Dvfs
- + );
- +
- +gceSTATUS
- +gckDVFS_Start(
- + IN gckDVFS Dvfs
- + );
- +
- +gceSTATUS
- +gckDVFS_Stop(
- + IN gckDVFS Dvfs
- + );
- +
- +/******************************************************************************\
- +******************************* gckHARDWARE Object *****************************
- +\******************************************************************************/
- +
- +/* Construct a new gckHARDWARE object. */
- +gceSTATUS
- +gckHARDWARE_Construct(
- + IN gckOS Os,
- + IN gceCORE Core,
- + OUT gckHARDWARE * Hardware
- + );
- +
- +/* Destroy an gckHARDWARE object. */
- +gceSTATUS
- +gckHARDWARE_Destroy(
- + IN gckHARDWARE Hardware
- + );
- +
- +/* Get hardware type. */
- +gceSTATUS
- +gckHARDWARE_GetType(
- + IN gckHARDWARE Hardware,
- + OUT gceHARDWARE_TYPE * Type
- + );
- +
- +/* Query system memory requirements. */
- +gceSTATUS
- +gckHARDWARE_QuerySystemMemory(
- + IN gckHARDWARE Hardware,
- + OUT gctSIZE_T * SystemSize,
- + OUT gctUINT32 * SystemBaseAddress
- + );
- +
- +/* Build virtual address. */
- +gceSTATUS
- +gckHARDWARE_BuildVirtualAddress(
- + IN gckHARDWARE Hardware,
- + IN gctUINT32 Index,
- + IN gctUINT32 Offset,
- + OUT gctUINT32 * Address
- + );
- +
- +/* Query command buffer requirements. */
- +gceSTATUS
- +gckHARDWARE_QueryCommandBuffer(
- + IN gckHARDWARE Hardware,
- + OUT gctSIZE_T * Alignment,
- + OUT gctSIZE_T * ReservedHead,
- + OUT gctSIZE_T * ReservedTail
- + );
- +
- +/* Add a WAIT/LINK pair in the command queue. */
- +gceSTATUS
- +gckHARDWARE_WaitLink(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + IN gctUINT32 Offset,
- + IN OUT gctSIZE_T * Bytes,
- + OUT gctUINT32 * WaitOffset,
- + OUT gctSIZE_T * WaitBytes
- + );
- +
- +/* Kickstart the command processor. */
- +gceSTATUS
- +gckHARDWARE_Execute(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- +#ifdef __QNXNTO__
- + IN gctPOINTER Physical,
- + IN gctBOOL PhysicalAddresses,
- +#endif
- + IN gctSIZE_T Bytes
- + );
- +
- +/* Add an END command in the command queue. */
- +gceSTATUS
- +gckHARDWARE_End(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + IN OUT gctSIZE_T * Bytes
- + );
- +
- +/* Add a NOP command in the command queue. */
- +gceSTATUS
- +gckHARDWARE_Nop(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + IN OUT gctSIZE_T * Bytes
- + );
- +
- +/* Add a WAIT command in the command queue. */
- +gceSTATUS
- +gckHARDWARE_Wait(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + IN gctUINT32 Count,
- + IN OUT gctSIZE_T * Bytes
- + );
- +
- +/* Add a PIPESELECT command in the command queue. */
- +gceSTATUS
- +gckHARDWARE_PipeSelect(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + IN gcePIPE_SELECT Pipe,
- + IN OUT gctSIZE_T * Bytes
- + );
- +
- +/* Add a LINK command in the command queue. */
- +gceSTATUS
- +gckHARDWARE_Link(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + IN gctPOINTER FetchAddress,
- + IN gctSIZE_T FetchSize,
- + IN OUT gctSIZE_T * Bytes
- + );
- +
- +/* Add an EVENT command in the command queue. */
- +gceSTATUS
- +gckHARDWARE_Event(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + IN gctUINT8 Event,
- + IN gceKERNEL_WHERE FromWhere,
- + IN OUT gctSIZE_T * Bytes
- + );
- +
- +/* Query the available memory. */
- +gceSTATUS
- +gckHARDWARE_QueryMemory(
- + IN gckHARDWARE Hardware,
- + OUT gctSIZE_T * InternalSize,
- + OUT gctUINT32 * InternalBaseAddress,
- + OUT gctUINT32 * InternalAlignment,
- + OUT gctSIZE_T * ExternalSize,
- + OUT gctUINT32 * ExternalBaseAddress,
- + OUT gctUINT32 * ExternalAlignment,
- + OUT gctUINT32 * HorizontalTileSize,
- + OUT gctUINT32 * VerticalTileSize
- + );
- +
- +/* Query the identity of the hardware. */
- +gceSTATUS
- +gckHARDWARE_QueryChipIdentity(
- + IN gckHARDWARE Hardware,
- + OUT gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
- + );
- +
- +/* Query the shader support. */
- +gceSTATUS
- +gckHARDWARE_QueryShaderCaps(
- + IN gckHARDWARE Hardware,
- + OUT gctUINT * VertexUniforms,
- + OUT gctUINT * FragmentUniforms,
- + OUT gctUINT * Varyings
- + );
- +
- +/* Split a harwdare specific address into API stuff. */
- +gceSTATUS
- +gckHARDWARE_SplitMemory(
- + IN gckHARDWARE Hardware,
- + IN gctUINT32 Address,
- + OUT gcePOOL * Pool,
- + OUT gctUINT32 * Offset
- + );
- +
- +/* Update command queue tail pointer. */
- +gceSTATUS
- +gckHARDWARE_UpdateQueueTail(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + IN gctUINT32 Offset
- + );
- +
- +/* Convert logical address to hardware specific address. */
- +gceSTATUS
- +gckHARDWARE_ConvertLogical(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + OUT gctUINT32 * Address
- + );
- +
- +#ifdef __QNXNTO__
- +/* Convert physical address to hardware specific address. */
- +gceSTATUS
- +gckHARDWARE_ConvertPhysical(
- + IN gckHARDWARE Hardware,
- + IN gctPHYS_ADDR Physical,
- + OUT gctUINT32 * Address
- + );
- +#endif
- +
- +/* Interrupt manager. */
- +gceSTATUS
- +gckHARDWARE_Interrupt(
- + IN gckHARDWARE Hardware,
- + IN gctBOOL InterruptValid
- + );
- +
- +/* Program MMU. */
- +gceSTATUS
- +gckHARDWARE_SetMMU(
- + IN gckHARDWARE Hardware,
- + IN gctPOINTER Logical
- + );
- +
- +/* Flush the MMU. */
- +gceSTATUS
- +gckHARDWARE_FlushMMU(
- + IN gckHARDWARE Hardware
- + );
- +
- +/* Set the page table base address. */
- +gceSTATUS
- +gckHARDWARE_SetMMUv2(
- + IN gckHARDWARE Hardware,
- + IN gctBOOL Enable,
- + IN gctPOINTER MtlbAddress,
- + IN gceMMU_MODE Mode,
- + IN gctPOINTER SafeAddress,
- + IN gctBOOL FromPower
- + );
- +
- +/* Get idle register. */
- +gceSTATUS
- +gckHARDWARE_GetIdle(
- + IN gckHARDWARE Hardware,
- + IN gctBOOL Wait,
- + OUT gctUINT32 * Data
- + );
- +
- +/* Flush the caches. */
- +gceSTATUS
- +gckHARDWARE_Flush(
- + IN gckHARDWARE Hardware,
- + IN gceKERNEL_FLUSH Flush,
- + IN gctPOINTER Logical,
- + IN OUT gctSIZE_T * Bytes
- + );
- +
- +/* Enable/disable fast clear. */
- +gceSTATUS
- +gckHARDWARE_SetFastClear(
- + IN gckHARDWARE Hardware,
- + IN gctINT Enable,
- + IN gctINT Compression
- + );
- +
- +gceSTATUS
- +gckHARDWARE_ReadInterrupt(
- + IN gckHARDWARE Hardware,
- + OUT gctUINT32_PTR IDs
- + );
- +
- +/* Power management. */
- +gceSTATUS
- +gckHARDWARE_SetPowerManagementState(
- + IN gckHARDWARE Hardware,
- + IN gceCHIPPOWERSTATE State
- + );
- +
- +gceSTATUS
- +gckHARDWARE_QueryPowerManagementState(
- + IN gckHARDWARE Hardware,
- + OUT gceCHIPPOWERSTATE* State
- + );
- +
- +gceSTATUS
- +gckHARDWARE_SetPowerManagement(
- + IN gckHARDWARE Hardware,
- + IN gctBOOL PowerManagement
- + );
- +
- +gceSTATUS
- +gckHARDWARE_SetGpuProfiler(
- + IN gckHARDWARE Hardware,
- + IN gctBOOL GpuProfiler
- + );
- +
- +#if gcdENABLE_FSCALE_VAL_ADJUST
- +gceSTATUS
- +gckHARDWARE_SetFscaleValue(
- + IN gckHARDWARE Hardware,
- + IN gctUINT32 FscaleValue
- + );
- +
- +gceSTATUS
- +gckHARDWARE_GetFscaleValue(
- + IN gckHARDWARE Hardware,
- + IN gctUINT * FscaleValue,
- + IN gctUINT * MinFscaleValue,
- + IN gctUINT * MaxFscaleValue
- + );
- +#endif
- +
- +#if gcdPOWEROFF_TIMEOUT
- +gceSTATUS
- +gckHARDWARE_SetPowerOffTimeout(
- + IN gckHARDWARE Hardware,
- + IN gctUINT32 Timeout
- +);
- +
- +gceSTATUS
- +gckHARDWARE_QueryPowerOffTimeout(
- + IN gckHARDWARE Hardware,
- + OUT gctUINT32* Timeout
- +);
- +#endif
- +
- +/* Profile 2D Engine. */
- +gceSTATUS
- +gckHARDWARE_ProfileEngine2D(
- + IN gckHARDWARE Hardware,
- + OUT gcs2D_PROFILE_PTR Profile
- + );
- +
- +gceSTATUS
- +gckHARDWARE_InitializeHardware(
- + IN gckHARDWARE Hardware
- + );
- +
- +gceSTATUS
- +gckHARDWARE_Reset(
- + IN gckHARDWARE Hardware
- + );
- +
- +typedef gceSTATUS (*gctISRMANAGERFUNC)(gctPOINTER Context, gceCORE Core);
- +
- +gceSTATUS
- +gckHARDWARE_SetIsrManager(
- + IN gckHARDWARE Hardware,
- + IN gctISRMANAGERFUNC StartIsr,
- + IN gctISRMANAGERFUNC StopIsr,
- + IN gctPOINTER Context
- + );
- +
- +/* Start a composition. */
- +gceSTATUS
- +gckHARDWARE_Compose(
- + IN gckHARDWARE Hardware,
- + IN gctUINT32 ProcessID,
- + IN gctPHYS_ADDR Physical,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Offset,
- + IN gctSIZE_T Size,
- + IN gctUINT8 EventID
- + );
- +
- +/* Check for Hardware features. */
- +gceSTATUS
- +gckHARDWARE_IsFeatureAvailable(
- + IN gckHARDWARE Hardware,
- + IN gceFEATURE Feature
- + );
- +
- +gceSTATUS
- +gckHARDWARE_DumpMMUException(
- + IN gckHARDWARE Hardware
- + );
- +
- +gceSTATUS
- +gckHARDWARE_DumpGPUState(
- + IN gckHARDWARE Hardware
- + );
- +
- +gceSTATUS
- +gckHARDWARE_InitDVFS(
- + IN gckHARDWARE Hardware
- + );
- +
- +gceSTATUS
- +gckHARDWARE_QueryLoad(
- + IN gckHARDWARE Hardware,
- + OUT gctUINT32 * Load
- + );
- +
- +gceSTATUS
- +gckHARDWARE_SetDVFSPeroid(
- + IN gckHARDWARE Hardware,
- + IN gctUINT32 Frequency
- + );
- +
- +#if !gcdENABLE_VG
- +/******************************************************************************\
- +***************************** gckINTERRUPT Object ******************************
- +\******************************************************************************/
- +
- +typedef struct _gckINTERRUPT * gckINTERRUPT;
- +
- +typedef gceSTATUS (* gctINTERRUPT_HANDLER)(
- + IN gckKERNEL Kernel
- + );
- +
- +gceSTATUS
- +gckINTERRUPT_Construct(
- + IN gckKERNEL Kernel,
- + OUT gckINTERRUPT * Interrupt
- + );
- +
- +gceSTATUS
- +gckINTERRUPT_Destroy(
- + IN gckINTERRUPT Interrupt
- + );
- +
- +gceSTATUS
- +gckINTERRUPT_SetHandler(
- + IN gckINTERRUPT Interrupt,
- + IN OUT gctINT32_PTR Id,
- + IN gctINTERRUPT_HANDLER Handler
- + );
- +
- +gceSTATUS
- +gckINTERRUPT_Notify(
- + IN gckINTERRUPT Interrupt,
- + IN gctBOOL Valid
- + );
- +#endif
- +/******************************************************************************\
- +******************************** gckEVENT Object *******************************
- +\******************************************************************************/
- +
- +typedef struct _gckEVENT * gckEVENT;
- +
- +/* Construct a new gckEVENT object. */
- +gceSTATUS
- +gckEVENT_Construct(
- + IN gckKERNEL Kernel,
- + OUT gckEVENT * Event
- + );
- +
- +/* Destroy an gckEVENT object. */
- +gceSTATUS
- +gckEVENT_Destroy(
- + IN gckEVENT Event
- + );
- +
- +/* Add a new event to the list of events. */
- +gceSTATUS
- +gckEVENT_AddList(
- + IN gckEVENT Event,
- + IN gcsHAL_INTERFACE_PTR Interface,
- + IN gceKERNEL_WHERE FromWhere,
- + IN gctBOOL AllocateAllowed,
- + IN gctBOOL FromKernel
- + );
- +
- +/* Schedule a FreeNonPagedMemory event. */
- +gceSTATUS
- +gckEVENT_FreeNonPagedMemory(
- + IN gckEVENT Event,
- + IN gctSIZE_T Bytes,
- + IN gctPHYS_ADDR Physical,
- + IN gctPOINTER Logical,
- + IN gceKERNEL_WHERE FromWhere
- + );
- +
- +/* Schedule a FreeContiguousMemory event. */
- +gceSTATUS
- +gckEVENT_FreeContiguousMemory(
- + IN gckEVENT Event,
- + IN gctSIZE_T Bytes,
- + IN gctPHYS_ADDR Physical,
- + IN gctPOINTER Logical,
- + IN gceKERNEL_WHERE FromWhere
- + );
- +
- +/* Schedule a FreeVideoMemory event. */
- +gceSTATUS
- +gckEVENT_FreeVideoMemory(
- + IN gckEVENT Event,
- + IN gcuVIDMEM_NODE_PTR VideoMemory,
- + IN gceKERNEL_WHERE FromWhere
- + );
- +
- +/* Schedule a signal event. */
- +gceSTATUS
- +gckEVENT_Signal(
- + IN gckEVENT Event,
- + IN gctSIGNAL Signal,
- + IN gceKERNEL_WHERE FromWhere
- + );
- +
- +/* Schedule an Unlock event. */
- +gceSTATUS
- +gckEVENT_Unlock(
- + IN gckEVENT Event,
- + IN gceKERNEL_WHERE FromWhere,
- + IN gcuVIDMEM_NODE_PTR Node,
- + IN gceSURF_TYPE Type
- + );
- +
- +gceSTATUS
- +gckEVENT_CommitDone(
- + IN gckEVENT Event,
- + IN gceKERNEL_WHERE FromWhere
- + );
- +
- +#if gcdVIRTUAL_COMMAND_BUFFER
- +/* Schedule a FreeVirtualCommandBuffer event. */
- +gceSTATUS
- +gckEVENT_DestroyVirtualCommandBuffer(
- + IN gckEVENT Event,
- + IN gctSIZE_T Bytes,
- + IN gctPHYS_ADDR Physical,
- + IN gctPOINTER Logical,
- + IN gceKERNEL_WHERE FromWhere
- + );
- +#endif
- +
- +gceSTATUS
- +gckEVENT_Submit(
- + IN gckEVENT Event,
- + IN gctBOOL Wait,
- + IN gctBOOL FromPower
- + );
- +
- +/* Commit an event queue. */
- +gceSTATUS
- +gckEVENT_Commit(
- + IN gckEVENT Event,
- + IN gcsQUEUE_PTR Queue
- + );
- +
- +/* Schedule a composition event. */
- +gceSTATUS
- +gckEVENT_Compose(
- + IN gckEVENT Event,
- + IN gcsHAL_COMPOSE_PTR Info
- + );
- +
- +/* Event callback routine. */
- +gceSTATUS
- +gckEVENT_Notify(
- + IN gckEVENT Event,
- + IN gctUINT32 IDs
- + );
- +
- +/* Event callback routine. */
- +gceSTATUS
- +gckEVENT_Interrupt(
- + IN gckEVENT Event,
- + IN gctUINT32 IDs
- + );
- +
- +gceSTATUS
- +gckEVENT_Dump(
- + IN gckEVENT Event
- + );
- +/******************************************************************************\
- +******************************* gckCOMMAND Object ******************************
- +\******************************************************************************/
- +
- +typedef struct _gckCOMMAND * gckCOMMAND;
- +
- +/* Construct a new gckCOMMAND object. */
- +gceSTATUS
- +gckCOMMAND_Construct(
- + IN gckKERNEL Kernel,
- + OUT gckCOMMAND * Command
- + );
- +
- +/* Destroy an gckCOMMAND object. */
- +gceSTATUS
- +gckCOMMAND_Destroy(
- + IN gckCOMMAND Command
- + );
- +
- +/* Acquire command queue synchronization objects. */
- +gceSTATUS
- +gckCOMMAND_EnterCommit(
- + IN gckCOMMAND Command,
- + IN gctBOOL FromPower
- + );
- +
- +/* Release command queue synchronization objects. */
- +gceSTATUS
- +gckCOMMAND_ExitCommit(
- + IN gckCOMMAND Command,
- + IN gctBOOL FromPower
- + );
- +
- +/* Start the command queue. */
- +gceSTATUS
- +gckCOMMAND_Start(
- + IN gckCOMMAND Command
- + );
- +
- +/* Stop the command queue. */
- +gceSTATUS
- +gckCOMMAND_Stop(
- + IN gckCOMMAND Command,
- + IN gctBOOL FromRecovery
- + );
- +
- +/* Commit a buffer to the command queue. */
- +gceSTATUS
- +gckCOMMAND_Commit(
- + IN gckCOMMAND Command,
- + IN gckCONTEXT Context,
- + IN gcoCMDBUF CommandBuffer,
- + IN gcsSTATE_DELTA_PTR StateDelta,
- + IN gcsQUEUE_PTR EventQueue,
- + IN gctUINT32 ProcessID
- + );
- +
- +/* Reserve space in the command buffer. */
- +gceSTATUS
- +gckCOMMAND_Reserve(
- + IN gckCOMMAND Command,
- + IN gctSIZE_T RequestedBytes,
- + OUT gctPOINTER * Buffer,
- + OUT gctSIZE_T * BufferSize
- + );
- +
- +/* Execute reserved space in the command buffer. */
- +gceSTATUS
- +gckCOMMAND_Execute(
- + IN gckCOMMAND Command,
- + IN gctSIZE_T RequstedBytes
- + );
- +
- +/* Stall the command queue. */
- +gceSTATUS
- +gckCOMMAND_Stall(
- + IN gckCOMMAND Command,
- + IN gctBOOL FromPower
- + );
- +
- +/* Attach user process. */
- +gceSTATUS
- +gckCOMMAND_Attach(
- + IN gckCOMMAND Command,
- + OUT gckCONTEXT * Context,
- + OUT gctSIZE_T * StateCount,
- + IN gctUINT32 ProcessID
- + );
- +
- +/* Detach user process. */
- +gceSTATUS
- +gckCOMMAND_Detach(
- + IN gckCOMMAND Command,
- + IN gckCONTEXT Context
- + );
- +
- +#if gcdVIRTUAL_COMMAND_BUFFER
- +gceSTATUS
- +gckCOMMAND_DumpExecutingBuffer(
- + IN gckCOMMAND Command
- + );
- +#endif
- +
- +/******************************************************************************\
- +********************************* gckMMU Object ********************************
- +\******************************************************************************/
- +
- +typedef struct _gckMMU * gckMMU;
- +
- +/* Construct a new gckMMU object. */
- +gceSTATUS
- +gckMMU_Construct(
- + IN gckKERNEL Kernel,
- + IN gctSIZE_T MmuSize,
- + OUT gckMMU * Mmu
- + );
- +
- +/* Destroy an gckMMU object. */
- +gceSTATUS
- +gckMMU_Destroy(
- + IN gckMMU Mmu
- + );
- +
- +/* Enable the MMU. */
- +gceSTATUS
- +gckMMU_Enable(
- + IN gckMMU Mmu,
- + IN gctUINT32 PhysBaseAddr,
- + IN gctUINT32 PhysSize
- + );
- +
- +/* Allocate pages inside the MMU. */
- +gceSTATUS
- +gckMMU_AllocatePages(
- + IN gckMMU Mmu,
- + IN gctSIZE_T PageCount,
- + OUT gctPOINTER * PageTable,
- + OUT gctUINT32 * Address
- + );
- +
- +gceSTATUS
- +gckMMU_AllocatePagesEx(
- + IN gckMMU Mmu,
- + IN gctSIZE_T PageCount,
- + IN gceSURF_TYPE Type,
- + OUT gctPOINTER * PageTable,
- + OUT gctUINT32 * Address
- + );
- +
- +/* Remove a page table from the MMU. */
- +gceSTATUS
- +gckMMU_FreePages(
- + IN gckMMU Mmu,
- + IN gctPOINTER PageTable,
- + IN gctSIZE_T PageCount
- + );
- +
- +/* Set the MMU page with info. */
- +gceSTATUS
- +gckMMU_SetPage(
- + IN gckMMU Mmu,
- + IN gctUINT32 PageAddress,
- + IN gctUINT32 *PageEntry
- + );
- +
- +#ifdef __QNXNTO__
- +gceSTATUS
- +gckMMU_InsertNode(
- + IN gckMMU Mmu,
- + IN gcuVIDMEM_NODE_PTR Node);
- +
- +gceSTATUS
- +gckMMU_RemoveNode(
- + IN gckMMU Mmu,
- + IN gcuVIDMEM_NODE_PTR Node);
- +#endif
- +
- +#ifdef __QNXNTO__
- +gceSTATUS
- +gckMMU_FreeHandleMemory(
- + IN gckKERNEL Kernel,
- + IN gckMMU Mmu,
- + IN gctUINT32 Pid
- + );
- +#endif
- +
- +gceSTATUS
- +gckMMU_Flush(
- + IN gckMMU Mmu
- + );
- +
- +gceSTATUS
- +gckMMU_DumpPageTableEntry(
- + IN gckMMU Mmu,
- + IN gctUINT32 Address
- + );
- +
- +
- +#if VIVANTE_PROFILER
- +gceSTATUS
- +gckHARDWARE_QueryProfileRegisters(
- + IN gckHARDWARE Hardware,
- + IN gctBOOL Clear,
- + OUT gcsPROFILER_COUNTERS * Counters
- + );
- +#endif
- +
- +#if VIVANTE_PROFILER_CONTEXT
- +gceSTATUS
- +gckHARDWARE_QueryContextProfile(
- + IN gckHARDWARE Hardware,
- + IN gctBOOL Clear,
- + IN gckCONTEXT Context,
- + OUT gcsPROFILER_COUNTERS * Counters
- + );
- +
- +gceSTATUS
- +gckHARDWARE_UpdateContextProfile(
- + IN gckHARDWARE Hardware,
- + IN gckCONTEXT Context
- + );
- +#endif
- +
- +gceSTATUS
- +gckOS_SignalQueryHardware(
- + IN gckOS Os,
- + IN gctSIGNAL Signal,
- + OUT gckHARDWARE * Hardware
- + );
- +
- +gceSTATUS
- +gckOS_SignalSetHardware(
- + IN gckOS Os,
- + IN gctSIGNAL Signal,
- + gckHARDWARE Hardware
- + );
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#if gcdENABLE_VG
- +#include "gc_hal_vg.h"
- +#endif
- +
- +#endif /* __gc_hal_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_kernel_buffer.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_kernel_buffer.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_kernel_buffer.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_kernel_buffer.h 2015-03-08 14:27:37.645684500 -0500
- @@ -0,0 +1,185 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_kernel_buffer_h_
- +#define __gc_hal_kernel_buffer_h_
- +
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +/******************************************************************************\
- +************************ Command Buffer and Event Objects **********************
- +\******************************************************************************/
- +
- +/* The number of context buffers per user. */
- +#define gcdCONTEXT_BUFFER_COUNT 2
- +
- +/* State delta record. */
- +typedef struct _gcsSTATE_DELTA_RECORD * gcsSTATE_DELTA_RECORD_PTR;
- +typedef struct _gcsSTATE_DELTA_RECORD
- +{
- + /* State address. */
- + gctUINT address;
- +
- + /* State mask. */
- + gctUINT32 mask;
- +
- + /* State data. */
- + gctUINT32 data;
- +}
- +gcsSTATE_DELTA_RECORD;
- +
- +/* State delta. */
- +typedef struct _gcsSTATE_DELTA
- +{
- + /* For debugging: the number of delta in the order of creation. */
- +#if gcmIS_DEBUG(gcdDEBUG_CODE)
- + gctUINT num;
- +#endif
- +
- + /* Main state delta ID. Every time state delta structure gets reinitialized,
- + main ID is incremented. If main state ID overflows, all map entry IDs get
- + reinitialized to make sure there is no potential erroneous match after
- + the overflow.*/
- + gctUINT id;
- +
- + /* The number of contexts pending modification by the delta. */
- + gctINT refCount;
- +
- + /* Vertex element count for the delta buffer. */
- + gctUINT elementCount;
- +
- + /* Number of states currently stored in the record array. */
- + gctUINT recordCount;
- +
- + /* Record array; holds all modified states in gcsSTATE_DELTA_RECORD. */
- + gctUINT64 recordArray;
- +
- + /* Map entry ID is used for map entry validation. If map entry ID does not
- + match the main state delta ID, the entry and the corresponding state are
- + considered not in use. */
- + gctUINT64 mapEntryID;
- + gctUINT mapEntryIDSize;
- +
- + /* If the map entry ID matches the main state delta ID, index points to
- + the state record in the record array. */
- + gctUINT64 mapEntryIndex;
- +
- + /* Previous and next state deltas in gcsSTATE_DELTA. */
- + gctUINT64 prev;
- + gctUINT64 next;
- +}
- +gcsSTATE_DELTA;
- +
- +/* Command buffer object. */
- +struct _gcoCMDBUF
- +{
- + /* The object. */
- + gcsOBJECT object;
- +
- + /* Command buffer entry and exit pipes. */
- + gcePIPE_SELECT entryPipe;
- + gcePIPE_SELECT exitPipe;
- +
- + /* Feature usage flags. */
- + gctBOOL using2D;
- + gctBOOL using3D;
- + gctBOOL usingFilterBlit;
- + gctBOOL usingPalette;
- +
- + /* Physical address of command buffer. Just a name. */
- + gctUINT32 physical;
- +
- + /* Logical address of command buffer. */
- + gctUINT64 logical;
- +
- + /* Number of bytes in command buffer. */
- + gctUINT bytes;
- +
- + /* Start offset into the command buffer. */
- + gctUINT startOffset;
- +
- + /* Current offset into the command buffer. */
- + gctUINT offset;
- +
- + /* Number of free bytes in command buffer. */
- + gctUINT free;
- +
- + /* Location of the last reserved area. */
- + gctUINT64 lastReserve;
- + gctUINT lastOffset;
- +
- +#if gcdSECURE_USER
- + /* Hint array for the current command buffer. */
- + gctUINT hintArraySize;
- + gctUINT64 hintArray;
- + gctUINT64 hintArrayTail;
- +#endif
- +
- +#if gcmIS_DEBUG(gcdDEBUG_CODE)
- + /* Last load state command location and hardware address. */
- + gctUINT64 lastLoadStatePtr;
- + gctUINT32 lastLoadStateAddress;
- + gctUINT32 lastLoadStateCount;
- +#endif
- +};
- +
- +typedef struct _gcsQUEUE
- +{
- + /* Pointer to next gcsQUEUE structure in gcsQUEUE. */
- + gctUINT64 next;
- +
- + /* Event information. */
- + gcsHAL_INTERFACE iface;
- +}
- +gcsQUEUE;
- +
- +/* Event queue. */
- +struct _gcoQUEUE
- +{
- + /* The object. */
- + gcsOBJECT object;
- +
- + /* Pointer to current event queue. */
- + gcsQUEUE_PTR head;
- + gcsQUEUE_PTR tail;
- +
- +#ifdef __QNXNTO__
- + /* Buffer for records. */
- + gcsQUEUE_PTR records;
- + gctUINT32 freeBytes;
- + gctUINT32 offset;
- +#else
- + /* List of free records. */
- + gcsQUEUE_PTR freeList;
- +#endif
- + #define gcdIN_QUEUE_RECORD_LIMIT 16
- + /* Number of records currently in queue */
- + gctUINT32 recordCount;
- +};
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* __gc_hal_kernel_buffer_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_mem.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_mem.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_mem.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_mem.h 2015-03-08 14:27:37.645684500 -0500
- @@ -0,0 +1,530 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +/*
- +** Include file for the local memory management.
- +*/
- +
- +#ifndef __gc_hal_mem_h_
- +#define __gc_hal_mem_h_
- +#ifndef VIVANTE_NO_3D
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +/*******************************************************************************
- +** Usage:
- +
- + The macros to declare MemPool type and functions are
- + gcmMEM_DeclareFSMemPool (Type, TypeName, Prefix)
- + gcmMEM_DeclareVSMemPool (Type, TypeName, Prefix)
- + gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix)
- +
- + The data structures for MemPool are
- + typedef struct _gcsMEM_FS_MEM_POOL * gcsMEM_FS_MEM_POOL;
- + typedef struct _gcsMEM_VS_MEM_POOL * gcsMEM_VS_MEM_POOL;
- + typedef struct _gcsMEM_AFS_MEM_POOL * gcsMEM_AFS_MEM_POOL;
- +
- + The MemPool constructor and destructor functions are
- + gcfMEM_InitFSMemPool(gcsMEM_FS_MEM_POOL *, gcoOS, gctUINT, gctUINT);
- + gcfMEM_FreeFSMemPool(gcsMEM_FS_MEM_POOL *);
- + gcfMEM_InitVSMemPool(gcsMEM_VS_MEM_POOL *, gcoOS, gctUINT, gctBOOL);
- + gcfMEM_FreeVSMemPool(gcsMEM_VS_MEM_POOL *);
- + gcfMEM_InitAFSMemPool(gcsMEM_AFS_MEM_POOL *, gcoOS, gctUINT);
- + gcfMEM_FreeAFSMemPool(gcsMEM_AFS_MEM_POOL *);
- +
- + FS: for Fixed-Size data structures
- + VS: for Variable-size data structures
- + AFS: for Array of Fixed-Size data structures
- +
- +
- + // Example 1: For a fixed-size data structure, struct gcsNode.
- + // It is used locally in a file, so the functions are static without prefix.
- + // At top level, declear allocate and free functions.
- + // The first argument is the data type.
- + // The second armument is the short name used in the fuctions.
- + gcmMEM_DeclareFSMemPool(struct gcsNode, Node, );
- +
- + // The previous macro creates two inline functions,
- + // _AllocateNode and _FreeNode.
- +
- + // In function or struct
- + gcsMEM_FS_MEM_POOL nodeMemPool;
- +
- + // In function,
- + struct gcsNode * node;
- + gceSTATUS status;
- +
- + // Before using the memory pool, initialize it.
- + // The second argument is the gcoOS object.
- + // The third argument is the number of data structures to allocate for each chunk.
- + status = gcfMEM_InitFSMemPool(&nodeMemPool, os, 100, sizeof(struct gcsNode));
- + ...
- +
- + // Allocate a node.
- + status = _AllocateNode(nodeMemPool, &node);
- + ...
- + // Free a node.
- + _FreeNode(nodeMemPool, node);
- +
- + // After using the memory pool, free it.
- + gcfMEM_FreeFSMemPool(&nodeMemPool);
- +
- +
- + // Example 2: For array of fixed-size data structures, struct gcsNode.
- + // It is used in several files, so the functions are extern with prefix.
- + // At top level, declear allocate and free functions.
- + // The first argument is the data type, and the second one is the short name
- + // used in the fuctions.
- + gcmMEM_DeclareAFSMemPool(struct gcsNode, NodeArray, gcfOpt);
- +
- + // The previous macro creates two inline functions,
- + // gcfOpt_AllocateNodeArray and gcfOpt_FreeNodeArray.
- +
- + // In function or struct
- + gcsMEM_AFS_MEM_POOL nodeArrayMemPool;
- +
- + // In function,
- + struct gcsNode * nodeArray;
- + gceSTATUS status;
- +
- + // Before using the array memory pool, initialize it.
- + // The second argument is the gcoOS object, the third is the number of data
- + // structures to allocate for each chunk.
- + status = gcfMEM_InitAFSMemPool(&nodeArrayMemPool, os, sizeof(struct gcsNode));
- + ...
- +
- + // Allocate a node array of size 100.
- + status = gcfOpt_AllocateNodeArray(nodeArrayMemPool, &nodeArray, 100);
- + ...
- + // Free a node array.
- + gcfOpt_FreeNodeArray(&nodeArrayMemPool, nodeArray);
- +
- + // After using the array memory pool, free it.
- + gcfMEM_FreeAFSMemPool(&nodeArrayMemPool);
- +
- +*******************************************************************************/
- +
- +/*******************************************************************************
- +** To switch back to use gcoOS_Allocate and gcoOS_Free, add
- +** #define USE_LOCAL_MEMORY_POOL 0
- +** before including this file.
- +*******************************************************************************/
- +#ifndef USE_LOCAL_MEMORY_POOL
- +/*
- + USE_LOCAL_MEMORY_POOL
- +
- + This define enables the local memory management to improve performance.
- +*/
- +#define USE_LOCAL_MEMORY_POOL 1
- +#endif
- +
- +/*******************************************************************************
- +** Memory Pool Data Structures
- +*******************************************************************************/
- +#if USE_LOCAL_MEMORY_POOL
- + typedef struct _gcsMEM_FS_MEM_POOL * gcsMEM_FS_MEM_POOL;
- + typedef struct _gcsMEM_VS_MEM_POOL * gcsMEM_VS_MEM_POOL;
- + typedef struct _gcsMEM_AFS_MEM_POOL * gcsMEM_AFS_MEM_POOL;
- +#else
- + typedef gcoOS gcsMEM_FS_MEM_POOL;
- + typedef gcoOS gcsMEM_VS_MEM_POOL;
- + typedef gcoOS gcsMEM_AFS_MEM_POOL;
- +#endif
- +
- +/*******************************************************************************
- +** Memory Pool Macros
- +*******************************************************************************/
- +#if USE_LOCAL_MEMORY_POOL
- +#define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
- +gceSTATUS \
- +Prefix##_Allocate##TypeName( \
- + gcsMEM_FS_MEM_POOL MemPool, \
- + Type ** Pointer \
- + ) \
- +{ \
- + return(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
- +} \
- + \
- +gceSTATUS \
- +Prefix##_CAllocate##TypeName( \
- + gcsMEM_FS_MEM_POOL MemPool, \
- + Type ** Pointer \
- + ) \
- +{ \
- + gceSTATUS status; \
- + gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
- + gcmERR_RETURN(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
- + gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type)); \
- + gcmFOOTER(); \
- + return gcvSTATUS_OK; \
- +} \
- + \
- +gceSTATUS \
- +Prefix##_Free##TypeName( \
- + gcsMEM_FS_MEM_POOL MemPool, \
- + Type * Pointer \
- + ) \
- +{ \
- + gceSTATUS status; \
- + gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
- + status = gcfMEM_FSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
- + gcmFOOTER(); \
- + return status; \
- +} \
- + \
- +gceSTATUS \
- +Prefix##_Free##TypeName##List( \
- + gcsMEM_FS_MEM_POOL MemPool, \
- + Type * FirstPointer, \
- + Type * LastPointer \
- + ) \
- +{ \
- + gceSTATUS status; \
- + gcmHEADER_ARG("MemPool=0x%x FirstPointer=0x%x LastPointer=0x%x", MemPool, FirstPointer, LastPointer); \
- + status = gcfMEM_FSMemPoolFreeAList(MemPool, (gctPOINTER) FirstPointer, (gctPOINTER) LastPointer); \
- + gcmFOOTER(); \
- + return status; \
- +}
- +
- +#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
- +gceSTATUS \
- +Prefix##_Allocate##TypeName( \
- + gcsMEM_FS_MEM_POOL MemPool, \
- + Type ** Pointer, \
- + gctUINT Size \
- + ) \
- +{ \
- + gceSTATUS status;\
- + gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
- + status = gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer); \
- + gcmFOOTER(); \
- + return status; \
- +} \
- + \
- +gceSTATUS \
- + Prefix##_CAllocate##TypeName( \
- + gcsMEM_FS_MEM_POOL MemPool, \
- + Type ** Pointer, \
- + gctUINT Size \
- + ) \
- +{ \
- + gceSTATUS status; \
- + gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
- + gcmERR_RETURN(gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer)); \
- + gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, size); \
- + gcmFOOTER(); \
- + return gcvSTATUS_OK; \
- +} \
- + \
- +gceSTATUS \
- +Prefix##_Free##TypeName( \
- + gcsMEM_FS_MEM_POOL MemPool, \
- + Type * Pointer \
- + ) \
- +{ \
- + gceSTATUS status; \
- + gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pinter); \
- + status = gcfMEM_VSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
- + gcmFOOTER(); \
- + return status; \
- +}
- +
- +#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
- +gceSTATUS \
- +Prefix##_Allocate##TypeName( \
- + gcsMEM_AFS_MEM_POOL MemPool, \
- + Type ** Pointer, \
- + gctUINT Count \
- + ) \
- +{ \
- + gceSTATUS status; \
- + gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
- + status = gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer); \
- + gcmFOOTER(); \
- + return status; \
- +} \
- + \
- +gceSTATUS \
- +Prefix##_CAllocate##TypeName( \
- + gcsMEM_AFS_MEM_POOL MemPool, \
- + Type ** Pointer, \
- + gctUINT Count \
- + ) \
- +{ \
- + gceSTATUS status; \
- + gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
- + gcmERR_RETURN(gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer)); \
- + gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type)); \
- + gcmFOOTER(); \
- + return gcvSTATUS_OK; \
- +} \
- + \
- +gceSTATUS \
- +Prefix##_Free##TypeName( \
- + gcsMEM_AFS_MEM_POOL MemPool, \
- + Type * Pointer \
- + ) \
- +{ \
- + gceSTATUS status; \
- + gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
- + status = gcfMEM_AFSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
- + gcmFOOTER(); \
- + return status; \
- +}
- +
- +#else
- +
- +#define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
- +gceSTATUS \
- +Prefix##_Allocate##TypeName( \
- + gcsMEM_FS_MEM_POOL MemPool, \
- + Type ** Pointer \
- + ) \
- +{ \
- + gceSTATUS status; \
- + gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
- + status = gcoOS_Allocate(MemPool, \
- + gcmSIZEOF(Type), \
- + (gctPOINTER *) Pointer); \
- + gcmFOOTER(); \
- + return status; \
- +} \
- + \
- +gceSTATUS \
- +Prefix##_CAllocate##TypeName( \
- + gcsMEM_FS_MEM_POOL MemPool, \
- + Type ** Pointer \
- + ) \
- +{ \
- + gceSTATUS status; \
- + gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
- + gcmERR_RETURN(gcoOS_Allocate(MemPool, \
- + gcmSIZEOF(Type), \
- + (gctPOINTER *) Pointer)); \
- + gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type)); \
- + gcmFOOTER(); \
- + return gcvSTATUS_OK; \
- +} \
- + \
- +gceSTATUS \
- +Prefix##_Free##TypeName( \
- + gcsMEM_FS_MEM_POOL MemPool, \
- + Type * Pointer \
- + ) \
- +{ \
- + gceSTATUS status; \
- + gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
- + status = gcmOS_SAFE_FREE(MemPool, Pointer); \
- + gcmFOOTER(); \
- + return status; \
- +}
- +
- +#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
- +gceSTATUS \
- +Prefix##_Allocate##TypeName( \
- + gcsMEM_VS_MEM_POOL MemPool, \
- + Type ** Pointer, \
- + gctUINT Size \
- + ) \
- +{ \
- + gceSTATUS status; \
- + gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
- + status = gcoOS_Allocate(MemPool, \
- + Size, \
- + (gctPOINTER *) Pointer); \
- + gcmFOOTER(); \
- + return status; \
- +} \
- + \
- +gceSTATUS \
- +Prefix##_CAllocate##TypeName( \
- + gcsMEM_VS_MEM_POOL MemPool, \
- + Type ** Pointer, \
- + gctUINT Size \
- + ) \
- +{ \
- + gceSTATUS status; \
- + gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
- + gcmERR_RETURN(gcoOS_Allocate(MemPool, \
- + Size, \
- + (gctPOINTER *) Pointer)); \
- + gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Size); \
- + gcmFOOTER(); \
- + return gcvSTATUS_OK; \
- +} \
- + \
- +gceSTATUS \
- +Prefix##_Free##TypeName( \
- + gcsMEM_VS_MEM_POOL MemPool, \
- + Type * Pointer \
- + ) \
- +{ \
- + gceSTATUS status; \
- + gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
- + status = gcmOS_SAFE_FREE(MemPool, Pointer); \
- + gcmFOOTER(); \
- + return status; \
- +}
- +
- +#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
- +gceSTATUS \
- +Prefix##_Allocate##TypeName( \
- + gcsMEM_AFS_MEM_POOL MemPool, \
- + Type ** Pointer, \
- + gctUINT Count \
- + ) \
- +{ \
- + gceSTATUS status; \
- + gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
- + status = gcoOS_Allocate(MemPool, \
- + Count * gcmSIZEOF(Type), \
- + (gctPOINTER *) Pointer); \
- + gcmFOOTER(); \
- + return status; \
- +} \
- + \
- +gceSTATUS \
- +Prefix##_CAllocate##TypeName( \
- + gcsMEM_AFS_MEM_POOL MemPool, \
- + Type ** Pointer, \
- + gctUINT Count \
- + ) \
- +{ \
- + gceSTATUS status; \
- + gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
- + gcmERR_RETURN(gcoOS_Allocate(MemPool, \
- + Count * gcmSIZEOF(Type), \
- + (gctPOINTER *) Pointer)); \
- + gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type)); \
- + gcmFOOTER(); \
- + return gcvSTATUS_OK; \
- +} \
- + \
- +gceSTATUS \
- +Prefix##_Free##TypeName( \
- + gcsMEM_AFS_MEM_POOL MemPool, \
- + Type * Pointer \
- + ) \
- +{ \
- + gceSTATUS status; \
- + gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
- + status = gcmOS_SAFE_FREE(MemPool, Pointer); \
- + gcmFOOTER(); \
- + return status; \
- +}
- +#endif
- +
- +/*******************************************************************************
- +** Memory Pool Data Functions
- +*******************************************************************************/
- +gceSTATUS
- +gcfMEM_InitFSMemPool(
- + IN gcsMEM_FS_MEM_POOL * MemPool,
- + IN gcoOS OS,
- + IN gctUINT NodeCount,
- + IN gctUINT NodeSize
- + );
- +
- +gceSTATUS
- +gcfMEM_FreeFSMemPool(
- + IN gcsMEM_FS_MEM_POOL * MemPool
- + );
- +
- +gceSTATUS
- +gcfMEM_FSMemPoolGetANode(
- + IN gcsMEM_FS_MEM_POOL MemPool,
- + OUT gctPOINTER * Node
- + );
- +
- +gceSTATUS
- +gcfMEM_FSMemPoolFreeANode(
- + IN gcsMEM_FS_MEM_POOL MemPool,
- + IN gctPOINTER Node
- + );
- +
- +gceSTATUS
- +gcfMEM_FSMemPoolFreeAList(
- + IN gcsMEM_FS_MEM_POOL MemPool,
- + IN gctPOINTER FirstNode,
- + IN gctPOINTER LastNode
- + );
- +
- +gceSTATUS
- +gcfMEM_InitVSMemPool(
- + IN gcsMEM_VS_MEM_POOL * MemPool,
- + IN gcoOS OS,
- + IN gctUINT BlockSize,
- + IN gctBOOL RecycleFreeNode
- + );
- +
- +gceSTATUS
- +gcfMEM_FreeVSMemPool(
- + IN gcsMEM_VS_MEM_POOL * MemPool
- + );
- +
- +gceSTATUS
- +gcfMEM_VSMemPoolGetANode(
- + IN gcsMEM_VS_MEM_POOL MemPool,
- + IN gctUINT Size,
- + IN gctUINT Alignment,
- + OUT gctPOINTER * Node
- + );
- +
- +gceSTATUS
- +gcfMEM_VSMemPoolFreeANode(
- + IN gcsMEM_VS_MEM_POOL MemPool,
- + IN gctPOINTER Node
- + );
- +
- +gceSTATUS
- +gcfMEM_InitAFSMemPool(
- + IN gcsMEM_AFS_MEM_POOL *MemPool,
- + IN gcoOS OS,
- + IN gctUINT NodeCount,
- + IN gctUINT NodeSize
- + );
- +
- +gceSTATUS
- +gcfMEM_FreeAFSMemPool(
- + IN gcsMEM_AFS_MEM_POOL *MemPool
- + );
- +
- +gceSTATUS
- +gcfMEM_AFSMemPoolGetANode(
- + IN gcsMEM_AFS_MEM_POOL MemPool,
- + IN gctUINT Count,
- + OUT gctPOINTER * Node
- + );
- +
- +gceSTATUS
- +gcfMEM_AFSMemPoolFreeANode(
- + IN gcsMEM_AFS_MEM_POOL MemPool,
- + IN gctPOINTER Node
- + );
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* VIVANTE_NO_3D */
- +#endif /* __gc_hal_mem_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h 2015-03-08 14:27:37.649684500 -0500
- @@ -0,0 +1,947 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_options_h_
- +#define __gc_hal_options_h_
- +
- +/*
- + gcdPRINT_VERSION
- +
- + Print HAL version.
- +*/
- +#ifndef gcdPRINT_VERSION
- +# define gcdPRINT_VERSION 0
- +#endif
- +
- +/*
- + USE_NEW_LINUX_SIGNAL
- +
- + This define enables the Linux kernel signaling between kernel and user.
- +*/
- +#ifndef USE_NEW_LINUX_SIGNAL
- +# define USE_NEW_LINUX_SIGNAL 0
- +#endif
- +
- +/*
- + VIVANTE_PROFILER
- +
- + This define enables the profiler.
- +*/
- +#ifndef VIVANTE_PROFILER
- +# define VIVANTE_PROFILER 1
- +#endif
- +
- +#ifndef VIVANTE_PROFILER_PERDRAW
- +# define VIVANTE_PROFILER_PERDRAW 0
- +#endif
- +
- +/*
- + VIVANTE_PROFILER_CONTEXT
- +
- + This define enables the profiler according to each hw context.
- +*/
- +#ifndef VIVANTE_PROFILER_CONTEXT
- +# define VIVANTE_PROFILER_CONTEXT 1
- +#endif
- +
- +/*
- + gcdUSE_VG
- +
- + Enable VG HAL layer (only for GC350).
- +*/
- +#ifndef gcdUSE_VG
- +# define gcdUSE_VG 0
- +#endif
- +
- +/*
- + USE_SW_FB
- +
- + Set to 1 if the frame buffer memory cannot be accessed by the GPU.
- +*/
- +#ifndef USE_SW_FB
- +# define USE_SW_FB 0
- +#endif
- +
- +/*
- + USE_SUPER_SAMPLING
- +
- + This define enables super-sampling support.
- +*/
- +#define USE_SUPER_SAMPLING 0
- +
- +/*
- + PROFILE_HAL_COUNTERS
- +
- + This define enables HAL counter profiling support. HW and SHADER
- + counter profiling depends on this.
- +*/
- +#ifndef PROFILE_HAL_COUNTERS
- +# define PROFILE_HAL_COUNTERS 1
- +#endif
- +
- +/*
- + PROFILE_HW_COUNTERS
- +
- + This define enables HW counter profiling support.
- +*/
- +#ifndef PROFILE_HW_COUNTERS
- +# define PROFILE_HW_COUNTERS 1
- +#endif
- +
- +/*
- + PROFILE_SHADER_COUNTERS
- +
- + This define enables SHADER counter profiling support.
- +*/
- +#ifndef PROFILE_SHADER_COUNTERS
- +# define PROFILE_SHADER_COUNTERS 1
- +#endif
- +
- +/*
- + COMMAND_PROCESSOR_VERSION
- +
- + The version of the command buffer and task manager.
- +*/
- +#define COMMAND_PROCESSOR_VERSION 1
- +
- +/*
- + gcdDUMP_KEY
- +
- + Set this to a string that appears in 'cat /proc/<pid>/cmdline'. E.g. 'camera'.
- + HAL will create dumps for the processes matching this key.
- +*/
- +#ifndef gcdDUMP_KEY
- +# define gcdDUMP_KEY "process"
- +#endif
- +
- +/*
- + gcdDUMP_PATH
- +
- + The dump file location. Some processes cannot write to the sdcard.
- + Try apps' data dir, e.g. /data/data/com.android.launcher
- +*/
- +#ifndef gcdDUMP_PATH
- +#if defined(ANDROID)
- +# define gcdDUMP_PATH "/mnt/sdcard/"
- +#else
- +# define gcdDUMP_PATH "./"
- +#endif
- +#endif
- +
- +/*
- + gcdDUMP
- +
- + When set to 1, a dump of all states and memory uploads, as well as other
- + hardware related execution will be printed to the debug console. This
- + data can be used for playing back applications.
- +*/
- +#ifndef gcdDUMP
- +# define gcdDUMP 0
- +#endif
- +
- +/*
- + gcdDUMP_API
- +
- + When set to 1, a high level dump of the EGL and GL/VG APs's are
- + captured.
- +*/
- +#ifndef gcdDUMP_API
- +# define gcdDUMP_API 0
- +#endif
- +
- +/*
- + gcdDUMP_FRAMERATE
- + When set to a value other than zero, averaqe frame rate will be dumped.
- + The value set is the starting frame that the average will be calculated.
- + This is needed because sometimes first few frames are too slow to be included
- + in the average. Frame count starts from 1.
- +*/
- +#ifndef gcdDUMP_FRAMERATE
- +# define gcdDUMP_FRAMERATE 0
- +#endif
- +
- +/*
- + gcdVIRTUAL_COMMAND_BUFFER
- + When set to 1, user command buffer and context buffer will be allocated
- + from gcvPOOL_VIRTUAL.
- +*/
- +#ifndef gcdVIRTUAL_COMMAND_BUFFER
- +# define gcdVIRTUAL_COMMAND_BUFFER 0
- +#endif
- +
- +/*
- + gcdENABLE_FSCALE_VAL_ADJUST
- + When non-zero, FSCALE_VAL when gcvPOWER_ON can be adjusted externally.
- + */
- +#ifndef gcdENABLE_FSCALE_VAL_ADJUST
- +# define gcdENABLE_FSCALE_VAL_ADJUST 1
- +#endif
- +
- +/*
- + gcdDUMP_IN_KERNEL
- +
- + When set to 1, all dumps will happen in the kernel. This is handy if
- + you want the kernel to dump its command buffers as well and the data
- + needs to be in sync.
- +*/
- +#ifndef gcdDUMP_IN_KERNEL
- +# define gcdDUMP_IN_KERNEL 0
- +#endif
- +
- +/*
- + gcdDUMP_COMMAND
- +
- + When set to non-zero, the command queue will dump all incoming command
- + and context buffers as well as all other modifications to the command
- + queue.
- +*/
- +#ifndef gcdDUMP_COMMAND
- +# define gcdDUMP_COMMAND 0
- +#endif
- +
- +/*
- + gcdDUMP_FRAME_TGA
- +
- + When set to a value other than 0, a dump of the frame specified by the value,
- + will be done into frame.tga. Frame count starts from 1.
- + */
- +#ifndef gcdDUMP_FRAME_TGA
- +#define gcdDUMP_FRAME_TGA 0
- +#endif
- +/*
- + gcdNULL_DRIVER
- +
- + Set to 1 for infinite speed hardware.
- + Set to 2 for bypassing the HAL.
- + Set to 3 for bypassing the drivers.
- +*/
- +#ifndef gcdNULL_DRIVER
- +# define gcdNULL_DRIVER 0
- +#endif
- +
- +/*
- + gcdENABLE_TIMEOUT_DETECTION
- +
- + Enable timeout detection.
- +*/
- +#ifndef gcdENABLE_TIMEOUT_DETECTION
- +# define gcdENABLE_TIMEOUT_DETECTION 0
- +#endif
- +
- +/*
- + gcdCMD_BUFFER_SIZE
- +
- + Number of bytes in a command buffer.
- +*/
- +#ifndef gcdCMD_BUFFER_SIZE
- +# define gcdCMD_BUFFER_SIZE (128 << 10)
- +#endif
- +
- +/*
- + gcdCMD_BUFFERS
- +
- + Number of command buffers to use per client.
- +*/
- +#ifndef gcdCMD_BUFFERS
- +# define gcdCMD_BUFFERS 2
- +#endif
- +
- +/*
- + gcdMAX_CMD_BUFFERS
- +
- + Maximum number of command buffers to use per client.
- +*/
- +#ifndef gcdMAX_CMD_BUFFERS
- +# define gcdMAX_CMD_BUFFERS 8
- +#endif
- +
- +/*
- + gcdCOMMAND_QUEUES
- +
- + Number of command queues in the kernel.
- +*/
- +#ifndef gcdCOMMAND_QUEUES
- +# define gcdCOMMAND_QUEUES 2
- +#endif
- +
- +/*
- + gcdPOWER_CONTROL_DELAY
- +
- + The delay in milliseconds required to wait until the GPU has woke up
- + from a suspend or power-down state. This is system dependent because
- + the bus clock also needs to stabalize.
- +*/
- +#ifndef gcdPOWER_CONTROL_DELAY
- +# define gcdPOWER_CONTROL_DELAY 0
- +#endif
- +
- +/*
- + gcdMIRROR_PAGETABLE
- +
- + Enable it when GPUs with old MMU and new MMU exist at same SoC. It makes
- + each GPU use same virtual address to access same physical memory.
- +*/
- +#ifndef gcdMIRROR_PAGETABLE
- +# define gcdMIRROR_PAGETABLE 0
- +#endif
- +
- +/*
- + gcdMMU_SIZE
- +
- + Size of the MMU page table in bytes. Each 4 bytes can hold 4kB worth of
- + virtual data.
- +*/
- +#ifndef gcdMMU_SIZE
- +#if gcdMIRROR_PAGETABLE
- +# define gcdMMU_SIZE 0x200000
- +#else
- +# define gcdMMU_SIZE (2048 << 10)
- +#endif
- +#endif
- +
- +/*
- + gcdSECURE_USER
- +
- + Use logical addresses instead of physical addresses in user land. In
- + this case a hint table is created for both command buffers and context
- + buffers, and that hint table will be used to patch up those buffers in
- + the kernel when they are ready to submit.
- +*/
- +#ifndef gcdSECURE_USER
- +# define gcdSECURE_USER 0
- +#endif
- +
- +/*
- + gcdSECURE_CACHE_SLOTS
- +
- + Number of slots in the logical to DMA address cache table. Each time a
- + logical address needs to be translated into a DMA address for the GPU,
- + this cache will be walked. The replacement scheme is LRU.
- +*/
- +#ifndef gcdSECURE_CACHE_SLOTS
- +# define gcdSECURE_CACHE_SLOTS 1024
- +#endif
- +
- +/*
- + gcdSECURE_CACHE_METHOD
- +
- + Replacement scheme used for Secure Cache. The following options are
- + available:
- +
- + gcdSECURE_CACHE_LRU
- + A standard LRU cache.
- +
- + gcdSECURE_CACHE_LINEAR
- + A linear walker with the idea that an application will always
- + render the scene in a similar way, so the next entry in the
- + cache should be a hit most of the time.
- +
- + gcdSECURE_CACHE_HASH
- + A 256-entry hash table.
- +
- + gcdSECURE_CACHE_TABLE
- + A simple cache but with potential of a lot of cache replacement.
- +*/
- +#ifndef gcdSECURE_CACHE_METHOD
- +# define gcdSECURE_CACHE_METHOD gcdSECURE_CACHE_HASH
- +#endif
- +
- +/*
- + gcdREGISTER_ACCESS_FROM_USER
- +
- + Set to 1 to allow IOCTL calls to get through from user land. This
- + should only be in debug or development drops.
- +*/
- +#ifndef gcdREGISTER_ACCESS_FROM_USER
- +# define gcdREGISTER_ACCESS_FROM_USER 1
- +#endif
- +
- +/*
- + gcdUSER_HEAP_ALLOCATOR
- +
- + Set to 1 to enable user mode heap allocator for fast memory allocation
- + and destroying. Otherwise, memory allocation/destroying in user mode
- + will be directly managed by system. Only for linux for now.
- +*/
- +#ifndef gcdUSER_HEAP_ALLOCATOR
- +# define gcdUSER_HEAP_ALLOCATOR 1
- +#endif
- +
- +/*
- + gcdHEAP_SIZE
- +
- + Set the allocation size for the internal heaps. Each time a heap is
- + full, a new heap will be allocated with this minmimum amount of bytes.
- + The bigger this size, the fewer heaps there are to allocate, the better
- + the performance. However, heaps won't be freed until they are
- + completely free, so there might be some more memory waste if the size is
- + too big.
- +*/
- +#ifndef gcdHEAP_SIZE
- +# define gcdHEAP_SIZE (64 << 10)
- +#endif
- +
- +/*
- + gcdPOWER_SUSNPEND_WHEN_IDLE
- +
- + Set to 1 to make GPU enter gcvPOWER_SUSPEND when idle detected,
- + otherwise GPU will enter gcvPOWER_IDLE.
- +*/
- +#ifndef gcdPOWER_SUSNPEND_WHEN_IDLE
- +# define gcdPOWER_SUSNPEND_WHEN_IDLE 1
- +#endif
- +
- +/*
- + gcdFPGA_BUILD
- +
- + This define enables work arounds for FPGA images.
- +*/
- +#ifndef gcdFPGA_BUILD
- +# define gcdFPGA_BUILD 0
- +#endif
- +
- +/*
- + gcdGPU_TIMEOUT
- +
- + This define specified the number of milliseconds the system will wait
- + before it broadcasts the GPU is stuck. In other words, it will define
- + the timeout of any operation that needs to wait for the GPU.
- +
- + If the value is 0, no timeout will be checked for.
- +*/
- +#ifndef gcdGPU_TIMEOUT
- +#if gcdFPGA_BUILD
- +# define gcdGPU_TIMEOUT 0
- +# else
- +# define gcdGPU_TIMEOUT 20000
- +# endif
- +#endif
- +
- +/*
- + gcdGPU_ADVANCETIMER
- +
- + it is advance timer.
- +*/
- +#ifndef gcdGPU_ADVANCETIMER
- +# define gcdGPU_ADVANCETIMER 250
- +#endif
- +
- +/*
- + gcdSTATIC_LINK
- +
- + This define disalbes static linking;
- +*/
- +#ifndef gcdSTATIC_LINK
- +# define gcdSTATIC_LINK 0
- +#endif
- +
- +/*
- + gcdUSE_NEW_HEAP
- +
- + Setting this define to 1 enables new heap.
- +*/
- +#ifndef gcdUSE_NEW_HEAP
- +# define gcdUSE_NEW_HEAP 0
- +#endif
- +
- +/*
- + gcdCMD_NO_2D_CONTEXT
- +
- + This define enables no-context 2D command buffer.
- +*/
- +#ifndef gcdCMD_NO_2D_CONTEXT
- +# define gcdCMD_NO_2D_CONTEXT 1
- +#endif
- +
- +/*
- + gcdENABLE_BANK_ALIGNMENT
- +
- + When enabled, video memory is allocated bank aligned. The vendor can modify
- + _GetSurfaceBankAlignment() and gcoSURF_GetBankOffsetBytes() to define how
- + different types of allocations are bank and channel aligned.
- + When disabled (default), no bank alignment is done.
- +*/
- +#ifndef gcdENABLE_BANK_ALIGNMENT
- +# define gcdENABLE_BANK_ALIGNMENT 0
- +#endif
- +
- +/*
- + gcdBANK_BIT_START
- +
- + Specifies the start bit of the bank (inclusive).
- +*/
- +#ifndef gcdBANK_BIT_START
- +# define gcdBANK_BIT_START 12
- +#endif
- +
- +/*
- + gcdBANK_BIT_END
- +
- + Specifies the end bit of the bank (inclusive).
- +*/
- +#ifndef gcdBANK_BIT_END
- +# define gcdBANK_BIT_END 14
- +#endif
- +
- +/*
- + gcdBANK_CHANNEL_BIT
- +
- + When set, video memory when allocated bank aligned is allocated such that
- + render and depth buffer addresses alternate on the channel bit specified.
- + This option has an effect only when gcdENABLE_BANK_ALIGNMENT is enabled.
- + When disabled (default), no alteration is done.
- +*/
- +#ifndef gcdBANK_CHANNEL_BIT
- +# define gcdBANK_CHANNEL_BIT 7
- +#endif
- +
- +/*
- + gcdDYNAMIC_SPEED
- +
- + When non-zero, it informs the kernel driver to use the speed throttling
- + broadcasting functions to inform the system the GPU should be spet up or
- + slowed down. It will send a broadcast for slowdown each "interval"
- + specified by this define in milliseconds
- + (gckOS_BroadcastCalibrateSpeed).
- +*/
- +#ifndef gcdDYNAMIC_SPEED
- +# define gcdDYNAMIC_SPEED 2000
- +#endif
- +
- +/*
- + gcdDYNAMIC_EVENT_THRESHOLD
- +
- + When non-zero, it specifies the maximum number of available events at
- + which the kernel driver will issue a broadcast to speed up the GPU
- + (gckOS_BroadcastHurry).
- +*/
- +#ifndef gcdDYNAMIC_EVENT_THRESHOLD
- +# define gcdDYNAMIC_EVENT_THRESHOLD 5
- +#endif
- +
- +/*
- + gcdENABLE_PROFILING
- +
- + Enable profiling macros.
- +*/
- +#ifndef gcdENABLE_PROFILING
- +# define gcdENABLE_PROFILING 0
- +#endif
- +
- +/*
- + gcdENABLE_128B_MERGE
- +
- + Enable 128B merge for the BUS control.
- +*/
- +#ifndef gcdENABLE_128B_MERGE
- +# define gcdENABLE_128B_MERGE 0
- +#endif
- +
- +/*
- + gcdFRAME_DB
- +
- + When non-zero, it specified the number of frames inside the frame
- + database. The frame DB will collect per-frame timestamps and hardware
- + counters.
- +*/
- +#ifndef gcdFRAME_DB
- +# define gcdFRAME_DB 0
- +# define gcdFRAME_DB_RESET 0
- +# define gcdFRAME_DB_NAME "/var/log/frameDB.log"
- +#endif
- +
- +/*
- + gcdENABLE_VG
- + enable the 2D openVG
- +*/
- +
- +#ifndef gcdENABLE_VG
- +# define gcdENABLE_VG 0
- +#endif
- +
- +/*
- + gcdDYNAMIC_MAP_RESERVED_MEMORY
- +
- + When gcvPOOL_SYSTEM is constructed from RESERVED memory,
- + driver can map the whole reserved memory to kernel space
- + at the beginning, or just map a piece of memory when need
- + to access.
- +
- + Notice:
- + - It's only for the 2D openVG. For other cores, there is
- + _NO_ need to map reserved memory to kernel.
- + - It's meaningless when memory is allocated by
- + gckOS_AllocateContiguous, in that case, memory is always
- + mapped by system when allocated.
- +*/
- +#ifndef gcdDYNAMIC_MAP_RESERVED_MEMORY
- +# define gcdDYNAMIC_MAP_RESERVED_MEMORY 1
- +#endif
- +
- +/*
- + gcdPAGED_MEMORY_CACHEABLE
- +
- + When non-zero, paged memory will be cacheable.
- +
- + Normally, driver will detemines whether a video memory
- + is cacheable or not. When cacheable is not neccessary,
- + it will be writecombine.
- +
- + This option is only for those SOC which can't enable
- + writecombine without enabling cacheable.
- +*/
- +
- +#ifndef gcdPAGED_MEMORY_CACHEABLE
- +# define gcdPAGED_MEMORY_CACHEABLE 0
- +#endif
- +
- +/*
- + gcdNONPAGED_MEMORY_CACHEABLE
- +
- + When non-zero, non paged memory will be cacheable.
- +*/
- +
- +#ifndef gcdNONPAGED_MEMORY_CACHEABLE
- +# define gcdNONPAGED_MEMORY_CACHEABLE 0
- +#endif
- +
- +/*
- + gcdNONPAGED_MEMORY_BUFFERABLE
- +
- + When non-zero, non paged memory will be bufferable.
- + gcdNONPAGED_MEMORY_BUFFERABLE and gcdNONPAGED_MEMORY_CACHEABLE
- + can't be set 1 at same time
- +*/
- +
- +#ifndef gcdNONPAGED_MEMORY_BUFFERABLE
- +# define gcdNONPAGED_MEMORY_BUFFERABLE 1
- +#endif
- +
- +/*
- + gcdENABLE_INFINITE_SPEED_HW
- + enable the Infinte HW , this is for 2D openVG
- +*/
- +
- +#ifndef gcdENABLE_INFINITE_SPEED_HW
- +# define gcdENABLE_INFINITE_SPEED_HW 0
- +#endif
- +
- +/*
- + gcdENABLE_TS_DOUBLE_BUFFER
- + enable the TS double buffer, this is for 2D openVG
- +*/
- +
- +#ifndef gcdENABLE_TS_DOUBLE_BUFFER
- +# define gcdENABLE_TS_DOUBLE_BUFFER 1
- +#endif
- +
- +/*
- + gcd6000_SUPPORT
- +
- + Temporary define to enable/disable 6000 support.
- + */
- +#ifndef gcd6000_SUPPORT
- +# define gcd6000_SUPPORT 0
- +#endif
- +
- +/*
- + gcdPOWEROFF_TIMEOUT
- +
- + When non-zero, GPU will power off automatically from
- + idle state, and gcdPOWEROFF_TIMEOUT is also the default
- + timeout in milliseconds.
- + */
- +
- +#ifndef gcdPOWEROFF_TIMEOUT
- +# define gcdPOWEROFF_TIMEOUT 300
- +#endif
- +
- +/*
- + gcdUSE_VIDMEM_PER_PID
- +*/
- +#ifndef gcdUSE_VIDMEM_PER_PID
- +# define gcdUSE_VIDMEM_PER_PID 0
- +#endif
- +
- +/*
- + QNX_SINGLE_THREADED_DEBUGGING
- +*/
- +#ifndef QNX_SINGLE_THREADED_DEBUGGING
- +# define QNX_SINGLE_THREADED_DEBUGGING 0
- +#endif
- +
- +/*
- + gcdENABLE_RECOVERY
- +
- + This define enables the recovery code.
- +*/
- +#ifndef gcdENABLE_RECOVERY
- +# define gcdENABLE_RECOVERY 1
- +#endif
- +
- +/*
- + gcdRENDER_THREADS
- +
- + Number of render threads. Make it zero, and there will be no render
- + threads.
- +*/
- +#ifndef gcdRENDER_THREADS
- +# define gcdRENDER_THREADS 0
- +#endif
- +
- +/*
- + gcdSMP
- +
- + This define enables SMP support.
- +
- + Currently, it only works on Linux/Android,
- + Kbuild will config it according to whether
- + CONFIG_SMP is set.
- +
- +*/
- +#ifndef gcdSMP
- +# define gcdSMP 0
- +#endif
- +
- +/*
- + gcdSUPPORT_SWAP_RECTANGLE
- +
- + Support swap with a specific rectangle.
- +
- + Set the rectangle with eglSetSwapRectangleANDROID api.
- +*/
- +#ifndef gcdSUPPORT_SWAP_RECTANGLE
- +# define gcdSUPPORT_SWAP_RECTANGLE 0
- +#endif
- +
- +/*
- + gcdGPU_LINEAR_BUFFER_ENABLED
- +
- + Use linear buffer for GPU apps so HWC can do 2D composition.
- +*/
- +#ifndef gcdGPU_LINEAR_BUFFER_ENABLED
- +# define gcdGPU_LINEAR_BUFFER_ENABLED 1
- +#endif
- +
- +/*
- + gcdENABLE_RENDER_INTO_WINDOW
- +
- + Enable Render-Into-Window (ie, No-Resolve) feature on android.
- + NOTE that even if enabled, it still depends on hardware feature and
- + android application behavior. When hardware feature or application
- + behavior can not support render into window mode, it will fail back
- + to normal mode.
- + When Render-Into-Window is finally used, window back buffer of android
- + applications will be allocated matching render target tiling format.
- + Otherwise buffer tiling is decided by the above option
- + 'gcdGPU_LINEAR_BUFFER_ENABLED'.
- +*/
- +#ifndef gcdENABLE_RENDER_INTO_WINDOW
- +# define gcdENABLE_RENDER_INTO_WINDOW 1
- +#endif
- +
- +/*
- + gcdSHARED_RESOLVE_BUFFER_ENABLED
- +
- + Use shared resolve buffer for all app buffers.
- +*/
- +#ifndef gcdSHARED_RESOLVE_BUFFER_ENABLED
- +# define gcdSHARED_RESOLVE_BUFFER_ENABLED 0
- +#endif
- +
- +/*
- + gcdUSE_TRIANGLE_STRIP_PATCH
- + */
- +#ifndef gcdUSE_TRIANGLE_STRIP_PATCH
- +# define gcdUSE_TRIANGLE_STRIP_PATCH 1
- +#endif
- +
- +/*
- + gcdENABLE_OUTER_CACHE_PATCH
- +
- + Enable the outer cache patch.
- +*/
- +#ifndef gcdENABLE_OUTER_CACHE_PATCH
- +# define gcdENABLE_OUTER_CACHE_PATCH 0
- +#endif
- +
- +#ifndef gcdANDROID_UNALIGNED_LINEAR_COMPOSITION_ADJUST
- +# ifdef ANDROID
- +# define gcdANDROID_UNALIGNED_LINEAR_COMPOSITION_ADJUST 1
- +# else
- +# define gcdANDROID_UNALIGNED_LINEAR_COMPOSITION_ADJUST 0
- +# endif
- +#endif
- +
- +#ifndef gcdENABLE_PE_DITHER_FIX
- +# define gcdENABLE_PE_DITHER_FIX 1
- +#endif
- +
- +#ifndef gcdSHARED_PAGETABLE
- +# define gcdSHARED_PAGETABLE 1
- +#endif
- +#ifndef gcdUSE_PVR
- +# define gcdUSE_PVR 1
- +#endif
- +
- +/*
- + gcdSMALL_BLOCK_SIZE
- +
- + When non-zero, a part of VIDMEM will be reserved for requests
- + whose requesting size is less than gcdSMALL_BLOCK_SIZE.
- +
- + For Linux, it's the size of a page. If this requeset fallbacks
- + to gcvPOOL_CONTIGUOUS or gcvPOOL_VIRTUAL, memory will be wasted
- + because they allocate a page at least.
- + */
- +#ifndef gcdSMALL_BLOCK_SIZE
- +# define gcdSMALL_BLOCK_SIZE 4096
- +# define gcdRATIO_FOR_SMALL_MEMORY 32
- +#endif
- +
- +/*
- + gcdCONTIGUOUS_SIZE_LIMIT
- + When non-zero, size of video node from gcvPOOL_CONTIGUOUS is
- + limited by gcdCONTIGUOUS_SIZE_LIMIT.
- + */
- +#ifndef gcdCONTIGUOUS_SIZE_LIMIT
- +# define gcdCONTIGUOUS_SIZE_LIMIT 0
- +#endif
- +
- +#ifndef gcdDISALBE_EARLY_EARLY_Z
- +# define gcdDISALBE_EARLY_EARLY_Z 1
- +#endif
- +
- +#ifndef gcdSHADER_SRC_BY_MACHINECODE
- +# define gcdSHADER_SRC_BY_MACHINECODE 1
- +#endif
- +
- +/*
- + gcdLINK_QUEUE_SIZE
- +
- + When non-zero, driver maintains a queue to record information of
- + latest lined context buffer and command buffer. Data in this queue
- + is be used to debug.
- +*/
- +#ifndef gcdLINK_QUEUE_SIZE
- +# define gcdLINK_QUEUE_SIZE 0
- +#endif
- +
- +/* gcdALPHA_KILL_IN_SHADER
- + *
- + * Enable alpha kill inside the shader. This will be set automatically by the
- + * HAL if certain states match a criteria.
- + */
- +#ifndef gcdALPHA_KILL_IN_SHADER
- +# define gcdALPHA_KILL_IN_SHADER 1
- +#endif
- +
- +/* gcdHIGH_PRECISION_DELAY_ENABLE
- + *
- + * Enable high precision schedule delay with 1ms unit. otherwise schedule delay up to 10ms.
- + * Browser app performance will have obvious drop without this enablement
- + */
- +#ifndef gcdHIGH_PRECISION_DELAY_ENABLE
- +# define gcdHIGH_PRECISION_DELAY_ENABLE 1
- +#endif
- +
- +#ifndef gcdUSE_WCLIP_PATCH
- +# define gcdUSE_WCLIP_PATCH 1
- +#endif
- +
- +#ifndef gcdHZ_L2_DISALBE
- +# define gcdHZ_L2_DISALBE 1
- +#endif
- +
- +#ifndef gcdBUGFIX15_DISABLE
- +# define gcdBUGFIX15_DISABLE 1
- +#endif
- +
- +#ifndef gcdDISABLE_HZ_FAST_CLEAR
- +# define gcdDISABLE_HZ_FAST_CLEAR 1
- +#endif
- +
- +#ifndef gcdUSE_NPOT_PATCH
- +#define gcdUSE_NPOT_PATCH 1
- +#endif
- +
- +#ifndef gcdSYNC
- +# define gcdSYNC 1
- +#endif
- +
- +#ifndef gcdENABLE_SPECIAL_HINT3
- +# define gcdENABLE_SPECIAL_HINT3 1
- +#endif
- +
- +#if defined(ANDROID)
- +#ifndef gcdPRE_ROTATION
- +# define gcdPRE_ROTATION 1
- +#endif
- +#endif
- +
- +/*
- + gcdDVFS
- +
- + When non-zero, software will make use of dynamic voltage and
- + frequency feature.
- + */
- +#ifndef gcdDVFS
- +# define gcdDVFS 0
- +# define gcdDVFS_ANAYLSE_WINDOW 4
- +# define gcdDVFS_POLLING_TIME (gcdDVFS_ANAYLSE_WINDOW * 4)
- +#endif
- +
- +/*
- + gcdANDROID_NATIVE_FENCE_SYNC
- +
- + Enable android native fence sync. It is introduced since jellybean-4.2.
- + Depends on linux kernel option: CONFIG_SYNC.
- +
- + 0: Disabled
- + 1: Build framework for native fence sync feature, and EGL extension
- + 2: Enable async swap buffers for client
- + * Native fence sync for client 'queueBuffer' in EGL, which is
- + 'acquireFenceFd' for layer in compositor side.
- + 3. Enable async hwcomposer composition.
- + * 'releaseFenceFd' for layer in compositor side, which is native
- + fence sync when client 'dequeueBuffer'
- + * Native fence sync for compositor 'queueBuffer' in EGL, which is
- + 'acquireFenceFd' for framebuffer target for DC
- + */
- +#ifndef gcdANDROID_NATIVE_FENCE_SYNC
- +# define gcdANDROID_NATIVE_FENCE_SYNC 0
- +#endif
- +
- +#ifndef gcdFORCE_MIPMAP
- +# define gcdFORCE_MIPMAP 0
- +#endif
- +
- +/*
- + gcdFORCE_GAL_LOAD_TWICE
- +
- + When non-zero, each thread except the main one will load libGAL.so twice to avoid potential segmetantion fault when app using dlopen/dlclose.
- + If threads exit arbitrarily, libGAL.so may not unload until the process quit.
- + */
- +#ifndef gcdFORCE_GAL_LOAD_TWICE
- +# define gcdFORCE_GAL_LOAD_TWICE 0
- +#endif
- +
- +#endif /* __gc_hal_options_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_profiler.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_profiler.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_profiler.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_profiler.h 2015-03-08 14:27:37.649684500 -0500
- @@ -0,0 +1,584 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_profiler_h_
- +#define __gc_hal_profiler_h_
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +#define GLVERTEX_OBJECT 10
- +#define GLVERTEX_OBJECT_BYTES 11
- +
- +#define GLINDEX_OBJECT 20
- +#define GLINDEX_OBJECT_BYTES 21
- +
- +#define GLTEXTURE_OBJECT 30
- +#define GLTEXTURE_OBJECT_BYTES 31
- +
- +#if VIVANTE_PROFILER
- +#define gcmPROFILE_GC(Enum, Value) gcoPROFILER_Count(gcvNULL, Enum, Value)
- +#else
- +#define gcmPROFILE_GC(Enum, Value) do { } while (gcvFALSE)
- +#endif
- +
- +#ifndef gcdNEW_PROFILER_FILE
- +#define gcdNEW_PROFILER_FILE 1
- +#endif
- +
- +#define ES11_CALLS 151
- +#define ES11_DRAWCALLS (ES11_CALLS + 1)
- +#define ES11_STATECHANGECALLS (ES11_DRAWCALLS + 1)
- +#define ES11_POINTCOUNT (ES11_STATECHANGECALLS + 1)
- +#define ES11_LINECOUNT (ES11_POINTCOUNT + 1)
- +#define ES11_TRIANGLECOUNT (ES11_LINECOUNT + 1)
- +
- +#define ES20_CALLS 159
- +#define ES20_DRAWCALLS (ES20_CALLS + 1)
- +#define ES20_STATECHANGECALLS (ES20_DRAWCALLS + 1)
- +#define ES20_POINTCOUNT (ES20_STATECHANGECALLS + 1)
- +#define ES20_LINECOUNT (ES20_POINTCOUNT + 1)
- +#define ES20_TRIANGLECOUNT (ES20_LINECOUNT + 1)
- +
- +#define VG11_CALLS 88
- +#define VG11_DRAWCALLS (VG11_CALLS + 1)
- +#define VG11_STATECHANGECALLS (VG11_DRAWCALLS + 1)
- +#define VG11_FILLCOUNT (VG11_STATECHANGECALLS + 1)
- +#define VG11_STROKECOUNT (VG11_FILLCOUNT + 1)
- +/* End of Driver API ID Definitions. */
- +
- +/* HAL & MISC IDs. */
- +#define HAL_VERTBUFNEWBYTEALLOC 1
- +#define HAL_VERTBUFTOTALBYTEALLOC (HAL_VERTBUFNEWBYTEALLOC + 1)
- +#define HAL_VERTBUFNEWOBJALLOC (HAL_VERTBUFTOTALBYTEALLOC + 1)
- +#define HAL_VERTBUFTOTALOBJALLOC (HAL_VERTBUFNEWOBJALLOC + 1)
- +#define HAL_INDBUFNEWBYTEALLOC (HAL_VERTBUFTOTALOBJALLOC + 1)
- +#define HAL_INDBUFTOTALBYTEALLOC (HAL_INDBUFNEWBYTEALLOC + 1)
- +#define HAL_INDBUFNEWOBJALLOC (HAL_INDBUFTOTALBYTEALLOC + 1)
- +#define HAL_INDBUFTOTALOBJALLOC (HAL_INDBUFNEWOBJALLOC + 1)
- +#define HAL_TEXBUFNEWBYTEALLOC (HAL_INDBUFTOTALOBJALLOC + 1)
- +#define HAL_TEXBUFTOTALBYTEALLOC (HAL_TEXBUFNEWBYTEALLOC + 1)
- +#define HAL_TEXBUFNEWOBJALLOC (HAL_TEXBUFTOTALBYTEALLOC + 1)
- +#define HAL_TEXBUFTOTALOBJALLOC (HAL_TEXBUFNEWOBJALLOC + 1)
- +
- +#define GPU_CYCLES 1
- +#define GPU_READ64BYTE (GPU_CYCLES + 1)
- +#define GPU_WRITE64BYTE (GPU_READ64BYTE + 1)
- +#define GPU_TOTALCYCLES (GPU_WRITE64BYTE + 1)
- +#define GPU_IDLECYCLES (GPU_TOTALCYCLES + 1)
- +
- +#define VS_INSTCOUNT 1
- +#define VS_BRANCHINSTCOUNT (VS_INSTCOUNT + 1)
- +#define VS_TEXLDINSTCOUNT (VS_BRANCHINSTCOUNT + 1)
- +#define VS_RENDEREDVERTCOUNT (VS_TEXLDINSTCOUNT + 1)
- +#define VS_SOURCE (VS_RENDEREDVERTCOUNT + 1)
- +
- +#define PS_INSTCOUNT 1
- +#define PS_BRANCHINSTCOUNT (PS_INSTCOUNT + 1)
- +#define PS_TEXLDINSTCOUNT (PS_BRANCHINSTCOUNT + 1)
- +#define PS_RENDEREDPIXCOUNT (PS_TEXLDINSTCOUNT + 1)
- +#define PS_SOURCE (PS_RENDEREDPIXCOUNT + 1)
- +
- +#define PA_INVERTCOUNT 1
- +#define PA_INPRIMCOUNT (PA_INVERTCOUNT + 1)
- +#define PA_OUTPRIMCOUNT (PA_INPRIMCOUNT + 1)
- +#define PA_DEPTHCLIPCOUNT (PA_OUTPRIMCOUNT + 1)
- +#define PA_TRIVIALREJCOUNT (PA_DEPTHCLIPCOUNT + 1)
- +#define PA_CULLCOUNT (PA_TRIVIALREJCOUNT + 1)
- +
- +#define SE_TRIANGLECOUNT 1
- +#define SE_LINECOUNT (SE_TRIANGLECOUNT + 1)
- +
- +#define RA_VALIDPIXCOUNT 1
- +#define RA_TOTALQUADCOUNT (RA_VALIDPIXCOUNT + 1)
- +#define RA_VALIDQUADCOUNTEZ (RA_TOTALQUADCOUNT + 1)
- +#define RA_TOTALPRIMCOUNT (RA_VALIDQUADCOUNTEZ + 1)
- +#define RA_PIPECACHEMISSCOUNT (RA_TOTALPRIMCOUNT + 1)
- +#define RA_PREFCACHEMISSCOUNT (RA_PIPECACHEMISSCOUNT + 1)
- +#define RA_EEZCULLCOUNT (RA_PREFCACHEMISSCOUNT + 1)
- +
- +#define TX_TOTBILINEARREQ 1
- +#define TX_TOTTRILINEARREQ (TX_TOTBILINEARREQ + 1)
- +#define TX_TOTDISCARDTEXREQ (TX_TOTTRILINEARREQ + 1)
- +#define TX_TOTTEXREQ (TX_TOTDISCARDTEXREQ + 1)
- +#define TX_MEMREADCOUNT (TX_TOTTEXREQ + 1)
- +#define TX_MEMREADIN8BCOUNT (TX_MEMREADCOUNT + 1)
- +#define TX_CACHEMISSCOUNT (TX_MEMREADIN8BCOUNT + 1)
- +#define TX_CACHEHITTEXELCOUNT (TX_CACHEMISSCOUNT + 1)
- +#define TX_CACHEMISSTEXELCOUNT (TX_CACHEHITTEXELCOUNT + 1)
- +
- +#define PE_KILLEDBYCOLOR 1
- +#define PE_KILLEDBYDEPTH (PE_KILLEDBYCOLOR + 1)
- +#define PE_DRAWNBYCOLOR (PE_KILLEDBYDEPTH + 1)
- +#define PE_DRAWNBYDEPTH (PE_DRAWNBYCOLOR + 1)
- +
- +#define MC_READREQ8BPIPE 1
- +#define MC_READREQ8BIP (MC_READREQ8BPIPE + 1)
- +#define MC_WRITEREQ8BPIPE (MC_READREQ8BIP + 1)
- +
- +#define AXI_READREQSTALLED 1
- +#define AXI_WRITEREQSTALLED (AXI_READREQSTALLED + 1)
- +#define AXI_WRITEDATASTALLED (AXI_WRITEREQSTALLED + 1)
- +
- +#define PVS_INSTRCOUNT 1
- +#define PVS_ALUINSTRCOUNT (PVS_INSTRCOUNT + 1)
- +#define PVS_TEXINSTRCOUNT (PVS_ALUINSTRCOUNT + 1)
- +#define PVS_ATTRIBCOUNT (PVS_TEXINSTRCOUNT + 1)
- +#define PVS_UNIFORMCOUNT (PVS_ATTRIBCOUNT + 1)
- +#define PVS_FUNCTIONCOUNT (PVS_UNIFORMCOUNT + 1)
- +#define PVS_SOURCE (PVS_FUNCTIONCOUNT + 1)
- +
- +#define PPS_INSTRCOUNT 1
- +#define PPS_ALUINSTRCOUNT (PPS_INSTRCOUNT + 1)
- +#define PPS_TEXINSTRCOUNT (PPS_ALUINSTRCOUNT + 1)
- +#define PPS_ATTRIBCOUNT (PPS_TEXINSTRCOUNT + 1)
- +#define PPS_UNIFORMCOUNT (PPS_ATTRIBCOUNT + 1)
- +#define PPS_FUNCTIONCOUNT (PPS_UNIFORMCOUNT + 1)
- +#define PPS_SOURCE (PPS_FUNCTIONCOUNT + 1)
- +/* End of MISC Counter IDs. */
- +
- +#ifdef gcdNEW_PROFILER_FILE
- +
- +/* Category Constants. */
- +#define VPHEADER 0x010000
- +#define VPG_INFO 0x020000
- +#define VPG_TIME 0x030000
- +#define VPG_MEM 0x040000
- +#define VPG_ES11 0x050000
- +#define VPG_ES20 0x060000
- +#define VPG_VG11 0x070000
- +#define VPG_HAL 0x080000
- +#define VPG_HW 0x090000
- +#define VPG_GPU 0x0a0000
- +#define VPG_VS 0x0b0000
- +#define VPG_PS 0x0c0000
- +#define VPG_PA 0x0d0000
- +#define VPG_SETUP 0x0e0000
- +#define VPG_RA 0x0f0000
- +#define VPG_TX 0x100000
- +#define VPG_PE 0x110000
- +#define VPG_MC 0x120000
- +#define VPG_AXI 0x130000
- +#define VPG_PROG 0x140000
- +#define VPG_PVS 0x150000
- +#define VPG_PPS 0x160000
- +#define VPG_ES11_TIME 0x170000
- +#define VPG_ES20_TIME 0x180000
- +#define VPG_FRAME 0x190000
- +#define VPG_ES11_DRAW 0x200000
- +#define VPG_ES20_DRAW 0x210000
- +#define VPG_END 0xff0000
- +
- +/* Info. */
- +#define VPC_INFOCOMPANY (VPG_INFO + 1)
- +#define VPC_INFOVERSION (VPC_INFOCOMPANY + 1)
- +#define VPC_INFORENDERER (VPC_INFOVERSION + 1)
- +#define VPC_INFOREVISION (VPC_INFORENDERER + 1)
- +#define VPC_INFODRIVER (VPC_INFOREVISION + 1)
- +#define VPC_INFODRIVERMODE (VPC_INFODRIVER + 1)
- +#define VPC_INFOSCREENSIZE (VPC_INFODRIVERMODE + 1)
- +
- +/* Counter Constants. */
- +#define VPC_ELAPSETIME (VPG_TIME + 1)
- +#define VPC_CPUTIME (VPC_ELAPSETIME + 1)
- +
- +#define VPC_MEMMAXRES (VPG_MEM + 1)
- +#define VPC_MEMSHARED (VPC_MEMMAXRES + 1)
- +#define VPC_MEMUNSHAREDDATA (VPC_MEMSHARED + 1)
- +#define VPC_MEMUNSHAREDSTACK (VPC_MEMUNSHAREDDATA + 1)
- +
- +/* OpenGL ES11 Statics Counter IDs. */
- +#define VPC_ES11CALLS (VPG_ES11 + ES11_CALLS)
- +#define VPC_ES11DRAWCALLS (VPG_ES11 + ES11_DRAWCALLS)
- +#define VPC_ES11STATECHANGECALLS (VPG_ES11 + ES11_STATECHANGECALLS)
- +#define VPC_ES11POINTCOUNT (VPG_ES11 + ES11_POINTCOUNT)
- +#define VPC_ES11LINECOUNT (VPG_ES11 + ES11_LINECOUNT)
- +#define VPC_ES11TRIANGLECOUNT (VPG_ES11 + ES11_TRIANGLECOUNT)
- +
- +/* OpenGL ES20 Statistics Counter IDs. */
- +#define VPC_ES20CALLS (VPG_ES20 + ES20_CALLS)
- +#define VPC_ES20DRAWCALLS (VPG_ES20 + ES20_DRAWCALLS)
- +#define VPC_ES20STATECHANGECALLS (VPG_ES20 + ES20_STATECHANGECALLS)
- +#define VPC_ES20POINTCOUNT (VPG_ES20 + ES20_POINTCOUNT)
- +#define VPC_ES20LINECOUNT (VPG_ES20 + ES20_LINECOUNT)
- +#define VPC_ES20TRIANGLECOUNT (VPG_ES20 + ES20_TRIANGLECOUNT)
- +
- +/* OpenVG Statistics Counter IDs. */
- +#define VPC_VG11CALLS (VPG_VG11 + VG11_CALLS)
- +#define VPC_VG11DRAWCALLS (VPG_VG11 + VG11_DRAWCALLS)
- +#define VPC_VG11STATECHANGECALLS (VPG_VG11 + VG11_STATECHANGECALLS)
- +#define VPC_VG11FILLCOUNT (VPG_VG11 + VG11_FILLCOUNT)
- +#define VPC_VG11STROKECOUNT (VPG_VG11 + VG11_STROKECOUNT)
- +
- +/* HAL Counters. */
- +#define VPC_HALVERTBUFNEWBYTEALLOC (VPG_HAL + HAL_VERTBUFNEWBYTEALLOC)
- +#define VPC_HALVERTBUFTOTALBYTEALLOC (VPG_HAL + HAL_VERTBUFTOTALBYTEALLOC)
- +#define VPC_HALVERTBUFNEWOBJALLOC (VPG_HAL + HAL_VERTBUFNEWOBJALLOC)
- +#define VPC_HALVERTBUFTOTALOBJALLOC (VPG_HAL + HAL_VERTBUFTOTALOBJALLOC)
- +#define VPC_HALINDBUFNEWBYTEALLOC (VPG_HAL + HAL_INDBUFNEWBYTEALLOC)
- +#define VPC_HALINDBUFTOTALBYTEALLOC (VPG_HAL + HAL_INDBUFTOTALBYTEALLOC)
- +#define VPC_HALINDBUFNEWOBJALLOC (VPG_HAL + HAL_INDBUFNEWOBJALLOC)
- +#define VPC_HALINDBUFTOTALOBJALLOC (VPG_HAL + HAL_INDBUFTOTALOBJALLOC)
- +#define VPC_HALTEXBUFNEWBYTEALLOC (VPG_HAL + HAL_TEXBUFNEWBYTEALLOC)
- +#define VPC_HALTEXBUFTOTALBYTEALLOC (VPG_HAL + HAL_TEXBUFTOTALBYTEALLOC)
- +#define VPC_HALTEXBUFNEWOBJALLOC (VPG_HAL + HAL_TEXBUFNEWOBJALLOC)
- +#define VPC_HALTEXBUFTOTALOBJALLOC (VPG_HAL + HAL_TEXBUFTOTALOBJALLOC)
- +
- +/* HW: GPU Counters. */
- +#define VPC_GPUCYCLES (VPG_GPU + GPU_CYCLES)
- +#define VPC_GPUREAD64BYTE (VPG_GPU + GPU_READ64BYTE)
- +#define VPC_GPUWRITE64BYTE (VPG_GPU + GPU_WRITE64BYTE)
- +#define VPC_GPUTOTALCYCLES (VPG_GPU + GPU_TOTALCYCLES)
- +#define VPC_GPUIDLECYCLES (VPG_GPU + GPU_IDLECYCLES)
- +
- +/* HW: Shader Counters. */
- +#define VPC_VSINSTCOUNT (VPG_VS + VS_INSTCOUNT)
- +#define VPC_VSBRANCHINSTCOUNT (VPG_VS + VS_BRANCHINSTCOUNT)
- +#define VPC_VSTEXLDINSTCOUNT (VPG_VS + VS_TEXLDINSTCOUNT)
- +#define VPC_VSRENDEREDVERTCOUNT (VPG_VS + VS_RENDEREDVERTCOUNT)
- +/* HW: PS Count. */
- +#define VPC_PSINSTCOUNT (VPG_PS + PS_INSTCOUNT)
- +#define VPC_PSBRANCHINSTCOUNT (VPG_PS + PS_BRANCHINSTCOUNT)
- +#define VPC_PSTEXLDINSTCOUNT (VPG_PS + PS_TEXLDINSTCOUNT)
- +#define VPC_PSRENDEREDPIXCOUNT (VPG_PS + PS_RENDEREDPIXCOUNT)
- +
- +
- +/* HW: PA Counters. */
- +#define VPC_PAINVERTCOUNT (VPG_PA + PA_INVERTCOUNT)
- +#define VPC_PAINPRIMCOUNT (VPG_PA + PA_INPRIMCOUNT)
- +#define VPC_PAOUTPRIMCOUNT (VPG_PA + PA_OUTPRIMCOUNT)
- +#define VPC_PADEPTHCLIPCOUNT (VPG_PA + PA_DEPTHCLIPCOUNT)
- +#define VPC_PATRIVIALREJCOUNT (VPG_PA + PA_TRIVIALREJCOUNT)
- +#define VPC_PACULLCOUNT (VPG_PA + PA_CULLCOUNT)
- +
- +/* HW: Setup Counters. */
- +#define VPC_SETRIANGLECOUNT (VPG_SETUP + SE_TRIANGLECOUNT)
- +#define VPC_SELINECOUNT (VPG_SETUP + SE_LINECOUNT)
- +
- +/* HW: RA Counters. */
- +#define VPC_RAVALIDPIXCOUNT (VPG_RA + RA_VALIDPIXCOUNT)
- +#define VPC_RATOTALQUADCOUNT (VPG_RA + RA_TOTALQUADCOUNT)
- +#define VPC_RAVALIDQUADCOUNTEZ (VPG_RA + RA_VALIDQUADCOUNTEZ)
- +#define VPC_RATOTALPRIMCOUNT (VPG_RA + RA_TOTALPRIMCOUNT)
- +#define VPC_RAPIPECACHEMISSCOUNT (VPG_RA + RA_PIPECACHEMISSCOUNT)
- +#define VPC_RAPREFCACHEMISSCOUNT (VPG_RA + RA_PREFCACHEMISSCOUNT)
- +#define VPC_RAEEZCULLCOUNT (VPG_RA + RA_EEZCULLCOUNT)
- +
- +/* HW: TEX Counters. */
- +#define VPC_TXTOTBILINEARREQ (VPG_TX + TX_TOTBILINEARREQ)
- +#define VPC_TXTOTTRILINEARREQ (VPG_TX + TX_TOTTRILINEARREQ)
- +#define VPC_TXTOTDISCARDTEXREQ (VPG_TX + TX_TOTDISCARDTEXREQ)
- +#define VPC_TXTOTTEXREQ (VPG_TX + TX_TOTTEXREQ)
- +#define VPC_TXMEMREADCOUNT (VPG_TX + TX_MEMREADCOUNT)
- +#define VPC_TXMEMREADIN8BCOUNT (VPG_TX + TX_MEMREADIN8BCOUNT)
- +#define VPC_TXCACHEMISSCOUNT (VPG_TX + TX_CACHEMISSCOUNT)
- +#define VPC_TXCACHEHITTEXELCOUNT (VPG_TX + TX_CACHEHITTEXELCOUNT)
- +#define VPC_TXCACHEMISSTEXELCOUNT (VPG_TX + TX_CACHEMISSTEXELCOUNT)
- +
- +/* HW: PE Counters. */
- +#define VPC_PEKILLEDBYCOLOR (VPG_PE + PE_KILLEDBYCOLOR)
- +#define VPC_PEKILLEDBYDEPTH (VPG_PE + PE_KILLEDBYDEPTH)
- +#define VPC_PEDRAWNBYCOLOR (VPG_PE + PE_DRAWNBYCOLOR)
- +#define VPC_PEDRAWNBYDEPTH (VPG_PE + PE_DRAWNBYDEPTH)
- +
- +/* HW: MC Counters. */
- +#define VPC_MCREADREQ8BPIPE (VPG_MC + MC_READREQ8BPIPE)
- +#define VPC_MCREADREQ8BIP (VPG_MC + MC_READREQ8BIP)
- +#define VPC_MCWRITEREQ8BPIPE (VPG_MC + MC_WRITEREQ8BPIPE)
- +
- +/* HW: AXI Counters. */
- +#define VPC_AXIREADREQSTALLED (VPG_AXI + AXI_READREQSTALLED)
- +#define VPC_AXIWRITEREQSTALLED (VPG_AXI + AXI_WRITEREQSTALLED)
- +#define VPC_AXIWRITEDATASTALLED (VPG_AXI + AXI_WRITEDATASTALLED)
- +
- +/* PROGRAM: Shader program counters. */
- +#define VPC_PVSINSTRCOUNT (VPG_PVS + PVS_INSTRCOUNT)
- +#define VPC_PVSALUINSTRCOUNT (VPG_PVS + PVS_ALUINSTRCOUNT)
- +#define VPC_PVSTEXINSTRCOUNT (VPG_PVS + PVS_TEXINSTRCOUNT)
- +#define VPC_PVSATTRIBCOUNT (VPG_PVS + PVS_ATTRIBCOUNT)
- +#define VPC_PVSUNIFORMCOUNT (VPG_PVS + PVS_UNIFORMCOUNT)
- +#define VPC_PVSFUNCTIONCOUNT (VPG_PVS + PVS_FUNCTIONCOUNT)
- +#define VPC_PVSSOURCE (VPG_PVS + PVS_SOURCE)
- +
- +#define VPC_PPSINSTRCOUNT (VPG_PPS + PPS_INSTRCOUNT)
- +#define VPC_PPSALUINSTRCOUNT (VPG_PPS + PPS_ALUINSTRCOUNT)
- +#define VPC_PPSTEXINSTRCOUNT (VPG_PPS + PPS_TEXINSTRCOUNT)
- +#define VPC_PPSATTRIBCOUNT (VPG_PPS + PPS_ATTRIBCOUNT)
- +#define VPC_PPSUNIFORMCOUNT (VPG_PPS + PPS_UNIFORMCOUNT)
- +#define VPC_PPSFUNCTIONCOUNT (VPG_PPS + PPS_FUNCTIONCOUNT)
- +#define VPC_PPSSOURCE (VPG_PPS + PPS_SOURCE)
- +
- +#define VPC_PROGRAMHANDLE (VPG_PROG + 1)
- +
- +#define VPG_ES20_DRAW_NO (VPG_ES20_DRAW + 1)
- +#define VPG_ES11_DRAW_NO (VPG_ES11_DRAW + 1)
- +
- +#define VPG_FRAME_USEVBO (VPG_FRAME + 1)
- +
- +#endif
- +
- +
- +/* HW profile information. */
- +typedef struct _gcsPROFILER_COUNTERS
- +{
- + /* HW static counters. */
- + gctUINT32 gpuClock;
- + gctUINT32 axiClock;
- + gctUINT32 shaderClock;
- +
- + /* HW vairable counters. */
- + gctUINT32 gpuClockStart;
- + gctUINT32 gpuClockEnd;
- +
- + /* HW vairable counters. */
- + gctUINT32 gpuCyclesCounter;
- + gctUINT32 gpuTotalCyclesCounter;
- + gctUINT32 gpuIdleCyclesCounter;
- + gctUINT32 gpuTotalRead64BytesPerFrame;
- + gctUINT32 gpuTotalWrite64BytesPerFrame;
- +
- + /* PE */
- + gctUINT32 pe_pixel_count_killed_by_color_pipe;
- + gctUINT32 pe_pixel_count_killed_by_depth_pipe;
- + gctUINT32 pe_pixel_count_drawn_by_color_pipe;
- + gctUINT32 pe_pixel_count_drawn_by_depth_pipe;
- +
- + /* SH */
- + gctUINT32 ps_inst_counter;
- + gctUINT32 rendered_pixel_counter;
- + gctUINT32 vs_inst_counter;
- + gctUINT32 rendered_vertice_counter;
- + gctUINT32 vtx_branch_inst_counter;
- + gctUINT32 vtx_texld_inst_counter;
- + gctUINT32 pxl_branch_inst_counter;
- + gctUINT32 pxl_texld_inst_counter;
- +
- + /* PA */
- + gctUINT32 pa_input_vtx_counter;
- + gctUINT32 pa_input_prim_counter;
- + gctUINT32 pa_output_prim_counter;
- + gctUINT32 pa_depth_clipped_counter;
- + gctUINT32 pa_trivial_rejected_counter;
- + gctUINT32 pa_culled_counter;
- +
- + /* SE */
- + gctUINT32 se_culled_triangle_count;
- + gctUINT32 se_culled_lines_count;
- +
- + /* RA */
- + gctUINT32 ra_valid_pixel_count;
- + gctUINT32 ra_total_quad_count;
- + gctUINT32 ra_valid_quad_count_after_early_z;
- + gctUINT32 ra_total_primitive_count;
- + gctUINT32 ra_pipe_cache_miss_counter;
- + gctUINT32 ra_prefetch_cache_miss_counter;
- + gctUINT32 ra_eez_culled_counter;
- +
- + /* TX */
- + gctUINT32 tx_total_bilinear_requests;
- + gctUINT32 tx_total_trilinear_requests;
- + gctUINT32 tx_total_discarded_texture_requests;
- + gctUINT32 tx_total_texture_requests;
- + gctUINT32 tx_mem_read_count;
- + gctUINT32 tx_mem_read_in_8B_count;
- + gctUINT32 tx_cache_miss_count;
- + gctUINT32 tx_cache_hit_texel_count;
- + gctUINT32 tx_cache_miss_texel_count;
- +
- + /* MC */
- + gctUINT32 mc_total_read_req_8B_from_pipeline;
- + gctUINT32 mc_total_read_req_8B_from_IP;
- + gctUINT32 mc_total_write_req_8B_from_pipeline;
- +
- + /* HI */
- + gctUINT32 hi_axi_cycles_read_request_stalled;
- + gctUINT32 hi_axi_cycles_write_request_stalled;
- + gctUINT32 hi_axi_cycles_write_data_stalled;
- +}
- +gcsPROFILER_COUNTERS;
- +
- +/* HAL profile information. */
- +typedef struct _gcsPROFILER
- +{
- + gctUINT32 enable;
- + gctBOOL enableHal;
- + gctBOOL enableHW;
- + gctBOOL enableSH;
- + gctBOOL isSyncMode;
- +
- + gctBOOL useSocket;
- + gctINT sockFd;
- +
- + gctFILE file;
- +
- + /* Aggregate Information */
- +
- + /* Clock Info */
- + gctUINT64 frameStart;
- + gctUINT64 frameEnd;
- +
- + /* Current frame information */
- + gctUINT32 frameNumber;
- + gctUINT64 frameStartTimeusec;
- + gctUINT64 frameEndTimeusec;
- + gctUINT64 frameStartCPUTimeusec;
- + gctUINT64 frameEndCPUTimeusec;
- +
- +#if PROFILE_HAL_COUNTERS
- + gctUINT32 vertexBufferTotalBytesAlloc;
- + gctUINT32 vertexBufferNewBytesAlloc;
- + int vertexBufferTotalObjectsAlloc;
- + int vertexBufferNewObjectsAlloc;
- +
- + gctUINT32 indexBufferTotalBytesAlloc;
- + gctUINT32 indexBufferNewBytesAlloc;
- + int indexBufferTotalObjectsAlloc;
- + int indexBufferNewObjectsAlloc;
- +
- + gctUINT32 textureBufferTotalBytesAlloc;
- + gctUINT32 textureBufferNewBytesAlloc;
- + int textureBufferTotalObjectsAlloc;
- + int textureBufferNewObjectsAlloc;
- +
- + gctUINT32 numCommits;
- + gctUINT32 drawPointCount;
- + gctUINT32 drawLineCount;
- + gctUINT32 drawTriangleCount;
- + gctUINT32 drawVertexCount;
- + gctUINT32 redundantStateChangeCalls;
- +#endif
- +
- + gctUINT32 prevVSInstCount;
- + gctUINT32 prevVSBranchInstCount;
- + gctUINT32 prevVSTexInstCount;
- + gctUINT32 prevVSVertexCount;
- + gctUINT32 prevPSInstCount;
- + gctUINT32 prevPSBranchInstCount;
- + gctUINT32 prevPSTexInstCount;
- + gctUINT32 prevPSPixelCount;
- +
- + char* psSource;
- + char* vsSource;
- +
- +}
- +gcsPROFILER;
- +
- +/* Memory profile information. */
- +struct _gcsMemProfile
- +{
- + /* Memory Usage */
- + gctUINT32 videoMemUsed;
- + gctUINT32 systemMemUsed;
- + gctUINT32 commitBufferSize;
- + gctUINT32 contextBufferCopyBytes;
- +};
- +
- +/* Shader profile information. */
- +struct _gcsSHADER_PROFILER
- +{
- + gctUINT32 shaderLength;
- + gctUINT32 shaderALUCycles;
- + gctUINT32 shaderTexLoadCycles;
- + gctUINT32 shaderTempRegCount;
- + gctUINT32 shaderSamplerRegCount;
- + gctUINT32 shaderInputRegCount;
- + gctUINT32 shaderOutputRegCount;
- +};
- +
- +/* Initialize the gcsProfiler. */
- +gceSTATUS
- +gcoPROFILER_Initialize(
- + IN gcoHAL Hal
- + );
- +
- +/* Destroy the gcProfiler. */
- +gceSTATUS
- +gcoPROFILER_Destroy(
- + IN gcoHAL Hal
- + );
- +
- +/* Write data to profiler. */
- +gceSTATUS
- +gcoPROFILER_Write(
- + IN gcoHAL Hal,
- + IN gctSIZE_T ByteCount,
- + IN gctCONST_POINTER Data
- + );
- +
- +/* Flush data out. */
- +gceSTATUS
- +gcoPROFILER_Flush(
- + IN gcoHAL Hal
- + );
- +
- +/* Call to signal end of frame. */
- +gceSTATUS
- +gcoPROFILER_EndFrame(
- + IN gcoHAL Hal
- + );
- +
- +/* Call to signal end of draw. */
- +gceSTATUS
- +gcoPROFILER_EndDraw(
- + IN gcoHAL Hal,
- + IN gctBOOL FirstDraw
- + );
- +
- +/* Increase profile counter Enum by Value. */
- +gceSTATUS
- +gcoPROFILER_Count(
- + IN gcoHAL Hal,
- + IN gctUINT32 Enum,
- + IN gctINT Value
- + );
- +
- +gceSTATUS
- +gcoPROFILER_ShaderSourceFS(
- + IN gcoHAL Hal,
- + IN char* source
- + );
- +
- +gceSTATUS
- +gcoPROFILER_ShaderSourceVS(
- + IN gcoHAL Hal,
- + IN char* source
- + );
- +
- +/* Profile input vertex shader. */
- +gceSTATUS
- +gcoPROFILER_ShaderVS(
- + IN gcoHAL Hal,
- + IN gctPOINTER Vs
- + );
- +
- +/* Profile input fragment shader. */
- +gceSTATUS
- +gcoPROFILER_ShaderFS(
- + IN gcoHAL Hal,
- + IN gctPOINTER Fs
- + );
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* __gc_hal_profiler_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_raster.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_raster.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_raster.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_raster.h 2015-03-08 14:27:37.649684500 -0500
- @@ -0,0 +1,1010 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_raster_h_
- +#define __gc_hal_raster_h_
- +
- +#include "gc_hal_enum.h"
- +#include "gc_hal_types.h"
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +/******************************************************************************\
- +****************************** Object Declarations *****************************
- +\******************************************************************************/
- +
- +typedef struct _gcoBRUSH * gcoBRUSH;
- +typedef struct _gcoBRUSH_CACHE * gcoBRUSH_CACHE;
- +
- +/******************************************************************************\
- +******************************** gcoBRUSH Object *******************************
- +\******************************************************************************/
- +
- +/* Create a new solid color gcoBRUSH object. */
- +gceSTATUS
- +gcoBRUSH_ConstructSingleColor(
- + IN gcoHAL Hal,
- + IN gctUINT32 ColorConvert,
- + IN gctUINT32 Color,
- + IN gctUINT64 Mask,
- + gcoBRUSH * Brush
- + );
- +
- +/* Create a new monochrome gcoBRUSH object. */
- +gceSTATUS
- +gcoBRUSH_ConstructMonochrome(
- + IN gcoHAL Hal,
- + IN gctUINT32 OriginX,
- + IN gctUINT32 OriginY,
- + IN gctUINT32 ColorConvert,
- + IN gctUINT32 FgColor,
- + IN gctUINT32 BgColor,
- + IN gctUINT64 Bits,
- + IN gctUINT64 Mask,
- + gcoBRUSH * Brush
- + );
- +
- +/* Create a color gcoBRUSH object. */
- +gceSTATUS
- +gcoBRUSH_ConstructColor(
- + IN gcoHAL Hal,
- + IN gctUINT32 OriginX,
- + IN gctUINT32 OriginY,
- + IN gctPOINTER Address,
- + IN gceSURF_FORMAT Format,
- + IN gctUINT64 Mask,
- + gcoBRUSH * Brush
- + );
- +
- +/* Destroy an gcoBRUSH object. */
- +gceSTATUS
- +gcoBRUSH_Destroy(
- + IN gcoBRUSH Brush
- + );
- +
- +/******************************************************************************\
- +******************************** gcoSURF Object *******************************
- +\******************************************************************************/
- +
- +/* Set cipping rectangle. */
- +gceSTATUS
- +gcoSURF_SetClipping(
- + IN gcoSURF Surface
- + );
- +
- +/* Clear one or more rectangular areas. */
- +gceSTATUS
- +gcoSURF_Clear2D(
- + IN gcoSURF DestSurface,
- + IN gctUINT32 RectCount,
- + IN gcsRECT_PTR DestRect,
- + IN gctUINT32 LoColor,
- + IN gctUINT32 HiColor
- + );
- +
- +/* Draw one or more Bresenham lines. */
- +gceSTATUS
- +gcoSURF_Line(
- + IN gcoSURF Surface,
- + IN gctUINT32 LineCount,
- + IN gcsRECT_PTR Position,
- + IN gcoBRUSH Brush,
- + IN gctUINT8 FgRop,
- + IN gctUINT8 BgRop
- + );
- +
- +/* Generic rectangular blit. */
- +gceSTATUS
- +gcoSURF_Blit(
- + IN OPTIONAL gcoSURF SrcSurface,
- + IN gcoSURF DestSurface,
- + IN gctUINT32 RectCount,
- + IN OPTIONAL gcsRECT_PTR SrcRect,
- + IN gcsRECT_PTR DestRect,
- + IN OPTIONAL gcoBRUSH Brush,
- + IN gctUINT8 FgRop,
- + IN gctUINT8 BgRop,
- + IN OPTIONAL gceSURF_TRANSPARENCY Transparency,
- + IN OPTIONAL gctUINT32 TransparencyColor,
- + IN OPTIONAL gctPOINTER Mask,
- + IN OPTIONAL gceSURF_MONOPACK MaskPack
- + );
- +
- +/* Monochrome blit. */
- +gceSTATUS
- +gcoSURF_MonoBlit(
- + IN gcoSURF DestSurface,
- + IN gctPOINTER Source,
- + IN gceSURF_MONOPACK SourcePack,
- + IN gcsPOINT_PTR SourceSize,
- + IN gcsPOINT_PTR SourceOrigin,
- + IN gcsRECT_PTR DestRect,
- + IN OPTIONAL gcoBRUSH Brush,
- + IN gctUINT8 FgRop,
- + IN gctUINT8 BgRop,
- + IN gctBOOL ColorConvert,
- + IN gctUINT8 MonoTransparency,
- + IN gceSURF_TRANSPARENCY Transparency,
- + IN gctUINT32 FgColor,
- + IN gctUINT32 BgColor
- + );
- +
- +/* Filter blit. */
- +gceSTATUS
- +gcoSURF_FilterBlit(
- + IN gcoSURF SrcSurface,
- + IN gcoSURF DestSurface,
- + IN gcsRECT_PTR SrcRect,
- + IN gcsRECT_PTR DestRect,
- + IN gcsRECT_PTR DestSubRect
- + );
- +
- +/* Enable alpha blending engine in the hardware and disengage the ROP engine. */
- +gceSTATUS
- +gcoSURF_EnableAlphaBlend(
- + IN gcoSURF Surface,
- + IN gctUINT8 SrcGlobalAlphaValue,
- + IN gctUINT8 DstGlobalAlphaValue,
- + IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
- + IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
- + IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
- + IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
- + IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
- + IN gceSURF_BLEND_FACTOR_MODE DstFactorMode,
- + IN gceSURF_PIXEL_COLOR_MODE SrcColorMode,
- + IN gceSURF_PIXEL_COLOR_MODE DstColorMode
- + );
- +
- +/* Disable alpha blending engine in the hardware and engage the ROP engine. */
- +gceSTATUS
- +gcoSURF_DisableAlphaBlend(
- + IN gcoSURF Surface
- + );
- +
- +/* Copy a rectangular area with format conversion. */
- +gceSTATUS
- +gcoSURF_CopyPixels(
- + IN gcoSURF Source,
- + IN gcoSURF Target,
- + IN gctINT SourceX,
- + IN gctINT SourceY,
- + IN gctINT TargetX,
- + IN gctINT TargetY,
- + IN gctINT Width,
- + IN gctINT Height
- + );
- +
- +/* Read surface pixel. */
- +gceSTATUS
- +gcoSURF_ReadPixel(
- + IN gcoSURF Surface,
- + IN gctPOINTER Memory,
- + IN gctINT X,
- + IN gctINT Y,
- + IN gceSURF_FORMAT Format,
- + OUT gctPOINTER PixelValue
- + );
- +
- +/* Write surface pixel. */
- +gceSTATUS
- +gcoSURF_WritePixel(
- + IN gcoSURF Surface,
- + IN gctPOINTER Memory,
- + IN gctINT X,
- + IN gctINT Y,
- + IN gceSURF_FORMAT Format,
- + IN gctPOINTER PixelValue
- + );
- +
- +gceSTATUS
- +gcoSURF_SetDither(
- + IN gcoSURF Surface,
- + IN gctBOOL Dither
- + );
- +/******************************************************************************\
- +********************************** gco2D Object *********************************
- +\******************************************************************************/
- +
- +/* Construct a new gco2D object. */
- +gceSTATUS
- +gco2D_Construct(
- + IN gcoHAL Hal,
- + OUT gco2D * Hardware
- + );
- +
- +/* Destroy an gco2D object. */
- +gceSTATUS
- +gco2D_Destroy(
- + IN gco2D Hardware
- + );
- +
- +/* Sets the maximum number of brushes in the brush cache. */
- +gceSTATUS
- +gco2D_SetBrushLimit(
- + IN gco2D Hardware,
- + IN gctUINT MaxCount
- + );
- +
- +/* Flush the brush. */
- +gceSTATUS
- +gco2D_FlushBrush(
- + IN gco2D Engine,
- + IN gcoBRUSH Brush,
- + IN gceSURF_FORMAT Format
- + );
- +
- +/* Program the specified solid color brush. */
- +gceSTATUS
- +gco2D_LoadSolidBrush(
- + IN gco2D Engine,
- + IN gceSURF_FORMAT Format,
- + IN gctUINT32 ColorConvert,
- + IN gctUINT32 Color,
- + IN gctUINT64 Mask
- + );
- +
- +gceSTATUS
- +gco2D_LoadMonochromeBrush(
- + IN gco2D Engine,
- + IN gctUINT32 OriginX,
- + IN gctUINT32 OriginY,
- + IN gctUINT32 ColorConvert,
- + IN gctUINT32 FgColor,
- + IN gctUINT32 BgColor,
- + IN gctUINT64 Bits,
- + IN gctUINT64 Mask
- + );
- +
- +gceSTATUS
- +gco2D_LoadColorBrush(
- + IN gco2D Engine,
- + IN gctUINT32 OriginX,
- + IN gctUINT32 OriginY,
- + IN gctUINT32 Address,
- + IN gceSURF_FORMAT Format,
- + IN gctUINT64 Mask
- + );
- +
- +/* Configure monochrome source. */
- +gceSTATUS
- +gco2D_SetMonochromeSource(
- + IN gco2D Engine,
- + IN gctBOOL ColorConvert,
- + IN gctUINT8 MonoTransparency,
- + IN gceSURF_MONOPACK DataPack,
- + IN gctBOOL CoordRelative,
- + IN gceSURF_TRANSPARENCY Transparency,
- + IN gctUINT32 FgColor,
- + IN gctUINT32 BgColor
- + );
- +
- +/* Configure color source. */
- +gceSTATUS
- +gco2D_SetColorSource(
- + IN gco2D Engine,
- + IN gctUINT32 Address,
- + IN gctUINT32 Stride,
- + IN gceSURF_FORMAT Format,
- + IN gceSURF_ROTATION Rotation,
- + IN gctUINT32 SurfaceWidth,
- + IN gctBOOL CoordRelative,
- + IN gceSURF_TRANSPARENCY Transparency,
- + IN gctUINT32 TransparencyColor
- + );
- +
- +/* Configure color source extension for full rotation. */
- +gceSTATUS
- +gco2D_SetColorSourceEx(
- + IN gco2D Engine,
- + IN gctUINT32 Address,
- + IN gctUINT32 Stride,
- + IN gceSURF_FORMAT Format,
- + IN gceSURF_ROTATION Rotation,
- + IN gctUINT32 SurfaceWidth,
- + IN gctUINT32 SurfaceHeight,
- + IN gctBOOL CoordRelative,
- + IN gceSURF_TRANSPARENCY Transparency,
- + IN gctUINT32 TransparencyColor
- + );
- +
- +/* Configure color source. */
- +gceSTATUS
- +gco2D_SetColorSourceAdvanced(
- + IN gco2D Engine,
- + IN gctUINT32 Address,
- + IN gctUINT32 Stride,
- + IN gceSURF_FORMAT Format,
- + IN gceSURF_ROTATION Rotation,
- + IN gctUINT32 SurfaceWidth,
- + IN gctUINT32 SurfaceHeight,
- + IN gctBOOL CoordRelative
- + );
- +
- +gceSTATUS
- +gco2D_SetColorSourceN(
- + IN gco2D Engine,
- + IN gctUINT32 Address,
- + IN gctUINT32 Stride,
- + IN gceSURF_FORMAT Format,
- + IN gceSURF_ROTATION Rotation,
- + IN gctUINT32 SurfaceWidth,
- + IN gctUINT32 SurfaceHeight,
- + IN gctUINT32 SurfaceNumber
- + );
- +
- +/* Configure masked color source. */
- +gceSTATUS
- +gco2D_SetMaskedSource(
- + IN gco2D Engine,
- + IN gctUINT32 Address,
- + IN gctUINT32 Stride,
- + IN gceSURF_FORMAT Format,
- + IN gctBOOL CoordRelative,
- + IN gceSURF_MONOPACK MaskPack
- + );
- +
- +/* Configure masked color source extension for full rotation. */
- +gceSTATUS
- +gco2D_SetMaskedSourceEx(
- + IN gco2D Engine,
- + IN gctUINT32 Address,
- + IN gctUINT32 Stride,
- + IN gceSURF_FORMAT Format,
- + IN gctBOOL CoordRelative,
- + IN gceSURF_MONOPACK MaskPack,
- + IN gceSURF_ROTATION Rotation,
- + IN gctUINT32 SurfaceWidth,
- + IN gctUINT32 SurfaceHeight
- + );
- +
- +/* Setup the source rectangle. */
- +gceSTATUS
- +gco2D_SetSource(
- + IN gco2D Engine,
- + IN gcsRECT_PTR SrcRect
- + );
- +
- +/* Set clipping rectangle. */
- +gceSTATUS
- +gco2D_SetClipping(
- + IN gco2D Engine,
- + IN gcsRECT_PTR Rect
- + );
- +
- +/* Configure destination. */
- +gceSTATUS
- +gco2D_SetTarget(
- + IN gco2D Engine,
- + IN gctUINT32 Address,
- + IN gctUINT32 Stride,
- + IN gceSURF_ROTATION Rotation,
- + IN gctUINT32 SurfaceWidth
- + );
- +
- +/* Configure destination extension for full rotation. */
- +gceSTATUS
- +gco2D_SetTargetEx(
- + IN gco2D Engine,
- + IN gctUINT32 Address,
- + IN gctUINT32 Stride,
- + IN gceSURF_ROTATION Rotation,
- + IN gctUINT32 SurfaceWidth,
- + IN gctUINT32 SurfaceHeight
- + );
- +
- +/* Calculate and program the stretch factors. */
- +gceSTATUS
- +gco2D_CalcStretchFactor(
- + IN gco2D Engine,
- + IN gctINT32 SrcSize,
- + IN gctINT32 DestSize,
- + OUT gctUINT32_PTR Factor
- + );
- +
- +gceSTATUS
- +gco2D_SetStretchFactors(
- + IN gco2D Engine,
- + IN gctUINT32 HorFactor,
- + IN gctUINT32 VerFactor
- + );
- +
- +/* Calculate and program the stretch factors based on the rectangles. */
- +gceSTATUS
- +gco2D_SetStretchRectFactors(
- + IN gco2D Engine,
- + IN gcsRECT_PTR SrcRect,
- + IN gcsRECT_PTR DestRect
- + );
- +
- +/* Create a new solid color gcoBRUSH object. */
- +gceSTATUS
- +gco2D_ConstructSingleColorBrush(
- + IN gco2D Engine,
- + IN gctUINT32 ColorConvert,
- + IN gctUINT32 Color,
- + IN gctUINT64 Mask,
- + gcoBRUSH * Brush
- + );
- +
- +/* Create a new monochrome gcoBRUSH object. */
- +gceSTATUS
- +gco2D_ConstructMonochromeBrush(
- + IN gco2D Engine,
- + IN gctUINT32 OriginX,
- + IN gctUINT32 OriginY,
- + IN gctUINT32 ColorConvert,
- + IN gctUINT32 FgColor,
- + IN gctUINT32 BgColor,
- + IN gctUINT64 Bits,
- + IN gctUINT64 Mask,
- + gcoBRUSH * Brush
- + );
- +
- +/* Create a color gcoBRUSH object. */
- +gceSTATUS
- +gco2D_ConstructColorBrush(
- + IN gco2D Engine,
- + IN gctUINT32 OriginX,
- + IN gctUINT32 OriginY,
- + IN gctPOINTER Address,
- + IN gceSURF_FORMAT Format,
- + IN gctUINT64 Mask,
- + gcoBRUSH * Brush
- + );
- +
- +/* Clear one or more rectangular areas. */
- +gceSTATUS
- +gco2D_Clear(
- + IN gco2D Engine,
- + IN gctUINT32 RectCount,
- + IN gcsRECT_PTR Rect,
- + IN gctUINT32 Color32,
- + IN gctUINT8 FgRop,
- + IN gctUINT8 BgRop,
- + IN gceSURF_FORMAT DestFormat
- + );
- +
- +/* Draw one or more Bresenham lines. */
- +gceSTATUS
- +gco2D_Line(
- + IN gco2D Engine,
- + IN gctUINT32 LineCount,
- + IN gcsRECT_PTR Position,
- + IN gcoBRUSH Brush,
- + IN gctUINT8 FgRop,
- + IN gctUINT8 BgRop,
- + IN gceSURF_FORMAT DestFormat
- + );
- +
- +/* Draw one or more Bresenham lines based on the 32-bit color. */
- +gceSTATUS
- +gco2D_ColorLine(
- + IN gco2D Engine,
- + IN gctUINT32 LineCount,
- + IN gcsRECT_PTR Position,
- + IN gctUINT32 Color32,
- + IN gctUINT8 FgRop,
- + IN gctUINT8 BgRop,
- + IN gceSURF_FORMAT DestFormat
- + );
- +
- +/* Generic blit. */
- +gceSTATUS
- +gco2D_Blit(
- + IN gco2D Engine,
- + IN gctUINT32 RectCount,
- + IN gcsRECT_PTR Rect,
- + IN gctUINT8 FgRop,
- + IN gctUINT8 BgRop,
- + IN gceSURF_FORMAT DestFormat
- + );
- +
- +gceSTATUS
- +gco2D_Blend(
- + IN gco2D Engine,
- + IN gctUINT32 SrcCount,
- + IN gctUINT32 RectCount,
- + IN gcsRECT_PTR Rect,
- + IN gctUINT8 FgRop,
- + IN gctUINT8 BgRop,
- + IN gceSURF_FORMAT DestFormat
- + );
- +
- +/* Batch blit. */
- +gceSTATUS
- +gco2D_BatchBlit(
- + IN gco2D Engine,
- + IN gctUINT32 RectCount,
- + IN gcsRECT_PTR SrcRect,
- + IN gcsRECT_PTR DestRect,
- + IN gctUINT8 FgRop,
- + IN gctUINT8 BgRop,
- + IN gceSURF_FORMAT DestFormat
- + );
- +
- +/* Stretch blit. */
- +gceSTATUS
- +gco2D_StretchBlit(
- + IN gco2D Engine,
- + IN gctUINT32 RectCount,
- + IN gcsRECT_PTR Rect,
- + IN gctUINT8 FgRop,
- + IN gctUINT8 BgRop,
- + IN gceSURF_FORMAT DestFormat
- + );
- +
- +/* Monochrome blit. */
- +gceSTATUS
- +gco2D_MonoBlit(
- + IN gco2D Engine,
- + IN gctPOINTER StreamBits,
- + IN gcsPOINT_PTR StreamSize,
- + IN gcsRECT_PTR StreamRect,
- + IN gceSURF_MONOPACK SrcStreamPack,
- + IN gceSURF_MONOPACK DestStreamPack,
- + IN gcsRECT_PTR DestRect,
- + IN gctUINT32 FgRop,
- + IN gctUINT32 BgRop,
- + IN gceSURF_FORMAT DestFormat
- + );
- +
- +gceSTATUS
- +gco2D_MonoBlitEx(
- + IN gco2D Engine,
- + IN gctPOINTER StreamBits,
- + IN gctINT32 StreamStride,
- + IN gctINT32 StreamWidth,
- + IN gctINT32 StreamHeight,
- + IN gctINT32 StreamX,
- + IN gctINT32 StreamY,
- + IN gctUINT32 FgColor,
- + IN gctUINT32 BgColor,
- + IN gcsRECT_PTR SrcRect,
- + IN gcsRECT_PTR DstRect,
- + IN gctUINT8 FgRop,
- + IN gctUINT8 BgRop
- + );
- +
- +/* Set kernel size. */
- +gceSTATUS
- +gco2D_SetKernelSize(
- + IN gco2D Engine,
- + IN gctUINT8 HorKernelSize,
- + IN gctUINT8 VerKernelSize
- + );
- +
- +/* Set filter type. */
- +gceSTATUS
- +gco2D_SetFilterType(
- + IN gco2D Engine,
- + IN gceFILTER_TYPE FilterType
- + );
- +
- +/* Set the filter kernel by user. */
- +gceSTATUS
- +gco2D_SetUserFilterKernel(
- + IN gco2D Engine,
- + IN gceFILTER_PASS_TYPE PassType,
- + IN gctUINT16_PTR KernelArray
- + );
- +
- +/* Select the pass(es) to be done for user defined filter. */
- +gceSTATUS
- +gco2D_EnableUserFilterPasses(
- + IN gco2D Engine,
- + IN gctBOOL HorPass,
- + IN gctBOOL VerPass
- + );
- +
- +/* Frees the temporary buffer allocated by filter blit operation. */
- +gceSTATUS
- +gco2D_FreeFilterBuffer(
- + IN gco2D Engine
- + );
- +
- +/* Filter blit. */
- +gceSTATUS
- +gco2D_FilterBlit(
- + IN gco2D Engine,
- + IN gctUINT32 SrcAddress,
- + IN gctUINT SrcStride,
- + IN gctUINT32 SrcUAddress,
- + IN gctUINT SrcUStride,
- + IN gctUINT32 SrcVAddress,
- + IN gctUINT SrcVStride,
- + IN gceSURF_FORMAT SrcFormat,
- + IN gceSURF_ROTATION SrcRotation,
- + IN gctUINT32 SrcSurfaceWidth,
- + IN gcsRECT_PTR SrcRect,
- + IN gctUINT32 DestAddress,
- + IN gctUINT DestStride,
- + IN gceSURF_FORMAT DestFormat,
- + IN gceSURF_ROTATION DestRotation,
- + IN gctUINT32 DestSurfaceWidth,
- + IN gcsRECT_PTR DestRect,
- + IN gcsRECT_PTR DestSubRect
- + );
- +
- +/* Filter blit extension for full rotation. */
- +gceSTATUS
- +gco2D_FilterBlitEx(
- + IN gco2D Engine,
- + IN gctUINT32 SrcAddress,
- + IN gctUINT SrcStride,
- + IN gctUINT32 SrcUAddress,
- + IN gctUINT SrcUStride,
- + IN gctUINT32 SrcVAddress,
- + IN gctUINT SrcVStride,
- + IN gceSURF_FORMAT SrcFormat,
- + IN gceSURF_ROTATION SrcRotation,
- + IN gctUINT32 SrcSurfaceWidth,
- + IN gctUINT32 SrcSurfaceHeight,
- + IN gcsRECT_PTR SrcRect,
- + IN gctUINT32 DestAddress,
- + IN gctUINT DestStride,
- + IN gceSURF_FORMAT DestFormat,
- + IN gceSURF_ROTATION DestRotation,
- + IN gctUINT32 DestSurfaceWidth,
- + IN gctUINT32 DestSurfaceHeight,
- + IN gcsRECT_PTR DestRect,
- + IN gcsRECT_PTR DestSubRect
- + );
- +
- +gceSTATUS
- +gco2D_FilterBlitEx2(
- + IN gco2D Engine,
- + IN gctUINT32_PTR SrcAddresses,
- + IN gctUINT32 SrcAddressNum,
- + IN gctUINT32_PTR SrcStrides,
- + IN gctUINT32 SrcStrideNum,
- + IN gceTILING SrcTiling,
- + IN gceSURF_FORMAT SrcFormat,
- + IN gceSURF_ROTATION SrcRotation,
- + IN gctUINT32 SrcSurfaceWidth,
- + IN gctUINT32 SrcSurfaceHeight,
- + IN gcsRECT_PTR SrcRect,
- + IN gctUINT32_PTR DestAddresses,
- + IN gctUINT32 DestAddressNum,
- + IN gctUINT32_PTR DestStrides,
- + IN gctUINT32 DestStrideNum,
- + IN gceTILING DestTiling,
- + IN gceSURF_FORMAT DestFormat,
- + IN gceSURF_ROTATION DestRotation,
- + IN gctUINT32 DestSurfaceWidth,
- + IN gctUINT32 DestSurfaceHeight,
- + IN gcsRECT_PTR DestRect,
- + IN gcsRECT_PTR DestSubRect
- + );
- +
- +/* Enable alpha blending engine in the hardware and disengage the ROP engine. */
- +gceSTATUS
- +gco2D_EnableAlphaBlend(
- + IN gco2D Engine,
- + IN gctUINT8 SrcGlobalAlphaValue,
- + IN gctUINT8 DstGlobalAlphaValue,
- + IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
- + IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
- + IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
- + IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
- + IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
- + IN gceSURF_BLEND_FACTOR_MODE DstFactorMode,
- + IN gceSURF_PIXEL_COLOR_MODE SrcColorMode,
- + IN gceSURF_PIXEL_COLOR_MODE DstColorMode
- + );
- +
- +/* Enable alpha blending engine in the hardware. */
- +gceSTATUS
- +gco2D_EnableAlphaBlendAdvanced(
- + IN gco2D Engine,
- + IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
- + IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
- + IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
- + IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
- + IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
- + IN gceSURF_BLEND_FACTOR_MODE DstFactorMode
- + );
- +
- +/* Enable alpha blending engine with Porter Duff rule. */
- +gceSTATUS
- +gco2D_SetPorterDuffBlending(
- + IN gco2D Engine,
- + IN gce2D_PORTER_DUFF_RULE Rule
- + );
- +
- +/* Disable alpha blending engine in the hardware and engage the ROP engine. */
- +gceSTATUS
- +gco2D_DisableAlphaBlend(
- + IN gco2D Engine
- + );
- +
- +/* Retrieve the maximum number of 32-bit data chunks for a single DE command. */
- +gctUINT32
- +gco2D_GetMaximumDataCount(
- + void
- + );
- +
- +/* Retrieve the maximum number of rectangles, that can be passed in a single DE command. */
- +gctUINT32
- +gco2D_GetMaximumRectCount(
- + void
- + );
- +
- +/* Returns the pixel alignment of the surface. */
- +gceSTATUS
- +gco2D_GetPixelAlignment(
- + gceSURF_FORMAT Format,
- + gcsPOINT_PTR Alignment
- + );
- +
- +/* Retrieve monochrome stream pack size. */
- +gceSTATUS
- +gco2D_GetPackSize(
- + IN gceSURF_MONOPACK StreamPack,
- + OUT gctUINT32 * PackWidth,
- + OUT gctUINT32 * PackHeight
- + );
- +
- +/* Flush the 2D pipeline. */
- +gceSTATUS
- +gco2D_Flush(
- + IN gco2D Engine
- + );
- +
- +/* Load 256-entry color table for INDEX8 source surfaces. */
- +gceSTATUS
- +gco2D_LoadPalette(
- + IN gco2D Engine,
- + IN gctUINT FirstIndex,
- + IN gctUINT IndexCount,
- + IN gctPOINTER ColorTable,
- + IN gctBOOL ColorConvert
- + );
- +
- +/* Enable/disable 2D BitBlt mirrorring. */
- +gceSTATUS
- +gco2D_SetBitBlitMirror(
- + IN gco2D Engine,
- + IN gctBOOL HorizontalMirror,
- + IN gctBOOL VerticalMirror
- + );
- +
- +/*
- + * Set the transparency for source, destination and pattern.
- + * It also enable or disable the DFB color key mode.
- + */
- +gceSTATUS
- +gco2D_SetTransparencyAdvancedEx(
- + IN gco2D Engine,
- + IN gce2D_TRANSPARENCY SrcTransparency,
- + IN gce2D_TRANSPARENCY DstTransparency,
- + IN gce2D_TRANSPARENCY PatTransparency,
- + IN gctBOOL EnableDFBColorKeyMode
- + );
- +
- +/* Set the transparency for source, destination and pattern. */
- +gceSTATUS
- +gco2D_SetTransparencyAdvanced(
- + IN gco2D Engine,
- + IN gce2D_TRANSPARENCY SrcTransparency,
- + IN gce2D_TRANSPARENCY DstTransparency,
- + IN gce2D_TRANSPARENCY PatTransparency
- + );
- +
- +/* Set the source color key. */
- +gceSTATUS
- +gco2D_SetSourceColorKeyAdvanced(
- + IN gco2D Engine,
- + IN gctUINT32 ColorKey
- + );
- +
- +/* Set the source color key range. */
- +gceSTATUS
- +gco2D_SetSourceColorKeyRangeAdvanced(
- + IN gco2D Engine,
- + IN gctUINT32 ColorKeyLow,
- + IN gctUINT32 ColorKeyHigh
- + );
- +
- +/* Set the target color key. */
- +gceSTATUS
- +gco2D_SetTargetColorKeyAdvanced(
- + IN gco2D Engine,
- + IN gctUINT32 ColorKey
- + );
- +
- +/* Set the target color key range. */
- +gceSTATUS
- +gco2D_SetTargetColorKeyRangeAdvanced(
- + IN gco2D Engine,
- + IN gctUINT32 ColorKeyLow,
- + IN gctUINT32 ColorKeyHigh
- + );
- +
- +/* Set the YUV color space mode. */
- +gceSTATUS
- +gco2D_SetYUVColorMode(
- + IN gco2D Engine,
- + IN gce2D_YUV_COLOR_MODE Mode
- + );
- +
- +/* Setup the source global color value in ARGB8 format. */
- +gceSTATUS gco2D_SetSourceGlobalColorAdvanced(
- + IN gco2D Engine,
- + IN gctUINT32 Color32
- + );
- +
- +/* Setup the target global color value in ARGB8 format. */
- +gceSTATUS gco2D_SetTargetGlobalColorAdvanced(
- + IN gco2D Engine,
- + IN gctUINT32 Color32
- + );
- +
- +/* Setup the source and target pixel multiply modes. */
- +gceSTATUS
- +gco2D_SetPixelMultiplyModeAdvanced(
- + IN gco2D Engine,
- + IN gce2D_PIXEL_COLOR_MULTIPLY_MODE SrcPremultiplySrcAlpha,
- + IN gce2D_PIXEL_COLOR_MULTIPLY_MODE DstPremultiplyDstAlpha,
- + IN gce2D_GLOBAL_COLOR_MULTIPLY_MODE SrcPremultiplyGlobalMode,
- + IN gce2D_PIXEL_COLOR_MULTIPLY_MODE DstDemultiplyDstAlpha
- + );
- +
- +/* Set the GPU clock cycles after which the idle engine will keep auto-flushing. */
- +gceSTATUS
- +gco2D_SetAutoFlushCycles(
- + IN gco2D Engine,
- + IN gctUINT32 Cycles
- + );
- +
- +#if VIVANTE_PROFILER
- +/* Read the profile registers available in the 2D engine and sets them in the profile.
- + The function will also reset the pixelsRendered counter every time.
- +*/
- +gceSTATUS
- +gco2D_ProfileEngine(
- + IN gco2D Engine,
- + OPTIONAL gcs2D_PROFILE_PTR Profile
- + );
- +#endif
- +
- +/* Enable or disable 2D dithering. */
- +gceSTATUS
- +gco2D_EnableDither(
- + IN gco2D Engine,
- + IN gctBOOL Enable
- + );
- +
- +gceSTATUS
- +gco2D_SetGenericSource(
- + IN gco2D Engine,
- + IN gctUINT32_PTR Addresses,
- + IN gctUINT32 AddressNum,
- + IN gctUINT32_PTR Strides,
- + IN gctUINT32 StrideNum,
- + IN gceTILING Tiling,
- + IN gceSURF_FORMAT Format,
- + IN gceSURF_ROTATION Rotation,
- + IN gctUINT32 SurfaceWidth,
- + IN gctUINT32 SurfaceHeight
- +);
- +
- +gceSTATUS
- +gco2D_SetGenericTarget(
- + IN gco2D Engine,
- + IN gctUINT32_PTR Addresses,
- + IN gctUINT32 AddressNum,
- + IN gctUINT32_PTR Strides,
- + IN gctUINT32 StrideNum,
- + IN gceTILING Tiling,
- + IN gceSURF_FORMAT Format,
- + IN gceSURF_ROTATION Rotation,
- + IN gctUINT32 SurfaceWidth,
- + IN gctUINT32 SurfaceHeight
- +);
- +
- +gceSTATUS
- +gco2D_SetCurrentSourceIndex(
- + IN gco2D Engine,
- + IN gctUINT32 SrcIndex
- + );
- +
- +gceSTATUS
- +gco2D_MultiSourceBlit(
- + IN gco2D Engine,
- + IN gctUINT32 SourceMask,
- + IN gcsRECT_PTR DestRect,
- + IN gctUINT32 RectCount
- + );
- +
- +gceSTATUS
- +gco2D_SetROP(
- + IN gco2D Engine,
- + IN gctUINT8 FgRop,
- + IN gctUINT8 BgRop
- + );
- +
- +gceSTATUS
- +gco2D_SetGdiStretchMode(
- + IN gco2D Engine,
- + IN gctBOOL Enable
- + );
- +
- +gceSTATUS
- +gco2D_SetSourceTileStatus(
- + IN gco2D Engine,
- + IN gce2D_TILE_STATUS_CONFIG TSControl,
- + IN gceSURF_FORMAT CompressedFormat,
- + IN gctUINT32 ClearValue,
- + IN gctUINT32 GpuAddress
- + );
- +
- +gceSTATUS
- +gco2D_SetTargetTileStatus(
- + IN gco2D Engine,
- + IN gce2D_TILE_STATUS_CONFIG TileStatusConfig,
- + IN gceSURF_FORMAT CompressedFormat,
- + IN gctUINT32 ClearValue,
- + IN gctUINT32 GpuAddress
- + );
- +
- +gceSTATUS
- +gco2D_QueryU32(
- + IN gco2D Engine,
- + IN gce2D_QUERY Item,
- + OUT gctUINT32_PTR Value
- + );
- +
- +gceSTATUS
- +gco2D_SetStateU32(
- + IN gco2D Engine,
- + IN gce2D_STATE State,
- + IN gctUINT32 Value
- + );
- +
- +gceSTATUS
- +gco2D_SetStateArrayI32(
- + IN gco2D Engine,
- + IN gce2D_STATE State,
- + IN gctINT32_PTR Array,
- + IN gctINT32 ArraySize
- + );
- +
- +gceSTATUS
- +gco2D_SetStateArrayU32(
- + IN gco2D Engine,
- + IN gce2D_STATE State,
- + IN gctUINT32_PTR Array,
- + IN gctINT32 ArraySize
- + );
- +
- +gceSTATUS
- +gco2D_SetTargetRect(
- + IN gco2D Engine,
- + IN gcsRECT_PTR Rect
- + );
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* __gc_hal_raster_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_rename.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_rename.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_rename.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_rename.h 2015-03-08 14:27:37.649684500 -0500
- @@ -0,0 +1,248 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_rename_h_
- +#define __gc_hal_rename_h_
- +
- +
- +#if defined(_HAL2D_APPENDIX)
- +
- +#define _HAL2D_RENAME_2(api, appendix) api ## appendix
- +#define _HAL2D_RENAME_1(api, appendix) _HAL2D_RENAME_2(api, appendix)
- +#define gcmHAL2D(api) _HAL2D_RENAME_1(api, _HAL2D_APPENDIX)
- +
- +
- +#define gckOS_Construct gcmHAL2D(gckOS_Construct)
- +#define gckOS_Destroy gcmHAL2D(gckOS_Destroy)
- +#define gckOS_QueryVideoMemory gcmHAL2D(gckOS_QueryVideoMemory)
- +#define gckOS_Allocate gcmHAL2D(gckOS_Allocate)
- +#define gckOS_Free gcmHAL2D(gckOS_Free)
- +#define gckOS_AllocateMemory gcmHAL2D(gckOS_AllocateMemory)
- +#define gckOS_FreeMemory gcmHAL2D(gckOS_FreeMemory)
- +#define gckOS_AllocatePagedMemory gcmHAL2D(gckOS_AllocatePagedMemory)
- +#define gckOS_AllocatePagedMemoryEx gcmHAL2D(gckOS_AllocatePagedMemoryEx)
- +#define gckOS_LockPages gcmHAL2D(gckOS_LockPages)
- +#define gckOS_MapPages gcmHAL2D(gckOS_MapPages)
- +#define gckOS_UnlockPages gcmHAL2D(gckOS_UnlockPages)
- +#define gckOS_FreePagedMemory gcmHAL2D(gckOS_FreePagedMemory)
- +#define gckOS_AllocateNonPagedMemory gcmHAL2D(gckOS_AllocateNonPagedMemory)
- +#define gckOS_FreeNonPagedMemory gcmHAL2D(gckOS_FreeNonPagedMemory)
- +#define gckOS_AllocateContiguous gcmHAL2D(gckOS_AllocateContiguous)
- +#define gckOS_FreeContiguous gcmHAL2D(gckOS_FreeContiguous)
- +#define gckOS_GetPageSize gcmHAL2D(gckOS_GetPageSize)
- +#define gckOS_GetPhysicalAddress gcmHAL2D(gckOS_GetPhysicalAddress)
- +#define gckOS_GetPhysicalAddressProcess gcmHAL2D(gckOS_GetPhysicalAddressProcess)
- +#define gckOS_MapPhysical gcmHAL2D(gckOS_MapPhysical)
- +#define gckOS_UnmapPhysical gcmHAL2D(gckOS_UnmapPhysical)
- +#define gckOS_ReadRegister gcmHAL2D(gckOS_ReadRegister)
- +#define gckOS_WriteRegister gcmHAL2D(gckOS_WriteRegister)
- +#define gckOS_WriteMemory gcmHAL2D(gckOS_WriteMemory)
- +#define gckOS_MapMemory gcmHAL2D(gckOS_MapMemory)
- +#define gckOS_UnmapMemory gcmHAL2D(gckOS_UnmapMemory)
- +#define gckOS_UnmapMemoryEx gcmHAL2D(gckOS_UnmapMemoryEx)
- +#define gckOS_CreateMutex gcmHAL2D(gckOS_CreateMutex)
- +#define gckOS_DeleteMutex gcmHAL2D(gckOS_DeleteMutex)
- +#define gckOS_AcquireMutex gcmHAL2D(gckOS_AcquireMutex)
- +#define gckOS_ReleaseMutex gcmHAL2D(gckOS_ReleaseMutex)
- +#define gckOS_AtomicExchange gcmHAL2D(gckOS_AtomicExchange)
- +#define gckOS_AtomicExchangePtr gcmHAL2D(gckOS_AtomicExchangePtr)
- +#define gckOS_AtomConstruct gcmHAL2D(gckOS_AtomConstruct)
- +#define gckOS_AtomDestroy gcmHAL2D(gckOS_AtomDestroy)
- +#define gckOS_AtomGet gcmHAL2D(gckOS_AtomGet)
- +#define gckOS_AtomIncrement gcmHAL2D(gckOS_AtomIncrement)
- +#define gckOS_AtomDecrement gcmHAL2D(gckOS_AtomDecrement)
- +#define gckOS_Delay gcmHAL2D(gckOS_Delay)
- +#define gckOS_GetTime gcmHAL2D(gckOS_GetTime)
- +#define gckOS_MemoryBarrier gcmHAL2D(gckOS_MemoryBarrier)
- +#define gckOS_MapUserPointer gcmHAL2D(gckOS_MapUserPointer)
- +#define gckOS_UnmapUserPointer gcmHAL2D(gckOS_UnmapUserPointer)
- +#define gckOS_QueryNeedCopy gcmHAL2D(gckOS_QueryNeedCopy)
- +#define gckOS_CopyFromUserData gcmHAL2D(gckOS_CopyFromUserData)
- +#define gckOS_CopyToUserData gcmHAL2D(gckOS_CopyToUserData)
- +#define gckOS_MapUserPhysical gcmHAL2D(gckOS_MapUserPhysical)
- +#define gckOS_SuspendInterrupt gcmHAL2D(gckOS_SuspendInterrupt)
- +#define gckOS_ResumeInterrupt gcmHAL2D(gckOS_ResumeInterrupt)
- +#define gckOS_GetBaseAddress gcmHAL2D(gckOS_GetBaseAddress)
- +#define gckOS_MemCopy gcmHAL2D(gckOS_MemCopy)
- +#define gckOS_ZeroMemory gcmHAL2D(gckOS_ZeroMemory)
- +#define gckOS_DeviceControl gcmHAL2D(gckOS_DeviceControl)
- +#define gckOS_GetProcessID gcmHAL2D(gckOS_GetProcessID)
- +#define gckOS_GetThreadID gcmHAL2D(gckOS_GetThreadID)
- +#define gckOS_CreateSignal gcmHAL2D(gckOS_CreateSignal)
- +#define gckOS_DestroySignal gcmHAL2D(gckOS_DestroySignal)
- +#define gckOS_Signal gcmHAL2D(gckOS_Signal)
- +#define gckOS_WaitSignal gcmHAL2D(gckOS_WaitSignal)
- +#define gckOS_MapSignal gcmHAL2D(gckOS_MapSignal)
- +#define gckOS_MapUserMemory gcmHAL2D(gckOS_MapUserMemory)
- +#define gckOS_UnmapUserMemory gcmHAL2D(gckOS_UnmapUserMemory)
- +#define gckOS_CreateUserSignal gcmHAL2D(gckOS_CreateUserSignal)
- +#define gckOS_DestroyUserSignal gcmHAL2D(gckOS_DestroyUserSignal)
- +#define gckOS_WaitUserSignal gcmHAL2D(gckOS_WaitUserSignal)
- +#define gckOS_SignalUserSignal gcmHAL2D(gckOS_SignalUserSignal)
- +#define gckOS_UserSignal gcmHAL2D(gckOS_UserSignal)
- +#define gckOS_UserSignal gcmHAL2D(gckOS_UserSignal)
- +#define gckOS_CacheClean gcmHAL2D(gckOS_CacheClean)
- +#define gckOS_CacheFlush gcmHAL2D(gckOS_CacheFlush)
- +#define gckOS_SetDebugLevel gcmHAL2D(gckOS_SetDebugLevel)
- +#define gckOS_SetDebugZone gcmHAL2D(gckOS_SetDebugZone)
- +#define gckOS_SetDebugLevelZone gcmHAL2D(gckOS_SetDebugLevelZone)
- +#define gckOS_SetDebugZones gcmHAL2D(gckOS_SetDebugZones)
- +#define gckOS_SetDebugFile gcmHAL2D(gckOS_SetDebugFile)
- +#define gckOS_Broadcast gcmHAL2D(gckOS_Broadcast)
- +#define gckOS_SetGPUPower gcmHAL2D(gckOS_SetGPUPower)
- +#define gckOS_CreateSemaphore gcmHAL2D(gckOS_CreateSemaphore)
- +#define gckOS_DestroySemaphore gcmHAL2D(gckOS_DestroySemaphore)
- +#define gckOS_AcquireSemaphore gcmHAL2D(gckOS_AcquireSemaphore)
- +#define gckOS_ReleaseSemaphore gcmHAL2D(gckOS_ReleaseSemaphore)
- +#define gckHEAP_Construct gcmHAL2D(gckHEAP_Construct)
- +#define gckHEAP_Destroy gcmHAL2D(gckHEAP_Destroy)
- +#define gckHEAP_Allocate gcmHAL2D(gckHEAP_Allocate)
- +#define gckHEAP_Free gcmHAL2D(gckHEAP_Free)
- +#define gckHEAP_ProfileStart gcmHAL2D(gckHEAP_ProfileStart)
- +#define gckHEAP_ProfileEnd gcmHAL2D(gckHEAP_ProfileEnd)
- +#define gckHEAP_Test gcmHAL2D(gckHEAP_Test)
- +#define gckVIDMEM_Construct gcmHAL2D(gckVIDMEM_Construct)
- +#define gckVIDMEM_Destroy gcmHAL2D(gckVIDMEM_Destroy)
- +#define gckVIDMEM_Allocate gcmHAL2D(gckVIDMEM_Allocate)
- +#define gckVIDMEM_AllocateLinear gcmHAL2D(gckVIDMEM_AllocateLinear)
- +#define gckVIDMEM_Free gcmHAL2D(gckVIDMEM_Free)
- +#define gckVIDMEM_Lock gcmHAL2D(gckVIDMEM_Lock)
- +#define gckVIDMEM_Unlock gcmHAL2D(gckVIDMEM_Unlock)
- +#define gckVIDMEM_ConstructVirtual gcmHAL2D(gckVIDMEM_ConstructVirtual)
- +#define gckVIDMEM_DestroyVirtual gcmHAL2D(gckVIDMEM_DestroyVirtual)
- +#define gckKERNEL_Construct gcmHAL2D(gckKERNEL_Construct)
- +#define gckKERNEL_Destroy gcmHAL2D(gckKERNEL_Destroy)
- +#define gckKERNEL_Dispatch gcmHAL2D(gckKERNEL_Dispatch)
- +#define gckKERNEL_QueryVideoMemory gcmHAL2D(gckKERNEL_QueryVideoMemory)
- +#define gckKERNEL_GetVideoMemoryPool gcmHAL2D(gckKERNEL_GetVideoMemoryPool)
- +#define gckKERNEL_MapVideoMemory gcmHAL2D(gckKERNEL_MapVideoMemory)
- +#define gckKERNEL_UnmapVideoMemory gcmHAL2D(gckKERNEL_UnmapVideoMemory)
- +#define gckKERNEL_MapMemory gcmHAL2D(gckKERNEL_MapMemory)
- +#define gckKERNEL_UnmapMemory gcmHAL2D(gckKERNEL_UnmapMemory)
- +#define gckKERNEL_Notify gcmHAL2D(gckKERNEL_Notify)
- +#define gckKERNEL_QuerySettings gcmHAL2D(gckKERNEL_QuerySettings)
- +#define gckKERNEL_Recovery gcmHAL2D(gckKERNEL_Recovery)
- +#define gckKERNEL_OpenUserData gcmHAL2D(gckKERNEL_OpenUserData)
- +#define gckKERNEL_CloseUserData gcmHAL2D(gckKERNEL_CloseUserData)
- +#define gckHARDWARE_Construct gcmHAL2D(gckHARDWARE_Construct)
- +#define gckHARDWARE_Destroy gcmHAL2D(gckHARDWARE_Destroy)
- +#define gckHARDWARE_QuerySystemMemory gcmHAL2D(gckHARDWARE_QuerySystemMemory)
- +#define gckHARDWARE_BuildVirtualAddress gcmHAL2D(gckHARDWARE_BuildVirtualAddress)
- +#define gckHARDWARE_QueryCommandBuffer gcmHAL2D(gckHARDWARE_QueryCommandBuffer)
- +#define gckHARDWARE_WaitLink gcmHAL2D(gckHARDWARE_WaitLink)
- +#define gckHARDWARE_Execute gcmHAL2D(gckHARDWARE_Execute)
- +#define gckHARDWARE_End gcmHAL2D(gckHARDWARE_End)
- +#define gckHARDWARE_Nop gcmHAL2D(gckHARDWARE_Nop)
- +#define gckHARDWARE_Wait gcmHAL2D(gckHARDWARE_Wait)
- +#define gckHARDWARE_PipeSelect gcmHAL2D(gckHARDWARE_PipeSelect)
- +#define gckHARDWARE_Link gcmHAL2D(gckHARDWARE_Link)
- +#define gckHARDWARE_Event gcmHAL2D(gckHARDWARE_Event)
- +#define gckHARDWARE_QueryMemory gcmHAL2D(gckHARDWARE_QueryMemory)
- +#define gckHARDWARE_QueryChipIdentity gcmHAL2D(gckHARDWARE_QueryChipIdentity)
- +#define gckHARDWARE_QueryChipSpecs gcmHAL2D(gckHARDWARE_QueryChipSpecs)
- +#define gckHARDWARE_QueryShaderCaps gcmHAL2D(gckHARDWARE_QueryShaderCaps)
- +#define gckHARDWARE_ConvertFormat gcmHAL2D(gckHARDWARE_ConvertFormat)
- +#define gckHARDWARE_SplitMemory gcmHAL2D(gckHARDWARE_SplitMemory)
- +#define gckHARDWARE_AlignToTile gcmHAL2D(gckHARDWARE_AlignToTile)
- +#define gckHARDWARE_UpdateQueueTail gcmHAL2D(gckHARDWARE_UpdateQueueTail)
- +#define gckHARDWARE_ConvertLogical gcmHAL2D(gckHARDWARE_ConvertLogical)
- +#define gckHARDWARE_ConvertPhysical gcmHAL2D(gckHARDWARE_ConvertPhysical)
- +#define gckHARDWARE_Interrupt gcmHAL2D(gckHARDWARE_Interrupt)
- +#define gckHARDWARE_SetMMU gcmHAL2D(gckHARDWARE_SetMMU)
- +#define gckHARDWARE_FlushMMU gcmHAL2D(gckHARDWARE_FlushMMU)
- +#define gckHARDWARE_GetIdle gcmHAL2D(gckHARDWARE_GetIdle)
- +#define gckHARDWARE_Flush gcmHAL2D(gckHARDWARE_Flush)
- +#define gckHARDWARE_SetFastClear gcmHAL2D(gckHARDWARE_SetFastClear)
- +#define gckHARDWARE_ReadInterrupt gcmHAL2D(gckHARDWARE_ReadInterrupt)
- +#define gckHARDWARE_SetPowerManagementState gcmHAL2D(gckHARDWARE_SetPowerManagementState)
- +#define gckHARDWARE_QueryPowerManagementState gcmHAL2D(gckHARDWARE_QueryPowerManagementState)
- +#define gckHARDWARE_ProfileEngine2D gcmHAL2D(gckHARDWARE_ProfileEngine2D)
- +#define gckHARDWARE_InitializeHardware gcmHAL2D(gckHARDWARE_InitializeHardware)
- +#define gckHARDWARE_Reset gcmHAL2D(gckHARDWARE_Reset)
- +#define gckINTERRUPT_Construct gcmHAL2D(gckINTERRUPT_Construct)
- +#define gckINTERRUPT_Destroy gcmHAL2D(gckINTERRUPT_Destroy)
- +#define gckINTERRUPT_SetHandler gcmHAL2D(gckINTERRUPT_SetHandler)
- +#define gckINTERRUPT_Notify gcmHAL2D(gckINTERRUPT_Notify)
- +#define gckEVENT_Construct gcmHAL2D(gckEVENT_Construct)
- +#define gckEVENT_Destroy gcmHAL2D(gckEVENT_Destroy)
- +#define gckEVENT_AddList gcmHAL2D(gckEVENT_AddList)
- +#define gckEVENT_FreeNonPagedMemory gcmHAL2D(gckEVENT_FreeNonPagedMemory)
- +#define gckEVENT_FreeContiguousMemory gcmHAL2D(gckEVENT_FreeContiguousMemory)
- +#define gckEVENT_FreeVideoMemory gcmHAL2D(gckEVENT_FreeVideoMemory)
- +#define gckEVENT_Signal gcmHAL2D(gckEVENT_Signal)
- +#define gckEVENT_Unlock gcmHAL2D(gckEVENT_Unlock)
- +#define gckEVENT_Submit gcmHAL2D(gckEVENT_Submit)
- +#define gckEVENT_Commit gcmHAL2D(gckEVENT_Commit)
- +#define gckEVENT_Notify gcmHAL2D(gckEVENT_Notify)
- +#define gckEVENT_Interrupt gcmHAL2D(gckEVENT_Interrupt)
- +#define gckCOMMAND_Construct gcmHAL2D(gckCOMMAND_Construct)
- +#define gckCOMMAND_Destroy gcmHAL2D(gckCOMMAND_Destroy)
- +#define gckCOMMAND_EnterCommit gcmHAL2D(gckCOMMAND_EnterCommit)
- +#define gckCOMMAND_ExitCommit gcmHAL2D(gckCOMMAND_ExitCommit)
- +#define gckCOMMAND_Start gcmHAL2D(gckCOMMAND_Start)
- +#define gckCOMMAND_Stop gcmHAL2D(gckCOMMAND_Stop)
- +#define gckCOMMAND_Commit gcmHAL2D(gckCOMMAND_Commit)
- +#define gckCOMMAND_Reserve gcmHAL2D(gckCOMMAND_Reserve)
- +#define gckCOMMAND_Execute gcmHAL2D(gckCOMMAND_Execute)
- +#define gckCOMMAND_Stall gcmHAL2D(gckCOMMAND_Stall)
- +#define gckCOMMAND_Attach gcmHAL2D(gckCOMMAND_Attach)
- +#define gckCOMMAND_Detach gcmHAL2D(gckCOMMAND_Detach)
- +#define gckMMU_Construct gcmHAL2D(gckMMU_Construct)
- +#define gckMMU_Destroy gcmHAL2D(gckMMU_Destroy)
- +#define gckMMU_AllocatePages gcmHAL2D(gckMMU_AllocatePages)
- +#define gckMMU_FreePages gcmHAL2D(gckMMU_FreePages)
- +#define gckMMU_InsertNode gcmHAL2D(gckMMU_InsertNode)
- +#define gckMMU_RemoveNode gcmHAL2D(gckMMU_RemoveNode)
- +#define gckMMU_FreeHandleMemory gcmHAL2D(gckMMU_FreeHandleMemory)
- +#define gckMMU_Test gcmHAL2D(gckMMU_Test)
- +#define gckHARDWARE_QueryProfileRegisters gcmHAL2D(gckHARDWARE_QueryProfileRegisters)
- +
- +
- +#define FindMdlMap gcmHAL2D(FindMdlMap)
- +#define OnProcessExit gcmHAL2D(OnProcessExit)
- +
- +#define gckGALDEVICE_Destroy gcmHAL2D(gckGALDEVICE_Destroy)
- +#define gckOS_Print gcmHAL2D(gckOS_Print)
- +#define gckGALDEVICE_FreeMemory gcmHAL2D(gckGALDEVICE_FreeMemory)
- +#define gckGALDEVICE_AllocateMemory gcmHAL2D(gckGALDEVICE_AllocateMemory)
- +#define gckOS_DebugBreak gcmHAL2D(gckOS_DebugBreak)
- +#define gckGALDEVICE_Release_ISR gcmHAL2D(gckGALDEVICE_Release_ISR)
- +#define gckOS_Verify gcmHAL2D(gckOS_Verify)
- +#define gckCOMMAND_Release gcmHAL2D(gckCOMMAND_Release)
- +#define gckGALDEVICE_Stop gcmHAL2D(gckGALDEVICE_Stop)
- +#define gckGALDEVICE_Construct gcmHAL2D(gckGALDEVICE_Construct)
- +#define gckOS_DebugFatal gcmHAL2D(gckOS_DebugFatal)
- +#define gckOS_DebugTrace gcmHAL2D(gckOS_DebugTrace)
- +#define gckHARDWARE_GetBaseAddress gcmHAL2D(gckHARDWARE_GetBaseAddress)
- +#define gckGALDEVICE_Setup_ISR gcmHAL2D(gckGALDEVICE_Setup_ISR)
- +#define gckKERNEL_AttachProcess gcmHAL2D(gckKERNEL_AttachProcess)
- +#define gckKERNEL_AttachProcessEx gcmHAL2D(gckKERNEL_AttachProcessEx)
- +#define gckGALDEVICE_Start_Thread gcmHAL2D(gckGALDEVICE_Start_Thread)
- +#define gckHARDWARE_QueryIdle gcmHAL2D(gckHARDWARE_QueryIdle)
- +#define gckGALDEVICE_Start gcmHAL2D(gckGALDEVICE_Start)
- +#define gckOS_GetKernelLogical gcmHAL2D(gckOS_GetKernelLogical)
- +#define gckOS_DebugTraceZone gcmHAL2D(gckOS_DebugTraceZone)
- +#define gckGALDEVICE_Stop_Thread gcmHAL2D(gckGALDEVICE_Stop_Thread)
- +#define gckHARDWARE_NeedBaseAddress gcmHAL2D(gckHARDWARE_NeedBaseAddress)
- +
- +#endif
- +
- +#endif /* __gc_hal_rename_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_statistics.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_statistics.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_statistics.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_statistics.h 2015-03-08 14:27:37.649684500 -0500
- @@ -0,0 +1,115 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_statistics_h_
- +#define __gc_hal_statistics_h_
- +
- +
- +#define VIV_STAT_ENABLE_STATISTICS 0
- +
- +/* Toal number of frames for which the frame time is accounted. We have storage
- + to keep frame times for last this many frames.
- +*/
- +#define VIV_STAT_FRAME_BUFFER_SIZE 30
- +
- +/*
- + Total number of frames sampled for a mode. This means
- +
- + # of frames for HZ Current : VIV_STAT_EARLY_Z_SAMPLE_FRAMES
- + # of frames for HZ Switched : VIV_STAT_EARLY_Z_SAMPLE_FRAMES
- + +
- + --------------------------------------------------------
- + : (2 * VIV_STAT_EARLY_Z_SAMPLE_FRAMES) frames needed
- +
- + IMPORTANT: This total must be smaller than VIV_STAT_FRAME_BUFFER_SIZE
- +*/
- +#define VIV_STAT_EARLY_Z_SAMPLE_FRAMES 7
- +#define VIV_STAT_EARLY_Z_LATENCY_FRAMES 2
- +
- +/* Multiplication factor for previous Hz off mode. Make it more than 1.0 to advertise HZ on.*/
- +#define VIV_STAT_EARLY_Z_FACTOR (1.05f)
- +
- +/* Defines the statistical data keys monitored by the statistics module */
- +typedef enum _gceSTATISTICS
- +{
- + gcvFRAME_FPS = 1,
- +}
- +gceSTATISTICS;
- +
- +/* HAL statistics information. */
- +typedef struct _gcsSTATISTICS_EARLYZ
- +{
- + gctUINT switchBackCount;
- + gctUINT nextCheckPoint;
- + gctBOOL disabled;
- +}
- +gcsSTATISTICS_EARLYZ;
- +
- +
- +/* Defines the statistical data keys monitored by the statistics module */
- +typedef enum _gceSTATISTICS_Call
- +{
- + gcvSTAT_ES11_GLDRAWELEMENTS = 1,
- +}
- +gceSTATISTICS_Call;
- +
- +
- +/* HAL statistics information. */
- +typedef struct _gcsSTATISTICS
- +{
- + gctUINT64 frameTime[VIV_STAT_FRAME_BUFFER_SIZE];
- + gctUINT64 previousFrameTime;
- + gctUINT frame;
- + gcsSTATISTICS_EARLYZ earlyZ;
- + gctUINT ES11_drawElementsCount;
- + gctBOOL applyRTestVAFix;
- +}
- +gcsSTATISTICS;
- +
- +
- +/* Add a frame based data into current statistics. */
- +void
- +gcfSTATISTICS_AddData(
- + IN gceSTATISTICS Key,
- + IN gctUINT Value
- + );
- +
- +/* Marks the frame end and triggers statistical calculations and decisions.*/
- +void
- +gcfSTATISTICS_MarkFrameEnd (
- + void
- + );
- +
- +/* Sets whether the dynmaic HZ is disabled or not .*/
- +void
- +gcfSTATISTICS_DisableDynamicEarlyZ (
- + IN gctBOOL Disabled
- + );
- +
- +/* Checks whether or not glDrawArray function call will be discarded */
- +gctBOOL
- +gcfSTATISTICS_DiscardCall(
- + gceSTATISTICS_Call Function
- + );
- +
- +
- +#endif /*__gc_hal_statistics_h_ */
- +
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_types.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_types.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_types.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_types.h 2015-03-08 14:27:37.649684500 -0500
- @@ -0,0 +1,1080 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_types_h_
- +#define __gc_hal_types_h_
- +
- +#include "gc_hal_version.h"
- +#include "gc_hal_options.h"
- +
- +#ifdef _WIN32
- +#pragma warning(disable:4127) /* Conditional expression is constant (do { }
- + ** while(0)). */
- +#pragma warning(disable:4100) /* Unreferenced formal parameter. */
- +#pragma warning(disable:4204) /* Non-constant aggregate initializer (C99). */
- +#pragma warning(disable:4131) /* Uses old-style declarator (for Bison and
- + ** Flex generated files). */
- +#pragma warning(disable:4206) /* Translation unit is empty. */
- +#endif
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +/******************************************************************************\
- +** Platform macros.
- +*/
- +
- +#if defined(__GNUC__)
- +# define gcdHAS_ELLIPSES 1 /* GCC always has it. */
- +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
- +# define gcdHAS_ELLIPSES 1 /* C99 has it. */
- +#elif defined(_MSC_VER) && (_MSC_VER >= 1500)
- +# define gcdHAS_ELLIPSES 1 /* MSVC 2007+ has it. */
- +#elif defined(UNDER_CE)
- +#if UNDER_CE >= 600
- +# define gcdHAS_ELLIPSES 1
- +# else
- +# define gcdHAS_ELLIPSES 0
- +# endif
- +#else
- +# error "gcdHAS_ELLIPSES: Platform could not be determined"
- +#endif
- +
- +/******************************************************************************\
- +************************************ Keyword ***********************************
- +\******************************************************************************/
- +
- +#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))
- +# define gcmINLINE inline /* C99 keyword. */
- +#elif defined(__GNUC__)
- +# define gcmINLINE __inline__ /* GNU keyword. */
- +#elif defined(_MSC_VER) || defined(UNDER_CE)
- +# define gcmINLINE __inline /* Internal keyword. */
- +#else
- +# error "gcmINLINE: Platform could not be determined"
- +#endif
- +
- +/* Possible debug flags. */
- +#define gcdDEBUG_NONE 0
- +#define gcdDEBUG_ALL (1 << 0)
- +#define gcdDEBUG_FATAL (1 << 1)
- +#define gcdDEBUG_TRACE (1 << 2)
- +#define gcdDEBUG_BREAK (1 << 3)
- +#define gcdDEBUG_ASSERT (1 << 4)
- +#define gcdDEBUG_CODE (1 << 5)
- +#define gcdDEBUG_STACK (1 << 6)
- +
- +#define gcmIS_DEBUG(flag) ( gcdDEBUG & (flag | gcdDEBUG_ALL) )
- +
- +#ifndef gcdDEBUG
- +#if (defined(DBG) && DBG) || defined(DEBUG) || defined(_DEBUG)
- +# define gcdDEBUG gcdDEBUG_ALL
- +# else
- +# define gcdDEBUG gcdDEBUG_NONE
- +# endif
- +#endif
- +
- +#ifdef _USRDLL
- +#ifdef _MSC_VER
- +#ifdef HAL_EXPORTS
- +# define HALAPI __declspec(dllexport)
- +# else
- +# define HALAPI __declspec(dllimport)
- +# endif
- +# define HALDECL __cdecl
- +# else
- +#ifdef HAL_EXPORTS
- +# define HALAPI
- +# else
- +# define HALAPI extern
- +# endif
- +# endif
- +#else
- +# define HALAPI
- +# define HALDECL
- +#endif
- +
- +/******************************************************************************\
- +********************************** Common Types ********************************
- +\******************************************************************************/
- +
- +#define gcvFALSE 0
- +#define gcvTRUE 1
- +
- +#define gcvINFINITE ((gctUINT32) ~0U)
- +
- +#define gcvINVALID_HANDLE ((gctHANDLE) ~0U)
- +
- +typedef int gctBOOL;
- +typedef gctBOOL * gctBOOL_PTR;
- +
- +typedef int gctINT;
- +typedef long gctLONG;
- +typedef signed char gctINT8;
- +typedef signed short gctINT16;
- +typedef signed int gctINT32;
- +typedef signed long long gctINT64;
- +
- +typedef gctINT * gctINT_PTR;
- +typedef gctINT8 * gctINT8_PTR;
- +typedef gctINT16 * gctINT16_PTR;
- +typedef gctINT32 * gctINT32_PTR;
- +typedef gctINT64 * gctINT64_PTR;
- +
- +typedef unsigned int gctUINT;
- +typedef unsigned char gctUINT8;
- +typedef unsigned short gctUINT16;
- +typedef unsigned int gctUINT32;
- +typedef unsigned long long gctUINT64;
- +typedef unsigned long gctUINTPTR_T;
- +
- +typedef gctUINT * gctUINT_PTR;
- +typedef gctUINT8 * gctUINT8_PTR;
- +typedef gctUINT16 * gctUINT16_PTR;
- +typedef gctUINT32 * gctUINT32_PTR;
- +typedef gctUINT64 * gctUINT64_PTR;
- +
- +typedef unsigned long gctSIZE_T;
- +typedef gctSIZE_T * gctSIZE_T_PTR;
- +
- +#ifdef __cplusplus
- +# define gcvNULL 0
- +#else
- +# define gcvNULL ((void *) 0)
- +#endif
- +
- +typedef float gctFLOAT;
- +typedef signed int gctFIXED_POINT;
- +typedef float * gctFLOAT_PTR;
- +
- +typedef void * gctPHYS_ADDR;
- +typedef void * gctHANDLE;
- +typedef void * gctFILE;
- +typedef void * gctSIGNAL;
- +typedef void * gctWINDOW;
- +typedef void * gctIMAGE;
- +typedef void * gctSYNC_POINT;
- +
- +typedef void * gctSEMAPHORE;
- +
- +typedef void * gctPOINTER;
- +typedef const void * gctCONST_POINTER;
- +
- +typedef char gctCHAR;
- +typedef char * gctSTRING;
- +typedef const char * gctCONST_STRING;
- +
- +typedef struct _gcsCOUNT_STRING
- +{
- + gctSIZE_T Length;
- + gctCONST_STRING String;
- +}
- +gcsCOUNT_STRING;
- +
- +typedef union _gcuFLOAT_UINT32
- +{
- + gctFLOAT f;
- + gctUINT32 u;
- +}
- +gcuFLOAT_UINT32;
- +
- +/* Fixed point constants. */
- +#define gcvZERO_X ((gctFIXED_POINT) 0x00000000)
- +#define gcvHALF_X ((gctFIXED_POINT) 0x00008000)
- +#define gcvONE_X ((gctFIXED_POINT) 0x00010000)
- +#define gcvNEGONE_X ((gctFIXED_POINT) 0xFFFF0000)
- +#define gcvTWO_X ((gctFIXED_POINT) 0x00020000)
- +
- +/* Stringizing macro. */
- +#define gcmSTRING(Value) #Value
- +
- +/******************************************************************************\
- +******************************* Fixed Point Math *******************************
- +\******************************************************************************/
- +
- +#define gcmXMultiply(x1, x2) gcoMATH_MultiplyFixed(x1, x2)
- +#define gcmXDivide(x1, x2) gcoMATH_DivideFixed(x1, x2)
- +#define gcmXMultiplyDivide(x1, x2, x3) gcoMATH_MultiplyDivideFixed(x1, x2, x3)
- +
- +/* 2D Engine profile. */
- +typedef struct _gcs2D_PROFILE
- +{
- + /* Cycle count.
- + 32bit counter incremented every 2D clock cycle.
- + Wraps back to 0 when the counter overflows.
- + */
- + gctUINT32 cycleCount;
- +
- + /* Pixels rendered by the 2D engine.
- + Resets to 0 every time it is read. */
- + gctUINT32 pixelsRendered;
- +}
- +gcs2D_PROFILE;
- +
- +/* Macro to combine four characters into a Charcater Code. */
- +#define gcmCC(c1, c2, c3, c4) \
- +( \
- + (char) (c1) \
- + | \
- + ((char) (c2) << 8) \
- + | \
- + ((char) (c3) << 16) \
- + | \
- + ((char) (c4) << 24) \
- +)
- +
- +#define gcmPRINTABLE(c) ((((c) >= ' ') && ((c) <= '}')) ? ((c) != '%' ? (c) : ' ') : ' ')
- +
- +#define gcmCC_PRINT(cc) \
- + gcmPRINTABLE((char) ( (cc) & 0xFF)), \
- + gcmPRINTABLE((char) (((cc) >> 8) & 0xFF)), \
- + gcmPRINTABLE((char) (((cc) >> 16) & 0xFF)), \
- + gcmPRINTABLE((char) (((cc) >> 24) & 0xFF))
- +
- +/******************************************************************************\
- +****************************** Function Parameters *****************************
- +\******************************************************************************/
- +
- +#define IN
- +#define OUT
- +#define OPTIONAL
- +
- +/******************************************************************************\
- +********************************* Status Codes *********************************
- +\******************************************************************************/
- +
- +typedef enum _gceSTATUS
- +{
- + gcvSTATUS_OK = 0,
- + gcvSTATUS_FALSE = 0,
- + gcvSTATUS_TRUE = 1,
- + gcvSTATUS_NO_MORE_DATA = 2,
- + gcvSTATUS_CACHED = 3,
- + gcvSTATUS_MIPMAP_TOO_LARGE = 4,
- + gcvSTATUS_NAME_NOT_FOUND = 5,
- + gcvSTATUS_NOT_OUR_INTERRUPT = 6,
- + gcvSTATUS_MISMATCH = 7,
- + gcvSTATUS_MIPMAP_TOO_SMALL = 8,
- + gcvSTATUS_LARGER = 9,
- + gcvSTATUS_SMALLER = 10,
- + gcvSTATUS_CHIP_NOT_READY = 11,
- + gcvSTATUS_NEED_CONVERSION = 12,
- + gcvSTATUS_SKIP = 13,
- + gcvSTATUS_DATA_TOO_LARGE = 14,
- + gcvSTATUS_INVALID_CONFIG = 15,
- + gcvSTATUS_CHANGED = 16,
- + gcvSTATUS_NOT_SUPPORT_DITHER = 17,
- + gcvSTATUS_EXECUTED = 18,
- + gcvSTATUS_TERMINATE = 19,
- +
- + gcvSTATUS_CONVERT_TO_SINGLE_STREAM = 20,
- +
- + gcvSTATUS_INVALID_ARGUMENT = -1,
- + gcvSTATUS_INVALID_OBJECT = -2,
- + gcvSTATUS_OUT_OF_MEMORY = -3,
- + gcvSTATUS_MEMORY_LOCKED = -4,
- + gcvSTATUS_MEMORY_UNLOCKED = -5,
- + gcvSTATUS_HEAP_CORRUPTED = -6,
- + gcvSTATUS_GENERIC_IO = -7,
- + gcvSTATUS_INVALID_ADDRESS = -8,
- + gcvSTATUS_CONTEXT_LOSSED = -9,
- + gcvSTATUS_TOO_COMPLEX = -10,
- + gcvSTATUS_BUFFER_TOO_SMALL = -11,
- + gcvSTATUS_INTERFACE_ERROR = -12,
- + gcvSTATUS_NOT_SUPPORTED = -13,
- + gcvSTATUS_MORE_DATA = -14,
- + gcvSTATUS_TIMEOUT = -15,
- + gcvSTATUS_OUT_OF_RESOURCES = -16,
- + gcvSTATUS_INVALID_DATA = -17,
- + gcvSTATUS_INVALID_MIPMAP = -18,
- + gcvSTATUS_NOT_FOUND = -19,
- + gcvSTATUS_NOT_ALIGNED = -20,
- + gcvSTATUS_INVALID_REQUEST = -21,
- + gcvSTATUS_GPU_NOT_RESPONDING = -22,
- + gcvSTATUS_TIMER_OVERFLOW = -23,
- + gcvSTATUS_VERSION_MISMATCH = -24,
- + gcvSTATUS_LOCKED = -25,
- + gcvSTATUS_INTERRUPTED = -26,
- + gcvSTATUS_DEVICE = -27,
- + gcvSTATUS_NOT_MULTI_PIPE_ALIGNED = -28,
- +
- + /* Linker errors. */
- + gcvSTATUS_GLOBAL_TYPE_MISMATCH = -1000,
- + gcvSTATUS_TOO_MANY_ATTRIBUTES = -1001,
- + gcvSTATUS_TOO_MANY_UNIFORMS = -1002,
- + gcvSTATUS_TOO_MANY_VARYINGS = -1003,
- + gcvSTATUS_UNDECLARED_VARYING = -1004,
- + gcvSTATUS_VARYING_TYPE_MISMATCH = -1005,
- + gcvSTATUS_MISSING_MAIN = -1006,
- + gcvSTATUS_NAME_MISMATCH = -1007,
- + gcvSTATUS_INVALID_INDEX = -1008,
- + gcvSTATUS_UNIFORM_TYPE_MISMATCH = -1009,
- +
- + /* Compiler errors. */
- + gcvSTATUS_COMPILER_FE_PREPROCESSOR_ERROR = -2000,
- + gcvSTATUS_COMPILER_FE_PARSER_ERROR = -2001,
- +}
- +gceSTATUS;
- +
- +/******************************************************************************\
- +********************************* Status Macros ********************************
- +\******************************************************************************/
- +
- +#define gcmIS_ERROR(status) (status < 0)
- +#define gcmNO_ERROR(status) (status >= 0)
- +#define gcmIS_SUCCESS(status) (status == gcvSTATUS_OK)
- +
- +/******************************************************************************\
- +********************************* Field Macros *********************************
- +\******************************************************************************/
- +
- +#define __gcmSTART(reg_field) \
- + (0 ? reg_field)
- +
- +#define __gcmEND(reg_field) \
- + (1 ? reg_field)
- +
- +#define __gcmGETSIZE(reg_field) \
- + (__gcmEND(reg_field) - __gcmSTART(reg_field) + 1)
- +
- +#define __gcmALIGN(data, reg_field) \
- + (((gctUINT32) (data)) << __gcmSTART(reg_field))
- +
- +#define __gcmMASK(reg_field) \
- + ((gctUINT32) ((__gcmGETSIZE(reg_field) == 32) \
- + ? ~0 \
- + : (~(~0 << __gcmGETSIZE(reg_field)))))
- +
- +/*******************************************************************************
- +**
- +** gcmFIELDMASK
- +**
- +** Get aligned field mask.
- +**
- +** ARGUMENTS:
- +**
- +** reg Name of register.
- +** field Name of field within register.
- +*/
- +#define gcmFIELDMASK(reg, field) \
- +( \
- + __gcmALIGN(__gcmMASK(reg##_##field), reg##_##field) \
- +)
- +
- +/*******************************************************************************
- +**
- +** gcmGETFIELD
- +**
- +** Extract the value of a field from specified data.
- +**
- +** ARGUMENTS:
- +**
- +** data Data value.
- +** reg Name of register.
- +** field Name of field within register.
- +*/
- +#define gcmGETFIELD(data, reg, field) \
- +( \
- + ((((gctUINT32) (data)) >> __gcmSTART(reg##_##field)) \
- + & __gcmMASK(reg##_##field)) \
- +)
- +
- +/*******************************************************************************
- +**
- +** gcmSETFIELD
- +**
- +** Set the value of a field within specified data.
- +**
- +** ARGUMENTS:
- +**
- +** data Data value.
- +** reg Name of register.
- +** field Name of field within register.
- +** value Value for field.
- +*/
- +#define gcmSETFIELD(data, reg, field, value) \
- +( \
- + (((gctUINT32) (data)) \
- + & ~__gcmALIGN(__gcmMASK(reg##_##field), reg##_##field)) \
- + | __gcmALIGN((gctUINT32) (value) \
- + & __gcmMASK(reg##_##field), reg##_##field) \
- +)
- +
- +/*******************************************************************************
- +**
- +** gcmSETFIELDVALUE
- +**
- +** Set the value of a field within specified data with a
- +** predefined value.
- +**
- +** ARGUMENTS:
- +**
- +** data Data value.
- +** reg Name of register.
- +** field Name of field within register.
- +** value Name of the value within the field.
- +*/
- +#define gcmSETFIELDVALUE(data, reg, field, value) \
- +( \
- + (((gctUINT32) (data)) \
- + & ~__gcmALIGN(__gcmMASK(reg##_##field), reg##_##field)) \
- + | __gcmALIGN(reg##_##field##_##value \
- + & __gcmMASK(reg##_##field), reg##_##field) \
- +)
- +
- +/*******************************************************************************
- +**
- +** gcmGETMASKEDFIELDMASK
- +**
- +** Determine field mask of a masked field.
- +**
- +** ARGUMENTS:
- +**
- +** reg Name of register.
- +** field Name of field within register.
- +*/
- +#define gcmGETMASKEDFIELDMASK(reg, field) \
- +( \
- + gcmSETFIELD(0, reg, field, ~0) | \
- + gcmSETFIELD(0, reg, MASK_ ## field, ~0) \
- +)
- +
- +/*******************************************************************************
- +**
- +** gcmSETMASKEDFIELD
- +**
- +** Set the value of a masked field with specified data.
- +**
- +** ARGUMENTS:
- +**
- +** reg Name of register.
- +** field Name of field within register.
- +** value Value for field.
- +*/
- +#define gcmSETMASKEDFIELD(reg, field, value) \
- +( \
- + gcmSETFIELD (~0, reg, field, value) & \
- + gcmSETFIELDVALUE(~0, reg, MASK_ ## field, ENABLED) \
- +)
- +
- +/*******************************************************************************
- +**
- +** gcmSETMASKEDFIELDVALUE
- +**
- +** Set the value of a masked field with specified data.
- +**
- +** ARGUMENTS:
- +**
- +** reg Name of register.
- +** field Name of field within register.
- +** value Value for field.
- +*/
- +#define gcmSETMASKEDFIELDVALUE(reg, field, value) \
- +( \
- + gcmSETFIELDVALUE(~0, reg, field, value) & \
- + gcmSETFIELDVALUE(~0, reg, MASK_ ## field, ENABLED) \
- +)
- +
- +/*******************************************************************************
- +**
- +** gcmVERIFYFIELDVALUE
- +**
- +** Verify if the value of a field within specified data equals a
- +** predefined value.
- +**
- +** ARGUMENTS:
- +**
- +** data Data value.
- +** reg Name of register.
- +** field Name of field within register.
- +** value Name of the value within the field.
- +*/
- +#define gcmVERIFYFIELDVALUE(data, reg, field, value) \
- +( \
- + (((gctUINT32) (data)) >> __gcmSTART(reg##_##field) & \
- + __gcmMASK(reg##_##field)) \
- + == \
- + (reg##_##field##_##value & __gcmMASK(reg##_##field)) \
- +)
- +
- +/*******************************************************************************
- +** Bit field macros.
- +*/
- +
- +#define __gcmSTARTBIT(Field) \
- + ( 1 ? Field )
- +
- +#define __gcmBITSIZE(Field) \
- + ( 0 ? Field )
- +
- +#define __gcmBITMASK(Field) \
- +( \
- + (1 << __gcmBITSIZE(Field)) - 1 \
- +)
- +
- +#define gcmGETBITS(Value, Type, Field) \
- +( \
- + ( ((Type) (Value)) >> __gcmSTARTBIT(Field) ) \
- + & \
- + __gcmBITMASK(Field) \
- +)
- +
- +#define gcmSETBITS(Value, Type, Field, NewValue) \
- +( \
- + ( ((Type) (Value)) \
- + & ~(__gcmBITMASK(Field) << __gcmSTARTBIT(Field)) \
- + ) \
- + | \
- + ( ( ((Type) (NewValue)) \
- + & __gcmBITMASK(Field) \
- + ) << __gcmSTARTBIT(Field) \
- + ) \
- +)
- +
- +/*******************************************************************************
- +**
- +** gcmISINREGRANGE
- +**
- +** Verify whether the specified address is in the register range.
- +**
- +** ARGUMENTS:
- +**
- +** Address Address to be verified.
- +** Name Name of a register.
- +*/
- +
- +#define gcmISINREGRANGE(Address, Name) \
- +( \
- + ((Address & (~0U << Name ## _LSB)) == (Name ## _Address >> 2)) \
- +)
- +
- +/*******************************************************************************
- +**
- +** A set of macros to aid state loading.
- +**
- +** ARGUMENTS:
- +**
- +** CommandBuffer Pointer to a gcoCMDBUF object.
- +** StateDelta Pointer to a gcsSTATE_DELTA state delta structure.
- +** Memory Destination memory pointer of gctUINT32_PTR type.
- +** PartOfContext Whether or not the state is a part of the context.
- +** FixedPoint Whether or not the state is of the fixed point format.
- +** Count Number of consecutive states to be loaded.
- +** Address State address.
- +** Data Data to be set to the state.
- +*/
- +
- +/*----------------------------------------------------------------------------*/
- +
- +#if gcmIS_DEBUG(gcdDEBUG_CODE)
- +
- +# define gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count) \
- + CommandBuffer->lastLoadStatePtr = gcmPTR_TO_UINT64(Memory); \
- + CommandBuffer->lastLoadStateAddress = Address; \
- + CommandBuffer->lastLoadStateCount = Count
- +
- +# define gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address) \
- + gcmASSERT( \
- + (gctUINT) (Memory - gcmUINT64_TO_TYPE(CommandBuffer->lastLoadStatePtr, gctUINT32_PTR) - 1) \
- + == \
- + (gctUINT) (Address - CommandBuffer->lastLoadStateAddress) \
- + ); \
- + \
- + gcmASSERT(CommandBuffer->lastLoadStateCount > 0); \
- + \
- + CommandBuffer->lastLoadStateCount -= 1
- +
- +# define gcmVERIFYLOADSTATEDONE(CommandBuffer) \
- + gcmASSERT(CommandBuffer->lastLoadStateCount == 0)
- +
- +#else
- +
- +# define gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count)
- +# define gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address)
- +# define gcmVERIFYLOADSTATEDONE(CommandBuffer)
- +
- +#endif
- +
- +#if gcdSECURE_USER
- +
- +# define gcmDEFINESECUREUSER() \
- + gctUINT __secure_user_offset__; \
- + gctUINT32_PTR __secure_user_hintArray__;
- +
- +# define gcmBEGINSECUREUSER() \
- + __secure_user_offset__ = reserve->lastOffset; \
- + \
- + __secure_user_hintArray__ = gcmUINT64_TO_PTR(reserve->hintArrayTail)
- +
- +# define gcmENDSECUREUSER() \
- + reserve->hintArrayTail = gcmPTR_TO_UINT64(__secure_user_hintArray__)
- +
- +# define gcmSKIPSECUREUSER() \
- + __secure_user_offset__ += gcmSIZEOF(gctUINT32)
- +
- +# define gcmUPDATESECUREUSER() \
- + *__secure_user_hintArray__ = __secure_user_offset__; \
- + \
- + __secure_user_offset__ += gcmSIZEOF(gctUINT32); \
- + __secure_user_hintArray__ += 1
- +
- +#else
- +
- +# define gcmDEFINESECUREUSER()
- +# define gcmBEGINSECUREUSER()
- +# define gcmENDSECUREUSER()
- +# define gcmSKIPSECUREUSER()
- +# define gcmUPDATESECUREUSER()
- +
- +#endif
- +
- +/*----------------------------------------------------------------------------*/
- +
- +#if gcdDUMP
- +# define gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, Data) \
- + if (FixedPoint) \
- + { \
- + gcmDUMP(gcvNULL, "@[state.x 0x%04X 0x%08X]", \
- + Address, Data \
- + ); \
- + } \
- + else \
- + { \
- + gcmDUMP(gcvNULL, "@[state 0x%04X 0x%08X]", \
- + Address, Data \
- + ); \
- + }
- +#else
- +# define gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, Data)
- +#endif
- +
- +/*----------------------------------------------------------------------------*/
- +
- +#define gcmDEFINESTATEBUFFER(CommandBuffer, StateDelta, Memory, ReserveSize) \
- + gcmDEFINESECUREUSER() \
- + gctSIZE_T ReserveSize; \
- + gcoCMDBUF CommandBuffer; \
- + gctUINT32_PTR Memory; \
- + gcsSTATE_DELTA_PTR StateDelta
- +
- +#define gcmBEGINSTATEBUFFER(Hardware, CommandBuffer, StateDelta, Memory, ReserveSize) \
- +{ \
- + gcmONERROR(gcoBUFFER_Reserve( \
- + Hardware->buffer, ReserveSize, gcvTRUE, &CommandBuffer \
- + )); \
- + \
- + Memory = gcmUINT64_TO_PTR(CommandBuffer->lastReserve); \
- + \
- + StateDelta = Hardware->delta; \
- + \
- + gcmBEGINSECUREUSER(); \
- +}
- +
- +#define gcmENDSTATEBUFFER(CommandBuffer, Memory, ReserveSize) \
- +{ \
- + gcmENDSECUREUSER(); \
- + \
- + gcmASSERT( \
- + gcmUINT64_TO_TYPE(CommandBuffer->lastReserve, gctUINT8_PTR) + ReserveSize \
- + == \
- + (gctUINT8_PTR) Memory \
- + ); \
- +}
- +
- +/*----------------------------------------------------------------------------*/
- +
- +#define gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, Count) \
- +{ \
- + gcmASSERT(((Memory - gcmUINT64_TO_TYPE(CommandBuffer->lastReserve, gctUINT32_PTR)) & 1) == 0); \
- + gcmASSERT((gctUINT32)Count <= 1024); \
- + \
- + gcmVERIFYLOADSTATEDONE(CommandBuffer); \
- + \
- + gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count); \
- + \
- + *Memory++ \
- + = gcmSETFIELDVALUE(0, AQ_COMMAND_LOAD_STATE_COMMAND, OPCODE, LOAD_STATE) \
- + | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, FLOAT, FixedPoint) \
- + | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, COUNT, Count) \
- + | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, ADDRESS, Address); \
- + \
- + gcmSKIPSECUREUSER(); \
- +}
- +
- +#define gcmENDSTATEBATCH(CommandBuffer, Memory) \
- +{ \
- + gcmVERIFYLOADSTATEDONE(CommandBuffer); \
- + \
- + gcmASSERT(((Memory - gcmUINT64_TO_TYPE(CommandBuffer->lastReserve, gctUINT32_PTR)) & 1) == 0); \
- +}
- +
- +/*----------------------------------------------------------------------------*/
- +
- +#define gcmSETSTATEDATA(StateDelta, CommandBuffer, Memory, FixedPoint, \
- + Address, Data) \
- +{ \
- + gctUINT32 __temp_data32__; \
- + \
- + gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
- + \
- + __temp_data32__ = Data; \
- + \
- + *Memory++ = __temp_data32__; \
- + \
- + gcoHARDWARE_UpdateDelta( \
- + StateDelta, FixedPoint, Address, 0, __temp_data32__ \
- + ); \
- + \
- + gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
- + \
- + gcmUPDATESECUREUSER(); \
- +}
- +
- +#define gcmSETCTRLSTATE(StateDelta, CommandBuffer, Memory, Address, Data) \
- +{ \
- + gctUINT32 __temp_data32__; \
- + \
- + gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
- + \
- + __temp_data32__ = Data; \
- + \
- + *Memory++ = __temp_data32__; \
- + \
- + gcmDUMPSTATEDATA(StateDelta, gcvFALSE, Address, __temp_data32__); \
- + \
- + gcmSKIPSECUREUSER(); \
- +}
- +
- +#define gcmSETFILLER(CommandBuffer, Memory) \
- +{ \
- + gcmVERIFYLOADSTATEDONE(CommandBuffer); \
- + \
- + Memory += 1; \
- + \
- + gcmSKIPSECUREUSER(); \
- +}
- +
- +/*----------------------------------------------------------------------------*/
- +
- +#define gcmSETSINGLESTATE(StateDelta, CommandBuffer, Memory, FixedPoint, \
- + Address, Data) \
- +{ \
- + gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
- + gcmSETSTATEDATA(StateDelta, CommandBuffer, Memory, FixedPoint, \
- + Address, Data); \
- + gcmENDSTATEBATCH(CommandBuffer, Memory); \
- +}
- +
- +#define gcmSETSINGLECTRLSTATE(StateDelta, CommandBuffer, Memory, FixedPoint, \
- + Address, Data) \
- +{ \
- + gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
- + gcmSETCTRLSTATE(StateDelta, CommandBuffer, Memory, Address, Data); \
- + gcmENDSTATEBATCH(CommandBuffer, Memory); \
- +}
- +
- +
- +/*******************************************************************************
- +**
- +** gcmSETSTARTDECOMMAND
- +**
- +** Form a START_DE command.
- +**
- +** ARGUMENTS:
- +**
- +** Memory Destination memory pointer of gctUINT32_PTR type.
- +** Count Number of the rectangles.
- +*/
- +
- +#define gcmSETSTARTDECOMMAND(Memory, Count) \
- +{ \
- + *Memory++ \
- + = gcmSETFIELDVALUE(0, AQ_COMMAND_START_DE_COMMAND, OPCODE, START_DE) \
- + | gcmSETFIELD (0, AQ_COMMAND_START_DE_COMMAND, COUNT, Count) \
- + | gcmSETFIELD (0, AQ_COMMAND_START_DE_COMMAND, DATA_COUNT, 0); \
- + \
- + *Memory++ = 0xDEADDEED; \
- +}
- +
- +/******************************************************************************\
- +******************************** Ceiling Macro ********************************
- +\******************************************************************************/
- +#define gcmCEIL(x) ((x - (gctUINT32)x) == 0 ? (gctUINT32)x : (gctUINT32)x + 1)
- +
- +/******************************************************************************\
- +******************************** Min/Max Macros ********************************
- +\******************************************************************************/
- +
- +#define gcmMIN(x, y) (((x) <= (y)) ? (x) : (y))
- +#define gcmMAX(x, y) (((x) >= (y)) ? (x) : (y))
- +#define gcmCLAMP(x, min, max) (((x) < (min)) ? (min) : \
- + ((x) > (max)) ? (max) : (x))
- +#define gcmABS(x) (((x) < 0) ? -(x) : (x))
- +#define gcmNEG(x) (((x) < 0) ? (x) : -(x))
- +
- +/*******************************************************************************
- +**
- +** gcmPTR2INT
- +**
- +** Convert a pointer to an integer value.
- +**
- +** ARGUMENTS:
- +**
- +** p Pointer value.
- +*/
- +#if defined(_WIN32) || (defined(__LP64__) && __LP64__)
- +# define gcmPTR2INT(p) \
- + ( \
- + (gctUINT32) (gctUINT64) (p) \
- + )
- +#else
- +# define gcmPTR2INT(p) \
- + ( \
- + (gctUINT32) (p) \
- + )
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gcmINT2PTR
- +**
- +** Convert an integer value into a pointer.
- +**
- +** ARGUMENTS:
- +**
- +** v Integer value.
- +*/
- +#ifdef __LP64__
- +# define gcmINT2PTR(i) \
- + ( \
- + (gctPOINTER) (gctINT64) (i) \
- + )
- +#else
- +# define gcmINT2PTR(i) \
- + ( \
- + (gctPOINTER) (i) \
- + )
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gcmOFFSETOF
- +**
- +** Compute the byte offset of a field inside a structure.
- +**
- +** ARGUMENTS:
- +**
- +** s Structure name.
- +** field Field name.
- +*/
- +#define gcmOFFSETOF(s, field) \
- +( \
- + gcmPTR2INT(& (((struct s *) 0)->field)) \
- +)
- +
- +#define gcmSWAB32(x) ((gctUINT32)( \
- + (((gctUINT32)(x) & (gctUINT32)0x000000FFUL) << 24) | \
- + (((gctUINT32)(x) & (gctUINT32)0x0000FF00UL) << 8) | \
- + (((gctUINT32)(x) & (gctUINT32)0x00FF0000UL) >> 8) | \
- + (((gctUINT32)(x) & (gctUINT32)0xFF000000UL) >> 24)))
- +
- +/*******************************************************************************
- +***** Database ****************************************************************/
- +
- +typedef struct _gcsDATABASE_COUNTERS
- +{
- + /* Number of currently allocated bytes. */
- + gctUINT64 bytes;
- +
- + /* Maximum number of bytes allocated (memory footprint). */
- + gctUINT64 maxBytes;
- +
- + /* Total number of bytes allocated. */
- + gctUINT64 totalBytes;
- +}
- +gcsDATABASE_COUNTERS;
- +
- +typedef struct _gcuDATABASE_INFO
- +{
- + /* Counters. */
- + gcsDATABASE_COUNTERS counters;
- +
- + /* Time value. */
- + gctUINT64 time;
- +}
- +gcuDATABASE_INFO;
- +
- +/*******************************************************************************
- +***** Frame database **********************************************************/
- +
- +/* gcsHAL_FRAME_INFO */
- +typedef struct _gcsHAL_FRAME_INFO
- +{
- + /* Current timer tick. */
- + OUT gctUINT64 ticks;
- +
- + /* Bandwidth counters. */
- + OUT gctUINT readBytes8[8];
- + OUT gctUINT writeBytes8[8];
- +
- + /* Counters. */
- + OUT gctUINT cycles[8];
- + OUT gctUINT idleCycles[8];
- + OUT gctUINT mcCycles[8];
- + OUT gctUINT readRequests[8];
- + OUT gctUINT writeRequests[8];
- +
- + /* FE counters. */
- + OUT gctUINT drawCount;
- + OUT gctUINT vertexOutCount;
- + OUT gctUINT vertexMissCount;
- +
- + /* 3D counters. */
- + OUT gctUINT vertexCount;
- + OUT gctUINT primitiveCount;
- + OUT gctUINT rejectedPrimitives;
- + OUT gctUINT culledPrimitives;
- + OUT gctUINT clippedPrimitives;
- + OUT gctUINT droppedPrimitives;
- + OUT gctUINT frustumClippedPrimitives;
- + OUT gctUINT outPrimitives;
- + OUT gctUINT inPrimitives;
- + OUT gctUINT culledQuadCount;
- + OUT gctUINT totalQuadCount;
- + OUT gctUINT quadCount;
- + OUT gctUINT totalPixelCount;
- +
- + /* PE counters. */
- + OUT gctUINT colorKilled[8];
- + OUT gctUINT colorDrawn[8];
- + OUT gctUINT depthKilled[8];
- + OUT gctUINT depthDrawn[8];
- +
- + /* Shader counters. */
- + OUT gctUINT shaderCycles;
- + OUT gctUINT vsInstructionCount;
- + OUT gctUINT vsTextureCount;
- + OUT gctUINT vsBranchCount;
- + OUT gctUINT vsVertices;
- + OUT gctUINT psInstructionCount;
- + OUT gctUINT psTextureCount;
- + OUT gctUINT psBranchCount;
- + OUT gctUINT psPixels;
- +
- + /* Texture counters. */
- + OUT gctUINT bilinearRequests;
- + OUT gctUINT trilinearRequests;
- + OUT gctUINT txBytes8[2];
- + OUT gctUINT txHitCount;
- + OUT gctUINT txMissCount;
- +}
- +gcsHAL_FRAME_INFO;
- +
- +typedef enum _gcePATCH_ID
- +{
- + gcePATCH_UNKNOWN = 0xFFFFFFFF,
- +
- + /* Benchmark list*/
- + gcePATCH_GLB11 = 0x0,
- + gcePATCH_GLB21,
- + gcePATCH_GLB25,
- + gcePATCH_GLB27,
- +
- + gcePATCH_BM21,
- + gcePATCH_MM,
- + gcePATCH_MM06,
- + gcePATCH_MM07,
- + gcePATCH_QUADRANT,
- + gcePATCH_ANTUTU,
- + gcePATCH_SMARTBENCH,
- + gcePATCH_JPCT,
- + gcePATCH_NENAMARK,
- + gcePATCH_NENAMARK2,
- + gcePATCH_NEOCORE,
- + gcePATCH_GLB,
- + gcePATCH_GB,
- + gcePATCH_RTESTVA,
- + gcePATCH_BMX,
- + gcePATCH_BMGUI,
- +
- + /* Game list */
- + gcePATCH_NBA2013,
- + gcePATCH_BARDTALE,
- + gcePATCH_BUSPARKING3D,
- + gcePATCH_FISHBOODLE,
- + gcePATCH_SUBWAYSURFER,
- + gcePATCH_HIGHWAYDRIVER,
- + gcePATCH_PREMIUM,
- + gcePATCH_RACEILLEGAL,
- + gcePATCH_BLABLA,
- + gcePATCH_MEGARUN,
- + gcePATCH_GALAXYONFIRE2,
- + gcePATCH_GLOFTR3HM,
- + gcePATCH_GLOFTSXHM,
- + gcePATCH_GLOFTF3HM,
- + gcePATCH_GLOFTGANG,
- + gcePATCH_XRUNNER,
- + gcePATCH_WP,
- + gcePATCH_DEVIL,
- + gcePATCH_HOLYARCH,
- + gcePATCH_MUSE,
- + gcePATCH_SG,
- + gcePATCH_SIEGECRAFT,
- + gcePATCH_CARCHALLENGE,
- + gcePATCH_HEROESCALL,
- + gcePATCH_MONOPOLY,
- + gcePATCH_CTGL20,
- + gcePATCH_FIREFOX,
- + gcePATCH_CHORME,
- + gcePATCH_DUOKANTV,
- + gcePATCH_TESTAPP,
- + gcePATCH_GOOGLEEARTH,
- +
- + /* Count enum*/
- + gcePATCH_COUNT,
- +}
- +gcePATCH_ID;
- +
- +#if gcdLINK_QUEUE_SIZE
- +typedef struct _gckLINKDATA * gckLINKDATA;
- +struct _gckLINKDATA
- +{
- + gctUINT32 start;
- + gctUINT32 end;
- + gctINT pid;
- +};
- +
- +typedef struct _gckLINKQUEUE * gckLINKQUEUE;
- +struct _gckLINKQUEUE
- +{
- + struct _gckLINKDATA data[gcdLINK_QUEUE_SIZE];
- + gctUINT32 rear;
- + gctUINT32 front;
- + gctUINT32 count;
- +};
- +#endif
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* __gc_hal_types_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h 2015-03-08 14:27:37.649684500 -0500
- @@ -0,0 +1,37 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_version_h_
- +#define __gc_hal_version_h_
- +
- +#define gcvVERSION_MAJOR 4
- +
- +#define gcvVERSION_MINOR 6
- +
- +#define gcvVERSION_PATCH 9
- +
- +#define gcvVERSION_BUILD 9754
- +
- +#define gcvVERSION_DATE __DATE__
- +
- +#define gcvVERSION_TIME __TIME__
- +
- +#endif /* __gc_hal_version_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h 2015-03-08 14:27:37.649684500 -0500
- @@ -0,0 +1,913 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_vg_h_
- +#define __gc_hal_vg_h_
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +
- +#include "gc_hal_rename.h"
- +#include "gc_hal_types.h"
- +#include "gc_hal_enum.h"
- +#include "gc_hal_base.h"
- +
- +#if gcdENABLE_VG
- +
- +/* Thread routine type. */
- +#if defined(LINUX)
- + typedef gctINT gctTHREADFUNCRESULT;
- + typedef gctPOINTER gctTHREADFUNCPARAMETER;
- +# define gctTHREADFUNCTYPE
- +#elif defined(WIN32)
- + typedef gctUINT gctTHREADFUNCRESULT;
- + typedef gctPOINTER gctTHREADFUNCPARAMETER;
- +# define gctTHREADFUNCTYPE __stdcall
- +#elif defined(__QNXNTO__)
- + typedef void * gctTHREADFUNCRESULT;
- + typedef gctPOINTER gctTHREADFUNCPARAMETER;
- +# define gctTHREADFUNCTYPE
- +#endif
- +
- +typedef gctTHREADFUNCRESULT (gctTHREADFUNCTYPE * gctTHREADFUNC) (
- + gctTHREADFUNCPARAMETER ThreadParameter
- + );
- +
- +
- +#if defined(gcvDEBUG)
- +# undef gcvDEBUG
- +#endif
- +
- +#define gcdFORCE_DEBUG 0
- +#define gcdFORCE_MESSAGES 0
- +
- +
- +#if DBG || defined(DEBUG) || defined(_DEBUG) || gcdFORCE_DEBUG
- +# define gcvDEBUG 1
- +#else
- +# define gcvDEBUG 0
- +#endif
- +
- +#define _gcmERROR_RETURN(prefix, func) \
- + status = func; \
- + if (gcmIS_ERROR(status)) \
- + { \
- + prefix##PRINT_VERSION(); \
- + prefix##TRACE(gcvLEVEL_ERROR, \
- + #prefix "ERR_RETURN: status=%d(%s) @ %s(%d)", \
- + status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
- + return status; \
- + } \
- + do { } while (gcvFALSE)
- +
- +#define gcmERROR_RETURN(func) _gcmERROR_RETURN(gcm, func)
- +
- +#define gcmLOG_LOCATION()
- +
- +#define gcmkIS_ERROR(status) (status < 0)
- +
- +#define gcmALIGNDOWN(n, align) \
- +( \
- + (n) & ~((align) - 1) \
- +)
- +
- +#define gcmIS_VALID_INDEX(Index, Array) \
- + (((gctUINT) (Index)) < gcmCOUNTOF(Array))
- +
- +
- +#define gcmIS_NAN(x) \
- +( \
- + ((* (gctUINT32_PTR) &(x)) & 0x7FFFFFFF) == 0x7FFFFFFF \
- +)
- +
- +#define gcmLERP(v1, v2, w) \
- + ((v1) * (w) + (v2) * (1.0f - (w)))
- +
- +#define gcmINTERSECT(Start1, Start2, Length) \
- + (gcmABS((Start1) - (Start2)) < (Length))
- +
- +/*******************************************************************************
- +**
- +** gcmERR_GOTO
- +**
- +** Prints a message and terminates the current loop on error.
- +**
- +** ASSUMPTIONS:
- +**
- +** 'status' variable of gceSTATUS type must be defined.
- +**
- +** ARGUMENTS:
- +**
- +** Function
- +** Function to evaluate.
- +*/
- +
- +#define gcmERR_GOTO(Function) \
- + status = Function; \
- + if (gcmIS_ERROR(status)) \
- + { \
- + gcmTRACE( \
- + gcvLEVEL_ERROR, \
- + "gcmERR_GOTO: status=%d @ line=%d in function %s.\n", \
- + status, __LINE__, __FUNCTION__ \
- + ); \
- + goto ErrorHandler; \
- + }
- +
- +#if gcvDEBUG || gcdFORCE_MESSAGES
- +# define gcmVERIFY_BOOLEAN(Expression) \
- + gcmASSERT( \
- + ( (Expression) == gcvFALSE ) || \
- + ( (Expression) == gcvTRUE ) \
- + )
- +#else
- +# define gcmVERIFY_BOOLEAN(Expression)
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gcmVERIFYFIELDFIT
- +**
- +** Verify whether the value fits in the field.
- +**
- +** ARGUMENTS:
- +**
- +** data Data value.
- +** reg Name of register.
- +** field Name of field within register.
- +** value Value for field.
- +*/
- +#define gcmVERIFYFIELDFIT(reg, field, value) \
- + gcmASSERT( \
- + (value) <= gcmFIELDMAX(reg, field) \
- + )
- +/*******************************************************************************
- +**
- +** gcmFIELDMAX
- +**
- +** Get field maximum value.
- +**
- +** ARGUMENTS:
- +**
- +** reg Name of register.
- +** field Name of field within register.
- +*/
- +#define gcmFIELDMAX(reg, field) \
- +( \
- + (gctUINT32) \
- + ( \
- + (__gcmGETSIZE(reg##_##field) == 32) \
- + ? ~0 \
- + : (~(~0 << __gcmGETSIZE(reg##_##field))) \
- + ) \
- +)
- +
- +
- +/* ANSI C does not have the 'f' functions, define replacements here. */
- +#define gcmSINF(x) ((gctFLOAT) sin(x))
- +#define gcmCOSF(x) ((gctFLOAT) cos(x))
- +#define gcmASINF(x) ((gctFLOAT) asin(x))
- +#define gcmACOSF(x) ((gctFLOAT) acos(x))
- +#define gcmSQRTF(x) ((gctFLOAT) sqrt(x))
- +#define gcmFABSF(x) ((gctFLOAT) fabs(x))
- +#define gcmFMODF(x, y) ((gctFLOAT) fmod((x), (y)))
- +#define gcmCEILF(x) ((gctFLOAT) ceil(x))
- +#define gcmFLOORF(x) ((gctFLOAT) floor(x))
- +
- +
- +
- +/* Fixed point constants. */
- +#define gcvZERO_X ((gctFIXED_POINT) 0x00000000)
- +#define gcvHALF_X ((gctFIXED_POINT) 0x00008000)
- +#define gcvONE_X ((gctFIXED_POINT) 0x00010000)
- +#define gcvNEGONE_X ((gctFIXED_POINT) 0xFFFF0000)
- +#define gcvTWO_X ((gctFIXED_POINT) 0x00020000)
- +
- +/* Integer constants. */
- +#define gcvMAX_POS_INT ((gctINT) 0x7FFFFFFF)
- +#define gcvMAX_NEG_INT ((gctINT) 0x80000000)
- +
- +/* Float constants. */
- +#define gcvMAX_POS_FLOAT ((gctFLOAT) 3.4028235e+038)
- +#define gcvMAX_NEG_FLOAT ((gctFLOAT) -3.4028235e+038)
- +
- +/******************************************************************************\
- +***************************** Miscellaneous Macro ******************************
- +\******************************************************************************/
- +
- +#define gcmKB2BYTES(Kilobyte) \
- +( \
- + (Kilobyte) << 10 \
- +)
- +
- +#define gcmMB2BYTES(Megabyte) \
- +( \
- + (Megabyte) << 20 \
- +)
- +
- +#define gcmMAT(Matrix, Row, Column) \
- +( \
- + (Matrix) [(Row) * 3 + (Column)] \
- +)
- +
- +#define gcmMAKE2CHAR(Char1, Char2) \
- +( \
- + ((gctUINT16) (gctUINT8) (Char1) << 0) | \
- + ((gctUINT16) (gctUINT8) (Char2) << 8) \
- +)
- +
- +#define gcmMAKE4CHAR(Char1, Char2, Char3, Char4) \
- +( \
- + ((gctUINT32)(gctUINT8) (Char1) << 0) | \
- + ((gctUINT32)(gctUINT8) (Char2) << 8) | \
- + ((gctUINT32)(gctUINT8) (Char3) << 16) | \
- + ((gctUINT32)(gctUINT8) (Char4) << 24) \
- +)
- +
- +/* some platforms need to fix the physical address for HW to access*/
- +#define gcmFIXADDRESS(address) \
- +(\
- + (address)\
- +)
- +
- +#define gcmkFIXADDRESS(address) \
- +(\
- + (address)\
- +)
- +
- +/******************************************************************************\
- +****************************** Kernel Debug Macro ******************************
- +\******************************************************************************/
- +
- +/* Set signal to signaled state for specified process. */
- +gceSTATUS
- +gckOS_SetSignal(
- + IN gckOS Os,
- + IN gctHANDLE Process,
- + IN gctSIGNAL Signal
- + );
- +
- +/* Return the kernel logical pointer for the given physical one. */
- +gceSTATUS
- +gckOS_GetKernelLogical(
- + IN gckOS Os,
- + IN gctUINT32 Address,
- + OUT gctPOINTER * KernelPointer
- + );
- +
- +/* Return the kernel logical pointer for the given physical one. */
- +gceSTATUS
- +gckOS_GetKernelLogicalEx(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctUINT32 Address,
- + OUT gctPOINTER * KernelPointer
- + );
- +
- +/*----------------------------------------------------------------------------*/
- +/*----------------------------- Semaphore Object -----------------------------*/
- +
- +/* Increment the value of a semaphore. */
- +gceSTATUS
- +gckOS_IncrementSemaphore(
- + IN gckOS Os,
- + IN gctSEMAPHORE Semaphore
- + );
- +
- +/* Decrement the value of a semaphore (waiting might occur). */
- +gceSTATUS
- +gckOS_DecrementSemaphore(
- + IN gckOS Os,
- + IN gctSEMAPHORE Semaphore
- + );
- +
- +
- +/*----------------------------------------------------------------------------*/
- +/*------------------------------- Thread Object ------------------------------*/
- +
- +/* Start a thread. */
- +gceSTATUS
- +gckOS_StartThread(
- + IN gckOS Os,
- + IN gctTHREADFUNC ThreadFunction,
- + IN gctPOINTER ThreadParameter,
- + OUT gctTHREAD * Thread
- + );
- +
- +/* Stop a thread. */
- +gceSTATUS
- +gckOS_StopThread(
- + IN gckOS Os,
- + IN gctTHREAD Thread
- + );
- +
- +/* Verify whether the thread is still running. */
- +gceSTATUS
- +gckOS_VerifyThread(
- + IN gckOS Os,
- + IN gctTHREAD Thread
- + );
- +
- +
- +/* Construct a new gckVGKERNEL object. */
- +gceSTATUS
- +gckVGKERNEL_Construct(
- + IN gckOS Os,
- + IN gctPOINTER Context,
- + IN gckKERNEL inKernel,
- + OUT gckVGKERNEL * Kernel
- + );
- +
- +/* Destroy an gckVGKERNEL object. */
- +gceSTATUS
- +gckVGKERNEL_Destroy(
- + IN gckVGKERNEL Kernel
- + );
- +
- +/* Allocate linear video memory. */
- +gceSTATUS
- +gckKERNEL_AllocateLinearMemory(
- + IN gckKERNEL Kernel,
- + IN OUT gcePOOL * Pool,
- + IN gctSIZE_T Bytes,
- + IN gctSIZE_T Alignment,
- + IN gceSURF_TYPE Type,
- + OUT gcuVIDMEM_NODE_PTR * Node
- + );
- +
- +/* Unmap memory. */
- +gceSTATUS
- +gckKERNEL_UnmapMemory(
- + IN gckKERNEL Kernel,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes,
- + IN gctPOINTER Logical
- + );
- +
- +/* Dispatch a user-level command. */
- +gceSTATUS
- +gckVGKERNEL_Dispatch(
- + IN gckKERNEL Kernel,
- + IN gctBOOL FromUser,
- + IN OUT struct _gcsHAL_INTERFACE * Interface
- + );
- +
- +/* Query command buffer requirements. */
- +gceSTATUS
- +gckKERNEL_QueryCommandBuffer(
- + IN gckKERNEL Kernel,
- + OUT gcsCOMMAND_BUFFER_INFO_PTR Information
- + );
- +
- +#if gcdDYNAMIC_MAP_RESERVED_MEMORY
- +gceSTATUS
- +gckOS_MapReservedMemoryToKernel(
- + IN gckOS Os,
- + IN gctUINT32 Physical,
- + IN gctINT Bytes,
- + IN OUT gctPOINTER *Virtual
- + );
- +
- +gceSTATUS
- +gckOS_UnmapReservedMemoryFromKernel(
- + IN gctPOINTER Virtual
- + );
- +#endif
- +
- +/******************************************************************************\
- +******************************* gckVGHARDWARE Object ******************************
- +\******************************************************************************/
- +
- +/* Construct a new gckVGHARDWARE object. */
- +gceSTATUS
- +gckVGHARDWARE_Construct(
- + IN gckOS Os,
- + OUT gckVGHARDWARE * Hardware
- + );
- +
- +/* Destroy an gckVGHARDWARE object. */
- +gceSTATUS
- +gckVGHARDWARE_Destroy(
- + IN gckVGHARDWARE Hardware
- + );
- +
- +/* Query system memory requirements. */
- +gceSTATUS
- +gckVGHARDWARE_QuerySystemMemory(
- + IN gckVGHARDWARE Hardware,
- + OUT gctSIZE_T * SystemSize,
- + OUT gctUINT32 * SystemBaseAddress
- + );
- +
- +/* Build virtual address. */
- +gceSTATUS
- +gckVGHARDWARE_BuildVirtualAddress(
- + IN gckVGHARDWARE Hardware,
- + IN gctUINT32 Index,
- + IN gctUINT32 Offset,
- + OUT gctUINT32 * Address
- + );
- +
- +/* Kickstart the command processor. */
- +gceSTATUS
- +gckVGHARDWARE_Execute(
- + IN gckVGHARDWARE Hardware,
- + IN gctUINT32 Address,
- + IN gctSIZE_T Count
- + );
- +
- +/* Query the available memory. */
- +gceSTATUS
- +gckVGHARDWARE_QueryMemory(
- + IN gckVGHARDWARE Hardware,
- + OUT gctSIZE_T * InternalSize,
- + OUT gctUINT32 * InternalBaseAddress,
- + OUT gctUINT32 * InternalAlignment,
- + OUT gctSIZE_T * ExternalSize,
- + OUT gctUINT32 * ExternalBaseAddress,
- + OUT gctUINT32 * ExternalAlignment,
- + OUT gctUINT32 * HorizontalTileSize,
- + OUT gctUINT32 * VerticalTileSize
- + );
- +
- +/* Query the identity of the hardware. */
- +gceSTATUS
- +gckVGHARDWARE_QueryChipIdentity(
- + IN gckVGHARDWARE Hardware,
- + OUT gceCHIPMODEL* ChipModel,
- + OUT gctUINT32* ChipRevision,
- + OUT gctUINT32* ChipFeatures,
- + OUT gctUINT32* ChipMinorFeatures,
- + OUT gctUINT32* ChipMinorFeatures1
- + );
- +
- +/* Convert an API format. */
- +gceSTATUS
- +gckVGHARDWARE_ConvertFormat(
- + IN gckVGHARDWARE Hardware,
- + IN gceSURF_FORMAT Format,
- + OUT gctUINT32 * BitsPerPixel,
- + OUT gctUINT32 * BytesPerTile
- + );
- +
- +/* Split a harwdare specific address into API stuff. */
- +gceSTATUS
- +gckVGHARDWARE_SplitMemory(
- + IN gckVGHARDWARE Hardware,
- + IN gctUINT32 Address,
- + OUT gcePOOL * Pool,
- + OUT gctUINT32 * Offset
- + );
- +
- +/* Align size to tile boundary. */
- +gceSTATUS
- +gckVGHARDWARE_AlignToTile(
- + IN gckVGHARDWARE Hardware,
- + IN gceSURF_TYPE Type,
- + IN OUT gctUINT32_PTR Width,
- + IN OUT gctUINT32_PTR Height
- + );
- +
- +/* Convert logical address to hardware specific address. */
- +gceSTATUS
- +gckVGHARDWARE_ConvertLogical(
- + IN gckVGHARDWARE Hardware,
- + IN gctPOINTER Logical,
- + OUT gctUINT32 * Address
- + );
- +
- +/* Program MMU. */
- +gceSTATUS
- +gckVGHARDWARE_SetMMU(
- + IN gckVGHARDWARE Hardware,
- + IN gctPOINTER Logical
- + );
- +
- +/* Flush the MMU. */
- +gceSTATUS
- +gckVGHARDWARE_FlushMMU(
- + IN gckVGHARDWARE Hardware
- + );
- +
- +/* Get idle register. */
- +gceSTATUS
- +gckVGHARDWARE_GetIdle(
- + IN gckVGHARDWARE Hardware,
- + OUT gctUINT32 * Data
- + );
- +
- +/* Flush the caches. */
- +gceSTATUS
- +gckVGHARDWARE_Flush(
- + IN gckVGHARDWARE Hardware,
- + IN gceKERNEL_FLUSH Flush,
- + IN gctPOINTER Logical,
- + IN OUT gctSIZE_T * Bytes
- + );
- +
- +/* Enable/disable fast clear. */
- +gceSTATUS
- +gckVGHARDWARE_SetFastClear(
- + IN gckVGHARDWARE Hardware,
- + IN gctINT Enable
- + );
- +
- +gceSTATUS
- +gckVGHARDWARE_ReadInterrupt(
- + IN gckVGHARDWARE Hardware,
- + OUT gctUINT32_PTR IDs
- + );
- +
- +/* Power management. */
- +gceSTATUS
- +gckVGHARDWARE_SetPowerManagementState(
- + IN gckVGHARDWARE Hardware,
- + IN gceCHIPPOWERSTATE State
- + );
- +
- +gceSTATUS
- +gckVGHARDWARE_QueryPowerManagementState(
- + IN gckVGHARDWARE Hardware,
- + OUT gceCHIPPOWERSTATE* State
- + );
- +
- +gceSTATUS
- +gckVGHARDWARE_SetPowerManagement(
- + IN gckVGHARDWARE Hardware,
- + IN gctBOOL PowerManagement
- + );
- +
- +gceSTATUS
- +gckVGHARDWARE_SetPowerOffTimeout(
- + IN gckVGHARDWARE Hardware,
- + IN gctUINT32 Timeout
- + );
- +
- +gceSTATUS
- +gckVGHARDWARE_QueryPowerOffTimeout(
- + IN gckVGHARDWARE Hardware,
- + OUT gctUINT32* Timeout
- + );
- +
- +gceSTATUS
- +gckVGHARDWARE_QueryIdle(
- + IN gckVGHARDWARE Hardware,
- + OUT gctBOOL_PTR IsIdle
- + );
- +/******************************************************************************\
- +*************************** Command Buffer Structures **************************
- +\******************************************************************************/
- +
- +/* Vacant command buffer marker. */
- +#define gcvVACANT_BUFFER ((gcsCOMPLETION_SIGNAL_PTR) (1))
- +
- +/* Command buffer header. */
- +typedef struct _gcsCMDBUFFER * gcsCMDBUFFER_PTR;
- +typedef struct _gcsCMDBUFFER
- +{
- + /* Pointer to the completion signal. */
- + gcsCOMPLETION_SIGNAL_PTR completion;
- +
- + /* The user sets this to the node of the container buffer whitin which
- + this particular command buffer resides. The kernel sets this to the
- + node of the internally allocated buffer. */
- + gctUINT64 node;
- +
- + /* Command buffer hardware address. */
- + gctUINT32 address;
- +
- + /* The offset of the buffer from the beginning of the header. */
- + gctUINT32 bufferOffset;
- +
- + /* Size of the area allocated for the data portion of this particular
- + command buffer (headers and tail reserves are excluded). */
- + gctSIZE_T size;
- +
- + /* Offset into the buffer [0..size]; reflects exactly how much data has
- + been put into the command buffer. */
- + gctUINT offset;
- +
- + /* The number of command units in the buffer for the hardware to
- + execute. */
- + gctSIZE_T dataCount;
- +
- + /* MANAGED BY : user HAL (gcoBUFFER object).
- + USED BY : user HAL (gcoBUFFER object).
- + Points to the immediate next allocated command buffer. */
- + gcsCMDBUFFER_PTR nextAllocated;
- +
- + /* MANAGED BY : user layers (HAL and drivers).
- + USED BY : kernel HAL (gcoBUFFER object).
- + Points to the next subbuffer if any. A family of subbuffers are chained
- + together and are meant to be executed inseparably as a unit. Meaning
- + that context switching cannot occur while a chain of subbuffers is being
- + executed. */
- + gcsCMDBUFFER_PTR nextSubBuffer;
- +}
- +gcsCMDBUFFER;
- +
- +/* Command queue element. */
- +typedef struct _gcsVGCMDQUEUE
- +{
- + /* Pointer to the command buffer header. */
- + gcsCMDBUFFER_PTR commandBuffer;
- +
- + /* Dynamic vs. static command buffer state. */
- + gctBOOL dynamic;
- +}
- +gcsVGCMDQUEUE;
- +
- +/* Context map entry. */
- +typedef struct _gcsVGCONTEXT_MAP
- +{
- + /* State index. */
- + gctUINT32 index;
- +
- + /* New state value. */
- + gctUINT32 data;
- +
- + /* Points to the next entry in the mod list. */
- + gcsVGCONTEXT_MAP_PTR next;
- +}
- +gcsVGCONTEXT_MAP;
- +
- +/* gcsVGCONTEXT structure that holds the current context. */
- +typedef struct _gcsVGCONTEXT
- +{
- + /* Context ID. */
- + gctUINT64 id;
- +
- + /* State caching ebable flag. */
- + gctBOOL stateCachingEnabled;
- +
- + /* Current pipe. */
- + gctUINT32 currentPipe;
- +
- + /* State map/mod buffer. */
- + gctSIZE_T mapFirst;
- + gctSIZE_T mapLast;
- +#ifdef __QNXNTO__
- + gctSIZE_T mapContainerSize;
- +#endif
- + gcsVGCONTEXT_MAP_PTR mapContainer;
- + gcsVGCONTEXT_MAP_PTR mapPrev;
- + gcsVGCONTEXT_MAP_PTR mapCurr;
- + gcsVGCONTEXT_MAP_PTR firstPrevMap;
- + gcsVGCONTEXT_MAP_PTR firstCurrMap;
- +
- + /* Main context buffer. */
- + gcsCMDBUFFER_PTR header;
- + gctUINT32_PTR buffer;
- +
- + /* Completion signal. */
- + gctHANDLE process;
- + gctSIGNAL signal;
- +
- +#if defined(__QNXNTO__)
- + gctINT32 coid;
- + gctINT32 rcvid;
- +#endif
- +}
- +gcsVGCONTEXT;
- +
- +/* User space task header. */
- +typedef struct _gcsTASK * gcsTASK_PTR;
- +typedef struct _gcsTASK
- +{
- + /* Pointer to the next task for the same interrupt in user space. */
- + gcsTASK_PTR next;
- +
- + /* Size of the task data that immediately follows the structure. */
- + gctUINT size;
- +
- + /* Task data starts here. */
- + /* ... */
- +}
- +gcsTASK;
- +
- +/* User space task master table entry. */
- +typedef struct _gcsTASK_MASTER_ENTRY * gcsTASK_MASTER_ENTRY_PTR;
- +typedef struct _gcsTASK_MASTER_ENTRY
- +{
- + /* Pointers to the head and to the tail of the task chain. */
- + gcsTASK_PTR head;
- + gcsTASK_PTR tail;
- +}
- +gcsTASK_MASTER_ENTRY;
- +
- +/* User space task master table entry. */
- +typedef struct _gcsTASK_MASTER_TABLE
- +{
- + /* Table with one entry per block. */
- + gcsTASK_MASTER_ENTRY table[gcvBLOCK_COUNT];
- +
- + /* The total number of tasks sckeduled. */
- + gctUINT count;
- +
- + /* The total size of event data in bytes. */
- + gctUINT size;
- +
- +#if defined(__QNXNTO__)
- + gctINT32 coid;
- + gctINT32 rcvid;
- +#endif
- +}
- +gcsTASK_MASTER_TABLE;
- +
- +/******************************************************************************\
- +***************************** gckVGINTERRUPT Object ******************************
- +\******************************************************************************/
- +
- +typedef struct _gckVGINTERRUPT * gckVGINTERRUPT;
- +
- +typedef gceSTATUS (* gctINTERRUPT_HANDLER)(
- + IN gckVGKERNEL Kernel
- + );
- +
- +gceSTATUS
- +gckVGINTERRUPT_Construct(
- + IN gckVGKERNEL Kernel,
- + OUT gckVGINTERRUPT * Interrupt
- + );
- +
- +gceSTATUS
- +gckVGINTERRUPT_Destroy(
- + IN gckVGINTERRUPT Interrupt
- + );
- +
- +gceSTATUS
- +gckVGINTERRUPT_Enable(
- + IN gckVGINTERRUPT Interrupt,
- + IN OUT gctINT32_PTR Id,
- + IN gctINTERRUPT_HANDLER Handler
- + );
- +
- +gceSTATUS
- +gckVGINTERRUPT_Disable(
- + IN gckVGINTERRUPT Interrupt,
- + IN gctINT32 Id
- + );
- +
- +#ifndef __QNXNTO__
- +
- +gceSTATUS
- +gckVGINTERRUPT_Enque(
- + IN gckVGINTERRUPT Interrupt
- + );
- +
- +#else
- +
- +gceSTATUS
- +gckVGINTERRUPT_Enque(
- + IN gckVGINTERRUPT Interrupt,
- + OUT gckOS *Os,
- + OUT gctSEMAPHORE *Semaphore
- + );
- +
- +#endif
- +
- +gceSTATUS
- +gckVGINTERRUPT_DumpState(
- + IN gckVGINTERRUPT Interrupt
- + );
- +
- +
- +/******************************************************************************\
- +******************************* gckVGCOMMAND Object *******************************
- +\******************************************************************************/
- +
- +typedef struct _gckVGCOMMAND * gckVGCOMMAND;
- +
- +/* Construct a new gckVGCOMMAND object. */
- +gceSTATUS
- +gckVGCOMMAND_Construct(
- + IN gckVGKERNEL Kernel,
- + IN gctUINT TaskGranularity,
- + IN gctUINT QueueSize,
- + OUT gckVGCOMMAND * Command
- + );
- +
- +/* Destroy an gckVGCOMMAND object. */
- +gceSTATUS
- +gckVGCOMMAND_Destroy(
- + IN gckVGCOMMAND Command
- + );
- +
- +/* Query command buffer attributes. */
- +gceSTATUS
- +gckVGCOMMAND_QueryCommandBuffer(
- + IN gckVGCOMMAND Command,
- + OUT gcsCOMMAND_BUFFER_INFO_PTR Information
- + );
- +
- +/* Allocate a command queue. */
- +gceSTATUS
- +gckVGCOMMAND_Allocate(
- + IN gckVGCOMMAND Command,
- + IN gctSIZE_T Size,
- + OUT gcsCMDBUFFER_PTR * CommandBuffer,
- + OUT gctPOINTER * Data
- + );
- +
- +/* Release memory held by the command queue. */
- +gceSTATUS
- +gckVGCOMMAND_Free(
- + IN gckVGCOMMAND Command,
- + IN gcsCMDBUFFER_PTR CommandBuffer
- + );
- +
- +/* Schedule the command queue for execution. */
- +gceSTATUS
- +gckVGCOMMAND_Execute(
- + IN gckVGCOMMAND Command,
- + IN gcsCMDBUFFER_PTR CommandBuffer
- + );
- +
- +/* Commit a buffer to the command queue. */
- +gceSTATUS
- +gckVGCOMMAND_Commit(
- + IN gckVGCOMMAND Command,
- + IN gcsVGCONTEXT_PTR Context,
- + IN gcsVGCMDQUEUE_PTR Queue,
- + IN gctUINT EntryCount,
- + IN gcsTASK_MASTER_TABLE_PTR TaskTable
- + );
- +
- +/******************************************************************************\
- +********************************* gckVGMMU Object ********************************
- +\******************************************************************************/
- +
- +typedef struct _gckVGMMU * gckVGMMU;
- +
- +/* Construct a new gckVGMMU object. */
- +gceSTATUS
- +gckVGMMU_Construct(
- + IN gckVGKERNEL Kernel,
- + IN gctSIZE_T MmuSize,
- + OUT gckVGMMU * Mmu
- + );
- +
- +/* Destroy an gckVGMMU object. */
- +gceSTATUS
- +gckVGMMU_Destroy(
- + IN gckVGMMU Mmu
- + );
- +
- +/* Allocate pages inside the MMU. */
- +gceSTATUS
- +gckVGMMU_AllocatePages(
- + IN gckVGMMU Mmu,
- + IN gctSIZE_T PageCount,
- + OUT gctPOINTER * PageTable,
- + OUT gctUINT32 * Address
- + );
- +
- +/* Remove a page table from the MMU. */
- +gceSTATUS
- +gckVGMMU_FreePages(
- + IN gckVGMMU Mmu,
- + IN gctPOINTER PageTable,
- + IN gctSIZE_T PageCount
- + );
- +
- +/* Set the MMU page with info. */
- +gceSTATUS
- +gckVGMMU_SetPage(
- + IN gckVGMMU Mmu,
- + IN gctUINT32 PageAddress,
- + IN gctUINT32 *PageEntry
- + );
- +
- +/* Flush MMU */
- +gceSTATUS
- +gckVGMMU_Flush(
- + IN gckVGMMU Mmu
- + );
- +
- +#endif /* gcdENABLE_VG */
- +
- +#ifdef __cplusplus
- +} /* extern "C" */
- +#endif
- +
- +#endif /* __gc_hal_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.c linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.c 2015-03-08 14:27:37.649684500 -0500
- @@ -0,0 +1,795 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#ifdef MODULE
- +#include <linux/module.h>
- +#endif
- +#include <linux/init.h>
- +#include <linux/debugfs.h>
- +#include <linux/slab.h>
- +#ifdef MODVERSIONS
- +#include <linux/modversions.h>
- +#endif
- +#include <linux/stddef.h>
- +#include <linux/sched.h>
- +#include <linux/kernel.h>
- +#include <linux/timer.h>
- +#include <linux/delay.h>
- +#include <linux/errno.h>
- +#include <linux/mutex.h>
- +#include <linux/vmalloc.h>
- +#include <linux/types.h>
- +#include <linux/fs.h>
- +#include <linux/poll.h>
- +#include <asm/uaccess.h>
- +#include <linux/completion.h>
- +#include "gc_hal_kernel_linux.h"
- +
- +/*
- + Prequsite:
- +
- + 1) Debugfs feature must be enabled in the kernel.
- + 1.a) You can enable this, in the compilation of the uImage, all you have to do is, In the "make menuconfig" part,
- + you have to enable the debugfs in the kernel hacking part of the menu.
- +
- + HOW TO USE:
- + 1) insert the driver with the following option logFileSize, Ex: insmod galcore.ko ...... logFileSize=10240
- + This gives a circular buffer of 10 MB
- +
- + 2)Usually after inserting the driver, the debug file system is mounted under /sys/kernel/debug/
- +
- + 2.a)If the debugfs is not mounted, you must do "mount -t debugfs none /sys/kernel/debug"
- +
- + 3) To read what is being printed in the debugfs file system:
- + Ex : cat /sys/kernel/debug/gpu/galcore_trace
- +
- + 4)To write into the debug file system from user side :
- + Ex: echo "hello" > cat /sys/kernel/debug/gpu/galcore_trace
- +
- + 5)To write into debugfs from kernel side, Use the function called gckDebugFileSystemPrint
- +
- +
- + USECASE Kernel Dump:
- +
- + 1) Go to /hal/inc/gc_hal_options.h, and enable the following flags:
- + - # define gcdDUMP 1
- + - # define gcdDUMP_IN_KERNEL 1
- + - # define gcdDUMP_COMMAND 1
- +
- + 2) Go to /hal/kernel/gc_hal_kernel_command.c and disable the following flag
- + -#define gcdSIMPLE_COMMAND_DUMP 0
- +
- + 3) Compile the driver
- + 4) insmod it with the logFileSize option
- + 5) Run an application
- + 6) You can get the dump by cat /sys/kernel/debug/gpu/galcore_trace
- +
- + */
- +
- +/**/
- +typedef va_list gctDBGARGS ;
- +#define gcmkARGS_START(argument, pointer) va_start(argument, pointer)
- +#define gcmkARGS_END(argument) va_end(argument)
- +
- +#define gcmkDBGFSPRINT(ArgumentSize, Message) \
- + { \
- + gctDBGARGS __arguments__; \
- + gcmkARGS_START(__arguments__, Message); \
- + _DebugFSPrint(ArgumentSize, Message, __arguments__);\
- + gcmkARGS_END(__arguments__); \
- + }
- +
- +/*Debug File System Node Struct*/
- +struct _gcsDebugFileSystemNode
- +{
- + /*wait queues for read and write operations*/
- +#if defined(DECLARE_WAIT_QUEUE_HEAD)
- + wait_queue_head_t read_q , write_q ;
- +#else
- + struct wait_queue *read_q , *write_q ;
- +#endif
- + struct dentry *parent ; /*parent directory*/
- + struct dentry *filen ; /*filename*/
- + struct semaphore sem ; /* mutual exclusion semaphore */
- + char *data ; /* The circular buffer data */
- + int size ; /* Size of the buffer pointed to by 'data' */
- + int refcount ; /* Files that have this buffer open */
- + int read_point ; /* Offset in circ. buffer of oldest data */
- + int write_point ; /* Offset in circ. buffer of newest data */
- + int offset ; /* Byte number of read_point in the stream */
- + struct _gcsDebugFileSystemNode *next ;
- +} ;
- +
- +/* amount of data in the queue */
- +#define gcmkNODE_QLEN(node) ( (node)->write_point >= (node)->read_point ? \
- + (node)->write_point - (node)->read_point : \
- + (node)->size - (node)->read_point + (node)->write_point)
- +
- +/* byte number of the last byte in the queue */
- +#define gcmkNODE_FIRST_EMPTY_BYTE(node) ((node)->offset + gcmkNODE_QLEN(node))
- +
- +/*Synchronization primitives*/
- +#define gcmkNODE_READQ(node) (&((node)->read_q))
- +#define gcmkNODE_WRITEQ(node) (&((node)->write_q))
- +#define gcmkNODE_SEM(node) (&((node)->sem))
- +
- +/*Utilities*/
- +#define gcmkMIN(x, y) ((x) < (y) ? (x) : y)
- +
- +/*Debug File System Struct*/
- +typedef struct _gcsDebugFileSystem
- +{
- + gcsDebugFileSystemNode* linkedlist ;
- + gcsDebugFileSystemNode* currentNode ;
- + int isInited ;
- +} gcsDebugFileSystem ;
- +
- +
- +/*debug file system*/
- +static gcsDebugFileSystem gc_dbgfs ;
- +
- +
- +
- +/*******************************************************************************
- + **
- + ** READ & WRITE FUNCTIONS (START)
- + **
- + *******************************************************************************/
- +
- +/*******************************************************************************
- + **
- + ** _ReadFromNode
- + **
- + ** 1) reading bytes out of a circular buffer with wraparound.
- + ** 2)returns caddr_t, pointer to data read, which the caller must free.
- + ** 3) length is (a pointer to) the number of bytes to be read, which will be set by this function to
- + ** be the number of bytes actually returned
- + **
- + *******************************************************************************/
- +static caddr_t
- +_ReadFromNode (
- + gcsDebugFileSystemNode* Node ,
- + size_t *Length ,
- + loff_t *Offset
- + )
- +{
- + caddr_t retval ;
- + int bytes_copied = 0 , n , start_point , remaining ;
- +
- + /* is the user trying to read data that has already scrolled off? */
- + if ( *Offset < Node->offset )
- + {
- + *Offset = Node->offset ;
- + }
- +
- + /* is the user trying to read past EOF? */
- + if ( *Offset >= gcmkNODE_FIRST_EMPTY_BYTE ( Node ) )
- + {
- + return NULL ;
- + }
- +
- + /* find the smaller of the total bytes we have available and what
- + * the user is asking for */
- +
- + *Length = gcmkMIN ( *Length , gcmkNODE_FIRST_EMPTY_BYTE ( Node ) - *Offset ) ;
- +
- + remaining = * Length ;
- +
- + /* figure out where to start based on user's Offset */
- + start_point = Node->read_point + ( *Offset - Node->offset ) ;
- +
- + start_point = start_point % Node->size ;
- +
- + /* allocate memory to return */
- + if ( ( retval = kmalloc ( sizeof (char ) * remaining , GFP_KERNEL ) ) == NULL )
- + return NULL ;
- +
- + /* copy the (possibly noncontiguous) data to our buffer */
- + while ( remaining )
- + {
- + n = gcmkMIN ( remaining , Node->size - start_point ) ;
- + memcpy ( retval + bytes_copied , Node->data + start_point , n ) ;
- + bytes_copied += n ;
- + remaining -= n ;
- + start_point = ( start_point + n ) % Node->size ;
- + }
- +
- + /* advance user's file pointer */
- + *Offset += * Length ;
- +
- + return retval ;
- +}
- +
- +/*******************************************************************************
- + **
- + ** _WriteToNode
- + **
- + ** 1) writes to a circular buffer with wraparound.
- + ** 2)in case of an overflow, it overwrites the oldest unread data.
- + **
- + *********************************************************************************/
- +static void
- +_WriteToNode (
- + gcsDebugFileSystemNode* Node ,
- + caddr_t Buf ,
- + int Length
- + )
- +{
- + int bytes_copied = 0 ;
- + int overflow = 0 ;
- + int n ;
- +
- + if ( Length + gcmkNODE_QLEN ( Node ) >= ( Node->size - 1 ) )
- + {
- + overflow = 1 ;
- +
- + /* in case of overflow, figure out where the new buffer will
- + * begin. we start by figuring out where the current buffer ENDS:
- + * node->parent->offset + gcmkNODE_QLEN. we then advance the end-offset
- + * by the Length of the current write, and work backwards to
- + * figure out what the oldest unoverwritten data will be (i.e.,
- + * size of the buffer). */
- + Node->offset = Node->offset + gcmkNODE_QLEN ( Node ) + Length
- + - Node->size + 1 ;
- + }
- +
- + while ( Length )
- + {
- + /* how many contiguous bytes are available from the write point to
- + * the end of the circular buffer? */
- + n = gcmkMIN ( Length , Node->size - Node->write_point ) ;
- + memcpy ( Node->data + Node->write_point , Buf + bytes_copied , n ) ;
- + bytes_copied += n ;
- + Length -= n ;
- + Node->write_point = ( Node->write_point + n ) % Node->size ;
- + }
- +
- + /* if there is an overflow, reset the read point to read whatever is
- + * the oldest data that we have, that has not yet been
- + * overwritten. */
- + if ( overflow )
- + {
- + Node->read_point = ( Node->write_point + 1 ) % Node->size ;
- + }
- +}
- +
- +
- +/*******************************************************************************
- + **
- + ** PRINTING UTILITY (START)
- + **
- + *******************************************************************************/
- +
- +/*******************************************************************************
- + **
- + ** _GetArgumentSize
- + **
- + **
- + *******************************************************************************/
- +static gctINT
- +_GetArgumentSize (
- + IN gctCONST_STRING Message
- + )
- +{
- + gctINT i , count ;
- +
- + for ( i = 0 , count = 0 ; Message[i] ; i += 1 )
- + {
- + if ( Message[i] == '%' )
- + {
- + count += 1 ;
- + }
- + }
- + return count * sizeof (unsigned int ) ;
- +}
- +
- +/*******************************************************************************
- + **
- + ** _AppendString
- + **
- + **
- + *******************************************************************************/
- +static ssize_t
- +_AppendString (
- + IN gcsDebugFileSystemNode* Node ,
- + IN gctCONST_STRING String ,
- + IN int Length
- + )
- +{
- + caddr_t message = NULL ;
- + int n ;
- +
- + /* if the message is longer than the buffer, just take the beginning
- + * of it, in hopes that the reader (if any) will have time to read
- + * before we wrap around and obliterate it */
- + n = gcmkMIN ( Length , Node->size - 1 ) ;
- +
- + /* make sure we have the memory for it */
- + if ( ( message = kmalloc ( n , GFP_KERNEL ) ) == NULL )
- + return - ENOMEM ;
- +
- + /* copy into our temp buffer */
- + memcpy ( message , String , n ) ;
- +
- + /* now copy it into the circular buffer and free our temp copy */
- + _WriteToNode ( Node , message , n ) ;
- + kfree ( message ) ;
- + return n ;
- +}
- +
- +/*******************************************************************************
- + **
- + ** _DebugFSPrint
- + **
- + **
- + *******************************************************************************/
- +static void
- +_DebugFSPrint (
- + IN unsigned int ArgumentSize ,
- + IN const char* Message ,
- + IN gctDBGARGS Arguments
- +
- + )
- +{
- + char buffer[MAX_LINE_SIZE] ;
- + int len ;
- + down ( gcmkNODE_SEM ( gc_dbgfs.currentNode ) ) ;
- + len = vsnprintf ( buffer , sizeof (buffer ) , Message , *( va_list * ) & Arguments ) ;
- + buffer[len] = '\0' ;
- +
- + /* Add end-of-line if missing. */
- + if ( buffer[len - 1] != '\n' )
- + {
- + buffer[len ++] = '\n' ;
- + buffer[len] = '\0' ;
- + }
- + _AppendString ( gc_dbgfs.currentNode , buffer , len ) ;
- + up ( gcmkNODE_SEM ( gc_dbgfs.currentNode ) ) ;
- + wake_up_interruptible ( gcmkNODE_READQ ( gc_dbgfs.currentNode ) ) ; /* blocked in read*/
- +}
- +
- +/*******************************************************************************
- + **
- + ** LINUX SYSTEM FUNCTIONS (START)
- + **
- + *******************************************************************************/
- +
- +/*******************************************************************************
- + **
- + ** find the vivlog structure associated with an inode.
- + ** returns a pointer to the structure if found, NULL if not found
- + **
- + *******************************************************************************/
- +static gcsDebugFileSystemNode*
- +_GetNodeInfo (
- + IN struct inode *Inode
- + )
- +{
- + gcsDebugFileSystemNode* node ;
- +
- + if ( Inode == NULL )
- + return NULL ;
- +
- + for ( node = gc_dbgfs.linkedlist ; node != NULL ; node = node->next )
- + if ( node->filen->d_inode->i_ino == Inode->i_ino )
- + return node ;
- +
- + return NULL ;
- +}
- +
- +/*******************************************************************************
- + **
- + ** _DebugFSRead
- + **
- + *******************************************************************************/
- +static ssize_t
- +_DebugFSRead (
- + struct file *file ,
- + char __user * buffer ,
- + size_t length ,
- + loff_t * offset
- + )
- +{
- + int retval ;
- + caddr_t data_to_return ;
- + gcsDebugFileSystemNode* node ;
- + /* get the metadata about this emlog */
- + if ( ( node = _GetNodeInfo ( file->f_dentry->d_inode ) ) == NULL )
- + {
- + printk ( "debugfs_read: record not found\n" ) ;
- + return - EIO ;
- + }
- +
- + if ( down_interruptible ( gcmkNODE_SEM ( node ) ) )
- + {
- + return - ERESTARTSYS ;
- + }
- +
- + /* wait until there's data available (unless we do nonblocking reads) */
- + while ( *offset >= gcmkNODE_FIRST_EMPTY_BYTE ( node ) )
- + {
- + up ( gcmkNODE_SEM ( node ) ) ;
- + if ( file->f_flags & O_NONBLOCK )
- + {
- + return - EAGAIN ;
- + }
- + if ( wait_event_interruptible ( ( *( gcmkNODE_READQ ( node ) ) ) , ( *offset < gcmkNODE_FIRST_EMPTY_BYTE ( node ) ) ) )
- + {
- + return - ERESTARTSYS ; /* signal: tell the fs layer to handle it */
- + }
- + /* otherwise loop, but first reacquire the lock */
- + if ( down_interruptible ( gcmkNODE_SEM ( node ) ) )
- + {
- + return - ERESTARTSYS ;
- + }
- + }
- + data_to_return = _ReadFromNode ( node , &length , offset ) ;
- + if ( data_to_return == NULL )
- + {
- + retval = 0 ;
- + goto unlock ;
- + }
- + if ( copy_to_user ( buffer , data_to_return , length ) > 0 )
- + {
- + retval = - EFAULT ;
- + }
- + else
- + {
- + retval = length ;
- + }
- + kfree ( data_to_return ) ;
- +unlock:
- + up ( gcmkNODE_SEM ( node ) ) ;
- + wake_up_interruptible ( gcmkNODE_WRITEQ ( node ) ) ;
- + return retval ;
- +}
- +
- +/*******************************************************************************
- + **
- + **_DebugFSWrite
- + **
- + *******************************************************************************/
- +static ssize_t
- +_DebugFSWrite (
- + struct file *file ,
- + const char __user * buffer ,
- + size_t length ,
- + loff_t * offset
- + )
- +{
- + caddr_t message = NULL ;
- + int n ;
- + gcsDebugFileSystemNode*node ;
- +
- + /* get the metadata about this log */
- + if ( ( node = _GetNodeInfo ( file->f_dentry->d_inode ) ) == NULL )
- + {
- + return - EIO ;
- + }
- +
- + if ( down_interruptible ( gcmkNODE_SEM ( node ) ) )
- + {
- + return - ERESTARTSYS ;
- + }
- +
- + /* if the message is longer than the buffer, just take the beginning
- + * of it, in hopes that the reader (if any) will have time to read
- + * before we wrap around and obliterate it */
- + n = gcmkMIN ( length , node->size - 1 ) ;
- +
- + /* make sure we have the memory for it */
- + if ( ( message = kmalloc ( n , GFP_KERNEL ) ) == NULL )
- + {
- + up ( gcmkNODE_SEM ( node ) ) ;
- + return - ENOMEM ;
- + }
- +
- + /* copy into our temp buffer */
- + if ( copy_from_user ( message , buffer , n ) > 0 )
- + {
- + up ( gcmkNODE_SEM ( node ) ) ;
- + kfree ( message ) ;
- + return - EFAULT ;
- + }
- +
- + /* now copy it into the circular buffer and free our temp copy */
- + _WriteToNode ( node , message , n ) ;
- +
- + kfree ( message ) ;
- + up ( gcmkNODE_SEM ( node ) ) ;
- +
- + /* wake up any readers that might be waiting for the data. we call
- + * schedule in the vague hope that a reader will run before the
- + * writer's next write, to avoid losing data. */
- + wake_up_interruptible ( gcmkNODE_READQ ( node ) ) ;
- +
- + return n ;
- +}
- +
- +/*******************************************************************************
- + **
- + ** File Operations Table
- + **
- + *******************************************************************************/
- +static const struct file_operations debugfs_operations = {
- + .owner = THIS_MODULE ,
- + .read = _DebugFSRead ,
- + .write = _DebugFSWrite ,
- +} ;
- +
- +/*******************************************************************************
- + **
- + ** INTERFACE FUNCTIONS (START)
- + **
- + *******************************************************************************/
- +
- +/*******************************************************************************
- + **
- + ** gckDebugFileSystemIsEnabled
- + **
- + **
- + ** INPUT:
- + **
- + ** OUTPUT:
- + **
- + *******************************************************************************/
- +
- +
- +gctINT
- +gckDebugFileSystemIsEnabled ( void )
- +{
- + return gc_dbgfs.isInited ;
- +}
- +/*******************************************************************************
- + **
- + ** gckDebugFileSystemInitialize
- + **
- + **
- + ** INPUT:
- + **
- + ** OUTPUT:
- + **
- + *******************************************************************************/
- +
- +gctINT
- +gckDebugFileSystemInitialize ( void )
- +{
- + if ( ! gc_dbgfs.isInited )
- + {
- + gc_dbgfs.linkedlist = gcvNULL ;
- + gc_dbgfs.currentNode = gcvNULL ;
- + gc_dbgfs.isInited = 1 ;
- + }
- + return gc_dbgfs.isInited ;
- +}
- +/*******************************************************************************
- + **
- + ** gckDebugFileSystemTerminate
- + **
- + **
- + ** INPUT:
- + **
- + ** OUTPUT:
- + **
- + *******************************************************************************/
- +
- +gctINT
- +gckDebugFileSystemTerminate ( void )
- +{
- + gcsDebugFileSystemNode * next = gcvNULL ;
- + gcsDebugFileSystemNode * temp = gcvNULL ;
- + if ( gc_dbgfs.isInited )
- + {
- + temp = gc_dbgfs.linkedlist ;
- + while ( temp != gcvNULL )
- + {
- + next = temp->next ;
- + gckDebugFileSystemFreeNode ( temp ) ;
- + kfree ( temp ) ;
- + temp = next ;
- + }
- + gc_dbgfs.isInited = 0 ;
- + }
- + return 0 ;
- +}
- +
- +
- +/*******************************************************************************
- + **
- + ** gckDebugFileSystemCreateNode
- + **
- + **
- + ** INPUT:
- + **
- + ** OUTPUT:
- + **
- + ** gckDebugFileSystemFreeNode * Device
- + ** Pointer to a variable receiving the gcsDebugFileSystemNode object pointer on
- + ** success.
- + *********************************************************************************/
- +
- +gctINT
- +gckDebugFileSystemCreateNode (
- + IN gctINT SizeInKB ,
- + IN gctCONST_STRING ParentName ,
- + IN gctCONST_STRING NodeName ,
- + OUT gcsDebugFileSystemNode **Node
- + )
- +{
- + gcsDebugFileSystemNode*node ;
- + /* allocate space for our metadata and initialize it */
- + if ( ( node = kmalloc ( sizeof (gcsDebugFileSystemNode ) , GFP_KERNEL ) ) == NULL )
- + goto struct_malloc_failed ;
- +
- + /*Zero it out*/
- + memset ( node , 0 , sizeof (gcsDebugFileSystemNode ) ) ;
- +
- + /*Init the sync primitives*/
- +#if defined(DECLARE_WAIT_QUEUE_HEAD)
- + init_waitqueue_head ( gcmkNODE_READQ ( node ) ) ;
- +#else
- + init_waitqueue ( gcmkNODE_READQ ( node ) ) ;
- +#endif
- +
- +#if defined(DECLARE_WAIT_QUEUE_HEAD)
- + init_waitqueue_head ( gcmkNODE_WRITEQ ( node ) ) ;
- +#else
- + init_waitqueue ( gcmkNODE_WRITEQ ( node ) ) ;
- +#endif
- + sema_init ( gcmkNODE_SEM ( node ) , 1 ) ;
- + /*End the sync primitives*/
- +
- +
- + /* figure out how much of a buffer this should be and allocate the buffer */
- + node->size = 1024 * SizeInKB ;
- + if ( ( node->data = ( char * ) vmalloc ( sizeof (char ) * node->size ) ) == NULL )
- + goto data_malloc_failed ;
- +
- + /*creating the debug file system*/
- + node->parent = debugfs_create_dir ( ParentName , NULL ) ;
- +
- + /*creating the file*/
- + node->filen = debugfs_create_file ( NodeName , S_IRUGO | S_IWUSR , node->parent , NULL ,
- + &debugfs_operations ) ;
- +
- + /* add it to our linked list */
- + node->next = gc_dbgfs.linkedlist ;
- + gc_dbgfs.linkedlist = node ;
- +
- + /* pass the struct back */
- + *Node = node ;
- + return 0 ;
- +
- + vfree ( node->data ) ;
- +data_malloc_failed:
- + kfree ( node ) ;
- +struct_malloc_failed:
- + return - ENOMEM ;
- +}
- +
- +/*******************************************************************************
- + **
- + ** gckDebugFileSystemFreeNode
- + **
- + **
- + ** INPUT:
- + **
- + ** OUTPUT:
- + **
- + *******************************************************************************/
- +void
- +gckDebugFileSystemFreeNode (
- + IN gcsDebugFileSystemNode * Node
- + )
- +{
- +
- + gcsDebugFileSystemNode **ptr ;
- +
- + if ( Node == NULL )
- + {
- + printk ( "null passed to free_vinfo\n" ) ;
- + return ;
- + }
- +
- + down ( gcmkNODE_SEM ( Node ) ) ;
- + /*free data*/
- + vfree ( Node->data ) ;
- +
- + /*Close Debug fs*/
- + if ( Node->filen )
- + {
- + debugfs_remove ( Node->filen ) ;
- + }
- + if ( Node->parent )
- + {
- + debugfs_remove ( Node->parent ) ;
- + }
- +
- + /* now delete the node from the linked list */
- + ptr = & ( gc_dbgfs.linkedlist ) ;
- + while ( *ptr != Node )
- + {
- + if ( ! *ptr )
- + {
- + printk ( "corrupt info list!\n" ) ;
- + break ;
- + }
- + else
- + ptr = & ( ( **ptr ).next ) ;
- + }
- + *ptr = Node->next ;
- + up ( gcmkNODE_SEM ( Node ) ) ;
- +}
- +
- +/*******************************************************************************
- + **
- + ** gckDebugFileSystemSetCurrentNode
- + **
- + **
- + ** INPUT:
- + **
- + ** OUTPUT:
- + **
- + *******************************************************************************/
- +void
- +gckDebugFileSystemSetCurrentNode (
- + IN gcsDebugFileSystemNode * Node
- + )
- +{
- + gc_dbgfs.currentNode = Node ;
- +}
- +
- +/*******************************************************************************
- + **
- + ** gckDebugFileSystemGetCurrentNode
- + **
- + **
- + ** INPUT:
- + **
- + ** OUTPUT:
- + **
- + *******************************************************************************/
- +void
- +gckDebugFileSystemGetCurrentNode (
- + OUT gcsDebugFileSystemNode ** Node
- + )
- +{
- + *Node = gc_dbgfs.currentNode ;
- +}
- +
- +/*******************************************************************************
- + **
- + ** gckDebugFileSystemPrint
- + **
- + **
- + ** INPUT:
- + **
- + ** OUTPUT:
- + **
- + *******************************************************************************/
- +void
- +gckDebugFileSystemPrint (
- + IN gctCONST_STRING Message ,
- + ...
- + )
- +{
- + gcmkDBGFSPRINT ( _GetArgumentSize ( Message ) , Message ) ;
- +}
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.h linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.h 2015-03-08 14:27:37.649684500 -0500
- @@ -0,0 +1,84 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include <stdarg.h>
- +
- +#ifndef __gc_hal_kernel_debugfs_h_
- +#define __gc_hal_kernel_debugfs_h_
- +
- + #define MAX_LINE_SIZE 768 /* Max bytes for a line of debug info */
- +
- +
- + typedef struct _gcsDebugFileSystemNode gcsDebugFileSystemNode ;
- +
- +
- +/*******************************************************************************
- + **
- + ** System Related
- + **
- + *******************************************************************************/
- +
- +gctINT gckDebugFileSystemIsEnabled(void);
- +
- +gctINT gckDebugFileSystemInitialize(void);
- +
- +gctINT gckDebugFileSystemTerminate(void);
- +
- +
- +/*******************************************************************************
- + **
- + ** Node Related
- + **
- + *******************************************************************************/
- +
- +gctINT gckDebugFileSystemCreateNode(
- + IN gctINT SizeInKB,
- + IN gctCONST_STRING ParentName ,
- + IN gctCONST_STRING NodeName,
- + OUT gcsDebugFileSystemNode **Node
- + );
- +
- +
- +void gckDebugFileSystemFreeNode(
- + IN gcsDebugFileSystemNode * Node
- + );
- +
- +
- +
- +void gckDebugFileSystemSetCurrentNode(
- + IN gcsDebugFileSystemNode * Node
- + );
- +
- +
- +
- +void gckDebugFileSystemGetCurrentNode(
- + OUT gcsDebugFileSystemNode ** Node
- + );
- +
- +
- +void gckDebugFileSystemPrint(
- + IN gctCONST_STRING Message,
- + ...
- + );
- +
- +#endif
- +
- +
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h 2015-03-08 14:27:37.649684500 -0500
- @@ -0,0 +1,102 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_kernel_debug_h_
- +#define __gc_hal_kernel_debug_h_
- +
- +#include <gc_hal_kernel_linux.h>
- +#include <linux/spinlock.h>
- +#include <linux/time.h>
- +#include <stdarg.h>
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +/******************************************************************************\
- +****************************** OS-dependent Macros *****************************
- +\******************************************************************************/
- +
- +typedef va_list gctARGUMENTS;
- +
- +#define gcmkARGUMENTS_START(Arguments, Pointer) \
- + va_start(Arguments, Pointer)
- +
- +#define gcmkARGUMENTS_END(Arguments) \
- + va_end(Arguments)
- +
- +#define gcmkDECLARE_LOCK(__spinLock__) \
- + static DEFINE_SPINLOCK(__spinLock__);
- +
- +#define gcmkLOCKSECTION(__spinLock__) \
- + spin_lock(&__spinLock__)
- +
- +#define gcmkUNLOCKSECTION(__spinLock__) \
- + spin_unlock(&__spinLock__)
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
- +# define gcmkGETPROCESSID() \
- + task_tgid_vnr(current)
- +#else
- +# define gcmkGETPROCESSID() \
- + current->tgid
- +#endif
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
- +# define gcmkGETTHREADID() \
- + task_pid_vnr(current)
- +#else
- +# define gcmkGETTHREADID() \
- + current->pid
- +#endif
- +
- +#define gcmkOUTPUT_STRING(String) \
- + if(gckDebugFileSystemIsEnabled()) \
- + gckDebugFileSystemPrint(String);\
- + else\
- + printk(String); \
- + touch_softlockup_watchdog()
- +
- +
- +#define gcmkSPRINTF(Destination, Size, Message, Value) \
- + snprintf(Destination, Size, Message, Value)
- +
- +#define gcmkSPRINTF2(Destination, Size, Message, Value1, Value2) \
- + snprintf(Destination, Size, Message, Value1, Value2)
- +
- +#define gcmkSPRINTF3(Destination, Size, Message, Value1, Value2, Value3) \
- + snprintf(Destination, Size, Message, Value1, Value2, Value3)
- +
- +#define gcmkVSPRINTF(Destination, Size, Message, Arguments) \
- + vsnprintf(Destination, Size, Message, *(va_list *) &Arguments)
- +
- +#define gcmkSTRCAT(Destination, Size, String) \
- + strncat(Destination, String, Size)
- +
- +/* If not zero, forces data alignment in the variable argument list
- + by its individual size. */
- +#define gcdALIGNBYSIZE 1
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* __gc_hal_kernel_debug_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c 2015-03-08 14:27:37.653684501 -0500
- @@ -0,0 +1,1676 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal_kernel_linux.h"
- +#include <linux/pagemap.h>
- +#include <linux/seq_file.h>
- +#include <linux/mm.h>
- +#include <linux/mman.h>
- +#include <linux/slab.h>
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
- +#include <mach/hardware.h>
- +#endif
- +#include <linux/pm_runtime.h>
- +
- +#define _GC_OBJ_ZONE gcvZONE_DEVICE
- +
- +#define DEBUG_FILE "galcore_trace"
- +#define PARENT_FILE "gpu"
- +
- +
- +#ifdef FLAREON
- + static struct dove_gpio_irq_handler gc500_handle;
- +#endif
- +
- +#define gcmIS_CORE_PRESENT(Device, Core) (Device->irqLines[Core] > 0)
- +
- +/******************************************************************************\
- +*************************** Memory Allocation Wrappers *************************
- +\******************************************************************************/
- +
- +static gceSTATUS
- +_AllocateMemory(
- + IN gckGALDEVICE Device,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER *Logical,
- + OUT gctPHYS_ADDR *Physical,
- + OUT gctUINT32 *PhysAddr
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Device=0x%x Bytes=%lu", Device, Bytes);
- +
- + gcmkVERIFY_ARGUMENT(Device != NULL);
- + gcmkVERIFY_ARGUMENT(Logical != NULL);
- + gcmkVERIFY_ARGUMENT(Physical != NULL);
- + gcmkVERIFY_ARGUMENT(PhysAddr != NULL);
- +
- + gcmkONERROR(gckOS_AllocateContiguous(
- + Device->os, gcvFALSE, &Bytes, Physical, Logical
- + ));
- +
- + *PhysAddr = ((PLINUX_MDL)*Physical)->dmaHandle - Device->baseAddress;
- +
- + /* Success. */
- + gcmkFOOTER_ARG(
- + "*Logical=0x%x *Physical=0x%x *PhysAddr=0x%08x",
- + *Logical, *Physical, *PhysAddr
- + );
- +
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +
- +static gceSTATUS
- +_FreeMemory(
- + IN gckGALDEVICE Device,
- + IN gctPOINTER Logical,
- + IN gctPHYS_ADDR Physical)
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Device=0x%x Logical=0x%x Physical=0x%x",
- + Device, Logical, Physical);
- +
- + gcmkVERIFY_ARGUMENT(Device != NULL);
- +
- + status = gckOS_FreeContiguous(
- + Device->os, Physical, Logical,
- + ((PLINUX_MDL) Physical)->numPages * PAGE_SIZE
- + );
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +
- +
- +/******************************************************************************\
- +******************************* Interrupt Handler ******************************
- +\******************************************************************************/
- +static irqreturn_t isrRoutine(int irq, void *ctxt)
- +{
- + gceSTATUS status;
- + gckGALDEVICE device;
- +
- + device = (gckGALDEVICE) ctxt;
- +
- + /* Call kernel interrupt notification. */
- + status = gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR], gcvNOTIFY_INTERRUPT, gcvTRUE);
- +
- + if (gcmIS_SUCCESS(status))
- + {
- + device->dataReadys[gcvCORE_MAJOR] = gcvTRUE;
- +
- + up(&device->semas[gcvCORE_MAJOR]);
- +
- + return IRQ_HANDLED;
- + }
- +
- + return IRQ_NONE;
- +}
- +
- +static int threadRoutine(void *ctxt)
- +{
- + gckGALDEVICE device = (gckGALDEVICE) ctxt;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
- + "Starting isr Thread with extension=%p",
- + device);
- +
- + for (;;)
- + {
- + static int down;
- +
- + down = down_interruptible(&device->semas[gcvCORE_MAJOR]);
- + if (down); /*To make gcc 4.6 happye*/
- + device->dataReadys[gcvCORE_MAJOR] = gcvFALSE;
- +
- + if (device->killThread == gcvTRUE)
- + {
- + /* The daemon exits. */
- + while (!kthread_should_stop())
- + {
- + gckOS_Delay(device->os, 1);
- + }
- +
- + return 0;
- + }
- +
- + gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR], gcvNOTIFY_INTERRUPT, gcvFALSE);
- + }
- +}
- +
- +static irqreturn_t isrRoutine2D(int irq, void *ctxt)
- +{
- + gceSTATUS status;
- + gckGALDEVICE device;
- +
- + device = (gckGALDEVICE) ctxt;
- +
- + /* Call kernel interrupt notification. */
- + status = gckKERNEL_Notify(device->kernels[gcvCORE_2D], gcvNOTIFY_INTERRUPT, gcvTRUE);
- +
- + if (gcmIS_SUCCESS(status))
- + {
- + device->dataReadys[gcvCORE_2D] = gcvTRUE;
- +
- + up(&device->semas[gcvCORE_2D]);
- +
- + return IRQ_HANDLED;
- + }
- +
- + return IRQ_NONE;
- +}
- +
- +static int threadRoutine2D(void *ctxt)
- +{
- + gckGALDEVICE device = (gckGALDEVICE) ctxt;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
- + "Starting isr Thread with extension=%p",
- + device);
- +
- + for (;;)
- + {
- + static int down;
- +
- + down = down_interruptible(&device->semas[gcvCORE_2D]);
- + if (down); /*To make gcc 4.6 happye*/
- + device->dataReadys[gcvCORE_2D] = gcvFALSE;
- +
- + if (device->killThread == gcvTRUE)
- + {
- + /* The daemon exits. */
- + while (!kthread_should_stop())
- + {
- + gckOS_Delay(device->os, 1);
- + }
- +
- + return 0;
- + }
- +
- + gckKERNEL_Notify(device->kernels[gcvCORE_2D], gcvNOTIFY_INTERRUPT, gcvFALSE);
- + }
- +}
- +
- +static irqreturn_t isrRoutineVG(int irq, void *ctxt)
- +{
- +#if gcdENABLE_VG
- + gceSTATUS status;
- + gckGALDEVICE device;
- +
- + device = (gckGALDEVICE) ctxt;
- +
- + /* Serve the interrupt. */
- + status = gckVGINTERRUPT_Enque(device->kernels[gcvCORE_VG]->vg->interrupt);
- +
- + /* Determine the return value. */
- + return (status == gcvSTATUS_NOT_OUR_INTERRUPT)
- + ? IRQ_RETVAL(0)
- + : IRQ_RETVAL(1);
- +#else
- + return IRQ_NONE;
- +#endif
- +}
- +
- +static int threadRoutineVG(void *ctxt)
- +{
- + gckGALDEVICE device = (gckGALDEVICE) ctxt;
- +
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
- + "Starting isr Thread with extension=%p",
- + device);
- +
- + for (;;)
- + {
- + static int down;
- +
- + down = down_interruptible(&device->semas[gcvCORE_VG]);
- + if (down); /*To make gcc 4.6 happye*/
- + device->dataReadys[gcvCORE_VG] = gcvFALSE;
- +
- + if (device->killThread == gcvTRUE)
- + {
- + /* The daemon exits. */
- + while (!kthread_should_stop())
- + {
- + gckOS_Delay(device->os, 1);
- + }
- +
- + return 0;
- + }
- +
- + gckKERNEL_Notify(device->kernels[gcvCORE_VG], gcvNOTIFY_INTERRUPT, gcvFALSE);
- + }
- +}
- +
- +/******************************************************************************\
- +******************************* gckGALDEVICE Code ******************************
- +\******************************************************************************/
- +
- +/*******************************************************************************
- +**
- +** gckGALDEVICE_Construct
- +**
- +** Constructor.
- +**
- +** INPUT:
- +**
- +** OUTPUT:
- +**
- +** gckGALDEVICE * Device
- +** Pointer to a variable receiving the gckGALDEVICE object pointer on
- +** success.
- +*/
- +gceSTATUS
- +gckGALDEVICE_Construct(
- + IN gctINT IrqLine,
- + IN gctUINT32 RegisterMemBase,
- + IN gctSIZE_T RegisterMemSize,
- + IN gctINT IrqLine2D,
- + IN gctUINT32 RegisterMemBase2D,
- + IN gctSIZE_T RegisterMemSize2D,
- + IN gctINT IrqLineVG,
- + IN gctUINT32 RegisterMemBaseVG,
- + IN gctSIZE_T RegisterMemSizeVG,
- + IN gctUINT32 ContiguousBase,
- + IN gctSIZE_T ContiguousSize,
- + IN gctSIZE_T BankSize,
- + IN gctINT FastClear,
- + IN gctINT Compression,
- + IN gctUINT32 PhysBaseAddr,
- + IN gctUINT32 PhysSize,
- + IN gctINT Signal,
- + IN gctUINT LogFileSize,
- + IN struct device *pdev,
- + IN gctINT PowerManagement,
- + IN gctINT GpuProfiler,
- + OUT gckGALDEVICE *Device
- + )
- +{
- + gctUINT32 internalBaseAddress = 0, internalAlignment = 0;
- + gctUINT32 externalBaseAddress = 0, externalAlignment = 0;
- + gctUINT32 horizontalTileSize, verticalTileSize;
- + struct resource* mem_region;
- + gctUINT32 physAddr;
- + gctUINT32 physical;
- + gckGALDEVICE device;
- + gceSTATUS status;
- + gctINT32 i;
- + gceHARDWARE_TYPE type;
- + gckDB sharedDB = gcvNULL;
- + gckKERNEL kernel = gcvNULL;
- +
- + gcmkHEADER_ARG("IrqLine=%d RegisterMemBase=0x%08x RegisterMemSize=%u "
- + "IrqLine2D=%d RegisterMemBase2D=0x%08x RegisterMemSize2D=%u "
- + "IrqLineVG=%d RegisterMemBaseVG=0x%08x RegisterMemSizeVG=%u "
- + "ContiguousBase=0x%08x ContiguousSize=%lu BankSize=%lu "
- + "FastClear=%d Compression=%d PhysBaseAddr=0x%x PhysSize=%d Signal=%d",
- + IrqLine, RegisterMemBase, RegisterMemSize,
- + IrqLine2D, RegisterMemBase2D, RegisterMemSize2D,
- + IrqLineVG, RegisterMemBaseVG, RegisterMemSizeVG,
- + ContiguousBase, ContiguousSize, BankSize, FastClear, Compression,
- + PhysBaseAddr, PhysSize, Signal);
- +
- + /* Allocate device structure. */
- + device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL);
- +
- + if (!device)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + memset(device, 0, sizeof(struct _gckGALDEVICE));
- +
- + device->dbgnode = gcvNULL;
- + if(LogFileSize != 0)
- + {
- + if(gckDebugFileSystemCreateNode(LogFileSize,PARENT_FILE,DEBUG_FILE,&(device->dbgnode)) != 0)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): Failed to create the debug file system %s/%s \n",
- + __FUNCTION__, __LINE__,
- + PARENT_FILE, DEBUG_FILE
- + );
- + }
- + else
- + {
- + /*Everything is OK*/
- + gckDebugFileSystemSetCurrentNode(device->dbgnode);
- + }
- + }
- +#ifdef CONFIG_PM
- + /*Init runtime pm for gpu*/
- + pm_runtime_enable(pdev);
- + device->pmdev = pdev;
- +#endif
- +
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
- + /*get gpu regulator*/
- + device->gpu_regulator = regulator_get(pdev, "cpu_vddgpu");
- +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- + device->gpu_regulator = devm_regulator_get(pdev, "pu");
- +#endif
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- + if (IS_ERR(device->gpu_regulator)) {
- + gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): Failed to get gpu regulator %s/%s \n",
- + __FUNCTION__, __LINE__,
- + PARENT_FILE, DEBUG_FILE);
- + gcmkONERROR(gcvSTATUS_NOT_FOUND);
- + }
- +#endif
- + /*Initialize the clock structure*/
- + if (IrqLine != -1) {
- + device->clk_3d_core = clk_get(pdev, "gpu3d_clk");
- + if (!IS_ERR(device->clk_3d_core)) {
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
- + if (cpu_is_mx6q()) {
- + device->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk");
- + if (IS_ERR(device->clk_3d_shader)) {
- + IrqLine = -1;
- + clk_put(device->clk_3d_core);
- + device->clk_3d_core = NULL;
- + device->clk_3d_shader = NULL;
- + gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
- + }
- + }
- +#else
- + device->clk_3d_axi = clk_get(pdev, "gpu3d_axi_clk");
- + device->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk");
- + if (IS_ERR(device->clk_3d_shader)) {
- + IrqLine = -1;
- + clk_put(device->clk_3d_core);
- + device->clk_3d_core = NULL;
- + device->clk_3d_shader = NULL;
- + gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
- + }
- +#endif
- + } else {
- + IrqLine = -1;
- + device->clk_3d_core = NULL;
- + gckOS_Print("galcore: clk_get gpu3d_clk failed, disable 3d!\n");
- + }
- + }
- + if ((IrqLine2D != -1) || (IrqLineVG != -1)) {
- + device->clk_2d_core = clk_get(pdev, "gpu2d_clk");
- + if (IS_ERR(device->clk_2d_core)) {
- + IrqLine2D = -1;
- + IrqLineVG = -1;
- + device->clk_2d_core = NULL;
- + gckOS_Print("galcore: clk_get 2d core clock failed, disable 2d/vg!\n");
- + } else {
- + if (IrqLine2D != -1) {
- + device->clk_2d_axi = clk_get(pdev, "gpu2d_axi_clk");
- + if (IS_ERR(device->clk_2d_axi)) {
- + device->clk_2d_axi = NULL;
- + IrqLine2D = -1;
- + gckOS_Print("galcore: clk_get 2d axi clock failed, disable 2d\n");
- + }
- + }
- + if (IrqLineVG != -1) {
- + device->clk_vg_axi = clk_get(pdev, "openvg_axi_clk");
- + if (IS_ERR(device->clk_vg_axi)) {
- + IrqLineVG = -1;
- + device->clk_vg_axi = NULL;
- + gckOS_Print("galcore: clk_get vg clock failed, disable vg!\n");
- + }
- + }
- + }
- + }
- +
- + if (IrqLine != -1)
- + {
- + device->requestedRegisterMemBases[gcvCORE_MAJOR] = RegisterMemBase;
- + device->requestedRegisterMemSizes[gcvCORE_MAJOR] = RegisterMemSize;
- + }
- +
- + if (IrqLine2D != -1)
- + {
- + device->requestedRegisterMemBases[gcvCORE_2D] = RegisterMemBase2D;
- + device->requestedRegisterMemSizes[gcvCORE_2D] = RegisterMemSize2D;
- + }
- +
- + if (IrqLineVG != -1)
- + {
- + device->requestedRegisterMemBases[gcvCORE_VG] = RegisterMemBaseVG;
- + device->requestedRegisterMemSizes[gcvCORE_VG] = RegisterMemSizeVG;
- + }
- +
- + device->requestedContiguousBase = 0;
- + device->requestedContiguousSize = 0;
- +
- +
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + physical = device->requestedRegisterMemBases[i];
- +
- + /* Set up register memory region. */
- + if (physical != 0)
- + {
- + mem_region = request_mem_region(
- + physical, device->requestedRegisterMemSizes[i], "galcore register region"
- + );
- +
- + if (mem_region == gcvNULL)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): Failed to claim %lu bytes @ 0x%08X\n",
- + __FUNCTION__, __LINE__,
- + physical, device->requestedRegisterMemSizes[i]
- + );
- +
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +
- + device->registerBases[i] = (gctPOINTER) ioremap_nocache(
- + physical, device->requestedRegisterMemSizes[i]);
- +
- + if (device->registerBases[i] == gcvNULL)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): Unable to map %ld bytes @ 0x%08X\n",
- + __FUNCTION__, __LINE__,
- + physical, device->requestedRegisterMemSizes[i]
- + );
- +
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +
- + physical += device->requestedRegisterMemSizes[i];
- + }
- + else
- + {
- + device->registerBases[i] = gcvNULL;
- + }
- + }
- +
- + /* Set the base address */
- + device->baseAddress = PhysBaseAddr;
- +
- + /* Construct the gckOS object. */
- + gcmkONERROR(gckOS_Construct(device, &device->os));
- +
- + if (IrqLine != -1)
- + {
- + /* Construct the gckKERNEL object. */
- + gcmkONERROR(gckKERNEL_Construct(
- + device->os, gcvCORE_MAJOR, device,
- + gcvNULL, &device->kernels[gcvCORE_MAJOR]));
- +
- + sharedDB = device->kernels[gcvCORE_MAJOR]->db;
- +
- + /* Initialize core mapping */
- + for (i = 0; i < 8; i++)
- + {
- + device->coreMapping[i] = gcvCORE_MAJOR;
- + }
- +
- + /* Setup the ISR manager. */
- + gcmkONERROR(gckHARDWARE_SetIsrManager(
- + device->kernels[gcvCORE_MAJOR]->hardware,
- + (gctISRMANAGERFUNC) gckGALDEVICE_Enable_ISR,
- + (gctISRMANAGERFUNC) gckGALDEVICE_Disable_ISR,
- + device
- + ));
- +
- + gcmkONERROR(gckHARDWARE_SetFastClear(
- + device->kernels[gcvCORE_MAJOR]->hardware, FastClear, Compression
- + ));
- +
- + gcmkONERROR(gckHARDWARE_SetPowerManagement(
- + device->kernels[gcvCORE_MAJOR]->hardware, PowerManagement
- + ));
- +
- + gcmkONERROR(gckHARDWARE_SetGpuProfiler(
- + device->kernels[gcvCORE_MAJOR]->hardware, GpuProfiler
- + ));
- +
- +#if COMMAND_PROCESSOR_VERSION == 1
- + /* Start the command queue. */
- + gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_MAJOR]->command));
- +#endif
- + }
- + else
- + {
- + device->kernels[gcvCORE_MAJOR] = gcvNULL;
- + }
- +
- + if (IrqLine2D != -1)
- + {
- + gcmkONERROR(gckKERNEL_Construct(
- + device->os, gcvCORE_2D, device,
- + sharedDB, &device->kernels[gcvCORE_2D]));
- +
- + if (sharedDB == gcvNULL) sharedDB = device->kernels[gcvCORE_2D]->db;
- +
- + /* Verify the hardware type */
- + gcmkONERROR(gckHARDWARE_GetType(device->kernels[gcvCORE_2D]->hardware, &type));
- +
- + if (type != gcvHARDWARE_2D)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): Unexpected hardware type: %d\n",
- + __FUNCTION__, __LINE__,
- + type
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + /* Initialize core mapping */
- + if (device->kernels[gcvCORE_MAJOR] == gcvNULL)
- + {
- + for (i = 0; i < 8; i++)
- + {
- + device->coreMapping[i] = gcvCORE_2D;
- + }
- + }
- + else
- + {
- + device->coreMapping[gcvHARDWARE_2D] = gcvCORE_2D;
- + }
- +
- + /* Setup the ISR manager. */
- + gcmkONERROR(gckHARDWARE_SetIsrManager(
- + device->kernels[gcvCORE_2D]->hardware,
- + (gctISRMANAGERFUNC) gckGALDEVICE_Enable_ISR,
- + (gctISRMANAGERFUNC) gckGALDEVICE_Disable_ISR,
- + device
- + ));
- +
- + gcmkONERROR(gckHARDWARE_SetPowerManagement(
- + device->kernels[gcvCORE_2D]->hardware, PowerManagement
- + ));
- +
- +
- +#if COMMAND_PROCESSOR_VERSION == 1
- + /* Start the command queue. */
- + gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_2D]->command));
- +#endif
- + }
- + else
- + {
- + device->kernels[gcvCORE_2D] = gcvNULL;
- + }
- +
- + if (IrqLineVG != -1)
- + {
- +#if gcdENABLE_VG
- + gcmkONERROR(gckKERNEL_Construct(
- + device->os, gcvCORE_VG, device,
- + sharedDB, &device->kernels[gcvCORE_VG]));
- + /* Initialize core mapping */
- + if (device->kernels[gcvCORE_MAJOR] == gcvNULL
- + && device->kernels[gcvCORE_2D] == gcvNULL
- + )
- + {
- + for (i = 0; i < 8; i++)
- + {
- + device->coreMapping[i] = gcvCORE_VG;
- + }
- + }
- + else
- + {
- + device->coreMapping[gcvHARDWARE_VG] = gcvCORE_VG;
- + }
- +
- +
- + gcmkONERROR(gckVGHARDWARE_SetPowerManagement(
- + device->kernels[gcvCORE_VG]->vg->hardware,
- + PowerManagement
- + ));
- +
- +#endif
- + }
- + else
- + {
- + device->kernels[gcvCORE_VG] = gcvNULL;
- + }
- +
- + /* Initialize the ISR. */
- + device->irqLines[gcvCORE_MAJOR] = IrqLine;
- + device->irqLines[gcvCORE_2D] = IrqLine2D;
- + device->irqLines[gcvCORE_VG] = IrqLineVG;
- +
- + /* Initialize the kernel thread semaphores. */
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + if (device->irqLines[i] != -1) sema_init(&device->semas[i], 0);
- + }
- +
- + device->signal = Signal;
- +
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + if (device->kernels[i] != gcvNULL) break;
- + }
- +
- + if (i == gcdMAX_GPU_COUNT)
- + {
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- +#if gcdENABLE_VG
- + if (i == gcvCORE_VG)
- + {
- + /* Query the ceiling of the system memory. */
- + gcmkONERROR(gckVGHARDWARE_QuerySystemMemory(
- + device->kernels[i]->vg->hardware,
- + &device->systemMemorySize,
- + &device->systemMemoryBaseAddress
- + ));
- + /* query the amount of video memory */
- + gcmkONERROR(gckVGHARDWARE_QueryMemory(
- + device->kernels[i]->vg->hardware,
- + &device->internalSize, &internalBaseAddress, &internalAlignment,
- + &device->externalSize, &externalBaseAddress, &externalAlignment,
- + &horizontalTileSize, &verticalTileSize
- + ));
- + }
- + else
- +#endif
- + {
- + /* Query the ceiling of the system memory. */
- + gcmkONERROR(gckHARDWARE_QuerySystemMemory(
- + device->kernels[i]->hardware,
- + &device->systemMemorySize,
- + &device->systemMemoryBaseAddress
- + ));
- +
- + /* query the amount of video memory */
- + gcmkONERROR(gckHARDWARE_QueryMemory(
- + device->kernels[i]->hardware,
- + &device->internalSize, &internalBaseAddress, &internalAlignment,
- + &device->externalSize, &externalBaseAddress, &externalAlignment,
- + &horizontalTileSize, &verticalTileSize
- + ));
- + }
- +
- +
- + /* Grab the first availiable kernel */
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + if (device->irqLines[i] != -1)
- + {
- + kernel = device->kernels[i];
- + break;
- + }
- + }
- +
- + /* Set up the internal memory region. */
- + if (device->internalSize > 0)
- + {
- + status = gckVIDMEM_Construct(
- + device->os,
- + internalBaseAddress, device->internalSize, internalAlignment,
- + 0, &device->internalVidMem
- + );
- +
- + if (gcmIS_ERROR(status))
- + {
- + /* Error, disable internal heap. */
- + device->internalSize = 0;
- + }
- + else
- + {
- + /* Map internal memory. */
- + device->internalLogical
- + = (gctPOINTER) ioremap_nocache(physical, device->internalSize);
- +
- + if (device->internalLogical == gcvNULL)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +
- + device->internalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
- + device->internalPhysicalName = gcmPTR_TO_NAME(device->internalPhysical);
- + physical += device->internalSize;
- + }
- + }
- +
- + if (device->externalSize > 0)
- + {
- + /* create the external memory heap */
- + status = gckVIDMEM_Construct(
- + device->os,
- + externalBaseAddress, device->externalSize, externalAlignment,
- + 0, &device->externalVidMem
- + );
- +
- + if (gcmIS_ERROR(status))
- + {
- + /* Error, disable internal heap. */
- + device->externalSize = 0;
- + }
- + else
- + {
- + /* Map external memory. */
- + device->externalLogical
- + = (gctPOINTER) ioremap_nocache(physical, device->externalSize);
- +
- + if (device->externalLogical == gcvNULL)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +
- + device->externalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
- + device->externalPhysicalName = gcmPTR_TO_NAME(device->externalPhysical);
- + physical += device->externalSize;
- + }
- + }
- +
- + /* set up the contiguous memory */
- + device->contiguousSize = ContiguousSize;
- +
- + if (ContiguousSize > 0)
- + {
- + if (ContiguousBase == 0)
- + {
- + while (device->contiguousSize > 0)
- + {
- + /* Allocate contiguous memory. */
- + status = _AllocateMemory(
- + device,
- + device->contiguousSize,
- + &device->contiguousBase,
- + &device->contiguousPhysical,
- + &physAddr
- + );
- +
- + if (gcmIS_SUCCESS(status))
- + {
- + device->contiguousPhysicalName = gcmPTR_TO_NAME(device->contiguousPhysical);
- + status = gckVIDMEM_Construct(
- + device->os,
- + physAddr | device->systemMemoryBaseAddress,
- + device->contiguousSize,
- + 64,
- + BankSize,
- + &device->contiguousVidMem
- + );
- +
- + if (gcmIS_SUCCESS(status))
- + {
- + break;
- + }
- +
- + gcmkONERROR(_FreeMemory(
- + device,
- + device->contiguousBase,
- + device->contiguousPhysical
- + ));
- +
- + gcmRELEASE_NAME(device->contiguousPhysicalName);
- + device->contiguousBase = gcvNULL;
- + device->contiguousPhysical = gcvNULL;
- + }
- +
- + if (device->contiguousSize <= (4 << 20))
- + {
- + device->contiguousSize = 0;
- + }
- + else
- + {
- + device->contiguousSize -= (4 << 20);
- + }
- + }
- + }
- + else
- + {
- + /* Create the contiguous memory heap. */
- + status = gckVIDMEM_Construct(
- + device->os,
- + ContiguousBase | device->systemMemoryBaseAddress,
- + ContiguousSize,
- + 64, BankSize,
- + &device->contiguousVidMem
- + );
- +
- + if (gcmIS_ERROR(status))
- + {
- + /* Error, disable contiguous memory pool. */
- + device->contiguousVidMem = gcvNULL;
- + device->contiguousSize = 0;
- + }
- + else
- + {
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
- + mem_region = request_mem_region(
- + ContiguousBase, ContiguousSize, "galcore managed memory"
- + );
- +
- + if (mem_region == gcvNULL)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): Failed to claim %ld bytes @ 0x%08X\n",
- + __FUNCTION__, __LINE__,
- + ContiguousSize, ContiguousBase
- + );
- +
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +#endif
- +
- + device->requestedContiguousBase = ContiguousBase;
- + device->requestedContiguousSize = ContiguousSize;
- +
- +#if !gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
- + if (gcmIS_CORE_PRESENT(device, gcvCORE_VG))
- + {
- + device->contiguousBase
- +#if gcdPAGED_MEMORY_CACHEABLE
- + = (gctPOINTER) ioremap_cached(ContiguousBase, ContiguousSize);
- +#else
- + = (gctPOINTER) ioremap_nocache(ContiguousBase, ContiguousSize);
- +#endif
- + if (device->contiguousBase == gcvNULL)
- + {
- + device->contiguousVidMem = gcvNULL;
- + device->contiguousSize = 0;
- +
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- + }
- +#endif
- +
- + device->contiguousPhysical = gcvNULL;
- + device->contiguousPhysicalName = 0;
- + device->contiguousSize = ContiguousSize;
- + device->contiguousMapped = gcvTRUE;
- + }
- + }
- + }
- +
- + /* Return pointer to the device. */
- + * Device = device;
- +
- + gcmkFOOTER_ARG("*Device=0x%x", * Device);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Roll back. */
- + gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckGALDEVICE_Destroy
- +**
- +** Class destructor.
- +**
- +** INPUT:
- +**
- +** Nothing.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +**
- +** RETURNS:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckGALDEVICE_Destroy(
- + gckGALDEVICE Device)
- +{
- + gctINT i;
- + gceSTATUS status = gcvSTATUS_OK;
- + gckKERNEL kernel = gcvNULL;
- +
- + gcmkHEADER_ARG("Device=0x%x", Device);
- +
- + if (Device != gcvNULL)
- + {
- + /* Grab the first availiable kernel */
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + if (Device->irqLines[i] != -1)
- + {
- + kernel = Device->kernels[i];
- + break;
- + }
- + }
- + if (Device->internalPhysicalName != 0)
- + {
- + gcmRELEASE_NAME(Device->internalPhysicalName);
- + Device->internalPhysicalName = 0;
- + }
- + if (Device->externalPhysicalName != 0)
- + {
- + gcmRELEASE_NAME(Device->externalPhysicalName);
- + Device->externalPhysicalName = 0;
- + }
- + if (Device->contiguousPhysicalName != 0)
- + {
- + gcmRELEASE_NAME(Device->contiguousPhysicalName);
- + Device->contiguousPhysicalName = 0;
- + }
- +
- +
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + if (Device->kernels[i] != gcvNULL)
- + {
- + /* Destroy the gckKERNEL object. */
- + gcmkVERIFY_OK(gckKERNEL_Destroy(Device->kernels[i]));
- + Device->kernels[i] = gcvNULL;
- + }
- + }
- +
- + {
- + if (Device->internalLogical != gcvNULL)
- + {
- + /* Unmap the internal memory. */
- + iounmap(Device->internalLogical);
- + Device->internalLogical = gcvNULL;
- + }
- +
- + if (Device->internalVidMem != gcvNULL)
- + {
- + /* Destroy the internal heap. */
- + gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->internalVidMem));
- + Device->internalVidMem = gcvNULL;
- + }
- + }
- +
- + {
- + if (Device->externalLogical != gcvNULL)
- + {
- + /* Unmap the external memory. */
- + iounmap(Device->externalLogical);
- + Device->externalLogical = gcvNULL;
- + }
- +
- + if (Device->externalVidMem != gcvNULL)
- + {
- + /* destroy the external heap */
- + gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->externalVidMem));
- + Device->externalVidMem = gcvNULL;
- + }
- + }
- +
- + {
- + if (Device->contiguousBase != gcvNULL)
- + {
- + if (Device->contiguousMapped)
- + {
- +#if !gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
- + if (Device->contiguousBase)
- + {
- + /* Unmap the contiguous memory. */
- + iounmap(Device->contiguousBase);
- + }
- +#endif
- + }
- + else
- + {
- + gcmkONERROR(_FreeMemory(
- + Device,
- + Device->contiguousBase,
- + Device->contiguousPhysical
- + ));
- + }
- +
- + Device->contiguousBase = gcvNULL;
- + Device->contiguousPhysical = gcvNULL;
- + }
- +
- + if (Device->requestedContiguousBase != 0)
- + {
- + release_mem_region(Device->requestedContiguousBase, Device->requestedContiguousSize);
- + Device->requestedContiguousBase = 0;
- + Device->requestedContiguousSize = 0;
- + }
- +
- + if (Device->contiguousVidMem != gcvNULL)
- + {
- + /* Destroy the contiguous heap. */
- + gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->contiguousVidMem));
- + Device->contiguousVidMem = gcvNULL;
- + }
- + }
- +
- + {
- + if(gckDebugFileSystemIsEnabled())
- + {
- + gckDebugFileSystemFreeNode(Device->dbgnode);
- + kfree(Device->dbgnode);
- + Device->dbgnode = gcvNULL;
- + }
- + }
- +
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + if (Device->registerBases[i] != gcvNULL)
- + {
- + /* Unmap register memory. */
- + iounmap(Device->registerBases[i]);
- + if (Device->requestedRegisterMemBases[i] != 0)
- + {
- + release_mem_region(Device->requestedRegisterMemBases[i], Device->requestedRegisterMemSizes[i]);
- + }
- +
- + Device->registerBases[i] = gcvNULL;
- + Device->requestedRegisterMemBases[i] = 0;
- + Device->requestedRegisterMemSizes[i] = 0;
- + }
- + }
- +
- + /*Disable clock*/
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
- + if (Device->clk_3d_axi) {
- + clk_put(Device->clk_3d_axi);
- + Device->clk_3d_axi = NULL;
- + }
- +#endif
- + if (Device->clk_3d_core) {
- + clk_put(Device->clk_3d_core);
- + Device->clk_3d_core = NULL;
- + }
- + if (Device->clk_3d_shader) {
- + clk_put(Device->clk_3d_shader);
- + Device->clk_3d_shader = NULL;
- + }
- + if (Device->clk_2d_core) {
- + clk_put(Device->clk_2d_core);
- + Device->clk_2d_core = NULL;
- + }
- + if (Device->clk_2d_axi) {
- + clk_put(Device->clk_2d_axi);
- + Device->clk_2d_axi = NULL;
- + }
- + if (Device->clk_vg_axi) {
- + clk_put(Device->clk_vg_axi);
- + Device->clk_vg_axi = NULL;
- + }
- +
- +#ifdef CONFIG_PM
- + if(Device->pmdev)
- + pm_runtime_disable(Device->pmdev);
- +#endif
- +
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
- + if (Device->gpu_regulator) {
- + regulator_put(Device->gpu_regulator);
- + Device->gpu_regulator = NULL;
- + }
- +#endif
- +
- + /* Destroy the gckOS object. */
- + if (Device->os != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_Destroy(Device->os));
- + Device->os = gcvNULL;
- + }
- +
- + /* Free the device. */
- + kfree(Device);
- + }
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckGALDEVICE_Setup_ISR
- +**
- +** Start the ISR routine.
- +**
- +** INPUT:
- +**
- +** gckGALDEVICE Device
- +** Pointer to an gckGALDEVICE object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +**
- +** RETURNS:
- +**
- +** gcvSTATUS_OK
- +** Setup successfully.
- +** gcvSTATUS_GENERIC_IO
- +** Setup failed.
- +*/
- +gceSTATUS
- +gckGALDEVICE_Setup_ISR(
- + IN gckGALDEVICE Device,
- + IN gceCORE Core
- + )
- +{
- + gceSTATUS status;
- + gctINT ret = -1;
- +
- + gcmkHEADER_ARG("Device=0x%x Core=%d", Device, Core);
- +
- + gcmkVERIFY_ARGUMENT(Device != NULL);
- +
- + if (Device->irqLines[Core] < 0)
- + {
- + gcmkONERROR(gcvSTATUS_GENERIC_IO);
- + }
- +
- + /* Hook up the isr based on the irq line. */
- +#ifdef FLAREON
- + gc500_handle.dev_name = "galcore interrupt service";
- + gc500_handle.dev_id = Device;
- + switch (Core) {
- + case gcvCORE_MAJOR:
- + gc500_handle.handler = isrRoutine;
- + break;
- + case gcvCORE_2D:
- + gc500_handle.handler = isrRoutine2D;
- + break;
- + case gcvCORE_VG:
- + gc500_handle.handler = isrRoutineVG;
- + break;
- + default:
- + break;
- + }
- + gc500_handle.intr_gen = GPIO_INTR_LEVEL_TRIGGER;
- + gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
- +
- + ret = dove_gpio_request(
- + DOVE_GPIO0_7, &gc500_handle
- + );
- +#else
- + switch (Core) {
- + case gcvCORE_MAJOR:
- + ret = request_irq(
- + Device->irqLines[Core], isrRoutine, IRQF_DISABLED,
- + "galcore interrupt service", Device
- + );
- + break;
- + case gcvCORE_2D:
- + ret = request_irq(
- + Device->irqLines[Core], isrRoutine2D, IRQF_DISABLED,
- + "galcore 2D interrupt service", Device
- + );
- + break;
- + case gcvCORE_VG:
- + ret = request_irq(
- + Device->irqLines[Core], isrRoutineVG, IRQF_DISABLED,
- + "galcore VG interrupt service", Device
- + );
- + break;
- + default:
- + break;
- + }
- +#endif
- +
- + if (ret != 0)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): Could not register irq line %d (error=%d)\n",
- + __FUNCTION__, __LINE__,
- + Device->irqLines[Core], ret
- + );
- +
- + gcmkONERROR(gcvSTATUS_GENERIC_IO);
- + }
- +
- + Device->isrEnabled[Core] = 1;
- +
- + /* Mark ISR as initialized. */
- + Device->isrInitializeds[Core] = gcvTRUE;
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckGALDEVICE_Enable_ISR(
- + IN gckGALDEVICE Device,
- + IN gceCORE Core
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Device=0x%x Core=%d", Device, Core);
- +
- + gcmkVERIFY_ARGUMENT(Device != NULL);
- +
- + if (Device->irqLines[Core] < 0)
- + {
- + gcmkONERROR(gcvSTATUS_GENERIC_IO);
- + }
- +
- + spin_lock(&Device->kernels[Core]->irq_lock);
- + if (Device->isrEnabled[Core] == 0)
- + {
- + enable_irq(Device->irqLines[Core]);
- + /* Mark ISR as initialized. */
- + Device->isrEnabled[Core] = gcvTRUE;
- + }
- + Device->isrEnabled[Core]++;
- + spin_unlock(&Device->kernels[Core]->irq_lock);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckGALDEVICE_Release_ISR
- +**
- +** Release the irq line.
- +**
- +** INPUT:
- +**
- +** gckGALDEVICE Device
- +** Pointer to an gckGALDEVICE object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +**
- +** RETURNS:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckGALDEVICE_Release_ISR(
- + IN gckGALDEVICE Device,
- + IN gceCORE Core
- + )
- +{
- + gcmkHEADER_ARG("Device=0x%x Core=%d", Device, Core);
- +
- + gcmkVERIFY_ARGUMENT(Device != NULL);
- +
- + /* release the irq */
- + if (Device->isrInitializeds[Core])
- + {
- +#ifdef FLAREON
- + dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
- +#else
- + free_irq(Device->irqLines[Core], Device);
- +#endif
- +
- + Device->isrInitializeds[Core] = gcvFALSE;
- + }
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckGALDEVICE_Disable_ISR(
- + IN gckGALDEVICE Device,
- + IN gceCORE Core
- + )
- +{
- + gcmkHEADER_ARG("Device=0x%x Core=%d", Device, Core);
- +
- + gcmkVERIFY_ARGUMENT(Device != NULL);
- +
- + /* disable the irq */
- + spin_lock(&Device->kernels[Core]->irq_lock);
- + if (Device->isrEnabled[Core] > 0)
- + {
- + Device->isrEnabled[Core]--;
- + if (Device->isrEnabled[Core] == 0)
- + disable_irq(Device->irqLines[Core]);
- + }
- + spin_unlock(&Device->kernels[Core]->irq_lock);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckGALDEVICE_Start_Threads
- +**
- +** Start the daemon threads.
- +**
- +** INPUT:
- +**
- +** gckGALDEVICE Device
- +** Pointer to an gckGALDEVICE object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +**
- +** RETURNS:
- +**
- +** gcvSTATUS_OK
- +** Start successfully.
- +** gcvSTATUS_GENERIC_IO
- +** Start failed.
- +*/
- +gceSTATUS
- +gckGALDEVICE_Start_Threads(
- + IN gckGALDEVICE Device
- + )
- +{
- + gceSTATUS status;
- + struct task_struct * task;
- +
- + gcmkHEADER_ARG("Device=0x%x", Device);
- +
- + gcmkVERIFY_ARGUMENT(Device != NULL);
- +
- + if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
- + {
- + /* Start the kernel thread. */
- + task = kthread_run(threadRoutine, Device, "galcore daemon thread");
- +
- + if (IS_ERR(task))
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): Could not start the kernel thread.\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_GENERIC_IO);
- + }
- +
- + Device->threadCtxts[gcvCORE_MAJOR] = task;
- + Device->threadInitializeds[gcvCORE_MAJOR] = gcvTRUE;
- + }
- +
- + if (Device->kernels[gcvCORE_2D] != gcvNULL)
- + {
- + /* Start the kernel thread. */
- + task = kthread_run(threadRoutine2D, Device, "galcore daemon thread for 2D");
- +
- + if (IS_ERR(task))
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): Could not start the kernel thread.\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_GENERIC_IO);
- + }
- +
- + Device->threadCtxts[gcvCORE_2D] = task;
- + Device->threadInitializeds[gcvCORE_2D] = gcvTRUE;
- + }
- + else
- + {
- + Device->threadInitializeds[gcvCORE_2D] = gcvFALSE;
- + }
- +
- + if (Device->kernels[gcvCORE_VG] != gcvNULL)
- + {
- + /* Start the kernel thread. */
- + task = kthread_run(threadRoutineVG, Device, "galcore daemon thread for VG");
- +
- + if (IS_ERR(task))
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): Could not start the kernel thread.\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_GENERIC_IO);
- + }
- +
- + Device->threadCtxts[gcvCORE_VG] = task;
- + Device->threadInitializeds[gcvCORE_VG] = gcvTRUE;
- + }
- + else
- + {
- + Device->threadInitializeds[gcvCORE_VG] = gcvFALSE;
- + }
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckGALDEVICE_Stop_Threads
- +**
- +** Stop the gal device, including the following actions: stop the daemon
- +** thread, release the irq.
- +**
- +** INPUT:
- +**
- +** gckGALDEVICE Device
- +** Pointer to an gckGALDEVICE object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +**
- +** RETURNS:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckGALDEVICE_Stop_Threads(
- + gckGALDEVICE Device
- + )
- +{
- + gctINT i;
- +
- + gcmkHEADER_ARG("Device=0x%x", Device);
- +
- + gcmkVERIFY_ARGUMENT(Device != NULL);
- +
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + /* Stop the kernel threads. */
- + if (Device->threadInitializeds[i])
- + {
- + Device->killThread = gcvTRUE;
- + up(&Device->semas[i]);
- +
- + kthread_stop(Device->threadCtxts[i]);
- + Device->threadCtxts[i] = gcvNULL;
- + Device->threadInitializeds[i] = gcvFALSE;
- + }
- + }
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckGALDEVICE_Start
- +**
- +** Start the gal device, including the following actions: setup the isr routine
- +** and start the daemoni thread.
- +**
- +** INPUT:
- +**
- +** gckGALDEVICE Device
- +** Pointer to an gckGALDEVICE object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +**
- +** RETURNS:
- +**
- +** gcvSTATUS_OK
- +** Start successfully.
- +*/
- +gceSTATUS
- +gckGALDEVICE_Start(
- + IN gckGALDEVICE Device
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Device=0x%x", Device);
- +
- + /* Start the kernel thread. */
- + gcmkONERROR(gckGALDEVICE_Start_Threads(Device));
- +
- + if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
- + {
- + /* Setup the ISR routine. */
- + gcmkONERROR(gckGALDEVICE_Setup_ISR(Device, gcvCORE_MAJOR));
- +
- + /* Switch to SUSPEND power state. */
- + gcmkONERROR(gckHARDWARE_SetPowerManagementState(
- + Device->kernels[gcvCORE_MAJOR]->hardware, gcvPOWER_OFF_BROADCAST
- + ));
- + }
- +
- + if (Device->kernels[gcvCORE_2D] != gcvNULL)
- + {
- + /* Setup the ISR routine. */
- + gcmkONERROR(gckGALDEVICE_Setup_ISR(Device, gcvCORE_2D));
- +
- + /* Switch to SUSPEND power state. */
- + gcmkONERROR(gckHARDWARE_SetPowerManagementState(
- + Device->kernels[gcvCORE_2D]->hardware, gcvPOWER_OFF_BROADCAST
- + ));
- + }
- +
- + if (Device->kernels[gcvCORE_VG] != gcvNULL)
- + {
- + /* Setup the ISR routine. */
- + gcmkONERROR(gckGALDEVICE_Setup_ISR(Device, gcvCORE_VG));
- +
- + /* Switch to SUSPEND power state. */
- + gcmkONERROR(gckVGHARDWARE_SetPowerManagementState(
- + Device->kernels[gcvCORE_VG]->vg->hardware, gcvPOWER_OFF_BROADCAST
- + ));
- + }
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckGALDEVICE_Stop
- +**
- +** Stop the gal device, including the following actions: stop the daemon
- +** thread, release the irq.
- +**
- +** INPUT:
- +**
- +** gckGALDEVICE Device
- +** Pointer to an gckGALDEVICE object.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +**
- +** RETURNS:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckGALDEVICE_Stop(
- + gckGALDEVICE Device
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Device=0x%x", Device);
- +
- + gcmkVERIFY_ARGUMENT(Device != NULL);
- +
- + if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
- + {
- + /* Switch to OFF power state. */
- + gcmkONERROR(gckHARDWARE_SetPowerManagementState(
- + Device->kernels[gcvCORE_MAJOR]->hardware, gcvPOWER_OFF
- + ));
- +
- + /* Remove the ISR routine. */
- + gcmkONERROR(gckGALDEVICE_Release_ISR(Device, gcvCORE_MAJOR));
- + }
- +
- + if (Device->kernels[gcvCORE_2D] != gcvNULL)
- + {
- + /* Setup the ISR routine. */
- + gcmkONERROR(gckGALDEVICE_Release_ISR(Device, gcvCORE_2D));
- +
- + /* Switch to OFF power state. */
- + gcmkONERROR(gckHARDWARE_SetPowerManagementState(
- + Device->kernels[gcvCORE_2D]->hardware, gcvPOWER_OFF
- + ));
- + }
- +
- + if (Device->kernels[gcvCORE_VG] != gcvNULL)
- + {
- + /* Setup the ISR routine. */
- + gcmkONERROR(gckGALDEVICE_Release_ISR(Device, gcvCORE_VG));
- +
- +#if gcdENABLE_VG
- + /* Switch to OFF power state. */
- + gcmkONERROR(gckVGHARDWARE_SetPowerManagementState(
- + Device->kernels[gcvCORE_VG]->vg->hardware, gcvPOWER_OFF
- + ));
- +#endif
- + }
- +
- + /* Stop the kernel thread. */
- + gcmkONERROR(gckGALDEVICE_Stop_Threads(Device));
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h 2015-03-08 14:27:37.653684501 -0500
- @@ -0,0 +1,192 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_kernel_device_h_
- +#define __gc_hal_kernel_device_h_
- +
- +/******************************************************************************\
- +******************************* gckGALDEVICE Structure *******************************
- +\******************************************************************************/
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- +struct contiguous_mem_pool {
- + struct dma_attrs attrs;
- + dma_addr_t phys;
- + void *virt;
- + size_t size;
- +};
- +#endif
- +
- +typedef struct _gckGALDEVICE
- +{
- + /* Objects. */
- + gckOS os;
- + gckKERNEL kernels[gcdMAX_GPU_COUNT];
- +
- + /* Attributes. */
- + gctSIZE_T internalSize;
- + gctPHYS_ADDR internalPhysical;
- + gctUINT32 internalPhysicalName;
- + gctPOINTER internalLogical;
- + gckVIDMEM internalVidMem;
- + gctSIZE_T externalSize;
- + gctPHYS_ADDR externalPhysical;
- + gctUINT32 externalPhysicalName;
- + gctPOINTER externalLogical;
- + gckVIDMEM externalVidMem;
- + gckVIDMEM contiguousVidMem;
- + gctPOINTER contiguousBase;
- + gctPHYS_ADDR contiguousPhysical;
- + gctUINT32 contiguousPhysicalName;
- + gctSIZE_T contiguousSize;
- + gctBOOL contiguousMapped;
- + gctPOINTER contiguousMappedUser;
- + gctSIZE_T systemMemorySize;
- + gctUINT32 systemMemoryBaseAddress;
- + gctPOINTER registerBases[gcdMAX_GPU_COUNT];
- + gctSIZE_T registerSizes[gcdMAX_GPU_COUNT];
- + gctUINT32 baseAddress;
- + gctUINT32 requestedRegisterMemBases[gcdMAX_GPU_COUNT];
- + gctSIZE_T requestedRegisterMemSizes[gcdMAX_GPU_COUNT];
- + gctUINT32 requestedContiguousBase;
- + gctSIZE_T requestedContiguousSize;
- +
- + /* IRQ management. */
- + gctINT irqLines[gcdMAX_GPU_COUNT];
- + gctBOOL isrInitializeds[gcdMAX_GPU_COUNT];
- + gctINT isrEnabled[gcdMAX_GPU_COUNT];
- + gctBOOL dataReadys[gcdMAX_GPU_COUNT];
- +
- + /* Thread management. */
- + struct task_struct *threadCtxts[gcdMAX_GPU_COUNT];
- + struct semaphore semas[gcdMAX_GPU_COUNT];
- + gctBOOL threadInitializeds[gcdMAX_GPU_COUNT];
- + gctBOOL killThread;
- +
- + /* Signal management. */
- + gctINT signal;
- +
- + /* Core mapping */
- + gceCORE coreMapping[8];
- +
- + /* States before suspend. */
- + gceCHIPPOWERSTATE statesStored[gcdMAX_GPU_COUNT];
- +
- + /*Device Debug File System Entry in Kernel*/
- + struct _gcsDebugFileSystemNode * dbgnode;
- +
- + /* Clock management.*/
- + struct clk *clk_3d_core;
- + struct clk *clk_3d_shader;
- + struct clk *clk_3d_axi;
- + struct clk *clk_2d_core;
- + struct clk *clk_2d_axi;
- + struct clk *clk_vg_axi;
- +
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- + /*Power management.*/
- + struct regulator *gpu_regulator;
- +#endif
- + /*Run time pm*/
- + struct device *pmdev;
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- + struct contiguous_mem_pool *pool;
- + struct reset_control *rstc[gcdMAX_GPU_COUNT];
- +#endif
- +}
- +* gckGALDEVICE;
- +
- +typedef struct _gcsHAL_PRIVATE_DATA
- +{
- + gckGALDEVICE device;
- + gctPOINTER mappedMemory;
- + gctPOINTER contiguousLogical;
- + /* The process opening the device may not be the same as the one that closes it. */
- + gctUINT32 pidOpen;
- +}
- +gcsHAL_PRIVATE_DATA, * gcsHAL_PRIVATE_DATA_PTR;
- +
- +gceSTATUS gckGALDEVICE_Enable_ISR(
- + IN gckGALDEVICE Device,
- + IN gceCORE Core
- + );
- +
- +gceSTATUS gckGALDEVICE_Disable_ISR(
- + IN gckGALDEVICE Device,
- + IN gceCORE Core
- + );
- +
- +gceSTATUS gckGALDEVICE_Setup_ISR(
- + IN gckGALDEVICE Device,
- + IN gceCORE Core
- + );
- +
- +gceSTATUS gckGALDEVICE_Release_ISR(
- + IN gckGALDEVICE Device,
- + IN gceCORE Core
- + );
- +
- +gceSTATUS gckGALDEVICE_Start_Threads(
- + IN gckGALDEVICE Device
- + );
- +
- +gceSTATUS gckGALDEVICE_Stop_Threads(
- + gckGALDEVICE Device
- + );
- +
- +gceSTATUS gckGALDEVICE_Start(
- + IN gckGALDEVICE Device
- + );
- +
- +gceSTATUS gckGALDEVICE_Stop(
- + gckGALDEVICE Device
- + );
- +
- +gceSTATUS gckGALDEVICE_Construct(
- + IN gctINT IrqLine,
- + IN gctUINT32 RegisterMemBase,
- + IN gctSIZE_T RegisterMemSize,
- + IN gctINT IrqLine2D,
- + IN gctUINT32 RegisterMemBase2D,
- + IN gctSIZE_T RegisterMemSize2D,
- + IN gctINT IrqLineVG,
- + IN gctUINT32 RegisterMemBaseVG,
- + IN gctSIZE_T RegisterMemSizeVG,
- + IN gctUINT32 ContiguousBase,
- + IN gctSIZE_T ContiguousSize,
- + IN gctSIZE_T BankSize,
- + IN gctINT FastClear,
- + IN gctINT Compression,
- + IN gctUINT32 PhysBaseAddr,
- + IN gctUINT32 PhysSize,
- + IN gctINT Signal,
- + IN gctUINT LogFileSize,
- + IN struct device *pdev,
- + IN gctINT PowerManagement,
- + IN gctINT GpuProfiler,
- + OUT gckGALDEVICE *Device
- + );
- +
- +gceSTATUS gckGALDEVICE_Destroy(
- + IN gckGALDEVICE Device
- + );
- +
- +#endif /* __gc_hal_kernel_device_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c 2015-03-08 14:27:37.653684501 -0500
- @@ -0,0 +1,1471 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +* Copyright (C) 2011-2013 Freescale Semiconductor, 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +#include <linux/device.h>
- +#include <linux/slab.h>
- +#include <linux/notifier.h>
- +#include "gc_hal_kernel_linux.h"
- +#include "gc_hal_driver.h"
- +
- +#if USE_PLATFORM_DRIVER
- +# include <linux/platform_device.h>
- +#endif
- +
- +#ifdef CONFIG_PXA_DVFM
- +# include <mach/dvfm.h>
- +# include <mach/pxa3xx_dvfm.h>
- +#endif
- +
- +
- +#ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
- +# include <linux/resmem_account.h>
- +# include <linux/kernel.h>
- +# include <linux/mm.h>
- +# include <linux/oom.h>
- +# include <linux/sched.h>
- +# include <linux/notifier.h>
- +
- +struct task_struct *lowmem_deathpending;
- +
- +static int
- +task_notify_func(struct notifier_block *self, unsigned long val, void *data);
- +
- +static struct notifier_block task_nb = {
- + .notifier_call = task_notify_func,
- +};
- +
- +static int
- +task_notify_func(struct notifier_block *self, unsigned long val, void *data)
- +{
- + struct task_struct *task = data;
- +
- + if (task == lowmem_deathpending)
- + lowmem_deathpending = NULL;
- +
- + return NOTIFY_OK;
- +}
- +#endif
- +
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
- +#include <mach/viv_gpu.h>
- +#else
- +#include <linux/pm_runtime.h>
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
- +#include <mach/busfreq.h>
- +#else
- +#include <linux/busfreq-imx6.h>
- +#include <linux/reset.h>
- +#endif
- +#endif
- +/* Zone used for header/footer. */
- +#define _GC_OBJ_ZONE gcvZONE_DRIVER
- +
- +#if gcdENABLE_FSCALE_VAL_ADJUST
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- +#include <linux/device_cooling.h>
- +#define REG_THERMAL_NOTIFIER(a) register_devfreq_cooling_notifier(a);
- +#define UNREG_THERMAL_NOTIFIER(a) unregister_devfreq_cooling_notifier(a);
- +#else
- +extern int register_thermal_notifier(struct notifier_block *nb);
- +extern int unregister_thermal_notifier(struct notifier_block *nb);
- +#define REG_THERMAL_NOTIFIER(a) register_thermal_notifier(a);
- +#define UNREG_THERMAL_NOTIFIER(a) unregister_thermal_notifier(a);
- +#endif
- +#endif
- +
- +MODULE_DESCRIPTION("Vivante Graphics Driver");
- +MODULE_LICENSE("GPL");
- +
- +static struct class* gpuClass;
- +
- +static gckGALDEVICE galDevice;
- +
- +static uint major = 199;
- +module_param(major, uint, 0644);
- +
- +static int irqLine = -1;
- +module_param(irqLine, int, 0644);
- +
- +static ulong registerMemBase = 0x80000000;
- +module_param(registerMemBase, ulong, 0644);
- +
- +static ulong registerMemSize = 2 << 10;
- +module_param(registerMemSize, ulong, 0644);
- +
- +static int irqLine2D = -1;
- +module_param(irqLine2D, int, 0644);
- +
- +static ulong registerMemBase2D = 0x00000000;
- +module_param(registerMemBase2D, ulong, 0644);
- +
- +static ulong registerMemSize2D = 2 << 10;
- +module_param(registerMemSize2D, ulong, 0644);
- +
- +static int irqLineVG = -1;
- +module_param(irqLineVG, int, 0644);
- +
- +static ulong registerMemBaseVG = 0x00000000;
- +module_param(registerMemBaseVG, ulong, 0644);
- +
- +static ulong registerMemSizeVG = 2 << 10;
- +module_param(registerMemSizeVG, ulong, 0644);
- +
- +#if gcdENABLE_FSCALE_VAL_ADJUST
- +static ulong contiguousSize = 128 << 20;
- +#else
- +static ulong contiguousSize = 4 << 20;
- +#endif
- +module_param(contiguousSize, ulong, 0644);
- +
- +static ulong contiguousBase = 0;
- +module_param(contiguousBase, ulong, 0644);
- +
- +static ulong bankSize = 0;
- +module_param(bankSize, ulong, 0644);
- +
- +static int fastClear = -1;
- +module_param(fastClear, int, 0644);
- +
- +static int compression = -1;
- +module_param(compression, int, 0644);
- +
- +static int powerManagement = 1;
- +module_param(powerManagement, int, 0644);
- +
- +static int gpuProfiler = 0;
- +module_param(gpuProfiler, int, 0644);
- +
- +static int signal = 48;
- +module_param(signal, int, 0644);
- +
- +static ulong baseAddress = 0;
- +module_param(baseAddress, ulong, 0644);
- +
- +static ulong physSize = 0;
- +module_param(physSize, ulong, 0644);
- +
- +static uint logFileSize=0;
- +module_param(logFileSize,uint, 0644);
- +
- +static int showArgs = 0;
- +module_param(showArgs, int, 0644);
- +
- +int gpu3DMinClock = 0;
- +module_param(gpu3DMinClock, int, 0644);
- +
- +#if ENABLE_GPU_CLOCK_BY_DRIVER
- + unsigned long coreClock = 156000000;
- + module_param(coreClock, ulong, 0644);
- +#endif
- +
- +static int drv_open(
- + struct inode* inode,
- + struct file* filp
- + );
- +
- +static int drv_release(
- + struct inode* inode,
- + struct file* filp
- + );
- +
- +static long drv_ioctl(
- + struct file* filp,
- + unsigned int ioctlCode,
- + unsigned long arg
- + );
- +
- +static int drv_mmap(
- + struct file* filp,
- + struct vm_area_struct* vma
- + );
- +
- +static struct file_operations driver_fops =
- +{
- + .owner = THIS_MODULE,
- + .open = drv_open,
- + .release = drv_release,
- + .unlocked_ioctl = drv_ioctl,
- +#ifdef HAVE_COMPAT_IOCTL
- + .compat_ioctl = drv_ioctl,
- +#endif
- + .mmap = drv_mmap,
- +};
- +
- +#ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
- +static size_t viv_gpu_resmem_query(struct task_struct *p, struct reserved_memory_account *m);
- +static struct reserved_memory_account viv_gpu_resmem_handler = {
- + .name = "viv_gpu",
- + .get_page_used_by_process = viv_gpu_resmem_query,
- +};
- +
- +size_t viv_gpu_resmem_query(struct task_struct *p, struct reserved_memory_account *m)
- +{
- + gcuDATABASE_INFO info;
- + unsigned int processid = p->pid;
- + gckKERNEL gpukernel = m->data;
- +
- + /* ignore error happens in this api. */
- + if (gckKERNEL_QueryProcessDB(gpukernel, processid, false, gcvDB_VIDEO_MEMORY, &info) != gcvSTATUS_OK)
- + return 0;
- +
- + /* we return pages. */
- + if (info.counters.bytes > 0)
- + return info.counters.bytes / PAGE_SIZE;
- + return 0;
- +}
- +#endif
- +
- +int drv_open(
- + struct inode* inode,
- + struct file* filp
- + )
- +{
- + gceSTATUS status;
- + gctBOOL attached = gcvFALSE;
- + gcsHAL_PRIVATE_DATA_PTR data = gcvNULL;
- + gctINT i;
- +
- + gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
- +
- + if (filp == gcvNULL)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): filp is NULL\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + data = kmalloc(sizeof(gcsHAL_PRIVATE_DATA), GFP_KERNEL);
- +
- + if (data == gcvNULL)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): private_data is NULL\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + data->device = galDevice;
- + data->mappedMemory = gcvNULL;
- + data->contiguousLogical = gcvNULL;
- + gcmkONERROR(gckOS_GetProcessID(&data->pidOpen));
- +
- + /* Attached the process. */
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + if (galDevice->kernels[i] != gcvNULL)
- + {
- + gcmkONERROR(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvTRUE));
- + }
- + }
- + attached = gcvTRUE;
- +
- + if (!galDevice->contiguousMapped)
- + {
- + gcmkONERROR(gckOS_MapMemory(
- + galDevice->os,
- + galDevice->contiguousPhysical,
- + galDevice->contiguousSize,
- + &data->contiguousLogical
- + ));
- + }
- +
- + filp->private_data = data;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return 0;
- +
- +OnError:
- + if (data != gcvNULL)
- + {
- + if (data->contiguousLogical != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckOS_UnmapMemory(
- + galDevice->os,
- + galDevice->contiguousPhysical,
- + galDevice->contiguousSize,
- + data->contiguousLogical
- + ));
- + }
- +
- + kfree(data);
- + }
- +
- + if (attached)
- + {
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + if (galDevice->kernels[i] != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvFALSE));
- + }
- + }
- + }
- +
- + gcmkFOOTER();
- + return -ENOTTY;
- +}
- +
- +int drv_release(
- + struct inode* inode,
- + struct file* filp
- + )
- +{
- + gceSTATUS status;
- + gcsHAL_PRIVATE_DATA_PTR data;
- + gckGALDEVICE device;
- + gctINT i;
- +
- + gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
- +
- + if (filp == gcvNULL)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): filp is NULL\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + data = filp->private_data;
- +
- + if (data == gcvNULL)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): private_data is NULL\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + device = data->device;
- +
- + if (device == gcvNULL)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): device is NULL\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + if (!device->contiguousMapped)
- + {
- + if (data->contiguousLogical != gcvNULL)
- + {
- + gcmkONERROR(gckOS_UnmapMemoryEx(
- + galDevice->os,
- + galDevice->contiguousPhysical,
- + galDevice->contiguousSize,
- + data->contiguousLogical,
- + data->pidOpen
- + ));
- +
- + data->contiguousLogical = gcvNULL;
- + }
- + }
- +
- + /* A process gets detached. */
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + if (galDevice->kernels[i] != gcvNULL)
- + {
- + gcmkONERROR(gckKERNEL_AttachProcessEx(galDevice->kernels[i], gcvFALSE, data->pidOpen));
- + }
- + }
- +
- + kfree(data);
- + filp->private_data = NULL;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return 0;
- +
- +OnError:
- + gcmkFOOTER();
- + return -ENOTTY;
- +}
- +
- +long drv_ioctl(
- + struct file* filp,
- + unsigned int ioctlCode,
- + unsigned long arg
- + )
- +{
- + gceSTATUS status;
- + gcsHAL_INTERFACE iface;
- + gctUINT32 copyLen;
- + DRIVER_ARGS drvArgs;
- + gckGALDEVICE device;
- + gcsHAL_PRIVATE_DATA_PTR data;
- + gctINT32 i, count;
- +
- + gcmkHEADER_ARG(
- + "filp=0x%08X ioctlCode=0x%08X arg=0x%08X",
- + filp, ioctlCode, arg
- + );
- +
- + if (filp == gcvNULL)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): filp is NULL\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + data = filp->private_data;
- +
- + if (data == gcvNULL)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): private_data is NULL\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + device = data->device;
- +
- + if (device == gcvNULL)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): device is NULL\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + if ((ioctlCode != IOCTL_GCHAL_INTERFACE)
- + && (ioctlCode != IOCTL_GCHAL_KERNEL_INTERFACE)
- + )
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): unknown command %d\n",
- + __FUNCTION__, __LINE__,
- + ioctlCode
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + /* Get the drvArgs. */
- + copyLen = copy_from_user(
- + &drvArgs, (void *) arg, sizeof(DRIVER_ARGS)
- + );
- +
- + if (copyLen != 0)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): error copying of the input arguments.\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + /* Now bring in the gcsHAL_INTERFACE structure. */
- + if ((drvArgs.InputBufferSize != sizeof(gcsHAL_INTERFACE))
- + || (drvArgs.OutputBufferSize != sizeof(gcsHAL_INTERFACE))
- + )
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): input or/and output structures are invalid.\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + copyLen = copy_from_user(
- + &iface, gcmUINT64_TO_PTR(drvArgs.InputBuffer), sizeof(gcsHAL_INTERFACE)
- + );
- +
- + if (copyLen != 0)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): error copying of input HAL interface.\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + if (iface.command == gcvHAL_CHIP_INFO)
- + {
- + count = 0;
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + if (device->kernels[i] != gcvNULL)
- + {
- +#if gcdENABLE_VG
- + if (i == gcvCORE_VG)
- + {
- + iface.u.ChipInfo.types[count] = gcvHARDWARE_VG;
- + }
- + else
- +#endif
- + {
- + gcmkVERIFY_OK(gckHARDWARE_GetType(device->kernels[i]->hardware,
- + &iface.u.ChipInfo.types[count]));
- + }
- + count++;
- + }
- + }
- +
- + iface.u.ChipInfo.count = count;
- + iface.status = status = gcvSTATUS_OK;
- + }
- + else
- + {
- + if (iface.hardwareType < 0 || iface.hardwareType > 7)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): unknown hardwareType %d\n",
- + __FUNCTION__, __LINE__,
- + iface.hardwareType
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- +#if gcdENABLE_VG
- + if (device->coreMapping[iface.hardwareType] == gcvCORE_VG)
- + {
- + status = gckVGKERNEL_Dispatch(device->kernels[gcvCORE_VG],
- + (ioctlCode == IOCTL_GCHAL_INTERFACE),
- + &iface);
- + }
- + else
- +#endif
- + {
- + status = gckKERNEL_Dispatch(device->kernels[device->coreMapping[iface.hardwareType]],
- + (ioctlCode == IOCTL_GCHAL_INTERFACE),
- + &iface);
- + }
- + }
- +
- + /* Redo system call after pending signal is handled. */
- + if (status == gcvSTATUS_INTERRUPTED)
- + {
- + gcmkFOOTER();
- + return -ERESTARTSYS;
- + }
- +
- + if (gcmIS_SUCCESS(status) && (iface.command == gcvHAL_LOCK_VIDEO_MEMORY))
- + {
- + gcuVIDMEM_NODE_PTR node = gcmUINT64_TO_PTR(iface.u.LockVideoMemory.node);
- + /* Special case for mapped memory. */
- + if ((data->mappedMemory != gcvNULL)
- + && (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
- + )
- + {
- + /* Compute offset into mapped memory. */
- + gctUINT32 offset
- + = (gctUINT8 *) gcmUINT64_TO_PTR(iface.u.LockVideoMemory.memory)
- + - (gctUINT8 *) device->contiguousBase;
- +
- + /* Compute offset into user-mapped region. */
- + iface.u.LockVideoMemory.memory =
- + gcmPTR_TO_UINT64((gctUINT8 *) data->mappedMemory + offset);
- + }
- + }
- +
- + /* Copy data back to the user. */
- + copyLen = copy_to_user(
- + gcmUINT64_TO_PTR(drvArgs.OutputBuffer), &iface, sizeof(gcsHAL_INTERFACE)
- + );
- +
- + if (copyLen != 0)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): error copying of output HAL interface.\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return 0;
- +
- +OnError:
- + gcmkFOOTER();
- + return -ENOTTY;
- +}
- +
- +static int drv_mmap(
- + struct file* filp,
- + struct vm_area_struct* vma
- + )
- +{
- + gceSTATUS status = gcvSTATUS_OK;
- + gcsHAL_PRIVATE_DATA_PTR data;
- + gckGALDEVICE device;
- +
- + gcmkHEADER_ARG("filp=0x%08X vma=0x%08X", filp, vma);
- +
- + if (filp == gcvNULL)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): filp is NULL\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + data = filp->private_data;
- +
- + if (data == gcvNULL)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): private_data is NULL\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + device = data->device;
- +
- + if (device == gcvNULL)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): device is NULL\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- +#if !gcdPAGED_MEMORY_CACHEABLE
- + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- + vma->vm_flags |= gcdVM_FLAGS;
- +#endif
- + vma->vm_pgoff = 0;
- +
- + if (device->contiguousMapped)
- + {
- + unsigned long size = vma->vm_end - vma->vm_start;
- + int ret = 0;
- +
- + if (size > device->contiguousSize)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): Invalid mapping size.\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + ret = io_remap_pfn_range(
- + vma,
- + vma->vm_start,
- + device->requestedContiguousBase >> PAGE_SHIFT,
- + size,
- + vma->vm_page_prot
- + );
- +
- + if (ret != 0)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): io_remap_pfn_range failed %d\n",
- + __FUNCTION__, __LINE__,
- + ret
- + );
- +
- + data->mappedMemory = gcvNULL;
- +
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +
- + data->mappedMemory = (gctPOINTER) vma->vm_start;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return 0;
- + }
- +
- +
- +OnError:
- + gcmkFOOTER();
- + return -ENOTTY;
- +}
- +
- +
- +#if !USE_PLATFORM_DRIVER
- +static int __init drv_init(void)
- +#else
- +static int drv_init(struct device *pdev)
- +#endif
- +{
- + int ret;
- + int result = -EINVAL;
- + gceSTATUS status;
- + gckGALDEVICE device = gcvNULL;
- + struct class* device_class = gcvNULL;
- +
- + gcmkHEADER();
- +
- +#if ENABLE_GPU_CLOCK_BY_DRIVER && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28))
- + {
- +# if 0
- + struct clk * clk;
- +
- + clk = clk_get(NULL, "GCCLK");
- +
- + if (IS_ERR(clk))
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): clk get error: %d\n",
- + __FUNCTION__, __LINE__,
- + PTR_ERR(clk)
- + );
- +
- + result = -ENODEV;
- + gcmkONERROR(gcvSTATUS_GENERIC_IO);
- + }
- +
- + /*
- + * APMU_GC_156M, APMU_GC_312M, APMU_GC_PLL2, APMU_GC_PLL2_DIV2 currently.
- + * Use the 2X clock.
- + */
- + if (clk_set_rate(clk, coreClock * 2))
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): Failed to set core clock.\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + result = -EAGAIN;
- + gcmkONERROR(gcvSTATUS_GENERIC_IO);
- + }
- +
- + clk_enable(clk);
- +
- +#if defined(CONFIG_PXA_DVFM) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
- + gc_pwr(1);
- +# endif
- +# endif
- + }
- +#endif
- +
- + printk(KERN_INFO "Galcore version %d.%d.%d.%d\n",
- + gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, gcvVERSION_BUILD);
- + /* when enable gpu profiler, we need to turn off gpu powerMangement */
- + if(gpuProfiler)
- + powerManagement = 0;
- + if (showArgs)
- + {
- + printk("galcore options:\n");
- + printk(" irqLine = %d\n", irqLine);
- + printk(" registerMemBase = 0x%08lX\n", registerMemBase);
- + printk(" registerMemSize = 0x%08lX\n", registerMemSize);
- +
- + if (irqLine2D != -1)
- + {
- + printk(" irqLine2D = %d\n", irqLine2D);
- + printk(" registerMemBase2D = 0x%08lX\n", registerMemBase2D);
- + printk(" registerMemSize2D = 0x%08lX\n", registerMemSize2D);
- + }
- +
- + if (irqLineVG != -1)
- + {
- + printk(" irqLineVG = %d\n", irqLineVG);
- + printk(" registerMemBaseVG = 0x%08lX\n", registerMemBaseVG);
- + printk(" registerMemSizeVG = 0x%08lX\n", registerMemSizeVG);
- + }
- +
- + printk(" contiguousSize = %ld\n", contiguousSize);
- + printk(" contiguousBase = 0x%08lX\n", contiguousBase);
- + printk(" bankSize = 0x%08lX\n", bankSize);
- + printk(" fastClear = %d\n", fastClear);
- + printk(" compression = %d\n", compression);
- + printk(" signal = %d\n", signal);
- + printk(" baseAddress = 0x%08lX\n", baseAddress);
- + printk(" physSize = 0x%08lX\n", physSize);
- + printk(" logFileSize = %d KB \n", logFileSize);
- + printk(" powerManagement = %d\n", powerManagement);
- + printk(" gpuProfiler = %d\n", gpuProfiler);
- +#if ENABLE_GPU_CLOCK_BY_DRIVER
- + printk(" coreClock = %lu\n", coreClock);
- +#endif
- + }
- +
- + if(logFileSize != 0)
- + {
- + gckDebugFileSystemInitialize();
- + }
- +
- + /* Create the GAL device. */
- + gcmkONERROR(gckGALDEVICE_Construct(
- + irqLine,
- + registerMemBase, registerMemSize,
- + irqLine2D,
- + registerMemBase2D, registerMemSize2D,
- + irqLineVG,
- + registerMemBaseVG, registerMemSizeVG,
- + contiguousBase, contiguousSize,
- + bankSize, fastClear, compression, baseAddress, physSize, signal,
- + logFileSize,
- + pdev,
- + powerManagement,
- + gpuProfiler,
- + &device
- + ));
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- + device->pool = dev_get_drvdata(pdev);
- +#endif
- +
- + /* Start the GAL device. */
- + gcmkONERROR(gckGALDEVICE_Start(device));
- +
- + if ((physSize != 0)
- + && (device->kernels[gcvCORE_MAJOR] != gcvNULL)
- + && (device->kernels[gcvCORE_MAJOR]->hardware->mmuVersion != 0))
- + {
- + status = gckMMU_Enable(device->kernels[gcvCORE_MAJOR]->mmu, baseAddress, physSize);
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
- + "Enable new MMU: status=%d\n", status);
- +
- + if ((device->kernels[gcvCORE_2D] != gcvNULL)
- + && (device->kernels[gcvCORE_2D]->hardware->mmuVersion != 0))
- + {
- + status = gckMMU_Enable(device->kernels[gcvCORE_2D]->mmu, baseAddress, physSize);
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
- + "Enable new MMU for 2D: status=%d\n", status);
- + }
- +
- + /* Reset the base address */
- + device->baseAddress = 0;
- + }
- +
- +#ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
- + task_free_register(&task_nb);
- + viv_gpu_resmem_handler.data = device->kernels[gcvCORE_MAJOR];
- + register_reserved_memory_account(&viv_gpu_resmem_handler);
- +#endif
- +
- +
- + /* Register the character device. */
- + ret = register_chrdev(major, DRV_NAME, &driver_fops);
- +
- + if (ret < 0)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): Could not allocate major number for mmap.\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + if (major == 0)
- + {
- + major = ret;
- + }
- +
- + /* Create the device class. */
- + device_class = class_create(THIS_MODULE, "graphics_class");
- +
- + if (IS_ERR(device_class))
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_DRIVER,
- + "%s(%d): Failed to create the class.\n",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
- + device_create(device_class, NULL, MKDEV(major, 0), NULL, "galcore");
- +#else
- + device_create(device_class, NULL, MKDEV(major, 0), "galcore");
- +#endif
- +
- + galDevice = device;
- + gpuClass = device_class;
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_DRIVER,
- + "%s(%d): irqLine=%d, contiguousSize=%lu, memBase=0x%lX\n",
- + __FUNCTION__, __LINE__,
- + irqLine, contiguousSize, registerMemBase
- + );
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return 0;
- +
- +OnError:
- + /* Roll back. */
- + if (device_class != gcvNULL)
- + {
- + device_destroy(device_class, MKDEV(major, 0));
- + class_destroy(device_class);
- + }
- +
- + if (device != gcvNULL)
- + {
- + gcmkVERIFY_OK(gckGALDEVICE_Stop(device));
- + gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
- + }
- +
- + gcmkFOOTER();
- + return result;
- +}
- +
- +#if !USE_PLATFORM_DRIVER
- +static void __exit drv_exit(void)
- +#else
- +static void drv_exit(void)
- +#endif
- +{
- + gcmkHEADER();
- +
- +#ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
- + task_free_unregister(&task_nb);
- + unregister_reserved_memory_account(&viv_gpu_resmem_handler);
- +#endif
- +
- + gcmkASSERT(gpuClass != gcvNULL);
- + device_destroy(gpuClass, MKDEV(major, 0));
- + class_destroy(gpuClass);
- +
- + unregister_chrdev(major, DRV_NAME);
- +
- + gcmkVERIFY_OK(gckGALDEVICE_Stop(galDevice));
- + gcmkVERIFY_OK(gckGALDEVICE_Destroy(galDevice));
- +
- + if(gckDebugFileSystemIsEnabled())
- + {
- + gckDebugFileSystemTerminate();
- + }
- +
- +#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
- + {
- +# if 0
- + struct clk * clk = NULL;
- +
- +#if defined(CONFIG_PXA_DVFM) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
- + gc_pwr(0);
- +#endif
- + clk = clk_get(NULL, "GCCLK");
- + clk_disable(clk);
- +# endif
- + }
- +#endif
- +
- + gcmkFOOTER_NO();
- +}
- +
- +#if !USE_PLATFORM_DRIVER
- + module_init(drv_init);
- + module_exit(drv_exit);
- +#else
- +
- +#ifdef CONFIG_DOVE_GPU
- +# define DEVICE_NAME "dove_gpu"
- +#else
- +# define DEVICE_NAME "galcore"
- +#endif
- +
- +#if gcdENABLE_FSCALE_VAL_ADJUST
- +static int thermal_hot_pm_notify(struct notifier_block *nb, unsigned long event,
- + void *dummy)
- +{
- + static gctUINT orgFscale, minFscale, maxFscale;
- + static gctBOOL bAlreadyTooHot = gcvFALSE;
- + gckHARDWARE hardware = galDevice->kernels[gcvCORE_MAJOR]->hardware;
- +
- + if (event && !bAlreadyTooHot) {
- + gckHARDWARE_GetFscaleValue(hardware,&orgFscale,&minFscale, &maxFscale);
- + gckHARDWARE_SetFscaleValue(hardware, minFscale);
- + bAlreadyTooHot = gcvTRUE;
- + gckOS_Print("System is too hot. GPU3D will work at %d/64 clock.\n", minFscale);
- + } else if (!event && bAlreadyTooHot) {
- + gckHARDWARE_SetFscaleValue(hardware, orgFscale);
- + gckOS_Print("Hot alarm is canceled. GPU3D clock will return to %d/64\n", orgFscale);
- + bAlreadyTooHot = gcvFALSE;
- + }
- + return NOTIFY_OK;
- +}
- +
- +static struct notifier_block thermal_hot_pm_notifier = {
- + .notifier_call = thermal_hot_pm_notify,
- + };
- +#endif
- +
- +
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
- +static int gpu_probe(struct platform_device *pdev)
- +#else
- +static int __devinit gpu_probe(struct platform_device *pdev)
- +#endif
- +{
- + int ret = -ENODEV;
- + struct resource* res;
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- + struct contiguous_mem_pool *pool;
- + struct reset_control *rstc;
- +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
- + struct device_node *dn =pdev->dev.of_node;
- + const u32 *prop;
- +#else
- + struct viv_gpu_platform_data *pdata;
- +#endif
- + gcmkHEADER();
- +
- + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phys_baseaddr");
- + if (res)
- + baseAddress = res->start;
- +
- + res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_3d");
- + if (res)
- + irqLine = res->start;
- +
- + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_3d");
- + if (res)
- + {
- + registerMemBase = res->start;
- + registerMemSize = res->end - res->start + 1;
- + }
- +
- + res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_2d");
- + if (res)
- + irqLine2D = res->start;
- +
- + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_2d");
- + if (res)
- + {
- + registerMemBase2D = res->start;
- + registerMemSize2D = res->end - res->start + 1;
- + }
- +
- + res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_vg");
- + if (res)
- + irqLineVG = res->start;
- +
- + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_vg");
- + if (res)
- + {
- + registerMemBaseVG = res->start;
- + registerMemSizeVG = res->end - res->start + 1;
- + }
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- + pool = devm_kzalloc(&pdev->dev, sizeof(*pool), GFP_KERNEL);
- + if (!pool)
- + return -ENOMEM;
- + pool->size = contiguousSize;
- + init_dma_attrs(&pool->attrs);
- + dma_set_attr(DMA_ATTR_WRITE_COMBINE, &pool->attrs);
- + pool->virt = dma_alloc_attrs(&pdev->dev, pool->size, &pool->phys,
- + GFP_KERNEL, &pool->attrs);
- + if (!pool->virt) {
- + dev_err(&pdev->dev, "Failed to allocate contiguous memory\n");
- + return -ENOMEM;
- + }
- + contiguousBase = pool->phys;
- + dev_set_drvdata(&pdev->dev, pool);
- +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
- + prop = of_get_property(dn, "contiguousbase", NULL);
- + if(prop)
- + contiguousBase = *prop;
- + of_property_read_u32(dn,"contiguoussize", (u32 *)&contiguousSize);
- +#else
- + pdata = pdev->dev.platform_data;
- + if (pdata) {
- + contiguousBase = pdata->reserved_mem_base;
- + contiguousSize = pdata->reserved_mem_size;
- + }
- +#endif
- + if (contiguousSize == 0)
- + gckOS_Print("Warning: No contiguous memory is reserverd for gpu.!\n ");
- + ret = drv_init(&pdev->dev);
- +
- + if (!ret)
- + {
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- + rstc = devm_reset_control_get(&pdev->dev, "gpu3d");
- + galDevice->rstc[gcvCORE_MAJOR] = IS_ERR(rstc) ? NULL : rstc;
- +
- + rstc = devm_reset_control_get(&pdev->dev, "gpu2d");
- + galDevice->rstc[gcvCORE_2D] = IS_ERR(rstc) ? NULL : rstc;
- +
- + rstc = devm_reset_control_get(&pdev->dev, "gpuvg");
- + galDevice->rstc[gcvCORE_VG] = IS_ERR(rstc) ? NULL : rstc;
- +#endif
- + platform_set_drvdata(pdev, galDevice);
- +
- +#if gcdENABLE_FSCALE_VAL_ADJUST
- + if (galDevice->kernels[gcvCORE_MAJOR])
- + REG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier);
- +#endif
- + gcmkFOOTER_NO();
- + return ret;
- + }
- +#if gcdENABLE_FSCALE_VAL_ADJUST
- + UNREG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier);
- +#endif
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- + dma_free_attrs(&pdev->dev, pool->size, pool->virt, pool->phys,
- + &pool->attrs);
- +#endif
- + gcmkFOOTER_ARG(KERN_INFO "Failed to register gpu driver: %d\n", ret);
- + return ret;
- +}
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
- +static int gpu_remove(struct platform_device *pdev)
- +#else
- +static int __devexit gpu_remove(struct platform_device *pdev)
- +#endif
- +{
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- + gckGALDEVICE device = platform_get_drvdata(pdev);
- + struct contiguous_mem_pool *pool = device->pool;
- +#endif
- + gcmkHEADER();
- +#if gcdENABLE_FSCALE_VAL_ADJUST
- + if(galDevice->kernels[gcvCORE_MAJOR])
- + UNREG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier);
- +#endif
- + drv_exit();
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- + dma_free_attrs(&pdev->dev, pool->size, pool->virt, pool->phys,
- + &pool->attrs);
- +#endif
- + gcmkFOOTER_NO();
- + return 0;
- +}
- +
- +static int gpu_suspend(struct platform_device *dev, pm_message_t state)
- +{
- + gceSTATUS status;
- + gckGALDEVICE device;
- + gctINT i;
- +
- + device = platform_get_drvdata(dev);
- +
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + if (device->kernels[i] != gcvNULL)
- + {
- + /* Store states. */
- +#if gcdENABLE_VG
- + if (i == gcvCORE_VG)
- + {
- + status = gckVGHARDWARE_QueryPowerManagementState(device->kernels[i]->vg->hardware, &device->statesStored[i]);
- + }
- + else
- +#endif
- + {
- + status = gckHARDWARE_QueryPowerManagementState(device->kernels[i]->hardware, &device->statesStored[i]);
- + }
- +
- + if (gcmIS_ERROR(status))
- + {
- + return -1;
- + }
- +
- +#if gcdENABLE_VG
- + if (i == gcvCORE_VG)
- + {
- + status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, gcvPOWER_OFF);
- + }
- + else
- +#endif
- + {
- + status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_OFF);
- + }
- + if (gcmIS_ERROR(status))
- + {
- + return -1;
- + }
- +
- + }
- + }
- +
- + return 0;
- +}
- +
- +static int gpu_resume(struct platform_device *dev)
- +{
- + gceSTATUS status;
- + gckGALDEVICE device;
- + gctINT i;
- + gceCHIPPOWERSTATE statesStored;
- +
- + device = platform_get_drvdata(dev);
- +
- + for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- + {
- + if (device->kernels[i] != gcvNULL)
- + {
- +#if gcdENABLE_VG
- + if (i == gcvCORE_VG)
- + {
- + status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, gcvPOWER_ON);
- + }
- + else
- +#endif
- + {
- + status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_ON);
- + }
- +
- + if (gcmIS_ERROR(status))
- + {
- + return -1;
- + }
- +
- + /* Convert global state to crossponding internal state. */
- + switch(device->statesStored[i])
- + {
- + case gcvPOWER_OFF:
- + statesStored = gcvPOWER_OFF_BROADCAST;
- + break;
- + case gcvPOWER_IDLE:
- + statesStored = gcvPOWER_IDLE_BROADCAST;
- + break;
- + case gcvPOWER_SUSPEND:
- + statesStored = gcvPOWER_SUSPEND_BROADCAST;
- + break;
- + case gcvPOWER_ON:
- + statesStored = gcvPOWER_ON_AUTO;
- + break;
- + default:
- + statesStored = device->statesStored[i];
- + break;
- + }
- +
- + /* Restore states. */
- +#if gcdENABLE_VG
- + if (i == gcvCORE_VG)
- + {
- + status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, statesStored);
- + }
- + else
- +#endif
- + {
- + status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, statesStored);
- + }
- +
- + if (gcmIS_ERROR(status))
- + {
- + return -1;
- + }
- + }
- + }
- +
- + return 0;
- +}
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
- +static const struct of_device_id mxs_gpu_dt_ids[] = {
- + { .compatible = "fsl,imx6q-gpu", },
- + {/* sentinel */}
- +};
- +MODULE_DEVICE_TABLE(of, mxs_gpu_dt_ids);
- +
- +#ifdef CONFIG_PM
- +static int gpu_runtime_suspend(struct device *dev)
- +{
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 7)
- + release_bus_freq(BUS_FREQ_HIGH);
- +#endif
- + return 0;
- +}
- +
- +static int gpu_runtime_resume(struct device *dev)
- +{
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 7)
- + request_bus_freq(BUS_FREQ_HIGH);
- +#endif
- + return 0;
- +}
- +
- +static int gpu_system_suspend(struct device *dev)
- +{
- + pm_message_t state={0};
- + return gpu_suspend(to_platform_device(dev), state);
- +}
- +
- +static int gpu_system_resume(struct device *dev)
- +{
- + return gpu_resume(to_platform_device(dev));
- +}
- +
- +static const struct dev_pm_ops gpu_pm_ops = {
- + SET_RUNTIME_PM_OPS(gpu_runtime_suspend, gpu_runtime_resume, NULL)
- + SET_SYSTEM_SLEEP_PM_OPS(gpu_system_suspend, gpu_system_resume)
- +};
- +#endif
- +#endif
- +
- +static struct platform_driver gpu_driver = {
- + .probe = gpu_probe,
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
- + .remove = gpu_remove,
- +#else
- + .remove = __devexit_p(gpu_remove),
- +#endif
- +
- + .suspend = gpu_suspend,
- + .resume = gpu_resume,
- +
- + .driver = {
- + .name = DEVICE_NAME,
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
- + .of_match_table = mxs_gpu_dt_ids,
- +#if CONFIG_PM
- + .pm = &gpu_pm_ops,
- +#endif
- +#endif
- + }
- +};
- +
- +#if 0 /*CONFIG_DOVE_GPU*/
- +static struct resource gpu_resources[] = {
- + {
- + .name = "gpu_irq",
- + .flags = IORESOURCE_IRQ,
- + },
- + {
- + .name = "gpu_base",
- + .flags = IORESOURCE_MEM,
- + },
- + {
- + .name = "gpu_mem",
- + .flags = IORESOURCE_MEM,
- + },
- +};
- +
- +static struct platform_device * gpu_device;
- +#endif
- +
- +static int __init gpu_init(void)
- +{
- + int ret = 0;
- +
- +#if 0 /*ndef CONFIG_DOVE_GPU*/
- + gpu_resources[0].start = gpu_resources[0].end = irqLine;
- +
- + gpu_resources[1].start = registerMemBase;
- + gpu_resources[1].end = registerMemBase + registerMemSize - 1;
- +
- + gpu_resources[2].start = contiguousBase;
- + gpu_resources[2].end = contiguousBase + contiguousSize - 1;
- +
- + /* Allocate device */
- + gpu_device = platform_device_alloc(DEVICE_NAME, -1);
- + if (!gpu_device)
- + {
- + printk(KERN_ERR "galcore: platform_device_alloc failed.\n");
- + ret = -ENOMEM;
- + goto out;
- + }
- +
- + /* Insert resource */
- + ret = platform_device_add_resources(gpu_device, gpu_resources, 3);
- + if (ret)
- + {
- + printk(KERN_ERR "galcore: platform_device_add_resources failed.\n");
- + goto put_dev;
- + }
- +
- + /* Add device */
- + ret = platform_device_add(gpu_device);
- + if (ret)
- + {
- + printk(KERN_ERR "galcore: platform_device_add failed.\n");
- + goto put_dev;
- + }
- +#endif
- +
- + ret = platform_driver_register(&gpu_driver);
- + if (!ret)
- + {
- + goto out;
- + }
- +
- +#if 0 /*ndef CONFIG_DOVE_GPU*/
- + platform_device_del(gpu_device);
- +put_dev:
- + platform_device_put(gpu_device);
- +#endif
- +
- +out:
- + return ret;
- +}
- +
- +static void __exit gpu_exit(void)
- +{
- + platform_driver_unregister(&gpu_driver);
- +#if 0 /*ndef CONFIG_DOVE_GPU*/
- + platform_device_unregister(gpu_device);
- +#endif
- +}
- +
- +module_init(gpu_init);
- +module_exit(gpu_exit);
- +
- +#endif
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.c linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.c 2015-03-08 14:27:37.653684501 -0500
- @@ -0,0 +1,481 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal_kernel_linux.h"
- +
- +#define _GC_OBJ_ZONE gcvZONE_KERNEL
- +
- +/******************************************************************************\
- +******************************* gckKERNEL API Code ******************************
- +\******************************************************************************/
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_QueryVideoMemory
- +**
- +** Query the amount of video memory.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** OUTPUT:
- +**
- +** gcsHAL_INTERFACE * Interface
- +** Pointer to an gcsHAL_INTERFACE structure that will be filled in with
- +** the memory information.
- +*/
- +gceSTATUS
- +gckKERNEL_QueryVideoMemory(
- + IN gckKERNEL Kernel,
- + OUT gcsHAL_INTERFACE * Interface
- + )
- +{
- + gckGALDEVICE device;
- +
- + gcmkHEADER_ARG("Kernel=%p", Kernel);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(Interface != NULL);
- +
- + /* Extract the pointer to the gckGALDEVICE class. */
- + device = (gckGALDEVICE) Kernel->context;
- +
- + /* Get internal memory size and physical address. */
- + Interface->u.QueryVideoMemory.internalSize = device->internalSize;
- + Interface->u.QueryVideoMemory.internalPhysical = device->internalPhysicalName;
- +
- + /* Get external memory size and physical address. */
- + Interface->u.QueryVideoMemory.externalSize = device->externalSize;
- + Interface->u.QueryVideoMemory.externalPhysical = device->externalPhysicalName;
- +
- + /* Get contiguous memory size and physical address. */
- + Interface->u.QueryVideoMemory.contiguousSize = device->contiguousSize;
- + Interface->u.QueryVideoMemory.contiguousPhysical = device->contiguousPhysicalName;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_GetVideoMemoryPool
- +**
- +** Get the gckVIDMEM object belonging to the specified pool.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gcePOOL Pool
- +** Pool to query gckVIDMEM object for.
- +**
- +** OUTPUT:
- +**
- +** gckVIDMEM * VideoMemory
- +** Pointer to a variable that will hold the pointer to the gckVIDMEM
- +** object belonging to the requested pool.
- +*/
- +gceSTATUS
- +gckKERNEL_GetVideoMemoryPool(
- + IN gckKERNEL Kernel,
- + IN gcePOOL Pool,
- + OUT gckVIDMEM * VideoMemory
- + )
- +{
- + gckGALDEVICE device;
- + gckVIDMEM videoMemory;
- +
- + gcmkHEADER_ARG("Kernel=%p Pool=%d", Kernel, Pool);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(VideoMemory != NULL);
- +
- + /* Extract the pointer to the gckGALDEVICE class. */
- + device = (gckGALDEVICE) Kernel->context;
- +
- + /* Dispatch on pool. */
- + switch (Pool)
- + {
- + case gcvPOOL_LOCAL_INTERNAL:
- + /* Internal memory. */
- + videoMemory = device->internalVidMem;
- + break;
- +
- + case gcvPOOL_LOCAL_EXTERNAL:
- + /* External memory. */
- + videoMemory = device->externalVidMem;
- + break;
- +
- + case gcvPOOL_SYSTEM:
- + /* System memory. */
- + videoMemory = device->contiguousVidMem;
- + break;
- +
- + default:
- + /* Unknown pool. */
- + videoMemory = NULL;
- + }
- +
- + /* Return pointer to the gckVIDMEM object. */
- + *VideoMemory = videoMemory;
- +
- + /* Return status. */
- + gcmkFOOTER_ARG("*VideoMemory=%p", *VideoMemory);
- + return (videoMemory == NULL) ? gcvSTATUS_OUT_OF_MEMORY : gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_MapMemory
- +**
- +** Map video memory into the current process space.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gctPHYS_ADDR Physical
- +** Physical address of video memory to map.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes to map.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * Logical
- +** Pointer to a variable that will hold the base address of the mapped
- +** memory region.
- +*/
- +gceSTATUS
- +gckKERNEL_MapMemory(
- + IN gckKERNEL Kernel,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER * Logical
- + )
- +{
- + gckKERNEL kernel = Kernel;
- + gctPHYS_ADDR physical = gcmNAME_TO_PTR(Physical);
- +
- + return gckOS_MapMemory(Kernel->os, physical, Bytes, Logical);
- +}
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_UnmapMemory
- +**
- +** Unmap video memory from the current process space.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gctPHYS_ADDR Physical
- +** Physical address of video memory to map.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes to map.
- +**
- +** gctPOINTER Logical
- +** Base address of the mapped memory region.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckKERNEL_UnmapMemory(
- + IN gckKERNEL Kernel,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes,
- + IN gctPOINTER Logical
- + )
- +{
- + gckKERNEL kernel = Kernel;
- + gctPHYS_ADDR physical = gcmNAME_TO_PTR(Physical);
- +
- + return gckOS_UnmapMemory(Kernel->os, physical, Bytes, Logical);
- +}
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_MapVideoMemory
- +**
- +** Get the logical address for a hardware specific memory address for the
- +** current process.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gctBOOL InUserSpace
- +** gcvTRUE to map the memory into the user space.
- +**
- +** gctUINT32 Address
- +** Hardware specific memory address.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * Logical
- +** Pointer to a variable that will hold the logical address of the
- +** specified memory address.
- +*/
- +gceSTATUS
- +gckKERNEL_MapVideoMemoryEx(
- + IN gckKERNEL Kernel,
- + IN gceCORE Core,
- + IN gctBOOL InUserSpace,
- + IN gctUINT32 Address,
- + OUT gctPOINTER * Logical
- + )
- +{
- + gckGALDEVICE device;
- + PLINUX_MDL mdl;
- + PLINUX_MDL_MAP mdlMap;
- + gcePOOL pool;
- + gctUINT32 offset, base;
- + gceSTATUS status;
- + gctPOINTER logical;
- +
- + gcmkHEADER_ARG("Kernel=%p InUserSpace=%d Address=%08x",
- + Kernel, InUserSpace, Address);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(Logical != NULL);
- +
- + /* Extract the pointer to the gckGALDEVICE class. */
- + device = (gckGALDEVICE) Kernel->context;
- +
- +#if gcdENABLE_VG
- + if (Core == gcvCORE_VG)
- + {
- + /* Split the memory address into a pool type and offset. */
- + gcmkONERROR(
- + gckVGHARDWARE_SplitMemory(Kernel->vg->hardware, Address, &pool, &offset));
- + }
- + else
- +#endif
- + {
- + /* Split the memory address into a pool type and offset. */
- + gcmkONERROR(
- + gckHARDWARE_SplitMemory(Kernel->hardware, Address, &pool, &offset));
- + }
- +
- + /* Dispatch on pool. */
- + switch (pool)
- + {
- + case gcvPOOL_LOCAL_INTERNAL:
- + /* Internal memory. */
- + logical = device->internalLogical;
- + break;
- +
- + case gcvPOOL_LOCAL_EXTERNAL:
- + /* External memory. */
- + logical = device->externalLogical;
- + break;
- +
- + case gcvPOOL_SYSTEM:
- + /* System memory. */
- + if (device->contiguousMapped)
- + {
- + logical = device->contiguousBase;
- + }
- + else
- + {
- + gctINT processID;
- + gckOS_GetProcessID(&processID);
- +
- + mdl = (PLINUX_MDL) device->contiguousPhysical;
- +
- + mdlMap = FindMdlMap(mdl, processID);
- + gcmkASSERT(mdlMap);
- +
- + logical = (gctPOINTER) mdlMap->vmaAddr;
- + }
- +#if gcdENABLE_VG
- + if (Core == gcvCORE_VG)
- + {
- + gcmkVERIFY_OK(
- + gckVGHARDWARE_SplitMemory(Kernel->vg->hardware,
- + device->contiguousVidMem->baseAddress,
- + &pool,
- + &base));
- + }
- + else
- +#endif
- + {
- + gctUINT32 baseAddress = 0;
- +
- + if (Kernel->hardware->mmuVersion == 0)
- + {
- + gcmkONERROR(gckOS_GetBaseAddress(Kernel->os, &baseAddress));
- + }
- +
- + gcmkVERIFY_OK(
- + gckHARDWARE_SplitMemory(Kernel->hardware,
- + device->contiguousVidMem->baseAddress - baseAddress,
- + &pool,
- + &base));
- + }
- + offset -= base;
- + break;
- +
- + default:
- + /* Invalid memory pool. */
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + /* Build logical address of specified address. */
- + *Logical = (gctPOINTER) ((gctUINT8_PTR) logical + offset);
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Logical=%p", *Logical);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Retunn the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckKERNEL_MapVideoMemory
- +**
- +** Get the logical address for a hardware specific memory address for the
- +** current process.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gctBOOL InUserSpace
- +** gcvTRUE to map the memory into the user space.
- +**
- +** gctUINT32 Address
- +** Hardware specific memory address.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * Logical
- +** Pointer to a variable that will hold the logical address of the
- +** specified memory address.
- +*/
- +gceSTATUS
- +gckKERNEL_MapVideoMemory(
- + IN gckKERNEL Kernel,
- + IN gctBOOL InUserSpace,
- + IN gctUINT32 Address,
- + OUT gctPOINTER * Logical
- + )
- +{
- + return gckKERNEL_MapVideoMemoryEx(Kernel, gcvCORE_MAJOR, InUserSpace, Address, Logical);
- +}
- +/*******************************************************************************
- +**
- +** gckKERNEL_Notify
- +**
- +** This function iscalled by clients to notify the gckKERNRL object of an event.
- +**
- +** INPUT:
- +**
- +** gckKERNEL Kernel
- +** Pointer to an gckKERNEL object.
- +**
- +** gceNOTIFY Notification
- +** Notification event.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckKERNEL_Notify(
- + IN gckKERNEL Kernel,
- + IN gceNOTIFY Notification,
- + IN gctBOOL Data
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Kernel=%p Notification=%d Data=%d",
- + Kernel, Notification, Data);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- +
- + /* Dispatch on notifcation. */
- + switch (Notification)
- + {
- + case gcvNOTIFY_INTERRUPT:
- + /* Process the interrupt. */
- +#if COMMAND_PROCESSOR_VERSION > 1
- + status = gckINTERRUPT_Notify(Kernel->interrupt, Data);
- +#else
- + status = gckHARDWARE_Interrupt(Kernel->hardware, Data);
- +#endif
- + break;
- +
- + default:
- + status = gcvSTATUS_OK;
- + break;
- + }
- +
- + /* Success. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckKERNEL_QuerySettings(
- + IN gckKERNEL Kernel,
- + OUT gcsKERNEL_SETTINGS * Settings
- + )
- +{
- + gckGALDEVICE device;
- +
- + gcmkHEADER_ARG("Kernel=%p", Kernel);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
- + gcmkVERIFY_ARGUMENT(Settings != gcvNULL);
- +
- + /* Extract the pointer to the gckGALDEVICE class. */
- + device = (gckGALDEVICE) Kernel->context;
- +
- + /* Fill in signal. */
- + Settings->signal = device->signal;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("Settings->signal=%d", Settings->signal);
- + return gcvSTATUS_OK;
- +}
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h 2015-03-08 14:27:37.653684501 -0500
- @@ -0,0 +1,94 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_kernel_linux_h_
- +#define __gc_hal_kernel_linux_h_
- +
- +#include <linux/version.h>
- +#include <linux/init.h>
- +#include <linux/module.h>
- +#include <linux/fs.h>
- +#include <linux/mm.h>
- +#include <linux/sched.h>
- +#include <linux/signal.h>
- +#ifdef FLAREON
- +# include <asm/arch-realview/dove_gpio_irq.h>
- +#endif
- +#include <linux/interrupt.h>
- +#include <linux/vmalloc.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/kthread.h>
- +
- +#ifdef MODVERSIONS
- +# include <linux/modversions.h>
- +#endif
- +#include <asm/io.h>
- +#include <asm/uaccess.h>
- +
- +#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
- +#include <linux/clk.h>
- +#include <linux/regulator/consumer.h>
- +#endif
- +
- +#define NTSTRSAFE_NO_CCH_FUNCTIONS
- +#include "gc_hal.h"
- +#include "gc_hal_driver.h"
- +#include "gc_hal_kernel.h"
- +#include "gc_hal_kernel_device.h"
- +#include "gc_hal_kernel_os.h"
- +#include "gc_hal_kernel_debugfs.h"
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
- +#define FIND_TASK_BY_PID(x) pid_task(find_vpid(x), PIDTYPE_PID)
- +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
- +#define FIND_TASK_BY_PID(x) find_task_by_vpid(x)
- +#else
- +#define FIND_TASK_BY_PID(x) find_task_by_pid(x)
- +#endif
- +
- +#define _WIDE(string) L##string
- +#define WIDE(string) _WIDE(string)
- +
- +#define countof(a) (sizeof(a) / sizeof(a[0]))
- +
- +#define DRV_NAME "galcore"
- +
- +#define GetPageCount(size, offset) ((((size) + ((offset) & ~PAGE_CACHE_MASK)) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION (3,7,0)
- +#define gcdVM_FLAGS (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP)
- +#else
- +#define gcdVM_FLAGS (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED)
- +#endif
- +
- +static inline gctINT
- +GetOrder(
- + IN gctINT numPages
- + )
- +{
- + gctINT order = 0;
- +
- + while ((1 << order) < numPages) order++;
- +
- + return order;
- +}
- +
- +#endif /* __gc_hal_kernel_linux_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_math.c linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_math.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_math.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_math.c 2015-03-08 14:27:37.653684501 -0500
- @@ -0,0 +1,32 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal_kernel_linux.h"
- +
- +gctINT
- +gckMATH_ModuloInt(
- + IN gctINT X,
- + IN gctINT Y
- + )
- +{
- + if(Y ==0) {return 0;}
- + else {return X % Y;}
- +}
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c 2015-03-08 14:27:37.657684501 -0500
- @@ -0,0 +1,9019 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include "gc_hal_kernel_linux.h"
- +
- +#include <linux/pagemap.h>
- +#include <linux/seq_file.h>
- +#include <linux/mm.h>
- +#include <linux/mman.h>
- +#include <linux/sched.h>
- +#include <asm/atomic.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/slab.h>
- +#include <linux/idr.h>
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
- +#include <mach/hardware.h>
- +#endif
- +#include <linux/workqueue.h>
- +#include <linux/idr.h>
- +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
- +#include <linux/math64.h>
- +#endif
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- +#include <linux/reset.h>
- +static inline void imx_gpc_power_up_pu(bool flag) {}
- +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
- +#include <mach/common.h>
- +#endif
- +#include <linux/delay.h>
- +#include <linux/pm_runtime.h>
- +
- +
- +#if gcdANDROID_NATIVE_FENCE_SYNC
- +#include <linux/file.h>
- +#include "gc_hal_kernel_sync.h"
- +#endif
- +
- +
- +#define _GC_OBJ_ZONE gcvZONE_OS
- +
- +/*******************************************************************************
- +***** Version Signature *******************************************************/
- +
- +#ifdef ANDROID
- +const char * _PLATFORM = "\n\0$PLATFORM$Android$\n";
- +#else
- +const char * _PLATFORM = "\n\0$PLATFORM$Linux$\n";
- +#endif
- +
- +#define USER_SIGNAL_TABLE_LEN_INIT 64
- +#define gcdSUPPRESS_OOM_MESSAGE 1
- +
- +#define MEMORY_LOCK(os) \
- + gcmkVERIFY_OK(gckOS_AcquireMutex( \
- + (os), \
- + (os)->memoryLock, \
- + gcvINFINITE))
- +
- +#define MEMORY_UNLOCK(os) \
- + gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryLock))
- +
- +#define MEMORY_MAP_LOCK(os) \
- + gcmkVERIFY_OK(gckOS_AcquireMutex( \
- + (os), \
- + (os)->memoryMapLock, \
- + gcvINFINITE))
- +
- +#define MEMORY_MAP_UNLOCK(os) \
- + gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryMapLock))
- +
- +/* Protection bit when mapping memroy to user sapce */
- +#define gcmkPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
- +
- +#if gcdNONPAGED_MEMORY_BUFFERABLE
- +#define gcmkIOREMAP ioremap_wc
- +#define gcmkNONPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
- +#elif !gcdNONPAGED_MEMORY_CACHEABLE
- +#define gcmkIOREMAP ioremap_nocache
- +#define gcmkNONPAGED_MEMROY_PROT(x) pgprot_noncached(x)
- +#endif
- +
- +#if gcdSUPPRESS_OOM_MESSAGE
- +#define gcdNOWARN __GFP_NOWARN
- +#else
- +#define gcdNOWARN 0
- +#endif
- +
- +#define gcdINFINITE_TIMEOUT (60 * 1000)
- +#define gcdDETECT_TIMEOUT 0
- +#define gcdDETECT_DMA_ADDRESS 1
- +#define gcdDETECT_DMA_STATE 1
- +
- +#define gcdUSE_NON_PAGED_MEMORY_CACHE 10
- +
- +/******************************************************************************\
- +********************************** Structures **********************************
- +\******************************************************************************/
- +#if gcdUSE_NON_PAGED_MEMORY_CACHE
- +typedef struct _gcsNonPagedMemoryCache
- +{
- +#ifndef NO_DMA_COHERENT
- + gctINT size;
- + gctSTRING addr;
- + dma_addr_t dmaHandle;
- +#else
- + long order;
- + struct page * page;
- +#endif
- +
- + struct _gcsNonPagedMemoryCache * prev;
- + struct _gcsNonPagedMemoryCache * next;
- +}
- +gcsNonPagedMemoryCache;
- +#endif /* gcdUSE_NON_PAGED_MEMORY_CACHE */
- +
- +typedef struct _gcsUSER_MAPPING * gcsUSER_MAPPING_PTR;
- +typedef struct _gcsUSER_MAPPING
- +{
- + /* Pointer to next mapping structure. */
- + gcsUSER_MAPPING_PTR next;
- +
- + /* Physical address of this mapping. */
- + gctUINT32 physical;
- +
- + /* Logical address of this mapping. */
- + gctPOINTER logical;
- +
- + /* Number of bytes of this mapping. */
- + gctSIZE_T bytes;
- +
- + /* Starting address of this mapping. */
- + gctINT8_PTR start;
- +
- + /* Ending address of this mapping. */
- + gctINT8_PTR end;
- +}
- +gcsUSER_MAPPING;
- +
- +typedef struct _gcsINTEGER_DB * gcsINTEGER_DB_PTR;
- +typedef struct _gcsINTEGER_DB
- +{
- + struct idr idr;
- + spinlock_t lock;
- + gctINT curr;
- +}
- +gcsINTEGER_DB;
- +
- +struct _gckOS
- +{
- + /* Object. */
- + gcsOBJECT object;
- +
- + /* Heap. */
- + gckHEAP heap;
- +
- + /* Pointer to device */
- + gckGALDEVICE device;
- +
- + /* Memory management */
- + gctPOINTER memoryLock;
- + gctPOINTER memoryMapLock;
- +
- + struct _LINUX_MDL *mdlHead;
- + struct _LINUX_MDL *mdlTail;
- +
- + /* Kernel process ID. */
- + gctUINT32 kernelProcessID;
- +
- + /* Signal management. */
- +
- + /* Lock. */
- + gctPOINTER signalMutex;
- +
- + /* signal id database. */
- + gcsINTEGER_DB signalDB;
- +
- +#if gcdANDROID_NATIVE_FENCE_SYNC
- + /* Lock. */
- + gctPOINTER syncPointMutex;
- +
- + /* sync point id database. */
- + gcsINTEGER_DB syncPointDB;
- +#endif
- +
- + gcsUSER_MAPPING_PTR userMap;
- + gctPOINTER debugLock;
- +
- +#if gcdUSE_NON_PAGED_MEMORY_CACHE
- + gctUINT cacheSize;
- + gcsNonPagedMemoryCache * cacheHead;
- + gcsNonPagedMemoryCache * cacheTail;
- +#endif
- +
- + /* workqueue for os timer. */
- + struct workqueue_struct * workqueue;
- +};
- +
- +typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
- +typedef struct _gcsSIGNAL
- +{
- + /* Kernel sync primitive. */
- + struct completion obj;
- +
- + /* Manual reset flag. */
- + gctBOOL manualReset;
- +
- + /* The reference counter. */
- + atomic_t ref;
- +
- + /* The owner of the signal. */
- + gctHANDLE process;
- +
- + gckHARDWARE hardware;
- +
- + /* ID. */
- + gctUINT32 id;
- +}
- +gcsSIGNAL;
- +
- +#if gcdANDROID_NATIVE_FENCE_SYNC
- +typedef struct _gcsSYNC_POINT * gcsSYNC_POINT_PTR;
- +typedef struct _gcsSYNC_POINT
- +{
- + /* The reference counter. */
- + atomic_t ref;
- +
- + /* State. */
- + atomic_t state;
- +
- + /* timeline. */
- + struct sync_timeline * timeline;
- +
- + /* ID. */
- + gctUINT32 id;
- +}
- +gcsSYNC_POINT;
- +#endif
- +
- +typedef struct _gcsPageInfo * gcsPageInfo_PTR;
- +typedef struct _gcsPageInfo
- +{
- + struct page **pages;
- + gctUINT32_PTR pageTable;
- +}
- +gcsPageInfo;
- +
- +typedef struct _gcsOSTIMER * gcsOSTIMER_PTR;
- +typedef struct _gcsOSTIMER
- +{
- + struct delayed_work work;
- + gctTIMERFUNCTION function;
- + gctPOINTER data;
- +} gcsOSTIMER;
- +
- +/******************************************************************************\
- +******************************* Private Functions ******************************
- +\******************************************************************************/
- +
- +static gctINT
- +_GetProcessID(
- + void
- + )
- +{
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
- + return task_tgid_vnr(current);
- +#else
- + return current->tgid;
- +#endif
- +}
- +
- +static gctINT
- +_GetThreadID(
- + void
- + )
- +{
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
- + return task_pid_vnr(current);
- +#else
- + return current->pid;
- +#endif
- +}
- +
- +static PLINUX_MDL
- +_CreateMdl(
- + IN gctINT ProcessID
- + )
- +{
- + PLINUX_MDL mdl;
- +
- + gcmkHEADER_ARG("ProcessID=%d", ProcessID);
- +
- + mdl = (PLINUX_MDL)kzalloc(sizeof(struct _LINUX_MDL), GFP_KERNEL | gcdNOWARN);
- + if (mdl == gcvNULL)
- + {
- + gcmkFOOTER_NO();
- + return gcvNULL;
- + }
- +
- + mdl->pid = ProcessID;
- + mdl->maps = gcvNULL;
- + mdl->prev = gcvNULL;
- + mdl->next = gcvNULL;
- +
- + gcmkFOOTER_ARG("0x%X", mdl);
- + return mdl;
- +}
- +
- +static gceSTATUS
- +_DestroyMdlMap(
- + IN PLINUX_MDL Mdl,
- + IN PLINUX_MDL_MAP MdlMap
- + );
- +
- +static gceSTATUS
- +_DestroyMdl(
- + IN PLINUX_MDL Mdl
- + )
- +{
- + PLINUX_MDL_MAP mdlMap, next;
- +
- + gcmkHEADER_ARG("Mdl=0x%X", Mdl);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_ARGUMENT(Mdl != gcvNULL);
- +
- + mdlMap = Mdl->maps;
- +
- + while (mdlMap != gcvNULL)
- + {
- + next = mdlMap->next;
- +
- + gcmkVERIFY_OK(_DestroyMdlMap(Mdl, mdlMap));
- +
- + mdlMap = next;
- + }
- +
- + kfree(Mdl);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +static PLINUX_MDL_MAP
- +_CreateMdlMap(
- + IN PLINUX_MDL Mdl,
- + IN gctINT ProcessID
- + )
- +{
- + PLINUX_MDL_MAP mdlMap;
- +
- + gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
- +
- + mdlMap = (PLINUX_MDL_MAP)kmalloc(sizeof(struct _LINUX_MDL_MAP), GFP_KERNEL | gcdNOWARN);
- + if (mdlMap == gcvNULL)
- + {
- + gcmkFOOTER_NO();
- + return gcvNULL;
- + }
- +
- + mdlMap->pid = ProcessID;
- + mdlMap->vmaAddr = gcvNULL;
- + mdlMap->vma = gcvNULL;
- + mdlMap->count = 0;
- +
- + mdlMap->next = Mdl->maps;
- + Mdl->maps = mdlMap;
- +
- + gcmkFOOTER_ARG("0x%X", mdlMap);
- + return mdlMap;
- +}
- +
- +static gceSTATUS
- +_DestroyMdlMap(
- + IN PLINUX_MDL Mdl,
- + IN PLINUX_MDL_MAP MdlMap
- + )
- +{
- + PLINUX_MDL_MAP prevMdlMap;
- +
- + gcmkHEADER_ARG("Mdl=0x%X MdlMap=0x%X", Mdl, MdlMap);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_ARGUMENT(MdlMap != gcvNULL);
- + gcmkASSERT(Mdl->maps != gcvNULL);
- +
- + if (Mdl->maps == MdlMap)
- + {
- + Mdl->maps = MdlMap->next;
- + }
- + else
- + {
- + prevMdlMap = Mdl->maps;
- +
- + while (prevMdlMap->next != MdlMap)
- + {
- + prevMdlMap = prevMdlMap->next;
- +
- + gcmkASSERT(prevMdlMap != gcvNULL);
- + }
- +
- + prevMdlMap->next = MdlMap->next;
- + }
- +
- + kfree(MdlMap);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +extern PLINUX_MDL_MAP
- +FindMdlMap(
- + IN PLINUX_MDL Mdl,
- + IN gctINT ProcessID
- + )
- +{
- + PLINUX_MDL_MAP mdlMap;
- +
- + gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
- + if(Mdl == gcvNULL)
- + {
- + gcmkFOOTER_NO();
- + return gcvNULL;
- + }
- + mdlMap = Mdl->maps;
- +
- + while (mdlMap != gcvNULL)
- + {
- + if (mdlMap->pid == ProcessID)
- + {
- + gcmkFOOTER_ARG("0x%X", mdlMap);
- + return mdlMap;
- + }
- +
- + mdlMap = mdlMap->next;
- + }
- +
- + gcmkFOOTER_NO();
- + return gcvNULL;
- +}
- +
- +void
- +OnProcessExit(
- + IN gckOS Os,
- + IN gckKERNEL Kernel
- + )
- +{
- +}
- +
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
- +static inline int
- +is_vmalloc_addr(
- + void *Addr
- + )
- +{
- + unsigned long addr = (unsigned long)Addr;
- +
- + return addr >= VMALLOC_START && addr < VMALLOC_END;
- +}
- +#endif
- +
- +static void
- +_NonContiguousFree(
- + IN struct page ** Pages,
- + IN gctUINT32 NumPages
- + )
- +{
- + gctINT i;
- +
- + gcmkHEADER_ARG("Pages=0x%X, NumPages=%d", Pages, NumPages);
- +
- + gcmkASSERT(Pages != gcvNULL);
- +
- + for (i = 0; i < NumPages; i++)
- + {
- + __free_page(Pages[i]);
- + }
- +
- + if (is_vmalloc_addr(Pages))
- + {
- + vfree(Pages);
- + }
- + else
- + {
- + kfree(Pages);
- + }
- +
- + gcmkFOOTER_NO();
- +}
- +
- +static struct page **
- +_NonContiguousAlloc(
- + IN gctUINT32 NumPages
- + )
- +{
- + struct page ** pages;
- + struct page *p;
- + gctINT i, size;
- +
- + gcmkHEADER_ARG("NumPages=%lu", NumPages);
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
- + if (NumPages > totalram_pages)
- +#else
- + if (NumPages > num_physpages)
- +#endif
- + {
- + gcmkFOOTER_NO();
- + return gcvNULL;
- + }
- +
- + size = NumPages * sizeof(struct page *);
- +
- + pages = kmalloc(size, GFP_KERNEL | gcdNOWARN);
- +
- + if (!pages)
- + {
- + pages = vmalloc(size);
- +
- + if (!pages)
- + {
- + gcmkFOOTER_NO();
- + return gcvNULL;
- + }
- + }
- +
- + for (i = 0; i < NumPages; i++)
- + {
- + p = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN);
- +
- + if (!p)
- + {
- + _NonContiguousFree(pages, i);
- + gcmkFOOTER_NO();
- + return gcvNULL;
- + }
- +
- + pages[i] = p;
- + }
- +
- + gcmkFOOTER_ARG("pages=0x%X", pages);
- + return pages;
- +}
- +
- +static inline struct page *
- +_NonContiguousToPage(
- + IN struct page ** Pages,
- + IN gctUINT32 Index
- + )
- +{
- + gcmkASSERT(Pages != gcvNULL);
- + return Pages[Index];
- +}
- +
- +static inline unsigned long
- +_NonContiguousToPfn(
- + IN struct page ** Pages,
- + IN gctUINT32 Index
- + )
- +{
- + gcmkASSERT(Pages != gcvNULL);
- + return page_to_pfn(_NonContiguousToPage(Pages, Index));
- +}
- +
- +static inline unsigned long
- +_NonContiguousToPhys(
- + IN struct page ** Pages,
- + IN gctUINT32 Index
- + )
- +{
- + gcmkASSERT(Pages != gcvNULL);
- + return page_to_phys(_NonContiguousToPage(Pages, Index));
- +}
- +
- +
- +#if gcdUSE_NON_PAGED_MEMORY_CACHE
- +
- +static gctBOOL
- +_AddNonPagedMemoryCache(
- + gckOS Os,
- +#ifndef NO_DMA_COHERENT
- + gctINT Size,
- + gctSTRING Addr,
- + dma_addr_t DmaHandle
- +#else
- + long Order,
- + struct page * Page
- +#endif
- + )
- +{
- + gcsNonPagedMemoryCache *cache;
- +
- + if (Os->cacheSize >= gcdUSE_NON_PAGED_MEMORY_CACHE)
- + {
- + return gcvFALSE;
- + }
- +
- + /* Allocate the cache record */
- + cache = (gcsNonPagedMemoryCache *)kmalloc(sizeof(gcsNonPagedMemoryCache), GFP_ATOMIC);
- +
- + if (cache == gcvNULL) return gcvFALSE;
- +
- +#ifndef NO_DMA_COHERENT
- + cache->size = Size;
- + cache->addr = Addr;
- + cache->dmaHandle = DmaHandle;
- +#else
- + cache->order = Order;
- + cache->page = Page;
- +#endif
- +
- + /* Add to list */
- + if (Os->cacheHead == gcvNULL)
- + {
- + cache->prev = gcvNULL;
- + cache->next = gcvNULL;
- + Os->cacheHead =
- + Os->cacheTail = cache;
- + }
- + else
- + {
- + /* Add to the tail. */
- + cache->prev = Os->cacheTail;
- + cache->next = gcvNULL;
- + Os->cacheTail->next = cache;
- + Os->cacheTail = cache;
- + }
- +
- + Os->cacheSize++;
- +
- + return gcvTRUE;
- +}
- +
- +#ifndef NO_DMA_COHERENT
- +static gctSTRING
- +_GetNonPagedMemoryCache(
- + gckOS Os,
- + gctINT Size,
- + dma_addr_t * DmaHandle
- + )
- +#else
- +static struct page *
- +_GetNonPagedMemoryCache(
- + gckOS Os,
- + long Order
- + )
- +#endif
- +{
- + gcsNonPagedMemoryCache *cache;
- +#ifndef NO_DMA_COHERENT
- + gctSTRING addr;
- +#else
- + struct page * page;
- +#endif
- +
- + if (Os->cacheHead == gcvNULL) return gcvNULL;
- +
- + /* Find the right cache */
- + cache = Os->cacheHead;
- +
- + while (cache != gcvNULL)
- + {
- +#ifndef NO_DMA_COHERENT
- + if (cache->size == Size) break;
- +#else
- + if (cache->order == Order) break;
- +#endif
- +
- + cache = cache->next;
- + }
- +
- + if (cache == gcvNULL) return gcvNULL;
- +
- + /* Remove the cache from list */
- + if (cache == Os->cacheHead)
- + {
- + Os->cacheHead = cache->next;
- +
- + if (Os->cacheHead == gcvNULL)
- + {
- + Os->cacheTail = gcvNULL;
- + }
- + }
- + else
- + {
- + cache->prev->next = cache->next;
- +
- + if (cache == Os->cacheTail)
- + {
- + Os->cacheTail = cache->prev;
- + }
- + else
- + {
- + cache->next->prev = cache->prev;
- + }
- + }
- +
- + /* Destroy cache */
- +#ifndef NO_DMA_COHERENT
- + addr = cache->addr;
- + *DmaHandle = cache->dmaHandle;
- +#else
- + page = cache->page;
- +#endif
- +
- + kfree(cache);
- +
- + Os->cacheSize--;
- +
- +#ifndef NO_DMA_COHERENT
- + return addr;
- +#else
- + return page;
- +#endif
- +}
- +
- +static void
- +_FreeAllNonPagedMemoryCache(
- + gckOS Os
- + )
- +{
- + gcsNonPagedMemoryCache *cache, *nextCache;
- +
- + MEMORY_LOCK(Os);
- +
- + cache = Os->cacheHead;
- +
- + while (cache != gcvNULL)
- + {
- + if (cache != Os->cacheTail)
- + {
- + nextCache = cache->next;
- + }
- + else
- + {
- + nextCache = gcvNULL;
- + }
- +
- + /* Remove the cache from list */
- + if (cache == Os->cacheHead)
- + {
- + Os->cacheHead = cache->next;
- +
- + if (Os->cacheHead == gcvNULL)
- + {
- + Os->cacheTail = gcvNULL;
- + }
- + }
- + else
- + {
- + cache->prev->next = cache->next;
- +
- + if (cache == Os->cacheTail)
- + {
- + Os->cacheTail = cache->prev;
- + }
- + else
- + {
- + cache->next->prev = cache->prev;
- + }
- + }
- +
- +#ifndef NO_DMA_COHERENT
- + dma_free_coherent(gcvNULL,
- + cache->size,
- + cache->addr,
- + cache->dmaHandle);
- +#else
- + free_pages((unsigned long)page_address(cache->page), cache->order);
- +#endif
- +
- + kfree(cache);
- +
- + cache = nextCache;
- + }
- +
- + MEMORY_UNLOCK(Os);
- +}
- +
- +#endif /* gcdUSE_NON_PAGED_MEMORY_CACHE */
- +
- +/*******************************************************************************
- +** Integer Id Management.
- +*/
- +gceSTATUS
- +_AllocateIntegerId(
- + IN gcsINTEGER_DB_PTR Database,
- + IN gctPOINTER KernelPointer,
- + OUT gctUINT32 *Id
- + )
- +{
- + int result;
- + gctINT next;
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
- + idr_preload(GFP_KERNEL | gcdNOWARN);
- +
- + spin_lock(&Database->lock);
- +
- + next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1;
- + result = idr_alloc(&Database->idr, KernelPointer, next, 0, GFP_ATOMIC);
- +
- + if (!result)
- + {
- + Database->curr = *Id;
- + }
- +
- + spin_unlock(&Database->lock);
- +
- + idr_preload_end();
- +
- + if (result < 0)
- + {
- + return gcvSTATUS_OUT_OF_RESOURCES;
- + }
- +
- + *Id = result;
- +#else
- +again:
- + if (idr_pre_get(&Database->idr, GFP_KERNEL | gcdNOWARN) == 0)
- + {
- + return gcvSTATUS_OUT_OF_MEMORY;
- + }
- +
- + spin_lock(&Database->lock);
- +
- + next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1;
- +
- + /* Try to get a id greater than current id. */
- + result = idr_get_new_above(&Database->idr, KernelPointer, next, Id);
- +
- + if (!result)
- + {
- + Database->curr = *Id;
- + }
- +
- + spin_unlock(&Database->lock);
- +
- + if (result == -EAGAIN)
- + {
- + goto again;
- + }
- +
- + if (result != 0)
- + {
- + return gcvSTATUS_OUT_OF_RESOURCES;
- + }
- +#endif
- +
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +_QueryIntegerId(
- + IN gcsINTEGER_DB_PTR Database,
- + IN gctUINT32 Id,
- + OUT gctPOINTER * KernelPointer
- + )
- +{
- + gctPOINTER pointer;
- +
- + spin_lock(&Database->lock);
- +
- + pointer = idr_find(&Database->idr, Id);
- +
- + spin_unlock(&Database->lock);
- +
- + if(pointer)
- + {
- + *KernelPointer = pointer;
- + return gcvSTATUS_OK;
- + }
- + else
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_ERROR, gcvZONE_OS,
- + "%s(%d) Id = %d is not found",
- + __FUNCTION__, __LINE__, Id);
- +
- + return gcvSTATUS_NOT_FOUND;
- + }
- +}
- +
- +gceSTATUS
- +_DestroyIntegerId(
- + IN gcsINTEGER_DB_PTR Database,
- + IN gctUINT32 Id
- + )
- +{
- + spin_lock(&Database->lock);
- +
- + idr_remove(&Database->idr, Id);
- +
- + spin_unlock(&Database->lock);
- +
- + return gcvSTATUS_OK;
- +}
- +
- +static void
- +_UnmapUserLogical(
- + IN gctINT Pid,
- + IN gctPOINTER Logical,
- + IN gctUINT32 Size
- +)
- +{
- + if (unlikely(current->mm == gcvNULL))
- + {
- + /* Do nothing if process is exiting. */
- + return;
- + }
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
- + if (vm_munmap((unsigned long)Logical, Size) < 0)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_WARNING, gcvZONE_OS,
- + "%s(%d): vm_munmap failed",
- + __FUNCTION__, __LINE__
- + );
- + }
- +#else
- + down_write(¤t->mm->mmap_sem);
- + if (do_munmap(current->mm, (unsigned long)Logical, Size) < 0)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_WARNING, gcvZONE_OS,
- + "%s(%d): do_munmap failed",
- + __FUNCTION__, __LINE__
- + );
- + }
- + up_write(¤t->mm->mmap_sem);
- +#endif
- +}
- +
- +gceSTATUS
- +_QueryProcessPageTable(
- + IN gctPOINTER Logical,
- + OUT gctUINT32 * Address
- + )
- +{
- + spinlock_t *lock;
- + gctUINTPTR_T logical = (gctUINTPTR_T)Logical;
- + pgd_t *pgd;
- + pud_t *pud;
- + pmd_t *pmd;
- + pte_t *pte;
- +
- + if (!current->mm)
- + {
- + return gcvSTATUS_NOT_FOUND;
- + }
- +
- + pgd = pgd_offset(current->mm, logical);
- + if (pgd_none(*pgd) || pgd_bad(*pgd))
- + {
- + return gcvSTATUS_NOT_FOUND;
- + }
- +
- + pud = pud_offset(pgd, logical);
- + if (pud_none(*pud) || pud_bad(*pud))
- + {
- + return gcvSTATUS_NOT_FOUND;
- + }
- +
- + pmd = pmd_offset(pud, logical);
- + if (pmd_none(*pmd) || pmd_bad(*pmd))
- + {
- + return gcvSTATUS_NOT_FOUND;
- + }
- +
- + pte = pte_offset_map_lock(current->mm, pmd, logical, &lock);
- + if (!pte)
- + {
- + return gcvSTATUS_NOT_FOUND;
- + }
- +
- + if (!pte_present(*pte))
- + {
- + pte_unmap_unlock(pte, lock);
- + return gcvSTATUS_NOT_FOUND;
- + }
- +
- + *Address = (pte_pfn(*pte) << PAGE_SHIFT) | (logical & ~PAGE_MASK);
- + pte_unmap_unlock(pte, lock);
- +
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_Construct
- +**
- +** Construct a new gckOS object.
- +**
- +** INPUT:
- +**
- +** gctPOINTER Context
- +** Pointer to the gckGALDEVICE class.
- +**
- +** OUTPUT:
- +**
- +** gckOS * Os
- +** Pointer to a variable that will hold the pointer to the gckOS object.
- +*/
- +gceSTATUS
- +gckOS_Construct(
- + IN gctPOINTER Context,
- + OUT gckOS * Os
- + )
- +{
- + gckOS os;
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Context=0x%X", Context);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_ARGUMENT(Os != gcvNULL);
- +
- + /* Allocate the gckOS object. */
- + os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_KERNEL | gcdNOWARN);
- +
- + if (os == gcvNULL)
- + {
- + /* Out of memory. */
- + gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
- + return gcvSTATUS_OUT_OF_MEMORY;
- + }
- +
- + /* Zero the memory. */
- + gckOS_ZeroMemory(os, gcmSIZEOF(struct _gckOS));
- +
- + /* Initialize the gckOS object. */
- + os->object.type = gcvOBJ_OS;
- +
- + /* Set device device. */
- + os->device = Context;
- +
- + /* IMPORTANT! No heap yet. */
- + os->heap = gcvNULL;
- +
- + /* Initialize the memory lock. */
- + gcmkONERROR(gckOS_CreateMutex(os, &os->memoryLock));
- + gcmkONERROR(gckOS_CreateMutex(os, &os->memoryMapLock));
- +
- + /* Create debug lock mutex. */
- + gcmkONERROR(gckOS_CreateMutex(os, &os->debugLock));
- +
- +
- + os->mdlHead = os->mdlTail = gcvNULL;
- +
- + /* Get the kernel process ID. */
- + gcmkONERROR(gckOS_GetProcessID(&os->kernelProcessID));
- +
- + /*
- + * Initialize the signal manager.
- + */
- +
- + /* Initialize mutex. */
- + gcmkONERROR(gckOS_CreateMutex(os, &os->signalMutex));
- +
- + /* Initialize signal id database lock. */
- + spin_lock_init(&os->signalDB.lock);
- +
- + /* Initialize signal id database. */
- + idr_init(&os->signalDB.idr);
- +
- +#if gcdANDROID_NATIVE_FENCE_SYNC
- + /*
- + * Initialize the sync point manager.
- + */
- +
- + /* Initialize mutex. */
- + gcmkONERROR(gckOS_CreateMutex(os, &os->syncPointMutex));
- +
- + /* Initialize sync point id database lock. */
- + spin_lock_init(&os->syncPointDB.lock);
- +
- + /* Initialize sync point id database. */
- + idr_init(&os->syncPointDB.idr);
- +#endif
- +
- +#if gcdUSE_NON_PAGED_MEMORY_CACHE
- + os->cacheSize = 0;
- + os->cacheHead = gcvNULL;
- + os->cacheTail = gcvNULL;
- +#endif
- +
- + /* Create a workqueue for os timer. */
- + os->workqueue = create_singlethread_workqueue("galcore workqueue");
- +
- + if (os->workqueue == gcvNULL)
- + {
- + /* Out of memory. */
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + /* Return pointer to the gckOS object. */
- + *Os = os;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Os=0x%X", *Os);
- + return gcvSTATUS_OK;
- +
- +OnError:
- +
- +#if gcdANDROID_NATIVE_FENCE_SYNC
- + if (os->syncPointMutex != gcvNULL)
- + {
- + gcmkVERIFY_OK(
- + gckOS_DeleteMutex(os, os->syncPointMutex));
- + }
- +#endif
- +
- + if (os->signalMutex != gcvNULL)
- + {
- + gcmkVERIFY_OK(
- + gckOS_DeleteMutex(os, os->signalMutex));
- + }
- +
- + if (os->heap != gcvNULL)
- + {
- + gcmkVERIFY_OK(
- + gckHEAP_Destroy(os->heap));
- + }
- +
- + if (os->memoryMapLock != gcvNULL)
- + {
- + gcmkVERIFY_OK(
- + gckOS_DeleteMutex(os, os->memoryMapLock));
- + }
- +
- + if (os->memoryLock != gcvNULL)
- + {
- + gcmkVERIFY_OK(
- + gckOS_DeleteMutex(os, os->memoryLock));
- + }
- +
- + if (os->debugLock != gcvNULL)
- + {
- + gcmkVERIFY_OK(
- + gckOS_DeleteMutex(os, os->debugLock));
- + }
- +
- + if (os->workqueue != gcvNULL)
- + {
- + destroy_workqueue(os->workqueue);
- + }
- +
- + kfree(os);
- +
- + /* Return the error. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_Destroy
- +**
- +** Destroy an gckOS object.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object that needs to be destroyed.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_Destroy(
- + IN gckOS Os
- + )
- +{
- + gckHEAP heap;
- +
- + gcmkHEADER_ARG("Os=0x%X", Os);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- +
- +#if gcdUSE_NON_PAGED_MEMORY_CACHE
- + _FreeAllNonPagedMemoryCache(Os);
- +#endif
- +
- +#if gcdANDROID_NATIVE_FENCE_SYNC
- + /*
- + * Destroy the sync point manager.
- + */
- +
- + /* Destroy the mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->syncPointMutex));
- +#endif
- +
- + /*
- + * Destroy the signal manager.
- + */
- +
- + /* Destroy the mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->signalMutex));
- +
- + if (Os->heap != gcvNULL)
- + {
- + /* Mark gckHEAP as gone. */
- + heap = Os->heap;
- + Os->heap = gcvNULL;
- +
- + /* Destroy the gckHEAP object. */
- + gcmkVERIFY_OK(gckHEAP_Destroy(heap));
- + }
- +
- + /* Destroy the memory lock. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryMapLock));
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryLock));
- +
- + /* Destroy debug lock mutex. */
- + gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->debugLock));
- +
- + /* Wait for all works done. */
- + flush_workqueue(Os->workqueue);
- +
- + /* Destory work queue. */
- + destroy_workqueue(Os->workqueue);
- +
- + /* Flush the debug cache. */
- + gcmkDEBUGFLUSH(~0U);
- +
- + /* Mark the gckOS object as unknown. */
- + Os->object.type = gcvOBJ_UNKNOWN;
- +
- + /* Free the gckOS object. */
- + kfree(Os);
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +static gctSTRING
- +_CreateKernelVirtualMapping(
- + IN PLINUX_MDL Mdl
- + )
- +{
- + gctSTRING addr = 0;
- + gctINT numPages = Mdl->numPages;
- +
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + if (Mdl->contiguous)
- + {
- + addr = page_address(Mdl->u.contiguousPages);
- + }
- + else
- + {
- + addr = vmap(Mdl->u.nonContiguousPages,
- + numPages,
- + 0,
- + PAGE_KERNEL);
- +
- + /* Trigger a page fault. */
- + memset(addr, 0, numPages * PAGE_SIZE);
- + }
- +#else
- + struct page ** pages;
- + gctBOOL free = gcvFALSE;
- + gctINT i;
- +
- + if (Mdl->contiguous)
- + {
- + pages = kmalloc(sizeof(struct page *) * numPages, GFP_KERNEL | gcdNOWARN);
- +
- + if (!pages)
- + {
- + return gcvNULL;
- + }
- +
- + for (i = 0; i < numPages; i++)
- + {
- + pages[i] = nth_page(Mdl->u.contiguousPages, i);
- + }
- +
- + free = gcvTRUE;
- + }
- + else
- + {
- + pages = Mdl->u.nonContiguousPages;
- + }
- +
- + /* ioremap() can't work on system memory since 2.6.38. */
- + addr = vmap(pages, numPages, 0, gcmkNONPAGED_MEMROY_PROT(PAGE_KERNEL));
- +
- + /* Trigger a page fault. */
- + memset(addr, 0, numPages * PAGE_SIZE);
- +
- + if (free)
- + {
- + kfree(pages);
- + }
- +
- +#endif
- +
- + return addr;
- +}
- +
- +static void
- +_DestoryKernelVirtualMapping(
- + IN gctSTRING Addr
- + )
- +{
- +#if !gcdNONPAGED_MEMORY_CACHEABLE
- + vunmap(Addr);
- +#endif
- +}
- +
- +gceSTATUS
- +gckOS_CreateKernelVirtualMapping(
- + IN gctPHYS_ADDR Physical,
- + OUT gctSIZE_T * PageCount,
- + OUT gctPOINTER * Logical
- + )
- +{
- + *PageCount = ((PLINUX_MDL)Physical)->numPages;
- + *Logical = _CreateKernelVirtualMapping((PLINUX_MDL)Physical);
- +
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckOS_DestroyKernelVirtualMapping(
- + IN gctPOINTER Logical
- + )
- +{
- + _DestoryKernelVirtualMapping((gctSTRING)Logical);
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_Allocate
- +**
- +** Allocate memory.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes to allocate.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * Memory
- +** Pointer to a variable that will hold the allocated memory location.
- +*/
- +gceSTATUS
- +gckOS_Allocate(
- + IN gckOS Os,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER * Memory
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- + gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
- +
- + /* Do we have a heap? */
- + if (Os->heap != gcvNULL)
- + {
- + /* Allocate from the heap. */
- + gcmkONERROR(gckHEAP_Allocate(Os->heap, Bytes, Memory));
- + }
- + else
- + {
- + gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_Free
- +**
- +** Free allocated memory.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPOINTER Memory
- +** Pointer to memory allocation to free.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_Free(
- + IN gckOS Os,
- + IN gctPOINTER Memory
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%X Memory=0x%X", Os, Memory);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
- +
- + /* Do we have a heap? */
- + if (Os->heap != gcvNULL)
- + {
- + /* Free from the heap. */
- + gcmkONERROR(gckHEAP_Free(Os->heap, Memory));
- + }
- + else
- + {
- + gcmkONERROR(gckOS_FreeMemory(Os, Memory));
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_AllocateMemory
- +**
- +** Allocate memory wrapper.
- +**
- +** INPUT:
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes to allocate.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * Memory
- +** Pointer to a variable that will hold the allocated memory location.
- +*/
- +gceSTATUS
- +gckOS_AllocateMemory(
- + IN gckOS Os,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER * Memory
- + )
- +{
- + gctPOINTER memory;
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- + gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
- +
- + if (Bytes > PAGE_SIZE)
- + {
- + memory = (gctPOINTER) vmalloc(Bytes);
- + }
- + else
- + {
- + memory = (gctPOINTER) kmalloc(Bytes, GFP_KERNEL | gcdNOWARN);
- + }
- +
- + if (memory == gcvNULL)
- + {
- + /* Out of memory. */
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + /* Return pointer to the memory allocation. */
- + *Memory = memory;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_FreeMemory
- +**
- +** Free allocated memory wrapper.
- +**
- +** INPUT:
- +**
- +** gctPOINTER Memory
- +** Pointer to memory allocation to free.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_FreeMemory(
- + IN gckOS Os,
- + IN gctPOINTER Memory
- + )
- +{
- + gcmkHEADER_ARG("Memory=0x%X", Memory);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
- +
- + /* Free the memory from the OS pool. */
- + if (is_vmalloc_addr(Memory))
- + {
- + vfree(Memory);
- + }
- + else
- + {
- + kfree(Memory);
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_MapMemory
- +**
- +** Map physical memory into the current process.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPHYS_ADDR Physical
- +** Start of physical address memory.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes to map.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * Memory
- +** Pointer to a variable that will hold the logical address of the
- +** mapped memory.
- +*/
- +gceSTATUS
- +gckOS_MapMemory(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER * Logical
- + )
- +{
- + PLINUX_MDL_MAP mdlMap;
- + PLINUX_MDL mdl = (PLINUX_MDL)Physical;
- +
- + gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Physical != 0);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- +
- + MEMORY_LOCK(Os);
- +
- + mdlMap = FindMdlMap(mdl, _GetProcessID());
- +
- + if (mdlMap == gcvNULL)
- + {
- + mdlMap = _CreateMdlMap(mdl, _GetProcessID());
- +
- + if (mdlMap == gcvNULL)
- + {
- + MEMORY_UNLOCK(Os);
- +
- + gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
- + return gcvSTATUS_OUT_OF_MEMORY;
- + }
- + }
- +
- + if (mdlMap->vmaAddr == gcvNULL)
- + {
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
- + mdlMap->vmaAddr = (char *)vm_mmap(gcvNULL,
- + 0L,
- + mdl->numPages * PAGE_SIZE,
- + PROT_READ | PROT_WRITE,
- + MAP_SHARED,
- + 0);
- +#else
- + down_write(¤t->mm->mmap_sem);
- +
- + mdlMap->vmaAddr = (char *)do_mmap_pgoff(gcvNULL,
- + 0L,
- + mdl->numPages * PAGE_SIZE,
- + PROT_READ | PROT_WRITE,
- + MAP_SHARED,
- + 0);
- +
- + up_write(¤t->mm->mmap_sem);
- +#endif
- +
- + if (IS_ERR(mdlMap->vmaAddr))
- + {
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): do_mmap_pgoff error",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): mdl->numPages: %d mdl->vmaAddr: 0x%X",
- + __FUNCTION__, __LINE__,
- + mdl->numPages,
- + mdlMap->vmaAddr
- + );
- +
- + mdlMap->vmaAddr = gcvNULL;
- +
- + MEMORY_UNLOCK(Os);
- +
- + gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
- + return gcvSTATUS_OUT_OF_MEMORY;
- + }
- +
- + down_write(¤t->mm->mmap_sem);
- +
- + mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
- +
- + if (!mdlMap->vma)
- + {
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): find_vma error.",
- + __FUNCTION__, __LINE__
- + );
- +
- + mdlMap->vmaAddr = gcvNULL;
- +
- + up_write(¤t->mm->mmap_sem);
- +
- + MEMORY_UNLOCK(Os);
- +
- + gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
- + return gcvSTATUS_OUT_OF_RESOURCES;
- + }
- +
- +#ifndef NO_DMA_COHERENT
- + if (dma_mmap_coherent(gcvNULL,
- + mdlMap->vma,
- + mdl->addr,
- + mdl->dmaHandle,
- + mdl->numPages * PAGE_SIZE) < 0)
- + {
- + up_write(¤t->mm->mmap_sem);
- +
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): dma_mmap_coherent error.",
- + __FUNCTION__, __LINE__
- + );
- +
- + mdlMap->vmaAddr = gcvNULL;
- +
- + MEMORY_UNLOCK(Os);
- +
- + gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
- + return gcvSTATUS_OUT_OF_RESOURCES;
- + }
- +#else
- +#if !gcdPAGED_MEMORY_CACHEABLE
- + mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
- + mdlMap->vma->vm_flags |= gcdVM_FLAGS;
- +# endif
- + mdlMap->vma->vm_pgoff = 0;
- +
- + if (remap_pfn_range(mdlMap->vma,
- + mdlMap->vma->vm_start,
- + mdl->dmaHandle >> PAGE_SHIFT,
- + mdl->numPages*PAGE_SIZE,
- + mdlMap->vma->vm_page_prot) < 0)
- + {
- + up_write(¤t->mm->mmap_sem);
- +
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): remap_pfn_range error.",
- + __FUNCTION__, __LINE__
- + );
- +
- + mdlMap->vmaAddr = gcvNULL;
- +
- + MEMORY_UNLOCK(Os);
- +
- + gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
- + return gcvSTATUS_OUT_OF_RESOURCES;
- + }
- +#endif
- +
- + up_write(¤t->mm->mmap_sem);
- + }
- +
- + MEMORY_UNLOCK(Os);
- +
- + *Logical = mdlMap->vmaAddr;
- +
- + gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_UnmapMemory
- +**
- +** Unmap physical memory out of the current process.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPHYS_ADDR Physical
- +** Start of physical address memory.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes to unmap.
- +**
- +** gctPOINTER Memory
- +** Pointer to a previously mapped memory region.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_UnmapMemory(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes,
- + IN gctPOINTER Logical
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
- + Os, Physical, Bytes, Logical);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Physical != 0);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- +
- + gckOS_UnmapMemoryEx(Os, Physical, Bytes, Logical, _GetProcessID());
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +
- +/*******************************************************************************
- +**
- +** gckOS_UnmapMemoryEx
- +**
- +** Unmap physical memory in the specified process.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPHYS_ADDR Physical
- +** Start of physical address memory.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes to unmap.
- +**
- +** gctPOINTER Memory
- +** Pointer to a previously mapped memory region.
- +**
- +** gctUINT32 PID
- +** Pid of the process that opened the device and mapped this memory.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_UnmapMemoryEx(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes,
- + IN gctPOINTER Logical,
- + IN gctUINT32 PID
- + )
- +{
- + PLINUX_MDL_MAP mdlMap;
- + PLINUX_MDL mdl = (PLINUX_MDL)Physical;
- +
- + gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X PID=%d",
- + Os, Physical, Bytes, Logical, PID);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Physical != 0);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(PID != 0);
- +
- + MEMORY_LOCK(Os);
- +
- + if (Logical)
- + {
- + mdlMap = FindMdlMap(mdl, PID);
- +
- + if (mdlMap == gcvNULL || mdlMap->vmaAddr == gcvNULL)
- + {
- + MEMORY_UNLOCK(Os);
- +
- + gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
- + return gcvSTATUS_INVALID_ARGUMENT;
- + }
- +
- + _UnmapUserLogical(PID, mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
- +
- + gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
- + }
- +
- + MEMORY_UNLOCK(Os);
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_UnmapUserLogical
- +**
- +** Unmap user logical memory out of physical memory.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPHYS_ADDR Physical
- +** Start of physical address memory.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes to unmap.
- +**
- +** gctPOINTER Memory
- +** Pointer to a previously mapped memory region.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_UnmapUserLogical(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes,
- + IN gctPOINTER Logical
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
- + Os, Physical, Bytes, Logical);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Physical != 0);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- +
- + gckOS_UnmapMemory(Os, Physical, Bytes, Logical);
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_AllocateNonPagedMemory
- +**
- +** Allocate a number of pages from non-paged memory.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctBOOL InUserSpace
- +** gcvTRUE if the pages need to be mapped into user space.
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to a variable that holds the number of bytes to allocate.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to a variable that hold the number of bytes allocated.
- +**
- +** gctPHYS_ADDR * Physical
- +** Pointer to a variable that will hold the physical address of the
- +** allocation.
- +**
- +** gctPOINTER * Logical
- +** Pointer to a variable that will hold the logical address of the
- +** allocation.
- +*/
- +gceSTATUS
- +gckOS_AllocateNonPagedMemory(
- + IN gckOS Os,
- + IN gctBOOL InUserSpace,
- + IN OUT gctSIZE_T * Bytes,
- + OUT gctPHYS_ADDR * Physical,
- + OUT gctPOINTER * Logical
- + )
- +{
- + gctSIZE_T bytes;
- + gctINT numPages;
- + PLINUX_MDL mdl = gcvNULL;
- + PLINUX_MDL_MAP mdlMap = gcvNULL;
- + gctSTRING addr;
- +#ifdef NO_DMA_COHERENT
- + struct page * page;
- + long size, order;
- + gctPOINTER vaddr;
- +#endif
- + gctBOOL locked = gcvFALSE;
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
- + Os, InUserSpace, gcmOPT_VALUE(Bytes));
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
- + gcmkVERIFY_ARGUMENT(*Bytes > 0);
- + gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- +
- + /* Align number of bytes to page size. */
- + bytes = gcmALIGN(*Bytes, PAGE_SIZE);
- +
- + /* Get total number of pages.. */
- + numPages = GetPageCount(bytes, 0);
- +
- + /* Allocate mdl+vector structure */
- + mdl = _CreateMdl(_GetProcessID());
- + if (mdl == gcvNULL)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + mdl->pagedMem = 0;
- + mdl->numPages = numPages;
- +
- + MEMORY_LOCK(Os);
- + locked = gcvTRUE;
- +
- +#ifndef NO_DMA_COHERENT
- +#if gcdUSE_NON_PAGED_MEMORY_CACHE
- + addr = _GetNonPagedMemoryCache(Os,
- + mdl->numPages * PAGE_SIZE,
- + &mdl->dmaHandle);
- +
- + if (addr == gcvNULL)
- +#endif
- + {
- + addr = dma_alloc_coherent(gcvNULL,
- + mdl->numPages * PAGE_SIZE,
- + &mdl->dmaHandle,
- + GFP_KERNEL | gcdNOWARN);
- + }
- +#if gcdUSE_NON_PAGED_MEMORY_CACHE
- + if(addr == gcvNULL)
- + {
- + MEMORY_UNLOCK(Os);
- + locked = gcvFALSE;
- + /*Free all cache and try again*/
- + _FreeAllNonPagedMemoryCache(Os);
- + MEMORY_LOCK(Os);
- + locked = gcvTRUE;
- + addr = dma_alloc_coherent(gcvNULL,
- + mdl->numPages * PAGE_SIZE,
- + &mdl->dmaHandle,
- + GFP_KERNEL | gcdNOWARN);
- + }
- +#endif
- +#else
- + size = mdl->numPages * PAGE_SIZE;
- + order = get_order(size);
- +#if gcdUSE_NON_PAGED_MEMORY_CACHE
- + page = _GetNonPagedMemoryCache(Os, order);
- +
- + if (page == gcvNULL)
- +#endif
- + {
- + page = alloc_pages(GFP_KERNEL | gcdNOWARN, order);
- + }
- +
- + if (page == gcvNULL)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + vaddr = (gctPOINTER)page_address(page);
- + mdl->contiguous = gcvTRUE;
- + mdl->u.contiguousPages = page;
- + addr = _CreateKernelVirtualMapping(mdl);
- + mdl->dmaHandle = virt_to_phys(vaddr);
- + mdl->kaddr = vaddr;
- + mdl->u.contiguousPages = page;
- +
- +#if !defined(CONFIG_PPC)
- + /* Cache invalidate. */
- + dma_sync_single_for_device(
- + gcvNULL,
- + page_to_phys(page),
- + bytes,
- + DMA_FROM_DEVICE);
- +#endif
- +
- + while (size > 0)
- + {
- + SetPageReserved(virt_to_page(vaddr));
- +
- + vaddr += PAGE_SIZE;
- + size -= PAGE_SIZE;
- + }
- +#endif
- +
- + if (addr == gcvNULL)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + mdl->addr = addr;
- +
- + /* Return allocated memory. */
- + *Bytes = bytes;
- + *Physical = (gctPHYS_ADDR) mdl;
- +
- + if (InUserSpace)
- + {
- + mdlMap = _CreateMdlMap(mdl, _GetProcessID());
- +
- + if (mdlMap == gcvNULL)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + /* Only after mmap this will be valid. */
- +
- + /* We need to map this to user space. */
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
- + mdlMap->vmaAddr = (gctSTRING) vm_mmap(gcvNULL,
- + 0L,
- + mdl->numPages * PAGE_SIZE,
- + PROT_READ | PROT_WRITE,
- + MAP_SHARED,
- + 0);
- +#else
- + down_write(¤t->mm->mmap_sem);
- +
- + mdlMap->vmaAddr = (gctSTRING) do_mmap_pgoff(gcvNULL,
- + 0L,
- + mdl->numPages * PAGE_SIZE,
- + PROT_READ | PROT_WRITE,
- + MAP_SHARED,
- + 0);
- +
- + up_write(¤t->mm->mmap_sem);
- +#endif
- +
- + if (IS_ERR(mdlMap->vmaAddr))
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_WARNING, gcvZONE_OS,
- + "%s(%d): do_mmap_pgoff error",
- + __FUNCTION__, __LINE__
- + );
- +
- + mdlMap->vmaAddr = gcvNULL;
- +
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + down_write(¤t->mm->mmap_sem);
- +
- + mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
- +
- + if (mdlMap->vma == gcvNULL)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_WARNING, gcvZONE_OS,
- + "%s(%d): find_vma error",
- + __FUNCTION__, __LINE__
- + );
- +
- + up_write(¤t->mm->mmap_sem);
- +
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +
- +#ifndef NO_DMA_COHERENT
- + if (dma_mmap_coherent(gcvNULL,
- + mdlMap->vma,
- + mdl->addr,
- + mdl->dmaHandle,
- + mdl->numPages * PAGE_SIZE) < 0)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_WARNING, gcvZONE_OS,
- + "%s(%d): dma_mmap_coherent error",
- + __FUNCTION__, __LINE__
- + );
- +
- + up_write(¤t->mm->mmap_sem);
- +
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +#else
- + mdlMap->vma->vm_page_prot = gcmkNONPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
- + mdlMap->vma->vm_flags |= gcdVM_FLAGS;
- + mdlMap->vma->vm_pgoff = 0;
- +
- + if (remap_pfn_range(mdlMap->vma,
- + mdlMap->vma->vm_start,
- + mdl->dmaHandle >> PAGE_SHIFT,
- + mdl->numPages * PAGE_SIZE,
- + mdlMap->vma->vm_page_prot))
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_WARNING, gcvZONE_OS,
- + "%s(%d): remap_pfn_range error",
- + __FUNCTION__, __LINE__
- + );
- +
- + up_write(¤t->mm->mmap_sem);
- +
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +#endif /* NO_DMA_COHERENT */
- +
- + up_write(¤t->mm->mmap_sem);
- +
- + *Logical = mdlMap->vmaAddr;
- + }
- + else
- + {
- + *Logical = (gctPOINTER)mdl->addr;
- + }
- +
- + /*
- + * Add this to a global list.
- + * Will be used by get physical address
- + * and mapuser pointer functions.
- + */
- +
- + if (!Os->mdlHead)
- + {
- + /* Initialize the queue. */
- + Os->mdlHead = Os->mdlTail = mdl;
- + }
- + else
- + {
- + /* Add to the tail. */
- + mdl->prev = Os->mdlTail;
- + Os->mdlTail->next = mdl;
- + Os->mdlTail = mdl;
- + }
- +
- + MEMORY_UNLOCK(Os);
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
- + *Bytes, *Physical, *Logical);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (mdlMap != gcvNULL)
- + {
- + /* Free LINUX_MDL_MAP. */
- + gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
- + }
- +
- + if (mdl != gcvNULL)
- + {
- + /* Free LINUX_MDL. */
- + gcmkVERIFY_OK(_DestroyMdl(mdl));
- + }
- +
- + if (locked)
- + {
- + /* Unlock memory. */
- + MEMORY_UNLOCK(Os);
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_FreeNonPagedMemory
- +**
- +** Free previously allocated and mapped pages from non-paged memory.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes allocated.
- +**
- +** gctPHYS_ADDR Physical
- +** Physical address of the allocated memory.
- +**
- +** gctPOINTER Logical
- +** Logical address of the allocated memory.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS gckOS_FreeNonPagedMemory(
- + IN gckOS Os,
- + IN gctSIZE_T Bytes,
- + IN gctPHYS_ADDR Physical,
- + IN gctPOINTER Logical
- + )
- +{
- + PLINUX_MDL mdl;
- + PLINUX_MDL_MAP mdlMap;
- +#ifdef NO_DMA_COHERENT
- + unsigned size;
- + gctPOINTER vaddr;
- +#endif /* NO_DMA_COHERENT */
- +
- + gcmkHEADER_ARG("Os=0x%X Bytes=%lu Physical=0x%X Logical=0x%X",
- + Os, Bytes, Physical, Logical);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- + gcmkVERIFY_ARGUMENT(Physical != 0);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- +
- + /* Convert physical address into a pointer to a MDL. */
- + mdl = (PLINUX_MDL) Physical;
- +
- + MEMORY_LOCK(Os);
- +
- +#ifndef NO_DMA_COHERENT
- +#if gcdUSE_NON_PAGED_MEMORY_CACHE
- + if (!_AddNonPagedMemoryCache(Os,
- + mdl->numPages * PAGE_SIZE,
- + mdl->addr,
- + mdl->dmaHandle))
- +#endif
- + {
- + dma_free_coherent(gcvNULL,
- + mdl->numPages * PAGE_SIZE,
- + mdl->addr,
- + mdl->dmaHandle);
- + }
- +#else
- + size = mdl->numPages * PAGE_SIZE;
- + vaddr = mdl->kaddr;
- +
- + while (size > 0)
- + {
- + ClearPageReserved(virt_to_page(vaddr));
- +
- + vaddr += PAGE_SIZE;
- + size -= PAGE_SIZE;
- + }
- +
- +#if gcdUSE_NON_PAGED_MEMORY_CACHE
- + if (!_AddNonPagedMemoryCache(Os,
- + get_order(mdl->numPages * PAGE_SIZE),
- + virt_to_page(mdl->kaddr)))
- +#endif
- + {
- + free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
- + }
- +
- + _DestoryKernelVirtualMapping(mdl->addr);
- +#endif /* NO_DMA_COHERENT */
- +
- + mdlMap = mdl->maps;
- +
- + while (mdlMap != gcvNULL)
- + {
- + if (mdlMap->vmaAddr != gcvNULL)
- + {
- + /* No mapped memory exists when free nonpaged memory */
- + gcmkASSERT(0);
- + }
- +
- + mdlMap = mdlMap->next;
- + }
- +
- + /* Remove the node from global list.. */
- + if (mdl == Os->mdlHead)
- + {
- + if ((Os->mdlHead = mdl->next) == gcvNULL)
- + {
- + Os->mdlTail = gcvNULL;
- + }
- + }
- + else
- + {
- + mdl->prev->next = mdl->next;
- + if (mdl == Os->mdlTail)
- + {
- + Os->mdlTail = mdl->prev;
- + }
- + else
- + {
- + mdl->next->prev = mdl->prev;
- + }
- + }
- +
- + MEMORY_UNLOCK(Os);
- +
- + gcmkVERIFY_OK(_DestroyMdl(mdl));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_ReadRegister
- +**
- +** Read data from a register.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctUINT32 Address
- +** Address of register.
- +**
- +** OUTPUT:
- +**
- +** gctUINT32 * Data
- +** Pointer to a variable that receives the data read from the register.
- +*/
- +gceSTATUS
- +gckOS_ReadRegister(
- + IN gckOS Os,
- + IN gctUINT32 Address,
- + OUT gctUINT32 * Data
- + )
- +{
- + return gckOS_ReadRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
- +}
- +
- +gceSTATUS
- +gckOS_ReadRegisterEx(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctUINT32 Address,
- + OUT gctUINT32 * Data
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X", Os, Core, Address);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
- + gcmkVERIFY_ARGUMENT(Data != gcvNULL);
- +
- + *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Data=0x%08x", *Data);
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_WriteRegister
- +**
- +** Write data to a register.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctUINT32 Address
- +** Address of register.
- +**
- +** gctUINT32 Data
- +** Data for register.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_WriteRegister(
- + IN gckOS Os,
- + IN gctUINT32 Address,
- + IN gctUINT32 Data
- + )
- +{
- + return gckOS_WriteRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
- +}
- +
- +gceSTATUS
- +gckOS_WriteRegisterEx(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctUINT32 Address,
- + IN gctUINT32 Data
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X Data=0x%08x", Os, Core, Address, Data);
- +
- + gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
- +
- + writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_GetPageSize
- +**
- +** Get the system's page size.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * PageSize
- +** Pointer to a variable that will receive the system's page size.
- +*/
- +gceSTATUS gckOS_GetPageSize(
- + IN gckOS Os,
- + OUT gctSIZE_T * PageSize
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X", Os);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(PageSize != gcvNULL);
- +
- + /* Return the page size. */
- + *PageSize = (gctSIZE_T) PAGE_SIZE;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*PageSize", *PageSize);
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_GetPhysicalAddress
- +**
- +** Get the physical system address of a corresponding virtual address.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPOINTER Logical
- +** Logical address.
- +**
- +** OUTPUT:
- +**
- +** gctUINT32 * Address
- +** Poinetr to a variable that receives the 32-bit physical adress.
- +*/
- +gceSTATUS
- +gckOS_GetPhysicalAddress(
- + IN gckOS Os,
- + IN gctPOINTER Logical,
- + OUT gctUINT32 * Address
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 processID;
- +
- + gcmkHEADER_ARG("Os=0x%X Logical=0x%X", Os, Logical);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Address != gcvNULL);
- +
- + /* Query page table of current process first. */
- + status = _QueryProcessPageTable(Logical, Address);
- +
- + if (gcmIS_ERROR(status))
- + {
- + /* Get current process ID. */
- + processID = _GetProcessID();
- +
- + /* Route through other function. */
- + gcmkONERROR(
- + gckOS_GetPhysicalAddressProcess(Os, Logical, processID, Address));
- + }
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Address=0x%08x", *Address);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +#if gcdSECURE_USER
- +static gceSTATUS
- +gckOS_AddMapping(
- + IN gckOS Os,
- + IN gctUINT32 Physical,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes
- + )
- +{
- + gceSTATUS status;
- + gcsUSER_MAPPING_PTR map;
- +
- + gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
- + Os, Physical, Logical, Bytes);
- +
- + gcmkONERROR(gckOS_Allocate(Os,
- + gcmSIZEOF(gcsUSER_MAPPING),
- + (gctPOINTER *) &map));
- +
- + map->next = Os->userMap;
- + map->physical = Physical - Os->device->baseAddress;
- + map->logical = Logical;
- + map->bytes = Bytes;
- + map->start = (gctINT8_PTR) Logical;
- + map->end = map->start + Bytes;
- +
- + Os->userMap = map;
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +
- +static gceSTATUS
- +gckOS_RemoveMapping(
- + IN gckOS Os,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes
- + )
- +{
- + gceSTATUS status;
- + gcsUSER_MAPPING_PTR map, prev;
- +
- + gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
- +
- + for (map = Os->userMap, prev = gcvNULL; map != gcvNULL; map = map->next)
- + {
- + if ((map->logical == Logical)
- + && (map->bytes == Bytes)
- + )
- + {
- + break;
- + }
- +
- + prev = map;
- + }
- +
- + if (map == gcvNULL)
- + {
- + gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
- + }
- +
- + if (prev == gcvNULL)
- + {
- + Os->userMap = map->next;
- + }
- + else
- + {
- + prev->next = map->next;
- + }
- +
- + gcmkONERROR(gcmkOS_SAFE_FREE(Os, map));
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +#endif
- +
- +static gceSTATUS
- +_ConvertLogical2Physical(
- + IN gckOS Os,
- + IN gctPOINTER Logical,
- + IN gctUINT32 ProcessID,
- + IN PLINUX_MDL Mdl,
- + OUT gctUINT32_PTR Physical
- + )
- +{
- + gctINT8_PTR base, vBase;
- + gctUINT32 offset;
- + PLINUX_MDL_MAP map;
- + gcsUSER_MAPPING_PTR userMap;
- +
- + base = (Mdl == gcvNULL) ? gcvNULL : (gctINT8_PTR) Mdl->addr;
- +
- + /* Check for the logical address match. */
- + if ((base != gcvNULL)
- + && ((gctINT8_PTR) Logical >= base)
- + && ((gctINT8_PTR) Logical < base + Mdl->numPages * PAGE_SIZE)
- + )
- + {
- + offset = (gctINT8_PTR) Logical - base;
- +
- + if (Mdl->dmaHandle != 0)
- + {
- + /* The memory was from coherent area. */
- + *Physical = (gctUINT32) Mdl->dmaHandle + offset;
- + }
- + else if (Mdl->pagedMem && !Mdl->contiguous)
- + {
- + /* paged memory is not mapped to kernel space. */
- + return gcvSTATUS_INVALID_ADDRESS;
- + }
- + else
- + {
- + *Physical = gcmPTR2INT(virt_to_phys(base)) + offset;
- + }
- +
- + return gcvSTATUS_OK;
- + }
- +
- + /* Walk user maps. */
- + for (userMap = Os->userMap; userMap != gcvNULL; userMap = userMap->next)
- + {
- + if (((gctINT8_PTR) Logical >= userMap->start)
- + && ((gctINT8_PTR) Logical < userMap->end)
- + )
- + {
- + *Physical = userMap->physical
- + + (gctUINT32) ((gctINT8_PTR) Logical - userMap->start);
- +
- + return gcvSTATUS_OK;
- + }
- + }
- +
- + if (ProcessID != Os->kernelProcessID)
- + {
- + map = FindMdlMap(Mdl, (gctINT) ProcessID);
- + vBase = (map == gcvNULL) ? gcvNULL : (gctINT8_PTR) map->vmaAddr;
- +
- + /* Is the given address within that range. */
- + if ((vBase != gcvNULL)
- + && ((gctINT8_PTR) Logical >= vBase)
- + && ((gctINT8_PTR) Logical < vBase + Mdl->numPages * PAGE_SIZE)
- + )
- + {
- + offset = (gctINT8_PTR) Logical - vBase;
- +
- + if (Mdl->dmaHandle != 0)
- + {
- + /* The memory was from coherent area. */
- + *Physical = (gctUINT32) Mdl->dmaHandle + offset;
- + }
- + else if (Mdl->pagedMem && !Mdl->contiguous)
- + {
- + *Physical = _NonContiguousToPhys(Mdl->u.nonContiguousPages, offset/PAGE_SIZE);
- + }
- + else
- + {
- + *Physical = page_to_phys(Mdl->u.contiguousPages) + offset;
- + }
- +
- + return gcvSTATUS_OK;
- + }
- + }
- +
- + /* Address not yet found. */
- + return gcvSTATUS_INVALID_ADDRESS;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_GetPhysicalAddressProcess
- +**
- +** Get the physical system address of a corresponding virtual address for a
- +** given process.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to gckOS object.
- +**
- +** gctPOINTER Logical
- +** Logical address.
- +**
- +** gctUINT32 ProcessID
- +** Process ID.
- +**
- +** OUTPUT:
- +**
- +** gctUINT32 * Address
- +** Poinetr to a variable that receives the 32-bit physical adress.
- +*/
- +gceSTATUS
- +gckOS_GetPhysicalAddressProcess(
- + IN gckOS Os,
- + IN gctPOINTER Logical,
- + IN gctUINT32 ProcessID,
- + OUT gctUINT32 * Address
- + )
- +{
- + PLINUX_MDL mdl;
- + gctINT8_PTR base;
- + gceSTATUS status = gcvSTATUS_INVALID_ADDRESS;
- +
- + gcmkHEADER_ARG("Os=0x%X Logical=0x%X ProcessID=%d", Os, Logical, ProcessID);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Address != gcvNULL);
- +
- + MEMORY_LOCK(Os);
- +
- + /* First try the contiguous memory pool. */
- + if (Os->device->contiguousMapped)
- + {
- + base = (gctINT8_PTR) Os->device->contiguousBase;
- +
- + if (((gctINT8_PTR) Logical >= base)
- + && ((gctINT8_PTR) Logical < base + Os->device->contiguousSize)
- + )
- + {
- + /* Convert logical address into physical. */
- + *Address = Os->device->contiguousVidMem->baseAddress
- + + (gctINT8_PTR) Logical - base;
- + status = gcvSTATUS_OK;
- + }
- + }
- + else
- + {
- + /* Try the contiguous memory pool. */
- + mdl = (PLINUX_MDL) Os->device->contiguousPhysical;
- + status = _ConvertLogical2Physical(Os,
- + Logical,
- + ProcessID,
- + mdl,
- + Address);
- + }
- +
- + if (gcmIS_ERROR(status))
- + {
- + /* Walk all MDLs. */
- + for (mdl = Os->mdlHead; mdl != gcvNULL; mdl = mdl->next)
- + {
- + /* Try this MDL. */
- + status = _ConvertLogical2Physical(Os,
- + Logical,
- + ProcessID,
- + mdl,
- + Address);
- + if (gcmIS_SUCCESS(status))
- + {
- + break;
- + }
- + }
- + }
- +
- + MEMORY_UNLOCK(Os);
- +
- + gcmkONERROR(status);
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Address=0x%08x", *Address);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_MapPhysical
- +**
- +** Map a physical address into kernel space.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctUINT32 Physical
- +** Physical address of the memory to map.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes to map.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * Logical
- +** Pointer to a variable that receives the base address of the mapped
- +** memory.
- +*/
- +gceSTATUS
- +gckOS_MapPhysical(
- + IN gckOS Os,
- + IN gctUINT32 Physical,
- + IN gctSIZE_T Bytes,
- + OUT gctPOINTER * Logical
- + )
- +{
- + gctPOINTER logical;
- + PLINUX_MDL mdl;
- + gctUINT32 physical = Physical;
- +
- + gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- +
- + MEMORY_LOCK(Os);
- +
- + /* Go through our mapping to see if we know this physical address already. */
- + mdl = Os->mdlHead;
- +
- + while (mdl != gcvNULL)
- + {
- + if (mdl->dmaHandle != 0)
- + {
- + if ((physical >= mdl->dmaHandle)
- + && (physical < mdl->dmaHandle + mdl->numPages * PAGE_SIZE)
- + )
- + {
- + *Logical = mdl->addr + (physical - mdl->dmaHandle);
- + break;
- + }
- + }
- +
- + mdl = mdl->next;
- + }
- +
- + if (mdl == gcvNULL)
- + {
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- + struct contiguous_mem_pool *pool = Os->device->pool;
- +
- + if (Physical >= pool->phys && Physical < pool->phys + pool->size)
- + logical = (gctPOINTER)(Physical - pool->phys + pool->virt);
- + else
- + logical = gcvNULL;
- +#else
- + /* Map memory as cached memory. */
- + request_mem_region(physical, Bytes, "MapRegion");
- + logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
- +#endif
- +
- + if (logical == gcvNULL)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_OS,
- + "%s(%d): Failed to map physical address 0x%08x",
- + __FUNCTION__, __LINE__, Physical
- + );
- +
- + MEMORY_UNLOCK(Os);
- +
- + /* Out of resources. */
- + gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
- + return gcvSTATUS_OUT_OF_RESOURCES;
- + }
- +
- + /* Return pointer to mapped memory. */
- + *Logical = logical;
- + }
- +
- + MEMORY_UNLOCK(Os);
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_UnmapPhysical
- +**
- +** Unmap a previously mapped memory region from kernel memory.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPOINTER Logical
- +** Pointer to the base address of the memory to unmap.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes to unmap.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_UnmapPhysical(
- + IN gckOS Os,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes
- + )
- +{
- + PLINUX_MDL mdl;
- +
- + gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- +
- + MEMORY_LOCK(Os);
- +
- + mdl = Os->mdlHead;
- +
- + while (mdl != gcvNULL)
- + {
- + if (mdl->addr != gcvNULL)
- + {
- + if (Logical >= (gctPOINTER)mdl->addr
- + && Logical < (gctPOINTER)((gctSTRING)mdl->addr + mdl->numPages * PAGE_SIZE))
- + {
- + break;
- + }
- + }
- +
- + mdl = mdl->next;
- + }
- +
- + if (mdl == gcvNULL)
- + {
- + /* Unmap the memory. */
- + iounmap(Logical);
- + }
- +
- + MEMORY_UNLOCK(Os);
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_CreateMutex
- +**
- +** Create a new mutex.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * Mutex
- +** Pointer to a variable that will hold a pointer to the mutex.
- +*/
- +gceSTATUS
- +gckOS_CreateMutex(
- + IN gckOS Os,
- + OUT gctPOINTER * Mutex
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%X", Os);
- +
- + /* Validate the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
- +
- + /* Allocate the mutex structure. */
- + gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(struct mutex), Mutex));
- +
- + /* Initialize the mutex. */
- + mutex_init(*Mutex);
- +
- + /* Return status. */
- + gcmkFOOTER_ARG("*Mutex=0x%X", *Mutex);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_DeleteMutex
- +**
- +** Delete a mutex.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPOINTER Mutex
- +** Pointer to the mute to be deleted.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_DeleteMutex(
- + IN gckOS Os,
- + IN gctPOINTER Mutex
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%X Mutex=0x%X", Os, Mutex);
- +
- + /* Validate the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
- +
- + /* Destroy the mutex. */
- + mutex_destroy(Mutex);
- +
- + /* Free the mutex structure. */
- + gcmkONERROR(gckOS_Free(Os, Mutex));
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_AcquireMutex
- +**
- +** Acquire a mutex.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPOINTER Mutex
- +** Pointer to the mutex to be acquired.
- +**
- +** gctUINT32 Timeout
- +** Timeout value specified in milliseconds.
- +** Specify the value of gcvINFINITE to keep the thread suspended
- +** until the mutex has been acquired.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_AcquireMutex(
- + IN gckOS Os,
- + IN gctPOINTER Mutex,
- + IN gctUINT32 Timeout
- + )
- +{
- +#if gcdDETECT_TIMEOUT
- + gctUINT32 timeout;
- +#endif
- +
- + gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x Timeout=%u", Os, Mutex, Timeout);
- +
- + /* Validate the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
- +
- +#if gcdDETECT_TIMEOUT
- + timeout = 0;
- +
- + for (;;)
- + {
- + /* Try to acquire the mutex. */
- + if (mutex_trylock(Mutex))
- + {
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- +
- + /* Advance the timeout. */
- + timeout += 1;
- +
- + if (Timeout == gcvINFINITE)
- + {
- + if (timeout == gcdINFINITE_TIMEOUT)
- + {
- + gctUINT32 dmaAddress1, dmaAddress2;
- + gctUINT32 dmaState1, dmaState2;
- +
- + dmaState1 = dmaState2 =
- + dmaAddress1 = dmaAddress2 = 0;
- +
- + /* Verify whether DMA is running. */
- + gcmkVERIFY_OK(_VerifyDMA(
- + Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
- + ));
- +
- +#if gcdDETECT_DMA_ADDRESS
- + /* Dump only if DMA appears stuck. */
- + if (
- + (dmaAddress1 == dmaAddress2)
- +#if gcdDETECT_DMA_STATE
- + && (dmaState1 == dmaState2)
- +# endif
- + )
- +# endif
- + {
- + gcmkVERIFY_OK(_DumpGPUState(Os, gcvCORE_MAJOR));
- +
- + gcmkPRINT(
- + "%s(%d): mutex 0x%X; forced message flush.",
- + __FUNCTION__, __LINE__, Mutex
- + );
- +
- + /* Flush the debug cache. */
- + gcmkDEBUGFLUSH(dmaAddress2);
- + }
- +
- + timeout = 0;
- + }
- + }
- + else
- + {
- + /* Timedout? */
- + if (timeout >= Timeout)
- + {
- + break;
- + }
- + }
- +
- + /* Wait for 1 millisecond. */
- + gcmkVERIFY_OK(gckOS_Delay(Os, 1));
- + }
- +#else
- + if (Timeout == gcvINFINITE)
- + {
- + /* Lock the mutex. */
- + mutex_lock(Mutex);
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- +
- + for (;;)
- + {
- + /* Try to acquire the mutex. */
- + if (mutex_trylock(Mutex))
- + {
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- +
- + if (Timeout-- == 0)
- + {
- + break;
- + }
- +
- + /* Wait for 1 millisecond. */
- + gcmkVERIFY_OK(gckOS_Delay(Os, 1));
- + }
- +#endif
- +
- + /* Timeout. */
- + gcmkFOOTER_ARG("status=%d", gcvSTATUS_TIMEOUT);
- + return gcvSTATUS_TIMEOUT;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_ReleaseMutex
- +**
- +** Release an acquired mutex.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPOINTER Mutex
- +** Pointer to the mutex to be released.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_ReleaseMutex(
- + IN gckOS Os,
- + IN gctPOINTER Mutex
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x", Os, Mutex);
- +
- + /* Validate the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
- +
- + /* Release the mutex. */
- + mutex_unlock(Mutex);
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_AtomicExchange
- +**
- +** Atomically exchange a pair of 32-bit values.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** IN OUT gctINT32_PTR Target
- +** Pointer to the 32-bit value to exchange.
- +**
- +** IN gctINT32 NewValue
- +** Specifies a new value for the 32-bit value pointed to by Target.
- +**
- +** OUT gctINT32_PTR OldValue
- +** The old value of the 32-bit value pointed to by Target.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_AtomicExchange(
- + IN gckOS Os,
- + IN OUT gctUINT32_PTR Target,
- + IN gctUINT32 NewValue,
- + OUT gctUINT32_PTR OldValue
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=%u", Os, Target, NewValue);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- +
- + /* Exchange the pair of 32-bit values. */
- + *OldValue = (gctUINT32) atomic_xchg((atomic_t *) Target, (int) NewValue);
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*OldValue=%u", *OldValue);
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_AtomicExchangePtr
- +**
- +** Atomically exchange a pair of pointers.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** IN OUT gctPOINTER * Target
- +** Pointer to the 32-bit value to exchange.
- +**
- +** IN gctPOINTER NewValue
- +** Specifies a new value for the pointer pointed to by Target.
- +**
- +** OUT gctPOINTER * OldValue
- +** The old value of the pointer pointed to by Target.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_AtomicExchangePtr(
- + IN gckOS Os,
- + IN OUT gctPOINTER * Target,
- + IN gctPOINTER NewValue,
- + OUT gctPOINTER * OldValue
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=0x%X", Os, Target, NewValue);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- +
- + /* Exchange the pair of pointers. */
- + *OldValue = (gctPOINTER)(gctUINTPTR_T) atomic_xchg((atomic_t *) Target, (int)(gctUINTPTR_T) NewValue);
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*OldValue=0x%X", *OldValue);
- + return gcvSTATUS_OK;
- +}
- +
- +#if gcdSMP
- +/*******************************************************************************
- +**
- +** gckOS_AtomicSetMask
- +**
- +** Atomically set mask to Atom
- +**
- +** INPUT:
- +** IN OUT gctPOINTER Atom
- +** Pointer to the atom to set.
- +**
- +** IN gctUINT32 Mask
- +** Mask to set.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_AtomSetMask(
- + IN gctPOINTER Atom,
- + IN gctUINT32 Mask
- + )
- +{
- + gctUINT32 oval, nval;
- +
- + gcmkHEADER_ARG("Atom=0x%0x", Atom);
- + gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
- +
- + do
- + {
- + oval = atomic_read((atomic_t *) Atom);
- + nval = oval | Mask;
- + } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_AtomClearMask
- +**
- +** Atomically clear mask from Atom
- +**
- +** INPUT:
- +** IN OUT gctPOINTER Atom
- +** Pointer to the atom to clear.
- +**
- +** IN gctUINT32 Mask
- +** Mask to clear.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_AtomClearMask(
- + IN gctPOINTER Atom,
- + IN gctUINT32 Mask
- + )
- +{
- + gctUINT32 oval, nval;
- +
- + gcmkHEADER_ARG("Atom=0x%0x", Atom);
- + gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
- +
- + do
- + {
- + oval = atomic_read((atomic_t *) Atom);
- + nval = oval & ~Mask;
- + } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gckOS_AtomConstruct
- +**
- +** Create an atom.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * Atom
- +** Pointer to a variable receiving the constructed atom.
- +*/
- +gceSTATUS
- +gckOS_AtomConstruct(
- + IN gckOS Os,
- + OUT gctPOINTER * Atom
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%X", Os);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
- +
- + /* Allocate the atom. */
- + gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(atomic_t), Atom));
- +
- + /* Initialize the atom. */
- + atomic_set((atomic_t *) *Atom, 0);
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Atom=0x%X", *Atom);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_AtomDestroy
- +**
- +** Destroy an atom.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** gctPOINTER Atom
- +** Pointer to the atom to destroy.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_AtomDestroy(
- + IN gckOS Os,
- + OUT gctPOINTER Atom
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
- +
- + /* Free the atom. */
- + gcmkONERROR(gcmkOS_SAFE_FREE(Os, Atom));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_AtomGet
- +**
- +** Get the 32-bit value protected by an atom.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** gctPOINTER Atom
- +** Pointer to the atom.
- +**
- +** OUTPUT:
- +**
- +** gctINT32_PTR Value
- +** Pointer to a variable the receives the value of the atom.
- +*/
- +gceSTATUS
- +gckOS_AtomGet(
- + IN gckOS Os,
- + IN gctPOINTER Atom,
- + OUT gctINT32_PTR Value
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
- +
- + /* Return the current value of atom. */
- + *Value = atomic_read((atomic_t *) Atom);
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Value=%d", *Value);
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_AtomSet
- +**
- +** Set the 32-bit value protected by an atom.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** gctPOINTER Atom
- +** Pointer to the atom.
- +**
- +** gctINT32 Value
- +** The value of the atom.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_AtomSet(
- + IN gckOS Os,
- + IN gctPOINTER Atom,
- + IN gctINT32 Value
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Atom=0x%0x Value=%d", Os, Atom);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
- +
- + /* Set the current value of atom. */
- + atomic_set((atomic_t *) Atom, Value);
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_AtomIncrement
- +**
- +** Atomically increment the 32-bit integer value inside an atom.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** gctPOINTER Atom
- +** Pointer to the atom.
- +**
- +** OUTPUT:
- +**
- +** gctINT32_PTR Value
- +** Pointer to a variable that receives the original value of the atom.
- +*/
- +gceSTATUS
- +gckOS_AtomIncrement(
- + IN gckOS Os,
- + IN gctPOINTER Atom,
- + OUT gctINT32_PTR Value
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
- +
- + /* Increment the atom. */
- + *Value = atomic_inc_return((atomic_t *) Atom) - 1;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Value=%d", *Value);
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_AtomDecrement
- +**
- +** Atomically decrement the 32-bit integer value inside an atom.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** gctPOINTER Atom
- +** Pointer to the atom.
- +**
- +** OUTPUT:
- +**
- +** gctINT32_PTR Value
- +** Pointer to a variable that receives the original value of the atom.
- +*/
- +gceSTATUS
- +gckOS_AtomDecrement(
- + IN gckOS Os,
- + IN gctPOINTER Atom,
- + OUT gctINT32_PTR Value
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
- +
- + /* Decrement the atom. */
- + *Value = atomic_dec_return((atomic_t *) Atom) + 1;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Value=%d", *Value);
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_Delay
- +**
- +** Delay execution of the current thread for a number of milliseconds.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctUINT32 Delay
- +** Delay to sleep, specified in milliseconds.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_Delay(
- + IN gckOS Os,
- + IN gctUINT32 Delay
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Delay=%u", Os, Delay);
- +
- + if (Delay > 0)
- + {
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
- + ktime_t delay = ktime_set(Delay/1000, (Delay%1000) * NSEC_PER_MSEC);
- + __set_current_state(TASK_UNINTERRUPTIBLE);
- + schedule_hrtimeout(&delay, HRTIMER_MODE_REL);
- +#else
- + msleep(Delay);
- +#endif
- +
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_GetTicks
- +**
- +** Get the number of milliseconds since the system started.
- +**
- +** INPUT:
- +**
- +** OUTPUT:
- +**
- +** gctUINT32_PTR Time
- +** Pointer to a variable to get time.
- +**
- +*/
- +gceSTATUS
- +gckOS_GetTicks(
- + OUT gctUINT32_PTR Time
- + )
- +{
- + gcmkHEADER();
- +
- + *Time = jiffies_to_msecs(jiffies);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_TicksAfter
- +**
- +** Compare time values got from gckOS_GetTicks.
- +**
- +** INPUT:
- +** gctUINT32 Time1
- +** First time value to be compared.
- +**
- +** gctUINT32 Time2
- +** Second time value to be compared.
- +**
- +** OUTPUT:
- +**
- +** gctBOOL_PTR IsAfter
- +** Pointer to a variable to result.
- +**
- +*/
- +gceSTATUS
- +gckOS_TicksAfter(
- + IN gctUINT32 Time1,
- + IN gctUINT32 Time2,
- + OUT gctBOOL_PTR IsAfter
- + )
- +{
- + gcmkHEADER();
- +
- + *IsAfter = time_after((unsigned long)Time1, (unsigned long)Time2);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_GetTime
- +**
- +** Get the number of microseconds since the system started.
- +**
- +** INPUT:
- +**
- +** OUTPUT:
- +**
- +** gctUINT64_PTR Time
- +** Pointer to a variable to get time.
- +**
- +*/
- +gceSTATUS
- +gckOS_GetTime(
- + OUT gctUINT64_PTR Time
- + )
- +{
- + gcmkHEADER();
- +
- + *Time = 0;
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_MemoryBarrier
- +**
- +** Make sure the CPU has executed everything up to this point and the data got
- +** written to the specified pointer.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPOINTER Address
- +** Address of memory that needs to be barriered.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_MemoryBarrier(
- + IN gckOS Os,
- + IN gctPOINTER Address
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Address=0x%X", Os, Address);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- +
- +#if gcdNONPAGED_MEMORY_BUFFERABLE \
- + && defined (CONFIG_ARM) \
- + && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
- + /* drain write buffer */
- + dsb();
- +
- + /* drain outer cache's write buffer? */
- +#else
- + mb();
- +#endif
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_AllocatePagedMemory
- +**
- +** Allocate memory from the paged pool.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes to allocate.
- +**
- +** OUTPUT:
- +**
- +** gctPHYS_ADDR * Physical
- +** Pointer to a variable that receives the physical address of the
- +** memory allocation.
- +*/
- +gceSTATUS
- +gckOS_AllocatePagedMemory(
- + IN gckOS Os,
- + IN gctSIZE_T Bytes,
- + OUT gctPHYS_ADDR * Physical
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- + gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
- +
- + /* Allocate the memory. */
- + gcmkONERROR(gckOS_AllocatePagedMemoryEx(Os, gcvFALSE, Bytes, Physical));
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_AllocatePagedMemoryEx
- +**
- +** Allocate memory from the paged pool.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctBOOL Contiguous
- +** Need contiguous memory or not.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes to allocate.
- +**
- +** OUTPUT:
- +**
- +** gctPHYS_ADDR * Physical
- +** Pointer to a variable that receives the physical address of the
- +** memory allocation.
- +*/
- +gceSTATUS
- +gckOS_AllocatePagedMemoryEx(
- + IN gckOS Os,
- + IN gctBOOL Contiguous,
- + IN gctSIZE_T Bytes,
- + OUT gctPHYS_ADDR * Physical
- + )
- +{
- + gctINT numPages;
- + gctINT i;
- + PLINUX_MDL mdl = gcvNULL;
- + gctSIZE_T bytes;
- + gctBOOL locked = gcvFALSE;
- + gceSTATUS status;
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
- + gctPOINTER addr = gcvNULL;
- +#endif
- +
- + gcmkHEADER_ARG("Os=0x%X Contiguous=%d Bytes=%lu", Os, Contiguous, Bytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- + gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
- +
- + bytes = gcmALIGN(Bytes, PAGE_SIZE);
- +
- + numPages = GetPageCount(bytes, 0);
- +
- + MEMORY_LOCK(Os);
- + locked = gcvTRUE;
- +
- + mdl = _CreateMdl(_GetProcessID());
- + if (mdl == gcvNULL)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + if (Contiguous)
- + {
- + gctUINT32 order = get_order(bytes);
- +
- + if (order >= MAX_ORDER)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
- + addr =
- + alloc_pages_exact(numPages * PAGE_SIZE, GFP_KERNEL | gcdNOWARN | __GFP_NORETRY);
- +
- + mdl->u.contiguousPages = addr
- + ? virt_to_page(addr)
- + : gcvNULL;
- +
- + mdl->exact = gcvTRUE;
- +#else
- + mdl->u.contiguousPages =
- + alloc_pages(GFP_KERNEL | gcdNOWARN | __GFP_NORETRY, order);
- +#endif
- + if (mdl->u.contiguousPages == gcvNULL)
- + {
- + mdl->u.contiguousPages =
- + alloc_pages(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN, order);
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
- + mdl->exact = gcvFALSE;
- +#endif
- + }
- + }
- + else
- + {
- + mdl->u.nonContiguousPages = _NonContiguousAlloc(numPages);
- + }
- +
- + if (mdl->u.contiguousPages == gcvNULL && mdl->u.nonContiguousPages == gcvNULL)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + mdl->dmaHandle = 0;
- + mdl->addr = 0;
- + mdl->numPages = numPages;
- + mdl->pagedMem = 1;
- + mdl->contiguous = Contiguous;
- +
- + for (i = 0; i < mdl->numPages; i++)
- + {
- + struct page *page;
- +
- + if (mdl->contiguous)
- + {
- + page = nth_page(mdl->u.contiguousPages, i);
- + }
- + else
- + {
- + page = _NonContiguousToPage(mdl->u.nonContiguousPages, i);
- + }
- +
- + SetPageReserved(page);
- +
- + if (!PageHighMem(page) && page_to_phys(page))
- + {
- + gcmkVERIFY_OK(
- + gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
- + (gctPOINTER)(gctUINTPTR_T)page_to_phys(page),
- + page_address(page),
- + PAGE_SIZE));
- + }
- + }
- +
- + /* Return physical address. */
- + *Physical = (gctPHYS_ADDR) mdl;
- +
- + /*
- + * Add this to a global list.
- + * Will be used by get physical address
- + * and mapuser pointer functions.
- + */
- + if (!Os->mdlHead)
- + {
- + /* Initialize the queue. */
- + Os->mdlHead = Os->mdlTail = mdl;
- + }
- + else
- + {
- + /* Add to tail. */
- + mdl->prev = Os->mdlTail;
- + Os->mdlTail->next = mdl;
- + Os->mdlTail = mdl;
- + }
- +
- + MEMORY_UNLOCK(Os);
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (mdl != gcvNULL)
- + {
- + /* Free the memory. */
- + _DestroyMdl(mdl);
- + }
- +
- + if (locked)
- + {
- + /* Unlock the memory. */
- + MEMORY_UNLOCK(Os);
- + }
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_FreePagedMemory
- +**
- +** Free memory allocated from the paged pool.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPHYS_ADDR Physical
- +** Physical address of the allocation.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes of the allocation.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_FreePagedMemory(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes
- + )
- +{
- + PLINUX_MDL mdl = (PLINUX_MDL) Physical;
- + gctINT i;
- +
- + gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- +
- + /*addr = mdl->addr;*/
- +
- + MEMORY_LOCK(Os);
- +
- + for (i = 0; i < mdl->numPages; i++)
- + {
- + if (mdl->contiguous)
- + {
- + ClearPageReserved(nth_page(mdl->u.contiguousPages, i));
- + }
- + else
- + {
- + ClearPageReserved(_NonContiguousToPage(mdl->u.nonContiguousPages, i));
- + }
- + }
- +
- + if (mdl->contiguous)
- + {
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
- + if (mdl->exact == gcvTRUE)
- + {
- + free_pages_exact(page_address(mdl->u.contiguousPages), mdl->numPages * PAGE_SIZE);
- + }
- + else
- +#endif
- + {
- + __free_pages(mdl->u.contiguousPages, GetOrder(mdl->numPages));
- + }
- + }
- + else
- + {
- + _NonContiguousFree(mdl->u.nonContiguousPages, mdl->numPages);
- + }
- +
- + /* Remove the node from global list. */
- + if (mdl == Os->mdlHead)
- + {
- + if ((Os->mdlHead = mdl->next) == gcvNULL)
- + {
- + Os->mdlTail = gcvNULL;
- + }
- + }
- + else
- + {
- + mdl->prev->next = mdl->next;
- +
- + if (mdl == Os->mdlTail)
- + {
- + Os->mdlTail = mdl->prev;
- + }
- + else
- + {
- + mdl->next->prev = mdl->prev;
- + }
- + }
- +
- + MEMORY_UNLOCK(Os);
- +
- + /* Free the structure... */
- + gcmkVERIFY_OK(_DestroyMdl(mdl));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_LockPages
- +**
- +** Lock memory allocated from the paged pool.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPHYS_ADDR Physical
- +** Physical address of the allocation.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes of the allocation.
- +**
- +** gctBOOL Cacheable
- +** Cache mode of mapping.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * Logical
- +** Pointer to a variable that receives the address of the mapped
- +** memory.
- +**
- +** gctSIZE_T * PageCount
- +** Pointer to a variable that receives the number of pages required for
- +** the page table according to the GPU page size.
- +*/
- +gceSTATUS
- +gckOS_LockPages(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes,
- + IN gctBOOL Cacheable,
- + OUT gctPOINTER * Logical,
- + OUT gctSIZE_T * PageCount
- + )
- +{
- + PLINUX_MDL mdl;
- + PLINUX_MDL_MAP mdlMap;
- + gctSTRING addr;
- + unsigned long start;
- + unsigned long pfn;
- + gctINT i;
- +
- + gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Logical);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(PageCount != gcvNULL);
- +
- + mdl = (PLINUX_MDL) Physical;
- +
- + MEMORY_LOCK(Os);
- +
- + mdlMap = FindMdlMap(mdl, _GetProcessID());
- +
- + if (mdlMap == gcvNULL)
- + {
- + mdlMap = _CreateMdlMap(mdl, _GetProcessID());
- +
- + if (mdlMap == gcvNULL)
- + {
- + MEMORY_UNLOCK(Os);
- +
- + gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
- + return gcvSTATUS_OUT_OF_MEMORY;
- + }
- + }
- +
- + if (mdlMap->vmaAddr == gcvNULL)
- + {
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
- + mdlMap->vmaAddr = (gctSTRING)vm_mmap(gcvNULL,
- + 0L,
- + mdl->numPages * PAGE_SIZE,
- + PROT_READ | PROT_WRITE,
- + MAP_SHARED,
- + 0);
- +#else
- + down_write(¤t->mm->mmap_sem);
- +
- + mdlMap->vmaAddr = (gctSTRING)do_mmap_pgoff(gcvNULL,
- + 0L,
- + mdl->numPages * PAGE_SIZE,
- + PROT_READ | PROT_WRITE,
- + MAP_SHARED,
- + 0);
- +
- + up_write(¤t->mm->mmap_sem);
- +#endif
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_OS,
- + "%s(%d): vmaAddr->0x%X for phys_addr->0x%X",
- + __FUNCTION__, __LINE__,
- + (gctUINT32)(gctUINTPTR_T)mdlMap->vmaAddr,
- + (gctUINT32)(gctUINTPTR_T)mdl
- + );
- +
- + if (IS_ERR(mdlMap->vmaAddr))
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_OS,
- + "%s(%d): do_mmap_pgoff error",
- + __FUNCTION__, __LINE__
- + );
- +
- + mdlMap->vmaAddr = gcvNULL;
- +
- + MEMORY_UNLOCK(Os);
- +
- + gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
- + return gcvSTATUS_OUT_OF_MEMORY;
- + }
- +
- + down_write(¤t->mm->mmap_sem);
- +
- + mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
- +
- + if (mdlMap->vma == gcvNULL)
- + {
- + up_write(¤t->mm->mmap_sem);
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_OS,
- + "%s(%d): find_vma error",
- + __FUNCTION__, __LINE__
- + );
- +
- + mdlMap->vmaAddr = gcvNULL;
- +
- + MEMORY_UNLOCK(Os);
- +
- + gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_RESOURCES);
- + return gcvSTATUS_OUT_OF_RESOURCES;
- + }
- +
- + mdlMap->vma->vm_flags |= gcdVM_FLAGS;
- +
- + if (Cacheable == gcvFALSE)
- + {
- + /* Make this mapping non-cached. */
- + mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
- + }
- +
- + addr = mdl->addr;
- +
- + /* Now map all the vmalloc pages to this user address. */
- + if (mdl->contiguous)
- + {
- + /* map kernel memory to user space.. */
- + if (remap_pfn_range(mdlMap->vma,
- + mdlMap->vma->vm_start,
- + page_to_pfn(mdl->u.contiguousPages),
- + mdlMap->vma->vm_end - mdlMap->vma->vm_start,
- + mdlMap->vma->vm_page_prot) < 0)
- + {
- + up_write(¤t->mm->mmap_sem);
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_OS,
- + "%s(%d): unable to mmap ret",
- + __FUNCTION__, __LINE__
- + );
- +
- + mdlMap->vmaAddr = gcvNULL;
- +
- + MEMORY_UNLOCK(Os);
- +
- + gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
- + return gcvSTATUS_OUT_OF_MEMORY;
- + }
- + }
- + else
- + {
- + start = mdlMap->vma->vm_start;
- +
- + for (i = 0; i < mdl->numPages; i++)
- + {
- + pfn = _NonContiguousToPfn(mdl->u.nonContiguousPages, i);
- +
- + if (remap_pfn_range(mdlMap->vma,
- + start,
- + pfn,
- + PAGE_SIZE,
- + mdlMap->vma->vm_page_prot) < 0)
- + {
- + up_write(¤t->mm->mmap_sem);
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_OS,
- + "%s(%d): gctPHYS_ADDR->0x%X Logical->0x%X Unable to map addr->0x%X to start->0x%X",
- + __FUNCTION__, __LINE__,
- + (gctUINT32)(gctUINTPTR_T)Physical,
- + (gctUINT32)(gctUINTPTR_T)*Logical,
- + (gctUINT32)(gctUINTPTR_T)addr,
- + (gctUINT32)(gctUINTPTR_T)start
- + );
- +
- + mdlMap->vmaAddr = gcvNULL;
- +
- + MEMORY_UNLOCK(Os);
- +
- + gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
- + return gcvSTATUS_OUT_OF_MEMORY;
- + }
- +
- + start += PAGE_SIZE;
- + addr += PAGE_SIZE;
- + }
- + }
- +
- + up_write(¤t->mm->mmap_sem);
- + }
- +
- + mdlMap->count++;
- +
- + /* Convert pointer to MDL. */
- + *Logical = mdlMap->vmaAddr;
- +
- + /* Return the page number according to the GPU page size. */
- + gcmkASSERT((PAGE_SIZE % 4096) == 0);
- + gcmkASSERT((PAGE_SIZE / 4096) >= 1);
- +
- + *PageCount = mdl->numPages * (PAGE_SIZE / 4096);
- +
- + MEMORY_UNLOCK(Os);
- +
- + gcmkVERIFY_OK(gckOS_CacheFlush(
- + Os,
- + _GetProcessID(),
- + Physical,
- + gcvNULL,
- + (gctPOINTER)mdlMap->vmaAddr,
- + mdl->numPages * PAGE_SIZE
- + ));
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Logical=0x%X *PageCount=%lu", *Logical, *PageCount);
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_MapPages
- +**
- +** Map paged memory into a page table.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPHYS_ADDR Physical
- +** Physical address of the allocation.
- +**
- +** gctSIZE_T PageCount
- +** Number of pages required for the physical address.
- +**
- +** gctPOINTER PageTable
- +** Pointer to the page table to fill in.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_MapPages(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T PageCount,
- + IN gctPOINTER PageTable
- + )
- +{
- + return gckOS_MapPagesEx(Os,
- + gcvCORE_MAJOR,
- + Physical,
- + PageCount,
- + PageTable);
- +}
- +
- +gceSTATUS
- +gckOS_MapPagesEx(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T PageCount,
- + IN gctPOINTER PageTable
- + )
- +{
- + gceSTATUS status = gcvSTATUS_OK;
- + PLINUX_MDL mdl;
- + gctUINT32* table;
- + gctUINT32 offset;
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + gckMMU mmu;
- + PLINUX_MDL mmuMdl;
- + gctUINT32 bytes;
- + gctPHYS_ADDR pageTablePhysical;
- +#endif
- +
- + gcmkHEADER_ARG("Os=0x%X Core=%d Physical=0x%X PageCount=%u PageTable=0x%X",
- + Os, Core, Physical, PageCount, PageTable);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(PageCount > 0);
- + gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
- +
- + /* Convert pointer to MDL. */
- + mdl = (PLINUX_MDL)Physical;
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_OS,
- + "%s(%d): Physical->0x%X PageCount->0x%X PagedMemory->?%d",
- + __FUNCTION__, __LINE__,
- + (gctUINT32)(gctUINTPTR_T)Physical,
- + (gctUINT32)(gctUINTPTR_T)PageCount,
- + mdl->pagedMem
- + );
- +
- + MEMORY_LOCK(Os);
- +
- + table = (gctUINT32 *)PageTable;
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + mmu = Os->device->kernels[Core]->mmu;
- + bytes = PageCount * sizeof(*table);
- + mmuMdl = (PLINUX_MDL)mmu->pageTablePhysical;
- +#endif
- +
- + /* Get all the physical addresses and store them in the page table. */
- +
- + offset = 0;
- +
- + if (mdl->pagedMem)
- + {
- + /* Try to get the user pages so DMA can happen. */
- + while (PageCount-- > 0)
- + {
- +#if gcdENABLE_VG
- + if (Core == gcvCORE_VG)
- + {
- + if (mdl->contiguous)
- + {
- + gcmkONERROR(
- + gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
- + page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
- + table));
- + }
- + else
- + {
- + gcmkONERROR(
- + gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
- + _NonContiguousToPhys(mdl->u.nonContiguousPages, offset),
- + table));
- + }
- + }
- + else
- +#endif
- + {
- + if (mdl->contiguous)
- + {
- + gcmkONERROR(
- + gckMMU_SetPage(Os->device->kernels[Core]->mmu,
- + page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
- + table));
- + }
- + else
- + {
- + gcmkONERROR(
- + gckMMU_SetPage(Os->device->kernels[Core]->mmu,
- + _NonContiguousToPhys(mdl->u.nonContiguousPages, offset),
- + table));
- + }
- + }
- +
- + table++;
- + offset += 1;
- + }
- + }
- + else
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_OS,
- + "%s(%d): we should not get this call for Non Paged Memory!",
- + __FUNCTION__, __LINE__
- + );
- +
- + while (PageCount-- > 0)
- + {
- +#if gcdENABLE_VG
- + if (Core == gcvCORE_VG)
- + {
- + gcmkONERROR(
- + gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
- + page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
- + table));
- + }
- + else
- +#endif
- + {
- + gcmkONERROR(
- + gckMMU_SetPage(Os->device->kernels[Core]->mmu,
- + page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
- + table));
- + }
- + table++;
- + offset += 1;
- + }
- + }
- +
- +#if gcdNONPAGED_MEMORY_CACHEABLE
- + /* Get physical address of pageTable */
- + pageTablePhysical = (gctPHYS_ADDR)(mmuMdl->dmaHandle +
- + ((gctUINT32 *)PageTable - mmu->pageTableLogical));
- +
- + /* Flush the mmu page table cache. */
- + gcmkONERROR(gckOS_CacheClean(
- + Os,
- + _GetProcessID(),
- + gcvNULL,
- + pageTablePhysical,
- + PageTable,
- + bytes
- + ));
- +#endif
- +
- +OnError:
- +
- + MEMORY_UNLOCK(Os);
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_UnlockPages
- +**
- +** Unlock memory allocated from the paged pool.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPHYS_ADDR Physical
- +** Physical address of the allocation.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes of the allocation.
- +**
- +** gctPOINTER Logical
- +** Address of the mapped memory.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_UnlockPages(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctSIZE_T Bytes,
- + IN gctPOINTER Logical
- + )
- +{
- + PLINUX_MDL_MAP mdlMap;
- + PLINUX_MDL mdl = (PLINUX_MDL)Physical;
- +
- + gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%u Logical=0x%X",
- + Os, Physical, Bytes, Logical);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- +
- + /* Make sure there is already a mapping...*/
- + gcmkVERIFY_ARGUMENT(mdl->u.nonContiguousPages != gcvNULL
- + || mdl->u.contiguousPages != gcvNULL);
- +
- + MEMORY_LOCK(Os);
- +
- + mdlMap = mdl->maps;
- +
- + while (mdlMap != gcvNULL)
- + {
- + if ((mdlMap->vmaAddr != gcvNULL) && (_GetProcessID() == mdlMap->pid))
- + {
- + if (--mdlMap->count == 0)
- + {
- + _UnmapUserLogical(mdlMap->pid, mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
- + mdlMap->vmaAddr = gcvNULL;
- + }
- + }
- +
- + mdlMap = mdlMap->next;
- + }
- +
- + MEMORY_UNLOCK(Os);
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +
- +/*******************************************************************************
- +**
- +** gckOS_AllocateContiguous
- +**
- +** Allocate memory from the contiguous pool.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctBOOL InUserSpace
- +** gcvTRUE if the pages need to be mapped into user space.
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to the number of bytes to allocate.
- +**
- +** OUTPUT:
- +**
- +** gctSIZE_T * Bytes
- +** Pointer to a variable that receives the number of bytes allocated.
- +**
- +** gctPHYS_ADDR * Physical
- +** Pointer to a variable that receives the physical address of the
- +** memory allocation.
- +**
- +** gctPOINTER * Logical
- +** Pointer to a variable that receives the logical address of the
- +** memory allocation.
- +*/
- +gceSTATUS
- +gckOS_AllocateContiguous(
- + IN gckOS Os,
- + IN gctBOOL InUserSpace,
- + IN OUT gctSIZE_T * Bytes,
- + OUT gctPHYS_ADDR * Physical,
- + OUT gctPOINTER * Logical
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
- + Os, InUserSpace, gcmOPT_VALUE(Bytes));
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
- + gcmkVERIFY_ARGUMENT(*Bytes > 0);
- + gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- +
- + /* Same as non-paged memory for now. */
- + gcmkONERROR(gckOS_AllocateNonPagedMemory(Os,
- + InUserSpace,
- + Bytes,
- + Physical,
- + Logical));
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
- + *Bytes, *Physical, *Logical);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_FreeContiguous
- +**
- +** Free memory allocated from the contiguous pool.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPHYS_ADDR Physical
- +** Physical address of the allocation.
- +**
- +** gctPOINTER Logical
- +** Logicval address of the allocation.
- +**
- +** gctSIZE_T Bytes
- +** Number of bytes of the allocation.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_FreeContiguous(
- + IN gckOS Os,
- + IN gctPHYS_ADDR Physical,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
- + Os, Physical, Logical, Bytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- +
- + /* Same of non-paged memory for now. */
- + gcmkONERROR(gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical));
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +#if gcdENABLE_VG
- +/******************************************************************************
- +**
- +** gckOS_GetKernelLogical
- +**
- +** Return the kernel logical pointer that corresponods to the specified
- +** hardware address.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctUINT32 Address
- +** Hardware physical address.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * KernelPointer
- +** Pointer to a variable receiving the pointer in kernel address space.
- +*/
- +gceSTATUS
- +gckOS_GetKernelLogical(
- + IN gckOS Os,
- + IN gctUINT32 Address,
- + OUT gctPOINTER * KernelPointer
- + )
- +{
- + return gckOS_GetKernelLogicalEx(Os, gcvCORE_MAJOR, Address, KernelPointer);
- +}
- +
- +gceSTATUS
- +gckOS_GetKernelLogicalEx(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctUINT32 Address,
- + OUT gctPOINTER * KernelPointer
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%08x", Os, Core, Address);
- +
- + do
- + {
- + gckGALDEVICE device;
- + gckKERNEL kernel;
- + gcePOOL pool;
- + gctUINT32 offset;
- + gctPOINTER logical;
- +
- + /* Extract the pointer to the gckGALDEVICE class. */
- + device = (gckGALDEVICE) Os->device;
- +
- + /* Kernel shortcut. */
- + kernel = device->kernels[Core];
- +#if gcdENABLE_VG
- + if (Core == gcvCORE_VG)
- + {
- + gcmkERR_BREAK(gckVGHARDWARE_SplitMemory(
- + kernel->vg->hardware, Address, &pool, &offset
- + ));
- + }
- + else
- +#endif
- + {
- + /* Split the memory address into a pool type and offset. */
- + gcmkERR_BREAK(gckHARDWARE_SplitMemory(
- + kernel->hardware, Address, &pool, &offset
- + ));
- + }
- +
- + /* Dispatch on pool. */
- + switch (pool)
- + {
- + case gcvPOOL_LOCAL_INTERNAL:
- + /* Internal memory. */
- + logical = device->internalLogical;
- + break;
- +
- + case gcvPOOL_LOCAL_EXTERNAL:
- + /* External memory. */
- + logical = device->externalLogical;
- + break;
- +
- + case gcvPOOL_SYSTEM:
- + /* System memory. */
- + logical = device->contiguousBase;
- + break;
- +
- + default:
- + /* Invalid memory pool. */
- + gcmkFOOTER();
- + return gcvSTATUS_INVALID_ARGUMENT;
- + }
- +
- + /* Build logical address of specified address. */
- + * KernelPointer = ((gctUINT8_PTR) logical) + offset;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
- + return gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + /* Return status. */
- + gcmkFOOTER();
- + return status;
- +}
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gckOS_MapUserPointer
- +**
- +** Map a pointer from the user process into the kernel address space.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPOINTER Pointer
- +** Pointer in user process space that needs to be mapped.
- +**
- +** gctSIZE_T Size
- +** Number of bytes that need to be mapped.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * KernelPointer
- +** Pointer to a variable receiving the mapped pointer in kernel address
- +** space.
- +*/
- +gceSTATUS
- +gckOS_MapUserPointer(
- + IN gckOS Os,
- + IN gctPOINTER Pointer,
- + IN gctSIZE_T Size,
- + OUT gctPOINTER * KernelPointer
- + )
- +{
- + gctPOINTER buf = gcvNULL;
- + gctUINT32 len;
- +
- + gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu", Os, Pointer, Size);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Size > 0);
- + gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
- +
- + buf = kmalloc(Size, GFP_KERNEL | gcdNOWARN);
- + if (buf == gcvNULL)
- + {
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): Failed to allocate memory.",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
- + return gcvSTATUS_OUT_OF_MEMORY;
- + }
- +
- + len = copy_from_user(buf, Pointer, Size);
- + if (len != 0)
- + {
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): Failed to copy data from user.",
- + __FUNCTION__, __LINE__
- + );
- +
- + if (buf != gcvNULL)
- + {
- + kfree(buf);
- + }
- +
- + gcmkFOOTER_ARG("*status=%d", gcvSTATUS_GENERIC_IO);
- + return gcvSTATUS_GENERIC_IO;
- + }
- +
- + *KernelPointer = buf;
- +
- + gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_UnmapUserPointer
- +**
- +** Unmap a user process pointer from the kernel address space.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPOINTER Pointer
- +** Pointer in user process space that needs to be unmapped.
- +**
- +** gctSIZE_T Size
- +** Number of bytes that need to be unmapped.
- +**
- +** gctPOINTER KernelPointer
- +** Pointer in kernel address space that needs to be unmapped.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_UnmapUserPointer(
- + IN gckOS Os,
- + IN gctPOINTER Pointer,
- + IN gctSIZE_T Size,
- + IN gctPOINTER KernelPointer
- + )
- +{
- + gctUINT32 len;
- +
- + gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu KernelPointer=0x%X",
- + Os, Pointer, Size, KernelPointer);
- +
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Size > 0);
- + gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
- +
- + len = copy_to_user(Pointer, KernelPointer, Size);
- +
- + kfree(KernelPointer);
- +
- + if (len != 0)
- + {
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): Failed to copy data to user.",
- + __FUNCTION__, __LINE__
- + );
- +
- + gcmkFOOTER_ARG("status=%d", gcvSTATUS_GENERIC_IO);
- + return gcvSTATUS_GENERIC_IO;
- + }
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_QueryNeedCopy
- +**
- +** Query whether the memory can be accessed or mapped directly or it has to be
- +** copied.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctUINT32 ProcessID
- +** Process ID of the current process.
- +**
- +** OUTPUT:
- +**
- +** gctBOOL_PTR NeedCopy
- +** Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
- +** gcvFALSE if the memory can be accessed or mapped dircetly.
- +*/
- +gceSTATUS
- +gckOS_QueryNeedCopy(
- + IN gckOS Os,
- + IN gctUINT32 ProcessID,
- + OUT gctBOOL_PTR NeedCopy
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X ProcessID=%d", Os, ProcessID);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(NeedCopy != gcvNULL);
- +
- + /* We need to copy data. */
- + *NeedCopy = gcvTRUE;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*NeedCopy=%d", *NeedCopy);
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_CopyFromUserData
- +**
- +** Copy data from user to kernel memory.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPOINTER KernelPointer
- +** Pointer to kernel memory.
- +**
- +** gctPOINTER Pointer
- +** Pointer to user memory.
- +**
- +** gctSIZE_T Size
- +** Number of bytes to copy.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_CopyFromUserData(
- + IN gckOS Os,
- + IN gctPOINTER KernelPointer,
- + IN gctPOINTER Pointer,
- + IN gctSIZE_T Size
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
- + Os, KernelPointer, Pointer, Size);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Size > 0);
- +
- + /* Copy data from user. */
- + if (copy_from_user(KernelPointer, Pointer, Size) != 0)
- + {
- + /* Could not copy all the bytes. */
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_CopyToUserData
- +**
- +** Copy data from kernel to user memory.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPOINTER KernelPointer
- +** Pointer to kernel memory.
- +**
- +** gctPOINTER Pointer
- +** Pointer to user memory.
- +**
- +** gctSIZE_T Size
- +** Number of bytes to copy.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_CopyToUserData(
- + IN gckOS Os,
- + IN gctPOINTER KernelPointer,
- + IN gctPOINTER Pointer,
- + IN gctSIZE_T Size
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
- + Os, KernelPointer, Pointer, Size);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Size > 0);
- +
- + /* Copy data to user. */
- + if (copy_to_user(Pointer, KernelPointer, Size) != 0)
- + {
- + /* Could not copy all the bytes. */
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_WriteMemory
- +**
- +** Write data to a memory.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctPOINTER Address
- +** Address of the memory to write to.
- +**
- +** gctUINT32 Data
- +** Data for register.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_WriteMemory(
- + IN gckOS Os,
- + IN gctPOINTER Address,
- + IN gctUINT32 Data
- + )
- +{
- + gceSTATUS status;
- + gcmkHEADER_ARG("Os=0x%X Address=0x%X Data=%u", Os, Address, Data);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_ARGUMENT(Address != gcvNULL);
- +
- + /* Write memory. */
- + if (access_ok(VERIFY_WRITE, Address, 4))
- + {
- + /* User address. */
- + if(put_user(Data, (gctUINT32*)Address))
- + {
- + gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
- + }
- + }
- + else
- + {
- + /* Kernel address. */
- + *(gctUINT32 *)Address = Data;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_MapUserMemory
- +**
- +** Lock down a user buffer and return an DMA'able address to be used by the
- +** hardware to access it.
- +**
- +** INPUT:
- +**
- +** gctPOINTER Memory
- +** Pointer to memory to lock down.
- +**
- +** gctSIZE_T Size
- +** Size in bytes of the memory to lock down.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * Info
- +** Pointer to variable receiving the information record required by
- +** gckOS_UnmapUserMemory.
- +**
- +** gctUINT32_PTR Address
- +** Pointer to a variable that will receive the address DMA'able by the
- +** hardware.
- +*/
- +gceSTATUS
- +gckOS_MapUserMemory(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctPOINTER Memory,
- + IN gctUINT32 Physical,
- + IN gctSIZE_T Size,
- + OUT gctPOINTER * Info,
- + OUT gctUINT32_PTR Address
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%x Core=%d Memory=0x%x Size=%lu", Os, Core, Memory, Size);
- +
- +#if gcdSECURE_USER
- + gcmkONERROR(gckOS_AddMapping(Os, *Address, Memory, Size));
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +#else
- +{
- + gctSIZE_T pageCount, i, j;
- + gctUINT32_PTR pageTable;
- + gctUINT32 address = 0, physical = ~0U;
- + gctUINTPTR_T start, end, memory;
- + gctUINT32 offset;
- + gctINT result = 0;
- +
- + gcsPageInfo_PTR info = gcvNULL;
- + struct page **pages = gcvNULL;
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Memory != gcvNULL || Physical != ~0U);
- + gcmkVERIFY_ARGUMENT(Size > 0);
- + gcmkVERIFY_ARGUMENT(Info != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Address != gcvNULL);
- +
- + do
- + {
- + memory = (gctUINTPTR_T) Memory;
- +
- + /* Get the number of required pages. */
- + end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
- + start = memory >> PAGE_SHIFT;
- + pageCount = end - start;
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_OS,
- + "%s(%d): pageCount: %d.",
- + __FUNCTION__, __LINE__,
- + pageCount
- + );
- +
- + /* Overflow. */
- + if ((memory + Size) < memory)
- + {
- + gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
- + return gcvSTATUS_INVALID_ARGUMENT;
- + }
- +
- + MEMORY_MAP_LOCK(Os);
- +
- + /* Allocate the Info struct. */
- + info = (gcsPageInfo_PTR)kmalloc(sizeof(gcsPageInfo), GFP_KERNEL | gcdNOWARN);
- +
- + if (info == gcvNULL)
- + {
- + status = gcvSTATUS_OUT_OF_MEMORY;
- + break;
- + }
- +
- + /* Allocate the array of page addresses. */
- + pages = (struct page **)kmalloc(pageCount * sizeof(struct page *), GFP_KERNEL | gcdNOWARN);
- +
- + if (pages == gcvNULL)
- + {
- + status = gcvSTATUS_OUT_OF_MEMORY;
- + break;
- + }
- +
- + if (Physical != ~0U)
- + {
- + for (i = 0; i < pageCount; i++)
- + {
- + pages[i] = pfn_to_page((Physical >> PAGE_SHIFT) + i);
- + get_page(pages[i]);
- + }
- + }
- + else
- + {
- + /* Get the user pages. */
- + down_read(¤t->mm->mmap_sem);
- +
- + result = get_user_pages(current,
- + current->mm,
- + memory & PAGE_MASK,
- + pageCount,
- + 1,
- + 0,
- + pages,
- + gcvNULL
- + );
- +
- + up_read(¤t->mm->mmap_sem);
- +
- + if (result <=0 || result < pageCount)
- + {
- + struct vm_area_struct *vma;
- +
- + /* Release the pages if any. */
- + if (result > 0)
- + {
- + for (i = 0; i < result; i++)
- + {
- + if (pages[i] == gcvNULL)
- + {
- + break;
- + }
- +
- + page_cache_release(pages[i]);
- + pages[i] = gcvNULL;
- + }
- +
- + result = 0;
- + }
- +
- + vma = find_vma(current->mm, memory);
- +
- + if (vma && (vma->vm_flags & VM_PFNMAP))
- + {
- + pte_t * pte;
- + spinlock_t * ptl;
- + gctUINTPTR_T logical = memory;
- +
- + for (i = 0; i < pageCount; i++)
- + {
- + pgd_t * pgd = pgd_offset(current->mm, logical);
- + pud_t * pud = pud_offset(pgd, logical);
- +
- + if (pud)
- + {
- + pmd_t * pmd = pmd_offset(pud, logical);
- + pte = pte_offset_map_lock(current->mm, pmd, logical, &ptl);
- + if (!pte)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- + }
- + else
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +
- + pages[i] = pte_page(*pte);
- + pte_unmap_unlock(pte, ptl);
- +
- + /* Advance to next. */
- + logical += PAGE_SIZE;
- + }
- + }
- + else
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +
- + /* Check if this memory is contiguous for old mmu. */
- + if (Os->device->kernels[Core]->hardware->mmuVersion == 0)
- + {
- + for (i = 1; i < pageCount; i++)
- + {
- + if (pages[i] != nth_page(pages[0], i))
- + {
- + /* Non-contiguous. */
- + break;
- + }
- + }
- +
- + if (i == pageCount)
- + {
- + /* Contiguous memory. */
- + physical = page_to_phys(pages[0]) | (memory & ~PAGE_MASK);
- +
- + if (!((physical - Os->device->baseAddress) & 0x80000000))
- + {
- + kfree(pages);
- + pages = gcvNULL;
- +
- + info->pages = gcvNULL;
- + info->pageTable = gcvNULL;
- +
- + MEMORY_MAP_UNLOCK(Os);
- +
- + *Address = physical - Os->device->baseAddress;
- + *Info = info;
- +
- + gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x",
- + *Info, *Address);
- +
- + return gcvSTATUS_OK;
- + }
- + }
- + }
- +
- + /* Reference pages. */
- + for (i = 0; i < pageCount; i++)
- + {
- + get_page(pages[i]);
- + }
- + }
- + }
- +
- + for (i = 0; i < pageCount; i++)
- + {
- +#ifdef CONFIG_ARM
- + gctUINT32 data;
- + get_user(data, (gctUINT32*)((memory & PAGE_MASK) + i * PAGE_SIZE));
- +#endif
- +
- + /* Flush(clean) the data cache. */
- + gcmkONERROR(gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
- + (gctPOINTER)(gctUINTPTR_T)page_to_phys(pages[i]),
- + (gctPOINTER)(memory & PAGE_MASK) + i*PAGE_SIZE,
- + PAGE_SIZE));
- + }
- +
- +#if gcdENABLE_VG
- + if (Core == gcvCORE_VG)
- + {
- + /* Allocate pages inside the page table. */
- + gcmkERR_BREAK(gckVGMMU_AllocatePages(Os->device->kernels[Core]->vg->mmu,
- + pageCount * (PAGE_SIZE/4096),
- + (gctPOINTER *) &pageTable,
- + &address));
- + }
- + else
- +#endif
- + {
- + /* Allocate pages inside the page table. */
- + gcmkERR_BREAK(gckMMU_AllocatePages(Os->device->kernels[Core]->mmu,
- + pageCount * (PAGE_SIZE/4096),
- + (gctPOINTER *) &pageTable,
- + &address));
- + }
- +
- + /* Fill the page table. */
- + for (i = 0; i < pageCount; i++)
- + {
- + gctUINT32 phys;
- + gctUINT32_PTR tab = pageTable + i * (PAGE_SIZE/4096);
- +
- + phys = page_to_phys(pages[i]);
- +
- +#if gcdENABLE_VG
- + if (Core == gcvCORE_VG)
- + {
- + /* Get the physical address from page struct. */
- + gcmkONERROR(
- + gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
- + phys,
- + tab));
- + }
- + else
- +#endif
- + {
- + /* Get the physical address from page struct. */
- + gcmkONERROR(
- + gckMMU_SetPage(Os->device->kernels[Core]->mmu,
- + phys,
- + tab));
- + }
- +
- + for (j = 1; j < (PAGE_SIZE/4096); j++)
- + {
- + pageTable[i * (PAGE_SIZE/4096) + j] = pageTable[i * (PAGE_SIZE/4096)] + 4096 * j;
- + }
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_OS,
- + "%s(%d): pageTable[%d]: 0x%X 0x%X.",
- + __FUNCTION__, __LINE__,
- + i, phys, pageTable[i]);
- + }
- +
- +#if gcdENABLE_VG
- + if (Core == gcvCORE_VG)
- + {
- + gcmkONERROR(gckVGMMU_Flush(Os->device->kernels[Core]->vg->mmu));
- + }
- + else
- +#endif
- + {
- + gcmkONERROR(gckMMU_Flush(Os->device->kernels[Core]->mmu));
- + }
- +
- + /* Save pointer to page table. */
- + info->pageTable = pageTable;
- + info->pages = pages;
- +
- + *Info = (gctPOINTER) info;
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_OS,
- + "%s(%d): info->pages: 0x%X, info->pageTable: 0x%X, info: 0x%X.",
- + __FUNCTION__, __LINE__,
- + info->pages,
- + info->pageTable,
- + info
- + );
- +
- + offset = (Physical != ~0U)
- + ? (Physical & ~PAGE_MASK)
- + : (memory & ~PAGE_MASK);
- +
- + /* Return address. */
- + *Address = address + offset;
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_OS,
- + "%s(%d): Address: 0x%X.",
- + __FUNCTION__, __LINE__,
- + *Address
- + );
- +
- + /* Success. */
- + status = gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- +OnError:
- +
- + if (gcmIS_ERROR(status))
- + {
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): error occured: %d.",
- + __FUNCTION__, __LINE__,
- + status
- + );
- +
- + /* Release page array. */
- + if (result > 0 && pages != gcvNULL)
- + {
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): error: page table is freed.",
- + __FUNCTION__, __LINE__
- + );
- +
- + for (i = 0; i < result; i++)
- + {
- + if (pages[i] == gcvNULL)
- + {
- + break;
- + }
- + page_cache_release(pages[i]);
- + }
- + }
- +
- + if (info!= gcvNULL && pages != gcvNULL)
- + {
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): error: pages is freed.",
- + __FUNCTION__, __LINE__
- + );
- +
- + /* Free the page table. */
- + kfree(pages);
- + info->pages = gcvNULL;
- + }
- +
- + /* Release page info struct. */
- + if (info != gcvNULL)
- + {
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): error: info is freed.",
- + __FUNCTION__, __LINE__
- + );
- +
- + /* Free the page info struct. */
- + kfree(info);
- + *Info = gcvNULL;
- + }
- + }
- +
- + MEMORY_MAP_UNLOCK(Os);
- +
- + /* Return the status. */
- + if (gcmIS_SUCCESS(status))
- + {
- + gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x", *Info, *Address);
- + }
- + else
- + {
- + gcmkFOOTER();
- + }
- +
- + return status;
- +}
- +#endif
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_UnmapUserMemory
- +**
- +** Unlock a user buffer and that was previously locked down by
- +** gckOS_MapUserMemory.
- +**
- +** INPUT:
- +**
- +** gctPOINTER Memory
- +** Pointer to memory to unlock.
- +**
- +** gctSIZE_T Size
- +** Size in bytes of the memory to unlock.
- +**
- +** gctPOINTER Info
- +** Information record returned by gckOS_MapUserMemory.
- +**
- +** gctUINT32_PTR Address
- +** The address returned by gckOS_MapUserMemory.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_UnmapUserMemory(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctPOINTER Memory,
- + IN gctSIZE_T Size,
- + IN gctPOINTER Info,
- + IN gctUINT32 Address
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%X Core=%d Memory=0x%X Size=%lu Info=0x%X Address0x%08x",
- + Os, Core, Memory, Size, Info, Address);
- +
- +#if gcdSECURE_USER
- + gcmkONERROR(gckOS_RemoveMapping(Os, Memory, Size));
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +#else
- +{
- + gctUINTPTR_T memory, start, end;
- + gcsPageInfo_PTR info;
- + gctSIZE_T pageCount, i;
- + struct page **pages;
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Size > 0);
- + gcmkVERIFY_ARGUMENT(Info != gcvNULL);
- +
- + do
- + {
- + info = (gcsPageInfo_PTR) Info;
- +
- + pages = info->pages;
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_OS,
- + "%s(%d): info=0x%X, pages=0x%X.",
- + __FUNCTION__, __LINE__,
- + info, pages
- + );
- +
- + /* Invalid page array. */
- + if (pages == gcvNULL && info->pageTable == gcvNULL)
- + {
- + kfree(info);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- + }
- +
- + memory = (gctUINTPTR_T)Memory;
- + end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
- + start = memory >> PAGE_SHIFT;
- + pageCount = end - start;
- +
- + /* Overflow. */
- + if ((memory + Size) < memory)
- + {
- + gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
- + return gcvSTATUS_INVALID_ARGUMENT;
- + }
- +
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_OS,
- + "%s(%d): memory: 0x%X, pageCount: %d, pageTable: 0x%X.",
- + __FUNCTION__, __LINE__,
- + memory, pageCount, info->pageTable
- + );
- +
- + MEMORY_MAP_LOCK(Os);
- +
- + gcmkASSERT(info->pageTable != gcvNULL);
- +
- +#if gcdENABLE_VG
- + if (Core == gcvCORE_VG)
- + {
- + /* Free the pages from the MMU. */
- + gcmkERR_BREAK(gckVGMMU_FreePages(Os->device->kernels[Core]->vg->mmu,
- + info->pageTable,
- + pageCount * (PAGE_SIZE/4096)
- + ));
- + }
- + else
- +#endif
- + {
- + /* Free the pages from the MMU. */
- + gcmkERR_BREAK(gckMMU_FreePages(Os->device->kernels[Core]->mmu,
- + info->pageTable,
- + pageCount * (PAGE_SIZE/4096)
- + ));
- + }
- +
- + /* Release the page cache. */
- + if (pages)
- + {
- + for (i = 0; i < pageCount; i++)
- + {
- + gcmkTRACE_ZONE(
- + gcvLEVEL_INFO, gcvZONE_OS,
- + "%s(%d): pages[%d]: 0x%X.",
- + __FUNCTION__, __LINE__,
- + i, pages[i]
- + );
- +
- + if (!PageReserved(pages[i]))
- + {
- + SetPageDirty(pages[i]);
- + }
- +
- + page_cache_release(pages[i]);
- + }
- + }
- +
- + /* Success. */
- + status = gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + if (info != gcvNULL)
- + {
- + /* Free the page array. */
- + if (info->pages != gcvNULL)
- + {
- + kfree(info->pages);
- + }
- +
- + kfree(info);
- + }
- +
- + MEMORY_MAP_UNLOCK(Os);
- +
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +#endif
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_GetBaseAddress
- +**
- +** Get the base address for the physical memory.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to the gckOS object.
- +**
- +** OUTPUT:
- +**
- +** gctUINT32_PTR BaseAddress
- +** Pointer to a variable that will receive the base address.
- +*/
- +gceSTATUS
- +gckOS_GetBaseAddress(
- + IN gckOS Os,
- + OUT gctUINT32_PTR BaseAddress
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X", Os);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
- +
- + /* Return base address. */
- + *BaseAddress = Os->device->baseAddress;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckOS_SuspendInterrupt(
- + IN gckOS Os
- + )
- +{
- + return gckOS_SuspendInterruptEx(Os, gcvCORE_MAJOR);
- +}
- +
- +gceSTATUS
- +gckOS_SuspendInterruptEx(
- + IN gckOS Os,
- + IN gceCORE Core
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- +
- + disable_irq(Os->device->irqLines[Core]);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckOS_ResumeInterrupt(
- + IN gckOS Os
- + )
- +{
- + return gckOS_ResumeInterruptEx(Os, gcvCORE_MAJOR);
- +}
- +
- +gceSTATUS
- +gckOS_ResumeInterruptEx(
- + IN gckOS Os,
- + IN gceCORE Core
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- +
- + enable_irq(Os->device->irqLines[Core]);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckOS_MemCopy(
- + IN gctPOINTER Destination,
- + IN gctCONST_POINTER Source,
- + IN gctSIZE_T Bytes
- + )
- +{
- + gcmkHEADER_ARG("Destination=0x%X Source=0x%X Bytes=%lu",
- + Destination, Source, Bytes);
- +
- + gcmkVERIFY_ARGUMENT(Destination != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Source != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- +
- + memcpy(Destination, Source, Bytes);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckOS_ZeroMemory(
- + IN gctPOINTER Memory,
- + IN gctSIZE_T Bytes
- + )
- +{
- + gcmkHEADER_ARG("Memory=0x%X Bytes=%lu", Memory, Bytes);
- +
- + gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- +
- + memset(Memory, 0, Bytes);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +********************************* Cache Control ********************************
- +*******************************************************************************/
- +
- +#if !gcdCACHE_FUNCTION_UNIMPLEMENTED && defined(CONFIG_OUTER_CACHE)
- +static inline gceSTATUS
- +outer_func(
- + gceCACHEOPERATION Type,
- + unsigned long Start,
- + unsigned long End
- + )
- +{
- + switch (Type)
- + {
- + case gcvCACHE_CLEAN:
- + outer_clean_range(Start, End);
- + break;
- + case gcvCACHE_INVALIDATE:
- + outer_inv_range(Start, End);
- + break;
- + case gcvCACHE_FLUSH:
- + outer_flush_range(Start, End);
- + break;
- + default:
- + return gcvSTATUS_INVALID_ARGUMENT;
- + break;
- + }
- + return gcvSTATUS_OK;
- +}
- +
- +#if gcdENABLE_OUTER_CACHE_PATCH
- +/*******************************************************************************
- +** _HandleOuterCache
- +**
- +** Handle the outer cache for the specified addresses.
- +**
- +** ARGUMENTS:
- +**
- +** gckOS Os
- +** Pointer to gckOS object.
- +**
- +** gctUINT32 ProcessID
- +** Process ID Logical belongs.
- +**
- +** gctPHYS_ADDR Handle
- +** Physical address handle. If gcvNULL it is video memory.
- +**
- +** gctPOINTER Physical
- +** Physical address to flush.
- +**
- +** gctPOINTER Logical
- +** Logical address to flush.
- +**
- +** gctSIZE_T Bytes
- +** Size of the address range in bytes to flush.
- +**
- +** gceOUTERCACHE_OPERATION Type
- +** Operation need to be execute.
- +*/
- +static gceSTATUS
- +_HandleOuterCache(
- + IN gckOS Os,
- + IN gctUINT32 ProcessID,
- + IN gctPHYS_ADDR Handle,
- + IN gctPOINTER Physical,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes,
- + IN gceCACHEOPERATION Type
- + )
- +{
- + gceSTATUS status;
- + gctUINT32 i, pageNum;
- + unsigned long paddr;
- + gctPOINTER vaddr;
- +
- + gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
- + Os, ProcessID, Handle, Logical, Bytes);
- +
- + if (Physical != gcvNULL)
- + {
- + /* Non paged memory or gcvPOOL_USER surface */
- + paddr = (unsigned long) Physical;
- + gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
- + }
- + else if ((Handle == gcvNULL)
- + || (Handle != gcvNULL && ((PLINUX_MDL)Handle)->contiguous)
- + )
- + {
- + /* Video Memory or contiguous virtual memory */
- + gcmkONERROR(gckOS_GetPhysicalAddress(Os, Logical, (gctUINT32*)&paddr));
- + gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
- + }
- + else
- + {
- + /* Non contiguous virtual memory */
- + vaddr = (gctPOINTER)gcmALIGN_BASE((gctUINTPTR_T)Logical, PAGE_SIZE);
- + pageNum = GetPageCount(Bytes, 0);
- +
- + for (i = 0; i < pageNum; i += 1)
- + {
- + gcmkONERROR(_ConvertLogical2Physical(
- + Os,
- + vaddr + PAGE_SIZE * i,
- + ProcessID,
- + (PLINUX_MDL)Handle,
- + (gctUINT32*)&paddr
- + ));
- +
- + gcmkONERROR(outer_func(Type, paddr, paddr + PAGE_SIZE));
- + }
- + }
- +
- + mb();
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +#endif
- +#endif
- +
- +/*******************************************************************************
- +** gckOS_CacheClean
- +**
- +** Clean the cache for the specified addresses. The GPU is going to need the
- +** data. If the system is allocating memory as non-cachable, this function can
- +** be ignored.
- +**
- +** ARGUMENTS:
- +**
- +** gckOS Os
- +** Pointer to gckOS object.
- +**
- +** gctUINT32 ProcessID
- +** Process ID Logical belongs.
- +**
- +** gctPHYS_ADDR Handle
- +** Physical address handle. If gcvNULL it is video memory.
- +**
- +** gctPOINTER Physical
- +** Physical address to flush.
- +**
- +** gctPOINTER Logical
- +** Logical address to flush.
- +**
- +** gctSIZE_T Bytes
- +** Size of the address range in bytes to flush.
- +*/
- +gceSTATUS
- +gckOS_CacheClean(
- + IN gckOS Os,
- + IN gctUINT32 ProcessID,
- + IN gctPHYS_ADDR Handle,
- + IN gctPOINTER Physical,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
- + Os, ProcessID, Handle, Logical, Bytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- +
- +#if !gcdCACHE_FUNCTION_UNIMPLEMENTED
- +#ifdef CONFIG_ARM
- +
- + /* Inner cache. */
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
- + dmac_map_area(Logical, Bytes, DMA_TO_DEVICE);
- +# else
- + dmac_clean_range(Logical, Logical + Bytes);
- +# endif
- +
- +#if defined(CONFIG_OUTER_CACHE)
- + /* Outer cache. */
- +#if gcdENABLE_OUTER_CACHE_PATCH
- + _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_CLEAN);
- +#else
- + outer_clean_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
- +#endif
- +#endif
- +
- +#elif defined(CONFIG_MIPS)
- +
- + dma_cache_wback((unsigned long) Logical, Bytes);
- +
- +#elif defined(CONFIG_PPC)
- +
- + /* TODO */
- +
- +#else
- + dma_sync_single_for_device(
- + gcvNULL,
- + (dma_addr_t)Physical,
- + Bytes,
- + DMA_TO_DEVICE);
- +#endif
- +#endif
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +** gckOS_CacheInvalidate
- +**
- +** Invalidate the cache for the specified addresses. The GPU is going to need
- +** data. If the system is allocating memory as non-cachable, this function can
- +** be ignored.
- +**
- +** ARGUMENTS:
- +**
- +** gckOS Os
- +** Pointer to gckOS object.
- +**
- +** gctUINT32 ProcessID
- +** Process ID Logical belongs.
- +**
- +** gctPHYS_ADDR Handle
- +** Physical address handle. If gcvNULL it is video memory.
- +**
- +** gctPOINTER Logical
- +** Logical address to flush.
- +**
- +** gctSIZE_T Bytes
- +** Size of the address range in bytes to flush.
- +*/
- +gceSTATUS
- +gckOS_CacheInvalidate(
- + IN gckOS Os,
- + IN gctUINT32 ProcessID,
- + IN gctPHYS_ADDR Handle,
- + IN gctPOINTER Physical,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
- + Os, ProcessID, Handle, Logical, Bytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- +
- +#if !gcdCACHE_FUNCTION_UNIMPLEMENTED
- +#ifdef CONFIG_ARM
- +
- + /* Inner cache. */
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
- + dmac_map_area(Logical, Bytes, DMA_FROM_DEVICE);
- +# else
- + dmac_inv_range(Logical, Logical + Bytes);
- +# endif
- +
- +#if defined(CONFIG_OUTER_CACHE)
- + /* Outer cache. */
- +#if gcdENABLE_OUTER_CACHE_PATCH
- + _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_INVALIDATE);
- +#else
- + outer_inv_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
- +#endif
- +#endif
- +
- +#elif defined(CONFIG_MIPS)
- + dma_cache_inv((unsigned long) Logical, Bytes);
- +#elif defined(CONFIG_PPC)
- + /* TODO */
- +#else
- + dma_sync_single_for_device(
- + gcvNULL,
- + (dma_addr_t)Physical,
- + Bytes,
- + DMA_FROM_DEVICE);
- +#endif
- +#endif
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +** gckOS_CacheFlush
- +**
- +** Clean the cache for the specified addresses and invalidate the lines as
- +** well. The GPU is going to need and modify the data. If the system is
- +** allocating memory as non-cachable, this function can be ignored.
- +**
- +** ARGUMENTS:
- +**
- +** gckOS Os
- +** Pointer to gckOS object.
- +**
- +** gctUINT32 ProcessID
- +** Process ID Logical belongs.
- +**
- +** gctPHYS_ADDR Handle
- +** Physical address handle. If gcvNULL it is video memory.
- +**
- +** gctPOINTER Logical
- +** Logical address to flush.
- +**
- +** gctSIZE_T Bytes
- +** Size of the address range in bytes to flush.
- +*/
- +gceSTATUS
- +gckOS_CacheFlush(
- + IN gckOS Os,
- + IN gctUINT32 ProcessID,
- + IN gctPHYS_ADDR Handle,
- + IN gctPOINTER Physical,
- + IN gctPOINTER Logical,
- + IN gctSIZE_T Bytes
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
- + Os, ProcessID, Handle, Logical, Bytes);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Bytes > 0);
- +
- +#if !gcdCACHE_FUNCTION_UNIMPLEMENTED
- +#ifdef CONFIG_ARM
- + /* Inner cache. */
- + dmac_flush_range(Logical, Logical + Bytes);
- +
- +#if defined(CONFIG_OUTER_CACHE)
- + /* Outer cache. */
- +#if gcdENABLE_OUTER_CACHE_PATCH
- + _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_FLUSH);
- +#else
- + outer_flush_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
- +#endif
- +#endif
- +
- +#elif defined(CONFIG_MIPS)
- + dma_cache_wback_inv((unsigned long) Logical, Bytes);
- +#elif defined(CONFIG_PPC)
- + /* TODO */
- +#else
- + dma_sync_single_for_device(
- + gcvNULL,
- + (dma_addr_t)Physical,
- + Bytes,
- + DMA_BIDIRECTIONAL);
- +#endif
- +#endif
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +********************************* Broadcasting *********************************
- +*******************************************************************************/
- +
- +/*******************************************************************************
- +**
- +** gckOS_Broadcast
- +**
- +** System hook for broadcast events from the kernel driver.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to the gckOS object.
- +**
- +** gckHARDWARE Hardware
- +** Pointer to the gckHARDWARE object.
- +**
- +** gceBROADCAST Reason
- +** Reason for the broadcast. Can be one of the following values:
- +**
- +** gcvBROADCAST_GPU_IDLE
- +** Broadcasted when the kernel driver thinks the GPU might be
- +** idle. This can be used to handle power management.
- +**
- +** gcvBROADCAST_GPU_COMMIT
- +** Broadcasted when any client process commits a command
- +** buffer. This can be used to handle power management.
- +**
- +** gcvBROADCAST_GPU_STUCK
- +** Broadcasted when the kernel driver hits the timeout waiting
- +** for the GPU.
- +**
- +** gcvBROADCAST_FIRST_PROCESS
- +** First process is trying to connect to the kernel.
- +**
- +** gcvBROADCAST_LAST_PROCESS
- +** Last process has detached from the kernel.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_Broadcast(
- + IN gckOS Os,
- + IN gckHARDWARE Hardware,
- + IN gceBROADCAST Reason
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%X Hardware=0x%X Reason=%d", Os, Hardware, Reason);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- +
- + switch (Reason)
- + {
- + case gcvBROADCAST_FIRST_PROCESS:
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "First process has attached");
- + break;
- +
- + case gcvBROADCAST_LAST_PROCESS:
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "Last process has detached");
- +
- + /* Put GPU OFF. */
- + gcmkONERROR(
- + gckHARDWARE_SetPowerManagementState(Hardware,
- + gcvPOWER_OFF_BROADCAST));
- + break;
- +
- + case gcvBROADCAST_GPU_IDLE:
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "GPU idle.");
- +
- + /* Put GPU IDLE. */
- + gcmkONERROR(
- + gckHARDWARE_SetPowerManagementState(Hardware,
- +#if gcdPOWER_SUSNPEND_WHEN_IDLE
- + gcvPOWER_SUSPEND_BROADCAST));
- +#else
- + gcvPOWER_IDLE_BROADCAST));
- +#endif
- +
- + /* Add idle process DB. */
- + gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
- + 1,
- + gcvDB_IDLE,
- + gcvNULL, gcvNULL, 0));
- + break;
- +
- + case gcvBROADCAST_GPU_COMMIT:
- + gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "COMMIT has arrived.");
- +
- + /* Add busy process DB. */
- + gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
- + 0,
- + gcvDB_IDLE,
- + gcvNULL, gcvNULL, 0));
- +
- + /* Put GPU ON. */
- + gcmkONERROR(
- + gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON_AUTO));
- + break;
- +
- + case gcvBROADCAST_GPU_STUCK:
- + gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_GPU_STUCK\n");
- +#if !gcdENABLE_RECOVERY
- + gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
- +#endif
- + gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
- + break;
- +
- + case gcvBROADCAST_AXI_BUS_ERROR:
- + gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_AXI_BUS_ERROR\n");
- + gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
- + gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
- + break;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_BroadcastHurry
- +**
- +** The GPU is running too slow.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to the gckOS object.
- +**
- +** gckHARDWARE Hardware
- +** Pointer to the gckHARDWARE object.
- +**
- +** gctUINT Urgency
- +** The higher the number, the higher the urgency to speed up the GPU.
- +** The maximum value is defined by the gcdDYNAMIC_EVENT_THRESHOLD.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_BroadcastHurry(
- + IN gckOS Os,
- + IN gckHARDWARE Hardware,
- + IN gctUINT Urgency
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Urgency=%u", Os, Hardware, Urgency);
- +
- + /* Do whatever you need to do to speed up the GPU now. */
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_BroadcastCalibrateSpeed
- +**
- +** Calibrate the speed of the GPU.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to the gckOS object.
- +**
- +** gckHARDWARE Hardware
- +** Pointer to the gckHARDWARE object.
- +**
- +** gctUINT Idle, Time
- +** Idle/Time will give the percentage the GPU is idle, so you can use
- +** this to calibrate the working point of the GPU.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_BroadcastCalibrateSpeed(
- + IN gckOS Os,
- + IN gckHARDWARE Hardware,
- + IN gctUINT Idle,
- + IN gctUINT Time
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Idle=%u Time=%u",
- + Os, Hardware, Idle, Time);
- +
- + /* Do whatever you need to do to callibrate the GPU speed. */
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +********************************** Semaphores **********************************
- +*******************************************************************************/
- +
- +/*******************************************************************************
- +**
- +** gckOS_CreateSemaphore
- +**
- +** Create a semaphore.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to the gckOS object.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * Semaphore
- +** Pointer to the variable that will receive the created semaphore.
- +*/
- +gceSTATUS
- +gckOS_CreateSemaphore(
- + IN gckOS Os,
- + OUT gctPOINTER * Semaphore
- + )
- +{
- + gceSTATUS status;
- + struct semaphore *sem = gcvNULL;
- +
- + gcmkHEADER_ARG("Os=0x%X", Os);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
- +
- + /* Allocate the semaphore structure. */
- + sem = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
- + if (sem == gcvNULL)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + /* Initialize the semaphore. */
- + sema_init(sem, 1);
- +
- + /* Return to caller. */
- + *Semaphore = (gctPOINTER) sem;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_AcquireSemaphore
- +**
- +** Acquire a semaphore.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to the gckOS object.
- +**
- +** gctPOINTER Semaphore
- +** Pointer to the semaphore thet needs to be acquired.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_AcquireSemaphore(
- + IN gckOS Os,
- + IN gctPOINTER Semaphore
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%08X Semaphore=0x%08X", Os, Semaphore);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
- +
- + /* Acquire the semaphore. */
- + if (down_interruptible((struct semaphore *) Semaphore))
- + {
- + gcmkONERROR(gcvSTATUS_INTERRUPTED);
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_TryAcquireSemaphore
- +**
- +** Try to acquire a semaphore.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to the gckOS object.
- +**
- +** gctPOINTER Semaphore
- +** Pointer to the semaphore thet needs to be acquired.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_TryAcquireSemaphore(
- + IN gckOS Os,
- + IN gctPOINTER Semaphore
- + )
- +{
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%x", Os);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
- +
- + /* Acquire the semaphore. */
- + if (down_trylock((struct semaphore *) Semaphore))
- + {
- + /* Timeout. */
- + status = gcvSTATUS_TIMEOUT;
- + gcmkFOOTER();
- + return status;
- + }
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_ReleaseSemaphore
- +**
- +** Release a previously acquired semaphore.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to the gckOS object.
- +**
- +** gctPOINTER Semaphore
- +** Pointer to the semaphore thet needs to be released.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_ReleaseSemaphore(
- + IN gckOS Os,
- + IN gctPOINTER Semaphore
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
- +
- + /* Release the semaphore. */
- + up((struct semaphore *) Semaphore);
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_DestroySemaphore
- +**
- +** Destroy a semaphore.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to the gckOS object.
- +**
- +** gctPOINTER Semaphore
- +** Pointer to the semaphore thet needs to be destroyed.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_DestroySemaphore(
- + IN gckOS Os,
- + IN gctPOINTER Semaphore
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
- +
- + /* Free the sempahore structure. */
- + kfree(Semaphore);
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_GetProcessID
- +**
- +** Get current process ID.
- +**
- +** INPUT:
- +**
- +** Nothing.
- +**
- +** OUTPUT:
- +**
- +** gctUINT32_PTR ProcessID
- +** Pointer to the variable that receives the process ID.
- +*/
- +gceSTATUS
- +gckOS_GetProcessID(
- + OUT gctUINT32_PTR ProcessID
- + )
- +{
- + /* Get process ID. */
- + if (ProcessID != gcvNULL)
- + {
- + *ProcessID = _GetProcessID();
- + }
- +
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_GetThreadID
- +**
- +** Get current thread ID.
- +**
- +** INPUT:
- +**
- +** Nothing.
- +**
- +** OUTPUT:
- +**
- +** gctUINT32_PTR ThreadID
- +** Pointer to the variable that receives the thread ID.
- +*/
- +gceSTATUS
- +gckOS_GetThreadID(
- + OUT gctUINT32_PTR ThreadID
- + )
- +{
- + /* Get thread ID. */
- + if (ThreadID != gcvNULL)
- + {
- + *ThreadID = _GetThreadID();
- + }
- +
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_SetGPUPower
- +**
- +** Set the power of the GPU on or off.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** gckCORE Core
- +** GPU whose power is set.
- +**
- +** gctBOOL Clock
- +** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
- +**
- +** gctBOOL Power
- +** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_SetGPUPower(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctBOOL Clock,
- + IN gctBOOL Power
- + )
- +{
- + struct clk *clk_3dcore = Os->device->clk_3d_core;
- + struct clk *clk_3dshader = Os->device->clk_3d_shader;
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
- + struct clk *clk_3d_axi = Os->device->clk_3d_axi;
- +#endif
- + struct clk *clk_2dcore = Os->device->clk_2d_core;
- + struct clk *clk_2d_axi = Os->device->clk_2d_axi;
- + struct clk *clk_vg_axi = Os->device->clk_vg_axi;
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- + int ret;
- +#endif
- +
- + gctBOOL oldClockState = gcvFALSE;
- + gctBOOL oldPowerState = gcvFALSE;
- +
- + gcmkHEADER_ARG("Os=0x%X Core=%d Clock=%d Power=%d", Os, Core, Clock, Power);
- +
- + if (Os->device->kernels[Core] != NULL)
- + {
- +#if gcdENABLE_VG
- + if (Core == gcvCORE_VG)
- + {
- + oldClockState = Os->device->kernels[Core]->vg->hardware->clockState;
- + oldPowerState = Os->device->kernels[Core]->vg->hardware->powerState;
- + }
- + else
- + {
- +#endif
- + oldClockState = Os->device->kernels[Core]->hardware->clockState;
- + oldPowerState = Os->device->kernels[Core]->hardware->powerState;
- +#if gcdENABLE_VG
- + }
- +#endif
- + }
- + if((Power == gcvTRUE) && (oldPowerState == gcvFALSE))
- + {
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- + if(!IS_ERR(Os->device->gpu_regulator)) {
- + ret = regulator_enable(Os->device->gpu_regulator);
- + if (ret != 0)
- + gckOS_Print("%s(%d): fail to enable pu regulator %d!\n",
- + __FUNCTION__, __LINE__, ret);
- + }
- +#else
- + imx_gpc_power_up_pu(true);
- +#endif
- +
- +#ifdef CONFIG_PM
- + pm_runtime_get_sync(Os->device->pmdev);
- +#endif
- + }
- +
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
- + if (Clock == gcvTRUE) {
- + if (oldClockState == gcvFALSE) {
- + switch (Core) {
- + case gcvCORE_MAJOR:
- + clk_enable(clk_3dcore);
- + if (cpu_is_mx6q())
- + clk_enable(clk_3dshader);
- + break;
- + case gcvCORE_2D:
- + clk_enable(clk_2dcore);
- + clk_enable(clk_2d_axi);
- + break;
- + case gcvCORE_VG:
- + clk_enable(clk_2dcore);
- + clk_enable(clk_vg_axi);
- + break;
- + default:
- + break;
- + }
- + }
- + } else {
- + if (oldClockState == gcvTRUE) {
- + switch (Core) {
- + case gcvCORE_MAJOR:
- + if (cpu_is_mx6q())
- + clk_disable(clk_3dshader);
- + clk_disable(clk_3dcore);
- + break;
- + case gcvCORE_2D:
- + clk_disable(clk_2dcore);
- + clk_disable(clk_2d_axi);
- + break;
- + case gcvCORE_VG:
- + clk_disable(clk_2dcore);
- + clk_disable(clk_vg_axi);
- + break;
- + default:
- + break;
- + }
- + }
- + }
- +#else
- + if (Clock == gcvTRUE) {
- + if (oldClockState == gcvFALSE) {
- + switch (Core) {
- + case gcvCORE_MAJOR:
- + clk_prepare_enable(clk_3dcore);
- + clk_prepare_enable(clk_3dshader);
- + clk_prepare_enable(clk_3d_axi);
- + break;
- + case gcvCORE_2D:
- + clk_prepare_enable(clk_2dcore);
- + clk_prepare_enable(clk_2d_axi);
- + break;
- + case gcvCORE_VG:
- + clk_prepare_enable(clk_2dcore);
- + clk_prepare_enable(clk_vg_axi);
- + break;
- + default:
- + break;
- + }
- + }
- + } else {
- + if (oldClockState == gcvTRUE) {
- + switch (Core) {
- + case gcvCORE_MAJOR:
- + clk_disable_unprepare(clk_3d_axi);
- + clk_disable_unprepare(clk_3dshader);
- + clk_disable_unprepare(clk_3dcore);
- + break;
- + case gcvCORE_2D:
- + clk_disable_unprepare(clk_2d_axi);
- + clk_disable_unprepare(clk_2dcore);
- + break;
- + case gcvCORE_VG:
- + clk_disable_unprepare(clk_vg_axi);
- + clk_disable_unprepare(clk_2dcore);
- + break;
- + default:
- + break;
- + }
- + }
- + }
- +#endif
- + if((Power == gcvFALSE) && (oldPowerState == gcvTRUE))
- + {
- +#ifdef CONFIG_PM
- + pm_runtime_put_sync(Os->device->pmdev);
- +#endif
- +
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- + if(!IS_ERR(Os->device->gpu_regulator))
- + regulator_disable(Os->device->gpu_regulator);
- +#else
- + imx_gpc_power_up_pu(false);
- +#endif
- +
- + }
- + /* TODO: Put your code here. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_ResetGPU
- +**
- +** Reset the GPU.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** gckCORE Core
- +** GPU whose power is set.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_ResetGPU(
- + IN gckOS Os,
- + IN gceCORE Core
- + )
- +{
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
- +#define SRC_SCR_OFFSET 0
- +#define BP_SRC_SCR_GPU3D_RST 1
- +#define BP_SRC_SCR_GPU2D_RST 4
- + void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR);
- + gctUINT32 bit_offset,val;
- +
- + gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
- +
- + if(Core == gcvCORE_MAJOR) {
- + bit_offset = BP_SRC_SCR_GPU3D_RST;
- + } else if((Core == gcvCORE_VG)
- + ||(Core == gcvCORE_2D)) {
- + bit_offset = BP_SRC_SCR_GPU2D_RST;
- + } else {
- + return gcvSTATUS_INVALID_CONFIG;
- + }
- + val = __raw_readl(src_base + SRC_SCR_OFFSET);
- + val &= ~(1 << (bit_offset));
- + val |= (1 << (bit_offset));
- + __raw_writel(val, src_base + SRC_SCR_OFFSET);
- +
- + while ((__raw_readl(src_base + SRC_SCR_OFFSET) &
- + (1 << (bit_offset))) != 0) {
- + }
- +
- + gcmkFOOTER_NO();
- +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
- + struct reset_control *rstc = Os->device->rstc[Core];
- + if (rstc)
- + reset_control_reset(rstc);
- +#else
- + imx_src_reset_gpu((int)Core);
- +#endif
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_PrepareGPUFrequency
- +**
- +** Prepare to set GPU frequency and voltage.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** gckCORE Core
- +** GPU whose frequency and voltage will be set.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_PrepareGPUFrequency(
- + IN gckOS Os,
- + IN gceCORE Core
- + )
- +{
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_FinishGPUFrequency
- +**
- +** Finish GPU frequency setting.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** gckCORE Core
- +** GPU whose frequency and voltage is set.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_FinishGPUFrequency(
- + IN gckOS Os,
- + IN gceCORE Core
- + )
- +{
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_QueryGPUFrequency
- +**
- +** Query the current frequency of the GPU.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** gckCORE Core
- +** GPU whose power is set.
- +**
- +** gctUINT32 * Frequency
- +** Pointer to a gctUINT32 to obtain current frequency, in MHz.
- +**
- +** gctUINT8 * Scale
- +** Pointer to a gctUINT8 to obtain current scale(1 - 64).
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_QueryGPUFrequency(
- + IN gckOS Os,
- + IN gceCORE Core,
- + OUT gctUINT32 * Frequency,
- + OUT gctUINT8 * Scale
- + )
- +{
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_SetGPUFrequency
- +**
- +** Set frequency and voltage of the GPU.
- +**
- +** 1. DVFS manager gives the target scale of full frequency, BSP must find
- +** a real frequency according to this scale and board's configure.
- +**
- +** 2. BSP should find a suitable voltage for this frequency.
- +**
- +** 3. BSP must make sure setting take effect before this function returns.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to a gckOS object.
- +**
- +** gckCORE Core
- +** GPU whose power is set.
- +**
- +** gctUINT8 Scale
- +** Target scale of full frequency, range is [1, 64]. 1 means 1/64 of
- +** full frequency and 64 means 64/64 of full frequency.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_SetGPUFrequency(
- + IN gckOS Os,
- + IN gceCORE Core,
- + IN gctUINT8 Scale
- + )
- +{
- + return gcvSTATUS_OK;
- +}
- +
- +/*----------------------------------------------------------------------------*/
- +/*----- Profile --------------------------------------------------------------*/
- +
- +gceSTATUS
- +gckOS_GetProfileTick(
- + OUT gctUINT64_PTR Tick
- + )
- +{
- + struct timespec time;
- +
- + ktime_get_ts(&time);
- +
- + *Tick = time.tv_nsec + time.tv_sec * 1000000000ULL;
- +
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckOS_QueryProfileTickRate(
- + OUT gctUINT64_PTR TickRate
- + )
- +{
- + struct timespec res;
- +
- + hrtimer_get_res(CLOCK_MONOTONIC, &res);
- +
- + *TickRate = res.tv_nsec + res.tv_sec * 1000000000ULL;
- +
- + return gcvSTATUS_OK;
- +}
- +
- +gctUINT32
- +gckOS_ProfileToMS(
- + IN gctUINT64 Ticks
- + )
- +{
- +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
- + return div_u64(Ticks, 1000000);
- +#else
- + gctUINT64 rem = Ticks;
- + gctUINT64 b = 1000000;
- + gctUINT64 res, d = 1;
- + gctUINT32 high = rem >> 32;
- +
- + /* Reduce the thing a bit first */
- + res = 0;
- + if (high >= 1000000)
- + {
- + high /= 1000000;
- + res = (gctUINT64) high << 32;
- + rem -= (gctUINT64) (high * 1000000) << 32;
- + }
- +
- + while (((gctINT64) b > 0) && (b < rem))
- + {
- + b <<= 1;
- + d <<= 1;
- + }
- +
- + do
- + {
- + if (rem >= b)
- + {
- + rem -= b;
- + res += d;
- + }
- +
- + b >>= 1;
- + d >>= 1;
- + }
- + while (d);
- +
- + return (gctUINT32) res;
- +#endif
- +}
- +
- +/******************************************************************************\
- +******************************* Signal Management ******************************
- +\******************************************************************************/
- +
- +#undef _GC_OBJ_ZONE
- +#define _GC_OBJ_ZONE gcvZONE_SIGNAL
- +
- +/*******************************************************************************
- +**
- +** gckOS_CreateSignal
- +**
- +** Create a new signal.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctBOOL ManualReset
- +** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
- +** order to set the signal to nonsignaled state.
- +** If set to gcvFALSE, the signal will automatically be set to
- +** nonsignaled state by gckOS_WaitSignal function.
- +**
- +** OUTPUT:
- +**
- +** gctSIGNAL * Signal
- +** Pointer to a variable receiving the created gctSIGNAL.
- +*/
- +gceSTATUS
- +gckOS_CreateSignal(
- + IN gckOS Os,
- + IN gctBOOL ManualReset,
- + OUT gctSIGNAL * Signal
- + )
- +{
- + gceSTATUS status;
- + gcsSIGNAL_PTR signal;
- +
- + gcmkHEADER_ARG("Os=0x%X ManualReset=%d", Os, ManualReset);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
- +
- + /* Create an event structure. */
- + signal = (gcsSIGNAL_PTR) kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL | gcdNOWARN);
- +
- + if (signal == gcvNULL)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + /* Save the process ID. */
- + signal->process = (gctHANDLE)(gctUINTPTR_T) _GetProcessID();
- + signal->manualReset = ManualReset;
- + signal->hardware = gcvNULL;
- + init_completion(&signal->obj);
- + atomic_set(&signal->ref, 1);
- +
- + gcmkONERROR(_AllocateIntegerId(&Os->signalDB, signal, &signal->id));
- +
- + *Signal = (gctSIGNAL)(gctUINTPTR_T)signal->id;
- +
- + gcmkFOOTER_ARG("*Signal=0x%X", *Signal);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (signal != gcvNULL)
- + {
- + kfree(signal);
- + }
- +
- + gcmkFOOTER_NO();
- + return status;
- +}
- +
- +gceSTATUS
- +gckOS_SignalQueryHardware(
- + IN gckOS Os,
- + IN gctSIGNAL Signal,
- + OUT gckHARDWARE * Hardware
- + )
- +{
- + gceSTATUS status;
- + gcsSIGNAL_PTR signal;
- +
- + gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
- +
- + gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
- +
- + *Hardware = signal->hardware;
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckOS_SignalSetHardware(
- + IN gckOS Os,
- + IN gctSIGNAL Signal,
- + IN gckHARDWARE Hardware
- + )
- +{
- + gceSTATUS status;
- + gcsSIGNAL_PTR signal;
- +
- + gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
- +
- + gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
- +
- + signal->hardware = Hardware;
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_DestroySignal
- +**
- +** Destroy a signal.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctSIGNAL Signal
- +** Pointer to the gctSIGNAL.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_DestroySignal(
- + IN gckOS Os,
- + IN gctSIGNAL Signal
- + )
- +{
- + gceSTATUS status;
- + gcsSIGNAL_PTR signal;
- + gctBOOL acquired = gcvFALSE;
- +
- + gcmkHEADER_ARG("Os=0x%X Signal=0x%X", Os, Signal);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
- +
- + gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
- +
- + gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
- +
- + if (atomic_dec_and_test(&signal->ref))
- + {
- + gcmkVERIFY_OK(_DestroyIntegerId(&Os->signalDB, signal->id));
- +
- + /* Free the sgianl. */
- + kfree(signal);
- + }
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
- + acquired = gcvFALSE;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_Signal
- +**
- +** Set a state of the specified signal.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctSIGNAL Signal
- +** Pointer to the gctSIGNAL.
- +**
- +** gctBOOL State
- +** If gcvTRUE, the signal will be set to signaled state.
- +** If gcvFALSE, the signal will be set to nonsignaled state.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_Signal(
- + IN gckOS Os,
- + IN gctSIGNAL Signal,
- + IN gctBOOL State
- + )
- +{
- + gceSTATUS status;
- + gcsSIGNAL_PTR signal;
- + gctBOOL acquired = gcvFALSE;
- +
- + gcmkHEADER_ARG("Os=0x%X Signal=0x%X State=%d", Os, Signal, State);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
- +
- + gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
- +
- + gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
- +
- + if (State)
- + {
- + /* unbind the signal from hardware. */
- + signal->hardware = gcvNULL;
- +
- + /* Set the event to a signaled state. */
- + complete(&signal->obj);
- + }
- + else
- + {
- + /* Set the event to an unsignaled state. */
- + reinit_completion(&signal->obj);
- + }
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
- + acquired = gcvFALSE;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +#if gcdENABLE_VG
- +gceSTATUS
- +gckOS_SetSignalVG(
- + IN gckOS Os,
- + IN gctHANDLE Process,
- + IN gctSIGNAL Signal
- + )
- +{
- + gceSTATUS status;
- + gctINT result;
- + struct task_struct * userTask;
- + struct siginfo info;
- +
- + userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
- +
- + if (userTask != gcvNULL)
- + {
- + info.si_signo = 48;
- + info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
- + info.si_pid = 0;
- + info.si_uid = 0;
- + info.si_ptr = (gctPOINTER) Signal;
- +
- + /* Signals with numbers between 32 and 63 are real-time,
- + send a real-time signal to the user process. */
- + result = send_sig_info(48, &info, userTask);
- +
- + printk("gckOS_SetSignalVG:0x%x\n", result);
- + /* Error? */
- + if (result < 0)
- + {
- + status = gcvSTATUS_GENERIC_IO;
- +
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): an error has occurred.\n",
- + __FUNCTION__, __LINE__
- + );
- + }
- + else
- + {
- + status = gcvSTATUS_OK;
- + }
- + }
- + else
- + {
- + status = gcvSTATUS_GENERIC_IO;
- +
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): an error has occurred.\n",
- + __FUNCTION__, __LINE__
- + );
- + }
- +
- + /* Return status. */
- + return status;
- +}
- +#endif
- +
- +/*******************************************************************************
- +**
- +** gckOS_UserSignal
- +**
- +** Set the specified signal which is owned by a process to signaled state.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctSIGNAL Signal
- +** Pointer to the gctSIGNAL.
- +**
- +** gctHANDLE Process
- +** Handle of process owning the signal.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_UserSignal(
- + IN gckOS Os,
- + IN gctSIGNAL Signal,
- + IN gctHANDLE Process
- + )
- +{
- + gceSTATUS status;
- + gctSIGNAL signal;
- +
- + gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=%d",
- + Os, Signal, (gctINT32)(gctUINTPTR_T)Process);
- +
- + /* Map the signal into kernel space. */
- + gcmkONERROR(gckOS_MapSignal(Os, Signal, Process, &signal));
- +
- + /* Signal. */
- + status = gckOS_Signal(Os, signal, gcvTRUE);
- +
- + /* Unmap the signal */
- + gcmkVERIFY_OK(gckOS_UnmapSignal(Os, Signal));
- +
- + gcmkFOOTER();
- + return status;
- +
- +OnError:
- + /* Return the status. */
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_WaitSignal
- +**
- +** Wait for a signal to become signaled.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctSIGNAL Signal
- +** Pointer to the gctSIGNAL.
- +**
- +** gctUINT32 Wait
- +** Number of milliseconds to wait.
- +** Pass the value of gcvINFINITE for an infinite wait.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_WaitSignal(
- + IN gckOS Os,
- + IN gctSIGNAL Signal,
- + IN gctUINT32 Wait
- + )
- +{
- + gceSTATUS status = gcvSTATUS_OK;
- + gcsSIGNAL_PTR signal;
- +
- + gcmkHEADER_ARG("Os=0x%X Signal=0x%X Wait=0x%08X", Os, Signal, Wait);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
- +
- + gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
- +
- + gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
- +
- + might_sleep();
- +
- + spin_lock_irq(&signal->obj.wait.lock);
- +
- + if (signal->obj.done)
- + {
- + if (!signal->manualReset)
- + {
- + signal->obj.done = 0;
- + }
- +
- + status = gcvSTATUS_OK;
- + }
- + else if (Wait == 0)
- + {
- + status = gcvSTATUS_TIMEOUT;
- + }
- + else
- + {
- + /* Convert wait to milliseconds. */
- +#if gcdDETECT_TIMEOUT
- + gctINT timeout = (Wait == gcvINFINITE)
- + ? gcdINFINITE_TIMEOUT * HZ / 1000
- + : Wait * HZ / 1000;
- +
- + gctUINT complained = 0;
- +#else
- + gctINT timeout = (Wait == gcvINFINITE)
- + ? MAX_SCHEDULE_TIMEOUT
- + : Wait * HZ / 1000;
- +#endif
- +
- + DECLARE_WAITQUEUE(wait, current);
- + wait.flags |= WQ_FLAG_EXCLUSIVE;
- + __add_wait_queue_tail(&signal->obj.wait, &wait);
- +
- + while (gcvTRUE)
- + {
- + if (signal_pending(current))
- + {
- + /* Interrupt received. */
- + status = gcvSTATUS_INTERRUPTED;
- + break;
- + }
- +
- + __set_current_state(TASK_INTERRUPTIBLE);
- + spin_unlock_irq(&signal->obj.wait.lock);
- + timeout = schedule_timeout(timeout);
- + spin_lock_irq(&signal->obj.wait.lock);
- +
- + if (signal->obj.done)
- + {
- + if (!signal->manualReset)
- + {
- + signal->obj.done = 0;
- + }
- +
- + status = gcvSTATUS_OK;
- + break;
- + }
- +
- +#if gcdDETECT_TIMEOUT
- + if ((Wait == gcvINFINITE) && (timeout == 0))
- + {
- + gctUINT32 dmaAddress1, dmaAddress2;
- + gctUINT32 dmaState1, dmaState2;
- +
- + dmaState1 = dmaState2 =
- + dmaAddress1 = dmaAddress2 = 0;
- +
- + /* Verify whether DMA is running. */
- + gcmkVERIFY_OK(_VerifyDMA(
- + Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
- + ));
- +
- +#if gcdDETECT_DMA_ADDRESS
- + /* Dump only if DMA appears stuck. */
- + if (
- + (dmaAddress1 == dmaAddress2)
- +#if gcdDETECT_DMA_STATE
- + && (dmaState1 == dmaState2)
- +#endif
- + )
- +#endif
- + {
- + /* Increment complain count. */
- + complained += 1;
- +
- + gcmkVERIFY_OK(_DumpGPUState(Os, gcvCORE_MAJOR));
- +
- + gcmkPRINT(
- + "%s(%d): signal 0x%X; forced message flush (%d).",
- + __FUNCTION__, __LINE__, Signal, complained
- + );
- +
- + /* Flush the debug cache. */
- + gcmkDEBUGFLUSH(dmaAddress2);
- + }
- +
- + /* Reset timeout. */
- + timeout = gcdINFINITE_TIMEOUT * HZ / 1000;
- + }
- +#endif
- +
- + if (timeout == 0)
- + {
- +
- + status = gcvSTATUS_TIMEOUT;
- + break;
- + }
- + }
- +
- + __remove_wait_queue(&signal->obj.wait, &wait);
- +
- +#if gcdDETECT_TIMEOUT
- + if (complained)
- + {
- + gcmkPRINT(
- + "%s(%d): signal=0x%X; waiting done; status=%d",
- + __FUNCTION__, __LINE__, Signal, status
- + );
- + }
- +#endif
- + }
- +
- + spin_unlock_irq(&signal->obj.wait.lock);
- +
- +OnError:
- + /* Return status. */
- + gcmkFOOTER_ARG("Signal=0x%X status=%d", Signal, status);
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_MapSignal
- +**
- +** Map a signal in to the current process space.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctSIGNAL Signal
- +** Pointer to tha gctSIGNAL to map.
- +**
- +** gctHANDLE Process
- +** Handle of process owning the signal.
- +**
- +** OUTPUT:
- +**
- +** gctSIGNAL * MappedSignal
- +** Pointer to a variable receiving the mapped gctSIGNAL.
- +*/
- +gceSTATUS
- +gckOS_MapSignal(
- + IN gckOS Os,
- + IN gctSIGNAL Signal,
- + IN gctHANDLE Process,
- + OUT gctSIGNAL * MappedSignal
- + )
- +{
- + gceSTATUS status;
- + gcsSIGNAL_PTR signal;
- + gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=0x%X", Os, Signal, Process);
- +
- + gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
- + gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
- +
- + gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
- +
- + if(atomic_inc_return(&signal->ref) <= 1)
- + {
- + /* The previous value is 0, it has been deleted. */
- + gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
- + }
- +
- + *MappedSignal = (gctSIGNAL) Signal;
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*MappedSignal=0x%X", *MappedSignal);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER_NO();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_UnmapSignal
- +**
- +** Unmap a signal .
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctSIGNAL Signal
- +** Pointer to that gctSIGNAL mapped.
- +*/
- +gceSTATUS
- +gckOS_UnmapSignal(
- + IN gckOS Os,
- + IN gctSIGNAL Signal
- + )
- +{
- + return gckOS_DestroySignal(Os, Signal);
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_CreateUserSignal
- +**
- +** Create a new signal to be used in the user space.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctBOOL ManualReset
- +** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
- +** order to set the signal to nonsignaled state.
- +** If set to gcvFALSE, the signal will automatically be set to
- +** nonsignaled state by gckOS_WaitSignal function.
- +**
- +** OUTPUT:
- +**
- +** gctINT * SignalID
- +** Pointer to a variable receiving the created signal's ID.
- +*/
- +gceSTATUS
- +gckOS_CreateUserSignal(
- + IN gckOS Os,
- + IN gctBOOL ManualReset,
- + OUT gctINT * SignalID
- + )
- +{
- + gceSTATUS status;
- + gctSIZE_T signal;
- +
- + /* Create a new signal. */
- + status = gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal);
- + *SignalID = (gctINT) signal;
- +
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_DestroyUserSignal
- +**
- +** Destroy a signal to be used in the user space.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctINT SignalID
- +** The signal's ID.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_DestroyUserSignal(
- + IN gckOS Os,
- + IN gctINT SignalID
- + )
- +{
- + return gckOS_DestroySignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID);
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_WaitUserSignal
- +**
- +** Wait for a signal used in the user mode to become signaled.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctINT SignalID
- +** Signal ID.
- +**
- +** gctUINT32 Wait
- +** Number of milliseconds to wait.
- +** Pass the value of gcvINFINITE for an infinite wait.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_WaitUserSignal(
- + IN gckOS Os,
- + IN gctINT SignalID,
- + IN gctUINT32 Wait
- + )
- +{
- + return gckOS_WaitSignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, Wait);
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_SignalUserSignal
- +**
- +** Set a state of the specified signal to be used in the user space.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to an gckOS object.
- +**
- +** gctINT SignalID
- +** SignalID.
- +**
- +** gctBOOL State
- +** If gcvTRUE, the signal will be set to signaled state.
- +** If gcvFALSE, the signal will be set to nonsignaled state.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_SignalUserSignal(
- + IN gckOS Os,
- + IN gctINT SignalID,
- + IN gctBOOL State
- + )
- +{
- + return gckOS_Signal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, State);
- +}
- +
- +#if gcdENABLE_VG
- +gceSTATUS
- +gckOS_CreateSemaphoreVG(
- + IN gckOS Os,
- + OUT gctSEMAPHORE * Semaphore
- + )
- +{
- + gceSTATUS status;
- + struct semaphore * newSemaphore;
- +
- + gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
- +
- + do
- + {
- + /* Allocate the semaphore structure. */
- + newSemaphore = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
- + if (newSemaphore == gcvNULL)
- + {
- + gcmkERR_BREAK(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + /* Initialize the semaphore. */
- + sema_init(newSemaphore, 0);
- +
- + /* Set the handle. */
- + * Semaphore = (gctSEMAPHORE) newSemaphore;
- +
- + /* Success. */
- + status = gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + gcmkFOOTER();
- + /* Return the status. */
- + return status;
- +}
- +
- +
- +gceSTATUS
- +gckOS_IncrementSemaphore(
- + IN gckOS Os,
- + IN gctSEMAPHORE Semaphore
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
- +
- + /* Increment the semaphore's count. */
- + up((struct semaphore *) Semaphore);
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckOS_DecrementSemaphore(
- + IN gckOS Os,
- + IN gctSEMAPHORE Semaphore
- + )
- +{
- + gceSTATUS status;
- + gctINT result;
- +
- + gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
- +
- + do
- + {
- + /* Decrement the semaphore's count. If the count is zero, wait
- + until it gets incremented. */
- + result = down_interruptible((struct semaphore *) Semaphore);
- +
- + /* Signal received? */
- + if (result != 0)
- + {
- + status = gcvSTATUS_TERMINATE;
- + break;
- + }
- +
- + /* Success. */
- + status = gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + gcmkFOOTER();
- + /* Return the status. */
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_SetSignal
- +**
- +** Set the specified signal to signaled state.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to the gckOS object.
- +**
- +** gctHANDLE Process
- +** Handle of process owning the signal.
- +**
- +** gctSIGNAL Signal
- +** Pointer to the gctSIGNAL.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_SetSignal(
- + IN gckOS Os,
- + IN gctHANDLE Process,
- + IN gctSIGNAL Signal
- + )
- +{
- + gceSTATUS status;
- + gctINT result;
- + struct task_struct * userTask;
- + struct siginfo info;
- +
- + userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
- +
- + if (userTask != gcvNULL)
- + {
- + info.si_signo = 48;
- + info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
- + info.si_pid = 0;
- + info.si_uid = 0;
- + info.si_ptr = (gctPOINTER) Signal;
- +
- + /* Signals with numbers between 32 and 63 are real-time,
- + send a real-time signal to the user process. */
- + result = send_sig_info(48, &info, userTask);
- +
- + /* Error? */
- + if (result < 0)
- + {
- + status = gcvSTATUS_GENERIC_IO;
- +
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): an error has occurred.\n",
- + __FUNCTION__, __LINE__
- + );
- + }
- + else
- + {
- + status = gcvSTATUS_OK;
- + }
- + }
- + else
- + {
- + status = gcvSTATUS_GENERIC_IO;
- +
- + gcmkTRACE(
- + gcvLEVEL_ERROR,
- + "%s(%d): an error has occurred.\n",
- + __FUNCTION__, __LINE__
- + );
- + }
- +
- + /* Return status. */
- + return status;
- +}
- +
- +/******************************************************************************\
- +******************************** Thread Object *********************************
- +\******************************************************************************/
- +
- +gceSTATUS
- +gckOS_StartThread(
- + IN gckOS Os,
- + IN gctTHREADFUNC ThreadFunction,
- + IN gctPOINTER ThreadParameter,
- + OUT gctTHREAD * Thread
- + )
- +{
- + gceSTATUS status;
- + struct task_struct * thread;
- +
- + gcmkHEADER_ARG("Os=0x%X ", Os);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(ThreadFunction != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
- +
- + do
- + {
- + /* Create the thread. */
- + thread = kthread_create(
- + ThreadFunction,
- + ThreadParameter,
- + "Vivante Kernel Thread"
- + );
- +
- + /* Failed? */
- + if (IS_ERR(thread))
- + {
- + status = gcvSTATUS_GENERIC_IO;
- + break;
- + }
- +
- + /* Start the thread. */
- + wake_up_process(thread);
- +
- + /* Set the thread handle. */
- + * Thread = (gctTHREAD) thread;
- +
- + /* Success. */
- + status = gcvSTATUS_OK;
- + }
- + while (gcvFALSE);
- +
- + gcmkFOOTER();
- + /* Return the status. */
- + return status;
- +}
- +
- +gceSTATUS
- +gckOS_StopThread(
- + IN gckOS Os,
- + IN gctTHREAD Thread
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
- +
- + /* Thread should have already been enabled to terminate. */
- + kthread_stop((struct task_struct *) Thread);
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckOS_VerifyThread(
- + IN gckOS Os,
- + IN gctTHREAD Thread
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
- +
- + gcmkFOOTER_NO();
- + /* Success. */
- + return gcvSTATUS_OK;
- +}
- +#endif
- +
- +/******************************************************************************\
- +******************************** Software Timer ********************************
- +\******************************************************************************/
- +
- +void
- +_TimerFunction(
- + struct work_struct * work
- + )
- +{
- + gcsOSTIMER_PTR timer = (gcsOSTIMER_PTR)work;
- +
- + gctTIMERFUNCTION function = timer->function;
- +
- + function(timer->data);
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_CreateTimer
- +**
- +** Create a software timer.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to the gckOS object.
- +**
- +** gctTIMERFUNCTION Function.
- +** Pointer to a call back function which will be called when timer is
- +** expired.
- +**
- +** gctPOINTER Data.
- +** Private data which will be passed to call back function.
- +**
- +** OUTPUT:
- +**
- +** gctPOINTER * Timer
- +** Pointer to a variable receiving the created timer.
- +*/
- +gceSTATUS
- +gckOS_CreateTimer(
- + IN gckOS Os,
- + IN gctTIMERFUNCTION Function,
- + IN gctPOINTER Data,
- + OUT gctPOINTER * Timer
- + )
- +{
- + gceSTATUS status;
- + gcsOSTIMER_PTR pointer;
- + gcmkHEADER_ARG("Os=0x%X Function=0x%X Data=0x%X", Os, Function, Data);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
- +
- + gcmkONERROR(gckOS_Allocate(Os, sizeof(gcsOSTIMER), (gctPOINTER)&pointer));
- +
- + pointer->function = Function;
- + pointer->data = Data;
- +
- + INIT_DELAYED_WORK(&pointer->work, _TimerFunction);
- +
- + *Timer = pointer;
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_DestroyTimer
- +**
- +** Destory a software timer.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to the gckOS object.
- +**
- +** gctPOINTER Timer
- +** Pointer to the timer to be destoryed.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_DestroyTimer(
- + IN gckOS Os,
- + IN gctPOINTER Timer
- + )
- +{
- + gcsOSTIMER_PTR timer;
- + gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
- +
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
- +
- + timer = (gcsOSTIMER_PTR)Timer;
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
- + cancel_delayed_work_sync(&timer->work);
- +#else
- + cancel_delayed_work(&timer->work);
- + flush_workqueue(Os->workqueue);
- +#endif
- +
- + gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, Timer));
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_StartTimer
- +**
- +** Schedule a software timer.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to the gckOS object.
- +**
- +** gctPOINTER Timer
- +** Pointer to the timer to be scheduled.
- +**
- +** gctUINT32 Delay
- +** Delay in milliseconds.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_StartTimer(
- + IN gckOS Os,
- + IN gctPOINTER Timer,
- + IN gctUINT32 Delay
- + )
- +{
- + gcsOSTIMER_PTR timer;
- +
- + gcmkHEADER_ARG("Os=0x%X Timer=0x%X Delay=%u", Os, Timer, Delay);
- +
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
- + gcmkVERIFY_ARGUMENT(Delay != 0);
- +
- + timer = (gcsOSTIMER_PTR)Timer;
- +
- + if (unlikely(delayed_work_pending(&timer->work)))
- + {
- + if (unlikely(!cancel_delayed_work(&timer->work)))
- + {
- + cancel_work_sync(&timer->work.work);
- +
- + if (unlikely(delayed_work_pending(&timer->work)))
- + {
- + gckOS_Print("gckOS_StartTimer error, the pending worker cannot complete!!!! \n");
- +
- + return gcvSTATUS_INVALID_REQUEST;
- + }
- + }
- + }
- +
- + queue_delayed_work(Os->workqueue, &timer->work, msecs_to_jiffies(Delay));
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +/*******************************************************************************
- +**
- +** gckOS_StopTimer
- +**
- +** Cancel a unscheduled timer.
- +**
- +** INPUT:
- +**
- +** gckOS Os
- +** Pointer to the gckOS object.
- +**
- +** gctPOINTER Timer
- +** Pointer to the timer to be cancel.
- +**
- +** OUTPUT:
- +**
- +** Nothing.
- +*/
- +gceSTATUS
- +gckOS_StopTimer(
- + IN gckOS Os,
- + IN gctPOINTER Timer
- + )
- +{
- + gcsOSTIMER_PTR timer;
- + gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
- +
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
- +
- + timer = (gcsOSTIMER_PTR)Timer;
- +
- + cancel_delayed_work(&timer->work);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +
- +gceSTATUS
- +gckOS_DumpCallStack(
- + IN gckOS Os
- + )
- +{
- + gcmkHEADER_ARG("Os=0x%X", Os);
- +
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- +
- + dump_stack();
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +}
- +
- +
- +gceSTATUS
- +gckOS_GetProcessNameByPid(
- + IN gctINT Pid,
- + IN gctSIZE_T Length,
- + OUT gctUINT8_PTR String
- + )
- +{
- + struct task_struct *task;
- +
- + /* Get the task_struct of the task with pid. */
- + rcu_read_lock();
- +
- + task = FIND_TASK_BY_PID(Pid);
- +
- + if (task == gcvNULL)
- + {
- + rcu_read_unlock();
- + return gcvSTATUS_NOT_FOUND;
- + }
- +
- + /* Get name of process. */
- + strncpy(String, task->comm, Length);
- +
- + rcu_read_unlock();
- +
- + return gcvSTATUS_OK;
- +}
- +
- +#if gcdANDROID_NATIVE_FENCE_SYNC
- +
- +gceSTATUS
- +gckOS_CreateSyncPoint(
- + IN gckOS Os,
- + OUT gctSYNC_POINT * SyncPoint
- + )
- +{
- + gceSTATUS status;
- + gcsSYNC_POINT_PTR syncPoint;
- +
- + gcmkHEADER_ARG("Os=0x%X", Os);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- +
- + /* Create an sync point structure. */
- + syncPoint = (gcsSYNC_POINT_PTR) kmalloc(
- + sizeof(gcsSYNC_POINT), GFP_KERNEL | gcdNOWARN);
- +
- + if (syncPoint == gcvNULL)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + /* Initialize the sync point. */
- + atomic_set(&syncPoint->ref, 1);
- + atomic_set(&syncPoint->state, 0);
- +
- + gcmkONERROR(_AllocateIntegerId(&Os->syncPointDB, syncPoint, &syncPoint->id));
- +
- + *SyncPoint = (gctSYNC_POINT)(gctUINTPTR_T)syncPoint->id;
- +
- + gcmkFOOTER_ARG("*SyncPonint=%d", syncPoint->id);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (syncPoint != gcvNULL)
- + {
- + kfree(syncPoint);
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckOS_ReferenceSyncPoint(
- + IN gckOS Os,
- + IN gctSYNC_POINT SyncPoint
- + )
- +{
- + gceSTATUS status;
- + gcsSYNC_POINT_PTR syncPoint;
- +
- + gcmkHEADER_ARG("Os=0x%X", Os);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
- +
- + gcmkONERROR(
- + _QueryIntegerId(&Os->syncPointDB,
- + (gctUINT32)(gctUINTPTR_T)SyncPoint,
- + (gctPOINTER)&syncPoint));
- +
- + /* Initialize the sync point. */
- + atomic_inc(&syncPoint->ref);
- +
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckOS_DestroySyncPoint(
- + IN gckOS Os,
- + IN gctSYNC_POINT SyncPoint
- + )
- +{
- + gceSTATUS status;
- + gcsSYNC_POINT_PTR syncPoint;
- + gctBOOL acquired = gcvFALSE;
- +
- + gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
- +
- + gcmkONERROR(gckOS_AcquireMutex(Os, Os->syncPointMutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + gcmkONERROR(
- + _QueryIntegerId(&Os->syncPointDB,
- + (gctUINT32)(gctUINTPTR_T)SyncPoint,
- + (gctPOINTER)&syncPoint));
- +
- + gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
- +
- + if (atomic_dec_and_test(&syncPoint->ref))
- + {
- + gcmkVERIFY_OK(_DestroyIntegerId(&Os->syncPointDB, syncPoint->id));
- +
- + /* Free the sgianl. */
- + syncPoint->timeline = gcvNULL;
- + kfree(syncPoint);
- + }
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
- + acquired = gcvFALSE;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckOS_SignalSyncPoint(
- + IN gckOS Os,
- + IN gctSYNC_POINT SyncPoint
- + )
- +{
- + gceSTATUS status;
- + gcsSYNC_POINT_PTR syncPoint;
- + gctBOOL acquired = gcvFALSE;
- +
- + gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
- +
- + gcmkONERROR(gckOS_AcquireMutex(Os, Os->syncPointMutex, gcvINFINITE));
- + acquired = gcvTRUE;
- +
- + gcmkONERROR(
- + _QueryIntegerId(&Os->syncPointDB,
- + (gctUINT32)(gctUINTPTR_T)SyncPoint,
- + (gctPOINTER)&syncPoint));
- +
- + gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
- +
- + /* Get state. */
- + atomic_set(&syncPoint->state, gcvTRUE);
- +
- + /* Signal timeline. */
- + if (syncPoint->timeline)
- + {
- + sync_timeline_signal(syncPoint->timeline);
- + }
- +
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
- + acquired = gcvFALSE;
- +
- + /* Success. */
- + gcmkFOOTER_NO();
- + return gcvSTATUS_OK;
- +
- +OnError:
- + if (acquired)
- + {
- + /* Release the mutex. */
- + gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckOS_QuerySyncPoint(
- + IN gckOS Os,
- + IN gctSYNC_POINT SyncPoint,
- + OUT gctBOOL_PTR State
- + )
- +{
- + gceSTATUS status;
- + gcsSYNC_POINT_PTR syncPoint;
- +
- + gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
- +
- + /* Verify the arguments. */
- + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- + gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
- +
- + gcmkONERROR(
- + _QueryIntegerId(&Os->syncPointDB,
- + (gctUINT32)(gctUINTPTR_T)SyncPoint,
- + (gctPOINTER)&syncPoint));
- +
- + gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
- +
- + /* Get state. */
- + *State = atomic_read(&syncPoint->state);
- +
- + /* Success. */
- + gcmkFOOTER_ARG("*State=%d", *State);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + gcmkFOOTER();
- + return status;
- +}
- +
- +gceSTATUS
- +gckOS_CreateSyncTimeline(
- + IN gckOS Os,
- + OUT gctHANDLE * Timeline
- + )
- +{
- + struct viv_sync_timeline * timeline;
- +
- + /* Create viv sync timeline. */
- + timeline = viv_sync_timeline_create("viv timeline", Os);
- +
- + if (timeline == gcvNULL)
- + {
- + /* Out of memory. */
- + return gcvSTATUS_OUT_OF_MEMORY;
- + }
- +
- + *Timeline = (gctHANDLE) timeline;
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckOS_DestroySyncTimeline(
- + IN gckOS Os,
- + IN gctHANDLE Timeline
- + )
- +{
- + struct viv_sync_timeline * timeline;
- + gcmkASSERT(Timeline != gcvNULL);
- +
- + /* Destroy timeline. */
- + timeline = (struct viv_sync_timeline *) Timeline;
- + sync_timeline_destroy(&timeline->obj);
- +
- + return gcvSTATUS_OK;
- +}
- +
- +gceSTATUS
- +gckOS_CreateNativeFence(
- + IN gckOS Os,
- + IN gctHANDLE Timeline,
- + IN gctSYNC_POINT SyncPoint,
- + OUT gctINT * FenceFD
- + )
- +{
- + int fd = -1;
- + struct viv_sync_timeline *timeline;
- + struct sync_pt * pt = gcvNULL;
- + struct sync_fence * fence;
- + char name[32];
- + gcsSYNC_POINT_PTR syncPoint;
- + gceSTATUS status;
- +
- + gcmkHEADER_ARG("Os=0x%X Timeline=0x%X SyncPoint=%d",
- + Os, Timeline, (gctUINT)(gctUINTPTR_T)SyncPoint);
- +
- + gcmkONERROR(
- + _QueryIntegerId(&Os->syncPointDB,
- + (gctUINT32)(gctUINTPTR_T)SyncPoint,
- + (gctPOINTER)&syncPoint));
- +
- + /* Cast timeline. */
- + timeline = (struct viv_sync_timeline *) Timeline;
- +
- + fd = get_unused_fd();
- +
- + if (fd < 0)
- + {
- + /* Out of resources. */
- + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
- + }
- +
- + /* Create viv_sync_pt. */
- + pt = viv_sync_pt_create(timeline, SyncPoint);
- +
- + if (pt == gcvNULL)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + /* Reference sync_timeline. */
- + syncPoint->timeline = &timeline->obj;
- +
- + /* Build fence name. */
- + snprintf(name, 32, "viv sync_fence-%u", (gctUINT)(gctUINTPTR_T)SyncPoint);
- +
- + /* Create sync_fence. */
- + fence = sync_fence_create(name, pt);
- +
- + if (fence == NULL)
- + {
- + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
- + }
- +
- + /* Install fence to fd. */
- + sync_fence_install(fence, fd);
- +
- + *FenceFD = fd;
- + gcmkFOOTER_ARG("*FenceFD=%d", fd);
- + return gcvSTATUS_OK;
- +
- +OnError:
- + /* Error roll back. */
- + if (pt)
- + {
- + sync_pt_free(pt);
- + }
- +
- + if (fd > 0)
- + {
- + put_unused_fd(fd);
- + }
- +
- + gcmkFOOTER();
- + return status;
- +}
- +#endif
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h 2015-03-08 14:27:37.657684501 -0500
- @@ -0,0 +1,83 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_kernel_os_h_
- +#define __gc_hal_kernel_os_h_
- +
- +typedef struct _LINUX_MDL_MAP
- +{
- + gctINT pid;
- + gctPOINTER vmaAddr;
- + gctUINT32 count;
- + struct vm_area_struct * vma;
- + struct _LINUX_MDL_MAP * next;
- +}
- +LINUX_MDL_MAP;
- +
- +typedef struct _LINUX_MDL_MAP * PLINUX_MDL_MAP;
- +
- +typedef struct _LINUX_MDL
- +{
- + gctINT pid;
- + char * addr;
- +
- + union _pages
- + {
- + /* Pointer to a array of pages. */
- + struct page * contiguousPages;
- + /* Pointer to a array of pointers to page. */
- + struct page ** nonContiguousPages;
- + }
- + u;
- +
- +#ifdef NO_DMA_COHERENT
- + gctPOINTER kaddr;
- +#endif /* NO_DMA_COHERENT */
- +
- + gctINT numPages;
- + gctINT pagedMem;
- + gctBOOL contiguous;
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
- + gctBOOL exact;
- +#endif
- + dma_addr_t dmaHandle;
- + PLINUX_MDL_MAP maps;
- + struct _LINUX_MDL * prev;
- + struct _LINUX_MDL * next;
- +}
- +LINUX_MDL, *PLINUX_MDL;
- +
- +extern PLINUX_MDL_MAP
- +FindMdlMap(
- + IN PLINUX_MDL Mdl,
- + IN gctINT PID
- + );
- +
- +typedef struct _DRIVER_ARGS
- +{
- + gctUINT64 InputBuffer;
- + gctUINT64 InputBufferSize;
- + gctUINT64 OutputBuffer;
- + gctUINT64 OutputBufferSize;
- +}
- +DRIVER_ARGS;
- +
- +#endif /* __gc_hal_kernel_os_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c 2015-03-08 14:27:37.657684501 -0500
- @@ -0,0 +1,174 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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.
- +*
- +*****************************************************************************/
- +
- +
- +#include <linux/kernel.h>
- +#include <linux/file.h>
- +#include <linux/fs.h>
- +#include <linux/miscdevice.h>
- +#include <linux/module.h>
- +#include <linux/syscalls.h>
- +#include <linux/uaccess.h>
- +
- +#include "gc_hal_kernel_sync.h"
- +
- +#if gcdANDROID_NATIVE_FENCE_SYNC
- +
- +static struct sync_pt *
- +viv_sync_pt_dup(
- + struct sync_pt * sync_pt
- + )
- +{
- + gceSTATUS status;
- + struct viv_sync_pt *pt;
- + struct viv_sync_pt *src;
- + struct viv_sync_timeline *obj;
- +
- + src = (struct viv_sync_pt *) sync_pt;
- + obj = (struct viv_sync_timeline *) sync_pt->parent;
- +
- + /* Create the new sync_pt. */
- + pt = (struct viv_sync_pt *)
- + sync_pt_create(&obj->obj, sizeof(struct viv_sync_pt));
- +
- + pt->stamp = src->stamp;
- + pt->sync = src->sync;
- +
- + /* Reference sync point. */
- + status = gckOS_ReferenceSyncPoint(obj->os, pt->sync);
- +
- + if (gcmIS_ERROR(status))
- + {
- + sync_pt_free((struct sync_pt *)pt);
- + return NULL;
- + }
- +
- + return (struct sync_pt *)pt;
- +}
- +
- +static int
- +viv_sync_pt_has_signaled(
- + struct sync_pt * sync_pt
- + )
- +{
- + gceSTATUS status;
- + gctBOOL state;
- + struct viv_sync_pt * pt;
- + struct viv_sync_timeline * obj;
- +
- + pt = (struct viv_sync_pt *)sync_pt;
- + obj = (struct viv_sync_timeline *)sync_pt->parent;
- +
- + status = gckOS_QuerySyncPoint(obj->os, pt->sync, &state);
- +
- + if (gcmIS_ERROR(status))
- + {
- + /* Error. */
- + return -1;
- + }
- +
- + return state;
- +}
- +
- +static int
- +viv_sync_pt_compare(
- + struct sync_pt * a,
- + struct sync_pt * b
- + )
- +{
- + int ret;
- + struct viv_sync_pt * pt1 = (struct viv_sync_pt *) a;
- + struct viv_sync_pt * pt2 = (struct viv_sync_pt *) b;
- +
- + ret = (pt1->stamp < pt2->stamp) ? -1
- + : (pt1->stamp == pt2->stamp) ? 0
- + : 1;
- +
- + return ret;
- +}
- +
- +static void
- +viv_sync_pt_free(
- + struct sync_pt * sync_pt
- + )
- +{
- + struct viv_sync_pt * pt;
- + struct viv_sync_timeline * obj;
- +
- + pt = (struct viv_sync_pt *) sync_pt;
- + obj = (struct viv_sync_timeline *) sync_pt->parent;
- +
- + gckOS_DestroySyncPoint(obj->os, pt->sync);
- +}
- +
- +static struct sync_timeline_ops viv_timeline_ops =
- +{
- + .driver_name = "viv_sync",
- + .dup = viv_sync_pt_dup,
- + .has_signaled = viv_sync_pt_has_signaled,
- + .compare = viv_sync_pt_compare,
- + .free_pt = viv_sync_pt_free,
- +};
- +
- +struct viv_sync_timeline *
- +viv_sync_timeline_create(
- + const char * name,
- + gckOS os
- + )
- +{
- + struct viv_sync_timeline * obj;
- +
- + obj = (struct viv_sync_timeline *)
- + sync_timeline_create(&viv_timeline_ops, sizeof(struct viv_sync_timeline), name);
- +
- + obj->os = os;
- + obj->stamp = 0;
- +
- + return obj;
- +}
- +
- +struct sync_pt *
- +viv_sync_pt_create(
- + struct viv_sync_timeline * obj,
- + gctSYNC_POINT SyncPoint
- + )
- +{
- + gceSTATUS status;
- + struct viv_sync_pt * pt;
- +
- + pt = (struct viv_sync_pt *)
- + sync_pt_create(&obj->obj, sizeof(struct viv_sync_pt));
- +
- + pt->stamp = obj->stamp++;
- + pt->sync = SyncPoint;
- +
- + /* Dup signal. */
- + status = gckOS_ReferenceSyncPoint(obj->os, SyncPoint);
- +
- + if (gcmIS_ERROR(status))
- + {
- + sync_pt_free((struct sync_pt *)pt);
- + return NULL;
- + }
- +
- + return (struct sync_pt *) pt;
- +}
- +
- +#endif
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h 2015-03-08 14:27:37.657684501 -0500
- @@ -0,0 +1,71 @@
- +/****************************************************************************
- +*
- +* Copyright (C) 2005 - 2013 by Vivante Corp.
- +*
- +* 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 program is distributed in the hope that it will be useful,
- +* but WITHOUT ANY WARRANTY; without even the implied warranty of
- +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +* GNU General Public License for more details.
- +*
- +* 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 __gc_hal_kernel_sync_h_
- +#define __gc_hal_kernel_sync_h_
- +
- +#include <linux/types.h>
- +
- +#include <linux/sync.h>
- +
- +#include <gc_hal.h>
- +#include <gc_hal_base.h>
- +
- +struct viv_sync_timeline
- +{
- + /* Parent object. */
- + struct sync_timeline obj;
- +
- + /* Timestamp when sync_pt is created. */
- + gctUINT stamp;
- +
- + /* Pointer to os struct. */
- + gckOS os;
- +};
- +
- +
- +struct viv_sync_pt
- +{
- + /* Parent object. */
- + struct sync_pt pt;
- +
- + /* Reference sync point*/
- + gctSYNC_POINT sync;
- +
- + /* Timestamp when sync_pt is created. */
- + gctUINT stamp;
- +};
- +
- +/* Create viv_sync_timeline object. */
- +struct viv_sync_timeline *
- +viv_sync_timeline_create(
- + const char * Name,
- + gckOS Os
- + );
- +
- +/* Create viv_sync_pt object. */
- +struct sync_pt *
- +viv_sync_pt_create(
- + struct viv_sync_timeline * Obj,
- + gctSYNC_POINT SyncPoint
- + );
- +
- +#endif /* __gc_hal_kernel_sync_h_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/Kbuild linux-3.14.35/drivers/mxc/gpu-viv/Kbuild
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/Kbuild 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/Kbuild 2015-03-08 14:27:37.657684501 -0500
- @@ -0,0 +1,236 @@
- +##############################################################################
- +#
- +# Copyright (C) 2005 - 2013 by Vivante Corp.
- +#
- +# 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 program is distributed in the hope that it will be useful,
- +# but WITHOUT ANY WARRANTY; without even the implied warranty of
- +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +# GNU General Public License for more details.
- +#
- +# 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.
- +#
- +##############################################################################
- +
- +
- +#
- +# Linux build file for kernel HAL driver.
- +#
- +
- +AQROOT := $(srctree)/drivers/mxc/gpu-viv
- +AQARCH := $(AQROOT)/arch/XAQ2
- +AQVGARCH := $(AQROOT)/arch/GC350
- +
- +include $(AQROOT)/config
- +
- +KERNEL_DIR ?= $(TOOL_DIR)/kernel
- +
- +OS_KERNEL_DIR := hal/os/linux/kernel
- +ARCH_KERNEL_DIR := arch/$(notdir $(AQARCH))/hal/kernel
- +ARCH_VG_KERNEL_DIR := arch/$(notdir $(AQVGARCH))/hal/kernel
- +HAL_KERNEL_DIR := hal/kernel
- +
- +# EXTRA_CFLAGS += -Werror
- +
- +OBJS := $(OS_KERNEL_DIR)/gc_hal_kernel_device.o \
- + $(OS_KERNEL_DIR)/gc_hal_kernel_driver.o \
- + $(OS_KERNEL_DIR)/gc_hal_kernel_linux.o \
- + $(OS_KERNEL_DIR)/gc_hal_kernel_math.o \
- + $(OS_KERNEL_DIR)/gc_hal_kernel_os.o \
- + $(OS_KERNEL_DIR)/gc_hal_kernel_debugfs.o
- +
- +OBJS += $(HAL_KERNEL_DIR)/gc_hal_kernel.o \
- + $(HAL_KERNEL_DIR)/gc_hal_kernel_command.o \
- + $(HAL_KERNEL_DIR)/gc_hal_kernel_db.o \
- + $(HAL_KERNEL_DIR)/gc_hal_kernel_debug.o \
- + $(HAL_KERNEL_DIR)/gc_hal_kernel_event.o \
- + $(HAL_KERNEL_DIR)/gc_hal_kernel_heap.o \
- + $(HAL_KERNEL_DIR)/gc_hal_kernel_mmu.o \
- + $(HAL_KERNEL_DIR)/gc_hal_kernel_video_memory.o \
- + $(HAL_KERNEL_DIR)/gc_hal_kernel_power.o
- +
- +OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_context.o \
- + $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware.o
- +
- +ifeq ($(VIVANTE_ENABLE_VG), 1)
- +OBJS +=\
- + $(HAL_KERNEL_DIR)/gc_hal_kernel_vg.o\
- + $(HAL_KERNEL_DIR)/gc_hal_kernel_command_vg.o\
- + $(HAL_KERNEL_DIR)/gc_hal_kernel_interrupt_vg.o\
- + $(HAL_KERNEL_DIR)/gc_hal_kernel_mmu_vg.o\
- + $(ARCH_VG_KERNEL_DIR)/gc_hal_kernel_hardware_command_vg.o\
- + $(ARCH_VG_KERNEL_DIR)/gc_hal_kernel_hardware_vg.o
- +endif
- +
- +ifneq ($(CONFIG_SYNC),)
- +OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_sync.o
- +endif
- +
- +ifeq ($(KERNELRELEASE), )
- +
- +.PHONY: all clean install
- +
- +# Define targets.
- +all:
- + @make V=$(V) ARCH=$(ARCH_TYPE) -C $(KERNEL_DIR) SUBDIRS=`pwd` modules
- +
- +clean:
- + @rm -rf $(OBJS)
- + @rm -rf modules.order Module.symvers
- + @find $(AQROOT) -name ".gc_*.cmd" | xargs rm -f
- +
- +install: all
- + @mkdir -p $(SDK_DIR)/drivers
- +
- +else
- +
- +
- +EXTRA_CFLAGS += -DLINUX -DDRIVER
- +
- +ifeq ($(ENUM_WORKAROUND), 1)
- +EXTRA_CFLAGS += -DENUM_WORKAROUND=1
- +else
- +EXTRA_CFLAGS += -DENUM_WORKAROUND=0
- +endif
- +
- +ifeq ($(FLAREON),1)
- +EXTRA_CFLAGS += -DFLAREON
- +endif
- +
- +ifeq ($(DEBUG), 1)
- +EXTRA_CFLAGS += -DDBG=1 -DDEBUG -D_DEBUG
- +else
- +EXTRA_CFLAGS += -DDBG=0
- +endif
- +
- +ifeq ($(NO_DMA_COHERENT), 1)
- +EXTRA_CFLAGS += -DNO_DMA_COHERENT
- +endif
- +
- +ifeq ($(CONFIG_DOVE_GPU), 1)
- +EXTRA_CFLAGS += -DCONFIG_DOVE_GPU=1
- +endif
- +
- +ifneq ($(USE_PLATFORM_DRIVER), 0)
- +EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=1
- +else
- +EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=0
- +endif
- +
- +
- +EXTRA_CFLAGS += -DVIVANTE_PROFILER=1
- +EXTRA_CFLAGS += -DVIVANTE_PROFILER_CONTEXT=1
- +
- +
- +ifeq ($(ANDROID), 1)
- +EXTRA_CFLAGS += -DANDROID=1
- +endif
- +
- +ifeq ($(ENABLE_GPU_CLOCK_BY_DRIVER), 1)
- +EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=1
- +else
- +EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=0
- +endif
- +
- +ifeq ($(USE_NEW_LINUX_SIGNAL), 1)
- +EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=1
- +else
- +EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=0
- +endif
- +
- +ifeq ($(NO_USER_DIRECT_ACCESS_FROM_KERNEL), 1)
- +EXTRA_CFLAGS += -DNO_USER_DIRECT_ACCESS_FROM_KERNEL=1
- +else
- +EXTRA_CFLAGS += -DNO_USER_DIRECT_ACCESS_FROM_KERNEL=0
- +endif
- +
- +ifeq ($(FORCE_ALL_VIDEO_MEMORY_CACHED), 1)
- +EXTRA_CFLAGS += -DgcdPAGED_MEMORY_CACHEABLE=1
- +else
- +EXTRA_CFLAGS += -DgcdPAGED_MEMORY_CACHEABLE=0
- +endif
- +
- +ifeq ($(NONPAGED_MEMORY_CACHEABLE), 1)
- +EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_CACHEABLE=1
- +else
- +EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_CACHEABLE=0
- +endif
- +
- +ifeq ($(NONPAGED_MEMORY_BUFFERABLE), 1)
- +EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_BUFFERABLE=1
- +else
- +EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_BUFFERABLE=0
- +endif
- +
- +ifeq ($(CACHE_FUNCTION_UNIMPLEMENTED), 1)
- +EXTRA_CFLAGS += -DgcdCACHE_FUNCTION_UNIMPLEMENTED=1
- +else
- +EXTRA_CFLAGS += -DgcdCACHE_FUNCTION_UNIMPLEMENTED=0
- +endif
- +
- +ifeq ($(SUPPORT_SWAP_RECTANGLE), 1)
- +EXTRA_CFLAGS += -DgcdSUPPORT_SWAP_RECTANGLE=1
- +else
- +EXTRA_CFLAGS += -DgcdSUPPORT_SWAP_RECTANGLE=0
- +endif
- +
- +ifeq ($(VIVANTE_ENABLE_VG), 1)
- +EXTRA_CFLAGS += -DgcdENABLE_VG=1
- +else
- +EXTRA_CFLAGS += -DgcdENABLE_VG=0
- +endif
- +
- +ifeq ($(CONFIG_SMP), y)
- +EXTRA_CFLAGS += -DgcdSMP=1
- +else
- +EXTRA_CFLAGS += -DgcdSMP=0
- +endif
- +
- +ifeq ($(VIVANTE_NO_3D),1)
- +EXTRA_CFLAGS += -DVIVANTE_NO_3D
- +endif
- +
- +ifeq ($(ENABLE_OUTER_CACHE_PATCH), 1)
- +EXTRA_CFLAGS += -DgcdENABLE_OUTER_CACHE_PATCH=1
- +else
- +EXTRA_CFLAGS += -DgcdENABLE_OUTER_CACHE_PATCH=0
- +endif
- +
- +ifeq ($(USE_BANK_ALIGNMENT), 1)
- + EXTRA_CFLAGS += -DgcdENABLE_BANK_ALIGNMENT=1
- + ifneq ($(BANK_BIT_START), 0)
- + ifneq ($(BANK_BIT_END), 0)
- + EXTRA_CFLAGS += -DgcdBANK_BIT_START=$(BANK_BIT_START)
- + EXTRA_CFLAGS += -DgcdBANK_BIT_END=$(BANK_BIT_END)
- + endif
- + endif
- +
- + ifneq ($(BANK_CHANNEL_BIT), 0)
- + EXTRA_CFLAGS += -DgcdBANK_CHANNEL_BIT=$(BANK_CHANNEL_BIT)
- + endif
- +endif
- +
- +ifneq ($(CONFIG_SYNC),)
- +EXTRA_CFLAGS += -DgcdANDROID_NATIVE_FENCE_SYNC=1
- +endif
- +
- +EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/inc
- +EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel
- +EXTRA_CFLAGS += -I$(AQARCH)/hal/kernel
- +EXTRA_CFLAGS += -I$(AQROOT)/hal/os/linux/kernel
- +
- +ifeq ($(VIVANTE_ENABLE_VG), 1)
- +EXTRA_CFLAGS += -I$(AQVGARCH)/hal/kernel
- +endif
- +
- +obj-$(CONFIG_MXC_GPU_VIV) += galcore.o
- +
- +galcore-objs := $(OBJS)
- +
- +endif
- diff -Nur linux-3.14.35.orig/drivers/mxc/gpu-viv/Kconfig linux-3.14.35/drivers/mxc/gpu-viv/Kconfig
- --- linux-3.14.35.orig/drivers/mxc/gpu-viv/Kconfig 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/gpu-viv/Kconfig 2015-03-08 14:27:37.657684501 -0500
- @@ -0,0 +1,9 @@
- +menu "MXC Vivante GPU support"
- + depends on SOC_IMX6Q
- +
- +config MXC_GPU_VIV
- + tristate "MXC Vivante GPU support"
- + ---help---
- + Say Y to get the GPU driver support.
- +
- +endmenu
- diff -Nur linux-3.14.35.orig/drivers/mxc/hdmi-cec/Kconfig linux-3.14.35/drivers/mxc/hdmi-cec/Kconfig
- --- linux-3.14.35.orig/drivers/mxc/hdmi-cec/Kconfig 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/hdmi-cec/Kconfig 2015-03-08 14:27:37.657684501 -0500
- @@ -0,0 +1,11 @@
- +
- +menu "MXC HDMI CEC (Consumer Electronics Control) support"
- +
- +config MXC_HDMI_CEC
- + tristate "Support for MXC HDMI CEC (Consumer Electronics Control)"
- + depends on MFD_MXC_HDMI
- + depends on FB_MXC_HDMI
- + help
- + The HDMI CEC device implement low level protocol on i.MX6x platforms.
- +
- +endmenu
- diff -Nur linux-3.14.35.orig/drivers/mxc/hdmi-cec/Makefile linux-3.14.35/drivers/mxc/hdmi-cec/Makefile
- --- linux-3.14.35.orig/drivers/mxc/hdmi-cec/Makefile 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/hdmi-cec/Makefile 2015-03-08 14:27:37.657684501 -0500
- @@ -0,0 +1 @@
- +obj-$(CONFIG_MXC_HDMI_CEC) += mxc_hdmi-cec.o
- diff -Nur linux-3.14.35.orig/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c linux-3.14.35/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c
- --- linux-3.14.35.orig/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c 2015-03-08 14:27:37.657684501 -0500
- @@ -0,0 +1,629 @@
- +/*
- + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file mxc_hdmi-cec.c
- + *
- + * @brief HDMI CEC system initialization and file operation implementation
- + *
- + * @ingroup HDMI
- + */
- +
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/mm.h>
- +#include <linux/fs.h>
- +#include <linux/stat.h>
- +#include <linux/platform_device.h>
- +#include <linux/poll.h>
- +#include <linux/wait.h>
- +#include <linux/list.h>
- +#include <linux/delay.h>
- +#include <linux/fsl_devices.h>
- +#include <linux/uaccess.h>
- +#include <linux/io.h>
- +#include <linux/slab.h>
- +#include <linux/vmalloc.h>
- +#include <linux/workqueue.h>
- +#include <linux/sizes.h>
- +
- +#include <linux/console.h>
- +#include <linux/types.h>
- +#include <linux/mfd/mxc-hdmi-core.h>
- +#include <linux/pinctrl/consumer.h>
- +
- +#include <video/mxc_hdmi.h>
- +
- +#include "mxc_hdmi-cec.h"
- +
- +
- +#define MAX_MESSAGE_LEN 17
- +
- +#define MESSAGE_TYPE_RECEIVE_SUCCESS 1
- +#define MESSAGE_TYPE_NOACK 2
- +#define MESSAGE_TYPE_DISCONNECTED 3
- +#define MESSAGE_TYPE_CONNECTED 4
- +#define MESSAGE_TYPE_SEND_SUCCESS 5
- +
- +#define CEC_TX_INPROGRESS -1
- +#define CEC_TX_AVAIL 0
- +
- +struct hdmi_cec_priv {
- + int receive_error;
- + int send_error;
- + u8 Logical_address;
- + bool cec_state;
- + u8 last_msg[MAX_MESSAGE_LEN];
- + u8 msg_len;
- + int tx_answer;
- + u16 latest_cec_stat;
- + u8 link_status;
- + spinlock_t irq_lock;
- + struct delayed_work hdmi_cec_work;
- + struct mutex lock;
- +};
- +
- +struct hdmi_cec_event {
- + int event_type;
- + int msg_len;
- + u8 msg[MAX_MESSAGE_LEN];
- + struct list_head list;
- +};
- +
- +
- +static LIST_HEAD(head);
- +
- +static int hdmi_cec_ready = 0;
- +static int hdmi_cec_started;
- +static int hdmi_cec_major;
- +static struct class *hdmi_cec_class;
- +static struct hdmi_cec_priv hdmi_cec_data;
- +static u8 open_count;
- +
- +static wait_queue_head_t hdmi_cec_queue;
- +static wait_queue_head_t tx_cec_queue;
- +
- +static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data)
- +{
- + struct hdmi_cec_priv *hdmi_cec = data;
- + u16 cec_stat = 0;
- + unsigned long flags;
- + u8 phy_stat0;
- + irqreturn_t ret = IRQ_HANDLED;
- +
- + spin_lock_irqsave(&hdmi_cec->irq_lock, flags);
- +
- + hdmi_writeb(0x7f, HDMI_IH_MUTE_CEC_STAT0);
- +
- + cec_stat = hdmi_readb(HDMI_IH_CEC_STAT0);
- + hdmi_writeb(cec_stat, HDMI_IH_CEC_STAT0);
- + phy_stat0 = hdmi_readb(HDMI_PHY_STAT0) & 0x02;
- +
- + if ((cec_stat & (HDMI_IH_CEC_STAT0_ERROR_INIT | \
- + HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | \
- + HDMI_IH_CEC_STAT0_DONE)) == 0) {
- + ret = IRQ_NONE;
- + cec_stat = 0;
- + }
- + if (hdmi_cec->link_status ^ phy_stat0) {
- + /* HPD value changed */
- + hdmi_cec->link_status = phy_stat0;
- + if (hdmi_cec->link_status)
- + cec_stat |= 0x80; /* Connected */
- + else
- + cec_stat |= 0x100; /* Disconnected */
- + }
- + pr_debug("HDMI CEC interrupt received\n");
- + hdmi_cec->latest_cec_stat = cec_stat ;
- +
- + schedule_delayed_work(&(hdmi_cec->hdmi_cec_work), msecs_to_jiffies(20));
- +
- + spin_unlock_irqrestore(&hdmi_cec->irq_lock, flags);
- +
- + return ret;
- +}
- +
- +void mxc_hdmi_cec_handle(u16 cec_stat)
- +{
- + u8 val = 0, i = 0;
- + struct hdmi_cec_event *event = NULL;
- + /*The current transmission is successful (for initiator only).*/
- + if (!open_count)
- + return;
- +
- + if (cec_stat & HDMI_IH_CEC_STAT0_DONE) {
- + hdmi_cec_data.tx_answer = cec_stat;
- + wake_up(&tx_cec_queue);
- + }
- + /*EOM is detected so that the received data is ready in the receiver data buffer*/
- + if (cec_stat & HDMI_IH_CEC_STAT0_EOM) {
- + hdmi_writeb(0x02, HDMI_IH_CEC_STAT0);
- + event = vmalloc(sizeof(struct hdmi_cec_event));
- + if (NULL == event) {
- + pr_err("%s: Not enough memory!\n", __func__);
- + return;
- + }
- + memset(event, 0, sizeof(struct hdmi_cec_event));
- + event->msg_len = hdmi_readb(HDMI_CEC_RX_CNT);
- + if (!event->msg_len) {
- + pr_err("%s: Invalid CEC message length!\n", __func__);
- + return;
- + }
- + event->event_type = MESSAGE_TYPE_RECEIVE_SUCCESS;
- + for (i = 0; i < event->msg_len; i++)
- + event->msg[i] = hdmi_readb(HDMI_CEC_RX_DATA0+i);
- + hdmi_writeb(0x0, HDMI_CEC_LOCK);
- + mutex_lock(&hdmi_cec_data.lock);
- + list_add_tail(&event->list, &head);
- + mutex_unlock(&hdmi_cec_data.lock);
- + wake_up(&hdmi_cec_queue);
- + }
- + /*An error is detected on cec line (for initiator only). */
- + if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_INIT) {
- + mutex_lock(&hdmi_cec_data.lock);
- + hdmi_cec_data.send_error++;
- + if (hdmi_cec_data.send_error > 2) {
- + pr_err("%s:Re-transmission is attempted more than 2 times!\n", __func__);
- + hdmi_cec_data.send_error = 0;
- + mutex_unlock(&hdmi_cec_data.lock);
- + hdmi_cec_data.tx_answer = cec_stat;
- + wake_up(&tx_cec_queue);
- + return;
- + }
- + for (i = 0; i < hdmi_cec_data.msg_len; i++)
- + hdmi_writeb(hdmi_cec_data.last_msg[i], HDMI_CEC_TX_DATA0+i);
- + hdmi_writeb(hdmi_cec_data.msg_len, HDMI_CEC_TX_CNT);
- + val = hdmi_readb(HDMI_CEC_CTRL);
- + val |= 0x01;
- + hdmi_writeb(val, HDMI_CEC_CTRL);
- + mutex_unlock(&hdmi_cec_data.lock);
- + }
- + /*A frame is not acknowledged in a directly addressed message. Or a frame is negatively acknowledged in
- + a broadcast message (for initiator only).*/
- + if (cec_stat & HDMI_IH_CEC_STAT0_NACK) {
- + hdmi_cec_data.tx_answer = cec_stat;
- + wake_up(&tx_cec_queue);
- + }
- + /*An error is notified by a follower. Abnormal logic data bit error (for follower).*/
- + if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_FOLL) {
- + hdmi_cec_data.receive_error++;
- + }
- + /*HDMI cable connected*/
- + if (cec_stat & 0x80) {
- + pr_info("HDMI link connected\n");
- + event = vmalloc(sizeof(struct hdmi_cec_event));
- + if (NULL == event) {
- + pr_err("%s: Not enough memory\n", __func__);
- + return;
- + }
- + memset(event, 0, sizeof(struct hdmi_cec_event));
- + event->event_type = MESSAGE_TYPE_CONNECTED;
- + mutex_lock(&hdmi_cec_data.lock);
- + list_add_tail(&event->list, &head);
- + mutex_unlock(&hdmi_cec_data.lock);
- + wake_up(&hdmi_cec_queue);
- + }
- + /*HDMI cable disconnected*/
- + if (cec_stat & 0x100) {
- + pr_info("HDMI link disconnected\n");
- + event = vmalloc(sizeof(struct hdmi_cec_event));
- + if (NULL == event) {
- + pr_err("%s: Not enough memory!\n", __func__);
- + return;
- + }
- + memset(event, 0, sizeof(struct hdmi_cec_event));
- + event->event_type = MESSAGE_TYPE_DISCONNECTED;
- + mutex_lock(&hdmi_cec_data.lock);
- + list_add_tail(&event->list, &head);
- + mutex_unlock(&hdmi_cec_data.lock);
- + wake_up(&hdmi_cec_queue);
- + }
- + return;
- +}
- +EXPORT_SYMBOL(mxc_hdmi_cec_handle);
- +static void mxc_hdmi_cec_worker(struct work_struct *work)
- +{
- + u8 val;
- + mxc_hdmi_cec_handle(hdmi_cec_data.latest_cec_stat);
- + val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL | HDMI_IH_CEC_STAT0_ARB_LOST;
- + hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0);
- +}
- +
- +/*!
- + * @brief open function for cec file operation
- + *
- + * @return 0 on success or negative error code on error
- + */
- +static int hdmi_cec_open(struct inode *inode, struct file *filp)
- +{
- + mutex_lock(&hdmi_cec_data.lock);
- + if (open_count) {
- + mutex_unlock(&hdmi_cec_data.lock);
- + return -EBUSY;
- + }
- + open_count = 1;
- + filp->private_data = (void *)(&hdmi_cec_data);
- + hdmi_cec_data.Logical_address = 15;
- + hdmi_cec_data.cec_state = false;
- + mutex_unlock(&hdmi_cec_data.lock);
- + return 0;
- +}
- +
- +static ssize_t hdmi_cec_read(struct file *file, char __user *buf, size_t count,
- + loff_t *ppos)
- +{
- + struct hdmi_cec_event *event = NULL;
- + pr_debug("function : %s\n", __func__);
- +
- + if (!open_count)
- + return -ENODEV;
- + mutex_lock(&hdmi_cec_data.lock);
- + if (false == hdmi_cec_data.cec_state) {
- + mutex_unlock(&hdmi_cec_data.lock);
- + return -EACCES;
- + }
- +
- + if (list_empty(&head)) {
- + if (file->f_flags & O_NONBLOCK) {
- + mutex_unlock(&hdmi_cec_data.lock);
- + return -EAGAIN;
- + } else {
- + do {
- + mutex_unlock(&hdmi_cec_data.lock);
- + if (wait_event_interruptible(hdmi_cec_queue, (!list_empty(&head))))
- + return -ERESTARTSYS;
- + mutex_lock(&hdmi_cec_data.lock);
- + } while (list_empty(&head));
- + }
- + }
- +
- + event = list_first_entry(&head, struct hdmi_cec_event, list);
- + list_del(&event->list);
- + mutex_unlock(&hdmi_cec_data.lock);
- + if (copy_to_user(buf, event,
- + sizeof(struct hdmi_cec_event) - sizeof(struct list_head))) {
- + vfree(event);
- + return -EFAULT;
- + }
- + vfree(event);
- + return (sizeof(struct hdmi_cec_event) - sizeof(struct list_head));
- +}
- +
- +static ssize_t hdmi_cec_write(struct file *file, const char __user *buf,
- + size_t count, loff_t *ppos)
- +{
- + int ret = 0 , i = 0;
- + u8 msg[MAX_MESSAGE_LEN];
- + u8 msg_len = 0, val = 0;
- +
- + pr_debug("function : %s\n", __func__);
- +
- + if (!open_count)
- + return -ENODEV;
- + mutex_lock(&hdmi_cec_data.lock);
- + if (false == hdmi_cec_data.cec_state) {
- + mutex_unlock(&hdmi_cec_data.lock);
- + return -EACCES;
- + }
- + /* Ensure that there is only one writer who is the only listener of tx_cec_queue */
- + if (hdmi_cec_data.tx_answer != CEC_TX_AVAIL) {
- + mutex_unlock(&hdmi_cec_data.lock);
- + return -EBUSY;
- + }
- + mutex_unlock(&hdmi_cec_data.lock);
- + if (count > MAX_MESSAGE_LEN)
- + return -EINVAL;
- + memset(&msg, 0, MAX_MESSAGE_LEN);
- + ret = copy_from_user(&msg, buf, count);
- + if (ret)
- + return -EACCES;
- + mutex_lock(&hdmi_cec_data.lock);
- + hdmi_cec_data.send_error = 0;
- + hdmi_cec_data.tx_answer = CEC_TX_INPROGRESS;
- + msg_len = count;
- + hdmi_writeb(msg_len, HDMI_CEC_TX_CNT);
- + for (i = 0; i < msg_len; i++)
- + hdmi_writeb(msg[i], HDMI_CEC_TX_DATA0+i);
- + val = hdmi_readb(HDMI_CEC_CTRL);
- + val |= 0x01;
- + hdmi_writeb(val, HDMI_CEC_CTRL);
- + memcpy(hdmi_cec_data.last_msg, msg, msg_len);
- + hdmi_cec_data.msg_len = msg_len;
- + mutex_unlock(&hdmi_cec_data.lock);
- +
- + ret = wait_event_interruptible_timeout(tx_cec_queue, hdmi_cec_data.tx_answer != CEC_TX_INPROGRESS, HZ);
- +
- + if (ret < 0) {
- + ret = -ERESTARTSYS;
- + goto tx_out;
- + }
- +
- + if (hdmi_cec_data.tx_answer & HDMI_IH_CEC_STAT0_DONE)
- + /* msg correctly sent */
- + ret = msg_len;
- + else
- + ret = -EIO;
- +
- + tx_out:
- + hdmi_cec_data.tx_answer = CEC_TX_AVAIL;
- + return ret;
- +}
- +
- +void hdmi_cec_start_device(void)
- +{
- + u8 val;
- +
- + if (!hdmi_cec_ready || hdmi_cec_started)
- + return;
- +
- + val = hdmi_readb(HDMI_MC_CLKDIS);
- + val &= ~HDMI_MC_CLKDIS_CECCLK_DISABLE;
- + hdmi_writeb(val, HDMI_MC_CLKDIS);
- + hdmi_writeb(0x02, HDMI_CEC_CTRL);
- + /* Force read unlock */
- + hdmi_writeb(0x0, HDMI_CEC_LOCK);
- + val = HDMI_IH_CEC_STAT0_ERROR_INIT | HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | HDMI_IH_CEC_STAT0_DONE;
- + hdmi_writeb(val, HDMI_CEC_POLARITY);
- + val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL | HDMI_IH_CEC_STAT0_ARB_LOST;
- + hdmi_writeb(val, HDMI_CEC_MASK);
- + hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0);
- + hdmi_cec_data.link_status = hdmi_readb(HDMI_PHY_STAT0) & 0x02;
- + mutex_lock(&hdmi_cec_data.lock);
- + hdmi_cec_data.cec_state = true;
- + mutex_unlock(&hdmi_cec_data.lock);
- +
- + hdmi_cec_started = 1;
- +}
- +EXPORT_SYMBOL(hdmi_cec_start_device);
- +
- +void hdmi_cec_stop_device(void)
- +{
- + u8 val;
- +
- + if (!hdmi_cec_ready || !hdmi_cec_started)
- + return;
- +
- + hdmi_writeb(0x10, HDMI_CEC_CTRL);
- + val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL | HDMI_IH_CEC_STAT0_ERROR_INIT | HDMI_IH_CEC_STAT0_ARB_LOST | \
- + HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | HDMI_IH_CEC_STAT0_DONE;
- + hdmi_writeb(val, HDMI_CEC_MASK);
- + hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0);
- + hdmi_writeb(0x0, HDMI_CEC_POLARITY);
- + val = hdmi_readb(HDMI_MC_CLKDIS);
- + val |= HDMI_MC_CLKDIS_CECCLK_DISABLE;
- + hdmi_writeb(val, HDMI_MC_CLKDIS);
- + mutex_lock(&hdmi_cec_data.lock);
- + hdmi_cec_data.cec_state = false;
- + mutex_unlock(&hdmi_cec_data.lock);
- +
- + hdmi_cec_started = 0;
- +}
- +EXPORT_SYMBOL(hdmi_cec_stop_device);
- +
- +/*!
- + * @brief IO ctrl function for vpu file operation
- + * @param cmd IO ctrl command
- + * @return 0 on success or negative error code on error
- + */
- +static long hdmi_cec_ioctl(struct file *filp, u_int cmd,
- + u_long arg)
- +{
- + int ret = 0, status = 0;
- + u8 val = 0, msg = 0;
- + struct mxc_edid_cfg hdmi_edid_cfg;
- + pr_debug("function : %s\n", __func__);
- + if (!open_count)
- + return -ENODEV;
- + switch (cmd) {
- + case HDMICEC_IOC_SETLOGICALADDRESS:
- + mutex_lock(&hdmi_cec_data.lock);
- + if (false == hdmi_cec_data.cec_state) {
- + mutex_unlock(&hdmi_cec_data.lock);
- + pr_err("Trying to set logical address while not started\n");
- + return -EACCES;
- + }
- + hdmi_cec_data.Logical_address = (u8)arg;
- + if (hdmi_cec_data.Logical_address <= 7) {
- + val = 1 << hdmi_cec_data.Logical_address;
- + hdmi_writeb(val, HDMI_CEC_ADDR_L);
- + hdmi_writeb(0, HDMI_CEC_ADDR_H);
- + } else if (hdmi_cec_data.Logical_address > 7 && hdmi_cec_data.Logical_address <= 15) {
- + val = 1 << (hdmi_cec_data.Logical_address - 8);
- + hdmi_writeb(val, HDMI_CEC_ADDR_H);
- + hdmi_writeb(0, HDMI_CEC_ADDR_L);
- + } else
- + ret = -EINVAL;
- + /*Send Polling message with same source and destination address*/
- + if (0 == ret && 15 != hdmi_cec_data.Logical_address) {
- + msg = (hdmi_cec_data.Logical_address << 4)|hdmi_cec_data.Logical_address;
- + hdmi_writeb(1, HDMI_CEC_TX_CNT);
- + hdmi_writeb(msg, HDMI_CEC_TX_DATA0);
- + val = hdmi_readb(HDMI_CEC_CTRL);
- + val |= 0x01;
- + hdmi_writeb(val, HDMI_CEC_CTRL);
- + }
- + mutex_unlock(&hdmi_cec_data.lock);
- + break;
- + case HDMICEC_IOC_STARTDEVICE:
- + hdmi_cec_start_device();
- + break;
- + case HDMICEC_IOC_STOPDEVICE:
- + hdmi_cec_stop_device();
- + break;
- + case HDMICEC_IOC_GETPHYADDRESS:
- + hdmi_get_edid_cfg(&hdmi_edid_cfg);
- + status = copy_to_user((void __user *)arg,
- + &hdmi_edid_cfg.physical_address,
- + 4*sizeof(u8));
- + if (status)
- + ret = -EFAULT;
- + break;
- + default:
- + ret = -EINVAL;
- + break;
- + }
- + return ret;
- +}
- +
- +/*!
- + * @brief Release function for vpu file operation
- + * @return 0 on success or negative error code on error
- + */
- +static int hdmi_cec_release(struct inode *inode, struct file *filp)
- +{
- + mutex_lock(&hdmi_cec_data.lock);
- + if (open_count) {
- + open_count = 0;
- + hdmi_cec_data.cec_state = false;
- + hdmi_cec_data.Logical_address = 15;
- + }
- + mutex_unlock(&hdmi_cec_data.lock);
- +
- + return 0;
- +}
- +
- +static unsigned int hdmi_cec_poll(struct file *file, poll_table *wait)
- +{
- + unsigned int mask = 0;
- +
- + pr_debug("function : %s\n", __func__);
- +
- + poll_wait(file, &hdmi_cec_queue, wait);
- +
- + mutex_lock(&hdmi_cec_data.lock);
- + if (hdmi_cec_data.tx_answer == CEC_TX_AVAIL)
- + mask = (POLLOUT | POLLWRNORM);
- + if (!list_empty(&head))
- + mask |= (POLLIN | POLLRDNORM);
- + mutex_unlock(&hdmi_cec_data.lock);
- + return mask;
- +}
- +
- +
- +const struct file_operations hdmi_cec_fops = {
- + .owner = THIS_MODULE,
- + .read = hdmi_cec_read,
- + .write = hdmi_cec_write,
- + .open = hdmi_cec_open,
- + .unlocked_ioctl = hdmi_cec_ioctl,
- + .release = hdmi_cec_release,
- + .poll = hdmi_cec_poll,
- +};
- +
- +static int hdmi_cec_dev_probe(struct platform_device *pdev)
- +{
- + int err = 0;
- + struct device *temp_class;
- + struct resource *res;
- + struct pinctrl *pinctrl;
- + int irq = platform_get_irq(pdev, 0);
- +
- + hdmi_cec_major = register_chrdev(hdmi_cec_major, "mxc_hdmi_cec", &hdmi_cec_fops);
- + if (hdmi_cec_major < 0) {
- + dev_err(&pdev->dev, "hdmi_cec: unable to get a major for HDMI CEC\n");
- + err = -EBUSY;
- + goto out;
- + }
- +
- + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- + if (unlikely(res == NULL)) {
- + dev_err(&pdev->dev, "hdmi_cec:No HDMI irq line provided\n");
- + goto err_out_chrdev;
- + }
- + spin_lock_init(&hdmi_cec_data.irq_lock);
- +
- + err = devm_request_irq(&pdev->dev, irq, mxc_hdmi_cec_isr, IRQF_SHARED,
- + dev_name(&pdev->dev), &hdmi_cec_data);
- + if (err < 0) {
- + dev_err(&pdev->dev, "hdmi_cec:Unable to request irq: %d\n", err);
- + goto err_out_chrdev;
- + }
- +
- + hdmi_cec_class = class_create(THIS_MODULE, "mxc_hdmi_cec");
- + if (IS_ERR(hdmi_cec_class)) {
- + err = PTR_ERR(hdmi_cec_class);
- + goto err_out_chrdev;
- + }
- +
- + temp_class = device_create(hdmi_cec_class, NULL, MKDEV(hdmi_cec_major, 0),
- + NULL, "mxc_hdmi_cec");
- + if (IS_ERR(temp_class)) {
- + err = PTR_ERR(temp_class);
- + goto err_out_class;
- + }
- +
- + pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
- + if (IS_ERR(pinctrl)) {
- + dev_err(&pdev->dev, "can't get/select CEC pinctrl\n");
- + goto err_out_class;
- + }
- +
- + init_waitqueue_head(&hdmi_cec_queue);
- + init_waitqueue_head(&tx_cec_queue);
- +
- + INIT_LIST_HEAD(&head);
- +
- + mutex_init(&hdmi_cec_data.lock);
- + hdmi_cec_data.Logical_address = 15;
- + hdmi_cec_data.tx_answer = CEC_TX_AVAIL;
- + platform_set_drvdata(pdev, &hdmi_cec_data);
- + INIT_DELAYED_WORK(&hdmi_cec_data.hdmi_cec_work, mxc_hdmi_cec_worker);
- +
- + dev_info(&pdev->dev, "HDMI CEC initialized\n");
- + hdmi_cec_ready = 1;
- + goto out;
- +
- +err_out_class:
- + device_destroy(hdmi_cec_class, MKDEV(hdmi_cec_major, 0));
- + class_destroy(hdmi_cec_class);
- +err_out_chrdev:
- + unregister_chrdev(hdmi_cec_major, "mxc_hdmi_cec");
- +out:
- + return err;
- +}
- +
- +static int hdmi_cec_dev_remove(struct platform_device *pdev)
- +{
- + if (hdmi_cec_data.cec_state)
- + hdmi_cec_stop_device();
- + if (hdmi_cec_major > 0) {
- + device_destroy(hdmi_cec_class, MKDEV(hdmi_cec_major, 0));
- + class_destroy(hdmi_cec_class);
- + unregister_chrdev(hdmi_cec_major, "mxc_hdmi_cec");
- + hdmi_cec_major = 0;
- +}
- + return 0;
- +}
- +
- +static const struct of_device_id imx_hdmi_cec_match[] = {
- + { .compatible = "fsl,imx6q-hdmi-cec", },
- + { .compatible = "fsl,imx6dl-hdmi-cec", },
- + { /* sentinel */ }
- +};
- +
- +static struct platform_driver mxc_hdmi_cec_driver = {
- + .probe = hdmi_cec_dev_probe,
- + .remove = hdmi_cec_dev_remove,
- + .driver = {
- + .name = "mxc_hdmi_cec",
- + .of_match_table = imx_hdmi_cec_match,
- + },
- +};
- +
- +module_platform_driver(mxc_hdmi_cec_driver);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("Linux HDMI CEC driver for Freescale i.MX/MXC");
- +MODULE_LICENSE("GPL");
- +MODULE_ALIAS("platform:mxc_hdmi_cec");
- +
- diff -Nur linux-3.14.35.orig/drivers/mxc/hdmi-cec/mxc_hdmi-cec.h linux-3.14.35/drivers/mxc/hdmi-cec/mxc_hdmi-cec.h
- --- linux-3.14.35.orig/drivers/mxc/hdmi-cec/mxc_hdmi-cec.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/hdmi-cec/mxc_hdmi-cec.h 2015-03-08 14:27:37.657684501 -0500
- @@ -0,0 +1,38 @@
- +/*
- + * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +#ifndef _HDMICEC_H_
- +#define _HDMICEC_H_
- +#include <linux/ioctl.h>
- +
- +/*
- + * Ioctl definitions
- + */
- +
- +/* Use 'k' as magic number */
- +#define HDMICEC_IOC_MAGIC 'H'
- +/*
- + * S means "Set" through a ptr,
- + * T means "Tell" directly with the argument value
- + * G means "Get": reply by setting through a pointer
- + * Q means "Query": response is on the return value
- + * X means "eXchange": G and S atomically
- + * H means "sHift": T and Q atomically
- + */
- +#define HDMICEC_IOC_SETLOGICALADDRESS \
- + _IOW(HDMICEC_IOC_MAGIC, 1, unsigned char)
- +#define HDMICEC_IOC_STARTDEVICE _IO(HDMICEC_IOC_MAGIC, 2)
- +#define HDMICEC_IOC_STOPDEVICE _IO(HDMICEC_IOC_MAGIC, 3)
- +#define HDMICEC_IOC_GETPHYADDRESS \
- + _IOR(HDMICEC_IOC_MAGIC, 4, unsigned char[4])
- +
- +#endif /* !_HDMICEC_H_ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c linux-3.14.35/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c
- --- linux-3.14.35.orig/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c 2015-03-08 14:27:37.657684501 -0500
- @@ -0,0 +1,495 @@
- +/*
- + * Copyright 2009-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*
- + * @file ipu_calc_stripes_sizes.c
- + *
- + * @brief IPU IC functions
- + *
- + * @ingroup IPU
- + */
- +
- +#include <linux/ipu-v3.h>
- +#include <linux/module.h>
- +#include <linux/math64.h>
- +
- +#define BPP_32 0
- +#define BPP_16 3
- +#define BPP_8 5
- +#define BPP_24 1
- +#define BPP_12 4
- +#define BPP_18 2
- +
- +static u32 truncate(u32 up, /* 0: down; else: up */
- + u64 a, /* must be non-negative */
- + u32 b)
- +{
- + u32 d;
- + u64 div;
- + div = div_u64(a, b);
- + d = b * (div >> 32);
- + if (up && (a > (((u64)d) << 32)))
- + return d+b;
- + else
- + return d;
- +}
- +
- +static unsigned int f_calc(unsigned int pfs, unsigned int bpp, unsigned int *write)
- +{/* return input_f */
- + unsigned int f_calculated = 0;
- + switch (pfs) {
- + case IPU_PIX_FMT_YVU422P:
- + case IPU_PIX_FMT_YUV422P:
- + case IPU_PIX_FMT_YUV420P2:
- + case IPU_PIX_FMT_YUV420P:
- + case IPU_PIX_FMT_YVU420P:
- + case IPU_PIX_FMT_YUV444P:
- + f_calculated = 16;
- + break;
- +
- + case IPU_PIX_FMT_RGB565:
- + case IPU_PIX_FMT_YUYV:
- + case IPU_PIX_FMT_UYVY:
- + f_calculated = 8;
- + break;
- +
- + case IPU_PIX_FMT_NV12:
- + f_calculated = 8;
- + break;
- +
- + default:
- + f_calculated = 0;
- + break;
- +
- + }
- + if (!f_calculated) {
- + switch (bpp) {
- + case BPP_32:
- + f_calculated = 2;
- + break;
- +
- + case BPP_16:
- + f_calculated = 4;
- + break;
- +
- + case BPP_8:
- + case BPP_24:
- + f_calculated = 8;
- + break;
- +
- + case BPP_12:
- + f_calculated = 16;
- + break;
- +
- + case BPP_18:
- + f_calculated = 32;
- + break;
- +
- + default:
- + f_calculated = 0;
- + break;
- + }
- + }
- + return f_calculated;
- +}
- +
- +
- +static unsigned int m_calc(unsigned int pfs)
- +{
- + unsigned int m_calculated = 0;
- + switch (pfs) {
- + case IPU_PIX_FMT_YUV420P2:
- + case IPU_PIX_FMT_YUV420P:
- + case IPU_PIX_FMT_YVU422P:
- + case IPU_PIX_FMT_YUV422P:
- + case IPU_PIX_FMT_YVU420P:
- + case IPU_PIX_FMT_YUV444P:
- + m_calculated = 16;
- + break;
- +
- + case IPU_PIX_FMT_NV12:
- + case IPU_PIX_FMT_YUYV:
- + case IPU_PIX_FMT_UYVY:
- + m_calculated = 8;
- + break;
- +
- + default:
- + m_calculated = 8;
- + break;
- +
- + }
- + return m_calculated;
- +}
- +
- +static int calc_split_resize_coeffs(unsigned int inSize, unsigned int outSize,
- + unsigned int *resizeCoeff,
- + unsigned int *downsizeCoeff)
- +{
- + uint32_t tempSize;
- + uint32_t tempDownsize;
- +
- + if (inSize > 4096) {
- + pr_debug("IC input size(%d) cannot exceed 4096\n",
- + inSize);
- + return -EINVAL;
- + }
- +
- + if (outSize > 1024) {
- + pr_debug("IC output size(%d) cannot exceed 1024\n",
- + outSize);
- + return -EINVAL;
- + }
- +
- + if ((outSize << 3) < inSize) {
- + pr_debug("IC cannot downsize more than 8:1\n");
- + return -EINVAL;
- + }
- +
- + /* Compute downsizing coefficient */
- + /* Output of downsizing unit cannot be more than 1024 */
- + tempDownsize = 0;
- + tempSize = inSize;
- + while (((tempSize > 1024) || (tempSize >= outSize * 2)) &&
- + (tempDownsize < 2)) {
- + tempSize >>= 1;
- + tempDownsize++;
- + }
- + *downsizeCoeff = tempDownsize;
- +
- + /* compute resizing coefficient using the following equation:
- + resizeCoeff = M*(SI -1)/(SO - 1)
- + where M = 2^13, SI - input size, SO - output size */
- + *resizeCoeff = (8192L * (tempSize - 1)) / (outSize - 1);
- + if (*resizeCoeff >= 16384L) {
- + pr_debug("Overflow on IC resize coefficient.\n");
- + return -EINVAL;
- + }
- +
- + pr_debug("resizing from %u -> %u pixels, "
- + "downsize=%u, resize=%u.%lu (reg=%u)\n", inSize, outSize,
- + *downsizeCoeff, (*resizeCoeff >= 8192L) ? 1 : 0,
- + ((*resizeCoeff & 0x1FFF) * 10000L) / 8192L, *resizeCoeff);
- +
- + return 0;
- +}
- +
- +/* Stripe parameters calculator */
- +/**************************************************************************
- +Notes:
- +MSW = the maximal width allowed for a stripe
- + i.MX31: 720, i.MX35: 800, i.MX37/51/53: 1024
- +cirr = the maximal inverse resizing ratio for which overlap in the input
- + is requested; typically cirr~2
- +flags
- + bit 0 - equal_stripes
- + 0 each stripe is allowed to have independent parameters
- + for maximal image quality
- + 1 the stripes are requested to have identical parameters
- + (except the base address), for maximal performance
- + bit 1 - vertical/horizontal
- + 0 horizontal
- + 1 vertical
- +
- +If performance is the top priority (above image quality)
- + Avoid overlap, by setting CIRR = 0
- + This will also force effectively identical_stripes = 1
- + Choose IF & OF that corresponds to the same IOX/SX for both stripes
- + Choose IFW & OFW such that
- + IFW/IM, IFW/IF, OFW/OM, OFW/OF are even integers
- + The function returns an error status:
- + 0: no error
- + 1: invalid input parameters -> aborted without result
- + Valid parameters should satisfy the following conditions
- + IFW <= OFW, otherwise downsizing is required
- + - which is not supported yet
- + 4 <= IFW,OFW, so some interpolation may be needed even without overlap
- + IM, OM, IF, OF should not vanish
- + 2*IF <= IFW
- + so the frame can be split to two equal stripes, even without overlap
- + 2*(OF+IF/irr_opt) <= OFW
- + so a valid positive INW exists even for equal stripes
- + OF <= MSW, otherwise, the left stripe cannot be sufficiently large
- + MSW < OFW, so splitting to stripes is required
- + OFW <= 2*MSW, so two stripes are sufficient
- + (this also implies that 2<=MSW)
- + 2: OF is not a multiple of OM - not fully-supported yet
- + Output is produced but OW is not guaranited to be a multiple of OM
- + 4: OFW reduced to be a multiple of OM
- + 8: CIRR > 1: truncated to 1
- + Overlap is not supported (and not needed) y for upsizing)
- +**************************************************************************/
- +int ipu_calc_stripes_sizes(const unsigned int input_frame_width,
- + /* input frame width;>1 */
- + unsigned int output_frame_width, /* output frame width; >1 */
- + const unsigned int maximal_stripe_width,
- + /* the maximal width allowed for a stripe */
- + const unsigned long long cirr, /* see above */
- + const unsigned int flags, /* see above */
- + u32 input_pixelformat,/* pixel format after of read channel*/
- + u32 output_pixelformat,/* pixel format after of write channel*/
- + struct stripe_param *left,
- + struct stripe_param *right)
- +{
- + const unsigned int irr_frac_bits = 13;
- + const unsigned long irr_steps = 1 << irr_frac_bits;
- + const u64 dirr = ((u64)1) << (32 - 2);
- + /* The maximum relative difference allowed between the irrs */
- + const u64 cr = ((u64)4) << 32;
- + /* The importance ratio between the two terms in the cost function below */
- +
- + unsigned int status;
- + unsigned int temp;
- + unsigned int onw_min;
- + unsigned int inw = 0, onw = 0, inw_best = 0;
- + /* number of pixels in the left stripe NOT hidden by the right stripe */
- + u64 irr_opt; /* the optimal inverse resizing ratio */
- + u64 rr_opt; /* the optimal resizing ratio = 1/irr_opt*/
- + u64 dinw; /* the misalignment between the stripes */
- + /* (measured in units of input columns) */
- + u64 difwl, difwr = 0;
- + /* The number of input columns not reflected in the output */
- + /* the resizing ratio used for the right stripe is */
- + /* left->irr and right->irr respectively */
- + u64 cost, cost_min;
- + u64 div; /* result of division */
- + bool equal_stripes = (flags & 0x1) != 0;
- + bool vertical = (flags & 0x2) != 0;
- +
- + unsigned int input_m, input_f, output_m, output_f; /* parameters for upsizing by stripes */
- + unsigned int resize_coeff;
- + unsigned int downsize_coeff;
- +
- + status = 0;
- +
- + if (vertical) {
- + input_f = 2;
- + input_m = 8;
- + output_f = 8;
- + output_m = 2;
- + } else {
- + input_f = f_calc(input_pixelformat, 0, NULL);
- + input_m = m_calc(input_pixelformat);
- + output_f = input_m;
- + output_m = m_calc(output_pixelformat);
- + }
- + if ((input_frame_width < 4) || (output_frame_width < 4))
- + return 1;
- +
- + irr_opt = div_u64((((u64)(input_frame_width - 1)) << 32),
- + (output_frame_width - 1));
- + rr_opt = div_u64((((u64)(output_frame_width - 1)) << 32),
- + (input_frame_width - 1));
- +
- + if ((input_m == 0) || (output_m == 0) || (input_f == 0) || (output_f == 0)
- + || (input_frame_width < (2 * input_f))
- + || ((((u64)output_frame_width) << 32) <
- + (2 * ((((u64)output_f) << 32) + (input_f * rr_opt))))
- + || (maximal_stripe_width < output_f)
- + || ((output_frame_width <= maximal_stripe_width)
- + && (equal_stripes == 0))
- + || ((2 * maximal_stripe_width) < output_frame_width))
- + return 1;
- +
- + if (output_f % output_m)
- + status += 2;
- +
- + temp = truncate(0, (((u64)output_frame_width) << 32), output_m);
- + if (temp < output_frame_width) {
- + output_frame_width = temp;
- + status += 4;
- + }
- +
- + pr_debug("---------------->\n"
- + "if = %d\n"
- + "im = %d\n"
- + "of = %d\n"
- + "om = %d\n"
- + "irr_opt = %llu\n"
- + "rr_opt = %llu\n"
- + "cirr = %llu\n"
- + "pixel in = %08x\n"
- + "pixel out = %08x\n"
- + "ifw = %d\n"
- + "ofwidth = %d\n",
- + input_f,
- + input_m,
- + output_f,
- + output_m,
- + irr_opt,
- + rr_opt,
- + cirr,
- + input_pixelformat,
- + output_pixelformat,
- + input_frame_width,
- + output_frame_width
- + );
- +
- + if (equal_stripes) {
- + if ((irr_opt > cirr) /* overlap in the input is not requested */
- + && ((input_frame_width % (input_m << 1)) == 0)
- + && ((input_frame_width % (input_f << 1)) == 0)
- + && ((output_frame_width % (output_m << 1)) == 0)
- + && ((output_frame_width % (output_f << 1)) == 0)) {
- + /* without overlap */
- + left->input_width = right->input_width = right->input_column =
- + input_frame_width >> 1;
- + left->output_width = right->output_width = right->output_column =
- + output_frame_width >> 1;
- + left->input_column = 0;
- + left->output_column = 0;
- + div = div_u64(((((u64)irr_steps) << 32) *
- + (right->input_width - 1)), (right->output_width - 1));
- + left->irr = right->irr = truncate(0, div, 1);
- + } else { /* with overlap */
- + onw = truncate(0, (((u64)output_frame_width - 1) << 32) >> 1,
- + output_f);
- + inw = truncate(0, onw * irr_opt, input_f);
- + /* this is the maximal inw which allows the same resizing ratio */
- + /* in both stripes */
- + onw = truncate(1, (inw * rr_opt), output_f);
- + div = div_u64((((u64)(irr_steps * inw)) <<
- + 32), onw);
- + left->irr = right->irr = truncate(0, div, 1);
- + left->output_width = right->output_width =
- + output_frame_width - onw;
- + /* These are valid assignments for output_width, */
- + /* assuming output_f is a multiple of output_m */
- + div = (((u64)(left->output_width-1) * (left->irr)) << 32);
- + div = (((u64)1) << 32) + div_u64(div, irr_steps);
- +
- + left->input_width = right->input_width = truncate(1, div, input_m);
- +
- + div = div_u64((((u64)((right->output_width - 1) * right->irr)) <<
- + 32), irr_steps);
- + difwr = (((u64)(input_frame_width - 1 - inw)) << 32) - div;
- + div = div_u64((difwr + (((u64)input_f) << 32)), 2);
- + left->input_column = truncate(0, div, input_f);
- +
- +
- + /* This splits the truncated input columns evenly */
- + /* between the left and right margins */
- + right->input_column = left->input_column + inw;
- + left->output_column = 0;
- + right->output_column = onw;
- + }
- + if (left->input_width > left->output_width) {
- + if (calc_split_resize_coeffs(left->input_width,
- + left->output_width,
- + &resize_coeff,
- + &downsize_coeff) < 0)
- + return -EINVAL;
- +
- + if (downsize_coeff > 0) {
- + left->irr = right->irr =
- + (downsize_coeff << 14) | resize_coeff;
- + }
- + }
- + pr_debug("inw %d, onw %d, ilw %d, ilc %d, olw %d,"
- + " irw %d, irc %d, orw %d, orc %d, "
- + "difwr %llu, lirr %u\n",
- + inw, onw, left->input_width,
- + left->input_column, left->output_width,
- + right->input_width, right->input_column,
- + right->output_width,
- + right->output_column, difwr, left->irr);
- + } else { /* independent stripes */
- + onw_min = output_frame_width - maximal_stripe_width;
- + /* onw is a multiple of output_f, in the range */
- + /* [max(output_f,output_frame_width-maximal_stripe_width),*/
- + /*min(output_frame_width-2,maximal_stripe_width)] */
- + /* definitely beyond the cost of any valid setting */
- + cost_min = (((u64)input_frame_width) << 32) + cr;
- + onw = truncate(0, ((u64)maximal_stripe_width), output_f);
- + if (output_frame_width - onw == 1)
- + onw -= output_f; /* => onw and output_frame_width-1-onw are positive */
- + inw = truncate(0, onw * irr_opt, input_f);
- + /* this is the maximal inw which allows the same resizing ratio */
- + /* in both stripes */
- + onw = truncate(1, inw * rr_opt, output_f);
- + do {
- + div = div_u64((((u64)(irr_steps * inw)) << 32), onw);
- + left->irr = truncate(0, div, 1);
- + div = div_u64((((u64)(onw * left->irr)) << 32),
- + irr_steps);
- + dinw = (((u64)inw) << 32) - div;
- +
- + div = div_u64((((u64)((output_frame_width - 1 - onw) * left->irr)) <<
- + 32), irr_steps);
- +
- + difwl = (((u64)(input_frame_width - 1 - inw)) << 32) - div;
- +
- + cost = difwl + (((u64)(cr * dinw)) >> 32);
- +
- + if (cost < cost_min) {
- + inw_best = inw;
- + cost_min = cost;
- + }
- +
- + inw -= input_f;
- + onw = truncate(1, inw * rr_opt, output_f);
- + /* This is the minimal onw which allows the same resizing ratio */
- + /* in both stripes */
- + } while (onw >= onw_min);
- +
- + inw = inw_best;
- + onw = truncate(1, inw * rr_opt, output_f);
- + div = div_u64((((u64)(irr_steps * inw)) << 32), onw);
- + left->irr = truncate(0, div, 1);
- +
- + left->output_width = onw;
- + right->output_width = output_frame_width - onw;
- + /* These are valid assignments for output_width, */
- + /* assuming output_f is a multiple of output_m */
- + left->input_width = truncate(1, ((u64)(inw + 1)) << 32, input_m);
- + right->input_width = truncate(1, ((u64)(input_frame_width - inw)) <<
- + 32, input_m);
- +
- + div = div_u64((((u64)(irr_steps * (input_frame_width - 1 - inw))) <<
- + 32), (right->output_width - 1));
- + right->irr = truncate(0, div, 1);
- + temp = truncate(0, ((u64)left->irr) * ((((u64)1) << 32) + dirr), 1);
- + if (temp < right->irr)
- + right->irr = temp;
- + div = div_u64(((u64)((right->output_width - 1) * right->irr) <<
- + 32), irr_steps);
- + difwr = (u64)(input_frame_width - 1 - inw) - div;
- +
- +
- + div = div_u64((difwr + (((u64)input_f) << 32)), 2);
- + left->input_column = truncate(0, div, input_f);
- +
- + /* This splits the truncated input columns evenly */
- + /* between the left and right margins */
- + right->input_column = left->input_column + inw;
- + left->output_column = 0;
- + right->output_column = onw;
- + if (left->input_width > left->output_width) {
- + if (calc_split_resize_coeffs(left->input_width,
- + left->output_width,
- + &resize_coeff,
- + &downsize_coeff) < 0)
- + return -EINVAL;
- + left->irr = (downsize_coeff << 14) | resize_coeff;
- + }
- + if (right->input_width > right->output_width) {
- + if (calc_split_resize_coeffs(right->input_width,
- + right->output_width,
- + &resize_coeff,
- + &downsize_coeff) < 0)
- + return -EINVAL;
- + right->irr = (downsize_coeff << 14) | resize_coeff;
- + }
- + }
- + return status;
- +}
- +EXPORT_SYMBOL(ipu_calc_stripes_sizes);
- diff -Nur linux-3.14.35.orig/drivers/mxc/ipu3/ipu_capture.c linux-3.14.35/drivers/mxc/ipu3/ipu_capture.c
- --- linux-3.14.35.orig/drivers/mxc/ipu3/ipu_capture.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/ipu3/ipu_capture.c 2015-03-08 14:27:37.657684501 -0500
- @@ -0,0 +1,816 @@
- +/*
- + * Copyright 2008-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file ipu_capture.c
- + *
- + * @brief IPU capture dase functions
- + *
- + * @ingroup IPU
- + */
- +#include <linux/clk.h>
- +#include <linux/delay.h>
- +#include <linux/errno.h>
- +#include <linux/init.h>
- +#include <linux/io.h>
- +#include <linux/ipu-v3.h>
- +#include <linux/module.h>
- +#include <linux/spinlock.h>
- +#include <linux/types.h>
- +
- +#include "ipu_prv.h"
- +#include "ipu_regs.h"
- +
- +/*!
- + * _ipu_csi_mclk_set
- + *
- + * @param ipu ipu handler
- + * @param pixel_clk desired pixel clock frequency in Hz
- + * @param csi csi 0 or csi 1
- + *
- + * @return Returns 0 on success or negative error code on fail
- + */
- +int _ipu_csi_mclk_set(struct ipu_soc *ipu, uint32_t pixel_clk, uint32_t csi)
- +{
- + uint32_t temp;
- + uint32_t div_ratio;
- +
- + div_ratio = (clk_get_rate(ipu->ipu_clk) / pixel_clk) - 1;
- +
- + if (div_ratio > 0xFF || div_ratio < 0) {
- + dev_dbg(ipu->dev, "value of pixel_clk extends normal range\n");
- + return -EINVAL;
- + }
- +
- + temp = ipu_csi_read(ipu, csi, CSI_SENS_CONF);
- + temp &= ~CSI_SENS_CONF_DIVRATIO_MASK;
- + ipu_csi_write(ipu, csi, temp |
- + (div_ratio << CSI_SENS_CONF_DIVRATIO_SHIFT),
- + CSI_SENS_CONF);
- +
- + return 0;
- +}
- +
- +/*!
- + * ipu_csi_init_interface
- + * Sets initial values for the CSI registers.
- + * The width and height of the sensor and the actual frame size will be
- + * set to the same values.
- + * @param ipu ipu handler
- + * @param width Sensor width
- + * @param height Sensor height
- + * @param pixel_fmt pixel format
- + * @param cfg_param ipu_csi_signal_cfg_t structure
- + * @param csi csi 0 or csi 1
- + *
- + * @return 0 for success, -EINVAL for error
- + */
- +int32_t
- +ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
- + uint32_t pixel_fmt, ipu_csi_signal_cfg_t cfg_param)
- +{
- + uint32_t data = 0;
- + uint32_t csi = cfg_param.csi;
- +
- + /* Set SENS_DATA_FORMAT bits (8, 9 and 10)
- + RGB or YUV444 is 0 which is current value in data so not set
- + explicitly
- + This is also the default value if attempts are made to set it to
- + something invalid. */
- + switch (pixel_fmt) {
- + case IPU_PIX_FMT_YUYV:
- + cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_YUYV;
- + break;
- + case IPU_PIX_FMT_UYVY:
- + cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_UYVY;
- + break;
- + case IPU_PIX_FMT_RGB24:
- + case IPU_PIX_FMT_BGR24:
- + cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_RGB_YUV444;
- + break;
- + case IPU_PIX_FMT_GENERIC:
- + case IPU_PIX_FMT_GENERIC_16:
- + cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
- + break;
- + case IPU_PIX_FMT_RGB565:
- + cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_RGB565;
- + break;
- + case IPU_PIX_FMT_RGB555:
- + cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_RGB555;
- + break;
- + default:
- + return -EINVAL;
- + }
- +
- + /* Set the CSI_SENS_CONF register remaining fields */
- + data |= cfg_param.data_width << CSI_SENS_CONF_DATA_WIDTH_SHIFT |
- + cfg_param.data_fmt << CSI_SENS_CONF_DATA_FMT_SHIFT |
- + cfg_param.data_pol << CSI_SENS_CONF_DATA_POL_SHIFT |
- + cfg_param.Vsync_pol << CSI_SENS_CONF_VSYNC_POL_SHIFT |
- + cfg_param.Hsync_pol << CSI_SENS_CONF_HSYNC_POL_SHIFT |
- + cfg_param.pixclk_pol << CSI_SENS_CONF_PIX_CLK_POL_SHIFT |
- + cfg_param.ext_vsync << CSI_SENS_CONF_EXT_VSYNC_SHIFT |
- + cfg_param.clk_mode << CSI_SENS_CONF_SENS_PRTCL_SHIFT |
- + cfg_param.pack_tight << CSI_SENS_CONF_PACK_TIGHT_SHIFT |
- + cfg_param.force_eof << CSI_SENS_CONF_FORCE_EOF_SHIFT |
- + cfg_param.data_en_pol << CSI_SENS_CONF_DATA_EN_POL_SHIFT;
- +
- + _ipu_get(ipu);
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + ipu_csi_write(ipu, csi, data, CSI_SENS_CONF);
- +
- + /* Setup sensor frame size */
- + ipu_csi_write(ipu, csi, (width - 1) | (height - 1) << 16, CSI_SENS_FRM_SIZE);
- +
- + /* Set CCIR registers */
- + if (cfg_param.clk_mode == IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE) {
- + ipu_csi_write(ipu, csi, 0x40030, CSI_CCIR_CODE_1);
- + ipu_csi_write(ipu, csi, 0xFF0000, CSI_CCIR_CODE_3);
- + } else if (cfg_param.clk_mode == IPU_CSI_CLK_MODE_CCIR656_INTERLACED) {
- + if (width == 720 && height == 625) {
- + /* PAL case */
- + /*
- + * Field0BlankEnd = 0x6, Field0BlankStart = 0x2,
- + * Field0ActiveEnd = 0x4, Field0ActiveStart = 0
- + */
- + ipu_csi_write(ipu, csi, 0x40596, CSI_CCIR_CODE_1);
- + /*
- + * Field1BlankEnd = 0x7, Field1BlankStart = 0x3,
- + * Field1ActiveEnd = 0x5, Field1ActiveStart = 0x1
- + */
- + ipu_csi_write(ipu, csi, 0xD07DF, CSI_CCIR_CODE_2);
- +
- + ipu_csi_write(ipu, csi, 0xFF0000, CSI_CCIR_CODE_3);
- +
- + } else if (width == 720 && height == 525) {
- + /* NTSC case */
- + /*
- + * Field0BlankEnd = 0x7, Field0BlankStart = 0x3,
- + * Field0ActiveEnd = 0x5, Field0ActiveStart = 0x1
- + */
- + ipu_csi_write(ipu, csi, 0xD07DF, CSI_CCIR_CODE_1);
- + /*
- + * Field1BlankEnd = 0x6, Field1BlankStart = 0x2,
- + * Field1ActiveEnd = 0x4, Field1ActiveStart = 0
- + */
- + ipu_csi_write(ipu, csi, 0x40596, CSI_CCIR_CODE_2);
- + ipu_csi_write(ipu, csi, 0xFF0000, CSI_CCIR_CODE_3);
- + } else {
- + dev_err(ipu->dev, "Unsupported CCIR656 interlaced "
- + "video mode\n");
- + mutex_unlock(&ipu->mutex_lock);
- + _ipu_put(ipu);
- + return -EINVAL;
- + }
- + _ipu_csi_ccir_err_detection_enable(ipu, csi);
- + } else if ((cfg_param.clk_mode ==
- + IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR) ||
- + (cfg_param.clk_mode ==
- + IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR) ||
- + (cfg_param.clk_mode ==
- + IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR) ||
- + (cfg_param.clk_mode ==
- + IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR)) {
- + ipu_csi_write(ipu, csi, 0x40030, CSI_CCIR_CODE_1);
- + ipu_csi_write(ipu, csi, 0xFF0000, CSI_CCIR_CODE_3);
- + _ipu_csi_ccir_err_detection_enable(ipu, csi);
- + } else if ((cfg_param.clk_mode == IPU_CSI_CLK_MODE_GATED_CLK) ||
- + (cfg_param.clk_mode == IPU_CSI_CLK_MODE_NONGATED_CLK)) {
- + _ipu_csi_ccir_err_detection_disable(ipu, csi);
- + }
- +
- + dev_dbg(ipu->dev, "CSI_SENS_CONF = 0x%08X\n",
- + ipu_csi_read(ipu, csi, CSI_SENS_CONF));
- + dev_dbg(ipu->dev, "CSI_ACT_FRM_SIZE = 0x%08X\n",
- + ipu_csi_read(ipu, csi, CSI_ACT_FRM_SIZE));
- +
- + mutex_unlock(&ipu->mutex_lock);
- +
- + _ipu_put(ipu);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(ipu_csi_init_interface);
- +
- +/*!
- + * ipu_csi_get_sensor_protocol
- + *
- + * @param ipu ipu handler
- + * @param csi csi 0 or csi 1
- + *
- + * @return Returns sensor protocol
- + */
- +int32_t ipu_csi_get_sensor_protocol(struct ipu_soc *ipu, uint32_t csi)
- +{
- + int ret;
- + _ipu_get(ipu);
- + ret = (ipu_csi_read(ipu, csi, CSI_SENS_CONF) &
- + CSI_SENS_CONF_SENS_PRTCL_MASK) >>
- + CSI_SENS_CONF_SENS_PRTCL_SHIFT;
- + _ipu_put(ipu);
- + return ret;
- +}
- +EXPORT_SYMBOL(ipu_csi_get_sensor_protocol);
- +
- +/*!
- + * ipu_csi_enable_mclk
- + *
- + * @param ipu ipu handler
- + * @param csi csi 0 or csi 1
- + * @param flag true to enable mclk, false to disable mclk
- + * @param wait true to wait 100ms make clock stable, false not wait
- + *
- + * @return Returns 0 on success
- + */
- +int ipu_csi_enable_mclk(struct ipu_soc *ipu, int csi, bool flag, bool wait)
- +{
- + /* Return immediately if there is no csi_clk to manage */
- + if (ipu->csi_clk[csi] == NULL)
- + return 0;
- +
- + if (flag) {
- + clk_enable(ipu->csi_clk[csi]);
- + if (wait == true)
- + msleep(10);
- + } else {
- + clk_disable(ipu->csi_clk[csi]);
- + }
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(ipu_csi_enable_mclk);
- +
- +/*!
- + * ipu_csi_get_window_size
- + *
- + * @param ipu ipu handler
- + * @param width pointer to window width
- + * @param height pointer to window height
- + * @param csi csi 0 or csi 1
- + */
- +void ipu_csi_get_window_size(struct ipu_soc *ipu, uint32_t *width, uint32_t *height, uint32_t csi)
- +{
- + uint32_t reg;
- +
- + _ipu_get(ipu);
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + reg = ipu_csi_read(ipu, csi, CSI_ACT_FRM_SIZE);
- + *width = (reg & 0xFFFF) + 1;
- + *height = (reg >> 16 & 0xFFFF) + 1;
- +
- + mutex_unlock(&ipu->mutex_lock);
- +
- + _ipu_put(ipu);
- +}
- +EXPORT_SYMBOL(ipu_csi_get_window_size);
- +
- +/*!
- + * ipu_csi_set_window_size
- + *
- + * @param ipu ipu handler
- + * @param width window width
- + * @param height window height
- + * @param csi csi 0 or csi 1
- + */
- +void ipu_csi_set_window_size(struct ipu_soc *ipu, uint32_t width, uint32_t height, uint32_t csi)
- +{
- + _ipu_get(ipu);
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + ipu_csi_write(ipu, csi, (width - 1) | (height - 1) << 16, CSI_ACT_FRM_SIZE);
- +
- + mutex_unlock(&ipu->mutex_lock);
- +
- + _ipu_put(ipu);
- +}
- +EXPORT_SYMBOL(ipu_csi_set_window_size);
- +
- +/*!
- + * ipu_csi_set_window_pos
- + *
- + * @param ipu ipu handler
- + * @param left uint32 window x start
- + * @param top uint32 window y start
- + * @param csi csi 0 or csi 1
- + */
- +void ipu_csi_set_window_pos(struct ipu_soc *ipu, uint32_t left, uint32_t top, uint32_t csi)
- +{
- + uint32_t temp;
- +
- + _ipu_get(ipu);
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
- + temp &= ~(CSI_HSC_MASK | CSI_VSC_MASK);
- + temp |= ((top << CSI_VSC_SHIFT) | (left << CSI_HSC_SHIFT));
- + ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
- +
- + mutex_unlock(&ipu->mutex_lock);
- +
- + _ipu_put(ipu);
- +}
- +EXPORT_SYMBOL(ipu_csi_set_window_pos);
- +
- +/*!
- + * _ipu_csi_horizontal_downsize_enable
- + * Enable horizontal downsizing(decimation) by 2.
- + *
- + * @param ipu ipu handler
- + * @param csi csi 0 or csi 1
- + */
- +void _ipu_csi_horizontal_downsize_enable(struct ipu_soc *ipu, uint32_t csi)
- +{
- + uint32_t temp;
- +
- + temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
- + temp |= CSI_HORI_DOWNSIZE_EN;
- + ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
- +}
- +
- +/*!
- + * _ipu_csi_horizontal_downsize_disable
- + * Disable horizontal downsizing(decimation) by 2.
- + *
- + * @param ipu ipu handler
- + * @param csi csi 0 or csi 1
- + */
- +void _ipu_csi_horizontal_downsize_disable(struct ipu_soc *ipu, uint32_t csi)
- +{
- + uint32_t temp;
- +
- + temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
- + temp &= ~CSI_HORI_DOWNSIZE_EN;
- + ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
- +}
- +
- +/*!
- + * _ipu_csi_vertical_downsize_enable
- + * Enable vertical downsizing(decimation) by 2.
- + *
- + * @param ipu ipu handler
- + * @param csi csi 0 or csi 1
- + */
- +void _ipu_csi_vertical_downsize_enable(struct ipu_soc *ipu, uint32_t csi)
- +{
- + uint32_t temp;
- +
- + temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
- + temp |= CSI_VERT_DOWNSIZE_EN;
- + ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
- +}
- +
- +/*!
- + * _ipu_csi_vertical_downsize_disable
- + * Disable vertical downsizing(decimation) by 2.
- + *
- + * @param ipu ipu handler
- + * @param csi csi 0 or csi 1
- + */
- +void _ipu_csi_vertical_downsize_disable(struct ipu_soc *ipu, uint32_t csi)
- +{
- + uint32_t temp;
- +
- + temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
- + temp &= ~CSI_VERT_DOWNSIZE_EN;
- + ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
- +}
- +
- +/*!
- + * _ipu_csi_set_test_generator
- + *
- + * @param ipu ipu handler
- + * @param active 1 for active and 0 for inactive
- + * @param r_value red value for the generated pattern of even pixel
- + * @param g_value green value for the generated pattern of even
- + * pixel
- + * @param b_value blue value for the generated pattern of even pixel
- + * @param pixel_clk desired pixel clock frequency in Hz
- + * @param csi csi 0 or csi 1
- + */
- +void _ipu_csi_set_test_generator(struct ipu_soc *ipu, bool active, uint32_t r_value,
- + uint32_t g_value, uint32_t b_value, uint32_t pix_clk, uint32_t csi)
- +{
- + uint32_t temp;
- +
- + temp = ipu_csi_read(ipu, csi, CSI_TST_CTRL);
- +
- + if (active == false) {
- + temp &= ~CSI_TEST_GEN_MODE_EN;
- + ipu_csi_write(ipu, csi, temp, CSI_TST_CTRL);
- + } else {
- + /* Set sensb_mclk div_ratio*/
- + _ipu_csi_mclk_set(ipu, pix_clk, csi);
- +
- + temp &= ~(CSI_TEST_GEN_R_MASK | CSI_TEST_GEN_G_MASK |
- + CSI_TEST_GEN_B_MASK);
- + temp |= CSI_TEST_GEN_MODE_EN;
- + temp |= (r_value << CSI_TEST_GEN_R_SHIFT) |
- + (g_value << CSI_TEST_GEN_G_SHIFT) |
- + (b_value << CSI_TEST_GEN_B_SHIFT);
- + ipu_csi_write(ipu, csi, temp, CSI_TST_CTRL);
- + }
- +}
- +
- +/*!
- + * _ipu_csi_ccir_err_detection_en
- + * Enable error detection and correction for
- + * CCIR interlaced mode with protection bit.
- + *
- + * @param ipu ipu handler
- + * @param csi csi 0 or csi 1
- + */
- +void _ipu_csi_ccir_err_detection_enable(struct ipu_soc *ipu, uint32_t csi)
- +{
- + uint32_t temp;
- +
- + temp = ipu_csi_read(ipu, csi, CSI_CCIR_CODE_1);
- + temp |= CSI_CCIR_ERR_DET_EN;
- + ipu_csi_write(ipu, csi, temp, CSI_CCIR_CODE_1);
- +
- +}
- +
- +/*!
- + * _ipu_csi_ccir_err_detection_disable
- + * Disable error detection and correction for
- + * CCIR interlaced mode with protection bit.
- + *
- + * @param ipu ipu handler
- + * @param csi csi 0 or csi 1
- + */
- +void _ipu_csi_ccir_err_detection_disable(struct ipu_soc *ipu, uint32_t csi)
- +{
- + uint32_t temp;
- +
- + temp = ipu_csi_read(ipu, csi, CSI_CCIR_CODE_1);
- + temp &= ~CSI_CCIR_ERR_DET_EN;
- + ipu_csi_write(ipu, csi, temp, CSI_CCIR_CODE_1);
- +
- +}
- +
- +/*!
- + * _ipu_csi_set_mipi_di
- + *
- + * @param ipu ipu handler
- + * @param num MIPI data identifier 0-3 handled by CSI
- + * @param di_val data identifier value
- + * @param csi csi 0 or csi 1
- + *
- + * @return Returns 0 on success or negative error code on fail
- + */
- +int _ipu_csi_set_mipi_di(struct ipu_soc *ipu, uint32_t num, uint32_t di_val, uint32_t csi)
- +{
- + uint32_t temp;
- + int retval = 0;
- +
- + if (di_val > 0xFFL) {
- + retval = -EINVAL;
- + goto err;
- + }
- +
- + temp = ipu_csi_read(ipu, csi, CSI_MIPI_DI);
- +
- + switch (num) {
- + case IPU_CSI_MIPI_DI0:
- + temp &= ~CSI_MIPI_DI0_MASK;
- + temp |= (di_val << CSI_MIPI_DI0_SHIFT);
- + ipu_csi_write(ipu, csi, temp, CSI_MIPI_DI);
- + break;
- + case IPU_CSI_MIPI_DI1:
- + temp &= ~CSI_MIPI_DI1_MASK;
- + temp |= (di_val << CSI_MIPI_DI1_SHIFT);
- + ipu_csi_write(ipu, csi, temp, CSI_MIPI_DI);
- + break;
- + case IPU_CSI_MIPI_DI2:
- + temp &= ~CSI_MIPI_DI2_MASK;
- + temp |= (di_val << CSI_MIPI_DI2_SHIFT);
- + ipu_csi_write(ipu, csi, temp, CSI_MIPI_DI);
- + break;
- + case IPU_CSI_MIPI_DI3:
- + temp &= ~CSI_MIPI_DI3_MASK;
- + temp |= (di_val << CSI_MIPI_DI3_SHIFT);
- + ipu_csi_write(ipu, csi, temp, CSI_MIPI_DI);
- + break;
- + default:
- + retval = -EINVAL;
- + }
- +
- +err:
- + return retval;
- +}
- +
- +/*!
- + * _ipu_csi_set_skip_isp
- + *
- + * @param ipu ipu handler
- + * @param skip select frames to be skipped and set the
- + * correspond bits to 1
- + * @param max_ratio number of frames in a skipping set and the
- + * maximum value of max_ratio is 5
- + * @param csi csi 0 or csi 1
- + *
- + * @return Returns 0 on success or negative error code on fail
- + */
- +int _ipu_csi_set_skip_isp(struct ipu_soc *ipu, uint32_t skip, uint32_t max_ratio, uint32_t csi)
- +{
- + uint32_t temp;
- + int retval = 0;
- +
- + if (max_ratio > 5) {
- + retval = -EINVAL;
- + goto err;
- + }
- +
- + temp = ipu_csi_read(ipu, csi, CSI_SKIP);
- + temp &= ~(CSI_MAX_RATIO_SKIP_ISP_MASK | CSI_SKIP_ISP_MASK);
- + temp |= (max_ratio << CSI_MAX_RATIO_SKIP_ISP_SHIFT) |
- + (skip << CSI_SKIP_ISP_SHIFT);
- + ipu_csi_write(ipu, csi, temp, CSI_SKIP);
- +
- +err:
- + return retval;
- +}
- +
- +/*!
- + * _ipu_csi_set_skip_smfc
- + *
- + * @param ipu ipu handler
- + * @param skip select frames to be skipped and set the
- + * correspond bits to 1
- + * @param max_ratio number of frames in a skipping set and the
- + * maximum value of max_ratio is 5
- + * @param id csi to smfc skipping id
- + * @param csi csi 0 or csi 1
- + *
- + * @return Returns 0 on success or negative error code on fail
- + */
- +int _ipu_csi_set_skip_smfc(struct ipu_soc *ipu, uint32_t skip,
- + uint32_t max_ratio, uint32_t id, uint32_t csi)
- +{
- + uint32_t temp;
- + int retval = 0;
- +
- + if (max_ratio > 5 || id > 3) {
- + retval = -EINVAL;
- + goto err;
- + }
- +
- + temp = ipu_csi_read(ipu, csi, CSI_SKIP);
- + temp &= ~(CSI_MAX_RATIO_SKIP_SMFC_MASK | CSI_ID_2_SKIP_MASK |
- + CSI_SKIP_SMFC_MASK);
- + temp |= (max_ratio << CSI_MAX_RATIO_SKIP_SMFC_SHIFT) |
- + (id << CSI_ID_2_SKIP_SHIFT) |
- + (skip << CSI_SKIP_SMFC_SHIFT);
- + ipu_csi_write(ipu, csi, temp, CSI_SKIP);
- +
- +err:
- + return retval;
- +}
- +
- +/*!
- + * _ipu_smfc_init
- + * Map CSI frames to IDMAC channels.
- + *
- + * @param ipu ipu handler
- + * @param channel IDMAC channel 0-3
- + * @param mipi_id mipi id number 0-3
- + * @param csi csi0 or csi1
- + */
- +void _ipu_smfc_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t mipi_id, uint32_t csi)
- +{
- + uint32_t temp;
- +
- + temp = ipu_smfc_read(ipu, SMFC_MAP);
- +
- + switch (channel) {
- + case CSI_MEM0:
- + temp &= ~SMFC_MAP_CH0_MASK;
- + temp |= ((csi << 2) | mipi_id) << SMFC_MAP_CH0_SHIFT;
- + break;
- + case CSI_MEM1:
- + temp &= ~SMFC_MAP_CH1_MASK;
- + temp |= ((csi << 2) | mipi_id) << SMFC_MAP_CH1_SHIFT;
- + break;
- + case CSI_MEM2:
- + temp &= ~SMFC_MAP_CH2_MASK;
- + temp |= ((csi << 2) | mipi_id) << SMFC_MAP_CH2_SHIFT;
- + break;
- + case CSI_MEM3:
- + temp &= ~SMFC_MAP_CH3_MASK;
- + temp |= ((csi << 2) | mipi_id) << SMFC_MAP_CH3_SHIFT;
- + break;
- + default:
- + return;
- + }
- +
- + ipu_smfc_write(ipu, temp, SMFC_MAP);
- +}
- +
- +/*!
- + * _ipu_smfc_set_wmc
- + * Caution: The number of required channels, the enabled channels
- + * and the FIFO size per channel are configured restrictedly.
- + *
- + * @param ipu ipu handler
- + * @param channel IDMAC channel 0-3
- + * @param set set 1 or clear 0
- + * @param level water mark level when FIFO is on the
- + * relative size
- + */
- +void _ipu_smfc_set_wmc(struct ipu_soc *ipu, ipu_channel_t channel, bool set, uint32_t level)
- +{
- + uint32_t temp;
- +
- + temp = ipu_smfc_read(ipu, SMFC_WMC);
- +
- + switch (channel) {
- + case CSI_MEM0:
- + if (set == true) {
- + temp &= ~SMFC_WM0_SET_MASK;
- + temp |= level << SMFC_WM0_SET_SHIFT;
- + } else {
- + temp &= ~SMFC_WM0_CLR_MASK;
- + temp |= level << SMFC_WM0_CLR_SHIFT;
- + }
- + break;
- + case CSI_MEM1:
- + if (set == true) {
- + temp &= ~SMFC_WM1_SET_MASK;
- + temp |= level << SMFC_WM1_SET_SHIFT;
- + } else {
- + temp &= ~SMFC_WM1_CLR_MASK;
- + temp |= level << SMFC_WM1_CLR_SHIFT;
- + }
- + break;
- + case CSI_MEM2:
- + if (set == true) {
- + temp &= ~SMFC_WM2_SET_MASK;
- + temp |= level << SMFC_WM2_SET_SHIFT;
- + } else {
- + temp &= ~SMFC_WM2_CLR_MASK;
- + temp |= level << SMFC_WM2_CLR_SHIFT;
- + }
- + break;
- + case CSI_MEM3:
- + if (set == true) {
- + temp &= ~SMFC_WM3_SET_MASK;
- + temp |= level << SMFC_WM3_SET_SHIFT;
- + } else {
- + temp &= ~SMFC_WM3_CLR_MASK;
- + temp |= level << SMFC_WM3_CLR_SHIFT;
- + }
- + break;
- + default:
- + return;
- + }
- +
- + ipu_smfc_write(ipu, temp, SMFC_WMC);
- +}
- +
- +/*!
- + * _ipu_smfc_set_burst_size
- + *
- + * @param ipu ipu handler
- + * @param channel IDMAC channel 0-3
- + * @param bs burst size of IDMAC channel,
- + * the value programmed here shoud be BURST_SIZE-1
- + */
- +void _ipu_smfc_set_burst_size(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t bs)
- +{
- + uint32_t temp;
- +
- + temp = ipu_smfc_read(ipu, SMFC_BS);
- +
- + switch (channel) {
- + case CSI_MEM0:
- + temp &= ~SMFC_BS0_MASK;
- + temp |= bs << SMFC_BS0_SHIFT;
- + break;
- + case CSI_MEM1:
- + temp &= ~SMFC_BS1_MASK;
- + temp |= bs << SMFC_BS1_SHIFT;
- + break;
- + case CSI_MEM2:
- + temp &= ~SMFC_BS2_MASK;
- + temp |= bs << SMFC_BS2_SHIFT;
- + break;
- + case CSI_MEM3:
- + temp &= ~SMFC_BS3_MASK;
- + temp |= bs << SMFC_BS3_SHIFT;
- + break;
- + default:
- + return;
- + }
- +
- + ipu_smfc_write(ipu, temp, SMFC_BS);
- +}
- +
- +/*!
- + * _ipu_csi_init
- + *
- + * @param ipu ipu handler
- + * @param channel IDMAC channel
- + * @param csi csi 0 or csi 1
- + *
- + * @return Returns 0 on success or negative error code on fail
- + */
- +int _ipu_csi_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t csi)
- +{
- + uint32_t csi_sens_conf, csi_dest;
- + int retval = 0;
- +
- + switch (channel) {
- + case CSI_MEM0:
- + case CSI_MEM1:
- + case CSI_MEM2:
- + case CSI_MEM3:
- + csi_dest = CSI_DATA_DEST_IDMAC;
- + break;
- + case CSI_PRP_ENC_MEM:
- + case CSI_PRP_VF_MEM:
- + csi_dest = CSI_DATA_DEST_IC;
- + break;
- + default:
- + retval = -EINVAL;
- + goto err;
- + }
- +
- + csi_sens_conf = ipu_csi_read(ipu, csi, CSI_SENS_CONF);
- + csi_sens_conf &= ~CSI_SENS_CONF_DATA_DEST_MASK;
- + ipu_csi_write(ipu, csi, csi_sens_conf | (csi_dest <<
- + CSI_SENS_CONF_DATA_DEST_SHIFT), CSI_SENS_CONF);
- +err:
- + return retval;
- +}
- +
- +/*!
- + * csi_irq_handler
- + *
- + * @param irq interrupt id
- + * @param dev_id pointer to ipu handler
- + *
- + * @return Returns if irq is handled
- + */
- +static irqreturn_t csi_irq_handler(int irq, void *dev_id)
- +{
- + struct ipu_soc *ipu = dev_id;
- + struct completion *comp = &ipu->csi_comp;
- +
- + complete(comp);
- + return IRQ_HANDLED;
- +}
- +
- +/*!
- + * _ipu_csi_wait4eof
- + *
- + * @param ipu ipu handler
- + * @param channel IDMAC channel
- + *
- + */
- +void _ipu_csi_wait4eof(struct ipu_soc *ipu, ipu_channel_t channel)
- +{
- + int ret;
- + int irq = 0;
- +
- + if (channel == CSI_MEM0)
- + irq = IPU_IRQ_CSI0_OUT_EOF;
- + else if (channel == CSI_MEM1)
- + irq = IPU_IRQ_CSI1_OUT_EOF;
- + else if (channel == CSI_MEM2)
- + irq = IPU_IRQ_CSI2_OUT_EOF;
- + else if (channel == CSI_MEM3)
- + irq = IPU_IRQ_CSI3_OUT_EOF;
- + else if (channel == CSI_PRP_ENC_MEM)
- + irq = IPU_IRQ_PRP_ENC_OUT_EOF;
- + else if (channel == CSI_PRP_VF_MEM)
- + irq = IPU_IRQ_PRP_VF_OUT_EOF;
- + else{
- + dev_err(ipu->dev, "Not a CSI channel\n");
- + return;
- + }
- +
- + init_completion(&ipu->csi_comp);
- + ret = ipu_request_irq(ipu, irq, csi_irq_handler, 0, NULL, ipu);
- + if (ret < 0) {
- + dev_err(ipu->dev, "CSI irq %d in use\n", irq);
- + return;
- + }
- + ret = wait_for_completion_timeout(&ipu->csi_comp, msecs_to_jiffies(500));
- + ipu_free_irq(ipu, irq, ipu);
- + dev_dbg(ipu->dev, "CSI stop timeout - %d * 10ms\n", 5 - ret);
- +}
- diff -Nur linux-3.14.35.orig/drivers/mxc/ipu3/ipu_common.c linux-3.14.35/drivers/mxc/ipu3/ipu_common.c
- --- linux-3.14.35.orig/drivers/mxc/ipu3/ipu_common.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/ipu3/ipu_common.c 2015-03-08 14:27:37.661684500 -0500
- @@ -0,0 +1,3134 @@
- +/*
- + * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file ipu_common.c
- + *
- + * @brief This file contains the IPU driver common API functions.
- + *
- + * @ingroup IPU
- + */
- +#include <linux/busfreq-imx6.h>
- +#include <linux/clk.h>
- +#include <linux/clk-provider.h>
- +#include <linux/delay.h>
- +#include <linux/err.h>
- +#include <linux/init.h>
- +#include <linux/interrupt.h>
- +#include <linux/io.h>
- +#include <linux/ipu-v3.h>
- +#include <linux/irq.h>
- +#include <linux/irqdesc.h>
- +#include <linux/module.h>
- +#include <linux/mod_devicetable.h>
- +#include <linux/of_device.h>
- +#include <linux/platform_device.h>
- +#include <linux/pm_runtime.h>
- +#include <linux/reset.h>
- +#include <linux/spinlock.h>
- +#include <linux/types.h>
- +
- +#include <asm/cacheflush.h>
- +
- +#include "ipu_param_mem.h"
- +#include "ipu_regs.h"
- +
- +static struct ipu_soc ipu_array[MXC_IPU_MAX_NUM];
- +int g_ipu_hw_rev;
- +
- +/* Static functions */
- +static irqreturn_t ipu_sync_irq_handler(int irq, void *desc);
- +static irqreturn_t ipu_err_irq_handler(int irq, void *desc);
- +
- +static inline uint32_t channel_2_dma(ipu_channel_t ch, ipu_buffer_t type)
- +{
- + return ((uint32_t) ch >> (6 * type)) & 0x3F;
- +};
- +
- +static inline int _ipu_is_ic_chan(uint32_t dma_chan)
- +{
- + return (((dma_chan >= 11) && (dma_chan <= 22) && (dma_chan != 17) &&
- + (dma_chan != 18)));
- +}
- +
- +static inline int _ipu_is_vdi_out_chan(uint32_t dma_chan)
- +{
- + return (dma_chan == 5);
- +}
- +
- +static inline int _ipu_is_ic_graphic_chan(uint32_t dma_chan)
- +{
- + return (dma_chan == 14 || dma_chan == 15);
- +}
- +
- +/* Either DP BG or DP FG can be graphic window */
- +static inline int _ipu_is_dp_graphic_chan(uint32_t dma_chan)
- +{
- + return (dma_chan == 23 || dma_chan == 27);
- +}
- +
- +static inline int _ipu_is_irt_chan(uint32_t dma_chan)
- +{
- + return ((dma_chan >= 45) && (dma_chan <= 50));
- +}
- +
- +static inline int _ipu_is_dmfc_chan(uint32_t dma_chan)
- +{
- + return ((dma_chan >= 23) && (dma_chan <= 29));
- +}
- +
- +static inline int _ipu_is_smfc_chan(uint32_t dma_chan)
- +{
- + return ((dma_chan >= 0) && (dma_chan <= 3));
- +}
- +
- +static inline int _ipu_is_trb_chan(uint32_t dma_chan)
- +{
- + return (((dma_chan == 8) || (dma_chan == 9) ||
- + (dma_chan == 10) || (dma_chan == 13) ||
- + (dma_chan == 21) || (dma_chan == 23) ||
- + (dma_chan == 27) || (dma_chan == 28)) &&
- + (g_ipu_hw_rev >= IPU_V3DEX));
- +}
- +
- +/*
- + * We usually use IDMAC 23 as full plane and IDMAC 27 as partial
- + * plane.
- + * IDMAC 23/24/28/41 can drive a display respectively - primary
- + * IDMAC 27 depends on IDMAC 23 - nonprimary
- + */
- +static inline int _ipu_is_primary_disp_chan(uint32_t dma_chan)
- +{
- + return ((dma_chan == 23) || (dma_chan == 24) ||
- + (dma_chan == 28) || (dma_chan == 41));
- +}
- +
- +static inline int _ipu_is_sync_irq(uint32_t irq)
- +{
- + /* sync interrupt register number */
- + int reg_num = irq / 32 + 1;
- +
- + return ((reg_num == 1) || (reg_num == 2) || (reg_num == 3) ||
- + (reg_num == 4) || (reg_num == 7) || (reg_num == 8) ||
- + (reg_num == 11) || (reg_num == 12) || (reg_num == 13) ||
- + (reg_num == 14) || (reg_num == 15));
- +}
- +
- +#define idma_is_valid(ch) (ch != NO_DMA)
- +#define idma_mask(ch) (idma_is_valid(ch) ? (1UL << (ch & 0x1F)) : 0)
- +#define idma_is_set(ipu, reg, dma) (ipu_idmac_read(ipu, reg(dma)) & idma_mask(dma))
- +#define tri_cur_buf_mask(ch) (idma_mask(ch*2) * 3)
- +#define tri_cur_buf_shift(ch) (ffs(idma_mask(ch*2)) - 1)
- +
- +static int ipu_clk_setup_enable(struct ipu_soc *ipu,
- + struct ipu_pltfm_data *pdata)
- +{
- + char pixel_clk_0[] = "ipu1_pclk_0";
- + char pixel_clk_1[] = "ipu1_pclk_1";
- + char pixel_clk_0_sel[] = "ipu1_pclk0_sel";
- + char pixel_clk_1_sel[] = "ipu1_pclk1_sel";
- + char pixel_clk_0_div[] = "ipu1_pclk0_div";
- + char pixel_clk_1_div[] = "ipu1_pclk1_div";
- + char *ipu_pixel_clk_sel[] = { "ipu1", "ipu1_di0", "ipu1_di1", };
- + char *pclk_sel;
- + struct clk *clk;
- + int ret;
- + int i;
- +
- + pixel_clk_0[3] += pdata->id;
- + pixel_clk_1[3] += pdata->id;
- + pixel_clk_0_sel[3] += pdata->id;
- + pixel_clk_1_sel[3] += pdata->id;
- + pixel_clk_0_div[3] += pdata->id;
- + pixel_clk_1_div[3] += pdata->id;
- + for (i = 0; i < ARRAY_SIZE(ipu_pixel_clk_sel); i++) {
- + pclk_sel = ipu_pixel_clk_sel[i];
- + pclk_sel[3] += pdata->id;
- + }
- + dev_dbg(ipu->dev, "ipu_clk = %lu\n", clk_get_rate(ipu->ipu_clk));
- +
- + clk = clk_register_mux_pix_clk(ipu->dev, pixel_clk_0_sel,
- + (const char **)ipu_pixel_clk_sel,
- + ARRAY_SIZE(ipu_pixel_clk_sel),
- + 0, pdata->id, 0, 0);
- + if (IS_ERR(clk)) {
- + dev_err(ipu->dev, "clk_register mux di0 failed");
- + return PTR_ERR(clk);
- + }
- + ipu->pixel_clk_sel[0] = clk;
- + clk = clk_register_mux_pix_clk(ipu->dev, pixel_clk_1_sel,
- + (const char **)ipu_pixel_clk_sel,
- + ARRAY_SIZE(ipu_pixel_clk_sel),
- + 0, pdata->id, 1, 0);
- + if (IS_ERR(clk)) {
- + dev_err(ipu->dev, "clk_register mux di1 failed");
- + return PTR_ERR(clk);
- + }
- + ipu->pixel_clk_sel[1] = clk;
- +
- + clk = clk_register_div_pix_clk(ipu->dev, pixel_clk_0_div,
- + pixel_clk_0_sel, 0, pdata->id, 0, 0);
- + if (IS_ERR(clk)) {
- + dev_err(ipu->dev, "clk register di0 div failed");
- + return PTR_ERR(clk);
- + }
- + clk = clk_register_div_pix_clk(ipu->dev, pixel_clk_1_div,
- + pixel_clk_1_sel, CLK_SET_RATE_PARENT, pdata->id, 1, 0);
- + if (IS_ERR(clk)) {
- + dev_err(ipu->dev, "clk register di1 div failed");
- + return PTR_ERR(clk);
- + }
- +
- + ipu->pixel_clk[0] = clk_register_gate_pix_clk(ipu->dev, pixel_clk_0,
- + pixel_clk_0_div, CLK_SET_RATE_PARENT,
- + pdata->id, 0, 0);
- + if (IS_ERR(ipu->pixel_clk[0])) {
- + dev_err(ipu->dev, "clk register di0 gate failed");
- + return PTR_ERR(ipu->pixel_clk[0]);
- + }
- + ipu->pixel_clk[1] = clk_register_gate_pix_clk(ipu->dev, pixel_clk_1,
- + pixel_clk_1_div, CLK_SET_RATE_PARENT,
- + pdata->id, 1, 0);
- + if (IS_ERR(ipu->pixel_clk[1])) {
- + dev_err(ipu->dev, "clk register di1 gate failed");
- + return PTR_ERR(ipu->pixel_clk[1]);
- + }
- +
- + ret = clk_set_parent(ipu->pixel_clk_sel[0], ipu->ipu_clk);
- + if (ret) {
- + dev_err(ipu->dev, "clk set parent failed");
- + return ret;
- + }
- +
- + ret = clk_set_parent(ipu->pixel_clk_sel[1], ipu->ipu_clk);
- + if (ret) {
- + dev_err(ipu->dev, "clk set parent failed");
- + return ret;
- + }
- +
- + ipu->di_clk[0] = devm_clk_get(ipu->dev, "di0");
- + if (IS_ERR(ipu->di_clk[0])) {
- + dev_err(ipu->dev, "clk_get di0 failed");
- + return PTR_ERR(ipu->di_clk[0]);
- + }
- + ipu->di_clk[1] = devm_clk_get(ipu->dev, "di1");
- + if (IS_ERR(ipu->di_clk[1])) {
- + dev_err(ipu->dev, "clk_get di1 failed");
- + return PTR_ERR(ipu->di_clk[1]);
- + }
- +
- + ipu->di_clk_sel[0] = devm_clk_get(ipu->dev, "di0_sel");
- + if (IS_ERR(ipu->di_clk_sel[0])) {
- + dev_err(ipu->dev, "clk_get di0_sel failed");
- + return PTR_ERR(ipu->di_clk_sel[0]);
- + }
- + ipu->di_clk_sel[1] = devm_clk_get(ipu->dev, "di1_sel");
- + if (IS_ERR(ipu->di_clk_sel[1])) {
- + dev_err(ipu->dev, "clk_get di1_sel failed");
- + return PTR_ERR(ipu->di_clk_sel[1]);
- + }
- +
- + return 0;
- +}
- +
- +static int ipu_mem_reset(struct ipu_soc *ipu)
- +{
- + int timeout = 1000;
- +
- + ipu_cm_write(ipu, 0x807FFFFF, IPU_MEM_RST);
- +
- + while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x80000000) {
- + if (!timeout--)
- + return -ETIME;
- + msleep(1);
- + }
- +
- + return 0;
- +}
- +
- +struct ipu_soc *ipu_get_soc(int id)
- +{
- + if (id >= MXC_IPU_MAX_NUM)
- + return ERR_PTR(-ENODEV);
- + else if (!ipu_array[id].online)
- + return ERR_PTR(-ENODEV);
- + else
- + return &(ipu_array[id]);
- +}
- +EXPORT_SYMBOL_GPL(ipu_get_soc);
- +
- +void _ipu_get(struct ipu_soc *ipu)
- +{
- + int ret;
- +
- + ret = clk_enable(ipu->ipu_clk);
- + if (ret < 0)
- + BUG();
- +}
- +
- +void _ipu_put(struct ipu_soc *ipu)
- +{
- + clk_disable(ipu->ipu_clk);
- +}
- +
- +void ipu_disable_hsp_clk(struct ipu_soc *ipu)
- +{
- + _ipu_put(ipu);
- +}
- +EXPORT_SYMBOL(ipu_disable_hsp_clk);
- +
- +static struct platform_device_id imx_ipu_type[] = {
- + {
- + .name = "ipu-imx6q",
- + .driver_data = IPU_V3H,
- + }, {
- + /* sentinel */
- + }
- +};
- +MODULE_DEVICE_TABLE(platform, imx_ipu_type);
- +
- +static const struct of_device_id imx_ipuv3_dt_ids[] = {
- + { .compatible = "fsl,imx6q-ipu", .data = &imx_ipu_type[IMX6Q_IPU], },
- + { /* sentinel */ }
- +};
- +MODULE_DEVICE_TABLE(of, imx_ipuv3_dt_ids);
- +
- +/*!
- + * This function is called by the driver framework to initialize the IPU
- + * hardware.
- + *
- + * @param dev The device structure for the IPU passed in by the
- + * driver framework.
- + *
- + * @return Returns 0 on success or negative error code on error
- + */
- +static int ipu_probe(struct platform_device *pdev)
- +{
- + struct ipu_soc *ipu;
- + struct resource *res;
- + unsigned long ipu_base;
- + const struct of_device_id *of_id =
- + of_match_device(imx_ipuv3_dt_ids, &pdev->dev);
- + struct ipu_pltfm_data *pltfm_data;
- + int ret = 0;
- + u32 bypass_reset;
- +
- + dev_dbg(&pdev->dev, "<%s>\n", __func__);
- +
- + pltfm_data = devm_kzalloc(&pdev->dev, sizeof(struct ipu_pltfm_data),
- + GFP_KERNEL);
- + if (!pltfm_data)
- + return -ENOMEM;
- +
- + ret = of_property_read_u32(pdev->dev.of_node,
- + "bypass_reset", &bypass_reset);
- + if (ret < 0) {
- + dev_dbg(&pdev->dev, "can not get bypass_reset\n");
- + return ret;
- + }
- + pltfm_data->bypass_reset = (bool)bypass_reset;
- +
- + pltfm_data->id = of_alias_get_id(pdev->dev.of_node, "ipu");
- + if (pltfm_data->id < 0) {
- + dev_dbg(&pdev->dev, "can not get alias id\n");
- + return pltfm_data->id;
- + }
- +
- + if (of_id)
- + pdev->id_entry = of_id->data;
- + pltfm_data->devtype = pdev->id_entry->driver_data;
- + g_ipu_hw_rev = pltfm_data->devtype;
- +
- + ipu = &ipu_array[pltfm_data->id];
- + memset(ipu, 0, sizeof(struct ipu_soc));
- + ipu->dev = &pdev->dev;
- + ipu->pdata = pltfm_data;
- + dev_dbg(ipu->dev, "IPU rev:%d\n", g_ipu_hw_rev);
- + spin_lock_init(&ipu->int_reg_spin_lock);
- + spin_lock_init(&ipu->rdy_reg_spin_lock);
- + mutex_init(&ipu->mutex_lock);
- +
- + ipu->irq_sync = platform_get_irq(pdev, 0);
- + ipu->irq_err = platform_get_irq(pdev, 1);
- + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- +
- + if (!res || ipu->irq_sync < 0 || ipu->irq_err < 0) {
- + dev_err(&pdev->dev, "can't get device resources\n");
- + return -ENODEV;
- + }
- +
- + if (!devm_request_mem_region(&pdev->dev, res->start,
- + resource_size(res), pdev->name))
- + return -EBUSY;
- +
- + ret = devm_request_irq(&pdev->dev, ipu->irq_sync,
- + ipu_sync_irq_handler, 0, pdev->name, ipu);
- + if (ret) {
- + dev_err(ipu->dev, "request SYNC interrupt failed\n");
- + return ret;
- + }
- + ret = devm_request_irq(&pdev->dev, ipu->irq_err,
- + ipu_err_irq_handler, 0, pdev->name, ipu);
- + if (ret) {
- + dev_err(ipu->dev, "request ERR interrupt failed\n");
- + return ret;
- + }
- +
- + ipu_base = res->start;
- + /* base fixup */
- + if (g_ipu_hw_rev == IPU_V3H) /* IPUv3H */
- + ipu_base += IPUV3H_REG_BASE;
- + else if (g_ipu_hw_rev == IPU_V3M) /* IPUv3M */
- + ipu_base += IPUV3M_REG_BASE;
- + else /* IPUv3D, v3E, v3EX */
- + ipu_base += IPUV3DEX_REG_BASE;
- +
- + ipu->cm_reg = devm_ioremap(&pdev->dev,
- + ipu_base + IPU_CM_REG_BASE, PAGE_SIZE);
- + ipu->ic_reg = devm_ioremap(&pdev->dev,
- + ipu_base + IPU_IC_REG_BASE, PAGE_SIZE);
- + ipu->idmac_reg = devm_ioremap(&pdev->dev,
- + ipu_base + IPU_IDMAC_REG_BASE, PAGE_SIZE);
- + /* DP Registers are accessed thru the SRM */
- + ipu->dp_reg = devm_ioremap(&pdev->dev,
- + ipu_base + IPU_SRM_REG_BASE, PAGE_SIZE);
- + ipu->dc_reg = devm_ioremap(&pdev->dev,
- + ipu_base + IPU_DC_REG_BASE, PAGE_SIZE);
- + ipu->dmfc_reg = devm_ioremap(&pdev->dev,
- + ipu_base + IPU_DMFC_REG_BASE, PAGE_SIZE);
- + ipu->di_reg[0] = devm_ioremap(&pdev->dev,
- + ipu_base + IPU_DI0_REG_BASE, PAGE_SIZE);
- + ipu->di_reg[1] = devm_ioremap(&pdev->dev,
- + ipu_base + IPU_DI1_REG_BASE, PAGE_SIZE);
- + ipu->smfc_reg = devm_ioremap(&pdev->dev,
- + ipu_base + IPU_SMFC_REG_BASE, PAGE_SIZE);
- + ipu->csi_reg[0] = devm_ioremap(&pdev->dev,
- + ipu_base + IPU_CSI0_REG_BASE, PAGE_SIZE);
- + ipu->csi_reg[1] = devm_ioremap(&pdev->dev,
- + ipu_base + IPU_CSI1_REG_BASE, PAGE_SIZE);
- + ipu->cpmem_base = devm_ioremap(&pdev->dev,
- + ipu_base + IPU_CPMEM_REG_BASE, SZ_128K);
- + ipu->tpmem_base = devm_ioremap(&pdev->dev,
- + ipu_base + IPU_TPM_REG_BASE, SZ_64K);
- + ipu->dc_tmpl_reg = devm_ioremap(&pdev->dev,
- + ipu_base + IPU_DC_TMPL_REG_BASE, SZ_128K);
- + ipu->vdi_reg = devm_ioremap(&pdev->dev,
- + ipu_base + IPU_VDI_REG_BASE, PAGE_SIZE);
- + ipu->disp_base[1] = devm_ioremap(&pdev->dev,
- + ipu_base + IPU_DISP1_BASE, SZ_4K);
- + if (!ipu->cm_reg || !ipu->ic_reg || !ipu->idmac_reg ||
- + !ipu->dp_reg || !ipu->dc_reg || !ipu->dmfc_reg ||
- + !ipu->di_reg[0] || !ipu->di_reg[1] || !ipu->smfc_reg ||
- + !ipu->csi_reg[0] || !ipu->csi_reg[1] || !ipu->cpmem_base ||
- + !ipu->tpmem_base || !ipu->dc_tmpl_reg || !ipu->disp_base[1]
- + || !ipu->vdi_reg)
- + return -ENOMEM;
- +
- + dev_dbg(ipu->dev, "IPU CM Regs = %p\n", ipu->cm_reg);
- + dev_dbg(ipu->dev, "IPU IC Regs = %p\n", ipu->ic_reg);
- + dev_dbg(ipu->dev, "IPU IDMAC Regs = %p\n", ipu->idmac_reg);
- + dev_dbg(ipu->dev, "IPU DP Regs = %p\n", ipu->dp_reg);
- + dev_dbg(ipu->dev, "IPU DC Regs = %p\n", ipu->dc_reg);
- + dev_dbg(ipu->dev, "IPU DMFC Regs = %p\n", ipu->dmfc_reg);
- + dev_dbg(ipu->dev, "IPU DI0 Regs = %p\n", ipu->di_reg[0]);
- + dev_dbg(ipu->dev, "IPU DI1 Regs = %p\n", ipu->di_reg[1]);
- + dev_dbg(ipu->dev, "IPU SMFC Regs = %p\n", ipu->smfc_reg);
- + dev_dbg(ipu->dev, "IPU CSI0 Regs = %p\n", ipu->csi_reg[0]);
- + dev_dbg(ipu->dev, "IPU CSI1 Regs = %p\n", ipu->csi_reg[1]);
- + dev_dbg(ipu->dev, "IPU CPMem = %p\n", ipu->cpmem_base);
- + dev_dbg(ipu->dev, "IPU TPMem = %p\n", ipu->tpmem_base);
- + dev_dbg(ipu->dev, "IPU DC Template Mem = %p\n", ipu->dc_tmpl_reg);
- + dev_dbg(ipu->dev, "IPU Display Region 1 Mem = %p\n", ipu->disp_base[1]);
- + dev_dbg(ipu->dev, "IPU VDI Regs = %p\n", ipu->vdi_reg);
- +
- + ipu->ipu_clk = devm_clk_get(ipu->dev, "bus");
- + if (IS_ERR(ipu->ipu_clk)) {
- + dev_err(ipu->dev, "clk_get ipu failed");
- + return PTR_ERR(ipu->ipu_clk);
- + }
- +
- + /* ipu_clk is always prepared */
- + ret = clk_prepare_enable(ipu->ipu_clk);
- + if (ret < 0) {
- + dev_err(ipu->dev, "ipu clk enable failed\n");
- + return ret;
- + }
- +
- + ipu->online = true;
- +
- + platform_set_drvdata(pdev, ipu);
- +
- + if (!pltfm_data->bypass_reset) {
- + ret = device_reset(&pdev->dev);
- + if (ret) {
- + dev_err(&pdev->dev, "failed to reset: %d\n", ret);
- + return ret;
- + }
- +
- + ipu_mem_reset(ipu);
- +
- + ipu_disp_init(ipu);
- +
- + /* Set MCU_T to divide MCU access window into 2 */
- + ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
- + IPU_DISP_GEN);
- + }
- +
- + /* setup ipu clk tree after ipu reset */
- + ret = ipu_clk_setup_enable(ipu, pltfm_data);
- + if (ret < 0) {
- + dev_err(ipu->dev, "ipu clk setup failed\n");
- + ipu->online = false;
- + return ret;
- + }
- +
- + /* Set sync refresh channels and CSI->mem channel as high priority */
- + ipu_idmac_write(ipu, 0x18800001L, IDMAC_CHA_PRI(0));
- +
- + /* Enable error interrupts by default */
- + ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(5));
- + ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(6));
- + ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(9));
- + ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(10));
- +
- + if (!pltfm_data->bypass_reset)
- + clk_disable(ipu->ipu_clk);
- +
- + register_ipu_device(ipu, ipu->pdata->id);
- +
- + pm_runtime_enable(&pdev->dev);
- +
- + return ret;
- +}
- +
- +int ipu_remove(struct platform_device *pdev)
- +{
- + struct ipu_soc *ipu = platform_get_drvdata(pdev);
- +
- + unregister_ipu_device(ipu, ipu->pdata->id);
- +
- + clk_put(ipu->ipu_clk);
- +
- + return 0;
- +}
- +
- +void ipu_dump_registers(struct ipu_soc *ipu)
- +{
- + dev_dbg(ipu->dev, "IPU_CONF = \t0x%08X\n", ipu_cm_read(ipu, IPU_CONF));
- + dev_dbg(ipu->dev, "IDMAC_CONF = \t0x%08X\n", ipu_idmac_read(ipu, IDMAC_CONF));
- + dev_dbg(ipu->dev, "IDMAC_CHA_EN1 = \t0x%08X\n",
- + ipu_idmac_read(ipu, IDMAC_CHA_EN(0)));
- + dev_dbg(ipu->dev, "IDMAC_CHA_EN2 = \t0x%08X\n",
- + ipu_idmac_read(ipu, IDMAC_CHA_EN(32)));
- + dev_dbg(ipu->dev, "IDMAC_CHA_PRI1 = \t0x%08X\n",
- + ipu_idmac_read(ipu, IDMAC_CHA_PRI(0)));
- + dev_dbg(ipu->dev, "IDMAC_CHA_PRI2 = \t0x%08X\n",
- + ipu_idmac_read(ipu, IDMAC_CHA_PRI(32)));
- + dev_dbg(ipu->dev, "IDMAC_BAND_EN1 = \t0x%08X\n",
- + ipu_idmac_read(ipu, IDMAC_BAND_EN(0)));
- + dev_dbg(ipu->dev, "IDMAC_BAND_EN2 = \t0x%08X\n",
- + ipu_idmac_read(ipu, IDMAC_BAND_EN(32)));
- + dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL0 = \t0x%08X\n",
- + ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(0)));
- + dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL1 = \t0x%08X\n",
- + ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(32)));
- + if (g_ipu_hw_rev >= IPU_V3DEX) {
- + dev_dbg(ipu->dev, "IPU_CHA_TRB_MODE_SEL0 = \t0x%08X\n",
- + ipu_cm_read(ipu, IPU_CHA_TRB_MODE_SEL(0)));
- + dev_dbg(ipu->dev, "IPU_CHA_TRB_MODE_SEL1 = \t0x%08X\n",
- + ipu_cm_read(ipu, IPU_CHA_TRB_MODE_SEL(32)));
- + }
- + dev_dbg(ipu->dev, "DMFC_WR_CHAN = \t0x%08X\n",
- + ipu_dmfc_read(ipu, DMFC_WR_CHAN));
- + dev_dbg(ipu->dev, "DMFC_WR_CHAN_DEF = \t0x%08X\n",
- + ipu_dmfc_read(ipu, DMFC_WR_CHAN_DEF));
- + dev_dbg(ipu->dev, "DMFC_DP_CHAN = \t0x%08X\n",
- + ipu_dmfc_read(ipu, DMFC_DP_CHAN));
- + dev_dbg(ipu->dev, "DMFC_DP_CHAN_DEF = \t0x%08X\n",
- + ipu_dmfc_read(ipu, DMFC_DP_CHAN_DEF));
- + dev_dbg(ipu->dev, "DMFC_IC_CTRL = \t0x%08X\n",
- + ipu_dmfc_read(ipu, DMFC_IC_CTRL));
- + dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW1 = \t0x%08X\n",
- + ipu_cm_read(ipu, IPU_FS_PROC_FLOW1));
- + dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW2 = \t0x%08X\n",
- + ipu_cm_read(ipu, IPU_FS_PROC_FLOW2));
- + dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW3 = \t0x%08X\n",
- + ipu_cm_read(ipu, IPU_FS_PROC_FLOW3));
- + dev_dbg(ipu->dev, "IPU_FS_DISP_FLOW1 = \t0x%08X\n",
- + ipu_cm_read(ipu, IPU_FS_DISP_FLOW1));
- + dev_dbg(ipu->dev, "IPU_VDIC_VDI_FSIZE = \t0x%08X\n",
- + ipu_vdi_read(ipu, VDI_FSIZE));
- + dev_dbg(ipu->dev, "IPU_VDIC_VDI_C = \t0x%08X\n",
- + ipu_vdi_read(ipu, VDI_C));
- + dev_dbg(ipu->dev, "IPU_IC_CONF = \t0x%08X\n",
- + ipu_ic_read(ipu, IC_CONF));
- +}
- +
- +/*!
- + * This function is called to initialize a logical IPU channel.
- + *
- + * @param ipu ipu handler
- + * @param channel Input parameter for the logical channel ID to init.
- + *
- + * @param params Input parameter containing union of channel
- + * initialization parameters.
- + *
- + * @return Returns 0 on success or negative error code on fail
- + */
- +int32_t ipu_init_channel(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel_params_t *params)
- +{
- + int ret = 0;
- + bool bad_pixfmt;
- + uint32_t ipu_conf, reg, in_g_pixel_fmt, sec_dma;
- +
- + dev_dbg(ipu->dev, "init channel = %d\n", IPU_CHAN_ID(channel));
- +
- + ret = pm_runtime_get_sync(ipu->dev);
- + if (ret < 0) {
- + dev_err(ipu->dev, "ch = %d, pm_runtime_get failed:%d!\n",
- + IPU_CHAN_ID(channel), ret);
- + dump_stack();
- + return ret;
- + }
- + /*
- + * Here, ret could be 1 if the device's runtime PM status was
- + * already 'active', so clear it to be 0.
- + */
- + ret = 0;
- +
- + _ipu_get(ipu);
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + /* Re-enable error interrupts every time a channel is initialized */
- + ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(5));
- + ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(6));
- + ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(9));
- + ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(10));
- +
- + if (ipu->channel_init_mask & (1L << IPU_CHAN_ID(channel))) {
- + dev_warn(ipu->dev, "Warning: channel already initialized %d\n",
- + IPU_CHAN_ID(channel));
- + }
- +
- + ipu_conf = ipu_cm_read(ipu, IPU_CONF);
- +
- + switch (channel) {
- + case CSI_MEM0:
- + case CSI_MEM1:
- + case CSI_MEM2:
- + case CSI_MEM3:
- + if (params->csi_mem.csi > 1) {
- + ret = -EINVAL;
- + goto err;
- + }
- +
- + if (params->csi_mem.interlaced)
- + ipu->chan_is_interlaced[channel_2_dma(channel,
- + IPU_OUTPUT_BUFFER)] = true;
- + else
- + ipu->chan_is_interlaced[channel_2_dma(channel,
- + IPU_OUTPUT_BUFFER)] = false;
- +
- + ipu->smfc_use_count++;
- + ipu->csi_channel[params->csi_mem.csi] = channel;
- +
- + /*SMFC setting*/
- + if (params->csi_mem.mipi_en) {
- + ipu_conf |= (1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
- + params->csi_mem.csi));
- + _ipu_smfc_init(ipu, channel, params->csi_mem.mipi_vc,
- + params->csi_mem.csi);
- + _ipu_csi_set_mipi_di(ipu, params->csi_mem.mipi_vc,
- + params->csi_mem.mipi_id, params->csi_mem.csi);
- + } else {
- + ipu_conf &= ~(1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
- + params->csi_mem.csi));
- + _ipu_smfc_init(ipu, channel, 0, params->csi_mem.csi);
- + }
- +
- + /*CSI data (include compander) dest*/
- + _ipu_csi_init(ipu, channel, params->csi_mem.csi);
- + break;
- + case CSI_PRP_ENC_MEM:
- + if (params->csi_prp_enc_mem.csi > 1) {
- + ret = -EINVAL;
- + goto err;
- + }
- + if ((ipu->using_ic_dirct_ch == MEM_VDI_PRP_VF_MEM) ||
- + (ipu->using_ic_dirct_ch == MEM_VDI_MEM)) {
- + ret = -EINVAL;
- + goto err;
- + }
- + ipu->using_ic_dirct_ch = CSI_PRP_ENC_MEM;
- +
- + ipu->ic_use_count++;
- + ipu->csi_channel[params->csi_prp_enc_mem.csi] = channel;
- +
- + if (params->csi_prp_enc_mem.mipi_en) {
- + ipu_conf |= (1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
- + params->csi_prp_enc_mem.csi));
- + _ipu_csi_set_mipi_di(ipu,
- + params->csi_prp_enc_mem.mipi_vc,
- + params->csi_prp_enc_mem.mipi_id,
- + params->csi_prp_enc_mem.csi);
- + } else
- + ipu_conf &= ~(1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
- + params->csi_prp_enc_mem.csi));
- +
- + /*CSI0/1 feed into IC*/
- + ipu_conf &= ~IPU_CONF_IC_INPUT;
- + if (params->csi_prp_enc_mem.csi)
- + ipu_conf |= IPU_CONF_CSI_SEL;
- + else
- + ipu_conf &= ~IPU_CONF_CSI_SEL;
- +
- + /*PRP skip buffer in memory, only valid when RWS_EN is true*/
- + reg = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
- + ipu_cm_write(ipu, reg & ~FS_ENC_IN_VALID, IPU_FS_PROC_FLOW1);
- +
- + /*CSI data (include compander) dest*/
- + _ipu_csi_init(ipu, channel, params->csi_prp_enc_mem.csi);
- + _ipu_ic_init_prpenc(ipu, params, true);
- + break;
- + case CSI_PRP_VF_MEM:
- + if (params->csi_prp_vf_mem.csi > 1) {
- + ret = -EINVAL;
- + goto err;
- + }
- + if ((ipu->using_ic_dirct_ch == MEM_VDI_PRP_VF_MEM) ||
- + (ipu->using_ic_dirct_ch == MEM_VDI_MEM)) {
- + ret = -EINVAL;
- + goto err;
- + }
- + ipu->using_ic_dirct_ch = CSI_PRP_VF_MEM;
- +
- + ipu->ic_use_count++;
- + ipu->csi_channel[params->csi_prp_vf_mem.csi] = channel;
- +
- + if (params->csi_prp_vf_mem.mipi_en) {
- + ipu_conf |= (1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
- + params->csi_prp_vf_mem.csi));
- + _ipu_csi_set_mipi_di(ipu,
- + params->csi_prp_vf_mem.mipi_vc,
- + params->csi_prp_vf_mem.mipi_id,
- + params->csi_prp_vf_mem.csi);
- + } else
- + ipu_conf &= ~(1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
- + params->csi_prp_vf_mem.csi));
- +
- + /*CSI0/1 feed into IC*/
- + ipu_conf &= ~IPU_CONF_IC_INPUT;
- + if (params->csi_prp_vf_mem.csi)
- + ipu_conf |= IPU_CONF_CSI_SEL;
- + else
- + ipu_conf &= ~IPU_CONF_CSI_SEL;
- +
- + /*PRP skip buffer in memory, only valid when RWS_EN is true*/
- + reg = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
- + ipu_cm_write(ipu, reg & ~FS_VF_IN_VALID, IPU_FS_PROC_FLOW1);
- +
- + /*CSI data (include compander) dest*/
- + _ipu_csi_init(ipu, channel, params->csi_prp_vf_mem.csi);
- + _ipu_ic_init_prpvf(ipu, params, true);
- + break;
- + case MEM_PRP_VF_MEM:
- + if (params->mem_prp_vf_mem.graphics_combine_en) {
- + sec_dma = channel_2_dma(channel, IPU_GRAPH_IN_BUFFER);
- + in_g_pixel_fmt = params->mem_prp_vf_mem.in_g_pixel_fmt;
- + bad_pixfmt =
- + _ipu_ch_param_bad_alpha_pos(in_g_pixel_fmt);
- +
- + if (params->mem_prp_vf_mem.alpha_chan_en) {
- + if (bad_pixfmt) {
- + dev_err(ipu->dev, "bad pixel format "
- + "for graphics plane from "
- + "ch%d\n", sec_dma);
- + ret = -EINVAL;
- + goto err;
- + }
- + ipu->thrd_chan_en[IPU_CHAN_ID(channel)] = true;
- + }
- + ipu->sec_chan_en[IPU_CHAN_ID(channel)] = true;
- + }
- +
- + reg = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
- + ipu_cm_write(ipu, reg | FS_VF_IN_VALID, IPU_FS_PROC_FLOW1);
- +
- + _ipu_ic_init_prpvf(ipu, params, false);
- + ipu->ic_use_count++;
- + break;
- + case MEM_VDI_PRP_VF_MEM:
- + if ((ipu->using_ic_dirct_ch == CSI_PRP_VF_MEM) ||
- + (ipu->using_ic_dirct_ch == MEM_VDI_MEM) ||
- + (ipu->using_ic_dirct_ch == CSI_PRP_ENC_MEM)) {
- + ret = -EINVAL;
- + goto err;
- + }
- + ipu->using_ic_dirct_ch = MEM_VDI_PRP_VF_MEM;
- + ipu->ic_use_count++;
- + ipu->vdi_use_count++;
- + reg = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
- + reg &= ~FS_VDI_SRC_SEL_MASK;
- + ipu_cm_write(ipu, reg , IPU_FS_PROC_FLOW1);
- +
- + if (params->mem_prp_vf_mem.graphics_combine_en)
- + ipu->sec_chan_en[IPU_CHAN_ID(channel)] = true;
- + _ipu_ic_init_prpvf(ipu, params, false);
- + _ipu_vdi_init(ipu, channel, params);
- + break;
- + case MEM_VDI_PRP_VF_MEM_P:
- + case MEM_VDI_PRP_VF_MEM_N:
- + case MEM_VDI_MEM_P:
- + case MEM_VDI_MEM_N:
- + _ipu_vdi_init(ipu, channel, params);
- + break;
- + case MEM_VDI_MEM:
- + if ((ipu->using_ic_dirct_ch == CSI_PRP_VF_MEM) ||
- + (ipu->using_ic_dirct_ch == MEM_VDI_PRP_VF_MEM) ||
- + (ipu->using_ic_dirct_ch == CSI_PRP_ENC_MEM)) {
- + ret = -EINVAL;
- + goto err;
- + }
- + ipu->using_ic_dirct_ch = MEM_VDI_MEM;
- + ipu->ic_use_count++;
- + ipu->vdi_use_count++;
- + _ipu_vdi_init(ipu, channel, params);
- + break;
- + case MEM_ROT_VF_MEM:
- + ipu->ic_use_count++;
- + ipu->rot_use_count++;
- + _ipu_ic_init_rotate_vf(ipu, params);
- + break;
- + case MEM_PRP_ENC_MEM:
- + ipu->ic_use_count++;
- + reg = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
- + ipu_cm_write(ipu, reg | FS_ENC_IN_VALID, IPU_FS_PROC_FLOW1);
- + _ipu_ic_init_prpenc(ipu, params, false);
- + break;
- + case MEM_ROT_ENC_MEM:
- + ipu->ic_use_count++;
- + ipu->rot_use_count++;
- + _ipu_ic_init_rotate_enc(ipu, params);
- + break;
- + case MEM_PP_MEM:
- + if (params->mem_pp_mem.graphics_combine_en) {
- + sec_dma = channel_2_dma(channel, IPU_GRAPH_IN_BUFFER);
- + in_g_pixel_fmt = params->mem_pp_mem.in_g_pixel_fmt;
- + bad_pixfmt =
- + _ipu_ch_param_bad_alpha_pos(in_g_pixel_fmt);
- +
- + if (params->mem_pp_mem.alpha_chan_en) {
- + if (bad_pixfmt) {
- + dev_err(ipu->dev, "bad pixel format "
- + "for graphics plane from "
- + "ch%d\n", sec_dma);
- + ret = -EINVAL;
- + goto err;
- + }
- + ipu->thrd_chan_en[IPU_CHAN_ID(channel)] = true;
- + }
- +
- + ipu->sec_chan_en[IPU_CHAN_ID(channel)] = true;
- + }
- +
- + _ipu_ic_init_pp(ipu, params);
- + ipu->ic_use_count++;
- + break;
- + case MEM_ROT_PP_MEM:
- + _ipu_ic_init_rotate_pp(ipu, params);
- + ipu->ic_use_count++;
- + ipu->rot_use_count++;
- + break;
- + case MEM_DC_SYNC:
- + if (params->mem_dc_sync.di > 1) {
- + ret = -EINVAL;
- + goto err;
- + }
- +
- + ipu->dc_di_assignment[1] = params->mem_dc_sync.di;
- + _ipu_dc_init(ipu, 1, params->mem_dc_sync.di,
- + params->mem_dc_sync.interlaced,
- + params->mem_dc_sync.out_pixel_fmt);
- + ipu->di_use_count[params->mem_dc_sync.di]++;
- + ipu->dc_use_count++;
- + ipu->dmfc_use_count++;
- + break;
- + case MEM_BG_SYNC:
- + if (params->mem_dp_bg_sync.di > 1) {
- + ret = -EINVAL;
- + goto err;
- + }
- +
- + if (params->mem_dp_bg_sync.alpha_chan_en)
- + ipu->thrd_chan_en[IPU_CHAN_ID(channel)] = true;
- +
- + ipu->dc_di_assignment[5] = params->mem_dp_bg_sync.di;
- + _ipu_dp_init(ipu, channel, params->mem_dp_bg_sync.in_pixel_fmt,
- + params->mem_dp_bg_sync.out_pixel_fmt);
- + _ipu_dc_init(ipu, 5, params->mem_dp_bg_sync.di,
- + params->mem_dp_bg_sync.interlaced,
- + params->mem_dp_bg_sync.out_pixel_fmt);
- + ipu->di_use_count[params->mem_dp_bg_sync.di]++;
- + ipu->dc_use_count++;
- + ipu->dp_use_count++;
- + ipu->dmfc_use_count++;
- + break;
- + case MEM_FG_SYNC:
- + _ipu_dp_init(ipu, channel, params->mem_dp_fg_sync.in_pixel_fmt,
- + params->mem_dp_fg_sync.out_pixel_fmt);
- +
- + if (params->mem_dp_fg_sync.alpha_chan_en)
- + ipu->thrd_chan_en[IPU_CHAN_ID(channel)] = true;
- +
- + ipu->dc_use_count++;
- + ipu->dp_use_count++;
- + ipu->dmfc_use_count++;
- + break;
- + case DIRECT_ASYNC0:
- + if (params->direct_async.di > 1) {
- + ret = -EINVAL;
- + goto err;
- + }
- +
- + ipu->dc_di_assignment[8] = params->direct_async.di;
- + _ipu_dc_init(ipu, 8, params->direct_async.di, false, IPU_PIX_FMT_GENERIC);
- + ipu->di_use_count[params->direct_async.di]++;
- + ipu->dc_use_count++;
- + break;
- + case DIRECT_ASYNC1:
- + if (params->direct_async.di > 1) {
- + ret = -EINVAL;
- + goto err;
- + }
- +
- + ipu->dc_di_assignment[9] = params->direct_async.di;
- + _ipu_dc_init(ipu, 9, params->direct_async.di, false, IPU_PIX_FMT_GENERIC);
- + ipu->di_use_count[params->direct_async.di]++;
- + ipu->dc_use_count++;
- + break;
- + default:
- + dev_err(ipu->dev, "Missing channel initialization\n");
- + break;
- + }
- +
- + ipu->channel_init_mask |= 1L << IPU_CHAN_ID(channel);
- +
- + ipu_cm_write(ipu, ipu_conf, IPU_CONF);
- +
- +err:
- + mutex_unlock(&ipu->mutex_lock);
- + return ret;
- +}
- +EXPORT_SYMBOL(ipu_init_channel);
- +
- +/*!
- + * This function is called to uninitialize a logical IPU channel.
- + *
- + * @param ipu ipu handler
- + * @param channel Input parameter for the logical channel ID to uninit.
- + */
- +void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel)
- +{
- + uint32_t reg;
- + uint32_t in_dma, out_dma = 0;
- + uint32_t ipu_conf;
- + uint32_t dc_chan = 0;
- + int ret;
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + if ((ipu->channel_init_mask & (1L << IPU_CHAN_ID(channel))) == 0) {
- + dev_dbg(ipu->dev, "Channel already uninitialized %d\n",
- + IPU_CHAN_ID(channel));
- + mutex_unlock(&ipu->mutex_lock);
- + return;
- + }
- +
- + /* Make sure channel is disabled */
- + /* Get input and output dma channels */
- + in_dma = channel_2_dma(channel, IPU_VIDEO_IN_BUFFER);
- + out_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER);
- +
- + if (idma_is_set(ipu, IDMAC_CHA_EN, in_dma) ||
- + idma_is_set(ipu, IDMAC_CHA_EN, out_dma)) {
- + dev_err(ipu->dev,
- + "Channel %d is not disabled, disable first\n",
- + IPU_CHAN_ID(channel));
- + mutex_unlock(&ipu->mutex_lock);
- + return;
- + }
- +
- + ipu_conf = ipu_cm_read(ipu, IPU_CONF);
- +
- + /* Reset the double buffer */
- + reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(in_dma));
- + ipu_cm_write(ipu, reg & ~idma_mask(in_dma), IPU_CHA_DB_MODE_SEL(in_dma));
- + reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(out_dma));
- + ipu_cm_write(ipu, reg & ~idma_mask(out_dma), IPU_CHA_DB_MODE_SEL(out_dma));
- +
- + /* Reset the triple buffer */
- + reg = ipu_cm_read(ipu, IPU_CHA_TRB_MODE_SEL(in_dma));
- + ipu_cm_write(ipu, reg & ~idma_mask(in_dma), IPU_CHA_TRB_MODE_SEL(in_dma));
- + reg = ipu_cm_read(ipu, IPU_CHA_TRB_MODE_SEL(out_dma));
- + ipu_cm_write(ipu, reg & ~idma_mask(out_dma), IPU_CHA_TRB_MODE_SEL(out_dma));
- +
- + if (_ipu_is_ic_chan(in_dma) || _ipu_is_dp_graphic_chan(in_dma)) {
- + ipu->sec_chan_en[IPU_CHAN_ID(channel)] = false;
- + ipu->thrd_chan_en[IPU_CHAN_ID(channel)] = false;
- + }
- +
- + switch (channel) {
- + case CSI_MEM0:
- + case CSI_MEM1:
- + case CSI_MEM2:
- + case CSI_MEM3:
- + ipu->smfc_use_count--;
- + if (ipu->csi_channel[0] == channel) {
- + ipu->csi_channel[0] = CHAN_NONE;
- + } else if (ipu->csi_channel[1] == channel) {
- + ipu->csi_channel[1] = CHAN_NONE;
- + }
- + break;
- + case CSI_PRP_ENC_MEM:
- + ipu->ic_use_count--;
- + if (ipu->using_ic_dirct_ch == CSI_PRP_ENC_MEM)
- + ipu->using_ic_dirct_ch = 0;
- + _ipu_ic_uninit_prpenc(ipu);
- + if (ipu->csi_channel[0] == channel) {
- + ipu->csi_channel[0] = CHAN_NONE;
- + } else if (ipu->csi_channel[1] == channel) {
- + ipu->csi_channel[1] = CHAN_NONE;
- + }
- + break;
- + case CSI_PRP_VF_MEM:
- + ipu->ic_use_count--;
- + if (ipu->using_ic_dirct_ch == CSI_PRP_VF_MEM)
- + ipu->using_ic_dirct_ch = 0;
- + _ipu_ic_uninit_prpvf(ipu);
- + if (ipu->csi_channel[0] == channel) {
- + ipu->csi_channel[0] = CHAN_NONE;
- + } else if (ipu->csi_channel[1] == channel) {
- + ipu->csi_channel[1] = CHAN_NONE;
- + }
- + break;
- + case MEM_PRP_VF_MEM:
- + ipu->ic_use_count--;
- + _ipu_ic_uninit_prpvf(ipu);
- + reg = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
- + ipu_cm_write(ipu, reg & ~FS_VF_IN_VALID, IPU_FS_PROC_FLOW1);
- + break;
- + case MEM_VDI_PRP_VF_MEM:
- + ipu->ic_use_count--;
- + ipu->vdi_use_count--;
- + if (ipu->using_ic_dirct_ch == MEM_VDI_PRP_VF_MEM)
- + ipu->using_ic_dirct_ch = 0;
- + _ipu_ic_uninit_prpvf(ipu);
- + _ipu_vdi_uninit(ipu);
- + reg = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
- + ipu_cm_write(ipu, reg & ~FS_VF_IN_VALID, IPU_FS_PROC_FLOW1);
- + break;
- + case MEM_VDI_MEM:
- + ipu->ic_use_count--;
- + ipu->vdi_use_count--;
- + if (ipu->using_ic_dirct_ch == MEM_VDI_MEM)
- + ipu->using_ic_dirct_ch = 0;
- + _ipu_vdi_uninit(ipu);
- + break;
- + case MEM_VDI_PRP_VF_MEM_P:
- + case MEM_VDI_PRP_VF_MEM_N:
- + case MEM_VDI_MEM_P:
- + case MEM_VDI_MEM_N:
- + break;
- + case MEM_ROT_VF_MEM:
- + ipu->rot_use_count--;
- + ipu->ic_use_count--;
- + _ipu_ic_uninit_rotate_vf(ipu);
- + break;
- + case MEM_PRP_ENC_MEM:
- + ipu->ic_use_count--;
- + _ipu_ic_uninit_prpenc(ipu);
- + reg = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
- + ipu_cm_write(ipu, reg & ~FS_ENC_IN_VALID, IPU_FS_PROC_FLOW1);
- + break;
- + case MEM_ROT_ENC_MEM:
- + ipu->rot_use_count--;
- + ipu->ic_use_count--;
- + _ipu_ic_uninit_rotate_enc(ipu);
- + break;
- + case MEM_PP_MEM:
- + ipu->ic_use_count--;
- + _ipu_ic_uninit_pp(ipu);
- + break;
- + case MEM_ROT_PP_MEM:
- + ipu->rot_use_count--;
- + ipu->ic_use_count--;
- + _ipu_ic_uninit_rotate_pp(ipu);
- + break;
- + case MEM_DC_SYNC:
- + dc_chan = 1;
- + _ipu_dc_uninit(ipu, 1);
- + ipu->di_use_count[ipu->dc_di_assignment[1]]--;
- + ipu->dc_use_count--;
- + ipu->dmfc_use_count--;
- + break;
- + case MEM_BG_SYNC:
- + dc_chan = 5;
- + _ipu_dp_uninit(ipu, channel);
- + _ipu_dc_uninit(ipu, 5);
- + ipu->di_use_count[ipu->dc_di_assignment[5]]--;
- + ipu->dc_use_count--;
- + ipu->dp_use_count--;
- + ipu->dmfc_use_count--;
- + break;
- + case MEM_FG_SYNC:
- + _ipu_dp_uninit(ipu, channel);
- + ipu->dc_use_count--;
- + ipu->dp_use_count--;
- + ipu->dmfc_use_count--;
- + break;
- + case DIRECT_ASYNC0:
- + dc_chan = 8;
- + _ipu_dc_uninit(ipu, 8);
- + ipu->di_use_count[ipu->dc_di_assignment[8]]--;
- + ipu->dc_use_count--;
- + break;
- + case DIRECT_ASYNC1:
- + dc_chan = 9;
- + _ipu_dc_uninit(ipu, 9);
- + ipu->di_use_count[ipu->dc_di_assignment[9]]--;
- + ipu->dc_use_count--;
- + break;
- + default:
- + break;
- + }
- +
- + if (ipu->ic_use_count == 0)
- + ipu_conf &= ~IPU_CONF_IC_EN;
- + if (ipu->vdi_use_count == 0) {
- + ipu_conf &= ~IPU_CONF_ISP_EN;
- + ipu_conf &= ~IPU_CONF_VDI_EN;
- + ipu_conf &= ~IPU_CONF_IC_INPUT;
- + }
- + if (ipu->rot_use_count == 0)
- + ipu_conf &= ~IPU_CONF_ROT_EN;
- + if (ipu->dc_use_count == 0)
- + ipu_conf &= ~IPU_CONF_DC_EN;
- + if (ipu->dp_use_count == 0)
- + ipu_conf &= ~IPU_CONF_DP_EN;
- + if (ipu->dmfc_use_count == 0)
- + ipu_conf &= ~IPU_CONF_DMFC_EN;
- + if (ipu->di_use_count[0] == 0) {
- + ipu_conf &= ~IPU_CONF_DI0_EN;
- + }
- + if (ipu->di_use_count[1] == 0) {
- + ipu_conf &= ~IPU_CONF_DI1_EN;
- + }
- + if (ipu->smfc_use_count == 0)
- + ipu_conf &= ~IPU_CONF_SMFC_EN;
- +
- + ipu_cm_write(ipu, ipu_conf, IPU_CONF);
- +
- + ipu->channel_init_mask &= ~(1L << IPU_CHAN_ID(channel));
- +
- + /*
- + * Disable pixel clk and its parent clock(if the parent clock
- + * usecount is 1) after clearing DC/DP/DI bits in IPU_CONF
- + * register to prevent LVDS display channel starvation.
- + */
- + if (_ipu_is_primary_disp_chan(in_dma))
- + clk_disable_unprepare(ipu->pixel_clk[ipu->dc_di_assignment[dc_chan]]);
- +
- + mutex_unlock(&ipu->mutex_lock);
- +
- + _ipu_put(ipu);
- +
- + ret = pm_runtime_put_sync_suspend(ipu->dev);
- + if (ret < 0) {
- + dev_err(ipu->dev, "ch = %d, pm_runtime_put failed:%d!\n",
- + IPU_CHAN_ID(channel), ret);
- + dump_stack();
- + }
- +
- + WARN_ON(ipu->ic_use_count < 0);
- + WARN_ON(ipu->vdi_use_count < 0);
- + WARN_ON(ipu->rot_use_count < 0);
- + WARN_ON(ipu->dc_use_count < 0);
- + WARN_ON(ipu->dp_use_count < 0);
- + WARN_ON(ipu->dmfc_use_count < 0);
- + WARN_ON(ipu->smfc_use_count < 0);
- +}
- +EXPORT_SYMBOL(ipu_uninit_channel);
- +
- +/*!
- + * This function is called to initialize buffer(s) for logical IPU channel.
- + *
- + * @param ipu ipu handler
- + *
- + * @param channel Input parameter for the logical channel ID.
- + *
- + * @param type Input parameter which buffer to initialize.
- + *
- + * @param pixel_fmt Input parameter for pixel format of buffer.
- + * Pixel format is a FOURCC ASCII code.
- + *
- + * @param width Input parameter for width of buffer in pixels.
- + *
- + * @param height Input parameter for height of buffer in pixels.
- + *
- + * @param stride Input parameter for stride length of buffer
- + * in pixels.
- + *
- + * @param rot_mode Input parameter for rotation setting of buffer.
- + * A rotation setting other than
- + * IPU_ROTATE_VERT_FLIP
- + * should only be used for input buffers of
- + * rotation channels.
- + *
- + * @param phyaddr_0 Input parameter buffer 0 physical address.
- + *
- + * @param phyaddr_1 Input parameter buffer 1 physical address.
- + * Setting this to a value other than NULL enables
- + * double buffering mode.
- + *
- + * @param phyaddr_2 Input parameter buffer 2 physical address.
- + * Setting this to a value other than NULL enables
- + * triple buffering mode, phyaddr_1 should not be
- + * NULL then.
- + *
- + * @param u private u offset for additional cropping,
- + * zero if not used.
- + *
- + * @param v private v offset for additional cropping,
- + * zero if not used.
- + *
- + * @return Returns 0 on success or negative error code on fail
- + */
- +int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
- + ipu_buffer_t type,
- + uint32_t pixel_fmt,
- + uint16_t width, uint16_t height,
- + uint32_t stride,
- + ipu_rotate_mode_t rot_mode,
- + dma_addr_t phyaddr_0, dma_addr_t phyaddr_1,
- + dma_addr_t phyaddr_2,
- + uint32_t u, uint32_t v)
- +{
- + uint32_t reg;
- + uint32_t dma_chan;
- + uint32_t burst_size;
- +
- + dma_chan = channel_2_dma(channel, type);
- + if (!idma_is_valid(dma_chan))
- + return -EINVAL;
- +
- + if (stride < width * bytes_per_pixel(pixel_fmt))
- + stride = width * bytes_per_pixel(pixel_fmt);
- +
- + if (stride % 4) {
- + dev_err(ipu->dev,
- + "Stride not 32-bit aligned, stride = %d\n", stride);
- + return -EINVAL;
- + }
- + /* IC & IRT channels' width must be multiple of 8 pixels */
- + if ((_ipu_is_ic_chan(dma_chan) || _ipu_is_irt_chan(dma_chan))
- + && (width % 8)) {
- + dev_err(ipu->dev, "Width must be 8 pixel multiple\n");
- + return -EINVAL;
- + }
- +
- + if (_ipu_is_vdi_out_chan(dma_chan) &&
- + ((width < 16) || (height < 16) || (width % 2) || (height % 4))) {
- + dev_err(ipu->dev, "vdi width/height limited err\n");
- + return -EINVAL;
- + }
- +
- + /* IPUv3EX and IPUv3M support triple buffer */
- + if ((!_ipu_is_trb_chan(dma_chan)) && phyaddr_2) {
- + dev_err(ipu->dev, "Chan%d doesn't support triple buffer "
- + "mode\n", dma_chan);
- + return -EINVAL;
- + }
- + if (!phyaddr_1 && phyaddr_2) {
- + dev_err(ipu->dev, "Chan%d's buf1 physical addr is NULL for "
- + "triple buffer mode\n", dma_chan);
- + return -EINVAL;
- + }
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + /* Build parameter memory data for DMA channel */
- + _ipu_ch_param_init(ipu, dma_chan, pixel_fmt, width, height, stride, u, v, 0,
- + phyaddr_0, phyaddr_1, phyaddr_2);
- +
- + /* Set correlative channel parameter of local alpha channel */
- + if ((_ipu_is_ic_graphic_chan(dma_chan) ||
- + _ipu_is_dp_graphic_chan(dma_chan)) &&
- + (ipu->thrd_chan_en[IPU_CHAN_ID(channel)] == true)) {
- + _ipu_ch_param_set_alpha_use_separate_channel(ipu, dma_chan, true);
- + _ipu_ch_param_set_alpha_buffer_memory(ipu, dma_chan);
- + _ipu_ch_param_set_alpha_condition_read(ipu, dma_chan);
- + /* fix alpha width as 8 and burst size as 16*/
- + _ipu_ch_params_set_alpha_width(ipu, dma_chan, 8);
- + _ipu_ch_param_set_burst_size(ipu, dma_chan, 16);
- + } else if (_ipu_is_ic_graphic_chan(dma_chan) &&
- + ipu_pixel_format_has_alpha(pixel_fmt))
- + _ipu_ch_param_set_alpha_use_separate_channel(ipu, dma_chan, false);
- +
- + if (rot_mode)
- + _ipu_ch_param_set_rotation(ipu, dma_chan, rot_mode);
- +
- + /* IC and ROT channels have restriction of 8 or 16 pix burst length */
- + if (_ipu_is_ic_chan(dma_chan) || _ipu_is_vdi_out_chan(dma_chan)) {
- + if ((width % 16) == 0)
- + _ipu_ch_param_set_burst_size(ipu, dma_chan, 16);
- + else
- + _ipu_ch_param_set_burst_size(ipu, dma_chan, 8);
- + } else if (_ipu_is_irt_chan(dma_chan)) {
- + _ipu_ch_param_set_burst_size(ipu, dma_chan, 8);
- + _ipu_ch_param_set_block_mode(ipu, dma_chan);
- + } else if (_ipu_is_dmfc_chan(dma_chan)) {
- + burst_size = _ipu_ch_param_get_burst_size(ipu, dma_chan);
- + _ipu_dmfc_set_wait4eot(ipu, dma_chan, width);
- + _ipu_dmfc_set_burst_size(ipu, dma_chan, burst_size);
- + }
- +
- + if (_ipu_disp_chan_is_interlaced(ipu, channel) ||
- + ipu->chan_is_interlaced[dma_chan])
- + _ipu_ch_param_set_interlaced_scan(ipu, dma_chan);
- +
- + if (_ipu_is_ic_chan(dma_chan) || _ipu_is_irt_chan(dma_chan) ||
- + _ipu_is_vdi_out_chan(dma_chan)) {
- + burst_size = _ipu_ch_param_get_burst_size(ipu, dma_chan);
- + _ipu_ic_idma_init(ipu, dma_chan, width, height, burst_size,
- + rot_mode);
- + } else if (_ipu_is_smfc_chan(dma_chan)) {
- + burst_size = _ipu_ch_param_get_burst_size(ipu, dma_chan);
- + /*
- + * This is different from IPUv3 spec, but it is confirmed
- + * in IPUforum that SMFC burst size should be NPB[6:3]
- + * when IDMAC works in 16-bit generic data mode.
- + */
- + if (pixel_fmt == IPU_PIX_FMT_GENERIC)
- + /* 8 bits per pixel */
- + burst_size = burst_size >> 4;
- + else if (pixel_fmt == IPU_PIX_FMT_GENERIC_16)
- + /* 16 bits per pixel */
- + burst_size = burst_size >> 3;
- + else
- + burst_size = burst_size >> 2;
- + _ipu_smfc_set_burst_size(ipu, channel, burst_size-1);
- + }
- +
- + /* AXI-id */
- + if (idma_is_set(ipu, IDMAC_CHA_PRI, dma_chan)) {
- + unsigned reg = IDMAC_CH_LOCK_EN_1;
- + uint32_t value = 0;
- + if (ipu->pdata->devtype == IPU_V3H) {
- + _ipu_ch_param_set_axi_id(ipu, dma_chan, 0);
- + switch (dma_chan) {
- + case 5:
- + value = 0x3;
- + break;
- + case 11:
- + value = 0x3 << 2;
- + break;
- + case 12:
- + value = 0x3 << 4;
- + break;
- + case 14:
- + value = 0x3 << 6;
- + break;
- + case 15:
- + value = 0x3 << 8;
- + break;
- + case 20:
- + value = 0x3 << 10;
- + break;
- + case 21:
- + value = 0x3 << 12;
- + break;
- + case 22:
- + value = 0x3 << 14;
- + break;
- + case 23:
- + value = 0x3 << 16;
- + break;
- + case 27:
- + value = 0x3 << 18;
- + break;
- + case 28:
- + value = 0x3 << 20;
- + break;
- + case 45:
- + reg = IDMAC_CH_LOCK_EN_2;
- + value = 0x3 << 0;
- + break;
- + case 46:
- + reg = IDMAC_CH_LOCK_EN_2;
- + value = 0x3 << 2;
- + break;
- + case 47:
- + reg = IDMAC_CH_LOCK_EN_2;
- + value = 0x3 << 4;
- + break;
- + case 48:
- + reg = IDMAC_CH_LOCK_EN_2;
- + value = 0x3 << 6;
- + break;
- + case 49:
- + reg = IDMAC_CH_LOCK_EN_2;
- + value = 0x3 << 8;
- + break;
- + case 50:
- + reg = IDMAC_CH_LOCK_EN_2;
- + value = 0x3 << 10;
- + break;
- + default:
- + break;
- + }
- + value |= ipu_idmac_read(ipu, reg);
- + ipu_idmac_write(ipu, value, reg);
- + } else
- + _ipu_ch_param_set_axi_id(ipu, dma_chan, 1);
- + } else {
- + if (ipu->pdata->devtype == IPU_V3H)
- + _ipu_ch_param_set_axi_id(ipu, dma_chan, 1);
- + }
- +
- + _ipu_ch_param_dump(ipu, dma_chan);
- +
- + if (phyaddr_2 && g_ipu_hw_rev >= IPU_V3DEX) {
- + reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(dma_chan));
- + reg &= ~idma_mask(dma_chan);
- + ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(dma_chan));
- +
- + reg = ipu_cm_read(ipu, IPU_CHA_TRB_MODE_SEL(dma_chan));
- + reg |= idma_mask(dma_chan);
- + ipu_cm_write(ipu, reg, IPU_CHA_TRB_MODE_SEL(dma_chan));
- +
- + /* Set IDMAC third buffer's cpmem number */
- + /* See __ipu_ch_get_third_buf_cpmem_num() for mapping */
- + ipu_idmac_write(ipu, 0x00444047L, IDMAC_SUB_ADDR_4);
- + ipu_idmac_write(ipu, 0x46004241L, IDMAC_SUB_ADDR_3);
- + ipu_idmac_write(ipu, 0x00000045L, IDMAC_SUB_ADDR_1);
- +
- + /* Reset to buffer 0 */
- + ipu_cm_write(ipu, tri_cur_buf_mask(dma_chan),
- + IPU_CHA_TRIPLE_CUR_BUF(dma_chan));
- + } else {
- + reg = ipu_cm_read(ipu, IPU_CHA_TRB_MODE_SEL(dma_chan));
- + reg &= ~idma_mask(dma_chan);
- + ipu_cm_write(ipu, reg, IPU_CHA_TRB_MODE_SEL(dma_chan));
- +
- + reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(dma_chan));
- + if (phyaddr_1)
- + reg |= idma_mask(dma_chan);
- + else
- + reg &= ~idma_mask(dma_chan);
- + ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(dma_chan));
- +
- + /* Reset to buffer 0 */
- + ipu_cm_write(ipu, idma_mask(dma_chan),
- + IPU_CHA_CUR_BUF(dma_chan));
- +
- + }
- +
- + mutex_unlock(&ipu->mutex_lock);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(ipu_init_channel_buffer);
- +
- +/*!
- + * This function is called to update the physical address of a buffer for
- + * a logical IPU channel.
- + *
- + * @param ipu ipu handler
- + * @param channel Input parameter for the logical channel ID.
- + *
- + * @param type Input parameter which buffer to initialize.
- + *
- + * @param bufNum Input parameter for buffer number to update.
- + * 0 or 1 are the only valid values.
- + *
- + * @param phyaddr Input parameter buffer physical address.
- + *
- + * @return This function returns 0 on success or negative error code on
- + * fail. This function will fail if the buffer is set to ready.
- + */
- +int32_t ipu_update_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
- + ipu_buffer_t type, uint32_t bufNum, dma_addr_t phyaddr)
- +{
- + uint32_t reg;
- + int ret = 0;
- + uint32_t dma_chan = channel_2_dma(channel, type);
- + unsigned long lock_flags;
- +
- + if (dma_chan == IDMA_CHAN_INVALID)
- + return -EINVAL;
- +
- + spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
- + if (bufNum == 0)
- + reg = ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(dma_chan));
- + else if (bufNum == 1)
- + reg = ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(dma_chan));
- + else
- + reg = ipu_cm_read(ipu, IPU_CHA_BUF2_RDY(dma_chan));
- +
- + if ((reg & idma_mask(dma_chan)) == 0)
- + _ipu_ch_param_set_buffer(ipu, dma_chan, bufNum, phyaddr);
- + else
- + ret = -EACCES;
- + spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
- +
- + return ret;
- +}
- +EXPORT_SYMBOL(ipu_update_channel_buffer);
- +
- +/*!
- + * This function is called to update the band mode setting for
- + * a logical IPU channel.
- + *
- + * @param ipu ipu handler
- + *
- + * @param channel Input parameter for the logical channel ID.
- + *
- + * @param type Input parameter which buffer to initialize.
- + *
- + * @param band_height Input parameter for band lines:
- + * shoule be log2(4/8/16/32/64/128/256).
- + *
- + * @return This function returns 0 on success or negative error code on
- + * fail.
- + */
- +int32_t ipu_set_channel_bandmode(struct ipu_soc *ipu, ipu_channel_t channel,
- + ipu_buffer_t type, uint32_t band_height)
- +{
- + uint32_t reg;
- + int ret = 0;
- + uint32_t dma_chan = channel_2_dma(channel, type);
- +
- + if ((2 > band_height) || (8 < band_height))
- + return -EINVAL;
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + reg = ipu_idmac_read(ipu, IDMAC_BAND_EN(dma_chan));
- + reg |= 1 << (dma_chan % 32);
- + ipu_idmac_write(ipu, reg, IDMAC_BAND_EN(dma_chan));
- +
- + _ipu_ch_param_set_bandmode(ipu, dma_chan, band_height);
- + dev_dbg(ipu->dev, "dma_chan:%d, band_height:%d.\n\n",
- + dma_chan, 1 << band_height);
- + mutex_unlock(&ipu->mutex_lock);
- +
- + return ret;
- +}
- +EXPORT_SYMBOL(ipu_set_channel_bandmode);
- +
- +/*!
- + * This function is called to initialize a buffer for logical IPU channel.
- + *
- + * @param ipu ipu handler
- + * @param channel Input parameter for the logical channel ID.
- + *
- + * @param type Input parameter which buffer to initialize.
- + *
- + * @param pixel_fmt Input parameter for pixel format of buffer.
- + * Pixel format is a FOURCC ASCII code.
- + *
- + * @param width Input parameter for width of buffer in pixels.
- + *
- + * @param height Input parameter for height of buffer in pixels.
- + *
- + * @param stride Input parameter for stride length of buffer
- + * in pixels.
- + *
- + * @param u predefined private u offset for additional cropping,
- + * zero if not used.
- + *
- + * @param v predefined private v offset for additional cropping,
- + * zero if not used.
- + *
- + * @param vertical_offset vertical offset for Y coordinate
- + * in the existed frame
- + *
- + *
- + * @param horizontal_offset horizontal offset for X coordinate
- + * in the existed frame
- + *
- + *
- + * @return Returns 0 on success or negative error code on fail
- + * This function will fail if any buffer is set to ready.
- + */
- +
- +int32_t ipu_update_channel_offset(struct ipu_soc *ipu,
- + ipu_channel_t channel, ipu_buffer_t type,
- + uint32_t pixel_fmt,
- + uint16_t width, uint16_t height,
- + uint32_t stride,
- + uint32_t u, uint32_t v,
- + uint32_t vertical_offset, uint32_t horizontal_offset)
- +{
- + int ret = 0;
- + uint32_t dma_chan = channel_2_dma(channel, type);
- + unsigned long lock_flags;
- +
- + if (dma_chan == IDMA_CHAN_INVALID)
- + return -EINVAL;
- +
- + spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
- + if ((ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(dma_chan)) & idma_mask(dma_chan)) ||
- + (ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(dma_chan)) & idma_mask(dma_chan)) ||
- + ((ipu_cm_read(ipu, IPU_CHA_BUF2_RDY(dma_chan)) & idma_mask(dma_chan)) &&
- + (ipu_cm_read(ipu, IPU_CHA_TRB_MODE_SEL(dma_chan)) & idma_mask(dma_chan)) &&
- + _ipu_is_trb_chan(dma_chan)))
- + ret = -EACCES;
- + else
- + _ipu_ch_offset_update(ipu, dma_chan, pixel_fmt, width, height, stride,
- + u, v, 0, vertical_offset, horizontal_offset);
- + spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
- +
- + return ret;
- +}
- +EXPORT_SYMBOL(ipu_update_channel_offset);
- +
- +
- +/*!
- + * This function is called to set a channel's buffer as ready.
- + *
- + * @param ipu ipu handler
- + * @param channel Input parameter for the logical channel ID.
- + *
- + * @param type Input parameter which buffer to initialize.
- + *
- + * @param bufNum Input parameter for which buffer number set to
- + * ready state.
- + *
- + * @return Returns 0 on success or negative error code on fail
- + */
- +int32_t ipu_select_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
- + ipu_buffer_t type, uint32_t bufNum)
- +{
- + uint32_t dma_chan = channel_2_dma(channel, type);
- + unsigned long lock_flags;
- +
- + if (dma_chan == IDMA_CHAN_INVALID)
- + return -EINVAL;
- +
- + spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
- + /* Mark buffer to be ready. */
- + if (bufNum == 0)
- + ipu_cm_write(ipu, idma_mask(dma_chan),
- + IPU_CHA_BUF0_RDY(dma_chan));
- + else if (bufNum == 1)
- + ipu_cm_write(ipu, idma_mask(dma_chan),
- + IPU_CHA_BUF1_RDY(dma_chan));
- + else
- + ipu_cm_write(ipu, idma_mask(dma_chan),
- + IPU_CHA_BUF2_RDY(dma_chan));
- + spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(ipu_select_buffer);
- +
- +/*!
- + * This function is called to set a channel's buffer as ready.
- + *
- + * @param ipu ipu handler
- + * @param bufNum Input parameter for which buffer number set to
- + * ready state.
- + *
- + * @return Returns 0 on success or negative error code on fail
- + */
- +int32_t ipu_select_multi_vdi_buffer(struct ipu_soc *ipu, uint32_t bufNum)
- +{
- +
- + uint32_t dma_chan = channel_2_dma(MEM_VDI_PRP_VF_MEM, IPU_INPUT_BUFFER);
- + uint32_t mask_bit =
- + idma_mask(channel_2_dma(MEM_VDI_PRP_VF_MEM_P, IPU_INPUT_BUFFER))|
- + idma_mask(dma_chan)|
- + idma_mask(channel_2_dma(MEM_VDI_PRP_VF_MEM_N, IPU_INPUT_BUFFER));
- + unsigned long lock_flags;
- +
- + spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
- + /* Mark buffers to be ready. */
- + if (bufNum == 0)
- + ipu_cm_write(ipu, mask_bit, IPU_CHA_BUF0_RDY(dma_chan));
- + else
- + ipu_cm_write(ipu, mask_bit, IPU_CHA_BUF1_RDY(dma_chan));
- + spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(ipu_select_multi_vdi_buffer);
- +
- +#define NA -1
- +static int proc_dest_sel[] = {
- + 0, 1, 1, 3, 5, 5, 4, 7, 8, 9, 10, 11, 12, 14, 15, 16,
- + 0, 1, 1, 5, 5, 5, 5, 5, 7, 8, 9, 10, 11, 12, 14, 31 };
- +static int proc_src_sel[] = { 0, 6, 7, 6, 7, 8, 5, NA, NA, NA,
- + NA, NA, NA, NA, NA, 1, 2, 3, 4, 7, 8, NA, 8, NA };
- +static int disp_src_sel[] = { 0, 6, 7, 8, 3, 4, 5, NA, NA, NA,
- + NA, NA, NA, NA, NA, 1, NA, 2, NA, 3, 4, 4, 4, 4 };
- +
- +
- +/*!
- + * This function links 2 channels together for automatic frame
- + * synchronization. The output of the source channel is linked to the input of
- + * the destination channel.
- + *
- + * @param ipu ipu handler
- + * @param src_ch Input parameter for the logical channel ID of
- + * the source channel.
- + *
- + * @param dest_ch Input parameter for the logical channel ID of
- + * the destination channel.
- + *
- + * @return This function returns 0 on success or negative error code on
- + * fail.
- + */
- +int32_t ipu_link_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch)
- +{
- + int retval = 0;
- + uint32_t fs_proc_flow1;
- + uint32_t fs_proc_flow2;
- + uint32_t fs_proc_flow3;
- + uint32_t fs_disp_flow1;
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + fs_proc_flow1 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
- + fs_proc_flow2 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW2);
- + fs_proc_flow3 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW3);
- + fs_disp_flow1 = ipu_cm_read(ipu, IPU_FS_DISP_FLOW1);
- +
- + switch (src_ch) {
- + case CSI_MEM0:
- + fs_proc_flow3 &= ~FS_SMFC0_DEST_SEL_MASK;
- + fs_proc_flow3 |=
- + proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
- + FS_SMFC0_DEST_SEL_OFFSET;
- + break;
- + case CSI_MEM1:
- + fs_proc_flow3 &= ~FS_SMFC1_DEST_SEL_MASK;
- + fs_proc_flow3 |=
- + proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
- + FS_SMFC1_DEST_SEL_OFFSET;
- + break;
- + case CSI_MEM2:
- + fs_proc_flow3 &= ~FS_SMFC2_DEST_SEL_MASK;
- + fs_proc_flow3 |=
- + proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
- + FS_SMFC2_DEST_SEL_OFFSET;
- + break;
- + case CSI_MEM3:
- + fs_proc_flow3 &= ~FS_SMFC3_DEST_SEL_MASK;
- + fs_proc_flow3 |=
- + proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
- + FS_SMFC3_DEST_SEL_OFFSET;
- + break;
- + case CSI_PRP_ENC_MEM:
- + fs_proc_flow2 &= ~FS_PRPENC_DEST_SEL_MASK;
- + fs_proc_flow2 |=
- + proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
- + FS_PRPENC_DEST_SEL_OFFSET;
- + break;
- + case CSI_PRP_VF_MEM:
- + fs_proc_flow2 &= ~FS_PRPVF_DEST_SEL_MASK;
- + fs_proc_flow2 |=
- + proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
- + FS_PRPVF_DEST_SEL_OFFSET;
- + break;
- + case MEM_PP_MEM:
- + fs_proc_flow2 &= ~FS_PP_DEST_SEL_MASK;
- + fs_proc_flow2 |=
- + proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
- + FS_PP_DEST_SEL_OFFSET;
- + break;
- + case MEM_ROT_PP_MEM:
- + fs_proc_flow2 &= ~FS_PP_ROT_DEST_SEL_MASK;
- + fs_proc_flow2 |=
- + proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
- + FS_PP_ROT_DEST_SEL_OFFSET;
- + break;
- + case MEM_PRP_ENC_MEM:
- + fs_proc_flow2 &= ~FS_PRPENC_DEST_SEL_MASK;
- + fs_proc_flow2 |=
- + proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
- + FS_PRPENC_DEST_SEL_OFFSET;
- + break;
- + case MEM_ROT_ENC_MEM:
- + fs_proc_flow2 &= ~FS_PRPENC_ROT_DEST_SEL_MASK;
- + fs_proc_flow2 |=
- + proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
- + FS_PRPENC_ROT_DEST_SEL_OFFSET;
- + break;
- + case MEM_PRP_VF_MEM:
- + fs_proc_flow2 &= ~FS_PRPVF_DEST_SEL_MASK;
- + fs_proc_flow2 |=
- + proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
- + FS_PRPVF_DEST_SEL_OFFSET;
- + break;
- + case MEM_VDI_PRP_VF_MEM:
- + fs_proc_flow2 &= ~FS_PRPVF_DEST_SEL_MASK;
- + fs_proc_flow2 |=
- + proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
- + FS_PRPVF_DEST_SEL_OFFSET;
- + break;
- + case MEM_ROT_VF_MEM:
- + fs_proc_flow2 &= ~FS_PRPVF_ROT_DEST_SEL_MASK;
- + fs_proc_flow2 |=
- + proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
- + FS_PRPVF_ROT_DEST_SEL_OFFSET;
- + break;
- + case MEM_VDOA_MEM:
- + fs_proc_flow3 &= ~FS_VDOA_DEST_SEL_MASK;
- + if (MEM_VDI_MEM == dest_ch)
- + fs_proc_flow3 |= FS_VDOA_DEST_SEL_VDI;
- + else if (MEM_PP_MEM == dest_ch)
- + fs_proc_flow3 |= FS_VDOA_DEST_SEL_IC;
- + else {
- + retval = -EINVAL;
- + goto err;
- + }
- + break;
- + default:
- + retval = -EINVAL;
- + goto err;
- + }
- +
- + switch (dest_ch) {
- + case MEM_PP_MEM:
- + fs_proc_flow1 &= ~FS_PP_SRC_SEL_MASK;
- + if (MEM_VDOA_MEM == src_ch)
- + fs_proc_flow1 |= FS_PP_SRC_SEL_VDOA;
- + else
- + fs_proc_flow1 |= proc_src_sel[IPU_CHAN_ID(src_ch)] <<
- + FS_PP_SRC_SEL_OFFSET;
- + break;
- + case MEM_ROT_PP_MEM:
- + fs_proc_flow1 &= ~FS_PP_ROT_SRC_SEL_MASK;
- + fs_proc_flow1 |=
- + proc_src_sel[IPU_CHAN_ID(src_ch)] <<
- + FS_PP_ROT_SRC_SEL_OFFSET;
- + break;
- + case MEM_PRP_ENC_MEM:
- + fs_proc_flow1 &= ~FS_PRP_SRC_SEL_MASK;
- + fs_proc_flow1 |=
- + proc_src_sel[IPU_CHAN_ID(src_ch)] << FS_PRP_SRC_SEL_OFFSET;
- + break;
- + case MEM_ROT_ENC_MEM:
- + fs_proc_flow1 &= ~FS_PRPENC_ROT_SRC_SEL_MASK;
- + fs_proc_flow1 |=
- + proc_src_sel[IPU_CHAN_ID(src_ch)] <<
- + FS_PRPENC_ROT_SRC_SEL_OFFSET;
- + break;
- + case MEM_PRP_VF_MEM:
- + fs_proc_flow1 &= ~FS_PRP_SRC_SEL_MASK;
- + fs_proc_flow1 |=
- + proc_src_sel[IPU_CHAN_ID(src_ch)] << FS_PRP_SRC_SEL_OFFSET;
- + break;
- + case MEM_VDI_PRP_VF_MEM:
- + fs_proc_flow1 &= ~FS_PRP_SRC_SEL_MASK;
- + fs_proc_flow1 |=
- + proc_src_sel[IPU_CHAN_ID(src_ch)] << FS_PRP_SRC_SEL_OFFSET;
- + break;
- + case MEM_ROT_VF_MEM:
- + fs_proc_flow1 &= ~FS_PRPVF_ROT_SRC_SEL_MASK;
- + fs_proc_flow1 |=
- + proc_src_sel[IPU_CHAN_ID(src_ch)] <<
- + FS_PRPVF_ROT_SRC_SEL_OFFSET;
- + break;
- + case MEM_DC_SYNC:
- + fs_disp_flow1 &= ~FS_DC1_SRC_SEL_MASK;
- + fs_disp_flow1 |=
- + disp_src_sel[IPU_CHAN_ID(src_ch)] << FS_DC1_SRC_SEL_OFFSET;
- + break;
- + case MEM_BG_SYNC:
- + fs_disp_flow1 &= ~FS_DP_SYNC0_SRC_SEL_MASK;
- + fs_disp_flow1 |=
- + disp_src_sel[IPU_CHAN_ID(src_ch)] <<
- + FS_DP_SYNC0_SRC_SEL_OFFSET;
- + break;
- + case MEM_FG_SYNC:
- + fs_disp_flow1 &= ~FS_DP_SYNC1_SRC_SEL_MASK;
- + fs_disp_flow1 |=
- + disp_src_sel[IPU_CHAN_ID(src_ch)] <<
- + FS_DP_SYNC1_SRC_SEL_OFFSET;
- + break;
- + case MEM_DC_ASYNC:
- + fs_disp_flow1 &= ~FS_DC2_SRC_SEL_MASK;
- + fs_disp_flow1 |=
- + disp_src_sel[IPU_CHAN_ID(src_ch)] << FS_DC2_SRC_SEL_OFFSET;
- + break;
- + case MEM_BG_ASYNC0:
- + fs_disp_flow1 &= ~FS_DP_ASYNC0_SRC_SEL_MASK;
- + fs_disp_flow1 |=
- + disp_src_sel[IPU_CHAN_ID(src_ch)] <<
- + FS_DP_ASYNC0_SRC_SEL_OFFSET;
- + break;
- + case MEM_FG_ASYNC0:
- + fs_disp_flow1 &= ~FS_DP_ASYNC1_SRC_SEL_MASK;
- + fs_disp_flow1 |=
- + disp_src_sel[IPU_CHAN_ID(src_ch)] <<
- + FS_DP_ASYNC1_SRC_SEL_OFFSET;
- + break;
- + case MEM_VDI_MEM:
- + fs_proc_flow1 &= ~FS_VDI_SRC_SEL_MASK;
- + if (MEM_VDOA_MEM == src_ch)
- + fs_proc_flow1 |= FS_VDI_SRC_SEL_VDOA;
- + else {
- + retval = -EINVAL;
- + goto err;
- + }
- + break;
- + default:
- + retval = -EINVAL;
- + goto err;
- + }
- +
- + ipu_cm_write(ipu, fs_proc_flow1, IPU_FS_PROC_FLOW1);
- + ipu_cm_write(ipu, fs_proc_flow2, IPU_FS_PROC_FLOW2);
- + ipu_cm_write(ipu, fs_proc_flow3, IPU_FS_PROC_FLOW3);
- + ipu_cm_write(ipu, fs_disp_flow1, IPU_FS_DISP_FLOW1);
- +
- +err:
- + mutex_unlock(&ipu->mutex_lock);
- + return retval;
- +}
- +EXPORT_SYMBOL(ipu_link_channels);
- +
- +/*!
- + * This function unlinks 2 channels and disables automatic frame
- + * synchronization.
- + *
- + * @param ipu ipu handler
- + * @param src_ch Input parameter for the logical channel ID of
- + * the source channel.
- + *
- + * @param dest_ch Input parameter for the logical channel ID of
- + * the destination channel.
- + *
- + * @return This function returns 0 on success or negative error code on
- + * fail.
- + */
- +int32_t ipu_unlink_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch)
- +{
- + int retval = 0;
- + uint32_t fs_proc_flow1;
- + uint32_t fs_proc_flow2;
- + uint32_t fs_proc_flow3;
- + uint32_t fs_disp_flow1;
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + fs_proc_flow1 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
- + fs_proc_flow2 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW2);
- + fs_proc_flow3 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW3);
- + fs_disp_flow1 = ipu_cm_read(ipu, IPU_FS_DISP_FLOW1);
- +
- + switch (src_ch) {
- + case CSI_MEM0:
- + fs_proc_flow3 &= ~FS_SMFC0_DEST_SEL_MASK;
- + break;
- + case CSI_MEM1:
- + fs_proc_flow3 &= ~FS_SMFC1_DEST_SEL_MASK;
- + break;
- + case CSI_MEM2:
- + fs_proc_flow3 &= ~FS_SMFC2_DEST_SEL_MASK;
- + break;
- + case CSI_MEM3:
- + fs_proc_flow3 &= ~FS_SMFC3_DEST_SEL_MASK;
- + break;
- + case CSI_PRP_ENC_MEM:
- + fs_proc_flow2 &= ~FS_PRPENC_DEST_SEL_MASK;
- + break;
- + case CSI_PRP_VF_MEM:
- + fs_proc_flow2 &= ~FS_PRPVF_DEST_SEL_MASK;
- + break;
- + case MEM_PP_MEM:
- + fs_proc_flow2 &= ~FS_PP_DEST_SEL_MASK;
- + break;
- + case MEM_ROT_PP_MEM:
- + fs_proc_flow2 &= ~FS_PP_ROT_DEST_SEL_MASK;
- + break;
- + case MEM_PRP_ENC_MEM:
- + fs_proc_flow2 &= ~FS_PRPENC_DEST_SEL_MASK;
- + break;
- + case MEM_ROT_ENC_MEM:
- + fs_proc_flow2 &= ~FS_PRPENC_ROT_DEST_SEL_MASK;
- + break;
- + case MEM_PRP_VF_MEM:
- + fs_proc_flow2 &= ~FS_PRPVF_DEST_SEL_MASK;
- + break;
- + case MEM_VDI_PRP_VF_MEM:
- + fs_proc_flow2 &= ~FS_PRPVF_DEST_SEL_MASK;
- + break;
- + case MEM_ROT_VF_MEM:
- + fs_proc_flow2 &= ~FS_PRPVF_ROT_DEST_SEL_MASK;
- + break;
- + case MEM_VDOA_MEM:
- + fs_proc_flow3 &= ~FS_VDOA_DEST_SEL_MASK;
- + break;
- + default:
- + retval = -EINVAL;
- + goto err;
- + }
- +
- + switch (dest_ch) {
- + case MEM_PP_MEM:
- + fs_proc_flow1 &= ~FS_PP_SRC_SEL_MASK;
- + break;
- + case MEM_ROT_PP_MEM:
- + fs_proc_flow1 &= ~FS_PP_ROT_SRC_SEL_MASK;
- + break;
- + case MEM_PRP_ENC_MEM:
- + fs_proc_flow1 &= ~FS_PRP_SRC_SEL_MASK;
- + break;
- + case MEM_ROT_ENC_MEM:
- + fs_proc_flow1 &= ~FS_PRPENC_ROT_SRC_SEL_MASK;
- + break;
- + case MEM_PRP_VF_MEM:
- + fs_proc_flow1 &= ~FS_PRP_SRC_SEL_MASK;
- + break;
- + case MEM_VDI_PRP_VF_MEM:
- + fs_proc_flow1 &= ~FS_PRP_SRC_SEL_MASK;
- + break;
- + case MEM_ROT_VF_MEM:
- + fs_proc_flow1 &= ~FS_PRPVF_ROT_SRC_SEL_MASK;
- + break;
- + case MEM_DC_SYNC:
- + fs_disp_flow1 &= ~FS_DC1_SRC_SEL_MASK;
- + break;
- + case MEM_BG_SYNC:
- + fs_disp_flow1 &= ~FS_DP_SYNC0_SRC_SEL_MASK;
- + break;
- + case MEM_FG_SYNC:
- + fs_disp_flow1 &= ~FS_DP_SYNC1_SRC_SEL_MASK;
- + break;
- + case MEM_DC_ASYNC:
- + fs_disp_flow1 &= ~FS_DC2_SRC_SEL_MASK;
- + break;
- + case MEM_BG_ASYNC0:
- + fs_disp_flow1 &= ~FS_DP_ASYNC0_SRC_SEL_MASK;
- + break;
- + case MEM_FG_ASYNC0:
- + fs_disp_flow1 &= ~FS_DP_ASYNC1_SRC_SEL_MASK;
- + break;
- + case MEM_VDI_MEM:
- + fs_proc_flow1 &= ~FS_VDI_SRC_SEL_MASK;
- + break;
- + default:
- + retval = -EINVAL;
- + goto err;
- + }
- +
- + ipu_cm_write(ipu, fs_proc_flow1, IPU_FS_PROC_FLOW1);
- + ipu_cm_write(ipu, fs_proc_flow2, IPU_FS_PROC_FLOW2);
- + ipu_cm_write(ipu, fs_proc_flow3, IPU_FS_PROC_FLOW3);
- + ipu_cm_write(ipu, fs_disp_flow1, IPU_FS_DISP_FLOW1);
- +
- +err:
- + mutex_unlock(&ipu->mutex_lock);
- + return retval;
- +}
- +EXPORT_SYMBOL(ipu_unlink_channels);
- +
- +/*!
- + * This function check whether a logical channel was enabled.
- + *
- + * @param ipu ipu handler
- + * @param channel Input parameter for the logical channel ID.
- + *
- + * @return This function returns 1 while request channel is enabled or
- + * 0 for not enabled.
- + */
- +int32_t ipu_is_channel_busy(struct ipu_soc *ipu, ipu_channel_t channel)
- +{
- + uint32_t reg;
- + uint32_t in_dma;
- + uint32_t out_dma;
- +
- + out_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER);
- + in_dma = channel_2_dma(channel, IPU_VIDEO_IN_BUFFER);
- +
- + reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(in_dma));
- + if (reg & idma_mask(in_dma))
- + return 1;
- + reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(out_dma));
- + if (reg & idma_mask(out_dma))
- + return 1;
- + return 0;
- +}
- +EXPORT_SYMBOL(ipu_is_channel_busy);
- +
- +/*!
- + * This function enables a logical channel.
- + *
- + * @param ipu ipu handler
- + * @param channel Input parameter for the logical channel ID.
- + *
- + * @return This function returns 0 on success or negative error code on
- + * fail.
- + */
- +int32_t ipu_enable_channel(struct ipu_soc *ipu, ipu_channel_t channel)
- +{
- + uint32_t reg;
- + uint32_t ipu_conf;
- + uint32_t in_dma;
- + uint32_t out_dma;
- + uint32_t sec_dma;
- + uint32_t thrd_dma;
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + if (ipu->channel_enable_mask & (1L << IPU_CHAN_ID(channel))) {
- + dev_err(ipu->dev, "Warning: channel already enabled %d\n",
- + IPU_CHAN_ID(channel));
- + mutex_unlock(&ipu->mutex_lock);
- + return -EACCES;
- + }
- +
- + /* Get input and output dma channels */
- + out_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER);
- + in_dma = channel_2_dma(channel, IPU_VIDEO_IN_BUFFER);
- +
- + ipu_conf = ipu_cm_read(ipu, IPU_CONF);
- + if (ipu->di_use_count[0] > 0) {
- + ipu_conf |= IPU_CONF_DI0_EN;
- + }
- + if (ipu->di_use_count[1] > 0) {
- + ipu_conf |= IPU_CONF_DI1_EN;
- + }
- + if (ipu->dp_use_count > 0)
- + ipu_conf |= IPU_CONF_DP_EN;
- + if (ipu->dc_use_count > 0)
- + ipu_conf |= IPU_CONF_DC_EN;
- + if (ipu->dmfc_use_count > 0)
- + ipu_conf |= IPU_CONF_DMFC_EN;
- + if (ipu->ic_use_count > 0)
- + ipu_conf |= IPU_CONF_IC_EN;
- + if (ipu->vdi_use_count > 0) {
- + ipu_conf |= IPU_CONF_ISP_EN;
- + ipu_conf |= IPU_CONF_VDI_EN;
- + ipu_conf |= IPU_CONF_IC_INPUT;
- + }
- + if (ipu->rot_use_count > 0)
- + ipu_conf |= IPU_CONF_ROT_EN;
- + if (ipu->smfc_use_count > 0)
- + ipu_conf |= IPU_CONF_SMFC_EN;
- + ipu_cm_write(ipu, ipu_conf, IPU_CONF);
- +
- + if (idma_is_valid(in_dma)) {
- + reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(in_dma));
- + ipu_idmac_write(ipu, reg | idma_mask(in_dma), IDMAC_CHA_EN(in_dma));
- + }
- + if (idma_is_valid(out_dma)) {
- + reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(out_dma));
- + ipu_idmac_write(ipu, reg | idma_mask(out_dma), IDMAC_CHA_EN(out_dma));
- + }
- +
- + if ((ipu->sec_chan_en[IPU_CHAN_ID(channel)]) &&
- + ((channel == MEM_PP_MEM) || (channel == MEM_PRP_VF_MEM) ||
- + (channel == MEM_VDI_PRP_VF_MEM))) {
- + sec_dma = channel_2_dma(channel, IPU_GRAPH_IN_BUFFER);
- + reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(sec_dma));
- + ipu_idmac_write(ipu, reg | idma_mask(sec_dma), IDMAC_CHA_EN(sec_dma));
- + }
- + if ((ipu->thrd_chan_en[IPU_CHAN_ID(channel)]) &&
- + ((channel == MEM_PP_MEM) || (channel == MEM_PRP_VF_MEM))) {
- + thrd_dma = channel_2_dma(channel, IPU_ALPHA_IN_BUFFER);
- + reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(thrd_dma));
- + ipu_idmac_write(ipu, reg | idma_mask(thrd_dma), IDMAC_CHA_EN(thrd_dma));
- +
- + sec_dma = channel_2_dma(channel, IPU_GRAPH_IN_BUFFER);
- + reg = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
- + ipu_idmac_write(ipu, reg | idma_mask(sec_dma), IDMAC_SEP_ALPHA);
- + } else if ((ipu->thrd_chan_en[IPU_CHAN_ID(channel)]) &&
- + ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC))) {
- + thrd_dma = channel_2_dma(channel, IPU_ALPHA_IN_BUFFER);
- + reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(thrd_dma));
- + ipu_idmac_write(ipu, reg | idma_mask(thrd_dma), IDMAC_CHA_EN(thrd_dma));
- + reg = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
- + ipu_idmac_write(ipu, reg | idma_mask(in_dma), IDMAC_SEP_ALPHA);
- + }
- +
- + if ((channel == MEM_DC_SYNC) || (channel == MEM_BG_SYNC) ||
- + (channel == MEM_FG_SYNC)) {
- + reg = ipu_idmac_read(ipu, IDMAC_WM_EN(in_dma));
- + ipu_idmac_write(ipu, reg | idma_mask(in_dma), IDMAC_WM_EN(in_dma));
- +
- + _ipu_dp_dc_enable(ipu, channel);
- + }
- +
- + if (_ipu_is_ic_chan(in_dma) || _ipu_is_ic_chan(out_dma) ||
- + _ipu_is_irt_chan(in_dma) || _ipu_is_irt_chan(out_dma) ||
- + _ipu_is_vdi_out_chan(out_dma))
- + _ipu_ic_enable_task(ipu, channel);
- +
- + ipu->channel_enable_mask |= 1L << IPU_CHAN_ID(channel);
- +
- + mutex_unlock(&ipu->mutex_lock);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(ipu_enable_channel);
- +
- +/*!
- + * This function check buffer ready for a logical channel.
- + *
- + * @param ipu ipu handler
- + * @param channel Input parameter for the logical channel ID.
- + *
- + * @param type Input parameter which buffer to clear.
- + *
- + * @param bufNum Input parameter for which buffer number clear
- + * ready state.
- + *
- + */
- +int32_t ipu_check_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
- + uint32_t bufNum)
- +{
- + uint32_t dma_chan = channel_2_dma(channel, type);
- + uint32_t reg;
- + unsigned long lock_flags;
- +
- + if (dma_chan == IDMA_CHAN_INVALID)
- + return -EINVAL;
- +
- + spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
- + if (bufNum == 0)
- + reg = ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(dma_chan));
- + else if (bufNum == 1)
- + reg = ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(dma_chan));
- + else
- + reg = ipu_cm_read(ipu, IPU_CHA_BUF2_RDY(dma_chan));
- + spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
- +
- + if (reg & idma_mask(dma_chan))
- + return 1;
- + else
- + return 0;
- +}
- +EXPORT_SYMBOL(ipu_check_buffer_ready);
- +
- +/*!
- + * This function clear buffer ready for a logical channel.
- + *
- + * @param ipu ipu handler
- + * @param channel Input parameter for the logical channel ID.
- + *
- + * @param type Input parameter which buffer to clear.
- + *
- + * @param bufNum Input parameter for which buffer number clear
- + * ready state.
- + *
- + */
- +void _ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
- + uint32_t bufNum)
- +{
- + uint32_t dma_ch = channel_2_dma(channel, type);
- +
- + if (!idma_is_valid(dma_ch))
- + return;
- +
- + ipu_cm_write(ipu, 0xF0300000, IPU_GPR); /* write one to clear */
- + if (bufNum == 0)
- + ipu_cm_write(ipu, idma_mask(dma_ch),
- + IPU_CHA_BUF0_RDY(dma_ch));
- + else if (bufNum == 1)
- + ipu_cm_write(ipu, idma_mask(dma_ch),
- + IPU_CHA_BUF1_RDY(dma_ch));
- + else
- + ipu_cm_write(ipu, idma_mask(dma_ch),
- + IPU_CHA_BUF2_RDY(dma_ch));
- + ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
- +}
- +
- +void ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
- + uint32_t bufNum)
- +{
- + unsigned long lock_flags;
- +
- + spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
- + _ipu_clear_buffer_ready(ipu, channel, type, bufNum);
- + spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
- +}
- +EXPORT_SYMBOL(ipu_clear_buffer_ready);
- +
- +/*!
- + * This function disables a logical channel.
- + *
- + * @param ipu ipu handler
- + * @param channel Input parameter for the logical channel ID.
- + *
- + * @param wait_for_stop Flag to set whether to wait for channel end
- + * of frame or return immediately.
- + *
- + * @return This function returns 0 on success or negative error code on
- + * fail.
- + */
- +int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wait_for_stop)
- +{
- + uint32_t reg;
- + uint32_t in_dma;
- + uint32_t out_dma;
- + uint32_t sec_dma = NO_DMA;
- + uint32_t thrd_dma = NO_DMA;
- + uint16_t fg_pos_x, fg_pos_y;
- + unsigned long lock_flags;
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + if ((ipu->channel_enable_mask & (1L << IPU_CHAN_ID(channel))) == 0) {
- + dev_dbg(ipu->dev, "Channel already disabled %d\n",
- + IPU_CHAN_ID(channel));
- + mutex_unlock(&ipu->mutex_lock);
- + return -EACCES;
- + }
- +
- + /* Get input and output dma channels */
- + out_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER);
- + in_dma = channel_2_dma(channel, IPU_VIDEO_IN_BUFFER);
- +
- + if ((idma_is_valid(in_dma) &&
- + !idma_is_set(ipu, IDMAC_CHA_EN, in_dma))
- + && (idma_is_valid(out_dma) &&
- + !idma_is_set(ipu, IDMAC_CHA_EN, out_dma))) {
- + mutex_unlock(&ipu->mutex_lock);
- + return -EINVAL;
- + }
- +
- + if (ipu->sec_chan_en[IPU_CHAN_ID(channel)])
- + sec_dma = channel_2_dma(channel, IPU_GRAPH_IN_BUFFER);
- + if (ipu->thrd_chan_en[IPU_CHAN_ID(channel)]) {
- + sec_dma = channel_2_dma(channel, IPU_GRAPH_IN_BUFFER);
- + thrd_dma = channel_2_dma(channel, IPU_ALPHA_IN_BUFFER);
- + }
- +
- + if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC) ||
- + (channel == MEM_DC_SYNC)) {
- + if (channel == MEM_FG_SYNC) {
- + _ipu_disp_get_window_pos(ipu, channel, &fg_pos_x, &fg_pos_y);
- + _ipu_disp_set_window_pos(ipu, channel, 0, 0);
- + }
- +
- + _ipu_dp_dc_disable(ipu, channel, false);
- +
- + /*
- + * wait for BG channel EOF then disable FG-IDMAC,
- + * it avoid FG NFB4EOF error.
- + */
- + if ((channel == MEM_FG_SYNC) && (ipu_is_channel_busy(ipu, MEM_BG_SYNC))) {
- + int timeout = 50;
- +
- + ipu_cm_write(ipu, IPUIRQ_2_MASK(IPU_IRQ_BG_SYNC_EOF),
- + IPUIRQ_2_STATREG(IPU_IRQ_BG_SYNC_EOF));
- + while ((ipu_cm_read(ipu, IPUIRQ_2_STATREG(IPU_IRQ_BG_SYNC_EOF)) &
- + IPUIRQ_2_MASK(IPU_IRQ_BG_SYNC_EOF)) == 0) {
- + msleep(10);
- + timeout -= 10;
- + if (timeout <= 0) {
- + dev_err(ipu->dev, "warning: wait for bg sync eof timeout\n");
- + break;
- + }
- + }
- + }
- + } else if (wait_for_stop && !_ipu_is_smfc_chan(out_dma) &&
- + channel != CSI_PRP_VF_MEM && channel != CSI_PRP_ENC_MEM) {
- + while (idma_is_set(ipu, IDMAC_CHA_BUSY, in_dma) ||
- + idma_is_set(ipu, IDMAC_CHA_BUSY, out_dma) ||
- + (ipu->sec_chan_en[IPU_CHAN_ID(channel)] &&
- + idma_is_set(ipu, IDMAC_CHA_BUSY, sec_dma)) ||
- + (ipu->thrd_chan_en[IPU_CHAN_ID(channel)] &&
- + idma_is_set(ipu, IDMAC_CHA_BUSY, thrd_dma))) {
- + uint32_t irq = 0xffffffff;
- + int timeout = 50000;
- +
- + if (idma_is_set(ipu, IDMAC_CHA_BUSY, out_dma))
- + irq = out_dma;
- + if (ipu->sec_chan_en[IPU_CHAN_ID(channel)] &&
- + idma_is_set(ipu, IDMAC_CHA_BUSY, sec_dma))
- + irq = sec_dma;
- + if (ipu->thrd_chan_en[IPU_CHAN_ID(channel)] &&
- + idma_is_set(ipu, IDMAC_CHA_BUSY, thrd_dma))
- + irq = thrd_dma;
- + if (idma_is_set(ipu, IDMAC_CHA_BUSY, in_dma))
- + irq = in_dma;
- +
- + if (irq == 0xffffffff) {
- + dev_dbg(ipu->dev, "warning: no channel busy, break\n");
- + break;
- + }
- +
- + ipu_cm_write(ipu, IPUIRQ_2_MASK(irq),
- + IPUIRQ_2_STATREG(irq));
- +
- + dev_dbg(ipu->dev, "warning: channel %d busy, need wait\n", irq);
- +
- + while (((ipu_cm_read(ipu, IPUIRQ_2_STATREG(irq))
- + & IPUIRQ_2_MASK(irq)) == 0) &&
- + (idma_is_set(ipu, IDMAC_CHA_BUSY, irq))) {
- + udelay(10);
- + timeout -= 10;
- + if (timeout <= 0) {
- + ipu_dump_registers(ipu);
- + dev_err(ipu->dev, "warning: disable ipu dma channel %d during its busy state\n", irq);
- + break;
- + }
- + }
- + dev_dbg(ipu->dev, "wait_time:%d\n", 50000 - timeout);
- +
- + }
- + }
- +
- + if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC) ||
- + (channel == MEM_DC_SYNC)) {
- + reg = ipu_idmac_read(ipu, IDMAC_WM_EN(in_dma));
- + ipu_idmac_write(ipu, reg & ~idma_mask(in_dma), IDMAC_WM_EN(in_dma));
- + }
- +
- + /* Disable IC task */
- + if (_ipu_is_ic_chan(in_dma) || _ipu_is_ic_chan(out_dma) ||
- + _ipu_is_irt_chan(in_dma) || _ipu_is_irt_chan(out_dma) ||
- + _ipu_is_vdi_out_chan(out_dma))
- + _ipu_ic_disable_task(ipu, channel);
- +
- + /* Disable DMA channel(s) */
- + if (idma_is_valid(in_dma)) {
- + reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(in_dma));
- + ipu_idmac_write(ipu, reg & ~idma_mask(in_dma), IDMAC_CHA_EN(in_dma));
- + ipu_cm_write(ipu, idma_mask(in_dma), IPU_CHA_CUR_BUF(in_dma));
- + ipu_cm_write(ipu, tri_cur_buf_mask(in_dma),
- + IPU_CHA_TRIPLE_CUR_BUF(in_dma));
- + }
- + if (idma_is_valid(out_dma)) {
- + reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(out_dma));
- + ipu_idmac_write(ipu, reg & ~idma_mask(out_dma), IDMAC_CHA_EN(out_dma));
- + ipu_cm_write(ipu, idma_mask(out_dma), IPU_CHA_CUR_BUF(out_dma));
- + ipu_cm_write(ipu, tri_cur_buf_mask(out_dma),
- + IPU_CHA_TRIPLE_CUR_BUF(out_dma));
- + }
- + if (ipu->sec_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(sec_dma)) {
- + reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(sec_dma));
- + ipu_idmac_write(ipu, reg & ~idma_mask(sec_dma), IDMAC_CHA_EN(sec_dma));
- + ipu_cm_write(ipu, idma_mask(sec_dma), IPU_CHA_CUR_BUF(sec_dma));
- + }
- + if (ipu->thrd_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(thrd_dma)) {
- + reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(thrd_dma));
- + ipu_idmac_write(ipu, reg & ~idma_mask(thrd_dma), IDMAC_CHA_EN(thrd_dma));
- + if (channel == MEM_BG_SYNC || channel == MEM_FG_SYNC) {
- + reg = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
- + ipu_idmac_write(ipu, reg & ~idma_mask(in_dma), IDMAC_SEP_ALPHA);
- + } else {
- + reg = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
- + ipu_idmac_write(ipu, reg & ~idma_mask(sec_dma), IDMAC_SEP_ALPHA);
- + }
- + ipu_cm_write(ipu, idma_mask(thrd_dma), IPU_CHA_CUR_BUF(thrd_dma));
- + }
- +
- + if (channel == MEM_FG_SYNC)
- + _ipu_disp_set_window_pos(ipu, channel, fg_pos_x, fg_pos_y);
- +
- + spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
- + /* Set channel buffers NOT to be ready */
- + if (idma_is_valid(in_dma)) {
- + _ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 0);
- + _ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 1);
- + _ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 2);
- + }
- + if (idma_is_valid(out_dma)) {
- + _ipu_clear_buffer_ready(ipu, channel, IPU_OUTPUT_BUFFER, 0);
- + _ipu_clear_buffer_ready(ipu, channel, IPU_OUTPUT_BUFFER, 1);
- + }
- + if (ipu->sec_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(sec_dma)) {
- + _ipu_clear_buffer_ready(ipu, channel, IPU_GRAPH_IN_BUFFER, 0);
- + _ipu_clear_buffer_ready(ipu, channel, IPU_GRAPH_IN_BUFFER, 1);
- + }
- + if (ipu->thrd_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(thrd_dma)) {
- + _ipu_clear_buffer_ready(ipu, channel, IPU_ALPHA_IN_BUFFER, 0);
- + _ipu_clear_buffer_ready(ipu, channel, IPU_ALPHA_IN_BUFFER, 1);
- + }
- + spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
- +
- + ipu->channel_enable_mask &= ~(1L << IPU_CHAN_ID(channel));
- +
- + mutex_unlock(&ipu->mutex_lock);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(ipu_disable_channel);
- +
- +/*!
- + * This function enables CSI.
- + *
- + * @param ipu ipu handler
- + * @param csi csi num 0 or 1
- + *
- + * @return This function returns 0 on success or negative error code on
- + * fail.
- + */
- +int32_t ipu_enable_csi(struct ipu_soc *ipu, uint32_t csi)
- +{
- + uint32_t reg;
- +
- + if (csi > 1) {
- + dev_err(ipu->dev, "Wrong csi num_%d\n", csi);
- + return -EINVAL;
- + }
- +
- + _ipu_get(ipu);
- + mutex_lock(&ipu->mutex_lock);
- + ipu->csi_use_count[csi]++;
- +
- + if (ipu->csi_use_count[csi] == 1) {
- + reg = ipu_cm_read(ipu, IPU_CONF);
- + if (csi == 0)
- + ipu_cm_write(ipu, reg | IPU_CONF_CSI0_EN, IPU_CONF);
- + else
- + ipu_cm_write(ipu, reg | IPU_CONF_CSI1_EN, IPU_CONF);
- + }
- + mutex_unlock(&ipu->mutex_lock);
- + _ipu_put(ipu);
- + return 0;
- +}
- +EXPORT_SYMBOL(ipu_enable_csi);
- +
- +/*!
- + * This function disables CSI.
- + *
- + * @param ipu ipu handler
- + * @param csi csi num 0 or 1
- + *
- + * @return This function returns 0 on success or negative error code on
- + * fail.
- + */
- +int32_t ipu_disable_csi(struct ipu_soc *ipu, uint32_t csi)
- +{
- + uint32_t reg;
- +
- + if (csi > 1) {
- + dev_err(ipu->dev, "Wrong csi num_%d\n", csi);
- + return -EINVAL;
- + }
- + _ipu_get(ipu);
- + mutex_lock(&ipu->mutex_lock);
- + ipu->csi_use_count[csi]--;
- + if (ipu->csi_use_count[csi] == 0) {
- + _ipu_csi_wait4eof(ipu, ipu->csi_channel[csi]);
- + reg = ipu_cm_read(ipu, IPU_CONF);
- + if (csi == 0)
- + ipu_cm_write(ipu, reg & ~IPU_CONF_CSI0_EN, IPU_CONF);
- + else
- + ipu_cm_write(ipu, reg & ~IPU_CONF_CSI1_EN, IPU_CONF);
- + }
- + mutex_unlock(&ipu->mutex_lock);
- + _ipu_put(ipu);
- + return 0;
- +}
- +EXPORT_SYMBOL(ipu_disable_csi);
- +
- +static irqreturn_t ipu_sync_irq_handler(int irq, void *desc)
- +{
- + struct ipu_soc *ipu = desc;
- + int i;
- + uint32_t line, bit, int_stat, int_ctrl;
- + irqreturn_t result = IRQ_NONE;
- + const int int_reg[] = { 1, 2, 3, 4, 11, 12, 13, 14, 15, 0 };
- +
- + spin_lock(&ipu->int_reg_spin_lock);
- +
- + for (i = 0; int_reg[i] != 0; i++) {
- + int_stat = ipu_cm_read(ipu, IPU_INT_STAT(int_reg[i]));
- + int_ctrl = ipu_cm_read(ipu, IPU_INT_CTRL(int_reg[i]));
- + int_stat &= int_ctrl;
- + ipu_cm_write(ipu, int_stat, IPU_INT_STAT(int_reg[i]));
- + while ((line = ffs(int_stat)) != 0) {
- + bit = --line;
- + int_stat &= ~(1UL << line);
- + line += (int_reg[i] - 1) * 32;
- + result |=
- + ipu->irq_list[line].handler(line,
- + ipu->irq_list[line].
- + dev_id);
- + if (ipu->irq_list[line].flags & IPU_IRQF_ONESHOT) {
- + int_ctrl &= ~(1UL << bit);
- + ipu_cm_write(ipu, int_ctrl,
- + IPU_INT_CTRL(int_reg[i]));
- + }
- + }
- + }
- +
- + spin_unlock(&ipu->int_reg_spin_lock);
- +
- + return result;
- +}
- +
- +static irqreturn_t ipu_err_irq_handler(int irq, void *desc)
- +{
- + struct ipu_soc *ipu = desc;
- + int i;
- + uint32_t int_stat;
- + const int err_reg[] = { 5, 6, 9, 10, 0 };
- +
- + spin_lock(&ipu->int_reg_spin_lock);
- +
- + for (i = 0; err_reg[i] != 0; i++) {
- + int_stat = ipu_cm_read(ipu, IPU_INT_STAT(err_reg[i]));
- + int_stat &= ipu_cm_read(ipu, IPU_INT_CTRL(err_reg[i]));
- + if (int_stat) {
- + ipu_cm_write(ipu, int_stat, IPU_INT_STAT(err_reg[i]));
- + dev_warn(ipu->dev,
- + "IPU Warning - IPU_INT_STAT_%d = 0x%08X\n",
- + err_reg[i], int_stat);
- + /* Disable interrupts so we only get error once */
- + int_stat = ipu_cm_read(ipu, IPU_INT_CTRL(err_reg[i])) &
- + ~int_stat;
- + ipu_cm_write(ipu, int_stat, IPU_INT_CTRL(err_reg[i]));
- + }
- + }
- +
- + spin_unlock(&ipu->int_reg_spin_lock);
- +
- + return IRQ_HANDLED;
- +}
- +
- +/*!
- + * This function enables the interrupt for the specified interrupt line.
- + * The interrupt lines are defined in \b ipu_irq_line enum.
- + *
- + * @param ipu ipu handler
- + * @param irq Interrupt line to enable interrupt for.
- + *
- + * @return This function returns 0 on success or negative error code on
- + * fail.
- + */
- +int ipu_enable_irq(struct ipu_soc *ipu, uint32_t irq)
- +{
- + uint32_t reg;
- + unsigned long lock_flags;
- + int ret = 0;
- +
- + _ipu_get(ipu);
- +
- + spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
- +
- + /*
- + * Check sync interrupt handler only, since we do nothing for
- + * error interrupts but than print out register values in the
- + * error interrupt source handler.
- + */
- + if (_ipu_is_sync_irq(irq) && (ipu->irq_list[irq].handler == NULL)) {
- + dev_err(ipu->dev, "handler hasn't been registered on sync "
- + "irq %d\n", irq);
- + ret = -EACCES;
- + goto out;
- + }
- +
- + reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
- + reg |= IPUIRQ_2_MASK(irq);
- + ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
- +out:
- + spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
- +
- + _ipu_put(ipu);
- +
- + return ret;
- +}
- +EXPORT_SYMBOL(ipu_enable_irq);
- +
- +/*!
- + * This function disables the interrupt for the specified interrupt line.
- + * The interrupt lines are defined in \b ipu_irq_line enum.
- + *
- + * @param ipu ipu handler
- + * @param irq Interrupt line to disable interrupt for.
- + *
- + */
- +void ipu_disable_irq(struct ipu_soc *ipu, uint32_t irq)
- +{
- + uint32_t reg;
- + unsigned long lock_flags;
- +
- + _ipu_get(ipu);
- +
- + spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
- +
- + reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
- + reg &= ~IPUIRQ_2_MASK(irq);
- + ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
- +
- + spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
- +
- + _ipu_put(ipu);
- +}
- +EXPORT_SYMBOL(ipu_disable_irq);
- +
- +/*!
- + * This function clears the interrupt for the specified interrupt line.
- + * The interrupt lines are defined in \b ipu_irq_line enum.
- + *
- + * @param ipu ipu handler
- + * @param irq Interrupt line to clear interrupt for.
- + *
- + */
- +void ipu_clear_irq(struct ipu_soc *ipu, uint32_t irq)
- +{
- + unsigned long lock_flags;
- +
- + _ipu_get(ipu);
- +
- + spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
- +
- + ipu_cm_write(ipu, IPUIRQ_2_MASK(irq), IPUIRQ_2_STATREG(irq));
- +
- + spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
- +
- + _ipu_put(ipu);
- +}
- +EXPORT_SYMBOL(ipu_clear_irq);
- +
- +/*!
- + * This function returns the current interrupt status for the specified
- + * interrupt line. The interrupt lines are defined in \b ipu_irq_line enum.
- + *
- + * @param ipu ipu handler
- + * @param irq Interrupt line to get status for.
- + *
- + * @return Returns true if the interrupt is pending/asserted or false if
- + * the interrupt is not pending.
- + */
- +bool ipu_get_irq_status(struct ipu_soc *ipu, uint32_t irq)
- +{
- + uint32_t reg;
- + unsigned long lock_flags;
- +
- + _ipu_get(ipu);
- +
- + spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
- + reg = ipu_cm_read(ipu, IPUIRQ_2_STATREG(irq));
- + spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
- +
- + _ipu_put(ipu);
- +
- + if (reg & IPUIRQ_2_MASK(irq))
- + return true;
- + else
- + return false;
- +}
- +EXPORT_SYMBOL(ipu_get_irq_status);
- +
- +/*!
- + * This function registers an interrupt handler function for the specified
- + * interrupt line. The interrupt lines are defined in \b ipu_irq_line enum.
- + *
- + * @param ipu ipu handler
- + * @param irq Interrupt line to get status for.
- + *
- + * @param handler Input parameter for address of the handler
- + * function.
- + *
- + * @param irq_flags Flags for interrupt mode. Currently not used.
- + *
- + * @param devname Input parameter for string name of driver
- + * registering the handler.
- + *
- + * @param dev_id Input parameter for pointer of data to be
- + * passed to the handler.
- + *
- + * @return This function returns 0 on success or negative error code on
- + * fail.
- + */
- +int ipu_request_irq(struct ipu_soc *ipu, uint32_t irq,
- + irqreturn_t(*handler) (int, void *),
- + uint32_t irq_flags, const char *devname, void *dev_id)
- +{
- + uint32_t reg;
- + unsigned long lock_flags;
- + int ret = 0;
- +
- + BUG_ON(irq >= IPU_IRQ_COUNT);
- +
- + _ipu_get(ipu);
- +
- + spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
- +
- + if (ipu->irq_list[irq].handler != NULL) {
- + dev_err(ipu->dev,
- + "handler already installed on irq %d\n", irq);
- + ret = -EINVAL;
- + goto out;
- + }
- +
- + /*
- + * Check sync interrupt handler only, since we do nothing for
- + * error interrupts but than print out register values in the
- + * error interrupt source handler.
- + */
- + if (_ipu_is_sync_irq(irq) && (handler == NULL)) {
- + dev_err(ipu->dev, "handler is NULL for sync irq %d\n", irq);
- + ret = -EINVAL;
- + goto out;
- + }
- +
- + ipu->irq_list[irq].handler = handler;
- + ipu->irq_list[irq].flags = irq_flags;
- + ipu->irq_list[irq].dev_id = dev_id;
- + ipu->irq_list[irq].name = devname;
- +
- + /* clear irq stat for previous use */
- + ipu_cm_write(ipu, IPUIRQ_2_MASK(irq), IPUIRQ_2_STATREG(irq));
- + /* enable the interrupt */
- + reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
- + reg |= IPUIRQ_2_MASK(irq);
- + ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
- +out:
- + spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
- +
- + _ipu_put(ipu);
- +
- + return ret;
- +}
- +EXPORT_SYMBOL(ipu_request_irq);
- +
- +/*!
- + * This function unregisters an interrupt handler for the specified interrupt
- + * line. The interrupt lines are defined in \b ipu_irq_line enum.
- + *
- + * @param ipu ipu handler
- + * @param irq Interrupt line to get status for.
- + *
- + * @param dev_id Input parameter for pointer of data to be passed
- + * to the handler. This must match value passed to
- + * ipu_request_irq().
- + *
- + */
- +void ipu_free_irq(struct ipu_soc *ipu, uint32_t irq, void *dev_id)
- +{
- + uint32_t reg;
- + unsigned long lock_flags;
- +
- + _ipu_get(ipu);
- +
- + spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
- +
- + /* disable the interrupt */
- + reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
- + reg &= ~IPUIRQ_2_MASK(irq);
- + ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
- + if (ipu->irq_list[irq].dev_id == dev_id)
- + memset(&ipu->irq_list[irq], 0, sizeof(ipu->irq_list[irq]));
- +
- + spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
- +
- + _ipu_put(ipu);
- +}
- +EXPORT_SYMBOL(ipu_free_irq);
- +
- +uint32_t ipu_get_cur_buffer_idx(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type)
- +{
- + uint32_t reg, dma_chan;
- +
- + dma_chan = channel_2_dma(channel, type);
- + if (!idma_is_valid(dma_chan))
- + return -EINVAL;
- +
- + reg = ipu_cm_read(ipu, IPU_CHA_TRB_MODE_SEL(dma_chan));
- + if ((reg & idma_mask(dma_chan)) && _ipu_is_trb_chan(dma_chan)) {
- + reg = ipu_cm_read(ipu, IPU_CHA_TRIPLE_CUR_BUF(dma_chan));
- + return (reg & tri_cur_buf_mask(dma_chan)) >>
- + tri_cur_buf_shift(dma_chan);
- + } else {
- + reg = ipu_cm_read(ipu, IPU_CHA_CUR_BUF(dma_chan));
- + if (reg & idma_mask(dma_chan))
- + return 1;
- + else
- + return 0;
- + }
- +}
- +EXPORT_SYMBOL(ipu_get_cur_buffer_idx);
- +
- +uint32_t _ipu_channel_status(struct ipu_soc *ipu, ipu_channel_t channel)
- +{
- + uint32_t stat = 0;
- + uint32_t task_stat_reg = ipu_cm_read(ipu, IPU_PROC_TASK_STAT);
- +
- + switch (channel) {
- + case MEM_PRP_VF_MEM:
- + stat = (task_stat_reg & TSTAT_VF_MASK) >> TSTAT_VF_OFFSET;
- + break;
- + case MEM_VDI_PRP_VF_MEM:
- + stat = (task_stat_reg & TSTAT_VF_MASK) >> TSTAT_VF_OFFSET;
- + break;
- + case MEM_ROT_VF_MEM:
- + stat =
- + (task_stat_reg & TSTAT_VF_ROT_MASK) >> TSTAT_VF_ROT_OFFSET;
- + break;
- + case MEM_PRP_ENC_MEM:
- + stat = (task_stat_reg & TSTAT_ENC_MASK) >> TSTAT_ENC_OFFSET;
- + break;
- + case MEM_ROT_ENC_MEM:
- + stat =
- + (task_stat_reg & TSTAT_ENC_ROT_MASK) >>
- + TSTAT_ENC_ROT_OFFSET;
- + break;
- + case MEM_PP_MEM:
- + stat = (task_stat_reg & TSTAT_PP_MASK) >> TSTAT_PP_OFFSET;
- + break;
- + case MEM_ROT_PP_MEM:
- + stat =
- + (task_stat_reg & TSTAT_PP_ROT_MASK) >> TSTAT_PP_ROT_OFFSET;
- + break;
- +
- + default:
- + stat = TASK_STAT_IDLE;
- + break;
- + }
- + return stat;
- +}
- +
- +/*!
- + * This function check for a logical channel status
- + *
- + * @param ipu ipu handler
- + * @param channel Input parameter for the logical channel ID.
- + *
- + * @return This function returns 0 on idle and 1 on busy.
- + *
- + */
- +uint32_t ipu_channel_status(struct ipu_soc *ipu, ipu_channel_t channel)
- +{
- + uint32_t dma_status;
- +
- + _ipu_get(ipu);
- + mutex_lock(&ipu->mutex_lock);
- + dma_status = ipu_is_channel_busy(ipu, channel);
- + mutex_unlock(&ipu->mutex_lock);
- + _ipu_put(ipu);
- +
- + dev_dbg(ipu->dev, "%s, dma_status:%d.\n", __func__, dma_status);
- +
- + return dma_status;
- +}
- +EXPORT_SYMBOL(ipu_channel_status);
- +
- +int32_t ipu_swap_channel(struct ipu_soc *ipu, ipu_channel_t from_ch, ipu_channel_t to_ch)
- +{
- + uint32_t reg;
- + unsigned long lock_flags;
- + int from_dma = channel_2_dma(from_ch, IPU_INPUT_BUFFER);
- + int to_dma = channel_2_dma(to_ch, IPU_INPUT_BUFFER);
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + /* enable target channel */
- + reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(to_dma));
- + ipu_idmac_write(ipu, reg | idma_mask(to_dma), IDMAC_CHA_EN(to_dma));
- +
- + ipu->channel_enable_mask |= 1L << IPU_CHAN_ID(to_ch);
- +
- + /* switch dp dc */
- + _ipu_dp_dc_disable(ipu, from_ch, true);
- +
- + /* disable source channel */
- + reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(from_dma));
- + ipu_idmac_write(ipu, reg & ~idma_mask(from_dma), IDMAC_CHA_EN(from_dma));
- + ipu_cm_write(ipu, idma_mask(from_dma), IPU_CHA_CUR_BUF(from_dma));
- + ipu_cm_write(ipu, tri_cur_buf_mask(from_dma),
- + IPU_CHA_TRIPLE_CUR_BUF(from_dma));
- +
- + ipu->channel_enable_mask &= ~(1L << IPU_CHAN_ID(from_ch));
- +
- + spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
- + _ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 0);
- + _ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 1);
- + _ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 2);
- + spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
- +
- + mutex_unlock(&ipu->mutex_lock);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(ipu_swap_channel);
- +
- +uint32_t bytes_per_pixel(uint32_t fmt)
- +{
- + switch (fmt) {
- + case IPU_PIX_FMT_GENERIC: /*generic data */
- + case IPU_PIX_FMT_RGB332:
- + case IPU_PIX_FMT_YUV420P:
- + case IPU_PIX_FMT_YVU420P:
- + case IPU_PIX_FMT_YUV422P:
- + case IPU_PIX_FMT_YUV444P:
- + return 1;
- + break;
- + case IPU_PIX_FMT_GENERIC_16: /* generic data */
- + case IPU_PIX_FMT_RGB565:
- + case IPU_PIX_FMT_YUYV:
- + case IPU_PIX_FMT_UYVY:
- + return 2;
- + break;
- + case IPU_PIX_FMT_BGR24:
- + case IPU_PIX_FMT_RGB24:
- + case IPU_PIX_FMT_YUV444:
- + return 3;
- + break;
- + case IPU_PIX_FMT_GENERIC_32: /*generic data */
- + case IPU_PIX_FMT_BGR32:
- + case IPU_PIX_FMT_BGRA32:
- + case IPU_PIX_FMT_RGB32:
- + case IPU_PIX_FMT_RGBA32:
- + case IPU_PIX_FMT_ABGR32:
- + return 4;
- + break;
- + default:
- + return 1;
- + break;
- + }
- + return 0;
- +}
- +EXPORT_SYMBOL(bytes_per_pixel);
- +
- +ipu_color_space_t format_to_colorspace(uint32_t fmt)
- +{
- + switch (fmt) {
- + case IPU_PIX_FMT_RGB666:
- + case IPU_PIX_FMT_RGB565:
- + case IPU_PIX_FMT_BGR24:
- + case IPU_PIX_FMT_RGB24:
- + case IPU_PIX_FMT_GBR24:
- + case IPU_PIX_FMT_BGR32:
- + case IPU_PIX_FMT_BGRA32:
- + case IPU_PIX_FMT_RGB32:
- + case IPU_PIX_FMT_RGBA32:
- + case IPU_PIX_FMT_ABGR32:
- + case IPU_PIX_FMT_LVDS666:
- + case IPU_PIX_FMT_LVDS888:
- + return RGB;
- + break;
- +
- + default:
- + return YCbCr;
- + break;
- + }
- + return RGB;
- +}
- +
- +bool ipu_pixel_format_has_alpha(uint32_t fmt)
- +{
- + switch (fmt) {
- + case IPU_PIX_FMT_RGBA32:
- + case IPU_PIX_FMT_BGRA32:
- + case IPU_PIX_FMT_ABGR32:
- + return true;
- + break;
- + default:
- + return false;
- + break;
- + }
- + return false;
- +}
- +
- +bool ipu_ch_param_bad_alpha_pos(uint32_t pixel_fmt)
- +{
- + return _ipu_ch_param_bad_alpha_pos(pixel_fmt);
- +}
- +EXPORT_SYMBOL(ipu_ch_param_bad_alpha_pos);
- +
- +#ifdef CONFIG_PM
- +static int ipu_suspend(struct device *dev)
- +{
- + struct ipu_soc *ipu = dev_get_drvdata(dev);
- +
- + /* All IDMAC channel and IPU clock should be disabled.*/
- + if (ipu->pdata->pg)
- + ipu->pdata->pg(1);
- +
- + dev_dbg(dev, "ipu suspend.\n");
- + return 0;
- +}
- +
- +static int ipu_resume(struct device *dev)
- +{
- + struct ipu_soc *ipu = dev_get_drvdata(dev);
- +
- + if (ipu->pdata->pg) {
- + ipu->pdata->pg(0);
- +
- + _ipu_get(ipu);
- + _ipu_dmfc_init(ipu, dmfc_type_setup, 1);
- + /* Set sync refresh channels as high priority */
- + ipu_idmac_write(ipu, 0x18800001L, IDMAC_CHA_PRI(0));
- + _ipu_put(ipu);
- + }
- + dev_dbg(dev, "ipu resume.\n");
- + return 0;
- +}
- +
- +int ipu_runtime_suspend(struct device *dev)
- +{
- + release_bus_freq(BUS_FREQ_HIGH);
- + dev_dbg(dev, "ipu busfreq high release.\n");
- +
- + return 0;
- +}
- +
- +int ipu_runtime_resume(struct device *dev)
- +{
- + request_bus_freq(BUS_FREQ_HIGH);
- + dev_dbg(dev, "ipu busfreq high requst.\n");
- +
- + return 0;
- +}
- +
- +static const struct dev_pm_ops ipu_pm_ops = {
- + SET_RUNTIME_PM_OPS(ipu_runtime_suspend, ipu_runtime_resume, NULL)
- + SET_SYSTEM_SLEEP_PM_OPS(ipu_suspend, ipu_resume)
- +};
- +#endif
- +
- +/*!
- + * This structure contains pointers to the power management callback functions.
- + */
- +static struct platform_driver mxcipu_driver = {
- + .driver = {
- + .name = "imx-ipuv3",
- + .of_match_table = imx_ipuv3_dt_ids,
- + #ifdef CONFIG_PM
- + .pm = &ipu_pm_ops,
- + #endif
- + },
- + .probe = ipu_probe,
- + .id_table = imx_ipu_type,
- + .remove = ipu_remove,
- +};
- +
- +int32_t __init ipu_gen_init(void)
- +{
- + int32_t ret;
- +
- + ret = platform_driver_register(&mxcipu_driver);
- + return 0;
- +}
- +
- +subsys_initcall(ipu_gen_init);
- +
- +static void __exit ipu_gen_uninit(void)
- +{
- + platform_driver_unregister(&mxcipu_driver);
- +}
- +
- +module_exit(ipu_gen_uninit);
- diff -Nur linux-3.14.35.orig/drivers/mxc/ipu3/ipu_device.c linux-3.14.35/drivers/mxc/ipu3/ipu_device.c
- --- linux-3.14.35.orig/drivers/mxc/ipu3/ipu_device.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/ipu3/ipu_device.c 2015-03-08 14:27:37.661684500 -0500
- @@ -0,0 +1,3717 @@
- +/*
- + * Copyright 2005-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file ipu_device.c
- + *
- + * @brief This file contains the IPUv3 driver device interface and fops functions.
- + *
- + * @ingroup IPU
- + */
- +#include <linux/clk.h>
- +#include <linux/cpumask.h>
- +#include <linux/delay.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/err.h>
- +#include <linux/init.h>
- +#include <linux/io.h>
- +#include <linux/ipu-v3.h>
- +#include <linux/kernel.h>
- +#include <linux/kthread.h>
- +#include <linux/module.h>
- +#include <linux/platform_device.h>
- +#include <linux/poll.h>
- +#include <linux/sched.h>
- +#include <linux/sched/rt.h>
- +#include <linux/slab.h>
- +#include <linux/spinlock.h>
- +#include <linux/time.h>
- +#include <linux/types.h>
- +#include <linux/vmalloc.h>
- +#include <linux/wait.h>
- +
- +#include <asm/cacheflush.h>
- +#include <asm/outercache.h>
- +
- +#include "ipu_param_mem.h"
- +#include "ipu_regs.h"
- +#include "vdoa.h"
- +
- +#define CHECK_RETCODE(cont, str, err, label, ret) \
- +do { \
- + if (cont) { \
- + dev_err(t->dev, "ERR:[0x%p]-no:0x%x "#str" ret:%d," \
- + "line:%d\n", t, t->task_no, ret, __LINE__);\
- + if (ret != -EACCES) { \
- + t->state = err; \
- + goto label; \
- + } \
- + } \
- +} while (0)
- +
- +#define CHECK_RETCODE_CONT(cont, str, err, ret) \
- +do { \
- + if (cont) { \
- + dev_err(t->dev, "ERR:[0x%p]-no:0x%x"#str" ret:%d," \
- + "line:%d\n", t, t->task_no, ret, __LINE__);\
- + if (ret != -EACCES) { \
- + if (t->state == STATE_OK) \
- + t->state = err; \
- + } \
- + } \
- +} while (0)
- +
- +#undef DBG_IPU_PERF
- +#ifdef DBG_IPU_PERF
- +#define CHECK_PERF(ts) \
- +do { \
- + getnstimeofday(ts); \
- +} while (0)
- +
- +#define DECLARE_PERF_VAR \
- + struct timespec ts_queue; \
- + struct timespec ts_dotask; \
- + struct timespec ts_waitirq; \
- + struct timespec ts_sche; \
- + struct timespec ts_rel; \
- + struct timespec ts_frame
- +
- +#define PRINT_TASK_STATISTICS \
- +do { \
- + ts_queue = timespec_sub(tsk->ts_dotask, tsk->ts_queue); \
- + ts_dotask = timespec_sub(tsk->ts_waitirq, tsk->ts_dotask); \
- + ts_waitirq = timespec_sub(tsk->ts_inirq, tsk->ts_waitirq); \
- + ts_sche = timespec_sub(tsk->ts_wakeup, tsk->ts_inirq); \
- + ts_rel = timespec_sub(tsk->ts_rel, tsk->ts_wakeup); \
- + ts_frame = timespec_sub(tsk->ts_rel, tsk->ts_queue); \
- + dev_dbg(tsk->dev, "[0x%p] no-0x%x, ts_q:%ldus, ts_do:%ldus," \
- + "ts_waitirq:%ldus,ts_sche:%ldus, ts_rel:%ldus," \
- + "ts_frame: %ldus\n", tsk, tsk->task_no, \
- + ts_queue.tv_nsec / NSEC_PER_USEC + ts_queue.tv_sec * USEC_PER_SEC,\
- + ts_dotask.tv_nsec / NSEC_PER_USEC + ts_dotask.tv_sec * USEC_PER_SEC,\
- + ts_waitirq.tv_nsec / NSEC_PER_USEC + ts_waitirq.tv_sec * USEC_PER_SEC,\
- + ts_sche.tv_nsec / NSEC_PER_USEC + ts_sche.tv_sec * USEC_PER_SEC,\
- + ts_rel.tv_nsec / NSEC_PER_USEC + ts_rel.tv_sec * USEC_PER_SEC,\
- + ts_frame.tv_nsec / NSEC_PER_USEC + ts_frame.tv_sec * USEC_PER_SEC); \
- + if ((ts_frame.tv_nsec/NSEC_PER_USEC + ts_frame.tv_sec*USEC_PER_SEC) > \
- + 80000) \
- + dev_dbg(tsk->dev, "ts_frame larger than 80ms [0x%p] no-0x%x.\n"\
- + , tsk, tsk->task_no); \
- +} while (0)
- +#else
- +#define CHECK_PERF(ts)
- +#define DECLARE_PERF_VAR
- +#define PRINT_TASK_STATISTICS
- +#endif
- +
- +#define IPU_PP_CH_VF (IPU_TASK_ID_VF - 1)
- +#define IPU_PP_CH_PP (IPU_TASK_ID_PP - 1)
- +#define MAX_PP_CH (IPU_TASK_ID_MAX - 1)
- +#define VDOA_DEF_TIMEOUT_MS (HZ/2)
- +
- +/* Strucutures and variables for exporting MXC IPU as device*/
- +typedef enum {
- + STATE_OK = 0,
- + STATE_QUEUE,
- + STATE_IN_PROGRESS,
- + STATE_ERR,
- + STATE_TIMEOUT,
- + STATE_RES_TIMEOUT,
- + STATE_NO_IPU,
- + STATE_NO_IRQ,
- + STATE_IPU_BUSY,
- + STATE_IRQ_FAIL,
- + STATE_IRQ_TIMEOUT,
- + STATE_ENABLE_CHAN_FAIL,
- + STATE_DISABLE_CHAN_FAIL,
- + STATE_SEL_BUF_FAIL,
- + STATE_INIT_CHAN_FAIL,
- + STATE_LINK_CHAN_FAIL,
- + STATE_UNLINK_CHAN_FAIL,
- + STATE_INIT_CHAN_BUF_FAIL,
- + STATE_INIT_CHAN_BAND_FAIL,
- + STATE_SYS_NO_MEM,
- + STATE_VDOA_IRQ_TIMEOUT,
- + STATE_VDOA_IRQ_FAIL,
- + STATE_VDOA_TASK_FAIL,
- +} ipu_state_t;
- +
- +enum {
- + INPUT_CHAN_VDI_P = 1,
- + INPUT_CHAN,
- + INPUT_CHAN_VDI_N,
- +};
- +
- +struct ipu_state_msg {
- + int state;
- + char *msg;
- +} state_msg[] = {
- + {STATE_OK, "ok"},
- + {STATE_QUEUE, "split queue"},
- + {STATE_IN_PROGRESS, "split in progress"},
- + {STATE_ERR, "error"},
- + {STATE_TIMEOUT, "split task timeout"},
- + {STATE_RES_TIMEOUT, "wait resource timeout"},
- + {STATE_NO_IPU, "no ipu found"},
- + {STATE_NO_IRQ, "no irq found for task"},
- + {STATE_IPU_BUSY, "ipu busy"},
- + {STATE_IRQ_FAIL, "request irq failed"},
- + {STATE_IRQ_TIMEOUT, "wait for irq timeout"},
- + {STATE_ENABLE_CHAN_FAIL, "ipu enable channel fail"},
- + {STATE_DISABLE_CHAN_FAIL, "ipu disable channel fail"},
- + {STATE_SEL_BUF_FAIL, "ipu select buf fail"},
- + {STATE_INIT_CHAN_FAIL, "ipu init channel fail"},
- + {STATE_LINK_CHAN_FAIL, "ipu link channel fail"},
- + {STATE_UNLINK_CHAN_FAIL, "ipu unlink channel fail"},
- + {STATE_INIT_CHAN_BUF_FAIL, "ipu init channel buffer fail"},
- + {STATE_INIT_CHAN_BAND_FAIL, "ipu init channel band mode fail"},
- + {STATE_SYS_NO_MEM, "sys no mem: -ENOMEM"},
- + {STATE_VDOA_IRQ_TIMEOUT, "wait for vdoa irq timeout"},
- + {STATE_VDOA_IRQ_FAIL, "vdoa irq fail"},
- + {STATE_VDOA_TASK_FAIL, "vdoa task fail"},
- +};
- +
- +struct stripe_setting {
- + u32 iw;
- + u32 ih;
- + u32 ow;
- + u32 oh;
- + u32 outh_resize_ratio;
- + u32 outv_resize_ratio;
- + u32 i_left_pos;
- + u32 i_right_pos;
- + u32 i_top_pos;
- + u32 i_bottom_pos;
- + u32 o_left_pos;
- + u32 o_right_pos;
- + u32 o_top_pos;
- + u32 o_bottom_pos;
- + u32 rl_split_line;
- + u32 ud_split_line;
- +};
- +
- +struct task_set {
- +#define NULL_MODE 0x0
- +#define IC_MODE 0x1
- +#define ROT_MODE 0x2
- +#define VDI_MODE 0x4
- +#define IPU_PREPROCESS_MODE_MASK (IC_MODE | ROT_MODE | VDI_MODE)
- +/* VDOA_MODE means this task use vdoa, and VDOA has two modes:
- + * BAND MODE and non-BAND MODE. Non-band mode will do transfer data
- + * to memory. BAND mode needs hareware sync with IPU, it is used default
- + * if connected to VDIC.
- + */
- +#define VDOA_MODE 0x8
- +#define VDOA_BAND_MODE 0x10
- + u8 mode;
- +#define IC_VF 0x1
- +#define IC_PP 0x2
- +#define ROT_VF 0x4
- +#define ROT_PP 0x8
- +#define VDI_VF 0x10
- +#define VDOA_ONLY 0x20
- + u8 task;
- +#define NO_SPLIT 0x0
- +#define RL_SPLIT 0x1
- +#define UD_SPLIT 0x2
- +#define LEFT_STRIPE 0x1
- +#define RIGHT_STRIPE 0x2
- +#define UP_STRIPE 0x4
- +#define DOWN_STRIPE 0x8
- +#define SPLIT_MASK 0xF
- + u8 split_mode;
- + u8 band_lines;
- + ipu_channel_t ic_chan;
- + ipu_channel_t rot_chan;
- + ipu_channel_t vdi_ic_p_chan;
- + ipu_channel_t vdi_ic_n_chan;
- +
- + u32 i_off;
- + u32 i_uoff;
- + u32 i_voff;
- + u32 istride;
- +
- + u32 ov_off;
- + u32 ov_uoff;
- + u32 ov_voff;
- + u32 ovstride;
- +
- + u32 ov_alpha_off;
- + u32 ov_alpha_stride;
- +
- + u32 o_off;
- + u32 o_uoff;
- + u32 o_voff;
- + u32 ostride;
- +
- + u32 r_fmt;
- + u32 r_width;
- + u32 r_height;
- + u32 r_stride;
- + dma_addr_t r_paddr;
- +
- + struct stripe_setting sp_setting;
- +};
- +
- +struct ipu_split_task {
- + struct ipu_task task;
- + struct ipu_task_entry *parent_task;
- + struct ipu_task_entry *child_task;
- + u32 task_no;
- +};
- +
- +struct ipu_task_entry {
- + struct ipu_input input;
- + struct ipu_output output;
- +
- + bool overlay_en;
- + struct ipu_overlay overlay;
- +#define DEF_TIMEOUT_MS 1000
- +#define DEF_DELAY_MS 20
- + int timeout;
- + int irq;
- +
- + u8 task_id;
- + u8 ipu_id;
- + u8 task_in_list;
- + u8 split_done;
- + struct mutex split_lock;
- + struct mutex vdic_lock;
- + wait_queue_head_t split_waitq;
- +
- + struct list_head node;
- + struct list_head split_list;
- + struct ipu_soc *ipu;
- + struct device *dev;
- + struct task_set set;
- + wait_queue_head_t task_waitq;
- + struct completion irq_comp;
- + struct kref refcount;
- + ipu_state_t state;
- + u32 task_no;
- + atomic_t done;
- + atomic_t res_free;
- + atomic_t res_get;
- +
- + struct ipu_task_entry *parent;
- + char *vditmpbuf[2];
- + u32 old_save_lines;
- + u32 old_size;
- + bool buf1filled;
- + bool buf0filled;
- +
- + vdoa_handle_t vdoa_handle;
- + struct vdoa_output_mem {
- + void *vaddr;
- + dma_addr_t paddr;
- + int size;
- + } vdoa_dma;
- +
- +#ifdef DBG_IPU_PERF
- + struct timespec ts_queue;
- + struct timespec ts_dotask;
- + struct timespec ts_waitirq;
- + struct timespec ts_inirq;
- + struct timespec ts_wakeup;
- + struct timespec ts_rel;
- +#endif
- +};
- +
- +struct ipu_channel_tabel {
- + struct mutex lock;
- + u8 used[MXC_IPU_MAX_NUM][MAX_PP_CH];
- + u8 vdoa_used;
- +};
- +
- +struct ipu_thread_data {
- + struct ipu_soc *ipu;
- + u32 id;
- + u32 is_vdoa;
- +};
- +
- +struct ipu_alloc_list {
- + struct list_head list;
- + dma_addr_t phy_addr;
- + void *cpu_addr;
- + u32 size;
- + void *file_index;
- +};
- +
- +static LIST_HEAD(ipu_alloc_list);
- +static DEFINE_MUTEX(ipu_alloc_lock);
- +static struct ipu_channel_tabel ipu_ch_tbl;
- +static LIST_HEAD(ipu_task_list);
- +static DEFINE_SPINLOCK(ipu_task_list_lock);
- +static DECLARE_WAIT_QUEUE_HEAD(thread_waitq);
- +static DECLARE_WAIT_QUEUE_HEAD(res_waitq);
- +static atomic_t req_cnt;
- +static atomic_t file_index = ATOMIC_INIT(1);
- +static int major;
- +static int max_ipu_no;
- +static int thread_id;
- +static atomic_t frame_no;
- +static struct class *ipu_class;
- +static struct device *ipu_dev;
- +static int debug;
- +module_param(debug, int, 0600);
- +#ifdef DBG_IPU_PERF
- +static struct timespec ts_frame_max;
- +static u32 ts_frame_avg;
- +static atomic_t frame_cnt;
- +#endif
- +
- +static bool deinterlace_3_field(struct ipu_task_entry *t)
- +{
- + return ((t->set.mode & VDI_MODE) &&
- + (t->input.deinterlace.motion != HIGH_MOTION));
- +}
- +
- +static u32 tiled_filed_size(struct ipu_task_entry *t)
- +{
- + u32 field_size;
- +
- + /* note: page_align is required by VPU hw ouput buffer */
- + field_size = TILED_NV12_FRAME_SIZE(t->input.width, t->input.height/2);
- + return field_size;
- +}
- +
- +static bool only_ic(u8 mode)
- +{
- + mode = mode & IPU_PREPROCESS_MODE_MASK;
- + return ((mode == IC_MODE) || (mode == VDI_MODE));
- +}
- +
- +static bool only_rot(u8 mode)
- +{
- + mode = mode & IPU_PREPROCESS_MODE_MASK;
- + return (mode == ROT_MODE);
- +}
- +
- +static bool ic_and_rot(u8 mode)
- +{
- + mode = mode & IPU_PREPROCESS_MODE_MASK;
- + return ((mode == (IC_MODE | ROT_MODE)) ||
- + (mode == (VDI_MODE | ROT_MODE)));
- +}
- +
- +static bool need_split(struct ipu_task_entry *t)
- +{
- + return ((t->set.split_mode != NO_SPLIT) || (t->task_no & SPLIT_MASK));
- +}
- +
- +unsigned int fmt_to_bpp(unsigned int pixelformat)
- +{
- + u32 bpp;
- +
- + switch (pixelformat) {
- + case IPU_PIX_FMT_RGB565:
- + /*interleaved 422*/
- + case IPU_PIX_FMT_YUYV:
- + case IPU_PIX_FMT_UYVY:
- + /*non-interleaved 422*/
- + case IPU_PIX_FMT_YUV422P:
- + case IPU_PIX_FMT_YVU422P:
- + bpp = 16;
- + break;
- + case IPU_PIX_FMT_BGR24:
- + case IPU_PIX_FMT_RGB24:
- + case IPU_PIX_FMT_YUV444:
- + case IPU_PIX_FMT_YUV444P:
- + bpp = 24;
- + break;
- + case IPU_PIX_FMT_BGR32:
- + case IPU_PIX_FMT_BGRA32:
- + case IPU_PIX_FMT_RGB32:
- + case IPU_PIX_FMT_RGBA32:
- + case IPU_PIX_FMT_ABGR32:
- + bpp = 32;
- + break;
- + /*non-interleaved 420*/
- + case IPU_PIX_FMT_YUV420P:
- + case IPU_PIX_FMT_YVU420P:
- + case IPU_PIX_FMT_YUV420P2:
- + case IPU_PIX_FMT_NV12:
- + bpp = 12;
- + break;
- + default:
- + bpp = 8;
- + break;
- + }
- + return bpp;
- +}
- +EXPORT_SYMBOL_GPL(fmt_to_bpp);
- +
- +cs_t colorspaceofpixel(int fmt)
- +{
- + switch (fmt) {
- + case IPU_PIX_FMT_RGB565:
- + case IPU_PIX_FMT_BGR24:
- + case IPU_PIX_FMT_RGB24:
- + case IPU_PIX_FMT_BGRA32:
- + case IPU_PIX_FMT_BGR32:
- + case IPU_PIX_FMT_RGBA32:
- + case IPU_PIX_FMT_RGB32:
- + case IPU_PIX_FMT_ABGR32:
- + return RGB_CS;
- + break;
- + case IPU_PIX_FMT_UYVY:
- + case IPU_PIX_FMT_YUYV:
- + case IPU_PIX_FMT_YUV420P2:
- + case IPU_PIX_FMT_YUV420P:
- + case IPU_PIX_FMT_YVU420P:
- + case IPU_PIX_FMT_YVU422P:
- + case IPU_PIX_FMT_YUV422P:
- + case IPU_PIX_FMT_YUV444:
- + case IPU_PIX_FMT_YUV444P:
- + case IPU_PIX_FMT_NV12:
- + case IPU_PIX_FMT_TILED_NV12:
- + case IPU_PIX_FMT_TILED_NV12F:
- + return YUV_CS;
- + break;
- + default:
- + return NULL_CS;
- + }
- +}
- +EXPORT_SYMBOL_GPL(colorspaceofpixel);
- +
- +int need_csc(int ifmt, int ofmt)
- +{
- + cs_t ics, ocs;
- +
- + ics = colorspaceofpixel(ifmt);
- + ocs = colorspaceofpixel(ofmt);
- +
- + if ((ics == NULL_CS) || (ocs == NULL_CS))
- + return -1;
- + else if (ics != ocs)
- + return 1;
- +
- + return 0;
- +}
- +EXPORT_SYMBOL_GPL(need_csc);
- +
- +static int soc_max_in_width(u32 is_vdoa)
- +{
- + return is_vdoa ? 8192 : 4096;
- +}
- +
- +static int soc_max_vdi_in_width(void)
- +{
- + return IPU_MAX_VDI_IN_WIDTH;
- +}
- +static int soc_max_in_height(void)
- +{
- + return 4096;
- +}
- +
- +static int soc_max_out_width(void)
- +{
- + /* mx51/mx53/mx6q is 1024*/
- + return 1024;
- +}
- +
- +static int soc_max_out_height(void)
- +{
- + /* mx51/mx53/mx6q is 1024*/
- + return 1024;
- +}
- +
- +static void dump_task_info(struct ipu_task_entry *t)
- +{
- + if (!debug)
- + return;
- + dev_dbg(t->dev, "[0x%p]input:\n", (void *)t);
- + dev_dbg(t->dev, "[0x%p]\tformat = 0x%x\n", (void *)t, t->input.format);
- + dev_dbg(t->dev, "[0x%p]\twidth = %d\n", (void *)t, t->input.width);
- + dev_dbg(t->dev, "[0x%p]\theight = %d\n", (void *)t, t->input.height);
- + dev_dbg(t->dev, "[0x%p]\tcrop.w = %d\n", (void *)t, t->input.crop.w);
- + dev_dbg(t->dev, "[0x%p]\tcrop.h = %d\n", (void *)t, t->input.crop.h);
- + dev_dbg(t->dev, "[0x%p]\tcrop.pos.x = %d\n",
- + (void *)t, t->input.crop.pos.x);
- + dev_dbg(t->dev, "[0x%p]\tcrop.pos.y = %d\n",
- + (void *)t, t->input.crop.pos.y);
- + dev_dbg(t->dev, "[0x%p]input buffer:\n", (void *)t);
- + dev_dbg(t->dev, "[0x%p]\tpaddr = 0x%x\n", (void *)t, t->input.paddr);
- + dev_dbg(t->dev, "[0x%p]\ti_off = 0x%x\n", (void *)t, t->set.i_off);
- + dev_dbg(t->dev, "[0x%p]\ti_uoff = 0x%x\n", (void *)t, t->set.i_uoff);
- + dev_dbg(t->dev, "[0x%p]\ti_voff = 0x%x\n", (void *)t, t->set.i_voff);
- + dev_dbg(t->dev, "[0x%p]\tistride = %d\n", (void *)t, t->set.istride);
- + if (t->input.deinterlace.enable) {
- + dev_dbg(t->dev, "[0x%p]deinterlace enabled with:\n", (void *)t);
- + if (t->input.deinterlace.motion != HIGH_MOTION) {
- + dev_dbg(t->dev, "[0x%p]\tlow/medium motion\n", (void *)t);
- + dev_dbg(t->dev, "[0x%p]\tpaddr_n = 0x%x\n",
- + (void *)t, t->input.paddr_n);
- + } else
- + dev_dbg(t->dev, "[0x%p]\thigh motion\n", (void *)t);
- + }
- +
- + dev_dbg(t->dev, "[0x%p]output:\n", (void *)t);
- + dev_dbg(t->dev, "[0x%p]\tformat = 0x%x\n", (void *)t, t->output.format);
- + dev_dbg(t->dev, "[0x%p]\twidth = %d\n", (void *)t, t->output.width);
- + dev_dbg(t->dev, "[0x%p]\theight = %d\n", (void *)t, t->output.height);
- + dev_dbg(t->dev, "[0x%p]\tcrop.w = %d\n", (void *)t, t->output.crop.w);
- + dev_dbg(t->dev, "[0x%p]\tcrop.h = %d\n", (void *)t, t->output.crop.h);
- + dev_dbg(t->dev, "[0x%p]\tcrop.pos.x = %d\n",
- + (void *)t, t->output.crop.pos.x);
- + dev_dbg(t->dev, "[0x%p]\tcrop.pos.y = %d\n",
- + (void *)t, t->output.crop.pos.y);
- + dev_dbg(t->dev, "[0x%p]\trotate = %d\n", (void *)t, t->output.rotate);
- + dev_dbg(t->dev, "[0x%p]output buffer:\n", (void *)t);
- + dev_dbg(t->dev, "[0x%p]\tpaddr = 0x%x\n", (void *)t, t->output.paddr);
- + dev_dbg(t->dev, "[0x%p]\to_off = 0x%x\n", (void *)t, t->set.o_off);
- + dev_dbg(t->dev, "[0x%p]\to_uoff = 0x%x\n", (void *)t, t->set.o_uoff);
- + dev_dbg(t->dev, "[0x%p]\to_voff = 0x%x\n", (void *)t, t->set.o_voff);
- + dev_dbg(t->dev, "[0x%p]\tostride = %d\n", (void *)t, t->set.ostride);
- +
- + if (t->overlay_en) {
- + dev_dbg(t->dev, "[0x%p]overlay:\n", (void *)t);
- + dev_dbg(t->dev, "[0x%p]\tformat = 0x%x\n",
- + (void *)t, t->overlay.format);
- + dev_dbg(t->dev, "[0x%p]\twidth = %d\n",
- + (void *)t, t->overlay.width);
- + dev_dbg(t->dev, "[0x%p]\theight = %d\n",
- + (void *)t, t->overlay.height);
- + dev_dbg(t->dev, "[0x%p]\tcrop.w = %d\n",
- + (void *)t, t->overlay.crop.w);
- + dev_dbg(t->dev, "[0x%p]\tcrop.h = %d\n",
- + (void *)t, t->overlay.crop.h);
- + dev_dbg(t->dev, "[0x%p]\tcrop.pos.x = %d\n",
- + (void *)t, t->overlay.crop.pos.x);
- + dev_dbg(t->dev, "[0x%p]\tcrop.pos.y = %d\n",
- + (void *)t, t->overlay.crop.pos.y);
- + dev_dbg(t->dev, "[0x%p]overlay buffer:\n", (void *)t);
- + dev_dbg(t->dev, "[0x%p]\tpaddr = 0x%x\n",
- + (void *)t, t->overlay.paddr);
- + dev_dbg(t->dev, "[0x%p]\tov_off = 0x%x\n",
- + (void *)t, t->set.ov_off);
- + dev_dbg(t->dev, "[0x%p]\tov_uoff = 0x%x\n",
- + (void *)t, t->set.ov_uoff);
- + dev_dbg(t->dev, "[0x%p]\tov_voff = 0x%x\n",
- + (void *)t, t->set.ov_voff);
- + dev_dbg(t->dev, "[0x%p]\tovstride = %d\n",
- + (void *)t, t->set.ovstride);
- + if (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL) {
- + dev_dbg(t->dev, "[0x%p]local alpha enabled with:\n",
- + (void *)t);
- + dev_dbg(t->dev, "[0x%p]\tpaddr = 0x%x\n",
- + (void *)t, t->overlay.alpha.loc_alp_paddr);
- + dev_dbg(t->dev, "[0x%p]\tov_alpha_off = 0x%x\n",
- + (void *)t, t->set.ov_alpha_off);
- + dev_dbg(t->dev, "[0x%p]\tov_alpha_stride = %d\n",
- + (void *)t, t->set.ov_alpha_stride);
- + } else
- + dev_dbg(t->dev, "[0x%p]globle alpha enabled with value 0x%x\n",
- + (void *)t, t->overlay.alpha.gvalue);
- + if (t->overlay.colorkey.enable)
- + dev_dbg(t->dev, "[0x%p]colorkey enabled with value 0x%x\n",
- + (void *)t, t->overlay.colorkey.value);
- + }
- +
- + dev_dbg(t->dev, "[0x%p]want task_id = %d\n", (void *)t, t->task_id);
- + dev_dbg(t->dev, "[0x%p]want task mode is 0x%x\n",
- + (void *)t, t->set.mode);
- + dev_dbg(t->dev, "[0x%p]\tIC_MODE = 0x%x\n", (void *)t, IC_MODE);
- + dev_dbg(t->dev, "[0x%p]\tROT_MODE = 0x%x\n", (void *)t, ROT_MODE);
- + dev_dbg(t->dev, "[0x%p]\tVDI_MODE = 0x%x\n", (void *)t, VDI_MODE);
- + dev_dbg(t->dev, "[0x%p]\tTask_no = 0x%x\n\n\n", (void *)t, t->task_no);
- +}
- +
- +static void dump_check_err(struct device *dev, int err)
- +{
- + switch (err) {
- + case IPU_CHECK_ERR_INPUT_CROP:
- + dev_err(dev, "input crop setting error\n");
- + break;
- + case IPU_CHECK_ERR_OUTPUT_CROP:
- + dev_err(dev, "output crop setting error\n");
- + break;
- + case IPU_CHECK_ERR_OVERLAY_CROP:
- + dev_err(dev, "overlay crop setting error\n");
- + break;
- + case IPU_CHECK_ERR_INPUT_OVER_LIMIT:
- + dev_err(dev, "input over limitation\n");
- + break;
- + case IPU_CHECK_ERR_OVERLAY_WITH_VDI:
- + dev_err(dev, "do not support overlay with deinterlace\n");
- + break;
- + case IPU_CHECK_ERR_OV_OUT_NO_FIT:
- + dev_err(dev,
- + "width/height of overlay and ic output should be same\n");
- + break;
- + case IPU_CHECK_ERR_PROC_NO_NEED:
- + dev_err(dev, "no ipu processing need\n");
- + break;
- + case IPU_CHECK_ERR_SPLIT_INPUTW_OVER:
- + dev_err(dev, "split mode input width overflow\n");
- + break;
- + case IPU_CHECK_ERR_SPLIT_INPUTH_OVER:
- + dev_err(dev, "split mode input height overflow\n");
- + break;
- + case IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER:
- + dev_err(dev, "split mode output width overflow\n");
- + break;
- + case IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER:
- + dev_err(dev, "split mode output height overflow\n");
- + break;
- + case IPU_CHECK_ERR_SPLIT_WITH_ROT:
- + dev_err(dev, "not support split mode with rotation\n");
- + break;
- + case IPU_CHECK_ERR_W_DOWNSIZE_OVER:
- + dev_err(dev, "horizontal downsizing ratio overflow\n");
- + break;
- + case IPU_CHECK_ERR_H_DOWNSIZE_OVER:
- + dev_err(dev, "vertical downsizing ratio overflow\n");
- + break;
- + default:
- + break;
- + }
- +}
- +
- +static void dump_check_warn(struct device *dev, int warn)
- +{
- + if (warn & IPU_CHECK_WARN_INPUT_OFFS_NOT8ALIGN)
- + dev_warn(dev, "input u/v offset not 8 align\n");
- + if (warn & IPU_CHECK_WARN_OUTPUT_OFFS_NOT8ALIGN)
- + dev_warn(dev, "output u/v offset not 8 align\n");
- + if (warn & IPU_CHECK_WARN_OVERLAY_OFFS_NOT8ALIGN)
- + dev_warn(dev, "overlay u/v offset not 8 align\n");
- +}
- +
- +static int set_crop(struct ipu_crop *crop, int width, int height, int fmt)
- +{
- + if ((width == 0) || (height == 0)) {
- + pr_err("Invalid param: width=%d, height=%d\n", width, height);
- + return -EINVAL;
- + }
- +
- + if ((IPU_PIX_FMT_TILED_NV12 == fmt) ||
- + (IPU_PIX_FMT_TILED_NV12F == fmt)) {
- + if (crop->w || crop->h) {
- + if (((crop->w + crop->pos.x) > width)
- + || ((crop->h + crop->pos.y) > height)
- + || (0 != (crop->w % IPU_PIX_FMT_TILED_NV12_MBALIGN))
- + || (0 != (crop->h % IPU_PIX_FMT_TILED_NV12_MBALIGN))
- + || (0 != (crop->pos.x % IPU_PIX_FMT_TILED_NV12_MBALIGN))
- + || (0 != (crop->pos.y % IPU_PIX_FMT_TILED_NV12_MBALIGN))
- + ) {
- + pr_err("set_crop error MB align.\n");
- + return -EINVAL;
- + }
- + } else {
- + crop->pos.x = 0;
- + crop->pos.y = 0;
- + crop->w = width;
- + crop->h = height;
- + if ((0 != (crop->w % IPU_PIX_FMT_TILED_NV12_MBALIGN))
- + || (0 != (crop->h % IPU_PIX_FMT_TILED_NV12_MBALIGN))) {
- + pr_err("set_crop error w/h MB align.\n");
- + return -EINVAL;
- + }
- + }
- + } else {
- + if (crop->w || crop->h) {
- + if (((crop->w + crop->pos.x) > (width + 16))
- + || ((crop->h + crop->pos.y) > height + 16)) {
- + pr_err("set_crop error exceeds width/height.\n");
- + return -EINVAL;
- + }
- + } else {
- + crop->pos.x = 0;
- + crop->pos.y = 0;
- + crop->w = width;
- + crop->h = height;
- + }
- + crop->w -= crop->w%8;
- + crop->h -= crop->h%8;
- + }
- +
- + if ((crop->w == 0) || (crop->h == 0)) {
- + pr_err("Invalid crop param: crop.w=%d, crop.h=%d\n",
- + crop->w, crop->h);
- + return -EINVAL;
- + }
- +
- + return 0;
- +}
- +
- +static void update_offset(unsigned int fmt,
- + unsigned int width, unsigned int height,
- + unsigned int pos_x, unsigned int pos_y,
- + int *off, int *uoff, int *voff, int *stride)
- +{
- + /* NOTE: u v offset should based on start point of off*/
- + switch (fmt) {
- + case IPU_PIX_FMT_YUV420P2:
- + case IPU_PIX_FMT_YUV420P:
- + *off = pos_y * width + pos_x;
- + *uoff = (width * (height - pos_y) - pos_x)
- + + (width/2) * (pos_y/2) + pos_x/2;
- + /* In case height is odd, round up to even */
- + *voff = *uoff + (width/2) * ((height+1)/2);
- + break;
- + case IPU_PIX_FMT_YVU420P:
- + *off = pos_y * width + pos_x;
- + *voff = (width * (height - pos_y) - pos_x)
- + + (width/2) * (pos_y/2) + pos_x/2;
- + /* In case height is odd, round up to even */
- + *uoff = *voff + (width/2) * ((height+1)/2);
- + break;
- + case IPU_PIX_FMT_YVU422P:
- + *off = pos_y * width + pos_x;
- + *voff = (width * (height - pos_y) - pos_x)
- + + (width/2) * pos_y + pos_x/2;
- + *uoff = *voff + (width/2) * height;
- + break;
- + case IPU_PIX_FMT_YUV422P:
- + *off = pos_y * width + pos_x;
- + *uoff = (width * (height - pos_y) - pos_x)
- + + (width/2) * pos_y + pos_x/2;
- + *voff = *uoff + (width/2) * height;
- + break;
- + case IPU_PIX_FMT_YUV444P:
- + *off = pos_y * width + pos_x;
- + *uoff = width * height;
- + *voff = width * height * 2;
- + break;
- + case IPU_PIX_FMT_NV12:
- + *off = pos_y * width + pos_x;
- + *uoff = (width * (height - pos_y) - pos_x)
- + + width * (pos_y/2) + pos_x;
- + break;
- + case IPU_PIX_FMT_TILED_NV12:
- + /*
- + * tiled format, progressive:
- + * assuming that line is aligned with MB height (aligned to 16)
- + * offset = line * stride + (pixel / MB_width) * pixels_in_MB
- + * = line * stride + (pixel / 16) * 256
- + * = line * stride + pixel * 16
- + */
- + *off = pos_y * width + (pos_x << 4);
- + *uoff = ALIGN(width * height, SZ_4K) + (*off >> 1) - *off;
- + break;
- + case IPU_PIX_FMT_TILED_NV12F:
- + /*
- + * tiled format, interlaced:
- + * same as above, only number of pixels in MB is 128,
- + * instead of 256
- + */
- + *off = (pos_y >> 1) * width + (pos_x << 3);
- + *uoff = ALIGN(width * height/2, SZ_4K) + (*off >> 1) - *off;
- + break;
- + default:
- + *off = (pos_y * width + pos_x) * fmt_to_bpp(fmt)/8;
- + break;
- + }
- + *stride = width * bytes_per_pixel(fmt);
- +}
- +
- +static int update_split_setting(struct ipu_task_entry *t, bool vdi_split)
- +{
- + struct stripe_param left_stripe;
- + struct stripe_param right_stripe;
- + struct stripe_param up_stripe;
- + struct stripe_param down_stripe;
- + u32 iw, ih, ow, oh;
- + u32 max_width;
- + int ret;
- +
- + if (t->output.rotate >= IPU_ROTATE_90_RIGHT)
- + return IPU_CHECK_ERR_SPLIT_WITH_ROT;
- +
- + iw = t->input.crop.w;
- + ih = t->input.crop.h;
- +
- + ow = t->output.crop.w;
- + oh = t->output.crop.h;
- +
- + memset(&left_stripe, 0, sizeof(left_stripe));
- + memset(&right_stripe, 0, sizeof(right_stripe));
- + memset(&up_stripe, 0, sizeof(up_stripe));
- + memset(&down_stripe, 0, sizeof(down_stripe));
- +
- + if (t->set.split_mode & RL_SPLIT) {
- + /*
- + * We do want equal strips: initialize stripes in case
- + * calc_stripes returns before actually doing the calculation
- + */
- + left_stripe.input_width = iw / 2;
- + left_stripe.output_width = ow / 2;
- + right_stripe.input_column = iw / 2;
- + right_stripe.output_column = ow / 2;
- +
- + if (vdi_split)
- + max_width = soc_max_vdi_in_width();
- + else
- + max_width = soc_max_out_width();
- + ret = ipu_calc_stripes_sizes(iw,
- + ow,
- + max_width,
- + (((unsigned long long)1) << 32), /* 32bit for fractional*/
- + 1, /* equal stripes */
- + t->input.format,
- + t->output.format,
- + &left_stripe,
- + &right_stripe);
- + if (ret < 0)
- + return IPU_CHECK_ERR_W_DOWNSIZE_OVER;
- + else if (ret)
- + dev_dbg(t->dev, "Warn: no:0x%x,calc_stripes ret:%d\n",
- + t->task_no, ret);
- + t->set.sp_setting.iw = left_stripe.input_width;
- + t->set.sp_setting.ow = left_stripe.output_width;
- + t->set.sp_setting.outh_resize_ratio = left_stripe.irr;
- + t->set.sp_setting.i_left_pos = left_stripe.input_column;
- + t->set.sp_setting.o_left_pos = left_stripe.output_column;
- + t->set.sp_setting.i_right_pos = right_stripe.input_column;
- + t->set.sp_setting.o_right_pos = right_stripe.output_column;
- + } else {
- + t->set.sp_setting.iw = iw;
- + t->set.sp_setting.ow = ow;
- + t->set.sp_setting.outh_resize_ratio = 0;
- + t->set.sp_setting.i_left_pos = 0;
- + t->set.sp_setting.o_left_pos = 0;
- + t->set.sp_setting.i_right_pos = 0;
- + t->set.sp_setting.o_right_pos = 0;
- + }
- + if ((t->set.sp_setting.iw + t->set.sp_setting.i_right_pos) > (iw+16))
- + return IPU_CHECK_ERR_SPLIT_INPUTW_OVER;
- + if (((t->set.sp_setting.ow + t->set.sp_setting.o_right_pos) > ow)
- + || (t->set.sp_setting.ow > soc_max_out_width()))
- + return IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER;
- + if (rounddown(t->set.sp_setting.ow, 8) * 8 <=
- + rounddown(t->set.sp_setting.iw, 8))
- + return IPU_CHECK_ERR_W_DOWNSIZE_OVER;
- +
- + if (t->set.split_mode & UD_SPLIT) {
- + /*
- + * We do want equal strips: initialize stripes in case
- + * calc_stripes returns before actually doing the calculation
- + */
- + up_stripe.input_width = ih / 2;
- + up_stripe.output_width = oh / 2;
- + down_stripe.input_column = ih / 2;
- + down_stripe.output_column = oh / 2;
- + ret = ipu_calc_stripes_sizes(ih,
- + oh,
- + soc_max_out_height(),
- + (((unsigned long long)1) << 32), /* 32bit for fractional*/
- + 0x1 | 0x2, /* equal stripes and vertical */
- + t->input.format,
- + t->output.format,
- + &up_stripe,
- + &down_stripe);
- + if (ret < 0)
- + return IPU_CHECK_ERR_H_DOWNSIZE_OVER;
- + else if (ret)
- + dev_err(t->dev, "Warn: no:0x%x,calc_stripes ret:%d\n",
- + t->task_no, ret);
- + t->set.sp_setting.ih = up_stripe.input_width;
- + t->set.sp_setting.oh = up_stripe.output_width;
- + t->set.sp_setting.outv_resize_ratio = up_stripe.irr;
- + t->set.sp_setting.i_top_pos = up_stripe.input_column;
- + t->set.sp_setting.o_top_pos = up_stripe.output_column;
- + t->set.sp_setting.i_bottom_pos = down_stripe.input_column;
- + t->set.sp_setting.o_bottom_pos = down_stripe.output_column;
- + } else {
- + t->set.sp_setting.ih = ih;
- + t->set.sp_setting.oh = oh;
- + t->set.sp_setting.outv_resize_ratio = 0;
- + t->set.sp_setting.i_top_pos = 0;
- + t->set.sp_setting.o_top_pos = 0;
- + t->set.sp_setting.i_bottom_pos = 0;
- + t->set.sp_setting.o_bottom_pos = 0;
- + }
- +
- + /* downscale case: enforce limits */
- + if (((t->set.sp_setting.ih + t->set.sp_setting.i_bottom_pos) > (ih))
- + && (t->set.sp_setting.ih >= t->set.sp_setting.oh))
- + return IPU_CHECK_ERR_SPLIT_INPUTH_OVER;
- + /* upscale case: relax limits because ipu_calc_stripes_sizes() may
- + create input stripe that falls just outside of the input window */
- + else if ((t->set.sp_setting.ih + t->set.sp_setting.i_bottom_pos)
- + > (ih+16))
- + return IPU_CHECK_ERR_SPLIT_INPUTH_OVER;
- + if (((t->set.sp_setting.oh + t->set.sp_setting.o_bottom_pos) > oh)
- + || (t->set.sp_setting.oh > soc_max_out_height()))
- + return IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER;
- + if (rounddown(t->set.sp_setting.oh, 8) * 8 <=
- + rounddown(t->set.sp_setting.ih, 8))
- + return IPU_CHECK_ERR_H_DOWNSIZE_OVER;
- +
- + return IPU_CHECK_OK;
- +}
- +
- +static int check_task(struct ipu_task_entry *t)
- +{
- + int tmp;
- + int ret = IPU_CHECK_OK;
- + int timeout;
- + bool vdi_split = false;
- + int ocw, och;
- +
- + if ((IPU_PIX_FMT_TILED_NV12 == t->overlay.format) ||
- + (IPU_PIX_FMT_TILED_NV12F == t->overlay.format) ||
- + (IPU_PIX_FMT_TILED_NV12 == t->output.format) ||
- + (IPU_PIX_FMT_TILED_NV12F == t->output.format) ||
- + ((IPU_PIX_FMT_TILED_NV12F == t->input.format) &&
- + !t->input.deinterlace.enable)) {
- + ret = IPU_CHECK_ERR_NOT_SUPPORT;
- + goto done;
- + }
- +
- + /* check input */
- + ret = set_crop(&t->input.crop, t->input.width, t->input.height,
- + t->input.format);
- + if (ret < 0) {
- + ret = IPU_CHECK_ERR_INPUT_CROP;
- + goto done;
- + } else
- + update_offset(t->input.format, t->input.width, t->input.height,
- + t->input.crop.pos.x, t->input.crop.pos.y,
- + &t->set.i_off, &t->set.i_uoff,
- + &t->set.i_voff, &t->set.istride);
- +
- + /* check output */
- + ret = set_crop(&t->output.crop, t->output.width, t->output.height,
- + t->output.format);
- + if (ret < 0) {
- + ret = IPU_CHECK_ERR_OUTPUT_CROP;
- + goto done;
- + } else
- + update_offset(t->output.format,
- + t->output.width, t->output.height,
- + t->output.crop.pos.x, t->output.crop.pos.y,
- + &t->set.o_off, &t->set.o_uoff,
- + &t->set.o_voff, &t->set.ostride);
- +
- + if (t->output.rotate >= IPU_ROTATE_90_RIGHT) {
- + /*
- + * Cache output width and height and
- + * swap them so that we may check
- + * downsize overflow correctly.
- + */
- + ocw = t->output.crop.h;
- + och = t->output.crop.w;
- + } else {
- + ocw = t->output.crop.w;
- + och = t->output.crop.h;
- + }
- +
- + if (ocw * 8 <= t->input.crop.w) {
- + ret = IPU_CHECK_ERR_W_DOWNSIZE_OVER;
- + goto done;
- + }
- +
- + if (och * 8 <= t->input.crop.h) {
- + ret = IPU_CHECK_ERR_H_DOWNSIZE_OVER;
- + goto done;
- + }
- +
- + if ((IPU_PIX_FMT_TILED_NV12 == t->input.format) ||
- + (IPU_PIX_FMT_TILED_NV12F == t->input.format)) {
- + if ((t->input.crop.w > soc_max_in_width(1)) ||
- + (t->input.crop.h > soc_max_in_height())) {
- + ret = IPU_CHECK_ERR_INPUT_OVER_LIMIT;
- + goto done;
- + }
- + /* output fmt: NV12 and YUYV, now don't support resize */
- + if (((IPU_PIX_FMT_NV12 != t->output.format) &&
- + (IPU_PIX_FMT_YUYV != t->output.format)) ||
- + (t->input.crop.w != t->output.crop.w) ||
- + (t->input.crop.h != t->output.crop.h)) {
- + ret = IPU_CHECK_ERR_NOT_SUPPORT;
- + goto done;
- + }
- + }
- +
- + /* check overlay if there is */
- + if (t->overlay_en) {
- + if (t->input.deinterlace.enable) {
- + ret = IPU_CHECK_ERR_OVERLAY_WITH_VDI;
- + goto done;
- + }
- +
- + ret = set_crop(&t->overlay.crop, t->overlay.width,
- + t->overlay.height, t->overlay.format);
- + if (ret < 0) {
- + ret = IPU_CHECK_ERR_OVERLAY_CROP;
- + goto done;
- + } else {
- + ocw = t->output.crop.w;
- + och = t->output.crop.h;
- +
- + if (t->output.rotate >= IPU_ROTATE_90_RIGHT) {
- + ocw = t->output.crop.h;
- + och = t->output.crop.w;
- + }
- + if ((t->overlay.crop.w != ocw) ||
- + (t->overlay.crop.h != och)) {
- + ret = IPU_CHECK_ERR_OV_OUT_NO_FIT;
- + goto done;
- + }
- +
- + update_offset(t->overlay.format,
- + t->overlay.width, t->overlay.height,
- + t->overlay.crop.pos.x, t->overlay.crop.pos.y,
- + &t->set.ov_off, &t->set.ov_uoff,
- + &t->set.ov_voff, &t->set.ovstride);
- + if (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL) {
- + t->set.ov_alpha_stride = t->overlay.width;
- + t->set.ov_alpha_off = t->overlay.crop.pos.y *
- + t->overlay.width + t->overlay.crop.pos.x;
- + }
- + }
- + }
- +
- + /* input overflow? */
- + if (!((IPU_PIX_FMT_TILED_NV12 == t->input.format) ||
- + (IPU_PIX_FMT_TILED_NV12F == t->input.format))) {
- + if ((t->input.crop.w > soc_max_in_width(0)) ||
- + (t->input.crop.h > soc_max_in_height())) {
- + ret = IPU_CHECK_ERR_INPUT_OVER_LIMIT;
- + goto done;
- + }
- + }
- +
- + /* check task mode */
- + t->set.mode = NULL_MODE;
- + t->set.split_mode = NO_SPLIT;
- +
- + if (t->output.rotate >= IPU_ROTATE_90_RIGHT) {
- + /*output swap*/
- + tmp = t->output.crop.w;
- + t->output.crop.w = t->output.crop.h;
- + t->output.crop.h = tmp;
- + }
- +
- + if (t->output.rotate >= IPU_ROTATE_90_RIGHT)
- + t->set.mode |= ROT_MODE;
- +
- + /*need resize or CSC?*/
- + if ((t->input.crop.w != t->output.crop.w) ||
- + (t->input.crop.h != t->output.crop.h) ||
- + need_csc(t->input.format, t->output.format))
- + t->set.mode |= IC_MODE;
- +
- + /*need flip?*/
- + if ((t->set.mode == NULL_MODE) && (t->output.rotate > IPU_ROTATE_NONE))
- + t->set.mode |= IC_MODE;
- +
- + /*need IDMAC do format(same color space)?*/
- + if ((t->set.mode == NULL_MODE) && (t->input.format != t->output.format))
- + t->set.mode |= IC_MODE;
- +
- + /*overlay support*/
- + if (t->overlay_en)
- + t->set.mode |= IC_MODE;
- +
- + /*deinterlace*/
- + if (t->input.deinterlace.enable) {
- + t->set.mode &= ~IC_MODE;
- + t->set.mode |= VDI_MODE;
- + }
- + if ((IPU_PIX_FMT_TILED_NV12 == t->input.format) ||
- + (IPU_PIX_FMT_TILED_NV12F == t->input.format)) {
- + if (t->set.mode & ROT_MODE) {
- + ret = IPU_CHECK_ERR_NOT_SUPPORT;
- + goto done;
- + }
- + t->set.mode |= VDOA_MODE;
- + if (IPU_PIX_FMT_TILED_NV12F == t->input.format)
- + t->set.mode |= VDOA_BAND_MODE;
- + t->set.mode &= ~IC_MODE;
- + }
- +
- + if ((t->set.mode & (IC_MODE | VDI_MODE)) &&
- + (IPU_PIX_FMT_TILED_NV12F != t->input.format)) {
- + if (t->output.crop.w > soc_max_out_width())
- + t->set.split_mode |= RL_SPLIT;
- + if (t->output.crop.h > soc_max_out_height())
- + t->set.split_mode |= UD_SPLIT;
- + if (!t->set.split_mode && (t->set.mode & VDI_MODE) &&
- + (t->input.crop.w > soc_max_vdi_in_width())) {
- + t->set.split_mode |= RL_SPLIT;
- + vdi_split = true;
- + }
- + if (t->set.split_mode) {
- + if ((t->set.split_mode == RL_SPLIT) ||
- + (t->set.split_mode == UD_SPLIT))
- + timeout = DEF_TIMEOUT_MS * 2 + DEF_DELAY_MS;
- + else
- + timeout = DEF_TIMEOUT_MS * 4 + DEF_DELAY_MS;
- + if (t->timeout < timeout)
- + t->timeout = timeout;
- +
- + ret = update_split_setting(t, vdi_split);
- + if (ret > IPU_CHECK_ERR_MIN)
- + goto done;
- + }
- + }
- +
- + if (t->output.rotate >= IPU_ROTATE_90_RIGHT) {
- + /*output swap*/
- + tmp = t->output.crop.w;
- + t->output.crop.w = t->output.crop.h;
- + t->output.crop.h = tmp;
- + }
- +
- + if (t->set.mode == NULL_MODE) {
- + ret = IPU_CHECK_ERR_PROC_NO_NEED;
- + goto done;
- + }
- +
- + if ((t->set.i_uoff % 8) || (t->set.i_voff % 8))
- + ret |= IPU_CHECK_WARN_INPUT_OFFS_NOT8ALIGN;
- + if ((t->set.o_uoff % 8) || (t->set.o_voff % 8))
- + ret |= IPU_CHECK_WARN_OUTPUT_OFFS_NOT8ALIGN;
- + if (t->overlay_en && ((t->set.ov_uoff % 8) || (t->set.ov_voff % 8)))
- + ret |= IPU_CHECK_WARN_OVERLAY_OFFS_NOT8ALIGN;
- +
- +done:
- + /* dump msg */
- + if (debug) {
- + if (ret > IPU_CHECK_ERR_MIN)
- + dump_check_err(t->dev, ret);
- + else if (ret != IPU_CHECK_OK)
- + dump_check_warn(t->dev, ret);
- + }
- +
- + return ret;
- +}
- +
- +static int prepare_task(struct ipu_task_entry *t)
- +{
- + int ret = 0;
- +
- + ret = check_task(t);
- + if (ret > IPU_CHECK_ERR_MIN)
- + return -EINVAL;
- +
- + if (t->set.mode & VDI_MODE) {
- + t->task_id = IPU_TASK_ID_VF;
- + t->set.task = VDI_VF;
- + if (t->set.mode & ROT_MODE)
- + t->set.task |= ROT_VF;
- + }
- +
- + if (VDOA_MODE == t->set.mode) {
- + if (t->set.task != 0) {
- + dev_err(t->dev, "ERR: vdoa only task:0x%x, [0x%p].\n",
- + t->set.task, t);
- + return -EINVAL;
- + }
- + t->set.task |= VDOA_ONLY;
- + }
- +
- + if (VDOA_BAND_MODE & t->set.mode) {
- + /* to save band size: 1<<3 = 8 lines */
- + t->set.band_lines = 3;
- + }
- +
- + dump_task_info(t);
- +
- + return ret;
- +}
- +
- +static uint32_t ic_vf_pp_is_busy(struct ipu_soc *ipu, bool is_vf)
- +{
- + uint32_t status;
- + uint32_t status_vf;
- + uint32_t status_rot;
- +
- + if (is_vf) {
- + status = ipu_channel_status(ipu, MEM_VDI_PRP_VF_MEM);
- + status_vf = ipu_channel_status(ipu, MEM_PRP_VF_MEM);
- + status_rot = ipu_channel_status(ipu, MEM_ROT_VF_MEM);
- + return status || status_vf || status_rot;
- + } else {
- + status = ipu_channel_status(ipu, MEM_PP_MEM);
- + status_rot = ipu_channel_status(ipu, MEM_ROT_PP_MEM);
- + return status || status_rot;
- + }
- +}
- +
- +static int _get_vdoa_ipu_res(struct ipu_task_entry *t)
- +{
- + int i;
- + struct ipu_soc *ipu;
- + u8 *used;
- + uint32_t found_ipu = 0;
- + uint32_t found_vdoa = 0;
- + struct ipu_channel_tabel *tbl = &ipu_ch_tbl;
- +
- + mutex_lock(&tbl->lock);
- + if (t->set.mode & VDOA_MODE) {
- + if (NULL != t->vdoa_handle)
- + found_vdoa = 1;
- + else {
- + found_vdoa = tbl->vdoa_used ? 0 : 1;
- + if (found_vdoa) {
- + tbl->vdoa_used = 1;
- + vdoa_get_handle(&t->vdoa_handle);
- + } else
- + /* first get vdoa->ipu resource sequence */
- + goto out;
- + if (t->set.task & VDOA_ONLY)
- + goto out;
- + }
- + }
- +
- + for (i = 0; i < max_ipu_no; i++) {
- + ipu = ipu_get_soc(i);
- + if (IS_ERR(ipu))
- + dev_err(t->dev, "no:0x%x,found_vdoa:%d, ipu:%d\n",
- + t->task_no, found_vdoa, i);
- +
- + used = &tbl->used[i][IPU_PP_CH_VF];
- + if (t->set.mode & VDI_MODE) {
- + if (0 == *used) {
- + *used = 1;
- + found_ipu = 1;
- + break;
- + }
- + } else if ((t->set.mode & IC_MODE) || only_rot(t->set.mode)) {
- + if (0 == *used) {
- + t->task_id = IPU_TASK_ID_VF;
- + if (t->set.mode & IC_MODE)
- + t->set.task |= IC_VF;
- + if (t->set.mode & ROT_MODE)
- + t->set.task |= ROT_VF;
- + *used = 1;
- + found_ipu = 1;
- + break;
- + }
- + } else
- + dev_err(t->dev, "no:0x%x,found_vdoa:%d, mode:0x%x\n",
- + t->task_no, found_vdoa, t->set.mode);
- + }
- + if (found_ipu)
- + goto next;
- +
- + for (i = 0; i < max_ipu_no; i++) {
- + ipu = ipu_get_soc(i);
- + if (IS_ERR(ipu))
- + dev_err(t->dev, "no:0x%x,found_vdoa:%d, ipu:%d\n",
- + t->task_no, found_vdoa, i);
- +
- + if ((t->set.mode & IC_MODE) || only_rot(t->set.mode)) {
- + used = &tbl->used[i][IPU_PP_CH_PP];
- + if (0 == *used) {
- + t->task_id = IPU_TASK_ID_PP;
- + if (t->set.mode & IC_MODE)
- + t->set.task |= IC_PP;
- + if (t->set.mode & ROT_MODE)
- + t->set.task |= ROT_PP;
- + *used = 1;
- + found_ipu = 1;
- + break;
- + }
- + }
- + }
- +
- +next:
- + if (found_ipu) {
- + t->ipu = ipu;
- + t->ipu_id = i;
- + t->dev = ipu->dev;
- + if (atomic_inc_return(&t->res_get) == 2)
- + dev_err(t->dev,
- + "ERR no:0x%x,found_vdoa:%d,get ipu twice\n",
- + t->task_no, found_vdoa);
- + }
- +out:
- + dev_dbg(t->dev,
- + "%s:no:0x%x,found_vdoa:%d, found_ipu:%d\n",
- + __func__, t->task_no, found_vdoa, found_ipu);
- + mutex_unlock(&tbl->lock);
- + if (t->set.task & VDOA_ONLY)
- + return found_vdoa;
- + else if (t->set.mode & VDOA_MODE)
- + return found_vdoa && found_ipu;
- + else
- + return found_ipu;
- +}
- +
- +static void put_vdoa_ipu_res(struct ipu_task_entry *tsk, int vdoa_only)
- +{
- + int ret;
- + int rel_vdoa = 0, rel_ipu = 0;
- + struct ipu_channel_tabel *tbl = &ipu_ch_tbl;
- +
- + mutex_lock(&tbl->lock);
- + if (tsk->set.mode & VDOA_MODE) {
- + if (!tbl->vdoa_used && tsk->vdoa_handle)
- + dev_err(tsk->dev,
- + "ERR no:0x%x,vdoa not used,mode:0x%x\n",
- + tsk->task_no, tsk->set.mode);
- + if (tbl->vdoa_used && tsk->vdoa_handle) {
- + tbl->vdoa_used = 0;
- + vdoa_put_handle(&tsk->vdoa_handle);
- + if (tsk->ipu)
- + tsk->ipu->vdoa_en = 0;
- + rel_vdoa = 1;
- + if (vdoa_only || (tsk->set.task & VDOA_ONLY))
- + goto out;
- + }
- + }
- +
- + tbl->used[tsk->ipu_id][tsk->task_id - 1] = 0;
- + rel_ipu = 1;
- + ret = atomic_inc_return(&tsk->res_free);
- + if (ret == 2)
- + dev_err(tsk->dev,
- + "ERR no:0x%x,rel_vdoa:%d,put ipu twice\n",
- + tsk->task_no, rel_vdoa);
- +out:
- + dev_dbg(tsk->dev,
- + "%s:no:0x%x,rel_vdoa:%d, rel_ipu:%d\n",
- + __func__, tsk->task_no, rel_vdoa, rel_ipu);
- + mutex_unlock(&tbl->lock);
- +}
- +
- +static int get_vdoa_ipu_res(struct ipu_task_entry *t)
- +{
- + int ret;
- + uint32_t found = 0;
- +
- + found = _get_vdoa_ipu_res(t);
- + if (!found) {
- + t->ipu_id = -1;
- + t->ipu = NULL;
- + /* blocking to get resource */
- + ret = atomic_inc_return(&req_cnt);
- + dev_dbg(t->dev,
- + "wait_res:no:0x%x,req_cnt:%d\n", t->task_no, ret);
- + ret = wait_event_timeout(res_waitq, _get_vdoa_ipu_res(t),
- + msecs_to_jiffies(t->timeout - DEF_DELAY_MS));
- + if (ret == 0) {
- + dev_err(t->dev, "ERR[0x%p,no-0x%x] wait_res timeout:%dms!\n",
- + t, t->task_no, t->timeout - DEF_DELAY_MS);
- + ret = -ETIMEDOUT;
- + t->state = STATE_RES_TIMEOUT;
- + goto out;
- + } else {
- + if (!(t->set.task & VDOA_ONLY) && (!t->ipu))
- + dev_err(t->dev,
- + "ERR[no-0x%x] can not get ipu!\n",
- + t->task_no);
- + ret = atomic_read(&req_cnt);
- + if (ret > 0)
- + ret = atomic_dec_return(&req_cnt);
- + else
- + dev_err(t->dev,
- + "ERR[no-0x%x] req_cnt:%d mismatch!\n",
- + t->task_no, ret);
- + dev_dbg(t->dev, "no-0x%x,[0x%p],req_cnt:%d, got_res!\n",
- + t->task_no, t, ret);
- + found = 1;
- + }
- + }
- +
- +out:
- + return found;
- +}
- +
- +static struct ipu_task_entry *create_task_entry(struct ipu_task *task)
- +{
- + struct ipu_task_entry *tsk;
- +
- + tsk = kzalloc(sizeof(struct ipu_task_entry), GFP_KERNEL);
- + if (!tsk)
- + return ERR_PTR(-ENOMEM);
- + kref_init(&tsk->refcount);
- + tsk->state = -EINVAL;
- + tsk->ipu_id = -1;
- + tsk->dev = ipu_dev;
- + tsk->input = task->input;
- + tsk->output = task->output;
- + tsk->overlay_en = task->overlay_en;
- + if (tsk->overlay_en)
- + tsk->overlay = task->overlay;
- + if (task->timeout > DEF_TIMEOUT_MS)
- + tsk->timeout = task->timeout;
- + else
- + tsk->timeout = DEF_TIMEOUT_MS;
- +
- + return tsk;
- +}
- +
- +static void task_mem_free(struct kref *ref)
- +{
- + struct ipu_task_entry *tsk =
- + container_of(ref, struct ipu_task_entry, refcount);
- + kfree(tsk);
- +}
- +
- +int create_split_child_task(struct ipu_split_task *sp_task)
- +{
- + int ret = 0;
- + struct ipu_task_entry *tsk;
- +
- + tsk = create_task_entry(&sp_task->task);
- + if (IS_ERR(tsk))
- + return PTR_ERR(tsk);
- +
- + sp_task->child_task = tsk;
- + tsk->task_no = sp_task->task_no;
- +
- + ret = prepare_task(tsk);
- + if (ret < 0)
- + goto err;
- +
- + tsk->parent = sp_task->parent_task;
- + tsk->set.sp_setting = sp_task->parent_task->set.sp_setting;
- +
- + list_add(&tsk->node, &tsk->parent->split_list);
- + dev_dbg(tsk->dev, "[0x%p] sp_tsk Q list,no-0x%x\n", tsk, tsk->task_no);
- + tsk->state = STATE_QUEUE;
- + CHECK_PERF(&tsk->ts_queue);
- +err:
- + return ret;
- +}
- +
- +static inline int sp_task_check_done(struct ipu_split_task *sp_task,
- + struct ipu_task_entry *parent, int num, int *idx)
- +{
- + int i;
- + int ret = 0;
- + struct ipu_task_entry *tsk;
- + struct mutex *lock = &parent->split_lock;
- +
- + *idx = -EINVAL;
- + mutex_lock(lock);
- + for (i = 0; i < num; i++) {
- + tsk = sp_task[i].child_task;
- + if (tsk && tsk->split_done) {
- + *idx = i;
- + ret = 1;
- + goto out;
- + }
- + }
- +
- +out:
- + mutex_unlock(lock);
- + return ret;
- +}
- +
- +static int create_split_task(
- + int stripe,
- + struct ipu_split_task *sp_task)
- +{
- + struct ipu_task *task = &(sp_task->task);
- + struct ipu_task_entry *t = sp_task->parent_task;
- + int ret;
- +
- + sp_task->task_no |= stripe;
- +
- + task->input = t->input;
- + task->output = t->output;
- + task->overlay_en = t->overlay_en;
- + if (task->overlay_en)
- + task->overlay = t->overlay;
- + task->task_id = t->task_id;
- + if ((t->set.split_mode == RL_SPLIT) ||
- + (t->set.split_mode == UD_SPLIT))
- + task->timeout = t->timeout / 2;
- + else
- + task->timeout = t->timeout / 4;
- +
- + task->input.crop.w = t->set.sp_setting.iw;
- + task->input.crop.h = t->set.sp_setting.ih;
- + if (task->overlay_en) {
- + task->overlay.crop.w = t->set.sp_setting.ow;
- + task->overlay.crop.h = t->set.sp_setting.oh;
- + }
- + if (t->output.rotate >= IPU_ROTATE_90_RIGHT) {
- + task->output.crop.w = t->set.sp_setting.oh;
- + task->output.crop.h = t->set.sp_setting.ow;
- + t->set.sp_setting.rl_split_line = t->set.sp_setting.o_bottom_pos;
- + t->set.sp_setting.ud_split_line = t->set.sp_setting.o_right_pos;
- +
- + } else {
- + task->output.crop.w = t->set.sp_setting.ow;
- + task->output.crop.h = t->set.sp_setting.oh;
- + t->set.sp_setting.rl_split_line = t->set.sp_setting.o_right_pos;
- + t->set.sp_setting.ud_split_line = t->set.sp_setting.o_bottom_pos;
- + }
- +
- + if (stripe & LEFT_STRIPE)
- + task->input.crop.pos.x += t->set.sp_setting.i_left_pos;
- + else if (stripe & RIGHT_STRIPE)
- + task->input.crop.pos.x += t->set.sp_setting.i_right_pos;
- + if (stripe & UP_STRIPE)
- + task->input.crop.pos.y += t->set.sp_setting.i_top_pos;
- + else if (stripe & DOWN_STRIPE)
- + task->input.crop.pos.y += t->set.sp_setting.i_bottom_pos;
- +
- + if (task->overlay_en) {
- + if (stripe & LEFT_STRIPE)
- + task->overlay.crop.pos.x += t->set.sp_setting.o_left_pos;
- + else if (stripe & RIGHT_STRIPE)
- + task->overlay.crop.pos.x += t->set.sp_setting.o_right_pos;
- + if (stripe & UP_STRIPE)
- + task->overlay.crop.pos.y += t->set.sp_setting.o_top_pos;
- + else if (stripe & DOWN_STRIPE)
- + task->overlay.crop.pos.y += t->set.sp_setting.o_bottom_pos;
- + }
- +
- + switch (t->output.rotate) {
- + case IPU_ROTATE_NONE:
- + if (stripe & LEFT_STRIPE)
- + task->output.crop.pos.x += t->set.sp_setting.o_left_pos;
- + else if (stripe & RIGHT_STRIPE)
- + task->output.crop.pos.x += t->set.sp_setting.o_right_pos;
- + if (stripe & UP_STRIPE)
- + task->output.crop.pos.y += t->set.sp_setting.o_top_pos;
- + else if (stripe & DOWN_STRIPE)
- + task->output.crop.pos.y += t->set.sp_setting.o_bottom_pos;
- + break;
- + case IPU_ROTATE_VERT_FLIP:
- + if (stripe & LEFT_STRIPE)
- + task->output.crop.pos.x += t->set.sp_setting.o_left_pos;
- + else if (stripe & RIGHT_STRIPE)
- + task->output.crop.pos.x += t->set.sp_setting.o_right_pos;
- + if (stripe & UP_STRIPE)
- + task->output.crop.pos.y =
- + t->output.crop.pos.y + t->output.crop.h
- + - t->set.sp_setting.o_top_pos - t->set.sp_setting.oh;
- + else if (stripe & DOWN_STRIPE)
- + task->output.crop.pos.y =
- + t->output.crop.pos.y + t->output.crop.h
- + - t->set.sp_setting.o_bottom_pos - t->set.sp_setting.oh;
- + break;
- + case IPU_ROTATE_HORIZ_FLIP:
- + if (stripe & LEFT_STRIPE)
- + task->output.crop.pos.x =
- + t->output.crop.pos.x + t->output.crop.w
- + - t->set.sp_setting.o_left_pos - t->set.sp_setting.ow;
- + else if (stripe & RIGHT_STRIPE)
- + task->output.crop.pos.x =
- + t->output.crop.pos.x + t->output.crop.w
- + - t->set.sp_setting.o_right_pos - t->set.sp_setting.ow;
- + if (stripe & UP_STRIPE)
- + task->output.crop.pos.y += t->set.sp_setting.o_top_pos;
- + else if (stripe & DOWN_STRIPE)
- + task->output.crop.pos.y += t->set.sp_setting.o_bottom_pos;
- + break;
- + case IPU_ROTATE_180:
- + if (stripe & LEFT_STRIPE)
- + task->output.crop.pos.x =
- + t->output.crop.pos.x + t->output.crop.w
- + - t->set.sp_setting.o_left_pos - t->set.sp_setting.ow;
- + else if (stripe & RIGHT_STRIPE)
- + task->output.crop.pos.x =
- + t->output.crop.pos.x + t->output.crop.w
- + - t->set.sp_setting.o_right_pos - t->set.sp_setting.ow;
- + if (stripe & UP_STRIPE)
- + task->output.crop.pos.y =
- + t->output.crop.pos.y + t->output.crop.h
- + - t->set.sp_setting.o_top_pos - t->set.sp_setting.oh;
- + else if (stripe & DOWN_STRIPE)
- + task->output.crop.pos.y =
- + t->output.crop.pos.y + t->output.crop.h
- + - t->set.sp_setting.o_bottom_pos - t->set.sp_setting.oh;
- + break;
- + case IPU_ROTATE_90_RIGHT:
- + if (stripe & UP_STRIPE)
- + task->output.crop.pos.x =
- + t->output.crop.pos.x + t->output.crop.w
- + - t->set.sp_setting.o_top_pos - t->set.sp_setting.oh;
- + else if (stripe & DOWN_STRIPE)
- + task->output.crop.pos.x =
- + t->output.crop.pos.x + t->output.crop.w
- + - t->set.sp_setting.o_bottom_pos - t->set.sp_setting.oh;
- + if (stripe & LEFT_STRIPE)
- + task->output.crop.pos.y += t->set.sp_setting.o_left_pos;
- + else if (stripe & RIGHT_STRIPE)
- + task->output.crop.pos.y += t->set.sp_setting.o_right_pos;
- + break;
- + case IPU_ROTATE_90_RIGHT_HFLIP:
- + if (stripe & UP_STRIPE)
- + task->output.crop.pos.x += t->set.sp_setting.o_top_pos;
- + else if (stripe & DOWN_STRIPE)
- + task->output.crop.pos.x += t->set.sp_setting.o_bottom_pos;
- + if (stripe & LEFT_STRIPE)
- + task->output.crop.pos.y += t->set.sp_setting.o_left_pos;
- + else if (stripe & RIGHT_STRIPE)
- + task->output.crop.pos.y += t->set.sp_setting.o_right_pos;
- + break;
- + case IPU_ROTATE_90_RIGHT_VFLIP:
- + if (stripe & UP_STRIPE)
- + task->output.crop.pos.x =
- + t->output.crop.pos.x + t->output.crop.w
- + - t->set.sp_setting.o_top_pos - t->set.sp_setting.oh;
- + else if (stripe & DOWN_STRIPE)
- + task->output.crop.pos.x =
- + t->output.crop.pos.x + t->output.crop.w
- + - t->set.sp_setting.o_bottom_pos - t->set.sp_setting.oh;
- + if (stripe & LEFT_STRIPE)
- + task->output.crop.pos.y =
- + t->output.crop.pos.y + t->output.crop.h
- + - t->set.sp_setting.o_left_pos - t->set.sp_setting.ow;
- + else if (stripe & RIGHT_STRIPE)
- + task->output.crop.pos.y =
- + t->output.crop.pos.y + t->output.crop.h
- + - t->set.sp_setting.o_right_pos - t->set.sp_setting.ow;
- + break;
- + case IPU_ROTATE_90_LEFT:
- + if (stripe & UP_STRIPE)
- + task->output.crop.pos.x += t->set.sp_setting.o_top_pos;
- + else if (stripe & DOWN_STRIPE)
- + task->output.crop.pos.x += t->set.sp_setting.o_bottom_pos;
- + if (stripe & LEFT_STRIPE)
- + task->output.crop.pos.y =
- + t->output.crop.pos.y + t->output.crop.h
- + - t->set.sp_setting.o_left_pos - t->set.sp_setting.ow;
- + else if (stripe & RIGHT_STRIPE)
- + task->output.crop.pos.y =
- + t->output.crop.pos.y + t->output.crop.h
- + - t->set.sp_setting.o_right_pos - t->set.sp_setting.ow;
- + break;
- + default:
- + dev_err(t->dev, "ERR:should not be here\n");
- + break;
- + }
- +
- + ret = create_split_child_task(sp_task);
- + if (ret < 0)
- + dev_err(t->dev, "ERR:create_split_child_task() ret:%d\n", ret);
- + return ret;
- +}
- +
- +static int queue_split_task(struct ipu_task_entry *t,
- + struct ipu_split_task *sp_task, uint32_t size)
- +{
- + int err[4];
- + int ret = 0;
- + int i, j;
- + struct ipu_task_entry *tsk = NULL;
- + struct mutex *lock = &t->split_lock;
- + struct mutex *vdic_lock = &t->vdic_lock;
- +
- + dev_dbg(t->dev, "Split task 0x%p, no-0x%x, size:%d\n",
- + t, t->task_no, size);
- + mutex_init(lock);
- + mutex_init(vdic_lock);
- + init_waitqueue_head(&t->split_waitq);
- + INIT_LIST_HEAD(&t->split_list);
- + for (j = 0; j < size; j++) {
- + memset(&sp_task[j], 0, sizeof(*sp_task));
- + sp_task[j].parent_task = t;
- + sp_task[j].task_no = t->task_no;
- + }
- +
- + if (t->set.split_mode == RL_SPLIT) {
- + i = 0;
- + err[i] = create_split_task(RIGHT_STRIPE, &sp_task[i]);
- + if (err[i] < 0)
- + goto err_start;
- + i = 1;
- + err[i] = create_split_task(LEFT_STRIPE, &sp_task[i]);
- + } else if (t->set.split_mode == UD_SPLIT) {
- + i = 0;
- + err[i] = create_split_task(DOWN_STRIPE, &sp_task[i]);
- + if (err[i] < 0)
- + goto err_start;
- + i = 1;
- + err[i] = create_split_task(UP_STRIPE, &sp_task[i]);
- + } else {
- + i = 0;
- + err[i] = create_split_task(RIGHT_STRIPE | DOWN_STRIPE, &sp_task[i]);
- + if (err[i] < 0)
- + goto err_start;
- + i = 1;
- + err[i] = create_split_task(LEFT_STRIPE | DOWN_STRIPE, &sp_task[i]);
- + if (err[i] < 0)
- + goto err_start;
- + i = 2;
- + err[i] = create_split_task(RIGHT_STRIPE | UP_STRIPE, &sp_task[i]);
- + if (err[i] < 0)
- + goto err_start;
- + i = 3;
- + err[i] = create_split_task(LEFT_STRIPE | UP_STRIPE, &sp_task[i]);
- + }
- +
- +err_start:
- + for (j = 0; j < (i + 1); j++) {
- + if (err[j] < 0) {
- + if (sp_task[j].child_task)
- + dev_err(t->dev,
- + "sp_task[%d],no-0x%x fail state:%d, queue err:%d.\n",
- + j, sp_task[j].child_task->task_no,
- + sp_task[j].child_task->state, err[j]);
- + goto err_exit;
- + }
- + dev_dbg(t->dev, "[0x%p] sp_task[%d], no-0x%x state:%s, queue ret:%d.\n",
- + sp_task[j].child_task, j, sp_task[j].child_task->task_no,
- + state_msg[sp_task[j].child_task->state].msg, err[j]);
- + }
- +
- + return ret;
- +
- +err_exit:
- + for (j = 0; j < (i + 1); j++) {
- + if (err[j] < 0 && !ret)
- + ret = err[j];
- + tsk = sp_task[j].child_task;
- + if (!tsk)
- + continue;
- + kfree(tsk);
- + }
- + t->state = STATE_ERR;
- + return ret;
- +
- +}
- +
- +static int init_tiled_buf(struct ipu_soc *ipu, struct ipu_task_entry *t,
- + ipu_channel_t channel, uint32_t ch_type)
- +{
- + int ret = 0;
- + int i;
- + uint32_t ipu_fmt;
- + dma_addr_t inbuf_base = 0;
- + u32 field_size;
- + struct vdoa_params param;
- + struct vdoa_ipu_buf buf;
- + struct ipu_soc *ipu_idx;
- + u32 ipu_stride, obuf_size;
- + u32 height, width;
- + ipu_buffer_t type;
- +
- + if ((IPU_PIX_FMT_YUYV != t->output.format) &&
- + (IPU_PIX_FMT_NV12 != t->output.format)) {
- + dev_err(t->dev, "ERR:[0x%d] output format\n", t->task_no);
- + return -EINVAL;
- + }
- +
- + memset(¶m, 0, sizeof(param));
- + /* init channel tiled bufs */
- + if (deinterlace_3_field(t) &&
- + (IPU_PIX_FMT_TILED_NV12F == t->input.format)) {
- + field_size = tiled_filed_size(t);
- + if (INPUT_CHAN_VDI_P == ch_type) {
- + inbuf_base = t->input.paddr + field_size;
- + param.vfield_buf.prev_veba = inbuf_base + t->set.i_off;
- + } else if (INPUT_CHAN == ch_type) {
- + inbuf_base = t->input.paddr_n;
- + param.vfield_buf.cur_veba = inbuf_base + t->set.i_off;
- + } else if (INPUT_CHAN_VDI_N == ch_type) {
- + inbuf_base = t->input.paddr_n + field_size;
- + param.vfield_buf.next_veba = inbuf_base + t->set.i_off;
- + } else
- + return -EINVAL;
- + height = t->input.crop.h >> 1; /* field format for vdoa */
- + width = t->input.crop.w;
- + param.vfield_buf.vubo = t->set.i_uoff;
- + param.interlaced = 1;
- + param.scan_order = 1;
- + type = IPU_INPUT_BUFFER;
- + } else if ((IPU_PIX_FMT_TILED_NV12 == t->input.format) &&
- + (INPUT_CHAN == ch_type)) {
- + height = t->input.crop.h;
- + width = t->input.crop.w;
- + param.vframe_buf.veba = t->input.paddr + t->set.i_off;
- + param.vframe_buf.vubo = t->set.i_uoff;
- + type = IPU_INPUT_BUFFER;
- + } else
- + return -EINVAL;
- +
- + param.band_mode = (t->set.mode & VDOA_BAND_MODE) ? 1 : 0;
- + if (param.band_mode && (t->set.band_lines != 3) &&
- + (t->set.band_lines != 4) && (t->set.band_lines != 5))
- + return -EINVAL;
- + else if (param.band_mode)
- + param.band_lines = (1 << t->set.band_lines);
- + for (i = 0; i < max_ipu_no; i++) {
- + ipu_idx = ipu_get_soc(i);
- + if (!IS_ERR(ipu_idx) && ipu_idx == ipu)
- + break;
- + }
- + if (t->set.task & VDOA_ONLY)
- + /* dummy, didn't need ipu res */
- + i = 0;
- + if (max_ipu_no == i) {
- + dev_err(t->dev, "ERR:[0x%p] get ipu num\n", t);
- + return -EINVAL;
- + }
- +
- + param.ipu_num = i;
- + param.vpu_stride = t->input.width;
- + param.height = height;
- + param.width = width;
- + if (IPU_PIX_FMT_NV12 == t->output.format)
- + param.pfs = VDOA_PFS_NV12;
- + else
- + param.pfs = VDOA_PFS_YUYV;
- + ipu_fmt = (param.pfs == VDOA_PFS_YUYV) ? IPU_PIX_FMT_YUYV :
- + IPU_PIX_FMT_NV12;
- + ipu_stride = param.width * bytes_per_pixel(ipu_fmt);
- + obuf_size = PAGE_ALIGN(param.width * param.height *
- + fmt_to_bpp(ipu_fmt)/8);
- + dev_dbg(t->dev, "band_mode:%d, band_lines:%d\n",
- + param.band_mode, param.band_lines);
- + if (!param.band_mode) {
- + /* note: if only for tiled -> raster convert and
- + no other post-processing, we don't need alloc buf
- + and use output buffer directly.
- + */
- + if (t->set.task & VDOA_ONLY)
- + param.ieba0 = t->output.paddr;
- + else {
- + dev_err(t->dev, "ERR:[0x%d] vdoa task\n", t->task_no);
- + return -EINVAL;
- + }
- + } else {
- + if (IPU_PIX_FMT_TILED_NV12F != t->input.format) {
- + dev_err(t->dev, "ERR [0x%d] vdoa task\n", t->task_no);
- + return -EINVAL;
- + }
- + }
- + ret = vdoa_setup(t->vdoa_handle, ¶m);
- + if (ret)
- + goto done;
- + vdoa_get_output_buf(t->vdoa_handle, &buf);
- + if (t->set.task & VDOA_ONLY)
- + goto done;
- +
- + ret = ipu_init_channel_buffer(ipu,
- + channel,
- + type,
- + ipu_fmt,
- + width,
- + height,
- + ipu_stride,
- + IPU_ROTATE_NONE,
- + buf.ieba0,
- + buf.ieba1,
- + 0,
- + buf.iubo,
- + 0);
- + if (ret < 0) {
- + t->state = STATE_INIT_CHAN_BUF_FAIL;
- + goto done;
- + }
- +
- + if (param.band_mode) {
- + ret = ipu_set_channel_bandmode(ipu, channel,
- + type, t->set.band_lines);
- + if (ret < 0) {
- + t->state = STATE_INIT_CHAN_BAND_FAIL;
- + goto done;
- + }
- + }
- +done:
- + return ret;
- +}
- +
- +static int init_tiled_ch_bufs(struct ipu_soc *ipu, struct ipu_task_entry *t)
- +{
- + int ret = 0;
- +
- + if (IPU_PIX_FMT_TILED_NV12 == t->input.format) {
- + ret = init_tiled_buf(ipu, t, t->set.ic_chan, INPUT_CHAN);
- + CHECK_RETCODE(ret < 0, "init tiled_ch", t->state, done, ret);
- + } else if (IPU_PIX_FMT_TILED_NV12F == t->input.format) {
- + ret = init_tiled_buf(ipu, t, t->set.ic_chan, INPUT_CHAN);
- + CHECK_RETCODE(ret < 0, "init tiled_ch-c", t->state, done, ret);
- + ret = init_tiled_buf(ipu, t, t->set.vdi_ic_p_chan,
- + INPUT_CHAN_VDI_P);
- + CHECK_RETCODE(ret < 0, "init tiled_ch-p", t->state, done, ret);
- + ret = init_tiled_buf(ipu, t, t->set.vdi_ic_n_chan,
- + INPUT_CHAN_VDI_N);
- + CHECK_RETCODE(ret < 0, "init tiled_ch-n", t->state, done, ret);
- + } else {
- + ret = -EINVAL;
- + dev_err(t->dev, "ERR[no-0x%x] invalid fmt:0x%x!\n",
- + t->task_no, t->input.format);
- + }
- +
- +done:
- + return ret;
- +}
- +
- +static int init_ic(struct ipu_soc *ipu, struct ipu_task_entry *t)
- +{
- + int ret = 0;
- + ipu_channel_params_t params;
- + dma_addr_t inbuf = 0, ovbuf = 0, ov_alp_buf = 0;
- + dma_addr_t inbuf_p = 0, inbuf_n = 0;
- + dma_addr_t outbuf = 0;
- + int out_uoff = 0, out_voff = 0, out_rot;
- + int out_w = 0, out_h = 0, out_stride;
- + int out_fmt;
- + u32 vdi_frame_idx = 0;
- +
- + memset(¶ms, 0, sizeof(params));
- +
- + /* is it need link a rot channel */
- + if (ic_and_rot(t->set.mode)) {
- + outbuf = t->set.r_paddr;
- + out_w = t->set.r_width;
- + out_h = t->set.r_height;
- + out_stride = t->set.r_stride;
- + out_fmt = t->set.r_fmt;
- + out_uoff = 0;
- + out_voff = 0;
- + out_rot = IPU_ROTATE_NONE;
- + } else {
- + outbuf = t->output.paddr + t->set.o_off;
- + out_w = t->output.crop.w;
- + out_h = t->output.crop.h;
- + out_stride = t->set.ostride;
- + out_fmt = t->output.format;
- + out_uoff = t->set.o_uoff;
- + out_voff = t->set.o_voff;
- + out_rot = t->output.rotate;
- + }
- +
- + /* settings */
- + params.mem_prp_vf_mem.in_width = t->input.crop.w;
- + params.mem_prp_vf_mem.out_width = out_w;
- + params.mem_prp_vf_mem.in_height = t->input.crop.h;
- + params.mem_prp_vf_mem.out_height = out_h;
- + params.mem_prp_vf_mem.in_pixel_fmt = t->input.format;
- + params.mem_prp_vf_mem.out_pixel_fmt = out_fmt;
- + params.mem_prp_vf_mem.motion_sel = t->input.deinterlace.motion;
- +
- + params.mem_prp_vf_mem.outh_resize_ratio =
- + t->set.sp_setting.outh_resize_ratio;
- + params.mem_prp_vf_mem.outv_resize_ratio =
- + t->set.sp_setting.outv_resize_ratio;
- +
- + if (t->overlay_en) {
- + params.mem_prp_vf_mem.in_g_pixel_fmt = t->overlay.format;
- + params.mem_prp_vf_mem.graphics_combine_en = 1;
- + if (t->overlay.alpha.mode == IPU_ALPHA_MODE_GLOBAL)
- + params.mem_prp_vf_mem.global_alpha_en = 1;
- + else if (t->overlay.alpha.loc_alp_paddr)
- + params.mem_prp_vf_mem.alpha_chan_en = 1;
- + /* otherwise, alpha bending per pixel is used. */
- + params.mem_prp_vf_mem.alpha = t->overlay.alpha.gvalue;
- + if (t->overlay.colorkey.enable) {
- + params.mem_prp_vf_mem.key_color_en = 1;
- + params.mem_prp_vf_mem.key_color = t->overlay.colorkey.value;
- + }
- + }
- +
- + if (t->input.deinterlace.enable) {
- + if (t->input.deinterlace.field_fmt & IPU_DEINTERLACE_FIELD_MASK)
- + params.mem_prp_vf_mem.field_fmt =
- + IPU_DEINTERLACE_FIELD_BOTTOM;
- + else
- + params.mem_prp_vf_mem.field_fmt =
- + IPU_DEINTERLACE_FIELD_TOP;
- +
- + if (t->input.deinterlace.field_fmt & IPU_DEINTERLACE_RATE_EN)
- + vdi_frame_idx = t->input.deinterlace.field_fmt &
- + IPU_DEINTERLACE_RATE_FRAME1;
- + }
- +
- + if (t->set.mode & VDOA_MODE)
- + ipu->vdoa_en = 1;
- +
- + /* init channels */
- + if (!(t->set.task & VDOA_ONLY)) {
- + ret = ipu_init_channel(ipu, t->set.ic_chan, ¶ms);
- + if (ret < 0) {
- + t->state = STATE_INIT_CHAN_FAIL;
- + goto done;
- + }
- + }
- +
- + if (deinterlace_3_field(t)) {
- + ret = ipu_init_channel(ipu, t->set.vdi_ic_p_chan, ¶ms);
- + if (ret < 0) {
- + t->state = STATE_INIT_CHAN_FAIL;
- + goto done;
- + }
- + ret = ipu_init_channel(ipu, t->set.vdi_ic_n_chan, ¶ms);
- + if (ret < 0) {
- + t->state = STATE_INIT_CHAN_FAIL;
- + goto done;
- + }
- + }
- +
- + /* init channel bufs */
- + if ((IPU_PIX_FMT_TILED_NV12 == t->input.format) ||
- + (IPU_PIX_FMT_TILED_NV12F == t->input.format)) {
- + ret = init_tiled_ch_bufs(ipu, t);
- + if (ret < 0)
- + goto done;
- + } else {
- + if ((deinterlace_3_field(t)) &&
- + (IPU_PIX_FMT_TILED_NV12F != t->input.format)) {
- + if (params.mem_prp_vf_mem.field_fmt ==
- + IPU_DEINTERLACE_FIELD_TOP) {
- + if (vdi_frame_idx) {
- + inbuf_p = t->input.paddr + t->set.istride +
- + t->set.i_off;
- + inbuf = t->input.paddr_n + t->set.i_off;
- + inbuf_n = t->input.paddr_n + t->set.istride +
- + t->set.i_off;
- + params.mem_prp_vf_mem.field_fmt =
- + IPU_DEINTERLACE_FIELD_BOTTOM;
- + } else {
- + inbuf_p = t->input.paddr + t->set.i_off;
- + inbuf = t->input.paddr + t->set.istride + t->set.i_off;
- + inbuf_n = t->input.paddr_n + t->set.i_off;
- + }
- + } else {
- + if (vdi_frame_idx) {
- + inbuf_p = t->input.paddr + t->set.i_off;
- + inbuf = t->input.paddr_n + t->set.istride + t->set.i_off;
- + inbuf_n = t->input.paddr_n + t->set.i_off;
- + params.mem_prp_vf_mem.field_fmt =
- + IPU_DEINTERLACE_FIELD_TOP;
- + } else {
- + inbuf_p = t->input.paddr + t->set.istride +
- + t->set.i_off;
- + inbuf = t->input.paddr + t->set.i_off;
- + inbuf_n = t->input.paddr_n + t->set.istride +
- + t->set.i_off;
- + }
- + }
- + } else {
- + if (t->input.deinterlace.enable) {
- + if (params.mem_prp_vf_mem.field_fmt ==
- + IPU_DEINTERLACE_FIELD_TOP) {
- + if (vdi_frame_idx) {
- + inbuf = t->input.paddr + t->set.istride + t->set.i_off;
- + params.mem_prp_vf_mem.field_fmt =
- + IPU_DEINTERLACE_FIELD_BOTTOM;
- + } else
- + inbuf = t->input.paddr + t->set.i_off;
- + } else {
- + if (vdi_frame_idx) {
- + inbuf = t->input.paddr + t->set.i_off;
- + params.mem_prp_vf_mem.field_fmt =
- + IPU_DEINTERLACE_FIELD_TOP;
- + } else
- + inbuf = t->input.paddr + t->set.istride + t->set.i_off;
- + }
- + } else
- + inbuf = t->input.paddr + t->set.i_off;
- + }
- +
- + if (t->overlay_en)
- + ovbuf = t->overlay.paddr + t->set.ov_off;
- + }
- + if (t->overlay_en && (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL))
- + ov_alp_buf = t->overlay.alpha.loc_alp_paddr
- + + t->set.ov_alpha_off;
- +
- + if ((IPU_PIX_FMT_TILED_NV12 != t->input.format) &&
- + (IPU_PIX_FMT_TILED_NV12F != t->input.format)) {
- + ret = ipu_init_channel_buffer(ipu,
- + t->set.ic_chan,
- + IPU_INPUT_BUFFER,
- + t->input.format,
- + t->input.crop.w,
- + t->input.crop.h,
- + t->set.istride,
- + IPU_ROTATE_NONE,
- + inbuf,
- + 0,
- + 0,
- + t->set.i_uoff,
- + t->set.i_voff);
- + if (ret < 0) {
- + t->state = STATE_INIT_CHAN_BUF_FAIL;
- + goto done;
- + }
- + }
- + if (deinterlace_3_field(t) &&
- + (IPU_PIX_FMT_TILED_NV12F != t->input.format)) {
- + ret = ipu_init_channel_buffer(ipu,
- + t->set.vdi_ic_p_chan,
- + IPU_INPUT_BUFFER,
- + t->input.format,
- + t->input.crop.w,
- + t->input.crop.h,
- + t->set.istride,
- + IPU_ROTATE_NONE,
- + inbuf_p,
- + 0,
- + 0,
- + t->set.i_uoff,
- + t->set.i_voff);
- + if (ret < 0) {
- + t->state = STATE_INIT_CHAN_BUF_FAIL;
- + goto done;
- + }
- +
- + ret = ipu_init_channel_buffer(ipu,
- + t->set.vdi_ic_n_chan,
- + IPU_INPUT_BUFFER,
- + t->input.format,
- + t->input.crop.w,
- + t->input.crop.h,
- + t->set.istride,
- + IPU_ROTATE_NONE,
- + inbuf_n,
- + 0,
- + 0,
- + t->set.i_uoff,
- + t->set.i_voff);
- + if (ret < 0) {
- + t->state = STATE_INIT_CHAN_BUF_FAIL;
- + goto done;
- + }
- + }
- +
- + if (t->overlay_en) {
- + ret = ipu_init_channel_buffer(ipu,
- + t->set.ic_chan,
- + IPU_GRAPH_IN_BUFFER,
- + t->overlay.format,
- + t->overlay.crop.w,
- + t->overlay.crop.h,
- + t->set.ovstride,
- + IPU_ROTATE_NONE,
- + ovbuf,
- + 0,
- + 0,
- + t->set.ov_uoff,
- + t->set.ov_voff);
- + if (ret < 0) {
- + t->state = STATE_INIT_CHAN_BUF_FAIL;
- + goto done;
- + }
- + }
- +
- + if (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL) {
- + ret = ipu_init_channel_buffer(ipu,
- + t->set.ic_chan,
- + IPU_ALPHA_IN_BUFFER,
- + IPU_PIX_FMT_GENERIC,
- + t->overlay.crop.w,
- + t->overlay.crop.h,
- + t->set.ov_alpha_stride,
- + IPU_ROTATE_NONE,
- + ov_alp_buf,
- + 0,
- + 0,
- + 0, 0);
- + if (ret < 0) {
- + t->state = STATE_INIT_CHAN_BUF_FAIL;
- + goto done;
- + }
- + }
- +
- + if (!(t->set.task & VDOA_ONLY)) {
- + ret = ipu_init_channel_buffer(ipu,
- + t->set.ic_chan,
- + IPU_OUTPUT_BUFFER,
- + out_fmt,
- + out_w,
- + out_h,
- + out_stride,
- + out_rot,
- + outbuf,
- + 0,
- + 0,
- + out_uoff,
- + out_voff);
- + if (ret < 0) {
- + t->state = STATE_INIT_CHAN_BUF_FAIL;
- + goto done;
- + }
- + }
- +
- + if ((t->set.mode & VDOA_BAND_MODE) && (t->set.task & VDI_VF)) {
- + ret = ipu_link_channels(ipu, MEM_VDOA_MEM, t->set.ic_chan);
- + CHECK_RETCODE(ret < 0, "ipu_link_ch vdoa_ic",
- + STATE_LINK_CHAN_FAIL, done, ret);
- + }
- +
- +done:
- + return ret;
- +}
- +
- +static void uninit_ic(struct ipu_soc *ipu, struct ipu_task_entry *t)
- +{
- + int ret;
- +
- + if ((t->set.mode & VDOA_BAND_MODE) && (t->set.task & VDI_VF)) {
- + ret = ipu_unlink_channels(ipu, MEM_VDOA_MEM, t->set.ic_chan);
- + CHECK_RETCODE_CONT(ret < 0, "ipu_unlink_ch vdoa_ic",
- + STATE_UNLINK_CHAN_FAIL, ret);
- + }
- + ipu_uninit_channel(ipu, t->set.ic_chan);
- + if (deinterlace_3_field(t)) {
- + ipu_uninit_channel(ipu, t->set.vdi_ic_p_chan);
- + ipu_uninit_channel(ipu, t->set.vdi_ic_n_chan);
- + }
- +}
- +
- +static int init_rot(struct ipu_soc *ipu, struct ipu_task_entry *t)
- +{
- + int ret = 0;
- + dma_addr_t inbuf = 0, outbuf = 0;
- + int in_uoff = 0, in_voff = 0;
- + int in_fmt, in_width, in_height, in_stride;
- +
- + /* init channel */
- + ret = ipu_init_channel(ipu, t->set.rot_chan, NULL);
- + if (ret < 0) {
- + t->state = STATE_INIT_CHAN_FAIL;
- + goto done;
- + }
- +
- + /* init channel buf */
- + /* is it need link to a ic channel */
- + if (ic_and_rot(t->set.mode)) {
- + in_fmt = t->set.r_fmt;
- + in_width = t->set.r_width;
- + in_height = t->set.r_height;
- + in_stride = t->set.r_stride;
- + inbuf = t->set.r_paddr;
- + in_uoff = 0;
- + in_voff = 0;
- + } else {
- + in_fmt = t->input.format;
- + in_width = t->input.crop.w;
- + in_height = t->input.crop.h;
- + in_stride = t->set.istride;
- + inbuf = t->input.paddr + t->set.i_off;
- + in_uoff = t->set.i_uoff;
- + in_voff = t->set.i_voff;
- + }
- + outbuf = t->output.paddr + t->set.o_off;
- +
- + ret = ipu_init_channel_buffer(ipu,
- + t->set.rot_chan,
- + IPU_INPUT_BUFFER,
- + in_fmt,
- + in_width,
- + in_height,
- + in_stride,
- + t->output.rotate,
- + inbuf,
- + 0,
- + 0,
- + in_uoff,
- + in_voff);
- + if (ret < 0) {
- + t->state = STATE_INIT_CHAN_BUF_FAIL;
- + goto done;
- + }
- +
- + ret = ipu_init_channel_buffer(ipu,
- + t->set.rot_chan,
- + IPU_OUTPUT_BUFFER,
- + t->output.format,
- + t->output.crop.w,
- + t->output.crop.h,
- + t->set.ostride,
- + IPU_ROTATE_NONE,
- + outbuf,
- + 0,
- + 0,
- + t->set.o_uoff,
- + t->set.o_voff);
- + if (ret < 0) {
- + t->state = STATE_INIT_CHAN_BUF_FAIL;
- + goto done;
- + }
- +
- +done:
- + return ret;
- +}
- +
- +static void uninit_rot(struct ipu_soc *ipu, struct ipu_task_entry *t)
- +{
- + ipu_uninit_channel(ipu, t->set.rot_chan);
- +}
- +
- +static int get_irq(struct ipu_task_entry *t)
- +{
- + int irq;
- + ipu_channel_t chan;
- +
- + if (only_ic(t->set.mode))
- + chan = t->set.ic_chan;
- + else
- + chan = t->set.rot_chan;
- +
- + switch (chan) {
- + case MEM_ROT_VF_MEM:
- + irq = IPU_IRQ_PRP_VF_ROT_OUT_EOF;
- + break;
- + case MEM_ROT_PP_MEM:
- + irq = IPU_IRQ_PP_ROT_OUT_EOF;
- + break;
- + case MEM_VDI_PRP_VF_MEM:
- + case MEM_PRP_VF_MEM:
- + irq = IPU_IRQ_PRP_VF_OUT_EOF;
- + break;
- + case MEM_PP_MEM:
- + irq = IPU_IRQ_PP_OUT_EOF;
- + break;
- + case MEM_VDI_MEM:
- + irq = IPU_IRQ_VDIC_OUT_EOF;
- + break;
- + default:
- + irq = -EINVAL;
- + }
- +
- + return irq;
- +}
- +
- +static irqreturn_t task_irq_handler(int irq, void *dev_id)
- +{
- + struct ipu_task_entry *prev_tsk = dev_id;
- +
- + CHECK_PERF(&prev_tsk->ts_inirq);
- + complete(&prev_tsk->irq_comp);
- + dev_dbg(prev_tsk->dev, "[0x%p] no-0x%x in-irq!",
- + prev_tsk, prev_tsk->task_no);
- +
- + return IRQ_HANDLED;
- +}
- +
- +/* Fix deinterlace up&down split mode medium line */
- +static void vdi_split_process(struct ipu_soc *ipu, struct ipu_task_entry *t)
- +{
- + u32 vdi_size;
- + u32 vdi_save_lines;
- + u32 stripe_mode;
- + u32 task_no;
- + u32 i, offset_addr;
- + u32 line_size;
- + unsigned char *base_off;
- + struct ipu_task_entry *parent = t->parent;
- + struct mutex *lock = &parent->vdic_lock;
- +
- + if (!parent) {
- + dev_err(t->dev, "ERR[0x%x]invalid parent\n", t->task_no);
- + return;
- + }
- + mutex_lock(lock);
- + stripe_mode = t->task_no & 0xf;
- + task_no = t->task_no >> 4;
- +
- + /* Save both luma and chroma part for interleaved YUV(e.g. YUYV).
- + * Save luma part for non-interleaved and partial-interleaved
- + * YUV format (e.g NV12 and YV12). */
- + if (t->output.format == IPU_PIX_FMT_YUYV ||
- + t->output.format == IPU_PIX_FMT_UYVY)
- + line_size = t->output.crop.w * fmt_to_bpp(t->output.format)/8;
- + else
- + line_size = t->output.crop.w;
- +
- + vdi_save_lines = (t->output.crop.h - t->set.sp_setting.ud_split_line)/2;
- + vdi_size = vdi_save_lines * line_size;
- + if (vdi_save_lines <= 0) {
- + dev_err(t->dev, "[0x%p] vdi_save_line error\n", (void *)t);
- + mutex_unlock(lock);
- + return;
- + }
- +
- + /*check vditmpbuf buffer have alloced or buffer size is changed */
- + if ((vdi_save_lines != parent->old_save_lines) ||
- + (vdi_size != parent->old_size)) {
- + if (parent->vditmpbuf[0] != NULL)
- + kfree(parent->vditmpbuf[0]);
- + if (parent->vditmpbuf[1] != NULL)
- + kfree(parent->vditmpbuf[1]);
- +
- + parent->vditmpbuf[0] = kmalloc(vdi_size, GFP_KERNEL);
- + if (parent->vditmpbuf[0] == NULL) {
- + dev_err(t->dev,
- + "[0x%p]Falied Alloc vditmpbuf[0]\n", (void *)t);
- + mutex_unlock(lock);
- + return;
- + }
- + memset(parent->vditmpbuf[0], 0, vdi_size);
- +
- + parent->vditmpbuf[1] = kmalloc(vdi_size, GFP_KERNEL);
- + if (parent->vditmpbuf[1] == NULL) {
- + dev_err(t->dev,
- + "[0x%p]Falied Alloc vditmpbuf[1]\n", (void *)t);
- + mutex_unlock(lock);
- + return;
- + }
- + memset(parent->vditmpbuf[1], 0, vdi_size);
- +
- + parent->old_save_lines = vdi_save_lines;
- + parent->old_size = vdi_size;
- + }
- +
- + if (pfn_valid(t->output.paddr >> PAGE_SHIFT)) {
- + base_off = page_address(pfn_to_page(t->output.paddr >> PAGE_SHIFT));
- + base_off += t->output.paddr & ((1 << PAGE_SHIFT) - 1);
- + } else {
- + base_off = (char *)ioremap_nocache(t->output.paddr,
- + t->output.width * t->output.height *
- + fmt_to_bpp(t->output.format)/8);
- + }
- + if (base_off == NULL) {
- + dev_err(t->dev, "ERR[0x%p]Failed get virtual address\n", t);
- + mutex_unlock(lock);
- + return;
- + }
- +
- + /* UP stripe or UP&LEFT stripe */
- + if ((stripe_mode == UP_STRIPE) ||
- + (stripe_mode == (UP_STRIPE | LEFT_STRIPE))) {
- + if (!parent->buf0filled) {
- + offset_addr = t->set.o_off +
- + t->set.sp_setting.ud_split_line*t->set.ostride;
- + dmac_flush_range(base_off + offset_addr,
- + base_off + offset_addr + vdi_size);
- + outer_flush_range(t->output.paddr + offset_addr,
- + t->output.paddr + offset_addr + vdi_size);
- +
- + for (i = 0; i < vdi_save_lines; i++)
- + memcpy(parent->vditmpbuf[0] + i*line_size,
- + base_off + offset_addr +
- + i*t->set.ostride, line_size);
- + parent->buf0filled = true;
- + } else {
- + offset_addr = t->set.o_off + (t->output.crop.h -
- + vdi_save_lines) * t->set.ostride;
- + for (i = 0; i < vdi_save_lines; i++)
- + memcpy(base_off + offset_addr + i*t->set.ostride,
- + parent->vditmpbuf[0] + i*line_size, line_size);
- +
- + dmac_flush_range(base_off + offset_addr,
- + base_off + offset_addr + i*t->set.ostride);
- + outer_flush_range(t->output.paddr + offset_addr,
- + t->output.paddr + offset_addr + i*t->set.ostride);
- + parent->buf0filled = false;
- + }
- + }
- + /*Down stripe or Down&Left stripe*/
- + else if ((stripe_mode == DOWN_STRIPE) ||
- + (stripe_mode == (DOWN_STRIPE | LEFT_STRIPE))) {
- + if (!parent->buf0filled) {
- + offset_addr = t->set.o_off + vdi_save_lines*t->set.ostride;
- + dmac_flush_range(base_off + offset_addr,
- + base_off + offset_addr + vdi_size);
- + outer_flush_range(t->output.paddr + offset_addr,
- + t->output.paddr + offset_addr + vdi_size);
- +
- + for (i = 0; i < vdi_save_lines; i++)
- + memcpy(parent->vditmpbuf[0] + i*line_size,
- + base_off + offset_addr + i*t->set.ostride,
- + line_size);
- + parent->buf0filled = true;
- + } else {
- + offset_addr = t->set.o_off;
- + for (i = 0; i < vdi_save_lines; i++)
- + memcpy(base_off + offset_addr + i*t->set.ostride,
- + parent->vditmpbuf[0] + i*line_size,
- + line_size);
- +
- + dmac_flush_range(base_off + offset_addr,
- + base_off + offset_addr + i*t->set.ostride);
- + outer_flush_range(t->output.paddr + offset_addr,
- + t->output.paddr + offset_addr + i*t->set.ostride);
- + parent->buf0filled = false;
- + }
- + }
- + /*Up&Right stripe*/
- + else if (stripe_mode == (UP_STRIPE | RIGHT_STRIPE)) {
- + if (!parent->buf1filled) {
- + offset_addr = t->set.o_off +
- + t->set.sp_setting.ud_split_line*t->set.ostride;
- + dmac_flush_range(base_off + offset_addr,
- + base_off + offset_addr + vdi_size);
- + outer_flush_range(t->output.paddr + offset_addr,
- + t->output.paddr + offset_addr + vdi_size);
- +
- + for (i = 0; i < vdi_save_lines; i++)
- + memcpy(parent->vditmpbuf[1] + i*line_size,
- + base_off + offset_addr + i*t->set.ostride,
- + line_size);
- + parent->buf1filled = true;
- + } else {
- + offset_addr = t->set.o_off +
- + (t->output.crop.h - vdi_save_lines)*t->set.ostride;
- + for (i = 0; i < vdi_save_lines; i++)
- + memcpy(base_off + offset_addr + i*t->set.ostride,
- + parent->vditmpbuf[1] + i*line_size,
- + line_size);
- +
- + dmac_flush_range(base_off + offset_addr,
- + base_off + offset_addr + i*t->set.ostride);
- + outer_flush_range(t->output.paddr + offset_addr,
- + t->output.paddr + offset_addr + i*t->set.ostride);
- + parent->buf1filled = false;
- + }
- + }
- + /*Down stripe or Down&Right stript*/
- + else if (stripe_mode == (DOWN_STRIPE | RIGHT_STRIPE)) {
- + if (!parent->buf1filled) {
- + offset_addr = t->set.o_off + vdi_save_lines*t->set.ostride;
- + dmac_flush_range(base_off + offset_addr,
- + base_off + offset_addr + vdi_save_lines*t->set.ostride);
- + outer_flush_range(t->output.paddr + offset_addr,
- + t->output.paddr + offset_addr + vdi_save_lines*t->set.ostride);
- +
- + for (i = 0; i < vdi_save_lines; i++)
- + memcpy(parent->vditmpbuf[1] + i*line_size,
- + base_off + offset_addr + i*t->set.ostride,
- + line_size);
- + parent->buf1filled = true;
- + } else {
- + offset_addr = t->set.o_off;
- + for (i = 0; i < vdi_save_lines; i++)
- + memcpy(base_off + offset_addr + i*t->set.ostride,
- + parent->vditmpbuf[1] + i*line_size,
- + line_size);
- +
- + dmac_flush_range(base_off + offset_addr,
- + base_off + offset_addr + vdi_save_lines*t->set.ostride);
- + outer_flush_range(t->output.paddr + offset_addr,
- + t->output.paddr + offset_addr + vdi_save_lines*t->set.ostride);
- + parent->buf1filled = false;
- + }
- + }
- + if (!pfn_valid(t->output.paddr >> PAGE_SHIFT))
- + iounmap(base_off);
- + mutex_unlock(lock);
- +}
- +
- +static void do_task_release(struct ipu_task_entry *t, int fail)
- +{
- + int ret;
- + struct ipu_soc *ipu = t->ipu;
- +
- + if (t->input.deinterlace.enable && !fail &&
- + (t->task_no & (UP_STRIPE | DOWN_STRIPE)))
- + vdi_split_process(ipu, t);
- +
- + ipu_free_irq(ipu, t->irq, t);
- +
- + if (t->vdoa_dma.vaddr)
- + dma_free_coherent(t->dev,
- + t->vdoa_dma.size,
- + t->vdoa_dma.vaddr,
- + t->vdoa_dma.paddr);
- +
- + if (only_ic(t->set.mode)) {
- + ret = ipu_disable_channel(ipu, t->set.ic_chan, true);
- + CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch only_ic",
- + STATE_DISABLE_CHAN_FAIL, ret);
- + if (deinterlace_3_field(t)) {
- + ret = ipu_disable_channel(ipu, t->set.vdi_ic_p_chan,
- + true);
- + CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch only_ic_p",
- + STATE_DISABLE_CHAN_FAIL, ret);
- + ret = ipu_disable_channel(ipu, t->set.vdi_ic_n_chan,
- + true);
- + CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch only_ic_n",
- + STATE_DISABLE_CHAN_FAIL, ret);
- + }
- + } else if (only_rot(t->set.mode)) {
- + ret = ipu_disable_channel(ipu, t->set.rot_chan, true);
- + CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch only_rot",
- + STATE_DISABLE_CHAN_FAIL, ret);
- + } else if (ic_and_rot(t->set.mode)) {
- + ret = ipu_unlink_channels(ipu, t->set.ic_chan, t->set.rot_chan);
- + CHECK_RETCODE_CONT(ret < 0, "ipu_unlink_ch",
- + STATE_UNLINK_CHAN_FAIL, ret);
- + ret = ipu_disable_channel(ipu, t->set.rot_chan, true);
- + CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch ic_and_rot-rot",
- + STATE_DISABLE_CHAN_FAIL, ret);
- + ret = ipu_disable_channel(ipu, t->set.ic_chan, true);
- + CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch ic_and_rot-ic",
- + STATE_DISABLE_CHAN_FAIL, ret);
- + if (deinterlace_3_field(t)) {
- + ret = ipu_disable_channel(ipu, t->set.vdi_ic_p_chan,
- + true);
- + CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch icrot-ic-p",
- + STATE_DISABLE_CHAN_FAIL, ret);
- + ret = ipu_disable_channel(ipu, t->set.vdi_ic_n_chan,
- + true);
- + CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch icrot-ic-n",
- + STATE_DISABLE_CHAN_FAIL, ret);
- + }
- + }
- +
- + if (only_ic(t->set.mode))
- + uninit_ic(ipu, t);
- + else if (only_rot(t->set.mode))
- + uninit_rot(ipu, t);
- + else if (ic_and_rot(t->set.mode)) {
- + uninit_ic(ipu, t);
- + uninit_rot(ipu, t);
- + }
- +
- + t->state = STATE_OK;
- + CHECK_PERF(&t->ts_rel);
- + return;
- +}
- +
- +static void do_task_vdoa_only(struct ipu_task_entry *t)
- +{
- + int ret;
- +
- + ret = init_tiled_ch_bufs(NULL, t);
- + CHECK_RETCODE(ret < 0, "do_vdoa_only", STATE_ERR, out, ret);
- + ret = vdoa_start(t->vdoa_handle, VDOA_DEF_TIMEOUT_MS);
- + vdoa_stop(t->vdoa_handle);
- + CHECK_RETCODE(ret < 0, "vdoa_wait4complete, do_vdoa_only",
- + STATE_VDOA_IRQ_TIMEOUT, out, ret);
- +
- + t->state = STATE_OK;
- +out:
- + return;
- +}
- +
- +static void do_task(struct ipu_task_entry *t)
- +{
- + int r_size;
- + int irq;
- + int ret;
- + uint32_t busy;
- + struct ipu_soc *ipu = t->ipu;
- +
- + CHECK_PERF(&t->ts_dotask);
- +
- + if (!ipu) {
- + t->state = STATE_NO_IPU;
- + return;
- + }
- +
- + init_completion(&t->irq_comp);
- + dev_dbg(ipu->dev, "[0x%p]Do task no:0x%x: id %d\n", (void *)t,
- + t->task_no, t->task_id);
- + dump_task_info(t);
- +
- + if (t->set.task & IC_PP) {
- + t->set.ic_chan = MEM_PP_MEM;
- + dev_dbg(ipu->dev, "[0x%p]ic channel MEM_PP_MEM\n", (void *)t);
- + } else if (t->set.task & IC_VF) {
- + t->set.ic_chan = MEM_PRP_VF_MEM;
- + dev_dbg(ipu->dev, "[0x%p]ic channel MEM_PRP_VF_MEM\n", (void *)t);
- + } else if (t->set.task & VDI_VF) {
- + if (t->set.mode & VDOA_BAND_MODE) {
- + t->set.ic_chan = MEM_VDI_MEM;
- + if (deinterlace_3_field(t)) {
- + t->set.vdi_ic_p_chan = MEM_VDI_MEM_P;
- + t->set.vdi_ic_n_chan = MEM_VDI_MEM_N;
- + }
- + dev_dbg(ipu->dev, "[0x%p]ic ch MEM_VDI_MEM\n",
- + (void *)t);
- + } else {
- + t->set.ic_chan = MEM_VDI_PRP_VF_MEM;
- + if (deinterlace_3_field(t)) {
- + t->set.vdi_ic_p_chan = MEM_VDI_PRP_VF_MEM_P;
- + t->set.vdi_ic_n_chan = MEM_VDI_PRP_VF_MEM_N;
- + }
- + dev_dbg(ipu->dev,
- + "[0x%p]ic ch MEM_VDI_PRP_VF_MEM\n", t);
- + }
- + }
- +
- + if (t->set.task & ROT_PP) {
- + t->set.rot_chan = MEM_ROT_PP_MEM;
- + dev_dbg(ipu->dev, "[0x%p]rot channel MEM_ROT_PP_MEM\n", (void *)t);
- + } else if (t->set.task & ROT_VF) {
- + t->set.rot_chan = MEM_ROT_VF_MEM;
- + dev_dbg(ipu->dev, "[0x%p]rot channel MEM_ROT_VF_MEM\n", (void *)t);
- + }
- +
- + if (t->task_id == IPU_TASK_ID_VF)
- + busy = ic_vf_pp_is_busy(ipu, true);
- + else if (t->task_id == IPU_TASK_ID_PP)
- + busy = ic_vf_pp_is_busy(ipu, false);
- + else {
- + dev_err(ipu->dev, "ERR[no:0x%x]ipu task_id:%d invalid!\n",
- + t->task_no, t->task_id);
- + return;
- + }
- + if (busy) {
- + dev_err(ipu->dev, "ERR[0x%p-no:0x%x]ipu task_id:%d busy!\n",
- + (void *)t, t->task_no, t->task_id);
- + t->state = STATE_IPU_BUSY;
- + return;
- + }
- +
- + irq = get_irq(t);
- + if (irq < 0) {
- + t->state = STATE_NO_IRQ;
- + return;
- + }
- + t->irq = irq;
- +
- + /* channel setup */
- + if (only_ic(t->set.mode)) {
- + dev_dbg(t->dev, "[0x%p]only ic mode\n", (void *)t);
- + ret = init_ic(ipu, t);
- + CHECK_RETCODE(ret < 0, "init_ic only_ic",
- + t->state, chan_setup, ret);
- + } else if (only_rot(t->set.mode)) {
- + dev_dbg(t->dev, "[0x%p]only rot mode\n", (void *)t);
- + ret = init_rot(ipu, t);
- + CHECK_RETCODE(ret < 0, "init_rot only_rot",
- + t->state, chan_setup, ret);
- + } else if (ic_and_rot(t->set.mode)) {
- + int rot_idx = (t->task_id == IPU_TASK_ID_VF) ? 0 : 1;
- +
- + dev_dbg(t->dev, "[0x%p]ic + rot mode\n", (void *)t);
- + t->set.r_fmt = t->output.format;
- + if (t->output.rotate >= IPU_ROTATE_90_RIGHT) {
- + t->set.r_width = t->output.crop.h;
- + t->set.r_height = t->output.crop.w;
- + } else {
- + t->set.r_width = t->output.crop.w;
- + t->set.r_height = t->output.crop.h;
- + }
- + t->set.r_stride = t->set.r_width *
- + bytes_per_pixel(t->set.r_fmt);
- + r_size = PAGE_ALIGN(t->set.r_width * t->set.r_height
- + * fmt_to_bpp(t->set.r_fmt)/8);
- +
- + if (r_size > ipu->rot_dma[rot_idx].size) {
- + dev_dbg(t->dev, "[0x%p]realloc rot buffer\n", (void *)t);
- +
- + if (ipu->rot_dma[rot_idx].vaddr)
- + dma_free_coherent(t->dev,
- + ipu->rot_dma[rot_idx].size,
- + ipu->rot_dma[rot_idx].vaddr,
- + ipu->rot_dma[rot_idx].paddr);
- +
- + ipu->rot_dma[rot_idx].size = r_size;
- + ipu->rot_dma[rot_idx].vaddr = dma_alloc_coherent(t->dev,
- + r_size,
- + &ipu->rot_dma[rot_idx].paddr,
- + GFP_DMA | GFP_KERNEL);
- + CHECK_RETCODE(ipu->rot_dma[rot_idx].vaddr == NULL,
- + "ic_and_rot", STATE_SYS_NO_MEM,
- + chan_setup, -ENOMEM);
- + }
- + t->set.r_paddr = ipu->rot_dma[rot_idx].paddr;
- +
- + dev_dbg(t->dev, "[0x%p]rotation:\n", (void *)t);
- + dev_dbg(t->dev, "[0x%p]\tformat = 0x%x\n", (void *)t, t->set.r_fmt);
- + dev_dbg(t->dev, "[0x%p]\twidth = %d\n", (void *)t, t->set.r_width);
- + dev_dbg(t->dev, "[0x%p]\theight = %d\n", (void *)t, t->set.r_height);
- + dev_dbg(t->dev, "[0x%p]\tpaddr = 0x%x\n", (void *)t, t->set.r_paddr);
- + dev_dbg(t->dev, "[0x%p]\trstride = %d\n", (void *)t, t->set.r_stride);
- +
- + ret = init_ic(ipu, t);
- + CHECK_RETCODE(ret < 0, "init_ic ic_and_rot",
- + t->state, chan_setup, ret);
- + ret = init_rot(ipu, t);
- + CHECK_RETCODE(ret < 0, "init_rot ic_and_rot",
- + t->state, chan_setup, ret);
- + ret = ipu_link_channels(ipu, t->set.ic_chan,
- + t->set.rot_chan);
- + CHECK_RETCODE(ret < 0, "ipu_link_ch ic_and_rot",
- + STATE_LINK_CHAN_FAIL, chan_setup, ret);
- + } else {
- + dev_err(t->dev, "ERR [0x%p]do task: should not be here\n", t);
- + t->state = STATE_ERR;
- + return;
- + }
- +
- + ret = ipu_request_irq(ipu, irq, task_irq_handler, 0, NULL, t);
- + CHECK_RETCODE(ret < 0, "ipu_req_irq",
- + STATE_IRQ_FAIL, chan_setup, ret);
- +
- + /* enable/start channel */
- + if (only_ic(t->set.mode)) {
- + ret = ipu_enable_channel(ipu, t->set.ic_chan);
- + CHECK_RETCODE(ret < 0, "ipu_enable_ch only_ic",
- + STATE_ENABLE_CHAN_FAIL, chan_en, ret);
- + if (deinterlace_3_field(t)) {
- + ret = ipu_enable_channel(ipu, t->set.vdi_ic_p_chan);
- + CHECK_RETCODE(ret < 0, "ipu_enable_ch only_ic_p",
- + STATE_ENABLE_CHAN_FAIL, chan_en, ret);
- + ret = ipu_enable_channel(ipu, t->set.vdi_ic_n_chan);
- + CHECK_RETCODE(ret < 0, "ipu_enable_ch only_ic_n",
- + STATE_ENABLE_CHAN_FAIL, chan_en, ret);
- + }
- +
- + ret = ipu_select_buffer(ipu, t->set.ic_chan, IPU_OUTPUT_BUFFER,
- + 0);
- + CHECK_RETCODE(ret < 0, "ipu_sel_buf only_ic",
- + STATE_SEL_BUF_FAIL, chan_buf, ret);
- + if (t->overlay_en) {
- + ret = ipu_select_buffer(ipu, t->set.ic_chan,
- + IPU_GRAPH_IN_BUFFER, 0);
- + CHECK_RETCODE(ret < 0, "ipu_sel_buf only_ic_g",
- + STATE_SEL_BUF_FAIL, chan_buf, ret);
- + if (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL) {
- + ret = ipu_select_buffer(ipu, t->set.ic_chan,
- + IPU_ALPHA_IN_BUFFER, 0);
- + CHECK_RETCODE(ret < 0, "ipu_sel_buf only_ic_a",
- + STATE_SEL_BUF_FAIL, chan_buf,
- + ret);
- + }
- + }
- + if (!(t->set.mode & VDOA_BAND_MODE)) {
- + if (deinterlace_3_field(t))
- + ipu_select_multi_vdi_buffer(ipu, 0);
- + else {
- + ret = ipu_select_buffer(ipu, t->set.ic_chan,
- + IPU_INPUT_BUFFER, 0);
- + CHECK_RETCODE(ret < 0, "ipu_sel_buf only_ic_i",
- + STATE_SEL_BUF_FAIL, chan_buf, ret);
- + }
- + }
- + } else if (only_rot(t->set.mode)) {
- + ret = ipu_enable_channel(ipu, t->set.rot_chan);
- + CHECK_RETCODE(ret < 0, "ipu_enable_ch only_rot",
- + STATE_ENABLE_CHAN_FAIL, chan_en, ret);
- + ret = ipu_select_buffer(ipu, t->set.rot_chan,
- + IPU_OUTPUT_BUFFER, 0);
- + CHECK_RETCODE(ret < 0, "ipu_sel_buf only_rot_o",
- + STATE_SEL_BUF_FAIL, chan_buf, ret);
- + ret = ipu_select_buffer(ipu, t->set.rot_chan,
- + IPU_INPUT_BUFFER, 0);
- + CHECK_RETCODE(ret < 0, "ipu_sel_buf only_rot_i",
- + STATE_SEL_BUF_FAIL, chan_buf, ret);
- + } else if (ic_and_rot(t->set.mode)) {
- + ret = ipu_enable_channel(ipu, t->set.rot_chan);
- + CHECK_RETCODE(ret < 0, "ipu_enable_ch ic_and_rot-rot",
- + STATE_ENABLE_CHAN_FAIL, chan_en, ret);
- + ret = ipu_enable_channel(ipu, t->set.ic_chan);
- + CHECK_RETCODE(ret < 0, "ipu_enable_ch ic_and_rot-ic",
- + STATE_ENABLE_CHAN_FAIL, chan_en, ret);
- + if (deinterlace_3_field(t)) {
- + ret = ipu_enable_channel(ipu, t->set.vdi_ic_p_chan);
- + CHECK_RETCODE(ret < 0, "ipu_enable_ch ic_and_rot-p",
- + STATE_ENABLE_CHAN_FAIL, chan_en, ret);
- + ret = ipu_enable_channel(ipu, t->set.vdi_ic_n_chan);
- + CHECK_RETCODE(ret < 0, "ipu_enable_ch ic_and_rot-n",
- + STATE_ENABLE_CHAN_FAIL, chan_en, ret);
- + }
- +
- + ret = ipu_select_buffer(ipu, t->set.rot_chan,
- + IPU_OUTPUT_BUFFER, 0);
- + CHECK_RETCODE(ret < 0, "ipu_sel_buf ic_and_rot-rot-o",
- + STATE_SEL_BUF_FAIL, chan_buf, ret);
- + if (t->overlay_en) {
- + ret = ipu_select_buffer(ipu, t->set.ic_chan,
- + IPU_GRAPH_IN_BUFFER, 0);
- + CHECK_RETCODE(ret < 0, "ipu_sel_buf ic_and_rot-ic-g",
- + STATE_SEL_BUF_FAIL, chan_buf, ret);
- + if (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL) {
- + ret = ipu_select_buffer(ipu, t->set.ic_chan,
- + IPU_ALPHA_IN_BUFFER, 0);
- + CHECK_RETCODE(ret < 0, "ipu_sel_buf icrot-ic-a",
- + STATE_SEL_BUF_FAIL,
- + chan_buf, ret);
- + }
- + }
- + ret = ipu_select_buffer(ipu, t->set.ic_chan,
- + IPU_OUTPUT_BUFFER, 0);
- + CHECK_RETCODE(ret < 0, "ipu_sel_buf ic_and_rot-ic-o",
- + STATE_SEL_BUF_FAIL, chan_buf, ret);
- + if (deinterlace_3_field(t))
- + ipu_select_multi_vdi_buffer(ipu, 0);
- + else {
- + ret = ipu_select_buffer(ipu, t->set.ic_chan,
- + IPU_INPUT_BUFFER, 0);
- + CHECK_RETCODE(ret < 0, "ipu_sel_buf ic_and_rot-ic-i",
- + STATE_SEL_BUF_FAIL, chan_buf, ret);
- + }
- + }
- +
- + if (need_split(t))
- + t->state = STATE_IN_PROGRESS;
- +
- + if (t->set.mode & VDOA_BAND_MODE) {
- + ret = vdoa_start(t->vdoa_handle, VDOA_DEF_TIMEOUT_MS);
- + CHECK_RETCODE(ret < 0, "vdoa_wait4complete, do_vdoa_band",
- + STATE_VDOA_IRQ_TIMEOUT, chan_rel, ret);
- + }
- +
- + CHECK_PERF(&t->ts_waitirq);
- + ret = wait_for_completion_timeout(&t->irq_comp,
- + msecs_to_jiffies(t->timeout - DEF_DELAY_MS));
- + CHECK_PERF(&t->ts_wakeup);
- + CHECK_RETCODE(ret == 0, "wait_for_comp_timeout",
- + STATE_IRQ_TIMEOUT, chan_rel, ret);
- + dev_dbg(t->dev, "[0x%p] no-0x%x ipu irq done!", t, t->task_no);
- +
- +chan_rel:
- +chan_buf:
- +chan_en:
- +chan_setup:
- + if (t->set.mode & VDOA_BAND_MODE)
- + vdoa_stop(t->vdoa_handle);
- + do_task_release(t, t->state >= STATE_ERR);
- + return;
- +}
- +
- +static void do_task_vdoa_vdi(struct ipu_task_entry *t)
- +{
- + int i;
- + int ret;
- + u32 stripe_width;
- +
- + /* FIXME: crop mode not support now */
- + stripe_width = t->input.width >> 1;
- + t->input.crop.pos.x = 0;
- + t->input.crop.pos.y = 0;
- + t->input.crop.w = stripe_width;
- + t->input.crop.h = t->input.height;
- + t->output.crop.w = stripe_width;
- + t->output.crop.h = t->input.height;
- +
- + for (i = 0; i < 2; i++) {
- + t->input.crop.pos.x = t->input.crop.pos.x + i * stripe_width;
- + t->output.crop.pos.x = t->output.crop.pos.x + i * stripe_width;
- + /* check input */
- + ret = set_crop(&t->input.crop, t->input.width, t->input.height,
- + t->input.format);
- + if (ret < 0) {
- + ret = STATE_ERR;
- + goto done;
- + } else
- + update_offset(t->input.format,
- + t->input.width, t->input.height,
- + t->input.crop.pos.x,
- + t->input.crop.pos.y,
- + &t->set.i_off, &t->set.i_uoff,
- + &t->set.i_voff, &t->set.istride);
- + dev_dbg(t->dev, "i_off:0x%x, i_uoff:0x%x, istride:%d.\n",
- + t->set.i_off, t->set.i_uoff, t->set.istride);
- + /* check output */
- + ret = set_crop(&t->output.crop, t->input.width,
- + t->output.height, t->output.format);
- + if (ret < 0) {
- + ret = STATE_ERR;
- + goto done;
- + } else
- + update_offset(t->output.format,
- + t->output.width, t->output.height,
- + t->output.crop.pos.x,
- + t->output.crop.pos.y,
- + &t->set.o_off, &t->set.o_uoff,
- + &t->set.o_voff, &t->set.ostride);
- +
- + dev_dbg(t->dev, "o_off:0x%x, o_uoff:0x%x, ostride:%d.\n",
- + t->set.o_off, t->set.o_uoff, t->set.ostride);
- +
- + do_task(t);
- + }
- +
- + return;
- +done:
- + dev_err(t->dev, "ERR %s set_crop.\n", __func__);
- + t->state = ret;
- + return;
- +}
- +
- +static void get_res_do_task(struct ipu_task_entry *t)
- +{
- + uint32_t found;
- + uint32_t split_child;
- + struct mutex *lock;
- +
- + found = get_vdoa_ipu_res(t);
- + if (!found) {
- + dev_err(t->dev, "ERR:[0x%p] no-0x%x can not get res\n",
- + t, t->task_no);
- + return;
- + } else {
- + if (t->set.task & VDOA_ONLY)
- + do_task_vdoa_only(t);
- + else if ((IPU_PIX_FMT_TILED_NV12F == t->input.format) &&
- + (t->set.mode & VDOA_BAND_MODE) &&
- + (t->input.crop.w > soc_max_vdi_in_width()))
- + do_task_vdoa_vdi(t);
- + else
- + do_task(t);
- + put_vdoa_ipu_res(t, 0);
- + }
- + if (t->state != STATE_OK) {
- + dev_err(t->dev, "ERR:[0x%p] no-0x%x state: %s\n",
- + t, t->task_no, state_msg[t->state].msg);
- + }
- +
- + split_child = need_split(t) && t->parent;
- + if (split_child) {
- + lock = &t->parent->split_lock;
- + mutex_lock(lock);
- + t->split_done = 1;
- + mutex_unlock(lock);
- + wake_up(&t->parent->split_waitq);
- + }
- +
- + return;
- +}
- +
- +static void wait_split_task_complete(struct ipu_task_entry *parent,
- + struct ipu_split_task *sp_task, uint32_t size)
- +{
- + struct ipu_task_entry *tsk = NULL;
- + int ret = 0, rc;
- + int j, idx = -1;
- + unsigned long flags;
- + struct mutex *lock = &parent->split_lock;
- + int k, busy_vf, busy_pp;
- + struct ipu_soc *ipu;
- + DECLARE_PERF_VAR;
- +
- + for (j = 0; j < size; j++) {
- + rc = wait_event_timeout(
- + parent->split_waitq,
- + sp_task_check_done(sp_task, parent, size, &idx),
- + msecs_to_jiffies(parent->timeout - DEF_DELAY_MS));
- + if (!rc) {
- + dev_err(parent->dev,
- + "ERR:[0x%p] no-0x%x, split_task timeout,j:%d,"
- + "size:%d.\n",
- + parent, parent->task_no, j, size);
- + ret = -ETIMEDOUT;
- + goto out;
- + } else {
- + if (idx < 0) {
- + dev_err(parent->dev,
- + "ERR:[0x%p] no-0x%x, invalid task idx:%d\n",
- + parent, parent->task_no, idx);
- + continue;
- + }
- + tsk = sp_task[idx].child_task;
- + mutex_lock(lock);
- + if (!tsk->split_done || !tsk->ipu)
- + dev_err(tsk->dev,
- + "ERR:no-0x%x,split not done:%d/null ipu:0x%p\n",
- + tsk->task_no, tsk->split_done, tsk->ipu);
- + tsk->split_done = 0;
- + mutex_unlock(lock);
- +
- + dev_dbg(tsk->dev,
- + "[0x%p] no-0x%x sp_tsk[%d] done,state:%d.\n",
- + tsk, tsk->task_no, idx, tsk->state);
- + #ifdef DBG_IPU_PERF
- + CHECK_PERF(&tsk->ts_rel);
- + PRINT_TASK_STATISTICS;
- + #endif
- + }
- + }
- +
- +out:
- + if (ret == -ETIMEDOUT) {
- + /* debug */
- + for (k = 0; k < max_ipu_no; k++) {
- + ipu = ipu_get_soc(k);
- + if (IS_ERR(ipu)) {
- + dev_err(parent->dev, "no:0x%x, null ipu:%d\n",
- + parent->task_no, k);
- + } else {
- + busy_vf = ic_vf_pp_is_busy(ipu, true);
- + busy_pp = ic_vf_pp_is_busy(ipu, false);
- + dev_err(parent->dev,
- + "ERR:ipu[%d] busy_vf:%d, busy_pp:%d.\n",
- + k, busy_vf, busy_pp);
- + }
- + }
- + for (k = 0; k < size; k++) {
- + tsk = sp_task[k].child_task;
- + if (!tsk)
- + continue;
- + dev_err(parent->dev,
- + "ERR: sp_task[%d][0x%p] no-0x%x done:%d,"
- + "state:%s,on_list:%d, ipu:0x%p,timeout!\n",
- + k, tsk, tsk->task_no, tsk->split_done,
- + state_msg[tsk->state].msg, tsk->task_in_list,
- + tsk->ipu);
- + }
- + }
- +
- + for (j = 0; j < size; j++) {
- + tsk = sp_task[j].child_task;
- + if (!tsk)
- + continue;
- + spin_lock_irqsave(&ipu_task_list_lock, flags);
- + if (tsk->task_in_list) {
- + list_del(&tsk->node);
- + tsk->task_in_list = 0;
- + dev_dbg(tsk->dev,
- + "[0x%p] no-0x%x,id:%d sp_tsk timeout list_del.\n",
- + tsk, tsk->task_no, tsk->task_id);
- + }
- + spin_unlock_irqrestore(&ipu_task_list_lock, flags);
- + if (!tsk->ipu)
- + continue;
- + if (tsk->state != STATE_OK) {
- + dev_err(tsk->dev,
- + "ERR:[0x%p] no-0x%x,id:%d, sp_tsk state: %s\n",
- + tsk, tsk->task_no, tsk->task_id,
- + state_msg[tsk->state].msg);
- + }
- + kref_put(&tsk->refcount, task_mem_free);
- + }
- +
- + kfree(parent->vditmpbuf[0]);
- + kfree(parent->vditmpbuf[1]);
- +
- + if (ret < 0)
- + parent->state = STATE_TIMEOUT;
- + else
- + parent->state = STATE_OK;
- + return;
- +}
- +
- +static inline int find_task(struct ipu_task_entry **t, int thread_id)
- +{
- + int found;
- + unsigned long flags;
- + struct ipu_task_entry *tsk;
- + struct list_head *task_list = &ipu_task_list;
- +
- + *t = NULL;
- + spin_lock_irqsave(&ipu_task_list_lock, flags);
- + found = !list_empty(task_list);
- + if (found) {
- + tsk = list_first_entry(task_list, struct ipu_task_entry, node);
- + if (tsk->task_in_list) {
- + list_del(&tsk->node);
- + tsk->task_in_list = 0;
- + *t = tsk;
- + kref_get(&tsk->refcount);
- + dev_dbg(tsk->dev,
- + "thread_id:%d,[0x%p] task_no:0x%x,mode:0x%x list_del\n",
- + thread_id, tsk, tsk->task_no, tsk->set.mode);
- + } else
- + dev_err(tsk->dev,
- + "thread_id:%d,task_no:0x%x,mode:0x%x not on list_del\n",
- + thread_id, tsk->task_no, tsk->set.mode);
- + }
- + spin_unlock_irqrestore(&ipu_task_list_lock, flags);
- +
- + return found;
- +}
- +
- +static int ipu_task_thread(void *argv)
- +{
- + struct ipu_task_entry *tsk;
- + struct ipu_task_entry *sp_tsk0;
- + struct ipu_split_task sp_task[4];
- + /* priority lower than irq_thread */
- + const struct sched_param param = {
- + .sched_priority = MAX_USER_RT_PRIO/2 - 1,
- + };
- + int ret;
- + int curr_thread_id;
- + uint32_t size;
- + unsigned long flags;
- + unsigned int cpu;
- + struct cpumask cpu_mask;
- + struct ipu_thread_data *data = (struct ipu_thread_data *)argv;
- +
- + thread_id++;
- + curr_thread_id = thread_id;
- + sched_setscheduler(current, SCHED_FIFO, ¶m);
- +
- + if (!data->is_vdoa) {
- + cpu = cpumask_first(cpu_online_mask);
- + cpumask_set_cpu(cpu, &cpu_mask);
- + ret = sched_setaffinity(data->ipu->thread[data->id]->pid,
- + &cpu_mask);
- + if (ret < 0) {
- + pr_err("%s: sched_setaffinity fail:%d.\n", __func__, ret);
- + }
- + pr_debug("%s: sched_setaffinity cpu:%d.\n", __func__, cpu);
- + }
- +
- + while (!kthread_should_stop()) {
- + int split_fail = 0;
- + int split_parent;
- + int split_child;
- +
- + wait_event_interruptible(thread_waitq, find_task(&tsk, curr_thread_id));
- +
- + if (!tsk) {
- + pr_err("thread:%d can not find task.\n",
- + curr_thread_id);
- + continue;
- + }
- +
- + /* note: other threads run split child task */
- + split_parent = need_split(tsk) && !tsk->parent;
- + split_child = need_split(tsk) && tsk->parent;
- + if (split_parent) {
- + if ((tsk->set.split_mode == RL_SPLIT) ||
- + (tsk->set.split_mode == UD_SPLIT))
- + size = 2;
- + else
- + size = 4;
- + ret = queue_split_task(tsk, sp_task, size);
- + if (ret < 0) {
- + split_fail = 1;
- + } else {
- + struct list_head *pos;
- +
- + spin_lock_irqsave(&ipu_task_list_lock, flags);
- +
- + sp_tsk0 = list_first_entry(&tsk->split_list,
- + struct ipu_task_entry, node);
- + list_del(&sp_tsk0->node);
- +
- + list_for_each(pos, &tsk->split_list) {
- + struct ipu_task_entry *tmp;
- +
- + tmp = list_entry(pos,
- + struct ipu_task_entry, node);
- + tmp->task_in_list = 1;
- + dev_dbg(tmp->dev,
- + "[0x%p] no-0x%x,id:%d sp_tsk "
- + "add_to_list.\n", tmp,
- + tmp->task_no, tmp->task_id);
- + }
- + /* add to global list */
- + list_splice(&tsk->split_list, &ipu_task_list);
- +
- + spin_unlock_irqrestore(&ipu_task_list_lock,
- + flags);
- + /* let the parent thread do the first sp_task */
- + /* FIXME: ensure the correct sequence for split
- + 4size: 5/6->9/a*/
- + if (!sp_tsk0)
- + dev_err(tsk->dev,
- + "ERR: no-0x%x,can not get split_tsk0\n",
- + tsk->task_no);
- + wake_up_interruptible(&thread_waitq);
- + get_res_do_task(sp_tsk0);
- + dev_dbg(sp_tsk0->dev,
- + "thread:%d complete tsk no:0x%x.\n",
- + curr_thread_id, sp_tsk0->task_no);
- + ret = atomic_read(&req_cnt);
- + if (ret > 0) {
- + wake_up(&res_waitq);
- + dev_dbg(sp_tsk0->dev,
- + "sp_tsk0 sche thread:%d no:0x%x,"
- + "req_cnt:%d\n", curr_thread_id,
- + sp_tsk0->task_no, ret);
- + /* For other threads to get_res */
- + schedule();
- + }
- + }
- + } else
- + get_res_do_task(tsk);
- +
- + /* wait for all 4 sp_task finished here or timeout
- + and then release all resources */
- + if (split_parent && !split_fail)
- + wait_split_task_complete(tsk, sp_task, size);
- +
- + if (!split_child) {
- + atomic_inc(&tsk->done);
- + wake_up(&tsk->task_waitq);
- + }
- +
- + dev_dbg(tsk->dev, "thread:%d complete tsk no:0x%x-[0x%p].\n",
- + curr_thread_id, tsk->task_no, tsk);
- + ret = atomic_read(&req_cnt);
- + if (ret > 0) {
- + wake_up(&res_waitq);
- + dev_dbg(tsk->dev, "sche thread:%d no:0x%x,req_cnt:%d\n",
- + curr_thread_id, tsk->task_no, ret);
- + /* note: give cpu to other threads to get_res */
- + schedule();
- + }
- +
- + kref_put(&tsk->refcount, task_mem_free);
- + }
- +
- + pr_info("ERR %s exit.\n", __func__);
- + return 0;
- +}
- +
- +int ipu_check_task(struct ipu_task *task)
- +{
- + struct ipu_task_entry *tsk;
- + int ret = 0;
- +
- + tsk = create_task_entry(task);
- + if (IS_ERR(tsk))
- + return PTR_ERR(tsk);
- +
- + ret = check_task(tsk);
- +
- + task->input = tsk->input;
- + task->output = tsk->output;
- + task->overlay = tsk->overlay;
- + dump_task_info(tsk);
- +
- + kref_put(&tsk->refcount, task_mem_free);
- + if (ret != 0)
- + pr_debug("%s ret:%d.\n", __func__, ret);
- + return ret;
- +}
- +EXPORT_SYMBOL_GPL(ipu_check_task);
- +
- +int ipu_queue_task(struct ipu_task *task)
- +{
- + struct ipu_task_entry *tsk;
- + unsigned long flags;
- + int ret;
- + u32 tmp_task_no;
- + DECLARE_PERF_VAR;
- +
- + tsk = create_task_entry(task);
- + if (IS_ERR(tsk))
- + return PTR_ERR(tsk);
- +
- + CHECK_PERF(&tsk->ts_queue);
- + ret = prepare_task(tsk);
- + if (ret < 0)
- + goto done;
- +
- + if (need_split(tsk)) {
- + CHECK_PERF(&tsk->ts_dotask);
- + CHECK_PERF(&tsk->ts_waitirq);
- + CHECK_PERF(&tsk->ts_inirq);
- + CHECK_PERF(&tsk->ts_wakeup);
- + }
- +
- + /* task_no last four bits for split task type*/
- + tmp_task_no = atomic_inc_return(&frame_no);
- + tsk->task_no = tmp_task_no << 4;
- + init_waitqueue_head(&tsk->task_waitq);
- +
- + spin_lock_irqsave(&ipu_task_list_lock, flags);
- + list_add_tail(&tsk->node, &ipu_task_list);
- + tsk->task_in_list = 1;
- + dev_dbg(tsk->dev, "[0x%p,no-0x%x] list_add_tail\n", tsk, tsk->task_no);
- + spin_unlock_irqrestore(&ipu_task_list_lock, flags);
- + wake_up_interruptible(&thread_waitq);
- +
- + ret = wait_event_timeout(tsk->task_waitq, atomic_read(&tsk->done),
- + msecs_to_jiffies(tsk->timeout));
- + if (0 == ret) {
- + /* note: the timeout should larger than the internal timeout!*/
- + ret = -ETIMEDOUT;
- + dev_err(tsk->dev, "ERR: [0x%p] no-0x%x, timeout:%dms!\n",
- + tsk, tsk->task_no, tsk->timeout);
- + } else {
- + if (STATE_OK != tsk->state) {
- + dev_err(tsk->dev, "ERR: [0x%p] no-0x%x,state %d: %s\n",
- + tsk, tsk->task_no, tsk->state,
- + state_msg[tsk->state].msg);
- + ret = -ECANCELED;
- + } else
- + ret = 0;
- + }
- +
- + spin_lock_irqsave(&ipu_task_list_lock, flags);
- + if (tsk->task_in_list) {
- + list_del(&tsk->node);
- + tsk->task_in_list = 0;
- + dev_dbg(tsk->dev, "[0x%p] no:0x%x list_del\n",
- + tsk, tsk->task_no);
- + }
- + spin_unlock_irqrestore(&ipu_task_list_lock, flags);
- +
- +#ifdef DBG_IPU_PERF
- + CHECK_PERF(&tsk->ts_rel);
- + PRINT_TASK_STATISTICS;
- + if (ts_frame_avg == 0)
- + ts_frame_avg = ts_frame.tv_nsec / NSEC_PER_USEC +
- + ts_frame.tv_sec * USEC_PER_SEC;
- + else
- + ts_frame_avg = (ts_frame_avg + ts_frame.tv_nsec / NSEC_PER_USEC
- + + ts_frame.tv_sec * USEC_PER_SEC)/2;
- + if (timespec_compare(&ts_frame, &ts_frame_max) > 0)
- + ts_frame_max = ts_frame;
- +
- + atomic_inc(&frame_cnt);
- +
- + if ((atomic_read(&frame_cnt) % 1000) == 0)
- + pr_debug("ipu_dev: max frame time:%ldus, avg frame time:%dus,"
- + "frame_cnt:%d\n", ts_frame_max.tv_nsec / NSEC_PER_USEC
- + + ts_frame_max.tv_sec * USEC_PER_SEC,
- + ts_frame_avg, atomic_read(&frame_cnt));
- +#endif
- +done:
- + if (ret < 0)
- + dev_err(tsk->dev, "ERR: no-0x%x,ipu_queue_task err:%d\n",
- + tsk->task_no, ret);
- +
- + kref_put(&tsk->refcount, task_mem_free);
- +
- + return ret;
- +}
- +EXPORT_SYMBOL_GPL(ipu_queue_task);
- +
- +static int mxc_ipu_open(struct inode *inode, struct file *file)
- +{
- + file->private_data = (void *)atomic_inc_return(&file_index);
- + return 0;
- +}
- +
- +static long mxc_ipu_ioctl(struct file *file,
- + unsigned int cmd, unsigned long arg)
- +{
- + int __user *argp = (void __user *)arg;
- + int ret = 0;
- +
- + switch (cmd) {
- + case IPU_CHECK_TASK:
- + {
- + struct ipu_task task;
- +
- + if (copy_from_user
- + (&task, (struct ipu_task *) arg,
- + sizeof(struct ipu_task)))
- + return -EFAULT;
- + ret = ipu_check_task(&task);
- + if (copy_to_user((struct ipu_task *) arg,
- + &task, sizeof(struct ipu_task)))
- + return -EFAULT;
- + break;
- + }
- + case IPU_QUEUE_TASK:
- + {
- + struct ipu_task task;
- +
- + if (copy_from_user
- + (&task, (struct ipu_task *) arg,
- + sizeof(struct ipu_task)))
- + return -EFAULT;
- + ret = ipu_queue_task(&task);
- + break;
- + }
- + case IPU_ALLOC:
- + {
- + int size;
- + struct ipu_alloc_list *mem;
- +
- + mem = kzalloc(sizeof(*mem), GFP_KERNEL);
- + if (mem == NULL)
- + return -ENOMEM;
- +
- + if (get_user(size, argp))
- + return -EFAULT;
- +
- + mem->size = PAGE_ALIGN(size);
- +
- + mem->cpu_addr = dma_alloc_coherent(ipu_dev, size,
- + &mem->phy_addr,
- + GFP_DMA | GFP_KERNEL);
- + if (mem->cpu_addr == NULL) {
- + kfree(mem);
- + return -ENOMEM;
- + }
- + mem->file_index = file->private_data;
- + mutex_lock(&ipu_alloc_lock);
- + list_add(&mem->list, &ipu_alloc_list);
- + mutex_unlock(&ipu_alloc_lock);
- +
- + dev_dbg(ipu_dev, "allocated %d bytes @ 0x%08X\n",
- + mem->size, mem->phy_addr);
- +
- + if (put_user(mem->phy_addr, argp))
- + return -EFAULT;
- +
- + break;
- + }
- + case IPU_FREE:
- + {
- + unsigned long offset;
- + struct ipu_alloc_list *mem;
- +
- + if (get_user(offset, argp))
- + return -EFAULT;
- +
- + ret = -EINVAL;
- + mutex_lock(&ipu_alloc_lock);
- + list_for_each_entry(mem, &ipu_alloc_list, list) {
- + if (mem->phy_addr == offset) {
- + list_del(&mem->list);
- + dma_free_coherent(ipu_dev,
- + mem->size,
- + mem->cpu_addr,
- + mem->phy_addr);
- + kfree(mem);
- + ret = 0;
- + break;
- + }
- + }
- + mutex_unlock(&ipu_alloc_lock);
- + if (0 == ret)
- + dev_dbg(ipu_dev, "free %d bytes @ 0x%08X\n",
- + mem->size, mem->phy_addr);
- +
- + break;
- + }
- + default:
- + break;
- + }
- + return ret;
- +}
- +
- +static int mxc_ipu_mmap(struct file *file, struct vm_area_struct *vma)
- +{
- + bool found = false;
- + u32 len;
- + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
- + struct ipu_alloc_list *mem;
- +
- + mutex_lock(&ipu_alloc_lock);
- + list_for_each_entry(mem, &ipu_alloc_list, list) {
- + if (offset == mem->phy_addr) {
- + found = true;
- + len = mem->size;
- + break;
- + }
- + }
- + mutex_unlock(&ipu_alloc_lock);
- + if (!found)
- + return -EINVAL;
- +
- + if (vma->vm_end - vma->vm_start > len)
- + return -EINVAL;
- +
- + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- +
- + if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- + vma->vm_end - vma->vm_start,
- + vma->vm_page_prot)) {
- + printk(KERN_ERR
- + "mmap failed!\n");
- + return -ENOBUFS;
- + }
- + return 0;
- +}
- +
- +static int mxc_ipu_release(struct inode *inode, struct file *file)
- +{
- + struct ipu_alloc_list *mem;
- + struct ipu_alloc_list *n;
- +
- + mutex_lock(&ipu_alloc_lock);
- + list_for_each_entry_safe(mem, n, &ipu_alloc_list, list) {
- + if ((mem->cpu_addr != 0) &&
- + (file->private_data == mem->file_index)) {
- + list_del(&mem->list);
- + dma_free_coherent(ipu_dev,
- + mem->size,
- + mem->cpu_addr,
- + mem->phy_addr);
- + dev_dbg(ipu_dev, "rel-free %d bytes @ 0x%08X\n",
- + mem->size, mem->phy_addr);
- + kfree(mem);
- + }
- + }
- + mutex_unlock(&ipu_alloc_lock);
- + atomic_dec(&file_index);
- +
- + return 0;
- +}
- +
- +static struct file_operations mxc_ipu_fops = {
- + .owner = THIS_MODULE,
- + .open = mxc_ipu_open,
- + .mmap = mxc_ipu_mmap,
- + .release = mxc_ipu_release,
- + .unlocked_ioctl = mxc_ipu_ioctl,
- +};
- +
- +int register_ipu_device(struct ipu_soc *ipu, int id)
- +{
- + int ret = 0;
- + static int idx;
- + static struct ipu_thread_data thread_data[5];
- +
- + if (!major) {
- + major = register_chrdev(0, "mxc_ipu", &mxc_ipu_fops);
- + if (major < 0) {
- + printk(KERN_ERR "Unable to register mxc_ipu as a char device\n");
- + ret = major;
- + goto register_cdev_fail;
- + }
- +
- + ipu_class = class_create(THIS_MODULE, "mxc_ipu");
- + if (IS_ERR(ipu_class)) {
- + ret = PTR_ERR(ipu_class);
- + goto ipu_class_fail;
- + }
- +
- + ipu_dev = device_create(ipu_class, NULL, MKDEV(major, 0),
- + NULL, "mxc_ipu");
- + if (IS_ERR(ipu_dev)) {
- + ret = PTR_ERR(ipu_dev);
- + goto dev_create_fail;
- + }
- + ipu_dev->dma_mask = kmalloc(sizeof(*ipu_dev->dma_mask), GFP_KERNEL);
- + *ipu_dev->dma_mask = DMA_BIT_MASK(32);
- + ipu_dev->coherent_dma_mask = DMA_BIT_MASK(32);
- +
- + mutex_init(&ipu_ch_tbl.lock);
- + }
- + max_ipu_no = ++id;
- + ipu->rot_dma[0].size = 0;
- + ipu->rot_dma[1].size = 0;
- +
- + thread_data[idx].ipu = ipu;
- + thread_data[idx].id = 0;
- + thread_data[idx].is_vdoa = 0;
- + ipu->thread[0] = kthread_run(ipu_task_thread, &thread_data[idx++],
- + "ipu%d_task", id);
- + if (IS_ERR(ipu->thread[0])) {
- + ret = PTR_ERR(ipu->thread[0]);
- + goto kthread0_fail;
- + }
- +
- + thread_data[idx].ipu = ipu;
- + thread_data[idx].id = 1;
- + thread_data[idx].is_vdoa = 0;
- + ipu->thread[1] = kthread_run(ipu_task_thread, &thread_data[idx++],
- + "ipu%d_task", id);
- + if (IS_ERR(ipu->thread[1])) {
- + ret = PTR_ERR(ipu->thread[1]);
- + goto kthread1_fail;
- + }
- +
- +
- + return ret;
- +
- +kthread1_fail:
- + kthread_stop(ipu->thread[0]);
- +kthread0_fail:
- + if (id == 0)
- + device_destroy(ipu_class, MKDEV(major, 0));
- +dev_create_fail:
- + if (id == 0) {
- + class_destroy(ipu_class);
- + }
- +ipu_class_fail:
- + if (id == 0)
- + unregister_chrdev(major, "mxc_ipu");
- +register_cdev_fail:
- + return ret;
- +}
- +
- +void unregister_ipu_device(struct ipu_soc *ipu, int id)
- +{
- + int i;
- +
- + kthread_stop(ipu->thread[0]);
- + kthread_stop(ipu->thread[1]);
- + for (i = 0; i < 2; i++) {
- + if (ipu->rot_dma[i].vaddr)
- + dma_free_coherent(ipu_dev,
- + ipu->rot_dma[i].size,
- + ipu->rot_dma[i].vaddr,
- + ipu->rot_dma[i].paddr);
- + }
- +
- + if (major) {
- + device_destroy(ipu_class, MKDEV(major, 0));
- + class_destroy(ipu_class);
- + unregister_chrdev(major, "mxc_ipu");
- + major = 0;
- + }
- +}
- diff -Nur linux-3.14.35.orig/drivers/mxc/ipu3/ipu_disp.c linux-3.14.35/drivers/mxc/ipu3/ipu_disp.c
- --- linux-3.14.35.orig/drivers/mxc/ipu3/ipu_disp.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/ipu3/ipu_disp.c 2015-03-08 14:27:37.661684500 -0500
- @@ -0,0 +1,1962 @@
- +/*
- + * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file ipu_disp.c
- + *
- + * @brief IPU display submodule API functions
- + *
- + * @ingroup IPU
- + */
- +
- +#include <linux/clk.h>
- +#include <linux/clk-provider.h>
- +#include <linux/delay.h>
- +#include <linux/err.h>
- +#include <linux/errno.h>
- +#include <linux/io.h>
- +#include <linux/ipu-v3.h>
- +#include <linux/module.h>
- +#include <linux/spinlock.h>
- +#include <linux/types.h>
- +
- +#include <asm/atomic.h>
- +
- +#include "ipu_param_mem.h"
- +#include "ipu_regs.h"
- +
- +struct dp_csc_param_t {
- + int mode;
- + void *coeff;
- +};
- +
- +#define SYNC_WAVE 0
- +#define NULL_WAVE (-1)
- +#define ASYNC_SER_WAVE 6
- +
- +/* DC display ID assignments */
- +#define DC_DISP_ID_SYNC(di) (di)
- +#define DC_DISP_ID_SERIAL 2
- +#define DC_DISP_ID_ASYNC 3
- +
- +int dmfc_type_setup;
- +
- +void _ipu_dmfc_init(struct ipu_soc *ipu, int dmfc_type, int first)
- +{
- + u32 dmfc_wr_chan, dmfc_dp_chan;
- +
- + if (first) {
- + if (dmfc_type_setup > dmfc_type)
- + dmfc_type = dmfc_type_setup;
- + else
- + dmfc_type_setup = dmfc_type;
- +
- + /* disable DMFC-IC channel*/
- + ipu_dmfc_write(ipu, 0x2, DMFC_IC_CTRL);
- + } else if (dmfc_type_setup >= DMFC_HIGH_RESOLUTION_DC) {
- + dev_dbg(ipu->dev, "DMFC high resolution has set, will not change\n");
- + return;
- + } else
- + dmfc_type_setup = dmfc_type;
- +
- + if (dmfc_type == DMFC_HIGH_RESOLUTION_DC) {
- + /* 1 - segment 0~3;
- + * 5B - segement 4, 5;
- + * 5F - segement 6, 7;
- + * 1C, 2C and 6B, 6F unused;
- + */
- + dev_info(ipu->dev, "IPU DMFC DC HIGH RESOLUTION: 1(0~3), 5B(4,5), 5F(6,7)\n");
- + dmfc_wr_chan = 0x00000088;
- + dmfc_dp_chan = 0x00009694;
- + ipu->dmfc_size_28 = 256*4;
- + ipu->dmfc_size_29 = 0;
- + ipu->dmfc_size_24 = 0;
- + ipu->dmfc_size_27 = 128*4;
- + ipu->dmfc_size_23 = 128*4;
- + } else if (dmfc_type == DMFC_HIGH_RESOLUTION_DP) {
- + /* 1 - segment 0, 1;
- + * 5B - segement 2~5;
- + * 5F - segement 6,7;
- + * 1C, 2C and 6B, 6F unused;
- + */
- + dev_info(ipu->dev, "IPU DMFC DP HIGH RESOLUTION: 1(0,1), 5B(2~5), 5F(6,7)\n");
- + dmfc_wr_chan = 0x00000090;
- + dmfc_dp_chan = 0x0000968a;
- + ipu->dmfc_size_28 = 128*4;
- + ipu->dmfc_size_29 = 0;
- + ipu->dmfc_size_24 = 0;
- + ipu->dmfc_size_27 = 128*4;
- + ipu->dmfc_size_23 = 256*4;
- + } else if (dmfc_type == DMFC_HIGH_RESOLUTION_ONLY_DP) {
- + /* 5B - segement 0~3;
- + * 5F - segement 4~7;
- + * 1, 1C, 2C and 6B, 6F unused;
- + */
- + dev_info(ipu->dev, "IPU DMFC ONLY-DP HIGH RESOLUTION: 5B(0~3), 5F(4~7)\n");
- + dmfc_wr_chan = 0x00000000;
- + dmfc_dp_chan = 0x00008c88;
- + ipu->dmfc_size_28 = 0;
- + ipu->dmfc_size_29 = 0;
- + ipu->dmfc_size_24 = 0;
- + ipu->dmfc_size_27 = 256*4;
- + ipu->dmfc_size_23 = 256*4;
- + } else {
- + /* 1 - segment 0, 1;
- + * 5B - segement 4, 5;
- + * 5F - segement 6, 7;
- + * 1C, 2C and 6B, 6F unused;
- + */
- + dev_info(ipu->dev, "IPU DMFC NORMAL mode: 1(0~1), 5B(4,5), 5F(6,7)\n");
- + dmfc_wr_chan = 0x00000090;
- + dmfc_dp_chan = 0x00009694;
- + ipu->dmfc_size_28 = 128*4;
- + ipu->dmfc_size_29 = 0;
- + ipu->dmfc_size_24 = 0;
- + ipu->dmfc_size_27 = 128*4;
- + ipu->dmfc_size_23 = 128*4;
- + }
- + ipu_dmfc_write(ipu, dmfc_wr_chan, DMFC_WR_CHAN);
- + ipu_dmfc_write(ipu, 0x202020F6, DMFC_WR_CHAN_DEF);
- + ipu_dmfc_write(ipu, dmfc_dp_chan, DMFC_DP_CHAN);
- + /* Enable chan 5 watermark set at 5 bursts and clear at 7 bursts */
- + ipu_dmfc_write(ipu, 0x2020F6F6, DMFC_DP_CHAN_DEF);
- +}
- +
- +static int __init dmfc_setup(char *options)
- +{
- + get_option(&options, &dmfc_type_setup);
- + if (dmfc_type_setup > DMFC_HIGH_RESOLUTION_ONLY_DP)
- + dmfc_type_setup = DMFC_HIGH_RESOLUTION_ONLY_DP;
- + return 1;
- +}
- +__setup("dmfc=", dmfc_setup);
- +
- +void _ipu_dmfc_set_wait4eot(struct ipu_soc *ipu, int dma_chan, int width)
- +{
- + u32 dmfc_gen1 = ipu_dmfc_read(ipu, DMFC_GENERAL1);
- +
- + if (width >= HIGH_RESOLUTION_WIDTH) {
- + if (dma_chan == 23)
- + _ipu_dmfc_init(ipu, DMFC_HIGH_RESOLUTION_DP, 0);
- + else if (dma_chan == 28)
- + _ipu_dmfc_init(ipu, DMFC_HIGH_RESOLUTION_DC, 0);
- + }
- +
- + if (dma_chan == 23) { /*5B*/
- + if (ipu->dmfc_size_23/width > 3)
- + dmfc_gen1 |= 1UL << 20;
- + else
- + dmfc_gen1 &= ~(1UL << 20);
- + } else if (dma_chan == 24) { /*6B*/
- + if (ipu->dmfc_size_24/width > 1)
- + dmfc_gen1 |= 1UL << 22;
- + else
- + dmfc_gen1 &= ~(1UL << 22);
- + } else if (dma_chan == 27) { /*5F*/
- + if (ipu->dmfc_size_27/width > 2)
- + dmfc_gen1 |= 1UL << 21;
- + else
- + dmfc_gen1 &= ~(1UL << 21);
- + } else if (dma_chan == 28) { /*1*/
- + if (ipu->dmfc_size_28/width > 2)
- + dmfc_gen1 |= 1UL << 16;
- + else
- + dmfc_gen1 &= ~(1UL << 16);
- + } else if (dma_chan == 29) { /*6F*/
- + if (ipu->dmfc_size_29/width > 1)
- + dmfc_gen1 |= 1UL << 23;
- + else
- + dmfc_gen1 &= ~(1UL << 23);
- + }
- +
- + ipu_dmfc_write(ipu, dmfc_gen1, DMFC_GENERAL1);
- +}
- +
- +void _ipu_dmfc_set_burst_size(struct ipu_soc *ipu, int dma_chan, int burst_size)
- +{
- + u32 dmfc_wr_chan = ipu_dmfc_read(ipu, DMFC_WR_CHAN);
- + u32 dmfc_dp_chan = ipu_dmfc_read(ipu, DMFC_DP_CHAN);
- + int dmfc_bs = 0;
- +
- + switch (burst_size) {
- + case 64:
- + dmfc_bs = 0x40;
- + break;
- + case 32:
- + case 20:
- + dmfc_bs = 0x80;
- + break;
- + case 16:
- + dmfc_bs = 0xc0;
- + break;
- + default:
- + dev_err(ipu->dev, "Unsupported burst size %d\n",
- + burst_size);
- + return;
- + }
- +
- + if (dma_chan == 23) { /*5B*/
- + dmfc_dp_chan &= ~(0xc0);
- + dmfc_dp_chan |= dmfc_bs;
- + } else if (dma_chan == 27) { /*5F*/
- + dmfc_dp_chan &= ~(0xc000);
- + dmfc_dp_chan |= (dmfc_bs << 8);
- + } else if (dma_chan == 28) { /*1*/
- + dmfc_wr_chan &= ~(0xc0);
- + dmfc_wr_chan |= dmfc_bs;
- + }
- +
- + ipu_dmfc_write(ipu, dmfc_wr_chan, DMFC_WR_CHAN);
- + ipu_dmfc_write(ipu, dmfc_dp_chan, DMFC_DP_CHAN);
- +}
- +
- +static void _ipu_di_data_wave_config(struct ipu_soc *ipu,
- + int di, int wave_gen,
- + int access_size, int component_size)
- +{
- + u32 reg;
- + reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) |
- + (component_size << DI_DW_GEN_COMPONENT_SIZE_OFFSET);
- + ipu_di_write(ipu, di, reg, DI_DW_GEN(wave_gen));
- +}
- +
- +static void _ipu_di_data_pin_config(struct ipu_soc *ipu,
- + int di, int wave_gen, int di_pin, int set,
- + int up, int down)
- +{
- + u32 reg;
- +
- + reg = ipu_di_read(ipu, di, DI_DW_GEN(wave_gen));
- + reg &= ~(0x3 << (di_pin * 2));
- + reg |= set << (di_pin * 2);
- + ipu_di_write(ipu, di, reg, DI_DW_GEN(wave_gen));
- +
- + ipu_di_write(ipu, di, (down << 16) | up, DI_DW_SET(wave_gen, set));
- +}
- +
- +static void _ipu_di_sync_config(struct ipu_soc *ipu,
- + int di, int wave_gen,
- + int run_count, int run_src,
- + int offset_count, int offset_src,
- + int repeat_count, int cnt_clr_src,
- + int cnt_polarity_gen_en,
- + int cnt_polarity_clr_src,
- + int cnt_polarity_trigger_src,
- + int cnt_up, int cnt_down)
- +{
- + u32 reg;
- +
- + if ((run_count >= 0x1000) || (offset_count >= 0x1000) || (repeat_count >= 0x1000) ||
- + (cnt_up >= 0x400) || (cnt_down >= 0x400)) {
- + dev_err(ipu->dev, "DI%d counters out of range.\n", di);
- + return;
- + }
- +
- + reg = (run_count << 19) | (++run_src << 16) |
- + (offset_count << 3) | ++offset_src;
- + ipu_di_write(ipu, di, reg, DI_SW_GEN0(wave_gen));
- + reg = (cnt_polarity_gen_en << 29) | (++cnt_clr_src << 25) |
- + (++cnt_polarity_trigger_src << 12) | (++cnt_polarity_clr_src << 9);
- + reg |= (cnt_down << 16) | cnt_up;
- + if (repeat_count == 0) {
- + /* Enable auto reload */
- + reg |= 0x10000000;
- + }
- + ipu_di_write(ipu, di, reg, DI_SW_GEN1(wave_gen));
- + reg = ipu_di_read(ipu, di, DI_STP_REP(wave_gen));
- + reg &= ~(0xFFFF << (16 * ((wave_gen - 1) & 0x1)));
- + reg |= repeat_count << (16 * ((wave_gen - 1) & 0x1));
- + ipu_di_write(ipu, di, reg, DI_STP_REP(wave_gen));
- +}
- +
- +static void _ipu_dc_map_link(struct ipu_soc *ipu,
- + int current_map,
- + int base_map_0, int buf_num_0,
- + int base_map_1, int buf_num_1,
- + int base_map_2, int buf_num_2)
- +{
- + int ptr_0 = base_map_0 * 3 + buf_num_0;
- + int ptr_1 = base_map_1 * 3 + buf_num_1;
- + int ptr_2 = base_map_2 * 3 + buf_num_2;
- + int ptr;
- + u32 reg;
- + ptr = (ptr_2 << 10) + (ptr_1 << 5) + ptr_0;
- +
- + reg = ipu_dc_read(ipu, DC_MAP_CONF_PTR(current_map));
- + reg &= ~(0x1F << ((16 * (current_map & 0x1))));
- + reg |= ptr << ((16 * (current_map & 0x1)));
- + ipu_dc_write(ipu, reg, DC_MAP_CONF_PTR(current_map));
- +}
- +
- +static void _ipu_dc_map_config(struct ipu_soc *ipu,
- + int map, int byte_num, int offset, int mask)
- +{
- + int ptr = map * 3 + byte_num;
- + u32 reg;
- +
- + reg = ipu_dc_read(ipu, DC_MAP_CONF_VAL(ptr));
- + reg &= ~(0xFFFF << (16 * (ptr & 0x1)));
- + reg |= ((offset << 8) | mask) << (16 * (ptr & 0x1));
- + ipu_dc_write(ipu, reg, DC_MAP_CONF_VAL(ptr));
- +
- + reg = ipu_dc_read(ipu, DC_MAP_CONF_PTR(map));
- + reg &= ~(0x1F << ((16 * (map & 0x1)) + (5 * byte_num)));
- + reg |= ptr << ((16 * (map & 0x1)) + (5 * byte_num));
- + ipu_dc_write(ipu, reg, DC_MAP_CONF_PTR(map));
- +}
- +
- +static void _ipu_dc_map_clear(struct ipu_soc *ipu, int map)
- +{
- + u32 reg = ipu_dc_read(ipu, DC_MAP_CONF_PTR(map));
- + ipu_dc_write(ipu, reg & ~(0xFFFF << (16 * (map & 0x1))),
- + DC_MAP_CONF_PTR(map));
- +}
- +
- +static void _ipu_dc_write_tmpl(struct ipu_soc *ipu,
- + int word, u32 opcode, u32 operand, int map,
- + int wave, int glue, int sync, int stop)
- +{
- + u32 reg;
- +
- + if (opcode == WRG) {
- + reg = sync;
- + reg |= (glue << 4);
- + reg |= (++wave << 11);
- + reg |= ((operand & 0x1FFFF) << 15);
- + ipu_dc_tmpl_write(ipu, reg, word * 8);
- +
- + reg = (operand >> 17);
- + reg |= opcode << 7;
- + reg |= (stop << 9);
- + ipu_dc_tmpl_write(ipu, reg, word * 8 + 4);
- + } else {
- + reg = sync;
- + reg |= (glue << 4);
- + reg |= (++wave << 11);
- + reg |= (++map << 15);
- + reg |= (operand << 20) & 0xFFF00000;
- + ipu_dc_tmpl_write(ipu, reg, word * 8);
- +
- + reg = (operand >> 12);
- + reg |= opcode << 4;
- + reg |= (stop << 9);
- + ipu_dc_tmpl_write(ipu, reg, word * 8 + 4);
- + }
- +}
- +
- +static void _ipu_dc_link_event(struct ipu_soc *ipu,
- + int chan, int event, int addr, int priority)
- +{
- + u32 reg;
- + u32 address_shift;
- + if (event < DC_EVEN_UGDE0) {
- + reg = ipu_dc_read(ipu, DC_RL_CH(chan, event));
- + reg &= ~(0xFFFF << (16 * (event & 0x1)));
- + reg |= ((addr << 8) | priority) << (16 * (event & 0x1));
- + ipu_dc_write(ipu, reg, DC_RL_CH(chan, event));
- + } else {
- + reg = ipu_dc_read(ipu, DC_UGDE_0((event - DC_EVEN_UGDE0) / 2));
- + if ((event - DC_EVEN_UGDE0) & 0x1) {
- + reg &= ~(0x2FF << 16);
- + reg |= (addr << 16);
- + reg |= priority ? (2 << 24) : 0x0;
- + } else {
- + reg &= ~0xFC00FFFF;
- + if (priority)
- + chan = (chan >> 1) +
- + ((((chan & 0x1) + ((chan & 0x2) >> 1))) | (chan >> 3));
- + else
- + chan = 0x7;
- + address_shift = ((event - DC_EVEN_UGDE0) >> 1) ? 7 : 8;
- + reg |= (addr << address_shift) | (priority << 3) | chan;
- + }
- + ipu_dc_write(ipu, reg, DC_UGDE_0((event - DC_EVEN_UGDE0) / 2));
- + }
- +}
- +
- +/* Y = R * 1.200 + G * 2.343 + B * .453 + 0.250;
- + U = R * -.672 + G * -1.328 + B * 2.000 + 512.250.;
- + V = R * 2.000 + G * -1.672 + B * -.328 + 512.250.;*/
- +static const int rgb2ycbcr_coeff[5][3] = {
- + {0x4D, 0x96, 0x1D},
- + {-0x2B, -0x55, 0x80},
- + {0x80, -0x6B, -0x15},
- + {0x0000, 0x0200, 0x0200}, /* B0, B1, B2 */
- + {0x2, 0x2, 0x2}, /* S0, S1, S2 */
- +};
- +
- +/* R = (1.164 * (Y - 16)) + (1.596 * (Cr - 128));
- + G = (1.164 * (Y - 16)) - (0.392 * (Cb - 128)) - (0.813 * (Cr - 128));
- + B = (1.164 * (Y - 16)) + (2.017 * (Cb - 128); */
- +static const int ycbcr2rgb_coeff[5][3] = {
- + {0x095, 0x000, 0x0CC},
- + {0x095, 0x3CE, 0x398},
- + {0x095, 0x0FF, 0x000},
- + {0x3E42, 0x010A, 0x3DD6}, /*B0,B1,B2 */
- + {0x1, 0x1, 0x1}, /*S0,S1,S2 */
- +};
- +
- +#define mask_a(a) ((u32)(a) & 0x3FF)
- +#define mask_b(b) ((u32)(b) & 0x3FFF)
- +
- +/* Pls keep S0, S1 and S2 as 0x2 by using this convertion */
- +static int _rgb_to_yuv(int n, int red, int green, int blue)
- +{
- + int c;
- + c = red * rgb2ycbcr_coeff[n][0];
- + c += green * rgb2ycbcr_coeff[n][1];
- + c += blue * rgb2ycbcr_coeff[n][2];
- + c /= 16;
- + c += rgb2ycbcr_coeff[3][n] * 4;
- + c += 8;
- + c /= 16;
- + if (c < 0)
- + c = 0;
- + if (c > 255)
- + c = 255;
- + return c;
- +}
- +
- +/*
- + * Row is for BG: RGB2YUV YUV2RGB RGB2RGB YUV2YUV CSC_NONE
- + * Column is for FG: RGB2YUV YUV2RGB RGB2RGB YUV2YUV CSC_NONE
- + */
- +static struct dp_csc_param_t dp_csc_array[CSC_NUM][CSC_NUM] = {
- +{{DP_COM_CONF_CSC_DEF_BOTH, &rgb2ycbcr_coeff}, {0, 0}, {0, 0}, {DP_COM_CONF_CSC_DEF_BG, &rgb2ycbcr_coeff}, {DP_COM_CONF_CSC_DEF_BG, &rgb2ycbcr_coeff} },
- +{{0, 0}, {DP_COM_CONF_CSC_DEF_BOTH, &ycbcr2rgb_coeff}, {DP_COM_CONF_CSC_DEF_BG, &ycbcr2rgb_coeff}, {0, 0}, {DP_COM_CONF_CSC_DEF_BG, &ycbcr2rgb_coeff} },
- +{{0, 0}, {DP_COM_CONF_CSC_DEF_FG, &ycbcr2rgb_coeff}, {0, 0}, {0, 0}, {0, 0} },
- +{{DP_COM_CONF_CSC_DEF_FG, &rgb2ycbcr_coeff}, {0, 0}, {0, 0}, {0, 0}, {0, 0} },
- +{{DP_COM_CONF_CSC_DEF_FG, &rgb2ycbcr_coeff}, {DP_COM_CONF_CSC_DEF_FG, &ycbcr2rgb_coeff}, {0, 0}, {0, 0}, {0, 0} }
- +};
- +
- +void __ipu_dp_csc_setup(struct ipu_soc *ipu,
- + int dp, struct dp_csc_param_t dp_csc_param,
- + bool srm_mode_update)
- +{
- + u32 reg;
- + const int (*coeff)[5][3];
- +
- + if (dp_csc_param.mode >= 0) {
- + reg = ipu_dp_read(ipu, DP_COM_CONF(dp));
- + reg &= ~DP_COM_CONF_CSC_DEF_MASK;
- + reg |= dp_csc_param.mode;
- + ipu_dp_write(ipu, reg, DP_COM_CONF(dp));
- + }
- +
- + coeff = dp_csc_param.coeff;
- +
- + if (coeff) {
- + ipu_dp_write(ipu, mask_a((*coeff)[0][0]) |
- + (mask_a((*coeff)[0][1]) << 16), DP_CSC_A_0(dp));
- + ipu_dp_write(ipu, mask_a((*coeff)[0][2]) |
- + (mask_a((*coeff)[1][0]) << 16), DP_CSC_A_1(dp));
- + ipu_dp_write(ipu, mask_a((*coeff)[1][1]) |
- + (mask_a((*coeff)[1][2]) << 16), DP_CSC_A_2(dp));
- + ipu_dp_write(ipu, mask_a((*coeff)[2][0]) |
- + (mask_a((*coeff)[2][1]) << 16), DP_CSC_A_3(dp));
- + ipu_dp_write(ipu, mask_a((*coeff)[2][2]) |
- + (mask_b((*coeff)[3][0]) << 16) |
- + ((*coeff)[4][0] << 30), DP_CSC_0(dp));
- + ipu_dp_write(ipu, mask_b((*coeff)[3][1]) | ((*coeff)[4][1] << 14) |
- + (mask_b((*coeff)[3][2]) << 16) |
- + ((*coeff)[4][2] << 30), DP_CSC_1(dp));
- + }
- +
- + if (srm_mode_update) {
- + reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
- + ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
- + }
- +}
- +
- +int _ipu_dp_init(struct ipu_soc *ipu,
- + ipu_channel_t channel, uint32_t in_pixel_fmt,
- + uint32_t out_pixel_fmt)
- +{
- + int in_fmt, out_fmt;
- + int dp;
- + int partial = false;
- + uint32_t reg;
- +
- + if (channel == MEM_FG_SYNC) {
- + dp = DP_SYNC;
- + partial = true;
- + } else if (channel == MEM_BG_SYNC) {
- + dp = DP_SYNC;
- + partial = false;
- + } else if (channel == MEM_BG_ASYNC0) {
- + dp = DP_ASYNC0;
- + partial = false;
- + } else {
- + return -EINVAL;
- + }
- +
- + in_fmt = format_to_colorspace(in_pixel_fmt);
- + out_fmt = format_to_colorspace(out_pixel_fmt);
- +
- + if (partial) {
- + if (in_fmt == RGB) {
- + if (out_fmt == RGB)
- + ipu->fg_csc_type = RGB2RGB;
- + else
- + ipu->fg_csc_type = RGB2YUV;
- + } else {
- + if (out_fmt == RGB)
- + ipu->fg_csc_type = YUV2RGB;
- + else
- + ipu->fg_csc_type = YUV2YUV;
- + }
- + } else {
- + if (in_fmt == RGB) {
- + if (out_fmt == RGB)
- + ipu->bg_csc_type = RGB2RGB;
- + else
- + ipu->bg_csc_type = RGB2YUV;
- + } else {
- + if (out_fmt == RGB)
- + ipu->bg_csc_type = YUV2RGB;
- + else
- + ipu->bg_csc_type = YUV2YUV;
- + }
- + }
- +
- + /* Transform color key from rgb to yuv if CSC is enabled */
- + reg = ipu_dp_read(ipu, DP_COM_CONF(dp));
- + if (ipu->color_key_4rgb && (reg & DP_COM_CONF_GWCKE) &&
- + (((ipu->fg_csc_type == RGB2YUV) && (ipu->bg_csc_type == YUV2YUV)) ||
- + ((ipu->fg_csc_type == YUV2YUV) && (ipu->bg_csc_type == RGB2YUV)) ||
- + ((ipu->fg_csc_type == YUV2YUV) && (ipu->bg_csc_type == YUV2YUV)) ||
- + ((ipu->fg_csc_type == YUV2RGB) && (ipu->bg_csc_type == YUV2RGB)))) {
- + int red, green, blue;
- + int y, u, v;
- + uint32_t color_key = ipu_dp_read(ipu, DP_GRAPH_WIND_CTRL(dp)) & 0xFFFFFFL;
- +
- + dev_dbg(ipu->dev, "_ipu_dp_init color key 0x%x need change to yuv fmt!\n", color_key);
- +
- + red = (color_key >> 16) & 0xFF;
- + green = (color_key >> 8) & 0xFF;
- + blue = color_key & 0xFF;
- +
- + y = _rgb_to_yuv(0, red, green, blue);
- + u = _rgb_to_yuv(1, red, green, blue);
- + v = _rgb_to_yuv(2, red, green, blue);
- + color_key = (y << 16) | (u << 8) | v;
- +
- + reg = ipu_dp_read(ipu, DP_GRAPH_WIND_CTRL(dp)) & 0xFF000000L;
- + ipu_dp_write(ipu, reg | color_key, DP_GRAPH_WIND_CTRL(dp));
- + ipu->color_key_4rgb = false;
- +
- + dev_dbg(ipu->dev, "_ipu_dp_init color key change to yuv fmt 0x%x!\n", color_key);
- + }
- +
- + __ipu_dp_csc_setup(ipu, dp, dp_csc_array[ipu->bg_csc_type][ipu->fg_csc_type], true);
- +
- + return 0;
- +}
- +
- +void _ipu_dp_uninit(struct ipu_soc *ipu, ipu_channel_t channel)
- +{
- + int dp;
- + int partial = false;
- +
- + if (channel == MEM_FG_SYNC) {
- + dp = DP_SYNC;
- + partial = true;
- + } else if (channel == MEM_BG_SYNC) {
- + dp = DP_SYNC;
- + partial = false;
- + } else if (channel == MEM_BG_ASYNC0) {
- + dp = DP_ASYNC0;
- + partial = false;
- + } else {
- + return;
- + }
- +
- + if (partial)
- + ipu->fg_csc_type = CSC_NONE;
- + else
- + ipu->bg_csc_type = CSC_NONE;
- +
- + __ipu_dp_csc_setup(ipu, dp, dp_csc_array[ipu->bg_csc_type][ipu->fg_csc_type], false);
- +}
- +
- +void _ipu_dc_init(struct ipu_soc *ipu, int dc_chan, int di, bool interlaced, uint32_t pixel_fmt)
- +{
- + u32 reg = 0;
- +
- + if ((dc_chan == 1) || (dc_chan == 5)) {
- + if (interlaced) {
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NL, 0, 3);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_EOL, 0, 2);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA, 0, 1);
- + } else {
- + if (di) {
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NL, 2, 3);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_EOL, 3, 2);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA, 1, 1);
- + if ((pixel_fmt == IPU_PIX_FMT_YUYV) ||
- + (pixel_fmt == IPU_PIX_FMT_UYVY) ||
- + (pixel_fmt == IPU_PIX_FMT_YVYU) ||
- + (pixel_fmt == IPU_PIX_FMT_VYUY)) {
- + _ipu_dc_link_event(ipu, dc_chan, DC_ODD_UGDE1, 9, 5);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVEN_UGDE1, 8, 5);
- + }
- + } else {
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NL, 5, 3);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_EOL, 6, 2);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA, 12, 1);
- + if ((pixel_fmt == IPU_PIX_FMT_YUYV) ||
- + (pixel_fmt == IPU_PIX_FMT_UYVY) ||
- + (pixel_fmt == IPU_PIX_FMT_YVYU) ||
- + (pixel_fmt == IPU_PIX_FMT_VYUY)) {
- + _ipu_dc_link_event(ipu, dc_chan, DC_ODD_UGDE0, 10, 5);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVEN_UGDE0, 11, 5);
- + }
- + }
- + }
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NF, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NFIELD, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_EOF, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_EOFIELD, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_CHAN, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_ADDR, 0, 0);
- +
- + reg = 0x2;
- + reg |= DC_DISP_ID_SYNC(di) << DC_WR_CH_CONF_PROG_DISP_ID_OFFSET;
- + reg |= di << 2;
- + if (interlaced)
- + reg |= DC_WR_CH_CONF_FIELD_MODE;
- + } else if ((dc_chan == 8) || (dc_chan == 9)) {
- + /* async channels */
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA_W_0, 0x64, 1);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA_W_1, 0x64, 1);
- +
- + reg = 0x3;
- + reg |= DC_DISP_ID_SERIAL << DC_WR_CH_CONF_PROG_DISP_ID_OFFSET;
- + }
- + ipu_dc_write(ipu, reg, DC_WR_CH_CONF(dc_chan));
- +
- + ipu_dc_write(ipu, 0x00000000, DC_WR_CH_ADDR(dc_chan));
- +
- + ipu_dc_write(ipu, 0x00000084, DC_GEN);
- +}
- +
- +void _ipu_dc_uninit(struct ipu_soc *ipu, int dc_chan)
- +{
- + if ((dc_chan == 1) || (dc_chan == 5)) {
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NL, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_EOL, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NF, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NFIELD, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_EOF, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_EOFIELD, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_CHAN, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_ADDR, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_ODD_UGDE0, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVEN_UGDE0, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_ODD_UGDE1, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVEN_UGDE1, 0, 0);
- + } else if ((dc_chan == 8) || (dc_chan == 9)) {
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_ADDR_W_0, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_ADDR_W_1, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_CHAN_W_0, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_CHAN_W_1, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA_W_0, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA_W_1, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_ADDR_R_0, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_ADDR_R_1, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_CHAN_R_0, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_CHAN_R_1, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA_R_0, 0, 0);
- + _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA_R_1, 0, 0);
- + }
- +}
- +
- +int _ipu_disp_chan_is_interlaced(struct ipu_soc *ipu, ipu_channel_t channel)
- +{
- + if (channel == MEM_DC_SYNC)
- + return !!(ipu_dc_read(ipu, DC_WR_CH_CONF_1) &
- + DC_WR_CH_CONF_FIELD_MODE);
- + else if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC))
- + return !!(ipu_dc_read(ipu, DC_WR_CH_CONF_5) &
- + DC_WR_CH_CONF_FIELD_MODE);
- + return 0;
- +}
- +
- +void _ipu_dp_dc_enable(struct ipu_soc *ipu, ipu_channel_t channel)
- +{
- + int di;
- + uint32_t reg;
- + uint32_t dc_chan;
- + int irq = 0;
- +
- + if (channel == MEM_FG_SYNC)
- + irq = IPU_IRQ_DP_SF_END;
- + else if (channel == MEM_DC_SYNC)
- + dc_chan = 1;
- + else if (channel == MEM_BG_SYNC)
- + dc_chan = 5;
- + else
- + return;
- +
- + if (channel == MEM_FG_SYNC) {
- + /* Enable FG channel */
- + reg = ipu_dp_read(ipu, DP_COM_CONF(DP_SYNC));
- + ipu_dp_write(ipu, reg | DP_COM_CONF_FG_EN, DP_COM_CONF(DP_SYNC));
- +
- + reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
- + ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
- + return;
- + } else if (channel == MEM_BG_SYNC) {
- + reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
- + ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
- + }
- +
- + di = ipu->dc_di_assignment[dc_chan];
- +
- + /* Make sure other DC sync channel is not assigned same DI */
- + reg = ipu_dc_read(ipu, DC_WR_CH_CONF(6 - dc_chan));
- + if ((di << 2) == (reg & DC_WR_CH_CONF_PROG_DI_ID)) {
- + reg &= ~DC_WR_CH_CONF_PROG_DI_ID;
- + reg |= di ? 0 : DC_WR_CH_CONF_PROG_DI_ID;
- + ipu_dc_write(ipu, reg, DC_WR_CH_CONF(6 - dc_chan));
- + }
- +
- + reg = ipu_dc_read(ipu, DC_WR_CH_CONF(dc_chan));
- + reg |= 4 << DC_WR_CH_CONF_PROG_TYPE_OFFSET;
- + ipu_dc_write(ipu, reg, DC_WR_CH_CONF(dc_chan));
- +
- + clk_prepare_enable(ipu->pixel_clk[di]);
- +}
- +
- +static irqreturn_t dc_irq_handler(int irq, void *dev_id)
- +{
- + struct ipu_soc *ipu = dev_id;
- + struct completion *comp = &ipu->dc_comp;
- + uint32_t reg;
- + uint32_t dc_chan;
- +
- + if (irq == IPU_IRQ_DC_FC_1)
- + dc_chan = 1;
- + else
- + dc_chan = 5;
- +
- + if (!ipu->dc_swap) {
- + reg = ipu_dc_read(ipu, DC_WR_CH_CONF(dc_chan));
- + reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
- + ipu_dc_write(ipu, reg, DC_WR_CH_CONF(dc_chan));
- +
- + reg = ipu_cm_read(ipu, IPU_DISP_GEN);
- + if (ipu->dc_di_assignment[dc_chan])
- + reg &= ~DI1_COUNTER_RELEASE;
- + else
- + reg &= ~DI0_COUNTER_RELEASE;
- + ipu_cm_write(ipu, reg, IPU_DISP_GEN);
- + }
- +
- + complete(comp);
- + return IRQ_HANDLED;
- +}
- +
- +void _ipu_dp_dc_disable(struct ipu_soc *ipu, ipu_channel_t channel, bool swap)
- +{
- + int ret;
- + uint32_t reg;
- + uint32_t csc;
- + uint32_t dc_chan;
- + int irq = 0;
- + int timeout = 50;
- +
- + ipu->dc_swap = swap;
- +
- + if (channel == MEM_DC_SYNC) {
- + dc_chan = 1;
- + irq = IPU_IRQ_DC_FC_1;
- + } else if (channel == MEM_BG_SYNC) {
- + dc_chan = 5;
- + irq = IPU_IRQ_DP_SF_END;
- + } else if (channel == MEM_FG_SYNC) {
- + /* Disable FG channel */
- + dc_chan = 5;
- +
- + reg = ipu_dp_read(ipu, DP_COM_CONF(DP_SYNC));
- + csc = reg & DP_COM_CONF_CSC_DEF_MASK;
- + if (csc == DP_COM_CONF_CSC_DEF_FG)
- + reg &= ~DP_COM_CONF_CSC_DEF_MASK;
- +
- + reg &= ~DP_COM_CONF_FG_EN;
- + ipu_dp_write(ipu, reg, DP_COM_CONF(DP_SYNC));
- +
- + reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
- + ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
- +
- + if (ipu_is_channel_busy(ipu, MEM_BG_SYNC)) {
- + ipu_cm_write(ipu, IPUIRQ_2_MASK(IPU_IRQ_DP_SF_END),
- + IPUIRQ_2_STATREG(IPU_IRQ_DP_SF_END));
- + while ((ipu_cm_read(ipu, IPUIRQ_2_STATREG(IPU_IRQ_DP_SF_END)) &
- + IPUIRQ_2_MASK(IPU_IRQ_DP_SF_END)) == 0) {
- + msleep(2);
- + timeout -= 2;
- + if (timeout <= 0)
- + break;
- + }
- + }
- + return;
- + } else {
- + return;
- + }
- +
- + init_completion(&ipu->dc_comp);
- + ret = ipu_request_irq(ipu, irq, dc_irq_handler, 0, NULL, ipu);
- + if (ret < 0) {
- + dev_err(ipu->dev, "DC irq %d in use\n", irq);
- + return;
- + }
- + ret = wait_for_completion_timeout(&ipu->dc_comp, msecs_to_jiffies(50));
- + ipu_free_irq(ipu, irq, ipu);
- + dev_dbg(ipu->dev, "DC stop timeout - %d * 10ms\n", 5 - ret);
- +
- + if (ipu->dc_swap) {
- + /* Swap DC channel 1 and 5 settings, and disable old dc chan */
- + reg = ipu_dc_read(ipu, DC_WR_CH_CONF(dc_chan));
- + ipu_dc_write(ipu, reg, DC_WR_CH_CONF(6 - dc_chan));
- + reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
- + reg ^= DC_WR_CH_CONF_PROG_DI_ID;
- + ipu_dc_write(ipu, reg, DC_WR_CH_CONF(dc_chan));
- + }
- +}
- +
- +void _ipu_init_dc_mappings(struct ipu_soc *ipu)
- +{
- + /* IPU_PIX_FMT_RGB24 */
- + _ipu_dc_map_clear(ipu, 0);
- + _ipu_dc_map_config(ipu, 0, 0, 7, 0xFF);
- + _ipu_dc_map_config(ipu, 0, 1, 15, 0xFF);
- + _ipu_dc_map_config(ipu, 0, 2, 23, 0xFF);
- +
- + /* IPU_PIX_FMT_RGB666 */
- + _ipu_dc_map_clear(ipu, 1);
- + _ipu_dc_map_config(ipu, 1, 0, 5, 0xFC);
- + _ipu_dc_map_config(ipu, 1, 1, 11, 0xFC);
- + _ipu_dc_map_config(ipu, 1, 2, 17, 0xFC);
- +
- + /* IPU_PIX_FMT_YUV444 */
- + _ipu_dc_map_clear(ipu, 2);
- + _ipu_dc_map_config(ipu, 2, 0, 15, 0xFF);
- + _ipu_dc_map_config(ipu, 2, 1, 23, 0xFF);
- + _ipu_dc_map_config(ipu, 2, 2, 7, 0xFF);
- +
- + /* IPU_PIX_FMT_RGB565 */
- + _ipu_dc_map_clear(ipu, 3);
- + _ipu_dc_map_config(ipu, 3, 0, 4, 0xF8);
- + _ipu_dc_map_config(ipu, 3, 1, 10, 0xFC);
- + _ipu_dc_map_config(ipu, 3, 2, 15, 0xF8);
- +
- + /* IPU_PIX_FMT_LVDS666 */
- + _ipu_dc_map_clear(ipu, 4);
- + _ipu_dc_map_config(ipu, 4, 0, 5, 0xFC);
- + _ipu_dc_map_config(ipu, 4, 1, 13, 0xFC);
- + _ipu_dc_map_config(ipu, 4, 2, 21, 0xFC);
- +
- + /* IPU_PIX_FMT_VYUY 16bit width */
- + _ipu_dc_map_clear(ipu, 5);
- + _ipu_dc_map_config(ipu, 5, 0, 7, 0xFF);
- + _ipu_dc_map_config(ipu, 5, 1, 0, 0x0);
- + _ipu_dc_map_config(ipu, 5, 2, 15, 0xFF);
- + _ipu_dc_map_clear(ipu, 6);
- + _ipu_dc_map_config(ipu, 6, 0, 0, 0x0);
- + _ipu_dc_map_config(ipu, 6, 1, 7, 0xFF);
- + _ipu_dc_map_config(ipu, 6, 2, 15, 0xFF);
- +
- + /* IPU_PIX_FMT_UYUV 16bit width */
- + _ipu_dc_map_clear(ipu, 7);
- + _ipu_dc_map_link(ipu, 7, 6, 0, 6, 1, 6, 2);
- + _ipu_dc_map_clear(ipu, 8);
- + _ipu_dc_map_link(ipu, 8, 5, 0, 5, 1, 5, 2);
- +
- + /* IPU_PIX_FMT_YUYV 16bit width */
- + _ipu_dc_map_clear(ipu, 9);
- + _ipu_dc_map_link(ipu, 9, 5, 2, 5, 1, 5, 0);
- + _ipu_dc_map_clear(ipu, 10);
- + _ipu_dc_map_link(ipu, 10, 5, 1, 5, 2, 5, 0);
- +
- + /* IPU_PIX_FMT_YVYU 16bit width */
- + _ipu_dc_map_clear(ipu, 11);
- + _ipu_dc_map_link(ipu, 11, 5, 1, 5, 2, 5, 0);
- + _ipu_dc_map_clear(ipu, 12);
- + _ipu_dc_map_link(ipu, 12, 5, 2, 5, 1, 5, 0);
- +
- + /* IPU_PIX_FMT_GBR24 */
- + /* IPU_PIX_FMT_VYU444 */
- + _ipu_dc_map_clear(ipu, 13);
- + _ipu_dc_map_link(ipu, 13, 0, 2, 0, 0, 0, 1);
- +
- + /* IPU_PIX_FMT_BGR24 */
- + _ipu_dc_map_clear(ipu, 14);
- + _ipu_dc_map_link(ipu, 14, 0, 2, 0, 1, 0, 0);
- +}
- +
- +int _ipu_pixfmt_to_map(uint32_t fmt)
- +{
- + switch (fmt) {
- + case IPU_PIX_FMT_GENERIC:
- + case IPU_PIX_FMT_RGB24:
- + return 0;
- + case IPU_PIX_FMT_RGB666:
- + return 1;
- + case IPU_PIX_FMT_YUV444:
- + return 2;
- + case IPU_PIX_FMT_RGB565:
- + return 3;
- + case IPU_PIX_FMT_LVDS666:
- + return 4;
- + case IPU_PIX_FMT_VYUY:
- + return 6;
- + case IPU_PIX_FMT_UYVY:
- + return 8;
- + case IPU_PIX_FMT_YUYV:
- + return 10;
- + case IPU_PIX_FMT_YVYU:
- + return 12;
- + case IPU_PIX_FMT_GBR24:
- + case IPU_PIX_FMT_VYU444:
- + return 13;
- + case IPU_PIX_FMT_BGR24:
- + return 14;
- + }
- +
- + return -1;
- +}
- +
- +/*!
- + * This function sets the colorspace for of dp.
- + * modes.
- + *
- + * @param ipu ipu handler
- + * @param channel Input parameter for the logical channel ID.
- + *
- + * @param param If it's not NULL, update the csc table
- + * with this parameter.
- + *
- + * @return N/A
- + */
- +void _ipu_dp_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3])
- +{
- + int dp;
- + struct dp_csc_param_t dp_csc_param;
- +
- + if (channel == MEM_FG_SYNC)
- + dp = DP_SYNC;
- + else if (channel == MEM_BG_SYNC)
- + dp = DP_SYNC;
- + else if (channel == MEM_BG_ASYNC0)
- + dp = DP_ASYNC0;
- + else
- + return;
- +
- + dp_csc_param.mode = -1;
- + dp_csc_param.coeff = param;
- + __ipu_dp_csc_setup(ipu, dp, dp_csc_param, true);
- +}
- +
- +void ipu_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3])
- +{
- + _ipu_dp_set_csc_coefficients(ipu, channel, param);
- +}
- +EXPORT_SYMBOL(ipu_set_csc_coefficients);
- +
- +/*!
- + * This function is called to adapt synchronous LCD panel to IPU restriction.
- + *
- + */
- +void adapt_panel_to_ipu_restricitions(struct ipu_soc *ipu, uint16_t *v_start_width,
- + uint16_t *v_sync_width,
- + uint16_t *v_end_width)
- +{
- + if (*v_end_width < 2) {
- + uint16_t diff = 2 - *v_end_width;
- + if (*v_start_width >= diff) {
- + *v_end_width = 2;
- + *v_start_width = *v_start_width - diff;
- + } else if (*v_sync_width > diff) {
- + *v_end_width = 2;
- + *v_sync_width = *v_sync_width - diff;
- + } else
- + dev_err(ipu->dev, "WARNING: try to adapt timming, but failed\n");
- + dev_err(ipu->dev, "WARNING: adapt panel end blank lines\n");
- + }
- +}
- +
- +/*!
- + * This function is called to initialize a synchronous LCD panel.
- + *
- + * @param ipu ipu handler
- + * @param disp The DI the panel is attached to.
- + *
- + * @param pixel_clk Desired pixel clock frequency in Hz.
- + *
- + * @param pixel_fmt Input parameter for pixel format of buffer.
- + * Pixel format is a FOURCC ASCII code.
- + *
- + * @param width The width of panel in pixels.
- + *
- + * @param height The height of panel in pixels.
- + *
- + * @param hStartWidth The number of pixel clocks between the HSYNC
- + * signal pulse and the start of valid data.
- + *
- + * @param hSyncWidth The width of the HSYNC signal in units of pixel
- + * clocks.
- + *
- + * @param hEndWidth The number of pixel clocks between the end of
- + * valid data and the HSYNC signal for next line.
- + *
- + * @param vStartWidth The number of lines between the VSYNC
- + * signal pulse and the start of valid data.
- + *
- + * @param vSyncWidth The width of the VSYNC signal in units of lines
- + *
- + * @param vEndWidth The number of lines between the end of valid
- + * data and the VSYNC signal for next frame.
- + *
- + * @param sig Bitfield of signal polarities for LCD interface.
- + *
- + * @return This function returns 0 on success or negative error code on
- + * fail.
- + */
- +int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp, uint32_t pixel_clk,
- + uint16_t width, uint16_t height,
- + uint32_t pixel_fmt,
- + uint16_t h_start_width, uint16_t h_sync_width,
- + uint16_t h_end_width, uint16_t v_start_width,
- + uint16_t v_sync_width, uint16_t v_end_width,
- + uint32_t v_to_h_sync, ipu_di_signal_cfg_t sig)
- +{
- + uint32_t field0_offset = 0;
- + uint32_t field1_offset;
- + uint32_t reg;
- + uint32_t di_gen, vsync_cnt;
- + uint32_t div, rounded_pixel_clk;
- + uint32_t h_total, v_total;
- + int map;
- + int ret;
- + struct clk *ldb_di0_clk, *ldb_di1_clk;
- + struct clk *di_parent;
- +
- + dev_dbg(ipu->dev, "panel size = %d x %d\n", width, height);
- +
- + if ((v_sync_width == 0) || (h_sync_width == 0))
- + return -EINVAL;
- +
- + adapt_panel_to_ipu_restricitions(ipu, &v_start_width, &v_sync_width, &v_end_width);
- + h_total = width + h_sync_width + h_start_width + h_end_width;
- + v_total = height + v_sync_width + v_start_width + v_end_width;
- +
- + /* Init clocking */
- + dev_dbg(ipu->dev, "pixel clk = %d\n", pixel_clk);
- +
- + di_parent = clk_get_parent(ipu->di_clk_sel[disp]);
- + if (!di_parent) {
- + dev_err(ipu->dev, "get di clk parent fail\n");
- + return -EINVAL;
- + }
- + ldb_di0_clk = clk_get(ipu->dev, "ldb_di0");
- + if (IS_ERR(ldb_di0_clk)) {
- + dev_err(ipu->dev, "clk_get di0 failed");
- + return PTR_ERR(ldb_di0_clk);
- + }
- + ldb_di1_clk = clk_get(ipu->dev, "ldb_di1");
- + if (IS_ERR(ldb_di1_clk)) {
- + dev_err(ipu->dev, "clk_get di1 failed");
- + return PTR_ERR(ldb_di1_clk);
- + }
- +
- + if (ldb_di0_clk == di_parent || ldb_di1_clk == di_parent) {
- + /* if di clk parent is tve/ldb, then keep it;*/
- + dev_dbg(ipu->dev, "use special clk parent\n");
- + ret = clk_set_parent(ipu->pixel_clk_sel[disp], ipu->di_clk[disp]);
- + if (ret) {
- + dev_err(ipu->dev, "set pixel clk error:%d\n", ret);
- + return ret;
- + }
- + clk_put(ldb_di0_clk);
- + clk_put(ldb_di1_clk);
- + } else {
- + /* try ipu clk first*/
- + dev_dbg(ipu->dev, "try ipu internal clk\n");
- + ret = clk_set_parent(ipu->pixel_clk_sel[disp], ipu->ipu_clk);
- + if (ret) {
- + dev_err(ipu->dev, "set pixel clk error:%d\n", ret);
- + return ret;
- + }
- + rounded_pixel_clk = clk_round_rate(ipu->pixel_clk[disp], pixel_clk);
- + dev_dbg(ipu->dev, "rounded pix clk:%d\n", rounded_pixel_clk);
- + /*
- + * we will only use 1/2 fraction for ipu clk,
- + * so if the clk rate is not fit, try ext clk.
- + */
- + if (!sig.int_clk &&
- + ((rounded_pixel_clk >= pixel_clk + pixel_clk/200) ||
- + (rounded_pixel_clk <= pixel_clk - pixel_clk/200))) {
- + dev_dbg(ipu->dev, "try ipu ext di clk\n");
- +
- + rounded_pixel_clk =
- + clk_round_rate(ipu->di_clk[disp], pixel_clk);
- + ret = clk_set_rate(ipu->di_clk[disp],
- + rounded_pixel_clk);
- + if (ret) {
- + dev_err(ipu->dev,
- + "set di clk rate error:%d\n", ret);
- + return ret;
- + }
- + dev_dbg(ipu->dev, "di clk:%d\n", rounded_pixel_clk);
- + ret = clk_set_parent(ipu->pixel_clk_sel[disp],
- + ipu->di_clk[disp]);
- + if (ret) {
- + dev_err(ipu->dev,
- + "set pixel clk parent error:%d\n", ret);
- + return ret;
- + }
- + }
- + }
- + rounded_pixel_clk = clk_round_rate(ipu->pixel_clk[disp], pixel_clk);
- + dev_dbg(ipu->dev, "round pixel clk:%d\n", rounded_pixel_clk);
- + ret = clk_set_rate(ipu->pixel_clk[disp], rounded_pixel_clk);
- + if (ret) {
- + dev_err(ipu->dev, "set pixel clk rate error:%d\n", ret);
- + return ret;
- + }
- + msleep(5);
- + /* Get integer portion of divider */
- + div = clk_get_rate(clk_get_parent(ipu->pixel_clk_sel[disp])) / rounded_pixel_clk;
- + dev_dbg(ipu->dev, "div:%d\n", div);
- + if (!div) {
- + dev_err(ipu->dev, "invalid pixel clk div = 0\n");
- + return -EINVAL;
- + }
- +
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + _ipu_di_data_wave_config(ipu, disp, SYNC_WAVE, div - 1, div - 1);
- + _ipu_di_data_pin_config(ipu, disp, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
- +
- + map = _ipu_pixfmt_to_map(pixel_fmt);
- + if (map < 0) {
- + dev_dbg(ipu->dev, "IPU_DISP: No MAP\n");
- + mutex_unlock(&ipu->mutex_lock);
- + return -EINVAL;
- + }
- +
- + /*clear DI*/
- + di_gen = ipu_di_read(ipu, disp, DI_GENERAL);
- + di_gen &= (0x3 << 20);
- + ipu_di_write(ipu, disp, di_gen, DI_GENERAL);
- +
- + if (sig.interlaced) {
- + if (g_ipu_hw_rev >= IPU_V3DEX) {
- + /* Setup internal HSYNC waveform */
- + _ipu_di_sync_config(ipu,
- + disp, /* display */
- + 1, /* counter */
- + h_total/2 - 1, /* run count */
- + DI_SYNC_CLK, /* run_resolution */
- + 0, /* offset */
- + DI_SYNC_NONE, /* offset resolution */
- + 0, /* repeat count */
- + DI_SYNC_NONE, /* CNT_CLR_SEL */
- + 0, /* CNT_POLARITY_GEN_EN */
- + DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
- + DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
- + 0, /* COUNT UP */
- + 0 /* COUNT DOWN */
- + );
- +
- + /* Field 1 VSYNC waveform */
- + _ipu_di_sync_config(ipu,
- + disp, /* display */
- + 2, /* counter */
- + h_total - 1, /* run count */
- + DI_SYNC_CLK, /* run_resolution */
- + 0, /* offset */
- + DI_SYNC_NONE, /* offset resolution */
- + 0, /* repeat count */
- + DI_SYNC_NONE, /* CNT_CLR_SEL */
- + 0, /* CNT_POLARITY_GEN_EN */
- + DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
- + DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
- + 0, /* COUNT UP */
- + 2*div /* COUNT DOWN */
- + );
- +
- + /* Setup internal HSYNC waveform */
- + _ipu_di_sync_config(ipu,
- + disp, /* display */
- + 3, /* counter */
- + v_total*2 - 1, /* run count */
- + DI_SYNC_INT_HSYNC, /* run_resolution */
- + 1, /* offset */
- + DI_SYNC_INT_HSYNC, /* offset resolution */
- + 0, /* repeat count */
- + DI_SYNC_NONE, /* CNT_CLR_SEL */
- + 0, /* CNT_POLARITY_GEN_EN */
- + DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
- + DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
- + 0, /* COUNT UP */
- + 2*div /* COUNT DOWN */
- + );
- +
- + /* Active Field ? */
- + _ipu_di_sync_config(ipu,
- + disp, /* display */
- + 4, /* counter */
- + v_total/2 - 1, /* run count */
- + DI_SYNC_HSYNC, /* run_resolution */
- + v_start_width, /* offset */
- + DI_SYNC_HSYNC, /* offset resolution */
- + 2, /* repeat count */
- + DI_SYNC_VSYNC, /* CNT_CLR_SEL */
- + 0, /* CNT_POLARITY_GEN_EN */
- + DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
- + DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
- + 0, /* COUNT UP */
- + 0 /* COUNT DOWN */
- + );
- +
- + /* Active Line */
- + _ipu_di_sync_config(ipu,
- + disp, /* display */
- + 5, /* counter */
- + 0, /* run count */
- + DI_SYNC_HSYNC, /* run_resolution */
- + 0, /* offset */
- + DI_SYNC_NONE, /* offset resolution */
- + height/2, /* repeat count */
- + 4, /* CNT_CLR_SEL */
- + 0, /* CNT_POLARITY_GEN_EN */
- + DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
- + DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
- + 0, /* COUNT UP */
- + 0 /* COUNT DOWN */
- + );
- +
- + /* Field 0 VSYNC waveform */
- + _ipu_di_sync_config(ipu,
- + disp, /* display */
- + 6, /* counter */
- + v_total - 1, /* run count */
- + DI_SYNC_HSYNC, /* run_resolution */
- + 0, /* offset */
- + DI_SYNC_NONE, /* offset resolution */
- + 0, /* repeat count */
- + DI_SYNC_NONE, /* CNT_CLR_SEL */
- + 0, /* CNT_POLARITY_GEN_EN */
- + DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
- + DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
- + 0, /* COUNT UP */
- + 0 /* COUNT DOWN */
- + );
- +
- + /* DC VSYNC waveform */
- + vsync_cnt = 7;
- + _ipu_di_sync_config(ipu,
- + disp, /* display */
- + 7, /* counter */
- + v_total/2 - 1, /* run count */
- + DI_SYNC_HSYNC, /* run_resolution */
- + 9, /* offset */
- + DI_SYNC_HSYNC, /* offset resolution */
- + 2, /* repeat count */
- + DI_SYNC_VSYNC, /* CNT_CLR_SEL */
- + 0, /* CNT_POLARITY_GEN_EN */
- + DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
- + DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
- + 0, /* COUNT UP */
- + 0 /* COUNT DOWN */
- + );
- +
- + /* active pixel waveform */
- + _ipu_di_sync_config(ipu,
- + disp, /* display */
- + 8, /* counter */
- + 0, /* run count */
- + DI_SYNC_CLK, /* run_resolution */
- + h_start_width, /* offset */
- + DI_SYNC_CLK, /* offset resolution */
- + width, /* repeat count */
- + 5, /* CNT_CLR_SEL */
- + 0, /* CNT_POLARITY_GEN_EN */
- + DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
- + DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
- + 0, /* COUNT UP */
- + 0 /* COUNT DOWN */
- + );
- +
- + /* Second VSYNC */
- + _ipu_di_sync_config(ipu,
- + disp, /* display */
- + 9, /* counter */
- + v_total - 1, /* run count */
- + DI_SYNC_INT_HSYNC, /* run_resolution */
- + v_total/2, /* offset */
- + DI_SYNC_INT_HSYNC, /* offset resolution */
- + 0, /* repeat count */
- + DI_SYNC_HSYNC, /* CNT_CLR_SEL */
- + 0, /* CNT_POLARITY_GEN_EN */
- + DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
- + DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
- + 0, /* COUNT UP */
- + 2*div /* COUNT DOWN */
- + );
- +
- + /* set gentime select and tag sel */
- + reg = ipu_di_read(ipu, disp, DI_SW_GEN1(9));
- + reg &= 0x1FFFFFFF;
- + reg |= (3-1)<<29 | 0x00008000;
- + ipu_di_write(ipu, disp, reg, DI_SW_GEN1(9));
- +
- + ipu_di_write(ipu, disp, v_total / 2 - 1, DI_SCR_CONF);
- +
- + /* set y_sel = 1 */
- + di_gen |= 0x10000000;
- + di_gen |= DI_GEN_POLARITY_5;
- + di_gen |= DI_GEN_POLARITY_8;
- + } else {
- + /* Setup internal HSYNC waveform */
- + _ipu_di_sync_config(ipu, disp, 1, h_total - 1, DI_SYNC_CLK,
- + 0, DI_SYNC_NONE, 0, DI_SYNC_NONE, 0, DI_SYNC_NONE,
- + DI_SYNC_NONE, 0, 0);
- +
- + field1_offset = v_sync_width + v_start_width + height / 2 +
- + v_end_width;
- + if (sig.odd_field_first) {
- + field0_offset = field1_offset - 1;
- + field1_offset = 0;
- + }
- + v_total += v_start_width + v_end_width;
- +
- + /* Field 1 VSYNC waveform */
- + _ipu_di_sync_config(ipu, disp, 2, v_total - 1, 1,
- + field0_offset,
- + field0_offset ? 1 : DI_SYNC_NONE,
- + 0, DI_SYNC_NONE, 0,
- + DI_SYNC_NONE, DI_SYNC_NONE, 0, 4);
- +
- + /* Setup internal HSYNC waveform */
- + _ipu_di_sync_config(ipu, disp, 3, h_total - 1, DI_SYNC_CLK,
- + 0, DI_SYNC_NONE, 0, DI_SYNC_NONE, 0,
- + DI_SYNC_NONE, DI_SYNC_NONE, 0, 4);
- +
- + /* Active Field ? */
- + _ipu_di_sync_config(ipu, disp, 4,
- + field0_offset ?
- + field0_offset : field1_offset - 2,
- + 1, v_start_width + v_sync_width, 1, 2, 2,
- + 0, DI_SYNC_NONE, DI_SYNC_NONE, 0, 0);
- +
- + /* Active Line */
- + _ipu_di_sync_config(ipu, disp, 5, 0, 1,
- + 0, DI_SYNC_NONE,
- + height / 2, 4, 0, DI_SYNC_NONE,
- + DI_SYNC_NONE, 0, 0);
- +
- + /* Field 0 VSYNC waveform */
- + _ipu_di_sync_config(ipu, disp, 6, v_total - 1, 1,
- + 0, DI_SYNC_NONE,
- + 0, DI_SYNC_NONE, 0, DI_SYNC_NONE,
- + DI_SYNC_NONE, 0, 0);
- +
- + /* DC VSYNC waveform */
- + vsync_cnt = 7;
- + _ipu_di_sync_config(ipu, disp, 7, 0, 1,
- + field1_offset,
- + field1_offset ? 1 : DI_SYNC_NONE,
- + 1, 2, 0, DI_SYNC_NONE, DI_SYNC_NONE, 0, 0);
- +
- + /* active pixel waveform */
- + _ipu_di_sync_config(ipu, disp, 8, 0, DI_SYNC_CLK,
- + h_sync_width + h_start_width, DI_SYNC_CLK,
- + width, 5, 0, DI_SYNC_NONE, DI_SYNC_NONE,
- + 0, 0);
- +
- + /* ??? */
- + _ipu_di_sync_config(ipu, disp, 9, v_total - 1, 2,
- + 0, DI_SYNC_NONE,
- + 0, DI_SYNC_NONE, 6, DI_SYNC_NONE,
- + DI_SYNC_NONE, 0, 0);
- +
- + reg = ipu_di_read(ipu, disp, DI_SW_GEN1(9));
- + reg |= 0x8000;
- + ipu_di_write(ipu, disp, reg, DI_SW_GEN1(9));
- +
- + ipu_di_write(ipu, disp, v_sync_width + v_start_width +
- + v_end_width + height / 2 - 1, DI_SCR_CONF);
- + }
- +
- + /* Init template microcode */
- + _ipu_dc_write_tmpl(ipu, 0, WROD(0), 0, map, SYNC_WAVE, 0, 8, 1);
- +
- + if (sig.Hsync_pol)
- + di_gen |= DI_GEN_POLARITY_3;
- + if (sig.Vsync_pol)
- + di_gen |= DI_GEN_POLARITY_2;
- + } else {
- + /* Setup internal HSYNC waveform */
- + _ipu_di_sync_config(ipu, disp, 1, h_total - 1, DI_SYNC_CLK,
- + 0, DI_SYNC_NONE, 0, DI_SYNC_NONE, 0, DI_SYNC_NONE,
- + DI_SYNC_NONE, 0, 0);
- +
- + /* Setup external (delayed) HSYNC waveform */
- + _ipu_di_sync_config(ipu, disp, DI_SYNC_HSYNC, h_total - 1,
- + DI_SYNC_CLK, div * v_to_h_sync, DI_SYNC_CLK,
- + 0, DI_SYNC_NONE, 1, DI_SYNC_NONE,
- + DI_SYNC_CLK, 0, h_sync_width * 2);
- + /* Setup VSYNC waveform */
- + vsync_cnt = DI_SYNC_VSYNC;
- + _ipu_di_sync_config(ipu, disp, DI_SYNC_VSYNC, v_total - 1,
- + DI_SYNC_INT_HSYNC, 0, DI_SYNC_NONE, 0,
- + DI_SYNC_NONE, 1, DI_SYNC_NONE,
- + DI_SYNC_INT_HSYNC, 0, v_sync_width * 2);
- + ipu_di_write(ipu, disp, v_total - 1, DI_SCR_CONF);
- +
- + /* Setup active data waveform to sync with DC */
- + _ipu_di_sync_config(ipu, disp, 4, 0, DI_SYNC_HSYNC,
- + v_sync_width + v_start_width, DI_SYNC_HSYNC, height,
- + DI_SYNC_VSYNC, 0, DI_SYNC_NONE,
- + DI_SYNC_NONE, 0, 0);
- + _ipu_di_sync_config(ipu, disp, 5, 0, DI_SYNC_CLK,
- + h_sync_width + h_start_width, DI_SYNC_CLK,
- + width, 4, 0, DI_SYNC_NONE, DI_SYNC_NONE, 0,
- + 0);
- +
- + /* set VGA delayed hsync/vsync no matter VGA enabled */
- + if (disp) {
- + /* couter 7 for VGA delay HSYNC */
- + _ipu_di_sync_config(ipu, disp, 7,
- + h_total - 1, DI_SYNC_CLK,
- + 18, DI_SYNC_CLK,
- + 0, DI_SYNC_NONE,
- + 1, DI_SYNC_NONE, DI_SYNC_CLK,
- + 0, h_sync_width * 2);
- +
- + /* couter 8 for VGA delay VSYNC */
- + _ipu_di_sync_config(ipu, disp, 8,
- + v_total - 1, DI_SYNC_INT_HSYNC,
- + 1, DI_SYNC_INT_HSYNC,
- + 0, DI_SYNC_NONE,
- + 1, DI_SYNC_NONE, DI_SYNC_INT_HSYNC,
- + 0, v_sync_width * 2);
- + }
- +
- + /* reset all unused counters */
- + ipu_di_write(ipu, disp, 0, DI_SW_GEN0(6));
- + ipu_di_write(ipu, disp, 0, DI_SW_GEN1(6));
- + if (!disp) {
- + ipu_di_write(ipu, disp, 0, DI_SW_GEN0(7));
- + ipu_di_write(ipu, disp, 0, DI_SW_GEN1(7));
- + ipu_di_write(ipu, disp, 0, DI_STP_REP(7));
- + ipu_di_write(ipu, disp, 0, DI_SW_GEN0(8));
- + ipu_di_write(ipu, disp, 0, DI_SW_GEN1(8));
- + ipu_di_write(ipu, disp, 0, DI_STP_REP(8));
- + }
- + ipu_di_write(ipu, disp, 0, DI_SW_GEN0(9));
- + ipu_di_write(ipu, disp, 0, DI_SW_GEN1(9));
- + ipu_di_write(ipu, disp, 0, DI_STP_REP(9));
- +
- + reg = ipu_di_read(ipu, disp, DI_STP_REP(6));
- + reg &= 0x0000FFFF;
- + ipu_di_write(ipu, disp, reg, DI_STP_REP(6));
- +
- + /* Init template microcode */
- + if (disp) {
- + if ((pixel_fmt == IPU_PIX_FMT_YUYV) ||
- + (pixel_fmt == IPU_PIX_FMT_UYVY) ||
- + (pixel_fmt == IPU_PIX_FMT_YVYU) ||
- + (pixel_fmt == IPU_PIX_FMT_VYUY)) {
- + _ipu_dc_write_tmpl(ipu, 8, WROD(0), 0, (map - 1), SYNC_WAVE, 0, 5, 1);
- + _ipu_dc_write_tmpl(ipu, 9, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
- + /* configure user events according to DISP NUM */
- + ipu_dc_write(ipu, (width - 1), DC_UGDE_3(disp));
- + }
- + _ipu_dc_write_tmpl(ipu, 2, WROD(0), 0, map, SYNC_WAVE, 8, 5, 1);
- + _ipu_dc_write_tmpl(ipu, 3, WROD(0), 0, map, SYNC_WAVE, 4, 5, 0);
- + _ipu_dc_write_tmpl(ipu, 4, WRG, 0, map, NULL_WAVE, 0, 0, 1);
- + _ipu_dc_write_tmpl(ipu, 1, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
- +
- + } else {
- + if ((pixel_fmt == IPU_PIX_FMT_YUYV) ||
- + (pixel_fmt == IPU_PIX_FMT_UYVY) ||
- + (pixel_fmt == IPU_PIX_FMT_YVYU) ||
- + (pixel_fmt == IPU_PIX_FMT_VYUY)) {
- + _ipu_dc_write_tmpl(ipu, 10, WROD(0), 0, (map - 1), SYNC_WAVE, 0, 5, 1);
- + _ipu_dc_write_tmpl(ipu, 11, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
- + /* configure user events according to DISP NUM */
- + ipu_dc_write(ipu, width - 1, DC_UGDE_3(disp));
- + }
- + _ipu_dc_write_tmpl(ipu, 5, WROD(0), 0, map, SYNC_WAVE, 8, 5, 1);
- + _ipu_dc_write_tmpl(ipu, 6, WROD(0), 0, map, SYNC_WAVE, 4, 5, 0);
- + _ipu_dc_write_tmpl(ipu, 7, WRG, 0, map, NULL_WAVE, 0, 0, 1);
- + _ipu_dc_write_tmpl(ipu, 12, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
- + }
- +
- + if (sig.Hsync_pol) {
- + di_gen |= DI_GEN_POLARITY_2;
- + if (disp)
- + di_gen |= DI_GEN_POLARITY_7;
- + }
- + if (sig.Vsync_pol) {
- + di_gen |= DI_GEN_POLARITY_3;
- + if (disp)
- + di_gen |= DI_GEN_POLARITY_8;
- + }
- + }
- + /* changinc DISP_CLK polarity: it can be wrong for some applications */
- + if ((pixel_fmt == IPU_PIX_FMT_YUYV) ||
- + (pixel_fmt == IPU_PIX_FMT_UYVY) ||
- + (pixel_fmt == IPU_PIX_FMT_YVYU) ||
- + (pixel_fmt == IPU_PIX_FMT_VYUY))
- + di_gen |= 0x00020000;
- +
- + if (!sig.clk_pol)
- + di_gen |= DI_GEN_POLARITY_DISP_CLK;
- +
- + ipu_di_write(ipu, disp, di_gen, DI_GENERAL);
- +
- + ipu_di_write(ipu, disp, (--vsync_cnt << DI_VSYNC_SEL_OFFSET) |
- + 0x00000002, DI_SYNC_AS_GEN);
- + reg = ipu_di_read(ipu, disp, DI_POL);
- + reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
- + if (sig.enable_pol)
- + reg |= DI_POL_DRDY_POLARITY_15;
- + if (sig.data_pol)
- + reg |= DI_POL_DRDY_DATA_POLARITY;
- + ipu_di_write(ipu, disp, reg, DI_POL);
- +
- + ipu_dc_write(ipu, width, DC_DISP_CONF2(DC_DISP_ID_SYNC(disp)));
- +
- + mutex_unlock(&ipu->mutex_lock);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(ipu_init_sync_panel);
- +
- +void ipu_uninit_sync_panel(struct ipu_soc *ipu, int disp)
- +{
- + uint32_t reg;
- + uint32_t di_gen;
- +
- + if ((disp != 0) || (disp != 1))
- + return;
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + di_gen = ipu_di_read(ipu, disp, DI_GENERAL);
- + di_gen |= 0x3ff | DI_GEN_POLARITY_DISP_CLK;
- + ipu_di_write(ipu, disp, di_gen, DI_GENERAL);
- +
- + reg = ipu_di_read(ipu, disp, DI_POL);
- + reg |= 0x3ffffff;
- + ipu_di_write(ipu, disp, reg, DI_POL);
- +
- + mutex_unlock(&ipu->mutex_lock);
- +}
- +EXPORT_SYMBOL(ipu_uninit_sync_panel);
- +
- +int ipu_init_async_panel(struct ipu_soc *ipu, int disp, int type, uint32_t cycle_time,
- + uint32_t pixel_fmt, ipu_adc_sig_cfg_t sig)
- +{
- + int map;
- + u32 ser_conf = 0;
- + u32 div;
- + u32 di_clk = clk_get_rate(ipu->ipu_clk);
- +
- + /* round up cycle_time, then calcalate the divider using scaled math */
- + cycle_time += (1000000000UL / di_clk) - 1;
- + div = (cycle_time * (di_clk / 256UL)) / (1000000000UL / 256UL);
- +
- + map = _ipu_pixfmt_to_map(pixel_fmt);
- + if (map < 0)
- + return -EINVAL;
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + if (type == IPU_PANEL_SERIAL) {
- + ipu_di_write(ipu, disp, (div << 24) | ((sig.ifc_width - 1) << 4),
- + DI_DW_GEN(ASYNC_SER_WAVE));
- +
- + _ipu_di_data_pin_config(ipu, disp, ASYNC_SER_WAVE, DI_PIN_CS,
- + 0, 0, (div * 2) + 1);
- + _ipu_di_data_pin_config(ipu, disp, ASYNC_SER_WAVE, DI_PIN_SER_CLK,
- + 1, div, div * 2);
- + _ipu_di_data_pin_config(ipu, disp, ASYNC_SER_WAVE, DI_PIN_SER_RS,
- + 2, 0, 0);
- +
- + _ipu_dc_write_tmpl(ipu, 0x64, WROD(0), 0, map, ASYNC_SER_WAVE, 0, 0, 1);
- +
- + /* Configure DC for serial panel */
- + ipu_dc_write(ipu, 0x14, DC_DISP_CONF1(DC_DISP_ID_SERIAL));
- +
- + if (sig.clk_pol)
- + ser_conf |= DI_SER_CONF_SERIAL_CLK_POL;
- + if (sig.data_pol)
- + ser_conf |= DI_SER_CONF_SERIAL_DATA_POL;
- + if (sig.rs_pol)
- + ser_conf |= DI_SER_CONF_SERIAL_RS_POL;
- + if (sig.cs_pol)
- + ser_conf |= DI_SER_CONF_SERIAL_CS_POL;
- + ipu_di_write(ipu, disp, ser_conf, DI_SER_CONF);
- + }
- +
- + mutex_unlock(&ipu->mutex_lock);
- + return 0;
- +}
- +EXPORT_SYMBOL(ipu_init_async_panel);
- +
- +/*!
- + * This function sets the foreground and background plane global alpha blending
- + * modes. This function also sets the DP graphic plane according to the
- + * parameter of IPUv3 DP channel.
- + *
- + * @param ipu ipu handler
- + * @param channel IPUv3 DP channel
- + *
- + * @param enable Boolean to enable or disable global alpha
- + * blending. If disabled, local blending is used.
- + *
- + * @param alpha Global alpha value.
- + *
- + * @return Returns 0 on success or negative error code on fail
- + */
- +int32_t ipu_disp_set_global_alpha(struct ipu_soc *ipu, ipu_channel_t channel,
- + bool enable, uint8_t alpha)
- +{
- + uint32_t reg;
- + uint32_t flow;
- + bool bg_chan;
- +
- + if (channel == MEM_BG_SYNC || channel == MEM_FG_SYNC)
- + flow = DP_SYNC;
- + else if (channel == MEM_BG_ASYNC0 || channel == MEM_FG_ASYNC0)
- + flow = DP_ASYNC0;
- + else if (channel == MEM_BG_ASYNC1 || channel == MEM_FG_ASYNC1)
- + flow = DP_ASYNC1;
- + else
- + return -EINVAL;
- +
- + if (channel == MEM_BG_SYNC || channel == MEM_BG_ASYNC0 ||
- + channel == MEM_BG_ASYNC1)
- + bg_chan = true;
- + else
- + bg_chan = false;
- +
- + _ipu_get(ipu);
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + if (bg_chan) {
- + reg = ipu_dp_read(ipu, DP_COM_CONF(flow));
- + ipu_dp_write(ipu, reg & ~DP_COM_CONF_GWSEL, DP_COM_CONF(flow));
- + } else {
- + reg = ipu_dp_read(ipu, DP_COM_CONF(flow));
- + ipu_dp_write(ipu, reg | DP_COM_CONF_GWSEL, DP_COM_CONF(flow));
- + }
- +
- + if (enable) {
- + reg = ipu_dp_read(ipu, DP_GRAPH_WIND_CTRL(flow)) & 0x00FFFFFFL;
- + ipu_dp_write(ipu, reg | ((uint32_t) alpha << 24),
- + DP_GRAPH_WIND_CTRL(flow));
- +
- + reg = ipu_dp_read(ipu, DP_COM_CONF(flow));
- + ipu_dp_write(ipu, reg | DP_COM_CONF_GWAM, DP_COM_CONF(flow));
- + } else {
- + reg = ipu_dp_read(ipu, DP_COM_CONF(flow));
- + ipu_dp_write(ipu, reg & ~DP_COM_CONF_GWAM, DP_COM_CONF(flow));
- + }
- +
- + reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
- + ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
- +
- + mutex_unlock(&ipu->mutex_lock);
- +
- + _ipu_put(ipu);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(ipu_disp_set_global_alpha);
- +
- +/*!
- + * This function sets the transparent color key for SDC graphic plane.
- + *
- + * @param ipu ipu handler
- + * @param channel Input parameter for the logical channel ID.
- + *
- + * @param enable Boolean to enable or disable color key
- + *
- + * @param colorKey 24-bit RGB color for transparent color key.
- + *
- + * @return Returns 0 on success or negative error code on fail
- + */
- +int32_t ipu_disp_set_color_key(struct ipu_soc *ipu, ipu_channel_t channel,
- + bool enable, uint32_t color_key)
- +{
- + uint32_t reg, flow;
- + int y, u, v;
- + int red, green, blue;
- +
- + if (channel == MEM_BG_SYNC || channel == MEM_FG_SYNC)
- + flow = DP_SYNC;
- + else if (channel == MEM_BG_ASYNC0 || channel == MEM_FG_ASYNC0)
- + flow = DP_ASYNC0;
- + else if (channel == MEM_BG_ASYNC1 || channel == MEM_FG_ASYNC1)
- + flow = DP_ASYNC1;
- + else
- + return -EINVAL;
- +
- + _ipu_get(ipu);
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + ipu->color_key_4rgb = true;
- + /* Transform color key from rgb to yuv if CSC is enabled */
- + if (((ipu->fg_csc_type == RGB2YUV) && (ipu->bg_csc_type == YUV2YUV)) ||
- + ((ipu->fg_csc_type == YUV2YUV) && (ipu->bg_csc_type == RGB2YUV)) ||
- + ((ipu->fg_csc_type == YUV2YUV) && (ipu->bg_csc_type == YUV2YUV)) ||
- + ((ipu->fg_csc_type == YUV2RGB) && (ipu->bg_csc_type == YUV2RGB))) {
- +
- + dev_dbg(ipu->dev, "color key 0x%x need change to yuv fmt\n", color_key);
- +
- + red = (color_key >> 16) & 0xFF;
- + green = (color_key >> 8) & 0xFF;
- + blue = color_key & 0xFF;
- +
- + y = _rgb_to_yuv(0, red, green, blue);
- + u = _rgb_to_yuv(1, red, green, blue);
- + v = _rgb_to_yuv(2, red, green, blue);
- + color_key = (y << 16) | (u << 8) | v;
- +
- + ipu->color_key_4rgb = false;
- +
- + dev_dbg(ipu->dev, "color key change to yuv fmt 0x%x\n", color_key);
- + }
- +
- + if (enable) {
- + reg = ipu_dp_read(ipu, DP_GRAPH_WIND_CTRL(flow)) & 0xFF000000L;
- + ipu_dp_write(ipu, reg | color_key, DP_GRAPH_WIND_CTRL(flow));
- +
- + reg = ipu_dp_read(ipu, DP_COM_CONF(flow));
- + ipu_dp_write(ipu, reg | DP_COM_CONF_GWCKE, DP_COM_CONF(flow));
- + } else {
- + reg = ipu_dp_read(ipu, DP_COM_CONF(flow));
- + ipu_dp_write(ipu, reg & ~DP_COM_CONF_GWCKE, DP_COM_CONF(flow));
- + }
- +
- + reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
- + ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
- +
- + mutex_unlock(&ipu->mutex_lock);
- +
- + _ipu_put(ipu);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(ipu_disp_set_color_key);
- +
- +/*!
- + * This function sets the gamma correction for DP output.
- + *
- + * @param ipu ipu handler
- + * @param channel Input parameter for the logical channel ID.
- + *
- + * @param enable Boolean to enable or disable gamma correction.
- + *
- + * @param constk Gamma piecewise linear approximation constk coeff.
- + *
- + * @param slopek Gamma piecewise linear approximation slopek coeff.
- + *
- + * @return Returns 0 on success or negative error code on fail
- + */
- +int32_t ipu_disp_set_gamma_correction(struct ipu_soc *ipu, ipu_channel_t channel, bool enable, int constk[], int slopek[])
- +{
- + uint32_t reg, flow, i;
- +
- + if (channel == MEM_BG_SYNC || channel == MEM_FG_SYNC)
- + flow = DP_SYNC;
- + else if (channel == MEM_BG_ASYNC0 || channel == MEM_FG_ASYNC0)
- + flow = DP_ASYNC0;
- + else if (channel == MEM_BG_ASYNC1 || channel == MEM_FG_ASYNC1)
- + flow = DP_ASYNC1;
- + else
- + return -EINVAL;
- +
- + _ipu_get(ipu);
- +
- + mutex_lock(&ipu->mutex_lock);
- +
- + for (i = 0; i < 8; i++)
- + ipu_dp_write(ipu, (constk[2*i] & 0x1ff) | ((constk[2*i+1] & 0x1ff) << 16), DP_GAMMA_C(flow, i));
- + for (i = 0; i < 4; i++)
- + ipu_dp_write(ipu, (slopek[4*i] & 0xff) | ((slopek[4*i+1] & 0xff) << 8) |
- + ((slopek[4*i+2] & 0xff) << 16) | ((slopek[4*i+3] & 0xff) << 24), DP_GAMMA_S(flow, i));
- +
- + reg = ipu_dp_read(ipu, DP_COM_CONF(flow));
- + if (enable) {
- + if ((ipu->bg_csc_type == RGB2YUV) || (ipu->bg_csc_type == YUV2YUV))
- + reg |= DP_COM_CONF_GAMMA_YUV_EN;
- + else
- + reg &= ~DP_COM_CONF_GAMMA_YUV_EN;
- + ipu_dp_write(ipu, reg | DP_COM_CONF_GAMMA_EN, DP_COM_CONF(flow));
- + } else
- + ipu_dp_write(ipu, reg & ~DP_COM_CONF_GAMMA_EN, DP_COM_CONF(flow));
- +
- + reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
- + ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
- +
- + mutex_unlock(&ipu->mutex_lock);
- +
- + _ipu_put(ipu);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(ipu_disp_set_gamma_correction);
- +
- +/*!
- + * This function sets the window position of the foreground or background plane.
- + * modes.
- + *
- + * @param ipu ipu handler
- + * @param channel Input parameter for the logical channel ID.
- + *
- + * @param x_pos The X coordinate position to place window at.
- + * The position is relative to the top left corner.
- + *
- + * @param y_pos The Y coordinate position to place window at.
- + * The position is relative to the top left corner.
- + *
- + * @return Returns 0 on success or negative error code on fail
- + */
- +int32_t _ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
- + int16_t x_pos, int16_t y_pos)
- +{
- + u32 reg;
- + uint32_t flow = 0;
- + uint32_t dp_srm_shift;
- +
- + if ((channel == MEM_FG_SYNC) || (channel == MEM_BG_SYNC)) {
- + flow = DP_SYNC;
- + dp_srm_shift = 3;
- + } else if (channel == MEM_FG_ASYNC0) {
- + flow = DP_ASYNC0;
- + dp_srm_shift = 5;
- + } else if (channel == MEM_FG_ASYNC1) {
- + flow = DP_ASYNC1;
- + dp_srm_shift = 7;
- + } else
- + return -EINVAL;
- +
- + ipu_dp_write(ipu, (x_pos << 16) | y_pos, DP_FG_POS(flow));
- +
- + if (ipu_is_channel_busy(ipu, channel)) {
- + /* controled by FSU if channel enabled */
- + reg = ipu_cm_read(ipu, IPU_SRM_PRI2) & (~(0x3 << dp_srm_shift));
- + reg |= (0x1 << dp_srm_shift);
- + ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
- + } else {
- + /* disable auto swap, controled by MCU if channel disabled */
- + reg = ipu_cm_read(ipu, IPU_SRM_PRI2) & (~(0x3 << dp_srm_shift));
- + ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
- + }
- +
- + return 0;
- +}
- +
- +int32_t ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
- + int16_t x_pos, int16_t y_pos)
- +{
- + int ret;
- +
- + _ipu_get(ipu);
- + mutex_lock(&ipu->mutex_lock);
- + ret = _ipu_disp_set_window_pos(ipu, channel, x_pos, y_pos);
- + mutex_unlock(&ipu->mutex_lock);
- + _ipu_put(ipu);
- + return ret;
- +}
- +EXPORT_SYMBOL(ipu_disp_set_window_pos);
- +
- +int32_t _ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
- + int16_t *x_pos, int16_t *y_pos)
- +{
- + u32 reg;
- + uint32_t flow = 0;
- +
- + if (channel == MEM_FG_SYNC)
- + flow = DP_SYNC;
- + else if (channel == MEM_FG_ASYNC0)
- + flow = DP_ASYNC0;
- + else if (channel == MEM_FG_ASYNC1)
- + flow = DP_ASYNC1;
- + else
- + return -EINVAL;
- +
- + reg = ipu_dp_read(ipu, DP_FG_POS(flow));
- +
- + *x_pos = (reg >> 16) & 0x7FF;
- + *y_pos = reg & 0x7FF;
- +
- + return 0;
- +}
- +int32_t ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
- + int16_t *x_pos, int16_t *y_pos)
- +{
- + int ret;
- +
- + _ipu_get(ipu);
- + mutex_lock(&ipu->mutex_lock);
- + ret = _ipu_disp_get_window_pos(ipu, channel, x_pos, y_pos);
- + mutex_unlock(&ipu->mutex_lock);
- + _ipu_put(ipu);
- + return ret;
- +}
- +EXPORT_SYMBOL(ipu_disp_get_window_pos);
- +
- +void ipu_disp_direct_write(struct ipu_soc *ipu, ipu_channel_t channel, u32 value, u32 offset)
- +{
- + if (channel == DIRECT_ASYNC0)
- + writel(value, ipu->disp_base[0] + offset);
- + else if (channel == DIRECT_ASYNC1)
- + writel(value, ipu->disp_base[1] + offset);
- +}
- +EXPORT_SYMBOL(ipu_disp_direct_write);
- +
- +void ipu_reset_disp_panel(struct ipu_soc *ipu)
- +{
- + uint32_t tmp;
- +
- + tmp = ipu_di_read(ipu, 1, DI_GENERAL);
- + ipu_di_write(ipu, 1, tmp | 0x08, DI_GENERAL);
- + msleep(10); /* tRES >= 100us */
- + tmp = ipu_di_read(ipu, 1, DI_GENERAL);
- + ipu_di_write(ipu, 1, tmp & ~0x08, DI_GENERAL);
- + msleep(60);
- +
- + return;
- +}
- +EXPORT_SYMBOL(ipu_reset_disp_panel);
- +
- +void ipu_disp_init(struct ipu_soc *ipu)
- +{
- + ipu->fg_csc_type = ipu->bg_csc_type = CSC_NONE;
- + ipu->color_key_4rgb = true;
- + _ipu_init_dc_mappings(ipu);
- + _ipu_dmfc_init(ipu, DMFC_NORMAL, 1);
- +}
- diff -Nur linux-3.14.35.orig/drivers/mxc/ipu3/ipu_ic.c linux-3.14.35/drivers/mxc/ipu3/ipu_ic.c
- --- linux-3.14.35.orig/drivers/mxc/ipu3/ipu_ic.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/ipu3/ipu_ic.c 2015-03-08 14:27:37.665684500 -0500
- @@ -0,0 +1,924 @@
- +/*
- + * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*
- + * @file ipu_ic.c
- + *
- + * @brief IPU IC functions
- + *
- + * @ingroup IPU
- + */
- +#include <linux/errno.h>
- +#include <linux/init.h>
- +#include <linux/io.h>
- +#include <linux/ipu-v3.h>
- +#include <linux/spinlock.h>
- +#include <linux/types.h>
- +#include <linux/videodev2.h>
- +
- +#include "ipu_param_mem.h"
- +#include "ipu_regs.h"
- +
- +enum {
- + IC_TASK_VIEWFINDER,
- + IC_TASK_ENCODER,
- + IC_TASK_POST_PROCESSOR
- +};
- +
- +static void _init_csc(struct ipu_soc *ipu, uint8_t ic_task, ipu_color_space_t in_format,
- + ipu_color_space_t out_format, int csc_index);
- +
- +static int _calc_resize_coeffs(struct ipu_soc *ipu,
- + uint32_t inSize, uint32_t outSize,
- + uint32_t *resizeCoeff,
- + uint32_t *downsizeCoeff);
- +
- +void _ipu_vdi_set_top_field_man(struct ipu_soc *ipu, bool top_field_0)
- +{
- + uint32_t reg;
- +
- + reg = ipu_vdi_read(ipu, VDI_C);
- + if (top_field_0)
- + reg &= ~VDI_C_TOP_FIELD_MAN_1;
- + else
- + reg |= VDI_C_TOP_FIELD_MAN_1;
- + ipu_vdi_write(ipu, reg, VDI_C);
- +}
- +
- +void _ipu_vdi_set_motion(struct ipu_soc *ipu, ipu_motion_sel motion_sel)
- +{
- + uint32_t reg;
- +
- + reg = ipu_vdi_read(ipu, VDI_C);
- + reg &= ~(VDI_C_MOT_SEL_FULL | VDI_C_MOT_SEL_MED | VDI_C_MOT_SEL_LOW);
- + if (motion_sel == HIGH_MOTION)
- + reg |= VDI_C_MOT_SEL_FULL;
- + else if (motion_sel == MED_MOTION)
- + reg |= VDI_C_MOT_SEL_MED;
- + else
- + reg |= VDI_C_MOT_SEL_LOW;
- +
- + ipu_vdi_write(ipu, reg, VDI_C);
- + dev_dbg(ipu->dev, "VDI_C = \t0x%08X\n", reg);
- +}
- +
- +void ic_dump_register(struct ipu_soc *ipu)
- +{
- + printk(KERN_DEBUG "IC_CONF = \t0x%08X\n", ipu_ic_read(ipu, IC_CONF));
- + printk(KERN_DEBUG "IC_PRP_ENC_RSC = \t0x%08X\n",
- + ipu_ic_read(ipu, IC_PRP_ENC_RSC));
- + printk(KERN_DEBUG "IC_PRP_VF_RSC = \t0x%08X\n",
- + ipu_ic_read(ipu, IC_PRP_VF_RSC));
- + printk(KERN_DEBUG "IC_PP_RSC = \t0x%08X\n", ipu_ic_read(ipu, IC_PP_RSC));
- + printk(KERN_DEBUG "IC_IDMAC_1 = \t0x%08X\n", ipu_ic_read(ipu, IC_IDMAC_1));
- + printk(KERN_DEBUG "IC_IDMAC_2 = \t0x%08X\n", ipu_ic_read(ipu, IC_IDMAC_2));
- + printk(KERN_DEBUG "IC_IDMAC_3 = \t0x%08X\n", ipu_ic_read(ipu, IC_IDMAC_3));
- +}
- +
- +void _ipu_ic_enable_task(struct ipu_soc *ipu, ipu_channel_t channel)
- +{
- + uint32_t ic_conf;
- +
- + ic_conf = ipu_ic_read(ipu, IC_CONF);
- + switch (channel) {
- + case CSI_PRP_VF_MEM:
- + case MEM_PRP_VF_MEM:
- + ic_conf |= IC_CONF_PRPVF_EN;
- + break;
- + case MEM_VDI_PRP_VF_MEM:
- + ic_conf |= IC_CONF_PRPVF_EN;
- + break;
- + case MEM_VDI_MEM:
- + ic_conf |= IC_CONF_PRPVF_EN | IC_CONF_RWS_EN ;
- + break;
- + case MEM_ROT_VF_MEM:
- + ic_conf |= IC_CONF_PRPVF_ROT_EN;
- + break;
- + case CSI_PRP_ENC_MEM:
- + case MEM_PRP_ENC_MEM:
- + ic_conf |= IC_CONF_PRPENC_EN;
- + break;
- + case MEM_ROT_ENC_MEM:
- + ic_conf |= IC_CONF_PRPENC_ROT_EN;
- + break;
- + case MEM_PP_MEM:
- + ic_conf |= IC_CONF_PP_EN;
- + break;
- + case MEM_ROT_PP_MEM:
- + ic_conf |= IC_CONF_PP_ROT_EN;
- + break;
- + default:
- + break;
- + }
- + ipu_ic_write(ipu, ic_conf, IC_CONF);
- +}
- +
- +void _ipu_ic_disable_task(struct ipu_soc *ipu, ipu_channel_t channel)
- +{
- + uint32_t ic_conf;
- +
- + ic_conf = ipu_ic_read(ipu, IC_CONF);
- + switch (channel) {
- + case CSI_PRP_VF_MEM:
- + case MEM_PRP_VF_MEM:
- + ic_conf &= ~IC_CONF_PRPVF_EN;
- + break;
- + case MEM_VDI_PRP_VF_MEM:
- + ic_conf &= ~IC_CONF_PRPVF_EN;
- + break;
- + case MEM_VDI_MEM:
- + ic_conf &= ~(IC_CONF_PRPVF_EN | IC_CONF_RWS_EN);
- + break;
- + case MEM_ROT_VF_MEM:
- + ic_conf &= ~IC_CONF_PRPVF_ROT_EN;
- + break;
- + case CSI_PRP_ENC_MEM:
- + case MEM_PRP_ENC_MEM:
- + ic_conf &= ~IC_CONF_PRPENC_EN;
- + break;
- + case MEM_ROT_ENC_MEM:
- + ic_conf &= ~IC_CONF_PRPENC_ROT_EN;
- + break;
- + case MEM_PP_MEM:
- + ic_conf &= ~IC_CONF_PP_EN;
- + break;
- + case MEM_ROT_PP_MEM:
- + ic_conf &= ~IC_CONF_PP_ROT_EN;
- + break;
- + default:
- + break;
- + }
- + ipu_ic_write(ipu, ic_conf, IC_CONF);
- +}
- +
- +void _ipu_vdi_init(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel_params_t *params)
- +{
- + uint32_t reg;
- + uint32_t pixel_fmt;
- + uint32_t pix_per_burst;
- +
- + reg = ((params->mem_prp_vf_mem.in_height-1) << 16) |
- + (params->mem_prp_vf_mem.in_width-1);
- + ipu_vdi_write(ipu, reg, VDI_FSIZE);
- +
- + /* Full motion, only vertical filter is used
- + Burst size is 4 accesses */
- + if (params->mem_prp_vf_mem.in_pixel_fmt ==
- + IPU_PIX_FMT_UYVY ||
- + params->mem_prp_vf_mem.in_pixel_fmt ==
- + IPU_PIX_FMT_YUYV) {
- + pixel_fmt = VDI_C_CH_422;
- + pix_per_burst = 32;
- + } else {
- + pixel_fmt = VDI_C_CH_420;
- + pix_per_burst = 64;
- + }
- +
- + reg = ipu_vdi_read(ipu, VDI_C);
- + reg |= pixel_fmt;
- + switch (channel) {
- + case MEM_VDI_PRP_VF_MEM:
- + reg |= VDI_C_BURST_SIZE2_4;
- + break;
- + case MEM_VDI_PRP_VF_MEM_P:
- + reg |= VDI_C_BURST_SIZE1_4 | VDI_C_VWM1_SET_1 | VDI_C_VWM1_CLR_2;
- + break;
- + case MEM_VDI_PRP_VF_MEM_N:
- + reg |= VDI_C_BURST_SIZE3_4 | VDI_C_VWM3_SET_1 | VDI_C_VWM3_CLR_2;
- + break;
- +
- + case MEM_VDI_MEM:
- + reg |= (((pix_per_burst >> 2) - 1) & VDI_C_BURST_SIZE_MASK)
- + << VDI_C_BURST_SIZE2_OFFSET;
- + break;
- + case MEM_VDI_MEM_P:
- + reg |= (((pix_per_burst >> 2) - 1) & VDI_C_BURST_SIZE_MASK)
- + << VDI_C_BURST_SIZE1_OFFSET;
- + reg |= VDI_C_VWM1_SET_2 | VDI_C_VWM1_CLR_2;
- + break;
- + case MEM_VDI_MEM_N:
- + reg |= (((pix_per_burst >> 2) - 1) & VDI_C_BURST_SIZE_MASK)
- + << VDI_C_BURST_SIZE3_OFFSET;
- + reg |= VDI_C_VWM3_SET_2 | VDI_C_VWM3_CLR_2;
- + break;
- + default:
- + break;
- + }
- + ipu_vdi_write(ipu, reg, VDI_C);
- +
- + if (params->mem_prp_vf_mem.field_fmt == IPU_DEINTERLACE_FIELD_TOP)
- + _ipu_vdi_set_top_field_man(ipu, true);
- + else if (params->mem_prp_vf_mem.field_fmt == IPU_DEINTERLACE_FIELD_BOTTOM)
- + _ipu_vdi_set_top_field_man(ipu, false);
- +
- + _ipu_vdi_set_motion(ipu, params->mem_prp_vf_mem.motion_sel);
- +
- + reg = ipu_ic_read(ipu, IC_CONF);
- + reg &= ~IC_CONF_RWS_EN;
- + ipu_ic_write(ipu, reg, IC_CONF);
- +}
- +
- +void _ipu_vdi_uninit(struct ipu_soc *ipu)
- +{
- + ipu_vdi_write(ipu, 0, VDI_FSIZE);
- + ipu_vdi_write(ipu, 0, VDI_C);
- +}
- +
- +int _ipu_ic_init_prpvf(struct ipu_soc *ipu, ipu_channel_params_t *params,
- + bool src_is_csi)
- +{
- + uint32_t reg, ic_conf;
- + uint32_t downsizeCoeff, resizeCoeff;
- + ipu_color_space_t in_fmt, out_fmt;
- + int ret = 0;
- +
- + /* Setup vertical resizing */
- + if (!params->mem_prp_vf_mem.outv_resize_ratio) {
- + ret = _calc_resize_coeffs(ipu, params->mem_prp_vf_mem.in_height,
- + params->mem_prp_vf_mem.out_height,
- + &resizeCoeff, &downsizeCoeff);
- + if (ret < 0) {
- + dev_err(ipu->dev, "failed to calculate prpvf height "
- + "scaling coefficients\n");
- + return ret;
- + }
- +
- + reg = (downsizeCoeff << 30) | (resizeCoeff << 16);
- + } else
- + reg = (params->mem_prp_vf_mem.outv_resize_ratio) << 16;
- +
- + /* Setup horizontal resizing */
- + if (!params->mem_prp_vf_mem.outh_resize_ratio) {
- + ret = _calc_resize_coeffs(ipu, params->mem_prp_vf_mem.in_width,
- + params->mem_prp_vf_mem.out_width,
- + &resizeCoeff, &downsizeCoeff);
- + if (ret < 0) {
- + dev_err(ipu->dev, "failed to calculate prpvf width "
- + "scaling coefficients\n");
- + return ret;
- + }
- +
- + reg |= (downsizeCoeff << 14) | resizeCoeff;
- + } else
- + reg |= params->mem_prp_vf_mem.outh_resize_ratio;
- +
- + ipu_ic_write(ipu, reg, IC_PRP_VF_RSC);
- +
- + ic_conf = ipu_ic_read(ipu, IC_CONF);
- +
- + /* Setup color space conversion */
- + in_fmt = format_to_colorspace(params->mem_prp_vf_mem.in_pixel_fmt);
- + out_fmt = format_to_colorspace(params->mem_prp_vf_mem.out_pixel_fmt);
- + if (in_fmt == RGB) {
- + if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
- + /* Enable RGB->YCBCR CSC1 */
- + _init_csc(ipu, IC_TASK_VIEWFINDER, RGB, out_fmt, 1);
- + ic_conf |= IC_CONF_PRPVF_CSC1;
- + }
- + }
- + if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
- + if (out_fmt == RGB) {
- + /* Enable YCBCR->RGB CSC1 */
- + _init_csc(ipu, IC_TASK_VIEWFINDER, YCbCr, RGB, 1);
- + ic_conf |= IC_CONF_PRPVF_CSC1;
- + } else {
- + /* TODO: Support YUV<->YCbCr conversion? */
- + }
- + }
- +
- + if (params->mem_prp_vf_mem.graphics_combine_en) {
- + ic_conf |= IC_CONF_PRPVF_CMB;
- +
- + if (!(ic_conf & IC_CONF_PRPVF_CSC1)) {
- + /* need transparent CSC1 conversion */
- + _init_csc(ipu, IC_TASK_VIEWFINDER, RGB, RGB, 1);
- + ic_conf |= IC_CONF_PRPVF_CSC1; /* Enable RGB->RGB CSC */
- + }
- + in_fmt = format_to_colorspace(params->mem_prp_vf_mem.in_g_pixel_fmt);
- + out_fmt = format_to_colorspace(params->mem_prp_vf_mem.out_pixel_fmt);
- + if (in_fmt == RGB) {
- + if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
- + /* Enable RGB->YCBCR CSC2 */
- + _init_csc(ipu, IC_TASK_VIEWFINDER, RGB, out_fmt, 2);
- + ic_conf |= IC_CONF_PRPVF_CSC2;
- + }
- + }
- + if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
- + if (out_fmt == RGB) {
- + /* Enable YCBCR->RGB CSC2 */
- + _init_csc(ipu, IC_TASK_VIEWFINDER, YCbCr, RGB, 2);
- + ic_conf |= IC_CONF_PRPVF_CSC2;
- + } else {
- + /* TODO: Support YUV<->YCbCr conversion? */
- + }
- + }
- +
- + if (params->mem_prp_vf_mem.global_alpha_en) {
- + ic_conf |= IC_CONF_IC_GLB_LOC_A;
- + reg = ipu_ic_read(ipu, IC_CMBP_1);
- + reg &= ~(0xff);
- + reg |= params->mem_prp_vf_mem.alpha;
- + ipu_ic_write(ipu, reg, IC_CMBP_1);
- + } else
- + ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
- +
- + if (params->mem_prp_vf_mem.key_color_en) {
- + ic_conf |= IC_CONF_KEY_COLOR_EN;
- + ipu_ic_write(ipu, params->mem_prp_vf_mem.key_color,
- + IC_CMBP_2);
- + } else
- + ic_conf &= ~IC_CONF_KEY_COLOR_EN;
- + } else {
- + ic_conf &= ~IC_CONF_PRPVF_CMB;
- + }
- +
- + if (src_is_csi)
- + ic_conf &= ~IC_CONF_RWS_EN;
- + else
- + ic_conf |= IC_CONF_RWS_EN;
- +
- + ipu_ic_write(ipu, ic_conf, IC_CONF);
- +
- + return ret;
- +}
- +
- +void _ipu_ic_uninit_prpvf(struct ipu_soc *ipu)
- +{
- + uint32_t reg;
- +
- + reg = ipu_ic_read(ipu, IC_CONF);
- + reg &= ~(IC_CONF_PRPVF_EN | IC_CONF_PRPVF_CMB |
- + IC_CONF_PRPVF_CSC2 | IC_CONF_PRPVF_CSC1);
- + ipu_ic_write(ipu, reg, IC_CONF);
- +}
- +
- +void _ipu_ic_init_rotate_vf(struct ipu_soc *ipu, ipu_channel_params_t *params)
- +{
- +}
- +
- +void _ipu_ic_uninit_rotate_vf(struct ipu_soc *ipu)
- +{
- + uint32_t reg;
- + reg = ipu_ic_read(ipu, IC_CONF);
- + reg &= ~IC_CONF_PRPVF_ROT_EN;
- + ipu_ic_write(ipu, reg, IC_CONF);
- +}
- +
- +int _ipu_ic_init_prpenc(struct ipu_soc *ipu, ipu_channel_params_t *params,
- + bool src_is_csi)
- +{
- + uint32_t reg, ic_conf;
- + uint32_t downsizeCoeff, resizeCoeff;
- + ipu_color_space_t in_fmt, out_fmt;
- + int ret = 0;
- +
- + /* Setup vertical resizing */
- + if (!params->mem_prp_enc_mem.outv_resize_ratio) {
- + ret = _calc_resize_coeffs(ipu,
- + params->mem_prp_enc_mem.in_height,
- + params->mem_prp_enc_mem.out_height,
- + &resizeCoeff, &downsizeCoeff);
- + if (ret < 0) {
- + dev_err(ipu->dev, "failed to calculate prpenc height "
- + "scaling coefficients\n");
- + return ret;
- + }
- +
- + reg = (downsizeCoeff << 30) | (resizeCoeff << 16);
- + } else
- + reg = (params->mem_prp_enc_mem.outv_resize_ratio) << 16;
- +
- + /* Setup horizontal resizing */
- + if (!params->mem_prp_enc_mem.outh_resize_ratio) {
- + ret = _calc_resize_coeffs(ipu, params->mem_prp_enc_mem.in_width,
- + params->mem_prp_enc_mem.out_width,
- + &resizeCoeff, &downsizeCoeff);
- + if (ret < 0) {
- + dev_err(ipu->dev, "failed to calculate prpenc width "
- + "scaling coefficients\n");
- + return ret;
- + }
- +
- + reg |= (downsizeCoeff << 14) | resizeCoeff;
- + } else
- + reg |= params->mem_prp_enc_mem.outh_resize_ratio;
- +
- + ipu_ic_write(ipu, reg, IC_PRP_ENC_RSC);
- +
- + ic_conf = ipu_ic_read(ipu, IC_CONF);
- +
- + /* Setup color space conversion */
- + in_fmt = format_to_colorspace(params->mem_prp_enc_mem.in_pixel_fmt);
- + out_fmt = format_to_colorspace(params->mem_prp_enc_mem.out_pixel_fmt);
- + if (in_fmt == RGB) {
- + if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
- + /* Enable RGB->YCBCR CSC1 */
- + _init_csc(ipu, IC_TASK_ENCODER, RGB, out_fmt, 1);
- + ic_conf |= IC_CONF_PRPENC_CSC1;
- + }
- + }
- + if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
- + if (out_fmt == RGB) {
- + /* Enable YCBCR->RGB CSC1 */
- + _init_csc(ipu, IC_TASK_ENCODER, YCbCr, RGB, 1);
- + ic_conf |= IC_CONF_PRPENC_CSC1;
- + } else {
- + /* TODO: Support YUV<->YCbCr conversion? */
- + }
- + }
- +
- + if (src_is_csi)
- + ic_conf &= ~IC_CONF_RWS_EN;
- + else
- + ic_conf |= IC_CONF_RWS_EN;
- +
- + ipu_ic_write(ipu, ic_conf, IC_CONF);
- +
- + return ret;
- +}
- +
- +void _ipu_ic_uninit_prpenc(struct ipu_soc *ipu)
- +{
- + uint32_t reg;
- +
- + reg = ipu_ic_read(ipu, IC_CONF);
- + reg &= ~(IC_CONF_PRPENC_EN | IC_CONF_PRPENC_CSC1);
- + ipu_ic_write(ipu, reg, IC_CONF);
- +}
- +
- +void _ipu_ic_init_rotate_enc(struct ipu_soc *ipu, ipu_channel_params_t *params)
- +{
- +}
- +
- +void _ipu_ic_uninit_rotate_enc(struct ipu_soc *ipu)
- +{
- + uint32_t reg;
- +
- + reg = ipu_ic_read(ipu, IC_CONF);
- + reg &= ~(IC_CONF_PRPENC_ROT_EN);
- + ipu_ic_write(ipu, reg, IC_CONF);
- +}
- +
- +int _ipu_ic_init_pp(struct ipu_soc *ipu, ipu_channel_params_t *params)
- +{
- + uint32_t reg, ic_conf;
- + uint32_t downsizeCoeff, resizeCoeff;
- + ipu_color_space_t in_fmt, out_fmt;
- + int ret = 0;
- +
- + /* Setup vertical resizing */
- + if (!params->mem_pp_mem.outv_resize_ratio) {
- + ret = _calc_resize_coeffs(ipu, params->mem_pp_mem.in_height,
- + params->mem_pp_mem.out_height,
- + &resizeCoeff, &downsizeCoeff);
- + if (ret < 0) {
- + dev_err(ipu->dev, "failed to calculate pp height "
- + "scaling coefficients\n");
- + return ret;
- + }
- +
- + reg = (downsizeCoeff << 30) | (resizeCoeff << 16);
- + } else {
- + reg = (params->mem_pp_mem.outv_resize_ratio) << 16;
- + }
- +
- + /* Setup horizontal resizing */
- + if (!params->mem_pp_mem.outh_resize_ratio) {
- + ret = _calc_resize_coeffs(ipu, params->mem_pp_mem.in_width,
- + params->mem_pp_mem.out_width,
- + &resizeCoeff, &downsizeCoeff);
- + if (ret < 0) {
- + dev_err(ipu->dev, "failed to calculate pp width "
- + "scaling coefficients\n");
- + return ret;
- + }
- +
- + reg |= (downsizeCoeff << 14) | resizeCoeff;
- + } else {
- + reg |= params->mem_pp_mem.outh_resize_ratio;
- + }
- +
- + ipu_ic_write(ipu, reg, IC_PP_RSC);
- +
- + ic_conf = ipu_ic_read(ipu, IC_CONF);
- +
- + /* Setup color space conversion */
- + in_fmt = format_to_colorspace(params->mem_pp_mem.in_pixel_fmt);
- + out_fmt = format_to_colorspace(params->mem_pp_mem.out_pixel_fmt);
- + if (in_fmt == RGB) {
- + if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
- + /* Enable RGB->YCBCR CSC1 */
- + _init_csc(ipu, IC_TASK_POST_PROCESSOR, RGB, out_fmt, 1);
- + ic_conf |= IC_CONF_PP_CSC1;
- + }
- + }
- + if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
- + if (out_fmt == RGB) {
- + /* Enable YCBCR->RGB CSC1 */
- + _init_csc(ipu, IC_TASK_POST_PROCESSOR, YCbCr, RGB, 1);
- + ic_conf |= IC_CONF_PP_CSC1;
- + } else {
- + /* TODO: Support YUV<->YCbCr conversion? */
- + }
- + }
- +
- + if (params->mem_pp_mem.graphics_combine_en) {
- + ic_conf |= IC_CONF_PP_CMB;
- +
- + if (!(ic_conf & IC_CONF_PP_CSC1)) {
- + /* need transparent CSC1 conversion */
- + _init_csc(ipu, IC_TASK_POST_PROCESSOR, RGB, RGB, 1);
- + ic_conf |= IC_CONF_PP_CSC1; /* Enable RGB->RGB CSC */
- + }
- +
- + in_fmt = format_to_colorspace(params->mem_pp_mem.in_g_pixel_fmt);
- + out_fmt = format_to_colorspace(params->mem_pp_mem.out_pixel_fmt);
- + if (in_fmt == RGB) {
- + if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
- + /* Enable RGB->YCBCR CSC2 */
- + _init_csc(ipu, IC_TASK_POST_PROCESSOR, RGB, out_fmt, 2);
- + ic_conf |= IC_CONF_PP_CSC2;
- + }
- + }
- + if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
- + if (out_fmt == RGB) {
- + /* Enable YCBCR->RGB CSC2 */
- + _init_csc(ipu, IC_TASK_POST_PROCESSOR, YCbCr, RGB, 2);
- + ic_conf |= IC_CONF_PP_CSC2;
- + } else {
- + /* TODO: Support YUV<->YCbCr conversion? */
- + }
- + }
- +
- + if (params->mem_pp_mem.global_alpha_en) {
- + ic_conf |= IC_CONF_IC_GLB_LOC_A;
- + reg = ipu_ic_read(ipu, IC_CMBP_1);
- + reg &= ~(0xff00);
- + reg |= (params->mem_pp_mem.alpha << 8);
- + ipu_ic_write(ipu, reg, IC_CMBP_1);
- + } else
- + ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
- +
- + if (params->mem_pp_mem.key_color_en) {
- + ic_conf |= IC_CONF_KEY_COLOR_EN;
- + ipu_ic_write(ipu, params->mem_pp_mem.key_color,
- + IC_CMBP_2);
- + } else
- + ic_conf &= ~IC_CONF_KEY_COLOR_EN;
- + } else {
- + ic_conf &= ~IC_CONF_PP_CMB;
- + }
- +
- + ipu_ic_write(ipu, ic_conf, IC_CONF);
- +
- + return ret;
- +}
- +
- +void _ipu_ic_uninit_pp(struct ipu_soc *ipu)
- +{
- + uint32_t reg;
- +
- + reg = ipu_ic_read(ipu, IC_CONF);
- + reg &= ~(IC_CONF_PP_EN | IC_CONF_PP_CSC1 | IC_CONF_PP_CSC2 |
- + IC_CONF_PP_CMB);
- + ipu_ic_write(ipu, reg, IC_CONF);
- +}
- +
- +void _ipu_ic_init_rotate_pp(struct ipu_soc *ipu, ipu_channel_params_t *params)
- +{
- +}
- +
- +void _ipu_ic_uninit_rotate_pp(struct ipu_soc *ipu)
- +{
- + uint32_t reg;
- + reg = ipu_ic_read(ipu, IC_CONF);
- + reg &= ~IC_CONF_PP_ROT_EN;
- + ipu_ic_write(ipu, reg, IC_CONF);
- +}
- +
- +int _ipu_ic_idma_init(struct ipu_soc *ipu, int dma_chan,
- + uint16_t width, uint16_t height,
- + int burst_size, ipu_rotate_mode_t rot)
- +{
- + u32 ic_idmac_1, ic_idmac_2, ic_idmac_3;
- + u32 temp_rot = bitrev8(rot) >> 5;
- + bool need_hor_flip = false;
- +
- + if ((burst_size != 8) && (burst_size != 16)) {
- + dev_dbg(ipu->dev, "Illegal burst length for IC\n");
- + return -EINVAL;
- + }
- +
- + width--;
- + height--;
- +
- + if (temp_rot & 0x2) /* Need horizontal flip */
- + need_hor_flip = true;
- +
- + ic_idmac_1 = ipu_ic_read(ipu, IC_IDMAC_1);
- + ic_idmac_2 = ipu_ic_read(ipu, IC_IDMAC_2);
- + ic_idmac_3 = ipu_ic_read(ipu, IC_IDMAC_3);
- + if (dma_chan == 22) { /* PP output - CB2 */
- + if (burst_size == 16)
- + ic_idmac_1 |= IC_IDMAC_1_CB2_BURST_16;
- + else
- + ic_idmac_1 &= ~IC_IDMAC_1_CB2_BURST_16;
- +
- + if (need_hor_flip)
- + ic_idmac_1 |= IC_IDMAC_1_PP_FLIP_RS;
- + else
- + ic_idmac_1 &= ~IC_IDMAC_1_PP_FLIP_RS;
- +
- + ic_idmac_2 &= ~IC_IDMAC_2_PP_HEIGHT_MASK;
- + ic_idmac_2 |= height << IC_IDMAC_2_PP_HEIGHT_OFFSET;
- +
- + ic_idmac_3 &= ~IC_IDMAC_3_PP_WIDTH_MASK;
- + ic_idmac_3 |= width << IC_IDMAC_3_PP_WIDTH_OFFSET;
- + } else if (dma_chan == 11) { /* PP Input - CB5 */
- + if (burst_size == 16)
- + ic_idmac_1 |= IC_IDMAC_1_CB5_BURST_16;
- + else
- + ic_idmac_1 &= ~IC_IDMAC_1_CB5_BURST_16;
- + } else if (dma_chan == 47) { /* PP Rot input */
- + ic_idmac_1 &= ~IC_IDMAC_1_PP_ROT_MASK;
- + ic_idmac_1 |= temp_rot << IC_IDMAC_1_PP_ROT_OFFSET;
- + }
- +
- + if (dma_chan == 12) { /* PRP Input - CB6 */
- + if (burst_size == 16)
- + ic_idmac_1 |= IC_IDMAC_1_CB6_BURST_16;
- + else
- + ic_idmac_1 &= ~IC_IDMAC_1_CB6_BURST_16;
- + }
- +
- + if (dma_chan == 20) { /* PRP ENC output - CB0 */
- + if (burst_size == 16)
- + ic_idmac_1 |= IC_IDMAC_1_CB0_BURST_16;
- + else
- + ic_idmac_1 &= ~IC_IDMAC_1_CB0_BURST_16;
- +
- + if (need_hor_flip)
- + ic_idmac_1 |= IC_IDMAC_1_PRPENC_FLIP_RS;
- + else
- + ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_FLIP_RS;
- +
- + ic_idmac_2 &= ~IC_IDMAC_2_PRPENC_HEIGHT_MASK;
- + ic_idmac_2 |= height << IC_IDMAC_2_PRPENC_HEIGHT_OFFSET;
- +
- + ic_idmac_3 &= ~IC_IDMAC_3_PRPENC_WIDTH_MASK;
- + ic_idmac_3 |= width << IC_IDMAC_3_PRPENC_WIDTH_OFFSET;
- +
- + } else if (dma_chan == 45) { /* PRP ENC Rot input */
- + ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_ROT_MASK;
- + ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPENC_ROT_OFFSET;
- + }
- +
- + if (dma_chan == 21) { /* PRP VF output - CB1 */
- + if (burst_size == 16)
- + ic_idmac_1 |= IC_IDMAC_1_CB1_BURST_16;
- + else
- + ic_idmac_1 &= ~IC_IDMAC_1_CB1_BURST_16;
- +
- + if (need_hor_flip)
- + ic_idmac_1 |= IC_IDMAC_1_PRPVF_FLIP_RS;
- + else
- + ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_FLIP_RS;
- +
- + ic_idmac_2 &= ~IC_IDMAC_2_PRPVF_HEIGHT_MASK;
- + ic_idmac_2 |= height << IC_IDMAC_2_PRPVF_HEIGHT_OFFSET;
- +
- + ic_idmac_3 &= ~IC_IDMAC_3_PRPVF_WIDTH_MASK;
- + ic_idmac_3 |= width << IC_IDMAC_3_PRPVF_WIDTH_OFFSET;
- +
- + } else if (dma_chan == 46) { /* PRP VF Rot input */
- + ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_ROT_MASK;
- + ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPVF_ROT_OFFSET;
- + }
- +
- + if (dma_chan == 14) { /* PRP VF graphics combining input - CB3 */
- + if (burst_size == 16)
- + ic_idmac_1 |= IC_IDMAC_1_CB3_BURST_16;
- + else
- + ic_idmac_1 &= ~IC_IDMAC_1_CB3_BURST_16;
- + } else if (dma_chan == 15) { /* PP graphics combining input - CB4 */
- + if (burst_size == 16)
- + ic_idmac_1 |= IC_IDMAC_1_CB4_BURST_16;
- + else
- + ic_idmac_1 &= ~IC_IDMAC_1_CB4_BURST_16;
- + } else if (dma_chan == 5) { /* VDIC OUTPUT - CB7 */
- + if (burst_size == 16)
- + ic_idmac_1 |= IC_IDMAC_1_CB7_BURST_16;
- + else
- + ic_idmac_1 &= ~IC_IDMAC_1_CB7_BURST_16;
- + }
- +
- + ipu_ic_write(ipu, ic_idmac_1, IC_IDMAC_1);
- + ipu_ic_write(ipu, ic_idmac_2, IC_IDMAC_2);
- + ipu_ic_write(ipu, ic_idmac_3, IC_IDMAC_3);
- + return 0;
- +}
- +
- +static void _init_csc(struct ipu_soc *ipu, uint8_t ic_task, ipu_color_space_t in_format,
- + ipu_color_space_t out_format, int csc_index)
- +{
- + /*
- + * Y = 0.257 * R + 0.504 * G + 0.098 * B + 16;
- + * U = -0.148 * R - 0.291 * G + 0.439 * B + 128;
- + * V = 0.439 * R - 0.368 * G - 0.071 * B + 128;
- + */
- + static const uint32_t rgb2ycbcr_coeff[4][3] = {
- + {0x0042, 0x0081, 0x0019},
- + {0x01DA, 0x01B6, 0x0070},
- + {0x0070, 0x01A2, 0x01EE},
- + {0x0040, 0x0200, 0x0200}, /* A0, A1, A2 */
- + };
- +
- + /* transparent RGB->RGB matrix for combining
- + */
- + static const uint32_t rgb2rgb_coeff[4][3] = {
- + {0x0080, 0x0000, 0x0000},
- + {0x0000, 0x0080, 0x0000},
- + {0x0000, 0x0000, 0x0080},
- + {0x0000, 0x0000, 0x0000}, /* A0, A1, A2 */
- + };
- +
- +/* R = (1.164 * (Y - 16)) + (1.596 * (Cr - 128));
- + G = (1.164 * (Y - 16)) - (0.392 * (Cb - 128)) - (0.813 * (Cr - 128));
- + B = (1.164 * (Y - 16)) + (2.017 * (Cb - 128); */
- + static const uint32_t ycbcr2rgb_coeff[4][3] = {
- + {149, 0, 204},
- + {149, 462, 408},
- + {149, 255, 0},
- + {8192 - 446, 266, 8192 - 554}, /* A0, A1, A2 */
- + };
- +
- + uint32_t param;
- + uint32_t *base = NULL;
- +
- + if (ic_task == IC_TASK_ENCODER) {
- + base = (uint32_t *)ipu->tpmem_base + 0x2008 / 4;
- + } else if (ic_task == IC_TASK_VIEWFINDER) {
- + if (csc_index == 1)
- + base = (uint32_t *)ipu->tpmem_base + 0x4028 / 4;
- + else
- + base = (uint32_t *)ipu->tpmem_base + 0x4040 / 4;
- + } else if (ic_task == IC_TASK_POST_PROCESSOR) {
- + if (csc_index == 1)
- + base = (uint32_t *)ipu->tpmem_base + 0x6060 / 4;
- + else
- + base = (uint32_t *)ipu->tpmem_base + 0x6078 / 4;
- + } else {
- + BUG();
- + }
- +
- + if ((in_format == YCbCr) && (out_format == RGB)) {
- + /* Init CSC (YCbCr->RGB) */
- + param = (ycbcr2rgb_coeff[3][0] << 27) |
- + (ycbcr2rgb_coeff[0][0] << 18) |
- + (ycbcr2rgb_coeff[1][1] << 9) | ycbcr2rgb_coeff[2][2];
- + writel(param, base++);
- + /* scale = 2, sat = 0 */
- + param = (ycbcr2rgb_coeff[3][0] >> 5) | (2L << (40 - 32));
- + writel(param, base++);
- +
- + param = (ycbcr2rgb_coeff[3][1] << 27) |
- + (ycbcr2rgb_coeff[0][1] << 18) |
- + (ycbcr2rgb_coeff[1][0] << 9) | ycbcr2rgb_coeff[2][0];
- + writel(param, base++);
- + param = (ycbcr2rgb_coeff[3][1] >> 5);
- + writel(param, base++);
- +
- + param = (ycbcr2rgb_coeff[3][2] << 27) |
- + (ycbcr2rgb_coeff[0][2] << 18) |
- + (ycbcr2rgb_coeff[1][2] << 9) | ycbcr2rgb_coeff[2][1];
- + writel(param, base++);
- + param = (ycbcr2rgb_coeff[3][2] >> 5);
- + writel(param, base++);
- + } else if ((in_format == RGB) && (out_format == YCbCr)) {
- + /* Init CSC (RGB->YCbCr) */
- + param = (rgb2ycbcr_coeff[3][0] << 27) |
- + (rgb2ycbcr_coeff[0][0] << 18) |
- + (rgb2ycbcr_coeff[1][1] << 9) | rgb2ycbcr_coeff[2][2];
- + writel(param, base++);
- + /* scale = 1, sat = 0 */
- + param = (rgb2ycbcr_coeff[3][0] >> 5) | (1UL << 8);
- + writel(param, base++);
- +
- + param = (rgb2ycbcr_coeff[3][1] << 27) |
- + (rgb2ycbcr_coeff[0][1] << 18) |
- + (rgb2ycbcr_coeff[1][0] << 9) | rgb2ycbcr_coeff[2][0];
- + writel(param, base++);
- + param = (rgb2ycbcr_coeff[3][1] >> 5);
- + writel(param, base++);
- +
- + param = (rgb2ycbcr_coeff[3][2] << 27) |
- + (rgb2ycbcr_coeff[0][2] << 18) |
- + (rgb2ycbcr_coeff[1][2] << 9) | rgb2ycbcr_coeff[2][1];
- + writel(param, base++);
- + param = (rgb2ycbcr_coeff[3][2] >> 5);
- + writel(param, base++);
- + } else if ((in_format == RGB) && (out_format == RGB)) {
- + /* Init CSC */
- + param =
- + (rgb2rgb_coeff[3][0] << 27) | (rgb2rgb_coeff[0][0] << 18) |
- + (rgb2rgb_coeff[1][1] << 9) | rgb2rgb_coeff[2][2];
- + writel(param, base++);
- + /* scale = 2, sat = 0 */
- + param = (rgb2rgb_coeff[3][0] >> 5) | (2UL << 8);
- + writel(param, base++);
- +
- + param =
- + (rgb2rgb_coeff[3][1] << 27) | (rgb2rgb_coeff[0][1] << 18) |
- + (rgb2rgb_coeff[1][0] << 9) | rgb2rgb_coeff[2][0];
- + writel(param, base++);
- + param = (rgb2rgb_coeff[3][1] >> 5);
- + writel(param, base++);
- +
- + param =
- + (rgb2rgb_coeff[3][2] << 27) | (rgb2rgb_coeff[0][2] << 18) |
- + (rgb2rgb_coeff[1][2] << 9) | rgb2rgb_coeff[2][1];
- + writel(param, base++);
- + param = (rgb2rgb_coeff[3][2] >> 5);
- + writel(param, base++);
- + } else {
- + dev_err(ipu->dev, "Unsupported color space conversion\n");
- + }
- +}
- +
- +static int _calc_resize_coeffs(struct ipu_soc *ipu,
- + uint32_t inSize, uint32_t outSize,
- + uint32_t *resizeCoeff,
- + uint32_t *downsizeCoeff)
- +{
- + uint32_t tempSize;
- + uint32_t tempDownsize;
- +
- + if (inSize > 4096) {
- + dev_err(ipu->dev, "IC input size(%d) cannot exceed 4096\n",
- + inSize);
- + return -EINVAL;
- + }
- +
- + if (outSize > 1024) {
- + dev_err(ipu->dev, "IC output size(%d) cannot exceed 1024\n",
- + outSize);
- + return -EINVAL;
- + }
- +
- + if ((outSize << 3) < inSize) {
- + dev_err(ipu->dev, "IC cannot downsize more than 8:1\n");
- + return -EINVAL;
- + }
- +
- + /* Compute downsizing coefficient */
- + /* Output of downsizing unit cannot be more than 1024 */
- + tempDownsize = 0;
- + tempSize = inSize;
- + while (((tempSize > 1024) || (tempSize >= outSize * 2)) &&
- + (tempDownsize < 2)) {
- + tempSize >>= 1;
- + tempDownsize++;
- + }
- + *downsizeCoeff = tempDownsize;
- +
- + /* compute resizing coefficient using the following equation:
- + resizeCoeff = M*(SI -1)/(SO - 1)
- + where M = 2^13, SI - input size, SO - output size */
- + *resizeCoeff = (8192L * (tempSize - 1)) / (outSize - 1);
- + if (*resizeCoeff >= 16384L) {
- + dev_err(ipu->dev, "Overflow on IC resize coefficient.\n");
- + return -EINVAL;
- + }
- +
- + dev_dbg(ipu->dev, "resizing from %u -> %u pixels, "
- + "downsize=%u, resize=%u.%lu (reg=%u)\n", inSize, outSize,
- + *downsizeCoeff, (*resizeCoeff >= 8192L) ? 1 : 0,
- + ((*resizeCoeff & 0x1FFF) * 10000L) / 8192L, *resizeCoeff);
- +
- + return 0;
- +}
- +
- +void _ipu_vdi_toggle_top_field_man(struct ipu_soc *ipu)
- +{
- + uint32_t reg;
- + uint32_t mask_reg;
- +
- + reg = ipu_vdi_read(ipu, VDI_C);
- + mask_reg = reg & VDI_C_TOP_FIELD_MAN_1;
- + if (mask_reg == VDI_C_TOP_FIELD_MAN_1)
- + reg &= ~VDI_C_TOP_FIELD_MAN_1;
- + else
- + reg |= VDI_C_TOP_FIELD_MAN_1;
- +
- + ipu_vdi_write(ipu, reg, VDI_C);
- +}
- diff -Nur linux-3.14.35.orig/drivers/mxc/ipu3/ipu_param_mem.h linux-3.14.35/drivers/mxc/ipu3/ipu_param_mem.h
- --- linux-3.14.35.orig/drivers/mxc/ipu3/ipu_param_mem.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/ipu3/ipu_param_mem.h 2015-03-08 14:27:37.665684500 -0500
- @@ -0,0 +1,921 @@
- +/*
- + * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +#ifndef __INCLUDE_IPU_PARAM_MEM_H__
- +#define __INCLUDE_IPU_PARAM_MEM_H__
- +
- +#include <linux/bitrev.h>
- +#include <linux/types.h>
- +
- +#include "ipu_prv.h"
- +
- +extern u32 *ipu_cpmem_base;
- +
- +struct ipu_ch_param_word {
- + uint32_t data[5];
- + uint32_t res[3];
- +};
- +
- +struct ipu_ch_param {
- + struct ipu_ch_param_word word[2];
- +};
- +
- +#define ipu_ch_param_addr(ipu, ch) (((struct ipu_ch_param *)ipu->cpmem_base) + (ch))
- +
- +#define _param_word(base, w) \
- + (((struct ipu_ch_param *)(base))->word[(w)].data)
- +
- +#define ipu_ch_param_set_field(base, w, bit, size, v) { \
- + int i = (bit) / 32; \
- + int off = (bit) % 32; \
- + _param_word(base, w)[i] |= (v) << off; \
- + if (((bit)+(size)-1)/32 > i) { \
- + _param_word(base, w)[i + 1] |= (v) >> (off ? (32 - off) : 0); \
- + } \
- +}
- +
- +#define ipu_ch_param_set_field_io(base, w, bit, size, v) { \
- + int i = (bit) / 32; \
- + int off = (bit) % 32; \
- + unsigned reg_offset; \
- + u32 temp; \
- + reg_offset = sizeof(struct ipu_ch_param_word) * w / 4; \
- + reg_offset += i; \
- + temp = readl((u32 *)base + reg_offset); \
- + temp |= (v) << off; \
- + writel(temp, (u32 *)base + reg_offset); \
- + if (((bit)+(size)-1)/32 > i) { \
- + reg_offset++; \
- + temp = readl((u32 *)base + reg_offset); \
- + temp |= (v) >> (off ? (32 - off) : 0); \
- + writel(temp, (u32 *)base + reg_offset); \
- + } \
- +}
- +
- +#define ipu_ch_param_mod_field(base, w, bit, size, v) { \
- + int i = (bit) / 32; \
- + int off = (bit) % 32; \
- + u32 mask = (1UL << size) - 1; \
- + u32 temp = _param_word(base, w)[i]; \
- + temp &= ~(mask << off); \
- + _param_word(base, w)[i] = temp | (v) << off; \
- + if (((bit)+(size)-1)/32 > i) { \
- + temp = _param_word(base, w)[i + 1]; \
- + temp &= ~(mask >> (32 - off)); \
- + _param_word(base, w)[i + 1] = \
- + temp | ((v) >> (off ? (32 - off) : 0)); \
- + } \
- +}
- +
- +#define ipu_ch_param_mod_field_io(base, w, bit, size, v) { \
- + int i = (bit) / 32; \
- + int off = (bit) % 32; \
- + u32 mask = (1UL << size) - 1; \
- + unsigned reg_offset; \
- + u32 temp; \
- + reg_offset = sizeof(struct ipu_ch_param_word) * w / 4; \
- + reg_offset += i; \
- + temp = readl((u32 *)base + reg_offset); \
- + temp &= ~(mask << off); \
- + temp |= (v) << off; \
- + writel(temp, (u32 *)base + reg_offset); \
- + if (((bit)+(size)-1)/32 > i) { \
- + reg_offset++; \
- + temp = readl((u32 *)base + reg_offset); \
- + temp &= ~(mask >> (32 - off)); \
- + temp |= ((v) >> (off ? (32 - off) : 0)); \
- + writel(temp, (u32 *)base + reg_offset); \
- + } \
- +}
- +
- +#define ipu_ch_param_read_field(base, w, bit, size) ({ \
- + u32 temp2; \
- + int i = (bit) / 32; \
- + int off = (bit) % 32; \
- + u32 mask = (1UL << size) - 1; \
- + u32 temp1 = _param_word(base, w)[i]; \
- + temp1 = mask & (temp1 >> off); \
- + if (((bit)+(size)-1)/32 > i) { \
- + temp2 = _param_word(base, w)[i + 1]; \
- + temp2 &= mask >> (off ? (32 - off) : 0); \
- + temp1 |= temp2 << (off ? (32 - off) : 0); \
- + } \
- + temp1; \
- +})
- +
- +#define ipu_ch_param_read_field_io(base, w, bit, size) ({ \
- + u32 temp1, temp2; \
- + int i = (bit) / 32; \
- + int off = (bit) % 32; \
- + u32 mask = (1UL << size) - 1; \
- + unsigned reg_offset; \
- + reg_offset = sizeof(struct ipu_ch_param_word) * w / 4; \
- + reg_offset += i; \
- + temp1 = readl((u32 *)base + reg_offset); \
- + temp1 = mask & (temp1 >> off); \
- + if (((bit)+(size)-1)/32 > i) { \
- + reg_offset++; \
- + temp2 = readl((u32 *)base + reg_offset); \
- + temp2 &= mask >> (off ? (32 - off) : 0); \
- + temp1 |= temp2 << (off ? (32 - off) : 0); \
- + } \
- + temp1; \
- +})
- +
- +static inline int __ipu_ch_get_third_buf_cpmem_num(int ch)
- +{
- + switch (ch) {
- + case 8:
- + return 64;
- + case 9:
- + return 65;
- + case 10:
- + return 66;
- + case 13:
- + return 67;
- + case 21:
- + return 68;
- + case 23:
- + return 69;
- + case 27:
- + return 70;
- + case 28:
- + return 71;
- + default:
- + return -EINVAL;
- + }
- + return 0;
- +}
- +
- +static inline void _ipu_ch_params_set_packing(struct ipu_ch_param *p,
- + int red_width, int red_offset,
- + int green_width, int green_offset,
- + int blue_width, int blue_offset,
- + int alpha_width, int alpha_offset)
- +{
- + /* Setup red width and offset */
- + ipu_ch_param_set_field(p, 1, 116, 3, red_width - 1);
- + ipu_ch_param_set_field(p, 1, 128, 5, red_offset);
- + /* Setup green width and offset */
- + ipu_ch_param_set_field(p, 1, 119, 3, green_width - 1);
- + ipu_ch_param_set_field(p, 1, 133, 5, green_offset);
- + /* Setup blue width and offset */
- + ipu_ch_param_set_field(p, 1, 122, 3, blue_width - 1);
- + ipu_ch_param_set_field(p, 1, 138, 5, blue_offset);
- + /* Setup alpha width and offset */
- + ipu_ch_param_set_field(p, 1, 125, 3, alpha_width - 1);
- + ipu_ch_param_set_field(p, 1, 143, 5, alpha_offset);
- +}
- +
- +static inline void _ipu_ch_param_dump(struct ipu_soc *ipu, int ch)
- +{
- + struct ipu_ch_param *p = ipu_ch_param_addr(ipu, ch);
- + dev_dbg(ipu->dev, "ch %d word 0 - %08X %08X %08X %08X %08X\n", ch,
- + p->word[0].data[0], p->word[0].data[1], p->word[0].data[2],
- + p->word[0].data[3], p->word[0].data[4]);
- + dev_dbg(ipu->dev, "ch %d word 1 - %08X %08X %08X %08X %08X\n", ch,
- + p->word[1].data[0], p->word[1].data[1], p->word[1].data[2],
- + p->word[1].data[3], p->word[1].data[4]);
- + dev_dbg(ipu->dev, "PFS 0x%x, ",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 85, 4));
- + dev_dbg(ipu->dev, "BPP 0x%x, ",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 107, 3));
- + dev_dbg(ipu->dev, "NPB 0x%x\n",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7));
- +
- + dev_dbg(ipu->dev, "FW %d, ",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 125, 13));
- + dev_dbg(ipu->dev, "FH %d, ",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 138, 12));
- + dev_dbg(ipu->dev, "EBA0 0x%x\n",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 0, 29) << 3);
- + dev_dbg(ipu->dev, "EBA1 0x%x\n",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 29, 29) << 3);
- + dev_dbg(ipu->dev, "Stride %d\n",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14));
- + dev_dbg(ipu->dev, "scan_order %d\n",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 113, 1));
- + dev_dbg(ipu->dev, "uv_stride %d\n",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 128, 14));
- + dev_dbg(ipu->dev, "u_offset 0x%x\n",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 46, 22) << 3);
- + dev_dbg(ipu->dev, "v_offset 0x%x\n",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 68, 22) << 3);
- +
- + dev_dbg(ipu->dev, "Width0 %d+1, ",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 116, 3));
- + dev_dbg(ipu->dev, "Width1 %d+1, ",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 119, 3));
- + dev_dbg(ipu->dev, "Width2 %d+1, ",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 122, 3));
- + dev_dbg(ipu->dev, "Width3 %d+1, ",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 125, 3));
- + dev_dbg(ipu->dev, "Offset0 %d, ",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 128, 5));
- + dev_dbg(ipu->dev, "Offset1 %d, ",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 133, 5));
- + dev_dbg(ipu->dev, "Offset2 %d, ",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 138, 5));
- + dev_dbg(ipu->dev, "Offset3 %d\n",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 143, 5));
- +}
- +
- +static inline void fill_cpmem(struct ipu_soc *ipu, int ch, struct ipu_ch_param *params)
- +{
- + int i, w;
- + void *addr = ipu_ch_param_addr(ipu, ch);
- +
- + /* 2 words, 5 valid data */
- + for (w = 0; w < 2; w++) {
- + for (i = 0; i < 5; i++) {
- + writel(params->word[w].data[i], addr);
- + addr += 4;
- + }
- + addr += 12;
- + }
- +}
- +
- +static inline void _ipu_ch_param_init(struct ipu_soc *ipu, int ch,
- + uint32_t pixel_fmt, uint32_t width,
- + uint32_t height, uint32_t stride,
- + uint32_t u, uint32_t v,
- + uint32_t uv_stride, dma_addr_t addr0,
- + dma_addr_t addr1, dma_addr_t addr2)
- +{
- + uint32_t u_offset = 0;
- + uint32_t v_offset = 0;
- + int32_t sub_ch = 0;
- + struct ipu_ch_param params;
- +
- + memset(¶ms, 0, sizeof(params));
- +
- + ipu_ch_param_set_field(¶ms, 0, 125, 13, width - 1);
- +
- + if (((ch == 8) || (ch == 9) || (ch == 10)) && !ipu->vdoa_en) {
- + ipu_ch_param_set_field(¶ms, 0, 138, 12, (height / 2) - 1);
- + ipu_ch_param_set_field(¶ms, 1, 102, 14, (stride * 2) - 1);
- + } else {
- + /* note: for vdoa+vdi- ch8/9/10, always use band mode */
- + ipu_ch_param_set_field(¶ms, 0, 138, 12, height - 1);
- + ipu_ch_param_set_field(¶ms, 1, 102, 14, stride - 1);
- + }
- +
- + /* EBA is 8-byte aligned */
- + ipu_ch_param_set_field(¶ms, 1, 0, 29, addr0 >> 3);
- + ipu_ch_param_set_field(¶ms, 1, 29, 29, addr1 >> 3);
- + if (addr0%8)
- + dev_warn(ipu->dev,
- + "IDMAC%d's EBA0 is not 8-byte aligned\n", ch);
- + if (addr1%8)
- + dev_warn(ipu->dev,
- + "IDMAC%d's EBA1 is not 8-byte aligned\n", ch);
- +
- + switch (pixel_fmt) {
- + case IPU_PIX_FMT_GENERIC:
- + /*Represents 8-bit Generic data */
- + ipu_ch_param_set_field(¶ms, 0, 107, 3, 5); /* bits/pixel */
- + ipu_ch_param_set_field(¶ms, 1, 85, 4, 6); /* pix format */
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 63); /* burst size */
- +
- + break;
- + case IPU_PIX_FMT_GENERIC_16:
- + /* Represents 16-bit generic data */
- + ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
- + ipu_ch_param_set_field(¶ms, 1, 85, 4, 6); /* pix format */
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
- +
- + break;
- + case IPU_PIX_FMT_GENERIC_32:
- + /*Represents 32-bit Generic data */
- + break;
- + case IPU_PIX_FMT_RGB565:
- + ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
- + ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
- +
- + _ipu_ch_params_set_packing(¶ms, 5, 0, 6, 5, 5, 11, 8, 16);
- + break;
- + case IPU_PIX_FMT_BGR24:
- + ipu_ch_param_set_field(¶ms, 0, 107, 3, 1); /* bits/pixel */
- + ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 19); /* burst size */
- +
- + _ipu_ch_params_set_packing(¶ms, 8, 0, 8, 8, 8, 16, 8, 24);
- + break;
- + case IPU_PIX_FMT_RGB24:
- + case IPU_PIX_FMT_YUV444:
- + ipu_ch_param_set_field(¶ms, 0, 107, 3, 1); /* bits/pixel */
- + ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 19); /* burst size */
- +
- + _ipu_ch_params_set_packing(¶ms, 8, 16, 8, 8, 8, 0, 8, 24);
- + break;
- + case IPU_PIX_FMT_VYU444:
- + ipu_ch_param_set_field(¶ms, 0, 107, 3, 1); /* bits/pixel */
- + ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 19); /* burst size */
- +
- + _ipu_ch_params_set_packing(¶ms, 8, 8, 8, 0, 8, 16, 8, 24);
- + break;
- + case IPU_PIX_FMT_BGRA32:
- + case IPU_PIX_FMT_BGR32:
- + ipu_ch_param_set_field(¶ms, 0, 107, 3, 0); /* bits/pixel */
- + ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
- +
- + _ipu_ch_params_set_packing(¶ms, 8, 8, 8, 16, 8, 24, 8, 0);
- + break;
- + case IPU_PIX_FMT_RGBA32:
- + case IPU_PIX_FMT_RGB32:
- + ipu_ch_param_set_field(¶ms, 0, 107, 3, 0); /* bits/pixel */
- + ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
- +
- + _ipu_ch_params_set_packing(¶ms, 8, 24, 8, 16, 8, 8, 8, 0);
- + break;
- + case IPU_PIX_FMT_ABGR32:
- + ipu_ch_param_set_field(¶ms, 0, 107, 3, 0); /* bits/pixel */
- + ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
- +
- + _ipu_ch_params_set_packing(¶ms, 8, 0, 8, 8, 8, 16, 8, 24);
- + break;
- + case IPU_PIX_FMT_UYVY:
- + ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
- + ipu_ch_param_set_field(¶ms, 1, 85, 4, 0xA); /* pix format */
- + if ((ch == 8) || (ch == 9) || (ch == 10)) {
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
- + } else {
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
- + }
- + break;
- + case IPU_PIX_FMT_YUYV:
- + ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
- + ipu_ch_param_set_field(¶ms, 1, 85, 4, 0x8); /* pix format */
- + if ((ch == 8) || (ch == 9) || (ch == 10)) {
- + if (ipu->vdoa_en) {
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 31);
- + } else {
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 15);
- + }
- + } else {
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
- + }
- + break;
- + case IPU_PIX_FMT_YUV420P2:
- + case IPU_PIX_FMT_YUV420P:
- + ipu_ch_param_set_field(¶ms, 1, 85, 4, 2); /* pix format */
- +
- + if (uv_stride < stride / 2)
- + uv_stride = stride / 2;
- +
- + u_offset = stride * height;
- + v_offset = u_offset + (uv_stride * height / 2);
- + if ((ch == 8) || (ch == 9) || (ch == 10)) {
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
- + uv_stride = uv_stride*2;
- + } else {
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
- + }
- + break;
- + case IPU_PIX_FMT_YVU420P:
- + ipu_ch_param_set_field(¶ms, 1, 85, 4, 2); /* pix format */
- +
- + if (uv_stride < stride / 2)
- + uv_stride = stride / 2;
- +
- + v_offset = stride * height;
- + u_offset = v_offset + (uv_stride * height / 2);
- + if ((ch == 8) || (ch == 9) || (ch == 10)) {
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
- + uv_stride = uv_stride*2;
- + } else {
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
- + }
- + break;
- + case IPU_PIX_FMT_YVU422P:
- + /* BPP & pixel format */
- + ipu_ch_param_set_field(¶ms, 1, 85, 4, 1); /* pix format */
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
- +
- + if (uv_stride < stride / 2)
- + uv_stride = stride / 2;
- +
- + v_offset = (v == 0) ? stride * height : v;
- + u_offset = (u == 0) ? v_offset + v_offset / 2 : u;
- + break;
- + case IPU_PIX_FMT_YUV422P:
- + /* BPP & pixel format */
- + ipu_ch_param_set_field(¶ms, 1, 85, 4, 1); /* pix format */
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
- +
- + if (uv_stride < stride / 2)
- + uv_stride = stride / 2;
- +
- + u_offset = (u == 0) ? stride * height : u;
- + v_offset = (v == 0) ? u_offset + u_offset / 2 : v;
- + break;
- + case IPU_PIX_FMT_YUV444P:
- + /* BPP & pixel format */
- + ipu_ch_param_set_field(¶ms, 1, 85, 4, 0); /* pix format */
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
- + uv_stride = stride;
- + u_offset = (u == 0) ? stride * height : u;
- + v_offset = (v == 0) ? u_offset * 2 : v;
- + break;
- + case IPU_PIX_FMT_NV12:
- + /* BPP & pixel format */
- + ipu_ch_param_set_field(¶ms, 1, 85, 4, 4); /* pix format */
- + uv_stride = stride;
- + u_offset = (u == 0) ? stride * height : u;
- + if ((ch == 8) || (ch == 9) || (ch == 10)) {
- + if (ipu->vdoa_en) {
- + /* one field buffer, memory width 64bits */
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 63);
- + } else {
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 15);
- + /* top/bottom field in one buffer*/
- + uv_stride = uv_stride*2;
- + }
- + } else {
- + ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
- + }
- + break;
- + default:
- + dev_err(ipu->dev, "mxc ipu: unimplemented pixel format\n");
- + break;
- + }
- + /*set burst size to 16*/
- +
- +
- + if (uv_stride)
- + ipu_ch_param_set_field(¶ms, 1, 128, 14, uv_stride - 1);
- +
- + /* Get the uv offset from user when need cropping */
- + if (u || v) {
- + u_offset = u;
- + v_offset = v;
- + }
- +
- + /* UBO and VBO are 22-bit and 8-byte aligned */
- + if (u_offset/8 > 0x3fffff)
- + dev_warn(ipu->dev,
- + "IDMAC%d's U offset exceeds IPU limitation\n", ch);
- + if (v_offset/8 > 0x3fffff)
- + dev_warn(ipu->dev,
- + "IDMAC%d's V offset exceeds IPU limitation\n", ch);
- + if (u_offset%8)
- + dev_warn(ipu->dev,
- + "IDMAC%d's U offset is not 8-byte aligned\n", ch);
- + if (v_offset%8)
- + dev_warn(ipu->dev,
- + "IDMAC%d's V offset is not 8-byte aligned\n", ch);
- +
- + ipu_ch_param_set_field(¶ms, 0, 46, 22, u_offset / 8);
- + ipu_ch_param_set_field(¶ms, 0, 68, 22, v_offset / 8);
- +
- + dev_dbg(ipu->dev, "initializing idma ch %d @ %p\n", ch, ipu_ch_param_addr(ipu, ch));
- + fill_cpmem(ipu, ch, ¶ms);
- + if (addr2) {
- + sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
- + if (sub_ch <= 0)
- + return;
- +
- + ipu_ch_param_set_field(¶ms, 1, 0, 29, addr2 >> 3);
- + ipu_ch_param_set_field(¶ms, 1, 29, 29, 0);
- + if (addr2%8)
- + dev_warn(ipu->dev,
- + "IDMAC%d's sub-CPMEM entry%d EBA0 is not "
- + "8-byte aligned\n", ch, sub_ch);
- +
- + dev_dbg(ipu->dev, "initializing idma ch %d @ %p sub cpmem\n", ch,
- + ipu_ch_param_addr(ipu, sub_ch));
- + fill_cpmem(ipu, sub_ch, ¶ms);
- + }
- +};
- +
- +static inline void _ipu_ch_param_set_burst_size(struct ipu_soc *ipu,
- + uint32_t ch,
- + uint16_t burst_pixels)
- +{
- + int32_t sub_ch = 0;
- +
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7,
- + burst_pixels - 1);
- +
- + sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
- + if (sub_ch <= 0)
- + return;
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 78, 7,
- + burst_pixels - 1);
- +};
- +
- +static inline int _ipu_ch_param_get_burst_size(struct ipu_soc *ipu, uint32_t ch)
- +{
- + return ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7) + 1;
- +};
- +
- +static inline int _ipu_ch_param_get_bpp(struct ipu_soc *ipu, uint32_t ch)
- +{
- + return ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 107, 3);
- +};
- +
- +static inline void _ipu_ch_param_set_buffer(struct ipu_soc *ipu, uint32_t ch,
- + int bufNum, dma_addr_t phyaddr)
- +{
- + if (bufNum == 2) {
- + ch = __ipu_ch_get_third_buf_cpmem_num(ch);
- + if (ch <= 0)
- + return;
- + bufNum = 0;
- + }
- +
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 29 * bufNum, 29,
- + phyaddr / 8);
- +};
- +
- +static inline void _ipu_ch_param_set_rotation(struct ipu_soc *ipu, uint32_t ch,
- + ipu_rotate_mode_t rot)
- +{
- + u32 temp_rot = bitrev8(rot) >> 5;
- + int32_t sub_ch = 0;
- +
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 119, 3, temp_rot);
- +
- + sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
- + if (sub_ch <= 0)
- + return;
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 119, 3, temp_rot);
- +};
- +
- +static inline void _ipu_ch_param_set_block_mode(struct ipu_soc *ipu, uint32_t ch)
- +{
- + int32_t sub_ch = 0;
- +
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 117, 2, 1);
- +
- + sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
- + if (sub_ch <= 0)
- + return;
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 117, 2, 1);
- +};
- +
- +static inline void _ipu_ch_param_set_alpha_use_separate_channel(struct ipu_soc *ipu,
- + uint32_t ch,
- + bool option)
- +{
- + int32_t sub_ch = 0;
- +
- + if (option) {
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 1);
- + } else {
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 0);
- + }
- +
- + sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
- + if (sub_ch <= 0)
- + return;
- +
- + if (option) {
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 1);
- + } else {
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 0);
- + }
- +};
- +
- +static inline void _ipu_ch_param_set_alpha_condition_read(struct ipu_soc *ipu, uint32_t ch)
- +{
- + int32_t sub_ch = 0;
- +
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 149, 1, 1);
- +
- + sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
- + if (sub_ch <= 0)
- + return;
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 149, 1, 1);
- +};
- +
- +static inline void _ipu_ch_param_set_alpha_buffer_memory(struct ipu_soc *ipu, uint32_t ch)
- +{
- + int alp_mem_idx;
- + int32_t sub_ch = 0;
- +
- + switch (ch) {
- + case 14: /* PRP graphic */
- + alp_mem_idx = 0;
- + break;
- + case 15: /* PP graphic */
- + alp_mem_idx = 1;
- + break;
- + case 23: /* DP BG SYNC graphic */
- + alp_mem_idx = 4;
- + break;
- + case 27: /* DP FG SYNC graphic */
- + alp_mem_idx = 2;
- + break;
- + default:
- + dev_err(ipu->dev, "unsupported correlative channel of local "
- + "alpha channel\n");
- + return;
- + }
- +
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 90, 3, alp_mem_idx);
- +
- + sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
- + if (sub_ch <= 0)
- + return;
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 90, 3, alp_mem_idx);
- +};
- +
- +static inline void _ipu_ch_param_set_interlaced_scan(struct ipu_soc *ipu, uint32_t ch)
- +{
- + u32 stride;
- + int32_t sub_ch = 0;
- +
- + sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
- +
- + ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch), 0, 113, 1, 1);
- + if (sub_ch > 0)
- + ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 113, 1, 1);
- + stride = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14) + 1;
- + /* ILO is 20-bit and 8-byte aligned */
- + if (stride/8 > 0xfffff)
- + dev_warn(ipu->dev,
- + "IDMAC%d's ILO exceeds IPU limitation\n", ch);
- + if (stride%8)
- + dev_warn(ipu->dev,
- + "IDMAC%d's ILO is not 8-byte aligned\n", ch);
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 58, 20, stride / 8);
- + if (sub_ch > 0)
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 58, 20,
- + stride / 8);
- + stride *= 2;
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14, stride - 1);
- + if (sub_ch > 0)
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 102, 14,
- + stride - 1);
- +};
- +
- +static inline void _ipu_ch_param_set_axi_id(struct ipu_soc *ipu, uint32_t ch, uint32_t id)
- +{
- + int32_t sub_ch = 0;
- +
- + id %= 4;
- +
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 93, 2, id);
- +
- + sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
- + if (sub_ch <= 0)
- + return;
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 93, 2, id);
- +};
- +
- +/* IDMAC U/V offset changing support */
- +/* U and V input is not affected, */
- +/* the update is done by new calculation according to */
- +/* vertical_offset and horizontal_offset */
- +static inline void _ipu_ch_offset_update(struct ipu_soc *ipu,
- + int ch,
- + uint32_t pixel_fmt,
- + uint32_t width,
- + uint32_t height,
- + uint32_t stride,
- + uint32_t u,
- + uint32_t v,
- + uint32_t uv_stride,
- + uint32_t vertical_offset,
- + uint32_t horizontal_offset)
- +{
- + uint32_t u_offset = 0;
- + uint32_t v_offset = 0;
- + uint32_t old_offset = 0;
- + uint32_t u_fix = 0;
- + uint32_t v_fix = 0;
- + int32_t sub_ch = 0;
- +
- + switch (pixel_fmt) {
- + case IPU_PIX_FMT_GENERIC:
- + case IPU_PIX_FMT_GENERIC_16:
- + case IPU_PIX_FMT_GENERIC_32:
- + case IPU_PIX_FMT_RGB565:
- + case IPU_PIX_FMT_BGR24:
- + case IPU_PIX_FMT_RGB24:
- + case IPU_PIX_FMT_YUV444:
- + case IPU_PIX_FMT_BGRA32:
- + case IPU_PIX_FMT_BGR32:
- + case IPU_PIX_FMT_RGBA32:
- + case IPU_PIX_FMT_RGB32:
- + case IPU_PIX_FMT_ABGR32:
- + case IPU_PIX_FMT_UYVY:
- + case IPU_PIX_FMT_YUYV:
- + break;
- +
- + case IPU_PIX_FMT_YUV420P2:
- + case IPU_PIX_FMT_YUV420P:
- + if (uv_stride < stride / 2)
- + uv_stride = stride / 2;
- +
- + u_offset = stride * (height - vertical_offset - 1) +
- + (stride - horizontal_offset) +
- + (uv_stride * vertical_offset / 2) +
- + horizontal_offset / 2;
- + v_offset = u_offset + (uv_stride * height / 2);
- + u_fix = u ? (u + (uv_stride * vertical_offset / 2) +
- + (horizontal_offset / 2) -
- + (stride * vertical_offset) - (horizontal_offset)) :
- + u_offset;
- + v_fix = v ? (v + (uv_stride * vertical_offset / 2) +
- + (horizontal_offset / 2) -
- + (stride * vertical_offset) - (horizontal_offset)) :
- + v_offset;
- +
- + break;
- + case IPU_PIX_FMT_YVU420P:
- + if (uv_stride < stride / 2)
- + uv_stride = stride / 2;
- +
- + v_offset = stride * (height - vertical_offset - 1) +
- + (stride - horizontal_offset) +
- + (uv_stride * vertical_offset / 2) +
- + horizontal_offset / 2;
- + u_offset = v_offset + (uv_stride * height / 2);
- + u_fix = u ? (u + (uv_stride * vertical_offset / 2) +
- + (horizontal_offset / 2) -
- + (stride * vertical_offset) - (horizontal_offset)) :
- + u_offset;
- + v_fix = v ? (v + (uv_stride * vertical_offset / 2) +
- + (horizontal_offset / 2) -
- + (stride * vertical_offset) - (horizontal_offset)) :
- + v_offset;
- +
- + break;
- + case IPU_PIX_FMT_YVU422P:
- + if (uv_stride < stride / 2)
- + uv_stride = stride / 2;
- +
- + v_offset = stride * (height - vertical_offset - 1) +
- + (stride - horizontal_offset) +
- + (uv_stride * vertical_offset) +
- + horizontal_offset / 2;
- + u_offset = v_offset + uv_stride * height;
- + u_fix = u ? (u + (uv_stride * vertical_offset) +
- + horizontal_offset / 2 -
- + (stride * vertical_offset) - (horizontal_offset)) :
- + u_offset;
- + v_fix = v ? (v + (uv_stride * vertical_offset) +
- + horizontal_offset / 2 -
- + (stride * vertical_offset) - (horizontal_offset)) :
- + v_offset;
- + break;
- + case IPU_PIX_FMT_YUV422P:
- + if (uv_stride < stride / 2)
- + uv_stride = stride / 2;
- +
- + u_offset = stride * (height - vertical_offset - 1) +
- + (stride - horizontal_offset) +
- + (uv_stride * vertical_offset) +
- + horizontal_offset / 2;
- + v_offset = u_offset + uv_stride * height;
- + u_fix = u ? (u + (uv_stride * vertical_offset) +
- + horizontal_offset / 2 -
- + (stride * vertical_offset) - (horizontal_offset)) :
- + u_offset;
- + v_fix = v ? (v + (uv_stride * vertical_offset) +
- + horizontal_offset / 2 -
- + (stride * vertical_offset) - (horizontal_offset)) :
- + v_offset;
- + break;
- +
- + case IPU_PIX_FMT_YUV444P:
- + uv_stride = stride;
- + u_offset = stride * (height - vertical_offset - 1) +
- + (stride - horizontal_offset) +
- + (uv_stride * vertical_offset) +
- + horizontal_offset;
- + v_offset = u_offset + uv_stride * height;
- + u_fix = u ? (u + (uv_stride * vertical_offset) +
- + horizontal_offset -
- + (stride * vertical_offset) -
- + (horizontal_offset)) :
- + u_offset;
- + v_fix = v ? (v + (uv_stride * vertical_offset) +
- + horizontal_offset -
- + (stride * vertical_offset) -
- + (horizontal_offset)) :
- + v_offset;
- + break;
- + case IPU_PIX_FMT_NV12:
- + uv_stride = stride;
- + u_offset = stride * (height - vertical_offset - 1) +
- + (stride - horizontal_offset) +
- + (uv_stride * vertical_offset / 2) +
- + horizontal_offset;
- + u_fix = u ? (u + (uv_stride * vertical_offset / 2) +
- + horizontal_offset -
- + (stride * vertical_offset) - (horizontal_offset)) :
- + u_offset;
- +
- + break;
- + default:
- + dev_err(ipu->dev, "mxc ipu: unimplemented pixel format\n");
- + break;
- + }
- +
- +
- +
- + if (u_fix > u_offset)
- + u_offset = u_fix;
- +
- + if (v_fix > v_offset)
- + v_offset = v_fix;
- +
- + /* UBO and VBO are 22-bit and 8-byte aligned */
- + if (u_offset/8 > 0x3fffff)
- + dev_warn(ipu->dev,
- + "IDMAC%d's U offset exceeds IPU limitation\n", ch);
- + if (v_offset/8 > 0x3fffff)
- + dev_warn(ipu->dev,
- + "IDMAC%d's V offset exceeds IPU limitation\n", ch);
- + if (u_offset%8)
- + dev_warn(ipu->dev,
- + "IDMAC%d's U offset is not 8-byte aligned\n", ch);
- + if (v_offset%8)
- + dev_warn(ipu->dev,
- + "IDMAC%d's V offset is not 8-byte aligned\n", ch);
- +
- + old_offset = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 46, 22);
- + if (old_offset != u_offset / 8)
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 46, 22, u_offset / 8);
- + old_offset = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 68, 22);
- + if (old_offset != v_offset / 8)
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 68, 22, v_offset / 8);
- +
- + sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
- + if (sub_ch <= 0)
- + return;
- + old_offset = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 46, 22);
- + if (old_offset != u_offset / 8)
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 46, 22, u_offset / 8);
- + old_offset = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 68, 22);
- + if (old_offset != v_offset / 8)
- + ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 68, 22, v_offset / 8);
- +};
- +
- +static inline void _ipu_ch_params_set_alpha_width(struct ipu_soc *ipu, uint32_t ch, int alpha_width)
- +{
- + int32_t sub_ch = 0;
- +
- + ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch), 1, 125, 3, alpha_width - 1);
- +
- + sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
- + if (sub_ch <= 0)
- + return;
- + ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 125, 3, alpha_width - 1);
- +};
- +
- +static inline void _ipu_ch_param_set_bandmode(struct ipu_soc *ipu,
- + uint32_t ch, uint32_t band_height)
- +{
- + int32_t sub_ch = 0;
- +
- + ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch),
- + 0, 114, 3, band_height - 1);
- + sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
- + if (sub_ch <= 0)
- + return;
- + ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch),
- + 0, 114, 3, band_height - 1);
- +
- + dev_dbg(ipu->dev, "BNDM 0x%x, ",
- + ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 114, 3));
- +}
- +
- +/*
- + * The IPUv3 IDMAC has a bug to read 32bpp pixels from a graphics plane
- + * whose alpha component is at the most significant 8 bits. The bug only
- + * impacts on cases in which the relevant separate alpha channel is enabled.
- + *
- + * Return true on bad alpha component position, otherwise, return false.
- + */
- +static inline bool _ipu_ch_param_bad_alpha_pos(uint32_t pixel_fmt)
- +{
- + switch (pixel_fmt) {
- + case IPU_PIX_FMT_BGRA32:
- + case IPU_PIX_FMT_BGR32:
- + case IPU_PIX_FMT_RGBA32:
- + case IPU_PIX_FMT_RGB32:
- + return true;
- + }
- +
- + return false;
- +}
- +#endif
- diff -Nur linux-3.14.35.orig/drivers/mxc/ipu3/ipu_pixel_clk.c linux-3.14.35/drivers/mxc/ipu3/ipu_pixel_clk.c
- --- linux-3.14.35.orig/drivers/mxc/ipu3/ipu_pixel_clk.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/ipu3/ipu_pixel_clk.c 2015-03-08 14:27:37.665684500 -0500
- @@ -0,0 +1,317 @@
- +/*
- + * Copyright (C) 2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file ipu_pixel_clk.c
- + *
- + * @brief IPU pixel clock implementation
- + *
- + * @ingroup IPU
- + */
- +
- +#include <linux/clk-provider.h>
- +#include <linux/err.h>
- +#include <linux/io.h>
- +#include <linux/ipu-v3.h>
- +#include <linux/module.h>
- +#include <linux/slab.h>
- +#include <linux/string.h>
- +
- +#include "ipu_prv.h"
- +#include "ipu_regs.h"
- +
- + /*
- + * muxd clock implementation
- + */
- +struct clk_di_mux {
- + struct clk_hw hw;
- + u8 ipu_id;
- + u8 di_id;
- + u8 flags;
- + u8 index;
- +};
- +#define to_clk_di_mux(_hw) container_of(_hw, struct clk_di_mux, hw)
- +
- +static int _ipu_pixel_clk_set_parent(struct clk_hw *hw, u8 index)
- +{
- + struct clk_di_mux *mux = to_clk_di_mux(hw);
- + struct ipu_soc *ipu = ipu_get_soc(mux->ipu_id);
- + u32 di_gen;
- +
- + di_gen = ipu_di_read(ipu, mux->di_id, DI_GENERAL);
- + if (index == 0)
- + /* ipu1_clk or ipu2_clk internal clk */
- + di_gen &= ~DI_GEN_DI_CLK_EXT;
- + else
- + di_gen |= DI_GEN_DI_CLK_EXT;
- +
- + ipu_di_write(ipu, mux->di_id, di_gen, DI_GENERAL);
- + mux->index = index;
- + pr_debug("ipu_pixel_clk: di_clk_ext:0x%x, di_gen reg:0x%x.\n",
- + !(di_gen & DI_GEN_DI_CLK_EXT), di_gen);
- + return 0;
- +}
- +
- +static u8 _ipu_pixel_clk_get_parent(struct clk_hw *hw)
- +{
- + struct clk_di_mux *mux = to_clk_di_mux(hw);
- +
- + return mux->index;
- +}
- +
- +const struct clk_ops clk_mux_di_ops = {
- + .get_parent = _ipu_pixel_clk_get_parent,
- + .set_parent = _ipu_pixel_clk_set_parent,
- +};
- +
- +struct clk *clk_register_mux_pix_clk(struct device *dev, const char *name,
- + const char **parent_names, u8 num_parents, unsigned long flags,
- + u8 ipu_id, u8 di_id, u8 clk_mux_flags)
- +{
- + struct clk_di_mux *mux;
- + struct clk *clk;
- + struct clk_init_data init;
- +
- + mux = kzalloc(sizeof(struct clk_di_mux), GFP_KERNEL);
- + if (!mux)
- + return ERR_PTR(-ENOMEM);
- +
- + init.name = name;
- + init.ops = &clk_mux_di_ops;
- + init.flags = flags;
- + init.parent_names = parent_names;
- + init.num_parents = num_parents;
- +
- + mux->ipu_id = ipu_id;
- + mux->di_id = di_id;
- + mux->flags = clk_mux_flags | CLK_SET_RATE_PARENT;
- + mux->hw.init = &init;
- +
- + clk = clk_register(dev, &mux->hw);
- + if (IS_ERR(clk))
- + kfree(mux);
- +
- + return clk;
- +}
- +
- +/*
- + * Gated clock implementation
- + */
- +struct clk_di_div {
- + struct clk_hw hw;
- + u8 ipu_id;
- + u8 di_id;
- + u8 flags;
- +};
- +#define to_clk_di_div(_hw) container_of(_hw, struct clk_di_div, hw)
- +
- +static unsigned long _ipu_pixel_clk_div_recalc_rate(struct clk_hw *hw,
- + unsigned long parent_rate)
- +{
- + struct clk_di_div *di_div = to_clk_di_div(hw);
- + struct ipu_soc *ipu = ipu_get_soc(di_div->ipu_id);
- + u32 div;
- + u64 final_rate = (unsigned long long)parent_rate * 16;
- +
- + _ipu_get(ipu);
- + div = ipu_di_read(ipu, di_div->di_id, DI_BS_CLKGEN0);
- + _ipu_put(ipu);
- + pr_debug("ipu_di%d read BS_CLKGEN0 div:%d, final_rate:%lld, prate:%ld\n",
- + di_div->di_id, div, final_rate, parent_rate);
- +
- + if (div == 0)
- + return 0;
- + do_div(final_rate, div);
- +
- + return (unsigned long)final_rate;
- +}
- +
- +static long _ipu_pixel_clk_div_round_rate(struct clk_hw *hw, unsigned long rate,
- + unsigned long *parent_clk_rate)
- +{
- + u64 div, final_rate;
- + u32 remainder;
- + u64 parent_rate = (unsigned long long)(*parent_clk_rate) * 16;
- +
- + /*
- + * Calculate divider
- + * Fractional part is 4 bits,
- + * so simply multiply by 2^4 to get fractional part.
- + */
- + div = parent_rate;
- + remainder = do_div(div, rate);
- + /* Round the divider value */
- + if (remainder > (rate/2))
- + div++;
- + if (div < 0x10) /* Min DI disp clock divider is 1 */
- + div = 0x10;
- + if (div & ~0xFEF)
- + div &= 0xFF8;
- + else {
- + /* Round up divider if it gets us closer to desired pix clk */
- + if ((div & 0xC) == 0xC) {
- + div += 0x10;
- + div &= ~0xF;
- + }
- + }
- + final_rate = parent_rate;
- + do_div(final_rate, div);
- +
- + return final_rate;
- +}
- +
- +static int _ipu_pixel_clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
- + unsigned long parent_clk_rate)
- +{
- + struct clk_di_div *di_div = to_clk_di_div(hw);
- + struct ipu_soc *ipu = ipu_get_soc(di_div->ipu_id);
- + u64 div, parent_rate;
- + u32 remainder;
- +
- + parent_rate = (unsigned long long)parent_clk_rate * 16;
- + div = parent_rate;
- + remainder = do_div(div, rate);
- + /* Round the divider value */
- + if (remainder > (rate/2))
- + div++;
- +
- + /* Round up divider if it gets us closer to desired pix clk */
- + if ((div & 0xC) == 0xC) {
- + div += 0x10;
- + div &= ~0xF;
- + }
- + if (div > 0x1000)
- + pr_err("Overflow, di:%d, DI_BS_CLKGEN0 div:0x%x\n",
- + di_div->di_id, (u32)div);
- + _ipu_get(ipu);
- + ipu_di_write(ipu, di_div->di_id, (u32)div, DI_BS_CLKGEN0);
- +
- + /* Setup pixel clock timing */
- + /* FIXME: needs to be more flexible */
- + /* Down time is half of period */
- + ipu_di_write(ipu, di_div->di_id, ((u32)div / 16) << 16, DI_BS_CLKGEN1);
- + _ipu_put(ipu);
- +
- + return 0;
- +}
- +
- +static struct clk_ops clk_div_ops = {
- + .recalc_rate = _ipu_pixel_clk_div_recalc_rate,
- + .round_rate = _ipu_pixel_clk_div_round_rate,
- + .set_rate = _ipu_pixel_clk_div_set_rate,
- +};
- +
- +struct clk *clk_register_div_pix_clk(struct device *dev, const char *name,
- + const char *parent_name, unsigned long flags,
- + u8 ipu_id, u8 di_id, u8 clk_div_flags)
- +{
- + struct clk_di_div *di_div;
- + struct clk *clk;
- + struct clk_init_data init;
- +
- + di_div = kzalloc(sizeof(struct clk_di_div), GFP_KERNEL);
- + if (!di_div)
- + return ERR_PTR(-ENOMEM);
- +
- + /* struct clk_di_div assignments */
- + di_div->ipu_id = ipu_id;
- + di_div->di_id = di_id;
- + di_div->flags = clk_div_flags;
- +
- + init.name = name;
- + init.ops = &clk_div_ops;
- + init.flags = flags | CLK_SET_RATE_PARENT;
- + init.parent_names = parent_name ? &parent_name : NULL;
- + init.num_parents = parent_name ? 1 : 0;
- +
- + di_div->hw.init = &init;
- +
- + clk = clk_register(dev, &di_div->hw);
- + if (IS_ERR(clk))
- + kfree(clk);
- +
- + return clk;
- +}
- +
- +/*
- + * Gated clock implementation
- + */
- +struct clk_di_gate {
- + struct clk_hw hw;
- + u8 ipu_id;
- + u8 di_id;
- + u8 flags;
- +};
- +#define to_clk_di_gate(_hw) container_of(_hw, struct clk_di_gate, hw)
- +
- +static int _ipu_pixel_clk_enable(struct clk_hw *hw)
- +{
- + struct clk_di_gate *gate = to_clk_di_gate(hw);
- + struct ipu_soc *ipu = ipu_get_soc(gate->ipu_id);
- + u32 disp_gen;
- +
- + disp_gen = ipu_cm_read(ipu, IPU_DISP_GEN);
- + disp_gen |= gate->di_id ? DI1_COUNTER_RELEASE : DI0_COUNTER_RELEASE;
- + ipu_cm_write(ipu, disp_gen, IPU_DISP_GEN);
- +
- + return 0;
- +}
- +
- +static void _ipu_pixel_clk_disable(struct clk_hw *hw)
- +{
- + struct clk_di_gate *gate = to_clk_di_gate(hw);
- + struct ipu_soc *ipu = ipu_get_soc(gate->ipu_id);
- + u32 disp_gen;
- +
- + disp_gen = ipu_cm_read(ipu, IPU_DISP_GEN);
- + disp_gen &= gate->di_id ? ~DI1_COUNTER_RELEASE : ~DI0_COUNTER_RELEASE;
- + ipu_cm_write(ipu, disp_gen, IPU_DISP_GEN);
- +
- +}
- +
- +
- +static struct clk_ops clk_gate_di_ops = {
- + .enable = _ipu_pixel_clk_enable,
- + .disable = _ipu_pixel_clk_disable,
- +};
- +
- +struct clk *clk_register_gate_pix_clk(struct device *dev, const char *name,
- + const char *parent_name, unsigned long flags,
- + u8 ipu_id, u8 di_id, u8 clk_gate_flags)
- +{
- + struct clk_di_gate *gate;
- + struct clk *clk;
- + struct clk_init_data init;
- +
- + gate = kzalloc(sizeof(struct clk_di_gate), GFP_KERNEL);
- + if (!gate)
- + return ERR_PTR(-ENOMEM);
- +
- + gate->ipu_id = ipu_id;
- + gate->di_id = di_id;
- + gate->flags = clk_gate_flags;
- +
- + init.name = name;
- + init.ops = &clk_gate_di_ops;
- + init.flags = flags | CLK_SET_RATE_PARENT;
- + init.parent_names = parent_name ? &parent_name : NULL;
- + init.num_parents = parent_name ? 1 : 0;
- +
- + gate->hw.init = &init;
- +
- + clk = clk_register(dev, &gate->hw);
- + if (IS_ERR(clk))
- + kfree(clk);
- +
- + return clk;
- +}
- diff -Nur linux-3.14.35.orig/drivers/mxc/ipu3/ipu_prv.h linux-3.14.35/drivers/mxc/ipu3/ipu_prv.h
- --- linux-3.14.35.orig/drivers/mxc/ipu3/ipu_prv.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/ipu3/ipu_prv.h 2015-03-08 14:27:37.665684500 -0500
- @@ -0,0 +1,356 @@
- +/*
- + * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +#ifndef __INCLUDE_IPU_PRV_H__
- +#define __INCLUDE_IPU_PRV_H__
- +
- +#include <linux/clkdev.h>
- +#include <linux/device.h>
- +#include <linux/fsl_devices.h>
- +#include <linux/interrupt.h>
- +#include <linux/types.h>
- +
- +#define MXC_IPU_MAX_NUM 2
- +#define MXC_DI_NUM_PER_IPU 2
- +
- +/* Globals */
- +extern int dmfc_type_setup;
- +
- +#define IDMA_CHAN_INVALID 0xFF
- +#define HIGH_RESOLUTION_WIDTH 1024
- +
- +struct ipu_irq_node {
- + irqreturn_t(*handler) (int, void *); /*!< the ISR */
- + const char *name; /*!< device associated with the interrupt */
- + void *dev_id; /*!< some unique information for the ISR */
- + __u32 flags; /*!< not used */
- +};
- +
- +enum csc_type_t {
- + RGB2YUV = 0,
- + YUV2RGB,
- + RGB2RGB,
- + YUV2YUV,
- + CSC_NONE,
- + CSC_NUM
- +};
- +
- +enum imx_ipu_type {
- + IMX6Q_IPU,
- +};
- +
- +struct ipu_pltfm_data {
- + u32 id;
- + u32 devtype;
- + int (*init) (int);
- + void (*pg) (int);
- +
- + /*
- + * Bypass reset to avoid display channel being
- + * stopped by probe since it may starts to work
- + * in bootloader.
- + */
- + bool bypass_reset;
- +};
- +
- +struct ipu_soc {
- + bool online;
- + struct ipu_pltfm_data *pdata;
- +
- + /*clk*/
- + struct clk *ipu_clk;
- + struct clk *di_clk[2];
- + struct clk *di_clk_sel[2];
- + struct clk *pixel_clk[2];
- + struct clk *pixel_clk_sel[2];
- + struct clk *csi_clk[2];
- +
- + /*irq*/
- + int irq_sync;
- + int irq_err;
- + struct ipu_irq_node irq_list[IPU_IRQ_COUNT];
- +
- + /*reg*/
- + void __iomem *cm_reg;
- + void __iomem *idmac_reg;
- + void __iomem *dp_reg;
- + void __iomem *ic_reg;
- + void __iomem *dc_reg;
- + void __iomem *dc_tmpl_reg;
- + void __iomem *dmfc_reg;
- + void __iomem *di_reg[2];
- + void __iomem *smfc_reg;
- + void __iomem *csi_reg[2];
- + void __iomem *cpmem_base;
- + void __iomem *tpmem_base;
- + void __iomem *disp_base[2];
- + void __iomem *vdi_reg;
- +
- + struct device *dev;
- +
- + ipu_channel_t csi_channel[2];
- + ipu_channel_t using_ic_dirct_ch;
- + unsigned char dc_di_assignment[10];
- + bool sec_chan_en[24];
- + bool thrd_chan_en[24];
- + bool chan_is_interlaced[52];
- + uint32_t channel_init_mask;
- + uint32_t channel_enable_mask;
- +
- + /*use count*/
- + int dc_use_count;
- + int dp_use_count;
- + int dmfc_use_count;
- + int smfc_use_count;
- + int ic_use_count;
- + int rot_use_count;
- + int vdi_use_count;
- + int di_use_count[2];
- + int csi_use_count[2];
- +
- + struct mutex mutex_lock;
- + spinlock_t int_reg_spin_lock;
- + spinlock_t rdy_reg_spin_lock;
- +
- + int dmfc_size_28;
- + int dmfc_size_29;
- + int dmfc_size_24;
- + int dmfc_size_27;
- + int dmfc_size_23;
- +
- + enum csc_type_t fg_csc_type;
- + enum csc_type_t bg_csc_type;
- + bool color_key_4rgb;
- + bool dc_swap;
- + struct completion dc_comp;
- + struct completion csi_comp;
- +
- + struct rot_mem {
- + void *vaddr;
- + dma_addr_t paddr;
- + int size;
- + } rot_dma[2];
- +
- + int vdoa_en;
- + struct task_struct *thread[2];
- +
- +};
- +
- +struct ipu_channel {
- + u8 video_in_dma;
- + u8 alpha_in_dma;
- + u8 graph_in_dma;
- + u8 out_dma;
- +};
- +
- +enum ipu_dmfc_type {
- + DMFC_NORMAL = 0,
- + DMFC_HIGH_RESOLUTION_DC,
- + DMFC_HIGH_RESOLUTION_DP,
- + DMFC_HIGH_RESOLUTION_ONLY_DP,
- +};
- +
- +static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset)
- +{
- + return readl(ipu->cm_reg + offset);
- +}
- +
- +static inline void ipu_cm_write(struct ipu_soc *ipu,
- + u32 value, unsigned offset)
- +{
- + writel(value, ipu->cm_reg + offset);
- +}
- +
- +static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
- +{
- + return readl(ipu->idmac_reg + offset);
- +}
- +
- +static inline void ipu_idmac_write(struct ipu_soc *ipu,
- + u32 value, unsigned offset)
- +{
- + writel(value, ipu->idmac_reg + offset);
- +}
- +
- +static inline u32 ipu_dc_read(struct ipu_soc *ipu, unsigned offset)
- +{
- + return readl(ipu->dc_reg + offset);
- +}
- +
- +static inline void ipu_dc_write(struct ipu_soc *ipu,
- + u32 value, unsigned offset)
- +{
- + writel(value, ipu->dc_reg + offset);
- +}
- +
- +static inline u32 ipu_dc_tmpl_read(struct ipu_soc *ipu, unsigned offset)
- +{
- + return readl(ipu->dc_tmpl_reg + offset);
- +}
- +
- +static inline void ipu_dc_tmpl_write(struct ipu_soc *ipu,
- + u32 value, unsigned offset)
- +{
- + writel(value, ipu->dc_tmpl_reg + offset);
- +}
- +
- +static inline u32 ipu_dmfc_read(struct ipu_soc *ipu, unsigned offset)
- +{
- + return readl(ipu->dmfc_reg + offset);
- +}
- +
- +static inline void ipu_dmfc_write(struct ipu_soc *ipu,
- + u32 value, unsigned offset)
- +{
- + writel(value, ipu->dmfc_reg + offset);
- +}
- +
- +static inline u32 ipu_dp_read(struct ipu_soc *ipu, unsigned offset)
- +{
- + return readl(ipu->dp_reg + offset);
- +}
- +
- +static inline void ipu_dp_write(struct ipu_soc *ipu,
- + u32 value, unsigned offset)
- +{
- + writel(value, ipu->dp_reg + offset);
- +}
- +
- +static inline u32 ipu_di_read(struct ipu_soc *ipu, int di, unsigned offset)
- +{
- + return readl(ipu->di_reg[di] + offset);
- +}
- +
- +static inline void ipu_di_write(struct ipu_soc *ipu, int di,
- + u32 value, unsigned offset)
- +{
- + writel(value, ipu->di_reg[di] + offset);
- +}
- +
- +static inline u32 ipu_csi_read(struct ipu_soc *ipu, int csi, unsigned offset)
- +{
- + return readl(ipu->csi_reg[csi] + offset);
- +}
- +
- +static inline void ipu_csi_write(struct ipu_soc *ipu, int csi,
- + u32 value, unsigned offset)
- +{
- + writel(value, ipu->csi_reg[csi] + offset);
- +}
- +
- +static inline u32 ipu_smfc_read(struct ipu_soc *ipu, unsigned offset)
- +{
- + return readl(ipu->smfc_reg + offset);
- +}
- +
- +static inline void ipu_smfc_write(struct ipu_soc *ipu,
- + u32 value, unsigned offset)
- +{
- + writel(value, ipu->smfc_reg + offset);
- +}
- +
- +static inline u32 ipu_vdi_read(struct ipu_soc *ipu, unsigned offset)
- +{
- + return readl(ipu->vdi_reg + offset);
- +}
- +
- +static inline void ipu_vdi_write(struct ipu_soc *ipu,
- + u32 value, unsigned offset)
- +{
- + writel(value, ipu->vdi_reg + offset);
- +}
- +
- +static inline u32 ipu_ic_read(struct ipu_soc *ipu, unsigned offset)
- +{
- + return readl(ipu->ic_reg + offset);
- +}
- +
- +static inline void ipu_ic_write(struct ipu_soc *ipu,
- + u32 value, unsigned offset)
- +{
- + writel(value, ipu->ic_reg + offset);
- +}
- +
- +int register_ipu_device(struct ipu_soc *ipu, int id);
- +void unregister_ipu_device(struct ipu_soc *ipu, int id);
- +ipu_color_space_t format_to_colorspace(uint32_t fmt);
- +bool ipu_pixel_format_has_alpha(uint32_t fmt);
- +
- +void ipu_dump_registers(struct ipu_soc *ipu);
- +
- +uint32_t _ipu_channel_status(struct ipu_soc *ipu, ipu_channel_t channel);
- +
- +void ipu_disp_init(struct ipu_soc *ipu);
- +void _ipu_init_dc_mappings(struct ipu_soc *ipu);
- +int _ipu_dp_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t in_pixel_fmt,
- + uint32_t out_pixel_fmt);
- +void _ipu_dp_uninit(struct ipu_soc *ipu, ipu_channel_t channel);
- +void _ipu_dc_init(struct ipu_soc *ipu, int dc_chan, int di, bool interlaced, uint32_t pixel_fmt);
- +void _ipu_dc_uninit(struct ipu_soc *ipu, int dc_chan);
- +void _ipu_dp_dc_enable(struct ipu_soc *ipu, ipu_channel_t channel);
- +void _ipu_dp_dc_disable(struct ipu_soc *ipu, ipu_channel_t channel, bool swap);
- +void _ipu_dmfc_init(struct ipu_soc *ipu, int dmfc_type, int first);
- +void _ipu_dmfc_set_wait4eot(struct ipu_soc *ipu, int dma_chan, int width);
- +void _ipu_dmfc_set_burst_size(struct ipu_soc *ipu, int dma_chan, int burst_size);
- +int _ipu_disp_chan_is_interlaced(struct ipu_soc *ipu, ipu_channel_t channel);
- +
- +void _ipu_ic_enable_task(struct ipu_soc *ipu, ipu_channel_t channel);
- +void _ipu_ic_disable_task(struct ipu_soc *ipu, ipu_channel_t channel);
- +int _ipu_ic_init_prpvf(struct ipu_soc *ipu, ipu_channel_params_t *params,
- + bool src_is_csi);
- +void _ipu_vdi_init(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel_params_t *params);
- +void _ipu_vdi_uninit(struct ipu_soc *ipu);
- +void _ipu_ic_uninit_prpvf(struct ipu_soc *ipu);
- +void _ipu_ic_init_rotate_vf(struct ipu_soc *ipu, ipu_channel_params_t *params);
- +void _ipu_ic_uninit_rotate_vf(struct ipu_soc *ipu);
- +void _ipu_ic_init_csi(struct ipu_soc *ipu, ipu_channel_params_t *params);
- +void _ipu_ic_uninit_csi(struct ipu_soc *ipu);
- +int _ipu_ic_init_prpenc(struct ipu_soc *ipu, ipu_channel_params_t *params,
- + bool src_is_csi);
- +void _ipu_ic_uninit_prpenc(struct ipu_soc *ipu);
- +void _ipu_ic_init_rotate_enc(struct ipu_soc *ipu, ipu_channel_params_t *params);
- +void _ipu_ic_uninit_rotate_enc(struct ipu_soc *ipu);
- +int _ipu_ic_init_pp(struct ipu_soc *ipu, ipu_channel_params_t *params);
- +void _ipu_ic_uninit_pp(struct ipu_soc *ipu);
- +void _ipu_ic_init_rotate_pp(struct ipu_soc *ipu, ipu_channel_params_t *params);
- +void _ipu_ic_uninit_rotate_pp(struct ipu_soc *ipu);
- +int _ipu_ic_idma_init(struct ipu_soc *ipu, int dma_chan, uint16_t width, uint16_t height,
- + int burst_size, ipu_rotate_mode_t rot);
- +void _ipu_vdi_toggle_top_field_man(struct ipu_soc *ipu);
- +int _ipu_csi_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t csi);
- +int _ipu_csi_set_mipi_di(struct ipu_soc *ipu, uint32_t num, uint32_t di_val, uint32_t csi);
- +void ipu_csi_set_test_generator(struct ipu_soc *ipu, bool active, uint32_t r_value,
- + uint32_t g_value, uint32_t b_value,
- + uint32_t pix_clk, uint32_t csi);
- +void _ipu_csi_ccir_err_detection_enable(struct ipu_soc *ipu, uint32_t csi);
- +void _ipu_csi_ccir_err_detection_disable(struct ipu_soc *ipu, uint32_t csi);
- +void _ipu_csi_wait4eof(struct ipu_soc *ipu, ipu_channel_t channel);
- +void _ipu_smfc_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t mipi_id, uint32_t csi);
- +void _ipu_smfc_set_burst_size(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t bs);
- +void _ipu_dp_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3]);
- +int32_t _ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
- + int16_t x_pos, int16_t y_pos);
- +int32_t _ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
- + int16_t *x_pos, int16_t *y_pos);
- +void _ipu_get(struct ipu_soc *ipu);
- +void _ipu_put(struct ipu_soc *ipu);
- +
- +struct clk *clk_register_mux_pix_clk(struct device *dev, const char *name,
- + const char **parent_names, u8 num_parents, unsigned long flags,
- + u8 ipu_id, u8 di_id, u8 clk_mux_flags);
- +struct clk *clk_register_div_pix_clk(struct device *dev, const char *name,
- + const char *parent_name, unsigned long flags,
- + u8 ipu_id, u8 di_id, u8 clk_div_flags);
- +struct clk *clk_register_gate_pix_clk(struct device *dev, const char *name,
- + const char *parent_name, unsigned long flags,
- + u8 ipu_id, u8 di_id, u8 clk_gate_flags);
- +#endif /* __INCLUDE_IPU_PRV_H__ */
- diff -Nur linux-3.14.35.orig/drivers/mxc/ipu3/ipu_regs.h linux-3.14.35/drivers/mxc/ipu3/ipu_regs.h
- --- linux-3.14.35.orig/drivers/mxc/ipu3/ipu_regs.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/ipu3/ipu_regs.h 2015-03-08 14:27:37.665684500 -0500
- @@ -0,0 +1,743 @@
- +/*
- + * Copyright (C) 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*
- + * @file ipu_regs.h
- + *
- + * @brief IPU Register definitions
- + *
- + * @ingroup IPU
- + */
- +#ifndef __IPU_REGS_INCLUDED__
- +#define __IPU_REGS_INCLUDED__
- +
- +enum imx_ipu_rev {
- + IPU_V3DEX = 2,
- + IPU_V3M,
- + IPU_V3H,
- +};
- +
- +/*
- + * hw_rev 2: IPUV3DEX
- + * hw_rev 3: IPUV3M
- + * hw_rev 4: IPUV3H
- + */
- +extern int g_ipu_hw_rev;
- +
- +#define IPU_MAX_VDI_IN_WIDTH ({g_ipu_hw_rev >= 3 ? \
- + (968) : \
- + (720); })
- +#define IPU_DISP0_BASE 0x00000000
- +#define IPU_MCU_T_DEFAULT 8
- +#define IPU_DISP1_BASE ({g_ipu_hw_rev < 4 ? \
- + (IPU_MCU_T_DEFAULT << 25) : \
- + (0x00000000); })
- +#define IPUV3DEX_REG_BASE 0x1E000000
- +#define IPUV3M_REG_BASE 0x06000000
- +#define IPUV3H_REG_BASE 0x00200000
- +
- +#define IPU_CM_REG_BASE 0x00000000
- +#define IPU_IDMAC_REG_BASE 0x00008000
- +#define IPU_ISP_REG_BASE 0x00010000
- +#define IPU_DP_REG_BASE 0x00018000
- +#define IPU_IC_REG_BASE 0x00020000
- +#define IPU_IRT_REG_BASE 0x00028000
- +#define IPU_CSI0_REG_BASE 0x00030000
- +#define IPU_CSI1_REG_BASE 0x00038000
- +#define IPU_DI0_REG_BASE 0x00040000
- +#define IPU_DI1_REG_BASE 0x00048000
- +#define IPU_SMFC_REG_BASE 0x00050000
- +#define IPU_DC_REG_BASE 0x00058000
- +#define IPU_DMFC_REG_BASE 0x00060000
- +#define IPU_VDI_REG_BASE 0x00068000
- +#define IPU_CPMEM_REG_BASE ({g_ipu_hw_rev >= 4 ? \
- + (0x00100000) : \
- + (0x01000000); })
- +#define IPU_LUT_REG_BASE 0x01020000
- +#define IPU_SRM_REG_BASE ({g_ipu_hw_rev >= 4 ? \
- + (0x00140000) : \
- + (0x01040000); })
- +#define IPU_TPM_REG_BASE ({g_ipu_hw_rev >= 4 ? \
- + (0x00160000) : \
- + (0x01060000); })
- +#define IPU_DC_TMPL_REG_BASE ({g_ipu_hw_rev >= 4 ? \
- + (0x00180000) : \
- + (0x01080000); })
- +#define IPU_ISP_TBPR_REG_BASE 0x010C0000
- +
- +/* Register addresses */
- +/* IPU Common registers */
- +#define IPU_CM_REG(offset) (offset)
- +
- +#define IPU_CONF IPU_CM_REG(0)
- +#define IPU_SRM_PRI1 IPU_CM_REG(0x00A0)
- +#define IPU_SRM_PRI2 IPU_CM_REG(0x00A4)
- +#define IPU_FS_PROC_FLOW1 IPU_CM_REG(0x00A8)
- +#define IPU_FS_PROC_FLOW2 IPU_CM_REG(0x00AC)
- +#define IPU_FS_PROC_FLOW3 IPU_CM_REG(0x00B0)
- +#define IPU_FS_DISP_FLOW1 IPU_CM_REG(0x00B4)
- +#define IPU_FS_DISP_FLOW2 IPU_CM_REG(0x00B8)
- +#define IPU_SKIP IPU_CM_REG(0x00BC)
- +#define IPU_DISP_ALT_CONF IPU_CM_REG(0x00C0)
- +#define IPU_DISP_GEN IPU_CM_REG(0x00C4)
- +#define IPU_DISP_ALT1 IPU_CM_REG(0x00C8)
- +#define IPU_DISP_ALT2 IPU_CM_REG(0x00CC)
- +#define IPU_DISP_ALT3 IPU_CM_REG(0x00D0)
- +#define IPU_DISP_ALT4 IPU_CM_REG(0x00D4)
- +#define IPU_SNOOP IPU_CM_REG(0x00D8)
- +#define IPU_MEM_RST IPU_CM_REG(0x00DC)
- +#define IPU_PM IPU_CM_REG(0x00E0)
- +#define IPU_GPR IPU_CM_REG(0x00E4)
- +#define IPU_CHA_DB_MODE_SEL(ch) IPU_CM_REG(0x0150 + 4 * ((ch) / 32))
- +#define IPU_ALT_CHA_DB_MODE_SEL(ch) IPU_CM_REG(0x0168 + 4 * ((ch) / 32))
- +/*
- + * IPUv3D doesn't support triple buffer, so point
- + * IPU_CHA_TRB_MODE_SEL, IPU_CHA_TRIPLE_CUR_BUF and
- + * IPU_CHA_BUF2_RDY to readonly
- + * IPU_ALT_CUR_BUF0 for IPUv3D.
- + */
- +#define IPU_CHA_TRB_MODE_SEL(ch) IPU_CM_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0178 + 4 * ((ch) / 32)) : \
- + (0x012C); })
- +#define IPU_CHA_TRIPLE_CUR_BUF(ch) IPU_CM_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0258 + \
- + 4 * (((ch) * 2) / 32)) : \
- + (0x012C); })
- +#define IPU_CHA_BUF2_RDY(ch) IPU_CM_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0288 + 4 * ((ch) / 32)) : \
- + (0x012C); })
- +#define IPU_CHA_CUR_BUF(ch) IPU_CM_REG({g_ipu_hw_rev >= 2 ? \
- + (0x023C + 4 * ((ch) / 32)) : \
- + (0x0124 + 4 * ((ch) / 32)); })
- +#define IPU_ALT_CUR_BUF0 IPU_CM_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0244) : \
- + (0x012C); })
- +#define IPU_ALT_CUR_BUF1 IPU_CM_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0248) : \
- + (0x0130); })
- +#define IPU_SRM_STAT IPU_CM_REG({g_ipu_hw_rev >= 2 ? \
- + (0x024C) : \
- + (0x0134); })
- +#define IPU_PROC_TASK_STAT IPU_CM_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0250) : \
- + (0x0138); })
- +#define IPU_DISP_TASK_STAT IPU_CM_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0254) : \
- + (0x013C); })
- +#define IPU_CHA_BUF0_RDY(ch) IPU_CM_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0268 + 4 * ((ch) / 32)) : \
- + (0x0140 + 4 * ((ch) / 32)); })
- +#define IPU_CHA_BUF1_RDY(ch) IPU_CM_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0270 + 4 * ((ch) / 32)) : \
- + (0x0148 + 4 * ((ch) / 32)); })
- +#define IPU_ALT_CHA_BUF0_RDY(ch) IPU_CM_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0278 + 4 * ((ch) / 32)) : \
- + (0x0158 + 4 * ((ch) / 32)); })
- +#define IPU_ALT_CHA_BUF1_RDY(ch) IPU_CM_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0280 + 4 * ((ch) / 32)) : \
- + (0x0160 + 4 * ((ch) / 32)); })
- +
- +#define IPU_INT_CTRL(n) IPU_CM_REG(0x003C + 4 * ((n) - 1))
- +#define IPU_INT_STAT(n) IPU_CM_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0200 + 4 * ((n) - 1)) : \
- + (0x00E8 + 4 * ((n) - 1)); })
- +
- +#define IPUIRQ_2_STATREG(irq) IPU_CM_REG(IPU_INT_STAT(1) + 4 * ((irq) / 32))
- +#define IPUIRQ_2_CTRLREG(irq) IPU_CM_REG(IPU_INT_CTRL(1) + 4 * ((irq) / 32))
- +#define IPUIRQ_2_MASK(irq) (1UL << ((irq) & 0x1F))
- +
- +/* IPU VDI registers */
- +#define IPU_VDI_REG(offset) (offset)
- +
- +#define VDI_FSIZE IPU_VDI_REG(0)
- +#define VDI_C IPU_VDI_REG(0x0004)
- +
- +/* IPU CSI Registers */
- +#define IPU_CSI_REG(offset) (offset)
- +
- +#define CSI_SENS_CONF IPU_CSI_REG(0)
- +#define CSI_SENS_FRM_SIZE IPU_CSI_REG(0x0004)
- +#define CSI_ACT_FRM_SIZE IPU_CSI_REG(0x0008)
- +#define CSI_OUT_FRM_CTRL IPU_CSI_REG(0x000C)
- +#define CSI_TST_CTRL IPU_CSI_REG(0x0010)
- +#define CSI_CCIR_CODE_1 IPU_CSI_REG(0x0014)
- +#define CSI_CCIR_CODE_2 IPU_CSI_REG(0x0018)
- +#define CSI_CCIR_CODE_3 IPU_CSI_REG(0x001C)
- +#define CSI_MIPI_DI IPU_CSI_REG(0x0020)
- +#define CSI_SKIP IPU_CSI_REG(0x0024)
- +#define CSI_CPD_CTRL IPU_CSI_REG(0x0028)
- +#define CSI_CPD_RC(n) IPU_CSI_REG(0x002C + 4 * (n))
- +#define CSI_CPD_RS(n) IPU_CSI_REG(0x004C + 4 * (n))
- +#define CSI_CPD_GRC(n) IPU_CSI_REG(0x005C + 4 * (n))
- +#define CSI_CPD_GRS(n) IPU_CSI_REG(0x007C + 4 * (n))
- +#define CSI_CPD_GBC(n) IPU_CSI_REG(0x008C + 4 * (n))
- +#define CSI_CPD_GBS(n) IPU_CSI_REG(0x00AC + 4 * (n))
- +#define CSI_CPD_BC(n) IPU_CSI_REG(0x00BC + 4 * (n))
- +#define CSI_CPD_BS(n) IPU_CSI_REG(0x00DC + 4 * (n))
- +#define CSI_CPD_OFFSET1 IPU_CSI_REG(0x00EC)
- +#define CSI_CPD_OFFSET2 IPU_CSI_REG(0x00F0)
- +
- +/* IPU SMFC Registers */
- +#define IPU_SMFC_REG(offset) (offset)
- +
- +#define SMFC_MAP IPU_SMFC_REG(0)
- +#define SMFC_WMC IPU_SMFC_REG(0x0004)
- +#define SMFC_BS IPU_SMFC_REG(0x0008)
- +
- +/* IPU IC Registers */
- +#define IPU_IC_REG(offset) (offset)
- +
- +#define IC_CONF IPU_IC_REG(0)
- +#define IC_PRP_ENC_RSC IPU_IC_REG(0x0004)
- +#define IC_PRP_VF_RSC IPU_IC_REG(0x0008)
- +#define IC_PP_RSC IPU_IC_REG(0x000C)
- +#define IC_CMBP_1 IPU_IC_REG(0x0010)
- +#define IC_CMBP_2 IPU_IC_REG(0x0014)
- +#define IC_IDMAC_1 IPU_IC_REG(0x0018)
- +#define IC_IDMAC_2 IPU_IC_REG(0x001C)
- +#define IC_IDMAC_3 IPU_IC_REG(0x0020)
- +#define IC_IDMAC_4 IPU_IC_REG(0x0024)
- +
- +/* IPU IDMAC Registers */
- +#define IPU_IDMAC_REG(offset) (offset)
- +
- +#define IDMAC_CONF IPU_IDMAC_REG(0x0000)
- +#define IDMAC_CHA_EN(ch) IPU_IDMAC_REG(0x0004 + 4 * ((ch) / 32))
- +#define IDMAC_SEP_ALPHA IPU_IDMAC_REG(0x000C)
- +#define IDMAC_ALT_SEP_ALPHA IPU_IDMAC_REG(0x0010)
- +#define IDMAC_CHA_PRI(ch) IPU_IDMAC_REG(0x0014 + 4 * ((ch) / 32))
- +#define IDMAC_WM_EN(ch) IPU_IDMAC_REG(0x001C + 4 * ((ch) / 32))
- +#define IDMAC_CH_LOCK_EN_1 IPU_IDMAC_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0024) : 0; })
- +#define IDMAC_CH_LOCK_EN_2 IPU_IDMAC_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0028) : \
- + (0x0024); })
- +#define IDMAC_SUB_ADDR_0 IPU_IDMAC_REG({g_ipu_hw_rev >= 2 ? \
- + (0x002C) : \
- + (0x0028); })
- +#define IDMAC_SUB_ADDR_1 IPU_IDMAC_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0030) : \
- + (0x002C); })
- +#define IDMAC_SUB_ADDR_2 IPU_IDMAC_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0034) : \
- + (0x0030); })
- +/*
- + * IPUv3D doesn't support IDMAC_SUB_ADDR_3 and IDMAC_SUB_ADDR_4,
- + * so point them to readonly IDMAC_CHA_BUSY1 for IPUv3D.
- + */
- +#define IDMAC_SUB_ADDR_3 IPU_IDMAC_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0038) : \
- + (0x0040); })
- +#define IDMAC_SUB_ADDR_4 IPU_IDMAC_REG({g_ipu_hw_rev >= 2 ? \
- + (0x003C) : \
- + (0x0040); })
- +#define IDMAC_BAND_EN(ch) IPU_IDMAC_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0040 + 4 * ((ch) / 32)) : \
- + (0x0034 + 4 * ((ch) / 32)); })
- +#define IDMAC_CHA_BUSY(ch) IPU_IDMAC_REG({g_ipu_hw_rev >= 2 ? \
- + (0x0100 + 4 * ((ch) / 32)) : \
- + (0x0040 + 4 * ((ch) / 32)); })
- +
- +/* IPU DI Registers */
- +#define IPU_DI_REG(offset) (offset)
- +
- +#define DI_GENERAL IPU_DI_REG(0)
- +#define DI_BS_CLKGEN0 IPU_DI_REG(0x0004)
- +#define DI_BS_CLKGEN1 IPU_DI_REG(0x0008)
- +#define DI_SW_GEN0(gen) IPU_DI_REG(0x000C + 4 * ((gen) - 1))
- +#define DI_SW_GEN1(gen) IPU_DI_REG(0x0030 + 4 * ((gen) - 1))
- +#define DI_STP_REP(gen) IPU_DI_REG(0x0148 + 4 * (((gen) - 1) / 2))
- +#define DI_SYNC_AS_GEN IPU_DI_REG(0x0054)
- +#define DI_DW_GEN(gen) IPU_DI_REG(0x0058 + 4 * (gen))
- +#define DI_DW_SET(gen, set) IPU_DI_REG(0x0088 + 4 * ((gen) + 0xC * (set)))
- +#define DI_SER_CONF IPU_DI_REG(0x015C)
- +#define DI_SSC IPU_DI_REG(0x0160)
- +#define DI_POL IPU_DI_REG(0x0164)
- +#define DI_AW0 IPU_DI_REG(0x0168)
- +#define DI_AW1 IPU_DI_REG(0x016C)
- +#define DI_SCR_CONF IPU_DI_REG(0x0170)
- +#define DI_STAT IPU_DI_REG(0x0174)
- +
- +/* IPU DMFC Registers */
- +#define IPU_DMFC_REG(offset) (offset)
- +
- +#define DMFC_RD_CHAN IPU_DMFC_REG(0)
- +#define DMFC_WR_CHAN IPU_DMFC_REG(0x0004)
- +#define DMFC_WR_CHAN_DEF IPU_DMFC_REG(0x0008)
- +#define DMFC_DP_CHAN IPU_DMFC_REG(0x000C)
- +#define DMFC_DP_CHAN_DEF IPU_DMFC_REG(0x0010)
- +#define DMFC_GENERAL1 IPU_DMFC_REG(0x0014)
- +#define DMFC_GENERAL2 IPU_DMFC_REG(0x0018)
- +#define DMFC_IC_CTRL IPU_DMFC_REG(0x001C)
- +#define DMFC_STAT IPU_DMFC_REG(0x0020)
- +
- +/* IPU DC Registers */
- +#define IPU_DC_REG(offset) (offset)
- +
- +#define DC_MAP_CONF_PTR(n) IPU_DC_REG(0x0108 + ((n) & ~0x1) * 2)
- +#define DC_MAP_CONF_VAL(n) IPU_DC_REG(0x0144 + ((n) & ~0x1) * 2)
- +
- +#define _RL_CH_2_OFFSET(ch) (((ch) == 0) ? 8 : ( \
- + ((ch) == 1) ? 0x24 : ( \
- + ((ch) == 2) ? 0x40 : ( \
- + ((ch) == 5) ? 0x64 : ( \
- + ((ch) == 6) ? 0x80 : ( \
- + ((ch) == 8) ? 0x9C : ( \
- + ((ch) == 9) ? 0xBC : (-1))))))))
- +#define DC_RL_CH(ch, evt) IPU_DC_REG(_RL_CH_2_OFFSET(ch) + \
- + ((evt) & ~0x1) * 2)
- +
- +#define DC_EVT_NF 0
- +#define DC_EVT_NL 1
- +#define DC_EVT_EOF 2
- +#define DC_EVT_NFIELD 3
- +#define DC_EVT_EOL 4
- +#define DC_EVT_EOFIELD 5
- +#define DC_EVT_NEW_ADDR 6
- +#define DC_EVT_NEW_CHAN 7
- +#define DC_EVT_NEW_DATA 8
- +
- +#define DC_EVT_NEW_ADDR_W_0 0
- +#define DC_EVT_NEW_ADDR_W_1 1
- +#define DC_EVT_NEW_CHAN_W_0 2
- +#define DC_EVT_NEW_CHAN_W_1 3
- +#define DC_EVT_NEW_DATA_W_0 4
- +#define DC_EVT_NEW_DATA_W_1 5
- +#define DC_EVT_NEW_ADDR_R_0 6
- +#define DC_EVT_NEW_ADDR_R_1 7
- +#define DC_EVT_NEW_CHAN_R_0 8
- +#define DC_EVT_NEW_CHAN_R_1 9
- +#define DC_EVT_NEW_DATA_R_0 10
- +#define DC_EVT_NEW_DATA_R_1 11
- +#define DC_EVEN_UGDE0 12
- +#define DC_ODD_UGDE0 13
- +#define DC_EVEN_UGDE1 14
- +#define DC_ODD_UGDE1 15
- +#define DC_EVEN_UGDE2 16
- +#define DC_ODD_UGDE2 17
- +#define DC_EVEN_UGDE3 18
- +#define DC_ODD_UGDE3 19
- +
- +#define dc_ch_offset(ch) \
- +({ \
- + const u8 _offset[] = { \
- + 0, 0x1C, 0x38, 0x54, 0x58, 0x5C, 0x78, 0, 0x94, 0xB4}; \
- + _offset[ch]; \
- +})
- +#define DC_WR_CH_CONF(ch) IPU_DC_REG(dc_ch_offset(ch))
- +#define DC_WR_CH_ADDR(ch) IPU_DC_REG(dc_ch_offset(ch) + 4)
- +
- +#define DC_WR_CH_CONF_1 IPU_DC_REG(0x001C)
- +#define DC_WR_CH_ADDR_1 IPU_DC_REG(0x0020)
- +#define DC_WR_CH_CONF_5 IPU_DC_REG(0x005C)
- +#define DC_WR_CH_ADDR_5 IPU_DC_REG(0x0060)
- +#define DC_GEN IPU_DC_REG(0x00D4)
- +#define DC_DISP_CONF1(disp) IPU_DC_REG(0x00D8 + 4 * (disp))
- +#define DC_DISP_CONF2(disp) IPU_DC_REG(0x00E8 + 4 * (disp))
- +#define DC_STAT IPU_DC_REG(0x01C8)
- +#define DC_UGDE_0(evt) IPU_DC_REG(0x0174 + 16 * (evt))
- +#define DC_UGDE_1(evt) IPU_DC_REG(0x0178 + 16 * (evt))
- +#define DC_UGDE_2(evt) IPU_DC_REG(0x017C + 16 * (evt))
- +#define DC_UGDE_3(evt) IPU_DC_REG(0x0180 + 16 * (evt))
- +
- +/* IPU DP Registers */
- +#define IPU_DP_REG(offset) (offset)
- +
- +#define DP_SYNC 0
- +#define DP_ASYNC0 0x60
- +#define DP_ASYNC1 0xBC
- +#define DP_COM_CONF(flow) IPU_DP_REG(flow)
- +#define DP_GRAPH_WIND_CTRL(flow) IPU_DP_REG(0x0004 + (flow))
- +#define DP_FG_POS(flow) IPU_DP_REG(0x0008 + (flow))
- +#define DP_GAMMA_C(flow, i) IPU_DP_REG(0x0014 + (flow) + 4 * (i))
- +#define DP_GAMMA_S(flow, i) IPU_DP_REG(0x0034 + (flow) + 4 * (i))
- +#define DP_CSC_A_0(flow) IPU_DP_REG(0x0044 + (flow))
- +#define DP_CSC_A_1(flow) IPU_DP_REG(0x0048 + (flow))
- +#define DP_CSC_A_2(flow) IPU_DP_REG(0x004C + (flow))
- +#define DP_CSC_A_3(flow) IPU_DP_REG(0x0050 + (flow))
- +#define DP_CSC_0(flow) IPU_DP_REG(0x0054 + (flow))
- +#define DP_CSC_1(flow) IPU_DP_REG(0x0058 + (flow))
- +
- +enum {
- + IPU_CONF_CSI0_EN = 0x00000001,
- + IPU_CONF_CSI1_EN = 0x00000002,
- + IPU_CONF_IC_EN = 0x00000004,
- + IPU_CONF_ROT_EN = 0x00000008,
- + IPU_CONF_ISP_EN = 0x00000010,
- + IPU_CONF_DP_EN = 0x00000020,
- + IPU_CONF_DI0_EN = 0x00000040,
- + IPU_CONF_DI1_EN = 0x00000080,
- + IPU_CONF_DMFC_EN = 0x00000400,
- + IPU_CONF_SMFC_EN = 0x00000100,
- + IPU_CONF_DC_EN = 0x00000200,
- + IPU_CONF_VDI_EN = 0x00001000,
- + IPU_CONF_IDMAC_DIS = 0x00400000,
- + IPU_CONF_IC_DMFC_SEL = 0x02000000,
- + IPU_CONF_IC_DMFC_SYNC = 0x04000000,
- + IPU_CONF_VDI_DMFC_SYNC = 0x08000000,
- + IPU_CONF_CSI0_DATA_SOURCE = 0x10000000,
- + IPU_CONF_CSI0_DATA_SOURCE_OFFSET = 28,
- + IPU_CONF_CSI1_DATA_SOURCE = 0x20000000,
- + IPU_CONF_IC_INPUT = 0x40000000,
- + IPU_CONF_CSI_SEL = 0x80000000,
- +
- + DI0_COUNTER_RELEASE = 0x01000000,
- + DI1_COUNTER_RELEASE = 0x02000000,
- +
- + FS_PRPVF_ROT_SRC_SEL_MASK = 0x00000F00,
- + FS_PRPVF_ROT_SRC_SEL_OFFSET = 8,
- + FS_PRPENC_ROT_SRC_SEL_MASK = 0x0000000F,
- + FS_PRPENC_ROT_SRC_SEL_OFFSET = 0,
- + FS_PP_ROT_SRC_SEL_MASK = 0x000F0000,
- + FS_PP_ROT_SRC_SEL_OFFSET = 16,
- + FS_PP_SRC_SEL_MASK = 0x0000F000,
- + FS_PP_SRC_SEL_VDOA = 0x00008000,
- + FS_PP_SRC_SEL_OFFSET = 12,
- + FS_PRP_SRC_SEL_MASK = 0x0F000000,
- + FS_PRP_SRC_SEL_OFFSET = 24,
- + FS_VF_IN_VALID = 0x80000000,
- + FS_ENC_IN_VALID = 0x40000000,
- + FS_VDI_SRC_SEL_MASK = 0x30000000,
- + FS_VDI_SRC_SEL_VDOA = 0x20000000,
- + FS_VDOA_DEST_SEL_MASK = 0x00030000,
- + FS_VDOA_DEST_SEL_VDI = 0x00020000,
- + FS_VDOA_DEST_SEL_IC = 0x00010000,
- + FS_VDI_SRC_SEL_OFFSET = 28,
- +
- +
- + FS_PRPENC_DEST_SEL_MASK = 0x0000000F,
- + FS_PRPENC_DEST_SEL_OFFSET = 0,
- + FS_PRPVF_DEST_SEL_MASK = 0x000000F0,
- + FS_PRPVF_DEST_SEL_OFFSET = 4,
- + FS_PRPVF_ROT_DEST_SEL_MASK = 0x00000F00,
- + FS_PRPVF_ROT_DEST_SEL_OFFSET = 8,
- + FS_PP_DEST_SEL_MASK = 0x0000F000,
- + FS_PP_DEST_SEL_OFFSET = 12,
- + FS_PP_ROT_DEST_SEL_MASK = 0x000F0000,
- + FS_PP_ROT_DEST_SEL_OFFSET = 16,
- + FS_PRPENC_ROT_DEST_SEL_MASK = 0x00F00000,
- + FS_PRPENC_ROT_DEST_SEL_OFFSET = 20,
- +
- + FS_SMFC0_DEST_SEL_MASK = 0x0000000F,
- + FS_SMFC0_DEST_SEL_OFFSET = 0,
- + FS_SMFC1_DEST_SEL_MASK = 0x00000070,
- + FS_SMFC1_DEST_SEL_OFFSET = 4,
- + FS_SMFC2_DEST_SEL_MASK = 0x00000780,
- + FS_SMFC2_DEST_SEL_OFFSET = 7,
- + FS_SMFC3_DEST_SEL_MASK = 0x00003800,
- + FS_SMFC3_DEST_SEL_OFFSET = 11,
- +
- + FS_DC1_SRC_SEL_MASK = 0x00F00000,
- + FS_DC1_SRC_SEL_OFFSET = 20,
- + FS_DC2_SRC_SEL_MASK = 0x000F0000,
- + FS_DC2_SRC_SEL_OFFSET = 16,
- + FS_DP_SYNC0_SRC_SEL_MASK = 0x0000000F,
- + FS_DP_SYNC0_SRC_SEL_OFFSET = 0,
- + FS_DP_SYNC1_SRC_SEL_MASK = 0x000000F0,
- + FS_DP_SYNC1_SRC_SEL_OFFSET = 4,
- + FS_DP_ASYNC0_SRC_SEL_MASK = 0x00000F00,
- + FS_DP_ASYNC0_SRC_SEL_OFFSET = 8,
- + FS_DP_ASYNC1_SRC_SEL_MASK = 0x0000F000,
- + FS_DP_ASYNC1_SRC_SEL_OFFSET = 12,
- +
- + FS_AUTO_REF_PER_MASK = 0,
- + FS_AUTO_REF_PER_OFFSET = 16,
- +
- + TSTAT_VF_MASK = 0x0000000C,
- + TSTAT_VF_OFFSET = 2,
- + TSTAT_VF_ROT_MASK = 0x00000300,
- + TSTAT_VF_ROT_OFFSET = 8,
- + TSTAT_ENC_MASK = 0x00000003,
- + TSTAT_ENC_OFFSET = 0,
- + TSTAT_ENC_ROT_MASK = 0x000000C0,
- + TSTAT_ENC_ROT_OFFSET = 6,
- + TSTAT_PP_MASK = 0x00000030,
- + TSTAT_PP_OFFSET = 4,
- + TSTAT_PP_ROT_MASK = 0x00000C00,
- + TSTAT_PP_ROT_OFFSET = 10,
- +
- + TASK_STAT_IDLE = 0,
- + TASK_STAT_ACTIVE = 1,
- + TASK_STAT_WAIT4READY = 2,
- +
- + /* Image Converter Register bits */
- + IC_CONF_PRPENC_EN = 0x00000001,
- + IC_CONF_PRPENC_CSC1 = 0x00000002,
- + IC_CONF_PRPENC_ROT_EN = 0x00000004,
- + IC_CONF_PRPVF_EN = 0x00000100,
- + IC_CONF_PRPVF_CSC1 = 0x00000200,
- + IC_CONF_PRPVF_CSC2 = 0x00000400,
- + IC_CONF_PRPVF_CMB = 0x00000800,
- + IC_CONF_PRPVF_ROT_EN = 0x00001000,
- + IC_CONF_PP_EN = 0x00010000,
- + IC_CONF_PP_CSC1 = 0x00020000,
- + IC_CONF_PP_CSC2 = 0x00040000,
- + IC_CONF_PP_CMB = 0x00080000,
- + IC_CONF_PP_ROT_EN = 0x00100000,
- + IC_CONF_IC_GLB_LOC_A = 0x10000000,
- + IC_CONF_KEY_COLOR_EN = 0x20000000,
- + IC_CONF_RWS_EN = 0x40000000,
- + IC_CONF_CSI_MEM_WR_EN = 0x80000000,
- +
- + IC_RSZ_MAX_RESIZE_RATIO = 0x00004000,
- +
- + IC_IDMAC_1_CB0_BURST_16 = 0x00000001,
- + IC_IDMAC_1_CB1_BURST_16 = 0x00000002,
- + IC_IDMAC_1_CB2_BURST_16 = 0x00000004,
- + IC_IDMAC_1_CB3_BURST_16 = 0x00000008,
- + IC_IDMAC_1_CB4_BURST_16 = 0x00000010,
- + IC_IDMAC_1_CB5_BURST_16 = 0x00000020,
- + IC_IDMAC_1_CB6_BURST_16 = 0x00000040,
- + IC_IDMAC_1_CB7_BURST_16 = 0x00000080,
- + IC_IDMAC_1_PRPENC_ROT_MASK = 0x00003800,
- + IC_IDMAC_1_PRPENC_ROT_OFFSET = 11,
- + IC_IDMAC_1_PRPVF_ROT_MASK = 0x0001C000,
- + IC_IDMAC_1_PRPVF_ROT_OFFSET = 14,
- + IC_IDMAC_1_PP_ROT_MASK = 0x000E0000,
- + IC_IDMAC_1_PP_ROT_OFFSET = 17,
- + IC_IDMAC_1_PP_FLIP_RS = 0x00400000,
- + IC_IDMAC_1_PRPVF_FLIP_RS = 0x00200000,
- + IC_IDMAC_1_PRPENC_FLIP_RS = 0x00100000,
- +
- + IC_IDMAC_2_PRPENC_HEIGHT_MASK = 0x000003FF,
- + IC_IDMAC_2_PRPENC_HEIGHT_OFFSET = 0,
- + IC_IDMAC_2_PRPVF_HEIGHT_MASK = 0x000FFC00,
- + IC_IDMAC_2_PRPVF_HEIGHT_OFFSET = 10,
- + IC_IDMAC_2_PP_HEIGHT_MASK = 0x3FF00000,
- + IC_IDMAC_2_PP_HEIGHT_OFFSET = 20,
- +
- + IC_IDMAC_3_PRPENC_WIDTH_MASK = 0x000003FF,
- + IC_IDMAC_3_PRPENC_WIDTH_OFFSET = 0,
- + IC_IDMAC_3_PRPVF_WIDTH_MASK = 0x000FFC00,
- + IC_IDMAC_3_PRPVF_WIDTH_OFFSET = 10,
- + IC_IDMAC_3_PP_WIDTH_MASK = 0x3FF00000,
- + IC_IDMAC_3_PP_WIDTH_OFFSET = 20,
- +
- + CSI_SENS_CONF_DATA_FMT_SHIFT = 8,
- + CSI_SENS_CONF_DATA_FMT_MASK = 0x00000700,
- + CSI_SENS_CONF_DATA_FMT_RGB_YUV444 = 0L,
- + CSI_SENS_CONF_DATA_FMT_YUV422_YUYV = 1L,
- + CSI_SENS_CONF_DATA_FMT_YUV422_UYVY = 2L,
- + CSI_SENS_CONF_DATA_FMT_BAYER = 3L,
- + CSI_SENS_CONF_DATA_FMT_RGB565 = 4L,
- + CSI_SENS_CONF_DATA_FMT_RGB555 = 5L,
- + CSI_SENS_CONF_DATA_FMT_RGB444 = 6L,
- + CSI_SENS_CONF_DATA_FMT_JPEG = 7L,
- +
- + CSI_SENS_CONF_VSYNC_POL_SHIFT = 0,
- + CSI_SENS_CONF_HSYNC_POL_SHIFT = 1,
- + CSI_SENS_CONF_DATA_POL_SHIFT = 2,
- + CSI_SENS_CONF_PIX_CLK_POL_SHIFT = 3,
- + CSI_SENS_CONF_SENS_PRTCL_MASK = 0x00000070L,
- + CSI_SENS_CONF_SENS_PRTCL_SHIFT = 4,
- + CSI_SENS_CONF_PACK_TIGHT_SHIFT = 7,
- + CSI_SENS_CONF_DATA_WIDTH_SHIFT = 11,
- + CSI_SENS_CONF_EXT_VSYNC_SHIFT = 15,
- + CSI_SENS_CONF_DIVRATIO_SHIFT = 16,
- +
- + CSI_SENS_CONF_DIVRATIO_MASK = 0x00FF0000L,
- + CSI_SENS_CONF_DATA_DEST_SHIFT = 24,
- + CSI_SENS_CONF_DATA_DEST_MASK = 0x07000000L,
- + CSI_SENS_CONF_JPEG8_EN_SHIFT = 27,
- + CSI_SENS_CONF_JPEG_EN_SHIFT = 28,
- + CSI_SENS_CONF_FORCE_EOF_SHIFT = 29,
- + CSI_SENS_CONF_DATA_EN_POL_SHIFT = 31,
- +
- + CSI_DATA_DEST_ISP = 1L,
- + CSI_DATA_DEST_IC = 2L,
- + CSI_DATA_DEST_IDMAC = 4L,
- +
- + CSI_CCIR_ERR_DET_EN = 0x01000000L,
- + CSI_HORI_DOWNSIZE_EN = 0x80000000L,
- + CSI_VERT_DOWNSIZE_EN = 0x40000000L,
- + CSI_TEST_GEN_MODE_EN = 0x01000000L,
- +
- + CSI_HSC_MASK = 0x1FFF0000,
- + CSI_HSC_SHIFT = 16,
- + CSI_VSC_MASK = 0x00000FFF,
- + CSI_VSC_SHIFT = 0,
- +
- + CSI_TEST_GEN_R_MASK = 0x000000FFL,
- + CSI_TEST_GEN_R_SHIFT = 0,
- + CSI_TEST_GEN_G_MASK = 0x0000FF00L,
- + CSI_TEST_GEN_G_SHIFT = 8,
- + CSI_TEST_GEN_B_MASK = 0x00FF0000L,
- + CSI_TEST_GEN_B_SHIFT = 16,
- +
- + CSI_MIPI_DI0_MASK = 0x000000FFL,
- + CSI_MIPI_DI0_SHIFT = 0,
- + CSI_MIPI_DI1_MASK = 0x0000FF00L,
- + CSI_MIPI_DI1_SHIFT = 8,
- + CSI_MIPI_DI2_MASK = 0x00FF0000L,
- + CSI_MIPI_DI2_SHIFT = 16,
- + CSI_MIPI_DI3_MASK = 0xFF000000L,
- + CSI_MIPI_DI3_SHIFT = 24,
- +
- + CSI_MAX_RATIO_SKIP_ISP_MASK = 0x00070000L,
- + CSI_MAX_RATIO_SKIP_ISP_SHIFT = 16,
- + CSI_SKIP_ISP_MASK = 0x00F80000L,
- + CSI_SKIP_ISP_SHIFT = 19,
- + CSI_MAX_RATIO_SKIP_SMFC_MASK = 0x00000007L,
- + CSI_MAX_RATIO_SKIP_SMFC_SHIFT = 0,
- + CSI_SKIP_SMFC_MASK = 0x000000F8L,
- + CSI_SKIP_SMFC_SHIFT = 3,
- + CSI_ID_2_SKIP_MASK = 0x00000300L,
- + CSI_ID_2_SKIP_SHIFT = 8,
- +
- + CSI_COLOR_FIRST_ROW_MASK = 0x00000002L,
- + CSI_COLOR_FIRST_COMP_MASK = 0x00000001L,
- +
- + SMFC_MAP_CH0_MASK = 0x00000007L,
- + SMFC_MAP_CH0_SHIFT = 0,
- + SMFC_MAP_CH1_MASK = 0x00000038L,
- + SMFC_MAP_CH1_SHIFT = 3,
- + SMFC_MAP_CH2_MASK = 0x000001C0L,
- + SMFC_MAP_CH2_SHIFT = 6,
- + SMFC_MAP_CH3_MASK = 0x00000E00L,
- + SMFC_MAP_CH3_SHIFT = 9,
- +
- + SMFC_WM0_SET_MASK = 0x00000007L,
- + SMFC_WM0_SET_SHIFT = 0,
- + SMFC_WM1_SET_MASK = 0x000001C0L,
- + SMFC_WM1_SET_SHIFT = 6,
- + SMFC_WM2_SET_MASK = 0x00070000L,
- + SMFC_WM2_SET_SHIFT = 16,
- + SMFC_WM3_SET_MASK = 0x01C00000L,
- + SMFC_WM3_SET_SHIFT = 22,
- +
- + SMFC_WM0_CLR_MASK = 0x00000038L,
- + SMFC_WM0_CLR_SHIFT = 3,
- + SMFC_WM1_CLR_MASK = 0x00000E00L,
- + SMFC_WM1_CLR_SHIFT = 9,
- + SMFC_WM2_CLR_MASK = 0x00380000L,
- + SMFC_WM2_CLR_SHIFT = 19,
- + SMFC_WM3_CLR_MASK = 0x0E000000L,
- + SMFC_WM3_CLR_SHIFT = 25,
- +
- + SMFC_BS0_MASK = 0x0000000FL,
- + SMFC_BS0_SHIFT = 0,
- + SMFC_BS1_MASK = 0x000000F0L,
- + SMFC_BS1_SHIFT = 4,
- + SMFC_BS2_MASK = 0x00000F00L,
- + SMFC_BS2_SHIFT = 8,
- + SMFC_BS3_MASK = 0x0000F000L,
- + SMFC_BS3_SHIFT = 12,
- +
- + PF_CONF_TYPE_MASK = 0x00000007,
- + PF_CONF_TYPE_SHIFT = 0,
- + PF_CONF_PAUSE_EN = 0x00000010,
- + PF_CONF_RESET = 0x00008000,
- + PF_CONF_PAUSE_ROW_MASK = 0x00FF0000,
- + PF_CONF_PAUSE_ROW_SHIFT = 16,
- +
- + DI_DW_GEN_ACCESS_SIZE_OFFSET = 24,
- + DI_DW_GEN_COMPONENT_SIZE_OFFSET = 16,
- +
- + DI_GEN_DI_CLK_EXT = 0x100000,
- + DI_GEN_POLARITY_DISP_CLK = 0x00020000,
- + DI_GEN_POLARITY_1 = 0x00000001,
- + DI_GEN_POLARITY_2 = 0x00000002,
- + DI_GEN_POLARITY_3 = 0x00000004,
- + DI_GEN_POLARITY_4 = 0x00000008,
- + DI_GEN_POLARITY_5 = 0x00000010,
- + DI_GEN_POLARITY_6 = 0x00000020,
- + DI_GEN_POLARITY_7 = 0x00000040,
- + DI_GEN_POLARITY_8 = 0x00000080,
- +
- + DI_POL_DRDY_DATA_POLARITY = 0x00000080,
- + DI_POL_DRDY_POLARITY_15 = 0x00000010,
- +
- + DI_VSYNC_SEL_OFFSET = 13,
- +
- + DC_WR_CH_CONF_FIELD_MODE = 0x00000200,
- + DC_WR_CH_CONF_PROG_TYPE_OFFSET = 5,
- + DC_WR_CH_CONF_PROG_TYPE_MASK = 0x000000E0,
- + DC_WR_CH_CONF_PROG_DI_ID = 0x00000004,
- + DC_WR_CH_CONF_PROG_DISP_ID_OFFSET = 3,
- + DC_WR_CH_CONF_PROG_DISP_ID_MASK = 0x00000018,
- +
- + DC_UGDE_0_ODD_EN = 0x02000000,
- + DC_UGDE_0_ID_CODED_MASK = 0x00000007,
- + DC_UGDE_0_ID_CODED_OFFSET = 0,
- + DC_UGDE_0_EV_PRIORITY_MASK = 0x00000078,
- + DC_UGDE_0_EV_PRIORITY_OFFSET = 3,
- +
- + DP_COM_CONF_FG_EN = 0x00000001,
- + DP_COM_CONF_GWSEL = 0x00000002,
- + DP_COM_CONF_GWAM = 0x00000004,
- + DP_COM_CONF_GWCKE = 0x00000008,
- + DP_COM_CONF_CSC_DEF_MASK = 0x00000300,
- + DP_COM_CONF_CSC_DEF_OFFSET = 8,
- + DP_COM_CONF_CSC_DEF_FG = 0x00000300,
- + DP_COM_CONF_CSC_DEF_BG = 0x00000200,
- + DP_COM_CONF_CSC_DEF_BOTH = 0x00000100,
- + DP_COM_CONF_GAMMA_EN = 0x00001000,
- + DP_COM_CONF_GAMMA_YUV_EN = 0x00002000,
- +
- + DI_SER_CONF_LLA_SER_ACCESS = 0x00000020,
- + DI_SER_CONF_SERIAL_CLK_POL = 0x00000010,
- + DI_SER_CONF_SERIAL_DATA_POL = 0x00000008,
- + DI_SER_CONF_SERIAL_RS_POL = 0x00000004,
- + DI_SER_CONF_SERIAL_CS_POL = 0x00000002,
- + DI_SER_CONF_WAIT4SERIAL = 0x00000001,
- +
- + VDI_C_CH_420 = 0x00000000,
- + VDI_C_CH_422 = 0x00000002,
- + VDI_C_MOT_SEL_FULL = 0x00000008,
- + VDI_C_MOT_SEL_LOW = 0x00000004,
- + VDI_C_MOT_SEL_MED = 0x00000000,
- + VDI_C_BURST_SIZE1_4 = 0x00000030,
- + VDI_C_BURST_SIZE2_4 = 0x00000300,
- + VDI_C_BURST_SIZE3_4 = 0x00003000,
- + VDI_C_BURST_SIZE_MASK = 0xF,
- + VDI_C_BURST_SIZE1_OFFSET = 4,
- + VDI_C_BURST_SIZE2_OFFSET = 8,
- + VDI_C_BURST_SIZE3_OFFSET = 12,
- + VDI_C_VWM1_SET_1 = 0x00000000,
- + VDI_C_VWM1_SET_2 = 0x00010000,
- + VDI_C_VWM1_CLR_2 = 0x00080000,
- + VDI_C_VWM3_SET_1 = 0x00000000,
- + VDI_C_VWM3_SET_2 = 0x00400000,
- + VDI_C_VWM3_CLR_2 = 0x02000000,
- + VDI_C_TOP_FIELD_MAN_1 = 0x40000000,
- + VDI_C_TOP_FIELD_AUTO_1 = 0x80000000,
- +};
- +
- +enum di_pins {
- + DI_PIN11 = 0,
- + DI_PIN12 = 1,
- + DI_PIN13 = 2,
- + DI_PIN14 = 3,
- + DI_PIN15 = 4,
- + DI_PIN16 = 5,
- + DI_PIN17 = 6,
- + DI_PIN_CS = 7,
- +
- + DI_PIN_SER_CLK = 0,
- + DI_PIN_SER_RS = 1,
- +};
- +
- +enum di_sync_wave {
- + DI_SYNC_NONE = -1,
- + DI_SYNC_CLK = 0,
- + DI_SYNC_INT_HSYNC = 1,
- + DI_SYNC_HSYNC = 2,
- + DI_SYNC_VSYNC = 3,
- + DI_SYNC_DE = 5,
- +};
- +
- +/* DC template opcodes */
- +#define WROD(lf) (0x18 | (lf << 1))
- +#define WRG (0x01)
- +
- +#endif
- diff -Nur linux-3.14.35.orig/drivers/mxc/ipu3/Kconfig linux-3.14.35/drivers/mxc/ipu3/Kconfig
- --- linux-3.14.35.orig/drivers/mxc/ipu3/Kconfig 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/ipu3/Kconfig 2015-03-08 14:27:37.665684500 -0500
- @@ -0,0 +1,2 @@
- +config MXC_IPU_V3
- + bool
- diff -Nur linux-3.14.35.orig/drivers/mxc/ipu3/Makefile linux-3.14.35/drivers/mxc/ipu3/Makefile
- --- linux-3.14.35.orig/drivers/mxc/ipu3/Makefile 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/ipu3/Makefile 2015-03-08 14:27:37.665684500 -0500
- @@ -0,0 +1,4 @@
- +obj-$(CONFIG_MXC_IPU_V3) = mxc_ipu.o
- +
- +mxc_ipu-objs := ipu_common.o ipu_ic.o ipu_disp.o ipu_capture.o ipu_device.o \
- + ipu_calc_stripes_sizes.o vdoa.o ipu_pixel_clk.o
- diff -Nur linux-3.14.35.orig/drivers/mxc/ipu3/vdoa.c linux-3.14.35/drivers/mxc/ipu3/vdoa.c
- --- linux-3.14.35.orig/drivers/mxc/ipu3/vdoa.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/ipu3/vdoa.c 2015-03-08 14:27:37.665684500 -0500
- @@ -0,0 +1,543 @@
- +/*
- + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +#include <linux/clk.h>
- +#include <linux/err.h>
- +#include <linux/io.h>
- +#include <linux/ipu.h>
- +#include <linux/genalloc.h>
- +#include <linux/module.h>
- +#include <linux/platform_device.h>
- +#include <linux/slab.h>
- +#include <linux/types.h>
- +
- +#include "vdoa.h"
- +/* 6band(3field* double buffer) * (width*2) * bandline(8)
- + = 6x1024x2x8 = 96k or 72k(1.5byte) */
- +#define MAX_VDOA_IRAM_SIZE (1024*96)
- +#define VDOA_IRAM_SIZE (1024*72)
- +
- +#define VDOAC_BAND_HEIGHT_32LINES (32)
- +#define VDOAC_BAND_HEIGHT_16LINES (16)
- +#define VDOAC_BAND_HEIGHT_8LINES (8)
- +#define VDOAC_THREE_FRAMES (0x1 << 2)
- +#define VDOAC_SYNC_BAND_MODE (0x1 << 3)
- +#define VDOAC_SCAN_ORDER_INTERLACED (0x1 << 4)
- +#define VDOAC_PFS_YUYV (0x1 << 5)
- +#define VDOAC_IPU_SEL_1 (0x1 << 6)
- +#define VDOAFP_FH_MASK (0x1FFF)
- +#define VDOAFP_FH_SHIFT (16)
- +#define VDOAFP_FW_MASK (0x3FFF)
- +#define VDOAFP_FW_SHIFT (0)
- +#define VDOASL_VSLY_MASK (0x3FFF)
- +#define VDOASL_VSLY_SHIFT (16)
- +#define VDOASL_ISLY_MASK (0x7FFF)
- +#define VDOASL_ISLY_SHIFT (0)
- +#define VDOASRR_START_XFER (0x2)
- +#define VDOASRR_SWRST (0x1)
- +#define VDOAIEIST_TRANSFER_ERR (0x2)
- +#define VDOAIEIST_TRANSFER_END (0x1)
- +
- +#define VDOAC (0x0) /* Control Register */
- +#define VDOASRR (0x4) /* Start and Reset Register */
- +#define VDOAIE (0x8) /* Interrupt Enable Register */
- +#define VDOAIST (0xc) /* Interrupt Status Register */
- +#define VDOAFP (0x10) /* Frame Parameters Register */
- +#define VDOAIEBA00 (0x14) /* External Buffer n Frame m Address Register */
- +#define VDOAIEBA01 (0x18) /* External Buffer n Frame m Address Register */
- +#define VDOAIEBA02 (0x1c) /* External Buffer n Frame m Address Register */
- +#define VDOAIEBA10 (0x20) /* External Buffer n Frame m Address Register */
- +#define VDOAIEBA11 (0x24) /* External Buffer n Frame m Address Register */
- +#define VDOAIEBA12 (0x28) /* External Buffer n Frame m Address Register */
- +#define VDOASL (0x2c) /* IPU Stride Line Register */
- +#define VDOAIUBO (0x30) /* IPU Chroma Buffer Offset Register */
- +#define VDOAVEBA0 (0x34) /* External Buffer m Address Register */
- +#define VDOAVEBA1 (0x38) /* External Buffer m Address Register */
- +#define VDOAVEBA2 (0x3c) /* External Buffer m Address Register */
- +#define VDOAVUBO (0x40) /* VPU Chroma Buffer Offset */
- +#define VDOASR (0x44) /* Status Register */
- +#define VDOATD (0x48) /* Test Debug Register */
- +
- +
- +enum {
- + VDOA_INIT = 0x1,
- + VDOA_GET = 0x2,
- + VDOA_SETUP = 0x4,
- + VDOA_GET_OBUF = 0x8,
- + VDOA_START = 0x10,
- + VDOA_INIRQ = 0x20,
- + VDOA_STOP = 0x40,
- + VDOA_PUT = VDOA_INIT,
- +};
- +
- +enum {
- + VDOA_NULL = 0,
- + VDOA_FRAME = 1,
- + VDOA_PREV_FIELD = 2,
- + VDOA_CURR_FIELD = 3,
- + VDOA_NEXT_FIELD = 4,
- +};
- +
- +#define CHECK_STATE(expect, retcode) \
- +do { \
- + if (!((expect) & vdoa->state)) { \
- + dev_err(vdoa->dev, "ERR: %s state:0x%x, expect:0x%x.\n",\
- + __func__, vdoa->state, (expect)); \
- + retcode; \
- + } \
- +} while (0)
- +
- +#define CHECK_NULL_PTR(ptr) \
- +do { \
- + pr_debug("vdoa_ptr:0x%p in %s state:0x%x.\n", \
- + vdoa, __func__, vdoa->state); \
- + if (NULL == (ptr)) { \
- + pr_err("ERR vdoa: %s state:0x%x null ptr.\n", \
- + __func__, vdoa->state); \
- + } \
- +} while (0)
- +
- +struct vdoa_info {
- + int state;
- + struct device *dev;
- + struct clk *vdoa_clk;
- + void __iomem *reg_base;
- + struct gen_pool *iram_pool;
- + unsigned long iram_base;
- + unsigned long iram_paddr;
- + int irq;
- + int field;
- + struct completion comp;
- +};
- +
- +static struct vdoa_info *g_vdoa;
- +static unsigned long iram_size;
- +static DEFINE_MUTEX(vdoa_lock);
- +
- +static inline void vdoa_read_register(struct vdoa_info *vdoa,
- + u32 reg, u32 *val)
- +{
- + *val = ioread32(vdoa->reg_base + reg);
- + dev_dbg(vdoa->dev, "read_reg:0x%02x, val:0x%08x.\n", reg, *val);
- +}
- +
- +static inline void vdoa_write_register(struct vdoa_info *vdoa,
- + u32 reg, u32 val)
- +{
- + iowrite32(val, vdoa->reg_base + reg);
- + dev_dbg(vdoa->dev, "\t\twrite_reg:0x%02x, val:0x%08x.\n", reg, val);
- +}
- +
- +static void dump_registers(struct vdoa_info *vdoa)
- +{
- + int i;
- + u32 data;
- +
- + for (i = VDOAC; i < VDOATD; i += 4)
- + vdoa_read_register(vdoa, i, &data);
- +}
- +
- +int vdoa_setup(vdoa_handle_t handle, struct vdoa_params *params)
- +{
- + int band_size;
- + int total_band_size = 0;
- + int ipu_stride;
- + u32 data;
- + struct vdoa_info *vdoa = (struct vdoa_info *)handle;
- +
- + CHECK_NULL_PTR(vdoa);
- + CHECK_STATE(VDOA_GET | VDOA_GET_OBUF | VDOA_STOP, return -EINVAL);
- + if (VDOA_GET == vdoa->state) {
- + dev_dbg(vdoa->dev, "w:%d, h:%d.\n",
- + params->width, params->height);
- + data = (params->band_lines == VDOAC_BAND_HEIGHT_32LINES) ? 2 :
- + ((params->band_lines == VDOAC_BAND_HEIGHT_16LINES) ?
- + 1 : 0);
- + data |= params->scan_order ? VDOAC_SCAN_ORDER_INTERLACED : 0;
- + data |= params->band_mode ? VDOAC_SYNC_BAND_MODE : 0;
- + data |= params->pfs ? VDOAC_PFS_YUYV : 0;
- + data |= params->ipu_num ? VDOAC_IPU_SEL_1 : 0;
- + vdoa_write_register(vdoa, VDOAC, data);
- +
- + data = ((params->width & VDOAFP_FW_MASK) << VDOAFP_FW_SHIFT) |
- + ((params->height & VDOAFP_FH_MASK) << VDOAFP_FH_SHIFT);
- + vdoa_write_register(vdoa, VDOAFP, data);
- +
- + ipu_stride = params->pfs ? params->width << 1 : params->width;
- + data = ((params->vpu_stride & VDOASL_VSLY_MASK) <<
- + VDOASL_VSLY_SHIFT) |
- + ((ipu_stride & VDOASL_ISLY_MASK) << VDOASL_ISLY_SHIFT);
- + vdoa_write_register(vdoa, VDOASL, data);
- +
- + dev_dbg(vdoa->dev, "band_mode:%d, band_line:%d, base:0x%lx.\n",
- + params->band_mode, params->band_lines, vdoa->iram_paddr);
- + }
- + /*
- + * band size = (luma_per_line + chroma_per_line) * bandLines
- + * = width * (3/2 or 2) * bandLines
- + * double buffer mode used.
- + */
- + if (params->pfs)
- + band_size = (params->width << 1) * params->band_lines;
- + else
- + band_size = ((params->width * 3) >> 1) *
- + params->band_lines;
- + if (params->interlaced) {
- + total_band_size = 6 * band_size; /* 3 frames*double buffer */
- + if (iram_size < total_band_size) {
- + dev_err(vdoa->dev, "iram_size:0x%lx is smaller than "
- + "request:0x%x!\n", iram_size, total_band_size);
- + return -EINVAL;
- + }
- + if (params->vfield_buf.prev_veba) {
- + if (params->band_mode) {
- + vdoa_write_register(vdoa, VDOAIEBA00,
- + vdoa->iram_paddr);
- + vdoa_write_register(vdoa, VDOAIEBA10,
- + vdoa->iram_paddr + band_size);
- + } else
- + vdoa_write_register(vdoa, VDOAIEBA00,
- + params->ieba0);
- + vdoa_write_register(vdoa, VDOAVEBA0,
- + params->vfield_buf.prev_veba);
- + vdoa->field = VDOA_PREV_FIELD;
- + }
- + if (params->vfield_buf.cur_veba) {
- + if (params->band_mode) {
- + vdoa_write_register(vdoa, VDOAIEBA01,
- + vdoa->iram_paddr + band_size * 2);
- + vdoa_write_register(vdoa, VDOAIEBA11,
- + vdoa->iram_paddr + band_size * 3);
- + } else
- + vdoa_write_register(vdoa, VDOAIEBA01,
- + params->ieba1);
- + vdoa_write_register(vdoa, VDOAVEBA1,
- + params->vfield_buf.cur_veba);
- + vdoa->field = VDOA_CURR_FIELD;
- + }
- + if (params->vfield_buf.next_veba) {
- + if (params->band_mode) {
- + vdoa_write_register(vdoa, VDOAIEBA02,
- + vdoa->iram_paddr + band_size * 4);
- + vdoa_write_register(vdoa, VDOAIEBA12,
- + vdoa->iram_paddr + band_size * 5);
- + } else
- + vdoa_write_register(vdoa, VDOAIEBA02,
- + params->ieba2);
- + vdoa_write_register(vdoa, VDOAVEBA2,
- + params->vfield_buf.next_veba);
- + vdoa->field = VDOA_NEXT_FIELD;
- + vdoa_read_register(vdoa, VDOAC, &data);
- + data |= VDOAC_THREE_FRAMES;
- + vdoa_write_register(vdoa, VDOAC, data);
- + }
- +
- + if (!params->pfs)
- + vdoa_write_register(vdoa, VDOAIUBO,
- + params->width * params->band_lines);
- + vdoa_write_register(vdoa, VDOAVUBO,
- + params->vfield_buf.vubo);
- + dev_dbg(vdoa->dev, "total band_size:0x%x.\n", band_size*6);
- + } else if (params->band_mode) {
- + /* used for progressive frame resize on PrP channel */
- + BUG(); /* currently not support */
- + /* progressvie frame: band mode */
- + vdoa_write_register(vdoa, VDOAIEBA00, vdoa->iram_paddr);
- + vdoa_write_register(vdoa, VDOAIEBA10,
- + vdoa->iram_paddr + band_size);
- + if (!params->pfs)
- + vdoa_write_register(vdoa, VDOAIUBO,
- + params->width * params->band_lines);
- + dev_dbg(vdoa->dev, "total band_size:0x%x\n", band_size*2);
- + } else {
- + /* progressive frame: mem->mem, non-band mode */
- + vdoa->field = VDOA_FRAME;
- + vdoa_write_register(vdoa, VDOAVEBA0, params->vframe_buf.veba);
- + vdoa_write_register(vdoa, VDOAVUBO, params->vframe_buf.vubo);
- + vdoa_write_register(vdoa, VDOAIEBA00, params->ieba0);
- + if (!params->pfs)
- + /* note: iubo is relative value, based on ieba0 */
- + vdoa_write_register(vdoa, VDOAIUBO,
- + params->width * params->height);
- + }
- + vdoa->state = VDOA_SETUP;
- + return 0;
- +}
- +
- +void vdoa_get_output_buf(vdoa_handle_t handle, struct vdoa_ipu_buf *buf)
- +{
- + u32 data;
- + struct vdoa_info *vdoa = (struct vdoa_info *)handle;
- +
- + CHECK_NULL_PTR(vdoa);
- + CHECK_STATE(VDOA_SETUP, return);
- + vdoa->state = VDOA_GET_OBUF;
- + memset(buf, 0, sizeof(*buf));
- +
- + vdoa_read_register(vdoa, VDOAC, &data);
- + switch (vdoa->field) {
- + case VDOA_FRAME:
- + case VDOA_PREV_FIELD:
- + vdoa_read_register(vdoa, VDOAIEBA00, &buf->ieba0);
- + if (data & VDOAC_SYNC_BAND_MODE)
- + vdoa_read_register(vdoa, VDOAIEBA10, &buf->ieba1);
- + break;
- + case VDOA_CURR_FIELD:
- + vdoa_read_register(vdoa, VDOAIEBA01, &buf->ieba0);
- + vdoa_read_register(vdoa, VDOAIEBA11, &buf->ieba1);
- + break;
- + case VDOA_NEXT_FIELD:
- + vdoa_read_register(vdoa, VDOAIEBA02, &buf->ieba0);
- + vdoa_read_register(vdoa, VDOAIEBA12, &buf->ieba1);
- + break;
- + default:
- + BUG();
- + break;
- + }
- + if (!(data & VDOAC_PFS_YUYV))
- + vdoa_read_register(vdoa, VDOAIUBO, &buf->iubo);
- +}
- +
- +int vdoa_start(vdoa_handle_t handle, int timeout_ms)
- +{
- + int ret;
- + struct vdoa_info *vdoa = (struct vdoa_info *)handle;
- +
- + CHECK_NULL_PTR(vdoa);
- + CHECK_STATE(VDOA_GET_OBUF, return -EINVAL);
- + vdoa->state = VDOA_START;
- + init_completion(&vdoa->comp);
- + vdoa_write_register(vdoa, VDOAIST,
- + VDOAIEIST_TRANSFER_ERR | VDOAIEIST_TRANSFER_END);
- + vdoa_write_register(vdoa, VDOAIE,
- + VDOAIEIST_TRANSFER_ERR | VDOAIEIST_TRANSFER_END);
- +
- + enable_irq(vdoa->irq);
- + vdoa_write_register(vdoa, VDOASRR, VDOASRR_START_XFER);
- + dump_registers(vdoa);
- +
- + ret = wait_for_completion_timeout(&vdoa->comp,
- + msecs_to_jiffies(timeout_ms));
- +
- + return ret > 0 ? 0 : -ETIMEDOUT;
- +}
- +
- +void vdoa_stop(vdoa_handle_t handle)
- +{
- + struct vdoa_info *vdoa = (struct vdoa_info *)handle;
- +
- + CHECK_NULL_PTR(vdoa);
- + CHECK_STATE(VDOA_GET | VDOA_START | VDOA_INIRQ, return);
- + vdoa->state = VDOA_STOP;
- +
- + disable_irq(vdoa->irq);
- +
- + vdoa_write_register(vdoa, VDOASRR, VDOASRR_SWRST);
- +}
- +
- +void vdoa_get_handle(vdoa_handle_t *handle)
- +{
- + struct vdoa_info *vdoa = g_vdoa;
- +
- + CHECK_NULL_PTR(handle);
- + *handle = (vdoa_handle_t *)NULL;
- + CHECK_STATE(VDOA_INIT, return);
- + mutex_lock(&vdoa_lock);
- + clk_prepare_enable(vdoa->vdoa_clk);
- + vdoa->state = VDOA_GET;
- + vdoa->field = VDOA_NULL;
- + vdoa_write_register(vdoa, VDOASRR, VDOASRR_SWRST);
- +
- + *handle = (vdoa_handle_t *)vdoa;
- +}
- +
- +void vdoa_put_handle(vdoa_handle_t *handle)
- +{
- + struct vdoa_info *vdoa = (struct vdoa_info *)(*handle);
- +
- + CHECK_NULL_PTR(vdoa);
- + CHECK_STATE(VDOA_STOP, return);
- + if (vdoa != g_vdoa)
- + BUG();
- +
- + clk_disable_unprepare(vdoa->vdoa_clk);
- + vdoa->state = VDOA_PUT;
- + *handle = (vdoa_handle_t *)NULL;
- + mutex_unlock(&vdoa_lock);
- +}
- +
- +static irqreturn_t vdoa_irq_handler(int irq, void *data)
- +{
- + u32 status, mask, val;
- + struct vdoa_info *vdoa = data;
- +
- + CHECK_NULL_PTR(vdoa);
- + CHECK_STATE(VDOA_START, return IRQ_HANDLED);
- + vdoa->state = VDOA_INIRQ;
- + vdoa_read_register(vdoa, VDOAIST, &status);
- + vdoa_read_register(vdoa, VDOAIE, &mask);
- + val = status & mask;
- + vdoa_write_register(vdoa, VDOAIST, val);
- + if (VDOAIEIST_TRANSFER_ERR & val)
- + dev_err(vdoa->dev, "vdoa Transfer err irq!\n");
- + if (VDOAIEIST_TRANSFER_END & val)
- + dev_dbg(vdoa->dev, "vdoa Transfer end irq!\n");
- + if (0 == val) {
- + dev_err(vdoa->dev, "vdoa unknown irq!\n");
- + BUG();
- + }
- +
- + complete(&vdoa->comp);
- + return IRQ_HANDLED;
- +}
- +
- +/* IRAM Size in Kbytes, example:vdoa_iram_size=64, 64KBytes */
- +static int __init vdoa_iram_size_setup(char *options)
- +{
- + int ret;
- +
- + ret = strict_strtoul(options, 0, &iram_size);
- + if (ret)
- + iram_size = 0;
- + else
- + iram_size *= SZ_1K;
- +
- + return 1;
- +}
- +__setup("vdoa_iram_size=", vdoa_iram_size_setup);
- +
- +static const struct of_device_id imx_vdoa_dt_ids[] = {
- + { .compatible = "fsl,imx6q-vdoa", },
- + { /* sentinel */ }
- +};
- +
- +static int vdoa_probe(struct platform_device *pdev)
- +{
- + int ret;
- + struct vdoa_info *vdoa;
- + struct resource *res;
- + struct resource *res_irq;
- + struct device *dev = &pdev->dev;
- + struct device_node *np = pdev->dev.of_node;
- +
- + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- + if (!res) {
- + dev_err(dev, "can't get device resources\n");
- + return -ENOENT;
- + }
- +
- + res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- + if (!res_irq) {
- + dev_err(dev, "failed to get irq resource\n");
- + return -ENOENT;
- + }
- +
- + vdoa = devm_kzalloc(dev, sizeof(struct vdoa_info), GFP_KERNEL);
- + if (!vdoa)
- + return -ENOMEM;
- + vdoa->dev = dev;
- +
- + vdoa->reg_base = devm_request_and_ioremap(&pdev->dev, res);
- + if (!vdoa->reg_base)
- + return -EBUSY;
- +
- + vdoa->irq = res_irq->start;
- + ret = devm_request_irq(dev, vdoa->irq, vdoa_irq_handler, 0,
- + "vdoa", vdoa);
- + if (ret) {
- + dev_err(dev, "can't claim irq %d\n", vdoa->irq);
- + return ret;
- + }
- + disable_irq(vdoa->irq);
- +
- + vdoa->vdoa_clk = devm_clk_get(dev, NULL);
- + if (IS_ERR(vdoa->vdoa_clk)) {
- + dev_err(dev, "failed to get vdoa_clk\n");
- + return PTR_ERR(vdoa->vdoa_clk);
- + }
- +
- + vdoa->iram_pool = of_get_named_gen_pool(np, "iram", 0);
- + if (!vdoa->iram_pool) {
- + dev_err(&pdev->dev, "iram pool not available\n");
- + return -ENOMEM;
- + }
- +
- + if ((iram_size == 0) || (iram_size > MAX_VDOA_IRAM_SIZE))
- + iram_size = VDOA_IRAM_SIZE;
- +
- + vdoa->iram_base = gen_pool_alloc(vdoa->iram_pool, iram_size);
- + if (!vdoa->iram_base) {
- + dev_err(&pdev->dev, "unable to alloc iram\n");
- + return -ENOMEM;
- + }
- +
- + vdoa->iram_paddr = gen_pool_virt_to_phys(vdoa->iram_pool,
- + vdoa->iram_base);
- +
- + dev_dbg(dev, "iram_base:0x%lx,iram_paddr:0x%lx,size:0x%lx\n",
- + vdoa->iram_base, vdoa->iram_paddr, iram_size);
- +
- + vdoa->state = VDOA_INIT;
- + dev_set_drvdata(dev, vdoa);
- + g_vdoa = vdoa;
- + dev_info(dev, "i.MX Video Data Order Adapter(VDOA) driver probed\n");
- + return 0;
- +}
- +
- +static int vdoa_remove(struct platform_device *pdev)
- +{
- + struct vdoa_info *vdoa = dev_get_drvdata(&pdev->dev);
- +
- + gen_pool_free(vdoa->iram_pool, vdoa->iram_base, iram_size);
- + kfree(vdoa);
- + dev_set_drvdata(&pdev->dev, NULL);
- +
- + return 0;
- +}
- +
- +static struct platform_driver vdoa_driver = {
- + .driver = {
- + .name = "mxc_vdoa",
- + .of_match_table = imx_vdoa_dt_ids,
- + },
- + .probe = vdoa_probe,
- + .remove = vdoa_remove,
- +};
- +
- +static int __init vdoa_init(void)
- +{
- + int err;
- +
- + err = platform_driver_register(&vdoa_driver);
- + if (err) {
- + pr_err("vdoa_driver register failed\n");
- + return -ENODEV;
- + }
- + return 0;
- +}
- +
- +static void __exit vdoa_cleanup(void)
- +{
- + platform_driver_unregister(&vdoa_driver);
- +}
- +
- +module_init(vdoa_init);
- +module_exit(vdoa_cleanup);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("i.MX Video Data Order Adapter(VDOA) driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/mxc/ipu3/vdoa.h linux-3.14.35/drivers/mxc/ipu3/vdoa.h
- --- linux-3.14.35.orig/drivers/mxc/ipu3/vdoa.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/ipu3/vdoa.h 2015-03-08 14:27:37.665684500 -0500
- @@ -0,0 +1,69 @@
- +/*
- + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#ifndef __VDOA_H__
- +#define __VDOA_H__
- +
- +#define VDOA_PFS_YUYV (1)
- +#define VDOA_PFS_NV12 (0)
- +
- +
- +struct vfield_buf {
- + u32 prev_veba;
- + u32 cur_veba;
- + u32 next_veba;
- + u32 vubo;
- +};
- +
- +struct vframe_buf {
- + u32 veba;
- + u32 vubo;
- +};
- +
- +struct vdoa_params {
- + u32 width;
- + u32 height;
- + int vpu_stride;
- + int interlaced;
- + int scan_order;
- + int ipu_num;
- + int band_lines;
- + int band_mode;
- + int pfs;
- + u32 ieba0;
- + u32 ieba1;
- + u32 ieba2;
- + struct vframe_buf vframe_buf;
- + struct vfield_buf vfield_buf;
- +};
- +struct vdoa_ipu_buf {
- + u32 ieba0;
- + u32 ieba1;
- + u32 iubo;
- +};
- +
- +struct vdoa_info;
- +typedef void *vdoa_handle_t;
- +
- +int vdoa_setup(vdoa_handle_t handle, struct vdoa_params *params);
- +void vdoa_get_output_buf(vdoa_handle_t handle, struct vdoa_ipu_buf *buf);
- +int vdoa_start(vdoa_handle_t handle, int timeout_ms);
- +void vdoa_stop(vdoa_handle_t handle);
- +void vdoa_get_handle(vdoa_handle_t *handle);
- +void vdoa_put_handle(vdoa_handle_t *handle);
- +#endif
- diff -Nur linux-3.14.35.orig/drivers/mxc/Kconfig linux-3.14.35/drivers/mxc/Kconfig
- --- linux-3.14.35.orig/drivers/mxc/Kconfig 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/Kconfig 2015-03-08 14:27:37.665684500 -0500
- @@ -0,0 +1,24 @@
- +# drivers/mxc/Kconfig
- +
- +if ARCH_MXC
- +
- +menu "MXC support drivers"
- +
- +config MXC_IPU
- + bool "Image Processing Unit Driver"
- + select MXC_IPU_V3
- + help
- + If you plan to use the Image Processing unit, say
- + Y here. IPU is needed by Framebuffer and V4L2 drivers.
- +
- +source "drivers/mxc/gpu-viv/Kconfig"
- +source "drivers/mxc/ipu3/Kconfig"
- +source "drivers/mxc/asrc/Kconfig"
- +source "drivers/mxc/vpu/Kconfig"
- +source "drivers/mxc/hdmi-cec/Kconfig"
- +source "drivers/mxc/mipi/Kconfig"
- +source "drivers/mxc/mlb/Kconfig"
- +
- +endmenu
- +
- +endif
- diff -Nur linux-3.14.35.orig/drivers/mxc/Makefile linux-3.14.35/drivers/mxc/Makefile
- --- linux-3.14.35.orig/drivers/mxc/Makefile 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/Makefile 2015-03-08 14:27:37.665684500 -0500
- @@ -0,0 +1,7 @@
- +obj-$(CONFIG_MXC_GPU_VIV) += gpu-viv/
- +obj-$(CONFIG_MXC_IPU_V3) += ipu3/
- +obj-$(CONFIG_MXC_ASRC) += asrc/
- +obj-$(CONFIG_MXC_VPU) += vpu/
- +obj-$(CONFIG_MXC_HDMI_CEC) += hdmi-cec/
- +obj-$(CONFIG_MXC_MIPI_CSI2) += mipi/
- +obj-$(CONFIG_MXC_MLB) += mlb/
- diff -Nur linux-3.14.35.orig/drivers/mxc/mipi/Kconfig linux-3.14.35/drivers/mxc/mipi/Kconfig
- --- linux-3.14.35.orig/drivers/mxc/mipi/Kconfig 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/mipi/Kconfig 2015-03-08 14:27:37.665684500 -0500
- @@ -0,0 +1,14 @@
- +#
- +# MIPI configuration
- +#
- +
- +menu "MXC MIPI Support"
- +
- +config MXC_MIPI_CSI2
- + tristate "MIPI CSI2 support"
- + depends on SOC_IMX6Q
- + default n
- + ---help---
- + Say Y to get the MIPI CSI2 support.
- +
- +endmenu
- diff -Nur linux-3.14.35.orig/drivers/mxc/mipi/Makefile linux-3.14.35/drivers/mxc/mipi/Makefile
- --- linux-3.14.35.orig/drivers/mxc/mipi/Makefile 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/mipi/Makefile 2015-03-08 14:27:37.665684500 -0500
- @@ -0,0 +1,4 @@
- +#
- +# Makefile for the mipi interface driver
- +#
- +obj-$(CONFIG_MXC_MIPI_CSI2) += mxc_mipi_csi2.o
- diff -Nur linux-3.14.35.orig/drivers/mxc/mipi/mxc_mipi_csi2.c linux-3.14.35/drivers/mxc/mipi/mxc_mipi_csi2.c
- --- linux-3.14.35.orig/drivers/mxc/mipi/mxc_mipi_csi2.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/mipi/mxc_mipi_csi2.c 2015-03-08 14:27:37.665684500 -0500
- @@ -0,0 +1,540 @@
- +/*
- + * Copyright (C) 2011-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/types.h>
- +#include <linux/interrupt.h>
- +#include <linux/irq.h>
- +#include <linux/irqdesc.h>
- +#include <linux/init.h>
- +#include <linux/platform_device.h>
- +#include <linux/err.h>
- +#include <linux/clk.h>
- +#include <linux/console.h>
- +#include <linux/io.h>
- +#include <linux/bitops.h>
- +#include <linux/delay.h>
- +#include <linux/fsl_devices.h>
- +#include <linux/slab.h>
- +#include <linux/of.h>
- +
- +#include <linux/mipi_csi2.h>
- +
- +#include "mxc_mipi_csi2.h"
- +
- +static struct mipi_csi2_info *gmipi_csi2;
- +
- +void _mipi_csi2_lock(struct mipi_csi2_info *info)
- +{
- + if (!in_irq() && !in_softirq())
- + mutex_lock(&info->mutex_lock);
- +}
- +
- +void _mipi_csi2_unlock(struct mipi_csi2_info *info)
- +{
- + if (!in_irq() && !in_softirq())
- + mutex_unlock(&info->mutex_lock);
- +}
- +
- +static inline void mipi_csi2_write(struct mipi_csi2_info *info,
- + unsigned value, unsigned offset)
- +{
- + writel(value, info->mipi_csi2_base + offset);
- +}
- +
- +static inline unsigned int mipi_csi2_read(struct mipi_csi2_info *info,
- + unsigned offset)
- +{
- + return readl(info->mipi_csi2_base + offset);
- +}
- +
- +/*!
- + * This function is called to enable the mipi csi2 interface.
- + *
- + * @param info mipi csi2 hander
- + * @return Returns setted value
- + */
- +bool mipi_csi2_enable(struct mipi_csi2_info *info)
- +{
- + bool status;
- +
- + _mipi_csi2_lock(info);
- +
- + if (!info->mipi_en) {
- + info->mipi_en = true;
- + clk_prepare_enable(info->cfg_clk);
- + clk_prepare_enable(info->dphy_clk);
- + } else
- + mipi_dbg("mipi csi2 already enabled!\n");
- +
- + status = info->mipi_en;
- +
- + _mipi_csi2_unlock(info);
- +
- + return status;
- +}
- +EXPORT_SYMBOL(mipi_csi2_enable);
- +
- +/*!
- + * This function is called to disable the mipi csi2 interface.
- + *
- + * @param info mipi csi2 hander
- + * @return Returns setted value
- + */
- +bool mipi_csi2_disable(struct mipi_csi2_info *info)
- +{
- + bool status;
- +
- + _mipi_csi2_lock(info);
- +
- + if (info->mipi_en) {
- + info->mipi_en = false;
- + clk_disable_unprepare(info->dphy_clk);
- + clk_disable_unprepare(info->cfg_clk);
- + } else
- + mipi_dbg("mipi csi2 already disabled!\n");
- +
- + status = info->mipi_en;
- +
- + _mipi_csi2_unlock(info);
- +
- + return status;
- +}
- +EXPORT_SYMBOL(mipi_csi2_disable);
- +
- +/*!
- + * This function is called to get mipi csi2 disable/enable status.
- + *
- + * @param info mipi csi2 hander
- + * @return Returns mipi csi2 status
- + */
- +bool mipi_csi2_get_status(struct mipi_csi2_info *info)
- +{
- + bool status;
- +
- + _mipi_csi2_lock(info);
- + status = info->mipi_en;
- + _mipi_csi2_unlock(info);
- +
- + return status;
- +}
- +EXPORT_SYMBOL(mipi_csi2_get_status);
- +
- +/*!
- + * This function is called to set mipi lanes.
- + *
- + * @param info mipi csi2 hander
- + * @return Returns setted value
- + */
- +unsigned int mipi_csi2_set_lanes(struct mipi_csi2_info *info)
- +{
- + unsigned int lanes;
- +
- + _mipi_csi2_lock(info);
- + mipi_csi2_write(info, info->lanes - 1, MIPI_CSI2_N_LANES);
- + lanes = mipi_csi2_read(info, MIPI_CSI2_N_LANES);
- + _mipi_csi2_unlock(info);
- +
- + return lanes;
- +}
- +EXPORT_SYMBOL(mipi_csi2_set_lanes);
- +
- +/*!
- + * This function is called to set mipi data type.
- + *
- + * @param info mipi csi2 hander
- + * @return Returns setted value
- + */
- +unsigned int mipi_csi2_set_datatype(struct mipi_csi2_info *info,
- + unsigned int datatype)
- +{
- + unsigned int dtype;
- +
- + _mipi_csi2_lock(info);
- + info->datatype = datatype;
- + dtype = info->datatype;
- + _mipi_csi2_unlock(info);
- +
- + return dtype;
- +}
- +EXPORT_SYMBOL(mipi_csi2_set_datatype);
- +
- +/*!
- + * This function is called to get mipi data type.
- + *
- + * @param info mipi csi2 hander
- + * @return Returns mipi data type
- + */
- +unsigned int mipi_csi2_get_datatype(struct mipi_csi2_info *info)
- +{
- + unsigned int dtype;
- +
- + _mipi_csi2_lock(info);
- + dtype = info->datatype;
- + _mipi_csi2_unlock(info);
- +
- + return dtype;
- +}
- +EXPORT_SYMBOL(mipi_csi2_get_datatype);
- +
- +/*!
- + * This function is called to get mipi csi2 dphy status.
- + *
- + * @param info mipi csi2 hander
- + * @return Returns dphy status
- + */
- +unsigned int mipi_csi2_dphy_status(struct mipi_csi2_info *info)
- +{
- + unsigned int status;
- +
- + _mipi_csi2_lock(info);
- + status = mipi_csi2_read(info, MIPI_CSI2_PHY_STATE);
- + _mipi_csi2_unlock(info);
- +
- + return status;
- +}
- +EXPORT_SYMBOL(mipi_csi2_dphy_status);
- +
- +/*!
- + * This function is called to get mipi csi2 error1 status.
- + *
- + * @param info mipi csi2 hander
- + * @return Returns error1 value
- + */
- +unsigned int mipi_csi2_get_error1(struct mipi_csi2_info *info)
- +{
- + unsigned int err1;
- +
- + _mipi_csi2_lock(info);
- + err1 = mipi_csi2_read(info, MIPI_CSI2_ERR1);
- + _mipi_csi2_unlock(info);
- +
- + return err1;
- +}
- +EXPORT_SYMBOL(mipi_csi2_get_error1);
- +
- +/*!
- + * This function is called to get mipi csi2 error1 status.
- + *
- + * @param info mipi csi2 hander
- + * @return Returns error1 value
- + */
- +unsigned int mipi_csi2_get_error2(struct mipi_csi2_info *info)
- +{
- + unsigned int err2;
- +
- + _mipi_csi2_lock(info);
- + err2 = mipi_csi2_read(info, MIPI_CSI2_ERR2);
- + _mipi_csi2_unlock(info);
- +
- + return err2;
- +}
- +EXPORT_SYMBOL(mipi_csi2_get_error2);
- +
- +/*!
- + * This function is called to enable mipi to ipu pixel clock.
- + *
- + * @param info mipi csi2 hander
- + * @return Returns 0 on success or negative error code on fail
- + */
- +int mipi_csi2_pixelclk_enable(struct mipi_csi2_info *info)
- +{
- + return clk_prepare_enable(info->pixel_clk);
- +}
- +EXPORT_SYMBOL(mipi_csi2_pixelclk_enable);
- +
- +/*!
- + * This function is called to disable mipi to ipu pixel clock.
- + *
- + * @param info mipi csi2 hander
- + * @return Returns 0 on success or negative error code on fail
- + */
- +void mipi_csi2_pixelclk_disable(struct mipi_csi2_info *info)
- +{
- + clk_disable_unprepare(info->pixel_clk);
- +}
- +EXPORT_SYMBOL(mipi_csi2_pixelclk_disable);
- +
- +/*!
- + * This function is called to power on mipi csi2.
- + *
- + * @param info mipi csi2 hander
- + * @return Returns 0 on success or negative error code on fail
- + */
- +int mipi_csi2_reset(struct mipi_csi2_info *info)
- +{
- + _mipi_csi2_lock(info);
- +
- + mipi_csi2_write(info, 0x0, MIPI_CSI2_PHY_SHUTDOWNZ);
- + mipi_csi2_write(info, 0x0, MIPI_CSI2_DPHY_RSTZ);
- + mipi_csi2_write(info, 0x0, MIPI_CSI2_CSI2_RESETN);
- +
- + mipi_csi2_write(info, 0x00000001, MIPI_CSI2_PHY_TST_CTRL0);
- + mipi_csi2_write(info, 0x00000000, MIPI_CSI2_PHY_TST_CTRL1);
- + mipi_csi2_write(info, 0x00000000, MIPI_CSI2_PHY_TST_CTRL0);
- + mipi_csi2_write(info, 0x00000002, MIPI_CSI2_PHY_TST_CTRL0);
- + mipi_csi2_write(info, 0x00010044, MIPI_CSI2_PHY_TST_CTRL1);
- + mipi_csi2_write(info, 0x00000000, MIPI_CSI2_PHY_TST_CTRL0);
- + mipi_csi2_write(info, 0x00000014, MIPI_CSI2_PHY_TST_CTRL1);
- + mipi_csi2_write(info, 0x00000002, MIPI_CSI2_PHY_TST_CTRL0);
- + mipi_csi2_write(info, 0x00000000, MIPI_CSI2_PHY_TST_CTRL0);
- +
- + mipi_csi2_write(info, 0xffffffff, MIPI_CSI2_PHY_SHUTDOWNZ);
- + mipi_csi2_write(info, 0xffffffff, MIPI_CSI2_DPHY_RSTZ);
- + mipi_csi2_write(info, 0xffffffff, MIPI_CSI2_CSI2_RESETN);
- +
- + _mipi_csi2_unlock(info);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(mipi_csi2_reset);
- +
- +/*!
- + * This function is called to get mipi csi2 info.
- + *
- + * @return Returns mipi csi2 info struct pointor
- + */
- +struct mipi_csi2_info *mipi_csi2_get_info(void)
- +{
- + return gmipi_csi2;
- +}
- +EXPORT_SYMBOL(mipi_csi2_get_info);
- +
- +/*!
- + * This function is called to get mipi csi2 bind ipu num.
- + *
- + * @return Returns mipi csi2 bind ipu num
- + */
- +int mipi_csi2_get_bind_ipu(struct mipi_csi2_info *info)
- +{
- + int ipu_id;
- +
- + _mipi_csi2_lock(info);
- + ipu_id = info->ipu_id;
- + _mipi_csi2_unlock(info);
- +
- + return ipu_id;
- +}
- +EXPORT_SYMBOL(mipi_csi2_get_bind_ipu);
- +
- +/*!
- + * This function is called to get mipi csi2 bind csi num.
- + *
- + * @return Returns mipi csi2 bind csi num
- + */
- +unsigned int mipi_csi2_get_bind_csi(struct mipi_csi2_info *info)
- +{
- + unsigned int csi_id;
- +
- + _mipi_csi2_lock(info);
- + csi_id = info->csi_id;
- + _mipi_csi2_unlock(info);
- +
- + return csi_id;
- +}
- +EXPORT_SYMBOL(mipi_csi2_get_bind_csi);
- +
- +/*!
- + * This function is called to get mipi csi2 virtual channel.
- + *
- + * @return Returns mipi csi2 virtual channel num
- + */
- +unsigned int mipi_csi2_get_virtual_channel(struct mipi_csi2_info *info)
- +{
- + unsigned int v_channel;
- +
- + _mipi_csi2_lock(info);
- + v_channel = info->v_channel;
- + _mipi_csi2_unlock(info);
- +
- + return v_channel;
- +}
- +EXPORT_SYMBOL(mipi_csi2_get_virtual_channel);
- +
- +/**
- + * This function is called by the driver framework to initialize the MIPI CSI2
- + * device.
- + *
- + * @param pdev The device structure for the MIPI CSI2 passed in by the
- + * driver framework.
- + *
- + * @return Returns 0 on success or negative error code on error
- + */
- +static int mipi_csi2_probe(struct platform_device *pdev)
- +{
- + struct device *dev = &pdev->dev;
- + struct device_node *np = pdev->dev.of_node;
- + struct resource *res;
- + u32 mipi_csi2_dphy_ver;
- + int ret;
- +
- + gmipi_csi2 = kmalloc(sizeof(struct mipi_csi2_info), GFP_KERNEL);
- + if (!gmipi_csi2) {
- + ret = -ENOMEM;
- + goto alloc_failed;
- + }
- +
- + ret = of_property_read_u32(np, "ipu_id", &(gmipi_csi2->ipu_id));
- + if (ret) {
- + dev_err(&pdev->dev, "ipu_id missing or invalid\n");
- + goto err;
- + }
- +
- + ret = of_property_read_u32(np, "csi_id", &(gmipi_csi2->csi_id));
- + if (ret) {
- + dev_err(&pdev->dev, "csi_id missing or invalid\n");
- + goto err;
- + }
- +
- + ret = of_property_read_u32(np, "v_channel", &(gmipi_csi2->v_channel));
- + if (ret) {
- + dev_err(&pdev->dev, "v_channel missing or invalid\n");
- + goto err;
- + }
- +
- + ret = of_property_read_u32(np, "lanes", &(gmipi_csi2->lanes));
- + if (ret) {
- + dev_err(&pdev->dev, "lanes missing or invalid\n");
- + goto err;
- + }
- +
- + if ((gmipi_csi2->ipu_id < 0) || (gmipi_csi2->ipu_id > 1) ||
- + (gmipi_csi2->csi_id > 1) || (gmipi_csi2->v_channel > 3) ||
- + (gmipi_csi2->lanes > 4)) {
- + dev_err(&pdev->dev, "invalid param for mipi csi2!\n");
- + ret = -EINVAL;
- + goto err;
- + }
- +
- + /* initialize mutex */
- + mutex_init(&gmipi_csi2->mutex_lock);
- +
- + /* get mipi csi2 informaiton */
- + gmipi_csi2->pdev = pdev;
- + gmipi_csi2->mipi_en = false;
- +
- + gmipi_csi2->cfg_clk = devm_clk_get(dev, "cfg_clk");
- + if (IS_ERR(gmipi_csi2->cfg_clk)) {
- + dev_err(&pdev->dev, "failed to get cfg_clk\n");
- + ret = PTR_ERR(gmipi_csi2->cfg_clk);
- + goto err;
- + }
- +
- + /* get mipi dphy clk */
- + gmipi_csi2->dphy_clk = devm_clk_get(dev, "dphy_clk");
- + if (IS_ERR(gmipi_csi2->dphy_clk)) {
- + dev_err(&pdev->dev, "failed to get dphy pll_ref_clk\n");
- + ret = PTR_ERR(gmipi_csi2->dphy_clk);
- + goto err;
- + }
- +
- + /* get mipi to ipu pixel clk */
- + gmipi_csi2->pixel_clk = devm_clk_get(dev, "pixel_clk");
- + if (IS_ERR(gmipi_csi2->pixel_clk)) {
- + dev_err(&pdev->dev, "failed to get mipi pixel clk\n");
- + ret = PTR_ERR(gmipi_csi2->pixel_clk);
- + goto err;
- + }
- +
- + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- + if (!res) {
- + ret = -ENODEV;
- + goto err;
- + }
- +
- + /* mipi register mapping */
- + gmipi_csi2->mipi_csi2_base = ioremap(res->start, PAGE_SIZE);
- + if (!gmipi_csi2->mipi_csi2_base) {
- + ret = -ENOMEM;
- + goto err;
- + }
- +
- + /* mipi dphy clk enable for register access */
- + clk_prepare_enable(gmipi_csi2->dphy_clk);
- + /* get mipi csi2 dphy version */
- + mipi_csi2_dphy_ver = mipi_csi2_read(gmipi_csi2, MIPI_CSI2_VERSION);
- +
- + clk_disable_unprepare(gmipi_csi2->dphy_clk);
- +
- + platform_set_drvdata(pdev, gmipi_csi2);
- +
- + dev_info(&pdev->dev, "i.MX MIPI CSI2 driver probed\n");
- + dev_info(&pdev->dev, "i.MX MIPI CSI2 dphy version is 0x%x\n",
- + mipi_csi2_dphy_ver);
- +
- + return 0;
- +
- +err:
- + kfree(gmipi_csi2);
- +alloc_failed:
- + dev_err(&pdev->dev, "i.MX MIPI CSI2 driver probed - error\n");
- + return ret;
- +}
- +
- +static int mipi_csi2_remove(struct platform_device *pdev)
- +{
- + /* unmapping mipi register */
- + iounmap(gmipi_csi2->mipi_csi2_base);
- +
- + kfree(gmipi_csi2);
- +
- + dev_set_drvdata(&pdev->dev, NULL);
- +
- + return 0;
- +}
- +
- +static const struct of_device_id imx_mipi_csi2_dt_ids[] = {
- + { .compatible = "fsl,imx6q-mipi-csi2", },
- + { /* sentinel */ }
- +};
- +
- +static struct platform_driver mipi_csi2_driver = {
- + .driver = {
- + .name = "mxc_mipi_csi2",
- + .of_match_table = imx_mipi_csi2_dt_ids,
- + },
- + .probe = mipi_csi2_probe,
- + .remove = mipi_csi2_remove,
- +};
- +
- +static int __init mipi_csi2_init(void)
- +{
- + int err;
- +
- + err = platform_driver_register(&mipi_csi2_driver);
- + if (err) {
- + pr_err("mipi_csi2_driver register failed\n");
- + return -ENODEV;
- + }
- +
- + pr_info("MIPI CSI2 driver module loaded\n");
- +
- + return 0;
- +}
- +
- +static void __exit mipi_csi2_cleanup(void)
- +{
- + platform_driver_unregister(&mipi_csi2_driver);
- +}
- +
- +subsys_initcall(mipi_csi2_init);
- +module_exit(mipi_csi2_cleanup);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("i.MX MIPI CSI2 driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/mxc/mipi/mxc_mipi_csi2.h linux-3.14.35/drivers/mxc/mipi/mxc_mipi_csi2.h
- --- linux-3.14.35.orig/drivers/mxc/mipi/mxc_mipi_csi2.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/mipi/mxc_mipi_csi2.h 2015-03-08 14:27:37.665684500 -0500
- @@ -0,0 +1,46 @@
- +/*
- + * Copyright (C) 2011-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#ifndef __MXC_MIPI_CSI2_H__
- +#define __MXC_MIPI_CSI2_H__
- +
- +#ifdef DEBUG
- +#define mipi_dbg(fmt, ...) \
- + printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
- +#else
- +#define mipi_dbg(fmt, ...)
- +#endif
- +
- +/* driver private data */
- +struct mipi_csi2_info {
- + bool mipi_en;
- + int ipu_id;
- + unsigned int csi_id;
- + unsigned int v_channel;
- + unsigned int lanes;
- + unsigned int datatype;
- + struct clk *cfg_clk;
- + struct clk *dphy_clk;
- + struct clk *pixel_clk;
- + void __iomem *mipi_csi2_base;
- + struct platform_device *pdev;
- +
- + struct mutex mutex_lock;
- +};
- +
- +#endif
- diff -Nur linux-3.14.35.orig/drivers/mxc/mlb/Kconfig linux-3.14.35/drivers/mxc/mlb/Kconfig
- --- linux-3.14.35.orig/drivers/mxc/mlb/Kconfig 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/mlb/Kconfig 2015-03-08 14:27:37.665684500 -0500
- @@ -0,0 +1,17 @@
- +#
- +# MLB150 configuration
- +#
- +
- +menu "MXC Media Local Bus Driver"
- +
- +config MXC_MLB
- + boolean
- +
- +config MXC_MLB150
- + tristate "MLB150 support"
- + depends on SOC_IMX6Q
- + select MXC_MLB
- + ---help---
- + Say Y to get the MLB150 support.
- +
- +endmenu
- diff -Nur linux-3.14.35.orig/drivers/mxc/mlb/Makefile linux-3.14.35/drivers/mxc/mlb/Makefile
- --- linux-3.14.35.orig/drivers/mxc/mlb/Makefile 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/mlb/Makefile 2015-03-08 14:27:37.665684500 -0500
- @@ -0,0 +1,5 @@
- +#
- +# Makefile for the i.MX6Q/DL MLB150 driver
- +#
- +
- +obj-$(CONFIG_MXC_MLB150) += mxc_mlb150.o
- diff -Nur linux-3.14.35.orig/drivers/mxc/mlb/mxc_mlb150.c linux-3.14.35/drivers/mxc/mlb/mxc_mlb150.c
- --- linux-3.14.35.orig/drivers/mxc/mlb/mxc_mlb150.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/mlb/mxc_mlb150.c 2015-03-08 14:27:37.669684500 -0500
- @@ -0,0 +1,2778 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#include <linux/cdev.h>
- +#include <linux/circ_buf.h>
- +#include <linux/clk.h>
- +#include <linux/delay.h>
- +#include <linux/device.h>
- +#include <linux/errno.h>
- +#include <linux/fs.h>
- +#include <linux/genalloc.h>
- +#include <linux/init.h>
- +#include <linux/interrupt.h>
- +#include <linux/io.h>
- +#include <linux/kernel.h>
- +#include <linux/module.h>
- +#include <linux/mxc_mlb.h>
- +#include <linux/of.h>
- +#include <linux/platform_device.h>
- +#include <linux/poll.h>
- +#include <linux/regulator/consumer.h>
- +#include <linux/sched.h>
- +#include <linux/slab.h>
- +#include <linux/spinlock.h>
- +#include <linux/uaccess.h>
- +
- +#define DRIVER_NAME "mxc_mlb150"
- +
- +/*
- + * MLB module memory map registers define
- + */
- +#define REG_MLBC0 0x0
- +#define MLBC0_MLBEN (0x1)
- +#define MLBC0_MLBCLK_MASK (0x7 << 2)
- +#define MLBC0_MLBCLK_SHIFT (2)
- +#define MLBC0_MLBPEN (0x1 << 5)
- +#define MLBC0_MLBLK (0x1 << 7)
- +#define MLBC0_ASYRETRY (0x1 << 12)
- +#define MLBC0_CTLRETRY (0x1 << 12)
- +#define MLBC0_FCNT_MASK (0x7 << 15)
- +#define MLBC0_FCNT_SHIFT (15)
- +
- +#define REG_MLBPC0 0x8
- +#define MLBPC0_MCLKHYS (0x1 << 11)
- +
- +#define REG_MS0 0xC
- +#define REG_MS1 0x14
- +
- +#define REG_MSS 0x20
- +#define MSS_RSTSYSCMD (0x1)
- +#define MSS_LKSYSCMD (0x1 << 1)
- +#define MSS_ULKSYSCMD (0x1 << 2)
- +#define MSS_CSSYSCMD (0x1 << 3)
- +#define MSS_SWSYSCMD (0x1 << 4)
- +#define MSS_SERVREQ (0x1 << 5)
- +
- +#define REG_MSD 0x24
- +
- +#define REG_MIEN 0x2C
- +#define MIEN_ISOC_PE (0x1)
- +#define MIEN_ISOC_BUFO (0x1 << 1)
- +#define MIEN_SYNC_PE (0x1 << 16)
- +#define MIEN_ARX_DONE (0x1 << 17)
- +#define MIEN_ARX_PE (0x1 << 18)
- +#define MIEN_ARX_BREAK (0x1 << 19)
- +#define MIEN_ATX_DONE (0x1 << 20)
- +#define MIEN_ATX_PE (0x1 << 21)
- +#define MIEN_ATX_BREAK (0x1 << 22)
- +#define MIEN_CRX_DONE (0x1 << 24)
- +#define MIEN_CRX_PE (0x1 << 25)
- +#define MIEN_CRX_BREAK (0x1 << 26)
- +#define MIEN_CTX_DONE (0x1 << 27)
- +#define MIEN_CTX_PE (0x1 << 28)
- +#define MIEN_CTX_BREAK (0x1 << 29)
- +
- +#define REG_MLBPC2 0x34
- +#define REG_MLBPC1 0x38
- +#define MLBPC1_VAL (0x00000888)
- +
- +#define REG_MLBC1 0x3C
- +#define MLBC1_LOCK (0x1 << 6)
- +#define MLBC1_CLKM (0x1 << 7)
- +#define MLBC1_NDA_MASK (0xFF << 8)
- +#define MLBC1_NDA_SHIFT (8)
- +
- +#define REG_HCTL 0x80
- +#define HCTL_RST0 (0x1)
- +#define HCTL_RST1 (0x1 << 1)
- +#define HCTL_EN (0x1 << 15)
- +
- +#define REG_HCMR0 0x88
- +#define REG_HCMR1 0x8C
- +#define REG_HCER0 0x90
- +#define REG_HCER1 0x94
- +#define REG_HCBR0 0x98
- +#define REG_HCBR1 0x9C
- +
- +#define REG_MDAT0 0xC0
- +#define REG_MDAT1 0xC4
- +#define REG_MDAT2 0xC8
- +#define REG_MDAT3 0xCC
- +
- +#define REG_MDWE0 0xD0
- +#define REG_MDWE1 0xD4
- +#define REG_MDWE2 0xD8
- +#define REG_MDWE3 0xDC
- +
- +#define REG_MCTL 0xE0
- +#define MCTL_XCMP (0x1)
- +
- +#define REG_MADR 0xE4
- +#define MADR_WNR (0x1 << 31)
- +#define MADR_TB (0x1 << 30)
- +#define MADR_ADDR_MASK (0x7f << 8)
- +#define MADR_ADDR_SHIFT (0)
- +
- +#define REG_ACTL 0x3C0
- +#define ACTL_MPB (0x1 << 4)
- +#define ACTL_DMAMODE (0x1 << 2)
- +#define ACTL_SMX (0x1 << 1)
- +#define ACTL_SCE (0x1)
- +
- +#define REG_ACSR0 0x3D0
- +#define REG_ACSR1 0x3D4
- +#define REG_ACMR0 0x3D8
- +#define REG_ACMR1 0x3DC
- +
- +#define REG_CAT_MDATn(ch) (REG_MDAT0 + ((ch % 8) >> 1) * 4)
- +#define REG_CAT_MDWEn(ch) (REG_MDWE0 + ((ch % 8) >> 1) * 4)
- +
- +#define INT_AHB0_CH_START (0)
- +#define INT_AHB1_CH_START (32)
- +
- +#define LOGIC_CH_NUM (64)
- +#define BUF_CDT_OFFSET (0x0)
- +#define BUF_ADT_OFFSET (0x40)
- +#define BUF_CAT_MLB_OFFSET (0x80)
- +#define BUF_CAT_HBI_OFFSET (0x88)
- +#define BUF_CTR_END_OFFSET (0x8F)
- +
- +#define CAT_MODE_RX (0x1 << 0)
- +#define CAT_MODE_TX (0x1 << 1)
- +#define CAT_MODE_INBOUND_DMA (0x1 << 8)
- +#define CAT_MODE_OUTBOUND_DMA (0x1 << 9)
- +
- +#define CH_SYNC_DEFAULT_QUAD (1)
- +#define CH_SYNC_MAX_QUAD (15)
- +#define CH_SYNC_CDT_BUF_DEP (CH_SYNC_DEFAULT_QUAD * 4 * 4)
- +#define CH_SYNC_ADT_BUF_MULTI (4)
- +#define CH_SYNC_ADT_BUF_DEP (CH_SYNC_CDT_BUF_DEP * CH_SYNC_ADT_BUF_MULTI)
- +#define CH_SYNC_BUF_SZ (CH_SYNC_MAX_QUAD * 4 * 4 * \
- + CH_SYNC_ADT_BUF_MULTI)
- +#define CH_CTRL_CDT_BUF_DEP (64)
- +#define CH_CTRL_ADT_BUF_DEP (CH_CTRL_CDT_BUF_DEP)
- +#define CH_CTRL_BUF_SZ (CH_CTRL_ADT_BUF_DEP)
- +#define CH_ASYNC_MDP_PACKET_LEN (1024)
- +#define CH_ASYNC_MEP_PACKET_LEN (1536)
- +#define CH_ASYNC_CDT_BUF_DEP (CH_ASYNC_MEP_PACKET_LEN)
- +#define CH_ASYNC_ADT_BUF_DEP (CH_ASYNC_CDT_BUF_DEP)
- +#define CH_ASYNC_BUF_SZ (CH_ASYNC_ADT_BUF_DEP)
- +#define CH_ISOC_BLK_SIZE_188 (188)
- +#define CH_ISOC_BLK_SIZE_196 (196)
- +#define CH_ISOC_BLK_SIZE (CH_ISOC_BLK_SIZE_188)
- +#define CH_ISOC_BLK_NUM (1)
- +#define CH_ISOC_CDT_BUF_DEP (CH_ISOC_BLK_SIZE * CH_ISOC_BLK_NUM)
- +#define CH_ISOC_ADT_BUF_DEP (CH_ISOC_CDT_BUF_DEP)
- +#define CH_ISOC_BUF_SZ (1024)
- +
- +#define CH_SYNC_DBR_BUF_OFFSET (0x0)
- +#define CH_CTRL_DBR_BUF_OFFSET (CH_SYNC_DBR_BUF_OFFSET + \
- + 2 * (CH_SYNC_MAX_QUAD * 4 * 4))
- +#define CH_ASYNC_DBR_BUF_OFFSET (CH_CTRL_DBR_BUF_OFFSET + \
- + 2 * CH_CTRL_CDT_BUF_DEP)
- +#define CH_ISOC_DBR_BUF_OFFSET (CH_ASYNC_DBR_BUF_OFFSET + \
- + 2 * CH_ASYNC_CDT_BUF_DEP)
- +
- +#define DBR_BUF_START 0x00000
- +
- +#define CDT_LEN (16)
- +#define ADT_LEN (16)
- +#define CAT_LEN (2)
- +
- +#define CDT_SZ (CDT_LEN * LOGIC_CH_NUM)
- +#define ADT_SZ (ADT_LEN * LOGIC_CH_NUM)
- +#define CAT_SZ (CAT_LEN * LOGIC_CH_NUM * 2)
- +
- +#define CDT_BASE(base) (base + BUF_CDT_OFFSET)
- +#define ADT_BASE(base) (base + BUF_ADT_OFFSET)
- +#define CAT_MLB_BASE(base) (base + BUF_CAT_MLB_OFFSET)
- +#define CAT_HBI_BASE(base) (base + BUF_CAT_HBI_OFFSET)
- +
- +#define CDTn_ADDR(base, n) (base + BUF_CDT_OFFSET + n * CDT_LEN)
- +#define ADTn_ADDR(base, n) (base + BUF_ADT_OFFSET + n * ADT_LEN)
- +#define CATn_MLB_ADDR(base, n) (base + BUF_CAT_MLB_OFFSET + n * CAT_LEN)
- +#define CATn_HBI_ADDR(base, n) (base + BUF_CAT_HBI_OFFSET + n * CAT_LEN)
- +
- +#define CAT_CL_SHIFT (0x0)
- +#define CAT_CT_SHIFT (8)
- +#define CAT_CE (0x1 << 11)
- +#define CAT_RNW (0x1 << 12)
- +#define CAT_MT (0x1 << 13)
- +#define CAT_FCE (0x1 << 14)
- +#define CAT_MFE (0x1 << 14)
- +
- +#define CDT_WSBC_SHIFT (14)
- +#define CDT_WPC_SHIFT (11)
- +#define CDT_RSBC_SHIFT (30)
- +#define CDT_RPC_SHIFT (27)
- +#define CDT_WPC_1_SHIFT (12)
- +#define CDT_RPC_1_SHIFT (28)
- +#define CDT_WPTR_SHIFT (0)
- +#define CDT_SYNC_WSTS_MASK (0x0000f000)
- +#define CDT_SYNC_WSTS_SHIFT (12)
- +#define CDT_CTRL_ASYNC_WSTS_MASK (0x0000f000)
- +#define CDT_CTRL_ASYNC_WSTS_SHIFT (12)
- +#define CDT_ISOC_WSTS_MASK (0x0000e000)
- +#define CDT_ISOC_WSTS_SHIFT (13)
- +#define CDT_RPTR_SHIFT (16)
- +#define CDT_SYNC_RSTS_MASK (0xf0000000)
- +#define CDT_SYNC_RSTS_SHIFT (28)
- +#define CDT_CTRL_ASYNC_RSTS_MASK (0xf0000000)
- +#define CDT_CTRL_ASYNC_RSTS_SHIFT (28)
- +#define CDT_ISOC_RSTS_MASK (0xe0000000)
- +#define CDT_ISOC_RSTS_SHIFT (29)
- +#define CDT_CTRL_ASYNC_WSTS_1 (0x1 << 14)
- +#define CDT_CTRL_ASYNC_RSTS_1 (0x1 << 15)
- +#define CDT_BD_SHIFT (0)
- +#define CDT_BA_SHIFT (16)
- +#define CDT_BS_SHIFT (0)
- +#define CDT_BF_SHIFT (31)
- +
- +#define ADT_PG (0x1 << 13)
- +#define ADT_LE (0x1 << 14)
- +#define ADT_CE (0x1 << 15)
- +#define ADT_BD1_SHIFT (0)
- +#define ADT_ERR1 (0x1 << 13)
- +#define ADT_DNE1 (0x1 << 14)
- +#define ADT_RDY1 (0x1 << 15)
- +#define ADT_BD2_SHIFT (16)
- +#define ADT_ERR2 (0x1 << 29)
- +#define ADT_DNE2 (0x1 << 30)
- +#define ADT_RDY2 (0x1 << 31)
- +#define ADT_BA1_SHIFT (0x0)
- +#define ADT_BA2_SHIFT (0x0)
- +#define ADT_PS1 (0x1 << 12)
- +#define ADT_PS2 (0x1 << 28)
- +#define ADT_MEP1 (0x1 << 11)
- +#define ADT_MEP2 (0x1 << 27)
- +
- +#define MLB_MINOR_DEVICES 4
- +#define MLB_CONTROL_DEV_NAME "ctrl"
- +#define MLB_ASYNC_DEV_NAME "async"
- +#define MLB_SYNC_DEV_NAME "sync"
- +#define MLB_ISOC_DEV_NAME "isoc"
- +
- +#define TX_CHANNEL 0
- +#define RX_CHANNEL 1
- +
- +#define TRANS_RING_NODES (1 << 3)
- +
- +enum MLB_CTYPE {
- + MLB_CTYPE_SYNC,
- + MLB_CTYPE_CTRL,
- + MLB_CTYPE_ASYNC,
- + MLB_CTYPE_ISOC,
- +};
- +
- +enum CLK_SPEED {
- + CLK_256FS,
- + CLK_512FS,
- + CLK_1024FS,
- + CLK_2048FS,
- + CLK_3072FS,
- + CLK_4096FS,
- + CLK_6144FS,
- + CLK_8192FS,
- +};
- +
- +struct mlb_ringbuf {
- + s8 *virt_bufs[TRANS_RING_NODES];
- + u32 phy_addrs[TRANS_RING_NODES];
- + s32 head;
- + s32 tail;
- + s32 unit_size;
- + s32 total_size;
- + rwlock_t rb_lock ____cacheline_aligned; /* ring index lock */
- +};
- +
- +struct mlb_channel_info {
- + /* Input MLB channel address */
- + u32 address;
- + /* Internal AHB channel label */
- + u32 cl;
- + /* DBR buf head */
- + u32 dbr_buf_head;
- +};
- +
- +struct mlb_dev_info {
- + /* device node name */
- + const char dev_name[20];
- + /* channel type */
- + const unsigned int channel_type;
- + /* ch fps */
- + enum CLK_SPEED fps;
- + /* channel info for tx/rx */
- + struct mlb_channel_info channels[2];
- + /* ring buffer */
- + u8 *rbuf_base_virt;
- + u32 rbuf_base_phy;
- + struct mlb_ringbuf rx_rbuf;
- + struct mlb_ringbuf tx_rbuf;
- + /* exception event */
- + unsigned long ex_event;
- + /* tx busy indicator */
- + unsigned long tx_busy;
- + /* channel started up or not */
- + atomic_t on;
- + /* device open count */
- + atomic_t opencnt;
- + /* wait queue head for channel */
- + wait_queue_head_t rx_wq;
- + wait_queue_head_t tx_wq;
- + /* TX OK */
- + s32 tx_ok;
- + /* spinlock for event access */
- + spinlock_t event_lock;
- + /*
- + * Block size for isoc mode
- + * This variable can be configured in ioctl
- + */
- + u32 isoc_blksz;
- + /*
- + * Quads number for sync mode
- + * This variable can be confifured in ioctl
- + */
- + u32 sync_quad;
- + /* Buffer depth in cdt */
- + u32 cdt_buf_dep;
- + /* Buffer depth in adt */
- + u32 adt_buf_dep;
- + /* Buffer size to hold data */
- + u32 buf_size;
- +};
- +
- +struct mlb_data {
- + struct mlb_dev_info *devinfo;
- + struct clk *clk_mlb3p;
- + struct clk *clk_mlb6p;
- + struct cdev cdev;
- + struct class *class; /* device class */
- + dev_t firstdev;
- +#ifdef CONFIG_REGULATOR
- + struct regulator *nvcc;
- +#endif
- + void __iomem *membase; /* mlb module base address */
- + struct gen_pool *iram_pool;
- + u32 iram_size;
- + u32 irq_ahb0;
- + u32 irq_ahb1;
- + u32 irq_mlb;
- +};
- +
- +/*
- + * For optimization, we use fixed channel label for
- + * input channels of each mode
- + * SYNC: CL = 0 for RX, CL = 64 for TX
- + * CTRL: CL = 1 for RX, CL = 65 for TX
- + * ASYNC: CL = 2 for RX, CL = 66 for TX
- + * ISOC: CL = 3 for RX, CL = 67 for TX
- + */
- +#define SYNC_RX_CL_AHB0 0
- +#define CTRL_RX_CL_AHB0 1
- +#define ASYNC_RX_CL_AHB0 2
- +#define ISOC_RX_CL_AHB0 3
- +#define SYNC_TX_CL_AHB0 4
- +#define CTRL_TX_CL_AHB0 5
- +#define ASYNC_TX_CL_AHB0 6
- +#define ISOC_TX_CL_AHB0 7
- +
- +#define SYNC_RX_CL_AHB1 32
- +#define CTRL_RX_CL_AHB1 33
- +#define ASYNC_RX_CL_AHB1 34
- +#define ISOC_RX_CL_AHB1 35
- +#define SYNC_TX_CL_AHB1 36
- +#define CTRL_TX_CL_AHB1 37
- +#define ASYNC_TX_CL_AHB1 38
- +#define ISOC_TX_CL_AHB1 39
- +
- +#define SYNC_RX_CL SYNC_RX_CL_AHB0
- +#define CTRL_RX_CL CTRL_RX_CL_AHB0
- +#define ASYNC_RX_CL ASYNC_RX_CL_AHB0
- +#define ISOC_RX_CL ISOC_RX_CL_AHB0
- +
- +#define SYNC_TX_CL SYNC_TX_CL_AHB0
- +#define CTRL_TX_CL CTRL_TX_CL_AHB0
- +#define ASYNC_TX_CL ASYNC_TX_CL_AHB0
- +#define ISOC_TX_CL ISOC_TX_CL_AHB0
- +
- +static struct mlb_dev_info mlb_devinfo[MLB_MINOR_DEVICES] = {
- + {
- + .dev_name = MLB_SYNC_DEV_NAME,
- + .channel_type = MLB_CTYPE_SYNC,
- + .channels = {
- + [0] = {
- + .cl = SYNC_TX_CL,
- + .dbr_buf_head = CH_SYNC_DBR_BUF_OFFSET,
- + },
- + [1] = {
- + .cl = SYNC_RX_CL,
- + .dbr_buf_head = CH_SYNC_DBR_BUF_OFFSET
- + + CH_SYNC_BUF_SZ,
- + },
- + },
- + .rx_rbuf = {
- + .unit_size = CH_SYNC_BUF_SZ,
- + .rb_lock =
- + __RW_LOCK_UNLOCKED(mlb_devinfo[0].rx_rbuf.rb_lock),
- + },
- + .tx_rbuf = {
- + .unit_size = CH_SYNC_BUF_SZ,
- + .rb_lock =
- + __RW_LOCK_UNLOCKED(mlb_devinfo[0].tx_rbuf.rb_lock),
- + },
- + .cdt_buf_dep = CH_SYNC_CDT_BUF_DEP,
- + .adt_buf_dep = CH_SYNC_ADT_BUF_DEP,
- + .buf_size = CH_SYNC_BUF_SZ,
- + .on = ATOMIC_INIT(0),
- + .opencnt = ATOMIC_INIT(0),
- + .event_lock = __SPIN_LOCK_UNLOCKED(mlb_devinfo[0].event_lock),
- + },
- + {
- + .dev_name = MLB_CONTROL_DEV_NAME,
- + .channel_type = MLB_CTYPE_CTRL,
- + .channels = {
- + [0] = {
- + .cl = CTRL_TX_CL,
- + .dbr_buf_head = CH_CTRL_DBR_BUF_OFFSET,
- + },
- + [1] = {
- + .cl = CTRL_RX_CL,
- + .dbr_buf_head = CH_CTRL_DBR_BUF_OFFSET
- + + CH_CTRL_BUF_SZ,
- + },
- + },
- + .rx_rbuf = {
- + .unit_size = CH_CTRL_BUF_SZ,
- + .rb_lock =
- + __RW_LOCK_UNLOCKED(mlb_devinfo[1].rx_rbuf.rb_lock),
- + },
- + .tx_rbuf = {
- + .unit_size = CH_CTRL_BUF_SZ,
- + .rb_lock =
- + __RW_LOCK_UNLOCKED(mlb_devinfo[1].tx_rbuf.rb_lock),
- + },
- + .cdt_buf_dep = CH_CTRL_CDT_BUF_DEP,
- + .adt_buf_dep = CH_CTRL_ADT_BUF_DEP,
- + .buf_size = CH_CTRL_BUF_SZ,
- + .on = ATOMIC_INIT(0),
- + .opencnt = ATOMIC_INIT(0),
- + .event_lock = __SPIN_LOCK_UNLOCKED(mlb_devinfo[1].event_lock),
- + },
- + {
- + .dev_name = MLB_ASYNC_DEV_NAME,
- + .channel_type = MLB_CTYPE_ASYNC,
- + .channels = {
- + [0] = {
- + .cl = ASYNC_TX_CL,
- + .dbr_buf_head = CH_ASYNC_DBR_BUF_OFFSET,
- + },
- + [1] = {
- + .cl = ASYNC_RX_CL,
- + .dbr_buf_head = CH_ASYNC_DBR_BUF_OFFSET
- + + CH_ASYNC_BUF_SZ,
- + },
- + },
- + .rx_rbuf = {
- + .unit_size = CH_ASYNC_BUF_SZ,
- + .rb_lock =
- + __RW_LOCK_UNLOCKED(mlb_devinfo[2].rx_rbuf.rb_lock),
- + },
- + .tx_rbuf = {
- + .unit_size = CH_ASYNC_BUF_SZ,
- + .rb_lock =
- + __RW_LOCK_UNLOCKED(mlb_devinfo[2].tx_rbuf.rb_lock),
- + },
- + .cdt_buf_dep = CH_ASYNC_CDT_BUF_DEP,
- + .adt_buf_dep = CH_ASYNC_ADT_BUF_DEP,
- + .buf_size = CH_ASYNC_BUF_SZ,
- + .on = ATOMIC_INIT(0),
- + .opencnt = ATOMIC_INIT(0),
- + .event_lock = __SPIN_LOCK_UNLOCKED(mlb_devinfo[2].event_lock),
- + },
- + {
- + .dev_name = MLB_ISOC_DEV_NAME,
- + .channel_type = MLB_CTYPE_ISOC,
- + .channels = {
- + [0] = {
- + .cl = ISOC_TX_CL,
- + .dbr_buf_head = CH_ISOC_DBR_BUF_OFFSET,
- + },
- + [1] = {
- + .cl = ISOC_RX_CL,
- + .dbr_buf_head = CH_ISOC_DBR_BUF_OFFSET
- + + CH_ISOC_BUF_SZ,
- + },
- + },
- + .rx_rbuf = {
- + .unit_size = CH_ISOC_BUF_SZ,
- + .rb_lock =
- + __RW_LOCK_UNLOCKED(mlb_devinfo[3].rx_rbuf.rb_lock),
- + },
- + .tx_rbuf = {
- + .unit_size = CH_ISOC_BUF_SZ,
- + .rb_lock =
- + __RW_LOCK_UNLOCKED(mlb_devinfo[3].tx_rbuf.rb_lock),
- + },
- + .cdt_buf_dep = CH_ISOC_CDT_BUF_DEP,
- + .adt_buf_dep = CH_ISOC_ADT_BUF_DEP,
- + .buf_size = CH_ISOC_BUF_SZ,
- + .on = ATOMIC_INIT(0),
- + .opencnt = ATOMIC_INIT(0),
- + .event_lock = __SPIN_LOCK_UNLOCKED(mlb_devinfo[3].event_lock),
- + .isoc_blksz = CH_ISOC_BLK_SIZE_188,
- + },
- +};
- +
- +static void __iomem *mlb_base;
- +
- +DEFINE_SPINLOCK(ctr_lock);
- +
- +#ifdef DEBUG
- +#define DUMP_REG(reg) pr_debug(#reg": 0x%08x\n", __raw_readl(mlb_base + reg))
- +
- +static void mlb150_dev_dump_reg(void)
- +{
- + pr_debug("mxc_mlb150: Dump registers:\n");
- + DUMP_REG(REG_MLBC0);
- + DUMP_REG(REG_MLBPC0);
- + DUMP_REG(REG_MS0);
- + DUMP_REG(REG_MS1);
- + DUMP_REG(REG_MSS);
- + DUMP_REG(REG_MSD);
- + DUMP_REG(REG_MIEN);
- + DUMP_REG(REG_MLBPC2);
- + DUMP_REG(REG_MLBPC1);
- + DUMP_REG(REG_MLBC1);
- + DUMP_REG(REG_HCTL);
- + DUMP_REG(REG_HCMR0);
- + DUMP_REG(REG_HCMR1);
- + DUMP_REG(REG_HCER0);
- + DUMP_REG(REG_HCER1);
- + DUMP_REG(REG_HCBR0);
- + DUMP_REG(REG_HCBR1);
- + DUMP_REG(REG_MDAT0);
- + DUMP_REG(REG_MDAT1);
- + DUMP_REG(REG_MDAT2);
- + DUMP_REG(REG_MDAT3);
- + DUMP_REG(REG_MDWE0);
- + DUMP_REG(REG_MDWE1);
- + DUMP_REG(REG_MDWE2);
- + DUMP_REG(REG_MDWE3);
- + DUMP_REG(REG_MCTL);
- + DUMP_REG(REG_MADR);
- + DUMP_REG(REG_ACTL);
- + DUMP_REG(REG_ACSR0);
- + DUMP_REG(REG_ACSR1);
- + DUMP_REG(REG_ACMR0);
- + DUMP_REG(REG_ACMR1);
- +}
- +
- +static void mlb150_dev_dump_hex(const u8 *buf, u32 len)
- +{
- + print_hex_dump(KERN_DEBUG, "CTR DUMP:",
- + DUMP_PREFIX_OFFSET, 8, 1, buf, len, 0);
- +}
- +#endif
- +
- +static inline void mlb150_dev_enable_ctr_write(u32 mdat0_bits_en,
- + u32 mdat1_bits_en, u32 mdat2_bits_en, u32 mdat3_bits_en)
- +{
- + __raw_writel(mdat0_bits_en, mlb_base + REG_MDWE0);
- + __raw_writel(mdat1_bits_en, mlb_base + REG_MDWE1);
- + __raw_writel(mdat2_bits_en, mlb_base + REG_MDWE2);
- + __raw_writel(mdat3_bits_en, mlb_base + REG_MDWE3);
- +}
- +
- +#ifdef DEBUG
- +static inline u8 mlb150_dev_dbr_read(u32 dbr_addr)
- +{
- + s32 timeout = 1000;
- + u8 dbr_val = 0;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&ctr_lock, flags);
- + __raw_writel(MADR_TB | dbr_addr,
- + mlb_base + REG_MADR);
- +
- + while ((!(__raw_readl(mlb_base + REG_MCTL)
- + & MCTL_XCMP)) &&
- + timeout--)
- + ;
- +
- + if (0 == timeout) {
- + spin_unlock_irqrestore(&ctr_lock, flags);
- + return -ETIME;
- + }
- +
- + dbr_val = __raw_readl(mlb_base + REG_MDAT0) & 0x000000ff;
- +
- + __raw_writel(0, mlb_base + REG_MCTL);
- + spin_unlock_irqrestore(&ctr_lock, flags);
- +
- + return dbr_val;
- +}
- +
- +static inline s32 mlb150_dev_dbr_write(u32 dbr_addr, u8 dbr_val)
- +{
- + s32 timeout = 1000;
- + u32 mdat0 = dbr_val & 0x000000ff;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&ctr_lock, flags);
- + __raw_writel(mdat0, mlb_base + REG_MDAT0);
- +
- + __raw_writel(MADR_WNR | MADR_TB | dbr_addr,
- + mlb_base + REG_MADR);
- +
- + while ((!(__raw_readl(mlb_base + REG_MCTL)
- + & MCTL_XCMP)) &&
- + timeout--)
- + ;
- +
- + if (timeout <= 0) {
- + spin_unlock_irqrestore(&ctr_lock, flags);
- + return -ETIME;
- + }
- +
- + __raw_writel(0, mlb_base + REG_MCTL);
- + spin_unlock_irqrestore(&ctr_lock, flags);
- +
- + return 0;
- +}
- +
- +static inline s32 mlb150_dev_dbr_dump(u32 addr, u32 size)
- +{
- + u8 *dump_buf = NULL;
- + u8 *buf_ptr = NULL;
- + s32 i;
- +
- + dump_buf = kzalloc(size, GFP_KERNEL);
- + if (!dump_buf) {
- + pr_err("can't allocate enough memory\n");
- + return -ENOMEM;
- + }
- +
- + for (i = 0, buf_ptr = dump_buf;
- + i < size; ++i, ++buf_ptr)
- + *buf_ptr = mlb150_dev_dbr_read(addr + i);
- +
- + mlb150_dev_dump_hex(dump_buf, size);
- +
- + kfree(dump_buf);
- +
- + return 0;
- +}
- +#endif
- +
- +static s32 mlb150_dev_ctr_read(u32 ctr_offset, u32 *ctr_val)
- +{
- + s32 timeout = 1000;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&ctr_lock, flags);
- + __raw_writel(ctr_offset, mlb_base + REG_MADR);
- +
- + while ((!(__raw_readl(mlb_base + REG_MCTL)
- + & MCTL_XCMP)) &&
- + timeout--)
- + ;
- +
- + if (timeout <= 0) {
- + spin_unlock_irqrestore(&ctr_lock, flags);
- + pr_debug("mxc_mlb150: Read CTR timeout\n");
- + return -ETIME;
- + }
- +
- + ctr_val[0] = __raw_readl(mlb_base + REG_MDAT0);
- + ctr_val[1] = __raw_readl(mlb_base + REG_MDAT1);
- + ctr_val[2] = __raw_readl(mlb_base + REG_MDAT2);
- + ctr_val[3] = __raw_readl(mlb_base + REG_MDAT3);
- +
- + __raw_writel(0, mlb_base + REG_MCTL);
- +
- + spin_unlock_irqrestore(&ctr_lock, flags);
- +
- + return 0;
- +}
- +
- +static s32 mlb150_dev_ctr_write(u32 ctr_offset, const u32 *ctr_val)
- +{
- + s32 timeout = 1000;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&ctr_lock, flags);
- +
- + __raw_writel(ctr_val[0], mlb_base + REG_MDAT0);
- + __raw_writel(ctr_val[1], mlb_base + REG_MDAT1);
- + __raw_writel(ctr_val[2], mlb_base + REG_MDAT2);
- + __raw_writel(ctr_val[3], mlb_base + REG_MDAT3);
- +
- + __raw_writel(MADR_WNR | ctr_offset,
- + mlb_base + REG_MADR);
- +
- + while ((!(__raw_readl(mlb_base + REG_MCTL)
- + & MCTL_XCMP)) &&
- + timeout--)
- + ;
- +
- + if (timeout <= 0) {
- + spin_unlock_irqrestore(&ctr_lock, flags);
- + pr_debug("mxc_mlb150: Write CTR timeout\n");
- + return -ETIME;
- + }
- +
- + __raw_writel(0, mlb_base + REG_MCTL);
- +
- + spin_unlock_irqrestore(&ctr_lock, flags);
- +
- +#ifdef DEBUG_CTR
- + {
- + u32 ctr_rd[4] = { 0 };
- +
- + if (!mlb150_dev_ctr_read(ctr_offset, ctr_rd)) {
- + if (ctr_val[0] == ctr_rd[0] &&
- + ctr_val[1] == ctr_rd[1] &&
- + ctr_val[2] == ctr_rd[2] &&
- + ctr_val[3] == ctr_rd[3])
- + return 0;
- + else {
- + pr_debug("mxc_mlb150: ctr write failed\n");
- + pr_debug("offset: 0x%x\n", ctr_offset);
- + pr_debug("Write: 0x%x 0x%x 0x%x 0x%x\n",
- + ctr_val[3], ctr_val[2],
- + ctr_val[1], ctr_val[0]);
- + pr_debug("Read: 0x%x 0x%x 0x%x 0x%x\n",
- + ctr_rd[3], ctr_rd[2],
- + ctr_rd[1], ctr_rd[0]);
- + return -EBADE;
- + }
- + } else {
- + pr_debug("mxc_mlb150: ctr read failed\n");
- + return -EBADE;
- + }
- + }
- +#endif
- +
- + return 0;
- +}
- +
- +#ifdef DEBUG
- +static s32 mlb150_dev_cat_read(u32 ctr_offset, u32 ch, u16 *cat_val)
- +{
- + u16 ctr_val[8] = { 0 };
- +
- + if (mlb150_dev_ctr_read(ctr_offset, (u32 *)ctr_val))
- + return -ETIME;
- +
- + /*
- + * Use u16 array to get u32 array value,
- + * need to convert
- + */
- + cat_val = ctr_val[ch % 8];
- +
- + return 0;
- +}
- +#endif
- +
- +static s32 mlb150_dev_cat_write(u32 ctr_offset, u32 ch, const u16 cat_val)
- +{
- + u16 ctr_val[8] = { 0 };
- +
- + if (mlb150_dev_ctr_read(ctr_offset, (u32 *)ctr_val))
- + return -ETIME;
- +
- + ctr_val[ch % 8] = cat_val;
- + if (mlb150_dev_ctr_write(ctr_offset, (u32 *)ctr_val))
- + return -ETIME;
- +
- + return 0;
- +}
- +
- +#define mlb150_dev_cat_mlb_read(ch, cat_val) \
- + mlb150_dev_cat_read(BUF_CAT_MLB_OFFSET + (ch >> 3), ch, cat_val)
- +#define mlb150_dev_cat_mlb_write(ch, cat_val) \
- + mlb150_dev_cat_write(BUF_CAT_MLB_OFFSET + (ch >> 3), ch, cat_val)
- +#define mlb150_dev_cat_hbi_read(ch, cat_val) \
- + mlb150_dev_cat_read(BUF_CAT_HBI_OFFSET + (ch >> 3), ch, cat_val)
- +#define mlb150_dev_cat_hbi_write(ch, cat_val) \
- + mlb150_dev_cat_write(BUF_CAT_HBI_OFFSET + (ch >> 3), ch, cat_val)
- +
- +#define mlb150_dev_cdt_read(ch, cdt_val) \
- + mlb150_dev_ctr_read(BUF_CDT_OFFSET + ch, cdt_val)
- +#define mlb150_dev_cdt_write(ch, cdt_val) \
- + mlb150_dev_ctr_write(BUF_CDT_OFFSET + ch, cdt_val)
- +#define mlb150_dev_adt_read(ch, adt_val) \
- + mlb150_dev_ctr_read(BUF_ADT_OFFSET + ch, adt_val)
- +#define mlb150_dev_adt_write(ch, adt_val) \
- + mlb150_dev_ctr_write(BUF_ADT_OFFSET + ch, adt_val)
- +
- +static s32 mlb150_dev_get_adt_sts(u32 ch)
- +{
- + s32 timeout = 1000;
- + unsigned long flags;
- + u32 reg;
- +
- + spin_lock_irqsave(&ctr_lock, flags);
- + __raw_writel(BUF_ADT_OFFSET + ch,
- + mlb_base + REG_MADR);
- +
- + while ((!(__raw_readl(mlb_base + REG_MCTL)
- + & MCTL_XCMP)) &&
- + timeout--)
- + ;
- +
- + if (timeout <= 0) {
- + spin_unlock_irqrestore(&ctr_lock, flags);
- + pr_debug("mxc_mlb150: Read CTR timeout\n");
- + return -ETIME;
- + }
- +
- + reg = __raw_readl(mlb_base + REG_MDAT1);
- +
- + __raw_writel(0, mlb_base + REG_MCTL);
- + spin_unlock_irqrestore(&ctr_lock, flags);
- +
- +#ifdef DEBUG_ADT
- + pr_debug("mxc_mlb150: Get ch %d adt sts: 0x%08x\n", ch, reg);
- +#endif
- +
- + return reg;
- +}
- +
- +#ifdef DEBUG
- +static void mlb150_dev_dump_ctr_tbl(u32 ch_start, u32 ch_end)
- +{
- + u32 i = 0;
- + u32 ctr_val[4] = { 0 };
- +
- + pr_debug("mxc_mlb150: CDT Table");
- + for (i = BUF_CDT_OFFSET + ch_start;
- + i < BUF_CDT_OFFSET + ch_end;
- + ++i) {
- + mlb150_dev_ctr_read(i, ctr_val);
- + pr_debug("CTR 0x%02x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
- + i, ctr_val[3], ctr_val[2], ctr_val[1], ctr_val[0]);
- + }
- +
- + pr_debug("mxc_mlb150: ADT Table");
- + for (i = BUF_ADT_OFFSET + ch_start;
- + i < BUF_ADT_OFFSET + ch_end;
- + ++i) {
- + mlb150_dev_ctr_read(i, ctr_val);
- + pr_debug("CTR 0x%02x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
- + i, ctr_val[3], ctr_val[2], ctr_val[1], ctr_val[0]);
- + }
- +
- + pr_debug("mxc_mlb150: CAT MLB Table");
- + for (i = BUF_CAT_MLB_OFFSET + (ch_start >> 3);
- + i <= BUF_CAT_MLB_OFFSET + ((ch_end + 8) >> 3);
- + ++i) {
- + mlb150_dev_ctr_read(i, ctr_val);
- + pr_debug("CTR 0x%02x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
- + i, ctr_val[3], ctr_val[2], ctr_val[1], ctr_val[0]);
- + }
- +
- + pr_debug("mxc_mlb150: CAT HBI Table");
- + for (i = BUF_CAT_HBI_OFFSET + (ch_start >> 3);
- + i <= BUF_CAT_HBI_OFFSET + ((ch_end + 8) >> 3);
- + ++i) {
- + mlb150_dev_ctr_read(i, ctr_val);
- + pr_debug("CTR 0x%02x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
- + i, ctr_val[3], ctr_val[2], ctr_val[1], ctr_val[0]);
- + }
- +}
- +#endif
- +
- +/*
- + * Initial the MLB module device
- + */
- +static inline void mlb150_dev_enable_dma_irq(u32 enable)
- +{
- + u32 ch_rx_mask = (1 << SYNC_RX_CL_AHB0) | (1 << CTRL_RX_CL_AHB0)
- + | (1 << ASYNC_RX_CL_AHB0) | (1 << ISOC_RX_CL_AHB0)
- + | (1 << SYNC_TX_CL_AHB0) | (1 << CTRL_TX_CL_AHB0)
- + | (1 << ASYNC_TX_CL_AHB0) | (1 << ISOC_TX_CL_AHB0);
- + u32 ch_tx_mask = (1 << (SYNC_RX_CL_AHB1 - INT_AHB1_CH_START)) |
- + (1 << (CTRL_RX_CL_AHB1 - INT_AHB1_CH_START)) |
- + (1 << (ASYNC_RX_CL_AHB1 - INT_AHB1_CH_START)) |
- + (1 << (ISOC_RX_CL_AHB1 - INT_AHB1_CH_START)) |
- + (1 << (SYNC_TX_CL_AHB1 - INT_AHB1_CH_START)) |
- + (1 << (CTRL_TX_CL_AHB1 - INT_AHB1_CH_START)) |
- + (1 << (ASYNC_TX_CL_AHB1 - INT_AHB1_CH_START)) |
- + (1 << (ISOC_TX_CL_AHB1 - INT_AHB1_CH_START));
- +
- + if (enable) {
- + __raw_writel(ch_rx_mask, mlb_base + REG_ACMR0);
- + __raw_writel(ch_tx_mask, mlb_base + REG_ACMR1);
- + } else {
- + __raw_writel(0x0, mlb_base + REG_ACMR0);
- + __raw_writel(0x0, mlb_base + REG_ACMR1);
- + }
- +}
- +
- +
- +static void mlb150_dev_init_ir_amba_ahb(void)
- +{
- + u32 reg = 0;
- +
- + /*
- + * Step 1. Program the ACMRn registers to enable interrupts from all
- + * active DMA channels
- + */
- + mlb150_dev_enable_dma_irq(1);
- +
- + /*
- + * Step 2. Select the status clear method:
- + * ACTL.SCE = 0, hardware clears on read
- + * ACTL.SCE = 1, software writes a '1' to clear
- + * We only support DMA MODE 1
- + */
- + reg = __raw_readl(mlb_base + REG_ACTL);
- + reg |= ACTL_DMAMODE;
- +#ifdef MULTIPLE_PACKAGE_MODE
- + reg |= REG_ACTL_MPB;
- +#endif
- +
- + /*
- + * Step 3. Select 1 or 2 interrupt signals:
- + * ACTL.SMX = 0: one interrupt for channels 0 - 31 on ahb_init[0]
- + * and another interrupt for channels 32 - 63 on ahb_init[1]
- + * ACTL.SMX = 1: singel interrupt all channels on ahb_init[0]
- + */
- + reg &= ~ACTL_SMX;
- +
- + __raw_writel(reg, mlb_base + REG_ACTL);
- +}
- +
- +static inline void mlb150_dev_enable_ir_mlb(u32 enable)
- +{
- + /*
- + * Step 1, Select the MSn to be cleared by software,
- + * writing a '0' to the appropriate bits
- + */
- + __raw_writel(0, mlb_base + REG_MS0);
- + __raw_writel(0, mlb_base + REG_MS1);
- +
- + /*
- + * Step 1, Program MIEN to enable protocol error
- + * interrupts for all active MLB channels
- + */
- + if (enable)
- + __raw_writel(MIEN_CTX_PE |
- + MIEN_CRX_PE | MIEN_ATX_PE |
- + MIEN_ARX_PE | MIEN_SYNC_PE |
- + MIEN_ISOC_PE,
- + mlb_base + REG_MIEN);
- + else
- + __raw_writel(0, mlb_base + REG_MIEN);
- +}
- +
- +static inline void mlb150_enable_pll(struct mlb_data *drvdata)
- +{
- + u32 c0_val;
- +
- + __raw_writel(MLBPC1_VAL,
- + drvdata->membase + REG_MLBPC1);
- +
- + c0_val = __raw_readl(drvdata->membase + REG_MLBC0);
- + if (c0_val & MLBC0_MLBPEN) {
- + c0_val &= ~MLBC0_MLBPEN;
- + __raw_writel(c0_val,
- + drvdata->membase + REG_MLBC0);
- + }
- +
- + clk_prepare_enable(drvdata->clk_mlb6p);
- +
- + c0_val |= (MLBC0_MLBPEN);
- + __raw_writel(c0_val, drvdata->membase + REG_MLBC0);
- +}
- +
- +static inline void mlb150_disable_pll(struct mlb_data *drvdata)
- +{
- + u32 c0_val;
- +
- + clk_disable_unprepare(drvdata->clk_mlb6p);
- +
- + c0_val = __raw_readl(drvdata->membase + REG_MLBC0);
- +
- + __raw_writel(0x0, drvdata->membase + REG_MLBPC1);
- +
- + c0_val &= ~MLBC0_MLBPEN;
- + __raw_writel(c0_val, drvdata->membase + REG_MLBC0);
- +}
- +
- +static void mlb150_dev_reset_cdt(void)
- +{
- + int i = 0;
- + u32 ctr_val[4] = { 0 };
- +
- + mlb150_dev_enable_ctr_write(0xffffffff, 0xffffffff,
- + 0xffffffff, 0xffffffff);
- +
- + for (i = 0; i < (LOGIC_CH_NUM); ++i)
- + mlb150_dev_ctr_write(BUF_CDT_OFFSET + i, ctr_val);
- +}
- +
- +static s32 mlb150_dev_init_ch_cdt(struct mlb_dev_info *pdevinfo, u32 ch,
- + enum MLB_CTYPE ctype, u32 ch_func)
- +{
- + u32 cdt_val[4] = { 0 };
- +
- + /* a. Set the 14-bit base address (BA) */
- + pr_debug("mxc_mlb150: ctype: %d, ch: %d, dbr_buf_head: 0x%08x",
- + ctype, ch, pdevinfo->channels[ch_func].dbr_buf_head);
- + cdt_val[3] = (pdevinfo->channels[ch_func].dbr_buf_head)
- + << CDT_BA_SHIFT;
- + /*
- + * b. Set the 12-bit or 13-bit buffer depth (BD)
- + * BD = buffer depth in bytes - 1
- + * For synchronous channels: (BD + 1) = 4 * m * bpf
- + * For control channels: (BD + 1) >= max packet length (64)
- + * For asynchronous channels: (BD + 1) >= max packet length
- + * 1024 for a MOST Data packet (MDP);
- + * 1536 for a MOST Ethernet Packet (MEP)
- + * For isochronous channels: (BD + 1) mod (BS + 1) = 0
- + * BS
- + */
- + if (MLB_CTYPE_ISOC == ctype)
- + cdt_val[1] |= (pdevinfo->isoc_blksz - 1);
- + /* BD */
- + cdt_val[3] |= (pdevinfo->cdt_buf_dep - 1) << CDT_BD_SHIFT;
- +
- + pr_debug("mxc_mlb150: Set CDT val of channel %d, type: %d: "
- + "0x%08x 0x%08x 0x%08x 0x%08x\n",
- + ch, ctype, cdt_val[3], cdt_val[2], cdt_val[1], cdt_val[0]);
- +
- + if (mlb150_dev_cdt_write(ch, cdt_val))
- + return -ETIME;
- +
- +#ifdef DEBUG_CTR
- + {
- + u32 cdt_rd[4] = { 0 };
- + if (!mlb150_dev_cdt_read(ch, cdt_rd)) {
- + pr_debug("mxc_mlb150: CDT val of channel %d: "
- + "0x%08x 0x%08x 0x%08x 0x%08x\n",
- + ch, cdt_rd[3], cdt_rd[2], cdt_rd[1], cdt_rd[0]);
- + if (cdt_rd[3] == cdt_val[3] &&
- + cdt_rd[2] == cdt_val[2] &&
- + cdt_rd[1] == cdt_val[1] &&
- + cdt_rd[0] == cdt_val[0]) {
- + pr_debug("mxc_mlb150: set cdt succeed!\n");
- + return 0;
- + } else {
- + pr_debug("mxc_mlb150: set cdt failed!\n");
- + return -EBADE;
- + }
- + } else {
- + pr_debug("mxc_mlb150: Read CDT val of channel %d failed\n",
- + ch);
- + return -EBADE;
- + }
- + }
- +#endif
- +
- + return 0;
- +}
- +
- +static s32 mlb150_dev_init_ch_cat(u32 ch, u32 cl,
- + u32 cat_mode, enum MLB_CTYPE ctype)
- +{
- + u16 cat_val = 0;
- +#ifdef DEBUG_CTR
- + u16 cat_rd = 0;
- +#endif
- +
- + cat_val = CAT_CE | (ctype << CAT_CT_SHIFT) | cl;
- +
- + if (cat_mode & CAT_MODE_OUTBOUND_DMA)
- + cat_val |= CAT_RNW;
- +
- + if (MLB_CTYPE_SYNC == ctype)
- + cat_val |= CAT_MT;
- +
- + switch (cat_mode) {
- + case CAT_MODE_RX | CAT_MODE_INBOUND_DMA:
- + case CAT_MODE_TX | CAT_MODE_OUTBOUND_DMA:
- + pr_debug("mxc_mlb150: set CAT val of channel %d, type: %d: 0x%04x\n",
- + ch, ctype, cat_val);
- +
- + if (mlb150_dev_cat_mlb_write(ch, cat_val))
- + return -ETIME;
- +#ifdef DEBUG_CTR
- + if (!mlb150_dev_cat_mlb_read(ch, &cat_rd))
- + pr_debug("mxc_mlb150: CAT val of mlb channel %d: 0x%04x",
- + ch, cat_rd);
- + else {
- + pr_debug("mxc_mlb150: Read CAT of mlb channel %d failed\n",
- + ch);
- + return -EBADE;
- + }
- +#endif
- + break;
- + case CAT_MODE_TX | CAT_MODE_INBOUND_DMA:
- + case CAT_MODE_RX | CAT_MODE_OUTBOUND_DMA:
- + pr_debug("mxc_mlb150: set CAT val of channel %d, type: %d: 0x%04x\n",
- + cl, ctype, cat_val);
- +
- + if (mlb150_dev_cat_hbi_write(cl, cat_val))
- + return -ETIME;
- +#ifdef DEBUG_CTR
- + if (!mlb150_dev_cat_hbi_read(cl, &cat_rd))
- + pr_debug("mxc_mlb150: CAT val of hbi channel %d: 0x%04x",
- + cl, cat_rd);
- + else {
- + pr_debug("mxc_mlb150: Read CAT of hbi channel %d failed\n",
- + cl);
- + return -EBADE;
- + }
- +#endif
- + break;
- + default:
- + return EBADRQC;
- + }
- +
- +#ifdef DEBUG_CTR
- + {
- + if (cat_val == cat_rd) {
- + pr_debug("mxc_mlb150: set cat succeed!\n");
- + return 0;
- + } else {
- + pr_debug("mxc_mlb150: set cat failed!\n");
- + return -EBADE;
- + }
- + }
- +#endif
- + return 0;
- +}
- +
- +static void mlb150_dev_reset_cat(void)
- +{
- + int i = 0;
- + u32 ctr_val[4] = { 0 };
- +
- + mlb150_dev_enable_ctr_write(0xffffffff, 0xffffffff,
- + 0xffffffff, 0xffffffff);
- +
- + for (i = 0; i < (LOGIC_CH_NUM >> 3); ++i) {
- + mlb150_dev_ctr_write(BUF_CAT_MLB_OFFSET + i, ctr_val);
- + mlb150_dev_ctr_write(BUF_CAT_HBI_OFFSET + i, ctr_val);
- + }
- +}
- +
- +static void mlb150_dev_init_rfb(struct mlb_dev_info *pdevinfo, u32 rx_ch,
- + u32 tx_ch, enum MLB_CTYPE ctype)
- +{
- + u32 rx_cl = pdevinfo->channels[RX_CHANNEL].cl;
- + u32 tx_cl = pdevinfo->channels[TX_CHANNEL].cl;
- + /* Step 1, Initialize all bits of CAT to '0' */
- + mlb150_dev_reset_cat();
- + mlb150_dev_reset_cdt();
- + /*
- + * Step 2, Initialize logical channel
- + * Step 3, Program the CDT for channel N
- + */
- + mlb150_dev_init_ch_cdt(pdevinfo, rx_cl, ctype, RX_CHANNEL);
- + mlb150_dev_init_ch_cdt(pdevinfo, tx_cl, ctype, TX_CHANNEL);
- +
- + /* Step 4&5, Program the CAT for the inbound and outbound DMA */
- + mlb150_dev_init_ch_cat(rx_ch, rx_cl,
- + CAT_MODE_RX | CAT_MODE_INBOUND_DMA,
- + ctype);
- + mlb150_dev_init_ch_cat(rx_ch, rx_cl,
- + CAT_MODE_RX | CAT_MODE_OUTBOUND_DMA,
- + ctype);
- + mlb150_dev_init_ch_cat(tx_ch, tx_cl,
- + CAT_MODE_TX | CAT_MODE_INBOUND_DMA,
- + ctype);
- + mlb150_dev_init_ch_cat(tx_ch, tx_cl,
- + CAT_MODE_TX | CAT_MODE_OUTBOUND_DMA,
- + ctype);
- +}
- +
- +static void mlb150_dev_reset_adt(void)
- +{
- + int i = 0;
- + u32 ctr_val[4] = { 0 };
- +
- + mlb150_dev_enable_ctr_write(0xffffffff, 0xffffffff,
- + 0xffffffff, 0xffffffff);
- +
- + for (i = 0; i < (LOGIC_CH_NUM); ++i)
- + mlb150_dev_ctr_write(BUF_ADT_OFFSET + i, ctr_val);
- +}
- +
- +static void mlb150_dev_reset_whole_ctr(void)
- +{
- + mlb150_dev_enable_ctr_write(0xffffffff, 0xffffffff,
- + 0xffffffff, 0xffffffff);
- + mlb150_dev_reset_cdt();
- + mlb150_dev_reset_adt();
- + mlb150_dev_reset_cat();
- +}
- +
- +#define CLR_REG(reg) __raw_writel(0x0, mlb_base + reg)
- +
- +static void mlb150_dev_reset_all_regs(void)
- +{
- + CLR_REG(REG_MLBC0);
- + CLR_REG(REG_MLBPC0);
- + CLR_REG(REG_MS0);
- + CLR_REG(REG_MS1);
- + CLR_REG(REG_MSS);
- + CLR_REG(REG_MSD);
- + CLR_REG(REG_MIEN);
- + CLR_REG(REG_MLBPC2);
- + CLR_REG(REG_MLBPC1);
- + CLR_REG(REG_MLBC1);
- + CLR_REG(REG_HCTL);
- + CLR_REG(REG_HCMR0);
- + CLR_REG(REG_HCMR1);
- + CLR_REG(REG_HCER0);
- + CLR_REG(REG_HCER1);
- + CLR_REG(REG_HCBR0);
- + CLR_REG(REG_HCBR1);
- + CLR_REG(REG_MDAT0);
- + CLR_REG(REG_MDAT1);
- + CLR_REG(REG_MDAT2);
- + CLR_REG(REG_MDAT3);
- + CLR_REG(REG_MDWE0);
- + CLR_REG(REG_MDWE1);
- + CLR_REG(REG_MDWE2);
- + CLR_REG(REG_MDWE3);
- + CLR_REG(REG_MCTL);
- + CLR_REG(REG_MADR);
- + CLR_REG(REG_ACTL);
- + CLR_REG(REG_ACSR0);
- + CLR_REG(REG_ACSR1);
- + CLR_REG(REG_ACMR0);
- + CLR_REG(REG_ACMR1);
- +}
- +
- +static inline s32 mlb150_dev_pipo_start(struct mlb_ringbuf *rbuf,
- + u32 ahb_ch, u32 buf_addr)
- +{
- + u32 ctr_val[4] = { 0 };
- +
- + ctr_val[1] |= ADT_RDY1;
- + ctr_val[2] = buf_addr;
- +
- + if (mlb150_dev_adt_write(ahb_ch, ctr_val))
- + return -ETIME;
- +
- + return 0;
- +}
- +
- +static inline s32 mlb150_dev_pipo_next(u32 ahb_ch, enum MLB_CTYPE ctype,
- + u32 dne_sts, u32 buf_addr)
- +{
- + u32 ctr_val[4] = { 0 };
- +
- + if (MLB_CTYPE_ASYNC == ctype ||
- + MLB_CTYPE_CTRL == ctype) {
- + ctr_val[1] |= ADT_PS1;
- + ctr_val[1] |= ADT_PS2;
- + }
- +
- + /*
- + * Clear DNE1 and ERR1
- + * Set the page ready bit (RDY1)
- + */
- + if (dne_sts & ADT_DNE1) {
- + ctr_val[1] |= ADT_RDY2;
- + ctr_val[3] = buf_addr;
- + } else {
- + ctr_val[1] |= ADT_RDY1;
- + ctr_val[2] = buf_addr;
- + }
- +
- + if (mlb150_dev_adt_write(ahb_ch, ctr_val))
- + return -ETIME;
- +
- + return 0;
- +}
- +
- +static inline s32 mlb150_dev_pipo_stop(struct mlb_ringbuf *rbuf, u32 ahb_ch)
- +{
- + u32 ctr_val[4] = { 0 };
- + unsigned long flags;
- +
- + write_lock_irqsave(&rbuf->rb_lock, flags);
- + rbuf->head = rbuf->tail = 0;
- + write_unlock_irqrestore(&rbuf->rb_lock, flags);
- +
- + if (mlb150_dev_adt_write(ahb_ch, ctr_val))
- + return -ETIME;
- +
- + return 0;
- +}
- +
- +static s32 mlb150_dev_init_ch_amba_ahb(struct mlb_dev_info *pdevinfo,
- + struct mlb_channel_info *chinfo,
- + enum MLB_CTYPE ctype)
- +{
- + u32 ctr_val[4] = { 0 };
- +
- + /* a. Set the 32-bit base address (BA1) */
- + ctr_val[3] = 0;
- + ctr_val[2] = 0;
- + ctr_val[1] = (pdevinfo->adt_buf_dep - 1) << ADT_BD1_SHIFT;
- + ctr_val[1] |= (pdevinfo->adt_buf_dep - 1) << ADT_BD2_SHIFT;
- + if (MLB_CTYPE_ASYNC == ctype ||
- + MLB_CTYPE_CTRL == ctype) {
- + ctr_val[1] |= ADT_PS1;
- + ctr_val[1] |= ADT_PS2;
- + }
- +
- + ctr_val[0] |= (ADT_LE | ADT_CE);
- +
- + pr_debug("mxc_mlb150: Set ADT val of channel %d, ctype: %d: "
- + "0x%08x 0x%08x 0x%08x 0x%08x\n",
- + chinfo->cl, ctype, ctr_val[3], ctr_val[2],
- + ctr_val[1], ctr_val[0]);
- +
- + if (mlb150_dev_adt_write(chinfo->cl, ctr_val))
- + return -ETIME;
- +
- +#ifdef DEBUG_CTR
- + {
- + u32 ctr_rd[4] = { 0 };
- + if (!mlb150_dev_adt_read(chinfo->cl, ctr_rd)) {
- + pr_debug("mxc_mlb150: ADT val of channel %d: "
- + "0x%08x 0x%08x 0x%08x 0x%08x\n",
- + chinfo->cl, ctr_rd[3], ctr_rd[2],
- + ctr_rd[1], ctr_rd[0]);
- + if (ctr_rd[3] == ctr_val[3] &&
- + ctr_rd[2] == ctr_val[2] &&
- + ctr_rd[1] == ctr_val[1] &&
- + ctr_rd[0] == ctr_val[0]) {
- + pr_debug("mxc_mlb150: set adt succeed!\n");
- + return 0;
- + } else {
- + pr_debug("mxc_mlb150: set adt failed!\n");
- + return -EBADE;
- + }
- + } else {
- + pr_debug("mxc_mlb150: Read ADT val of channel %d failed\n",
- + chinfo->cl);
- + return -EBADE;
- + }
- + }
- +#endif
- +
- + return 0;
- +}
- +
- +static void mlb150_dev_init_amba_ahb(struct mlb_dev_info *pdevinfo,
- + enum MLB_CTYPE ctype)
- +{
- + struct mlb_channel_info *tx_chinfo = &pdevinfo->channels[TX_CHANNEL];
- + struct mlb_channel_info *rx_chinfo = &pdevinfo->channels[RX_CHANNEL];
- +
- + /* Step 1, Initialize all bits of the ADT to '0' */
- + mlb150_dev_reset_adt();
- +
- + /*
- + * Step 2, Select a logic channel
- + * Step 3, Program the AMBA AHB block ping page for channel N
- + * Step 4, Program the AMBA AHB block pong page for channel N
- + */
- + mlb150_dev_init_ch_amba_ahb(pdevinfo, rx_chinfo, ctype);
- + mlb150_dev_init_ch_amba_ahb(pdevinfo, tx_chinfo, ctype);
- +}
- +
- +static void mlb150_dev_exit(void)
- +{
- + u32 c0_val, hctl_val;
- +
- + /* Disable EN bits */
- + c0_val = __raw_readl(mlb_base + REG_MLBC0);
- + c0_val &= ~(MLBC0_MLBEN | MLBC0_MLBPEN);
- + __raw_writel(c0_val, mlb_base + REG_MLBC0);
- +
- + hctl_val = __raw_readl(mlb_base + REG_HCTL);
- + hctl_val &= ~HCTL_EN;
- + __raw_writel(hctl_val, mlb_base + REG_HCTL);
- +
- + __raw_writel(0x0, mlb_base + REG_HCMR0);
- + __raw_writel(0x0, mlb_base + REG_HCMR1);
- +
- + mlb150_dev_enable_dma_irq(0);
- + mlb150_dev_enable_ir_mlb(0);
- +}
- +
- +static void mlb150_dev_init(void)
- +{
- + u32 c0_val;
- + u32 ch_rx_mask = (1 << SYNC_RX_CL_AHB0) | (1 << CTRL_RX_CL_AHB0)
- + | (1 << ASYNC_RX_CL_AHB0) | (1 << ISOC_RX_CL_AHB0)
- + | (1 << SYNC_TX_CL_AHB0) | (1 << CTRL_TX_CL_AHB0)
- + | (1 << ASYNC_TX_CL_AHB0) | (1 << ISOC_TX_CL_AHB0);
- + u32 ch_tx_mask = (1 << (SYNC_RX_CL_AHB1 - INT_AHB1_CH_START)) |
- + (1 << (CTRL_RX_CL_AHB1 - INT_AHB1_CH_START)) |
- + (1 << (ASYNC_RX_CL_AHB1 - INT_AHB1_CH_START)) |
- + (1 << (ISOC_RX_CL_AHB1 - INT_AHB1_CH_START)) |
- + (1 << (SYNC_TX_CL_AHB1 - INT_AHB1_CH_START)) |
- + (1 << (CTRL_TX_CL_AHB1 - INT_AHB1_CH_START)) |
- + (1 << (ASYNC_TX_CL_AHB1 - INT_AHB1_CH_START)) |
- + (1 << (ISOC_TX_CL_AHB1 - INT_AHB1_CH_START));
- +
- + /* Disable EN bits */
- + mlb150_dev_exit();
- +
- + /*
- + * Step 1. Initialize CTR and registers
- + * a. Set all bit of the CTR (CAT, CDT, and ADT) to 0.
- + */
- + mlb150_dev_reset_whole_ctr();
- +
- + /* a. Set all bit of the CTR (CAT, CDT, and ADT) to 0. */
- + mlb150_dev_reset_all_regs();
- +
- + /*
- + * Step 2, Configure the MediaLB interface
- + * Select pin mode and clock, 3-pin and 256fs
- + */
- + c0_val = __raw_readl(mlb_base + REG_MLBC0);
- + c0_val &= ~(MLBC0_MLBPEN | MLBC0_MLBCLK_MASK);
- + __raw_writel(c0_val, mlb_base + REG_MLBC0);
- +
- + c0_val |= MLBC0_MLBEN;
- + __raw_writel(c0_val, mlb_base + REG_MLBC0);
- +
- + /* Step 3, Configure the HBI interface */
- + __raw_writel(ch_rx_mask, mlb_base + REG_HCMR0);
- + __raw_writel(ch_tx_mask, mlb_base + REG_HCMR1);
- + __raw_writel(HCTL_EN, mlb_base + REG_HCTL);
- +
- + mlb150_dev_init_ir_amba_ahb();
- +
- + mlb150_dev_enable_ir_mlb(1);
- +}
- +
- +static s32 mlb150_dev_unmute_syn_ch(u32 rx_ch, u32 rx_cl, u32 tx_ch, u32 tx_cl)
- +{
- + u32 timeout = 10000;
- +
- + /*
- + * Check that MediaLB clock is running (MLBC1.CLKM = 0)
- + * If MLBC1.CLKM = 1, clear the register bit, wait one
- + * APB or I/O clock cycle and repeat the check
- + */
- + while ((__raw_readl(mlb_base + REG_MLBC1) & MLBC1_CLKM)
- + && --timeout)
- + __raw_writel(~MLBC1_CLKM, mlb_base + REG_MLBC1);
- +
- + if (0 == timeout)
- + return -ETIME;
- +
- + timeout = 10000;
- + /* Poll for MLB lock (MLBC0.MLBLK = 1) */
- + while (!(__raw_readl(mlb_base + REG_MLBC0) & MLBC0_MLBLK)
- + && --timeout)
- + ;
- +
- + if (0 == timeout)
- + return -ETIME;
- +
- + /* Unmute synchronous channel(s) */
- + mlb150_dev_cat_mlb_write(rx_ch, CAT_CE | rx_cl);
- + mlb150_dev_cat_mlb_write(tx_ch,
- + CAT_CE | tx_cl | CAT_RNW);
- + mlb150_dev_cat_hbi_write(rx_cl,
- + CAT_CE | rx_cl | CAT_RNW);
- + mlb150_dev_cat_hbi_write(tx_cl, CAT_CE | tx_cl);
- +
- + return 0;
- +}
- +
- +/* In case the user calls channel shutdown, but rx or tx is not completed yet */
- +static s32 mlb150_trans_complete_check(struct mlb_dev_info *pdevinfo)
- +{
- + struct mlb_ringbuf *rx_rbuf = &pdevinfo->rx_rbuf;
- + struct mlb_ringbuf *tx_rbuf = &pdevinfo->tx_rbuf;
- + s32 timeout = 1024;
- +
- + while (timeout--) {
- + read_lock(&tx_rbuf->rb_lock);
- + if (!CIRC_CNT(tx_rbuf->head, tx_rbuf->tail, TRANS_RING_NODES)) {
- + read_unlock(&tx_rbuf->rb_lock);
- + break;
- + } else
- + read_unlock(&tx_rbuf->rb_lock);
- + }
- +
- + if (timeout <= 0) {
- + pr_debug("TX complete check timeout!\n");
- + return -ETIME;
- + }
- +
- + timeout = 1024;
- + while (timeout--) {
- + read_lock(&rx_rbuf->rb_lock);
- + if (!CIRC_CNT(rx_rbuf->head, rx_rbuf->tail, TRANS_RING_NODES)) {
- + read_unlock(&rx_rbuf->rb_lock);
- + break;
- + } else
- + read_unlock(&rx_rbuf->rb_lock);
- + }
- +
- + if (timeout <= 0) {
- + pr_debug("RX complete check timeout!\n");
- + return -ETIME;
- + }
- +
- + /*
- + * Interrupt from TX can only inform that the data is sent
- + * to AHB bus, not mean that it is sent to MITB. Thus we add
- + * a delay here for data to be completed sent.
- + */
- + udelay(1000);
- +
- + return 0;
- +}
- +
- +/*
- + * Enable/Disable the MLB IRQ
- + */
- +static void mxc_mlb150_irq_enable(struct mlb_data *drvdata, u8 enable)
- +{
- + if (enable) {
- + enable_irq(drvdata->irq_ahb0);
- + enable_irq(drvdata->irq_ahb1);
- + enable_irq(drvdata->irq_mlb);
- + } else {
- + disable_irq(drvdata->irq_ahb0);
- + disable_irq(drvdata->irq_ahb1);
- + disable_irq(drvdata->irq_mlb);
- + }
- +}
- +
- +/*
- + * Enable the MLB channel
- + */
- +static s32 mlb_channel_enable(struct mlb_data *drvdata,
- + int chan_dev_id, int on)
- +{
- + struct mlb_dev_info *pdevinfo = drvdata->devinfo;
- + struct mlb_channel_info *tx_chinfo = &pdevinfo->channels[TX_CHANNEL];
- + struct mlb_channel_info *rx_chinfo = &pdevinfo->channels[RX_CHANNEL];
- + u32 tx_ch = tx_chinfo->address;
- + u32 rx_ch = rx_chinfo->address;
- + u32 tx_cl = tx_chinfo->cl;
- + u32 rx_cl = rx_chinfo->cl;
- + s32 ret = 0;
- +
- + /*
- + * setup the direction, enable, channel type,
- + * mode select, channel address and mask buf start
- + */
- + if (on) {
- + u32 ctype = pdevinfo->channel_type;
- +
- + mlb150_dev_enable_ctr_write(0xffffffff, 0xffffffff,
- + 0xffffffff, 0xffffffff);
- + mlb150_dev_init_rfb(pdevinfo, rx_ch, tx_ch, ctype);
- +
- + mlb150_dev_init_amba_ahb(pdevinfo, ctype);
- +
- +#ifdef DEBUG
- + mlb150_dev_dump_ctr_tbl(0, tx_chinfo->cl + 1);
- +#endif
- + /* Synchronize and unmute synchrouous channel */
- + if (MLB_CTYPE_SYNC == ctype) {
- + ret = mlb150_dev_unmute_syn_ch(rx_ch, rx_cl,
- + tx_ch, tx_cl);
- + if (ret)
- + return ret;
- + }
- +
- + mlb150_dev_enable_ctr_write(0x0, ADT_RDY1 | ADT_DNE1 |
- + ADT_ERR1 | ADT_PS1 |
- + ADT_RDY2 | ADT_DNE2 | ADT_ERR2 | ADT_PS2,
- + 0xffffffff, 0xffffffff);
- +
- + if (pdevinfo->fps >= CLK_2048FS)
- + mlb150_enable_pll(drvdata);
- +
- + atomic_set(&pdevinfo->on, 1);
- +
- +#ifdef DEBUG
- + mlb150_dev_dump_reg();
- + mlb150_dev_dump_ctr_tbl(0, tx_chinfo->cl + 1);
- +#endif
- + /* Init RX ADT */
- + mlb150_dev_pipo_start(&pdevinfo->rx_rbuf, rx_cl,
- + pdevinfo->rx_rbuf.phy_addrs[0]);
- + } else {
- + mlb150_dev_pipo_stop(&pdevinfo->rx_rbuf, rx_cl);
- +
- + mlb150_dev_enable_dma_irq(0);
- + mlb150_dev_enable_ir_mlb(0);
- +
- + mlb150_dev_reset_cat();
- +
- + atomic_set(&pdevinfo->on, 0);
- +
- + if (pdevinfo->fps >= CLK_2048FS)
- + mlb150_disable_pll(drvdata);
- + }
- +
- + return 0;
- +}
- +
- +/*
- + * MLB interrupt handler
- + */
- +static void mlb_rx_isr(s32 ctype, u32 ahb_ch, struct mlb_dev_info *pdevinfo)
- +{
- + struct mlb_ringbuf *rx_rbuf = &pdevinfo->rx_rbuf;
- + s32 head, tail, adt_sts;
- + u32 rx_buf_ptr;
- +
- +#ifdef DEBUG_RX
- + pr_debug("mxc_mlb150: mlb_rx_isr\n");
- +#endif
- +
- + read_lock(&rx_rbuf->rb_lock);
- +
- + head = (rx_rbuf->head + 1) & (TRANS_RING_NODES - 1);
- + tail = ACCESS_ONCE(rx_rbuf->tail);
- + read_unlock(&rx_rbuf->rb_lock);
- +
- + if (CIRC_SPACE(head, tail, TRANS_RING_NODES) >= 1) {
- + rx_buf_ptr = rx_rbuf->phy_addrs[head];
- +
- + /* commit the item before incrementing the head */
- + smp_wmb();
- +
- + write_lock(&rx_rbuf->rb_lock);
- + rx_rbuf->head = head;
- + write_unlock(&rx_rbuf->rb_lock);
- +
- + /* wake up the reader */
- + wake_up_interruptible(&pdevinfo->rx_wq);
- + } else {
- + rx_buf_ptr = rx_rbuf->phy_addrs[head];
- + pr_debug("drop RX package, due to no space, (%d,%d)\n",
- + head, tail);
- + }
- +
- + adt_sts = mlb150_dev_get_adt_sts(ahb_ch);
- + /* Set ADT for RX */
- + mlb150_dev_pipo_next(ahb_ch, ctype, adt_sts, rx_buf_ptr);
- +}
- +
- +static void mlb_tx_isr(s32 ctype, u32 ahb_ch, struct mlb_dev_info *pdevinfo)
- +{
- + struct mlb_ringbuf *tx_rbuf = &pdevinfo->tx_rbuf;
- + s32 head, tail, adt_sts;
- + u32 tx_buf_ptr;
- +
- + read_lock(&tx_rbuf->rb_lock);
- +
- + head = ACCESS_ONCE(tx_rbuf->head);
- + tail = (tx_rbuf->tail + 1) & (TRANS_RING_NODES - 1);
- + read_unlock(&tx_rbuf->rb_lock);
- +
- + smp_mb();
- + write_lock(&tx_rbuf->rb_lock);
- + tx_rbuf->tail = tail;
- + write_unlock(&tx_rbuf->rb_lock);
- +
- + /* check the current tx buffer is available or not */
- + if (CIRC_CNT(head, tail, TRANS_RING_NODES) >= 1) {
- + /* read index before reading contents at that index */
- + smp_read_barrier_depends();
- +
- + tx_buf_ptr = tx_rbuf->phy_addrs[tail];
- +
- + wake_up_interruptible(&pdevinfo->tx_wq);
- +
- + adt_sts = mlb150_dev_get_adt_sts(ahb_ch);
- + /* Set ADT for TX */
- + mlb150_dev_pipo_next(ahb_ch, ctype, adt_sts, tx_buf_ptr);
- + }
- +}
- +
- +static irqreturn_t mlb_ahb_isr(int irq, void *dev_id)
- +{
- + u32 acsr0, hcer0;
- + u32 ch_mask = (1 << SYNC_RX_CL) | (1 << CTRL_RX_CL)
- + | (1 << ASYNC_RX_CL) | (1 << ISOC_RX_CL)
- + | (1 << SYNC_TX_CL) | (1 << CTRL_TX_CL)
- + | (1 << ASYNC_TX_CL) | (1 << ISOC_TX_CL);
- +
- + /*
- + * Step 5, Read the ACSRn registers to determine which channel or
- + * channels are causing the interrupt
- + */
- + acsr0 = __raw_readl(mlb_base + REG_ACSR0);
- +
- + hcer0 = __raw_readl(mlb_base + REG_HCER0);
- +
- + /*
- + * Step 6, If ACTL.SCE = 1, write the result of step 5 back to ACSR0
- + * and ACSR1 to clear the interrupt
- + * We'll not set ACTL_SCE
- + */
- +
- + if (ch_mask & hcer0)
- + pr_err("CH encounters an AHB error: 0x%x\n", hcer0);
- +
- + if ((1 << SYNC_RX_CL) & acsr0)
- + mlb_rx_isr(MLB_CTYPE_SYNC, SYNC_RX_CL,
- + &mlb_devinfo[MLB_CTYPE_SYNC]);
- +
- + if ((1 << CTRL_RX_CL) & acsr0)
- + mlb_rx_isr(MLB_CTYPE_CTRL, CTRL_RX_CL,
- + &mlb_devinfo[MLB_CTYPE_CTRL]);
- +
- + if ((1 << ASYNC_RX_CL) & acsr0)
- + mlb_rx_isr(MLB_CTYPE_ASYNC, ASYNC_RX_CL,
- + &mlb_devinfo[MLB_CTYPE_ASYNC]);
- +
- + if ((1 << ISOC_RX_CL) & acsr0)
- + mlb_rx_isr(MLB_CTYPE_ISOC, ISOC_RX_CL,
- + &mlb_devinfo[MLB_CTYPE_ISOC]);
- +
- + if ((1 << SYNC_TX_CL) & acsr0)
- + mlb_tx_isr(MLB_CTYPE_SYNC, SYNC_TX_CL,
- + &mlb_devinfo[MLB_CTYPE_SYNC]);
- +
- + if ((1 << CTRL_TX_CL) & acsr0)
- + mlb_tx_isr(MLB_CTYPE_CTRL, CTRL_TX_CL,
- + &mlb_devinfo[MLB_CTYPE_CTRL]);
- +
- + if ((1 << ASYNC_TX_CL) & acsr0)
- + mlb_tx_isr(MLB_CTYPE_ASYNC, ASYNC_TX_CL,
- + &mlb_devinfo[MLB_CTYPE_ASYNC]);
- +
- + if ((1 << ISOC_TX_CL) & acsr0)
- + mlb_tx_isr(MLB_CTYPE_ASYNC, ISOC_TX_CL,
- + &mlb_devinfo[MLB_CTYPE_ISOC]);
- +
- + return IRQ_HANDLED;
- +}
- +
- +static irqreturn_t mlb_isr(int irq, void *dev_id)
- +{
- + u32 rx_int_sts, tx_int_sts, ms0,
- + ms1, tx_cis, rx_cis, ctype;
- + int minor;
- + u32 cdt_val[4] = { 0 };
- +
- + /*
- + * Step 4, Read the MSn register to determine which channel(s)
- + * are causing the interrupt
- + */
- + ms0 = __raw_readl(mlb_base + REG_MS0);
- + ms1 = __raw_readl(mlb_base + REG_MS1);
- +
- + /*
- + * The MLB150_MS0, MLB150_MS1 registers need to be cleared. In
- + * the spec description, the registers should be cleared when
- + * enabling interrupt. In fact, we also should clear it in ISR.
- + */
- + __raw_writel(0, mlb_base + REG_MS0);
- + __raw_writel(0, mlb_base + REG_MS1);
- +
- + pr_debug("mxc_mlb150: mlb interrupt:0x%08x 0x%08x\n",
- + (u32)ms0, (u32)ms1);
- +
- + for (minor = 0; minor < MLB_MINOR_DEVICES; minor++) {
- + struct mlb_dev_info *pdevinfo = &mlb_devinfo[minor];
- + u32 rx_mlb_ch = pdevinfo->channels[RX_CHANNEL].address;
- + u32 tx_mlb_ch = pdevinfo->channels[TX_CHANNEL].address;
- + u32 rx_mlb_cl = pdevinfo->channels[RX_CHANNEL].cl;
- + u32 tx_mlb_cl = pdevinfo->channels[TX_CHANNEL].cl;
- +
- + tx_cis = rx_cis = 0;
- +
- + ctype = pdevinfo->channel_type;
- + rx_int_sts = (rx_mlb_ch < 31) ? ms0 : ms1;
- + tx_int_sts = (tx_mlb_ch < 31) ? ms0 : ms1;
- +
- + pr_debug("mxc_mlb150: channel interrupt: "
- + "tx %d: 0x%08x, rx %d: 0x%08x\n",
- + tx_mlb_ch, (u32)tx_int_sts, rx_mlb_ch, (u32)rx_int_sts);
- +
- + /* Get tx channel interrupt status */
- + if (tx_int_sts & (1 << (tx_mlb_ch % 32))) {
- + mlb150_dev_cdt_read(tx_mlb_cl, cdt_val);
- + pr_debug("mxc_mlb150: TX_CH: %d, cdt_val[3]: 0x%08x, "
- + "cdt_val[2]: 0x%08x, "
- + "cdt_val[1]: 0x%08x, "
- + "cdt_val[0]: 0x%08x\n",
- + tx_mlb_ch, cdt_val[3], cdt_val[2],
- + cdt_val[1], cdt_val[0]);
- + switch (ctype) {
- + case MLB_CTYPE_SYNC:
- + tx_cis = (cdt_val[2] & ~CDT_SYNC_WSTS_MASK)
- + >> CDT_SYNC_WSTS_SHIFT;
- + /*
- + * Clear RSTS/WSTS errors to resume
- + * channel operation
- + * a. For synchronous channels: WSTS[3] = 0
- + */
- + cdt_val[2] &= ~(0x8 << CDT_SYNC_WSTS_SHIFT);
- + break;
- + case MLB_CTYPE_CTRL:
- + case MLB_CTYPE_ASYNC:
- + tx_cis = (cdt_val[2] &
- + ~CDT_CTRL_ASYNC_WSTS_MASK)
- + >> CDT_CTRL_ASYNC_WSTS_SHIFT;
- + tx_cis = (cdt_val[3] & CDT_CTRL_ASYNC_WSTS_1) ?
- + (tx_cis | (0x1 << 4)) : tx_cis;
- + /*
- + * b. For async and ctrl channels:
- + * RSTS[4]/WSTS[4] = 0
- + * and RSTS[2]/WSTS[2] = 0
- + */
- + cdt_val[3] &= ~CDT_CTRL_ASYNC_WSTS_1;
- + cdt_val[2] &=
- + ~(0x4 << CDT_CTRL_ASYNC_WSTS_SHIFT);
- + break;
- + case MLB_CTYPE_ISOC:
- + tx_cis = (cdt_val[2] & ~CDT_ISOC_WSTS_MASK)
- + >> CDT_ISOC_WSTS_SHIFT;
- + /* c. For isoc channels: WSTS[2:1] = 0x00 */
- + cdt_val[2] &= ~(0x6 << CDT_ISOC_WSTS_SHIFT);
- + break;
- + default:
- + break;
- + }
- + mlb150_dev_cdt_write(tx_mlb_ch, cdt_val);
- + }
- +
- + /* Get rx channel interrupt status */
- + if (rx_int_sts & (1 << (rx_mlb_ch % 32))) {
- + mlb150_dev_cdt_read(rx_mlb_cl, cdt_val);
- + pr_debug("mxc_mlb150: RX_CH: %d, cdt_val[3]: 0x%08x, "
- + "cdt_val[2]: 0x%08x, "
- + "cdt_val[1]: 0x%08x, "
- + "cdt_val[0]: 0x%08x\n",
- + rx_mlb_ch, cdt_val[3], cdt_val[2],
- + cdt_val[1], cdt_val[0]);
- + switch (ctype) {
- + case MLB_CTYPE_SYNC:
- + tx_cis = (cdt_val[2] & ~CDT_SYNC_RSTS_MASK)
- + >> CDT_SYNC_RSTS_SHIFT;
- + cdt_val[2] &= ~(0x8 << CDT_SYNC_WSTS_SHIFT);
- + break;
- + case MLB_CTYPE_CTRL:
- + case MLB_CTYPE_ASYNC:
- + tx_cis =
- + (cdt_val[2] & ~CDT_CTRL_ASYNC_RSTS_MASK)
- + >> CDT_CTRL_ASYNC_RSTS_SHIFT;
- + tx_cis = (cdt_val[3] & CDT_CTRL_ASYNC_RSTS_1) ?
- + (tx_cis | (0x1 << 4)) : tx_cis;
- + cdt_val[3] &= ~CDT_CTRL_ASYNC_RSTS_1;
- + cdt_val[2] &=
- + ~(0x4 << CDT_CTRL_ASYNC_RSTS_SHIFT);
- + break;
- + case MLB_CTYPE_ISOC:
- + tx_cis = (cdt_val[2] & ~CDT_ISOC_RSTS_MASK)
- + >> CDT_ISOC_RSTS_SHIFT;
- + cdt_val[2] &= ~(0x6 << CDT_ISOC_WSTS_SHIFT);
- + break;
- + default:
- + break;
- + }
- + mlb150_dev_cdt_write(rx_mlb_ch, cdt_val);
- + }
- +
- + if (!tx_cis && !rx_cis)
- + continue;
- +
- + /* fill exception event */
- + spin_lock(&pdevinfo->event_lock);
- + pdevinfo->ex_event |= (rx_cis << 16) | tx_cis;
- + spin_unlock(&pdevinfo->event_lock);
- + }
- +
- + return IRQ_HANDLED;
- +}
- +
- +static int mxc_mlb150_open(struct inode *inode, struct file *filp)
- +{
- + int minor, ring_buf_size, buf_size, j, ret;
- + void __iomem *buf_addr;
- + ulong phy_addr;
- + struct mlb_dev_info *pdevinfo = NULL;
- + struct mlb_channel_info *pchinfo = NULL;
- + struct mlb_data *drvdata;
- +
- + minor = MINOR(inode->i_rdev);
- + drvdata = container_of(inode->i_cdev, struct mlb_data, cdev);
- +
- + if (minor < 0 || minor >= MLB_MINOR_DEVICES) {
- + pr_err("no device\n");
- + return -ENODEV;
- + }
- +
- + /* open for each channel device */
- + if (atomic_cmpxchg(&mlb_devinfo[minor].opencnt, 0, 1) != 0) {
- + pr_err("busy\n");
- + return -EBUSY;
- + }
- +
- + clk_prepare_enable(drvdata->clk_mlb3p);
- +
- + /* initial MLB module */
- + mlb150_dev_init();
- +
- + pdevinfo = &mlb_devinfo[minor];
- + pchinfo = &pdevinfo->channels[TX_CHANNEL];
- +
- + ring_buf_size = pdevinfo->buf_size;
- + buf_size = ring_buf_size * (TRANS_RING_NODES * 2);
- + buf_addr = (void __iomem *)gen_pool_alloc(drvdata->iram_pool, buf_size);
- + if (buf_addr == NULL) {
- + ret = -ENOMEM;
- + pr_err("can not alloc rx/tx buffers: %d\n", buf_size);
- + return ret;
- + }
- + phy_addr = gen_pool_virt_to_phys(drvdata->iram_pool, (ulong)buf_addr);
- + pr_debug("IRAM Range: Virt 0x%p - 0x%p, Phys 0x%x - 0x%x, size: 0x%x\n",
- + buf_addr, (buf_addr + buf_size - 1), (u32)phy_addr,
- + (u32)(phy_addr + buf_size - 1), buf_size);
- + pdevinfo->rbuf_base_virt = buf_addr;
- + pdevinfo->rbuf_base_phy = phy_addr;
- + drvdata->iram_size = buf_size;
- +
- + memset(buf_addr, 0, buf_size);
- +
- + for (j = 0; j < (TRANS_RING_NODES);
- + ++j, buf_addr += ring_buf_size, phy_addr += ring_buf_size) {
- + pdevinfo->rx_rbuf.virt_bufs[j] = buf_addr;
- + pdevinfo->rx_rbuf.phy_addrs[j] = phy_addr;
- + pr_debug("RX Ringbuf[%d]: 0x%p 0x%x\n",
- + j, buf_addr, (u32)phy_addr);
- + }
- + pdevinfo->rx_rbuf.unit_size = ring_buf_size;
- + pdevinfo->rx_rbuf.total_size = buf_size;
- + for (j = 0; j < (TRANS_RING_NODES);
- + ++j, buf_addr += ring_buf_size, phy_addr += ring_buf_size) {
- + pdevinfo->tx_rbuf.virt_bufs[j] = buf_addr;
- + pdevinfo->tx_rbuf.phy_addrs[j] = phy_addr;
- + pr_debug("TX Ringbuf[%d]: 0x%p 0x%x\n",
- + j, buf_addr, (u32)phy_addr);
- + }
- +
- + pdevinfo->tx_rbuf.unit_size = ring_buf_size;
- + pdevinfo->tx_rbuf.total_size = buf_size;
- +
- + /* reset the buffer read/write ptr */
- + pdevinfo->rx_rbuf.head = pdevinfo->rx_rbuf.tail = 0;
- + pdevinfo->tx_rbuf.head = pdevinfo->tx_rbuf.tail = 0;
- + pdevinfo->ex_event = 0;
- + pdevinfo->tx_ok = 0;
- +
- + init_waitqueue_head(&pdevinfo->rx_wq);
- + init_waitqueue_head(&pdevinfo->tx_wq);
- +
- + drvdata = container_of(inode->i_cdev, struct mlb_data, cdev);
- + drvdata->devinfo = pdevinfo;
- + mxc_mlb150_irq_enable(drvdata, 1);
- + filp->private_data = drvdata;
- +
- + return 0;
- +}
- +
- +static int mxc_mlb150_release(struct inode *inode, struct file *filp)
- +{
- + int minor;
- + struct mlb_data *drvdata = filp->private_data;
- + struct mlb_dev_info *pdevinfo = drvdata->devinfo;
- +
- + minor = MINOR(inode->i_rdev);
- + mxc_mlb150_irq_enable(drvdata, 0);
- +
- +#ifdef DEBUG
- + mlb150_dev_dump_reg();
- + mlb150_dev_dump_ctr_tbl(0, pdevinfo->channels[TX_CHANNEL].cl + 1);
- +#endif
- +
- + gen_pool_free(drvdata->iram_pool,
- + (ulong)pdevinfo->rbuf_base_virt, drvdata->iram_size);
- +
- + mlb150_dev_exit();
- +
- + if (pdevinfo && atomic_read(&pdevinfo->on)
- + && (pdevinfo->fps >= CLK_2048FS))
- + clk_disable_unprepare(drvdata->clk_mlb6p);
- +
- + atomic_set(&pdevinfo->on, 0);
- +
- + clk_disable_unprepare(drvdata->clk_mlb3p);
- + /* decrease the open count */
- + atomic_set(&pdevinfo->opencnt, 0);
- +
- + drvdata->devinfo = NULL;
- +
- + return 0;
- +}
- +
- +static long mxc_mlb150_ioctl(struct file *filp,
- + unsigned int cmd, unsigned long arg)
- +{
- + struct inode *inode = filp->f_dentry->d_inode;
- + struct mlb_data *drvdata = filp->private_data;
- + struct mlb_dev_info *pdevinfo = drvdata->devinfo;
- + void __user *argp = (void __user *)arg;
- + unsigned long flags, event;
- + int minor;
- +
- + minor = MINOR(inode->i_rdev);
- +
- + switch (cmd) {
- + case MLB_CHAN_SETADDR:
- + {
- + unsigned int caddr;
- + /* get channel address from user space */
- + if (copy_from_user(&caddr, argp, sizeof(caddr))) {
- + pr_err("mxc_mlb150: copy from user failed\n");
- + return -EFAULT;
- + }
- + pdevinfo->channels[TX_CHANNEL].address =
- + (caddr >> 16) & 0xFFFF;
- + pdevinfo->channels[RX_CHANNEL].address = caddr & 0xFFFF;
- + pr_debug("mxc_mlb150: set ch addr, tx: %d, rx: %d\n",
- + pdevinfo->channels[TX_CHANNEL].address,
- + pdevinfo->channels[RX_CHANNEL].address);
- + break;
- + }
- +
- + case MLB_CHAN_STARTUP:
- + if (atomic_read(&pdevinfo->on)) {
- + pr_debug("mxc_mlb150: channel alreadly startup\n");
- + break;
- + }
- + if (mlb_channel_enable(drvdata, minor, 1))
- + return -EFAULT;
- + break;
- + case MLB_CHAN_SHUTDOWN:
- + if (atomic_read(&pdevinfo->on) == 0) {
- + pr_debug("mxc_mlb150: channel areadly shutdown\n");
- + break;
- + }
- + mlb150_trans_complete_check(pdevinfo);
- + mlb_channel_enable(drvdata, minor, 0);
- + break;
- + case MLB_CHAN_GETEVENT:
- + /* get and clear the ex_event */
- + spin_lock_irqsave(&pdevinfo->event_lock, flags);
- + event = pdevinfo->ex_event;
- + pdevinfo->ex_event = 0;
- + spin_unlock_irqrestore(&pdevinfo->event_lock, flags);
- +
- + if (event) {
- + if (copy_to_user(argp, &event, sizeof(event))) {
- + pr_err("mxc_mlb150: copy to user failed\n");
- + return -EFAULT;
- + }
- + } else
- + return -EAGAIN;
- + break;
- + case MLB_SET_ISOC_BLKSIZE_188:
- + pdevinfo->isoc_blksz = 188;
- + pdevinfo->cdt_buf_dep = pdevinfo->adt_buf_dep =
- + pdevinfo->isoc_blksz * CH_ISOC_BLK_NUM;
- + break;
- + case MLB_SET_ISOC_BLKSIZE_196:
- + pdevinfo->isoc_blksz = 196;
- + pdevinfo->cdt_buf_dep = pdevinfo->adt_buf_dep =
- + pdevinfo->isoc_blksz * CH_ISOC_BLK_NUM;
- + break;
- + case MLB_SET_SYNC_QUAD:
- + {
- + u32 quad;
- +
- + if (copy_from_user(&quad, argp, sizeof(quad))) {
- + pr_err("mxc_mlb150: get quad number "
- + "from user failed\n");
- + return -EFAULT;
- + }
- + if (quad <= 0 || quad > 3) {
- + pr_err("mxc_mlb150: Invalid Quadlets!"
- + "Quadlets in Sync mode can "
- + "only be 1, 2, 3\n");
- + return -EINVAL;
- + }
- + pdevinfo->sync_quad = quad;
- + /* Each quadlets is 4 bytes */
- + pdevinfo->cdt_buf_dep = quad * 4 * 4;
- + pdevinfo->adt_buf_dep =
- + pdevinfo->cdt_buf_dep * CH_SYNC_ADT_BUF_MULTI;
- + }
- + break;
- + case MLB_SET_FPS:
- + {
- + u32 fps, c0_val;
- +
- + /* get fps from user space */
- + if (copy_from_user(&fps, argp, sizeof(fps))) {
- + pr_err("mxc_mlb150: copy from user failed\n");
- + return -EFAULT;
- + }
- +
- + c0_val = __raw_readl(mlb_base + REG_MLBC0);
- + c0_val &= ~MLBC0_MLBCLK_MASK;
- +
- + /* check fps value */
- + switch (fps) {
- + case 256:
- + case 512:
- + case 1024:
- + pdevinfo->fps = fps >> 9;
- + c0_val &= ~MLBC0_MLBPEN;
- + c0_val |= (fps >> 9)
- + << MLBC0_MLBCLK_SHIFT;
- +
- + if (1024 == fps) {
- + /*
- + * Invert output clock phase
- + * in 1024 fps
- + */
- + __raw_writel(0x1,
- + mlb_base + REG_MLBPC2);
- + }
- + break;
- + case 2048:
- + case 3072:
- + case 4096:
- + pdevinfo->fps = (fps >> 10) + 1;
- + c0_val |= ((fps >> 10) + 1)
- + << MLBC0_MLBCLK_SHIFT;
- + break;
- + case 6144:
- + pdevinfo->fps = fps >> 10;
- + c0_val |= ((fps >> 10) + 1)
- + << MLBC0_MLBCLK_SHIFT;
- + break;
- + case 8192:
- + pdevinfo->fps = (fps >> 10) - 1;
- + c0_val |= ((fps >> 10) - 1)
- + << MLBC0_MLBCLK_SHIFT;
- + break;
- + default:
- + pr_debug("mxc_mlb150: invalid fps argument: %d\n",
- + fps);
- + return -EINVAL;
- + }
- +
- + __raw_writel(c0_val, mlb_base + REG_MLBC0);
- +
- + pr_debug("mxc_mlb150: set fps to %d, MLBC0: 0x%08x\n",
- + fps,
- + (u32)__raw_readl(mlb_base + REG_MLBC0));
- +
- + break;
- + }
- +
- + case MLB_GET_VER:
- + {
- + u32 version;
- +
- + /* get MLB device module version */
- + version = 0x03030003;
- +
- + pr_debug("mxc_mlb150: get version: 0x%08x\n",
- + version);
- +
- + if (copy_to_user(argp, &version, sizeof(version))) {
- + pr_err("mxc_mlb150: copy to user failed\n");
- + return -EFAULT;
- + }
- + break;
- + }
- +
- + case MLB_SET_DEVADDR:
- + {
- + u32 c1_val;
- + u8 devaddr;
- +
- + /* get MLB device address from user space */
- + if (copy_from_user
- + (&devaddr, argp, sizeof(unsigned char))) {
- + pr_err("mxc_mlb150: copy from user failed\n");
- + return -EFAULT;
- + }
- +
- + c1_val = __raw_readl(mlb_base + REG_MLBC1);
- + c1_val &= ~MLBC1_NDA_MASK;
- + c1_val |= devaddr << MLBC1_NDA_SHIFT;
- + __raw_writel(c1_val, mlb_base + REG_MLBC1);
- + pr_debug("mxc_mlb150: set dev addr, dev addr: %d, "
- + "MLBC1: 0x%08x\n", devaddr,
- + (u32)__raw_readl(mlb_base + REG_MLBC1));
- +
- + break;
- + }
- +
- + case MLB_IRQ_DISABLE:
- + {
- + disable_irq(drvdata->irq_mlb);
- + break;
- + }
- +
- + case MLB_IRQ_ENABLE:
- + {
- + enable_irq(drvdata->irq_mlb);
- + break;
- + }
- + default:
- + pr_info("mxc_mlb150: Invalid ioctl command\n");
- + return -EINVAL;
- + }
- +
- + return 0;
- +}
- +
- +/*
- + * MLB read routine
- + * Read the current received data from queued buffer,
- + * and free this buffer for hw to fill ingress data.
- + */
- +static ssize_t mxc_mlb150_read(struct file *filp, char __user *buf,
- + size_t count, loff_t *f_pos)
- +{
- + int size;
- + struct mlb_data *drvdata = filp->private_data;
- + struct mlb_dev_info *pdevinfo = drvdata->devinfo;
- + struct mlb_ringbuf *rx_rbuf = &pdevinfo->rx_rbuf;
- + int head, tail;
- + unsigned long flags;
- +
- + read_lock_irqsave(&rx_rbuf->rb_lock, flags);
- +
- + head = ACCESS_ONCE(rx_rbuf->head);
- + tail = rx_rbuf->tail;
- +
- + read_unlock_irqrestore(&rx_rbuf->rb_lock, flags);
- +
- + /* check the current rx buffer is available or not */
- + if (0 == CIRC_CNT(head, tail, TRANS_RING_NODES)) {
- +
- + if (filp->f_flags & O_NONBLOCK)
- + return -EAGAIN;
- +
- + do {
- + DEFINE_WAIT(__wait);
- +
- + for (;;) {
- + prepare_to_wait(&pdevinfo->rx_wq,
- + &__wait, TASK_INTERRUPTIBLE);
- +
- + read_lock_irqsave(&rx_rbuf->rb_lock, flags);
- + if (CIRC_CNT(rx_rbuf->head, rx_rbuf->tail,
- + TRANS_RING_NODES) > 0) {
- + read_unlock_irqrestore(&rx_rbuf->rb_lock,
- + flags);
- + break;
- + }
- + read_unlock_irqrestore(&rx_rbuf->rb_lock,
- + flags);
- +
- + if (!signal_pending(current)) {
- + schedule();
- + continue;
- + }
- + return -ERESTARTSYS;
- + }
- + finish_wait(&pdevinfo->rx_wq, &__wait);
- + } while (0);
- + }
- +
- + /* read index before reading contents at that index */
- + smp_read_barrier_depends();
- +
- + size = pdevinfo->adt_buf_dep;
- + if (size > count) {
- + /* the user buffer is too small */
- + pr_warning
- + ("mxc_mlb150: received data size is bigger than "
- + "size: %d, count: %d\n", size, count);
- + return -EINVAL;
- + }
- +
- + /* extract one item from the buffer */
- + if (copy_to_user(buf, rx_rbuf->virt_bufs[tail], size)) {
- + pr_err("mxc_mlb150: copy from user failed\n");
- + return -EFAULT;
- + }
- +
- + /* finish reading descriptor before incrementing tail */
- + smp_mb();
- +
- + write_lock_irqsave(&rx_rbuf->rb_lock, flags);
- + rx_rbuf->tail = (tail + 1) & (TRANS_RING_NODES - 1);
- + write_unlock_irqrestore(&rx_rbuf->rb_lock, flags);
- +
- + *f_pos = 0;
- +
- + return size;
- +}
- +
- +/*
- + * MLB write routine
- + * Copy the user data to tx channel buffer,
- + * and prepare the channel current/next buffer ptr.
- + */
- +static ssize_t mxc_mlb150_write(struct file *filp, const char __user *buf,
- + size_t count, loff_t *f_pos)
- +{
- + s32 ret = 0;
- + struct mlb_channel_info *pchinfo = NULL;
- + struct mlb_data *drvdata = filp->private_data;
- + struct mlb_dev_info *pdevinfo = drvdata->devinfo;
- + struct mlb_ringbuf *tx_rbuf = &pdevinfo->tx_rbuf;
- + int head, tail;
- + unsigned long flags;
- +
- + /*
- + * minor = MINOR(filp->f_dentry->d_inode->i_rdev);
- + */
- + pchinfo = &pdevinfo->channels[TX_CHANNEL];
- +
- + if (count > pdevinfo->buf_size) {
- + /* too many data to write */
- + pr_warning("mxc_mlb150: overflow write data\n");
- + return -EFBIG;
- + }
- +
- + *f_pos = 0;
- +
- + read_lock_irqsave(&tx_rbuf->rb_lock, flags);
- +
- + head = tx_rbuf->head;
- + tail = ACCESS_ONCE(tx_rbuf->tail);
- + read_unlock_irqrestore(&tx_rbuf->rb_lock, flags);
- +
- + if (0 == CIRC_SPACE(head, tail, TRANS_RING_NODES)) {
- + if (filp->f_flags & O_NONBLOCK)
- + return -EAGAIN;
- + do {
- + DEFINE_WAIT(__wait);
- +
- + for (;;) {
- + prepare_to_wait(&pdevinfo->tx_wq,
- + &__wait, TASK_INTERRUPTIBLE);
- +
- + read_lock_irqsave(&tx_rbuf->rb_lock, flags);
- + if (CIRC_SPACE(tx_rbuf->head, tx_rbuf->tail,
- + TRANS_RING_NODES) > 0) {
- + read_unlock_irqrestore(&tx_rbuf->rb_lock,
- + flags);
- + break;
- + }
- + read_unlock_irqrestore(&tx_rbuf->rb_lock,
- + flags);
- +
- + if (!signal_pending(current)) {
- + schedule();
- + continue;
- + }
- + return -ERESTARTSYS;
- + }
- + finish_wait(&pdevinfo->tx_wq, &__wait);
- + } while (0);
- + }
- +
- + if (copy_from_user((void *)tx_rbuf->virt_bufs[head], buf, count)) {
- + read_unlock_irqrestore(&tx_rbuf->rb_lock, flags);
- + pr_err("mxc_mlb: copy from user failed\n");
- + ret = -EFAULT;
- + goto out;
- + }
- +
- + write_lock_irqsave(&tx_rbuf->rb_lock, flags);
- + smp_wmb();
- + tx_rbuf->head = (head + 1) & (TRANS_RING_NODES - 1);
- + write_unlock_irqrestore(&tx_rbuf->rb_lock, flags);
- +
- + if (0 == CIRC_CNT(head, tail, TRANS_RING_NODES)) {
- + u32 tx_buf_ptr, ahb_ch;
- + s32 adt_sts;
- + u32 ctype = pdevinfo->channel_type;
- +
- + /* read index before reading contents at that index */
- + smp_read_barrier_depends();
- +
- + tx_buf_ptr = tx_rbuf->phy_addrs[tail];
- +
- + ahb_ch = pdevinfo->channels[TX_CHANNEL].cl;
- + adt_sts = mlb150_dev_get_adt_sts(ahb_ch);
- +
- + /* Set ADT for TX */
- + mlb150_dev_pipo_next(ahb_ch, ctype, adt_sts, tx_buf_ptr);
- + }
- +
- + ret = count;
- +out:
- + return ret;
- +}
- +
- +static unsigned int mxc_mlb150_poll(struct file *filp,
- + struct poll_table_struct *wait)
- +{
- + int minor;
- + unsigned int ret = 0;
- + struct mlb_data *drvdata = filp->private_data;
- + struct mlb_dev_info *pdevinfo = drvdata->devinfo;
- + struct mlb_ringbuf *tx_rbuf = &pdevinfo->tx_rbuf;
- + struct mlb_ringbuf *rx_rbuf = &pdevinfo->rx_rbuf;
- + int head, tail;
- + unsigned long flags;
- +
- +
- + minor = MINOR(filp->f_dentry->d_inode->i_rdev);
- +
- + poll_wait(filp, &pdevinfo->rx_wq, wait);
- + poll_wait(filp, &pdevinfo->tx_wq, wait);
- +
- + read_lock_irqsave(&tx_rbuf->rb_lock, flags);
- + head = tx_rbuf->head;
- + tail = tx_rbuf->tail;
- + read_unlock_irqrestore(&tx_rbuf->rb_lock, flags);
- +
- + /* check the tx buffer is avaiable or not */
- + if (CIRC_SPACE(head, tail, TRANS_RING_NODES) >= 1)
- + ret |= POLLOUT | POLLWRNORM;
- +
- + read_lock_irqsave(&rx_rbuf->rb_lock, flags);
- + head = rx_rbuf->head;
- + tail = rx_rbuf->tail;
- + read_unlock_irqrestore(&rx_rbuf->rb_lock, flags);
- +
- + /* check the rx buffer filled or not */
- + if (CIRC_CNT(head, tail, TRANS_RING_NODES) >= 1)
- + ret |= POLLIN | POLLRDNORM;
- +
- +
- + /* check the exception event */
- + if (pdevinfo->ex_event)
- + ret |= POLLIN | POLLRDNORM;
- +
- + return ret;
- +}
- +
- +/*
- + * char dev file operations structure
- + */
- +static const struct file_operations mxc_mlb150_fops = {
- +
- + .owner = THIS_MODULE,
- + .open = mxc_mlb150_open,
- + .release = mxc_mlb150_release,
- + .unlocked_ioctl = mxc_mlb150_ioctl,
- + .poll = mxc_mlb150_poll,
- + .read = mxc_mlb150_read,
- + .write = mxc_mlb150_write,
- +};
- +
- +static struct platform_device_id imx_mlb150_devtype[] = {
- + {
- + .name = "imx6q-mlb150",
- + .driver_data = 0,
- + }, {
- + /* sentinel */
- + }
- +};
- +MODULE_DEVICE_TABLE(platform, imx_mlb150_devtype);
- +
- +static const struct of_device_id mlb150_imx_dt_ids[] = {
- + { .compatible = "fsl,imx6q-mlb150", .data = &imx_mlb150_devtype[0], },
- + { /* sentinel */ }
- +};
- +
- +/*
- + * This function is called whenever the MLB device is detected.
- + */
- +static int mxc_mlb150_probe(struct platform_device *pdev)
- +{
- + int ret, mlb_major, i;
- + struct mlb_data *drvdata;
- + struct resource *res;
- + struct device_node *np = pdev->dev.of_node;
- +
- + drvdata = devm_kzalloc(&pdev->dev, sizeof(struct mlb_data),
- + GFP_KERNEL);
- + if (!drvdata) {
- + dev_err(&pdev->dev, "can't allocate enough memory\n");
- + return -ENOMEM;
- + }
- +
- + /*
- + * Register MLB lld as four character devices
- + */
- + ret = alloc_chrdev_region(&drvdata->firstdev, 0,
- + MLB_MINOR_DEVICES, "mxc_mlb150");
- + if (ret < 0) {
- + dev_err(&pdev->dev, "alloc region error\n");
- + goto err_reg;
- + }
- + mlb_major = MAJOR(drvdata->firstdev);
- + dev_dbg(&pdev->dev, "MLB device major: %d\n", mlb_major);
- +
- + cdev_init(&drvdata->cdev, &mxc_mlb150_fops);
- + drvdata->cdev.owner = THIS_MODULE;
- +
- + ret = cdev_add(&drvdata->cdev, drvdata->firstdev, MLB_MINOR_DEVICES);
- + if (ret) {
- + dev_err(&pdev->dev, "can't add cdev\n");
- + goto err_reg;
- + }
- +
- + /* create class and device for udev information */
- + drvdata->class = class_create(THIS_MODULE, "mlb150");
- + if (IS_ERR(drvdata->class)) {
- + dev_err(&pdev->dev, "failed to create device class\n");
- + ret = -ENOMEM;
- + goto err_class;
- + }
- +
- + for (i = 0; i < MLB_MINOR_DEVICES; i++) {
- + struct device *class_dev;
- +
- + class_dev = device_create(drvdata->class, NULL,
- + MKDEV(mlb_major, i),
- + NULL, mlb_devinfo[i].dev_name);
- + if (IS_ERR(class_dev)) {
- + dev_err(&pdev->dev, "failed to create mlb150 %s"
- + " class device\n", mlb_devinfo[i].dev_name);
- + ret = -ENOMEM;
- + goto err_dev;
- + }
- + }
- +
- + /* ahb0 irq */
- + drvdata->irq_ahb0 = platform_get_irq(pdev, 1);
- + if (drvdata->irq_ahb0 < 0) {
- + dev_err(&pdev->dev, "No ahb0 irq line provided\n");
- + goto err_dev;
- + }
- + dev_dbg(&pdev->dev, "ahb0_irq: %d\n", drvdata->irq_ahb0);
- + if (devm_request_irq(&pdev->dev, drvdata->irq_ahb0, mlb_ahb_isr,
- + 0, "mlb_ahb0", NULL)) {
- + dev_err(&pdev->dev, "can't claim irq %d\n", drvdata->irq_ahb0);
- + goto err_dev;
- + }
- +
- + /* ahb1 irq */
- + drvdata->irq_ahb1 = platform_get_irq(pdev, 2);
- + if (drvdata->irq_ahb1 < 0) {
- + dev_err(&pdev->dev, "No ahb1 irq line provided\n");
- + goto err_dev;
- + }
- + dev_dbg(&pdev->dev, "ahb1_irq: %d\n", drvdata->irq_ahb1);
- + if (devm_request_irq(&pdev->dev, drvdata->irq_ahb1, mlb_ahb_isr,
- + 0, "mlb_ahb1", NULL)) {
- + dev_err(&pdev->dev, "can't claim irq %d\n", drvdata->irq_ahb1);
- + goto err_dev;
- + }
- +
- + /* mlb irq */
- + drvdata->irq_mlb = platform_get_irq(pdev, 0);
- + if (drvdata->irq_mlb < 0) {
- + dev_err(&pdev->dev, "No mlb irq line provided\n");
- + goto err_dev;
- + }
- + dev_dbg(&pdev->dev, "mlb_irq: %d\n", drvdata->irq_mlb);
- + if (devm_request_irq(&pdev->dev, drvdata->irq_mlb, mlb_isr,
- + 0, "mlb", NULL)) {
- + dev_err(&pdev->dev, "can't claim irq %d\n", drvdata->irq_mlb);
- + goto err_dev;
- + }
- +
- + /* ioremap from phy mlb to kernel space */
- + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- + if (!res) {
- + dev_err(&pdev->dev, "can't get device resources\n");
- + ret = -ENOENT;
- + goto err_dev;
- + }
- + mlb_base = devm_request_and_ioremap(&pdev->dev, res);
- + dev_dbg(&pdev->dev, "mapped base address: 0x%08x\n", (u32)mlb_base);
- + if (IS_ERR(mlb_base)) {
- + dev_err(&pdev->dev,
- + "failed to get ioremap base\n");
- + ret = PTR_ERR(mlb_base);
- + goto err_dev;
- + }
- + drvdata->membase = mlb_base;
- +
- +#ifdef CONFIG_REGULATOR
- + drvdata->nvcc = devm_regulator_get(&pdev->dev, "reg_nvcc");
- + if (!IS_ERR(drvdata->nvcc)) {
- + regulator_set_voltage(drvdata->nvcc, 2500000, 2500000);
- + dev_err(&pdev->dev, "enalbe regulator\n");
- + ret = regulator_enable(drvdata->nvcc);
- + if (ret) {
- + dev_err(&pdev->dev, "vdd set voltage error\n");
- + goto err_dev;
- + }
- + }
- +#endif
- +
- + /* enable clock */
- + drvdata->clk_mlb3p = devm_clk_get(&pdev->dev, "mlb");
- + if (IS_ERR(drvdata->clk_mlb3p)) {
- + dev_err(&pdev->dev, "unable to get mlb clock\n");
- + ret = PTR_ERR(drvdata->clk_mlb3p);
- + goto err_dev;
- + }
- +
- + drvdata->clk_mlb6p = devm_clk_get(&pdev->dev, "pll8_mlb");
- + if (IS_ERR(drvdata->clk_mlb6p)) {
- + dev_err(&pdev->dev, "unable to get mlb pll clock\n");
- + ret = PTR_ERR(drvdata->clk_mlb6p);
- + goto err_dev;
- + }
- +
- +
- + drvdata->iram_pool = of_get_named_gen_pool(np, "iram", 0);
- + if (!drvdata->iram_pool) {
- + dev_err(&pdev->dev, "iram pool not available\n");
- + ret = -ENOMEM;
- + goto err_dev;
- + }
- +
- + drvdata->devinfo = NULL;
- + mxc_mlb150_irq_enable(drvdata, 0);
- + platform_set_drvdata(pdev, drvdata);
- + return 0;
- +
- +err_dev:
- + for (--i; i >= 0; i--)
- + device_destroy(drvdata->class, MKDEV(mlb_major, i));
- +
- + class_destroy(drvdata->class);
- +err_class:
- + cdev_del(&drvdata->cdev);
- +err_reg:
- + unregister_chrdev_region(drvdata->firstdev, MLB_MINOR_DEVICES);
- +
- + return ret;
- +}
- +
- +static int mxc_mlb150_remove(struct platform_device *pdev)
- +{
- + int i;
- + struct mlb_data *drvdata = platform_get_drvdata(pdev);
- + struct mlb_dev_info *pdevinfo = drvdata->devinfo;
- +
- + if (pdevinfo && atomic_read(&pdevinfo->on)
- + && (pdevinfo->fps >= CLK_2048FS))
- + clk_disable_unprepare(drvdata->clk_mlb6p);
- +
- + if (pdevinfo && atomic_read(&pdevinfo->opencnt))
- + clk_disable_unprepare(drvdata->clk_mlb3p);
- +
- + /* disable mlb power */
- +#ifdef CONFIG_REGULATOR
- + if (!IS_ERR(drvdata->nvcc))
- + regulator_disable(drvdata->nvcc);
- +#endif
- +
- + /* destroy mlb device class */
- + for (i = MLB_MINOR_DEVICES - 1; i >= 0; i--)
- + device_destroy(drvdata->class,
- + MKDEV(MAJOR(drvdata->firstdev), i));
- + class_destroy(drvdata->class);
- +
- + cdev_del(&drvdata->cdev);
- +
- + /* Unregister the two MLB devices */
- + unregister_chrdev_region(drvdata->firstdev, MLB_MINOR_DEVICES);
- +
- + return 0;
- +}
- +
- +#ifdef CONFIG_PM
- +static int mxc_mlb150_suspend(struct platform_device *pdev, pm_message_t state)
- +{
- + struct mlb_data *drvdata = platform_get_drvdata(pdev);
- + struct mlb_dev_info *pdevinfo = drvdata->devinfo;
- +
- + if (pdevinfo && atomic_read(&pdevinfo->on)
- + && (pdevinfo->fps >= CLK_2048FS))
- + clk_disable_unprepare(drvdata->clk_mlb6p);
- +
- + if (pdevinfo && atomic_read(&pdevinfo->opencnt)) {
- + mlb150_dev_exit();
- + clk_disable_unprepare(drvdata->clk_mlb3p);
- + }
- +
- + return 0;
- +}
- +
- +static int mxc_mlb150_resume(struct platform_device *pdev)
- +{
- + struct mlb_data *drvdata = platform_get_drvdata(pdev);
- + struct mlb_dev_info *pdevinfo = drvdata->devinfo;
- +
- + if (pdevinfo && atomic_read(&pdevinfo->opencnt)) {
- + clk_prepare_enable(drvdata->clk_mlb3p);
- + mlb150_dev_init();
- + }
- +
- + if (pdevinfo && atomic_read(&pdevinfo->on) &&
- + (pdevinfo->fps >= CLK_2048FS))
- + clk_prepare_enable(drvdata->clk_mlb6p);
- +
- + return 0;
- +}
- +#else
- +#define mxc_mlb150_suspend NULL
- +#define mxc_mlb150_resume NULL
- +#endif
- +
- +/*
- + * platform driver structure for MLB
- + */
- +static struct platform_driver mxc_mlb150_driver = {
- + .driver = {
- + .name = DRIVER_NAME,
- + .owner = THIS_MODULE,
- + .of_match_table = mlb150_imx_dt_ids,
- + },
- + .probe = mxc_mlb150_probe,
- + .remove = mxc_mlb150_remove,
- + .suspend = mxc_mlb150_suspend,
- + .resume = mxc_mlb150_resume,
- + .id_table = imx_mlb150_devtype,
- +};
- +
- +static int __init mxc_mlb150_init(void)
- +{
- + return platform_driver_register(&mxc_mlb150_driver);
- +}
- +
- +static void __exit mxc_mlb150_exit(void)
- +{
- + platform_driver_unregister(&mxc_mlb150_driver);
- +}
- +
- +module_init(mxc_mlb150_init);
- +module_exit(mxc_mlb150_exit);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("MLB150 low level driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/mxc/vpu/Kconfig linux-3.14.35/drivers/mxc/vpu/Kconfig
- --- linux-3.14.35.orig/drivers/mxc/vpu/Kconfig 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/vpu/Kconfig 2015-03-08 14:27:37.669684500 -0500
- @@ -0,0 +1,31 @@
- +#
- +# Codec configuration
- +#
- +
- +menu "MXC VPU(Video Processing Unit) support"
- +
- +config MXC_VPU
- + tristate "Support for MXC VPU(Video Processing Unit)"
- + depends on (SOC_IMX27 || SOC_IMX5 || SOC_IMX6Q)
- + default y
- + ---help---
- + The VPU codec device provides codec function for H.264/MPEG4/H.263,
- + as well as MPEG2/VC-1/DivX on some platforms.
- +
- +config MXC_VPU_DEBUG
- + bool "MXC VPU debugging"
- + depends on MXC_VPU != n
- + help
- + This is an option for the developers; most people should
- + say N here. This enables MXC VPU driver debugging.
- +
- +config MX6_VPU_352M
- + bool "MX6 VPU 352M"
- + depends on MXC_VPU
- + default n
- + help
- + Increase VPU frequncy to 352M, the config will disable bus frequency
- + adjust dynamic, and CPU lowest setpoint will be 352Mhz.
- + This config is used for special VPU use case.
- +
- +endmenu
- diff -Nur linux-3.14.35.orig/drivers/mxc/vpu/Makefile linux-3.14.35/drivers/mxc/vpu/Makefile
- --- linux-3.14.35.orig/drivers/mxc/vpu/Makefile 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/vpu/Makefile 2015-03-08 14:27:37.669684500 -0500
- @@ -0,0 +1,9 @@
- +#
- +# Makefile for the VPU drivers.
- +#
- +
- +obj-$(CONFIG_MXC_VPU) += mxc_vpu.o
- +
- +ifeq ($(CONFIG_MXC_VPU_DEBUG),y)
- +EXTRA_CFLAGS += -DDEBUG
- +endif
- diff -Nur linux-3.14.35.orig/drivers/mxc/vpu/mxc_vpu.c linux-3.14.35/drivers/mxc/vpu/mxc_vpu.c
- --- linux-3.14.35.orig/drivers/mxc/vpu/mxc_vpu.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/mxc/vpu/mxc_vpu.c 2015-03-08 14:27:37.669684500 -0500
- @@ -0,0 +1,1342 @@
- +/*
- + * Copyright 2006-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file mxc_vpu.c
- + *
- + * @brief VPU system initialization and file operation implementation
- + *
- + * @ingroup VPU
- + */
- +
- +#include <linux/kernel.h>
- +#include <linux/mm.h>
- +#include <linux/interrupt.h>
- +#include <linux/ioport.h>
- +#include <linux/stat.h>
- +#include <linux/platform_device.h>
- +#include <linux/kdev_t.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/wait.h>
- +#include <linux/list.h>
- +#include <linux/clk.h>
- +#include <linux/delay.h>
- +#include <linux/fsl_devices.h>
- +#include <linux/uaccess.h>
- +#include <linux/io.h>
- +#include <linux/slab.h>
- +#include <linux/workqueue.h>
- +#include <linux/sched.h>
- +#include <linux/vmalloc.h>
- +#include <linux/regulator/consumer.h>
- +#include <linux/page-flags.h>
- +#include <linux/mm_types.h>
- +#include <linux/types.h>
- +#include <linux/memblock.h>
- +#include <linux/memory.h>
- +#include <linux/version.h>
- +#include <asm/page.h>
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
- +#include <linux/module.h>
- +#include <linux/pm_runtime.h>
- +#include <linux/sizes.h>
- +#endif
- +
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
- +#include <linux/iram_alloc.h>
- +#include <mach/clock.h>
- +#include <mach/hardware.h>
- +#include <mach/mxc_vpu.h>
- +#endif
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
- +#include <linux/busfreq-imx6.h>
- +#include <linux/clk.h>
- +#include <linux/genalloc.h>
- +#include <linux/mxc_vpu.h>
- +#include <linux/of.h>
- +#include <linux/reset.h>
- +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
- +#include <mach/busfreq.h>
- +#include <mach/common.h>
- +#else
- +#include <asm/sizes.h>
- +#endif
- +
- +/* Define one new pgprot which combined uncached and XN(never executable) */
- +#define pgprot_noncachedxn(prot) \
- + __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED | L_PTE_XN)
- +
- +struct vpu_priv {
- + struct fasync_struct *async_queue;
- + struct work_struct work;
- + struct workqueue_struct *workqueue;
- + struct mutex lock;
- +};
- +
- +/* To track the allocated memory buffer */
- +struct memalloc_record {
- + struct list_head list;
- + struct vpu_mem_desc mem;
- +};
- +
- +struct iram_setting {
- + u32 start;
- + u32 end;
- +};
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
- +static struct gen_pool *iram_pool;
- +static u32 iram_base;
- +#endif
- +
- +static LIST_HEAD(head);
- +
- +static int vpu_major;
- +static int vpu_clk_usercount;
- +static struct class *vpu_class;
- +static struct vpu_priv vpu_data;
- +static u8 open_count;
- +static struct clk *vpu_clk;
- +static struct vpu_mem_desc bitwork_mem = { 0 };
- +static struct vpu_mem_desc pic_para_mem = { 0 };
- +static struct vpu_mem_desc user_data_mem = { 0 };
- +static struct vpu_mem_desc share_mem = { 0 };
- +static struct vpu_mem_desc vshare_mem = { 0 };
- +
- +static void __iomem *vpu_base;
- +static int vpu_ipi_irq;
- +static u32 phy_vpu_base_addr;
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
- +static phys_addr_t top_address_DRAM;
- +static struct mxc_vpu_platform_data *vpu_plat;
- +#endif
- +
- +static struct device *vpu_dev;
- +
- +/* IRAM setting */
- +static struct iram_setting iram;
- +
- +/* implement the blocking ioctl */
- +static int irq_status;
- +static int codec_done;
- +static wait_queue_head_t vpu_queue;
- +
- +#ifdef CONFIG_SOC_IMX6Q
- +#define MXC_VPU_HAS_JPU
- +#endif
- +
- +#ifdef MXC_VPU_HAS_JPU
- +static int vpu_jpu_irq;
- +#endif
- +
- +#ifdef CONFIG_PM
- +static unsigned int regBk[64];
- +static unsigned int pc_before_suspend;
- +#endif
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
- +static struct regulator *vpu_regulator;
- +#endif
- +static atomic_t clk_cnt_from_ioc = ATOMIC_INIT(0);
- +
- +#define READ_REG(x) readl_relaxed(vpu_base + x)
- +#define WRITE_REG(val, x) writel_relaxed(val, vpu_base + x)
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
- +/* redirect to static functions */
- +static int cpu_is_mx6dl(void)
- +{
- + int ret;
- + ret = of_machine_is_compatible("fsl,imx6dl");
- + return ret;
- +}
- +
- +static int cpu_is_mx6q(void)
- +{
- + int ret;
- + ret = of_machine_is_compatible("fsl,imx6q");
- + return ret;
- +}
- +#endif
- +
- +static void vpu_reset(void)
- +{
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
- + device_reset(vpu_dev);
- +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
- + imx_src_reset_vpu();
- +#else
- + if (vpu_plat->reset)
- + vpu_plat->reset();
- +#endif
- +}
- +
- +static long vpu_power_get(bool on)
- +{
- + long ret = 0;
- +
- + if (on) {
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
- + vpu_regulator = regulator_get(NULL, "cpu_vddvpu");
- + ret = IS_ERR(vpu_regulator);
- +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
- + vpu_regulator = devm_regulator_get(vpu_dev, "pu");
- + ret = IS_ERR(vpu_regulator);
- +#endif
- + } else {
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
- + if (!IS_ERR(vpu_regulator))
- + regulator_put(vpu_regulator);
- +#endif
- + }
- + return ret;
- +}
- +
- +static void vpu_power_up(bool on)
- +{
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
- + int ret = 0;
- +
- + if (on) {
- + if (!IS_ERR(vpu_regulator)) {
- + ret = regulator_enable(vpu_regulator);
- + if (ret)
- + dev_err(vpu_dev, "failed to power up vpu\n");
- + }
- + } else {
- + if (!IS_ERR(vpu_regulator)) {
- + ret = regulator_disable(vpu_regulator);
- + if (ret)
- + dev_err(vpu_dev, "failed to power down vpu\n");
- + }
- + }
- +#else
- + imx_gpc_power_up_pu(on);
- +#endif
- +}
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
- +static int cpu_is_mx53(void)
- +{
- + return 0;
- +}
- +
- +static int cpu_is_mx51(void)
- +{
- + return 0;
- +}
- +
- +#define VM_RESERVED 0
- +#endif
- +
- +/*!
- + * Private function to alloc dma buffer
- + * @return status 0 success.
- + */
- +static int vpu_alloc_dma_buffer(struct vpu_mem_desc *mem)
- +{
- + mem->cpu_addr = (unsigned long)
- + dma_alloc_coherent(NULL, PAGE_ALIGN(mem->size),
- + (dma_addr_t *) (&mem->phy_addr),
- + GFP_DMA | GFP_KERNEL);
- + dev_dbg(vpu_dev, "[ALLOC] mem alloc cpu_addr = 0x%x\n", mem->cpu_addr);
- + if ((void *)(mem->cpu_addr) == NULL) {
- + dev_err(vpu_dev, "Physical memory allocation error!\n");
- + return -1;
- + }
- + return 0;
- +}
- +
- +/*!
- + * Private function to free dma buffer
- + */
- +static void vpu_free_dma_buffer(struct vpu_mem_desc *mem)
- +{
- + if (mem->cpu_addr != 0) {
- + dma_free_coherent(0, PAGE_ALIGN(mem->size),
- + (void *)mem->cpu_addr, mem->phy_addr);
- + }
- +}
- +
- +/*!
- + * Private function to free buffers
- + * @return status 0 success.
- + */
- +static int vpu_free_buffers(void)
- +{
- + struct memalloc_record *rec, *n;
- + struct vpu_mem_desc mem;
- +
- + list_for_each_entry_safe(rec, n, &head, list) {
- + mem = rec->mem;
- + if (mem.cpu_addr != 0) {
- + vpu_free_dma_buffer(&mem);
- + dev_dbg(vpu_dev, "[FREE] freed paddr=0x%08X\n", mem.phy_addr);
- + /* delete from list */
- + list_del(&rec->list);
- + kfree(rec);
- + }
- + }
- +
- + return 0;
- +}
- +
- +static inline void vpu_worker_callback(struct work_struct *w)
- +{
- + struct vpu_priv *dev = container_of(w, struct vpu_priv,
- + work);
- +
- + if (dev->async_queue)
- + kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
- +
- + irq_status = 1;
- + /*
- + * Clock is gated on when dec/enc started, gate it off when
- + * codec is done.
- + */
- + if (codec_done)
- + codec_done = 0;
- +
- + wake_up_interruptible(&vpu_queue);
- +}
- +
- +/*!
- + * @brief vpu interrupt handler
- + */
- +static irqreturn_t vpu_ipi_irq_handler(int irq, void *dev_id)
- +{
- + struct vpu_priv *dev = dev_id;
- + unsigned long reg;
- +
- + reg = READ_REG(BIT_INT_REASON);
- + if (reg & 0x8)
- + codec_done = 1;
- + WRITE_REG(0x1, BIT_INT_CLEAR);
- +
- + queue_work(dev->workqueue, &dev->work);
- +
- + return IRQ_HANDLED;
- +}
- +
- +/*!
- + * @brief vpu jpu interrupt handler
- + */
- +#ifdef MXC_VPU_HAS_JPU
- +static irqreturn_t vpu_jpu_irq_handler(int irq, void *dev_id)
- +{
- + struct vpu_priv *dev = dev_id;
- + unsigned long reg;
- +
- + reg = READ_REG(MJPEG_PIC_STATUS_REG);
- + if (reg & 0x3)
- + codec_done = 1;
- +
- + queue_work(dev->workqueue, &dev->work);
- +
- + return IRQ_HANDLED;
- +}
- +#endif
- +
- +/*!
- + * @brief check phy memory prepare to pass to vpu is valid or not, we
- + * already address some issue that if pass a wrong address to vpu
- + * (like virtual address), system will hang.
- + *
- + * @return true return is a valid phy memory address, false return not.
- + */
- +bool vpu_is_valid_phy_memory(u32 paddr)
- +{
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
- + if (paddr > top_address_DRAM)
- + return false;
- +#endif
- +
- + return true;
- +}
- +
- +/*!
- + * @brief open function for vpu file operation
- + *
- + * @return 0 on success or negative error code on error
- + */
- +static int vpu_open(struct inode *inode, struct file *filp)
- +{
- +
- + mutex_lock(&vpu_data.lock);
- +
- + if (open_count++ == 0) {
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
- + pm_runtime_get_sync(vpu_dev);
- +#endif
- + vpu_power_up(true);
- +
- +#ifdef CONFIG_SOC_IMX6Q
- + clk_prepare(vpu_clk);
- + clk_enable(vpu_clk);
- + if (READ_REG(BIT_CUR_PC))
- + dev_dbg(vpu_dev, "Not power off before vpu open!\n");
- + clk_disable(vpu_clk);
- + clk_unprepare(vpu_clk);
- +#endif
- + }
- +
- + filp->private_data = (void *)(&vpu_data);
- + mutex_unlock(&vpu_data.lock);
- + return 0;
- +}
- +
- +/*!
- + * @brief IO ctrl function for vpu file operation
- + * @param cmd IO ctrl command
- + * @return 0 on success or negative error code on error
- + */
- +static long vpu_ioctl(struct file *filp, u_int cmd,
- + u_long arg)
- +{
- + int ret = 0;
- +
- + switch (cmd) {
- + case VPU_IOC_PHYMEM_ALLOC:
- + {
- + struct memalloc_record *rec;
- +
- + rec = kzalloc(sizeof(*rec), GFP_KERNEL);
- + if (!rec)
- + return -ENOMEM;
- +
- + ret = copy_from_user(&(rec->mem),
- + (struct vpu_mem_desc *)arg,
- + sizeof(struct vpu_mem_desc));
- + if (ret) {
- + kfree(rec);
- + return -EFAULT;
- + }
- +
- + dev_dbg(vpu_dev, "[ALLOC] mem alloc size = 0x%x\n",
- + rec->mem.size);
- +
- + ret = vpu_alloc_dma_buffer(&(rec->mem));
- + if (ret == -1) {
- + kfree(rec);
- + dev_err(vpu_dev,
- + "Physical memory allocation error!\n");
- + break;
- + }
- + ret = copy_to_user((void __user *)arg, &(rec->mem),
- + sizeof(struct vpu_mem_desc));
- + if (ret) {
- + kfree(rec);
- + ret = -EFAULT;
- + break;
- + }
- +
- + mutex_lock(&vpu_data.lock);
- + list_add(&rec->list, &head);
- + mutex_unlock(&vpu_data.lock);
- +
- + break;
- + }
- + case VPU_IOC_PHYMEM_FREE:
- + {
- + struct memalloc_record *rec, *n;
- + struct vpu_mem_desc vpu_mem;
- +
- + ret = copy_from_user(&vpu_mem,
- + (struct vpu_mem_desc *)arg,
- + sizeof(struct vpu_mem_desc));
- + if (ret)
- + return -EACCES;
- +
- + dev_dbg(vpu_dev, "[FREE] mem freed cpu_addr = 0x%x\n",
- + vpu_mem.cpu_addr);
- + if ((void *)vpu_mem.cpu_addr != NULL)
- + vpu_free_dma_buffer(&vpu_mem);
- +
- + mutex_lock(&vpu_data.lock);
- + list_for_each_entry_safe(rec, n, &head, list) {
- + if (rec->mem.cpu_addr == vpu_mem.cpu_addr) {
- + /* delete from list */
- + list_del(&rec->list);
- + kfree(rec);
- + break;
- + }
- + }
- + mutex_unlock(&vpu_data.lock);
- +
- + break;
- + }
- + case VPU_IOC_WAIT4INT:
- + {
- + u_long timeout = (u_long) arg;
- + if (!wait_event_interruptible_timeout
- + (vpu_queue, irq_status != 0,
- + msecs_to_jiffies(timeout))) {
- + dev_warn(vpu_dev, "VPU blocking: timeout.\n");
- + ret = -ETIME;
- + } else if (signal_pending(current)) {
- + dev_warn(vpu_dev, "VPU interrupt received.\n");
- + ret = -ERESTARTSYS;
- + } else
- + irq_status = 0;
- + break;
- + }
- + case VPU_IOC_IRAM_SETTING:
- + {
- + ret = copy_to_user((void __user *)arg, &iram,
- + sizeof(struct iram_setting));
- + if (ret)
- + ret = -EFAULT;
- +
- + break;
- + }
- + case VPU_IOC_CLKGATE_SETTING:
- + {
- + u32 clkgate_en;
- +
- + if (get_user(clkgate_en, (u32 __user *) arg))
- + return -EFAULT;
- +
- + if (clkgate_en) {
- + clk_prepare(vpu_clk);
- + clk_enable(vpu_clk);
- + atomic_inc(&clk_cnt_from_ioc);
- + } else {
- + clk_disable(vpu_clk);
- + clk_unprepare(vpu_clk);
- + atomic_dec(&clk_cnt_from_ioc);
- + }
- +
- + break;
- + }
- + case VPU_IOC_GET_SHARE_MEM:
- + {
- + mutex_lock(&vpu_data.lock);
- + if (share_mem.cpu_addr != 0) {
- + ret = copy_to_user((void __user *)arg,
- + &share_mem,
- + sizeof(struct vpu_mem_desc));
- + mutex_unlock(&vpu_data.lock);
- + break;
- + } else {
- + if (copy_from_user(&share_mem,
- + (struct vpu_mem_desc *)arg,
- + sizeof(struct vpu_mem_desc))) {
- + mutex_unlock(&vpu_data.lock);
- + return -EFAULT;
- + }
- + if (vpu_alloc_dma_buffer(&share_mem) == -1)
- + ret = -EFAULT;
- + else {
- + if (copy_to_user((void __user *)arg,
- + &share_mem,
- + sizeof(struct
- + vpu_mem_desc)))
- + ret = -EFAULT;
- + }
- + }
- + mutex_unlock(&vpu_data.lock);
- + break;
- + }
- + case VPU_IOC_REQ_VSHARE_MEM:
- + {
- + mutex_lock(&vpu_data.lock);
- + if (vshare_mem.cpu_addr != 0) {
- + ret = copy_to_user((void __user *)arg,
- + &vshare_mem,
- + sizeof(struct vpu_mem_desc));
- + mutex_unlock(&vpu_data.lock);
- + break;
- + } else {
- + if (copy_from_user(&vshare_mem,
- + (struct vpu_mem_desc *)arg,
- + sizeof(struct
- + vpu_mem_desc))) {
- + mutex_unlock(&vpu_data.lock);
- + return -EFAULT;
- + }
- + /* vmalloc shared memory if not allocated */
- + if (!vshare_mem.cpu_addr)
- + vshare_mem.cpu_addr =
- + (unsigned long)
- + vmalloc_user(vshare_mem.size);
- + if (copy_to_user
- + ((void __user *)arg, &vshare_mem,
- + sizeof(struct vpu_mem_desc)))
- + ret = -EFAULT;
- + }
- + mutex_unlock(&vpu_data.lock);
- + break;
- + }
- + case VPU_IOC_GET_WORK_ADDR:
- + {
- + if (bitwork_mem.cpu_addr != 0) {
- + ret =
- + copy_to_user((void __user *)arg,
- + &bitwork_mem,
- + sizeof(struct vpu_mem_desc));
- + break;
- + } else {
- + if (copy_from_user(&bitwork_mem,
- + (struct vpu_mem_desc *)arg,
- + sizeof(struct vpu_mem_desc)))
- + return -EFAULT;
- +
- + if (vpu_alloc_dma_buffer(&bitwork_mem) == -1)
- + ret = -EFAULT;
- + else if (copy_to_user((void __user *)arg,
- + &bitwork_mem,
- + sizeof(struct
- + vpu_mem_desc)))
- + ret = -EFAULT;
- + }
- + break;
- + }
- + /*
- + * The following two ioctl is used when user allocates working buffer
- + * and register it to vpu driver.
- + */
- + case VPU_IOC_QUERY_BITWORK_MEM:
- + {
- + if (copy_to_user((void __user *)arg,
- + &bitwork_mem,
- + sizeof(struct vpu_mem_desc)))
- + ret = -EFAULT;
- + break;
- + }
- + case VPU_IOC_SET_BITWORK_MEM:
- + {
- + if (copy_from_user(&bitwork_mem,
- + (struct vpu_mem_desc *)arg,
- + sizeof(struct vpu_mem_desc)))
- + ret = -EFAULT;
- + break;
- + }
- + case VPU_IOC_SYS_SW_RESET:
- + {
- + vpu_reset();
- + break;
- + }
- + case VPU_IOC_REG_DUMP:
- + break;
- + case VPU_IOC_PHYMEM_DUMP:
- + break;
- + case VPU_IOC_PHYMEM_CHECK:
- + {
- + struct vpu_mem_desc check_memory;
- + ret = copy_from_user(&check_memory,
- + (void __user *)arg,
- + sizeof(struct vpu_mem_desc));
- + if (ret != 0) {
- + dev_err(vpu_dev, "copy from user failure:%d\n", ret);
- + ret = -EFAULT;
- + break;
- + }
- + ret = vpu_is_valid_phy_memory((u32)check_memory.phy_addr);
- +
- + dev_dbg(vpu_dev, "vpu: memory phy:0x%x %s phy memory\n",
- + check_memory.phy_addr, (ret ? "is" : "isn't"));
- + /* borrow .size to pass back the result. */
- + check_memory.size = ret;
- + ret = copy_to_user((void __user *)arg, &check_memory,
- + sizeof(struct vpu_mem_desc));
- + if (ret) {
- + ret = -EFAULT;
- + break;
- + }
- + break;
- + }
- + case VPU_IOC_LOCK_DEV:
- + {
- + u32 lock_en;
- +
- + if (get_user(lock_en, (u32 __user *) arg))
- + return -EFAULT;
- +
- + if (lock_en)
- + mutex_lock(&vpu_data.lock);
- + else
- + mutex_unlock(&vpu_data.lock);
- +
- + break;
- + }
- + default:
- + {
- + dev_err(vpu_dev, "No such IOCTL, cmd is %d\n", cmd);
- + ret = -EINVAL;
- + break;
- + }
- + }
- + return ret;
- +}
- +
- +/*!
- + * @brief Release function for vpu file operation
- + * @return 0 on success or negative error code on error
- + */
- +static int vpu_release(struct inode *inode, struct file *filp)
- +{
- + int i;
- + unsigned long timeout;
- +
- + mutex_lock(&vpu_data.lock);
- +
- + if (open_count > 0 && !(--open_count)) {
- +
- + /* Wait for vpu go to idle state */
- + clk_prepare(vpu_clk);
- + clk_enable(vpu_clk);
- + if (READ_REG(BIT_CUR_PC)) {
- +
- + timeout = jiffies + HZ;
- + while (READ_REG(BIT_BUSY_FLAG)) {
- + msleep(1);
- + if (time_after(jiffies, timeout)) {
- + dev_warn(vpu_dev, "VPU timeout during release\n");
- + break;
- + }
- + }
- + clk_disable(vpu_clk);
- + clk_unprepare(vpu_clk);
- +
- + /* Clean up interrupt */
- + cancel_work_sync(&vpu_data.work);
- + flush_workqueue(vpu_data.workqueue);
- + irq_status = 0;
- +
- + clk_prepare(vpu_clk);
- + clk_enable(vpu_clk);
- + if (READ_REG(BIT_BUSY_FLAG)) {
- +
- + if (cpu_is_mx51() || cpu_is_mx53()) {
- + dev_err(vpu_dev,
- + "fatal error: can't gate/power off when VPU is busy\n");
- + clk_disable(vpu_clk);
- + clk_unprepare(vpu_clk);
- + mutex_unlock(&vpu_data.lock);
- + return -EFAULT;
- + }
- +
- +#ifdef CONFIG_SOC_IMX6Q
- + if (cpu_is_mx6dl() || cpu_is_mx6q()) {
- + WRITE_REG(0x11, 0x10F0);
- + timeout = jiffies + HZ;
- + while (READ_REG(0x10F4) != 0x77) {
- + msleep(1);
- + if (time_after(jiffies, timeout))
- + break;
- + }
- +
- + if (READ_REG(0x10F4) != 0x77) {
- + dev_err(vpu_dev,
- + "fatal error: can't gate/power off when VPU is busy\n");
- + WRITE_REG(0x0, 0x10F0);
- + clk_disable(vpu_clk);
- + clk_unprepare(vpu_clk);
- + mutex_unlock(&vpu_data.lock);
- + return -EFAULT;
- + } else
- + vpu_reset();
- + }
- +#endif
- + }
- + }
- + clk_disable(vpu_clk);
- + clk_unprepare(vpu_clk);
- +
- + vpu_free_buffers();
- +
- + /* Free shared memory when vpu device is idle */
- + vpu_free_dma_buffer(&share_mem);
- + share_mem.cpu_addr = 0;
- + vfree((void *)vshare_mem.cpu_addr);
- + vshare_mem.cpu_addr = 0;
- +
- + vpu_clk_usercount = atomic_read(&clk_cnt_from_ioc);
- + for (i = 0; i < vpu_clk_usercount; i++) {
- + clk_disable(vpu_clk);
- + clk_unprepare(vpu_clk);
- + atomic_dec(&clk_cnt_from_ioc);
- + }
- +
- + vpu_power_up(false);
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
- + pm_runtime_put_sync_suspend(vpu_dev);
- +#endif
- +
- + }
- + mutex_unlock(&vpu_data.lock);
- +
- + return 0;
- +}
- +
- +/*!
- + * @brief fasync function for vpu file operation
- + * @return 0 on success or negative error code on error
- + */
- +static int vpu_fasync(int fd, struct file *filp, int mode)
- +{
- + struct vpu_priv *dev = (struct vpu_priv *)filp->private_data;
- + return fasync_helper(fd, filp, mode, &dev->async_queue);
- +}
- +
- +/*!
- + * @brief memory map function of harware registers for vpu file operation
- + * @return 0 on success or negative error code on error
- + */
- +static int vpu_map_hwregs(struct file *fp, struct vm_area_struct *vm)
- +{
- + unsigned long pfn;
- +
- + vm->vm_flags |= VM_IO | VM_RESERVED;
- + /*
- + * Since vpu registers have been mapped with ioremap() at probe
- + * which L_PTE_XN is 1, and the same physical address must be
- + * mapped multiple times with same type, so set L_PTE_XN to 1 here.
- + * Otherwise, there may be unexpected result in video codec.
- + */
- + vm->vm_page_prot = pgprot_noncachedxn(vm->vm_page_prot);
- + pfn = phy_vpu_base_addr >> PAGE_SHIFT;
- + dev_dbg(vpu_dev, "size=0x%x, page no.=0x%x\n",
- + (int)(vm->vm_end - vm->vm_start), (int)pfn);
- + return remap_pfn_range(vm, vm->vm_start, pfn, vm->vm_end - vm->vm_start,
- + vm->vm_page_prot) ? -EAGAIN : 0;
- +}
- +
- +/*!
- + * @brief memory map function of memory for vpu file operation
- + * @return 0 on success or negative error code on error
- + */
- +static int vpu_map_dma_mem(struct file *fp, struct vm_area_struct *vm)
- +{
- + int request_size;
- + request_size = vm->vm_end - vm->vm_start;
- +
- + dev_dbg(vpu_dev, "start=0x%x, pgoff=0x%x, size=0x%x\n",
- + (unsigned int)(vm->vm_start), (unsigned int)(vm->vm_pgoff),
- + request_size);
- +
- + vm->vm_flags |= VM_IO | VM_RESERVED;
- + vm->vm_page_prot = pgprot_writecombine(vm->vm_page_prot);
- +
- + return remap_pfn_range(vm, vm->vm_start, vm->vm_pgoff,
- + request_size, vm->vm_page_prot) ? -EAGAIN : 0;
- +
- +}
- +
- +/* !
- + * @brief memory map function of vmalloced share memory
- + * @return 0 on success or negative error code on error
- + */
- +static int vpu_map_vshare_mem(struct file *fp, struct vm_area_struct *vm)
- +{
- + int ret = -EINVAL;
- +
- + ret = remap_vmalloc_range(vm, (void *)(vm->vm_pgoff << PAGE_SHIFT), 0);
- + vm->vm_flags |= VM_IO;
- +
- + return ret;
- +}
- +/*!
- + * @brief memory map interface for vpu file operation
- + * @return 0 on success or negative error code on error
- + */
- +static int vpu_mmap(struct file *fp, struct vm_area_struct *vm)
- +{
- + unsigned long offset;
- +
- + offset = vshare_mem.cpu_addr >> PAGE_SHIFT;
- +
- + if (vm->vm_pgoff && (vm->vm_pgoff == offset))
- + return vpu_map_vshare_mem(fp, vm);
- + else if (vm->vm_pgoff)
- + return vpu_map_dma_mem(fp, vm);
- + else
- + return vpu_map_hwregs(fp, vm);
- +}
- +
- +const struct file_operations vpu_fops = {
- + .owner = THIS_MODULE,
- + .open = vpu_open,
- + .unlocked_ioctl = vpu_ioctl,
- + .release = vpu_release,
- + .fasync = vpu_fasync,
- + .mmap = vpu_mmap,
- +};
- +
- +/*!
- + * This function is called by the driver framework to initialize the vpu device.
- + * @param dev The device structure for the vpu passed in by the framework.
- + * @return 0 on success or negative error code on error
- + */
- +static int vpu_dev_probe(struct platform_device *pdev)
- +{
- + int err = 0;
- + struct device *temp_class;
- + struct resource *res;
- + unsigned long addr = 0;
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
- + struct device_node *np = pdev->dev.of_node;
- + u32 iramsize;
- +
- + err = of_property_read_u32(np, "iramsize", (u32 *)&iramsize);
- + if (!err && iramsize)
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
- + {
- + iram_pool = of_get_named_gen_pool(np, "iram", 0);
- + if (!iram_pool) {
- + dev_err(&pdev->dev, "iram pool not available\n");
- + return -ENOMEM;
- + }
- +
- + iram_base = gen_pool_alloc(iram_pool, iramsize);
- + if (!iram_base) {
- + dev_err(&pdev->dev, "unable to alloc iram\n");
- + return -ENOMEM;
- + }
- +
- + addr = gen_pool_virt_to_phys(iram_pool, iram_base);
- + }
- +#else
- + iram_alloc(iramsize, &addr);
- +#endif
- + if (addr == 0)
- + iram.start = iram.end = 0;
- + else {
- + iram.start = addr;
- + iram.end = addr + iramsize - 1;
- + }
- +#else
- +
- + vpu_plat = pdev->dev.platform_data;
- +
- + if (vpu_plat && vpu_plat->iram_enable && vpu_plat->iram_size)
- + iram_alloc(vpu_plat->iram_size, &addr);
- + if (addr == 0)
- + iram.start = iram.end = 0;
- + else {
- + iram.start = addr;
- + iram.end = addr + vpu_plat->iram_size - 1;
- + }
- +#endif
- +
- + vpu_dev = &pdev->dev;
- +
- + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpu_regs");
- + if (!res) {
- + dev_err(vpu_dev, "vpu: unable to get vpu base addr\n");
- + return -ENODEV;
- + }
- + phy_vpu_base_addr = res->start;
- + vpu_base = ioremap(res->start, res->end - res->start);
- +
- + vpu_major = register_chrdev(vpu_major, "mxc_vpu", &vpu_fops);
- + if (vpu_major < 0) {
- + dev_err(vpu_dev, "vpu: unable to get a major for VPU\n");
- + err = -EBUSY;
- + goto error;
- + }
- +
- + vpu_class = class_create(THIS_MODULE, "mxc_vpu");
- + if (IS_ERR(vpu_class)) {
- + err = PTR_ERR(vpu_class);
- + goto err_out_chrdev;
- + }
- +
- + temp_class = device_create(vpu_class, NULL, MKDEV(vpu_major, 0),
- + NULL, "mxc_vpu");
- + if (IS_ERR(temp_class)) {
- + err = PTR_ERR(temp_class);
- + goto err_out_class;
- + }
- +
- + vpu_clk = clk_get(&pdev->dev, "vpu_clk");
- + if (IS_ERR(vpu_clk)) {
- + err = -ENOENT;
- + goto err_out_class;
- + }
- +
- + vpu_ipi_irq = platform_get_irq_byname(pdev, "vpu_ipi_irq");
- + if (vpu_ipi_irq < 0) {
- + dev_err(vpu_dev, "vpu: unable to get vpu interrupt\n");
- + err = -ENXIO;
- + goto err_out_class;
- + }
- + err = request_irq(vpu_ipi_irq, vpu_ipi_irq_handler, 0, "VPU_CODEC_IRQ",
- + (void *)(&vpu_data));
- + if (err)
- + goto err_out_class;
- + if (vpu_power_get(true)) {
- + if (!(cpu_is_mx51() || cpu_is_mx53())) {
- + dev_err(vpu_dev, "failed to get vpu power\n");
- + goto err_out_class;
- + } else {
- + /* regulator_get will return error on MX5x,
- + * just igore it everywhere*/
- + dev_warn(vpu_dev, "failed to get vpu power\n");
- + }
- + }
- +
- +#ifdef MXC_VPU_HAS_JPU
- + vpu_jpu_irq = platform_get_irq_byname(pdev, "vpu_jpu_irq");
- + if (vpu_jpu_irq < 0) {
- + dev_err(vpu_dev, "vpu: unable to get vpu jpu interrupt\n");
- + err = -ENXIO;
- + free_irq(vpu_ipi_irq, &vpu_data);
- + goto err_out_class;
- + }
- + err = request_irq(vpu_jpu_irq, vpu_jpu_irq_handler, IRQF_TRIGGER_RISING,
- + "VPU_JPG_IRQ", (void *)(&vpu_data));
- + if (err) {
- + free_irq(vpu_ipi_irq, &vpu_data);
- + goto err_out_class;
- + }
- +#endif
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
- + pm_runtime_enable(&pdev->dev);
- +#endif
- +
- + vpu_data.workqueue = create_workqueue("vpu_wq");
- + INIT_WORK(&vpu_data.work, vpu_worker_callback);
- + mutex_init(&vpu_data.lock);
- + dev_info(vpu_dev, "VPU initialized\n");
- + goto out;
- +
- +err_out_class:
- + device_destroy(vpu_class, MKDEV(vpu_major, 0));
- + class_destroy(vpu_class);
- +err_out_chrdev:
- + unregister_chrdev(vpu_major, "mxc_vpu");
- +error:
- + iounmap(vpu_base);
- +out:
- + return err;
- +}
- +
- +static int vpu_dev_remove(struct platform_device *pdev)
- +{
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
- + pm_runtime_disable(&pdev->dev);
- +#endif
- + free_irq(vpu_ipi_irq, &vpu_data);
- +#ifdef MXC_VPU_HAS_JPU
- + free_irq(vpu_jpu_irq, &vpu_data);
- +#endif
- + cancel_work_sync(&vpu_data.work);
- + flush_workqueue(vpu_data.workqueue);
- + destroy_workqueue(vpu_data.workqueue);
- +
- + iounmap(vpu_base);
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
- + if (iram.start)
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
- + gen_pool_free(iram_pool, iram_base, iram.end-iram.start+1);
- +#else
- + iram_free(iram.start, iram.end-iram.start+1);
- +#endif
- +#else
- + if (vpu_plat && vpu_plat->iram_enable && vpu_plat->iram_size)
- + iram_free(iram.start, vpu_plat->iram_size);
- +#endif
- +
- + vpu_power_get(false);
- + return 0;
- +}
- +
- +#ifdef CONFIG_PM
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
- +static int vpu_suspend(struct device *dev)
- +#else
- +static int vpu_suspend(struct platform_device *pdev, pm_message_t state)
- +#endif
- +{
- + int i;
- + unsigned long timeout;
- +
- + mutex_lock(&vpu_data.lock);
- + if (open_count == 0) {
- + /* VPU is released (all instances are freed),
- + * clock is already off, context is no longer needed,
- + * power is already off on MX6,
- + * gate power on MX51 */
- + if (cpu_is_mx51()) {
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
- + if (vpu_plat->pg)
- + vpu_plat->pg(1);
- +#endif
- + }
- + } else {
- + /* Wait for vpu go to idle state, suspect vpu cannot be changed
- + to idle state after about 1 sec */
- + timeout = jiffies + HZ;
- + clk_prepare(vpu_clk);
- + clk_enable(vpu_clk);
- + while (READ_REG(BIT_BUSY_FLAG)) {
- + msleep(1);
- + if (time_after(jiffies, timeout)) {
- + clk_disable(vpu_clk);
- + clk_unprepare(vpu_clk);
- + mutex_unlock(&vpu_data.lock);
- + return -EAGAIN;
- + }
- + }
- + clk_disable(vpu_clk);
- + clk_unprepare(vpu_clk);
- +
- + /* Make sure clock is disabled before suspend */
- + vpu_clk_usercount = atomic_read(&clk_cnt_from_ioc);
- + for (i = 0; i < vpu_clk_usercount; i++) {
- + clk_disable(vpu_clk);
- + clk_unprepare(vpu_clk);
- + }
- +
- + if (cpu_is_mx53()) {
- + mutex_unlock(&vpu_data.lock);
- + return 0;
- + }
- +
- + if (bitwork_mem.cpu_addr != 0) {
- + clk_prepare(vpu_clk);
- + clk_enable(vpu_clk);
- + /* Save 64 registers from BIT_CODE_BUF_ADDR */
- + for (i = 0; i < 64; i++)
- + regBk[i] = READ_REG(BIT_CODE_BUF_ADDR + (i * 4));
- + pc_before_suspend = READ_REG(BIT_CUR_PC);
- + clk_disable(vpu_clk);
- + clk_unprepare(vpu_clk);
- + }
- +
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
- + if (vpu_plat->pg)
- + vpu_plat->pg(1);
- +#endif
- +
- + /* If VPU is working before suspend, disable
- + * regulator to make usecount right. */
- + vpu_power_up(false);
- + }
- +
- + mutex_unlock(&vpu_data.lock);
- + return 0;
- +}
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
- +static int vpu_resume(struct device *dev)
- +#else
- +static int vpu_resume(struct platform_device *pdev)
- +#endif
- +{
- + int i;
- +
- + mutex_lock(&vpu_data.lock);
- + if (open_count == 0) {
- + /* VPU is released (all instances are freed),
- + * clock should be kept off, context is no longer needed,
- + * power should be kept off on MX6,
- + * disable power gating on MX51 */
- + if (cpu_is_mx51()) {
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
- + if (vpu_plat->pg)
- + vpu_plat->pg(0);
- +#endif
- + }
- + } else {
- + if (cpu_is_mx53())
- + goto recover_clk;
- +
- + /* If VPU is working before suspend, enable
- + * regulator to make usecount right. */
- + vpu_power_up(true);
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
- + if (vpu_plat->pg)
- + vpu_plat->pg(0);
- +#endif
- +
- + if (bitwork_mem.cpu_addr != 0) {
- + u32 *p = (u32 *) bitwork_mem.cpu_addr;
- + u32 data, pc;
- + u16 data_hi;
- + u16 data_lo;
- +
- + clk_prepare(vpu_clk);
- + clk_enable(vpu_clk);
- +
- + pc = READ_REG(BIT_CUR_PC);
- + if (pc) {
- + dev_warn(vpu_dev, "Not power off after suspend (PC=0x%x)\n", pc);
- + clk_disable(vpu_clk);
- + clk_unprepare(vpu_clk);
- + goto recover_clk;
- + }
- +
- + /* Restore registers */
- + for (i = 0; i < 64; i++)
- + WRITE_REG(regBk[i], BIT_CODE_BUF_ADDR + (i * 4));
- +
- + WRITE_REG(0x0, BIT_RESET_CTRL);
- + WRITE_REG(0x0, BIT_CODE_RUN);
- + /* MX6 RTL has a bug not to init MBC_SET_SUBBLK_EN on reset */
- +#ifdef CONFIG_SOC_IMX6Q
- + WRITE_REG(0x0, MBC_SET_SUBBLK_EN);
- +#endif
- +
- + /*
- + * Re-load boot code, from the codebuffer in external RAM.
- + * Thankfully, we only need 4096 bytes, same for all platforms.
- + */
- + for (i = 0; i < 2048; i += 4) {
- + data = p[(i / 2) + 1];
- + data_hi = (data >> 16) & 0xFFFF;
- + data_lo = data & 0xFFFF;
- + WRITE_REG((i << 16) | data_hi, BIT_CODE_DOWN);
- + WRITE_REG(((i + 1) << 16) | data_lo,
- + BIT_CODE_DOWN);
- +
- + data = p[i / 2];
- + data_hi = (data >> 16) & 0xFFFF;
- + data_lo = data & 0xFFFF;
- + WRITE_REG(((i + 2) << 16) | data_hi,
- + BIT_CODE_DOWN);
- + WRITE_REG(((i + 3) << 16) | data_lo,
- + BIT_CODE_DOWN);
- + }
- +
- + if (pc_before_suspend) {
- + WRITE_REG(0x1, BIT_BUSY_FLAG);
- + WRITE_REG(0x1, BIT_CODE_RUN);
- + while (READ_REG(BIT_BUSY_FLAG))
- + ;
- + } else {
- + dev_warn(vpu_dev, "PC=0 before suspend\n");
- + }
- + clk_disable(vpu_clk);
- + clk_unprepare(vpu_clk);
- + }
- +
- +recover_clk:
- + /* Recover vpu clock */
- + for (i = 0; i < vpu_clk_usercount; i++) {
- + clk_prepare(vpu_clk);
- + clk_enable(vpu_clk);
- + }
- + }
- +
- + mutex_unlock(&vpu_data.lock);
- + return 0;
- +}
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
- +static int vpu_runtime_suspend(struct device *dev)
- +{
- + release_bus_freq(BUS_FREQ_HIGH);
- + return 0;
- +}
- +
- +static int vpu_runtime_resume(struct device *dev)
- +{
- + request_bus_freq(BUS_FREQ_HIGH);
- + return 0;
- +}
- +
- +static const struct dev_pm_ops vpu_pm_ops = {
- + SET_RUNTIME_PM_OPS(vpu_runtime_suspend, vpu_runtime_resume, NULL)
- + SET_SYSTEM_SLEEP_PM_OPS(vpu_suspend, vpu_resume)
- +};
- +#endif
- +
- +#else
- +#define vpu_suspend NULL
- +#define vpu_resume NULL
- +#endif /* !CONFIG_PM */
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
- +static const struct of_device_id vpu_of_match[] = {
- + { .compatible = "fsl,imx6-vpu", },
- + {/* sentinel */}
- +};
- +MODULE_DEVICE_TABLE(of, vpu_of_match);
- +#endif
- +
- +/*! Driver definition
- + *
- + */
- +static struct platform_driver mxcvpu_driver = {
- + .driver = {
- + .name = "mxc_vpu",
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
- + .of_match_table = vpu_of_match,
- +#ifdef CONFIG_PM
- + .pm = &vpu_pm_ops,
- +#endif
- +#endif
- + },
- + .probe = vpu_dev_probe,
- + .remove = vpu_dev_remove,
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
- + .suspend = vpu_suspend,
- + .resume = vpu_resume,
- +#endif
- +};
- +
- +static int __init vpu_init(void)
- +{
- + int ret = platform_driver_register(&mxcvpu_driver);
- +
- + init_waitqueue_head(&vpu_queue);
- +
- +
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
- + memblock_analyze();
- + top_address_DRAM = memblock_end_of_DRAM_with_reserved();
- +#endif
- +
- + return ret;
- +}
- +
- +static void __exit vpu_exit(void)
- +{
- + if (vpu_major > 0) {
- + device_destroy(vpu_class, MKDEV(vpu_major, 0));
- + class_destroy(vpu_class);
- + unregister_chrdev(vpu_major, "mxc_vpu");
- + vpu_major = 0;
- + }
- +
- + vpu_free_dma_buffer(&bitwork_mem);
- + vpu_free_dma_buffer(&pic_para_mem);
- + vpu_free_dma_buffer(&user_data_mem);
- +
- + /* reset VPU state */
- + vpu_power_up(true);
- + clk_prepare(vpu_clk);
- + clk_enable(vpu_clk);
- + vpu_reset();
- + clk_disable(vpu_clk);
- + clk_unprepare(vpu_clk);
- + vpu_power_up(false);
- +
- + clk_put(vpu_clk);
- +
- + platform_driver_unregister(&mxcvpu_driver);
- + return;
- +}
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("Linux VPU driver for Freescale i.MX/MXC");
- +MODULE_LICENSE("GPL");
- +
- +module_init(vpu_init);
- +module_exit(vpu_exit);
- diff -Nur linux-3.14.35.orig/drivers/net/bonding/bonding.h linux-3.14.35/drivers/net/bonding/bonding.h
- --- linux-3.14.35.orig/drivers/net/bonding/bonding.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/bonding/bonding.h 2015-03-08 14:27:37.669684500 -0500
- @@ -188,7 +188,8 @@
- struct net_device *dev; /* first - useful for panic debug */
- struct bonding *bond; /* our master */
- int delay;
- - unsigned long jiffies;
- + /* all three in jiffies */
- + unsigned long last_link_up;
- unsigned long last_arp_rx;
- unsigned long target_last_arp_rx[BOND_MAX_ARP_TARGETS];
- s8 link; /* one of BOND_LINK_XXXX */
- diff -Nur linux-3.14.35.orig/drivers/net/bonding/bond_main.c linux-3.14.35/drivers/net/bonding/bond_main.c
- --- linux-3.14.35.orig/drivers/net/bonding/bond_main.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/bonding/bond_main.c 2015-03-08 14:27:37.669684500 -0500
- @@ -798,7 +798,7 @@
- return;
-
- if (new_active) {
- - new_active->jiffies = jiffies;
- + new_active->last_link_up = jiffies;
-
- if (new_active->link == BOND_LINK_BACK) {
- if (USES_PRIMARY(bond->params.mode)) {
- @@ -1457,7 +1457,7 @@
- }
-
- if (new_slave->link != BOND_LINK_DOWN)
- - new_slave->jiffies = jiffies;
- + new_slave->last_link_up = jiffies;
- pr_debug("Initial state of slave_dev is BOND_LINK_%s\n",
- new_slave->link == BOND_LINK_DOWN ? "DOWN" :
- (new_slave->link == BOND_LINK_UP ? "UP" : "BACK"));
- @@ -1908,7 +1908,7 @@
- * recovered before downdelay expired
- */
- slave->link = BOND_LINK_UP;
- - slave->jiffies = jiffies;
- + slave->last_link_up = jiffies;
- pr_info("%s: link status up again after %d ms for interface %s.\n",
- bond->dev->name,
- (bond->params.downdelay - slave->delay) *
- @@ -1983,7 +1983,7 @@
-
- case BOND_LINK_UP:
- slave->link = BOND_LINK_UP;
- - slave->jiffies = jiffies;
- + slave->last_link_up = jiffies;
-
- if (bond->params.mode == BOND_MODE_8023AD) {
- /* prevent it from being the active one */
- @@ -2268,6 +2268,7 @@
- struct slave *slave)
- {
- struct arphdr *arp = (struct arphdr *)skb->data;
- + struct slave *curr_active_slave;
- unsigned char *arp_ptr;
- __be32 sip, tip;
- int alen;
- @@ -2312,6 +2313,8 @@
- bond->params.arp_validate, slave_do_arp_validate(bond, slave),
- &sip, &tip);
-
- + curr_active_slave = rcu_dereference(bond->curr_active_slave);
- +
- /*
- * Backup slaves won't see the ARP reply, but do come through
- * here for each ARP probe (so we swap the sip/tip to validate
- @@ -2325,11 +2328,12 @@
- * is done to avoid endless looping when we can't reach the
- * arp_ip_target and fool ourselves with our own arp requests.
- */
- +
- if (bond_is_active_slave(slave))
- bond_validate_arp(bond, slave, sip, tip);
- - else if (bond->curr_active_slave &&
- - time_after(slave_last_rx(bond, bond->curr_active_slave),
- - bond->curr_active_slave->jiffies))
- + else if (curr_active_slave &&
- + time_after(slave_last_rx(bond, curr_active_slave),
- + curr_active_slave->last_link_up))
- bond_validate_arp(bond, slave, tip, sip);
-
- out_unlock:
- @@ -2376,9 +2380,9 @@
- oldcurrent = ACCESS_ONCE(bond->curr_active_slave);
- /* see if any of the previous devices are up now (i.e. they have
- * xmt and rcv traffic). the curr_active_slave does not come into
- - * the picture unless it is null. also, slave->jiffies is not needed
- - * here because we send an arp on each slave and give a slave as
- - * long as it needs to get the tx/rx within the delta.
- + * the picture unless it is null. also, slave->last_link_up is not
- + * needed here because we send an arp on each slave and give a slave
- + * as long as it needs to get the tx/rx within the delta.
- * TODO: what about up/down delay in arp mode? it wasn't here before
- * so it can wait
- */
- @@ -2505,7 +2509,7 @@
- * active. This avoids bouncing, as the last receive
- * times need a full ARP monitor cycle to be updated.
- */
- - if (bond_time_in_interval(bond, slave->jiffies, 2))
- + if (bond_time_in_interval(bond, slave->last_link_up, 2))
- continue;
-
- /*
- @@ -2698,7 +2702,7 @@
- new_slave->link = BOND_LINK_BACK;
- bond_set_slave_active_flags(new_slave, BOND_SLAVE_NOTIFY_LATER);
- bond_arp_send_all(bond, new_slave);
- - new_slave->jiffies = jiffies;
- + new_slave->last_link_up = jiffies;
- rcu_assign_pointer(bond->current_arp_slave, new_slave);
-
- check_state:
- diff -Nur linux-3.14.35.orig/drivers/net/can/flexcan.c linux-3.14.35/drivers/net/can/flexcan.c
- --- linux-3.14.35.orig/drivers/net/can/flexcan.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/can/flexcan.c 2015-03-08 14:27:37.669684500 -0500
- @@ -125,7 +125,8 @@
- FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT)
-
- /* FLEXCAN interrupt flag register (IFLAG) bits */
- -#define FLEXCAN_TX_BUF_ID 8
- +#define FLEXCAN_RESERVED_BUF_ID 8
- +#define FLEXCAN_TX_BUF_ID 13
- #define FLEXCAN_IFLAG_BUF(x) BIT(x)
- #define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW BIT(7)
- #define FLEXCAN_IFLAG_RX_FIFO_WARN BIT(6)
- @@ -162,6 +163,7 @@
- */
- #define FLEXCAN_HAS_V10_FEATURES BIT(1) /* For core version >= 10 */
- #define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* [TR]WRN_INT not connected */
- +#define FLEXCAN_HAS_ERR005829 BIT(3) /* have errata ERR005829 */
-
- /* Structure of the message buffer */
- struct flexcan_mb {
- @@ -221,7 +223,7 @@
- };
- static struct flexcan_devtype_data fsl_imx28_devtype_data;
- static struct flexcan_devtype_data fsl_imx6q_devtype_data = {
- - .features = FLEXCAN_HAS_V10_FEATURES,
- + .features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_ERR005829,
- };
-
- static const struct can_bittiming_const flexcan_bittiming_const = {
- @@ -428,6 +430,11 @@
- flexcan_write(can_id, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
- flexcan_write(ctrl, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
-
- + if (priv->devtype_data->features & FLEXCAN_HAS_ERR005829) {
- + writel(0x0, ®s->cantxfg[FLEXCAN_RESERVED_BUF_ID].can_ctrl);
- + writel(0x0, ®s->cantxfg[FLEXCAN_RESERVED_BUF_ID].can_ctrl);
- + }
- +
- return NETDEV_TX_OK;
- }
-
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/adi/bfin_mac.c linux-3.14.35/drivers/net/ethernet/adi/bfin_mac.c
- --- linux-3.14.35.orig/drivers/net/ethernet/adi/bfin_mac.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/adi/bfin_mac.c 2015-03-08 14:27:37.669684500 -0500
- @@ -1040,6 +1040,7 @@
- .n_alarm = 0,
- .n_ext_ts = 0,
- .n_per_out = 0,
- + .n_pins = 0,
- .pps = 0,
- .adjfreq = bfin_ptp_adjfreq,
- .adjtime = bfin_ptp_adjtime,
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/broadcom/tg3.c linux-3.14.35/drivers/net/ethernet/broadcom/tg3.c
- --- linux-3.14.35.orig/drivers/net/ethernet/broadcom/tg3.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/broadcom/tg3.c 2015-03-08 14:27:37.673684500 -0500
- @@ -6322,6 +6322,7 @@
- .n_alarm = 0,
- .n_ext_ts = 0,
- .n_per_out = 1,
- + .n_pins = 0,
- .pps = 0,
- .adjfreq = tg3_ptp_adjfreq,
- .adjtime = tg3_ptp_adjtime,
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/cadence/macb.c linux-3.14.35/drivers/net/ethernet/cadence/macb.c
- --- linux-3.14.35.orig/drivers/net/ethernet/cadence/macb.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/cadence/macb.c 2015-03-08 14:27:37.677684500 -0500
- @@ -604,25 +604,16 @@
- {
- unsigned int entry;
- struct sk_buff *skb;
- - struct macb_dma_desc *desc;
- dma_addr_t paddr;
-
- while (CIRC_SPACE(bp->rx_prepared_head, bp->rx_tail, RX_RING_SIZE) > 0) {
- - u32 addr, ctrl;
- -
- entry = macb_rx_ring_wrap(bp->rx_prepared_head);
- - desc = &bp->rx_ring[entry];
-
- /* Make hw descriptor updates visible to CPU */
- rmb();
-
- - addr = desc->addr;
- - ctrl = desc->ctrl;
- bp->rx_prepared_head++;
-
- - if ((addr & MACB_BIT(RX_USED)))
- - continue;
- -
- if (bp->rx_skbuff[entry] == NULL) {
- /* allocate sk_buff for this free entry in ring */
- skb = netdev_alloc_skb(bp->dev, bp->rx_buffer_size);
- @@ -703,7 +694,6 @@
- if (!(addr & MACB_BIT(RX_USED)))
- break;
-
- - desc->addr &= ~MACB_BIT(RX_USED);
- bp->rx_tail++;
- count++;
-
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/chelsio/cxgb4vf/sge.c linux-3.14.35/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
- --- linux-3.14.35.orig/drivers/net/ethernet/chelsio/cxgb4vf/sge.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/chelsio/cxgb4vf/sge.c 2015-03-08 14:27:37.677684500 -0500
- @@ -1510,7 +1510,8 @@
- {
- struct sk_buff *skb;
- const struct cpl_rx_pkt *pkt = (void *)rsp;
- - bool csum_ok = pkt->csum_calc && !pkt->err_vec;
- + bool csum_ok = pkt->csum_calc && !pkt->err_vec &&
- + (rspq->netdev->features & NETIF_F_RXCSUM);
- struct sge_eth_rxq *rxq = container_of(rspq, struct sge_eth_rxq, rspq);
-
- /*
- @@ -1538,8 +1539,8 @@
- skb_record_rx_queue(skb, rspq->idx);
- rxq->stats.pkts++;
-
- - if (csum_ok && (rspq->netdev->features & NETIF_F_RXCSUM) &&
- - !pkt->err_vec && (be32_to_cpu(pkt->l2info) & (RXF_UDP|RXF_TCP))) {
- + if (csum_ok && !pkt->err_vec &&
- + (be32_to_cpu(pkt->l2info) & (RXF_UDP|RXF_TCP))) {
- if (!pkt->ip_frag)
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- else {
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/freescale/fec.h linux-3.14.35/drivers/net/ethernet/freescale/fec.h
- --- linux-3.14.35.orig/drivers/net/ethernet/freescale/fec.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/freescale/fec.h 2015-03-08 14:27:37.677684500 -0500
- @@ -221,7 +221,7 @@
- #define BD_ENET_TX_RCMASK ((ushort)0x003c)
- #define BD_ENET_TX_UN ((ushort)0x0002)
- #define BD_ENET_TX_CSL ((ushort)0x0001)
- -#define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */
- +#define BD_ENET_TX_STATS ((ushort)0x0fff) /* All status bits */
-
- /*enhanced buffer descriptor control/status used by Ethernet transmit*/
- #define BD_ENET_TX_INT 0x40000000
- @@ -246,8 +246,8 @@
- #define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
- #define FEC_ENET_TX_FRSIZE 2048
- #define FEC_ENET_TX_FRPPG (PAGE_SIZE / FEC_ENET_TX_FRSIZE)
- -#define TX_RING_SIZE 16 /* Must be power of two */
- -#define TX_RING_MOD_MASK 15 /* for this to work */
- +#define TX_RING_SIZE 512 /* Must be power of two */
- +#define TX_RING_MOD_MASK 511 /* for this to work */
-
- #define BD_ENET_RX_INT 0x00800000
- #define BD_ENET_RX_PTP ((ushort)0x0400)
- @@ -256,12 +256,6 @@
- #define FLAG_RX_CSUM_ENABLED (BD_ENET_RX_ICE | BD_ENET_RX_PCR)
- #define FLAG_RX_CSUM_ERROR (BD_ENET_RX_ICE | BD_ENET_RX_PCR)
-
- -struct fec_enet_delayed_work {
- - struct delayed_work delay_work;
- - bool timeout;
- - bool trig_tx;
- -};
- -
- /* The FEC buffer descriptors track the ring buffers. The rx_bd_base and
- * tx_bd_base always point to the base of the buffer descriptors. The
- * cur_rx and cur_tx point to the currently available buffer.
- @@ -296,12 +290,18 @@
- /* The ring entries to be free()ed */
- struct bufdesc *dirty_tx;
-
- + unsigned short bufdesc_size;
- unsigned short tx_ring_size;
- unsigned short rx_ring_size;
- + unsigned short tx_stop_threshold;
- + unsigned short tx_wake_threshold;
- +
- + /* Software TSO */
- + char *tso_hdrs;
- + dma_addr_t tso_hdrs_dma;
-
- struct platform_device *pdev;
-
- - int opened;
- int dev_id;
-
- /* Phylib and MDIO interface */
- @@ -321,6 +321,8 @@
- struct napi_struct napi;
- int csum_flags;
-
- + struct work_struct tx_timeout_work;
- +
- struct ptp_clock *ptp_clock;
- struct ptp_clock_info ptp_caps;
- unsigned long last_overflow_check;
- @@ -333,7 +335,6 @@
- int hwts_rx_en;
- int hwts_tx_en;
- struct timer_list time_keep;
- - struct fec_enet_delayed_work delay_work;
- struct regulator *reg_phy;
- };
-
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/freescale/fec_main.c linux-3.14.35/drivers/net/ethernet/freescale/fec_main.c
- --- linux-3.14.35.orig/drivers/net/ethernet/freescale/fec_main.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/freescale/fec_main.c 2015-03-08 14:27:37.681684500 -0500
- @@ -36,6 +36,7 @@
- #include <linux/in.h>
- #include <linux/ip.h>
- #include <net/ip.h>
- +#include <net/tso.h>
- #include <linux/tcp.h>
- #include <linux/udp.h>
- #include <linux/icmp.h>
- @@ -54,6 +55,10 @@
- #include <linux/of_net.h>
- #include <linux/regulator/consumer.h>
- #include <linux/if_vlan.h>
- +#include <linux/pinctrl/consumer.h>
- +#include <linux/busfreq-imx6.h>
- +#include <linux/pm_runtime.h>
- +#include <linux/pm_qos.h>
-
- #include <asm/cacheflush.h>
-
- @@ -91,6 +96,8 @@
- #define FEC_QUIRK_HAS_CSUM (1 << 5)
- /* Controller has hardware vlan support */
- #define FEC_QUIRK_HAS_VLAN (1 << 6)
- +/* Controller is FEC-MAC */
- +#define FEC_QUIRK_FEC_MAC (1 << 7)
- /* ENET IP errata ERR006358
- *
- * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously
- @@ -100,7 +107,13 @@
- * frames not being transmitted until there is a 0-to-1 transition on
- * ENET_TDAR[TDAR].
- */
- -#define FEC_QUIRK_ERR006358 (1 << 7)
- +#define FEC_QUIRK_ERR006358 (1 << 8)
- +/*
- + * i.MX6Q/DL ENET cannot wake up system in wait mode because ENET tx & rx
- + * interrupt signal don't connect to GPC. So use pm qos to avoid cpu enter
- + * to wait mode.
- + */
- +#define FEC_QUIRK_BUG_WAITMODE (1 << 9)
-
- static struct platform_device_id fec_devtype[] = {
- {
- @@ -109,7 +122,7 @@
- .driver_data = 0,
- }, {
- .name = "imx25-fec",
- - .driver_data = FEC_QUIRK_USE_GASKET,
- + .driver_data = FEC_QUIRK_USE_GASKET | FEC_QUIRK_FEC_MAC,
- }, {
- .name = "imx27-fec",
- .driver_data = 0,
- @@ -120,7 +133,8 @@
- .name = "imx6q-fec",
- .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
- FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
- - FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358,
- + FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358 |
- + FEC_QUIRK_BUG_WAITMODE,
- }, {
- .name = "mvf600-fec",
- .driver_data = FEC_QUIRK_ENET_MAC,
- @@ -172,10 +186,6 @@
- #endif
- #endif /* CONFIG_M5272 */
-
- -#if (((RX_RING_SIZE + TX_RING_SIZE) * 32) > PAGE_SIZE)
- -#error "FEC: descriptor ring size constants too large"
- -#endif
- -
- /* Interrupt events/masks. */
- #define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */
- #define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */
- @@ -231,6 +241,15 @@
- #define FEC_PAUSE_FLAG_AUTONEG 0x1
- #define FEC_PAUSE_FLAG_ENABLE 0x2
-
- +#define TSO_HEADER_SIZE 128
- +/* Max number of allowed TCP segments for software TSO */
- +#define FEC_MAX_TSO_SEGS 100
- +#define FEC_MAX_SKB_DESCS (FEC_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS)
- +
- +#define IS_TSO_HEADER(txq, addr) \
- + ((addr >= txq->tso_hdrs_dma) && \
- + (addr < txq->tso_hdrs_dma + txq->tx_ring_size * TSO_HEADER_SIZE))
- +
- static int mii_cnt;
-
- static inline
- @@ -286,6 +305,22 @@
- return (new_bd < base) ? (new_bd + ring_size) : new_bd;
- }
-
- +static int fec_enet_get_bd_index(struct bufdesc *base, struct bufdesc *bdp,
- + struct fec_enet_private *fep)
- +{
- + return ((const char *)bdp - (const char *)base) / fep->bufdesc_size;
- +}
- +
- +static int fec_enet_get_free_txdesc_num(struct fec_enet_private *fep)
- +{
- + int entries;
- +
- + entries = ((const char *)fep->dirty_tx -
- + (const char *)fep->cur_tx) / fep->bufdesc_size - 1;
- +
- + return entries > 0 ? entries : entries + fep->tx_ring_size;
- +}
- +
- static void *swap_buffer(void *bufaddr, int len)
- {
- int i;
- @@ -297,6 +332,32 @@
- return bufaddr;
- }
-
- +static void fec_dump(struct net_device *ndev)
- +{
- + struct fec_enet_private *fep = netdev_priv(ndev);
- + struct bufdesc *bdp = fep->tx_bd_base;
- + unsigned int index = 0;
- +
- + netdev_info(ndev, "TX ring dump\n");
- + pr_info("Nr SC addr len SKB\n");
- +
- + do {
- + pr_info("%3u %c%c 0x%04x 0x%08lx %4u %p\n",
- + index,
- + bdp == fep->cur_tx ? 'S' : ' ',
- + bdp == fep->dirty_tx ? 'H' : ' ',
- + bdp->cbd_sc, bdp->cbd_bufaddr, bdp->cbd_datlen,
- + fep->tx_skbuff[index]);
- + bdp = fec_enet_get_nextdesc(bdp, fep);
- + index++;
- + } while (bdp != fep->tx_bd_base);
- +}
- +
- +static inline bool is_ipv4_pkt(struct sk_buff *skb)
- +{
- + return skb->protocol == htons(ETH_P_IP) && ip_hdr(skb)->version == 4;
- +}
- +
- static int
- fec_enet_clear_csum(struct sk_buff *skb, struct net_device *ndev)
- {
- @@ -307,137 +368,419 @@
- if (unlikely(skb_cow_head(skb, 0)))
- return -1;
-
- + if (is_ipv4_pkt(skb))
- + ip_hdr(skb)->check = 0;
- *(__sum16 *)(skb->head + skb->csum_start + skb->csum_offset) = 0;
-
- return 0;
- }
-
- -static netdev_tx_t
- -fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
- +static int
- +fec_enet_txq_submit_frag_skb(struct sk_buff *skb, struct net_device *ndev)
- {
- struct fec_enet_private *fep = netdev_priv(ndev);
- const struct platform_device_id *id_entry =
- platform_get_device_id(fep->pdev);
- - struct bufdesc *bdp, *bdp_pre;
- - void *bufaddr;
- - unsigned short status;
- + struct bufdesc *bdp = fep->cur_tx;
- + struct bufdesc_ex *ebdp;
- + int nr_frags = skb_shinfo(skb)->nr_frags;
- + int frag, frag_len;
- + unsigned short status;
- + unsigned int estatus = 0;
- + skb_frag_t *this_frag;
- unsigned int index;
- + void *bufaddr;
- + dma_addr_t addr;
- + int i;
-
- - /* Fill in a Tx ring entry */
- + for (frag = 0; frag < nr_frags; frag++) {
- + this_frag = &skb_shinfo(skb)->frags[frag];
- + bdp = fec_enet_get_nextdesc(bdp, fep);
- + ebdp = (struct bufdesc_ex *)bdp;
- +
- + status = bdp->cbd_sc;
- + status &= ~BD_ENET_TX_STATS;
- + status |= (BD_ENET_TX_TC | BD_ENET_TX_READY);
- + frag_len = skb_shinfo(skb)->frags[frag].size;
- +
- + /* Handle the last BD specially */
- + if (frag == nr_frags - 1) {
- + status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST);
- + if (fep->bufdesc_ex) {
- + estatus |= BD_ENET_TX_INT;
- + if (unlikely(skb_shinfo(skb)->tx_flags &
- + SKBTX_HW_TSTAMP && fep->hwts_tx_en))
- + estatus |= BD_ENET_TX_TS;
- + }
- + }
- +
- + if (fep->bufdesc_ex) {
- + if (skb->ip_summed == CHECKSUM_PARTIAL)
- + estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
- + ebdp->cbd_bdu = 0;
- + ebdp->cbd_esc = estatus;
- + }
- +
- + bufaddr = page_address(this_frag->page.p) + this_frag->page_offset;
- +
- + index = fec_enet_get_bd_index(fep->tx_bd_base, bdp, fep);
- + if (((unsigned long) bufaddr) & FEC_ALIGNMENT ||
- + id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) {
- + memcpy(fep->tx_bounce[index], bufaddr, frag_len);
- + bufaddr = fep->tx_bounce[index];
- +
- + if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
- + swap_buffer(bufaddr, frag_len);
- + }
- +
- + addr = dma_map_single(&fep->pdev->dev, bufaddr, frag_len,
- + DMA_TO_DEVICE);
- + if (dma_mapping_error(&fep->pdev->dev, addr)) {
- + dev_kfree_skb_any(skb);
- + if (net_ratelimit())
- + netdev_err(ndev, "Tx DMA memory map failed\n");
- + goto dma_mapping_error;
- + }
- +
- + bdp->cbd_bufaddr = addr;
- + bdp->cbd_datlen = frag_len;
- + bdp->cbd_sc = status;
- + }
- +
- + fep->cur_tx = bdp;
- +
- + return 0;
- +
- +dma_mapping_error:
- bdp = fep->cur_tx;
- + for (i = 0; i < frag; i++) {
- + bdp = fec_enet_get_nextdesc(bdp, fep);
- + dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
- + bdp->cbd_datlen, DMA_TO_DEVICE);
- + }
- + return NETDEV_TX_OK;
- +}
-
- - status = bdp->cbd_sc;
- +static int fec_enet_txq_submit_skb(struct sk_buff *skb, struct net_device *ndev)
- +{
- + struct fec_enet_private *fep = netdev_priv(ndev);
- + const struct platform_device_id *id_entry =
- + platform_get_device_id(fep->pdev);
- + int nr_frags = skb_shinfo(skb)->nr_frags;
- + struct bufdesc *bdp, *last_bdp;
- + void *bufaddr;
- + dma_addr_t addr;
- + unsigned short status;
- + unsigned short buflen;
- + unsigned int estatus = 0;
- + unsigned int index;
- + int entries_free;
- + int ret;
-
- - if (status & BD_ENET_TX_READY) {
- - /* Ooops. All transmit buffers are full. Bail out.
- - * This should not happen, since ndev->tbusy should be set.
- - */
- - netdev_err(ndev, "tx queue full!\n");
- - return NETDEV_TX_BUSY;
- + entries_free = fec_enet_get_free_txdesc_num(fep);
- + if (entries_free < MAX_SKB_FRAGS + 1) {
- + dev_kfree_skb_any(skb);
- + if (net_ratelimit())
- + netdev_err(ndev, "NOT enough BD for SG!\n");
- + return NETDEV_TX_OK;
- }
-
- /* Protocol checksum off-load for TCP and UDP. */
- if (fec_enet_clear_csum(skb, ndev)) {
- - kfree_skb(skb);
- + dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
- }
-
- - /* Clear all of the status flags */
- + /* Fill in a Tx ring entry */
- + bdp = fep->cur_tx;
- + status = bdp->cbd_sc;
- status &= ~BD_ENET_TX_STATS;
-
- /* Set buffer length and buffer pointer */
- bufaddr = skb->data;
- - bdp->cbd_datlen = skb->len;
- + buflen = skb_headlen(skb);
-
- - /*
- - * On some FEC implementations data must be aligned on
- - * 4-byte boundaries. Use bounce buffers to copy data
- - * and get it aligned. Ugh.
- - */
- - if (fep->bufdesc_ex)
- - index = (struct bufdesc_ex *)bdp -
- - (struct bufdesc_ex *)fep->tx_bd_base;
- - else
- - index = bdp - fep->tx_bd_base;
- -
- - if (((unsigned long) bufaddr) & FEC_ALIGNMENT) {
- - memcpy(fep->tx_bounce[index], skb->data, skb->len);
- + index = fec_enet_get_bd_index(fep->tx_bd_base, bdp, fep);
- + if (((unsigned long) bufaddr) & FEC_ALIGNMENT ||
- + id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) {
- + memcpy(fep->tx_bounce[index], skb->data, buflen);
- bufaddr = fep->tx_bounce[index];
- - }
- -
- - /*
- - * Some design made an incorrect assumption on endian mode of
- - * the system that it's running on. As the result, driver has to
- - * swap every frame going to and coming from the controller.
- - */
- - if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
- - swap_buffer(bufaddr, skb->len);
-
- - /* Save skb pointer */
- - fep->tx_skbuff[index] = skb;
- + if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
- + swap_buffer(bufaddr, buflen);
- + }
-
- - /* Push the data cache so the CPM does not get stale memory
- - * data.
- - */
- - bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr,
- - skb->len, DMA_TO_DEVICE);
- - if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
- - bdp->cbd_bufaddr = 0;
- - fep->tx_skbuff[index] = NULL;
- + /* Push the data cache so the CPM does not get stale memory data. */
- + addr = dma_map_single(&fep->pdev->dev, bufaddr, buflen, DMA_TO_DEVICE);
- + if (dma_mapping_error(&fep->pdev->dev, addr)) {
- dev_kfree_skb_any(skb);
- if (net_ratelimit())
- netdev_err(ndev, "Tx DMA memory map failed\n");
- return NETDEV_TX_OK;
- }
-
- + if (nr_frags) {
- + ret = fec_enet_txq_submit_frag_skb(skb, ndev);
- + if (ret)
- + return ret;
- + } else {
- + status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST);
- + if (fep->bufdesc_ex) {
- + estatus = BD_ENET_TX_INT;
- + if (unlikely(skb_shinfo(skb)->tx_flags &
- + SKBTX_HW_TSTAMP && fep->hwts_tx_en))
- + estatus |= BD_ENET_TX_TS;
- + }
- + }
- +
- if (fep->bufdesc_ex) {
-
- struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
- - ebdp->cbd_bdu = 0;
- +
- if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
- - fep->hwts_tx_en)) {
- - ebdp->cbd_esc = (BD_ENET_TX_TS | BD_ENET_TX_INT);
- + fep->hwts_tx_en))
- skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
- - } else {
- - ebdp->cbd_esc = BD_ENET_TX_INT;
-
- - /* Enable protocol checksum flags
- - * We do not bother with the IP Checksum bits as they
- - * are done by the kernel
- - */
- - if (skb->ip_summed == CHECKSUM_PARTIAL)
- - ebdp->cbd_esc |= BD_ENET_TX_PINS;
- - }
- + if (skb->ip_summed == CHECKSUM_PARTIAL)
- + estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
- +
- + ebdp->cbd_bdu = 0;
- + ebdp->cbd_esc = estatus;
- }
-
- + last_bdp = fep->cur_tx;
- + index = fec_enet_get_bd_index(fep->tx_bd_base, last_bdp, fep);
- + /* Save skb pointer */
- + fep->tx_skbuff[index] = skb;
- +
- + bdp->cbd_datlen = buflen;
- + bdp->cbd_bufaddr = addr;
- +
- /* Send it on its way. Tell FEC it's ready, interrupt when done,
- * it's the last BD of the frame, and to put the CRC on the end.
- */
- - status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR
- - | BD_ENET_TX_LAST | BD_ENET_TX_TC);
- + status |= (BD_ENET_TX_READY | BD_ENET_TX_TC);
- bdp->cbd_sc = status;
-
- - bdp_pre = fec_enet_get_prevdesc(bdp, fep);
- - if ((id_entry->driver_data & FEC_QUIRK_ERR006358) &&
- - !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) {
- - fep->delay_work.trig_tx = true;
- - schedule_delayed_work(&(fep->delay_work.delay_work),
- - msecs_to_jiffies(1));
- - }
- -
- /* If this was the last BD in the ring, start at the beginning again. */
- - bdp = fec_enet_get_nextdesc(bdp, fep);
- + bdp = fec_enet_get_nextdesc(last_bdp, fep);
-
- skb_tx_timestamp(skb);
-
- fep->cur_tx = bdp;
-
- - if (fep->cur_tx == fep->dirty_tx)
- - netif_stop_queue(ndev);
- + /* Trigger transmission start */
- + writel(0, fep->hwp + FEC_X_DES_ACTIVE);
- +
- + return 0;
- +}
- +
- +static int
- +fec_enet_txq_put_data_tso(struct sk_buff *skb, struct net_device *ndev,
- + struct bufdesc *bdp, int index, char *data,
- + int size, bool last_tcp, bool is_last)
- +{
- + struct fec_enet_private *fep = netdev_priv(ndev);
- + const struct platform_device_id *id_entry =
- + platform_get_device_id(fep->pdev);
- + struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
- + unsigned short status;
- + unsigned int estatus = 0;
- + dma_addr_t addr;
- +
- + status = bdp->cbd_sc;
- + status &= ~BD_ENET_TX_STATS;
- +
- + status |= (BD_ENET_TX_TC | BD_ENET_TX_READY);
- +
- + if (((unsigned long) data) & FEC_ALIGNMENT ||
- + id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) {
- + memcpy(fep->tx_bounce[index], data, size);
- + data = fep->tx_bounce[index];
- +
- + if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
- + swap_buffer(data, size);
- + }
- +
- + addr = dma_map_single(&fep->pdev->dev, data, size, DMA_TO_DEVICE);
- + if (dma_mapping_error(&fep->pdev->dev, addr)) {
- + dev_kfree_skb_any(skb);
- + if (net_ratelimit())
- + netdev_err(ndev, "Tx DMA memory map failed\n");
- + return NETDEV_TX_BUSY;
- + }
- +
- + bdp->cbd_datlen = size;
- + bdp->cbd_bufaddr = addr;
- +
- + if (fep->bufdesc_ex) {
- + if (skb->ip_summed == CHECKSUM_PARTIAL)
- + estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
- + ebdp->cbd_bdu = 0;
- + ebdp->cbd_esc = estatus;
- + }
- +
- + /* Handle the last BD specially */
- + if (last_tcp)
- + status |= (BD_ENET_TX_LAST | BD_ENET_TX_TC);
- + if (is_last) {
- + status |= BD_ENET_TX_INTR;
- + if (fep->bufdesc_ex)
- + ebdp->cbd_esc |= BD_ENET_TX_INT;
- + }
- +
- + bdp->cbd_sc = status;
- +
- + return 0;
- +}
- +
- +static int
- +fec_enet_txq_put_hdr_tso(struct sk_buff *skb, struct net_device *ndev,
- + struct bufdesc *bdp, int index)
- +{
- + struct fec_enet_private *fep = netdev_priv(ndev);
- + const struct platform_device_id *id_entry =
- + platform_get_device_id(fep->pdev);
- + int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
- + struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
- + void *bufaddr;
- + unsigned long dmabuf;
- + unsigned short status;
- + unsigned int estatus = 0;
- +
- + status = bdp->cbd_sc;
- + status &= ~BD_ENET_TX_STATS;
- + status |= (BD_ENET_TX_TC | BD_ENET_TX_READY);
- +
- + bufaddr = fep->tso_hdrs + index * TSO_HEADER_SIZE;
- + dmabuf = fep->tso_hdrs_dma + index * TSO_HEADER_SIZE;
- + if (((unsigned long) bufaddr) & FEC_ALIGNMENT ||
- + id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) {
- + memcpy(fep->tx_bounce[index], skb->data, hdr_len);
- + bufaddr = fep->tx_bounce[index];
- +
- + if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
- + swap_buffer(bufaddr, hdr_len);
- +
- + dmabuf = dma_map_single(&fep->pdev->dev, bufaddr,
- + hdr_len, DMA_TO_DEVICE);
- + if (dma_mapping_error(&fep->pdev->dev, dmabuf)) {
- + dev_kfree_skb_any(skb);
- + if (net_ratelimit())
- + netdev_err(ndev, "Tx DMA memory map failed\n");
- + return NETDEV_TX_BUSY;
- + }
- + }
- +
- + bdp->cbd_bufaddr = dmabuf;
- + bdp->cbd_datlen = hdr_len;
- +
- + if (fep->bufdesc_ex) {
- + if (skb->ip_summed == CHECKSUM_PARTIAL)
- + estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
- + ebdp->cbd_bdu = 0;
- + ebdp->cbd_esc = estatus;
- + }
- +
- + bdp->cbd_sc = status;
- +
- + return 0;
- +}
- +
- +static int fec_enet_txq_submit_tso(struct sk_buff *skb, struct net_device *ndev)
- +{
- + struct fec_enet_private *fep = netdev_priv(ndev);
- + int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
- + int total_len, data_left;
- + struct bufdesc *bdp = fep->cur_tx;
- + struct tso_t tso;
- + unsigned int index = 0;
- + int ret;
- +
- + if (tso_count_descs(skb) >= fec_enet_get_free_txdesc_num(fep)) {
- + dev_kfree_skb_any(skb);
- + if (net_ratelimit())
- + netdev_err(ndev, "NOT enough BD for TSO!\n");
- + return NETDEV_TX_OK;
- + }
- +
- + /* Protocol checksum off-load for TCP and UDP. */
- + if (fec_enet_clear_csum(skb, ndev)) {
- + dev_kfree_skb_any(skb);
- + return NETDEV_TX_OK;
- + }
- +
- + /* Initialize the TSO handler, and prepare the first payload */
- + tso_start(skb, &tso);
- +
- + total_len = skb->len - hdr_len;
- + while (total_len > 0) {
- + char *hdr;
- +
- + index = fec_enet_get_bd_index(fep->tx_bd_base, bdp, fep);
- + data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len);
- + total_len -= data_left;
- +
- + /* prepare packet headers: MAC + IP + TCP */
- + hdr = fep->tso_hdrs + index * TSO_HEADER_SIZE;
- + tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0);
- + ret = fec_enet_txq_put_hdr_tso(skb, ndev, bdp, index);
- + if (ret)
- + goto err_release;
- +
- + while (data_left > 0) {
- + int size;
- +
- + size = min_t(int, tso.size, data_left);
- + bdp = fec_enet_get_nextdesc(bdp, fep);
- + index = fec_enet_get_bd_index(fep->tx_bd_base, bdp, fep);
- + ret = fec_enet_txq_put_data_tso(skb, ndev, bdp, index, tso.data,
- + size, size == data_left,
- + total_len == 0);
- + if (ret)
- + goto err_release;
- +
- + data_left -= size;
- + tso_build_data(skb, &tso, size);
- + }
- +
- + bdp = fec_enet_get_nextdesc(bdp, fep);
- + }
- +
- + /* Save skb pointer */
- + fep->tx_skbuff[index] = skb;
- +
- + skb_tx_timestamp(skb);
- + fep->cur_tx = bdp;
-
- /* Trigger transmission start */
- writel(0, fep->hwp + FEC_X_DES_ACTIVE);
-
- + return 0;
- +
- +err_release:
- + /* TODO: Release all used data descriptors for TSO */
- + return ret;
- +}
- +
- +static netdev_tx_t
- +fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
- +{
- + struct fec_enet_private *fep = netdev_priv(ndev);
- + int entries_free;
- + int ret;
- +
- + if (skb_is_gso(skb))
- + ret = fec_enet_txq_submit_tso(skb, ndev);
- + else
- + ret = fec_enet_txq_submit_skb(skb, ndev);
- + if (ret)
- + return ret;
- +
- + entries_free = fec_enet_get_free_txdesc_num(fep);
- + if (entries_free <= fep->tx_stop_threshold)
- + netif_stop_queue(ndev);
- +
- return NETDEV_TX_OK;
- }
-
- @@ -474,7 +817,7 @@
-
- /* Initialize the BD for every fragment in the page. */
- bdp->cbd_sc = 0;
- - if (bdp->cbd_bufaddr && fep->tx_skbuff[i]) {
- + if (fep->tx_skbuff[i]) {
- dev_kfree_skb_any(fep->tx_skbuff[i]);
- fep->tx_skbuff[i] = NULL;
- }
- @@ -488,12 +831,13 @@
- fep->dirty_tx = bdp;
- }
-
- -/* This function is called to start or restart the FEC during a link
- - * change. This only happens when switching between half and full
- - * duplex.
- +/*
- + * This function is called to start or restart the FEC during a link
- + * change, transmit timeout, or to reconfigure the FEC. The network
- + * packet processing for this device must be stopped before this call.
- */
- static void
- -fec_restart(struct net_device *ndev, int duplex)
- +fec_restart(struct net_device *ndev)
- {
- struct fec_enet_private *fep = netdev_priv(ndev);
- const struct platform_device_id *id_entry =
- @@ -504,13 +848,6 @@
- u32 rcntl = OPT_FRAME_SIZE | 0x04;
- u32 ecntl = 0x2; /* ETHEREN */
-
- - if (netif_running(ndev)) {
- - netif_device_detach(ndev);
- - napi_disable(&fep->napi);
- - netif_stop_queue(ndev);
- - netif_tx_lock_bh(ndev);
- - }
- -
- /* Whack a reset. We should wait for this. */
- writel(1, fep->hwp + FEC_ECNTRL);
- udelay(10);
- @@ -519,7 +856,8 @@
- * enet-mac reset will reset mac address registers too,
- * so need to reconfigure it.
- */
- - if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
- + if (id_entry->driver_data & FEC_QUIRK_ENET_MAC ||
- + id_entry->driver_data & FEC_QUIRK_FEC_MAC) {
- memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN);
- writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW);
- writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH);
- @@ -551,7 +889,7 @@
- }
-
- /* Enable MII mode */
- - if (duplex) {
- + if (fep->full_duplex == DUPLEX_FULL) {
- /* FD enable */
- writel(0x04, fep->hwp + FEC_X_CNTRL);
- } else {
- @@ -560,8 +898,6 @@
- writel(0x0, fep->hwp + FEC_X_CNTRL);
- }
-
- - fep->full_duplex = duplex;
- -
- /* Set MII speed */
- writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
-
- @@ -679,13 +1015,6 @@
-
- /* Enable interrupts we wish to service */
- writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
- -
- - if (netif_running(ndev)) {
- - netif_tx_unlock_bh(ndev);
- - netif_wake_queue(ndev);
- - napi_enable(&fep->napi);
- - netif_device_attach(ndev);
- - }
- }
-
- static void
- @@ -723,29 +1052,44 @@
- {
- struct fec_enet_private *fep = netdev_priv(ndev);
-
- + fec_dump(ndev);
- +
- ndev->stats.tx_errors++;
-
- - fep->delay_work.timeout = true;
- - schedule_delayed_work(&(fep->delay_work.delay_work), 0);
- + schedule_work(&fep->tx_timeout_work);
- }
-
- -static void fec_enet_work(struct work_struct *work)
- +static void fec_enet_timeout_work(struct work_struct *work)
- {
- struct fec_enet_private *fep =
- - container_of(work,
- - struct fec_enet_private,
- - delay_work.delay_work.work);
- -
- - if (fep->delay_work.timeout) {
- - fep->delay_work.timeout = false;
- - fec_restart(fep->netdev, fep->full_duplex);
- - netif_wake_queue(fep->netdev);
- - }
- + container_of(work, struct fec_enet_private, tx_timeout_work);
- + struct net_device *ndev = fep->netdev;
-
- - if (fep->delay_work.trig_tx) {
- - fep->delay_work.trig_tx = false;
- - writel(0, fep->hwp + FEC_X_DES_ACTIVE);
- + rtnl_lock();
- + if (netif_device_present(ndev) || netif_running(ndev)) {
- + napi_disable(&fep->napi);
- + netif_tx_lock_bh(ndev);
- + fec_restart(ndev);
- + netif_wake_queue(ndev);
- + netif_tx_unlock_bh(ndev);
- + napi_enable(&fep->napi);
- }
- + rtnl_unlock();
- +}
- +
- +static void
- +fec_enet_hwtstamp(struct fec_enet_private *fep, unsigned ts,
- + struct skb_shared_hwtstamps *hwtstamps)
- +{
- + unsigned long flags;
- + u64 ns;
- +
- + spin_lock_irqsave(&fep->tmreg_lock, flags);
- + ns = timecounter_cyc2time(&fep->tc, ts);
- + spin_unlock_irqrestore(&fep->tmreg_lock, flags);
- +
- + memset(hwtstamps, 0, sizeof(*hwtstamps));
- + hwtstamps->hwtstamp = ns_to_ktime(ns);
- }
-
- static void
- @@ -756,6 +1100,7 @@
- unsigned short status;
- struct sk_buff *skb;
- int index = 0;
- + int entries_free;
-
- fep = netdev_priv(ndev);
- bdp = fep->dirty_tx;
- @@ -769,16 +1114,18 @@
- if (bdp == fep->cur_tx)
- break;
-
- - if (fep->bufdesc_ex)
- - index = (struct bufdesc_ex *)bdp -
- - (struct bufdesc_ex *)fep->tx_bd_base;
- - else
- - index = bdp - fep->tx_bd_base;
- + index = fec_enet_get_bd_index(fep->tx_bd_base, bdp, fep);
-
- skb = fep->tx_skbuff[index];
- - dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, skb->len,
- - DMA_TO_DEVICE);
- + fep->tx_skbuff[index] = NULL;
- + if (!IS_TSO_HEADER(fep, bdp->cbd_bufaddr))
- + dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
- + bdp->cbd_datlen, DMA_TO_DEVICE);
- bdp->cbd_bufaddr = 0;
- + if (!skb) {
- + bdp = fec_enet_get_nextdesc(bdp, fep);
- + continue;
- + }
-
- /* Check for errors. */
- if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
- @@ -797,26 +1144,18 @@
- ndev->stats.tx_carrier_errors++;
- } else {
- ndev->stats.tx_packets++;
- - ndev->stats.tx_bytes += bdp->cbd_datlen;
- + ndev->stats.tx_bytes += skb->len;
- }
-
- if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) &&
- fep->bufdesc_ex) {
- struct skb_shared_hwtstamps shhwtstamps;
- - unsigned long flags;
- struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
-
- - memset(&shhwtstamps, 0, sizeof(shhwtstamps));
- - spin_lock_irqsave(&fep->tmreg_lock, flags);
- - shhwtstamps.hwtstamp = ns_to_ktime(
- - timecounter_cyc2time(&fep->tc, ebdp->ts));
- - spin_unlock_irqrestore(&fep->tmreg_lock, flags);
- + fec_enet_hwtstamp(fep, ebdp->ts, &shhwtstamps);
- skb_tstamp_tx(skb, &shhwtstamps);
- }
-
- - if (status & BD_ENET_TX_READY)
- - netdev_err(ndev, "HEY! Enet xmit interrupt and TX_READY\n");
- -
- /* Deferred means some collisions occurred during transmit,
- * but we eventually sent the packet OK.
- */
- @@ -825,7 +1164,6 @@
-
- /* Free the sk buffer associated with this last transmit */
- dev_kfree_skb_any(skb);
- - fep->tx_skbuff[index] = NULL;
-
- fep->dirty_tx = bdp;
-
- @@ -834,14 +1172,17 @@
-
- /* Since we have freed up a buffer, the ring is no longer full
- */
- - if (fep->dirty_tx != fep->cur_tx) {
- - if (netif_queue_stopped(ndev))
- + if (netif_queue_stopped(ndev)) {
- + entries_free = fec_enet_get_free_txdesc_num(fep);
- + if (entries_free >= fep->tx_wake_threshold)
- netif_wake_queue(ndev);
- }
- }
- - return;
- -}
-
- + /* ERR006538: Keep the transmitter going */
- + if (bdp != fep->cur_tx && readl(fep->hwp + FEC_X_DES_ACTIVE) == 0)
- + writel(0, fep->hwp + FEC_X_DES_ACTIVE);
- +}
-
- /* During a receive, the cur_rx points to the current incoming buffer.
- * When we update through the ring, if the next incoming buffer has
- @@ -876,8 +1217,11 @@
-
- while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
-
- - if (pkt_received >= budget)
- + if (pkt_received >= budget) {
- + /* overwhelmed take a breath */
- + udelay(210);
- break;
- + }
- pkt_received++;
-
- /* Since we have allocated space to hold a complete frame,
- @@ -886,8 +1230,7 @@
- if ((status & BD_ENET_RX_LAST) == 0)
- netdev_err(ndev, "rcv is not +last\n");
-
- - if (!fep->opened)
- - goto rx_processing_done;
- + writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT);
-
- /* Check for errors. */
- if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
- @@ -920,11 +1263,7 @@
- pkt_len = bdp->cbd_datlen;
- ndev->stats.rx_bytes += pkt_len;
-
- - if (fep->bufdesc_ex)
- - index = (struct bufdesc_ex *)bdp -
- - (struct bufdesc_ex *)fep->rx_bd_base;
- - else
- - index = bdp - fep->rx_bd_base;
- + index = fec_enet_get_bd_index(fep->rx_bd_base, bdp, fep);
- data = fep->rx_skbuff[index]->data;
- dma_sync_single_for_cpu(&fep->pdev->dev, bdp->cbd_bufaddr,
- FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
- @@ -975,18 +1314,9 @@
- skb->protocol = eth_type_trans(skb, ndev);
-
- /* Get receive timestamp from the skb */
- - if (fep->hwts_rx_en && fep->bufdesc_ex) {
- - struct skb_shared_hwtstamps *shhwtstamps =
- - skb_hwtstamps(skb);
- - unsigned long flags;
- -
- - memset(shhwtstamps, 0, sizeof(*shhwtstamps));
- -
- - spin_lock_irqsave(&fep->tmreg_lock, flags);
- - shhwtstamps->hwtstamp = ns_to_ktime(
- - timecounter_cyc2time(&fep->tc, ebdp->ts));
- - spin_unlock_irqrestore(&fep->tmreg_lock, flags);
- - }
- + if (fep->hwts_rx_en && fep->bufdesc_ex)
- + fec_enet_hwtstamp(fep, ebdp->ts,
- + skb_hwtstamps(skb));
-
- if (fep->bufdesc_ex &&
- (fep->csum_flags & FLAG_RX_CSUM_ENABLED)) {
- @@ -1044,29 +1374,25 @@
- {
- struct net_device *ndev = dev_id;
- struct fec_enet_private *fep = netdev_priv(ndev);
- + const unsigned napi_mask = FEC_ENET_RXF | FEC_ENET_TXF;
- uint int_events;
- irqreturn_t ret = IRQ_NONE;
-
- - do {
- - int_events = readl(fep->hwp + FEC_IEVENT);
- - writel(int_events, fep->hwp + FEC_IEVENT);
- + int_events = readl(fep->hwp + FEC_IEVENT);
- + writel(int_events & ~napi_mask, fep->hwp + FEC_IEVENT);
-
- - if (int_events & (FEC_ENET_RXF | FEC_ENET_TXF)) {
- - ret = IRQ_HANDLED;
- + if (int_events & napi_mask) {
- + ret = IRQ_HANDLED;
-
- - /* Disable the RX interrupt */
- - if (napi_schedule_prep(&fep->napi)) {
- - writel(FEC_RX_DISABLED_IMASK,
- - fep->hwp + FEC_IMASK);
- - __napi_schedule(&fep->napi);
- - }
- - }
- + /* Disable the NAPI interrupts */
- + writel(FEC_ENET_MII, fep->hwp + FEC_IMASK);
- + napi_schedule(&fep->napi);
- + }
-
- - if (int_events & FEC_ENET_MII) {
- - ret = IRQ_HANDLED;
- - complete(&fep->mdio_done);
- - }
- - } while (int_events);
- + if (int_events & FEC_ENET_MII) {
- + ret = IRQ_HANDLED;
- + complete(&fep->mdio_done);
- + }
-
- return ret;
- }
- @@ -1074,8 +1400,16 @@
- static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
- {
- struct net_device *ndev = napi->dev;
- - int pkts = fec_enet_rx(ndev, budget);
- struct fec_enet_private *fep = netdev_priv(ndev);
- + int pkts;
- +
- + /*
- + * Clear any pending transmit or receive interrupts before
- + * processing the rings to avoid racing with the hardware.
- + */
- + writel(FEC_ENET_RXF | FEC_ENET_TXF, fep->hwp + FEC_IEVENT);
- +
- + pkts = fec_enet_rx(ndev, budget);
-
- fec_enet_tx(ndev);
-
- @@ -1173,14 +1507,23 @@
- return;
- }
-
- - if (phy_dev->link) {
- + /*
- + * If the netdev is down, or is going down, we're not interested
- + * in link state events, so just mark our idea of the link as down
- + * and ignore the event.
- + */
- + if (!netif_running(ndev) || !netif_device_present(ndev)) {
- + fep->link = 0;
- + } else if (phy_dev->link) {
- if (!fep->link) {
- fep->link = phy_dev->link;
- status_change = 1;
- }
-
- - if (fep->full_duplex != phy_dev->duplex)
- + if (fep->full_duplex != phy_dev->duplex) {
- + fep->full_duplex = phy_dev->duplex;
- status_change = 1;
- + }
-
- if (phy_dev->speed != fep->speed) {
- fep->speed = phy_dev->speed;
- @@ -1188,11 +1531,21 @@
- }
-
- /* if any of the above changed restart the FEC */
- - if (status_change)
- - fec_restart(ndev, phy_dev->duplex);
- + if (status_change) {
- + napi_disable(&fep->napi);
- + netif_tx_lock_bh(ndev);
- + fec_restart(ndev);
- + netif_wake_queue(ndev);
- + netif_tx_unlock_bh(ndev);
- + napi_enable(&fep->napi);
- + }
- } else {
- if (fep->link) {
- + napi_disable(&fep->napi);
- + netif_tx_lock_bh(ndev);
- fec_stop(ndev);
- + netif_tx_unlock_bh(ndev);
- + napi_enable(&fep->napi);
- fep->link = phy_dev->link;
- status_change = 1;
- }
- @@ -1255,9 +1608,51 @@
- return 0;
- }
-
- -static int fec_enet_mdio_reset(struct mii_bus *bus)
- +static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
- {
- + struct fec_enet_private *fep = netdev_priv(ndev);
- + int ret;
- +
- + if (enable) {
- + pm_runtime_enable(&fep->pdev->dev);
- +
- + ret = clk_prepare_enable(fep->clk_ahb);
- + if (ret)
- + return ret;
- + ret = clk_prepare_enable(fep->clk_ipg);
- + if (ret)
- + goto failed_clk_ipg;
- + if (fep->clk_enet_out) {
- + ret = clk_prepare_enable(fep->clk_enet_out);
- + if (ret)
- + goto failed_clk_enet_out;
- + }
- + if (fep->clk_ptp) {
- + ret = clk_prepare_enable(fep->clk_ptp);
- + if (ret)
- + goto failed_clk_ptp;
- + }
- + } else {
- + clk_disable_unprepare(fep->clk_ahb);
- + clk_disable_unprepare(fep->clk_ipg);
- + if (fep->clk_enet_out)
- + clk_disable_unprepare(fep->clk_enet_out);
- + if (fep->clk_ptp)
- + clk_disable_unprepare(fep->clk_ptp);
- +
- + pm_runtime_disable(&fep->pdev->dev);
- + }
- +
- return 0;
- +failed_clk_ptp:
- + if (fep->clk_enet_out)
- + clk_disable_unprepare(fep->clk_enet_out);
- +failed_clk_enet_out:
- + clk_disable_unprepare(fep->clk_ipg);
- +failed_clk_ipg:
- + clk_disable_unprepare(fep->clk_ahb);
- +
- + return ret;
- }
-
- static int fec_enet_mii_probe(struct net_device *ndev)
- @@ -1304,6 +1699,7 @@
- /* mask with MAC supported features */
- if (id_entry->driver_data & FEC_QUIRK_HAS_GBIT) {
- phy_dev->supported &= PHY_GBIT_FEATURES;
- + phy_dev->supported &= ~SUPPORTED_1000baseT_Half;
- #if !defined(CONFIG_M5272)
- phy_dev->supported |= SUPPORTED_Pause;
- #endif
- @@ -1369,7 +1765,7 @@
- * Reference Manual has an error on this, and gets fixed on i.MX6Q
- * document.
- */
- - fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk_ahb), 5000000);
- + fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk_ipg), 5000000);
- if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
- fep->phy_speed--;
- fep->phy_speed <<= 1;
- @@ -1384,7 +1780,6 @@
- fep->mii_bus->name = "fec_enet_mii_bus";
- fep->mii_bus->read = fec_enet_mdio_read;
- fep->mii_bus->write = fec_enet_mdio_write;
- - fep->mii_bus->reset = fec_enet_mdio_reset;
- snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
- pdev->name, fep->dev_id + 1);
- fep->mii_bus->priv = fep;
- @@ -1508,6 +1903,9 @@
- {
- struct fec_enet_private *fep = netdev_priv(ndev);
-
- + if (!fep->phy_dev)
- + return -ENODEV;
- +
- if (pause->tx_pause != pause->rx_pause) {
- netdev_info(ndev,
- "hardware only support enable/disable both tx and rx");
- @@ -1533,8 +1931,14 @@
- fec_stop(ndev);
- phy_start_aneg(fep->phy_dev);
- }
- - if (netif_running(ndev))
- - fec_restart(ndev, 0);
- + if (netif_running(ndev)) {
- + napi_disable(&fep->napi);
- + netif_tx_lock_bh(ndev);
- + fec_restart(ndev);
- + netif_wake_queue(ndev);
- + netif_tx_unlock_bh(ndev);
- + napi_enable(&fep->napi);
- + }
-
- return 0;
- }
- @@ -1651,21 +2055,19 @@
- }
-
- static const struct ethtool_ops fec_enet_ethtool_ops = {
- -#if !defined(CONFIG_M5272)
- - .get_pauseparam = fec_enet_get_pauseparam,
- - .set_pauseparam = fec_enet_set_pauseparam,
- -#endif
- .get_settings = fec_enet_get_settings,
- .set_settings = fec_enet_set_settings,
- .get_drvinfo = fec_enet_get_drvinfo,
- - .get_link = ethtool_op_get_link,
- - .get_ts_info = fec_enet_get_ts_info,
- .nway_reset = fec_enet_nway_reset,
- + .get_link = ethtool_op_get_link,
- #ifndef CONFIG_M5272
- - .get_ethtool_stats = fec_enet_get_ethtool_stats,
- + .get_pauseparam = fec_enet_get_pauseparam,
- + .set_pauseparam = fec_enet_set_pauseparam,
- .get_strings = fec_enet_get_strings,
- + .get_ethtool_stats = fec_enet_get_ethtool_stats,
- .get_sset_count = fec_enet_get_sset_count,
- #endif
- + .get_ts_info = fec_enet_get_ts_info,
- };
-
- static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
- @@ -1699,18 +2101,23 @@
- bdp = fep->rx_bd_base;
- for (i = 0; i < fep->rx_ring_size; i++) {
- skb = fep->rx_skbuff[i];
- -
- - if (bdp->cbd_bufaddr)
- + fep->rx_skbuff[i] = NULL;
- + if (skb) {
- dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
- FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
- - if (skb)
- dev_kfree_skb(skb);
- + }
- bdp = fec_enet_get_nextdesc(bdp, fep);
- }
-
- bdp = fep->tx_bd_base;
- - for (i = 0; i < fep->tx_ring_size; i++)
- + for (i = 0; i < fep->tx_ring_size; i++) {
- kfree(fep->tx_bounce[i]);
- + fep->tx_bounce[i] = NULL;
- + skb = fep->tx_skbuff[i];
- + fep->tx_skbuff[i] = NULL;
- + dev_kfree_skb(skb);
- + }
- }
-
- static int fec_enet_alloc_buffers(struct net_device *ndev)
- @@ -1722,21 +2129,23 @@
-
- bdp = fep->rx_bd_base;
- for (i = 0; i < fep->rx_ring_size; i++) {
- + dma_addr_t addr;
- +
- skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
- - if (!skb) {
- - fec_enet_free_buffers(ndev);
- - return -ENOMEM;
- - }
- - fep->rx_skbuff[i] = skb;
- + if (!skb)
- + goto err_alloc;
-
- - bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data,
- + addr = dma_map_single(&fep->pdev->dev, skb->data,
- FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
- - if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
- - fec_enet_free_buffers(ndev);
- + if (dma_mapping_error(&fep->pdev->dev, addr)) {
- + dev_kfree_skb(skb);
- if (net_ratelimit())
- netdev_err(ndev, "Rx DMA memory map failed\n");
- - return -ENOMEM;
- + goto err_alloc;
- }
- +
- + fep->rx_skbuff[i] = skb;
- + bdp->cbd_bufaddr = addr;
- bdp->cbd_sc = BD_ENET_RX_EMPTY;
-
- if (fep->bufdesc_ex) {
- @@ -1754,6 +2163,8 @@
- bdp = fep->tx_bd_base;
- for (i = 0; i < fep->tx_ring_size; i++) {
- fep->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
- + if (!fep->tx_bounce[i])
- + goto err_alloc;
-
- bdp->cbd_sc = 0;
- bdp->cbd_bufaddr = 0;
- @@ -1771,14 +2182,35 @@
- bdp->cbd_sc |= BD_SC_WRAP;
-
- return 0;
- +
- + err_alloc:
- + fec_enet_free_buffers(ndev);
- + return -ENOMEM;
- }
-
- static int
- fec_enet_open(struct net_device *ndev)
- {
- struct fec_enet_private *fep = netdev_priv(ndev);
- + const struct platform_device_id *id_entry =
- + platform_get_device_id(fep->pdev);
- int ret;
-
- + if (id_entry->driver_data & FEC_QUIRK_BUG_WAITMODE)
- + pm_qos_add_request(&ndev->pm_qos_req,
- + PM_QOS_CPU_DMA_LATENCY,
- + 0);
- + else
- + pm_qos_add_request(&ndev->pm_qos_req,
- + PM_QOS_CPU_DMA_LATENCY,
- + PM_QOS_DEFAULT_VALUE);
- +
- +
- + pinctrl_pm_select_default_state(&fep->pdev->dev);
- + ret = fec_enet_clk_enable(ndev, true);
- + if (ret)
- + return ret;
- +
- /* I should reset the ring buffers here, but I don't yet know
- * a simple way to do that.
- */
- @@ -1794,10 +2226,12 @@
- return ret;
- }
-
- + pm_runtime_get_sync(&fep->pdev->dev);
- +
- + fec_restart(ndev);
- napi_enable(&fep->napi);
- phy_start(fep->phy_dev);
- netif_start_queue(ndev);
- - fep->opened = 1;
- return 0;
- }
-
- @@ -1806,17 +2240,22 @@
- {
- struct fec_enet_private *fep = netdev_priv(ndev);
-
- - /* Don't know what to do yet. */
- - napi_disable(&fep->napi);
- - fep->opened = 0;
- - netif_stop_queue(ndev);
- - fec_stop(ndev);
- + phy_stop(fep->phy_dev);
-
- - if (fep->phy_dev) {
- - phy_stop(fep->phy_dev);
- - phy_disconnect(fep->phy_dev);
- + if (netif_device_present(ndev)) {
- + napi_disable(&fep->napi);
- + netif_tx_disable(ndev);
- + fec_stop(ndev);
- }
-
- + phy_disconnect(fep->phy_dev);
- + fep->phy_dev = NULL;
- +
- + fec_enet_clk_enable(ndev, false);
- + pinctrl_pm_select_sleep_state(&fep->pdev->dev);
- + pm_qos_remove_request(&ndev->pm_qos_req);
- + pm_runtime_put_sync_suspend(&fep->pdev->dev);
- +
- fec_enet_free_buffers(ndev);
-
- return 0;
- @@ -1904,10 +2343,11 @@
- struct fec_enet_private *fep = netdev_priv(ndev);
- struct sockaddr *addr = p;
-
- - if (!is_valid_ether_addr(addr->sa_data))
- - return -EADDRNOTAVAIL;
- -
- - memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
- + if (addr) {
- + if (!is_valid_ether_addr(addr->sa_data))
- + return -EADDRNOTAVAIL;
- + memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
- + }
-
- writel(ndev->dev_addr[3] | (ndev->dev_addr[2] << 8) |
- (ndev->dev_addr[1] << 16) | (ndev->dev_addr[0] << 24),
- @@ -1940,12 +2380,21 @@
- }
- #endif
-
- +#define FEATURES_NEED_QUIESCE NETIF_F_RXCSUM
- +
- static int fec_set_features(struct net_device *netdev,
- netdev_features_t features)
- {
- struct fec_enet_private *fep = netdev_priv(netdev);
- netdev_features_t changed = features ^ netdev->features;
-
- + /* Quiesce the device if necessary */
- + if (netif_running(netdev) && changed & FEATURES_NEED_QUIESCE) {
- + napi_disable(&fep->napi);
- + netif_tx_lock_bh(netdev);
- + fec_stop(netdev);
- + }
- +
- netdev->features = features;
-
- /* Receive checksum has been changed */
- @@ -1954,14 +2403,14 @@
- fep->csum_flags |= FLAG_RX_CSUM_ENABLED;
- else
- fep->csum_flags &= ~FLAG_RX_CSUM_ENABLED;
- + }
-
- - if (netif_running(netdev)) {
- - fec_stop(netdev);
- - fec_restart(netdev, fep->phy_dev->duplex);
- - netif_wake_queue(netdev);
- - } else {
- - fec_restart(netdev, fep->phy_dev->duplex);
- - }
- + /* Resume the device after updates */
- + if (netif_running(netdev) && changed & FEATURES_NEED_QUIESCE) {
- + fec_restart(netdev);
- + netif_wake_queue(netdev);
- + netif_tx_unlock_bh(netdev);
- + napi_enable(&fep->napi);
- }
-
- return 0;
- @@ -1993,23 +2442,43 @@
- const struct platform_device_id *id_entry =
- platform_get_device_id(fep->pdev);
- struct bufdesc *cbd_base;
- + int bd_size;
- +
- + /* init the tx & rx ring size */
- + fep->tx_ring_size = TX_RING_SIZE;
- + fep->rx_ring_size = RX_RING_SIZE;
- +
- + fep->tx_stop_threshold = FEC_MAX_SKB_DESCS;
- + fep->tx_wake_threshold = (fep->tx_ring_size - fep->tx_stop_threshold) / 2;
- +
- + if (fep->bufdesc_ex)
- + fep->bufdesc_size = sizeof(struct bufdesc_ex);
- + else
- + fep->bufdesc_size = sizeof(struct bufdesc);
- + bd_size = (fep->tx_ring_size + fep->rx_ring_size) *
- + fep->bufdesc_size;
-
- /* Allocate memory for buffer descriptors. */
- - cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma,
- + cbd_base = dma_alloc_coherent(NULL, bd_size, &fep->bd_dma,
- GFP_KERNEL);
- if (!cbd_base)
- return -ENOMEM;
-
- + fep->tso_hdrs = dma_alloc_coherent(NULL, fep->tx_ring_size * TSO_HEADER_SIZE,
- + &fep->tso_hdrs_dma, GFP_KERNEL);
- + if (!fep->tso_hdrs) {
- + dma_free_coherent(NULL, bd_size, cbd_base, fep->bd_dma);
- + return -ENOMEM;
- + }
- +
- memset(cbd_base, 0, PAGE_SIZE);
-
- fep->netdev = ndev;
-
- /* Get the Ethernet address */
- fec_get_mac(ndev);
- -
- - /* init the tx & rx ring size */
- - fep->tx_ring_size = TX_RING_SIZE;
- - fep->rx_ring_size = RX_RING_SIZE;
- + /* make sure MAC we just acquired is programmed into the hw */
- + fec_set_mac_address(ndev, NULL);
-
- /* Set receive and transmit descriptor base. */
- fep->rx_bd_base = cbd_base;
- @@ -2027,22 +2496,22 @@
- writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK);
- netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, NAPI_POLL_WEIGHT);
-
- - if (id_entry->driver_data & FEC_QUIRK_HAS_VLAN) {
- + if (id_entry->driver_data & FEC_QUIRK_HAS_VLAN)
- /* enable hw VLAN support */
- ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
- - ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
- - }
-
- if (id_entry->driver_data & FEC_QUIRK_HAS_CSUM) {
- + ndev->gso_max_segs = FEC_MAX_TSO_SEGS;
- +
- /* enable hw accelerator */
- ndev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
- - | NETIF_F_RXCSUM);
- - ndev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
- - | NETIF_F_RXCSUM);
- + | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO);
- fep->csum_flags |= FLAG_RX_CSUM_ENABLED;
- }
-
- - fec_restart(ndev, 0);
- + ndev->hw_features = ndev->features;
- +
- + fec_restart(ndev);
-
- return 0;
- }
- @@ -2117,6 +2586,9 @@
- fep->pause_flag |= FEC_PAUSE_FLAG_AUTONEG;
- #endif
-
- + /* Select default pin state */
- + pinctrl_pm_select_default_state(&pdev->dev);
- +
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- fep->hwp = devm_ioremap_resource(&pdev->dev, r);
- if (IS_ERR(fep->hwp)) {
- @@ -2167,26 +2639,10 @@
- fep->bufdesc_ex = 0;
- }
-
- - ret = clk_prepare_enable(fep->clk_ahb);
- + ret = fec_enet_clk_enable(ndev, true);
- if (ret)
- goto failed_clk;
-
- - ret = clk_prepare_enable(fep->clk_ipg);
- - if (ret)
- - goto failed_clk_ipg;
- -
- - if (fep->clk_enet_out) {
- - ret = clk_prepare_enable(fep->clk_enet_out);
- - if (ret)
- - goto failed_clk_enet_out;
- - }
- -
- - if (fep->clk_ptp) {
- - ret = clk_prepare_enable(fep->clk_ptp);
- - if (ret)
- - goto failed_clk_ptp;
- - }
- -
- fep->reg_phy = devm_regulator_get(&pdev->dev, "phy");
- if (!IS_ERR(fep->reg_phy)) {
- ret = regulator_enable(fep->reg_phy);
- @@ -2228,6 +2684,8 @@
-
- /* Carrier starts down, phylib will bring it up */
- netif_carrier_off(ndev);
- + fec_enet_clk_enable(ndev, false);
- + pinctrl_pm_select_sleep_state(&pdev->dev);
-
- ret = register_netdev(ndev);
- if (ret)
- @@ -2236,7 +2694,7 @@
- if (fep->bufdesc_ex && fep->ptp_clock)
- netdev_info(ndev, "registered PHC device %d\n", fep->dev_id);
-
- - INIT_DELAYED_WORK(&(fep->delay_work.delay_work), fec_enet_work);
- + INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work);
- return 0;
-
- failed_register:
- @@ -2246,16 +2704,10 @@
- failed_init:
- if (fep->reg_phy)
- regulator_disable(fep->reg_phy);
- + if (fep->ptp_clock)
- + ptp_clock_unregister(fep->ptp_clock);
- failed_regulator:
- - if (fep->clk_ptp)
- - clk_disable_unprepare(fep->clk_ptp);
- -failed_clk_ptp:
- - if (fep->clk_enet_out)
- - clk_disable_unprepare(fep->clk_enet_out);
- -failed_clk_enet_out:
- - clk_disable_unprepare(fep->clk_ipg);
- -failed_clk_ipg:
- - clk_disable_unprepare(fep->clk_ahb);
- + fec_enet_clk_enable(ndev, false);
- failed_clk:
- failed_ioremap:
- free_netdev(ndev);
- @@ -2269,42 +2721,40 @@
- struct net_device *ndev = platform_get_drvdata(pdev);
- struct fec_enet_private *fep = netdev_priv(ndev);
-
- - cancel_delayed_work_sync(&(fep->delay_work.delay_work));
- + cancel_work_sync(&fep->tx_timeout_work);
- unregister_netdev(ndev);
- fec_enet_mii_remove(fep);
- del_timer_sync(&fep->time_keep);
- if (fep->reg_phy)
- regulator_disable(fep->reg_phy);
- - if (fep->clk_ptp)
- - clk_disable_unprepare(fep->clk_ptp);
- if (fep->ptp_clock)
- ptp_clock_unregister(fep->ptp_clock);
- - if (fep->clk_enet_out)
- - clk_disable_unprepare(fep->clk_enet_out);
- - clk_disable_unprepare(fep->clk_ipg);
- - clk_disable_unprepare(fep->clk_ahb);
- + fec_enet_clk_enable(ndev, false);
- free_netdev(ndev);
-
- return 0;
- }
-
- -#ifdef CONFIG_PM_SLEEP
- +#ifdef CONFIG_PM
- static int
- fec_suspend(struct device *dev)
- {
- struct net_device *ndev = dev_get_drvdata(dev);
- struct fec_enet_private *fep = netdev_priv(ndev);
-
- + rtnl_lock();
- if (netif_running(ndev)) {
- - fec_stop(ndev);
- + phy_stop(fep->phy_dev);
- + napi_disable(&fep->napi);
- + netif_tx_lock_bh(ndev);
- netif_device_detach(ndev);
- + netif_tx_unlock_bh(ndev);
- + fec_stop(ndev);
- }
- - if (fep->clk_ptp)
- - clk_disable_unprepare(fep->clk_ptp);
- - if (fep->clk_enet_out)
- - clk_disable_unprepare(fep->clk_enet_out);
- - clk_disable_unprepare(fep->clk_ipg);
- - clk_disable_unprepare(fep->clk_ahb);
- + rtnl_unlock();
- +
- + fec_enet_clk_enable(ndev, false);
- + pinctrl_pm_select_sleep_state(&fep->pdev->dev);
-
- if (fep->reg_phy)
- regulator_disable(fep->reg_phy);
- @@ -2325,48 +2775,49 @@
- return ret;
- }
-
- - ret = clk_prepare_enable(fep->clk_ahb);
- - if (ret)
- - goto failed_clk_ahb;
- -
- - ret = clk_prepare_enable(fep->clk_ipg);
- + pinctrl_pm_select_default_state(&fep->pdev->dev);
- + ret = fec_enet_clk_enable(ndev, true);
- if (ret)
- - goto failed_clk_ipg;
- -
- - if (fep->clk_enet_out) {
- - ret = clk_prepare_enable(fep->clk_enet_out);
- - if (ret)
- - goto failed_clk_enet_out;
- - }
- -
- - if (fep->clk_ptp) {
- - ret = clk_prepare_enable(fep->clk_ptp);
- - if (ret)
- - goto failed_clk_ptp;
- - }
- + goto failed_clk;
-
- + rtnl_lock();
- if (netif_running(ndev)) {
- - fec_restart(ndev, fep->full_duplex);
- + fec_restart(ndev);
- + netif_tx_lock_bh(ndev);
- netif_device_attach(ndev);
- + netif_tx_unlock_bh(ndev);
- + napi_enable(&fep->napi);
- + phy_start(fep->phy_dev);
- }
- + rtnl_unlock();
-
- return 0;
-
- -failed_clk_ptp:
- - if (fep->clk_enet_out)
- - clk_disable_unprepare(fep->clk_enet_out);
- -failed_clk_enet_out:
- - clk_disable_unprepare(fep->clk_ipg);
- -failed_clk_ipg:
- - clk_disable_unprepare(fep->clk_ahb);
- -failed_clk_ahb:
- +failed_clk:
- if (fep->reg_phy)
- regulator_disable(fep->reg_phy);
- return ret;
- }
- +
- +static int fec_runtime_suspend(struct device *dev)
- +{
- + release_bus_freq(BUS_FREQ_HIGH);
- + return 0;
- +}
- +
- +static int fec_runtime_resume(struct device *dev)
- +{
- + request_bus_freq(BUS_FREQ_HIGH);
- + return 0;
- +}
- +
- +static const struct dev_pm_ops fec_pm_ops = {
- + SET_RUNTIME_PM_OPS(fec_runtime_suspend, fec_runtime_resume, NULL)
- + SET_SYSTEM_SLEEP_PM_OPS(fec_suspend, fec_resume)
- +};
- +
- #endif /* CONFIG_PM_SLEEP */
-
- -static SIMPLE_DEV_PM_OPS(fec_pm_ops, fec_suspend, fec_resume);
-
- static struct platform_driver fec_driver = {
- .driver = {
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/freescale/fec_ptp.c linux-3.14.35/drivers/net/ethernet/freescale/fec_ptp.c
- --- linux-3.14.35.orig/drivers/net/ethernet/freescale/fec_ptp.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/freescale/fec_ptp.c 2015-03-08 14:27:37.681684500 -0500
- @@ -372,6 +372,7 @@
- fep->ptp_caps.n_alarm = 0;
- fep->ptp_caps.n_ext_ts = 0;
- fep->ptp_caps.n_per_out = 0;
- + fep->ptp_caps.n_pins = 0;
- fep->ptp_caps.pps = 0;
- fep->ptp_caps.adjfreq = fec_ptp_adjfreq;
- fep->ptp_caps.adjtime = fec_ptp_adjtime;
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c linux-3.14.35/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
- --- linux-3.14.35.orig/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c 2015-03-08 14:27:37.681684500 -0500
- @@ -91,6 +91,9 @@
- u16 pkt_len, sc;
- int curidx;
-
- + if (budget <= 0)
- + return received;
- +
- /*
- * First, grab all of the stats for the incoming packet.
- * These get messed up if we get called due to a busy condition.
- @@ -789,10 +792,6 @@
- phydev = of_phy_connect(dev, fep->fpi->phy_node, &fs_adjust_link, 0,
- iface);
- if (!phydev) {
- - phydev = of_phy_connect_fixed_link(dev, &fs_adjust_link,
- - iface);
- - }
- - if (!phydev) {
- dev_err(&dev->dev, "Could not attach to PHY\n");
- return -ENODEV;
- }
- @@ -1026,9 +1025,16 @@
- fpi->use_napi = 1;
- fpi->napi_weight = 17;
- fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0);
- - if ((!fpi->phy_node) && (!of_get_property(ofdev->dev.of_node, "fixed-link",
- - NULL)))
- - goto out_free_fpi;
- + if (!fpi->phy_node && of_phy_is_fixed_link(ofdev->dev.of_node)) {
- + err = of_phy_register_fixed_link(ofdev->dev.of_node);
- + if (err)
- + goto out_free_fpi;
- +
- + /* In the case of a fixed PHY, the DT node associated
- + * to the PHY is the Ethernet MAC DT node.
- + */
- + fpi->phy_node = ofdev->dev.of_node;
- + }
-
- if (of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc5125-fec")) {
- phy_connection_type = of_get_property(ofdev->dev.of_node,
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/freescale/fs_enet/mii-fec.c linux-3.14.35/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
- --- linux-3.14.35.orig/drivers/net/ethernet/freescale/fs_enet/mii-fec.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/freescale/fs_enet/mii-fec.c 2015-03-08 14:27:37.681684500 -0500
- @@ -95,12 +95,6 @@
-
- }
-
- -static int fs_enet_fec_mii_reset(struct mii_bus *bus)
- -{
- - /* nothing here - for now */
- - return 0;
- -}
- -
- static struct of_device_id fs_enet_mdio_fec_match[];
- static int fs_enet_mdio_probe(struct platform_device *ofdev)
- {
- @@ -128,7 +122,6 @@
- new_bus->name = "FEC MII Bus";
- new_bus->read = &fs_enet_fec_mii_read;
- new_bus->write = &fs_enet_fec_mii_write;
- - new_bus->reset = &fs_enet_fec_mii_reset;
-
- ret = of_address_to_resource(ofdev->dev.of_node, 0, &res);
- if (ret)
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/freescale/gianfar.c linux-3.14.35/drivers/net/ethernet/freescale/gianfar.c
- --- linux-3.14.35.orig/drivers/net/ethernet/freescale/gianfar.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/freescale/gianfar.c 2015-03-08 14:27:37.681684500 -0500
- @@ -9,7 +9,7 @@
- * Maintainer: Kumar Gala
- * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>
- *
- - * Copyright 2002-2009, 2011 Freescale Semiconductor, Inc.
- + * Copyright 2002-2009, 2011-2013 Freescale Semiconductor, Inc.
- * Copyright 2007 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- @@ -121,7 +121,7 @@
- static irqreturn_t gfar_transmit(int irq, void *dev_id);
- static irqreturn_t gfar_interrupt(int irq, void *dev_id);
- static void adjust_link(struct net_device *dev);
- -static void init_registers(struct net_device *dev);
- +static noinline void gfar_update_link_state(struct gfar_private *priv);
- static int init_phy(struct net_device *dev);
- static int gfar_probe(struct platform_device *ofdev);
- static int gfar_remove(struct platform_device *ofdev);
- @@ -129,8 +129,10 @@
- static void gfar_set_multi(struct net_device *dev);
- static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
- static void gfar_configure_serdes(struct net_device *dev);
- -static int gfar_poll(struct napi_struct *napi, int budget);
- -static int gfar_poll_sq(struct napi_struct *napi, int budget);
- +static int gfar_poll_rx(struct napi_struct *napi, int budget);
- +static int gfar_poll_tx(struct napi_struct *napi, int budget);
- +static int gfar_poll_rx_sq(struct napi_struct *napi, int budget);
- +static int gfar_poll_tx_sq(struct napi_struct *napi, int budget);
- #ifdef CONFIG_NET_POLL_CONTROLLER
- static void gfar_netpoll(struct net_device *dev);
- #endif
- @@ -138,9 +140,7 @@
- static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue);
- static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
- int amount_pull, struct napi_struct *napi);
- -void gfar_halt(struct net_device *dev);
- -static void gfar_halt_nodisable(struct net_device *dev);
- -void gfar_start(struct net_device *dev);
- +static void gfar_halt_nodisable(struct gfar_private *priv);
- static void gfar_clear_exact_match(struct net_device *dev);
- static void gfar_set_mac_for_addr(struct net_device *dev, int num,
- const u8 *addr);
- @@ -332,72 +332,76 @@
- }
- }
-
- -static void gfar_init_mac(struct net_device *ndev)
- +static void gfar_rx_buff_size_config(struct gfar_private *priv)
- {
- - struct gfar_private *priv = netdev_priv(ndev);
- - struct gfar __iomem *regs = priv->gfargrp[0].regs;
- - u32 rctrl = 0;
- - u32 tctrl = 0;
- - u32 attrs = 0;
- -
- - /* write the tx/rx base registers */
- - gfar_init_tx_rx_base(priv);
- -
- - /* Configure the coalescing support */
- - gfar_configure_coalescing_all(priv);
- + int frame_size = priv->ndev->mtu + ETH_HLEN;
-
- /* set this when rx hw offload (TOE) functions are being used */
- priv->uses_rxfcb = 0;
-
- + if (priv->ndev->features & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX))
- + priv->uses_rxfcb = 1;
- +
- + if (priv->hwts_rx_en)
- + priv->uses_rxfcb = 1;
- +
- + if (priv->uses_rxfcb)
- + frame_size += GMAC_FCB_LEN;
- +
- + frame_size += priv->padding;
- +
- + frame_size = (frame_size & ~(INCREMENTAL_BUFFER_SIZE - 1)) +
- + INCREMENTAL_BUFFER_SIZE;
- +
- + priv->rx_buffer_size = frame_size;
- +}
- +
- +static void gfar_mac_rx_config(struct gfar_private *priv)
- +{
- + struct gfar __iomem *regs = priv->gfargrp[0].regs;
- + u32 rctrl = 0;
- +
- if (priv->rx_filer_enable) {
- rctrl |= RCTRL_FILREN;
- /* Program the RIR0 reg with the required distribution */
- - gfar_write(®s->rir0, DEFAULT_RIR0);
- + if (priv->poll_mode == GFAR_SQ_POLLING)
- + gfar_write(®s->rir0, DEFAULT_2RXQ_RIR0);
- + else /* GFAR_MQ_POLLING */
- + gfar_write(®s->rir0, DEFAULT_8RXQ_RIR0);
- }
-
- /* Restore PROMISC mode */
- - if (ndev->flags & IFF_PROMISC)
- + if (priv->ndev->flags & IFF_PROMISC)
- rctrl |= RCTRL_PROM;
-
- - if (ndev->features & NETIF_F_RXCSUM) {
- + if (priv->ndev->features & NETIF_F_RXCSUM)
- rctrl |= RCTRL_CHECKSUMMING;
- - priv->uses_rxfcb = 1;
- - }
- -
- - if (priv->extended_hash) {
- - rctrl |= RCTRL_EXTHASH;
-
- - gfar_clear_exact_match(ndev);
- - rctrl |= RCTRL_EMEN;
- - }
- + if (priv->extended_hash)
- + rctrl |= RCTRL_EXTHASH | RCTRL_EMEN;
-
- if (priv->padding) {
- rctrl &= ~RCTRL_PAL_MASK;
- rctrl |= RCTRL_PADDING(priv->padding);
- }
-
- - /* Insert receive time stamps into padding alignment bytes */
- - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) {
- - rctrl &= ~RCTRL_PAL_MASK;
- - rctrl |= RCTRL_PADDING(8);
- - priv->padding = 8;
- - }
- -
- /* Enable HW time stamping if requested from user space */
- - if (priv->hwts_rx_en) {
- + if (priv->hwts_rx_en)
- rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE;
- - priv->uses_rxfcb = 1;
- - }
-
- - if (ndev->features & NETIF_F_HW_VLAN_CTAG_RX) {
- + if (priv->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)
- rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
- - priv->uses_rxfcb = 1;
- - }
-
- /* Init rctrl based on our settings */
- gfar_write(®s->rctrl, rctrl);
- +}
-
- - if (ndev->features & NETIF_F_IP_CSUM)
- +static void gfar_mac_tx_config(struct gfar_private *priv)
- +{
- + struct gfar __iomem *regs = priv->gfargrp[0].regs;
- + u32 tctrl = 0;
- +
- + if (priv->ndev->features & NETIF_F_IP_CSUM)
- tctrl |= TCTRL_INIT_CSUM;
-
- if (priv->prio_sched_en)
- @@ -408,30 +412,51 @@
- gfar_write(®s->tr47wt, DEFAULT_WRRS_WEIGHT);
- }
-
- - gfar_write(®s->tctrl, tctrl);
- + if (priv->ndev->features & NETIF_F_HW_VLAN_CTAG_TX)
- + tctrl |= TCTRL_VLINS;
-
- - /* Set the extraction length and index */
- - attrs = ATTRELI_EL(priv->rx_stash_size) |
- - ATTRELI_EI(priv->rx_stash_index);
- + gfar_write(®s->tctrl, tctrl);
- +}
-
- - gfar_write(®s->attreli, attrs);
- +static void gfar_configure_coalescing(struct gfar_private *priv,
- + unsigned long tx_mask, unsigned long rx_mask)
- +{
- + struct gfar __iomem *regs = priv->gfargrp[0].regs;
- + u32 __iomem *baddr;
-
- - /* Start with defaults, and add stashing or locking
- - * depending on the approprate variables
- - */
- - attrs = ATTR_INIT_SETTINGS;
- + if (priv->mode == MQ_MG_MODE) {
- + int i = 0;
-
- - if (priv->bd_stash_en)
- - attrs |= ATTR_BDSTASH;
- + baddr = ®s->txic0;
- + for_each_set_bit(i, &tx_mask, priv->num_tx_queues) {
- + gfar_write(baddr + i, 0);
- + if (likely(priv->tx_queue[i]->txcoalescing))
- + gfar_write(baddr + i, priv->tx_queue[i]->txic);
- + }
-
- - if (priv->rx_stash_size != 0)
- - attrs |= ATTR_BUFSTASH;
- + baddr = ®s->rxic0;
- + for_each_set_bit(i, &rx_mask, priv->num_rx_queues) {
- + gfar_write(baddr + i, 0);
- + if (likely(priv->rx_queue[i]->rxcoalescing))
- + gfar_write(baddr + i, priv->rx_queue[i]->rxic);
- + }
- + } else {
- + /* Backward compatible case -- even if we enable
- + * multiple queues, there's only single reg to program
- + */
- + gfar_write(®s->txic, 0);
- + if (likely(priv->tx_queue[0]->txcoalescing))
- + gfar_write(®s->txic, priv->tx_queue[0]->txic);
-
- - gfar_write(®s->attr, attrs);
- + gfar_write(®s->rxic, 0);
- + if (unlikely(priv->rx_queue[0]->rxcoalescing))
- + gfar_write(®s->rxic, priv->rx_queue[0]->rxic);
- + }
- +}
-
- - gfar_write(®s->fifo_tx_thr, priv->fifo_threshold);
- - gfar_write(®s->fifo_tx_starve, priv->fifo_starve);
- - gfar_write(®s->fifo_tx_starve_shutoff, priv->fifo_starve_off);
- +void gfar_configure_coalescing_all(struct gfar_private *priv)
- +{
- + gfar_configure_coalescing(priv, 0xFF, 0xFF);
- }
-
- static struct net_device_stats *gfar_get_stats(struct net_device *dev)
- @@ -479,12 +504,27 @@
- #endif
- };
-
- -void lock_rx_qs(struct gfar_private *priv)
- +static void gfar_ints_disable(struct gfar_private *priv)
- {
- int i;
- + for (i = 0; i < priv->num_grps; i++) {
- + struct gfar __iomem *regs = priv->gfargrp[i].regs;
- + /* Clear IEVENT */
- + gfar_write(®s->ievent, IEVENT_INIT_CLEAR);
-
- - for (i = 0; i < priv->num_rx_queues; i++)
- - spin_lock(&priv->rx_queue[i]->rxlock);
- + /* Initialize IMASK */
- + gfar_write(®s->imask, IMASK_INIT_CLEAR);
- + }
- +}
- +
- +static void gfar_ints_enable(struct gfar_private *priv)
- +{
- + int i;
- + for (i = 0; i < priv->num_grps; i++) {
- + struct gfar __iomem *regs = priv->gfargrp[i].regs;
- + /* Unmask the interrupts we look for */
- + gfar_write(®s->imask, IMASK_DEFAULT);
- + }
- }
-
- void lock_tx_qs(struct gfar_private *priv)
- @@ -495,23 +535,50 @@
- spin_lock(&priv->tx_queue[i]->txlock);
- }
-
- -void unlock_rx_qs(struct gfar_private *priv)
- +void unlock_tx_qs(struct gfar_private *priv)
- {
- int i;
-
- - for (i = 0; i < priv->num_rx_queues; i++)
- - spin_unlock(&priv->rx_queue[i]->rxlock);
- + for (i = 0; i < priv->num_tx_queues; i++)
- + spin_unlock(&priv->tx_queue[i]->txlock);
- }
-
- -void unlock_tx_qs(struct gfar_private *priv)
- +static int gfar_alloc_tx_queues(struct gfar_private *priv)
- {
- int i;
-
- - for (i = 0; i < priv->num_tx_queues; i++)
- - spin_unlock(&priv->tx_queue[i]->txlock);
- + for (i = 0; i < priv->num_tx_queues; i++) {
- + priv->tx_queue[i] = kzalloc(sizeof(struct gfar_priv_tx_q),
- + GFP_KERNEL);
- + if (!priv->tx_queue[i])
- + return -ENOMEM;
- +
- + priv->tx_queue[i]->tx_skbuff = NULL;
- + priv->tx_queue[i]->qindex = i;
- + priv->tx_queue[i]->dev = priv->ndev;
- + spin_lock_init(&(priv->tx_queue[i]->txlock));
- + }
- + return 0;
- +}
- +
- +static int gfar_alloc_rx_queues(struct gfar_private *priv)
- +{
- + int i;
- +
- + for (i = 0; i < priv->num_rx_queues; i++) {
- + priv->rx_queue[i] = kzalloc(sizeof(struct gfar_priv_rx_q),
- + GFP_KERNEL);
- + if (!priv->rx_queue[i])
- + return -ENOMEM;
- +
- + priv->rx_queue[i]->rx_skbuff = NULL;
- + priv->rx_queue[i]->qindex = i;
- + priv->rx_queue[i]->dev = priv->ndev;
- + }
- + return 0;
- }
-
- -static void free_tx_pointers(struct gfar_private *priv)
- +static void gfar_free_tx_queues(struct gfar_private *priv)
- {
- int i;
-
- @@ -519,7 +586,7 @@
- kfree(priv->tx_queue[i]);
- }
-
- -static void free_rx_pointers(struct gfar_private *priv)
- +static void gfar_free_rx_queues(struct gfar_private *priv)
- {
- int i;
-
- @@ -553,23 +620,26 @@
- {
- int i;
-
- - for (i = 0; i < priv->num_grps; i++)
- - napi_disable(&priv->gfargrp[i].napi);
- + for (i = 0; i < priv->num_grps; i++) {
- + napi_disable(&priv->gfargrp[i].napi_rx);
- + napi_disable(&priv->gfargrp[i].napi_tx);
- + }
- }
-
- static void enable_napi(struct gfar_private *priv)
- {
- int i;
-
- - for (i = 0; i < priv->num_grps; i++)
- - napi_enable(&priv->gfargrp[i].napi);
- + for (i = 0; i < priv->num_grps; i++) {
- + napi_enable(&priv->gfargrp[i].napi_rx);
- + napi_enable(&priv->gfargrp[i].napi_tx);
- + }
- }
-
- static int gfar_parse_group(struct device_node *np,
- struct gfar_private *priv, const char *model)
- {
- struct gfar_priv_grp *grp = &priv->gfargrp[priv->num_grps];
- - u32 *queue_mask;
- int i;
-
- for (i = 0; i < GFAR_NUM_IRQS; i++) {
- @@ -598,16 +668,52 @@
- grp->priv = priv;
- spin_lock_init(&grp->grplock);
- if (priv->mode == MQ_MG_MODE) {
- - queue_mask = (u32 *)of_get_property(np, "fsl,rx-bit-map", NULL);
- - grp->rx_bit_map = queue_mask ?
- - *queue_mask : (DEFAULT_MAPPING >> priv->num_grps);
- - queue_mask = (u32 *)of_get_property(np, "fsl,tx-bit-map", NULL);
- - grp->tx_bit_map = queue_mask ?
- - *queue_mask : (DEFAULT_MAPPING >> priv->num_grps);
- + u32 *rxq_mask, *txq_mask;
- + rxq_mask = (u32 *)of_get_property(np, "fsl,rx-bit-map", NULL);
- + txq_mask = (u32 *)of_get_property(np, "fsl,tx-bit-map", NULL);
- +
- + if (priv->poll_mode == GFAR_SQ_POLLING) {
- + /* One Q per interrupt group: Q0 to G0, Q1 to G1 */
- + grp->rx_bit_map = (DEFAULT_MAPPING >> priv->num_grps);
- + grp->tx_bit_map = (DEFAULT_MAPPING >> priv->num_grps);
- + } else { /* GFAR_MQ_POLLING */
- + grp->rx_bit_map = rxq_mask ?
- + *rxq_mask : (DEFAULT_MAPPING >> priv->num_grps);
- + grp->tx_bit_map = txq_mask ?
- + *txq_mask : (DEFAULT_MAPPING >> priv->num_grps);
- + }
- } else {
- grp->rx_bit_map = 0xFF;
- grp->tx_bit_map = 0xFF;
- }
- +
- + /* bit_map's MSB is q0 (from q0 to q7) but, for_each_set_bit parses
- + * right to left, so we need to revert the 8 bits to get the q index
- + */
- + grp->rx_bit_map = bitrev8(grp->rx_bit_map);
- + grp->tx_bit_map = bitrev8(grp->tx_bit_map);
- +
- + /* Calculate RSTAT, TSTAT, RQUEUE and TQUEUE values,
- + * also assign queues to groups
- + */
- + for_each_set_bit(i, &grp->rx_bit_map, priv->num_rx_queues) {
- + if (!grp->rx_queue)
- + grp->rx_queue = priv->rx_queue[i];
- + grp->num_rx_queues++;
- + grp->rstat |= (RSTAT_CLEAR_RHALT >> i);
- + priv->rqueue |= ((RQUEUE_EN0 | RQUEUE_EX0) >> i);
- + priv->rx_queue[i]->grp = grp;
- + }
- +
- + for_each_set_bit(i, &grp->tx_bit_map, priv->num_tx_queues) {
- + if (!grp->tx_queue)
- + grp->tx_queue = priv->tx_queue[i];
- + grp->num_tx_queues++;
- + grp->tstat |= (TSTAT_CLEAR_THALT >> i);
- + priv->tqueue |= (TQUEUE_EN0 >> i);
- + priv->tx_queue[i]->grp = grp;
- + }
- +
- priv->num_grps++;
-
- return 0;
- @@ -628,13 +734,45 @@
- const u32 *stash_idx;
- unsigned int num_tx_qs, num_rx_qs;
- u32 *tx_queues, *rx_queues;
- + unsigned short mode, poll_mode;
-
- if (!np || !of_device_is_available(np))
- return -ENODEV;
-
- - /* parse the num of tx and rx queues */
- + if (of_device_is_compatible(np, "fsl,etsec2")) {
- + mode = MQ_MG_MODE;
- + poll_mode = GFAR_SQ_POLLING;
- + } else {
- + mode = SQ_SG_MODE;
- + poll_mode = GFAR_SQ_POLLING;
- + }
- +
- + /* parse the num of HW tx and rx queues */
- tx_queues = (u32 *)of_get_property(np, "fsl,num_tx_queues", NULL);
- - num_tx_qs = tx_queues ? *tx_queues : 1;
- + rx_queues = (u32 *)of_get_property(np, "fsl,num_rx_queues", NULL);
- +
- + if (mode == SQ_SG_MODE) {
- + num_tx_qs = 1;
- + num_rx_qs = 1;
- + } else { /* MQ_MG_MODE */
- + /* get the actual number of supported groups */
- + unsigned int num_grps = of_get_available_child_count(np);
- +
- + if (num_grps == 0 || num_grps > MAXGROUPS) {
- + dev_err(&ofdev->dev, "Invalid # of int groups(%d)\n",
- + num_grps);
- + pr_err("Cannot do alloc_etherdev, aborting\n");
- + return -EINVAL;
- + }
- +
- + if (poll_mode == GFAR_SQ_POLLING) {
- + num_tx_qs = num_grps; /* one txq per int group */
- + num_rx_qs = num_grps; /* one rxq per int group */
- + } else { /* GFAR_MQ_POLLING */
- + num_tx_qs = tx_queues ? *tx_queues : 1;
- + num_rx_qs = rx_queues ? *rx_queues : 1;
- + }
- + }
-
- if (num_tx_qs > MAX_TX_QS) {
- pr_err("num_tx_qs(=%d) greater than MAX_TX_QS(=%d)\n",
- @@ -643,9 +781,6 @@
- return -EINVAL;
- }
-
- - rx_queues = (u32 *)of_get_property(np, "fsl,num_rx_queues", NULL);
- - num_rx_qs = rx_queues ? *rx_queues : 1;
- -
- if (num_rx_qs > MAX_RX_QS) {
- pr_err("num_rx_qs(=%d) greater than MAX_RX_QS(=%d)\n",
- num_rx_qs, MAX_RX_QS);
- @@ -661,10 +796,20 @@
- priv = netdev_priv(dev);
- priv->ndev = dev;
-
- + priv->mode = mode;
- + priv->poll_mode = poll_mode;
- +
- priv->num_tx_queues = num_tx_qs;
- netif_set_real_num_rx_queues(dev, num_rx_qs);
- priv->num_rx_queues = num_rx_qs;
- - priv->num_grps = 0x0;
- +
- + err = gfar_alloc_tx_queues(priv);
- + if (err)
- + goto tx_alloc_failed;
- +
- + err = gfar_alloc_rx_queues(priv);
- + if (err)
- + goto rx_alloc_failed;
-
- /* Init Rx queue filer rule set linked list */
- INIT_LIST_HEAD(&priv->rx_list.list);
- @@ -677,52 +822,18 @@
- priv->gfargrp[i].regs = NULL;
-
- /* Parse and initialize group specific information */
- - if (of_device_is_compatible(np, "fsl,etsec2")) {
- - priv->mode = MQ_MG_MODE;
- + if (priv->mode == MQ_MG_MODE) {
- for_each_child_of_node(np, child) {
- err = gfar_parse_group(child, priv, model);
- if (err)
- goto err_grp_init;
- }
- - } else {
- - priv->mode = SQ_SG_MODE;
- + } else { /* SQ_SG_MODE */
- err = gfar_parse_group(np, priv, model);
- if (err)
- goto err_grp_init;
- }
-
- - for (i = 0; i < priv->num_tx_queues; i++)
- - priv->tx_queue[i] = NULL;
- - for (i = 0; i < priv->num_rx_queues; i++)
- - priv->rx_queue[i] = NULL;
- -
- - for (i = 0; i < priv->num_tx_queues; i++) {
- - priv->tx_queue[i] = kzalloc(sizeof(struct gfar_priv_tx_q),
- - GFP_KERNEL);
- - if (!priv->tx_queue[i]) {
- - err = -ENOMEM;
- - goto tx_alloc_failed;
- - }
- - priv->tx_queue[i]->tx_skbuff = NULL;
- - priv->tx_queue[i]->qindex = i;
- - priv->tx_queue[i]->dev = dev;
- - spin_lock_init(&(priv->tx_queue[i]->txlock));
- - }
- -
- - for (i = 0; i < priv->num_rx_queues; i++) {
- - priv->rx_queue[i] = kzalloc(sizeof(struct gfar_priv_rx_q),
- - GFP_KERNEL);
- - if (!priv->rx_queue[i]) {
- - err = -ENOMEM;
- - goto rx_alloc_failed;
- - }
- - priv->rx_queue[i]->rx_skbuff = NULL;
- - priv->rx_queue[i]->qindex = i;
- - priv->rx_queue[i]->dev = dev;
- - spin_lock_init(&(priv->rx_queue[i]->rxlock));
- - }
- -
- -
- stash = of_get_property(np, "bd-stash", NULL);
-
- if (stash) {
- @@ -749,17 +860,16 @@
- memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
-
- if (model && !strcasecmp(model, "TSEC"))
- - priv->device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
- + priv->device_flags |= FSL_GIANFAR_DEV_HAS_GIGABIT |
- FSL_GIANFAR_DEV_HAS_COALESCE |
- FSL_GIANFAR_DEV_HAS_RMON |
- FSL_GIANFAR_DEV_HAS_MULTI_INTR;
-
- if (model && !strcasecmp(model, "eTSEC"))
- - priv->device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
- + priv->device_flags |= FSL_GIANFAR_DEV_HAS_GIGABIT |
- FSL_GIANFAR_DEV_HAS_COALESCE |
- FSL_GIANFAR_DEV_HAS_RMON |
- FSL_GIANFAR_DEV_HAS_MULTI_INTR |
- - FSL_GIANFAR_DEV_HAS_PADDING |
- FSL_GIANFAR_DEV_HAS_CSUM |
- FSL_GIANFAR_DEV_HAS_VLAN |
- FSL_GIANFAR_DEV_HAS_MAGIC_PACKET |
- @@ -779,17 +889,28 @@
-
- priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
-
- + /* In the case of a fixed PHY, the DT node associated
- + * to the PHY is the Ethernet MAC DT node.
- + */
- + if (of_phy_is_fixed_link(np)) {
- + err = of_phy_register_fixed_link(np);
- + if (err)
- + goto err_grp_init;
- +
- + priv->phy_node = np;
- + }
- +
- /* Find the TBI PHY. If it's not there, we don't support SGMII */
- priv->tbi_node = of_parse_phandle(np, "tbi-handle", 0);
-
- return 0;
-
- -rx_alloc_failed:
- - free_rx_pointers(priv);
- -tx_alloc_failed:
- - free_tx_pointers(priv);
- err_grp_init:
- unmap_group_regs(priv);
- +rx_alloc_failed:
- + gfar_free_rx_queues(priv);
- +tx_alloc_failed:
- + gfar_free_tx_queues(priv);
- free_gfar_dev(priv);
- return err;
- }
- @@ -822,18 +943,16 @@
- switch (config.rx_filter) {
- case HWTSTAMP_FILTER_NONE:
- if (priv->hwts_rx_en) {
- - stop_gfar(netdev);
- priv->hwts_rx_en = 0;
- - startup_gfar(netdev);
- + reset_gfar(netdev);
- }
- break;
- default:
- if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER))
- return -ERANGE;
- if (!priv->hwts_rx_en) {
- - stop_gfar(netdev);
- priv->hwts_rx_en = 1;
- - startup_gfar(netdev);
- + reset_gfar(netdev);
- }
- config.rx_filter = HWTSTAMP_FILTER_ALL;
- break;
- @@ -875,19 +994,6 @@
- return phy_mii_ioctl(priv->phydev, rq, cmd);
- }
-
- -static unsigned int reverse_bitmap(unsigned int bit_map, unsigned int max_qs)
- -{
- - unsigned int new_bit_map = 0x0;
- - int mask = 0x1 << (max_qs - 1), i;
- -
- - for (i = 0; i < max_qs; i++) {
- - if (bit_map & mask)
- - new_bit_map = new_bit_map + (1 << i);
- - mask = mask >> 0x1;
- - }
- - return new_bit_map;
- -}
- -
- static u32 cluster_entry_per_class(struct gfar_private *priv, u32 rqfar,
- u32 class)
- {
- @@ -1005,100 +1111,141 @@
- priv->errata);
- }
-
- -/* Set up the ethernet device structure, private data,
- - * and anything else we need before we start
- - */
- -static int gfar_probe(struct platform_device *ofdev)
- +void gfar_mac_reset(struct gfar_private *priv)
- {
- + struct gfar __iomem *regs = priv->gfargrp[0].regs;
- u32 tempval;
- - struct net_device *dev = NULL;
- - struct gfar_private *priv = NULL;
- - struct gfar __iomem *regs = NULL;
- - int err = 0, i, grp_idx = 0;
- - u32 rstat = 0, tstat = 0, rqueue = 0, tqueue = 0;
- - u32 isrg = 0;
- - u32 __iomem *baddr;
- -
- - err = gfar_of_init(ofdev, &dev);
- -
- - if (err)
- - return err;
- -
- - priv = netdev_priv(dev);
- - priv->ndev = dev;
- - priv->ofdev = ofdev;
- - priv->dev = &ofdev->dev;
- - SET_NETDEV_DEV(dev, &ofdev->dev);
- -
- - spin_lock_init(&priv->bflock);
- - INIT_WORK(&priv->reset_task, gfar_reset_task);
- -
- - platform_set_drvdata(ofdev, priv);
- - regs = priv->gfargrp[0].regs;
- -
- - gfar_detect_errata(priv);
- -
- - /* Stop the DMA engine now, in case it was running before
- - * (The firmware could have used it, and left it running).
- - */
- - gfar_halt(dev);
-
- /* Reset MAC layer */
- gfar_write(®s->maccfg1, MACCFG1_SOFT_RESET);
-
- /* We need to delay at least 3 TX clocks */
- - udelay(2);
- + udelay(3);
-
- - tempval = 0;
- - if (!priv->pause_aneg_en && priv->tx_pause_en)
- - tempval |= MACCFG1_TX_FLOW;
- - if (!priv->pause_aneg_en && priv->rx_pause_en)
- - tempval |= MACCFG1_RX_FLOW;
- /* the soft reset bit is not self-resetting, so we need to
- * clear it before resuming normal operation
- */
- - gfar_write(®s->maccfg1, tempval);
- + gfar_write(®s->maccfg1, 0);
-
- - /* Initialize MACCFG2. */
- - tempval = MACCFG2_INIT_SETTINGS;
- - if (gfar_has_errata(priv, GFAR_ERRATA_74))
- - tempval |= MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK;
- - gfar_write(®s->maccfg2, tempval);
- + udelay(3);
-
- - /* Initialize ECNTRL */
- - gfar_write(®s->ecntrl, ECNTRL_INIT_SETTINGS);
- + /* Compute rx_buff_size based on config flags */
- + gfar_rx_buff_size_config(priv);
-
- - /* Set the dev->base_addr to the gfar reg region */
- - dev->base_addr = (unsigned long) regs;
- + /* Initialize the max receive frame/buffer lengths */
- + gfar_write(®s->maxfrm, priv->rx_buffer_size);
- + gfar_write(®s->mrblr, priv->rx_buffer_size);
-
- - /* Fill in the dev structure */
- - dev->watchdog_timeo = TX_TIMEOUT;
- - dev->mtu = 1500;
- - dev->netdev_ops = &gfar_netdev_ops;
- - dev->ethtool_ops = &gfar_ethtool_ops;
- + /* Initialize the Minimum Frame Length Register */
- + gfar_write(®s->minflr, MINFLR_INIT_SETTINGS);
-
- - /* Register for napi ...We are registering NAPI for each grp */
- - if (priv->mode == SQ_SG_MODE)
- - netif_napi_add(dev, &priv->gfargrp[0].napi, gfar_poll_sq,
- - GFAR_DEV_WEIGHT);
- - else
- - for (i = 0; i < priv->num_grps; i++)
- - netif_napi_add(dev, &priv->gfargrp[i].napi, gfar_poll,
- - GFAR_DEV_WEIGHT);
- + /* Initialize MACCFG2. */
- + tempval = MACCFG2_INIT_SETTINGS;
-
- - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) {
- - dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
- - NETIF_F_RXCSUM;
- - dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG |
- - NETIF_F_RXCSUM | NETIF_F_HIGHDMA;
- - }
- + /* If the mtu is larger than the max size for standard
- + * ethernet frames (ie, a jumbo frame), then set maccfg2
- + * to allow huge frames, and to check the length
- + */
- + if (priv->rx_buffer_size > DEFAULT_RX_BUFFER_SIZE ||
- + gfar_has_errata(priv, GFAR_ERRATA_74))
- + tempval |= MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK;
-
- - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
- - dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX |
- - NETIF_F_HW_VLAN_CTAG_RX;
- - dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
- + gfar_write(®s->maccfg2, tempval);
- +
- + /* Clear mac addr hash registers */
- + gfar_write(®s->igaddr0, 0);
- + gfar_write(®s->igaddr1, 0);
- + gfar_write(®s->igaddr2, 0);
- + gfar_write(®s->igaddr3, 0);
- + gfar_write(®s->igaddr4, 0);
- + gfar_write(®s->igaddr5, 0);
- + gfar_write(®s->igaddr6, 0);
- + gfar_write(®s->igaddr7, 0);
- +
- + gfar_write(®s->gaddr0, 0);
- + gfar_write(®s->gaddr1, 0);
- + gfar_write(®s->gaddr2, 0);
- + gfar_write(®s->gaddr3, 0);
- + gfar_write(®s->gaddr4, 0);
- + gfar_write(®s->gaddr5, 0);
- + gfar_write(®s->gaddr6, 0);
- + gfar_write(®s->gaddr7, 0);
- +
- + if (priv->extended_hash)
- + gfar_clear_exact_match(priv->ndev);
- +
- + gfar_mac_rx_config(priv);
- +
- + gfar_mac_tx_config(priv);
- +
- + gfar_set_mac_address(priv->ndev);
- +
- + gfar_set_multi(priv->ndev);
- +
- + /* clear ievent and imask before configuring coalescing */
- + gfar_ints_disable(priv);
- +
- + /* Configure the coalescing support */
- + gfar_configure_coalescing_all(priv);
- +}
- +
- +static void gfar_hw_init(struct gfar_private *priv)
- +{
- + struct gfar __iomem *regs = priv->gfargrp[0].regs;
- + u32 attrs;
- +
- + /* Stop the DMA engine now, in case it was running before
- + * (The firmware could have used it, and left it running).
- + */
- + gfar_halt(priv);
- +
- + gfar_mac_reset(priv);
- +
- + /* Zero out the rmon mib registers if it has them */
- + if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
- + memset_io(&(regs->rmon), 0, sizeof(struct rmon_mib));
- +
- + /* Mask off the CAM interrupts */
- + gfar_write(®s->rmon.cam1, 0xffffffff);
- + gfar_write(®s->rmon.cam2, 0xffffffff);
- }
-
- + /* Initialize ECNTRL */
- + gfar_write(®s->ecntrl, ECNTRL_INIT_SETTINGS);
- +
- + /* Set the extraction length and index */
- + attrs = ATTRELI_EL(priv->rx_stash_size) |
- + ATTRELI_EI(priv->rx_stash_index);
- +
- + gfar_write(®s->attreli, attrs);
- +
- + /* Start with defaults, and add stashing
- + * depending on driver parameters
- + */
- + attrs = ATTR_INIT_SETTINGS;
- +
- + if (priv->bd_stash_en)
- + attrs |= ATTR_BDSTASH;
- +
- + if (priv->rx_stash_size != 0)
- + attrs |= ATTR_BUFSTASH;
- +
- + gfar_write(®s->attr, attrs);
- +
- + /* FIFO configs */
- + gfar_write(®s->fifo_tx_thr, DEFAULT_FIFO_TX_THR);
- + gfar_write(®s->fifo_tx_starve, DEFAULT_FIFO_TX_STARVE);
- + gfar_write(®s->fifo_tx_starve_shutoff, DEFAULT_FIFO_TX_STARVE_OFF);
- +
- + /* Program the interrupt steering regs, only for MG devices */
- + if (priv->num_grps > 1)
- + gfar_write_isrg(priv);
- +}
- +
- +static void gfar_init_addr_hash_table(struct gfar_private *priv)
- +{
- + struct gfar __iomem *regs = priv->gfargrp[0].regs;
- +
- if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) {
- priv->extended_hash = 1;
- priv->hash_width = 9;
- @@ -1133,68 +1280,81 @@
- priv->hash_regs[6] = ®s->gaddr6;
- priv->hash_regs[7] = ®s->gaddr7;
- }
- +}
-
- - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_PADDING)
- - priv->padding = DEFAULT_PADDING;
- - else
- - priv->padding = 0;
- +/* Set up the ethernet device structure, private data,
- + * and anything else we need before we start
- + */
- +static int gfar_probe(struct platform_device *ofdev)
- +{
- + struct net_device *dev = NULL;
- + struct gfar_private *priv = NULL;
- + int err = 0, i;
-
- - if (dev->features & NETIF_F_IP_CSUM ||
- - priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
- - dev->needed_headroom = GMAC_FCB_LEN;
- + err = gfar_of_init(ofdev, &dev);
-
- - /* Program the isrg regs only if number of grps > 1 */
- - if (priv->num_grps > 1) {
- - baddr = ®s->isrg0;
- - for (i = 0; i < priv->num_grps; i++) {
- - isrg |= (priv->gfargrp[i].rx_bit_map << ISRG_SHIFT_RX);
- - isrg |= (priv->gfargrp[i].tx_bit_map << ISRG_SHIFT_TX);
- - gfar_write(baddr, isrg);
- - baddr++;
- - isrg = 0x0;
- + if (err)
- + return err;
- +
- + priv = netdev_priv(dev);
- + priv->ndev = dev;
- + priv->ofdev = ofdev;
- + priv->dev = &ofdev->dev;
- + SET_NETDEV_DEV(dev, &ofdev->dev);
- +
- + spin_lock_init(&priv->bflock);
- + INIT_WORK(&priv->reset_task, gfar_reset_task);
- +
- + platform_set_drvdata(ofdev, priv);
- +
- + gfar_detect_errata(priv);
- +
- + /* Set the dev->base_addr to the gfar reg region */
- + dev->base_addr = (unsigned long) priv->gfargrp[0].regs;
- +
- + /* Fill in the dev structure */
- + dev->watchdog_timeo = TX_TIMEOUT;
- + dev->mtu = 1500;
- + dev->netdev_ops = &gfar_netdev_ops;
- + dev->ethtool_ops = &gfar_ethtool_ops;
- +
- + /* Register for napi ...We are registering NAPI for each grp */
- + for (i = 0; i < priv->num_grps; i++) {
- + if (priv->poll_mode == GFAR_SQ_POLLING) {
- + netif_napi_add(dev, &priv->gfargrp[i].napi_rx,
- + gfar_poll_rx_sq, GFAR_DEV_WEIGHT);
- + netif_napi_add(dev, &priv->gfargrp[i].napi_tx,
- + gfar_poll_tx_sq, 2);
- + } else {
- + netif_napi_add(dev, &priv->gfargrp[i].napi_rx,
- + gfar_poll_rx, GFAR_DEV_WEIGHT);
- + netif_napi_add(dev, &priv->gfargrp[i].napi_tx,
- + gfar_poll_tx, 2);
- }
- }
-
- - /* Need to reverse the bit maps as bit_map's MSB is q0
- - * but, for_each_set_bit parses from right to left, which
- - * basically reverses the queue numbers
- - */
- - for (i = 0; i< priv->num_grps; i++) {
- - priv->gfargrp[i].tx_bit_map =
- - reverse_bitmap(priv->gfargrp[i].tx_bit_map, MAX_TX_QS);
- - priv->gfargrp[i].rx_bit_map =
- - reverse_bitmap(priv->gfargrp[i].rx_bit_map, MAX_RX_QS);
- + if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) {
- + dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
- + NETIF_F_RXCSUM;
- + dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG |
- + NETIF_F_RXCSUM | NETIF_F_HIGHDMA;
- }
-
- - /* Calculate RSTAT, TSTAT, RQUEUE and TQUEUE values,
- - * also assign queues to groups
- - */
- - for (grp_idx = 0; grp_idx < priv->num_grps; grp_idx++) {
- - priv->gfargrp[grp_idx].num_rx_queues = 0x0;
- -
- - for_each_set_bit(i, &priv->gfargrp[grp_idx].rx_bit_map,
- - priv->num_rx_queues) {
- - priv->gfargrp[grp_idx].num_rx_queues++;
- - priv->rx_queue[i]->grp = &priv->gfargrp[grp_idx];
- - rstat = rstat | (RSTAT_CLEAR_RHALT >> i);
- - rqueue = rqueue | ((RQUEUE_EN0 | RQUEUE_EX0) >> i);
- - }
- - priv->gfargrp[grp_idx].num_tx_queues = 0x0;
- -
- - for_each_set_bit(i, &priv->gfargrp[grp_idx].tx_bit_map,
- - priv->num_tx_queues) {
- - priv->gfargrp[grp_idx].num_tx_queues++;
- - priv->tx_queue[i]->grp = &priv->gfargrp[grp_idx];
- - tstat = tstat | (TSTAT_CLEAR_THALT >> i);
- - tqueue = tqueue | (TQUEUE_EN0 >> i);
- - }
- - priv->gfargrp[grp_idx].rstat = rstat;
- - priv->gfargrp[grp_idx].tstat = tstat;
- - rstat = tstat =0;
- + if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
- + dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX |
- + NETIF_F_HW_VLAN_CTAG_RX;
- + dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
- }
-
- - gfar_write(®s->rqueue, rqueue);
- - gfar_write(®s->tqueue, tqueue);
- + gfar_init_addr_hash_table(priv);
- +
- + /* Insert receive time stamps into padding alignment bytes */
- + if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
- + priv->padding = 8;
- +
- + if (dev->features & NETIF_F_IP_CSUM ||
- + priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
- + dev->needed_headroom = GMAC_FCB_LEN;
-
- priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE;
-
- @@ -1220,6 +1380,10 @@
- if (priv->num_tx_queues == 1)
- priv->prio_sched_en = 1;
-
- + set_bit(GFAR_DOWN, &priv->state);
- +
- + gfar_hw_init(priv);
- +
- /* Carrier starts down, phylib will bring it up */
- netif_carrier_off(dev);
-
- @@ -1251,9 +1415,6 @@
- /* Initialize the filer table */
- gfar_init_filer_table(priv);
-
- - /* Create all the sysfs files */
- - gfar_init_sysfs(dev);
- -
- /* Print out the device info */
- netdev_info(dev, "mac: %pM\n", dev->dev_addr);
-
- @@ -1272,8 +1433,8 @@
-
- register_fail:
- unmap_group_regs(priv);
- - free_tx_pointers(priv);
- - free_rx_pointers(priv);
- + gfar_free_rx_queues(priv);
- + gfar_free_tx_queues(priv);
- if (priv->phy_node)
- of_node_put(priv->phy_node);
- if (priv->tbi_node)
- @@ -1293,6 +1454,8 @@
-
- unregister_netdev(priv->ndev);
- unmap_group_regs(priv);
- + gfar_free_rx_queues(priv);
- + gfar_free_tx_queues(priv);
- free_gfar_dev(priv);
-
- return 0;
- @@ -1318,9 +1481,8 @@
-
- local_irq_save(flags);
- lock_tx_qs(priv);
- - lock_rx_qs(priv);
-
- - gfar_halt_nodisable(ndev);
- + gfar_halt_nodisable(priv);
-
- /* Disable Tx, and Rx if wake-on-LAN is disabled. */
- tempval = gfar_read(®s->maccfg1);
- @@ -1332,7 +1494,6 @@
-
- gfar_write(®s->maccfg1, tempval);
-
- - unlock_rx_qs(priv);
- unlock_tx_qs(priv);
- local_irq_restore(flags);
-
- @@ -1378,15 +1539,13 @@
- */
- local_irq_save(flags);
- lock_tx_qs(priv);
- - lock_rx_qs(priv);
-
- tempval = gfar_read(®s->maccfg2);
- tempval &= ~MACCFG2_MPEN;
- gfar_write(®s->maccfg2, tempval);
-
- - gfar_start(ndev);
- + gfar_start(priv);
-
- - unlock_rx_qs(priv);
- unlock_tx_qs(priv);
- local_irq_restore(flags);
-
- @@ -1413,10 +1572,11 @@
- return -ENOMEM;
- }
-
- - init_registers(ndev);
- - gfar_set_mac_address(ndev);
- - gfar_init_mac(ndev);
- - gfar_start(ndev);
- + gfar_mac_reset(priv);
- +
- + gfar_init_tx_rx_base(priv);
- +
- + gfar_start(priv);
-
- priv->oldlink = 0;
- priv->oldspeed = 0;
- @@ -1511,9 +1671,6 @@
-
- priv->phydev = of_phy_connect(dev, priv->phy_node, &adjust_link, 0,
- interface);
- - if (!priv->phydev)
- - priv->phydev = of_phy_connect_fixed_link(dev, &adjust_link,
- - interface);
- if (!priv->phydev) {
- dev_err(&dev->dev, "could not attach to PHY\n");
- return -ENODEV;
- @@ -1574,57 +1731,6 @@
- BMCR_SPEED1000);
- }
-
- -static void init_registers(struct net_device *dev)
- -{
- - struct gfar_private *priv = netdev_priv(dev);
- - struct gfar __iomem *regs = NULL;
- - int i;
- -
- - for (i = 0; i < priv->num_grps; i++) {
- - regs = priv->gfargrp[i].regs;
- - /* Clear IEVENT */
- - gfar_write(®s->ievent, IEVENT_INIT_CLEAR);
- -
- - /* Initialize IMASK */
- - gfar_write(®s->imask, IMASK_INIT_CLEAR);
- - }
- -
- - regs = priv->gfargrp[0].regs;
- - /* Init hash registers to zero */
- - gfar_write(®s->igaddr0, 0);
- - gfar_write(®s->igaddr1, 0);
- - gfar_write(®s->igaddr2, 0);
- - gfar_write(®s->igaddr3, 0);
- - gfar_write(®s->igaddr4, 0);
- - gfar_write(®s->igaddr5, 0);
- - gfar_write(®s->igaddr6, 0);
- - gfar_write(®s->igaddr7, 0);
- -
- - gfar_write(®s->gaddr0, 0);
- - gfar_write(®s->gaddr1, 0);
- - gfar_write(®s->gaddr2, 0);
- - gfar_write(®s->gaddr3, 0);
- - gfar_write(®s->gaddr4, 0);
- - gfar_write(®s->gaddr5, 0);
- - gfar_write(®s->gaddr6, 0);
- - gfar_write(®s->gaddr7, 0);
- -
- - /* Zero out the rmon mib registers if it has them */
- - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
- - memset_io(&(regs->rmon), 0, sizeof (struct rmon_mib));
- -
- - /* Mask off the CAM interrupts */
- - gfar_write(®s->rmon.cam1, 0xffffffff);
- - gfar_write(®s->rmon.cam2, 0xffffffff);
- - }
- -
- - /* Initialize the max receive buffer length */
- - gfar_write(®s->mrblr, priv->rx_buffer_size);
- -
- - /* Initialize the Minimum Frame Length Register */
- - gfar_write(®s->minflr, MINFLR_INIT_SETTINGS);
- -}
- -
- static int __gfar_is_rx_idle(struct gfar_private *priv)
- {
- u32 res;
- @@ -1648,23 +1754,13 @@
- }
-
- /* Halt the receive and transmit queues */
- -static void gfar_halt_nodisable(struct net_device *dev)
- +static void gfar_halt_nodisable(struct gfar_private *priv)
- {
- - struct gfar_private *priv = netdev_priv(dev);
- - struct gfar __iomem *regs = NULL;
- + struct gfar __iomem *regs = priv->gfargrp[0].regs;
- u32 tempval;
- - int i;
- -
- - for (i = 0; i < priv->num_grps; i++) {
- - regs = priv->gfargrp[i].regs;
- - /* Mask all interrupts */
- - gfar_write(®s->imask, IMASK_INIT_CLEAR);
-
- - /* Clear all interrupts */
- - gfar_write(®s->ievent, IEVENT_INIT_CLEAR);
- - }
- + gfar_ints_disable(priv);
-
- - regs = priv->gfargrp[0].regs;
- /* Stop the DMA, and wait for it to stop */
- tempval = gfar_read(®s->dmactrl);
- if ((tempval & (DMACTRL_GRS | DMACTRL_GTS)) !=
- @@ -1685,56 +1781,41 @@
- }
-
- /* Halt the receive and transmit queues */
- -void gfar_halt(struct net_device *dev)
- +void gfar_halt(struct gfar_private *priv)
- {
- - struct gfar_private *priv = netdev_priv(dev);
- struct gfar __iomem *regs = priv->gfargrp[0].regs;
- u32 tempval;
-
- - gfar_halt_nodisable(dev);
- + /* Dissable the Rx/Tx hw queues */
- + gfar_write(®s->rqueue, 0);
- + gfar_write(®s->tqueue, 0);
-
- - /* Disable Rx and Tx */
- + mdelay(10);
- +
- + gfar_halt_nodisable(priv);
- +
- + /* Disable Rx/Tx DMA */
- tempval = gfar_read(®s->maccfg1);
- tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN);
- gfar_write(®s->maccfg1, tempval);
- }
-
- -static void free_grp_irqs(struct gfar_priv_grp *grp)
- -{
- - free_irq(gfar_irq(grp, TX)->irq, grp);
- - free_irq(gfar_irq(grp, RX)->irq, grp);
- - free_irq(gfar_irq(grp, ER)->irq, grp);
- -}
- -
- void stop_gfar(struct net_device *dev)
- {
- struct gfar_private *priv = netdev_priv(dev);
- - unsigned long flags;
- - int i;
- -
- - phy_stop(priv->phydev);
-
- + netif_tx_stop_all_queues(dev);
-
- - /* Lock it down */
- - local_irq_save(flags);
- - lock_tx_qs(priv);
- - lock_rx_qs(priv);
- + smp_mb__before_clear_bit();
- + set_bit(GFAR_DOWN, &priv->state);
- + smp_mb__after_clear_bit();
-
- - gfar_halt(dev);
- + disable_napi(priv);
-
- - unlock_rx_qs(priv);
- - unlock_tx_qs(priv);
- - local_irq_restore(flags);
- + /* disable ints and gracefully shut down Rx/Tx DMA */
- + gfar_halt(priv);
-
- - /* Free the IRQs */
- - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
- - for (i = 0; i < priv->num_grps; i++)
- - free_grp_irqs(&priv->gfargrp[i]);
- - } else {
- - for (i = 0; i < priv->num_grps; i++)
- - free_irq(gfar_irq(&priv->gfargrp[i], TX)->irq,
- - &priv->gfargrp[i]);
- - }
- + phy_stop(priv->phydev);
-
- free_skb_resources(priv);
- }
- @@ -1825,17 +1906,15 @@
- priv->tx_queue[0]->tx_bd_dma_base);
- }
-
- -void gfar_start(struct net_device *dev)
- +void gfar_start(struct gfar_private *priv)
- {
- - struct gfar_private *priv = netdev_priv(dev);
- struct gfar __iomem *regs = priv->gfargrp[0].regs;
- u32 tempval;
- int i = 0;
-
- - /* Enable Rx and Tx in MACCFG1 */
- - tempval = gfar_read(®s->maccfg1);
- - tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
- - gfar_write(®s->maccfg1, tempval);
- + /* Enable Rx/Tx hw queues */
- + gfar_write(®s->rqueue, priv->rqueue);
- + gfar_write(®s->tqueue, priv->tqueue);
-
- /* Initialize DMACTRL to have WWR and WOP */
- tempval = gfar_read(®s->dmactrl);
- @@ -1852,52 +1931,23 @@
- /* Clear THLT/RHLT, so that the DMA starts polling now */
- gfar_write(®s->tstat, priv->gfargrp[i].tstat);
- gfar_write(®s->rstat, priv->gfargrp[i].rstat);
- - /* Unmask the interrupts we look for */
- - gfar_write(®s->imask, IMASK_DEFAULT);
- }
-
- - dev->trans_start = jiffies; /* prevent tx timeout */
- -}
- -
- -static void gfar_configure_coalescing(struct gfar_private *priv,
- - unsigned long tx_mask, unsigned long rx_mask)
- -{
- - struct gfar __iomem *regs = priv->gfargrp[0].regs;
- - u32 __iomem *baddr;
- + /* Enable Rx/Tx DMA */
- + tempval = gfar_read(®s->maccfg1);
- + tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
- + gfar_write(®s->maccfg1, tempval);
-
- - if (priv->mode == MQ_MG_MODE) {
- - int i = 0;
- + gfar_ints_enable(priv);
-
- - baddr = ®s->txic0;
- - for_each_set_bit(i, &tx_mask, priv->num_tx_queues) {
- - gfar_write(baddr + i, 0);
- - if (likely(priv->tx_queue[i]->txcoalescing))
- - gfar_write(baddr + i, priv->tx_queue[i]->txic);
- - }
- -
- - baddr = ®s->rxic0;
- - for_each_set_bit(i, &rx_mask, priv->num_rx_queues) {
- - gfar_write(baddr + i, 0);
- - if (likely(priv->rx_queue[i]->rxcoalescing))
- - gfar_write(baddr + i, priv->rx_queue[i]->rxic);
- - }
- - } else {
- - /* Backward compatible case -- even if we enable
- - * multiple queues, there's only single reg to program
- - */
- - gfar_write(®s->txic, 0);
- - if (likely(priv->tx_queue[0]->txcoalescing))
- - gfar_write(®s->txic, priv->tx_queue[0]->txic);
- -
- - gfar_write(®s->rxic, 0);
- - if (unlikely(priv->rx_queue[0]->rxcoalescing))
- - gfar_write(®s->rxic, priv->rx_queue[0]->rxic);
- - }
- + priv->ndev->trans_start = jiffies; /* prevent tx timeout */
- }
-
- -void gfar_configure_coalescing_all(struct gfar_private *priv)
- +static void free_grp_irqs(struct gfar_priv_grp *grp)
- {
- - gfar_configure_coalescing(priv, 0xFF, 0xFF);
- + free_irq(gfar_irq(grp, TX)->irq, grp);
- + free_irq(gfar_irq(grp, RX)->irq, grp);
- + free_irq(gfar_irq(grp, ER)->irq, grp);
- }
-
- static int register_grp_irqs(struct gfar_priv_grp *grp)
- @@ -1956,46 +2006,65 @@
-
- }
-
- -/* Bring the controller up and running */
- -int startup_gfar(struct net_device *ndev)
- +static void gfar_free_irq(struct gfar_private *priv)
- {
- - struct gfar_private *priv = netdev_priv(ndev);
- - struct gfar __iomem *regs = NULL;
- - int err, i, j;
- + int i;
-
- - for (i = 0; i < priv->num_grps; i++) {
- - regs= priv->gfargrp[i].regs;
- - gfar_write(®s->imask, IMASK_INIT_CLEAR);
- + /* Free the IRQs */
- + if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
- + for (i = 0; i < priv->num_grps; i++)
- + free_grp_irqs(&priv->gfargrp[i]);
- + } else {
- + for (i = 0; i < priv->num_grps; i++)
- + free_irq(gfar_irq(&priv->gfargrp[i], TX)->irq,
- + &priv->gfargrp[i]);
- }
- +}
-
- - regs= priv->gfargrp[0].regs;
- - err = gfar_alloc_skb_resources(ndev);
- - if (err)
- - return err;
- -
- - gfar_init_mac(ndev);
- +static int gfar_request_irq(struct gfar_private *priv)
- +{
- + int err, i, j;
-
- for (i = 0; i < priv->num_grps; i++) {
- err = register_grp_irqs(&priv->gfargrp[i]);
- if (err) {
- for (j = 0; j < i; j++)
- free_grp_irqs(&priv->gfargrp[j]);
- - goto irq_fail;
- + return err;
- }
- }
-
- - /* Start the controller */
- - gfar_start(ndev);
- + return 0;
- +}
- +
- +/* Bring the controller up and running */
- +int startup_gfar(struct net_device *ndev)
- +{
- + struct gfar_private *priv = netdev_priv(ndev);
- + int err;
- +
- + gfar_mac_reset(priv);
- +
- + err = gfar_alloc_skb_resources(ndev);
- + if (err)
- + return err;
- +
- + gfar_init_tx_rx_base(priv);
- +
- + smp_mb__before_clear_bit();
- + clear_bit(GFAR_DOWN, &priv->state);
- + smp_mb__after_clear_bit();
- +
- + /* Start Rx/Tx DMA and enable the interrupts */
- + gfar_start(priv);
-
- phy_start(priv->phydev);
-
- - gfar_configure_coalescing_all(priv);
- + enable_napi(priv);
-
- - return 0;
- + netif_tx_wake_all_queues(ndev);
-
- -irq_fail:
- - free_skb_resources(priv);
- - return err;
- + return 0;
- }
-
- /* Called when something needs to use the ethernet device
- @@ -2006,27 +2075,17 @@
- struct gfar_private *priv = netdev_priv(dev);
- int err;
-
- - enable_napi(priv);
- -
- - /* Initialize a bunch of registers */
- - init_registers(dev);
- -
- - gfar_set_mac_address(dev);
- -
- err = init_phy(dev);
- + if (err)
- + return err;
-
- - if (err) {
- - disable_napi(priv);
- + err = gfar_request_irq(priv);
- + if (err)
- return err;
- - }
-
- err = startup_gfar(dev);
- - if (err) {
- - disable_napi(priv);
- + if (err)
- return err;
- - }
- -
- - netif_tx_start_all_queues(dev);
-
- device_set_wakeup_enable(&dev->dev, priv->wol_en);
-
- @@ -2152,13 +2211,13 @@
- skb_new = skb_realloc_headroom(skb, fcb_len);
- if (!skb_new) {
- dev->stats.tx_errors++;
- - kfree_skb(skb);
- + dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
- }
-
- if (skb->sk)
- skb_set_owner_w(skb_new, skb->sk);
- - consume_skb(skb);
- + dev_consume_skb_any(skb);
- skb = skb_new;
- }
-
- @@ -2351,8 +2410,6 @@
- {
- struct gfar_private *priv = netdev_priv(dev);
-
- - disable_napi(priv);
- -
- cancel_work_sync(&priv->reset_task);
- stop_gfar(dev);
-
- @@ -2360,7 +2417,7 @@
- phy_disconnect(priv->phydev);
- priv->phydev = NULL;
-
- - netif_tx_stop_all_queues(dev);
- + gfar_free_irq(priv);
-
- return 0;
- }
- @@ -2373,77 +2430,9 @@
- return 0;
- }
-
- -/* Check if rx parser should be activated */
- -void gfar_check_rx_parser_mode(struct gfar_private *priv)
- -{
- - struct gfar __iomem *regs;
- - u32 tempval;
- -
- - regs = priv->gfargrp[0].regs;
- -
- - tempval = gfar_read(®s->rctrl);
- - /* If parse is no longer required, then disable parser */
- - if (tempval & RCTRL_REQ_PARSER) {
- - tempval |= RCTRL_PRSDEP_INIT;
- - priv->uses_rxfcb = 1;
- - } else {
- - tempval &= ~RCTRL_PRSDEP_INIT;
- - priv->uses_rxfcb = 0;
- - }
- - gfar_write(®s->rctrl, tempval);
- -}
- -
- -/* Enables and disables VLAN insertion/extraction */
- -void gfar_vlan_mode(struct net_device *dev, netdev_features_t features)
- -{
- - struct gfar_private *priv = netdev_priv(dev);
- - struct gfar __iomem *regs = NULL;
- - unsigned long flags;
- - u32 tempval;
- -
- - regs = priv->gfargrp[0].regs;
- - local_irq_save(flags);
- - lock_rx_qs(priv);
- -
- - if (features & NETIF_F_HW_VLAN_CTAG_TX) {
- - /* Enable VLAN tag insertion */
- - tempval = gfar_read(®s->tctrl);
- - tempval |= TCTRL_VLINS;
- - gfar_write(®s->tctrl, tempval);
- - } else {
- - /* Disable VLAN tag insertion */
- - tempval = gfar_read(®s->tctrl);
- - tempval &= ~TCTRL_VLINS;
- - gfar_write(®s->tctrl, tempval);
- - }
- -
- - if (features & NETIF_F_HW_VLAN_CTAG_RX) {
- - /* Enable VLAN tag extraction */
- - tempval = gfar_read(®s->rctrl);
- - tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT);
- - gfar_write(®s->rctrl, tempval);
- - priv->uses_rxfcb = 1;
- - } else {
- - /* Disable VLAN tag extraction */
- - tempval = gfar_read(®s->rctrl);
- - tempval &= ~RCTRL_VLEX;
- - gfar_write(®s->rctrl, tempval);
- -
- - gfar_check_rx_parser_mode(priv);
- - }
- -
- - gfar_change_mtu(dev, dev->mtu);
- -
- - unlock_rx_qs(priv);
- - local_irq_restore(flags);
- -}
- -
- static int gfar_change_mtu(struct net_device *dev, int new_mtu)
- {
- - int tempsize, tempval;
- struct gfar_private *priv = netdev_priv(dev);
- - struct gfar __iomem *regs = priv->gfargrp[0].regs;
- - int oldsize = priv->rx_buffer_size;
- int frame_size = new_mtu + ETH_HLEN;
-
- if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) {
- @@ -2451,45 +2440,33 @@
- return -EINVAL;
- }
-
- - if (priv->uses_rxfcb)
- - frame_size += GMAC_FCB_LEN;
- -
- - frame_size += priv->padding;
- -
- - tempsize = (frame_size & ~(INCREMENTAL_BUFFER_SIZE - 1)) +
- - INCREMENTAL_BUFFER_SIZE;
- + while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
- + cpu_relax();
-
- - /* Only stop and start the controller if it isn't already
- - * stopped, and we changed something
- - */
- - if ((oldsize != tempsize) && (dev->flags & IFF_UP))
- + if (dev->flags & IFF_UP)
- stop_gfar(dev);
-
- - priv->rx_buffer_size = tempsize;
- -
- dev->mtu = new_mtu;
-
- - gfar_write(®s->mrblr, priv->rx_buffer_size);
- - gfar_write(®s->maxfrm, priv->rx_buffer_size);
- + if (dev->flags & IFF_UP)
- + startup_gfar(dev);
-
- - /* If the mtu is larger than the max size for standard
- - * ethernet frames (ie, a jumbo frame), then set maccfg2
- - * to allow huge frames, and to check the length
- - */
- - tempval = gfar_read(®s->maccfg2);
- + clear_bit_unlock(GFAR_RESETTING, &priv->state);
-
- - if (priv->rx_buffer_size > DEFAULT_RX_BUFFER_SIZE ||
- - gfar_has_errata(priv, GFAR_ERRATA_74))
- - tempval |= (MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK);
- - else
- - tempval &= ~(MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK);
- + return 0;
- +}
-
- - gfar_write(®s->maccfg2, tempval);
- +void reset_gfar(struct net_device *ndev)
- +{
- + struct gfar_private *priv = netdev_priv(ndev);
-
- - if ((oldsize != tempsize) && (dev->flags & IFF_UP))
- - startup_gfar(dev);
- + while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
- + cpu_relax();
-
- - return 0;
- + stop_gfar(ndev);
- + startup_gfar(ndev);
- +
- + clear_bit_unlock(GFAR_RESETTING, &priv->state);
- }
-
- /* gfar_reset_task gets scheduled when a packet has not been
- @@ -2501,16 +2478,7 @@
- {
- struct gfar_private *priv = container_of(work, struct gfar_private,
- reset_task);
- - struct net_device *dev = priv->ndev;
- -
- - if (dev->flags & IFF_UP) {
- - netif_tx_stop_all_queues(dev);
- - stop_gfar(dev);
- - startup_gfar(dev);
- - netif_tx_start_all_queues(dev);
- - }
- -
- - netif_tx_schedule_all(dev);
- + reset_gfar(priv->ndev);
- }
-
- static void gfar_timeout(struct net_device *dev)
- @@ -2623,8 +2591,10 @@
- }
-
- /* If we freed a buffer, we can restart transmission, if necessary */
- - if (netif_tx_queue_stopped(txq) && tx_queue->num_txbdfree)
- - netif_wake_subqueue(dev, tqi);
- + if (tx_queue->num_txbdfree &&
- + netif_tx_queue_stopped(txq) &&
- + !(test_bit(GFAR_DOWN, &priv->state)))
- + netif_wake_subqueue(priv->ndev, tqi);
-
- /* Update dirty indicators */
- tx_queue->skb_dirtytx = skb_dirtytx;
- @@ -2633,31 +2603,6 @@
- netdev_tx_completed_queue(txq, howmany, bytes_sent);
- }
-
- -static void gfar_schedule_cleanup(struct gfar_priv_grp *gfargrp)
- -{
- - unsigned long flags;
- -
- - spin_lock_irqsave(&gfargrp->grplock, flags);
- - if (napi_schedule_prep(&gfargrp->napi)) {
- - gfar_write(&gfargrp->regs->imask, IMASK_RTX_DISABLED);
- - __napi_schedule(&gfargrp->napi);
- - } else {
- - /* Clear IEVENT, so interrupts aren't called again
- - * because of the packets that have already arrived.
- - */
- - gfar_write(&gfargrp->regs->ievent, IEVENT_RTX_MASK);
- - }
- - spin_unlock_irqrestore(&gfargrp->grplock, flags);
- -
- -}
- -
- -/* Interrupt Handler for Transmit complete */
- -static irqreturn_t gfar_transmit(int irq, void *grp_id)
- -{
- - gfar_schedule_cleanup((struct gfar_priv_grp *)grp_id);
- - return IRQ_HANDLED;
- -}
- -
- static void gfar_new_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp,
- struct sk_buff *skb)
- {
- @@ -2728,7 +2673,48 @@
-
- irqreturn_t gfar_receive(int irq, void *grp_id)
- {
- - gfar_schedule_cleanup((struct gfar_priv_grp *)grp_id);
- + struct gfar_priv_grp *grp = (struct gfar_priv_grp *)grp_id;
- + unsigned long flags;
- + u32 imask;
- +
- + if (likely(napi_schedule_prep(&grp->napi_rx))) {
- + spin_lock_irqsave(&grp->grplock, flags);
- + imask = gfar_read(&grp->regs->imask);
- + imask &= IMASK_RX_DISABLED;
- + gfar_write(&grp->regs->imask, imask);
- + spin_unlock_irqrestore(&grp->grplock, flags);
- + __napi_schedule(&grp->napi_rx);
- + } else {
- + /* Clear IEVENT, so interrupts aren't called again
- + * because of the packets that have already arrived.
- + */
- + gfar_write(&grp->regs->ievent, IEVENT_RX_MASK);
- + }
- +
- + return IRQ_HANDLED;
- +}
- +
- +/* Interrupt Handler for Transmit complete */
- +static irqreturn_t gfar_transmit(int irq, void *grp_id)
- +{
- + struct gfar_priv_grp *grp = (struct gfar_priv_grp *)grp_id;
- + unsigned long flags;
- + u32 imask;
- +
- + if (likely(napi_schedule_prep(&grp->napi_tx))) {
- + spin_lock_irqsave(&grp->grplock, flags);
- + imask = gfar_read(&grp->regs->imask);
- + imask &= IMASK_TX_DISABLED;
- + gfar_write(&grp->regs->imask, imask);
- + spin_unlock_irqrestore(&grp->grplock, flags);
- + __napi_schedule(&grp->napi_tx);
- + } else {
- + /* Clear IEVENT, so interrupts aren't called again
- + * because of the packets that have already arrived.
- + */
- + gfar_write(&grp->regs->ievent, IEVENT_TX_MASK);
- + }
- +
- return IRQ_HANDLED;
- }
-
- @@ -2852,7 +2838,7 @@
- rx_queue->stats.rx_bytes += pkt_len;
- skb_record_rx_queue(skb, rx_queue->qindex);
- gfar_process_frame(dev, skb, amount_pull,
- - &rx_queue->grp->napi);
- + &rx_queue->grp->napi_rx);
-
- } else {
- netif_warn(priv, rx_err, dev, "Missing skb!\n");
- @@ -2881,66 +2867,81 @@
- return howmany;
- }
-
- -static int gfar_poll_sq(struct napi_struct *napi, int budget)
- +static int gfar_poll_rx_sq(struct napi_struct *napi, int budget)
- {
- struct gfar_priv_grp *gfargrp =
- - container_of(napi, struct gfar_priv_grp, napi);
- + container_of(napi, struct gfar_priv_grp, napi_rx);
- struct gfar __iomem *regs = gfargrp->regs;
- - struct gfar_priv_tx_q *tx_queue = gfargrp->priv->tx_queue[0];
- - struct gfar_priv_rx_q *rx_queue = gfargrp->priv->rx_queue[0];
- + struct gfar_priv_rx_q *rx_queue = gfargrp->rx_queue;
- int work_done = 0;
-
- /* Clear IEVENT, so interrupts aren't called again
- * because of the packets that have already arrived
- */
- - gfar_write(®s->ievent, IEVENT_RTX_MASK);
- -
- - /* run Tx cleanup to completion */
- - if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx])
- - gfar_clean_tx_ring(tx_queue);
- + gfar_write(®s->ievent, IEVENT_RX_MASK);
-
- work_done = gfar_clean_rx_ring(rx_queue, budget);
-
- if (work_done < budget) {
- + u32 imask;
- napi_complete(napi);
- /* Clear the halt bit in RSTAT */
- gfar_write(®s->rstat, gfargrp->rstat);
-
- - gfar_write(®s->imask, IMASK_DEFAULT);
- -
- - /* If we are coalescing interrupts, update the timer
- - * Otherwise, clear it
- - */
- - gfar_write(®s->txic, 0);
- - if (likely(tx_queue->txcoalescing))
- - gfar_write(®s->txic, tx_queue->txic);
- -
- - gfar_write(®s->rxic, 0);
- - if (unlikely(rx_queue->rxcoalescing))
- - gfar_write(®s->rxic, rx_queue->rxic);
- + spin_lock_irq(&gfargrp->grplock);
- + imask = gfar_read(®s->imask);
- + imask |= IMASK_RX_DEFAULT;
- + gfar_write(®s->imask, imask);
- + spin_unlock_irq(&gfargrp->grplock);
- }
-
- return work_done;
- }
-
- -static int gfar_poll(struct napi_struct *napi, int budget)
- +static int gfar_poll_tx_sq(struct napi_struct *napi, int budget)
- +{
- + struct gfar_priv_grp *gfargrp =
- + container_of(napi, struct gfar_priv_grp, napi_tx);
- + struct gfar __iomem *regs = gfargrp->regs;
- + struct gfar_priv_tx_q *tx_queue = gfargrp->tx_queue;
- + u32 imask;
- +
- + /* Clear IEVENT, so interrupts aren't called again
- + * because of the packets that have already arrived
- + */
- + gfar_write(®s->ievent, IEVENT_TX_MASK);
- +
- + /* run Tx cleanup to completion */
- + if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx])
- + gfar_clean_tx_ring(tx_queue);
- +
- + napi_complete(napi);
- +
- + spin_lock_irq(&gfargrp->grplock);
- + imask = gfar_read(®s->imask);
- + imask |= IMASK_TX_DEFAULT;
- + gfar_write(®s->imask, imask);
- + spin_unlock_irq(&gfargrp->grplock);
- +
- + return 0;
- +}
- +
- +static int gfar_poll_rx(struct napi_struct *napi, int budget)
- {
- struct gfar_priv_grp *gfargrp =
- - container_of(napi, struct gfar_priv_grp, napi);
- + container_of(napi, struct gfar_priv_grp, napi_rx);
- struct gfar_private *priv = gfargrp->priv;
- struct gfar __iomem *regs = gfargrp->regs;
- - struct gfar_priv_tx_q *tx_queue = NULL;
- struct gfar_priv_rx_q *rx_queue = NULL;
- int work_done = 0, work_done_per_q = 0;
- int i, budget_per_q = 0;
- - int has_tx_work = 0;
- unsigned long rstat_rxf;
- int num_act_queues;
-
- /* Clear IEVENT, so interrupts aren't called again
- * because of the packets that have already arrived
- */
- - gfar_write(®s->ievent, IEVENT_RTX_MASK);
- + gfar_write(®s->ievent, IEVENT_RX_MASK);
-
- rstat_rxf = gfar_read(®s->rstat) & RSTAT_RXF_MASK;
-
- @@ -2948,15 +2949,6 @@
- if (num_act_queues)
- budget_per_q = budget/num_act_queues;
-
- - for_each_set_bit(i, &gfargrp->tx_bit_map, priv->num_tx_queues) {
- - tx_queue = priv->tx_queue[i];
- - /* run Tx cleanup to completion */
- - if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx]) {
- - gfar_clean_tx_ring(tx_queue);
- - has_tx_work = 1;
- - }
- - }
- -
- for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) {
- /* skip queue if not active */
- if (!(rstat_rxf & (RSTAT_CLEAR_RXF0 >> i)))
- @@ -2979,25 +2971,62 @@
- }
- }
-
- - if (!num_act_queues && !has_tx_work) {
- -
- + if (!num_act_queues) {
- + u32 imask;
- napi_complete(napi);
-
- /* Clear the halt bit in RSTAT */
- gfar_write(®s->rstat, gfargrp->rstat);
-
- - gfar_write(®s->imask, IMASK_DEFAULT);
- -
- - /* If we are coalescing interrupts, update the timer
- - * Otherwise, clear it
- - */
- - gfar_configure_coalescing(priv, gfargrp->rx_bit_map,
- - gfargrp->tx_bit_map);
- + spin_lock_irq(&gfargrp->grplock);
- + imask = gfar_read(®s->imask);
- + imask |= IMASK_RX_DEFAULT;
- + gfar_write(®s->imask, imask);
- + spin_unlock_irq(&gfargrp->grplock);
- }
-
- return work_done;
- }
-
- +static int gfar_poll_tx(struct napi_struct *napi, int budget)
- +{
- + struct gfar_priv_grp *gfargrp =
- + container_of(napi, struct gfar_priv_grp, napi_tx);
- + struct gfar_private *priv = gfargrp->priv;
- + struct gfar __iomem *regs = gfargrp->regs;
- + struct gfar_priv_tx_q *tx_queue = NULL;
- + int has_tx_work = 0;
- + int i;
- +
- + /* Clear IEVENT, so interrupts aren't called again
- + * because of the packets that have already arrived
- + */
- + gfar_write(®s->ievent, IEVENT_TX_MASK);
- +
- + for_each_set_bit(i, &gfargrp->tx_bit_map, priv->num_tx_queues) {
- + tx_queue = priv->tx_queue[i];
- + /* run Tx cleanup to completion */
- + if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx]) {
- + gfar_clean_tx_ring(tx_queue);
- + has_tx_work = 1;
- + }
- + }
- +
- + if (!has_tx_work) {
- + u32 imask;
- + napi_complete(napi);
- +
- + spin_lock_irq(&gfargrp->grplock);
- + imask = gfar_read(®s->imask);
- + imask |= IMASK_TX_DEFAULT;
- + gfar_write(®s->imask, imask);
- + spin_unlock_irq(&gfargrp->grplock);
- + }
- +
- + return 0;
- +}
- +
- +
- #ifdef CONFIG_NET_POLL_CONTROLLER
- /* Polling 'interrupt' - used by things like netconsole to send skbs
- * without having to re-enable interrupts. It's not called while
- @@ -3056,41 +3085,6 @@
- return IRQ_HANDLED;
- }
-
- -static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv)
- -{
- - struct phy_device *phydev = priv->phydev;
- - u32 val = 0;
- -
- - if (!phydev->duplex)
- - return val;
- -
- - if (!priv->pause_aneg_en) {
- - if (priv->tx_pause_en)
- - val |= MACCFG1_TX_FLOW;
- - if (priv->rx_pause_en)
- - val |= MACCFG1_RX_FLOW;
- - } else {
- - u16 lcl_adv, rmt_adv;
- - u8 flowctrl;
- - /* get link partner capabilities */
- - rmt_adv = 0;
- - if (phydev->pause)
- - rmt_adv = LPA_PAUSE_CAP;
- - if (phydev->asym_pause)
- - rmt_adv |= LPA_PAUSE_ASYM;
- -
- - lcl_adv = mii_advertise_flowctrl(phydev->advertising);
- -
- - flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
- - if (flowctrl & FLOW_CTRL_TX)
- - val |= MACCFG1_TX_FLOW;
- - if (flowctrl & FLOW_CTRL_RX)
- - val |= MACCFG1_RX_FLOW;
- - }
- -
- - return val;
- -}
- -
- /* Called every time the controller might need to be made
- * aware of new link state. The PHY code conveys this
- * information through variables in the phydev structure, and this
- @@ -3100,86 +3094,12 @@
- static void adjust_link(struct net_device *dev)
- {
- struct gfar_private *priv = netdev_priv(dev);
- - struct gfar __iomem *regs = priv->gfargrp[0].regs;
- - unsigned long flags;
- struct phy_device *phydev = priv->phydev;
- - int new_state = 0;
- -
- - local_irq_save(flags);
- - lock_tx_qs(priv);
- -
- - if (phydev->link) {
- - u32 tempval1 = gfar_read(®s->maccfg1);
- - u32 tempval = gfar_read(®s->maccfg2);
- - u32 ecntrl = gfar_read(®s->ecntrl);
- -
- - /* Now we make sure that we can be in full duplex mode.
- - * If not, we operate in half-duplex mode.
- - */
- - if (phydev->duplex != priv->oldduplex) {
- - new_state = 1;
- - if (!(phydev->duplex))
- - tempval &= ~(MACCFG2_FULL_DUPLEX);
- - else
- - tempval |= MACCFG2_FULL_DUPLEX;
- -
- - priv->oldduplex = phydev->duplex;
- - }
- -
- - if (phydev->speed != priv->oldspeed) {
- - new_state = 1;
- - switch (phydev->speed) {
- - case 1000:
- - tempval =
- - ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII);
- -
- - ecntrl &= ~(ECNTRL_R100);
- - break;
- - case 100:
- - case 10:
- - tempval =
- - ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII);
- -
- - /* Reduced mode distinguishes
- - * between 10 and 100
- - */
- - if (phydev->speed == SPEED_100)
- - ecntrl |= ECNTRL_R100;
- - else
- - ecntrl &= ~(ECNTRL_R100);
- - break;
- - default:
- - netif_warn(priv, link, dev,
- - "Ack! Speed (%d) is not 10/100/1000!\n",
- - phydev->speed);
- - break;
- - }
- -
- - priv->oldspeed = phydev->speed;
- - }
- -
- - tempval1 &= ~(MACCFG1_TX_FLOW | MACCFG1_RX_FLOW);
- - tempval1 |= gfar_get_flowctrl_cfg(priv);
- -
- - gfar_write(®s->maccfg1, tempval1);
- - gfar_write(®s->maccfg2, tempval);
- - gfar_write(®s->ecntrl, ecntrl);
- -
- - if (!priv->oldlink) {
- - new_state = 1;
- - priv->oldlink = 1;
- - }
- - } else if (priv->oldlink) {
- - new_state = 1;
- - priv->oldlink = 0;
- - priv->oldspeed = 0;
- - priv->oldduplex = -1;
- - }
-
- - if (new_state && netif_msg_link(priv))
- - phy_print_status(phydev);
- - unlock_tx_qs(priv);
- - local_irq_restore(flags);
- + if (unlikely(phydev->link != priv->oldlink ||
- + phydev->duplex != priv->oldduplex ||
- + phydev->speed != priv->oldspeed))
- + gfar_update_link_state(priv);
- }
-
- /* Update the hash table based on the current list of multicast
- @@ -3425,6 +3345,114 @@
- return IRQ_HANDLED;
- }
-
- +static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv)
- +{
- + struct phy_device *phydev = priv->phydev;
- + u32 val = 0;
- +
- + if (!phydev->duplex)
- + return val;
- +
- + if (!priv->pause_aneg_en) {
- + if (priv->tx_pause_en)
- + val |= MACCFG1_TX_FLOW;
- + if (priv->rx_pause_en)
- + val |= MACCFG1_RX_FLOW;
- + } else {
- + u16 lcl_adv, rmt_adv;
- + u8 flowctrl;
- + /* get link partner capabilities */
- + rmt_adv = 0;
- + if (phydev->pause)
- + rmt_adv = LPA_PAUSE_CAP;
- + if (phydev->asym_pause)
- + rmt_adv |= LPA_PAUSE_ASYM;
- +
- + lcl_adv = mii_advertise_flowctrl(phydev->advertising);
- +
- + flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
- + if (flowctrl & FLOW_CTRL_TX)
- + val |= MACCFG1_TX_FLOW;
- + if (flowctrl & FLOW_CTRL_RX)
- + val |= MACCFG1_RX_FLOW;
- + }
- +
- + return val;
- +}
- +
- +static noinline void gfar_update_link_state(struct gfar_private *priv)
- +{
- + struct gfar __iomem *regs = priv->gfargrp[0].regs;
- + struct phy_device *phydev = priv->phydev;
- +
- + if (unlikely(test_bit(GFAR_RESETTING, &priv->state)))
- + return;
- +
- + if (phydev->link) {
- + u32 tempval1 = gfar_read(®s->maccfg1);
- + u32 tempval = gfar_read(®s->maccfg2);
- + u32 ecntrl = gfar_read(®s->ecntrl);
- +
- + if (phydev->duplex != priv->oldduplex) {
- + if (!(phydev->duplex))
- + tempval &= ~(MACCFG2_FULL_DUPLEX);
- + else
- + tempval |= MACCFG2_FULL_DUPLEX;
- +
- + priv->oldduplex = phydev->duplex;
- + }
- +
- + if (phydev->speed != priv->oldspeed) {
- + switch (phydev->speed) {
- + case 1000:
- + tempval =
- + ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII);
- +
- + ecntrl &= ~(ECNTRL_R100);
- + break;
- + case 100:
- + case 10:
- + tempval =
- + ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII);
- +
- + /* Reduced mode distinguishes
- + * between 10 and 100
- + */
- + if (phydev->speed == SPEED_100)
- + ecntrl |= ECNTRL_R100;
- + else
- + ecntrl &= ~(ECNTRL_R100);
- + break;
- + default:
- + netif_warn(priv, link, priv->ndev,
- + "Ack! Speed (%d) is not 10/100/1000!\n",
- + phydev->speed);
- + break;
- + }
- +
- + priv->oldspeed = phydev->speed;
- + }
- +
- + tempval1 &= ~(MACCFG1_TX_FLOW | MACCFG1_RX_FLOW);
- + tempval1 |= gfar_get_flowctrl_cfg(priv);
- +
- + gfar_write(®s->maccfg1, tempval1);
- + gfar_write(®s->maccfg2, tempval);
- + gfar_write(®s->ecntrl, ecntrl);
- +
- + if (!priv->oldlink)
- + priv->oldlink = 1;
- +
- + } else if (priv->oldlink) {
- + priv->oldlink = 0;
- + priv->oldspeed = 0;
- + priv->oldduplex = -1;
- + }
- +
- + if (netif_msg_link(priv))
- + phy_print_status(phydev);
- +}
- +
- static struct of_device_id gfar_match[] =
- {
- {
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/freescale/gianfar_ethtool.c linux-3.14.35/drivers/net/ethernet/freescale/gianfar_ethtool.c
- --- linux-3.14.35.orig/drivers/net/ethernet/freescale/gianfar_ethtool.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/freescale/gianfar_ethtool.c 2015-03-08 14:27:37.681684500 -0500
- @@ -44,10 +44,6 @@
-
- #include "gianfar.h"
-
- -extern void gfar_start(struct net_device *dev);
- -extern int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue,
- - int rx_work_limit);
- -
- #define GFAR_MAX_COAL_USECS 0xffff
- #define GFAR_MAX_COAL_FRAMES 0xff
- static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
- @@ -364,25 +360,11 @@
- struct ethtool_coalesce *cvals)
- {
- struct gfar_private *priv = netdev_priv(dev);
- - int i = 0;
- + int i, err = 0;
-
- if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
- return -EOPNOTSUPP;
-
- - /* Set up rx coalescing */
- - /* As of now, we will enable/disable coalescing for all
- - * queues together in case of eTSEC2, this will be modified
- - * along with the ethtool interface
- - */
- - if ((cvals->rx_coalesce_usecs == 0) ||
- - (cvals->rx_max_coalesced_frames == 0)) {
- - for (i = 0; i < priv->num_rx_queues; i++)
- - priv->rx_queue[i]->rxcoalescing = 0;
- - } else {
- - for (i = 0; i < priv->num_rx_queues; i++)
- - priv->rx_queue[i]->rxcoalescing = 1;
- - }
- -
- if (NULL == priv->phydev)
- return -ENODEV;
-
- @@ -399,6 +381,32 @@
- return -EINVAL;
- }
-
- + /* Check the bounds of the values */
- + if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
- + netdev_info(dev, "Coalescing is limited to %d microseconds\n",
- + GFAR_MAX_COAL_USECS);
- + return -EINVAL;
- + }
- +
- + if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
- + netdev_info(dev, "Coalescing is limited to %d frames\n",
- + GFAR_MAX_COAL_FRAMES);
- + return -EINVAL;
- + }
- +
- + while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
- + cpu_relax();
- +
- + /* Set up rx coalescing */
- + if ((cvals->rx_coalesce_usecs == 0) ||
- + (cvals->rx_max_coalesced_frames == 0)) {
- + for (i = 0; i < priv->num_rx_queues; i++)
- + priv->rx_queue[i]->rxcoalescing = 0;
- + } else {
- + for (i = 0; i < priv->num_rx_queues; i++)
- + priv->rx_queue[i]->rxcoalescing = 1;
- + }
- +
- for (i = 0; i < priv->num_rx_queues; i++) {
- priv->rx_queue[i]->rxic = mk_ic_value(
- cvals->rx_max_coalesced_frames,
- @@ -415,28 +423,22 @@
- priv->tx_queue[i]->txcoalescing = 1;
- }
-
- - /* Check the bounds of the values */
- - if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
- - netdev_info(dev, "Coalescing is limited to %d microseconds\n",
- - GFAR_MAX_COAL_USECS);
- - return -EINVAL;
- - }
- -
- - if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
- - netdev_info(dev, "Coalescing is limited to %d frames\n",
- - GFAR_MAX_COAL_FRAMES);
- - return -EINVAL;
- - }
- -
- for (i = 0; i < priv->num_tx_queues; i++) {
- priv->tx_queue[i]->txic = mk_ic_value(
- cvals->tx_max_coalesced_frames,
- gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs));
- }
-
- - gfar_configure_coalescing_all(priv);
- + if (dev->flags & IFF_UP) {
- + stop_gfar(dev);
- + err = startup_gfar(dev);
- + } else {
- + gfar_mac_reset(priv);
- + }
- +
- + clear_bit_unlock(GFAR_RESETTING, &priv->state);
-
- - return 0;
- + return err;
- }
-
- /* Fills in rvals with the current ring parameters. Currently,
- @@ -467,15 +469,13 @@
- }
-
- /* Change the current ring parameters, stopping the controller if
- - * necessary so that we don't mess things up while we're in
- - * motion. We wait for the ring to be clean before reallocating
- - * the rings.
- + * necessary so that we don't mess things up while we're in motion.
- */
- static int gfar_sringparam(struct net_device *dev,
- struct ethtool_ringparam *rvals)
- {
- struct gfar_private *priv = netdev_priv(dev);
- - int err = 0, i = 0;
- + int err = 0, i;
-
- if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE)
- return -EINVAL;
- @@ -493,44 +493,25 @@
- return -EINVAL;
- }
-
- + while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
- + cpu_relax();
-
- - if (dev->flags & IFF_UP) {
- - unsigned long flags;
- -
- - /* Halt TX and RX, and process the frames which
- - * have already been received
- - */
- - local_irq_save(flags);
- - lock_tx_qs(priv);
- - lock_rx_qs(priv);
- -
- - gfar_halt(dev);
- -
- - unlock_rx_qs(priv);
- - unlock_tx_qs(priv);
- - local_irq_restore(flags);
- -
- - for (i = 0; i < priv->num_rx_queues; i++)
- - gfar_clean_rx_ring(priv->rx_queue[i],
- - priv->rx_queue[i]->rx_ring_size);
- -
- - /* Now we take down the rings to rebuild them */
- + if (dev->flags & IFF_UP)
- stop_gfar(dev);
- - }
-
- - /* Change the size */
- - for (i = 0; i < priv->num_rx_queues; i++) {
- + /* Change the sizes */
- + for (i = 0; i < priv->num_rx_queues; i++)
- priv->rx_queue[i]->rx_ring_size = rvals->rx_pending;
- +
- + for (i = 0; i < priv->num_tx_queues; i++)
- priv->tx_queue[i]->tx_ring_size = rvals->tx_pending;
- - priv->tx_queue[i]->num_txbdfree =
- - priv->tx_queue[i]->tx_ring_size;
- - }
-
- /* Rebuild the rings with the new size */
- - if (dev->flags & IFF_UP) {
- + if (dev->flags & IFF_UP)
- err = startup_gfar(dev);
- - netif_tx_wake_all_queues(dev);
- - }
- +
- + clear_bit_unlock(GFAR_RESETTING, &priv->state);
- +
- return err;
- }
-
- @@ -552,6 +533,9 @@
- struct gfar __iomem *regs = priv->gfargrp[0].regs;
- u32 oldadv, newadv;
-
- + if (!phydev)
- + return -ENODEV;
- +
- if (!(phydev->supported & SUPPORTED_Pause) ||
- (!(phydev->supported & SUPPORTED_Asym_Pause) &&
- (epause->rx_pause != epause->tx_pause)))
- @@ -608,43 +592,29 @@
-
- int gfar_set_features(struct net_device *dev, netdev_features_t features)
- {
- - struct gfar_private *priv = netdev_priv(dev);
- - unsigned long flags;
- - int err = 0, i = 0;
- netdev_features_t changed = dev->features ^ features;
- + struct gfar_private *priv = netdev_priv(dev);
- + int err = 0;
-
- - if (changed & (NETIF_F_HW_VLAN_CTAG_TX|NETIF_F_HW_VLAN_CTAG_RX))
- - gfar_vlan_mode(dev, features);
- -
- - if (!(changed & NETIF_F_RXCSUM))
- + if (!(changed & (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
- + NETIF_F_RXCSUM)))
- return 0;
-
- - if (dev->flags & IFF_UP) {
- - /* Halt TX and RX, and process the frames which
- - * have already been received
- - */
- - local_irq_save(flags);
- - lock_tx_qs(priv);
- - lock_rx_qs(priv);
- -
- - gfar_halt(dev);
- -
- - unlock_tx_qs(priv);
- - unlock_rx_qs(priv);
- - local_irq_restore(flags);
- + while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
- + cpu_relax();
-
- - for (i = 0; i < priv->num_rx_queues; i++)
- - gfar_clean_rx_ring(priv->rx_queue[i],
- - priv->rx_queue[i]->rx_ring_size);
- + dev->features = features;
-
- + if (dev->flags & IFF_UP) {
- /* Now we take down the rings to rebuild them */
- stop_gfar(dev);
- -
- - dev->features = features;
- -
- err = startup_gfar(dev);
- - netif_tx_wake_all_queues(dev);
- + } else {
- + gfar_mac_reset(priv);
- }
- +
- + clear_bit_unlock(GFAR_RESETTING, &priv->state);
- +
- return err;
- }
-
- @@ -1610,9 +1580,6 @@
- if (tab->index > MAX_FILER_IDX - 1)
- return -EBUSY;
-
- - /* Avoid inconsistent filer table to be processed */
- - lock_rx_qs(priv);
- -
- /* Fill regular entries */
- for (; i < MAX_FILER_IDX - 1 && (tab->fe[i].ctrl | tab->fe[i].ctrl);
- i++)
- @@ -1625,8 +1592,6 @@
- */
- gfar_write_filer(priv, i, 0x20, 0x0);
-
- - unlock_rx_qs(priv);
- -
- return 0;
- }
-
- @@ -1831,6 +1796,9 @@
- struct gfar_private *priv = netdev_priv(dev);
- int ret = 0;
-
- + if (test_bit(GFAR_RESETTING, &priv->state))
- + return -EBUSY;
- +
- mutex_lock(&priv->rx_queue_access);
-
- switch (cmd->cmd) {
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/freescale/gianfar.h linux-3.14.35/drivers/net/ethernet/freescale/gianfar.h
- --- linux-3.14.35.orig/drivers/net/ethernet/freescale/gianfar.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/freescale/gianfar.h 2015-03-08 14:27:37.681684500 -0500
- @@ -9,7 +9,7 @@
- * Maintainer: Kumar Gala
- * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>
- *
- - * Copyright 2002-2009, 2011 Freescale Semiconductor, Inc.
- + * Copyright 2002-2009, 2011-2013 Freescale Semiconductor, 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
- @@ -377,8 +377,11 @@
- IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \
- IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \
- | IMASK_PERR)
- -#define IMASK_RTX_DISABLED ((~(IMASK_RXFEN0 | IMASK_TXFEN | IMASK_BSY)) \
- - & IMASK_DEFAULT)
- +#define IMASK_RX_DEFAULT (IMASK_RXFEN0 | IMASK_BSY)
- +#define IMASK_TX_DEFAULT (IMASK_TXFEN | IMASK_TXBEN)
- +
- +#define IMASK_RX_DISABLED ((~(IMASK_RX_DEFAULT)) & IMASK_DEFAULT)
- +#define IMASK_TX_DISABLED ((~(IMASK_TX_DEFAULT)) & IMASK_DEFAULT)
-
- /* Fifo management */
- #define FIFO_TX_THR_MASK 0x01ff
- @@ -409,7 +412,9 @@
-
- /* This default RIR value directly corresponds
- * to the 3-bit hash value generated */
- -#define DEFAULT_RIR0 0x05397700
- +#define DEFAULT_8RXQ_RIR0 0x05397700
- +/* Map even hash values to Q0, and odd ones to Q1 */
- +#define DEFAULT_2RXQ_RIR0 0x04104100
-
- /* RQFCR register bits */
- #define RQFCR_GPI 0x80000000
- @@ -880,7 +885,6 @@
- #define FSL_GIANFAR_DEV_HAS_CSUM 0x00000010
- #define FSL_GIANFAR_DEV_HAS_VLAN 0x00000020
- #define FSL_GIANFAR_DEV_HAS_EXTENDED_HASH 0x00000040
- -#define FSL_GIANFAR_DEV_HAS_PADDING 0x00000080
- #define FSL_GIANFAR_DEV_HAS_MAGIC_PACKET 0x00000100
- #define FSL_GIANFAR_DEV_HAS_BD_STASHING 0x00000200
- #define FSL_GIANFAR_DEV_HAS_BUF_STASHING 0x00000400
- @@ -892,8 +896,8 @@
- #define DEFAULT_MAPPING 0xFF
- #endif
-
- -#define ISRG_SHIFT_TX 0x10
- -#define ISRG_SHIFT_RX 0x18
- +#define ISRG_RR0 0x80000000
- +#define ISRG_TR0 0x00800000
-
- /* The same driver can operate in two modes */
- /* SQ_SG_MODE: Single Queue Single Group Mode
- @@ -905,6 +909,22 @@
- MQ_MG_MODE
- };
-
- +/* GFAR_SQ_POLLING: Single Queue NAPI polling mode
- + * The driver supports a single pair of RX/Tx queues
- + * per interrupt group (Rx/Tx int line). MQ_MG mode
- + * devices have 2 interrupt groups, so the device will
- + * have a total of 2 Tx and 2 Rx queues in this case.
- + * GFAR_MQ_POLLING: Multi Queue NAPI polling mode
- + * The driver supports all the 8 Rx and Tx HW queues
- + * each queue mapped by the Device Tree to one of
- + * the 2 interrupt groups. This mode implies significant
- + * processing overhead (CPU and controller level).
- + */
- +enum gfar_poll_mode {
- + GFAR_SQ_POLLING = 0,
- + GFAR_MQ_POLLING
- +};
- +
- /*
- * Per TX queue stats
- */
- @@ -966,7 +986,6 @@
-
- /**
- * struct gfar_priv_rx_q - per rx queue structure
- - * @rxlock: per queue rx spin lock
- * @rx_skbuff: skb pointers
- * @skb_currx: currently use skb pointer
- * @rx_bd_base: First rx buffer descriptor
- @@ -979,8 +998,7 @@
- */
-
- struct gfar_priv_rx_q {
- - spinlock_t rxlock __attribute__ ((aligned (SMP_CACHE_BYTES)));
- - struct sk_buff ** rx_skbuff;
- + struct sk_buff **rx_skbuff __aligned(SMP_CACHE_BYTES);
- dma_addr_t rx_bd_dma_base;
- struct rxbd8 *rx_bd_base;
- struct rxbd8 *cur_rx;
- @@ -1016,17 +1034,20 @@
- */
-
- struct gfar_priv_grp {
- - spinlock_t grplock __attribute__ ((aligned (SMP_CACHE_BYTES)));
- - struct napi_struct napi;
- - struct gfar_private *priv;
- + spinlock_t grplock __aligned(SMP_CACHE_BYTES);
- + struct napi_struct napi_rx;
- + struct napi_struct napi_tx;
- struct gfar __iomem *regs;
- - unsigned int rstat;
- - unsigned long num_rx_queues;
- - unsigned long rx_bit_map;
- - /* cacheline 3 */
- + struct gfar_priv_tx_q *tx_queue;
- + struct gfar_priv_rx_q *rx_queue;
- unsigned int tstat;
- + unsigned int rstat;
- +
- + struct gfar_private *priv;
- unsigned long num_tx_queues;
- unsigned long tx_bit_map;
- + unsigned long num_rx_queues;
- + unsigned long rx_bit_map;
-
- struct gfar_irqinfo *irqinfo[GFAR_NUM_IRQS];
- };
- @@ -1041,6 +1062,11 @@
- GFAR_ERRATA_12 = 0x08, /* a.k.a errata eTSEC49 */
- };
-
- +enum gfar_dev_state {
- + GFAR_DOWN = 1,
- + GFAR_RESETTING
- +};
- +
- /* Struct stolen almost completely (and shamelessly) from the FCC enet source
- * (Ok, that's not so true anymore, but there is a family resemblance)
- * The GFAR buffer descriptors track the ring buffers. The rx_bd_base
- @@ -1051,8 +1077,6 @@
- * the buffer descriptor determines the actual condition.
- */
- struct gfar_private {
- - unsigned int num_rx_queues;
- -
- struct device *dev;
- struct net_device *ndev;
- enum gfar_errata errata;
- @@ -1060,6 +1084,7 @@
-
- u16 uses_rxfcb;
- u16 padding;
- + u32 device_flags;
-
- /* HW time stamping enabled flag */
- int hwts_rx_en;
- @@ -1069,10 +1094,12 @@
- struct gfar_priv_rx_q *rx_queue[MAX_RX_QS];
- struct gfar_priv_grp gfargrp[MAXGROUPS];
-
- - u32 device_flags;
- + unsigned long state;
-
- - unsigned int mode;
- + unsigned short mode;
- + unsigned short poll_mode;
- unsigned int num_tx_queues;
- + unsigned int num_rx_queues;
- unsigned int num_grps;
-
- /* Network Statistics */
- @@ -1113,6 +1140,9 @@
- unsigned int total_tx_ring_size;
- unsigned int total_rx_ring_size;
-
- + u32 rqueue;
- + u32 tqueue;
- +
- /* RX per device parameters */
- unsigned int rx_stash_size;
- unsigned int rx_stash_index;
- @@ -1127,11 +1157,6 @@
- u32 __iomem *hash_regs[16];
- int hash_width;
-
- - /* global parameters */
- - unsigned int fifo_threshold;
- - unsigned int fifo_starve;
- - unsigned int fifo_starve_off;
- -
- /*Filer table*/
- unsigned int ftp_rqfpr[MAX_FILER_IDX + 1];
- unsigned int ftp_rqfcr[MAX_FILER_IDX + 1];
- @@ -1176,21 +1201,42 @@
- *fpr = gfar_read(®s->rqfpr);
- }
-
- -void lock_rx_qs(struct gfar_private *priv);
- -void lock_tx_qs(struct gfar_private *priv);
- -void unlock_rx_qs(struct gfar_private *priv);
- -void unlock_tx_qs(struct gfar_private *priv);
- +static inline void gfar_write_isrg(struct gfar_private *priv)
- +{
- + struct gfar __iomem *regs = priv->gfargrp[0].regs;
- + u32 __iomem *baddr = ®s->isrg0;
- + u32 isrg = 0;
- + int grp_idx, i;
- +
- + for (grp_idx = 0; grp_idx < priv->num_grps; grp_idx++) {
- + struct gfar_priv_grp *grp = &priv->gfargrp[grp_idx];
- +
- + for_each_set_bit(i, &grp->rx_bit_map, priv->num_rx_queues) {
- + isrg |= (ISRG_RR0 >> i);
- + }
- +
- + for_each_set_bit(i, &grp->tx_bit_map, priv->num_tx_queues) {
- + isrg |= (ISRG_TR0 >> i);
- + }
- +
- + gfar_write(baddr, isrg);
- +
- + baddr++;
- + isrg = 0;
- + }
- +}
- +
- irqreturn_t gfar_receive(int irq, void *dev_id);
- int startup_gfar(struct net_device *dev);
- void stop_gfar(struct net_device *dev);
- -void gfar_halt(struct net_device *dev);
- +void reset_gfar(struct net_device *dev);
- +void gfar_mac_reset(struct gfar_private *priv);
- +void gfar_halt(struct gfar_private *priv);
- +void gfar_start(struct gfar_private *priv);
- void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, int enable,
- u32 regnum, u32 read);
- void gfar_configure_coalescing_all(struct gfar_private *priv);
- -void gfar_init_sysfs(struct net_device *dev);
- int gfar_set_features(struct net_device *dev, netdev_features_t features);
- -void gfar_check_rx_parser_mode(struct gfar_private *priv);
- -void gfar_vlan_mode(struct net_device *dev, netdev_features_t features);
-
- extern const struct ethtool_ops gfar_ethtool_ops;
-
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/freescale/gianfar_ptp.c linux-3.14.35/drivers/net/ethernet/freescale/gianfar_ptp.c
- --- linux-3.14.35.orig/drivers/net/ethernet/freescale/gianfar_ptp.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/freescale/gianfar_ptp.c 2015-03-08 14:27:37.685684500 -0500
- @@ -414,6 +414,7 @@
- .n_alarm = 0,
- .n_ext_ts = N_EXT_TS,
- .n_per_out = 0,
- + .n_pins = 0,
- .pps = 1,
- .adjfreq = ptp_gianfar_adjfreq,
- .adjtime = ptp_gianfar_adjtime,
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/freescale/gianfar_sysfs.c linux-3.14.35/drivers/net/ethernet/freescale/gianfar_sysfs.c
- --- linux-3.14.35.orig/drivers/net/ethernet/freescale/gianfar_sysfs.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/freescale/gianfar_sysfs.c 1969-12-31 18:00:00.000000000 -0600
- @@ -1,340 +0,0 @@
- -/*
- - * drivers/net/ethernet/freescale/gianfar_sysfs.c
- - *
- - * Gianfar Ethernet Driver
- - * This driver is designed for the non-CPM ethernet controllers
- - * on the 85xx and 83xx family of integrated processors
- - * Based on 8260_io/fcc_enet.c
- - *
- - * Author: Andy Fleming
- - * Maintainer: Kumar Gala (galak@kernel.crashing.org)
- - * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>
- - *
- - * Copyright 2002-2009 Freescale Semiconductor, 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.
- - *
- - * Sysfs file creation and management
- - */
- -
- -#include <linux/kernel.h>
- -#include <linux/string.h>
- -#include <linux/errno.h>
- -#include <linux/unistd.h>
- -#include <linux/delay.h>
- -#include <linux/etherdevice.h>
- -#include <linux/spinlock.h>
- -#include <linux/mm.h>
- -#include <linux/device.h>
- -
- -#include <asm/uaccess.h>
- -#include <linux/module.h>
- -
- -#include "gianfar.h"
- -
- -static ssize_t gfar_show_bd_stash(struct device *dev,
- - struct device_attribute *attr, char *buf)
- -{
- - struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- -
- - return sprintf(buf, "%s\n", priv->bd_stash_en ? "on" : "off");
- -}
- -
- -static ssize_t gfar_set_bd_stash(struct device *dev,
- - struct device_attribute *attr,
- - const char *buf, size_t count)
- -{
- - struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- - struct gfar __iomem *regs = priv->gfargrp[0].regs;
- - int new_setting = 0;
- - u32 temp;
- - unsigned long flags;
- -
- - if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BD_STASHING))
- - return count;
- -
- -
- - /* Find out the new setting */
- - if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1))
- - new_setting = 1;
- - else if (!strncmp("off", buf, count - 1) ||
- - !strncmp("0", buf, count - 1))
- - new_setting = 0;
- - else
- - return count;
- -
- -
- - local_irq_save(flags);
- - lock_rx_qs(priv);
- -
- - /* Set the new stashing value */
- - priv->bd_stash_en = new_setting;
- -
- - temp = gfar_read(®s->attr);
- -
- - if (new_setting)
- - temp |= ATTR_BDSTASH;
- - else
- - temp &= ~(ATTR_BDSTASH);
- -
- - gfar_write(®s->attr, temp);
- -
- - unlock_rx_qs(priv);
- - local_irq_restore(flags);
- -
- - return count;
- -}
- -
- -static DEVICE_ATTR(bd_stash, 0644, gfar_show_bd_stash, gfar_set_bd_stash);
- -
- -static ssize_t gfar_show_rx_stash_size(struct device *dev,
- - struct device_attribute *attr, char *buf)
- -{
- - struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- -
- - return sprintf(buf, "%d\n", priv->rx_stash_size);
- -}
- -
- -static ssize_t gfar_set_rx_stash_size(struct device *dev,
- - struct device_attribute *attr,
- - const char *buf, size_t count)
- -{
- - struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- - struct gfar __iomem *regs = priv->gfargrp[0].regs;
- - unsigned int length = simple_strtoul(buf, NULL, 0);
- - u32 temp;
- - unsigned long flags;
- -
- - if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING))
- - return count;
- -
- - local_irq_save(flags);
- - lock_rx_qs(priv);
- -
- - if (length > priv->rx_buffer_size)
- - goto out;
- -
- - if (length == priv->rx_stash_size)
- - goto out;
- -
- - priv->rx_stash_size = length;
- -
- - temp = gfar_read(®s->attreli);
- - temp &= ~ATTRELI_EL_MASK;
- - temp |= ATTRELI_EL(length);
- - gfar_write(®s->attreli, temp);
- -
- - /* Turn stashing on/off as appropriate */
- - temp = gfar_read(®s->attr);
- -
- - if (length)
- - temp |= ATTR_BUFSTASH;
- - else
- - temp &= ~(ATTR_BUFSTASH);
- -
- - gfar_write(®s->attr, temp);
- -
- -out:
- - unlock_rx_qs(priv);
- - local_irq_restore(flags);
- -
- - return count;
- -}
- -
- -static DEVICE_ATTR(rx_stash_size, 0644, gfar_show_rx_stash_size,
- - gfar_set_rx_stash_size);
- -
- -/* Stashing will only be enabled when rx_stash_size != 0 */
- -static ssize_t gfar_show_rx_stash_index(struct device *dev,
- - struct device_attribute *attr,
- - char *buf)
- -{
- - struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- -
- - return sprintf(buf, "%d\n", priv->rx_stash_index);
- -}
- -
- -static ssize_t gfar_set_rx_stash_index(struct device *dev,
- - struct device_attribute *attr,
- - const char *buf, size_t count)
- -{
- - struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- - struct gfar __iomem *regs = priv->gfargrp[0].regs;
- - unsigned short index = simple_strtoul(buf, NULL, 0);
- - u32 temp;
- - unsigned long flags;
- -
- - if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING))
- - return count;
- -
- - local_irq_save(flags);
- - lock_rx_qs(priv);
- -
- - if (index > priv->rx_stash_size)
- - goto out;
- -
- - if (index == priv->rx_stash_index)
- - goto out;
- -
- - priv->rx_stash_index = index;
- -
- - temp = gfar_read(®s->attreli);
- - temp &= ~ATTRELI_EI_MASK;
- - temp |= ATTRELI_EI(index);
- - gfar_write(®s->attreli, temp);
- -
- -out:
- - unlock_rx_qs(priv);
- - local_irq_restore(flags);
- -
- - return count;
- -}
- -
- -static DEVICE_ATTR(rx_stash_index, 0644, gfar_show_rx_stash_index,
- - gfar_set_rx_stash_index);
- -
- -static ssize_t gfar_show_fifo_threshold(struct device *dev,
- - struct device_attribute *attr,
- - char *buf)
- -{
- - struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- -
- - return sprintf(buf, "%d\n", priv->fifo_threshold);
- -}
- -
- -static ssize_t gfar_set_fifo_threshold(struct device *dev,
- - struct device_attribute *attr,
- - const char *buf, size_t count)
- -{
- - struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- - struct gfar __iomem *regs = priv->gfargrp[0].regs;
- - unsigned int length = simple_strtoul(buf, NULL, 0);
- - u32 temp;
- - unsigned long flags;
- -
- - if (length > GFAR_MAX_FIFO_THRESHOLD)
- - return count;
- -
- - local_irq_save(flags);
- - lock_tx_qs(priv);
- -
- - priv->fifo_threshold = length;
- -
- - temp = gfar_read(®s->fifo_tx_thr);
- - temp &= ~FIFO_TX_THR_MASK;
- - temp |= length;
- - gfar_write(®s->fifo_tx_thr, temp);
- -
- - unlock_tx_qs(priv);
- - local_irq_restore(flags);
- -
- - return count;
- -}
- -
- -static DEVICE_ATTR(fifo_threshold, 0644, gfar_show_fifo_threshold,
- - gfar_set_fifo_threshold);
- -
- -static ssize_t gfar_show_fifo_starve(struct device *dev,
- - struct device_attribute *attr, char *buf)
- -{
- - struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- -
- - return sprintf(buf, "%d\n", priv->fifo_starve);
- -}
- -
- -static ssize_t gfar_set_fifo_starve(struct device *dev,
- - struct device_attribute *attr,
- - const char *buf, size_t count)
- -{
- - struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- - struct gfar __iomem *regs = priv->gfargrp[0].regs;
- - unsigned int num = simple_strtoul(buf, NULL, 0);
- - u32 temp;
- - unsigned long flags;
- -
- - if (num > GFAR_MAX_FIFO_STARVE)
- - return count;
- -
- - local_irq_save(flags);
- - lock_tx_qs(priv);
- -
- - priv->fifo_starve = num;
- -
- - temp = gfar_read(®s->fifo_tx_starve);
- - temp &= ~FIFO_TX_STARVE_MASK;
- - temp |= num;
- - gfar_write(®s->fifo_tx_starve, temp);
- -
- - unlock_tx_qs(priv);
- - local_irq_restore(flags);
- -
- - return count;
- -}
- -
- -static DEVICE_ATTR(fifo_starve, 0644, gfar_show_fifo_starve,
- - gfar_set_fifo_starve);
- -
- -static ssize_t gfar_show_fifo_starve_off(struct device *dev,
- - struct device_attribute *attr,
- - char *buf)
- -{
- - struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- -
- - return sprintf(buf, "%d\n", priv->fifo_starve_off);
- -}
- -
- -static ssize_t gfar_set_fifo_starve_off(struct device *dev,
- - struct device_attribute *attr,
- - const char *buf, size_t count)
- -{
- - struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- - struct gfar __iomem *regs = priv->gfargrp[0].regs;
- - unsigned int num = simple_strtoul(buf, NULL, 0);
- - u32 temp;
- - unsigned long flags;
- -
- - if (num > GFAR_MAX_FIFO_STARVE_OFF)
- - return count;
- -
- - local_irq_save(flags);
- - lock_tx_qs(priv);
- -
- - priv->fifo_starve_off = num;
- -
- - temp = gfar_read(®s->fifo_tx_starve_shutoff);
- - temp &= ~FIFO_TX_STARVE_OFF_MASK;
- - temp |= num;
- - gfar_write(®s->fifo_tx_starve_shutoff, temp);
- -
- - unlock_tx_qs(priv);
- - local_irq_restore(flags);
- -
- - return count;
- -}
- -
- -static DEVICE_ATTR(fifo_starve_off, 0644, gfar_show_fifo_starve_off,
- - gfar_set_fifo_starve_off);
- -
- -void gfar_init_sysfs(struct net_device *dev)
- -{
- - struct gfar_private *priv = netdev_priv(dev);
- - int rc;
- -
- - /* Initialize the default values */
- - priv->fifo_threshold = DEFAULT_FIFO_TX_THR;
- - priv->fifo_starve = DEFAULT_FIFO_TX_STARVE;
- - priv->fifo_starve_off = DEFAULT_FIFO_TX_STARVE_OFF;
- -
- - /* Create our sysfs files */
- - rc = device_create_file(&dev->dev, &dev_attr_bd_stash);
- - rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_size);
- - rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_index);
- - rc |= device_create_file(&dev->dev, &dev_attr_fifo_threshold);
- - rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve);
- - rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve_off);
- - if (rc)
- - dev_err(&dev->dev, "Error creating gianfar sysfs files\n");
- -}
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/freescale/Kconfig linux-3.14.35/drivers/net/ethernet/freescale/Kconfig
- --- linux-3.14.35.orig/drivers/net/ethernet/freescale/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/freescale/Kconfig 2015-03-08 14:27:37.685684500 -0500
- @@ -67,6 +67,7 @@
- tristate "Freescale XGMAC MDIO"
- depends on FSL_SOC
- select PHYLIB
- + select OF_MDIO
- ---help---
- This driver supports the MDIO bus on the Fman 10G Ethernet MACs.
-
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/freescale/Makefile linux-3.14.35/drivers/net/ethernet/freescale/Makefile
- --- linux-3.14.35.orig/drivers/net/ethernet/freescale/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/freescale/Makefile 2015-03-08 14:27:37.685684500 -0500
- @@ -14,7 +14,6 @@
- obj-$(CONFIG_GIANFAR) += gianfar_driver.o
- obj-$(CONFIG_PTP_1588_CLOCK_GIANFAR) += gianfar_ptp.o
- gianfar_driver-objs := gianfar.o \
- - gianfar_ethtool.o \
- - gianfar_sysfs.o
- + gianfar_ethtool.o
- obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
- ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/freescale/ucc_geth.c linux-3.14.35/drivers/net/ethernet/freescale/ucc_geth.c
- --- linux-3.14.35.orig/drivers/net/ethernet/freescale/ucc_geth.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/freescale/ucc_geth.c 2015-03-08 14:27:37.685684500 -0500
- @@ -1728,9 +1728,6 @@
-
- phydev = of_phy_connect(dev, ug_info->phy_node, &adjust_link, 0,
- priv->phy_interface);
- - if (!phydev)
- - phydev = of_phy_connect_fixed_link(dev, &adjust_link,
- - priv->phy_interface);
- if (!phydev) {
- dev_err(&dev->dev, "Could not attach to PHY\n");
- return -ENODEV;
- @@ -3261,7 +3258,7 @@
-
- dev->stats.tx_packets++;
-
- - dev_kfree_skb(skb);
- + dev_consume_skb_any(skb);
-
- ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL;
- ugeth->skb_dirtytx[txQ] =
- @@ -3790,6 +3787,17 @@
- ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);
-
- ug_info->phy_node = of_parse_phandle(np, "phy-handle", 0);
- + if (!ug_info->phy_node) {
- + /* In the case of a fixed PHY, the DT node associated
- + * to the PHY is the Ethernet MAC DT node.
- + */
- + if (of_phy_is_fixed_link(np)) {
- + err = of_phy_register_fixed_link(np);
- + if (err)
- + return err;
- + }
- + ug_info->phy_node = np;
- + }
-
- /* Find the TBI PHY node. If it's not there, we don't support SGMII */
- ug_info->tbi_node = of_parse_phandle(np, "tbi-handle", 0);
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/freescale/xgmac_mdio.c linux-3.14.35/drivers/net/ethernet/freescale/xgmac_mdio.c
- --- linux-3.14.35.orig/drivers/net/ethernet/freescale/xgmac_mdio.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/freescale/xgmac_mdio.c 2015-03-08 14:27:37.685684500 -0500
- @@ -162,7 +162,9 @@
-
- /* Return all Fs if nothing was there */
- if (in_be32(®s->mdio_stat) & MDIO_STAT_RD_ER) {
- - dev_err(&bus->dev, "MDIO read error\n");
- + dev_err(&bus->dev,
- + "Error while reading PHY%d reg at %d.%d\n",
- + phy_id, dev_addr, regnum);
- return 0xffff;
- }
-
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/intel/e1000e/ptp.c linux-3.14.35/drivers/net/ethernet/intel/e1000e/ptp.c
- --- linux-3.14.35.orig/drivers/net/ethernet/intel/e1000e/ptp.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/intel/e1000e/ptp.c 2015-03-08 14:27:37.685684500 -0500
- @@ -191,6 +191,7 @@
- .n_alarm = 0,
- .n_ext_ts = 0,
- .n_per_out = 0,
- + .n_pins = 0,
- .pps = 0,
- .adjfreq = e1000e_phc_adjfreq,
- .adjtime = e1000e_phc_adjtime,
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/mellanox/mlx4/en_clock.c linux-3.14.35/drivers/net/ethernet/mellanox/mlx4/en_clock.c
- --- linux-3.14.35.orig/drivers/net/ethernet/mellanox/mlx4/en_clock.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/mellanox/mlx4/en_clock.c 2015-03-08 14:27:37.685684500 -0500
- @@ -276,6 +276,7 @@
- .n_alarm = 0,
- .n_ext_ts = 0,
- .n_per_out = 0,
- + .n_pins = 0,
- .pps = 0,
- .adjfreq = mlx4_en_phc_adjfreq,
- .adjtime = mlx4_en_phc_adjtime,
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/sfc/ptp.c linux-3.14.35/drivers/net/ethernet/sfc/ptp.c
- --- linux-3.14.35.orig/drivers/net/ethernet/sfc/ptp.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/sfc/ptp.c 2015-03-08 14:27:37.685684500 -0500
- @@ -1208,6 +1208,7 @@
- .n_alarm = 0,
- .n_ext_ts = 0,
- .n_per_out = 0,
- + .n_pins = 0,
- .pps = 1,
- .adjfreq = efx_phc_adjfreq,
- .adjtime = efx_phc_adjtime,
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c linux-3.14.35/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
- --- linux-3.14.35.orig/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c 2015-03-08 14:27:37.685684500 -0500
- @@ -164,6 +164,7 @@
- .n_alarm = 0,
- .n_ext_ts = 0,
- .n_per_out = 0,
- + .n_pins = 0,
- .pps = 0,
- .adjfreq = stmmac_adjust_freq,
- .adjtime = stmmac_adjust_time,
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/ti/cpts.c linux-3.14.35/drivers/net/ethernet/ti/cpts.c
- --- linux-3.14.35.orig/drivers/net/ethernet/ti/cpts.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/ti/cpts.c 2015-03-08 14:27:37.685684500 -0500
- @@ -217,6 +217,7 @@
- .name = "CTPS timer",
- .max_adj = 1000000,
- .n_ext_ts = 0,
- + .n_pins = 0,
- .pps = 0,
- .adjfreq = cpts_ptp_adjfreq,
- .adjtime = cpts_ptp_adjtime,
- diff -Nur linux-3.14.35.orig/drivers/net/ethernet/tile/tilegx.c linux-3.14.35/drivers/net/ethernet/tile/tilegx.c
- --- linux-3.14.35.orig/drivers/net/ethernet/tile/tilegx.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ethernet/tile/tilegx.c 2015-03-08 14:27:37.685684500 -0500
- @@ -870,6 +870,7 @@
- .name = "mPIPE clock",
- .max_adj = 999999999,
- .n_ext_ts = 0,
- + .n_pins = 0,
- .pps = 0,
- .adjfreq = ptp_mpipe_adjfreq,
- .adjtime = ptp_mpipe_adjtime,
- diff -Nur linux-3.14.35.orig/drivers/net/ieee802154/Kconfig linux-3.14.35/drivers/net/ieee802154/Kconfig
- --- linux-3.14.35.orig/drivers/net/ieee802154/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/ieee802154/Kconfig 2015-03-08 14:27:37.685684500 -0500
- @@ -15,9 +15,9 @@
- depends on IEEE802154_DRIVERS
- ---help---
- Say Y here to enable the fake driver that serves as an example
- - of HardMAC device driver.
- + of HardMAC device driver.
-
- - This driver can also be built as a module. To do so say M here.
- + This driver can also be built as a module. To do so say M here.
- The module will be called 'fakehard'.
-
- config IEEE802154_FAKELB
- @@ -31,17 +31,17 @@
- The module will be called 'fakelb'.
-
- config IEEE802154_AT86RF230
- - depends on IEEE802154_DRIVERS && MAC802154
- - tristate "AT86RF230/231 transceiver driver"
- - depends on SPI
- + depends on IEEE802154_DRIVERS && MAC802154
- + tristate "AT86RF230/231 transceiver driver"
- + depends on SPI
-
- config IEEE802154_MRF24J40
- - tristate "Microchip MRF24J40 transceiver driver"
- - depends on IEEE802154_DRIVERS && MAC802154
- - depends on SPI
- - ---help---
- - Say Y here to enable the MRF24J20 SPI 802.15.4 wireless
- - controller.
- + tristate "Microchip MRF24J40 transceiver driver"
- + depends on IEEE802154_DRIVERS && MAC802154
- + depends on SPI
- + ---help---
- + Say Y here to enable the MRF24J20 SPI 802.15.4 wireless
- + controller.
-
- - This driver can also be built as a module. To do so, say M here.
- - the module will be called 'mrf24j40'.
- + This driver can also be built as a module. To do so, say M here.
- + the module will be called 'mrf24j40'.
- diff -Nur linux-3.14.35.orig/drivers/net/phy/at803x.c linux-3.14.35/drivers/net/phy/at803x.c
- --- linux-3.14.35.orig/drivers/net/phy/at803x.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/phy/at803x.c 2015-03-08 14:27:37.689684500 -0500
- @@ -27,6 +27,9 @@
- #define AT803X_MMD_ACCESS_CONTROL 0x0D
- #define AT803X_MMD_ACCESS_CONTROL_DATA 0x0E
- #define AT803X_FUNC_DATA 0x4003
- +#define AT803X_INER 0x0012
- +#define AT803X_INER_INIT 0xec00
- +#define AT803X_INSR 0x0013
- #define AT803X_DEBUG_ADDR 0x1D
- #define AT803X_DEBUG_DATA 0x1E
- #define AT803X_DEBUG_SYSTEM_MODE_CTRL 0x05
- @@ -141,41 +144,11 @@
-
- static int at803x_config_init(struct phy_device *phydev)
- {
- - int val;
- int ret;
- - u32 features;
-
- - features = SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_AUI |
- - SUPPORTED_FIBRE | SUPPORTED_BNC;
- -
- - val = phy_read(phydev, MII_BMSR);
- - if (val < 0)
- - return val;
- -
- - if (val & BMSR_ANEGCAPABLE)
- - features |= SUPPORTED_Autoneg;
- - if (val & BMSR_100FULL)
- - features |= SUPPORTED_100baseT_Full;
- - if (val & BMSR_100HALF)
- - features |= SUPPORTED_100baseT_Half;
- - if (val & BMSR_10FULL)
- - features |= SUPPORTED_10baseT_Full;
- - if (val & BMSR_10HALF)
- - features |= SUPPORTED_10baseT_Half;
- -
- - if (val & BMSR_ESTATEN) {
- - val = phy_read(phydev, MII_ESTATUS);
- - if (val < 0)
- - return val;
- -
- - if (val & ESTATUS_1000_TFULL)
- - features |= SUPPORTED_1000baseT_Full;
- - if (val & ESTATUS_1000_THALF)
- - features |= SUPPORTED_1000baseT_Half;
- - }
- -
- - phydev->supported = features;
- - phydev->advertising = features;
- + ret = genphy_config_init(phydev);
- + if (ret < 0)
- + return ret;
-
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
- ret = phy_write(phydev, AT803X_DEBUG_ADDR,
- @@ -191,6 +164,31 @@
- return 0;
- }
-
- +static int at803x_ack_interrupt(struct phy_device *phydev)
- +{
- + int err;
- +
- + err = phy_read(phydev, AT803X_INSR);
- +
- + return (err < 0) ? err : 0;
- +}
- +
- +static int at803x_config_intr(struct phy_device *phydev)
- +{
- + int err;
- + int value;
- +
- + value = phy_read(phydev, AT803X_INER);
- +
- + if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
- + err = phy_write(phydev, AT803X_INER,
- + value | AT803X_INER_INIT);
- + else
- + err = phy_write(phydev, AT803X_INER, 0);
- +
- + return err;
- +}
- +
- static struct phy_driver at803x_driver[] = {
- {
- /* ATHEROS 8035 */
- @@ -240,6 +238,8 @@
- .flags = PHY_HAS_INTERRUPT,
- .config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
- + .ack_interrupt = &at803x_ack_interrupt,
- + .config_intr = &at803x_config_intr,
- .driver = {
- .owner = THIS_MODULE,
- },
- @@ -253,8 +253,7 @@
-
- static void __exit atheros_exit(void)
- {
- - return phy_drivers_unregister(at803x_driver,
- - ARRAY_SIZE(at803x_driver));
- + phy_drivers_unregister(at803x_driver, ARRAY_SIZE(at803x_driver));
- }
-
- module_init(atheros_init);
- diff -Nur linux-3.14.35.orig/drivers/net/phy/phy_device.c linux-3.14.35/drivers/net/phy/phy_device.c
- --- linux-3.14.35.orig/drivers/net/phy/phy_device.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/phy/phy_device.c 2015-03-08 14:27:37.689684500 -0500
- @@ -1029,7 +1029,7 @@
- return 0;
- }
-
- -static int genphy_config_init(struct phy_device *phydev)
- +int genphy_config_init(struct phy_device *phydev)
- {
- int val;
- u32 features;
- @@ -1075,6 +1075,8 @@
- return 0;
- }
-
- +EXPORT_SYMBOL(genphy_config_init);
- +
- static int gen10g_config_init(struct phy_device *phydev)
- {
- /* Temporarily just say we support everything */
- diff -Nur linux-3.14.35.orig/drivers/net/phy/smsc.c linux-3.14.35/drivers/net/phy/smsc.c
- --- linux-3.14.35.orig/drivers/net/phy/smsc.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/phy/smsc.c 2015-03-08 14:27:37.689684500 -0500
- @@ -249,8 +249,7 @@
-
- static void __exit smsc_exit(void)
- {
- - return phy_drivers_unregister(smsc_phy_driver,
- - ARRAY_SIZE(smsc_phy_driver));
- + phy_drivers_unregister(smsc_phy_driver, ARRAY_SIZE(smsc_phy_driver));
- }
-
- MODULE_DESCRIPTION("SMSC PHY driver");
- diff -Nur linux-3.14.35.orig/drivers/net/phy/vitesse.c linux-3.14.35/drivers/net/phy/vitesse.c
- --- linux-3.14.35.orig/drivers/net/phy/vitesse.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/phy/vitesse.c 2015-03-08 14:27:37.689684500 -0500
- @@ -319,8 +319,7 @@
-
- static void __exit vsc82xx_exit(void)
- {
- - return phy_drivers_unregister(vsc82xx_driver,
- - ARRAY_SIZE(vsc82xx_driver));
- + phy_drivers_unregister(vsc82xx_driver, ARRAY_SIZE(vsc82xx_driver));
- }
-
- module_init(vsc82xx_init);
- diff -Nur linux-3.14.35.orig/drivers/net/veth.c linux-3.14.35/drivers/net/veth.c
- --- linux-3.14.35.orig/drivers/net/veth.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/veth.c 2015-03-08 14:27:37.689684500 -0500
- @@ -14,6 +14,7 @@
- #include <linux/etherdevice.h>
- #include <linux/u64_stats_sync.h>
-
- +#include <net/rtnetlink.h>
- #include <net/dst.h>
- #include <net/xfrm.h>
- #include <linux/veth.h>
- @@ -336,10 +337,9 @@
-
- nla_peer = data[VETH_INFO_PEER];
- ifmp = nla_data(nla_peer);
- - err = nla_parse(peer_tb, IFLA_MAX,
- - nla_data(nla_peer) + sizeof(struct ifinfomsg),
- - nla_len(nla_peer) - sizeof(struct ifinfomsg),
- - ifla_policy);
- + err = rtnl_nla_parse_ifla(peer_tb,
- + nla_data(nla_peer) + sizeof(struct ifinfomsg),
- + nla_len(nla_peer) - sizeof(struct ifinfomsg));
- if (err < 0)
- return err;
-
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/ath/ar5523/ar5523.c linux-3.14.35/drivers/net/wireless/ath/ar5523/ar5523.c
- --- linux-3.14.35.orig/drivers/net/wireless/ath/ar5523/ar5523.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/ath/ar5523/ar5523.c 2015-03-08 14:27:37.689684500 -0500
- @@ -1090,7 +1090,8 @@
- return ret;
- }
-
- -static void ar5523_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
- +static void ar5523_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- + u32 queues, bool drop)
- {
- struct ar5523 *ar = hw->priv;
-
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/ath/ath10k/mac.c linux-3.14.35/drivers/net/wireless/ath/ath10k/mac.c
- --- linux-3.14.35.orig/drivers/net/wireless/ath/ath10k/mac.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/ath/ath10k/mac.c 2015-03-08 14:27:37.689684500 -0500
- @@ -3183,7 +3183,8 @@
- return ret;
- }
-
- -static void ath10k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
- +static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- + u32 queues, bool drop)
- {
- struct ath10k *ar = hw->priv;
- bool skip;
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/ath/ath6kl/cfg80211.c linux-3.14.35/drivers/net/wireless/ath/ath6kl/cfg80211.c
- --- linux-3.14.35.orig/drivers/net/wireless/ath/ath6kl/cfg80211.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/ath/ath6kl/cfg80211.c 2015-03-08 14:27:37.689684500 -0500
- @@ -790,7 +790,7 @@
- if (nw_type & ADHOC_NETWORK) {
- ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n",
- nw_type & ADHOC_CREATOR ? "creator" : "joiner");
- - cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
- + cfg80211_ibss_joined(vif->ndev, bssid, chan, GFP_KERNEL);
- cfg80211_put_bss(ar->wiphy, bss);
- return;
- }
- @@ -861,13 +861,9 @@
- }
-
- if (vif->nw_type & ADHOC_NETWORK) {
- - if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) {
- + if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC)
- ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
- "%s: ath6k not in ibss mode\n", __func__);
- - return;
- - }
- - memset(bssid, 0, ETH_ALEN);
- - cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
- return;
- }
-
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/ath/ath6kl/hif.h linux-3.14.35/drivers/net/wireless/ath/ath6kl/hif.h
- --- linux-3.14.35.orig/drivers/net/wireless/ath/ath6kl/hif.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/ath/ath6kl/hif.h 2015-03-08 14:27:37.689684500 -0500
- @@ -197,9 +197,9 @@
- /* bounce buffer for upper layers to copy to/from */
- u8 *virt_dma_buf;
-
- - struct hif_scatter_item scat_list[1];
- -
- u32 scat_q_depth;
- +
- + struct hif_scatter_item scat_list[0];
- };
-
- struct ath6kl_irq_proc_registers {
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/ath/ath6kl/sdio.c linux-3.14.35/drivers/net/wireless/ath/ath6kl/sdio.c
- --- linux-3.14.35.orig/drivers/net/wireless/ath/ath6kl/sdio.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/ath/ath6kl/sdio.c 2015-03-08 14:27:37.689684500 -0500
- @@ -222,6 +222,7 @@
- struct mmc_data *data)
- {
- struct scatterlist *sg;
- + struct hif_scatter_item *scat_list;
- int i;
-
- data->blksz = HIF_MBOX_BLOCK_SIZE;
- @@ -240,14 +241,14 @@
- sg = scat_req->sgentries;
- sg_init_table(sg, scat_req->scat_entries);
-
- + scat_list = &scat_req->scat_list[0];
- +
- /* assemble SG list */
- - for (i = 0; i < scat_req->scat_entries; i++, sg++) {
- + for (i = 0; i < scat_req->scat_entries; i++, sg++, scat_list++) {
- ath6kl_dbg(ATH6KL_DBG_SCATTER, "%d: addr:0x%p, len:%d\n",
- - i, scat_req->scat_list[i].buf,
- - scat_req->scat_list[i].len);
- + i, scat_list->buf, scat_list->len);
-
- - sg_set_buf(sg, scat_req->scat_list[i].buf,
- - scat_req->scat_list[i].len);
- + sg_set_buf(sg, scat_list->buf, scat_list->len);
- }
-
- /* set scatter-gather table for request */
- @@ -348,7 +349,7 @@
- int i, scat_req_sz, scat_list_sz, size;
- u8 *virt_buf;
-
- - scat_list_sz = (n_scat_entry - 1) * sizeof(struct hif_scatter_item);
- + scat_list_sz = n_scat_entry * sizeof(struct hif_scatter_item);
- scat_req_sz = sizeof(*s_req) + scat_list_sz;
-
- if (!virt_scat)
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/ath/ath9k/main.c linux-3.14.35/drivers/net/wireless/ath/ath9k/main.c
- --- linux-3.14.35.orig/drivers/net/wireless/ath/ath9k/main.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/ath/ath9k/main.c 2015-03-08 14:27:37.689684500 -0500
- @@ -1883,7 +1883,8 @@
- return !!npend;
- }
-
- -static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
- +static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- + u32 queues, bool drop)
- {
- struct ath_softc *sc = hw->priv;
- struct ath_hw *ah = sc->sc_ah;
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/ath/carl9170/main.c linux-3.14.35/drivers/net/wireless/ath/carl9170/main.c
- --- linux-3.14.35.orig/drivers/net/wireless/ath/carl9170/main.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/ath/carl9170/main.c 2015-03-08 14:27:37.693684500 -0500
- @@ -1707,7 +1707,9 @@
- return 0;
- }
-
- -static void carl9170_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
- +static void carl9170_op_flush(struct ieee80211_hw *hw,
- + struct ieee80211_vif *vif,
- + u32 queues, bool drop)
- {
- struct ar9170 *ar = hw->priv;
- unsigned int vid;
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c 2015-03-08 14:27:37.693684500 -0500
- @@ -43,7 +43,6 @@
- #include "dhd_bus.h"
- #include "dhd_dbg.h"
- #include "sdio_host.h"
- -#include "sdio_chip.h"
-
- #define SDIOH_API_ACCESS_RETRY_LIMIT 2
-
- @@ -54,6 +53,12 @@
- /* Maximum milliseconds to wait for F2 to come up */
- #define SDIO_WAIT_F2RDY 3000
-
- +#define BRCMF_DEFAULT_TXGLOM_SIZE 32 /* max tx frames in glom chain */
- +#define BRCMF_DEFAULT_RXGLOM_SIZE 32 /* max rx frames in glom chain */
- +
- +static int brcmf_sdiod_txglomsz = BRCMF_DEFAULT_TXGLOM_SIZE;
- +module_param_named(txglomsz, brcmf_sdiod_txglomsz, int, 0);
- +MODULE_PARM_DESC(txglomsz, "maximum tx packet chain size [SDIO]");
-
- static irqreturn_t brcmf_sdiod_oob_irqhandler(int irq, void *dev_id)
- {
- @@ -264,26 +269,17 @@
- break;
- }
-
- - if (ret) {
- - /*
- - * SleepCSR register access can fail when
- - * waking up the device so reduce this noise
- - * in the logs.
- - */
- - if (addr != SBSDIO_FUNC1_SLEEPCSR)
- - brcmf_err("failed to %s data F%d@0x%05x, err: %d\n",
- - write ? "write" : "read", fn, addr, ret);
- - else
- - brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n",
- - write ? "write" : "read", fn, addr, ret);
- - }
- + if (ret)
- + brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n",
- + write ? "write" : "read", fn, addr, ret);
- +
- return ret;
- }
-
- static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
- u8 regsz, void *data, bool write)
- {
- - u8 func_num;
- + u8 func;
- s32 retry = 0;
- int ret;
-
- @@ -297,9 +293,9 @@
- * The rest: function 1 silicon backplane core registers
- */
- if ((addr & ~REG_F0_REG_MASK) == 0)
- - func_num = SDIO_FUNC_0;
- + func = SDIO_FUNC_0;
- else
- - func_num = SDIO_FUNC_1;
- + func = SDIO_FUNC_1;
-
- do {
- if (!write)
- @@ -307,16 +303,26 @@
- /* for retry wait for 1 ms till bus get settled down */
- if (retry)
- usleep_range(1000, 2000);
- - ret = brcmf_sdiod_request_data(sdiodev, func_num, addr, regsz,
- + ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz,
- data, write);
- } while (ret != 0 && ret != -ENOMEDIUM &&
- retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
-
- if (ret == -ENOMEDIUM)
- brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_NOMEDIUM);
- - else if (ret != 0)
- - brcmf_err("failed with %d\n", ret);
- -
- + else if (ret != 0) {
- + /*
- + * SleepCSR register access can fail when
- + * waking up the device so reduce this noise
- + * in the logs.
- + */
- + if (addr != SBSDIO_FUNC1_SLEEPCSR)
- + brcmf_err("failed to %s data F%d@0x%05x, err: %d\n",
- + write ? "write" : "read", func, addr, ret);
- + else
- + brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n",
- + write ? "write" : "read", func, addr, ret);
- + }
- return ret;
- }
-
- @@ -488,7 +494,6 @@
- struct mmc_request mmc_req;
- struct mmc_command mmc_cmd;
- struct mmc_data mmc_dat;
- - struct sg_table st;
- struct scatterlist *sgl;
- int ret = 0;
-
- @@ -533,16 +538,11 @@
- pkt_offset = 0;
- pkt_next = target_list->next;
-
- - if (sg_alloc_table(&st, max_seg_cnt, GFP_KERNEL)) {
- - ret = -ENOMEM;
- - goto exit;
- - }
- -
- memset(&mmc_req, 0, sizeof(struct mmc_request));
- memset(&mmc_cmd, 0, sizeof(struct mmc_command));
- memset(&mmc_dat, 0, sizeof(struct mmc_data));
-
- - mmc_dat.sg = st.sgl;
- + mmc_dat.sg = sdiodev->sgtable.sgl;
- mmc_dat.blksz = func_blk_sz;
- mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
- mmc_cmd.opcode = SD_IO_RW_EXTENDED;
- @@ -558,7 +558,7 @@
- while (seg_sz) {
- req_sz = 0;
- sg_cnt = 0;
- - sgl = st.sgl;
- + sgl = sdiodev->sgtable.sgl;
- /* prep sg table */
- while (pkt_next != (struct sk_buff *)target_list) {
- pkt_data = pkt_next->data + pkt_offset;
- @@ -640,7 +640,7 @@
- }
-
- exit:
- - sg_free_table(&st);
- + sg_init_table(sdiodev->sgtable.sgl, sdiodev->sgtable.orig_nents);
- while ((pkt_next = __skb_dequeue(&local_list)) != NULL)
- brcmu_pkt_buf_free_skb(pkt_next);
-
- @@ -827,7 +827,7 @@
- }
- if (!write)
- memcpy(data, pkt->data, dsize);
- - skb_trim(pkt, dsize);
- + skb_trim(pkt, 0);
-
- /* Adjust for next transfer (if any) */
- size -= dsize;
- @@ -864,6 +864,29 @@
- return 0;
- }
-
- +static void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev)
- +{
- + uint nents;
- + int err;
- +
- + if (!sdiodev->sg_support)
- + return;
- +
- + nents = max_t(uint, BRCMF_DEFAULT_RXGLOM_SIZE, brcmf_sdiod_txglomsz);
- + nents += (nents >> 4) + 1;
- +
- + WARN_ON(nents > sdiodev->max_segment_count);
- +
- + brcmf_dbg(TRACE, "nents=%d\n", nents);
- + err = sg_alloc_table(&sdiodev->sgtable, nents, GFP_KERNEL);
- + if (err < 0) {
- + brcmf_err("allocation failed: disable scatter-gather");
- + sdiodev->sg_support = false;
- + }
- +
- + sdiodev->txglomsz = brcmf_sdiod_txglomsz;
- +}
- +
- static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev)
- {
- if (sdiodev->bus) {
- @@ -881,6 +904,7 @@
- sdio_disable_func(sdiodev->func[1]);
- sdio_release_host(sdiodev->func[1]);
-
- + sg_free_table(&sdiodev->sgtable);
- sdiodev->sbwad = 0;
-
- return 0;
- @@ -936,6 +960,11 @@
- SG_MAX_SINGLE_ALLOC);
- sdiodev->max_segment_size = host->max_seg_size;
-
- + /* allocate scatter-gather table. sg support
- + * will be disabled upon allocation failure.
- + */
- + brcmf_sdiod_sgtable_alloc(sdiodev);
- +
- /* try to attach to the target device */
- sdiodev->bus = brcmf_sdio_probe(sdiodev);
- if (!sdiodev->bus) {
- @@ -960,6 +989,7 @@
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43362)},
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM,
- SDIO_DEVICE_ID_BROADCOM_4335_4339)},
- + {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4354)},
- { /* end: all zeroes */ },
- };
- MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
- @@ -1073,9 +1103,7 @@
- struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
- int ret = 0;
-
- - brcmf_dbg(SDIO, "\n");
- -
- - atomic_set(&sdiodev->suspend, true);
- + brcmf_dbg(SDIO, "Enter\n");
-
- sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]);
- if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
- @@ -1083,9 +1111,12 @@
- return -EINVAL;
- }
-
- + atomic_set(&sdiodev->suspend, true);
- +
- ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER);
- if (ret) {
- brcmf_err("Failed to set pm_flags\n");
- + atomic_set(&sdiodev->suspend, false);
- return ret;
- }
-
- @@ -1099,6 +1130,7 @@
- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
-
- + brcmf_dbg(SDIO, "Enter\n");
- brcmf_sdio_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
- atomic_set(&sdiodev->suspend, false);
- return 0;
- @@ -1115,14 +1147,15 @@
- .remove = brcmf_ops_sdio_remove,
- .name = BRCMFMAC_SDIO_PDATA_NAME,
- .id_table = brcmf_sdmmc_ids,
- -#ifdef CONFIG_PM_SLEEP
- .drv = {
- + .owner = THIS_MODULE,
- +#ifdef CONFIG_PM_SLEEP
- .pm = &brcmf_sdio_pm_ops,
- - },
- #endif /* CONFIG_PM_SLEEP */
- + },
- };
-
- -static int brcmf_sdio_pd_probe(struct platform_device *pdev)
- +static int __init brcmf_sdio_pd_probe(struct platform_device *pdev)
- {
- brcmf_dbg(SDIO, "Enter\n");
-
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/chip.c linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/chip.c
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/chip.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/chip.c 2015-03-08 14:27:37.693684500 -0500
- @@ -0,0 +1,1035 @@
- +/*
- + * Copyright (c) 2014 Broadcom Corporation
- + *
- + * Permission to use, copy, modify, and/or distribute this software for any
- + * purpose with or without fee is hereby granted, provided that the above
- + * copyright notice and this permission notice appear in all copies.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- + */
- +#include <linux/kernel.h>
- +#include <linux/delay.h>
- +#include <linux/list.h>
- +#include <linux/ssb/ssb_regs.h>
- +#include <linux/bcma/bcma.h>
- +#include <linux/bcma/bcma_regs.h>
- +
- +#include <defs.h>
- +#include <soc.h>
- +#include <brcm_hw_ids.h>
- +#include <brcmu_utils.h>
- +#include <chipcommon.h>
- +#include "dhd_dbg.h"
- +#include "chip.h"
- +
- +/* SOC Interconnect types (aka chip types) */
- +#define SOCI_SB 0
- +#define SOCI_AI 1
- +
- +/* PL-368 DMP definitions */
- +#define DMP_DESC_TYPE_MSK 0x0000000F
- +#define DMP_DESC_EMPTY 0x00000000
- +#define DMP_DESC_VALID 0x00000001
- +#define DMP_DESC_COMPONENT 0x00000001
- +#define DMP_DESC_MASTER_PORT 0x00000003
- +#define DMP_DESC_ADDRESS 0x00000005
- +#define DMP_DESC_ADDRSIZE_GT32 0x00000008
- +#define DMP_DESC_EOT 0x0000000F
- +
- +#define DMP_COMP_DESIGNER 0xFFF00000
- +#define DMP_COMP_DESIGNER_S 20
- +#define DMP_COMP_PARTNUM 0x000FFF00
- +#define DMP_COMP_PARTNUM_S 8
- +#define DMP_COMP_CLASS 0x000000F0
- +#define DMP_COMP_CLASS_S 4
- +#define DMP_COMP_REVISION 0xFF000000
- +#define DMP_COMP_REVISION_S 24
- +#define DMP_COMP_NUM_SWRAP 0x00F80000
- +#define DMP_COMP_NUM_SWRAP_S 19
- +#define DMP_COMP_NUM_MWRAP 0x0007C000
- +#define DMP_COMP_NUM_MWRAP_S 14
- +#define DMP_COMP_NUM_SPORT 0x00003E00
- +#define DMP_COMP_NUM_SPORT_S 9
- +#define DMP_COMP_NUM_MPORT 0x000001F0
- +#define DMP_COMP_NUM_MPORT_S 4
- +
- +#define DMP_MASTER_PORT_UID 0x0000FF00
- +#define DMP_MASTER_PORT_UID_S 8
- +#define DMP_MASTER_PORT_NUM 0x000000F0
- +#define DMP_MASTER_PORT_NUM_S 4
- +
- +#define DMP_SLAVE_ADDR_BASE 0xFFFFF000
- +#define DMP_SLAVE_ADDR_BASE_S 12
- +#define DMP_SLAVE_PORT_NUM 0x00000F00
- +#define DMP_SLAVE_PORT_NUM_S 8
- +#define DMP_SLAVE_TYPE 0x000000C0
- +#define DMP_SLAVE_TYPE_S 6
- +#define DMP_SLAVE_TYPE_SLAVE 0
- +#define DMP_SLAVE_TYPE_BRIDGE 1
- +#define DMP_SLAVE_TYPE_SWRAP 2
- +#define DMP_SLAVE_TYPE_MWRAP 3
- +#define DMP_SLAVE_SIZE_TYPE 0x00000030
- +#define DMP_SLAVE_SIZE_TYPE_S 4
- +#define DMP_SLAVE_SIZE_4K 0
- +#define DMP_SLAVE_SIZE_8K 1
- +#define DMP_SLAVE_SIZE_16K 2
- +#define DMP_SLAVE_SIZE_DESC 3
- +
- +/* EROM CompIdentB */
- +#define CIB_REV_MASK 0xff000000
- +#define CIB_REV_SHIFT 24
- +
- +/* ARM CR4 core specific control flag bits */
- +#define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020
- +
- +/* D11 core specific control flag bits */
- +#define D11_BCMA_IOCTL_PHYCLOCKEN 0x0004
- +#define D11_BCMA_IOCTL_PHYRESET 0x0008
- +
- +/* chip core base & ramsize */
- +/* bcm4329 */
- +/* SDIO device core, ID 0x829 */
- +#define BCM4329_CORE_BUS_BASE 0x18011000
- +/* internal memory core, ID 0x80e */
- +#define BCM4329_CORE_SOCRAM_BASE 0x18003000
- +/* ARM Cortex M3 core, ID 0x82a */
- +#define BCM4329_CORE_ARM_BASE 0x18002000
- +#define BCM4329_RAMSIZE 0x48000
- +
- +/* bcm43143 */
- +/* SDIO device core */
- +#define BCM43143_CORE_BUS_BASE 0x18002000
- +/* internal memory core */
- +#define BCM43143_CORE_SOCRAM_BASE 0x18004000
- +/* ARM Cortex M3 core, ID 0x82a */
- +#define BCM43143_CORE_ARM_BASE 0x18003000
- +#define BCM43143_RAMSIZE 0x70000
- +
- +#define CORE_SB(base, field) \
- + (base + SBCONFIGOFF + offsetof(struct sbconfig, field))
- +#define SBCOREREV(sbidh) \
- + ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
- + ((sbidh) & SSB_IDHIGH_RCLO))
- +
- +struct sbconfig {
- + u32 PAD[2];
- + u32 sbipsflag; /* initiator port ocp slave flag */
- + u32 PAD[3];
- + u32 sbtpsflag; /* target port ocp slave flag */
- + u32 PAD[11];
- + u32 sbtmerrloga; /* (sonics >= 2.3) */
- + u32 PAD;
- + u32 sbtmerrlog; /* (sonics >= 2.3) */
- + u32 PAD[3];
- + u32 sbadmatch3; /* address match3 */
- + u32 PAD;
- + u32 sbadmatch2; /* address match2 */
- + u32 PAD;
- + u32 sbadmatch1; /* address match1 */
- + u32 PAD[7];
- + u32 sbimstate; /* initiator agent state */
- + u32 sbintvec; /* interrupt mask */
- + u32 sbtmstatelow; /* target state */
- + u32 sbtmstatehigh; /* target state */
- + u32 sbbwa0; /* bandwidth allocation table0 */
- + u32 PAD;
- + u32 sbimconfiglow; /* initiator configuration */
- + u32 sbimconfighigh; /* initiator configuration */
- + u32 sbadmatch0; /* address match0 */
- + u32 PAD;
- + u32 sbtmconfiglow; /* target configuration */
- + u32 sbtmconfighigh; /* target configuration */
- + u32 sbbconfig; /* broadcast configuration */
- + u32 PAD;
- + u32 sbbstate; /* broadcast state */
- + u32 PAD[3];
- + u32 sbactcnfg; /* activate configuration */
- + u32 PAD[3];
- + u32 sbflagst; /* current sbflags */
- + u32 PAD[3];
- + u32 sbidlow; /* identification */
- + u32 sbidhigh; /* identification */
- +};
- +
- +struct brcmf_core_priv {
- + struct brcmf_core pub;
- + u32 wrapbase;
- + struct list_head list;
- + struct brcmf_chip_priv *chip;
- +};
- +
- +/* ARM CR4 core specific control flag bits */
- +#define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020
- +
- +/* D11 core specific control flag bits */
- +#define D11_BCMA_IOCTL_PHYCLOCKEN 0x0004
- +#define D11_BCMA_IOCTL_PHYRESET 0x0008
- +
- +struct brcmf_chip_priv {
- + struct brcmf_chip pub;
- + const struct brcmf_buscore_ops *ops;
- + void *ctx;
- + /* assured first core is chipcommon, second core is buscore */
- + struct list_head cores;
- + u16 num_cores;
- +
- + bool (*iscoreup)(struct brcmf_core_priv *core);
- + void (*coredisable)(struct brcmf_core_priv *core, u32 prereset,
- + u32 reset);
- + void (*resetcore)(struct brcmf_core_priv *core, u32 prereset, u32 reset,
- + u32 postreset);
- +};
- +
- +static void brcmf_chip_sb_corerev(struct brcmf_chip_priv *ci,
- + struct brcmf_core *core)
- +{
- + u32 regdata;
- +
- + regdata = ci->ops->read32(ci->ctx, CORE_SB(core->base, sbidhigh));
- + core->rev = SBCOREREV(regdata);
- +}
- +
- +static bool brcmf_chip_sb_iscoreup(struct brcmf_core_priv *core)
- +{
- + struct brcmf_chip_priv *ci;
- + u32 regdata;
- + u32 address;
- +
- + ci = core->chip;
- + address = CORE_SB(core->pub.base, sbtmstatelow);
- + regdata = ci->ops->read32(ci->ctx, address);
- + regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
- + SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
- + return SSB_TMSLOW_CLOCK == regdata;
- +}
- +
- +static bool brcmf_chip_ai_iscoreup(struct brcmf_core_priv *core)
- +{
- + struct brcmf_chip_priv *ci;
- + u32 regdata;
- + bool ret;
- +
- + ci = core->chip;
- + regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);
- + ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK;
- +
- + regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL);
- + ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0);
- +
- + return ret;
- +}
- +
- +static void brcmf_chip_sb_coredisable(struct brcmf_core_priv *core,
- + u32 prereset, u32 reset)
- +{
- + struct brcmf_chip_priv *ci;
- + u32 val, base;
- +
- + ci = core->chip;
- + base = core->pub.base;
- + val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
- + if (val & SSB_TMSLOW_RESET)
- + return;
- +
- + val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
- + if ((val & SSB_TMSLOW_CLOCK) != 0) {
- + /*
- + * set target reject and spin until busy is clear
- + * (preserve core-specific bits)
- + */
- + val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
- + ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
- + val | SSB_TMSLOW_REJECT);
- +
- + val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
- + udelay(1);
- + SPINWAIT((ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh))
- + & SSB_TMSHIGH_BUSY), 100000);
- +
- + val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh));
- + if (val & SSB_TMSHIGH_BUSY)
- + brcmf_err("core state still busy\n");
- +
- + val = ci->ops->read32(ci->ctx, CORE_SB(base, sbidlow));
- + if (val & SSB_IDLOW_INITIATOR) {
- + val = ci->ops->read32(ci->ctx,
- + CORE_SB(base, sbimstate));
- + val |= SSB_IMSTATE_REJECT;
- + ci->ops->write32(ci->ctx,
- + CORE_SB(base, sbimstate), val);
- + val = ci->ops->read32(ci->ctx,
- + CORE_SB(base, sbimstate));
- + udelay(1);
- + SPINWAIT((ci->ops->read32(ci->ctx,
- + CORE_SB(base, sbimstate)) &
- + SSB_IMSTATE_BUSY), 100000);
- + }
- +
- + /* set reset and reject while enabling the clocks */
- + val = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
- + SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET;
- + ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), val);
- + val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
- + udelay(10);
- +
- + /* clear the initiator reject bit */
- + val = ci->ops->read32(ci->ctx, CORE_SB(base, sbidlow));
- + if (val & SSB_IDLOW_INITIATOR) {
- + val = ci->ops->read32(ci->ctx,
- + CORE_SB(base, sbimstate));
- + val &= ~SSB_IMSTATE_REJECT;
- + ci->ops->write32(ci->ctx,
- + CORE_SB(base, sbimstate), val);
- + }
- + }
- +
- + /* leave reset and reject asserted */
- + ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
- + (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
- + udelay(1);
- +}
- +
- +static void brcmf_chip_ai_coredisable(struct brcmf_core_priv *core,
- + u32 prereset, u32 reset)
- +{
- + struct brcmf_chip_priv *ci;
- + u32 regdata;
- +
- + ci = core->chip;
- +
- + /* if core is already in reset, skip reset */
- + regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL);
- + if ((regdata & BCMA_RESET_CTL_RESET) != 0)
- + goto in_reset_configure;
- +
- + /* configure reset */
- + ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
- + prereset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
- + ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);
- +
- + /* put in reset */
- + ci->ops->write32(ci->ctx, core->wrapbase + BCMA_RESET_CTL,
- + BCMA_RESET_CTL_RESET);
- + usleep_range(10, 20);
- +
- + /* wait till reset is 1 */
- + SPINWAIT(ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) !=
- + BCMA_RESET_CTL_RESET, 300);
- +
- +in_reset_configure:
- + /* in-reset configure */
- + ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
- + reset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
- + ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);
- +}
- +
- +static void brcmf_chip_sb_resetcore(struct brcmf_core_priv *core, u32 prereset,
- + u32 reset, u32 postreset)
- +{
- + struct brcmf_chip_priv *ci;
- + u32 regdata;
- + u32 base;
- +
- + ci = core->chip;
- + base = core->pub.base;
- + /*
- + * Must do the disable sequence first to work for
- + * arbitrary current core state.
- + */
- + brcmf_chip_sb_coredisable(core, 0, 0);
- +
- + /*
- + * Now do the initialization sequence.
- + * set reset while enabling the clock and
- + * forcing them on throughout the core
- + */
- + ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
- + SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
- + SSB_TMSLOW_RESET);
- + regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
- + udelay(1);
- +
- + /* clear any serror */
- + regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh));
- + if (regdata & SSB_TMSHIGH_SERR)
- + ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatehigh), 0);
- +
- + regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbimstate));
- + if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) {
- + regdata &= ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO);
- + ci->ops->write32(ci->ctx, CORE_SB(base, sbimstate), regdata);
- + }
- +
- + /* clear reset and allow it to propagate throughout the core */
- + ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
- + SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK);
- + regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
- + udelay(1);
- +
- + /* leave clock enabled */
- + ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
- + SSB_TMSLOW_CLOCK);
- + regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
- + udelay(1);
- +}
- +
- +static void brcmf_chip_ai_resetcore(struct brcmf_core_priv *core, u32 prereset,
- + u32 reset, u32 postreset)
- +{
- + struct brcmf_chip_priv *ci;
- + int count;
- +
- + ci = core->chip;
- +
- + /* must disable first to work for arbitrary current core state */
- + brcmf_chip_ai_coredisable(core, prereset, reset);
- +
- + count = 0;
- + while (ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) &
- + BCMA_RESET_CTL_RESET) {
- + ci->ops->write32(ci->ctx, core->wrapbase + BCMA_RESET_CTL, 0);
- + count++;
- + if (count > 50)
- + break;
- + usleep_range(40, 60);
- + }
- +
- + ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
- + postreset | BCMA_IOCTL_CLK);
- + ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);
- +}
- +
- +static char *brcmf_chip_name(uint chipid, char *buf, uint len)
- +{
- + const char *fmt;
- +
- + fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
- + snprintf(buf, len, fmt, chipid);
- + return buf;
- +}
- +
- +static struct brcmf_core *brcmf_chip_add_core(struct brcmf_chip_priv *ci,
- + u16 coreid, u32 base,
- + u32 wrapbase)
- +{
- + struct brcmf_core_priv *core;
- +
- + core = kzalloc(sizeof(*core), GFP_KERNEL);
- + if (!core)
- + return ERR_PTR(-ENOMEM);
- +
- + core->pub.id = coreid;
- + core->pub.base = base;
- + core->chip = ci;
- + core->wrapbase = wrapbase;
- +
- + list_add_tail(&core->list, &ci->cores);
- + return &core->pub;
- +}
- +
- +#ifdef DEBUG
- +/* safety check for chipinfo */
- +static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci)
- +{
- + struct brcmf_core_priv *core;
- + bool need_socram = false;
- + bool has_socram = false;
- + int idx = 1;
- +
- + list_for_each_entry(core, &ci->cores, list) {
- + brcmf_dbg(INFO, " [%-2d] core 0x%x:%-2d base 0x%08x wrap 0x%08x\n",
- + idx++, core->pub.id, core->pub.rev, core->pub.base,
- + core->wrapbase);
- +
- + switch (core->pub.id) {
- + case BCMA_CORE_ARM_CM3:
- + need_socram = true;
- + break;
- + case BCMA_CORE_INTERNAL_MEM:
- + has_socram = true;
- + break;
- + case BCMA_CORE_ARM_CR4:
- + if (ci->pub.rambase == 0) {
- + brcmf_err("RAM base not provided with ARM CR4 core\n");
- + return -ENOMEM;
- + }
- + break;
- + default:
- + break;
- + }
- + }
- +
- + /* check RAM core presence for ARM CM3 core */
- + if (need_socram && !has_socram) {
- + brcmf_err("RAM core not provided with ARM CM3 core\n");
- + return -ENODEV;
- + }
- + return 0;
- +}
- +#else /* DEBUG */
- +static inline int brcmf_chip_cores_check(struct brcmf_chip_priv *ci)
- +{
- + return 0;
- +}
- +#endif
- +
- +static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
- +{
- + switch (ci->pub.chip) {
- + case BCM4329_CHIP_ID:
- + ci->pub.ramsize = BCM4329_RAMSIZE;
- + break;
- + case BCM43143_CHIP_ID:
- + ci->pub.ramsize = BCM43143_RAMSIZE;
- + break;
- + case BCM43241_CHIP_ID:
- + ci->pub.ramsize = 0x90000;
- + break;
- + case BCM4330_CHIP_ID:
- + ci->pub.ramsize = 0x48000;
- + break;
- + case BCM4334_CHIP_ID:
- + ci->pub.ramsize = 0x80000;
- + break;
- + case BCM4335_CHIP_ID:
- + ci->pub.ramsize = 0xc0000;
- + ci->pub.rambase = 0x180000;
- + break;
- + case BCM43362_CHIP_ID:
- + ci->pub.ramsize = 0x3c000;
- + break;
- + case BCM4339_CHIP_ID:
- + case BCM4354_CHIP_ID:
- + ci->pub.ramsize = 0xc0000;
- + ci->pub.rambase = 0x180000;
- + break;
- + default:
- + brcmf_err("unknown chip: %s\n", ci->pub.name);
- + break;
- + }
- +}
- +
- +static u32 brcmf_chip_dmp_get_desc(struct brcmf_chip_priv *ci, u32 *eromaddr,
- + u8 *type)
- +{
- + u32 val;
- +
- + /* read next descriptor */
- + val = ci->ops->read32(ci->ctx, *eromaddr);
- + *eromaddr += 4;
- +
- + if (!type)
- + return val;
- +
- + /* determine descriptor type */
- + *type = (val & DMP_DESC_TYPE_MSK);
- + if ((*type & ~DMP_DESC_ADDRSIZE_GT32) == DMP_DESC_ADDRESS)
- + *type = DMP_DESC_ADDRESS;
- +
- + return val;
- +}
- +
- +static int brcmf_chip_dmp_get_regaddr(struct brcmf_chip_priv *ci, u32 *eromaddr,
- + u32 *regbase, u32 *wrapbase)
- +{
- + u8 desc;
- + u32 val;
- + u8 mpnum = 0;
- + u8 stype, sztype, wraptype;
- +
- + *regbase = 0;
- + *wrapbase = 0;
- +
- + val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc);
- + if (desc == DMP_DESC_MASTER_PORT) {
- + mpnum = (val & DMP_MASTER_PORT_NUM) >> DMP_MASTER_PORT_NUM_S;
- + wraptype = DMP_SLAVE_TYPE_MWRAP;
- + } else if (desc == DMP_DESC_ADDRESS) {
- + /* revert erom address */
- + *eromaddr -= 4;
- + wraptype = DMP_SLAVE_TYPE_SWRAP;
- + } else {
- + *eromaddr -= 4;
- + return -EILSEQ;
- + }
- +
- + do {
- + /* locate address descriptor */
- + do {
- + val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc);
- + /* unexpected table end */
- + if (desc == DMP_DESC_EOT) {
- + *eromaddr -= 4;
- + return -EFAULT;
- + }
- + } while (desc != DMP_DESC_ADDRESS);
- +
- + /* skip upper 32-bit address descriptor */
- + if (val & DMP_DESC_ADDRSIZE_GT32)
- + brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);
- +
- + sztype = (val & DMP_SLAVE_SIZE_TYPE) >> DMP_SLAVE_SIZE_TYPE_S;
- +
- + /* next size descriptor can be skipped */
- + if (sztype == DMP_SLAVE_SIZE_DESC) {
- + val = brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);
- + /* skip upper size descriptor if present */
- + if (val & DMP_DESC_ADDRSIZE_GT32)
- + brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);
- + }
- +
- + /* only look for 4K register regions */
- + if (sztype != DMP_SLAVE_SIZE_4K)
- + continue;
- +
- + stype = (val & DMP_SLAVE_TYPE) >> DMP_SLAVE_TYPE_S;
- +
- + /* only regular slave and wrapper */
- + if (*regbase == 0 && stype == DMP_SLAVE_TYPE_SLAVE)
- + *regbase = val & DMP_SLAVE_ADDR_BASE;
- + if (*wrapbase == 0 && stype == wraptype)
- + *wrapbase = val & DMP_SLAVE_ADDR_BASE;
- + } while (*regbase == 0 || *wrapbase == 0);
- +
- + return 0;
- +}
- +
- +static
- +int brcmf_chip_dmp_erom_scan(struct brcmf_chip_priv *ci)
- +{
- + struct brcmf_core *core;
- + u32 eromaddr;
- + u8 desc_type = 0;
- + u32 val;
- + u16 id;
- + u8 nmp, nsp, nmw, nsw, rev;
- + u32 base, wrap;
- + int err;
- +
- + eromaddr = ci->ops->read32(ci->ctx, CORE_CC_REG(SI_ENUM_BASE, eromptr));
- +
- + while (desc_type != DMP_DESC_EOT) {
- + val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type);
- + if (!(val & DMP_DESC_VALID))
- + continue;
- +
- + if (desc_type == DMP_DESC_EMPTY)
- + continue;
- +
- + /* need a component descriptor */
- + if (desc_type != DMP_DESC_COMPONENT)
- + continue;
- +
- + id = (val & DMP_COMP_PARTNUM) >> DMP_COMP_PARTNUM_S;
- +
- + /* next descriptor must be component as well */
- + val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type);
- + if (WARN_ON((val & DMP_DESC_TYPE_MSK) != DMP_DESC_COMPONENT))
- + return -EFAULT;
- +
- + /* only look at cores with master port(s) */
- + nmp = (val & DMP_COMP_NUM_MPORT) >> DMP_COMP_NUM_MPORT_S;
- + nsp = (val & DMP_COMP_NUM_SPORT) >> DMP_COMP_NUM_SPORT_S;
- + nmw = (val & DMP_COMP_NUM_MWRAP) >> DMP_COMP_NUM_MWRAP_S;
- + nsw = (val & DMP_COMP_NUM_SWRAP) >> DMP_COMP_NUM_SWRAP_S;
- + rev = (val & DMP_COMP_REVISION) >> DMP_COMP_REVISION_S;
- +
- + /* need core with ports */
- + if (nmw + nsw == 0)
- + continue;
- +
- + /* try to obtain register address info */
- + err = brcmf_chip_dmp_get_regaddr(ci, &eromaddr, &base, &wrap);
- + if (err)
- + continue;
- +
- + /* finally a core to be added */
- + core = brcmf_chip_add_core(ci, id, base, wrap);
- + if (IS_ERR(core))
- + return PTR_ERR(core);
- +
- + core->rev = rev;
- + }
- +
- + return 0;
- +}
- +
- +static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
- +{
- + struct brcmf_core *core;
- + u32 regdata;
- + u32 socitype;
- +
- + /* Get CC core rev
- + * Chipid is assume to be at offset 0 from SI_ENUM_BASE
- + * For different chiptypes or old sdio hosts w/o chipcommon,
- + * other ways of recognition should be added here.
- + */
- + regdata = ci->ops->read32(ci->ctx, CORE_CC_REG(SI_ENUM_BASE, chipid));
- + ci->pub.chip = regdata & CID_ID_MASK;
- + ci->pub.chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
- + socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
- +
- + brcmf_chip_name(ci->pub.chip, ci->pub.name, sizeof(ci->pub.name));
- + brcmf_dbg(INFO, "found %s chip: BCM%s, rev=%d\n",
- + socitype == SOCI_SB ? "SB" : "AXI", ci->pub.name,
- + ci->pub.chiprev);
- +
- + if (socitype == SOCI_SB) {
- + if (ci->pub.chip != BCM4329_CHIP_ID) {
- + brcmf_err("SB chip is not supported\n");
- + return -ENODEV;
- + }
- + ci->iscoreup = brcmf_chip_sb_iscoreup;
- + ci->coredisable = brcmf_chip_sb_coredisable;
- + ci->resetcore = brcmf_chip_sb_resetcore;
- +
- + core = brcmf_chip_add_core(ci, BCMA_CORE_CHIPCOMMON,
- + SI_ENUM_BASE, 0);
- + brcmf_chip_sb_corerev(ci, core);
- + core = brcmf_chip_add_core(ci, BCMA_CORE_SDIO_DEV,
- + BCM4329_CORE_BUS_BASE, 0);
- + brcmf_chip_sb_corerev(ci, core);
- + core = brcmf_chip_add_core(ci, BCMA_CORE_INTERNAL_MEM,
- + BCM4329_CORE_SOCRAM_BASE, 0);
- + brcmf_chip_sb_corerev(ci, core);
- + core = brcmf_chip_add_core(ci, BCMA_CORE_ARM_CM3,
- + BCM4329_CORE_ARM_BASE, 0);
- + brcmf_chip_sb_corerev(ci, core);
- +
- + core = brcmf_chip_add_core(ci, BCMA_CORE_80211, 0x18001000, 0);
- + brcmf_chip_sb_corerev(ci, core);
- + } else if (socitype == SOCI_AI) {
- + ci->iscoreup = brcmf_chip_ai_iscoreup;
- + ci->coredisable = brcmf_chip_ai_coredisable;
- + ci->resetcore = brcmf_chip_ai_resetcore;
- +
- + brcmf_chip_dmp_erom_scan(ci);
- + } else {
- + brcmf_err("chip backplane type %u is not supported\n",
- + socitype);
- + return -ENODEV;
- + }
- +
- + brcmf_chip_get_raminfo(ci);
- +
- + return brcmf_chip_cores_check(ci);
- +}
- +
- +static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id)
- +{
- + struct brcmf_core *core;
- + struct brcmf_core_priv *cr4;
- + u32 val;
- +
- +
- + core = brcmf_chip_get_core(&chip->pub, id);
- + if (!core)
- + return;
- +
- + switch (id) {
- + case BCMA_CORE_ARM_CM3:
- + brcmf_chip_coredisable(core, 0, 0);
- + break;
- + case BCMA_CORE_ARM_CR4:
- + cr4 = container_of(core, struct brcmf_core_priv, pub);
- +
- + /* clear all IOCTL bits except HALT bit */
- + val = chip->ops->read32(chip->ctx, cr4->wrapbase + BCMA_IOCTL);
- + val &= ARMCR4_BCMA_IOCTL_CPUHALT;
- + brcmf_chip_resetcore(core, val, ARMCR4_BCMA_IOCTL_CPUHALT,
- + ARMCR4_BCMA_IOCTL_CPUHALT);
- + break;
- + default:
- + brcmf_err("unknown id: %u\n", id);
- + break;
- + }
- +}
- +
- +static int brcmf_chip_setup(struct brcmf_chip_priv *chip)
- +{
- + struct brcmf_chip *pub;
- + struct brcmf_core_priv *cc;
- + u32 base;
- + u32 val;
- + int ret = 0;
- +
- + pub = &chip->pub;
- + cc = list_first_entry(&chip->cores, struct brcmf_core_priv, list);
- + base = cc->pub.base;
- +
- + /* get chipcommon capabilites */
- + pub->cc_caps = chip->ops->read32(chip->ctx,
- + CORE_CC_REG(base, capabilities));
- +
- + /* get pmu caps & rev */
- + if (pub->cc_caps & CC_CAP_PMU) {
- + val = chip->ops->read32(chip->ctx,
- + CORE_CC_REG(base, pmucapabilities));
- + pub->pmurev = val & PCAP_REV_MASK;
- + pub->pmucaps = val;
- + }
- +
- + brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, pmucaps=0x%x\n",
- + cc->pub.rev, pub->pmurev, pub->pmucaps);
- +
- + /* execute bus core specific setup */
- + if (chip->ops->setup)
- + ret = chip->ops->setup(chip->ctx, pub);
- +
- + /*
- + * Make sure any on-chip ARM is off (in case strapping is wrong),
- + * or downloaded code was already running.
- + */
- + brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3);
- + brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4);
- + return ret;
- +}
- +
- +struct brcmf_chip *brcmf_chip_attach(void *ctx,
- + const struct brcmf_buscore_ops *ops)
- +{
- + struct brcmf_chip_priv *chip;
- + int err = 0;
- +
- + if (WARN_ON(!ops->read32))
- + err = -EINVAL;
- + if (WARN_ON(!ops->write32))
- + err = -EINVAL;
- + if (WARN_ON(!ops->prepare))
- + err = -EINVAL;
- + if (WARN_ON(!ops->exit_dl))
- + err = -EINVAL;
- + if (err < 0)
- + return ERR_PTR(-EINVAL);
- +
- + chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- + if (!chip)
- + return ERR_PTR(-ENOMEM);
- +
- + INIT_LIST_HEAD(&chip->cores);
- + chip->num_cores = 0;
- + chip->ops = ops;
- + chip->ctx = ctx;
- +
- + err = ops->prepare(ctx);
- + if (err < 0)
- + goto fail;
- +
- + err = brcmf_chip_recognition(chip);
- + if (err < 0)
- + goto fail;
- +
- + err = brcmf_chip_setup(chip);
- + if (err < 0)
- + goto fail;
- +
- + return &chip->pub;
- +
- +fail:
- + brcmf_chip_detach(&chip->pub);
- + return ERR_PTR(err);
- +}
- +
- +void brcmf_chip_detach(struct brcmf_chip *pub)
- +{
- + struct brcmf_chip_priv *chip;
- + struct brcmf_core_priv *core;
- + struct brcmf_core_priv *tmp;
- +
- + chip = container_of(pub, struct brcmf_chip_priv, pub);
- + list_for_each_entry_safe(core, tmp, &chip->cores, list) {
- + list_del(&core->list);
- + kfree(core);
- + }
- + kfree(chip);
- +}
- +
- +struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *pub, u16 coreid)
- +{
- + struct brcmf_chip_priv *chip;
- + struct brcmf_core_priv *core;
- +
- + chip = container_of(pub, struct brcmf_chip_priv, pub);
- + list_for_each_entry(core, &chip->cores, list)
- + if (core->pub.id == coreid)
- + return &core->pub;
- +
- + return NULL;
- +}
- +
- +struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *pub)
- +{
- + struct brcmf_chip_priv *chip;
- + struct brcmf_core_priv *cc;
- +
- + chip = container_of(pub, struct brcmf_chip_priv, pub);
- + cc = list_first_entry(&chip->cores, struct brcmf_core_priv, list);
- + if (WARN_ON(!cc || cc->pub.id != BCMA_CORE_CHIPCOMMON))
- + return brcmf_chip_get_core(pub, BCMA_CORE_CHIPCOMMON);
- + return &cc->pub;
- +}
- +
- +bool brcmf_chip_iscoreup(struct brcmf_core *pub)
- +{
- + struct brcmf_core_priv *core;
- +
- + core = container_of(pub, struct brcmf_core_priv, pub);
- + return core->chip->iscoreup(core);
- +}
- +
- +void brcmf_chip_coredisable(struct brcmf_core *pub, u32 prereset, u32 reset)
- +{
- + struct brcmf_core_priv *core;
- +
- + core = container_of(pub, struct brcmf_core_priv, pub);
- + core->chip->coredisable(core, prereset, reset);
- +}
- +
- +void brcmf_chip_resetcore(struct brcmf_core *pub, u32 prereset, u32 reset,
- + u32 postreset)
- +{
- + struct brcmf_core_priv *core;
- +
- + core = container_of(pub, struct brcmf_core_priv, pub);
- + core->chip->resetcore(core, prereset, reset, postreset);
- +}
- +
- +static void
- +brcmf_chip_cm3_enterdl(struct brcmf_chip_priv *chip)
- +{
- + struct brcmf_core *core;
- +
- + brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3);
- + core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211);
- + brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET |
- + D11_BCMA_IOCTL_PHYCLOCKEN,
- + D11_BCMA_IOCTL_PHYCLOCKEN,
- + D11_BCMA_IOCTL_PHYCLOCKEN);
- + core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM);
- + brcmf_chip_resetcore(core, 0, 0, 0);
- +}
- +
- +static bool brcmf_chip_cm3_exitdl(struct brcmf_chip_priv *chip)
- +{
- + struct brcmf_core *core;
- +
- + core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM);
- + if (!brcmf_chip_iscoreup(core)) {
- + brcmf_err("SOCRAM core is down after reset?\n");
- + return false;
- + }
- +
- + chip->ops->exit_dl(chip->ctx, &chip->pub, 0);
- +
- + core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CM3);
- + brcmf_chip_resetcore(core, 0, 0, 0);
- +
- + return true;
- +}
- +
- +static inline void
- +brcmf_chip_cr4_enterdl(struct brcmf_chip_priv *chip)
- +{
- + struct brcmf_core *core;
- +
- + brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4);
- +
- + core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211);
- + brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET |
- + D11_BCMA_IOCTL_PHYCLOCKEN,
- + D11_BCMA_IOCTL_PHYCLOCKEN,
- + D11_BCMA_IOCTL_PHYCLOCKEN);
- +}
- +
- +static bool brcmf_chip_cr4_exitdl(struct brcmf_chip_priv *chip, u32 rstvec)
- +{
- + struct brcmf_core *core;
- +
- + chip->ops->exit_dl(chip->ctx, &chip->pub, rstvec);
- +
- + /* restore ARM */
- + core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CR4);
- + brcmf_chip_resetcore(core, ARMCR4_BCMA_IOCTL_CPUHALT, 0, 0);
- +
- + return true;
- +}
- +
- +void brcmf_chip_enter_download(struct brcmf_chip *pub)
- +{
- + struct brcmf_chip_priv *chip;
- + struct brcmf_core *arm;
- +
- + brcmf_dbg(TRACE, "Enter\n");
- +
- + chip = container_of(pub, struct brcmf_chip_priv, pub);
- + arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4);
- + if (arm) {
- + brcmf_chip_cr4_enterdl(chip);
- + return;
- + }
- +
- + brcmf_chip_cm3_enterdl(chip);
- +}
- +
- +bool brcmf_chip_exit_download(struct brcmf_chip *pub, u32 rstvec)
- +{
- + struct brcmf_chip_priv *chip;
- + struct brcmf_core *arm;
- +
- + brcmf_dbg(TRACE, "Enter\n");
- +
- + chip = container_of(pub, struct brcmf_chip_priv, pub);
- + arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4);
- + if (arm)
- + return brcmf_chip_cr4_exitdl(chip, rstvec);
- +
- + return brcmf_chip_cm3_exitdl(chip);
- +}
- +
- +bool brcmf_chip_sr_capable(struct brcmf_chip *pub)
- +{
- + u32 base, addr, reg, pmu_cc3_mask = ~0;
- + struct brcmf_chip_priv *chip;
- +
- + brcmf_dbg(TRACE, "Enter\n");
- +
- + /* old chips with PMU version less than 17 don't support save restore */
- + if (pub->pmurev < 17)
- + return false;
- +
- + base = brcmf_chip_get_chipcommon(pub)->base;
- + chip = container_of(pub, struct brcmf_chip_priv, pub);
- +
- + switch (pub->chip) {
- + case BCM4354_CHIP_ID:
- + /* explicitly check SR engine enable bit */
- + pmu_cc3_mask = BIT(2);
- + /* fall-through */
- + case BCM43241_CHIP_ID:
- + case BCM4335_CHIP_ID:
- + case BCM4339_CHIP_ID:
- + /* read PMU chipcontrol register 3 */
- + addr = CORE_CC_REG(base, chipcontrol_addr);
- + chip->ops->write32(chip->ctx, addr, 3);
- + addr = CORE_CC_REG(base, chipcontrol_data);
- + reg = chip->ops->read32(chip->ctx, addr);
- + return (reg & pmu_cc3_mask) != 0;
- + default:
- + addr = CORE_CC_REG(base, pmucapabilities_ext);
- + reg = chip->ops->read32(chip->ctx, addr);
- + if ((reg & PCAPEXT_SR_SUPPORTED_MASK) == 0)
- + return false;
- +
- + addr = CORE_CC_REG(base, retention_ctl);
- + reg = chip->ops->read32(chip->ctx, addr);
- + return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK |
- + PMU_RCTL_LOGIC_DISABLE_MASK)) == 0;
- + }
- +}
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/chip.h linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/chip.h
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/chip.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/chip.h 2015-03-08 14:27:37.693684500 -0500
- @@ -0,0 +1,91 @@
- +/*
- + * Copyright (c) 2014 Broadcom Corporation
- + *
- + * Permission to use, copy, modify, and/or distribute this software for any
- + * purpose with or without fee is hereby granted, provided that the above
- + * copyright notice and this permission notice appear in all copies.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- + */
- +#ifndef BRCMF_CHIP_H
- +#define BRCMF_CHIP_H
- +
- +#include <linux/types.h>
- +
- +#define CORE_CC_REG(base, field) \
- + (base + offsetof(struct chipcregs, field))
- +
- +/**
- + * struct brcmf_chip - chip level information.
- + *
- + * @chip: chip identifier.
- + * @chiprev: chip revision.
- + * @cc_caps: chipcommon core capabilities.
- + * @pmucaps: PMU capabilities.
- + * @pmurev: PMU revision.
- + * @rambase: RAM base address (only applicable for ARM CR4 chips).
- + * @ramsize: amount of RAM on chip.
- + * @name: string representation of the chip identifier.
- + */
- +struct brcmf_chip {
- + u32 chip;
- + u32 chiprev;
- + u32 cc_caps;
- + u32 pmucaps;
- + u32 pmurev;
- + u32 rambase;
- + u32 ramsize;
- + char name[8];
- +};
- +
- +/**
- + * struct brcmf_core - core related information.
- + *
- + * @id: core identifier.
- + * @rev: core revision.
- + * @base: base address of core register space.
- + */
- +struct brcmf_core {
- + u16 id;
- + u16 rev;
- + u32 base;
- +};
- +
- +/**
- + * struct brcmf_buscore_ops - buscore specific callbacks.
- + *
- + * @read32: read 32-bit value over bus.
- + * @write32: write 32-bit value over bus.
- + * @prepare: prepare bus for core configuration.
- + * @setup: bus-specific core setup.
- + * @exit_dl: exit download state.
- + * The callback should use the provided @rstvec when non-zero.
- + */
- +struct brcmf_buscore_ops {
- + u32 (*read32)(void *ctx, u32 addr);
- + void (*write32)(void *ctx, u32 addr, u32 value);
- + int (*prepare)(void *ctx);
- + int (*setup)(void *ctx, struct brcmf_chip *chip);
- + void (*exit_dl)(void *ctx, struct brcmf_chip *chip, u32 rstvec);
- +};
- +
- +struct brcmf_chip *brcmf_chip_attach(void *ctx,
- + const struct brcmf_buscore_ops *ops);
- +void brcmf_chip_detach(struct brcmf_chip *chip);
- +struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *chip, u16 coreid);
- +struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *chip);
- +bool brcmf_chip_iscoreup(struct brcmf_core *core);
- +void brcmf_chip_coredisable(struct brcmf_core *core, u32 prereset, u32 reset);
- +void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset,
- + u32 postreset);
- +void brcmf_chip_enter_download(struct brcmf_chip *ci);
- +bool brcmf_chip_exit_download(struct brcmf_chip *ci, u32 rstvec);
- +bool brcmf_chip_sr_capable(struct brcmf_chip *pub);
- +
- +#endif /* BRCMF_AXIDMP_H */
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h 2015-03-08 14:27:37.693684500 -0500
- @@ -63,7 +63,6 @@
- */
- struct brcmf_bus_ops {
- int (*preinit)(struct device *dev);
- - int (*init)(struct device *dev);
- void (*stop)(struct device *dev);
- int (*txdata)(struct device *dev, struct sk_buff *skb);
- int (*txctl)(struct device *dev, unsigned char *msg, uint len);
- @@ -99,6 +98,7 @@
- unsigned long tx_realloc;
- u32 chip;
- u32 chiprev;
- + bool always_use_fws_queue;
-
- struct brcmf_bus_ops *ops;
- };
- @@ -113,11 +113,6 @@
- return bus->ops->preinit(bus->dev);
- }
-
- -static inline int brcmf_bus_init(struct brcmf_bus *bus)
- -{
- - return bus->ops->init(bus->dev);
- -}
- -
- static inline void brcmf_bus_stop(struct brcmf_bus *bus)
- {
- bus->ops->stop(bus->dev);
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c 2015-03-08 14:27:37.693684500 -0500
- @@ -32,6 +32,9 @@
- #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40
- #define BRCMF_DEFAULT_PACKET_FILTER "100 0 0 0 0x01 0x00"
-
- +/* boost value for RSSI_DELTA in preferred join selection */
- +#define BRCMF_JOIN_PREF_RSSI_BOOST 8
- +
-
- bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
- struct sk_buff *pkt, int prec)
- @@ -246,6 +249,7 @@
- {
- s8 eventmask[BRCMF_EVENTING_MASK_LEN];
- u8 buf[BRCMF_DCMD_SMLEN];
- + struct brcmf_join_pref_params join_pref_params[2];
- char *ptr;
- s32 err;
-
- @@ -298,6 +302,20 @@
- goto done;
- }
-
- + /* Setup join_pref to select target by RSSI(with boost on 5GHz) */
- + join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA;
- + join_pref_params[0].len = 2;
- + join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST;
- + join_pref_params[0].band = WLC_BAND_5G;
- + join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI;
- + join_pref_params[1].len = 2;
- + join_pref_params[1].rssi_gain = 0;
- + join_pref_params[1].band = 0;
- + err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,
- + sizeof(join_pref_params));
- + if (err)
- + brcmf_err("Set join_pref error (%d)\n", err);
- +
- /* Setup event_msgs, enable E_IF */
- err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
- BRCMF_EVENTING_MASK_LEN);
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/dhd.h linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/dhd.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/dhd.h 2015-03-08 14:27:37.693684500 -0500
- @@ -186,7 +186,7 @@
- void brcmf_txflowblock_if(struct brcmf_if *ifp,
- enum brcmf_netif_stop_reason reason, bool state);
- u32 brcmf_get_chip_info(struct brcmf_if *ifp);
- -void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
- +void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
- bool success);
-
- /* Sets dongle media info (drv_version, mac address). */
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c 2015-03-08 14:27:37.693684500 -0500
- @@ -190,7 +190,7 @@
- int ret;
- struct brcmf_if *ifp = netdev_priv(ndev);
- struct brcmf_pub *drvr = ifp->drvr;
- - struct ethhdr *eh;
- + struct ethhdr *eh = (struct ethhdr *)(skb->data);
-
- brcmf_dbg(DATA, "Enter, idx=%d\n", ifp->bssidx);
-
- @@ -236,6 +236,9 @@
- goto done;
- }
-
- + if (eh->h_proto == htons(ETH_P_PAE))
- + atomic_inc(&ifp->pend_8021x_cnt);
- +
- ret = brcmf_fws_process_skb(ifp, skb);
-
- done:
- @@ -511,7 +514,7 @@
-
- void brcmf_rx_frame(struct device *dev, struct sk_buff *skb)
- {
- - struct brcmf_if *ifp;
- + struct brcmf_if *ifp = NULL;
- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_pub *drvr = bus_if->drvr;
- struct brcmf_skb_reorder_data *rd;
- @@ -522,7 +525,7 @@
-
- /* process and remove protocol-specific header */
- ret = brcmf_proto_hdrpull(drvr, true, &ifidx, skb);
- - ifp = drvr->iflist[ifidx];
- + if (!ret) ifp = drvr->iflist[ifidx];
-
- if (ret || !ifp || !ifp->ndev) {
- if ((ret != -ENODATA) && ifp)
- @@ -538,31 +541,26 @@
- brcmf_netif_rx(ifp, skb);
- }
-
- -void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
- +void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
- bool success)
- {
- struct brcmf_if *ifp;
- struct ethhdr *eh;
- - u8 ifidx;
- u16 type;
- - int res;
- -
- - res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp);
-
- ifp = drvr->iflist[ifidx];
- if (!ifp)
- goto done;
-
- - if (res == 0) {
- - eh = (struct ethhdr *)(txp->data);
- - type = ntohs(eh->h_proto);
- -
- - if (type == ETH_P_PAE) {
- - atomic_dec(&ifp->pend_8021x_cnt);
- - if (waitqueue_active(&ifp->pend_8021x_wait))
- - wake_up(&ifp->pend_8021x_wait);
- - }
- + eh = (struct ethhdr *)(txp->data);
- + type = ntohs(eh->h_proto);
- +
- + if (type == ETH_P_PAE) {
- + atomic_dec(&ifp->pend_8021x_cnt);
- + if (waitqueue_active(&ifp->pend_8021x_wait))
- + wake_up(&ifp->pend_8021x_wait);
- }
- +
- if (!success)
- ifp->stats.tx_errors++;
- done:
- @@ -573,13 +571,17 @@
- {
- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_pub *drvr = bus_if->drvr;
- + u8 ifidx;
-
- /* await txstatus signal for firmware if active */
- if (brcmf_fws_fc_active(drvr->fws)) {
- if (!success)
- brcmf_fws_bustxfail(drvr->fws, txp);
- } else {
- - brcmf_txfinalize(drvr, txp, success);
- + if (brcmf_proto_hdrpull(drvr, false, &ifidx, txp))
- + brcmu_pkt_buf_free_skb(txp);
- + else
- + brcmf_txfinalize(drvr, txp, ifidx, success);
- }
- }
-
- @@ -914,13 +916,6 @@
-
- brcmf_dbg(TRACE, "\n");
-
- - /* Bring up the bus */
- - ret = brcmf_bus_init(bus_if);
- - if (ret != 0) {
- - brcmf_err("brcmf_sdbrcm_bus_init failed %d\n", ret);
- - return ret;
- - }
- -
- /* add primary networking interface */
- ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL);
- if (IS_ERR(ifp))
- @@ -1040,12 +1035,12 @@
-
- brcmf_cfg80211_detach(drvr->config);
-
- + brcmf_fws_deinit(drvr);
- +
- brcmf_bus_detach(drvr);
-
- brcmf_proto_detach(drvr);
-
- - brcmf_fws_deinit(drvr);
- -
- brcmf_debugfs_detach(drvr);
- bus_if->drvr = NULL;
- kfree(drvr);
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c 2015-03-08 14:27:37.693684500 -0500
- @@ -23,6 +23,7 @@
- #include <linux/interrupt.h>
- #include <linux/sched.h>
- #include <linux/mmc/sdio.h>
- +#include <linux/mmc/sdio_ids.h>
- #include <linux/mmc/sdio_func.h>
- #include <linux/mmc/card.h>
- #include <linux/semaphore.h>
- @@ -40,8 +41,8 @@
- #include <brcm_hw_ids.h>
- #include <soc.h>
- #include "sdio_host.h"
- -#include "sdio_chip.h"
- -#include "nvram.h"
- +#include "chip.h"
- +#include "firmware.h"
-
- #define DCMD_RESP_TIMEOUT 2000 /* In milli second */
-
- @@ -112,8 +113,6 @@
- #define BRCMF_TXBOUND 20 /* Default for max tx frames in
- one scheduling */
-
- -#define BRCMF_DEFAULT_TXGLOM_SIZE 32 /* max tx frames in glom chain */
- -
- #define BRCMF_TXMINMAX 1 /* Max tx frames if rx still pending */
-
- #define MEMBLOCK 2048 /* Block size used for downloading
- @@ -156,6 +155,34 @@
- /* manfid tuple length, include tuple, link bytes */
- #define SBSDIO_CIS_MANFID_TUPLE_LEN 6
-
- +#define CORE_BUS_REG(base, field) \
- + (base + offsetof(struct sdpcmd_regs, field))
- +
- +/* SDIO function 1 register CHIPCLKCSR */
- +/* Force ALP request to backplane */
- +#define SBSDIO_FORCE_ALP 0x01
- +/* Force HT request to backplane */
- +#define SBSDIO_FORCE_HT 0x02
- +/* Force ILP request to backplane */
- +#define SBSDIO_FORCE_ILP 0x04
- +/* Make ALP ready (power up xtal) */
- +#define SBSDIO_ALP_AVAIL_REQ 0x08
- +/* Make HT ready (power up PLL) */
- +#define SBSDIO_HT_AVAIL_REQ 0x10
- +/* Squelch clock requests from HW */
- +#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20
- +/* Status: ALP is ready */
- +#define SBSDIO_ALP_AVAIL 0x40
- +/* Status: HT is ready */
- +#define SBSDIO_HT_AVAIL 0x80
- +#define SBSDIO_CSR_MASK 0x1F
- +#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL)
- +#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS)
- +#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS)
- +#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval))
- +#define SBSDIO_CLKAV(regval, alponly) \
- + (SBSDIO_ALPAV(regval) && (alponly ? 1 : SBSDIO_HTAV(regval)))
- +
- /* intstatus */
- #define I_SMB_SW0 (1 << 0) /* To SB Mail S/W interrupt 0 */
- #define I_SMB_SW1 (1 << 1) /* To SB Mail S/W interrupt 1 */
- @@ -276,7 +303,6 @@
- /* Flags for SDH calls */
- #define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
-
- -#define BRCMF_IDLE_IMMEDIATE (-1) /* Enter idle immediately */
- #define BRCMF_IDLE_ACTIVE 0 /* Do not request any SD clock change
- * when idle
- */
- @@ -433,10 +459,11 @@
- bool alp_only; /* Don't use HT clock (ALP only) */
-
- u8 *ctrl_frame_buf;
- - u32 ctrl_frame_len;
- + u16 ctrl_frame_len;
- bool ctrl_frame_stat;
-
- - spinlock_t txqlock;
- + spinlock_t txq_lock; /* protect bus->txq */
- + struct semaphore tx_seq_lock; /* protect bus->tx_seq */
- wait_queue_head_t ctrl_wait;
- wait_queue_head_t dcmd_resp_wait;
-
- @@ -483,16 +510,58 @@
-
- #define ALIGNMENT 4
-
- -static int brcmf_sdio_txglomsz = BRCMF_DEFAULT_TXGLOM_SIZE;
- -module_param_named(txglomsz, brcmf_sdio_txglomsz, int, 0);
- -MODULE_PARM_DESC(txglomsz, "maximum tx packet chain size [SDIO]");
- -
- enum brcmf_sdio_frmtype {
- BRCMF_SDIO_FT_NORMAL,
- BRCMF_SDIO_FT_SUPER,
- BRCMF_SDIO_FT_SUB,
- };
-
- +#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
- +
- +/* SDIO Pad drive strength to select value mappings */
- +struct sdiod_drive_str {
- + u8 strength; /* Pad Drive Strength in mA */
- + u8 sel; /* Chip-specific select value */
- +};
- +
- +/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */
- +static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = {
- + {32, 0x6},
- + {26, 0x7},
- + {22, 0x4},
- + {16, 0x5},
- + {12, 0x2},
- + {8, 0x3},
- + {4, 0x0},
- + {0, 0x1}
- +};
- +
- +/* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */
- +static const struct sdiod_drive_str sdiod_drive_strength_tab5_1v8[] = {
- + {6, 0x7},
- + {5, 0x6},
- + {4, 0x5},
- + {3, 0x4},
- + {2, 0x2},
- + {1, 0x1},
- + {0, 0x0}
- +};
- +
- +/* SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */
- +static const struct sdiod_drive_str sdiod_drvstr_tab6_1v8[] = {
- + {3, 0x3},
- + {2, 0x2},
- + {1, 0x1},
- + {0, 0x0} };
- +
- +/* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */
- +static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = {
- + {16, 0x7},
- + {12, 0x5},
- + {8, 0x3},
- + {4, 0x1}
- +};
- +
- #define BCM43143_FIRMWARE_NAME "brcm/brcmfmac43143-sdio.bin"
- #define BCM43143_NVRAM_NAME "brcm/brcmfmac43143-sdio.txt"
- #define BCM43241B0_FIRMWARE_NAME "brcm/brcmfmac43241b0-sdio.bin"
- @@ -511,6 +580,8 @@
- #define BCM43362_NVRAM_NAME "brcm/brcmfmac43362-sdio.txt"
- #define BCM4339_FIRMWARE_NAME "brcm/brcmfmac4339-sdio.bin"
- #define BCM4339_NVRAM_NAME "brcm/brcmfmac4339-sdio.txt"
- +#define BCM4354_FIRMWARE_NAME "brcm/brcmfmac4354-sdio.bin"
- +#define BCM4354_NVRAM_NAME "brcm/brcmfmac4354-sdio.txt"
-
- MODULE_FIRMWARE(BCM43143_FIRMWARE_NAME);
- MODULE_FIRMWARE(BCM43143_NVRAM_NAME);
- @@ -530,6 +601,8 @@
- MODULE_FIRMWARE(BCM43362_NVRAM_NAME);
- MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME);
- MODULE_FIRMWARE(BCM4339_NVRAM_NAME);
- +MODULE_FIRMWARE(BCM4354_FIRMWARE_NAME);
- +MODULE_FIRMWARE(BCM4354_NVRAM_NAME);
-
- struct brcmf_firmware_names {
- u32 chipid;
- @@ -555,46 +628,32 @@
- { BCM4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) },
- { BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) },
- { BCM43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) },
- - { BCM4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) }
- + { BCM4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) },
- + { BCM4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) }
- };
-
- -
- -static const struct firmware *brcmf_sdio_get_fw(struct brcmf_sdio *bus,
- - enum brcmf_firmware_type type)
- +static const char *brcmf_sdio_get_fwname(struct brcmf_chip *ci,
- + enum brcmf_firmware_type type)
- {
- - const struct firmware *fw;
- - const char *name;
- - int err, i;
- + int i;
-
- for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) {
- - if (brcmf_fwname_data[i].chipid == bus->ci->chip &&
- - brcmf_fwname_data[i].revmsk & BIT(bus->ci->chiprev)) {
- + if (brcmf_fwname_data[i].chipid == ci->chip &&
- + brcmf_fwname_data[i].revmsk & BIT(ci->chiprev)) {
- switch (type) {
- case BRCMF_FIRMWARE_BIN:
- - name = brcmf_fwname_data[i].bin;
- - break;
- + return brcmf_fwname_data[i].bin;
- case BRCMF_FIRMWARE_NVRAM:
- - name = brcmf_fwname_data[i].nv;
- - break;
- + return brcmf_fwname_data[i].nv;
- default:
- brcmf_err("invalid firmware type (%d)\n", type);
- return NULL;
- }
- - goto found;
- }
- }
- brcmf_err("Unknown chipid %d [%d]\n",
- - bus->ci->chip, bus->ci->chiprev);
- + ci->chip, ci->chiprev);
- return NULL;
- -
- -found:
- - err = request_firmware(&fw, name, &bus->sdiodev->func[2]->dev);
- - if ((err) || (!fw)) {
- - brcmf_err("fail to request firmware %s (%d)\n", name, err);
- - return NULL;
- - }
- -
- - return fw;
- }
-
- static void pkt_align(struct sk_buff *p, int len, int align)
- @@ -618,27 +677,24 @@
- * Reads a register in the SDIO hardware block. This block occupies a series of
- * adresses on the 32 bit backplane bus.
- */
- -static int
- -r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 offset)
- +static int r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 offset)
- {
- - u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
- + struct brcmf_core *core;
- int ret;
-
- - *regvar = brcmf_sdiod_regrl(bus->sdiodev,
- - bus->ci->c_inf[idx].base + offset, &ret);
- + core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
- + *regvar = brcmf_sdiod_regrl(bus->sdiodev, core->base + offset, &ret);
-
- return ret;
- }
-
- -static int
- -w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset)
- +static int w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset)
- {
- - u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
- + struct brcmf_core *core;
- int ret;
-
- - brcmf_sdiod_regwl(bus->sdiodev,
- - bus->ci->c_inf[idx].base + reg_offset,
- - regval, &ret);
- + core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
- + brcmf_sdiod_regwl(bus->sdiodev, core->base + reg_offset, regval, &ret);
-
- return ret;
- }
- @@ -650,16 +706,12 @@
- int err = 0;
- int try_cnt = 0;
-
- - brcmf_dbg(TRACE, "Enter\n");
- + brcmf_dbg(TRACE, "Enter: on=%d\n", on);
-
- wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
- /* 1st KSO write goes to AOS wake up core if device is asleep */
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
- wr_val, &err);
- - if (err) {
- - brcmf_err("SDIO_AOS KSO write error: %d\n", err);
- - return err;
- - }
-
- if (on) {
- /* device WAKEUP through KSO:
- @@ -689,18 +741,22 @@
- &err);
- if (((rd_val & bmask) == cmp_val) && !err)
- break;
- - brcmf_dbg(SDIO, "KSO wr/rd retry:%d (max: %d) ERR:%x\n",
- - try_cnt, MAX_KSO_ATTEMPTS, err);
- +
- udelay(KSO_WAIT_US);
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
- wr_val, &err);
- } while (try_cnt++ < MAX_KSO_ATTEMPTS);
-
- + if (try_cnt > 2)
- + brcmf_dbg(SDIO, "try_cnt=%d rd_val=0x%x err=%d\n", try_cnt,
- + rd_val, err);
- +
- + if (try_cnt > MAX_KSO_ATTEMPTS)
- + brcmf_err("max tries: rd_val=0x%x err=%d\n", rd_val, err);
- +
- return err;
- }
-
- -#define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND)
- -
- #define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE)
-
- /* Turn backplane clock on or off */
- @@ -799,7 +855,6 @@
- }
- #endif /* defined (DEBUG) */
-
- - bus->activity = true;
- } else {
- clkreq = 0;
-
- @@ -899,8 +954,9 @@
- brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok)
- {
- int err = 0;
- - brcmf_dbg(TRACE, "Enter\n");
- - brcmf_dbg(SDIO, "request %s currently %s\n",
- + u8 clkcsr;
- +
- + brcmf_dbg(SDIO, "Enter: request %s currently %s\n",
- (sleep ? "SLEEP" : "WAKE"),
- (bus->sleeping ? "SLEEP" : "WAKE"));
-
- @@ -917,8 +973,20 @@
- atomic_read(&bus->ipend) > 0 ||
- (!atomic_read(&bus->fcstate) &&
- brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
- - data_ok(bus)))
- - return -EBUSY;
- + data_ok(bus))) {
- + err = -EBUSY;
- + goto done;
- + }
- +
- + clkcsr = brcmf_sdiod_regrb(bus->sdiodev,
- + SBSDIO_FUNC1_CHIPCLKCSR,
- + &err);
- + if ((clkcsr & SBSDIO_CSR_MASK) == 0) {
- + brcmf_dbg(SDIO, "no clock, set ALP\n");
- + brcmf_sdiod_regwb(bus->sdiodev,
- + SBSDIO_FUNC1_CHIPCLKCSR,
- + SBSDIO_ALP_AVAIL_REQ, &err);
- + }
- err = brcmf_sdio_kso_control(bus, false);
- /* disable watchdog */
- if (!err)
- @@ -935,7 +1003,7 @@
- } else {
- brcmf_err("error while changing bus sleep state %d\n",
- err);
- - return err;
- + goto done;
- }
- }
-
- @@ -947,11 +1015,92 @@
- } else {
- brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok);
- }
- -
- +done:
- + brcmf_dbg(SDIO, "Exit: err=%d\n", err);
- return err;
-
- }
-
- +#ifdef DEBUG
- +static inline bool brcmf_sdio_valid_shared_address(u32 addr)
- +{
- + return !(addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff));
- +}
- +
- +static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
- + struct sdpcm_shared *sh)
- +{
- + u32 addr;
- + int rv;
- + u32 shaddr = 0;
- + struct sdpcm_shared_le sh_le;
- + __le32 addr_le;
- +
- + shaddr = bus->ci->rambase + bus->ramsize - 4;
- +
- + /*
- + * Read last word in socram to determine
- + * address of sdpcm_shared structure
- + */
- + sdio_claim_host(bus->sdiodev->func[1]);
- + brcmf_sdio_bus_sleep(bus, false, false);
- + rv = brcmf_sdiod_ramrw(bus->sdiodev, false, shaddr, (u8 *)&addr_le, 4);
- + sdio_release_host(bus->sdiodev->func[1]);
- + if (rv < 0)
- + return rv;
- +
- + addr = le32_to_cpu(addr_le);
- +
- + brcmf_dbg(SDIO, "sdpcm_shared address 0x%08X\n", addr);
- +
- + /*
- + * Check if addr is valid.
- + * NVRAM length at the end of memory should have been overwritten.
- + */
- + if (!brcmf_sdio_valid_shared_address(addr)) {
- + brcmf_err("invalid sdpcm_shared address 0x%08X\n",
- + addr);
- + return -EINVAL;
- + }
- +
- + /* Read hndrte_shared structure */
- + rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le,
- + sizeof(struct sdpcm_shared_le));
- + if (rv < 0)
- + return rv;
- +
- + /* Endianness */
- + sh->flags = le32_to_cpu(sh_le.flags);
- + sh->trap_addr = le32_to_cpu(sh_le.trap_addr);
- + sh->assert_exp_addr = le32_to_cpu(sh_le.assert_exp_addr);
- + sh->assert_file_addr = le32_to_cpu(sh_le.assert_file_addr);
- + sh->assert_line = le32_to_cpu(sh_le.assert_line);
- + sh->console_addr = le32_to_cpu(sh_le.console_addr);
- + sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr);
- +
- + if ((sh->flags & SDPCM_SHARED_VERSION_MASK) > SDPCM_SHARED_VERSION) {
- + brcmf_err("sdpcm shared version unsupported: dhd %d dongle %d\n",
- + SDPCM_SHARED_VERSION,
- + sh->flags & SDPCM_SHARED_VERSION_MASK);
- + return -EPROTO;
- + }
- +
- + return 0;
- +}
- +
- +static void brcmf_sdio_get_console_addr(struct brcmf_sdio *bus)
- +{
- + struct sdpcm_shared sh;
- +
- + if (brcmf_sdio_readshared(bus, &sh) == 0)
- + bus->console_addr = sh.console_addr;
- +}
- +#else
- +static void brcmf_sdio_get_console_addr(struct brcmf_sdio *bus)
- +{
- +}
- +#endif /* DEBUG */
- +
- static u32 brcmf_sdio_hostmail(struct brcmf_sdio *bus)
- {
- u32 intstatus = 0;
- @@ -995,6 +1144,12 @@
- else
- brcmf_dbg(SDIO, "Dongle ready, protocol version %d\n",
- bus->sdpcm_ver);
- +
- + /*
- + * Retrieve console state address now that firmware should have
- + * updated it.
- + */
- + brcmf_sdio_get_console_addr(bus);
- }
-
- /*
- @@ -1083,6 +1238,28 @@
- bus->cur_read.len = 0;
- }
-
- +static void brcmf_sdio_txfail(struct brcmf_sdio *bus)
- +{
- + struct brcmf_sdio_dev *sdiodev = bus->sdiodev;
- + u8 i, hi, lo;
- +
- + /* On failure, abort the command and terminate the frame */
- + brcmf_err("sdio error, abort command and terminate frame\n");
- + bus->sdcnt.tx_sderrs++;
- +
- + brcmf_sdiod_abort(sdiodev, SDIO_FUNC_2);
- + brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL);
- + bus->sdcnt.f1regdata++;
- +
- + for (i = 0; i < 3; i++) {
- + hi = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_WFRAMEBCHI, NULL);
- + lo = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_WFRAMEBCLO, NULL);
- + bus->sdcnt.f1regdata += 2;
- + if ((hi == 0) && (lo == 0))
- + break;
- + }
- +}
- +
- /* return total length of buffer chain */
- static uint brcmf_sdio_glom_len(struct brcmf_sdio *bus)
- {
- @@ -1955,7 +2132,7 @@
- memcpy(pkt_pad->data,
- pkt->data + pkt->len - tail_chop,
- tail_chop);
- - *(u32 *)(pkt_pad->cb) = ALIGN_SKB_FLAG + tail_chop;
- + *(u16 *)(pkt_pad->cb) = ALIGN_SKB_FLAG + tail_chop;
- skb_trim(pkt, pkt->len - tail_chop);
- skb_trim(pkt_pad, tail_pad + tail_chop);
- __skb_queue_after(pktq, pkt, pkt_pad);
- @@ -2003,7 +2180,7 @@
- * already properly aligned and does not
- * need an sdpcm header.
- */
- - if (*(u32 *)(pkt_next->cb) & ALIGN_SKB_FLAG)
- + if (*(u16 *)(pkt_next->cb) & ALIGN_SKB_FLAG)
- continue;
-
- /* align packet data pointer */
- @@ -2037,10 +2214,10 @@
- if (BRCMF_BYTES_ON() &&
- ((BRCMF_CTL_ON() && chan == SDPCM_CONTROL_CHANNEL) ||
- (BRCMF_DATA_ON() && chan != SDPCM_CONTROL_CHANNEL)))
- - brcmf_dbg_hex_dump(true, pkt_next, hd_info.len,
- + brcmf_dbg_hex_dump(true, pkt_next->data, hd_info.len,
- "Tx Frame:\n");
- else if (BRCMF_HDRS_ON())
- - brcmf_dbg_hex_dump(true, pkt_next,
- + brcmf_dbg_hex_dump(true, pkt_next->data,
- head_pad + bus->tx_hdrlen,
- "Tx Header:\n");
- }
- @@ -2067,11 +2244,11 @@
- u8 *hdr;
- u32 dat_offset;
- u16 tail_pad;
- - u32 dummy_flags, chop_len;
- + u16 dummy_flags, chop_len;
- struct sk_buff *pkt_next, *tmp, *pkt_prev;
-
- skb_queue_walk_safe(pktq, pkt_next, tmp) {
- - dummy_flags = *(u32 *)(pkt_next->cb);
- + dummy_flags = *(u16 *)(pkt_next->cb);
- if (dummy_flags & ALIGN_SKB_FLAG) {
- chop_len = dummy_flags & ALIGN_SKB_CHOP_LEN_MASK;
- if (chop_len) {
- @@ -2100,7 +2277,6 @@
- uint chan)
- {
- int ret;
- - int i;
- struct sk_buff *pkt_next, *tmp;
-
- brcmf_dbg(TRACE, "Enter\n");
- @@ -2113,28 +2289,9 @@
- ret = brcmf_sdiod_send_pkt(bus->sdiodev, pktq);
- bus->sdcnt.f2txdata++;
-
- - if (ret < 0) {
- - /* On failure, abort the command and terminate the frame */
- - brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n",
- - ret);
- - bus->sdcnt.tx_sderrs++;
- + if (ret < 0)
- + brcmf_sdio_txfail(bus);
-
- - brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2);
- - brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
- - SFC_WF_TERM, NULL);
- - bus->sdcnt.f1regdata++;
- -
- - for (i = 0; i < 3; i++) {
- - u8 hi, lo;
- - hi = brcmf_sdiod_regrb(bus->sdiodev,
- - SBSDIO_FUNC1_WFRAMEBCHI, NULL);
- - lo = brcmf_sdiod_regrb(bus->sdiodev,
- - SBSDIO_FUNC1_WFRAMEBCLO, NULL);
- - bus->sdcnt.f1regdata += 2;
- - if ((hi == 0) && (lo == 0))
- - break;
- - }
- - }
- sdio_release_host(bus->sdiodev->func[1]);
-
- done:
- @@ -2164,13 +2321,15 @@
- /* Send frames until the limit or some other event */
- for (cnt = 0; (cnt < maxframes) && data_ok(bus);) {
- pkt_num = 1;
- - __skb_queue_head_init(&pktq);
- + if (down_interruptible(&bus->tx_seq_lock))
- + return cnt;
- if (bus->txglom)
- pkt_num = min_t(u8, bus->tx_max - bus->tx_seq,
- - brcmf_sdio_txglomsz);
- + bus->sdiodev->txglomsz);
- pkt_num = min_t(u32, pkt_num,
- brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol));
- - spin_lock_bh(&bus->txqlock);
- + __skb_queue_head_init(&pktq);
- + spin_lock_bh(&bus->txq_lock);
- for (i = 0; i < pkt_num; i++) {
- pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map,
- &prec_out);
- @@ -2178,15 +2337,19 @@
- break;
- __skb_queue_tail(&pktq, pkt);
- }
- - spin_unlock_bh(&bus->txqlock);
- - if (i == 0)
- + spin_unlock_bh(&bus->txq_lock);
- + if (i == 0) {
- + up(&bus->tx_seq_lock);
- break;
- + }
-
- ret = brcmf_sdio_txpkt(bus, &pktq, SDPCM_DATA_CHANNEL);
- + up(&bus->tx_seq_lock);
- +
- cnt += i;
-
- /* In poll mode, need to check for other events */
- - if (!bus->intr && cnt) {
- + if (!bus->intr) {
- /* Check device status, signal pending interrupt */
- sdio_claim_host(bus->sdiodev->func[1]);
- ret = r_sdreg32(bus, &intstatus,
- @@ -2211,6 +2374,68 @@
- return cnt;
- }
-
- +static int brcmf_sdio_tx_ctrlframe(struct brcmf_sdio *bus, u8 *frame, u16 len)
- +{
- + u8 doff;
- + u16 pad;
- + uint retries = 0;
- + struct brcmf_sdio_hdrinfo hd_info = {0};
- + int ret;
- +
- + brcmf_dbg(TRACE, "Enter\n");
- +
- + /* Back the pointer to make room for bus header */
- + frame -= bus->tx_hdrlen;
- + len += bus->tx_hdrlen;
- +
- + /* Add alignment padding (optional for ctl frames) */
- + doff = ((unsigned long)frame % bus->head_align);
- + if (doff) {
- + frame -= doff;
- + len += doff;
- + memset(frame + bus->tx_hdrlen, 0, doff);
- + }
- +
- + /* Round send length to next SDIO block */
- + pad = 0;
- + if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
- + pad = bus->blocksize - (len % bus->blocksize);
- + if ((pad > bus->roundup) || (pad >= bus->blocksize))
- + pad = 0;
- + } else if (len % bus->head_align) {
- + pad = bus->head_align - (len % bus->head_align);
- + }
- + len += pad;
- +
- + hd_info.len = len - pad;
- + hd_info.channel = SDPCM_CONTROL_CHANNEL;
- + hd_info.dat_offset = doff + bus->tx_hdrlen;
- + hd_info.seq_num = bus->tx_seq;
- + hd_info.lastfrm = true;
- + hd_info.tail_pad = pad;
- + brcmf_sdio_hdpack(bus, frame, &hd_info);
- +
- + if (bus->txglom)
- + brcmf_sdio_update_hwhdr(frame, len);
- +
- + brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_CTL_ON(),
- + frame, len, "Tx Frame:\n");
- + brcmf_dbg_hex_dump(!(BRCMF_BYTES_ON() && BRCMF_CTL_ON()) &&
- + BRCMF_HDRS_ON(),
- + frame, min_t(u16, len, 16), "TxHdr:\n");
- +
- + do {
- + ret = brcmf_sdiod_send_buf(bus->sdiodev, frame, len);
- +
- + if (ret < 0)
- + brcmf_sdio_txfail(bus);
- + else
- + bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQ_WRAP;
- + } while (ret < 0 && retries++ < TXRETRIES);
- +
- + return ret;
- +}
- +
- static void brcmf_sdio_bus_stop(struct device *dev)
- {
- u32 local_hostintmask;
- @@ -2292,21 +2517,29 @@
- }
- }
-
- +static void atomic_orr(int val, atomic_t *v)
- +{
- + int old_val;
- +
- + old_val = atomic_read(v);
- + while (atomic_cmpxchg(v, old_val, val | old_val) != old_val)
- + old_val = atomic_read(v);
- +}
- +
- static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
- {
- - u8 idx;
- + struct brcmf_core *buscore;
- u32 addr;
- unsigned long val;
- - int n, ret;
- + int ret;
-
- - idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
- - addr = bus->ci->c_inf[idx].base +
- - offsetof(struct sdpcmd_regs, intstatus);
- + buscore = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
- + addr = buscore->base + offsetof(struct sdpcmd_regs, intstatus);
-
- val = brcmf_sdiod_regrl(bus->sdiodev, addr, &ret);
- bus->sdcnt.f1regdata++;
- if (ret != 0)
- - val = 0;
- + return ret;
-
- val &= bus->hostintmask;
- atomic_set(&bus->fcstate, !!(val & I_HMB_FC_STATE));
- @@ -2315,13 +2548,7 @@
- if (val) {
- brcmf_sdiod_regwl(bus->sdiodev, addr, val, &ret);
- bus->sdcnt.f1regdata++;
- - }
- -
- - if (ret) {
- - atomic_set(&bus->intstatus, 0);
- - } else if (val) {
- - for_each_set_bit(n, &val, 32)
- - set_bit(n, (unsigned long *)&bus->intstatus.counter);
- + atomic_orr(val, &bus->intstatus);
- }
-
- return ret;
- @@ -2331,10 +2558,9 @@
- {
- u32 newstatus = 0;
- unsigned long intstatus;
- - uint rxlimit = bus->rxbound; /* Rx frames to read before resched */
- uint txlimit = bus->txbound; /* Tx frames to send before resched */
- - uint framecnt = 0; /* Temporary counter of tx/rx frames */
- - int err = 0, n;
- + uint framecnt; /* Temporary counter of tx/rx frames */
- + int err = 0;
-
- brcmf_dbg(TRACE, "Enter\n");
-
- @@ -2431,70 +2657,38 @@
- intstatus &= ~I_HMB_FRAME_IND;
-
- /* On frame indication, read available frames */
- - if (PKT_AVAILABLE() && bus->clkstate == CLK_AVAIL) {
- - framecnt = brcmf_sdio_readframes(bus, rxlimit);
- + if ((intstatus & I_HMB_FRAME_IND) && (bus->clkstate == CLK_AVAIL)) {
- + brcmf_sdio_readframes(bus, bus->rxbound);
- if (!bus->rxpending)
- intstatus &= ~I_HMB_FRAME_IND;
- - rxlimit -= min(framecnt, rxlimit);
- }
-
- /* Keep still-pending events for next scheduling */
- - if (intstatus) {
- - for_each_set_bit(n, &intstatus, 32)
- - set_bit(n, (unsigned long *)&bus->intstatus.counter);
- - }
- + if (intstatus)
- + atomic_orr(intstatus, &bus->intstatus);
-
- brcmf_sdio_clrintr(bus);
-
- - if (data_ok(bus) && bus->ctrl_frame_stat &&
- - (bus->clkstate == CLK_AVAIL)) {
- - int i;
- -
- - sdio_claim_host(bus->sdiodev->func[1]);
- - err = brcmf_sdiod_send_buf(bus->sdiodev, bus->ctrl_frame_buf,
- - (u32)bus->ctrl_frame_len);
- -
- - if (err < 0) {
- - /* On failure, abort the command and
- - terminate the frame */
- - brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n",
- - err);
- - bus->sdcnt.tx_sderrs++;
- -
- - brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2);
- -
- - brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
- - SFC_WF_TERM, &err);
- - bus->sdcnt.f1regdata++;
- -
- - for (i = 0; i < 3; i++) {
- - u8 hi, lo;
- - hi = brcmf_sdiod_regrb(bus->sdiodev,
- - SBSDIO_FUNC1_WFRAMEBCHI,
- - &err);
- - lo = brcmf_sdiod_regrb(bus->sdiodev,
- - SBSDIO_FUNC1_WFRAMEBCLO,
- - &err);
- - bus->sdcnt.f1regdata += 2;
- - if ((hi == 0) && (lo == 0))
- - break;
- - }
- + if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) &&
- + (down_interruptible(&bus->tx_seq_lock) == 0)) {
- + if (data_ok(bus)) {
- + sdio_claim_host(bus->sdiodev->func[1]);
- + err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf,
- + bus->ctrl_frame_len);
- + sdio_release_host(bus->sdiodev->func[1]);
-
- - } else {
- - bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQ_WRAP;
- + bus->ctrl_frame_stat = false;
- + brcmf_sdio_wait_event_wakeup(bus);
- }
- - sdio_release_host(bus->sdiodev->func[1]);
- - bus->ctrl_frame_stat = false;
- - brcmf_sdio_wait_event_wakeup(bus);
- + up(&bus->tx_seq_lock);
- }
- /* Send queued frames (limit 1 if rx may still be pending) */
- - else if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) &&
- - brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit
- - && data_ok(bus)) {
- + if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) &&
- + brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit &&
- + data_ok(bus)) {
- framecnt = bus->rxpending ? min(txlimit, bus->txminmax) :
- txlimit;
- - framecnt = brcmf_sdio_sendfromq(bus, framecnt);
- - txlimit -= framecnt;
- + brcmf_sdio_sendfromq(bus, framecnt);
- }
-
- if (!brcmf_bus_ready(bus->sdiodev->bus_if) || (err != 0)) {
- @@ -2504,19 +2698,9 @@
- atomic_read(&bus->ipend) > 0 ||
- (!atomic_read(&bus->fcstate) &&
- brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
- - data_ok(bus)) || PKT_AVAILABLE()) {
- + data_ok(bus))) {
- atomic_inc(&bus->dpc_tskcnt);
- }
- -
- - /* If we're done for now, turn off clock request. */
- - if ((bus->clkstate != CLK_PENDING)
- - && bus->idletime == BRCMF_IDLE_IMMEDIATE) {
- - bus->activity = false;
- - brcmf_dbg(SDIO, "idle state\n");
- - sdio_claim_host(bus->sdiodev->func[1]);
- - brcmf_sdio_bus_sleep(bus, true, false);
- - sdio_release_host(bus->sdiodev->func[1]);
- - }
- }
-
- static struct pktq *brcmf_sdio_bus_gettxq(struct device *dev)
- @@ -2531,15 +2715,12 @@
- static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt)
- {
- int ret = -EBADE;
- - uint datalen, prec;
- + uint prec;
- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
- struct brcmf_sdio *bus = sdiodev->bus;
- - ulong flags;
- -
- - brcmf_dbg(TRACE, "Enter\n");
-
- - datalen = pkt->len;
- + brcmf_dbg(TRACE, "Enter: pkt: data %p len %d\n", pkt->data, pkt->len);
-
- /* Add space for the header */
- skb_push(pkt, bus->tx_hdrlen);
- @@ -2553,7 +2734,9 @@
- bus->sdcnt.fcqueued++;
-
- /* Priority based enq */
- - spin_lock_irqsave(&bus->txqlock, flags);
- + spin_lock_bh(&bus->txq_lock);
- + /* reset bus_flags in packet cb */
- + *(u16 *)(pkt->cb) = 0;
- if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) {
- skb_pull(pkt, bus->tx_hdrlen);
- brcmf_err("out of bus->txq !!!\n");
- @@ -2566,7 +2749,7 @@
- bus->txoff = true;
- brcmf_txflowblock(bus->sdiodev->dev, true);
- }
- - spin_unlock_irqrestore(&bus->txqlock, flags);
- + spin_unlock_bh(&bus->txq_lock);
-
- #ifdef DEBUG
- if (pktq_plen(&bus->txq, prec) > qcount[prec])
- @@ -2661,110 +2844,27 @@
- }
- #endif /* DEBUG */
-
- -static int brcmf_sdio_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len)
- -{
- - int i;
- - int ret;
- -
- - bus->ctrl_frame_stat = false;
- - ret = brcmf_sdiod_send_buf(bus->sdiodev, frame, len);
- -
- - if (ret < 0) {
- - /* On failure, abort the command and terminate the frame */
- - brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n",
- - ret);
- - bus->sdcnt.tx_sderrs++;
- -
- - brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2);
- -
- - brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
- - SFC_WF_TERM, NULL);
- - bus->sdcnt.f1regdata++;
- -
- - for (i = 0; i < 3; i++) {
- - u8 hi, lo;
- - hi = brcmf_sdiod_regrb(bus->sdiodev,
- - SBSDIO_FUNC1_WFRAMEBCHI, NULL);
- - lo = brcmf_sdiod_regrb(bus->sdiodev,
- - SBSDIO_FUNC1_WFRAMEBCLO, NULL);
- - bus->sdcnt.f1regdata += 2;
- - if (hi == 0 && lo == 0)
- - break;
- - }
- - return ret;
- - }
- -
- - bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQ_WRAP;
- -
- - return ret;
- -}
- -
- static int
- brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
- {
- - u8 *frame;
- - u16 len, pad;
- - uint retries = 0;
- - u8 doff = 0;
- - int ret = -1;
- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
- struct brcmf_sdio *bus = sdiodev->bus;
- - struct brcmf_sdio_hdrinfo hd_info = {0};
- + int ret = -1;
-
- brcmf_dbg(TRACE, "Enter\n");
-
- - /* Back the pointer to make a room for bus header */
- - frame = msg - bus->tx_hdrlen;
- - len = (msglen += bus->tx_hdrlen);
- + if (down_interruptible(&bus->tx_seq_lock))
- + return -EINTR;
-
- - /* Add alignment padding (optional for ctl frames) */
- - doff = ((unsigned long)frame % bus->head_align);
- - if (doff) {
- - frame -= doff;
- - len += doff;
- - msglen += doff;
- - memset(frame, 0, doff + bus->tx_hdrlen);
- - }
- - /* precondition: doff < bus->head_align */
- - doff += bus->tx_hdrlen;
- -
- - /* Round send length to next SDIO block */
- - pad = 0;
- - if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
- - pad = bus->blocksize - (len % bus->blocksize);
- - if ((pad > bus->roundup) || (pad >= bus->blocksize))
- - pad = 0;
- - } else if (len % bus->head_align) {
- - pad = bus->head_align - (len % bus->head_align);
- - }
- - len += pad;
- -
- - /* precondition: IS_ALIGNED((unsigned long)frame, 2) */
- -
- - /* Make sure backplane clock is on */
- - sdio_claim_host(bus->sdiodev->func[1]);
- - brcmf_sdio_bus_sleep(bus, false, false);
- - sdio_release_host(bus->sdiodev->func[1]);
- -
- - hd_info.len = (u16)msglen;
- - hd_info.channel = SDPCM_CONTROL_CHANNEL;
- - hd_info.dat_offset = doff;
- - hd_info.seq_num = bus->tx_seq;
- - hd_info.lastfrm = true;
- - hd_info.tail_pad = pad;
- - brcmf_sdio_hdpack(bus, frame, &hd_info);
- -
- - if (bus->txglom)
- - brcmf_sdio_update_hwhdr(frame, len);
- -
- - if (!data_ok(bus)) {
- - brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n",
- - bus->tx_max, bus->tx_seq);
- - bus->ctrl_frame_stat = true;
- - /* Send from dpc */
- - bus->ctrl_frame_buf = frame;
- - bus->ctrl_frame_len = len;
- + if (!data_ok(bus)) {
- + brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n",
- + bus->tx_max, bus->tx_seq);
- + up(&bus->tx_seq_lock);
- + /* Send from dpc */
- + bus->ctrl_frame_buf = msg;
- + bus->ctrl_frame_len = msglen;
- + bus->ctrl_frame_stat = true;
-
- wait_event_interruptible_timeout(bus->ctrl_wait,
- !bus->ctrl_frame_stat,
- @@ -2775,31 +2875,18 @@
- ret = 0;
- } else {
- brcmf_dbg(SDIO, "ctrl_frame_stat == true\n");
- + bus->ctrl_frame_stat = false;
- + if (down_interruptible(&bus->tx_seq_lock))
- + return -EINTR;
- ret = -1;
- }
- }
- -
- if (ret == -1) {
- - brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_CTL_ON(),
- - frame, len, "Tx Frame:\n");
- - brcmf_dbg_hex_dump(!(BRCMF_BYTES_ON() && BRCMF_CTL_ON()) &&
- - BRCMF_HDRS_ON(),
- - frame, min_t(u16, len, 16), "TxHdr:\n");
- -
- - do {
- - sdio_claim_host(bus->sdiodev->func[1]);
- - ret = brcmf_sdio_tx_frame(bus, frame, len);
- - sdio_release_host(bus->sdiodev->func[1]);
- - } while (ret < 0 && retries++ < TXRETRIES);
- - }
- -
- - if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) &&
- - atomic_read(&bus->dpc_tskcnt) == 0) {
- - bus->activity = false;
- sdio_claim_host(bus->sdiodev->func[1]);
- - brcmf_dbg(INFO, "idle\n");
- - brcmf_sdio_clkctl(bus, CLK_NONE, true);
- + brcmf_sdio_bus_sleep(bus, false, false);
- + ret = brcmf_sdio_tx_ctrlframe(bus, msg, msglen);
- sdio_release_host(bus->sdiodev->func[1]);
- + up(&bus->tx_seq_lock);
- }
-
- if (ret)
- @@ -2811,72 +2898,6 @@
- }
-
- #ifdef DEBUG
- -static inline bool brcmf_sdio_valid_shared_address(u32 addr)
- -{
- - return !(addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff));
- -}
- -
- -static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
- - struct sdpcm_shared *sh)
- -{
- - u32 addr;
- - int rv;
- - u32 shaddr = 0;
- - struct sdpcm_shared_le sh_le;
- - __le32 addr_le;
- -
- - shaddr = bus->ci->rambase + bus->ramsize - 4;
- -
- - /*
- - * Read last word in socram to determine
- - * address of sdpcm_shared structure
- - */
- - sdio_claim_host(bus->sdiodev->func[1]);
- - brcmf_sdio_bus_sleep(bus, false, false);
- - rv = brcmf_sdiod_ramrw(bus->sdiodev, false, shaddr, (u8 *)&addr_le, 4);
- - sdio_release_host(bus->sdiodev->func[1]);
- - if (rv < 0)
- - return rv;
- -
- - addr = le32_to_cpu(addr_le);
- -
- - brcmf_dbg(SDIO, "sdpcm_shared address 0x%08X\n", addr);
- -
- - /*
- - * Check if addr is valid.
- - * NVRAM length at the end of memory should have been overwritten.
- - */
- - if (!brcmf_sdio_valid_shared_address(addr)) {
- - brcmf_err("invalid sdpcm_shared address 0x%08X\n",
- - addr);
- - return -EINVAL;
- - }
- -
- - /* Read hndrte_shared structure */
- - rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le,
- - sizeof(struct sdpcm_shared_le));
- - if (rv < 0)
- - return rv;
- -
- - /* Endianness */
- - sh->flags = le32_to_cpu(sh_le.flags);
- - sh->trap_addr = le32_to_cpu(sh_le.trap_addr);
- - sh->assert_exp_addr = le32_to_cpu(sh_le.assert_exp_addr);
- - sh->assert_file_addr = le32_to_cpu(sh_le.assert_file_addr);
- - sh->assert_line = le32_to_cpu(sh_le.assert_line);
- - sh->console_addr = le32_to_cpu(sh_le.console_addr);
- - sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr);
- -
- - if ((sh->flags & SDPCM_SHARED_VERSION_MASK) > SDPCM_SHARED_VERSION) {
- - brcmf_err("sdpcm shared version unsupported: dhd %d dongle %d\n",
- - SDPCM_SHARED_VERSION,
- - sh->flags & SDPCM_SHARED_VERSION_MASK);
- - return -EPROTO;
- - }
- -
- - return 0;
- -}
- -
- static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
- struct sdpcm_shared *sh, char __user *data,
- size_t count)
- @@ -3106,6 +3127,8 @@
- debugfs_create_file("forensics", S_IRUGO, dentry, bus,
- &brcmf_sdio_forensic_ops);
- brcmf_debugfs_create_sdio_count(drvr, &bus->sdcnt);
- + debugfs_create_u32("console_interval", 0644, dentry,
- + &bus->console_interval);
- }
- #else
- static int brcmf_sdio_checkdied(struct brcmf_sdio *bus)
- @@ -3224,51 +3247,29 @@
- const struct firmware *fw)
- {
- int err;
- - int offset;
- - int address;
- - int len;
-
- brcmf_dbg(TRACE, "Enter\n");
-
- - err = 0;
- - offset = 0;
- - address = bus->ci->rambase;
- - while (offset < fw->size) {
- - len = ((offset + MEMBLOCK) < fw->size) ? MEMBLOCK :
- - fw->size - offset;
- - err = brcmf_sdiod_ramrw(bus->sdiodev, true, address,
- - (u8 *)&fw->data[offset], len);
- - if (err) {
- - brcmf_err("error %d on writing %d membytes at 0x%08x\n",
- - err, len, address);
- - return err;
- - }
- - offset += len;
- - address += len;
- - }
- - if (!err)
- - if (!brcmf_sdio_verifymemory(bus->sdiodev, bus->ci->rambase,
- - (u8 *)fw->data, fw->size))
- - err = -EIO;
- + err = brcmf_sdiod_ramrw(bus->sdiodev, true, bus->ci->rambase,
- + (u8 *)fw->data, fw->size);
- + if (err)
- + brcmf_err("error %d on writing %d membytes at 0x%08x\n",
- + err, (int)fw->size, bus->ci->rambase);
- + else if (!brcmf_sdio_verifymemory(bus->sdiodev, bus->ci->rambase,
- + (u8 *)fw->data, fw->size))
- + err = -EIO;
-
- return err;
- }
-
- static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus,
- - const struct firmware *nv)
- + void *vars, u32 varsz)
- {
- - void *vars;
- - u32 varsz;
- int address;
- int err;
-
- brcmf_dbg(TRACE, "Enter\n");
-
- - vars = brcmf_nvram_strip(nv, &varsz);
- -
- - if (vars == NULL)
- - return -EINVAL;
- -
- address = bus->ci->ramsize - varsz + bus->ci->rambase;
- err = brcmf_sdiod_ramrw(bus->sdiodev, true, address, vars, varsz);
- if (err)
- @@ -3277,28 +3278,21 @@
- else if (!brcmf_sdio_verifymemory(bus->sdiodev, address, vars, varsz))
- err = -EIO;
-
- - brcmf_nvram_free(vars);
- -
- return err;
- }
-
- -static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus)
- +static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus,
- + const struct firmware *fw,
- + void *nvram, u32 nvlen)
- {
- int bcmerror = -EFAULT;
- - const struct firmware *fw;
- u32 rstvec;
-
- sdio_claim_host(bus->sdiodev->func[1]);
- brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
-
- /* Keep arm in reset */
- - brcmf_sdio_chip_enter_download(bus->sdiodev, bus->ci);
- -
- - fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_BIN);
- - if (fw == NULL) {
- - bcmerror = -ENOENT;
- - goto err;
- - }
- + brcmf_chip_enter_download(bus->ci);
-
- rstvec = get_unaligned_le32(fw->data);
- brcmf_dbg(SDIO, "firmware rstvec: %x\n", rstvec);
- @@ -3307,24 +3301,19 @@
- release_firmware(fw);
- if (bcmerror) {
- brcmf_err("dongle image file download failed\n");
- + brcmf_fw_nvram_free(nvram);
- goto err;
- }
-
- - fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_NVRAM);
- - if (fw == NULL) {
- - bcmerror = -ENOENT;
- - goto err;
- - }
- -
- - bcmerror = brcmf_sdio_download_nvram(bus, fw);
- - release_firmware(fw);
- + bcmerror = brcmf_sdio_download_nvram(bus, nvram, nvlen);
- + brcmf_fw_nvram_free(nvram);
- if (bcmerror) {
- brcmf_err("dongle nvram file download failed\n");
- goto err;
- }
-
- /* Take arm out of reset */
- - if (!brcmf_sdio_chip_exit_download(bus->sdiodev, bus->ci, rstvec)) {
- + if (!brcmf_chip_exit_download(bus->ci, rstvec)) {
- brcmf_err("error getting out of ARM core reset\n");
- goto err;
- }
- @@ -3339,40 +3328,6 @@
- return bcmerror;
- }
-
- -static bool brcmf_sdio_sr_capable(struct brcmf_sdio *bus)
- -{
- - u32 addr, reg, pmu_cc3_mask = ~0;
- - int err;
- -
- - brcmf_dbg(TRACE, "Enter\n");
- -
- - /* old chips with PMU version less than 17 don't support save restore */
- - if (bus->ci->pmurev < 17)
- - return false;
- -
- - switch (bus->ci->chip) {
- - case BCM43241_CHIP_ID:
- - case BCM4335_CHIP_ID:
- - case BCM4339_CHIP_ID:
- - /* read PMU chipcontrol register 3 */
- - addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_addr);
- - brcmf_sdiod_regwl(bus->sdiodev, addr, 3, NULL);
- - addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_data);
- - reg = brcmf_sdiod_regrl(bus->sdiodev, addr, NULL);
- - return (reg & pmu_cc3_mask) != 0;
- - default:
- - addr = CORE_CC_REG(bus->ci->c_inf[0].base, pmucapabilities_ext);
- - reg = brcmf_sdiod_regrl(bus->sdiodev, addr, &err);
- - if ((reg & PCAPEXT_SR_SUPPORTED_MASK) == 0)
- - return false;
- -
- - addr = CORE_CC_REG(bus->ci->c_inf[0].base, retention_ctl);
- - reg = brcmf_sdiod_regrl(bus->sdiodev, addr, NULL);
- - return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK |
- - PMU_RCTL_LOGIC_DISABLE_MASK)) == 0;
- - }
- -}
- -
- static void brcmf_sdio_sr_init(struct brcmf_sdio *bus)
- {
- int err = 0;
- @@ -3424,7 +3379,7 @@
- brcmf_dbg(TRACE, "Enter\n");
-
- /* KSO bit added in SDIO core rev 12 */
- - if (bus->ci->c_inf[1].rev < 12)
- + if (brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV)->rev < 12)
- return 0;
-
- val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, &err);
- @@ -3455,15 +3410,13 @@
- struct brcmf_sdio *bus = sdiodev->bus;
- uint pad_size;
- u32 value;
- - u8 idx;
- int err;
-
- /* the commands below use the terms tx and rx from
- * a device perspective, ie. bus:txglom affects the
- * bus transfers from device to host.
- */
- - idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
- - if (bus->ci->c_inf[idx].rev < 12) {
- + if (brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV)->rev < 12) {
- /* for sdio core rev < 12, disable txgloming */
- value = 0;
- err = brcmf_iovar_data_set(dev, "bus:txglom", &value,
- @@ -3503,97 +3456,6 @@
- return err;
- }
-
- -static int brcmf_sdio_bus_init(struct device *dev)
- -{
- - struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
- - struct brcmf_sdio *bus = sdiodev->bus;
- - int err, ret = 0;
- - u8 saveclk;
- -
- - brcmf_dbg(TRACE, "Enter\n");
- -
- - /* try to download image and nvram to the dongle */
- - if (bus_if->state == BRCMF_BUS_DOWN) {
- - bus->alp_only = true;
- - err = brcmf_sdio_download_firmware(bus);
- - if (err)
- - return err;
- - bus->alp_only = false;
- - }
- -
- - if (!bus->sdiodev->bus_if->drvr)
- - return 0;
- -
- - /* Start the watchdog timer */
- - bus->sdcnt.tickcnt = 0;
- - brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
- -
- - sdio_claim_host(bus->sdiodev->func[1]);
- -
- - /* Make sure backplane clock is on, needed to generate F2 interrupt */
- - brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
- - if (bus->clkstate != CLK_AVAIL)
- - goto exit;
- -
- - /* Force clocks on backplane to be sure F2 interrupt propagates */
- - saveclk = brcmf_sdiod_regrb(bus->sdiodev,
- - SBSDIO_FUNC1_CHIPCLKCSR, &err);
- - if (!err) {
- - brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
- - (saveclk | SBSDIO_FORCE_HT), &err);
- - }
- - if (err) {
- - brcmf_err("Failed to force clock for F2: err %d\n", err);
- - goto exit;
- - }
- -
- - /* Enable function 2 (frame transfers) */
- - w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT,
- - offsetof(struct sdpcmd_regs, tosbmailboxdata));
- - err = sdio_enable_func(bus->sdiodev->func[SDIO_FUNC_2]);
- -
- -
- - brcmf_dbg(INFO, "enable F2: err=%d\n", err);
- -
- - /* If F2 successfully enabled, set core and enable interrupts */
- - if (!err) {
- - /* Set up the interrupt mask and enable interrupts */
- - bus->hostintmask = HOSTINTMASK;
- - w_sdreg32(bus, bus->hostintmask,
- - offsetof(struct sdpcmd_regs, hostintmask));
- -
- - brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_WATERMARK, 8, &err);
- - } else {
- - /* Disable F2 again */
- - sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]);
- - ret = -ENODEV;
- - }
- -
- - if (brcmf_sdio_sr_capable(bus)) {
- - brcmf_sdio_sr_init(bus);
- - } else {
- - /* Restore previous clock setting */
- - brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
- - saveclk, &err);
- - }
- -
- - if (ret == 0) {
- - ret = brcmf_sdiod_intr_register(bus->sdiodev);
- - if (ret != 0)
- - brcmf_err("intr register failed:%d\n", ret);
- - }
- -
- - /* If we didn't come up, turn off backplane clock */
- - if (ret != 0)
- - brcmf_sdio_clkctl(bus, CLK_NONE, false);
- -
- -exit:
- - sdio_release_host(bus->sdiodev->func[1]);
- -
- - return ret;
- -}
- -
- void brcmf_sdio_isr(struct brcmf_sdio *bus)
- {
- brcmf_dbg(TRACE, "Enter\n");
- @@ -3714,11 +3576,175 @@
- datawork);
-
- while (atomic_read(&bus->dpc_tskcnt)) {
- + atomic_set(&bus->dpc_tskcnt, 0);
- brcmf_sdio_dpc(bus);
- - atomic_dec(&bus->dpc_tskcnt);
- }
- }
-
- +static void
- +brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
- + struct brcmf_chip *ci, u32 drivestrength)
- +{
- + const struct sdiod_drive_str *str_tab = NULL;
- + u32 str_mask;
- + u32 str_shift;
- + u32 base;
- + u32 i;
- + u32 drivestrength_sel = 0;
- + u32 cc_data_temp;
- + u32 addr;
- +
- + if (!(ci->cc_caps & CC_CAP_PMU))
- + return;
- +
- + switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
- + case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
- + str_tab = sdiod_drvstr_tab1_1v8;
- + str_mask = 0x00003800;
- + str_shift = 11;
- + break;
- + case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17):
- + str_tab = sdiod_drvstr_tab6_1v8;
- + str_mask = 0x00001800;
- + str_shift = 11;
- + break;
- + case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
- + /* note: 43143 does not support tristate */
- + i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1;
- + if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) {
- + str_tab = sdiod_drvstr_tab2_3v3;
- + str_mask = 0x00000007;
- + str_shift = 0;
- + } else
- + brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
- + ci->name, drivestrength);
- + break;
- + case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13):
- + str_tab = sdiod_drive_strength_tab5_1v8;
- + str_mask = 0x00003800;
- + str_shift = 11;
- + break;
- + default:
- + brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
- + ci->name, ci->chiprev, ci->pmurev);
- + break;
- + }
- +
- + if (str_tab != NULL) {
- + for (i = 0; str_tab[i].strength != 0; i++) {
- + if (drivestrength >= str_tab[i].strength) {
- + drivestrength_sel = str_tab[i].sel;
- + break;
- + }
- + }
- + base = brcmf_chip_get_chipcommon(ci)->base;
- + addr = CORE_CC_REG(base, chipcontrol_addr);
- + brcmf_sdiod_regwl(sdiodev, addr, 1, NULL);
- + cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL);
- + cc_data_temp &= ~str_mask;
- + drivestrength_sel <<= str_shift;
- + cc_data_temp |= drivestrength_sel;
- + brcmf_sdiod_regwl(sdiodev, addr, cc_data_temp, NULL);
- +
- + brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n",
- + str_tab[i].strength, drivestrength, cc_data_temp);
- + }
- +}
- +
- +static int brcmf_sdio_buscoreprep(void *ctx)
- +{
- + struct brcmf_sdio_dev *sdiodev = ctx;
- + int err = 0;
- + u8 clkval, clkset;
- +
- + /* Try forcing SDIO core to do ALPAvail request only */
- + clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
- + brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
- + if (err) {
- + brcmf_err("error writing for HT off\n");
- + return err;
- + }
- +
- + /* If register supported, wait for ALPAvail and then force ALP */
- + /* This may take up to 15 milliseconds */
- + clkval = brcmf_sdiod_regrb(sdiodev,
- + SBSDIO_FUNC1_CHIPCLKCSR, NULL);
- +
- + if ((clkval & ~SBSDIO_AVBITS) != clkset) {
- + brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
- + clkset, clkval);
- + return -EACCES;
- + }
- +
- + SPINWAIT(((clkval = brcmf_sdiod_regrb(sdiodev,
- + SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
- + !SBSDIO_ALPAV(clkval)),
- + PMU_MAX_TRANSITION_DLY);
- + if (!SBSDIO_ALPAV(clkval)) {
- + brcmf_err("timeout on ALPAV wait, clkval 0x%02x\n",
- + clkval);
- + return -EBUSY;
- + }
- +
- + clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
- + brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
- + udelay(65);
- +
- + /* Also, disable the extra SDIO pull-ups */
- + brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
- +
- + return 0;
- +}
- +
- +static void brcmf_sdio_buscore_exitdl(void *ctx, struct brcmf_chip *chip,
- + u32 rstvec)
- +{
- + struct brcmf_sdio_dev *sdiodev = ctx;
- + struct brcmf_core *core;
- + u32 reg_addr;
- +
- + /* clear all interrupts */
- + core = brcmf_chip_get_core(chip, BCMA_CORE_SDIO_DEV);
- + reg_addr = core->base + offsetof(struct sdpcmd_regs, intstatus);
- + brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
- +
- + if (rstvec)
- + /* Write reset vector to address 0 */
- + brcmf_sdiod_ramrw(sdiodev, true, 0, (void *)&rstvec,
- + sizeof(rstvec));
- +}
- +
- +static u32 brcmf_sdio_buscore_read32(void *ctx, u32 addr)
- +{
- + struct brcmf_sdio_dev *sdiodev = ctx;
- + u32 val, rev;
- +
- + val = brcmf_sdiod_regrl(sdiodev, addr, NULL);
- + if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 &&
- + addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
- + rev = (val & CID_REV_MASK) >> CID_REV_SHIFT;
- + if (rev >= 2) {
- + val &= ~CID_ID_MASK;
- + val |= BCM4339_CHIP_ID;
- + }
- + }
- + return val;
- +}
- +
- +static void brcmf_sdio_buscore_write32(void *ctx, u32 addr, u32 val)
- +{
- + struct brcmf_sdio_dev *sdiodev = ctx;
- +
- + brcmf_sdiod_regwl(sdiodev, addr, val, NULL);
- +}
- +
- +static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = {
- + .prepare = brcmf_sdio_buscoreprep,
- + .exit_dl = brcmf_sdio_buscore_exitdl,
- + .read32 = brcmf_sdio_buscore_read32,
- + .write32 = brcmf_sdio_buscore_write32,
- +};
- +
- static bool
- brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
- {
- @@ -3734,7 +3760,7 @@
- brcmf_sdiod_regrl(bus->sdiodev, SI_ENUM_BASE, NULL));
-
- /*
- - * Force PLL off until brcmf_sdio_chip_attach()
- + * Force PLL off until brcmf_chip_attach()
- * programs PLL control regs
- */
-
- @@ -3755,8 +3781,10 @@
- */
- brcmf_bus_change_state(bus->sdiodev->bus_if, BRCMF_BUS_DOWN);
-
- - if (brcmf_sdio_chip_attach(bus->sdiodev, &bus->ci)) {
- - brcmf_err("brcmf_sdio_chip_attach failed!\n");
- + bus->ci = brcmf_chip_attach(bus->sdiodev, &brcmf_sdio_buscore_ops);
- + if (IS_ERR(bus->ci)) {
- + brcmf_err("brcmf_chip_attach failed!\n");
- + bus->ci = NULL;
- goto fail;
- }
-
- @@ -3769,7 +3797,7 @@
- drivestrength = bus->sdiodev->pdata->drive_strength;
- else
- drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH;
- - brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength);
- + brcmf_sdio_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength);
-
- /* Get info on the SOCRAM cores... */
- bus->ramsize = bus->ci->ramsize;
- @@ -3792,24 +3820,18 @@
- goto fail;
-
- /* set PMUControl so a backplane reset does PMU state reload */
- - reg_addr = CORE_CC_REG(bus->ci->c_inf[0].base,
- + reg_addr = CORE_CC_REG(brcmf_chip_get_chipcommon(bus->ci)->base,
- pmucontrol);
- - reg_val = brcmf_sdiod_regrl(bus->sdiodev,
- - reg_addr,
- - &err);
- + reg_val = brcmf_sdiod_regrl(bus->sdiodev, reg_addr, &err);
- if (err)
- goto fail;
-
- reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT);
-
- - brcmf_sdiod_regwl(bus->sdiodev,
- - reg_addr,
- - reg_val,
- - &err);
- + brcmf_sdiod_regwl(bus->sdiodev, reg_addr, reg_val, &err);
- if (err)
- goto fail;
-
- -
- sdio_release_host(bus->sdiodev->func[1]);
-
- brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
- @@ -3849,6 +3871,7 @@
- brcmf_sdio_bus_watchdog(bus);
- /* Count the tick for reference */
- bus->sdcnt.tickcnt++;
- + reinit_completion(&bus->watchdog_wait);
- } else
- break;
- }
- @@ -3872,13 +3895,114 @@
- static struct brcmf_bus_ops brcmf_sdio_bus_ops = {
- .stop = brcmf_sdio_bus_stop,
- .preinit = brcmf_sdio_bus_preinit,
- - .init = brcmf_sdio_bus_init,
- .txdata = brcmf_sdio_bus_txdata,
- .txctl = brcmf_sdio_bus_txctl,
- .rxctl = brcmf_sdio_bus_rxctl,
- .gettxq = brcmf_sdio_bus_gettxq,
- };
-
- +static void brcmf_sdio_firmware_callback(struct device *dev,
- + const struct firmware *code,
- + void *nvram, u32 nvram_len)
- +{
- + struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
- + struct brcmf_sdio *bus = sdiodev->bus;
- + int err = 0;
- + u8 saveclk;
- +
- + brcmf_dbg(TRACE, "Enter: dev=%s\n", dev_name(dev));
- +
- + /* try to download image and nvram to the dongle */
- + if (bus_if->state == BRCMF_BUS_DOWN) {
- + bus->alp_only = true;
- + err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len);
- + if (err)
- + goto fail;
- + bus->alp_only = false;
- + }
- +
- + if (!bus_if->drvr)
- + return;
- +
- + /* Start the watchdog timer */
- + bus->sdcnt.tickcnt = 0;
- + brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
- +
- + sdio_claim_host(sdiodev->func[1]);
- +
- + /* Make sure backplane clock is on, needed to generate F2 interrupt */
- + brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
- + if (bus->clkstate != CLK_AVAIL)
- + goto release;
- +
- + /* Force clocks on backplane to be sure F2 interrupt propagates */
- + saveclk = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, &err);
- + if (!err) {
- + brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
- + (saveclk | SBSDIO_FORCE_HT), &err);
- + }
- + if (err) {
- + brcmf_err("Failed to force clock for F2: err %d\n", err);
- + goto release;
- + }
- +
- + /* Enable function 2 (frame transfers) */
- + w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT,
- + offsetof(struct sdpcmd_regs, tosbmailboxdata));
- + err = sdio_enable_func(sdiodev->func[SDIO_FUNC_2]);
- +
- +
- + brcmf_dbg(INFO, "enable F2: err=%d\n", err);
- +
- + /* If F2 successfully enabled, set core and enable interrupts */
- + if (!err) {
- + /* Set up the interrupt mask and enable interrupts */
- + bus->hostintmask = HOSTINTMASK;
- + w_sdreg32(bus, bus->hostintmask,
- + offsetof(struct sdpcmd_regs, hostintmask));
- +
- + brcmf_sdiod_regwb(sdiodev, SBSDIO_WATERMARK, 8, &err);
- + } else {
- + /* Disable F2 again */
- + sdio_disable_func(sdiodev->func[SDIO_FUNC_2]);
- + goto release;
- + }
- +
- + if (brcmf_chip_sr_capable(bus->ci)) {
- + brcmf_sdio_sr_init(bus);
- + } else {
- + /* Restore previous clock setting */
- + brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
- + saveclk, &err);
- + }
- +
- + if (err == 0) {
- + err = brcmf_sdiod_intr_register(sdiodev);
- + if (err != 0)
- + brcmf_err("intr register failed:%d\n", err);
- + }
- +
- + /* If we didn't come up, turn off backplane clock */
- + if (err != 0)
- + brcmf_sdio_clkctl(bus, CLK_NONE, false);
- +
- + sdio_release_host(sdiodev->func[1]);
- +
- + err = brcmf_bus_start(dev);
- + if (err != 0) {
- + brcmf_err("dongle is not responding\n");
- + goto fail;
- + }
- + return;
- +
- +release:
- + sdio_release_host(sdiodev->func[1]);
- +fail:
- + brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err);
- + device_release_driver(dev);
- +}
- +
- struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
- {
- int ret;
- @@ -3925,7 +4049,8 @@
- }
-
- spin_lock_init(&bus->rxctl_lock);
- - spin_lock_init(&bus->txqlock);
- + spin_lock_init(&bus->txq_lock);
- + sema_init(&bus->tx_seq_lock, 1);
- init_waitqueue_head(&bus->ctrl_wait);
- init_waitqueue_head(&bus->dcmd_resp_wait);
-
- @@ -3961,8 +4086,13 @@
- goto fail;
- }
-
- + /* Query the F2 block size, set roundup accordingly */
- + bus->blocksize = bus->sdiodev->func[2]->cur_blksize;
- + bus->roundup = min(max_roundup, bus->blocksize);
- +
- /* Allocate buffers */
- if (bus->sdiodev->bus_if->maxctl) {
- + bus->sdiodev->bus_if->maxctl += bus->roundup;
- bus->rxblen =
- roundup((bus->sdiodev->bus_if->maxctl + SDPCM_HDRLEN),
- ALIGNMENT) + bus->head_align;
- @@ -3990,10 +4120,6 @@
- bus->idletime = BRCMF_IDLE_INTERVAL;
- bus->idleclock = BRCMF_IDLE_ACTIVE;
-
- - /* Query the F2 block size, set roundup accordingly */
- - bus->blocksize = bus->sdiodev->func[2]->cur_blksize;
- - bus->roundup = min(max_roundup, bus->blocksize);
- -
- /* SR state */
- bus->sleeping = false;
- bus->sr_enabled = false;
- @@ -4001,10 +4127,14 @@
- brcmf_sdio_debugfs_create(bus);
- brcmf_dbg(INFO, "completed!!\n");
-
- - /* if firmware path present try to download and bring up bus */
- - ret = brcmf_bus_start(bus->sdiodev->dev);
- + ret = brcmf_fw_get_firmwares(sdiodev->dev, BRCMF_FW_REQUEST_NVRAM,
- + brcmf_sdio_get_fwname(bus->ci,
- + BRCMF_FIRMWARE_BIN),
- + brcmf_sdio_get_fwname(bus->ci,
- + BRCMF_FIRMWARE_NVRAM),
- + brcmf_sdio_firmware_callback);
- if (ret != 0) {
- - brcmf_err("dongle is not responding\n");
- + brcmf_err("async firmware request failed: %d\n", ret);
- goto fail;
- }
-
- @@ -4024,14 +4154,12 @@
- /* De-register interrupt handler */
- brcmf_sdiod_intr_unregister(bus->sdiodev);
-
- + brcmf_detach(bus->sdiodev->dev);
- +
- cancel_work_sync(&bus->datawork);
- if (bus->brcmf_wq)
- destroy_workqueue(bus->brcmf_wq);
-
- - if (bus->sdiodev->bus_if->drvr) {
- - brcmf_detach(bus->sdiodev->dev);
- - }
- -
- if (bus->ci) {
- if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) {
- sdio_claim_host(bus->sdiodev->func[1]);
- @@ -4042,12 +4170,11 @@
- * all necessary cores.
- */
- msleep(20);
- - brcmf_sdio_chip_enter_download(bus->sdiodev,
- - bus->ci);
- + brcmf_chip_enter_download(bus->ci);
- brcmf_sdio_clkctl(bus, CLK_NONE, false);
- sdio_release_host(bus->sdiodev->func[1]);
- }
- - brcmf_sdio_chip_detach(&bus->ci);
- + brcmf_chip_detach(bus->ci);
- }
-
- kfree(bus->rxbuf);
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/firmware.c linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/firmware.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/firmware.c 2015-03-08 14:27:37.697684500 -0500
- @@ -0,0 +1,332 @@
- +/*
- + * Copyright (c) 2013 Broadcom Corporation
- + *
- + * Permission to use, copy, modify, and/or distribute this software for any
- + * purpose with or without fee is hereby granted, provided that the above
- + * copyright notice and this permission notice appear in all copies.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- + */
- +
- +#include <linux/kernel.h>
- +#include <linux/slab.h>
- +#include <linux/device.h>
- +#include <linux/firmware.h>
- +
- +#include "dhd_dbg.h"
- +#include "firmware.h"
- +
- +enum nvram_parser_state {
- + IDLE,
- + KEY,
- + VALUE,
- + COMMENT,
- + END
- +};
- +
- +/**
- + * struct nvram_parser - internal info for parser.
- + *
- + * @state: current parser state.
- + * @fwnv: input buffer being parsed.
- + * @nvram: output buffer with parse result.
- + * @nvram_len: lenght of parse result.
- + * @line: current line.
- + * @column: current column in line.
- + * @pos: byte offset in input buffer.
- + * @entry: start position of key,value entry.
- + */
- +struct nvram_parser {
- + enum nvram_parser_state state;
- + const struct firmware *fwnv;
- + u8 *nvram;
- + u32 nvram_len;
- + u32 line;
- + u32 column;
- + u32 pos;
- + u32 entry;
- +};
- +
- +static bool is_nvram_char(char c)
- +{
- + /* comment marker excluded */
- + if (c == '#')
- + return false;
- +
- + /* key and value may have any other readable character */
- + return (c > 0x20 && c < 0x7f);
- +}
- +
- +static bool is_whitespace(char c)
- +{
- + return (c == ' ' || c == '\r' || c == '\n' || c == '\t');
- +}
- +
- +static enum nvram_parser_state brcmf_nvram_handle_idle(struct nvram_parser *nvp)
- +{
- + char c;
- +
- + c = nvp->fwnv->data[nvp->pos];
- + if (c == '\n')
- + return COMMENT;
- + if (is_whitespace(c))
- + goto proceed;
- + if (c == '#')
- + return COMMENT;
- + if (is_nvram_char(c)) {
- + nvp->entry = nvp->pos;
- + return KEY;
- + }
- + brcmf_dbg(INFO, "warning: ln=%d:col=%d: ignoring invalid character\n",
- + nvp->line, nvp->column);
- +proceed:
- + nvp->column++;
- + nvp->pos++;
- + return IDLE;
- +}
- +
- +static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
- +{
- + enum nvram_parser_state st = nvp->state;
- + char c;
- +
- + c = nvp->fwnv->data[nvp->pos];
- + if (c == '=') {
- + st = VALUE;
- + } else if (!is_nvram_char(c)) {
- + brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
- + nvp->line, nvp->column);
- + return COMMENT;
- + }
- +
- + nvp->column++;
- + nvp->pos++;
- + return st;
- +}
- +
- +static enum nvram_parser_state
- +brcmf_nvram_handle_value(struct nvram_parser *nvp)
- +{
- + char c;
- + char *skv;
- + char *ekv;
- + u32 cplen;
- +
- + c = nvp->fwnv->data[nvp->pos];
- + if (!is_nvram_char(c)) {
- + /* key,value pair complete */
- + ekv = (u8 *)&nvp->fwnv->data[nvp->pos];
- + skv = (u8 *)&nvp->fwnv->data[nvp->entry];
- + cplen = ekv - skv;
- + /* copy to output buffer */
- + memcpy(&nvp->nvram[nvp->nvram_len], skv, cplen);
- + nvp->nvram_len += cplen;
- + nvp->nvram[nvp->nvram_len] = '\0';
- + nvp->nvram_len++;
- + return IDLE;
- + }
- + nvp->pos++;
- + nvp->column++;
- + return VALUE;
- +}
- +
- +static enum nvram_parser_state
- +brcmf_nvram_handle_comment(struct nvram_parser *nvp)
- +{
- + char *eol, *sol;
- +
- + sol = (char *)&nvp->fwnv->data[nvp->pos];
- + eol = strchr(sol, '\n');
- + if (eol == NULL)
- + return END;
- +
- + /* eat all moving to next line */
- + nvp->line++;
- + nvp->column = 1;
- + nvp->pos += (eol - sol) + 1;
- + return IDLE;
- +}
- +
- +static enum nvram_parser_state brcmf_nvram_handle_end(struct nvram_parser *nvp)
- +{
- + /* final state */
- + return END;
- +}
- +
- +static enum nvram_parser_state
- +(*nv_parser_states[])(struct nvram_parser *nvp) = {
- + brcmf_nvram_handle_idle,
- + brcmf_nvram_handle_key,
- + brcmf_nvram_handle_value,
- + brcmf_nvram_handle_comment,
- + brcmf_nvram_handle_end
- +};
- +
- +static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
- + const struct firmware *nv)
- +{
- + memset(nvp, 0, sizeof(*nvp));
- + nvp->fwnv = nv;
- + /* Alloc for extra 0 byte + roundup by 4 + length field */
- + nvp->nvram = kzalloc(nv->size + 1 + 3 + sizeof(u32), GFP_KERNEL);
- + if (!nvp->nvram)
- + return -ENOMEM;
- +
- + nvp->line = 1;
- + nvp->column = 1;
- + return 0;
- +}
- +
- +/* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a fil
- + * and ending in a NUL. Removes carriage returns, empty lines, comment lines,
- + * and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
- + * End of buffer is completed with token identifying length of buffer.
- + */
- +static void *brcmf_fw_nvram_strip(const struct firmware *nv, u32 *new_length)
- +{
- + struct nvram_parser nvp;
- + u32 pad;
- + u32 token;
- + __le32 token_le;
- +
- + if (brcmf_init_nvram_parser(&nvp, nv) < 0)
- + return NULL;
- +
- + while (nvp.pos < nv->size) {
- + nvp.state = nv_parser_states[nvp.state](&nvp);
- + if (nvp.state == END)
- + break;
- + }
- + pad = nvp.nvram_len;
- + *new_length = roundup(nvp.nvram_len + 1, 4);
- + while (pad != *new_length) {
- + nvp.nvram[pad] = 0;
- + pad++;
- + }
- +
- + token = *new_length / 4;
- + token = (~token << 16) | (token & 0x0000FFFF);
- + token_le = cpu_to_le32(token);
- +
- + memcpy(&nvp.nvram[*new_length], &token_le, sizeof(token_le));
- + *new_length += sizeof(token_le);
- +
- + return nvp.nvram;
- +}
- +
- +void brcmf_fw_nvram_free(void *nvram)
- +{
- + kfree(nvram);
- +}
- +
- +struct brcmf_fw {
- + struct device *dev;
- + u16 flags;
- + const struct firmware *code;
- + const char *nvram_name;
- + void (*done)(struct device *dev, const struct firmware *fw,
- + void *nvram_image, u32 nvram_len);
- +};
- +
- +static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
- +{
- + struct brcmf_fw *fwctx = ctx;
- + u32 nvram_length = 0;
- + void *nvram = NULL;
- +
- + brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
- + if (!fw && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
- + goto fail;
- +
- + if (fw) {
- + nvram = brcmf_fw_nvram_strip(fw, &nvram_length);
- + release_firmware(fw);
- + if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
- + goto fail;
- + }
- +
- + fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length);
- + kfree(fwctx);
- + return;
- +
- +fail:
- + brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
- + if (fwctx->code)
- + release_firmware(fwctx->code);
- + device_release_driver(fwctx->dev);
- + kfree(fwctx);
- +}
- +
- +static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)
- +{
- + struct brcmf_fw *fwctx = ctx;
- + int ret;
- +
- + brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
- + if (!fw)
- + goto fail;
- +
- + /* only requested code so done here */
- + if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) {
- + fwctx->done(fwctx->dev, fw, NULL, 0);
- + kfree(fwctx);
- + return;
- + }
- + fwctx->code = fw;
- + ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
- + fwctx->dev, GFP_KERNEL, fwctx,
- + brcmf_fw_request_nvram_done);
- +
- + if (!ret)
- + return;
- +
- + /* when nvram is optional call .done() callback here */
- + if (fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL) {
- + fwctx->done(fwctx->dev, fw, NULL, 0);
- + kfree(fwctx);
- + return;
- + }
- +
- + /* failed nvram request */
- + release_firmware(fw);
- +fail:
- + brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
- + device_release_driver(fwctx->dev);
- + kfree(fwctx);
- +}
- +
- +int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
- + const char *code, const char *nvram,
- + void (*fw_cb)(struct device *dev,
- + const struct firmware *fw,
- + void *nvram_image, u32 nvram_len))
- +{
- + struct brcmf_fw *fwctx;
- +
- + brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
- + if (!fw_cb || !code)
- + return -EINVAL;
- +
- + if ((flags & BRCMF_FW_REQUEST_NVRAM) && !nvram)
- + return -EINVAL;
- +
- + fwctx = kzalloc(sizeof(*fwctx), GFP_KERNEL);
- + if (!fwctx)
- + return -ENOMEM;
- +
- + fwctx->dev = dev;
- + fwctx->flags = flags;
- + fwctx->done = fw_cb;
- + if (flags & BRCMF_FW_REQUEST_NVRAM)
- + fwctx->nvram_name = nvram;
- +
- + return request_firmware_nowait(THIS_MODULE, true, code, dev,
- + GFP_KERNEL, fwctx,
- + brcmf_fw_request_code_done);
- +}
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/firmware.h linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/firmware.h
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/firmware.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/firmware.h 2015-03-08 14:27:37.697684500 -0500
- @@ -0,0 +1,36 @@
- +/*
- + * Copyright (c) 2013 Broadcom Corporation
- + *
- + * Permission to use, copy, modify, and/or distribute this software for any
- + * purpose with or without fee is hereby granted, provided that the above
- + * copyright notice and this permission notice appear in all copies.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- + */
- +#ifndef BRCMFMAC_FIRMWARE_H
- +#define BRCMFMAC_FIRMWARE_H
- +
- +#define BRCMF_FW_REQUEST 0x000F
- +#define BRCMF_FW_REQUEST_NVRAM 0x0001
- +#define BRCMF_FW_REQ_FLAGS 0x00F0
- +#define BRCMF_FW_REQ_NV_OPTIONAL 0x0010
- +
- +void brcmf_fw_nvram_free(void *nvram);
- +/*
- + * Request firmware(s) asynchronously. When the asynchronous request
- + * fails it will not use the callback, but call device_release_driver()
- + * instead which will call the driver .remove() callback.
- + */
- +int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
- + const char *code, const char *nvram,
- + void (*fw_cb)(struct device *dev,
- + const struct firmware *fw,
- + void *nvram_image, u32 nvram_len));
- +
- +#endif /* BRCMFMAC_FIRMWARE_H */
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/fwil.c linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/fwil.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/fwil.c 2015-03-08 14:27:37.697684500 -0500
- @@ -54,7 +54,7 @@
- if (err >= 0)
- err = 0;
- else
- - brcmf_err("Failed err=%d\n", err);
- + brcmf_dbg(FIL, "Failed err=%d\n", err);
-
- return err;
- }
- @@ -124,7 +124,8 @@
- }
-
- static u32
- -brcmf_create_iovar(char *name, char *data, u32 datalen, char *buf, u32 buflen)
- +brcmf_create_iovar(char *name, const char *data, u32 datalen,
- + char *buf, u32 buflen)
- {
- u32 len;
-
- @@ -144,7 +145,7 @@
-
-
- s32
- -brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
- +brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data,
- u32 len)
- {
- struct brcmf_pub *drvr = ifp->drvr;
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/fwil.h linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/fwil.h
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/fwil.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/fwil.h 2015-03-08 14:27:37.697684500 -0500
- @@ -83,7 +83,7 @@
- s32 brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data);
- s32 brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data);
-
- -s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
- +s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data,
- u32 len);
- s32 brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
- u32 len);
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h 2015-03-08 14:27:37.697684500 -0500
- @@ -48,6 +48,19 @@
-
- #define BRCMF_MAXRATES_IN_SET 16 /* max # of rates in rateset */
-
- +/* OBSS Coex Auto/On/Off */
- +#define BRCMF_OBSS_COEX_AUTO (-1)
- +#define BRCMF_OBSS_COEX_OFF 0
- +#define BRCMF_OBSS_COEX_ON 1
- +
- +/* join preference types for join_pref iovar */
- +enum brcmf_join_pref_types {
- + BRCMF_JOIN_PREF_RSSI = 1,
- + BRCMF_JOIN_PREF_WPA,
- + BRCMF_JOIN_PREF_BAND,
- + BRCMF_JOIN_PREF_RSSI_DELTA,
- +};
- +
- enum brcmf_fil_p2p_if_types {
- BRCMF_FIL_P2P_IF_CLIENT,
- BRCMF_FIL_P2P_IF_GO,
- @@ -87,6 +100,11 @@
- __le32 enable;
- };
-
- +struct brcmf_fil_bwcap_le {
- + __le32 band;
- + __le32 bw_cap;
- +};
- +
- /**
- * struct tdls_iovar - common structure for tdls iovars.
- *
- @@ -272,6 +290,22 @@
- __le16 chanspec_list[1];
- };
-
- +/**
- + * struct join_pref params - parameters for preferred join selection.
- + *
- + * @type: preference type (see enum brcmf_join_pref_types).
- + * @len: length of bytes following (currently always 2).
- + * @rssi_gain: signal gain for selection (only when @type is RSSI_DELTA).
- + * @band: band to which selection preference applies.
- + * This is used if @type is BAND or RSSI_DELTA.
- + */
- +struct brcmf_join_pref_params {
- + u8 type;
- + u8 len;
- + u8 rssi_gain;
- + u8 band;
- +};
- +
- /* used for join with or without a specific bssid and channel list */
- struct brcmf_join_params {
- struct brcmf_ssid_le ssid_le;
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c 2015-03-08 14:27:37.697684500 -0500
- @@ -476,6 +476,7 @@
- bool bus_flow_blocked;
- bool creditmap_received;
- u8 mode;
- + bool avoid_queueing;
- };
-
- /*
- @@ -1369,13 +1370,12 @@
- }
-
- static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
- - struct sk_buff *skb, u32 genbit,
- - u16 seq)
- + struct sk_buff *skb, u8 ifidx,
- + u32 genbit, u16 seq)
- {
- struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
- u32 hslot;
- int ret;
- - u8 ifidx;
-
- hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
-
- @@ -1389,29 +1389,21 @@
-
- entry->generation = genbit;
-
- - ret = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
- - if (ret == 0) {
- - brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit);
- - brcmf_skbcb(skb)->htod_seq = seq;
- - if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) {
- - brcmf_skb_htod_seq_set_field(skb, FROMDRV, 1);
- - brcmf_skb_htod_seq_set_field(skb, FROMFW, 0);
- - } else {
- - brcmf_skb_htod_seq_set_field(skb, FROMDRV, 0);
- - }
- - ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo,
- - skb);
- + brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit);
- + brcmf_skbcb(skb)->htod_seq = seq;
- + if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) {
- + brcmf_skb_htod_seq_set_field(skb, FROMDRV, 1);
- + brcmf_skb_htod_seq_set_field(skb, FROMFW, 0);
- + } else {
- + brcmf_skb_htod_seq_set_field(skb, FROMDRV, 0);
- }
- + ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, skb);
-
- if (ret != 0) {
- - /* suppress q is full or hdrpull failed, drop this packet */
- - brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
- - true);
- + /* suppress q is full drop this packet */
- + brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, true);
- } else {
- - /*
- - * Mark suppressed to avoid a double free during
- - * wlfc cleanup
- - */
- + /* Mark suppressed to avoid a double free during wlfc cleanup */
- brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot);
- }
-
- @@ -1428,6 +1420,7 @@
- struct sk_buff *skb;
- struct brcmf_skbuff_cb *skcb;
- struct brcmf_fws_mac_descriptor *entry = NULL;
- + u8 ifidx;
-
- brcmf_dbg(DATA, "flags %d\n", flags);
-
- @@ -1476,12 +1469,15 @@
- }
- brcmf_fws_macdesc_return_req_credit(skb);
-
- + if (brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb)) {
- + brcmu_pkt_buf_free_skb(skb);
- + return -EINVAL;
- + }
- if (!remove_from_hanger)
- - ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit,
- - seq);
- -
- + ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifidx,
- + genbit, seq);
- if (remove_from_hanger || ret)
- - brcmf_txfinalize(fws->drvr, skb, true);
- + brcmf_txfinalize(fws->drvr, skb, ifidx, true);
-
- return 0;
- }
- @@ -1868,7 +1864,7 @@
- struct ethhdr *eh = (struct ethhdr *)(skb->data);
- int fifo = BRCMF_FWS_FIFO_BCMC;
- bool multicast = is_multicast_ether_addr(eh->h_dest);
- - bool pae = eh->h_proto == htons(ETH_P_PAE);
- + int rc = 0;
-
- brcmf_dbg(DATA, "tx proto=0x%X\n", ntohs(eh->h_proto));
- /* determine the priority */
- @@ -1876,8 +1872,13 @@
- skb->priority = cfg80211_classify8021d(skb, NULL);
-
- drvr->tx_multicast += !!multicast;
- - if (pae)
- - atomic_inc(&ifp->pend_8021x_cnt);
- +
- + if (fws->avoid_queueing) {
- + rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb);
- + if (rc < 0)
- + brcmf_txfinalize(drvr, skb, ifp->ifidx, false);
- + return rc;
- + }
-
- /* set control buffer information */
- skcb->if_flags = 0;
- @@ -1899,15 +1900,12 @@
- brcmf_fws_schedule_deq(fws);
- } else {
- brcmf_err("drop skb: no hanger slot\n");
- - if (pae) {
- - atomic_dec(&ifp->pend_8021x_cnt);
- - if (waitqueue_active(&ifp->pend_8021x_wait))
- - wake_up(&ifp->pend_8021x_wait);
- - }
- - brcmu_pkt_buf_free_skb(skb);
- + brcmf_txfinalize(drvr, skb, ifp->ifidx, false);
- + rc = -ENOMEM;
- }
- brcmf_fws_unlock(fws);
- - return 0;
- +
- + return rc;
- }
-
- void brcmf_fws_reset_interface(struct brcmf_if *ifp)
- @@ -1982,7 +1980,8 @@
- ret = brcmf_proto_txdata(drvr, ifidx, 0, skb);
- brcmf_fws_lock(fws);
- if (ret < 0)
- - brcmf_txfinalize(drvr, skb, false);
- + brcmf_txfinalize(drvr, skb, ifidx,
- + false);
- if (fws->bus_flow_blocked)
- break;
- }
- @@ -2039,6 +2038,13 @@
- fws->drvr = drvr;
- fws->fcmode = fcmode;
-
- + if ((drvr->bus_if->always_use_fws_queue == false) &&
- + (fcmode == BRCMF_FWS_FCMODE_NONE)) {
- + fws->avoid_queueing = true;
- + brcmf_dbg(INFO, "FWS queueing will be avoided\n");
- + return 0;
- + }
- +
- fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq");
- if (fws->fws_wq == NULL) {
- brcmf_err("workqueue creation failed\n");
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/Makefile linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/Makefile
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/Makefile 2015-03-08 14:27:37.697684500 -0500
- @@ -24,6 +24,7 @@
- obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
- brcmfmac-objs += \
- wl_cfg80211.o \
- + chip.o \
- fwil.o \
- fweh.o \
- fwsignal.o \
- @@ -32,12 +33,11 @@
- bcdc.o \
- dhd_common.o \
- dhd_linux.o \
- - nvram.o \
- + firmware.o \
- btcoex.o
- brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
- dhd_sdio.o \
- - bcmsdh.o \
- - sdio_chip.o
- + bcmsdh.o
- brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
- usb.o
- brcmfmac-$(CONFIG_BRCMDBG) += \
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/nvram.c linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/nvram.c
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/nvram.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/nvram.c 1969-12-31 18:00:00.000000000 -0600
- @@ -1,94 +0,0 @@
- -/*
- - * Copyright (c) 2013 Broadcom Corporation
- - *
- - * Permission to use, copy, modify, and/or distribute this software for any
- - * purpose with or without fee is hereby granted, provided that the above
- - * copyright notice and this permission notice appear in all copies.
- - *
- - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- - */
- -
- -#include <linux/kernel.h>
- -#include <linux/slab.h>
- -#include <linux/firmware.h>
- -
- -#include "nvram.h"
- -
- -/* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a file
- - * and ending in a NUL. Removes carriage returns, empty lines, comment lines,
- - * and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
- - * End of buffer is completed with token identifying length of buffer.
- - */
- -void *brcmf_nvram_strip(const struct firmware *nv, u32 *new_length)
- -{
- - u8 *nvram;
- - u32 i;
- - u32 len;
- - u32 column;
- - u8 val;
- - bool comment;
- - u32 token;
- - __le32 token_le;
- -
- - /* Alloc for extra 0 byte + roundup by 4 + length field */
- - nvram = kmalloc(nv->size + 1 + 3 + sizeof(token_le), GFP_KERNEL);
- - if (!nvram)
- - return NULL;
- -
- - len = 0;
- - column = 0;
- - comment = false;
- - for (i = 0; i < nv->size; i++) {
- - val = nv->data[i];
- - if (val == 0)
- - break;
- - if (val == '\r')
- - continue;
- - if (comment && (val != '\n'))
- - continue;
- - comment = false;
- - if (val == '#') {
- - comment = true;
- - continue;
- - }
- - if (val == '\n') {
- - if (column == 0)
- - continue;
- - nvram[len] = 0;
- - len++;
- - column = 0;
- - continue;
- - }
- - nvram[len] = val;
- - len++;
- - column++;
- - }
- - column = len;
- - *new_length = roundup(len + 1, 4);
- - while (column != *new_length) {
- - nvram[column] = 0;
- - column++;
- - }
- -
- - token = *new_length / 4;
- - token = (~token << 16) | (token & 0x0000FFFF);
- - token_le = cpu_to_le32(token);
- -
- - memcpy(&nvram[*new_length], &token_le, sizeof(token_le));
- - *new_length += sizeof(token_le);
- -
- - return nvram;
- -}
- -
- -void brcmf_nvram_free(void *nvram)
- -{
- - kfree(nvram);
- -}
- -
- -
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/nvram.h linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/nvram.h
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/nvram.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/nvram.h 1969-12-31 18:00:00.000000000 -0600
- @@ -1,24 +0,0 @@
- -/*
- - * Copyright (c) 2013 Broadcom Corporation
- - *
- - * Permission to use, copy, modify, and/or distribute this software for any
- - * purpose with or without fee is hereby granted, provided that the above
- - * copyright notice and this permission notice appear in all copies.
- - *
- - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- - */
- -#ifndef BRCMFMAC_NVRAM_H
- -#define BRCMFMAC_NVRAM_H
- -
- -
- -void *brcmf_nvram_strip(const struct firmware *nv, u32 *new_length);
- -void brcmf_nvram_free(void *nvram);
- -
- -
- -#endif /* BRCMFMAC_NVRAM_H */
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/p2p.c linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/p2p.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/p2p.c 2015-03-08 14:27:37.697684500 -0500
- @@ -797,7 +797,8 @@
- /* SOCIAL CHANNELS 1, 6, 11 */
- search_state = WL_P2P_DISC_ST_SEARCH;
- brcmf_dbg(INFO, "P2P SEARCH PHASE START\n");
- - } else if (dev != NULL && vif->mode == WL_MODE_AP) {
- + } else if (dev != NULL &&
- + vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) {
- /* If you are already a GO, then do SEARCH only */
- brcmf_dbg(INFO, "Already a GO. Do SEARCH Only\n");
- search_state = WL_P2P_DISC_ST_SEARCH;
- @@ -2256,7 +2257,6 @@
- struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
- struct brcmf_cfg80211_vif *vif;
- enum brcmf_fil_p2p_if_types iftype;
- - enum wl_mode mode;
- int err;
-
- if (brcmf_cfg80211_vif_event_armed(cfg))
- @@ -2267,11 +2267,9 @@
- switch (type) {
- case NL80211_IFTYPE_P2P_CLIENT:
- iftype = BRCMF_FIL_P2P_IF_CLIENT;
- - mode = WL_MODE_BSS;
- break;
- case NL80211_IFTYPE_P2P_GO:
- iftype = BRCMF_FIL_P2P_IF_GO;
- - mode = WL_MODE_AP;
- break;
- case NL80211_IFTYPE_P2P_DEVICE:
- return brcmf_p2p_create_p2pdev(&cfg->p2p, wiphy,
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c 1969-12-31 18:00:00.000000000 -0600
- @@ -1,973 +0,0 @@
- -/*
- - * Copyright (c) 2011 Broadcom Corporation
- - *
- - * Permission to use, copy, modify, and/or distribute this software for any
- - * purpose with or without fee is hereby granted, provided that the above
- - * copyright notice and this permission notice appear in all copies.
- - *
- - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- - */
- -/* ***** SDIO interface chip backplane handle functions ***** */
- -
- -#include <linux/types.h>
- -#include <linux/netdevice.h>
- -#include <linux/mmc/card.h>
- -#include <linux/mmc/sdio_func.h>
- -#include <linux/mmc/sdio_ids.h>
- -#include <linux/ssb/ssb_regs.h>
- -#include <linux/bcma/bcma.h>
- -
- -#include <chipcommon.h>
- -#include <brcm_hw_ids.h>
- -#include <brcmu_wifi.h>
- -#include <brcmu_utils.h>
- -#include <soc.h>
- -#include "dhd_dbg.h"
- -#include "sdio_host.h"
- -#include "sdio_chip.h"
- -
- -/* chip core base & ramsize */
- -/* bcm4329 */
- -/* SDIO device core, ID 0x829 */
- -#define BCM4329_CORE_BUS_BASE 0x18011000
- -/* internal memory core, ID 0x80e */
- -#define BCM4329_CORE_SOCRAM_BASE 0x18003000
- -/* ARM Cortex M3 core, ID 0x82a */
- -#define BCM4329_CORE_ARM_BASE 0x18002000
- -#define BCM4329_RAMSIZE 0x48000
- -
- -/* bcm43143 */
- -/* SDIO device core */
- -#define BCM43143_CORE_BUS_BASE 0x18002000
- -/* internal memory core */
- -#define BCM43143_CORE_SOCRAM_BASE 0x18004000
- -/* ARM Cortex M3 core, ID 0x82a */
- -#define BCM43143_CORE_ARM_BASE 0x18003000
- -#define BCM43143_RAMSIZE 0x70000
- -
- -/* All D11 cores, ID 0x812 */
- -#define BCM43xx_CORE_D11_BASE 0x18001000
- -
- -#define SBCOREREV(sbidh) \
- - ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
- - ((sbidh) & SSB_IDHIGH_RCLO))
- -
- -/* SOC Interconnect types (aka chip types) */
- -#define SOCI_SB 0
- -#define SOCI_AI 1
- -
- -/* EROM CompIdentB */
- -#define CIB_REV_MASK 0xff000000
- -#define CIB_REV_SHIFT 24
- -
- -/* ARM CR4 core specific control flag bits */
- -#define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020
- -
- -/* D11 core specific control flag bits */
- -#define D11_BCMA_IOCTL_PHYCLOCKEN 0x0004
- -#define D11_BCMA_IOCTL_PHYRESET 0x0008
- -
- -#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
- -/* SDIO Pad drive strength to select value mappings */
- -struct sdiod_drive_str {
- - u8 strength; /* Pad Drive Strength in mA */
- - u8 sel; /* Chip-specific select value */
- -};
- -/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */
- -static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = {
- - {32, 0x6},
- - {26, 0x7},
- - {22, 0x4},
- - {16, 0x5},
- - {12, 0x2},
- - {8, 0x3},
- - {4, 0x0},
- - {0, 0x1}
- -};
- -
- -/* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */
- -static const struct sdiod_drive_str sdiod_drive_strength_tab5_1v8[] = {
- - {6, 0x7},
- - {5, 0x6},
- - {4, 0x5},
- - {3, 0x4},
- - {2, 0x2},
- - {1, 0x1},
- - {0, 0x0}
- -};
- -
- -/* SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */
- -static const struct sdiod_drive_str sdiod_drvstr_tab6_1v8[] = {
- - {3, 0x3},
- - {2, 0x2},
- - {1, 0x1},
- - {0, 0x0} };
- -
- -/* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */
- -static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = {
- - {16, 0x7},
- - {12, 0x5},
- - {8, 0x3},
- - {4, 0x1}
- -};
- -
- -u8
- -brcmf_sdio_chip_getinfidx(struct brcmf_chip *ci, u16 coreid)
- -{
- - u8 idx;
- -
- - for (idx = 0; idx < BRCMF_MAX_CORENUM; idx++)
- - if (coreid == ci->c_inf[idx].id)
- - return idx;
- -
- - return BRCMF_MAX_CORENUM;
- -}
- -
- -static u32
- -brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci, u16 coreid)
- -{
- - u32 regdata;
- - u8 idx;
- -
- - idx = brcmf_sdio_chip_getinfidx(ci, coreid);
- -
- - regdata = brcmf_sdiod_regrl(sdiodev,
- - CORE_SB(ci->c_inf[idx].base, sbidhigh),
- - NULL);
- - return SBCOREREV(regdata);
- -}
- -
- -static u32
- -brcmf_sdio_ai_corerev(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci, u16 coreid)
- -{
- - u8 idx;
- -
- - idx = brcmf_sdio_chip_getinfidx(ci, coreid);
- -
- - return (ci->c_inf[idx].cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
- -}
- -
- -static bool
- -brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci, u16 coreid)
- -{
- - u32 regdata;
- - u8 idx;
- -
- - idx = brcmf_sdio_chip_getinfidx(ci, coreid);
- - if (idx == BRCMF_MAX_CORENUM)
- - return false;
- -
- - regdata = brcmf_sdiod_regrl(sdiodev,
- - CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
- - NULL);
- - regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
- - SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
- - return (SSB_TMSLOW_CLOCK == regdata);
- -}
- -
- -static bool
- -brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci, u16 coreid)
- -{
- - u32 regdata;
- - u8 idx;
- - bool ret;
- -
- - idx = brcmf_sdio_chip_getinfidx(ci, coreid);
- - if (idx == BRCMF_MAX_CORENUM)
- - return false;
- -
- - regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
- - NULL);
- - ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK;
- -
- - regdata = brcmf_sdiod_regrl(sdiodev,
- - ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
- - NULL);
- - ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0);
- -
- - return ret;
- -}
- -
- -static void
- -brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
- - u32 in_resetbits)
- -{
- - u32 regdata, base;
- - u8 idx;
- -
- - idx = brcmf_sdio_chip_getinfidx(ci, coreid);
- - base = ci->c_inf[idx].base;
- -
- - regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
- - if (regdata & SSB_TMSLOW_RESET)
- - return;
- -
- - regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
- - if ((regdata & SSB_TMSLOW_CLOCK) != 0) {
- - /*
- - * set target reject and spin until busy is clear
- - * (preserve core-specific bits)
- - */
- - regdata = brcmf_sdiod_regrl(sdiodev,
- - CORE_SB(base, sbtmstatelow), NULL);
- - brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
- - regdata | SSB_TMSLOW_REJECT, NULL);
- -
- - regdata = brcmf_sdiod_regrl(sdiodev,
- - CORE_SB(base, sbtmstatelow), NULL);
- - udelay(1);
- - SPINWAIT((brcmf_sdiod_regrl(sdiodev,
- - CORE_SB(base, sbtmstatehigh),
- - NULL) &
- - SSB_TMSHIGH_BUSY), 100000);
- -
- - regdata = brcmf_sdiod_regrl(sdiodev,
- - CORE_SB(base, sbtmstatehigh),
- - NULL);
- - if (regdata & SSB_TMSHIGH_BUSY)
- - brcmf_err("core state still busy\n");
- -
- - regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbidlow),
- - NULL);
- - if (regdata & SSB_IDLOW_INITIATOR) {
- - regdata = brcmf_sdiod_regrl(sdiodev,
- - CORE_SB(base, sbimstate),
- - NULL);
- - regdata |= SSB_IMSTATE_REJECT;
- - brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbimstate),
- - regdata, NULL);
- - regdata = brcmf_sdiod_regrl(sdiodev,
- - CORE_SB(base, sbimstate),
- - NULL);
- - udelay(1);
- - SPINWAIT((brcmf_sdiod_regrl(sdiodev,
- - CORE_SB(base, sbimstate),
- - NULL) &
- - SSB_IMSTATE_BUSY), 100000);
- - }
- -
- - /* set reset and reject while enabling the clocks */
- - regdata = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
- - SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET;
- - brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
- - regdata, NULL);
- - regdata = brcmf_sdiod_regrl(sdiodev,
- - CORE_SB(base, sbtmstatelow), NULL);
- - udelay(10);
- -
- - /* clear the initiator reject bit */
- - regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbidlow),
- - NULL);
- - if (regdata & SSB_IDLOW_INITIATOR) {
- - regdata = brcmf_sdiod_regrl(sdiodev,
- - CORE_SB(base, sbimstate),
- - NULL);
- - regdata &= ~SSB_IMSTATE_REJECT;
- - brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbimstate),
- - regdata, NULL);
- - }
- - }
- -
- - /* leave reset and reject asserted */
- - brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
- - (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET), NULL);
- - udelay(1);
- -}
- -
- -static void
- -brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
- - u32 in_resetbits)
- -{
- - u8 idx;
- - u32 regdata;
- - u32 wrapbase;
- -
- - idx = brcmf_sdio_chip_getinfidx(ci, coreid);
- - if (idx == BRCMF_MAX_CORENUM)
- - return;
- -
- - wrapbase = ci->c_inf[idx].wrapbase;
- -
- - /* if core is already in reset, skip reset */
- - regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL);
- - if ((regdata & BCMA_RESET_CTL_RESET) != 0)
- - goto post_reset_config;
- -
- - /* configure reset */
- - brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, pre_resetbits |
- - BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
- - regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
- -
- - /* put in reset */
- - brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_RESET_CTL,
- - BCMA_RESET_CTL_RESET, NULL);
- - usleep_range(10, 20);
- -
- - /* wait till reset is 1 */
- - SPINWAIT(brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL) !=
- - BCMA_RESET_CTL_RESET, 300);
- -
- -post_reset_config:
- - /* post reset configure */
- - brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, pre_resetbits |
- - BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
- - regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
- -}
- -
- -static void
- -brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
- - u32 in_resetbits, u32 post_resetbits)
- -{
- - u32 regdata;
- - u8 idx;
- -
- - idx = brcmf_sdio_chip_getinfidx(ci, coreid);
- - if (idx == BRCMF_MAX_CORENUM)
- - return;
- -
- - /*
- - * Must do the disable sequence first to work for
- - * arbitrary current core state.
- - */
- - brcmf_sdio_sb_coredisable(sdiodev, ci, coreid, pre_resetbits,
- - in_resetbits);
- -
- - /*
- - * Now do the initialization sequence.
- - * set reset while enabling the clock and
- - * forcing them on throughout the core
- - */
- - brcmf_sdiod_regwl(sdiodev,
- - CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
- - SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET,
- - NULL);
- - regdata = brcmf_sdiod_regrl(sdiodev,
- - CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
- - NULL);
- - udelay(1);
- -
- - /* clear any serror */
- - regdata = brcmf_sdiod_regrl(sdiodev,
- - CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
- - NULL);
- - if (regdata & SSB_TMSHIGH_SERR)
- - brcmf_sdiod_regwl(sdiodev,
- - CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
- - 0, NULL);
- -
- - regdata = brcmf_sdiod_regrl(sdiodev,
- - CORE_SB(ci->c_inf[idx].base, sbimstate),
- - NULL);
- - if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO))
- - brcmf_sdiod_regwl(sdiodev,
- - CORE_SB(ci->c_inf[idx].base, sbimstate),
- - regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO),
- - NULL);
- -
- - /* clear reset and allow it to propagate throughout the core */
- - brcmf_sdiod_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
- - SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK, NULL);
- - regdata = brcmf_sdiod_regrl(sdiodev,
- - CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
- - NULL);
- - udelay(1);
- -
- - /* leave clock enabled */
- - brcmf_sdiod_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
- - SSB_TMSLOW_CLOCK, NULL);
- - regdata = brcmf_sdiod_regrl(sdiodev,
- - CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
- - NULL);
- - udelay(1);
- -}
- -
- -static void
- -brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
- - u32 in_resetbits, u32 post_resetbits)
- -{
- - u8 idx;
- - u32 regdata;
- - u32 wrapbase;
- -
- - idx = brcmf_sdio_chip_getinfidx(ci, coreid);
- - if (idx == BRCMF_MAX_CORENUM)
- - return;
- -
- - wrapbase = ci->c_inf[idx].wrapbase;
- -
- - /* must disable first to work for arbitrary current core state */
- - brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, pre_resetbits,
- - in_resetbits);
- -
- - while (brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL) &
- - BCMA_RESET_CTL_RESET) {
- - brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_RESET_CTL, 0, NULL);
- - usleep_range(40, 60);
- - }
- -
- - brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, post_resetbits |
- - BCMA_IOCTL_CLK, NULL);
- - regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
- -}
- -
- -#ifdef DEBUG
- -/* safety check for chipinfo */
- -static int brcmf_sdio_chip_cichk(struct brcmf_chip *ci)
- -{
- - u8 core_idx;
- -
- - /* check RAM core presence for ARM CM3 core */
- - core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
- - if (BRCMF_MAX_CORENUM != core_idx) {
- - core_idx = brcmf_sdio_chip_getinfidx(ci,
- - BCMA_CORE_INTERNAL_MEM);
- - if (BRCMF_MAX_CORENUM == core_idx) {
- - brcmf_err("RAM core not provided with ARM CM3 core\n");
- - return -ENODEV;
- - }
- - }
- -
- - /* check RAM base for ARM CR4 core */
- - core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CR4);
- - if (BRCMF_MAX_CORENUM != core_idx) {
- - if (ci->rambase == 0) {
- - brcmf_err("RAM base not provided with ARM CR4 core\n");
- - return -ENOMEM;
- - }
- - }
- -
- - return 0;
- -}
- -#else /* DEBUG */
- -static inline int brcmf_sdio_chip_cichk(struct brcmf_chip *ci)
- -{
- - return 0;
- -}
- -#endif
- -
- -static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci)
- -{
- - u32 regdata;
- - u32 socitype;
- -
- - /* Get CC core rev
- - * Chipid is assume to be at offset 0 from SI_ENUM_BASE
- - * For different chiptypes or old sdio hosts w/o chipcommon,
- - * other ways of recognition should be added here.
- - */
- - regdata = brcmf_sdiod_regrl(sdiodev,
- - CORE_CC_REG(SI_ENUM_BASE, chipid),
- - NULL);
- - ci->chip = regdata & CID_ID_MASK;
- - ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
- - if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 &&
- - ci->chiprev >= 2)
- - ci->chip = BCM4339_CHIP_ID;
- - socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
- -
- - brcmf_dbg(INFO, "found %s chip: id=0x%x, rev=%d\n",
- - socitype == SOCI_SB ? "SB" : "AXI", ci->chip, ci->chiprev);
- -
- - if (socitype == SOCI_SB) {
- - if (ci->chip != BCM4329_CHIP_ID) {
- - brcmf_err("SB chip is not supported\n");
- - return -ENODEV;
- - }
- - ci->iscoreup = brcmf_sdio_sb_iscoreup;
- - ci->corerev = brcmf_sdio_sb_corerev;
- - ci->coredisable = brcmf_sdio_sb_coredisable;
- - ci->resetcore = brcmf_sdio_sb_resetcore;
- -
- - ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
- - ci->c_inf[0].base = SI_ENUM_BASE;
- - ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
- - ci->c_inf[1].base = BCM4329_CORE_BUS_BASE;
- - ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
- - ci->c_inf[2].base = BCM4329_CORE_SOCRAM_BASE;
- - ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
- - ci->c_inf[3].base = BCM4329_CORE_ARM_BASE;
- - ci->c_inf[4].id = BCMA_CORE_80211;
- - ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
- - ci->ramsize = BCM4329_RAMSIZE;
- - } else if (socitype == SOCI_AI) {
- - ci->iscoreup = brcmf_sdio_ai_iscoreup;
- - ci->corerev = brcmf_sdio_ai_corerev;
- - ci->coredisable = brcmf_sdio_ai_coredisable;
- - ci->resetcore = brcmf_sdio_ai_resetcore;
- -
- - ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
- - ci->c_inf[0].base = SI_ENUM_BASE;
- -
- - /* Address of cores for new chips should be added here */
- - switch (ci->chip) {
- - case BCM43143_CHIP_ID:
- - ci->c_inf[0].wrapbase = ci->c_inf[0].base + 0x00100000;
- - ci->c_inf[0].cib = 0x2b000000;
- - ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
- - ci->c_inf[1].base = BCM43143_CORE_BUS_BASE;
- - ci->c_inf[1].wrapbase = ci->c_inf[1].base + 0x00100000;
- - ci->c_inf[1].cib = 0x18000000;
- - ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
- - ci->c_inf[2].base = BCM43143_CORE_SOCRAM_BASE;
- - ci->c_inf[2].wrapbase = ci->c_inf[2].base + 0x00100000;
- - ci->c_inf[2].cib = 0x14000000;
- - ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
- - ci->c_inf[3].base = BCM43143_CORE_ARM_BASE;
- - ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
- - ci->c_inf[3].cib = 0x07000000;
- - ci->c_inf[4].id = BCMA_CORE_80211;
- - ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
- - ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
- - ci->ramsize = BCM43143_RAMSIZE;
- - break;
- - case BCM43241_CHIP_ID:
- - ci->c_inf[0].wrapbase = 0x18100000;
- - ci->c_inf[0].cib = 0x2a084411;
- - ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
- - ci->c_inf[1].base = 0x18002000;
- - ci->c_inf[1].wrapbase = 0x18102000;
- - ci->c_inf[1].cib = 0x0e004211;
- - ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
- - ci->c_inf[2].base = 0x18004000;
- - ci->c_inf[2].wrapbase = 0x18104000;
- - ci->c_inf[2].cib = 0x14080401;
- - ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
- - ci->c_inf[3].base = 0x18003000;
- - ci->c_inf[3].wrapbase = 0x18103000;
- - ci->c_inf[3].cib = 0x07004211;
- - ci->c_inf[4].id = BCMA_CORE_80211;
- - ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
- - ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
- - ci->ramsize = 0x90000;
- - break;
- - case BCM4330_CHIP_ID:
- - ci->c_inf[0].wrapbase = 0x18100000;
- - ci->c_inf[0].cib = 0x27004211;
- - ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
- - ci->c_inf[1].base = 0x18002000;
- - ci->c_inf[1].wrapbase = 0x18102000;
- - ci->c_inf[1].cib = 0x07004211;
- - ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
- - ci->c_inf[2].base = 0x18004000;
- - ci->c_inf[2].wrapbase = 0x18104000;
- - ci->c_inf[2].cib = 0x0d080401;
- - ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
- - ci->c_inf[3].base = 0x18003000;
- - ci->c_inf[3].wrapbase = 0x18103000;
- - ci->c_inf[3].cib = 0x03004211;
- - ci->c_inf[4].id = BCMA_CORE_80211;
- - ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
- - ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
- - ci->ramsize = 0x48000;
- - break;
- - case BCM4334_CHIP_ID:
- - ci->c_inf[0].wrapbase = 0x18100000;
- - ci->c_inf[0].cib = 0x29004211;
- - ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
- - ci->c_inf[1].base = 0x18002000;
- - ci->c_inf[1].wrapbase = 0x18102000;
- - ci->c_inf[1].cib = 0x0d004211;
- - ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
- - ci->c_inf[2].base = 0x18004000;
- - ci->c_inf[2].wrapbase = 0x18104000;
- - ci->c_inf[2].cib = 0x13080401;
- - ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
- - ci->c_inf[3].base = 0x18003000;
- - ci->c_inf[3].wrapbase = 0x18103000;
- - ci->c_inf[3].cib = 0x07004211;
- - ci->c_inf[4].id = BCMA_CORE_80211;
- - ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
- - ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
- - ci->ramsize = 0x80000;
- - break;
- - case BCM4335_CHIP_ID:
- - ci->c_inf[0].wrapbase = 0x18100000;
- - ci->c_inf[0].cib = 0x2b084411;
- - ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
- - ci->c_inf[1].base = 0x18005000;
- - ci->c_inf[1].wrapbase = 0x18105000;
- - ci->c_inf[1].cib = 0x0f004211;
- - ci->c_inf[2].id = BCMA_CORE_ARM_CR4;
- - ci->c_inf[2].base = 0x18002000;
- - ci->c_inf[2].wrapbase = 0x18102000;
- - ci->c_inf[2].cib = 0x01084411;
- - ci->c_inf[3].id = BCMA_CORE_80211;
- - ci->c_inf[3].base = BCM43xx_CORE_D11_BASE;
- - ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
- - ci->ramsize = 0xc0000;
- - ci->rambase = 0x180000;
- - break;
- - case BCM43362_CHIP_ID:
- - ci->c_inf[0].wrapbase = 0x18100000;
- - ci->c_inf[0].cib = 0x27004211;
- - ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
- - ci->c_inf[1].base = 0x18002000;
- - ci->c_inf[1].wrapbase = 0x18102000;
- - ci->c_inf[1].cib = 0x0a004211;
- - ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
- - ci->c_inf[2].base = 0x18004000;
- - ci->c_inf[2].wrapbase = 0x18104000;
- - ci->c_inf[2].cib = 0x08080401;
- - ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
- - ci->c_inf[3].base = 0x18003000;
- - ci->c_inf[3].wrapbase = 0x18103000;
- - ci->c_inf[3].cib = 0x03004211;
- - ci->c_inf[4].id = BCMA_CORE_80211;
- - ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
- - ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
- - ci->ramsize = 0x3C000;
- - break;
- - case BCM4339_CHIP_ID:
- - ci->c_inf[0].wrapbase = 0x18100000;
- - ci->c_inf[0].cib = 0x2e084411;
- - ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
- - ci->c_inf[1].base = 0x18005000;
- - ci->c_inf[1].wrapbase = 0x18105000;
- - ci->c_inf[1].cib = 0x15004211;
- - ci->c_inf[2].id = BCMA_CORE_ARM_CR4;
- - ci->c_inf[2].base = 0x18002000;
- - ci->c_inf[2].wrapbase = 0x18102000;
- - ci->c_inf[2].cib = 0x04084411;
- - ci->c_inf[3].id = BCMA_CORE_80211;
- - ci->c_inf[3].base = BCM43xx_CORE_D11_BASE;
- - ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
- - ci->ramsize = 0xc0000;
- - ci->rambase = 0x180000;
- - break;
- - default:
- - brcmf_err("AXI chip is not supported\n");
- - return -ENODEV;
- - }
- - } else {
- - brcmf_err("chip backplane type %u is not supported\n",
- - socitype);
- - return -ENODEV;
- - }
- -
- - return brcmf_sdio_chip_cichk(ci);
- -}
- -
- -static int
- -brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
- -{
- - int err = 0;
- - u8 clkval, clkset;
- -
- - /* Try forcing SDIO core to do ALPAvail request only */
- - clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
- - brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
- - if (err) {
- - brcmf_err("error writing for HT off\n");
- - return err;
- - }
- -
- - /* If register supported, wait for ALPAvail and then force ALP */
- - /* This may take up to 15 milliseconds */
- - clkval = brcmf_sdiod_regrb(sdiodev,
- - SBSDIO_FUNC1_CHIPCLKCSR, NULL);
- -
- - if ((clkval & ~SBSDIO_AVBITS) != clkset) {
- - brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
- - clkset, clkval);
- - return -EACCES;
- - }
- -
- - SPINWAIT(((clkval = brcmf_sdiod_regrb(sdiodev,
- - SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
- - !SBSDIO_ALPAV(clkval)),
- - PMU_MAX_TRANSITION_DLY);
- - if (!SBSDIO_ALPAV(clkval)) {
- - brcmf_err("timeout on ALPAV wait, clkval 0x%02x\n",
- - clkval);
- - return -EBUSY;
- - }
- -
- - clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
- - brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
- - udelay(65);
- -
- - /* Also, disable the extra SDIO pull-ups */
- - brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
- -
- - return 0;
- -}
- -
- -static void
- -brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci)
- -{
- - u32 base = ci->c_inf[0].base;
- -
- - /* get chipcommon rev */
- - ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id);
- -
- - /* get chipcommon capabilites */
- - ci->c_inf[0].caps = brcmf_sdiod_regrl(sdiodev,
- - CORE_CC_REG(base, capabilities),
- - NULL);
- -
- - /* get pmu caps & rev */
- - if (ci->c_inf[0].caps & CC_CAP_PMU) {
- - ci->pmucaps =
- - brcmf_sdiod_regrl(sdiodev,
- - CORE_CC_REG(base, pmucapabilities),
- - NULL);
- - ci->pmurev = ci->pmucaps & PCAP_REV_MASK;
- - }
- -
- - ci->c_inf[1].rev = ci->corerev(sdiodev, ci, ci->c_inf[1].id);
- -
- - brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
- - ci->c_inf[0].rev, ci->pmurev,
- - ci->c_inf[1].rev, ci->c_inf[1].id);
- -
- - /*
- - * Make sure any on-chip ARM is off (in case strapping is wrong),
- - * or downloaded code was already running.
- - */
- - ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0);
- -}
- -
- -int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip **ci_ptr)
- -{
- - int ret;
- - struct brcmf_chip *ci;
- -
- - brcmf_dbg(TRACE, "Enter\n");
- -
- - ci = kzalloc(sizeof(*ci), GFP_ATOMIC);
- - if (!ci)
- - return -ENOMEM;
- -
- - ret = brcmf_sdio_chip_buscoreprep(sdiodev);
- - if (ret != 0)
- - goto err;
- -
- - ret = brcmf_sdio_chip_recognition(sdiodev, ci);
- - if (ret != 0)
- - goto err;
- -
- - brcmf_sdio_chip_buscoresetup(sdiodev, ci);
- -
- - brcmf_sdiod_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopullup),
- - 0, NULL);
- - brcmf_sdiod_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopulldown),
- - 0, NULL);
- -
- - *ci_ptr = ci;
- - return 0;
- -
- -err:
- - kfree(ci);
- - return ret;
- -}
- -
- -void
- -brcmf_sdio_chip_detach(struct brcmf_chip **ci_ptr)
- -{
- - brcmf_dbg(TRACE, "Enter\n");
- -
- - kfree(*ci_ptr);
- - *ci_ptr = NULL;
- -}
- -
- -static char *brcmf_sdio_chip_name(uint chipid, char *buf, uint len)
- -{
- - const char *fmt;
- -
- - fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
- - snprintf(buf, len, fmt, chipid);
- - return buf;
- -}
- -
- -void
- -brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci, u32 drivestrength)
- -{
- - const struct sdiod_drive_str *str_tab = NULL;
- - u32 str_mask;
- - u32 str_shift;
- - char chn[8];
- - u32 base = ci->c_inf[0].base;
- - u32 i;
- - u32 drivestrength_sel = 0;
- - u32 cc_data_temp;
- - u32 addr;
- -
- - if (!(ci->c_inf[0].caps & CC_CAP_PMU))
- - return;
- -
- - switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
- - case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
- - str_tab = sdiod_drvstr_tab1_1v8;
- - str_mask = 0x00003800;
- - str_shift = 11;
- - break;
- - case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17):
- - str_tab = sdiod_drvstr_tab6_1v8;
- - str_mask = 0x00001800;
- - str_shift = 11;
- - break;
- - case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
- - /* note: 43143 does not support tristate */
- - i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1;
- - if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) {
- - str_tab = sdiod_drvstr_tab2_3v3;
- - str_mask = 0x00000007;
- - str_shift = 0;
- - } else
- - brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
- - brcmf_sdio_chip_name(ci->chip, chn, 8),
- - drivestrength);
- - break;
- - case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13):
- - str_tab = sdiod_drive_strength_tab5_1v8;
- - str_mask = 0x00003800;
- - str_shift = 11;
- - break;
- - default:
- - brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
- - brcmf_sdio_chip_name(ci->chip, chn, 8),
- - ci->chiprev, ci->pmurev);
- - break;
- - }
- -
- - if (str_tab != NULL) {
- - for (i = 0; str_tab[i].strength != 0; i++) {
- - if (drivestrength >= str_tab[i].strength) {
- - drivestrength_sel = str_tab[i].sel;
- - break;
- - }
- - }
- - addr = CORE_CC_REG(base, chipcontrol_addr);
- - brcmf_sdiod_regwl(sdiodev, addr, 1, NULL);
- - cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL);
- - cc_data_temp &= ~str_mask;
- - drivestrength_sel <<= str_shift;
- - cc_data_temp |= drivestrength_sel;
- - brcmf_sdiod_regwl(sdiodev, addr, cc_data_temp, NULL);
- -
- - brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n",
- - str_tab[i].strength, drivestrength, cc_data_temp);
- - }
- -}
- -
- -static void
- -brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci)
- -{
- - ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0);
- - ci->resetcore(sdiodev, ci, BCMA_CORE_80211,
- - D11_BCMA_IOCTL_PHYRESET | D11_BCMA_IOCTL_PHYCLOCKEN,
- - D11_BCMA_IOCTL_PHYCLOCKEN, D11_BCMA_IOCTL_PHYCLOCKEN);
- - ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0, 0, 0);
- -}
- -
- -static bool brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci)
- -{
- - u8 core_idx;
- - u32 reg_addr;
- -
- - if (!ci->iscoreup(sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
- - brcmf_err("SOCRAM core is down after reset?\n");
- - return false;
- - }
- -
- - /* clear all interrupts */
- - core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
- - reg_addr = ci->c_inf[core_idx].base;
- - reg_addr += offsetof(struct sdpcmd_regs, intstatus);
- - brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
- -
- - ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0, 0);
- -
- - return true;
- -}
- -
- -static inline void
- -brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci)
- -{
- - u8 idx;
- - u32 regdata;
- - u32 wrapbase;
- - idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CR4);
- -
- - if (idx == BRCMF_MAX_CORENUM)
- - return;
- -
- - wrapbase = ci->c_inf[idx].wrapbase;
- - regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
- - regdata &= ARMCR4_BCMA_IOCTL_CPUHALT;
- - ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, regdata,
- - ARMCR4_BCMA_IOCTL_CPUHALT, ARMCR4_BCMA_IOCTL_CPUHALT);
- - ci->resetcore(sdiodev, ci, BCMA_CORE_80211,
- - D11_BCMA_IOCTL_PHYRESET | D11_BCMA_IOCTL_PHYCLOCKEN,
- - D11_BCMA_IOCTL_PHYCLOCKEN, D11_BCMA_IOCTL_PHYCLOCKEN);
- -}
- -
- -static bool brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci, u32 rstvec)
- -{
- - u8 core_idx;
- - u32 reg_addr;
- -
- - /* clear all interrupts */
- - core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
- - reg_addr = ci->c_inf[core_idx].base;
- - reg_addr += offsetof(struct sdpcmd_regs, intstatus);
- - brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
- -
- - /* Write reset vector to address 0 */
- - brcmf_sdiod_ramrw(sdiodev, true, 0, (void *)&rstvec,
- - sizeof(rstvec));
- -
- - /* restore ARM */
- - ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, ARMCR4_BCMA_IOCTL_CPUHALT,
- - 0, 0);
- -
- - return true;
- -}
- -
- -void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci)
- -{
- - u8 arm_core_idx;
- -
- - arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
- - if (BRCMF_MAX_CORENUM != arm_core_idx) {
- - brcmf_sdio_chip_cm3_enterdl(sdiodev, ci);
- - return;
- - }
- -
- - brcmf_sdio_chip_cr4_enterdl(sdiodev, ci);
- -}
- -
- -bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci, u32 rstvec)
- -{
- - u8 arm_core_idx;
- -
- - arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
- - if (BRCMF_MAX_CORENUM != arm_core_idx)
- - return brcmf_sdio_chip_cm3_exitdl(sdiodev, ci);
- -
- - return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci, rstvec);
- -}
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h 1969-12-31 18:00:00.000000000 -0600
- @@ -1,231 +0,0 @@
- -/*
- - * Copyright (c) 2011 Broadcom Corporation
- - *
- - * Permission to use, copy, modify, and/or distribute this software for any
- - * purpose with or without fee is hereby granted, provided that the above
- - * copyright notice and this permission notice appear in all copies.
- - *
- - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- - */
- -
- -#ifndef _BRCMFMAC_SDIO_CHIP_H_
- -#define _BRCMFMAC_SDIO_CHIP_H_
- -
- -/*
- - * Core reg address translation.
- - * Both macro's returns a 32 bits byte address on the backplane bus.
- - */
- -#define CORE_CC_REG(base, field) \
- - (base + offsetof(struct chipcregs, field))
- -#define CORE_BUS_REG(base, field) \
- - (base + offsetof(struct sdpcmd_regs, field))
- -#define CORE_SB(base, field) \
- - (base + SBCONFIGOFF + offsetof(struct sbconfig, field))
- -
- -/* SDIO function 1 register CHIPCLKCSR */
- -/* Force ALP request to backplane */
- -#define SBSDIO_FORCE_ALP 0x01
- -/* Force HT request to backplane */
- -#define SBSDIO_FORCE_HT 0x02
- -/* Force ILP request to backplane */
- -#define SBSDIO_FORCE_ILP 0x04
- -/* Make ALP ready (power up xtal) */
- -#define SBSDIO_ALP_AVAIL_REQ 0x08
- -/* Make HT ready (power up PLL) */
- -#define SBSDIO_HT_AVAIL_REQ 0x10
- -/* Squelch clock requests from HW */
- -#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20
- -/* Status: ALP is ready */
- -#define SBSDIO_ALP_AVAIL 0x40
- -/* Status: HT is ready */
- -#define SBSDIO_HT_AVAIL 0x80
- -#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL)
- -#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS)
- -#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS)
- -#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval))
- -#define SBSDIO_CLKAV(regval, alponly) \
- - (SBSDIO_ALPAV(regval) && (alponly ? 1 : SBSDIO_HTAV(regval)))
- -
- -#define BRCMF_MAX_CORENUM 6
- -
- -struct brcmf_core {
- - u16 id;
- - u16 rev;
- - u32 base;
- - u32 wrapbase;
- - u32 caps;
- - u32 cib;
- -};
- -
- -struct brcmf_chip {
- - u32 chip;
- - u32 chiprev;
- - /* core info */
- - /* always put chipcommon core at 0, bus core at 1 */
- - struct brcmf_core c_inf[BRCMF_MAX_CORENUM];
- - u32 pmurev;
- - u32 pmucaps;
- - u32 ramsize;
- - u32 rambase;
- - u32 rst_vec; /* reset vertor for ARM CR4 core */
- -
- - bool (*iscoreup)(struct brcmf_sdio_dev *sdiodev, struct brcmf_chip *ci,
- - u16 coreid);
- - u32 (*corerev)(struct brcmf_sdio_dev *sdiodev, struct brcmf_chip *ci,
- - u16 coreid);
- - void (*coredisable)(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
- - u32 in_resetbits);
- - void (*resetcore)(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
- - u32 in_resetbits, u32 post_resetbits);
- -};
- -
- -struct sbconfig {
- - u32 PAD[2];
- - u32 sbipsflag; /* initiator port ocp slave flag */
- - u32 PAD[3];
- - u32 sbtpsflag; /* target port ocp slave flag */
- - u32 PAD[11];
- - u32 sbtmerrloga; /* (sonics >= 2.3) */
- - u32 PAD;
- - u32 sbtmerrlog; /* (sonics >= 2.3) */
- - u32 PAD[3];
- - u32 sbadmatch3; /* address match3 */
- - u32 PAD;
- - u32 sbadmatch2; /* address match2 */
- - u32 PAD;
- - u32 sbadmatch1; /* address match1 */
- - u32 PAD[7];
- - u32 sbimstate; /* initiator agent state */
- - u32 sbintvec; /* interrupt mask */
- - u32 sbtmstatelow; /* target state */
- - u32 sbtmstatehigh; /* target state */
- - u32 sbbwa0; /* bandwidth allocation table0 */
- - u32 PAD;
- - u32 sbimconfiglow; /* initiator configuration */
- - u32 sbimconfighigh; /* initiator configuration */
- - u32 sbadmatch0; /* address match0 */
- - u32 PAD;
- - u32 sbtmconfiglow; /* target configuration */
- - u32 sbtmconfighigh; /* target configuration */
- - u32 sbbconfig; /* broadcast configuration */
- - u32 PAD;
- - u32 sbbstate; /* broadcast state */
- - u32 PAD[3];
- - u32 sbactcnfg; /* activate configuration */
- - u32 PAD[3];
- - u32 sbflagst; /* current sbflags */
- - u32 PAD[3];
- - u32 sbidlow; /* identification */
- - u32 sbidhigh; /* identification */
- -};
- -
- -/* sdio core registers */
- -struct sdpcmd_regs {
- - u32 corecontrol; /* 0x00, rev8 */
- - u32 corestatus; /* rev8 */
- - u32 PAD[1];
- - u32 biststatus; /* rev8 */
- -
- - /* PCMCIA access */
- - u16 pcmciamesportaladdr; /* 0x010, rev8 */
- - u16 PAD[1];
- - u16 pcmciamesportalmask; /* rev8 */
- - u16 PAD[1];
- - u16 pcmciawrframebc; /* rev8 */
- - u16 PAD[1];
- - u16 pcmciaunderflowtimer; /* rev8 */
- - u16 PAD[1];
- -
- - /* interrupt */
- - u32 intstatus; /* 0x020, rev8 */
- - u32 hostintmask; /* rev8 */
- - u32 intmask; /* rev8 */
- - u32 sbintstatus; /* rev8 */
- - u32 sbintmask; /* rev8 */
- - u32 funcintmask; /* rev4 */
- - u32 PAD[2];
- - u32 tosbmailbox; /* 0x040, rev8 */
- - u32 tohostmailbox; /* rev8 */
- - u32 tosbmailboxdata; /* rev8 */
- - u32 tohostmailboxdata; /* rev8 */
- -
- - /* synchronized access to registers in SDIO clock domain */
- - u32 sdioaccess; /* 0x050, rev8 */
- - u32 PAD[3];
- -
- - /* PCMCIA frame control */
- - u8 pcmciaframectrl; /* 0x060, rev8 */
- - u8 PAD[3];
- - u8 pcmciawatermark; /* rev8 */
- - u8 PAD[155];
- -
- - /* interrupt batching control */
- - u32 intrcvlazy; /* 0x100, rev8 */
- - u32 PAD[3];
- -
- - /* counters */
- - u32 cmd52rd; /* 0x110, rev8 */
- - u32 cmd52wr; /* rev8 */
- - u32 cmd53rd; /* rev8 */
- - u32 cmd53wr; /* rev8 */
- - u32 abort; /* rev8 */
- - u32 datacrcerror; /* rev8 */
- - u32 rdoutofsync; /* rev8 */
- - u32 wroutofsync; /* rev8 */
- - u32 writebusy; /* rev8 */
- - u32 readwait; /* rev8 */
- - u32 readterm; /* rev8 */
- - u32 writeterm; /* rev8 */
- - u32 PAD[40];
- - u32 clockctlstatus; /* rev8 */
- - u32 PAD[7];
- -
- - u32 PAD[128]; /* DMA engines */
- -
- - /* SDIO/PCMCIA CIS region */
- - char cis[512]; /* 0x400-0x5ff, rev6 */
- -
- - /* PCMCIA function control registers */
- - char pcmciafcr[256]; /* 0x600-6ff, rev6 */
- - u16 PAD[55];
- -
- - /* PCMCIA backplane access */
- - u16 backplanecsr; /* 0x76E, rev6 */
- - u16 backplaneaddr0; /* rev6 */
- - u16 backplaneaddr1; /* rev6 */
- - u16 backplaneaddr2; /* rev6 */
- - u16 backplaneaddr3; /* rev6 */
- - u16 backplanedata0; /* rev6 */
- - u16 backplanedata1; /* rev6 */
- - u16 backplanedata2; /* rev6 */
- - u16 backplanedata3; /* rev6 */
- - u16 PAD[31];
- -
- - /* sprom "size" & "blank" info */
- - u16 spromstatus; /* 0x7BE, rev2 */
- - u32 PAD[464];
- -
- - u16 PAD[0x80];
- -};
- -
- -int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip **ci_ptr);
- -void brcmf_sdio_chip_detach(struct brcmf_chip **ci_ptr);
- -void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci,
- - u32 drivestrength);
- -u8 brcmf_sdio_chip_getinfidx(struct brcmf_chip *ci, u16 coreid);
- -void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci);
- -bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
- - struct brcmf_chip *ci, u32 rstvec);
- -
- -#endif /* _BRCMFMAC_SDIO_CHIP_H_ */
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h 2015-03-08 14:27:37.697684500 -0500
- @@ -180,6 +180,97 @@
- uint max_request_size;
- ushort max_segment_count;
- uint max_segment_size;
- + uint txglomsz;
- + struct sg_table sgtable;
- +};
- +
- +/* sdio core registers */
- +struct sdpcmd_regs {
- + u32 corecontrol; /* 0x00, rev8 */
- + u32 corestatus; /* rev8 */
- + u32 PAD[1];
- + u32 biststatus; /* rev8 */
- +
- + /* PCMCIA access */
- + u16 pcmciamesportaladdr; /* 0x010, rev8 */
- + u16 PAD[1];
- + u16 pcmciamesportalmask; /* rev8 */
- + u16 PAD[1];
- + u16 pcmciawrframebc; /* rev8 */
- + u16 PAD[1];
- + u16 pcmciaunderflowtimer; /* rev8 */
- + u16 PAD[1];
- +
- + /* interrupt */
- + u32 intstatus; /* 0x020, rev8 */
- + u32 hostintmask; /* rev8 */
- + u32 intmask; /* rev8 */
- + u32 sbintstatus; /* rev8 */
- + u32 sbintmask; /* rev8 */
- + u32 funcintmask; /* rev4 */
- + u32 PAD[2];
- + u32 tosbmailbox; /* 0x040, rev8 */
- + u32 tohostmailbox; /* rev8 */
- + u32 tosbmailboxdata; /* rev8 */
- + u32 tohostmailboxdata; /* rev8 */
- +
- + /* synchronized access to registers in SDIO clock domain */
- + u32 sdioaccess; /* 0x050, rev8 */
- + u32 PAD[3];
- +
- + /* PCMCIA frame control */
- + u8 pcmciaframectrl; /* 0x060, rev8 */
- + u8 PAD[3];
- + u8 pcmciawatermark; /* rev8 */
- + u8 PAD[155];
- +
- + /* interrupt batching control */
- + u32 intrcvlazy; /* 0x100, rev8 */
- + u32 PAD[3];
- +
- + /* counters */
- + u32 cmd52rd; /* 0x110, rev8 */
- + u32 cmd52wr; /* rev8 */
- + u32 cmd53rd; /* rev8 */
- + u32 cmd53wr; /* rev8 */
- + u32 abort; /* rev8 */
- + u32 datacrcerror; /* rev8 */
- + u32 rdoutofsync; /* rev8 */
- + u32 wroutofsync; /* rev8 */
- + u32 writebusy; /* rev8 */
- + u32 readwait; /* rev8 */
- + u32 readterm; /* rev8 */
- + u32 writeterm; /* rev8 */
- + u32 PAD[40];
- + u32 clockctlstatus; /* rev8 */
- + u32 PAD[7];
- +
- + u32 PAD[128]; /* DMA engines */
- +
- + /* SDIO/PCMCIA CIS region */
- + char cis[512]; /* 0x400-0x5ff, rev6 */
- +
- + /* PCMCIA function control registers */
- + char pcmciafcr[256]; /* 0x600-6ff, rev6 */
- + u16 PAD[55];
- +
- + /* PCMCIA backplane access */
- + u16 backplanecsr; /* 0x76E, rev6 */
- + u16 backplaneaddr0; /* rev6 */
- + u16 backplaneaddr1; /* rev6 */
- + u16 backplaneaddr2; /* rev6 */
- + u16 backplaneaddr3; /* rev6 */
- + u16 backplanedata0; /* rev6 */
- + u16 backplanedata1; /* rev6 */
- + u16 backplanedata2; /* rev6 */
- + u16 backplanedata3; /* rev6 */
- + u16 PAD[31];
- +
- + /* sprom "size" & "blank" info */
- + u16 spromstatus; /* 0x7BE, rev2 */
- + u32 PAD[464];
- +
- + u16 PAD[0x80];
- };
-
- /* Register/deregister interrupt handler. */
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/usb.c linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/usb.c
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/usb.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/usb.c 2015-03-08 14:27:37.697684500 -0500
- @@ -25,6 +25,7 @@
- #include <dhd_bus.h>
- #include <dhd_dbg.h>
-
- +#include "firmware.h"
- #include "usb_rdl.h"
- #include "usb.h"
-
- @@ -61,12 +62,6 @@
- u8 *image;
- int image_len;
- };
- -static struct list_head fw_image_list;
- -
- -struct intr_transfer_buf {
- - u32 notification;
- - u32 reserved;
- -};
-
- struct brcmf_usbdev_info {
- struct brcmf_usbdev bus_pub; /* MUST BE FIRST */
- @@ -75,7 +70,7 @@
- struct list_head rx_postq;
- struct list_head tx_freeq;
- struct list_head tx_postq;
- - uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2;
- + uint rx_pipe, tx_pipe, rx_pipe2;
-
- int rx_low_watermark;
- int tx_low_watermark;
- @@ -87,7 +82,7 @@
- struct brcmf_usbreq *tx_reqs;
- struct brcmf_usbreq *rx_reqs;
-
- - u8 *image; /* buffer for combine fw and nvram */
- + const u8 *image; /* buffer for combine fw and nvram */
- int image_len;
-
- struct usb_device *usbdev;
- @@ -104,10 +99,6 @@
- ulong ctl_op;
-
- struct urb *bulk_urb; /* used for FW download */
- - struct urb *intr_urb; /* URB for interrupt endpoint */
- - int intr_size; /* Size of interrupt message */
- - int interval; /* Interrupt polling interval */
- - struct intr_transfer_buf intr; /* Data buffer for interrupt endpoint */
- };
-
- static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
- @@ -531,39 +522,6 @@
- }
- }
-
- -static void
- -brcmf_usb_intr_complete(struct urb *urb)
- -{
- - struct brcmf_usbdev_info *devinfo =
- - (struct brcmf_usbdev_info *)urb->context;
- - int err;
- -
- - brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status);
- -
- - if (devinfo == NULL)
- - return;
- -
- - if (unlikely(urb->status)) {
- - if (urb->status == -ENOENT ||
- - urb->status == -ESHUTDOWN ||
- - urb->status == -ENODEV) {
- - brcmf_usb_state_change(devinfo,
- - BRCMFMAC_USB_STATE_DOWN);
- - }
- - }
- -
- - if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_DOWN) {
- - brcmf_err("intr cb when DBUS down, ignoring\n");
- - return;
- - }
- -
- - if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) {
- - err = usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
- - if (err)
- - brcmf_err("usb_submit_urb, err=%d\n", err);
- - }
- -}
- -
- static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
- {
- struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
- @@ -619,7 +577,6 @@
- {
- struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
- u16 ifnum;
- - int ret;
-
- brcmf_dbg(USB, "Enter\n");
- if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP)
- @@ -628,23 +585,6 @@
- /* Success, indicate devinfo is fully up */
- brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_UP);
-
- - if (devinfo->intr_urb) {
- - usb_fill_int_urb(devinfo->intr_urb, devinfo->usbdev,
- - devinfo->intr_pipe,
- - &devinfo->intr,
- - devinfo->intr_size,
- - (usb_complete_t)brcmf_usb_intr_complete,
- - devinfo,
- - devinfo->interval);
- -
- - ret = usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
- - if (ret) {
- - brcmf_err("USB_SUBMIT_URB failed with status %d\n",
- - ret);
- - return -EINVAL;
- - }
- - }
- -
- if (devinfo->ctl_urb) {
- devinfo->ctl_in_pipe = usb_rcvctrlpipe(devinfo->usbdev, 0);
- devinfo->ctl_out_pipe = usb_sndctrlpipe(devinfo->usbdev, 0);
- @@ -681,8 +621,6 @@
- return;
-
- brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_DOWN);
- - if (devinfo->intr_urb)
- - usb_kill_urb(devinfo->intr_urb);
-
- if (devinfo->ctl_urb)
- usb_kill_urb(devinfo->ctl_urb);
- @@ -1021,7 +959,7 @@
- }
-
- err = brcmf_usb_dlstart(devinfo,
- - devinfo->image, devinfo->image_len);
- + (u8 *)devinfo->image, devinfo->image_len);
- if (err == 0)
- err = brcmf_usb_dlrun(devinfo);
- return err;
- @@ -1036,7 +974,6 @@
- brcmf_usb_free_q(&devinfo->rx_freeq, false);
- brcmf_usb_free_q(&devinfo->tx_freeq, false);
-
- - usb_free_urb(devinfo->intr_urb);
- usb_free_urb(devinfo->ctl_urb);
- usb_free_urb(devinfo->bulk_urb);
-
- @@ -1080,68 +1017,20 @@
- return -1;
- }
-
- -static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
- +static const char *brcmf_usb_get_fwname(struct brcmf_usbdev_info *devinfo)
- {
- - s8 *fwname;
- - const struct firmware *fw;
- - struct brcmf_usb_image *fw_image;
- - int err;
- -
- - brcmf_dbg(USB, "Enter\n");
- switch (devinfo->bus_pub.devid) {
- case 43143:
- - fwname = BRCMF_USB_43143_FW_NAME;
- - break;
- + return BRCMF_USB_43143_FW_NAME;
- case 43235:
- case 43236:
- case 43238:
- - fwname = BRCMF_USB_43236_FW_NAME;
- - break;
- + return BRCMF_USB_43236_FW_NAME;
- case 43242:
- - fwname = BRCMF_USB_43242_FW_NAME;
- - break;
- + return BRCMF_USB_43242_FW_NAME;
- default:
- - return -EINVAL;
- - break;
- - }
- - brcmf_dbg(USB, "Loading FW %s\n", fwname);
- - list_for_each_entry(fw_image, &fw_image_list, list) {
- - if (fw_image->fwname == fwname) {
- - devinfo->image = fw_image->image;
- - devinfo->image_len = fw_image->image_len;
- - return 0;
- - }
- - }
- - /* fw image not yet loaded. Load it now and add to list */
- - err = request_firmware(&fw, fwname, devinfo->dev);
- - if (!fw) {
- - brcmf_err("fail to request firmware %s\n", fwname);
- - return err;
- - }
- - if (check_file(fw->data) < 0) {
- - brcmf_err("invalid firmware %s\n", fwname);
- - return -EINVAL;
- + return NULL;
- }
- -
- - fw_image = kzalloc(sizeof(*fw_image), GFP_ATOMIC);
- - if (!fw_image)
- - return -ENOMEM;
- - INIT_LIST_HEAD(&fw_image->list);
- - list_add_tail(&fw_image->list, &fw_image_list);
- - fw_image->fwname = fwname;
- - fw_image->image = vmalloc(fw->size);
- - if (!fw_image->image)
- - return -ENOMEM;
- -
- - memcpy(fw_image->image, fw->data, fw->size);
- - fw_image->image_len = fw->size;
- -
- - release_firmware(fw);
- -
- - devinfo->image = fw_image->image;
- - devinfo->image_len = fw_image->image_len;
- -
- - return 0;
- }
-
-
- @@ -1186,11 +1075,6 @@
- goto error;
- devinfo->tx_freecount = ntxq;
-
- - devinfo->intr_urb = usb_alloc_urb(0, GFP_ATOMIC);
- - if (!devinfo->intr_urb) {
- - brcmf_err("usb_alloc_urb (intr) failed\n");
- - goto error;
- - }
- devinfo->ctl_urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!devinfo->ctl_urb) {
- brcmf_err("usb_alloc_urb (ctl) failed\n");
- @@ -1202,16 +1086,6 @@
- goto error;
- }
-
- - if (!brcmf_usb_dlneeded(devinfo))
- - return &devinfo->bus_pub;
- -
- - brcmf_dbg(USB, "Start fw downloading\n");
- - if (brcmf_usb_get_fw(devinfo))
- - goto error;
- -
- - if (brcmf_usb_fw_download(devinfo))
- - goto error;
- -
- return &devinfo->bus_pub;
-
- error:
- @@ -1222,18 +1096,77 @@
-
- static struct brcmf_bus_ops brcmf_usb_bus_ops = {
- .txdata = brcmf_usb_tx,
- - .init = brcmf_usb_up,
- .stop = brcmf_usb_down,
- .txctl = brcmf_usb_tx_ctlpkt,
- .rxctl = brcmf_usb_rx_ctlpkt,
- };
-
- +static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo)
- +{
- + int ret;
- +
- + /* Attach to the common driver interface */
- + ret = brcmf_attach(devinfo->dev);
- + if (ret) {
- + brcmf_err("brcmf_attach failed\n");
- + return ret;
- + }
- +
- + ret = brcmf_usb_up(devinfo->dev);
- + if (ret)
- + goto fail;
- +
- + ret = brcmf_bus_start(devinfo->dev);
- + if (ret)
- + goto fail;
- +
- + return 0;
- +fail:
- + brcmf_detach(devinfo->dev);
- + return ret;
- +}
- +
- +static void brcmf_usb_probe_phase2(struct device *dev,
- + const struct firmware *fw,
- + void *nvram, u32 nvlen)
- +{
- + struct brcmf_bus *bus = dev_get_drvdata(dev);
- + struct brcmf_usbdev_info *devinfo;
- + int ret;
- +
- + brcmf_dbg(USB, "Start fw downloading\n");
- + ret = check_file(fw->data);
- + if (ret < 0) {
- + brcmf_err("invalid firmware\n");
- + release_firmware(fw);
- + goto error;
- + }
- +
- + devinfo = bus->bus_priv.usb->devinfo;
- + devinfo->image = fw->data;
- + devinfo->image_len = fw->size;
- +
- + ret = brcmf_usb_fw_download(devinfo);
- + release_firmware(fw);
- + if (ret)
- + goto error;
- +
- + ret = brcmf_usb_bus_setup(devinfo);
- + if (ret)
- + goto error;
- +
- + return;
- +error:
- + brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), ret);
- + device_release_driver(dev);
- +}
- +
- static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
- {
- struct brcmf_bus *bus = NULL;
- struct brcmf_usbdev *bus_pub = NULL;
- - int ret;
- struct device *dev = devinfo->dev;
- + int ret;
-
- brcmf_dbg(USB, "Enter\n");
- bus_pub = brcmf_usb_attach(devinfo, BRCMF_USB_NRXQ, BRCMF_USB_NTXQ);
- @@ -1254,22 +1187,18 @@
- bus->chip = bus_pub->devid;
- bus->chiprev = bus_pub->chiprev;
- bus->proto_type = BRCMF_PROTO_BCDC;
- + bus->always_use_fws_queue = true;
-
- - /* Attach to the common driver interface */
- - ret = brcmf_attach(dev);
- - if (ret) {
- - brcmf_err("brcmf_attach failed\n");
- - goto fail;
- - }
- -
- - ret = brcmf_bus_start(dev);
- - if (ret) {
- - brcmf_err("dongle is not responding\n");
- - brcmf_detach(dev);
- - goto fail;
- + if (!brcmf_usb_dlneeded(devinfo)) {
- + ret = brcmf_usb_bus_setup(devinfo);
- + if (ret)
- + goto fail;
- }
- -
- + /* request firmware here */
- + brcmf_fw_get_firmwares(dev, 0, brcmf_usb_get_fwname(devinfo), NULL,
- + brcmf_usb_probe_phase2);
- return 0;
- +
- fail:
- /* Release resources in reverse order */
- kfree(bus);
- @@ -1357,9 +1286,6 @@
- goto fail;
- }
-
- - endpoint_num = endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
- - devinfo->intr_pipe = usb_rcvintpipe(usb, endpoint_num);
- -
- devinfo->rx_pipe = 0;
- devinfo->rx_pipe2 = 0;
- devinfo->tx_pipe = 0;
- @@ -1391,16 +1317,9 @@
- }
- }
-
- - /* Allocate interrupt URB and data buffer */
- - /* RNDIS says 8-byte intr, our old drivers used 4-byte */
- - if (IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize == cpu_to_le16(16))
- - devinfo->intr_size = 8;
- - else
- - devinfo->intr_size = 4;
- -
- - devinfo->interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval;
- -
- - if (usb->speed == USB_SPEED_HIGH)
- + if (usb->speed == USB_SPEED_SUPER)
- + brcmf_dbg(USB, "Broadcom super speed USB wireless device detected\n");
- + else if (usb->speed == USB_SPEED_HIGH)
- brcmf_dbg(USB, "Broadcom high speed USB wireless device detected\n");
- else
- brcmf_dbg(USB, "Broadcom full speed USB wireless device detected\n");
- @@ -1455,23 +1374,18 @@
- struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
-
- brcmf_dbg(USB, "Enter\n");
- - if (!brcmf_attach(devinfo->dev))
- - return brcmf_bus_start(&usb->dev);
- -
- - return 0;
- + return brcmf_usb_bus_setup(devinfo);
- }
-
- static int brcmf_usb_reset_resume(struct usb_interface *intf)
- {
- struct usb_device *usb = interface_to_usbdev(intf);
- struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
- -
- brcmf_dbg(USB, "Enter\n");
-
- - if (!brcmf_usb_fw_download(devinfo))
- - return brcmf_usb_resume(intf);
- -
- - return -EIO;
- + return brcmf_fw_get_firmwares(&usb->dev, 0,
- + brcmf_usb_get_fwname(devinfo), NULL,
- + brcmf_usb_probe_phase2);
- }
-
- #define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c
- @@ -1506,16 +1420,6 @@
- .disable_hub_initiated_lpm = 1,
- };
-
- -static void brcmf_release_fw(struct list_head *q)
- -{
- - struct brcmf_usb_image *fw_image, *next;
- -
- - list_for_each_entry_safe(fw_image, next, q, list) {
- - vfree(fw_image->image);
- - list_del_init(&fw_image->list);
- - }
- -}
- -
- static int brcmf_usb_reset_device(struct device *dev, void *notused)
- {
- /* device past is the usb interface so we
- @@ -1534,12 +1438,10 @@
- ret = driver_for_each_device(drv, NULL, NULL,
- brcmf_usb_reset_device);
- usb_deregister(&brcmf_usbdrvr);
- - brcmf_release_fw(&fw_image_list);
- }
-
- void brcmf_usb_register(void)
- {
- brcmf_dbg(USB, "Enter\n");
- - INIT_LIST_HEAD(&fw_image_list);
- usb_register(&brcmf_usbdrvr);
- }
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c 2015-03-08 14:27:37.701684500 -0500
- @@ -18,6 +18,7 @@
-
- #include <linux/kernel.h>
- #include <linux/etherdevice.h>
- +#include <linux/module.h>
- #include <net/cfg80211.h>
- #include <net/netlink.h>
-
- @@ -190,6 +191,7 @@
- .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
- .bitrates = wl_g_rates,
- .n_bitrates = wl_g_rates_size,
- + .ht_cap = {IEEE80211_HT_CAP_SUP_WIDTH_20_40, true},
- };
-
- static struct ieee80211_supported_band __wl_band_5ghz_a = {
- @@ -219,9 +221,9 @@
- */
- REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
- /* IEEE 802.11a, channel 36..64 */
- - REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
- + REG_RULE(5150-10, 5350+10, 80, 6, 20, 0),
- /* IEEE 802.11a, channel 100..165 */
- - REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
- + REG_RULE(5470-10, 5850+10, 80, 6, 20, 0), }
- };
-
- static const u32 __wl_cipher_suites[] = {
- @@ -251,6 +253,10 @@
- struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT];
- };
-
- +static int brcmf_roamoff;
- +module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR);
- +MODULE_PARM_DESC(roamoff, "do not use internal roaming engine");
- +
- /* Quarter dBm units to mW
- * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
- * Table is offset so the last entry is largest mW value that fits in
- @@ -335,6 +341,61 @@
- return qdbm;
- }
-
- +static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
- + struct cfg80211_chan_def *ch)
- +{
- + struct brcmu_chan ch_inf;
- + s32 primary_offset;
- +
- + brcmf_dbg(TRACE, "chandef: control %d center %d width %d\n",
- + ch->chan->center_freq, ch->center_freq1, ch->width);
- + ch_inf.chnum = ieee80211_frequency_to_channel(ch->center_freq1);
- + primary_offset = ch->center_freq1 - ch->chan->center_freq;
- + switch (ch->width) {
- + case NL80211_CHAN_WIDTH_20_NOHT:
- + case NL80211_CHAN_WIDTH_20:
- + ch_inf.bw = BRCMU_CHAN_BW_20;
- + WARN_ON(primary_offset != 0);
- + break;
- + case NL80211_CHAN_WIDTH_40:
- + ch_inf.bw = BRCMU_CHAN_BW_40;
- + if (primary_offset < 0)
- + ch_inf.sb = BRCMU_CHAN_SB_U;
- + else
- + ch_inf.sb = BRCMU_CHAN_SB_L;
- + break;
- + case NL80211_CHAN_WIDTH_80:
- + ch_inf.bw = BRCMU_CHAN_BW_80;
- + if (primary_offset < 0) {
- + if (primary_offset < -CH_10MHZ_APART)
- + ch_inf.sb = BRCMU_CHAN_SB_UU;
- + else
- + ch_inf.sb = BRCMU_CHAN_SB_UL;
- + } else {
- + if (primary_offset > CH_10MHZ_APART)
- + ch_inf.sb = BRCMU_CHAN_SB_LL;
- + else
- + ch_inf.sb = BRCMU_CHAN_SB_LU;
- + }
- + break;
- + default:
- + WARN_ON_ONCE(1);
- + }
- + switch (ch->chan->band) {
- + case IEEE80211_BAND_2GHZ:
- + ch_inf.band = BRCMU_CHAN_BAND_2G;
- + break;
- + case IEEE80211_BAND_5GHZ:
- + ch_inf.band = BRCMU_CHAN_BAND_5G;
- + break;
- + default:
- + WARN_ON_ONCE(1);
- + }
- + d11inf->encchspec(&ch_inf);
- +
- + return ch_inf.chspec;
- +}
- +
- u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
- struct ieee80211_channel *ch)
- {
- @@ -351,13 +412,11 @@
- * triples, returning a pointer to the substring whose first element
- * matches tag
- */
- -struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
- +const struct brcmf_tlv *
- +brcmf_parse_tlvs(const void *buf, int buflen, uint key)
- {
- - struct brcmf_tlv *elt;
- - int totlen;
- -
- - elt = (struct brcmf_tlv *)buf;
- - totlen = buflen;
- + const struct brcmf_tlv *elt = buf;
- + int totlen = buflen;
-
- /* find tagged parameter */
- while (totlen >= TLV_HDR_LEN) {
- @@ -378,8 +437,8 @@
- * not update the tlvs buffer pointer/length.
- */
- static bool
- -brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len,
- - u8 *oui, u32 oui_len, u8 type)
- +brcmf_tlv_has_ie(const u8 *ie, const u8 **tlvs, u32 *tlvs_len,
- + const u8 *oui, u32 oui_len, u8 type)
- {
- /* If the contents match the OUI and the type */
- if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
- @@ -401,12 +460,12 @@
- }
-
- static struct brcmf_vs_tlv *
- -brcmf_find_wpaie(u8 *parse, u32 len)
- +brcmf_find_wpaie(const u8 *parse, u32 len)
- {
- - struct brcmf_tlv *ie;
- + const struct brcmf_tlv *ie;
-
- while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {
- - if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len,
- + if (brcmf_tlv_has_ie((const u8 *)ie, &parse, &len,
- WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE))
- return (struct brcmf_vs_tlv *)ie;
- }
- @@ -414,9 +473,9 @@
- }
-
- static struct brcmf_vs_tlv *
- -brcmf_find_wpsie(u8 *parse, u32 len)
- +brcmf_find_wpsie(const u8 *parse, u32 len)
- {
- - struct brcmf_tlv *ie;
- + const struct brcmf_tlv *ie;
-
- while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {
- if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len,
- @@ -491,6 +550,19 @@
- return err;
- }
-
- +static bool brcmf_is_apmode(struct brcmf_cfg80211_vif *vif)
- +{
- + enum nl80211_iftype iftype;
- +
- + iftype = vif->wdev.iftype;
- + return iftype == NL80211_IFTYPE_AP || iftype == NL80211_IFTYPE_P2P_GO;
- +}
- +
- +static bool brcmf_is_ibssmode(struct brcmf_cfg80211_vif *vif)
- +{
- + return vif->wdev.iftype == NL80211_IFTYPE_ADHOC;
- +}
- +
- static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,
- const char *name,
- enum nl80211_iftype type,
- @@ -569,6 +641,9 @@
- if (err)
- brcmf_err("Scan abort failed\n");
- }
- +
- + brcmf_set_mpc(ifp, 1);
- +
- /*
- * e-scan can be initiated by scheduled scan
- * which takes precedence.
- @@ -578,12 +653,10 @@
- cfg->sched_escan = false;
- if (!aborted)
- cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
- - brcmf_set_mpc(ifp, 1);
- } else if (scan_request) {
- brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n",
- aborted ? "Aborted" : "Done");
- cfg80211_scan_done(scan_request, aborted);
- - brcmf_set_mpc(ifp, 1);
- }
- if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status))
- brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n");
- @@ -651,7 +724,6 @@
- type);
- return -EOPNOTSUPP;
- case NL80211_IFTYPE_ADHOC:
- - vif->mode = WL_MODE_IBSS;
- infra = 0;
- break;
- case NL80211_IFTYPE_STATION:
- @@ -667,12 +739,10 @@
- */
- return 0;
- }
- - vif->mode = WL_MODE_BSS;
- infra = 1;
- break;
- case NL80211_IFTYPE_AP:
- case NL80211_IFTYPE_P2P_GO:
- - vif->mode = WL_MODE_AP;
- ap = 1;
- break;
- default:
- @@ -696,7 +766,7 @@
- err = -EAGAIN;
- goto done;
- }
- - brcmf_dbg(INFO, "IF Type = %s\n", (vif->mode == WL_MODE_IBSS) ?
- + brcmf_dbg(INFO, "IF Type = %s\n", brcmf_is_ibssmode(vif) ?
- "Adhoc" : "Infra");
- }
- ndev->ieee80211_ptr->iftype = type;
- @@ -1222,8 +1292,8 @@
- params->chandef.chan->center_freq);
- if (params->channel_fixed) {
- /* adding chanspec */
- - chanspec = channel_to_chanspec(&cfg->d11inf,
- - params->chandef.chan);
- + chanspec = chandef_to_chanspec(&cfg->d11inf,
- + ¶ms->chandef);
- join_params.params_le.chanspec_list[0] =
- cpu_to_le16(chanspec);
- join_params.params_le.chanspec_num = cpu_to_le32(1);
- @@ -1340,13 +1410,14 @@
- }
-
- static s32
- -brcmf_set_set_cipher(struct net_device *ndev,
- - struct cfg80211_connect_params *sme)
- +brcmf_set_wsec_mode(struct net_device *ndev,
- + struct cfg80211_connect_params *sme, bool mfp)
- {
- struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
- struct brcmf_cfg80211_security *sec;
- s32 pval = 0;
- s32 gval = 0;
- + s32 wsec;
- s32 err = 0;
-
- if (sme->crypto.n_ciphers_pairwise) {
- @@ -1398,7 +1469,12 @@
- if (brcmf_find_wpsie(sme->ie, sme->ie_len) && !pval && !gval &&
- sme->privacy)
- pval = AES_ENABLED;
- - err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wsec", pval | gval);
- +
- + if (mfp)
- + wsec = pval | gval | MFP_CAPABLE;
- + else
- + wsec = pval | gval;
- + err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wsec", wsec);
- if (err) {
- brcmf_err("error (%d)\n", err);
- return err;
- @@ -1562,13 +1638,12 @@
- struct ieee80211_channel *chan = sme->channel;
- struct brcmf_join_params join_params;
- size_t join_params_size;
- - struct brcmf_tlv *rsn_ie;
- - struct brcmf_vs_tlv *wpa_ie;
- - void *ie;
- + const struct brcmf_tlv *rsn_ie;
- + const struct brcmf_vs_tlv *wpa_ie;
- + const void *ie;
- u32 ie_len;
- struct brcmf_ext_join_params_le *ext_join_params;
- u16 chanspec;
- -
- s32 err = 0;
-
- brcmf_dbg(TRACE, "Enter\n");
- @@ -1591,7 +1666,8 @@
- ie_len = wpa_ie->len + TLV_HDR_LEN;
- } else {
- /* find the RSN_IE */
- - rsn_ie = brcmf_parse_tlvs((u8 *)sme->ie, sme->ie_len,
- + rsn_ie = brcmf_parse_tlvs((const u8 *)sme->ie,
- + sme->ie_len,
- WLAN_EID_RSN);
- if (rsn_ie) {
- ie = rsn_ie;
- @@ -1636,7 +1712,7 @@
- goto done;
- }
-
- - err = brcmf_set_set_cipher(ndev, sme);
- + err = brcmf_set_wsec_mode(ndev, sme, sme->mfp == NL80211_MFP_REQUIRED);
- if (err) {
- brcmf_err("wl_set_set_cipher failed (%d)\n", err);
- goto done;
- @@ -1678,22 +1754,9 @@
- ext_join_params->ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len);
- memcpy(&ext_join_params->ssid_le.SSID, sme->ssid,
- profile->ssid.SSID_len);
- - /*increase dwell time to receive probe response or detect Beacon
- - * from target AP at a noisy air only during connect command
- - */
- - ext_join_params->scan_le.active_time =
- - cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS);
- - ext_join_params->scan_le.passive_time =
- - cpu_to_le32(BRCMF_SCAN_JOIN_PASSIVE_DWELL_TIME_MS);
- +
- /* Set up join scan parameters */
- ext_join_params->scan_le.scan_type = -1;
- - /* to sync with presence period of VSDB GO.
- - * Send probe request more frequently. Probe request will be stopped
- - * when it gets probe response from target AP/GO.
- - */
- - ext_join_params->scan_le.nprobes =
- - cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS /
- - BRCMF_SCAN_JOIN_PROBE_INTERVAL_MS);
- ext_join_params->scan_le.home_time = cpu_to_le32(-1);
-
- if (sme->bssid)
- @@ -1706,6 +1769,25 @@
-
- ext_join_params->assoc_le.chanspec_list[0] =
- cpu_to_le16(chanspec);
- + /* Increase dwell time to receive probe response or detect
- + * beacon from target AP at a noisy air only during connect
- + * command.
- + */
- + ext_join_params->scan_le.active_time =
- + cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS);
- + ext_join_params->scan_le.passive_time =
- + cpu_to_le32(BRCMF_SCAN_JOIN_PASSIVE_DWELL_TIME_MS);
- + /* To sync with presence period of VSDB GO send probe request
- + * more frequently. Probe request will be stopped when it gets
- + * probe response from target AP/GO.
- + */
- + ext_join_params->scan_le.nprobes =
- + cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS /
- + BRCMF_SCAN_JOIN_PROBE_INTERVAL_MS);
- + } else {
- + ext_join_params->scan_le.active_time = cpu_to_le32(-1);
- + ext_join_params->scan_le.passive_time = cpu_to_le32(-1);
- + ext_join_params->scan_le.nprobes = cpu_to_le32(-1);
- }
-
- err = brcmf_fil_bsscfg_data_set(ifp, "join", ext_join_params,
- @@ -1913,7 +1995,7 @@
- brcmf_dbg(CONN, "Setting the key index %d\n", key.index);
- memcpy(key.data, params->key, key.len);
-
- - if ((ifp->vif->mode != WL_MODE_AP) &&
- + if (!brcmf_is_apmode(ifp->vif) &&
- (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
- brcmf_dbg(CONN, "Swapping RX/TX MIC key\n");
- memcpy(keybuf, &key.data[24], sizeof(keybuf));
- @@ -1981,7 +2063,9 @@
- if (!check_vif_up(ifp->vif))
- return -EIO;
-
- - if (mac_addr) {
- + if (mac_addr &&
- + (params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
- + (params->cipher != WLAN_CIPHER_SUITE_WEP104)) {
- brcmf_dbg(TRACE, "Exit");
- return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params);
- }
- @@ -2010,7 +2094,7 @@
- brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
- break;
- case WLAN_CIPHER_SUITE_TKIP:
- - if (ifp->vif->mode != WL_MODE_AP) {
- + if (!brcmf_is_apmode(ifp->vif)) {
- brcmf_dbg(CONN, "Swapping RX/TX MIC key\n");
- memcpy(keybuf, &key.data[24], sizeof(keybuf));
- memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
- @@ -2164,12 +2248,14 @@
- s32 err = 0;
- u8 *bssid = profile->bssid;
- struct brcmf_sta_info_le sta_info_le;
- + u32 beacon_period;
- + u32 dtim_period;
-
- brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
- if (!check_vif_up(ifp->vif))
- return -EIO;
-
- - if (ifp->vif->mode == WL_MODE_AP) {
- + if (brcmf_is_apmode(ifp->vif)) {
- memcpy(&sta_info_le, mac, ETH_ALEN);
- err = brcmf_fil_iovar_data_get(ifp, "sta_info",
- &sta_info_le,
- @@ -2186,7 +2272,7 @@
- }
- brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n",
- sinfo->inactive_time, sinfo->connected_time);
- - } else if (ifp->vif->mode == WL_MODE_BSS) {
- + } else if (ifp->vif->wdev.iftype == NL80211_IFTYPE_STATION) {
- if (memcmp(mac, bssid, ETH_ALEN)) {
- brcmf_err("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n",
- mac, bssid);
- @@ -2218,6 +2304,30 @@
- sinfo->signal = rssi;
- brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);
- }
- + err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_BCNPRD,
- + &beacon_period);
- + if (err) {
- + brcmf_err("Could not get beacon period (%d)\n",
- + err);
- + goto done;
- + } else {
- + sinfo->bss_param.beacon_interval =
- + beacon_period;
- + brcmf_dbg(CONN, "Beacon peroid %d\n",
- + beacon_period);
- + }
- + err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_DTIMPRD,
- + &dtim_period);
- + if (err) {
- + brcmf_err("Could not get DTIM period (%d)\n",
- + err);
- + goto done;
- + } else {
- + sinfo->bss_param.dtim_period = dtim_period;
- + brcmf_dbg(CONN, "DTIM peroid %d\n",
- + dtim_period);
- + }
- + sinfo->filled |= STATION_INFO_BSS_PARAM;
- }
- } else
- err = -EPERM;
- @@ -2444,18 +2554,13 @@
- return err;
- }
-
- -static bool brcmf_is_ibssmode(struct brcmf_cfg80211_vif *vif)
- -{
- - return vif->mode == WL_MODE_IBSS;
- -}
- -
- static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,
- struct brcmf_if *ifp)
- {
- struct brcmf_cfg80211_profile *profile = ndev_to_prof(ifp->ndev);
- struct brcmf_bss_info_le *bi;
- struct brcmf_ssid *ssid;
- - struct brcmf_tlv *tim;
- + const struct brcmf_tlv *tim;
- u16 beacon_interval;
- u8 dtim_period;
- size_t ie_len;
- @@ -3075,7 +3180,7 @@
- }
-
- if (!request->n_ssids || !request->n_match_sets) {
- - brcmf_err("Invalid sched scan req!! n_ssids:%d\n",
- + brcmf_dbg(SCAN, "Invalid sched scan req!! n_ssids:%d\n",
- request->n_ssids);
- return -EINVAL;
- }
- @@ -3220,8 +3325,9 @@
- }
-
- static s32
- -brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
- - bool is_rsn_ie)
- +brcmf_configure_wpaie(struct net_device *ndev,
- + const struct brcmf_vs_tlv *wpa_ie,
- + bool is_rsn_ie)
- {
- struct brcmf_if *ifp = netdev_priv(ndev);
- u32 auth = 0; /* d11 open authentication */
- @@ -3684,42 +3790,26 @@
- }
-
- static s32
- -brcmf_cfg80211_set_channel(struct brcmf_cfg80211_info *cfg,
- - struct brcmf_if *ifp,
- - struct ieee80211_channel *channel)
- -{
- - u16 chanspec;
- - s32 err;
- -
- - brcmf_dbg(TRACE, "band=%d, center_freq=%d\n", channel->band,
- - channel->center_freq);
- -
- - chanspec = channel_to_chanspec(&cfg->d11inf, channel);
- - err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
- -
- - return err;
- -}
- -
- -static s32
- brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
- struct cfg80211_ap_settings *settings)
- {
- s32 ie_offset;
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- struct brcmf_if *ifp = netdev_priv(ndev);
- - struct brcmf_tlv *ssid_ie;
- + const struct brcmf_tlv *ssid_ie;
- struct brcmf_ssid_le ssid_le;
- s32 err = -EPERM;
- - struct brcmf_tlv *rsn_ie;
- - struct brcmf_vs_tlv *wpa_ie;
- + const struct brcmf_tlv *rsn_ie;
- + const struct brcmf_vs_tlv *wpa_ie;
- struct brcmf_join_params join_params;
- enum nl80211_iftype dev_role;
- struct brcmf_fil_bss_enable_le bss_enable;
- + u16 chanspec;
-
- - brcmf_dbg(TRACE, "channel_type=%d, beacon_interval=%d, dtim_period=%d,\n",
- - cfg80211_get_chandef_type(&settings->chandef),
- - settings->beacon_interval,
- - settings->dtim_period);
- + brcmf_dbg(TRACE, "ctrlchn=%d, center=%d, bw=%d, beacon_interval=%d, dtim_period=%d,\n",
- + settings->chandef.chan->hw_value,
- + settings->chandef.center_freq1, settings->chandef.width,
- + settings->beacon_interval, settings->dtim_period);
- brcmf_dbg(TRACE, "ssid=%s(%zu), auth_type=%d, inactivity_timeout=%d\n",
- settings->ssid, settings->ssid_len, settings->auth_type,
- settings->inactivity_timeout);
- @@ -3776,9 +3866,10 @@
-
- brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);
-
- - err = brcmf_cfg80211_set_channel(cfg, ifp, settings->chandef.chan);
- + chanspec = chandef_to_chanspec(&cfg->d11inf, &settings->chandef);
- + err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
- if (err < 0) {
- - brcmf_err("Set Channel failed, %d\n", err);
- + brcmf_err("Set Channel failed: chspec=%d, %d\n", chanspec, err);
- goto exit;
- }
-
- @@ -4220,32 +4311,6 @@
- CFG80211_TESTMODE_CMD(brcmf_cfg80211_testmode)
- };
-
- -static s32 brcmf_nl80211_iftype_to_mode(enum nl80211_iftype type)
- -{
- - switch (type) {
- - case NL80211_IFTYPE_AP_VLAN:
- - case NL80211_IFTYPE_WDS:
- - case NL80211_IFTYPE_MONITOR:
- - case NL80211_IFTYPE_MESH_POINT:
- - return -ENOTSUPP;
- - case NL80211_IFTYPE_ADHOC:
- - return WL_MODE_IBSS;
- - case NL80211_IFTYPE_STATION:
- - case NL80211_IFTYPE_P2P_CLIENT:
- - return WL_MODE_BSS;
- - case NL80211_IFTYPE_AP:
- - case NL80211_IFTYPE_P2P_GO:
- - return WL_MODE_AP;
- - case NL80211_IFTYPE_P2P_DEVICE:
- - return WL_MODE_P2P;
- - case NL80211_IFTYPE_UNSPECIFIED:
- - default:
- - break;
- - }
- -
- - return -EINVAL;
- -}
- -
- static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
- {
- /* scheduled scan settings */
- @@ -4340,6 +4405,8 @@
- WIPHY_FLAG_OFFCHAN_TX |
- WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
- WIPHY_FLAG_SUPPORTS_TDLS;
- + if (!brcmf_roamoff)
- + wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
- wiphy->mgmt_stypes = brcmf_txrx_stypes;
- wiphy->max_remain_on_channel_duration = 5000;
- brcmf_wiphy_pno_params(wiphy);
- @@ -4370,7 +4437,6 @@
- vif->wdev.wiphy = cfg->wiphy;
- vif->wdev.iftype = type;
-
- - vif->mode = brcmf_nl80211_iftype_to_mode(type);
- vif->pm_block = pm_block;
- vif->roam_off = -1;
-
- @@ -4416,7 +4482,9 @@
- u32 event = e->event_code;
- u16 flags = e->flags;
-
- - if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) {
- + if ((event == BRCMF_E_DEAUTH) || (event == BRCMF_E_DEAUTH_IND) ||
- + (event == BRCMF_E_DISASSOC_IND) ||
- + ((event == BRCMF_E_LINK) && (!(flags & BRCMF_EVENT_MSG_LINK)))) {
- brcmf_dbg(CONN, "Processing link down\n");
- return true;
- }
- @@ -4658,16 +4726,18 @@
- struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
- struct net_device *ndev = ifp->ndev;
- struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
- + struct ieee80211_channel *chan;
- s32 err = 0;
-
- - if (ifp->vif->mode == WL_MODE_AP) {
- + if (brcmf_is_apmode(ifp->vif)) {
- err = brcmf_notify_connect_status_ap(cfg, ndev, e, data);
- } else if (brcmf_is_linkup(e)) {
- brcmf_dbg(CONN, "Linkup\n");
- if (brcmf_is_ibssmode(ifp->vif)) {
- + chan = ieee80211_get_channel(cfg->wiphy, cfg->channel);
- memcpy(profile->bssid, e->addr, ETH_ALEN);
- wl_inform_ibss(cfg, ndev, e->addr);
- - cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
- + cfg80211_ibss_joined(ndev, e->addr, chan, GFP_KERNEL);
- clear_bit(BRCMF_VIF_STATUS_CONNECTING,
- &ifp->vif->sme_state);
- set_bit(BRCMF_VIF_STATUS_CONNECTED,
- @@ -4678,10 +4748,6 @@
- brcmf_dbg(CONN, "Linkdown\n");
- if (!brcmf_is_ibssmode(ifp->vif)) {
- brcmf_bss_connect_done(cfg, ndev, e, false);
- - if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED,
- - &ifp->vif->sme_state))
- - cfg80211_disconnected(ndev, 0, NULL, 0,
- - GFP_KERNEL);
- }
- brcmf_link_down(ifp->vif);
- brcmf_init_prof(ndev_to_prof(ndev));
- @@ -4875,11 +4941,8 @@
-
- cfg->scan_request = NULL;
- cfg->pwr_save = true;
- - cfg->roam_on = true; /* roam on & off switch.
- - we enable roam per default */
- - cfg->active_scan = true; /* we do active scan for
- - specific scan per default */
- - cfg->dongle_up = false; /* dongle is not up yet */
- + cfg->active_scan = true; /* we do active scan per default */
- + cfg->dongle_up = false; /* dongle is not up yet */
- err = brcmf_init_priv_mem(cfg);
- if (err)
- return err;
- @@ -4904,6 +4967,30 @@
- mutex_init(&event->vif_event_lock);
- }
-
- +static int brcmf_enable_bw40_2g(struct brcmf_if *ifp)
- +{
- + struct brcmf_fil_bwcap_le band_bwcap;
- + u32 val;
- + int err;
- +
- + /* verify support for bw_cap command */
- + val = WLC_BAND_5G;
- + err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &val);
- +
- + if (!err) {
- + /* only set 2G bandwidth using bw_cap command */
- + band_bwcap.band = cpu_to_le32(WLC_BAND_2G);
- + band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ);
- + err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap,
- + sizeof(band_bwcap));
- + } else {
- + brcmf_dbg(INFO, "fallback to mimo_bw_cap\n");
- + val = WLC_N_BW_40ALL;
- + err = brcmf_fil_iovar_int_set(ifp, "mimo_bw_cap", val);
- + }
- + return err;
- +}
- +
- struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
- struct device *busdev)
- {
- @@ -4961,6 +5048,17 @@
- goto cfg80211_p2p_attach_out;
- }
-
- + /* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(),
- + * setup 40MHz in 2GHz band and enable OBSS scanning.
- + */
- + if (wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap &
- + IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
- + err = brcmf_enable_bw40_2g(ifp);
- + if (!err)
- + err = brcmf_fil_iovar_int_set(ifp, "obss_coex",
- + BRCMF_OBSS_COEX_AUTO);
- + }
- +
- err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);
- if (err) {
- brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);
- @@ -4999,7 +5097,7 @@
- }
-
- static s32
- -brcmf_dongle_roam(struct brcmf_if *ifp, u32 roamvar, u32 bcn_timeout)
- +brcmf_dongle_roam(struct brcmf_if *ifp, u32 bcn_timeout)
- {
- s32 err = 0;
- __le32 roamtrigger[2];
- @@ -5009,7 +5107,7 @@
- * Setup timeout if Beacons are lost and roam is
- * off to report link down
- */
- - if (roamvar) {
- + if (brcmf_roamoff) {
- err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout);
- if (err) {
- brcmf_err("bcn_timeout error (%d)\n", err);
- @@ -5021,8 +5119,9 @@
- * Enable/Disable built-in roaming to allow supplicant
- * to take care of roaming
- */
- - brcmf_dbg(INFO, "Internal Roaming = %s\n", roamvar ? "Off" : "On");
- - err = brcmf_fil_iovar_int_set(ifp, "roam_off", roamvar);
- + brcmf_dbg(INFO, "Internal Roaming = %s\n",
- + brcmf_roamoff ? "Off" : "On");
- + err = brcmf_fil_iovar_int_set(ifp, "roam_off", !!(brcmf_roamoff));
- if (err) {
- brcmf_err("roam_off error (%d)\n", err);
- goto dongle_rom_out;
- @@ -5148,6 +5247,9 @@
- if (!(bw_cap[band] & WLC_BW_40MHZ_BIT) &&
- ch.bw == BRCMU_CHAN_BW_40)
- continue;
- + if (!(bw_cap[band] & WLC_BW_80MHZ_BIT) &&
- + ch.bw == BRCMU_CHAN_BW_80)
- + continue;
- update = false;
- for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
- if (band_chan_arr[j].hw_value == ch.chnum) {
- @@ -5164,13 +5266,13 @@
- ieee80211_channel_to_frequency(ch.chnum, band);
- band_chan_arr[index].hw_value = ch.chnum;
-
- - brcmf_err("channel %d: f=%d bw=%d sb=%d\n",
- - ch.chnum, band_chan_arr[index].center_freq,
- - ch.bw, ch.sb);
- - if (ch.bw == BRCMU_CHAN_BW_40) {
- - /* assuming the order is HT20, HT40 Upper,
- - * HT40 lower from chanspecs
- - */
- + /* assuming the chanspecs order is HT20,
- + * HT40 upper, HT40 lower, and VHT80.
- + */
- + if (ch.bw == BRCMU_CHAN_BW_80) {
- + band_chan_arr[index].flags &=
- + ~IEEE80211_CHAN_NO_80MHZ;
- + } else if (ch.bw == BRCMU_CHAN_BW_40) {
- ht40_flag = band_chan_arr[index].flags &
- IEEE80211_CHAN_NO_HT40;
- if (ch.sb == BRCMU_CHAN_SB_U) {
- @@ -5191,8 +5293,13 @@
- IEEE80211_CHAN_NO_HT40MINUS;
- }
- } else {
- + /* disable other bandwidths for now as mentioned
- + * order assure they are enabled for subsequent
- + * chanspecs.
- + */
- band_chan_arr[index].flags =
- - IEEE80211_CHAN_NO_HT40;
- + IEEE80211_CHAN_NO_HT40 |
- + IEEE80211_CHAN_NO_80MHZ;
- ch.bw = BRCMU_CHAN_BW_20;
- cfg->d11inf.encchspec(&ch);
- channel = ch.chspec;
- @@ -5259,14 +5366,66 @@
- }
- }
-
- +static void brcmf_update_ht_cap(struct ieee80211_supported_band *band,
- + u32 bw_cap[2], u32 nchain)
- +{
- + band->ht_cap.ht_supported = true;
- + if (bw_cap[band->band] & WLC_BW_40MHZ_BIT) {
- + band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
- + band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- + }
- + band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
- + band->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
- + band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
- + band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
- + memset(band->ht_cap.mcs.rx_mask, 0xff, nchain);
- + band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
- +}
- +
- +static __le16 brcmf_get_mcs_map(u32 nchain, enum ieee80211_vht_mcs_support supp)
- +{
- + u16 mcs_map;
- + int i;
- +
- + for (i = 0, mcs_map = 0xFFFF; i < nchain; i++)
- + mcs_map = (mcs_map << 2) | supp;
- +
- + return cpu_to_le16(mcs_map);
- +}
- +
- +static void brcmf_update_vht_cap(struct ieee80211_supported_band *band,
- + u32 bw_cap[2], u32 nchain)
- +{
- + __le16 mcs_map;
- +
- + /* not allowed in 2.4G band */
- + if (band->band == IEEE80211_BAND_2GHZ)
- + return;
- +
- + band->vht_cap.vht_supported = true;
- + /* 80MHz is mandatory */
- + band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
- + if (bw_cap[band->band] & WLC_BW_160MHZ_BIT) {
- + band->vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
- + band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
- + }
- + /* all support 256-QAM */
- + mcs_map = brcmf_get_mcs_map(nchain, IEEE80211_VHT_MCS_SUPPORT_0_9);
- + band->vht_cap.vht_mcs.rx_mcs_map = mcs_map;
- + band->vht_cap.vht_mcs.tx_mcs_map = mcs_map;
- +}
- +
- static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
- {
- struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
- struct wiphy *wiphy;
- s32 phy_list;
- u32 band_list[3];
- - u32 nmode;
- + u32 nmode = 0;
- + u32 vhtmode = 0;
- u32 bw_cap[2] = { 0, 0 };
- + u32 rxchain;
- + u32 nchain;
- s8 phy;
- s32 err;
- u32 nband;
- @@ -5294,14 +5453,26 @@
- brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n",
- band_list[0], band_list[1], band_list[2]);
-
- + (void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode);
- err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);
- if (err) {
- brcmf_err("nmode error (%d)\n", err);
- } else {
- brcmf_get_bwcap(ifp, bw_cap);
- }
- - brcmf_dbg(INFO, "nmode=%d, bw_cap=(%d, %d)\n", nmode,
- - bw_cap[IEEE80211_BAND_2GHZ], bw_cap[IEEE80211_BAND_5GHZ]);
- + brcmf_dbg(INFO, "nmode=%d, vhtmode=%d, bw_cap=(%d, %d)\n",
- + nmode, vhtmode, bw_cap[IEEE80211_BAND_2GHZ],
- + bw_cap[IEEE80211_BAND_5GHZ]);
- +
- + err = brcmf_fil_iovar_int_get(ifp, "rxchain", &rxchain);
- + if (err) {
- + brcmf_err("rxchain error (%d)\n", err);
- + nchain = 1;
- + } else {
- + for (nchain = 0; rxchain; nchain++)
- + rxchain = rxchain & (rxchain - 1);
- + }
- + brcmf_dbg(INFO, "nchain=%d\n", nchain);
-
- err = brcmf_construct_reginfo(cfg, bw_cap);
- if (err) {
- @@ -5322,20 +5493,10 @@
- else
- continue;
-
- - if (bw_cap[band->band] & WLC_BW_40MHZ_BIT) {
- - band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
- - band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- - }
- - band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
- - band->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
- - band->ht_cap.ht_supported = true;
- - band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
- - band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
- - /* An HT shall support all EQM rates for one spatial
- - * stream
- - */
- - band->ht_cap.mcs.rx_mask[0] = 0xff;
- - band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
- + if (nmode)
- + brcmf_update_ht_cap(band, bw_cap, nchain);
- + if (vhtmode)
- + brcmf_update_vht_cap(band, bw_cap, nchain);
- bands[band->band] = band;
- }
-
- @@ -5381,7 +5542,7 @@
- brcmf_dbg(INFO, "power save set to %s\n",
- (power_mode ? "enabled" : "disabled"));
-
- - err = brcmf_dongle_roam(ifp, (cfg->roam_on ? 0 : 1), WL_BEACON_TIMEOUT);
- + err = brcmf_dongle_roam(ifp, WL_BEACON_TIMEOUT);
- if (err)
- goto default_conf_out;
- err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype,
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h 2015-03-08 14:27:37.701684500 -0500
- @@ -89,21 +89,6 @@
- BRCMF_SCAN_STATUS_SUPPRESS,
- };
-
- -/**
- - * enum wl_mode - driver mode of virtual interface.
- - *
- - * @WL_MODE_BSS: connects to BSS.
- - * @WL_MODE_IBSS: operate as ad-hoc.
- - * @WL_MODE_AP: operate as access-point.
- - * @WL_MODE_P2P: provide P2P discovery.
- - */
- -enum wl_mode {
- - WL_MODE_BSS,
- - WL_MODE_IBSS,
- - WL_MODE_AP,
- - WL_MODE_P2P
- -};
- -
- /* dongle configuration */
- struct brcmf_cfg80211_conf {
- u32 frag_threshold;
- @@ -193,7 +178,6 @@
- * @ifp: lower layer interface pointer
- * @wdev: wireless device.
- * @profile: profile information.
- - * @mode: operating mode.
- * @roam_off: roaming state.
- * @sme_state: SME state using enum brcmf_vif_status bits.
- * @pm_block: power-management blocked.
- @@ -204,7 +188,6 @@
- struct brcmf_if *ifp;
- struct wireless_dev wdev;
- struct brcmf_cfg80211_profile profile;
- - s32 mode;
- s32 roam_off;
- unsigned long sme_state;
- bool pm_block;
- @@ -402,7 +385,6 @@
- bool ibss_starter;
- bool pwr_save;
- bool dongle_up;
- - bool roam_on;
- bool scan_tried;
- u8 *dcmd_buf;
- u8 *extra_buf;
- @@ -491,7 +473,8 @@
- s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
- const u8 *vndr_ie_buf, u32 vndr_ie_len);
- s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif);
- -struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key);
- +const struct brcmf_tlv *
- +brcmf_parse_tlvs(const void *buf, int buflen, uint key);
- u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
- struct ieee80211_channel *ch);
- u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state);
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c linux-3.14.35/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c 2015-03-08 14:27:37.701684500 -0500
- @@ -897,7 +897,8 @@
- return result;
- }
-
- -static void brcms_ops_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
- +static void brcms_ops_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- + u32 queues, bool drop)
- {
- struct brcms_info *wl = hw->priv;
- int ret;
- @@ -1092,12 +1093,6 @@
- * Attach to the WL device identified by vendor and device parameters.
- * regs is a host accessible memory address pointing to WL device registers.
- *
- - * brcms_attach is not defined as static because in the case where no bus
- - * is defined, wl_attach will never be called, and thus, gcc will issue
- - * a warning that this function is defined but not used if we declare
- - * it as static.
- - *
- - *
- * is called in brcms_bcma_probe() context, therefore no locking required.
- */
- static struct brcms_info *brcms_attach(struct bcma_device *pdev)
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmsmac/main.c linux-3.14.35/drivers/net/wireless/brcm80211/brcmsmac/main.c
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmsmac/main.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmsmac/main.c 2015-03-08 14:27:37.701684500 -0500
- @@ -4870,14 +4870,11 @@
- /*
- * low level detach
- */
- -static int brcms_b_detach(struct brcms_c_info *wlc)
- +static void brcms_b_detach(struct brcms_c_info *wlc)
- {
- uint i;
- struct brcms_hw_band *band;
- struct brcms_hardware *wlc_hw = wlc->hw;
- - int callbacks;
- -
- - callbacks = 0;
-
- brcms_b_detach_dmapio(wlc_hw);
-
- @@ -4900,9 +4897,6 @@
- ai_detach(wlc_hw->sih);
- wlc_hw->sih = NULL;
- }
- -
- - return callbacks;
- -
- }
-
- /*
- @@ -4917,14 +4911,15 @@
- */
- uint brcms_c_detach(struct brcms_c_info *wlc)
- {
- - uint callbacks = 0;
- + uint callbacks;
-
- if (wlc == NULL)
- return 0;
-
- - callbacks += brcms_b_detach(wlc);
- + brcms_b_detach(wlc);
-
- /* delete software timers */
- + callbacks = 0;
- if (!brcms_c_radio_monitor_stop(wlc))
- callbacks++;
-
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmutil/d11.c linux-3.14.35/drivers/net/wireless/brcm80211/brcmutil/d11.c
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/brcmutil/d11.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/brcmutil/d11.c 2015-03-08 14:27:37.701684500 -0500
- @@ -21,19 +21,46 @@
- #include <brcmu_wifi.h>
- #include <brcmu_d11.h>
-
- -static void brcmu_d11n_encchspec(struct brcmu_chan *ch)
- +static u16 d11n_sb(enum brcmu_chan_sb sb)
- {
- - ch->chspec = ch->chnum & BRCMU_CHSPEC_CH_MASK;
- + switch (sb) {
- + case BRCMU_CHAN_SB_NONE:
- + return BRCMU_CHSPEC_D11N_SB_N;
- + case BRCMU_CHAN_SB_L:
- + return BRCMU_CHSPEC_D11N_SB_L;
- + case BRCMU_CHAN_SB_U:
- + return BRCMU_CHSPEC_D11N_SB_U;
- + default:
- + WARN_ON(1);
- + }
- + return 0;
- +}
-
- - switch (ch->bw) {
- +static u16 d11n_bw(enum brcmu_chan_bw bw)
- +{
- + switch (bw) {
- case BRCMU_CHAN_BW_20:
- - ch->chspec |= BRCMU_CHSPEC_D11N_BW_20 | BRCMU_CHSPEC_D11N_SB_N;
- - break;
- + return BRCMU_CHSPEC_D11N_BW_20;
- case BRCMU_CHAN_BW_40:
- + return BRCMU_CHSPEC_D11N_BW_40;
- default:
- - WARN_ON_ONCE(1);
- - break;
- + WARN_ON(1);
- }
- + return 0;
- +}
- +
- +static void brcmu_d11n_encchspec(struct brcmu_chan *ch)
- +{
- + if (ch->bw == BRCMU_CHAN_BW_20)
- + ch->sb = BRCMU_CHAN_SB_NONE;
- +
- + ch->chspec = 0;
- + brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_CH_MASK,
- + BRCMU_CHSPEC_CH_SHIFT, ch->chnum);
- + brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11N_SB_MASK,
- + 0, d11n_sb(ch->sb));
- + brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11N_BW_MASK,
- + 0, d11n_bw(ch->bw));
-
- if (ch->chnum <= CH_MAX_2G_CHANNEL)
- ch->chspec |= BRCMU_CHSPEC_D11N_BND_2G;
- @@ -41,23 +68,34 @@
- ch->chspec |= BRCMU_CHSPEC_D11N_BND_5G;
- }
-
- -static void brcmu_d11ac_encchspec(struct brcmu_chan *ch)
- +static u16 d11ac_bw(enum brcmu_chan_bw bw)
- {
- - ch->chspec = ch->chnum & BRCMU_CHSPEC_CH_MASK;
- -
- - switch (ch->bw) {
- + switch (bw) {
- case BRCMU_CHAN_BW_20:
- - ch->chspec |= BRCMU_CHSPEC_D11AC_BW_20;
- - break;
- + return BRCMU_CHSPEC_D11AC_BW_20;
- case BRCMU_CHAN_BW_40:
- + return BRCMU_CHSPEC_D11AC_BW_40;
- case BRCMU_CHAN_BW_80:
- - case BRCMU_CHAN_BW_80P80:
- - case BRCMU_CHAN_BW_160:
- + return BRCMU_CHSPEC_D11AC_BW_80;
- default:
- - WARN_ON_ONCE(1);
- - break;
- + WARN_ON(1);
- }
- + return 0;
- +}
-
- +static void brcmu_d11ac_encchspec(struct brcmu_chan *ch)
- +{
- + if (ch->bw == BRCMU_CHAN_BW_20 || ch->sb == BRCMU_CHAN_SB_NONE)
- + ch->sb = BRCMU_CHAN_SB_L;
- +
- + brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_CH_MASK,
- + BRCMU_CHSPEC_CH_SHIFT, ch->chnum);
- + brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK,
- + BRCMU_CHSPEC_D11AC_SB_SHIFT, ch->sb);
- + brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11AC_BW_MASK,
- + 0, d11ac_bw(ch->bw));
- +
- + ch->chspec &= ~BRCMU_CHSPEC_D11AC_BND_MASK;
- if (ch->chnum <= CH_MAX_2G_CHANNEL)
- ch->chspec |= BRCMU_CHSPEC_D11AC_BND_2G;
- else
- @@ -73,6 +111,7 @@
- switch (ch->chspec & BRCMU_CHSPEC_D11N_BW_MASK) {
- case BRCMU_CHSPEC_D11N_BW_20:
- ch->bw = BRCMU_CHAN_BW_20;
- + ch->sb = BRCMU_CHAN_SB_NONE;
- break;
- case BRCMU_CHSPEC_D11N_BW_40:
- ch->bw = BRCMU_CHAN_BW_40;
- @@ -112,6 +151,7 @@
- switch (ch->chspec & BRCMU_CHSPEC_D11AC_BW_MASK) {
- case BRCMU_CHSPEC_D11AC_BW_20:
- ch->bw = BRCMU_CHAN_BW_20;
- + ch->sb = BRCMU_CHAN_SB_NONE;
- break;
- case BRCMU_CHSPEC_D11AC_BW_40:
- ch->bw = BRCMU_CHAN_BW_40;
- @@ -128,6 +168,25 @@
- break;
- case BRCMU_CHSPEC_D11AC_BW_80:
- ch->bw = BRCMU_CHAN_BW_80;
- + ch->sb = brcmu_maskget16(ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK,
- + BRCMU_CHSPEC_D11AC_SB_SHIFT);
- + switch (ch->sb) {
- + case BRCMU_CHAN_SB_LL:
- + ch->chnum -= CH_30MHZ_APART;
- + break;
- + case BRCMU_CHAN_SB_LU:
- + ch->chnum -= CH_10MHZ_APART;
- + break;
- + case BRCMU_CHAN_SB_UL:
- + ch->chnum += CH_10MHZ_APART;
- + break;
- + case BRCMU_CHAN_SB_UU:
- + ch->chnum += CH_30MHZ_APART;
- + break;
- + default:
- + WARN_ON_ONCE(1);
- + break;
- + }
- break;
- case BRCMU_CHSPEC_D11AC_BW_8080:
- case BRCMU_CHSPEC_D11AC_BW_160:
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h linux-3.14.35/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h 2015-03-08 14:27:37.701684500 -0500
- @@ -43,5 +43,6 @@
- #define BCM4335_CHIP_ID 0x4335
- #define BCM43362_CHIP_ID 43362
- #define BCM4339_CHIP_ID 0x4339
- +#define BCM4354_CHIP_ID 0x4354
-
- #endif /* _BRCM_HW_IDS_H_ */
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/include/brcmu_d11.h linux-3.14.35/drivers/net/wireless/brcm80211/include/brcmu_d11.h
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/include/brcmu_d11.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/include/brcmu_d11.h 2015-03-08 14:27:37.701684500 -0500
- @@ -108,13 +108,7 @@
- };
-
- enum brcmu_chan_sb {
- - BRCMU_CHAN_SB_NONE = 0,
- - BRCMU_CHAN_SB_L,
- - BRCMU_CHAN_SB_U,
- - BRCMU_CHAN_SB_LL,
- - BRCMU_CHAN_SB_LU,
- - BRCMU_CHAN_SB_UL,
- - BRCMU_CHAN_SB_UU,
- + BRCMU_CHAN_SB_NONE = -1,
- BRCMU_CHAN_SB_LLL,
- BRCMU_CHAN_SB_LLU,
- BRCMU_CHAN_SB_LUL,
- @@ -123,6 +117,12 @@
- BRCMU_CHAN_SB_ULU,
- BRCMU_CHAN_SB_UUL,
- BRCMU_CHAN_SB_UUU,
- + BRCMU_CHAN_SB_L = BRCMU_CHAN_SB_LLL,
- + BRCMU_CHAN_SB_U = BRCMU_CHAN_SB_LLU,
- + BRCMU_CHAN_SB_LL = BRCMU_CHAN_SB_LLL,
- + BRCMU_CHAN_SB_LU = BRCMU_CHAN_SB_LLU,
- + BRCMU_CHAN_SB_UL = BRCMU_CHAN_SB_LUL,
- + BRCMU_CHAN_SB_UU = BRCMU_CHAN_SB_LUU,
- };
-
- struct brcmu_chan {
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/brcm80211/include/brcmu_wifi.h linux-3.14.35/drivers/net/wireless/brcm80211/include/brcmu_wifi.h
- --- linux-3.14.35.orig/drivers/net/wireless/brcm80211/include/brcmu_wifi.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/brcm80211/include/brcmu_wifi.h 2015-03-08 14:27:37.701684500 -0500
- @@ -29,6 +29,7 @@
- #define CH_UPPER_SB 0x01
- #define CH_LOWER_SB 0x02
- #define CH_EWA_VALID 0x04
- +#define CH_30MHZ_APART 6
- #define CH_20MHZ_APART 4
- #define CH_10MHZ_APART 2
- #define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */
- @@ -217,6 +218,9 @@
- #define WSEC_SWFLAG 0x0008
- /* to go into transition mode without setting wep */
- #define SES_OW_ENABLED 0x0040
- +/* MFP */
- +#define MFP_CAPABLE 0x0200
- +#define MFP_REQUIRED 0x0400
-
- /* WPA authentication mode bitvec */
- #define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/cw1200/sta.c linux-3.14.35/drivers/net/wireless/cw1200/sta.c
- --- linux-3.14.35.orig/drivers/net/wireless/cw1200/sta.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/cw1200/sta.c 2015-03-08 14:27:37.701684500 -0500
- @@ -936,7 +936,8 @@
- return ret;
- }
-
- -void cw1200_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
- +void cw1200_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- + u32 queues, bool drop)
- {
- struct cw1200_common *priv = hw->priv;
-
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/cw1200/sta.h linux-3.14.35/drivers/net/wireless/cw1200/sta.h
- --- linux-3.14.35.orig/drivers/net/wireless/cw1200/sta.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/cw1200/sta.h 2015-03-08 14:27:37.701684500 -0500
- @@ -40,7 +40,8 @@
-
- int cw1200_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
-
- -void cw1200_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
- +void cw1200_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- + u32 queues, bool drop);
-
- u64 cw1200_prepare_multicast(struct ieee80211_hw *hw,
- struct netdev_hw_addr_list *mc_list);
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/iwlegacy/common.c linux-3.14.35/drivers/net/wireless/iwlegacy/common.c
- --- linux-3.14.35.orig/drivers/net/wireless/iwlegacy/common.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/iwlegacy/common.c 2015-03-08 14:27:37.705684500 -0500
- @@ -4701,7 +4701,8 @@
- }
- EXPORT_SYMBOL(il_mac_change_interface);
-
- -void il_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
- +void il_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- + u32 queues, bool drop)
- {
- struct il_priv *il = hw->priv;
- unsigned long timeout = jiffies + msecs_to_jiffies(500);
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/iwlegacy/common.h linux-3.14.35/drivers/net/wireless/iwlegacy/common.h
- --- linux-3.14.35.orig/drivers/net/wireless/iwlegacy/common.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/iwlegacy/common.h 2015-03-08 14:27:37.705684500 -0500
- @@ -1722,7 +1722,8 @@
- struct ieee80211_vif *vif);
- int il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- enum nl80211_iftype newtype, bool newp2p);
- -void il_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
- +void il_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- + u32 queues, bool drop);
- int il_alloc_txq_mem(struct il_priv *il);
- void il_free_txq_mem(struct il_priv *il);
-
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/iwlwifi/dvm/mac80211.c linux-3.14.35/drivers/net/wireless/iwlwifi/dvm/mac80211.c
- --- linux-3.14.35.orig/drivers/net/wireless/iwlwifi/dvm/mac80211.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/iwlwifi/dvm/mac80211.c 2015-03-08 14:27:37.705684500 -0500
- @@ -1091,7 +1091,8 @@
- FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
- }
-
- -static void iwlagn_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
- +static void iwlagn_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- + u32 queues, bool drop)
- {
- struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
-
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/libertas/cfg.c linux-3.14.35/drivers/net/wireless/libertas/cfg.c
- --- linux-3.14.35.orig/drivers/net/wireless/libertas/cfg.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/libertas/cfg.c 2015-03-08 14:27:37.705684500 -0500
- @@ -1766,7 +1766,8 @@
- memcpy(priv->wdev->ssid, params->ssid, params->ssid_len);
- priv->wdev->ssid_len = params->ssid_len;
-
- - cfg80211_ibss_joined(priv->dev, bssid, GFP_KERNEL);
- + cfg80211_ibss_joined(priv->dev, bssid, params->chandef.chan,
- + GFP_KERNEL);
-
- /* TODO: consider doing this at MACREG_INT_CODE_LINK_SENSED time */
- priv->connect_status = LBS_CONNECTED;
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/mac80211_hwsim.c linux-3.14.35/drivers/net/wireless/mac80211_hwsim.c
- --- linux-3.14.35.orig/drivers/net/wireless/mac80211_hwsim.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/mac80211_hwsim.c 2015-03-08 14:27:37.705684500 -0500
- @@ -1671,7 +1671,9 @@
- return 0;
- }
-
- -static void mac80211_hwsim_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
- +static void mac80211_hwsim_flush(struct ieee80211_hw *hw,
- + struct ieee80211_vif *vif,
- + u32 queues, bool drop)
- {
- /* Not implemented, queues only on kernel side */
- }
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/mwifiex/cfg80211.c linux-3.14.35/drivers/net/wireless/mwifiex/cfg80211.c
- --- linux-3.14.35.orig/drivers/net/wireless/mwifiex/cfg80211.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/mwifiex/cfg80211.c 2015-03-08 14:27:37.705684500 -0500
- @@ -1881,7 +1881,8 @@
- params->privacy);
- done:
- if (!ret) {
- - cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
- + cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
- + params->chandef.chan, GFP_KERNEL);
- dev_dbg(priv->adapter->dev,
- "info: joined/created adhoc network with bssid"
- " %pM successfully\n", priv->cfg_bssid);
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/mwifiex/main.h linux-3.14.35/drivers/net/wireless/mwifiex/main.h
- --- linux-3.14.35.orig/drivers/net/wireless/mwifiex/main.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/mwifiex/main.h 2015-03-08 14:27:37.705684500 -0500
- @@ -1078,7 +1078,7 @@
- const u8 *key, int key_len, u8 key_index,
- const u8 *mac_addr, int disable);
-
- -int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len);
- +int mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len);
-
- int mwifiex_get_ver_ext(struct mwifiex_private *priv);
-
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/mwifiex/sta_ioctl.c linux-3.14.35/drivers/net/wireless/mwifiex/sta_ioctl.c
- --- linux-3.14.35.orig/drivers/net/wireless/mwifiex/sta_ioctl.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/mwifiex/sta_ioctl.c 2015-03-08 14:27:37.705684500 -0500
- @@ -1391,7 +1391,7 @@
- * with requisite parameters and calls the IOCTL handler.
- */
- int
- -mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len)
- +mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len)
- {
- struct mwifiex_ds_misc_gen_ie gen_ie;
-
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/p54/main.c linux-3.14.35/drivers/net/wireless/p54/main.c
- --- linux-3.14.35.orig/drivers/net/wireless/p54/main.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/p54/main.c 2015-03-08 14:27:37.705684500 -0500
- @@ -669,7 +669,8 @@
- return total;
- }
-
- -static void p54_flush(struct ieee80211_hw *dev, u32 queues, bool drop)
- +static void p54_flush(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
- + u32 queues, bool drop)
- {
- struct p54_common *priv = dev->priv;
- unsigned int total, i;
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/rndis_wlan.c linux-3.14.35/drivers/net/wireless/rndis_wlan.c
- --- linux-3.14.35.orig/drivers/net/wireless/rndis_wlan.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/rndis_wlan.c 2015-03-08 14:27:37.705684500 -0500
- @@ -2835,7 +2835,9 @@
- bssid, req_ie, req_ie_len,
- resp_ie, resp_ie_len, GFP_KERNEL);
- } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
- - cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL);
- + cfg80211_ibss_joined(usbdev->net, bssid,
- + get_current_channel(usbdev, NULL),
- + GFP_KERNEL);
-
- kfree(info);
-
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/rt2x00/rt2x00.h linux-3.14.35/drivers/net/wireless/rt2x00/rt2x00.h
- --- linux-3.14.35.orig/drivers/net/wireless/rt2x00/rt2x00.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/rt2x00/rt2x00.h 2015-03-08 14:27:37.709684500 -0500
- @@ -1449,7 +1449,8 @@
- struct ieee80211_vif *vif, u16 queue,
- const struct ieee80211_tx_queue_params *params);
- void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
- -void rt2x00mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
- +void rt2x00mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- + u32 queues, bool drop);
- int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
- int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
- void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/rt2x00/rt2x00mac.c linux-3.14.35/drivers/net/wireless/rt2x00/rt2x00mac.c
- --- linux-3.14.35.orig/drivers/net/wireless/rt2x00/rt2x00mac.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/rt2x00/rt2x00mac.c 2015-03-08 14:27:37.709684500 -0500
- @@ -751,7 +751,8 @@
- }
- EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll);
-
- -void rt2x00mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
- +void rt2x00mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- + u32 queues, bool drop)
- {
- struct rt2x00_dev *rt2x00dev = hw->priv;
- struct data_queue *queue;
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/rtl818x/rtl8187/dev.c linux-3.14.35/drivers/net/wireless/rtl818x/rtl8187/dev.c
- --- linux-3.14.35.orig/drivers/net/wireless/rtl818x/rtl8187/dev.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/rtl818x/rtl8187/dev.c 2015-03-08 14:27:37.709684500 -0500
- @@ -1636,10 +1636,10 @@
-
- err_free_dmabuf:
- kfree(priv->io_dmabuf);
- - err_free_dev:
- - ieee80211_free_hw(dev);
- usb_set_intfdata(intf, NULL);
- usb_put_dev(udev);
- + err_free_dev:
- + ieee80211_free_hw(dev);
- return err;
- }
-
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/rtlwifi/core.c linux-3.14.35/drivers/net/wireless/rtlwifi/core.c
- --- linux-3.14.35.orig/drivers/net/wireless/rtlwifi/core.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/rtlwifi/core.c 2015-03-08 14:27:37.709684500 -0500
- @@ -1309,7 +1309,8 @@
- * before switch channel or power save, or tx buffer packet
- * maybe send after offchannel or rf sleep, this may cause
- * dis-association by AP */
- -static void rtl_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
- +static void rtl_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- + u32 queues, bool drop)
- {
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- diff -Nur linux-3.14.35.orig/drivers/net/wireless/ti/wlcore/main.c linux-3.14.35/drivers/net/wireless/ti/wlcore/main.c
- --- linux-3.14.35.orig/drivers/net/wireless/ti/wlcore/main.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/net/wireless/ti/wlcore/main.c 2015-03-08 14:27:37.709684500 -0500
- @@ -5156,7 +5156,8 @@
- mutex_unlock(&wl->mutex);
- }
-
- -static void wlcore_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
- +static void wlcore_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- + u32 queues, bool drop)
- {
- struct wl1271 *wl = hw->priv;
-
- diff -Nur linux-3.14.35.orig/drivers/pci/host/Kconfig linux-3.14.35/drivers/pci/host/Kconfig
- --- linux-3.14.35.orig/drivers/pci/host/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/pci/host/Kconfig 2015-03-08 14:27:37.709684500 -0500
- @@ -21,6 +21,23 @@
- select PCIEPORTBUS
- select PCIE_DW
-
- +config EP_MODE_IN_EP_RC_SYS
- + bool "PCI Express EP mode in the IMX6 RC/EP interconnection system"
- + depends on PCI_IMX6
- +
- +config EP_SELF_IO_TEST
- + bool "PCI Express EP_SELF_IO_TEST in EP mode"
- + depends on EP_MODE_IN_EP_RC_SYS
- +
- +config RC_MODE_IN_EP_RC_SYS
- + bool "PCI Express RC mode in the IMX6 RC/EP interconnection system"
- + depends on PCI_IMX6
- +
- +config PCI_IMX_EP_DRV
- + bool "i.MX6 PCI Express EP skeleton driver"
- + depends on RC_MODE_IN_EP_RC_SYS
- + default y
- +
- config PCI_TEGRA
- bool "NVIDIA Tegra PCIe controller"
- depends on ARCH_TEGRA
- diff -Nur linux-3.14.35.orig/drivers/pci/host/Makefile linux-3.14.35/drivers/pci/host/Makefile
- --- linux-3.14.35.orig/drivers/pci/host/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/pci/host/Makefile 2015-03-08 14:27:37.709684500 -0500
- @@ -1,6 +1,7 @@
- obj-$(CONFIG_PCIE_DW) += pcie-designware.o
- obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
- obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
- +obj-$(CONFIG_PCI_IMX_EP_DRV) += pci-imx6-ep-driver.o
- obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
- obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
- obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
- diff -Nur linux-3.14.35.orig/drivers/pci/host/pcie-designware.c linux-3.14.35/drivers/pci/host/pcie-designware.c
- --- linux-3.14.35.orig/drivers/pci/host/pcie-designware.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/pci/host/pcie-designware.c 2015-03-08 14:27:37.709684500 -0500
- @@ -23,48 +23,6 @@
-
- #include "pcie-designware.h"
-
- -/* Synopsis specific PCIE configuration registers */
- -#define PCIE_PORT_LINK_CONTROL 0x710
- -#define PORT_LINK_MODE_MASK (0x3f << 16)
- -#define PORT_LINK_MODE_1_LANES (0x1 << 16)
- -#define PORT_LINK_MODE_2_LANES (0x3 << 16)
- -#define PORT_LINK_MODE_4_LANES (0x7 << 16)
- -
- -#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
- -#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
- -#define PORT_LOGIC_LINK_WIDTH_MASK (0x1ff << 8)
- -#define PORT_LOGIC_LINK_WIDTH_1_LANES (0x1 << 8)
- -#define PORT_LOGIC_LINK_WIDTH_2_LANES (0x2 << 8)
- -#define PORT_LOGIC_LINK_WIDTH_4_LANES (0x4 << 8)
- -
- -#define PCIE_MSI_ADDR_LO 0x820
- -#define PCIE_MSI_ADDR_HI 0x824
- -#define PCIE_MSI_INTR0_ENABLE 0x828
- -#define PCIE_MSI_INTR0_MASK 0x82C
- -#define PCIE_MSI_INTR0_STATUS 0x830
- -
- -#define PCIE_ATU_VIEWPORT 0x900
- -#define PCIE_ATU_REGION_INBOUND (0x1 << 31)
- -#define PCIE_ATU_REGION_OUTBOUND (0x0 << 31)
- -#define PCIE_ATU_REGION_INDEX1 (0x1 << 0)
- -#define PCIE_ATU_REGION_INDEX0 (0x0 << 0)
- -#define PCIE_ATU_CR1 0x904
- -#define PCIE_ATU_TYPE_MEM (0x0 << 0)
- -#define PCIE_ATU_TYPE_IO (0x2 << 0)
- -#define PCIE_ATU_TYPE_CFG0 (0x4 << 0)
- -#define PCIE_ATU_TYPE_CFG1 (0x5 << 0)
- -#define PCIE_ATU_CR2 0x908
- -#define PCIE_ATU_ENABLE (0x1 << 31)
- -#define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30)
- -#define PCIE_ATU_LOWER_BASE 0x90C
- -#define PCIE_ATU_UPPER_BASE 0x910
- -#define PCIE_ATU_LIMIT 0x914
- -#define PCIE_ATU_LOWER_TARGET 0x918
- -#define PCIE_ATU_BUS(x) (((x) & 0xff) << 24)
- -#define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19)
- -#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
- -#define PCIE_ATU_UPPER_TARGET 0x91C
- -
- static struct hw_pci dw_pci;
-
- static unsigned long global_io_offset;
- @@ -332,23 +290,28 @@
- return -EINVAL;
- }
-
- - pci_read_config_word(pdev, desc->msi_attrib.pos+PCI_MSI_FLAGS,
- - &msg_ctr);
- - msgvec = (msg_ctr&PCI_MSI_FLAGS_QSIZE) >> 4;
- - if (msgvec == 0)
- - msgvec = (msg_ctr & PCI_MSI_FLAGS_QMASK) >> 1;
- - if (msgvec > 5)
- - msgvec = 0;
- -
- - irq = assign_irq((1 << msgvec), desc, &pos);
- - if (irq < 0)
- - return irq;
- -
- - /*
- - * write_msi_msg() will update PCI_MSI_FLAGS so there is
- - * no need to explicitly call pci_write_config_word().
- - */
- - desc->msi_attrib.multiple = msgvec;
- + if (pp->quirks & DW_PCIE_QUIRK_NO_MSI_VEC) {
- + irq = assign_irq(1, desc, &pos);
- + set_irq_flags(irq, IRQF_VALID);
- + } else {
- + pci_read_config_word(pdev, desc->msi_attrib.pos+PCI_MSI_FLAGS,
- + &msg_ctr);
- + msgvec = (msg_ctr&PCI_MSI_FLAGS_QSIZE) >> 4;
- + if (msgvec == 0)
- + msgvec = (msg_ctr & PCI_MSI_FLAGS_QMASK) >> 1;
- + if (msgvec > 5)
- + msgvec = 0;
- +
- + irq = assign_irq((1 << msgvec), desc, &pos);
- + if (irq < 0)
- + return irq;
- +
- + msg_ctr &= ~PCI_MSI_FLAGS_QSIZE;
- + msg_ctr |= msgvec << 4;
- + pci_write_config_word(pdev, desc->msi_attrib.pos + PCI_MSI_FLAGS,
- + msg_ctr);
- + desc->msi_attrib.multiple = msgvec;
- + }
-
- msg.address_lo = virt_to_phys((void *)pp->msi_data);
- msg.address_hi = 0x0;
- @@ -363,9 +326,30 @@
- clear_irq(irq);
- }
-
- +static int dw_msi_check_device(struct msi_chip *chip, struct pci_dev *pdev,
- + int nvec, int type)
- +{
- + struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
- + u32 val;
- +
- + if (pp->quirks & DW_PCIE_QUIRK_MSI_SELF_EN) {
- + if ((type == PCI_CAP_ID_MSI) || (type == PCI_CAP_ID_MSIX)) {
- + /* Set MSI enable of RC here */
- + val = readl(pp->dbi_base + 0x50);
- + if ((val & (PCI_MSI_FLAGS_ENABLE << 16)) == 0) {
- + val |= PCI_MSI_FLAGS_ENABLE << 16;
- + writel(val, pp->dbi_base + 0x50);
- + }
- + }
- + }
- +
- + return 0;
- +}
- +
- static struct msi_chip dw_pcie_msi_chip = {
- .setup_irq = dw_msi_setup_irq,
- .teardown_irq = dw_msi_teardown_irq,
- + .check_device = dw_msi_check_device,
- };
-
- int dw_pcie_link_up(struct pcie_port *pp)
- @@ -531,38 +515,6 @@
- dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
- }
-
- -static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp)
- -{
- - /* Program viewport 0 : OUTBOUND : MEM */
- - dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0,
- - PCIE_ATU_VIEWPORT);
- - dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1);
- - dw_pcie_writel_rc(pp, pp->mem_base, PCIE_ATU_LOWER_BASE);
- - dw_pcie_writel_rc(pp, (pp->mem_base >> 32), PCIE_ATU_UPPER_BASE);
- - dw_pcie_writel_rc(pp, pp->mem_base + pp->config.mem_size - 1,
- - PCIE_ATU_LIMIT);
- - dw_pcie_writel_rc(pp, pp->config.mem_bus_addr, PCIE_ATU_LOWER_TARGET);
- - dw_pcie_writel_rc(pp, upper_32_bits(pp->config.mem_bus_addr),
- - PCIE_ATU_UPPER_TARGET);
- - dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
- -}
- -
- -static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp)
- -{
- - /* Program viewport 1 : OUTBOUND : IO */
- - dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,
- - PCIE_ATU_VIEWPORT);
- - dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1);
- - dw_pcie_writel_rc(pp, pp->io_base, PCIE_ATU_LOWER_BASE);
- - dw_pcie_writel_rc(pp, (pp->io_base >> 32), PCIE_ATU_UPPER_BASE);
- - dw_pcie_writel_rc(pp, pp->io_base + pp->config.io_size - 1,
- - PCIE_ATU_LIMIT);
- - dw_pcie_writel_rc(pp, pp->config.io_bus_addr, PCIE_ATU_LOWER_TARGET);
- - dw_pcie_writel_rc(pp, upper_32_bits(pp->config.io_bus_addr),
- - PCIE_ATU_UPPER_TARGET);
- - dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
- -}
- -
- static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
- u32 devfn, int where, int size, u32 *val)
- {
- @@ -577,12 +529,10 @@
- dw_pcie_prog_viewport_cfg0(pp, busdev);
- ret = dw_pcie_cfg_read(pp->va_cfg0_base + address, where, size,
- val);
- - dw_pcie_prog_viewport_mem_outbound(pp);
- } else {
- dw_pcie_prog_viewport_cfg1(pp, busdev);
- ret = dw_pcie_cfg_read(pp->va_cfg1_base + address, where, size,
- val);
- - dw_pcie_prog_viewport_io_outbound(pp);
- }
-
- return ret;
- @@ -602,12 +552,10 @@
- dw_pcie_prog_viewport_cfg0(pp, busdev);
- ret = dw_pcie_cfg_write(pp->va_cfg0_base + address, where, size,
- val);
- - dw_pcie_prog_viewport_mem_outbound(pp);
- } else {
- dw_pcie_prog_viewport_cfg1(pp, busdev);
- ret = dw_pcie_cfg_write(pp->va_cfg1_base + address, where, size,
- val);
- - dw_pcie_prog_viewport_io_outbound(pp);
- }
-
- return ret;
- @@ -739,7 +687,13 @@
- {
- struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-
- - return pp->irq;
- + switch (pin) {
- + case 1: return pp->irq;
- + case 2: return pp->irq - 1;
- + case 3: return pp->irq - 2;
- + case 4: return pp->irq - 3;
- + default: return -1;
- + }
- }
-
- static void dw_pcie_add_bus(struct pci_bus *bus)
- diff -Nur linux-3.14.35.orig/drivers/pci/host/pcie-designware.h linux-3.14.35/drivers/pci/host/pcie-designware.h
- --- linux-3.14.35.orig/drivers/pci/host/pcie-designware.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/pci/host/pcie-designware.h 2015-03-08 14:27:37.709684500 -0500
- @@ -14,6 +14,48 @@
- #ifndef _PCIE_DESIGNWARE_H
- #define _PCIE_DESIGNWARE_H
-
- +/* Synopsis specific PCIE configuration registers */
- +#define PCIE_PORT_LINK_CONTROL 0x710
- +#define PORT_LINK_MODE_MASK (0x3f << 16)
- +#define PORT_LINK_MODE_1_LANES (0x1 << 16)
- +#define PORT_LINK_MODE_2_LANES (0x3 << 16)
- +#define PORT_LINK_MODE_4_LANES (0x7 << 16)
- +
- +#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
- +#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
- +#define PORT_LOGIC_LINK_WIDTH_MASK (0x1ff << 8)
- +#define PORT_LOGIC_LINK_WIDTH_1_LANES (0x1 << 8)
- +#define PORT_LOGIC_LINK_WIDTH_2_LANES (0x2 << 8)
- +#define PORT_LOGIC_LINK_WIDTH_4_LANES (0x4 << 8)
- +
- +#define PCIE_MSI_ADDR_LO 0x820
- +#define PCIE_MSI_ADDR_HI 0x824
- +#define PCIE_MSI_INTR0_ENABLE 0x828
- +#define PCIE_MSI_INTR0_MASK 0x82C
- +#define PCIE_MSI_INTR0_STATUS 0x830
- +
- +#define PCIE_ATU_VIEWPORT 0x900
- +#define PCIE_ATU_REGION_INBOUND (0x1 << 31)
- +#define PCIE_ATU_REGION_OUTBOUND (0x0 << 31)
- +#define PCIE_ATU_REGION_INDEX1 (0x1 << 0)
- +#define PCIE_ATU_REGION_INDEX0 (0x0 << 0)
- +#define PCIE_ATU_CR1 0x904
- +#define PCIE_ATU_TYPE_MEM (0x0 << 0)
- +#define PCIE_ATU_TYPE_IO (0x2 << 0)
- +#define PCIE_ATU_TYPE_CFG0 (0x4 << 0)
- +#define PCIE_ATU_TYPE_CFG1 (0x5 << 0)
- +#define PCIE_ATU_CR2 0x908
- +#define PCIE_ATU_ENABLE (0x1 << 31)
- +#define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30)
- +#define PCIE_ATU_LOWER_BASE 0x90C
- +#define PCIE_ATU_UPPER_BASE 0x910
- +#define PCIE_ATU_LIMIT 0x914
- +#define PCIE_ATU_LOWER_TARGET 0x918
- +#define PCIE_ATU_BUS(x) (((x) & 0xff) << 24)
- +#define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19)
- +#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
- +#define PCIE_ATU_UPPER_TARGET 0x91C
- +
- struct pcie_port_info {
- u32 cfg0_size;
- u32 cfg1_size;
- @@ -49,6 +91,11 @@
- int irq;
- u32 lanes;
- struct pcie_host_ops *ops;
- + u32 quirks; /* Deviations from spec. */
- +/* Controller doesn't support MSI VEC */
- +#define DW_PCIE_QUIRK_NO_MSI_VEC (1<<0)
- +/* MSI EN of Controller should be configured when MSI is enabled */
- +#define DW_PCIE_QUIRK_MSI_SELF_EN (1<<1)
- int msi_irq;
- struct irq_domain *irq_domain;
- unsigned long msi_data;
- diff -Nur linux-3.14.35.orig/drivers/pci/host/pci-imx6.c linux-3.14.35/drivers/pci/host/pci-imx6.c
- --- linux-3.14.35.orig/drivers/pci/host/pci-imx6.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/pci/host/pci-imx6.c 2015-03-08 14:27:37.709684500 -0500
- @@ -1,6 +1,7 @@
- /*
- * PCIe host controller driver for Freescale i.MX6 SoCs
- *
- + * Copyright (C) 2014 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2013 Kosagi
- * http://www.kosagi.com
- *
- @@ -14,6 +15,7 @@
- #include <linux/clk.h>
- #include <linux/delay.h>
- #include <linux/gpio.h>
- +#include <linux/interrupt.h>
- #include <linux/kernel.h>
- #include <linux/mfd/syscon.h>
- #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
- @@ -25,11 +27,22 @@
- #include <linux/resource.h>
- #include <linux/signal.h>
- #include <linux/types.h>
- +#include <linux/busfreq-imx6.h>
-
- +#include "../pci.h"
- #include "pcie-designware.h"
-
- #define to_imx6_pcie(x) container_of(x, struct imx6_pcie, pp)
-
- +/*
- + * The default value of the reserved ddr memory
- + * used to verify EP/RC memory space access operations.
- + * BTW, here is the layout of the 1G ddr on SD boards
- + * 0x1000_0000 ~ 0x4FFF_FFFF
- + */
- +static u32 ddr_test_region = 0x40000000;
- +static u32 test_region_size = SZ_2M;
- +
- struct imx6_pcie {
- int reset_gpio;
- int power_on_gpio;
- @@ -52,6 +65,9 @@
-
- /* PCIe Port Logic registers (memory-mapped) */
- #define PL_OFFSET 0x700
- +#define PCIE_PL_PFLR (PL_OFFSET + 0x08)
- +#define PCIE_PL_PFLR_LINK_STATE_MASK (0x3f << 16)
- +#define PCIE_PL_PFLR_FORCE_LINK (1 << 15)
- #define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
- #define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
- #define PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING (1 << 29)
- @@ -216,14 +232,14 @@
-
- static int imx6_pcie_assert_core_reset(struct pcie_port *pp)
- {
- - struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
- + struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
-
- - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- - IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18);
- - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- - IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
- + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- + IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18);
- + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- + IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
-
- - return 0;
- + return 0;
- }
-
- static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
- @@ -234,10 +250,7 @@
- if (gpio_is_valid(imx6_pcie->power_on_gpio))
- gpio_set_value(imx6_pcie->power_on_gpio, 1);
-
- - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- - IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
- - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- - IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
- + request_bus_freq(BUS_FREQ_HIGH);
-
- ret = clk_prepare_enable(imx6_pcie->sata_ref_100m);
- if (ret) {
- @@ -251,10 +264,13 @@
- goto err_pcie_ref;
- }
-
- - ret = clk_prepare_enable(imx6_pcie->lvds_gate);
- - if (ret) {
- - dev_err(pp->dev, "unable to enable lvds_gate\n");
- - goto err_lvds_gate;
- + if (!IS_ENABLED(CONFIG_EP_MODE_IN_EP_RC_SYS)
- + && !IS_ENABLED(CONFIG_RC_MODE_IN_EP_RC_SYS)) {
- + ret = clk_prepare_enable(imx6_pcie->lvds_gate);
- + if (ret) {
- + dev_err(pp->dev, "unable to enable lvds_gate\n");
- + goto err_lvds_gate;
- + }
- }
-
- ret = clk_prepare_enable(imx6_pcie->pcie_axi);
- @@ -266,6 +282,12 @@
- /* allow the clocks to stabilize */
- usleep_range(200, 500);
-
- + /* power up core phy and enable ref clock */
- + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- + IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
- + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- + IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
- +
- /* Some boards don't have PCIe reset GPIO. */
- if (gpio_is_valid(imx6_pcie->reset_gpio)) {
- gpio_set_value(imx6_pcie->reset_gpio, 0);
- @@ -281,6 +303,7 @@
- err_pcie_ref:
- clk_disable_unprepare(imx6_pcie->sata_ref_100m);
- err_sata_ref:
- + release_bus_freq(BUS_FREQ_HIGH);
- return ret;
-
- }
- @@ -288,13 +311,44 @@
- static void imx6_pcie_init_phy(struct pcie_port *pp)
- {
- struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
- + u32 val, gpr1, gpr12;
- +
- + /*
- + * If the bootloader already enabled the link we need some special
- + * handling to get the core back into a state where it is safe to
- + * touch it for configuration. As there is no dedicated reset signal
- + * wired up for MX6QDL, we need to manually force LTSSM into "detect"
- + * state before completely disabling LTSSM, which is a prerequisite
- + * for core configuration.
- + * If both LTSSM_ENABLE and REF_SSP_ENABLE are active we have a strong
- + * indication that the bootloader activated the link.
- + */
- + regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, &gpr1);
- + regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, &gpr12);
- +
- + if ((gpr1 & IMX6Q_GPR1_PCIE_REF_CLK_EN) &&
- + (gpr12 & IMX6Q_GPR12_PCIE_CTL_2)) {
- + val = readl(pp->dbi_base + PCIE_PL_PFLR);
- + val &= ~PCIE_PL_PFLR_LINK_STATE_MASK;
- + val |= PCIE_PL_PFLR_FORCE_LINK;
- + writel(val, pp->dbi_base + PCIE_PL_PFLR);
- +
- + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- + IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
- + }
-
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
-
- /* configure constant input signal to the pcie ctrl and phy */
- - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- - IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12);
- + if (IS_ENABLED(CONFIG_EP_MODE_IN_EP_RC_SYS))
- + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- + IMX6Q_GPR12_DEVICE_TYPE,
- + PCI_EXP_TYPE_ENDPOINT << 12);
- + else
- + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- + IMX6Q_GPR12_DEVICE_TYPE,
- + PCI_EXP_TYPE_ROOT_PORT << 12);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- IMX6Q_GPR12_LOS_LEVEL, 9 << 4);
-
- @@ -326,6 +380,12 @@
- return -EINVAL;
- }
-
- + if (IS_ENABLED(CONFIG_PCI_MSI)) {
- + pp->quirks |= DW_PCIE_QUIRK_NO_MSI_VEC;
- + pp->quirks |= DW_PCIE_QUIRK_MSI_SELF_EN;
- + dw_pcie_msi_init(pp);
- + }
- +
- return 0;
- }
-
- @@ -392,6 +452,15 @@
- return ret;
- }
-
- +static irqreturn_t imx_pcie_msi_irq_handler(int irq, void *arg)
- +{
- + struct pcie_port *pp = arg;
- +
- + dw_handle_msi_irq(pp);
- +
- + return IRQ_HANDLED;
- +}
- +
- static void imx6_pcie_host_init(struct pcie_port *pp)
- {
- imx6_pcie_assert_core_reset(pp);
- @@ -498,6 +567,22 @@
- return -ENODEV;
- }
-
- + if (IS_ENABLED(CONFIG_PCI_MSI)) {
- + pp->msi_irq = pp->irq - 3;
- + if (!pp->msi_irq) {
- + dev_err(&pdev->dev, "failed to get msi irq\n");
- + return -ENODEV;
- + }
- +
- + ret = devm_request_irq(&pdev->dev, pp->msi_irq,
- + imx_pcie_msi_irq_handler,
- + IRQF_SHARED, "imx6q-pcie", pp);
- + if (ret) {
- + dev_err(&pdev->dev, "failed to request msi irq\n");
- + return ret;
- + }
- + }
- +
- pp->root_bus_nr = -1;
- pp->ops = &imx6_pcie_host_ops;
-
- @@ -511,29 +596,188 @@
- return 0;
- }
-
- +static ssize_t imx_pcie_bar0_addr_info(struct device *dev,
- + struct device_attribute *devattr, char *buf)
- +{
- + struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
- + struct pcie_port *pp = &imx6_pcie->pp;
- +
- + return sprintf(buf, "imx-pcie-bar0-addr-info start 0x%08x\n",
- + readl(pp->dbi_base + PCI_BASE_ADDRESS_0));
- +}
- +
- +static ssize_t imx_pcie_bar0_addr_start(struct device *dev,
- + struct device_attribute *attr, const char *buf, size_t count)
- +{
- + u32 bar_start;
- + struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
- + struct pcie_port *pp = &imx6_pcie->pp;
- +
- + sscanf(buf, "%x\n", &bar_start);
- + writel(bar_start, pp->dbi_base + PCI_BASE_ADDRESS_0);
- +
- + return count;
- +}
- +
- +static void imx_pcie_regions_setup(struct device *dev)
- +{
- + struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
- + struct pcie_port *pp = &imx6_pcie->pp;
- +
- + if (IS_ENABLED(CONFIG_EP_MODE_IN_EP_RC_SYS)) {
- + /*
- + * region2 outbound used to access rc mem
- + * in imx6 pcie ep/rc validation system
- + */
- + writel(0, pp->dbi_base + PCIE_ATU_VIEWPORT);
- + writel(0x01000000, pp->dbi_base + PCIE_ATU_LOWER_BASE);
- + writel(0, pp->dbi_base + PCIE_ATU_UPPER_BASE);
- + writel(0x01000000 + test_region_size,
- + pp->dbi_base + PCIE_ATU_LIMIT);
- +
- + writel(ddr_test_region,
- + pp->dbi_base + PCIE_ATU_LOWER_TARGET);
- + writel(0, pp->dbi_base + PCIE_ATU_UPPER_TARGET);
- + writel(PCIE_ATU_TYPE_MEM, pp->dbi_base + PCIE_ATU_CR1);
- + writel(PCIE_ATU_ENABLE, pp->dbi_base + PCIE_ATU_CR2);
- + }
- +
- + if (IS_ENABLED(CONFIG_RC_MODE_IN_EP_RC_SYS)) {
- + /*
- + * region2 outbound used to access ep mem
- + * in imx6 pcie ep/rc validation system
- + */
- + writel(2, pp->dbi_base + PCIE_ATU_VIEWPORT);
- + writel(0x01000000, pp->dbi_base + PCIE_ATU_LOWER_BASE);
- + writel(0, pp->dbi_base + PCIE_ATU_UPPER_BASE);
- + writel(0x01000000 + test_region_size,
- + pp->dbi_base + PCIE_ATU_LIMIT);
- +
- + writel(ddr_test_region,
- + pp->dbi_base + PCIE_ATU_LOWER_TARGET);
- + writel(0, pp->dbi_base + PCIE_ATU_UPPER_TARGET);
- + writel(PCIE_ATU_TYPE_MEM, pp->dbi_base + PCIE_ATU_CR1);
- + writel(PCIE_ATU_ENABLE, pp->dbi_base + PCIE_ATU_CR2);
- + }
- +}
- +
- +static ssize_t imx_pcie_memw_info(struct device *dev,
- + struct device_attribute *devattr, char *buf)
- +{
- + return sprintf(buf, "imx-pcie-rc-memw-info start 0x%08x, size 0x%08x\n",
- + ddr_test_region, test_region_size);
- +}
- +
- +static ssize_t
- +imx_pcie_memw_start(struct device *dev, struct device_attribute *attr,
- + const char *buf, size_t count)
- +{
- + u32 memw_start;
- +
- + sscanf(buf, "%x\n", &memw_start);
- +
- + if (memw_start < 0x10000000) {
- + dev_err(dev, "Invalid memory start address.\n");
- + dev_info(dev, "For example: echo 0x41000000 > /sys/...");
- + return -1;
- + }
- +
- + if (ddr_test_region != memw_start) {
- + ddr_test_region = memw_start;
- + /* Re-setup the iATU */
- + imx_pcie_regions_setup(dev);
- + }
- +
- + return count;
- +}
- +
- +static ssize_t
- +imx_pcie_memw_size(struct device *dev, struct device_attribute *attr,
- + const char *buf, size_t count)
- +{
- + u32 memw_size;
- +
- + sscanf(buf, "%x\n", &memw_size);
- +
- + if ((memw_size > (SZ_16M - SZ_1M)) || (memw_size < SZ_64K)) {
- + dev_err(dev, "Invalid, should be [SZ_64K,SZ_16M - SZ_1MB].\n");
- + dev_info(dev, "For example: echo 0x800000 > /sys/...");
- + return -1;
- + }
- +
- + if (test_region_size != memw_size) {
- + test_region_size = memw_size;
- + /* Re-setup the iATU */
- + imx_pcie_regions_setup(dev);
- + }
- +
- + return count;
- +}
- +
- +static DEVICE_ATTR(memw_info, S_IRUGO, imx_pcie_memw_info, NULL);
- +static DEVICE_ATTR(memw_start_set, S_IWUGO, NULL, imx_pcie_memw_start);
- +static DEVICE_ATTR(memw_size_set, S_IWUGO, NULL, imx_pcie_memw_size);
- +static DEVICE_ATTR(ep_bar0_addr, S_IRWXUGO, imx_pcie_bar0_addr_info,
- + imx_pcie_bar0_addr_start);
- +
- +static struct attribute *imx_pcie_attrs[] = {
- + /*
- + * The start address, and the limitation (64KB ~ (16MB - 1MB))
- + * of the ddr mem window reserved by RC, and used for EP to access.
- + * BTW, these attrs are only configured at EP side.
- + */
- + &dev_attr_memw_info.attr,
- + &dev_attr_memw_start_set.attr,
- + &dev_attr_memw_size_set.attr,
- + &dev_attr_ep_bar0_addr.attr,
- + NULL
- +};
- +
- +static struct attribute_group imx_pcie_attrgroup = {
- + .attrs = imx_pcie_attrs,
- +};
- +
- static int __init imx6_pcie_probe(struct platform_device *pdev)
- {
- struct imx6_pcie *imx6_pcie;
- struct pcie_port *pp;
- struct device_node *np = pdev->dev.of_node;
- struct resource *dbi_base;
- - int ret;
- + int ret = 0;
- + int i;
- + void *test_reg1, *test_reg2;
- + void __iomem *pcie_arb_base_addr;
- + struct timeval tv1, tv2, tv3;
- + u32 tv_count1, tv_count2;
-
- imx6_pcie = devm_kzalloc(&pdev->dev, sizeof(*imx6_pcie), GFP_KERNEL);
- - if (!imx6_pcie)
- - return -ENOMEM;
- + if (!imx6_pcie) {
- + ret = -ENOMEM;
- + goto err;
- + }
-
- pp = &imx6_pcie->pp;
- pp->dev = &pdev->dev;
-
- + if (IS_ENABLED(CONFIG_EP_MODE_IN_EP_RC_SYS)) {
- + /* add attributes for device */
- + ret = sysfs_create_group(&pdev->dev.kobj, &imx_pcie_attrgroup);
- + if (ret) {
- + ret = -EINVAL;
- + goto err;
- + }
- + }
- +
- /* Added for PCI abort handling */
- hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
- "imprecise external abort");
-
- dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base);
- - if (IS_ERR(pp->dbi_base))
- - return PTR_ERR(pp->dbi_base);
- + if (IS_ERR(pp->dbi_base)) {
- + ret = PTR_ERR(pp->dbi_base);
- + goto err;
- + }
-
- /* Fetch GPIOs */
- imx6_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
- @@ -542,7 +786,7 @@
- GPIOF_OUT_INIT_LOW, "PCIe reset");
- if (ret) {
- dev_err(&pdev->dev, "unable to get reset gpio\n");
- - return ret;
- + goto err;
- }
- }
-
- @@ -554,7 +798,7 @@
- "PCIe power enable");
- if (ret) {
- dev_err(&pdev->dev, "unable to get power-on gpio\n");
- - return ret;
- + goto err;
- }
- }
-
- @@ -566,7 +810,7 @@
- "PCIe wake up");
- if (ret) {
- dev_err(&pdev->dev, "unable to get wake-up gpio\n");
- - return ret;
- + goto err;
- }
- }
-
- @@ -578,7 +822,7 @@
- "PCIe disable endpoint");
- if (ret) {
- dev_err(&pdev->dev, "unable to get disable-ep gpio\n");
- - return ret;
- + goto err;
- }
- }
-
- @@ -587,28 +831,32 @@
- if (IS_ERR(imx6_pcie->lvds_gate)) {
- dev_err(&pdev->dev,
- "lvds_gate clock select missing or invalid\n");
- - return PTR_ERR(imx6_pcie->lvds_gate);
- + ret = PTR_ERR(imx6_pcie->lvds_gate);
- + goto err;
- }
-
- imx6_pcie->sata_ref_100m = devm_clk_get(&pdev->dev, "sata_ref_100m");
- if (IS_ERR(imx6_pcie->sata_ref_100m)) {
- dev_err(&pdev->dev,
- "sata_ref_100m clock source missing or invalid\n");
- - return PTR_ERR(imx6_pcie->sata_ref_100m);
- + ret = PTR_ERR(imx6_pcie->sata_ref_100m);
- + goto err;
- }
-
- imx6_pcie->pcie_ref_125m = devm_clk_get(&pdev->dev, "pcie_ref_125m");
- if (IS_ERR(imx6_pcie->pcie_ref_125m)) {
- dev_err(&pdev->dev,
- "pcie_ref_125m clock source missing or invalid\n");
- - return PTR_ERR(imx6_pcie->pcie_ref_125m);
- + ret = PTR_ERR(imx6_pcie->pcie_ref_125m);
- + goto err;
- }
-
- imx6_pcie->pcie_axi = devm_clk_get(&pdev->dev, "pcie_axi");
- if (IS_ERR(imx6_pcie->pcie_axi)) {
- dev_err(&pdev->dev,
- "pcie_axi clock source missing or invalid\n");
- - return PTR_ERR(imx6_pcie->pcie_axi);
- + ret = PTR_ERR(imx6_pcie->pcie_axi);
- + goto err;
- }
-
- /* Grab GPR config register range */
- @@ -616,15 +864,178 @@
- syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
- if (IS_ERR(imx6_pcie->iomuxc_gpr)) {
- dev_err(&pdev->dev, "unable to find iomuxc registers\n");
- - return PTR_ERR(imx6_pcie->iomuxc_gpr);
- + ret = PTR_ERR(imx6_pcie->iomuxc_gpr);
- + goto err;
- }
-
- - ret = imx6_add_pcie_port(pp, pdev);
- - if (ret < 0)
- - return ret;
- + if (of_find_property(np, "no-msi", NULL))
- + pci_no_msi();
-
- - platform_set_drvdata(pdev, imx6_pcie);
- - return 0;
- + if (IS_ENABLED(CONFIG_EP_MODE_IN_EP_RC_SYS)) {
- + if (IS_ENABLED(CONFIG_EP_SELF_IO_TEST)) {
- + /* Prepare the test regions and data */
- + test_reg1 = devm_kzalloc(&pdev->dev,
- + test_region_size, GFP_KERNEL);
- + if (!test_reg1) {
- + pr_err("pcie ep: can't alloc the test reg1.\n");
- + ret = PTR_ERR(test_reg1);
- + goto err;
- + }
- +
- + test_reg2 = devm_kzalloc(&pdev->dev,
- + test_region_size, GFP_KERNEL);
- + if (!test_reg2) {
- + pr_err("pcie ep: can't alloc the test reg2.\n");
- + ret = PTR_ERR(test_reg1);
- + goto err;
- + }
- +
- + pcie_arb_base_addr = ioremap_cache(0x01000000,
- + test_region_size);
- +
- + if (!pcie_arb_base_addr) {
- + pr_err("error with ioremap in ep selftest\n");
- + ret = PTR_ERR(pcie_arb_base_addr);
- + goto err;
- + }
- +
- + for (i = 0; i < test_region_size; i = i + 4) {
- + writel(0xE6600D00 + i, test_reg1 + i);
- + writel(0xDEADBEAF, test_reg2 + i);
- + }
- + }
- +
- + imx6_pcie_init_phy(pp);
- +
- + imx6_pcie_deassert_core_reset(pp);
- +
- + /* assert LTSSM enable */
- + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- + IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
- +
- +
- + dev_info(&pdev->dev, "PCIe EP: waiting for link up...\n");
- +
- + platform_set_drvdata(pdev, imx6_pcie);
- + /* link is indicated by the bit4 of DB_R1 register */
- + do {
- + usleep_range(10, 20);
- + } while ((readl(pp->dbi_base + PCIE_PHY_DEBUG_R1) & 0x10) == 0);
- +
- + /* CMD reg:I/O space, MEM space, and Bus Master Enable */
- + writel(readl(pp->dbi_base + PCI_COMMAND)
- + | PCI_COMMAND_IO
- + | PCI_COMMAND_MEMORY
- + | PCI_COMMAND_MASTER,
- + pp->dbi_base + PCI_COMMAND);
- +
- + /*
- + * configure the class_rev(emaluate one memory ram ep device),
- + * bar0 and bar1 of ep
- + */
- + writel(0xdeadbeaf, pp->dbi_base + PCI_VENDOR_ID);
- + writel(readl(pp->dbi_base + PCI_CLASS_REVISION)
- + | (PCI_CLASS_MEMORY_RAM << 16),
- + pp->dbi_base + PCI_CLASS_REVISION);
- + writel(0xdeadbeaf, pp->dbi_base
- + + PCI_SUBSYSTEM_VENDOR_ID);
- +
- + /* 32bit none-prefetchable 8M bytes memory on bar0 */
- + writel(0x0, pp->dbi_base + PCI_BASE_ADDRESS_0);
- + writel(SZ_8M - 1, pp->dbi_base + (1 << 12)
- + + PCI_BASE_ADDRESS_0);
- +
- + /* None used bar1 */
- + writel(0x0, pp->dbi_base + PCI_BASE_ADDRESS_1);
- + writel(0, pp->dbi_base + (1 << 12) + PCI_BASE_ADDRESS_1);
- +
- + /* 4K bytes IO on bar2 */
- + writel(0x1, pp->dbi_base + PCI_BASE_ADDRESS_2);
- + writel(SZ_4K - 1, pp->dbi_base + (1 << 12) +
- + PCI_BASE_ADDRESS_2);
- +
- + /*
- + * 32bit prefetchable 1M bytes memory on bar3
- + * FIXME BAR MASK3 is not changable, the size
- + * is fixed to 256 bytes.
- + */
- + writel(0x8, pp->dbi_base + PCI_BASE_ADDRESS_3);
- + writel(SZ_1M - 1, pp->dbi_base + (1 << 12)
- + + PCI_BASE_ADDRESS_3);
- +
- + /*
- + * 64bit prefetchable 1M bytes memory on bar4-5.
- + * FIXME BAR4,5 are not enabled yet
- + */
- + writel(0xc, pp->dbi_base + PCI_BASE_ADDRESS_4);
- + writel(SZ_1M - 1, pp->dbi_base + (1 << 12)
- + + PCI_BASE_ADDRESS_4);
- + writel(0, pp->dbi_base + (1 << 12) + PCI_BASE_ADDRESS_5);
- +
- + /* Re-setup the iATU */
- + imx_pcie_regions_setup(&pdev->dev);
- +
- + if (IS_ENABLED(CONFIG_EP_SELF_IO_TEST)) {
- + /* PCIe EP start the data transfer after link up */
- + pr_info("pcie ep: Starting data transfer...\n");
- + do_gettimeofday(&tv1);
- +
- + memcpy((unsigned long *)pcie_arb_base_addr,
- + (unsigned long *)test_reg1,
- + test_region_size);
- +
- + do_gettimeofday(&tv2);
- +
- + memcpy((unsigned long *)test_reg2,
- + (unsigned long *)pcie_arb_base_addr,
- + test_region_size);
- +
- + do_gettimeofday(&tv3);
- +
- + if (memcmp(test_reg2, test_reg1, test_region_size) == 0) {
- + tv_count1 = (tv2.tv_sec - tv1.tv_sec)
- + * USEC_PER_SEC
- + + tv2.tv_usec - tv1.tv_usec;
- + tv_count2 = (tv3.tv_sec - tv2.tv_sec)
- + * USEC_PER_SEC
- + + tv3.tv_usec - tv2.tv_usec;
- +
- + pr_info("pcie ep: Data transfer is successful."
- + " tv_count1 %dus,"
- + " tv_count2 %dus.\n",
- + tv_count1, tv_count2);
- + pr_info("pcie ep: Data write speed:%ldMB/s.\n",
- + ((test_region_size/1024)
- + * MSEC_PER_SEC)
- + /(tv_count1));
- + pr_info("pcie ep: Data read speed:%ldMB/s.\n",
- + ((test_region_size/1024)
- + * MSEC_PER_SEC)
- + /(tv_count2));
- + } else {
- + pr_info("pcie ep: Data transfer is failed.\n");
- + }
- + }
- + } else {
- + ret = imx6_add_pcie_port(pp, pdev);
- + if (ret < 0)
- + goto err;
- + platform_set_drvdata(pdev, imx6_pcie);
- +
- + /* Re-setup the iATU */
- + imx_pcie_regions_setup(&pdev->dev);
- + }
- +
- +err:
- + return ret;
- +}
- +
- +static void imx6_pcie_shutdown(struct platform_device *pdev)
- +{
- + struct imx6_pcie *imx6_pcie = platform_get_drvdata(pdev);
- +
- + /* bring down link, so bootloader gets clean state in case of reboot */
- + imx6_pcie_assert_core_reset(&imx6_pcie->pp);
- }
-
- static const struct of_device_id imx6_pcie_of_match[] = {
- @@ -639,6 +1050,7 @@
- .owner = THIS_MODULE,
- .of_match_table = imx6_pcie_of_match,
- },
- + .shutdown = imx6_pcie_shutdown,
- };
-
- /* Freescale PCIe driver does not allow module unload */
- diff -Nur linux-3.14.35.orig/drivers/pci/host/pci-imx6-ep-driver.c linux-3.14.35/drivers/pci/host/pci-imx6-ep-driver.c
- --- linux-3.14.35.orig/drivers/pci/host/pci-imx6-ep-driver.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/pci/host/pci-imx6-ep-driver.c 2015-03-08 14:27:37.709684500 -0500
- @@ -0,0 +1,159 @@
- +/*
- + * PCIe endpoint skeleton driver for IMX6 SOCs
- + *
- + * Copyright (C) 2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#include <linux/kernel.h>
- +#include <linux/module.h>
- +#include <linux/init.h>
- +#include <linux/pci.h>
- +#include <linux/pci-aspm.h>
- +#include <linux/slab.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/delay.h>
- +#include <linux/sched.h>
- +#include <linux/interrupt.h>
- +
- +#define DRV_DESCRIPTION "i.MX PCIE endpoint device driver"
- +#define DRV_VERSION "version 0.1"
- +#define DRV_NAME "imx_pcie_ep"
- +
- +struct imx_pcie_ep_priv {
- + struct pci_dev *pci_dev;
- + void __iomem *hw_base;
- +};
- +
- +/**
- + * imx_pcie_ep_probe - Device Initialization Routine
- + * @pdev: PCI device information struct
- + * @id: entry in id_tbl
- + *
- + * Returns 0 on success, negative on failure
- + **/
- +static int imx_pcie_ep_probe(struct pci_dev *pdev,
- + const struct pci_device_id *id)
- +{
- + int ret = 0;
- + struct device *dev = &pdev->dev;
- + struct imx_pcie_ep_priv *priv;
- +
- + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- + if (!priv) {
- + dev_err(dev, "can't alloc imx pcie priv\n");
- + return -ENOMEM;
- + }
- +
- + priv->pci_dev = pdev;
- +
- + if (pci_enable_device(pdev)) {
- + ret = -ENODEV;
- + goto out;
- + }
- + pci_set_master(pdev);
- +
- + pci_set_drvdata(pdev, priv);
- +
- + priv->hw_base = pci_iomap(pdev, 0, 0);
- + if (!priv->hw_base) {
- + ret = -ENODEV;
- + goto out;
- + }
- +
- + pr_info("pci_resource_len = 0x%08llx\n",
- + (unsigned long long) pci_resource_len(pdev, 0));
- + pr_info("pci_resource_base = %p\n", priv->hw_base);
- +
- + ret = pci_enable_msi(priv->pci_dev);
- + if (ret < 0) {
- + dev_err(dev, "can't enable msi\n");
- + return ret;
- + }
- +
- + /*
- + * Force to use 0x01FF8000 as the MSI address,
- + * to do the MSI demo
- + */
- + pci_bus_write_config_dword(pdev->bus, 0, 0x54, 0x01FF8000);
- + pci_bus_write_config_dword(pdev->bus->parent, 0, 0x820, 0x01FF8000);
- +
- + /* configure rc's msi cap */
- + pci_bus_read_config_dword(pdev->bus->parent, 0, 0x50, &ret);
- + ret |= (PCI_MSI_FLAGS_ENABLE << 16);
- + pci_bus_write_config_dword(pdev->bus->parent, 0, 0x50, ret);
- + pci_bus_write_config_dword(pdev->bus->parent, 0, 0x828, 0x1);
- + pci_bus_write_config_dword(pdev->bus->parent, 0, 0x82C, 0xFFFFFFFE);
- +
- + return 0;
- +
- +out:
- + return ret;
- +}
- +
- +static void imx_pcie_ep_remove(struct pci_dev *pdev)
- +{
- + struct imx_pcie_ep_priv *priv = pci_get_drvdata(pdev);
- +
- + if (!priv)
- + return;
- + pr_info("***imx pcie ep driver unload***\n");
- +}
- +
- +static struct pci_device_id imx_pcie_ep_ids[] = {
- + {
- + .class = PCI_CLASS_MEMORY_RAM << 8,
- + .class_mask = ~0,
- + .vendor = 0xbeaf,
- + .device = 0xdead,
- + .subvendor = PCI_ANY_ID,
- + .subdevice = PCI_ANY_ID,
- + },
- + { } /* terminate list */
- +};
- +MODULE_DEVICE_TABLE(pci, imx_pcie_ep_ids);
- +
- +static struct pci_driver imx_pcie_ep_driver = {
- + .name = DRV_NAME,
- + .id_table = imx_pcie_ep_ids,
- + .probe = imx_pcie_ep_probe,
- + .remove = imx_pcie_ep_remove,
- +};
- +
- +static int __init imx_pcie_ep_init(void)
- +{
- + int ret;
- + pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
- +
- + ret = pci_register_driver(&imx_pcie_ep_driver);
- + if (ret)
- + pr_err("Unable to initialize PCI module\n");
- +
- + return ret;
- +}
- +
- +static void __exit imx_pcie_ep_exit(void)
- +{
- + pci_unregister_driver(&imx_pcie_ep_driver);
- +}
- +
- +module_exit(imx_pcie_ep_exit);
- +module_init(imx_pcie_ep_init);
- +
- +MODULE_DESCRIPTION(DRV_DESCRIPTION);
- +MODULE_VERSION(DRV_VERSION);
- +MODULE_LICENSE("GPL");
- +MODULE_ALIAS("imx_pcie_ep");
- diff -Nur linux-3.14.35.orig/drivers/pinctrl/devicetree.c linux-3.14.35/drivers/pinctrl/devicetree.c
- --- linux-3.14.35.orig/drivers/pinctrl/devicetree.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/pinctrl/devicetree.c 2015-03-08 14:27:37.709684500 -0500
- @@ -18,6 +18,7 @@
-
- #include <linux/device.h>
- #include <linux/of.h>
- +#include <linux/of_gpio.h>
- #include <linux/pinctrl/pinctrl.h>
- #include <linux/slab.h>
-
- @@ -172,6 +173,43 @@
- return dt_remember_or_free_map(p, statename, NULL, map, 1);
- }
-
- +static int dt_gpio_assert_pinctrl(struct pinctrl *p)
- +{
- + struct device_node *np = p->dev->of_node;
- + enum of_gpio_flags flags;
- + int gpio;
- + int index = 0;
- + int ret;
- +
- + if (!of_find_property(np, "pinctrl-assert-gpios", NULL))
- + return 0; /* Missing the property, so nothing to be done */
- +
- + for (;; index++) {
- + gpio = of_get_named_gpio_flags(np, "pinctrl-assert-gpios",
- + index, &flags);
- + if (gpio < 0)
- + break; /* End of the phandle list */
- +
- + if (!gpio_is_valid(gpio))
- + return -EINVAL;
- +
- + ret = devm_gpio_request_one(p->dev, gpio, GPIOF_OUT_INIT_LOW,
- + NULL);
- + if (ret < 0)
- + return ret;
- +
- + if (flags & OF_GPIO_ACTIVE_LOW)
- + continue;
- +
- + if (gpio_cansleep(gpio))
- + gpio_set_value_cansleep(gpio, 1);
- + else
- + gpio_set_value(gpio, 1);
- + }
- +
- + return 0;
- +}
- +
- int pinctrl_dt_to_map(struct pinctrl *p)
- {
- struct device_node *np = p->dev->of_node;
- @@ -190,6 +228,12 @@
- return 0;
- }
-
- + ret = dt_gpio_assert_pinctrl(p);
- + if (ret) {
- + dev_dbg(p->dev, "failed to assert pinctrl setting: %d\n", ret);
- + return ret;
- + }
- +
- /* We may store pointers to property names within the node */
- of_node_get(np);
-
- diff -Nur linux-3.14.35.orig/drivers/pinctrl/pinctrl-imx6sl.c linux-3.14.35/drivers/pinctrl/pinctrl-imx6sl.c
- --- linux-3.14.35.orig/drivers/pinctrl/pinctrl-imx6sl.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/pinctrl/pinctrl-imx6sl.c 2015-03-08 14:27:37.709684500 -0500
- @@ -384,6 +384,10 @@
- },
- .probe = imx6sl_pinctrl_probe,
- .remove = imx_pinctrl_remove,
- +#ifdef CONFIG_PM
- + .suspend = imx_pinctrl_suspend,
- + .resume = imx_pinctrl_resume,
- +#endif
- };
-
- static int __init imx6sl_pinctrl_init(void)
- diff -Nur linux-3.14.35.orig/drivers/pinctrl/pinctrl-imx.c linux-3.14.35/drivers/pinctrl/pinctrl-imx.c
- --- linux-3.14.35.orig/drivers/pinctrl/pinctrl-imx.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/pinctrl/pinctrl-imx.c 2015-03-08 14:27:37.709684500 -0500
- @@ -1,7 +1,7 @@
- /*
- * Core driver for the imx pin controller
- *
- - * Copyright (C) 2012 Freescale Semiconductor, Inc.
- + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc.
- * Copyright (C) 2012 Linaro Ltd.
- *
- * Author: Dong Aisheng <dong.aisheng@linaro.org>
- @@ -628,3 +628,25 @@
-
- return 0;
- }
- +
- +#ifdef CONFIG_PM
- +int imx_pinctrl_suspend(struct platform_device *pdev, pm_message_t state)
- +{
- + struct imx_pinctrl *ipctl = platform_get_drvdata(pdev);
- +
- + if (!ipctl)
- + return -EINVAL;
- +
- + return pinctrl_force_sleep(ipctl->pctl);
- +}
- +
- +int imx_pinctrl_resume(struct platform_device *pdev)
- +{
- + struct imx_pinctrl *ipctl = platform_get_drvdata(pdev);
- +
- + if (!ipctl)
- + return -EINVAL;
- +
- + return pinctrl_force_default(ipctl->pctl);
- +}
- +#endif
- diff -Nur linux-3.14.35.orig/drivers/pinctrl/pinctrl-imx.h linux-3.14.35/drivers/pinctrl/pinctrl-imx.h
- --- linux-3.14.35.orig/drivers/pinctrl/pinctrl-imx.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/pinctrl/pinctrl-imx.h 2015-03-08 14:27:37.709684500 -0500
- @@ -1,7 +1,7 @@
- /*
- * IMX pinmux core definitions
- *
- - * Copyright (C) 2012 Freescale Semiconductor, Inc.
- + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc.
- * Copyright (C) 2012 Linaro Ltd.
- *
- * Author: Dong Aisheng <dong.aisheng@linaro.org>
- @@ -98,4 +98,8 @@
- int imx_pinctrl_probe(struct platform_device *pdev,
- struct imx_pinctrl_soc_info *info);
- int imx_pinctrl_remove(struct platform_device *pdev);
- +#ifdef CONFIG_PM
- +int imx_pinctrl_suspend(struct platform_device *pdev, pm_message_t state);
- +int imx_pinctrl_resume(struct platform_device *pdev);
- +#endif
- #endif /* __DRIVERS_PINCTRL_IMX_H */
- diff -Nur linux-3.14.35.orig/drivers/power/imx6_usb_charger.c linux-3.14.35/drivers/power/imx6_usb_charger.c
- --- linux-3.14.35.orig/drivers/power/imx6_usb_charger.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/power/imx6_usb_charger.c 2015-03-08 14:27:37.713684500 -0500
- @@ -0,0 +1,294 @@
- +/*
- + * Copyright (C) 2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#include <linux/delay.h>
- +#include <linux/device.h>
- +#include <linux/power/imx6_usb_charger.h>
- +#include <linux/regmap.h>
- +
- +#define HW_ANADIG_REG_3P0_SET (0x00000124)
- +#define HW_ANADIG_REG_3P0_CLR (0x00000128)
- +#define BM_ANADIG_REG_3P0_ENABLE_ILIMIT 0x00000004
- +#define BM_ANADIG_REG_3P0_ENABLE_LINREG 0x00000001
- +
- +#define HW_ANADIG_USB1_CHRG_DETECT_SET (0x000001b4)
- +#define HW_ANADIG_USB1_CHRG_DETECT_CLR (0x000001b8)
- +
- +#define BM_ANADIG_USB1_CHRG_DETECT_EN_B 0x00100000
- +#define BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B 0x00080000
- +#define BM_ANADIG_USB1_CHRG_DETECT_CHK_CONTACT 0x00040000
- +
- +#define HW_ANADIG_USB1_VBUS_DET_STAT (0x000001c0)
- +
- +#define BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID 0x00000008
- +
- +#define HW_ANADIG_USB1_CHRG_DET_STAT (0x000001d0)
- +
- +#define BM_ANADIG_USB1_CHRG_DET_STAT_DM_STATE 0x00000004
- +#define BM_ANADIG_USB1_CHRG_DET_STAT_CHRG_DETECTED 0x00000002
- +#define BM_ANADIG_USB1_CHRG_DET_STAT_PLUG_CONTACT 0x00000001
- +
- +static char *imx6_usb_charger_supplied_to[] = {
- + "imx6_usb_charger",
- +};
- +
- +static enum power_supply_property imx6_usb_charger_power_props[] = {
- + POWER_SUPPLY_PROP_PRESENT, /* Charger detected */
- + POWER_SUPPLY_PROP_ONLINE, /* VBUS online */
- + POWER_SUPPLY_PROP_CURRENT_MAX, /* Maximum current in mA */
- +};
- +
- +static int imx6_usb_charger_get_property(struct power_supply *psy,
- + enum power_supply_property psp,
- + union power_supply_propval *val)
- +{
- + struct usb_charger *charger =
- + container_of(psy, struct usb_charger, psy);
- +
- + switch (psp) {
- + case POWER_SUPPLY_PROP_PRESENT:
- + val->intval = charger->present;
- + break;
- + case POWER_SUPPLY_PROP_ONLINE:
- + val->intval = charger->online;
- + break;
- + case POWER_SUPPLY_PROP_CURRENT_MAX:
- + val->intval = charger->max_current;
- + break;
- + default:
- + return -EINVAL;
- + }
- + return 0;
- +}
- +
- +static void disable_charger_detector(struct regmap *regmap)
- +{
- + regmap_write(regmap, HW_ANADIG_USB1_CHRG_DETECT_SET,
- + BM_ANADIG_USB1_CHRG_DETECT_EN_B |
- + BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B);
- +}
- +
- +static void disable_current_limiter(struct regmap *regmap)
- +{
- + /* Disable the vdd3p0 current limiter */
- + regmap_write(regmap, HW_ANADIG_REG_3P0_CLR,
- + BM_ANADIG_REG_3P0_ENABLE_ILIMIT);
- +}
- +
- +/* Return value if the charger is present */
- +static int imx6_usb_charger_detect(struct usb_charger *charger)
- +{
- + struct regmap *regmap = charger->anatop;
- + u32 val;
- + int i, data_pin_contact_count = 0;
- +
- + /* Enable the vdd3p0 curret limiter */
- + regmap_write(regmap, HW_ANADIG_REG_3P0_SET,
- + BM_ANADIG_REG_3P0_ENABLE_LINREG |
- + BM_ANADIG_REG_3P0_ENABLE_ILIMIT);
- +
- + /* check if vbus is valid */
- + regmap_read(regmap, HW_ANADIG_USB1_VBUS_DET_STAT, &val);
- + if (!(val & BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID)) {
- + dev_err(charger->dev, "vbus is error\n");
- + disable_current_limiter(regmap);
- + return -EINVAL;
- + }
- +
- + /* Enable charger detector */
- + regmap_write(regmap, HW_ANADIG_USB1_CHRG_DETECT_CLR,
- + BM_ANADIG_USB1_CHRG_DETECT_EN_B);
- + /*
- + * - Do not check whether a charger is connected to the USB port
- + * - Check whether the USB plug has been in contact with each other
- + */
- + regmap_write(regmap, HW_ANADIG_USB1_CHRG_DETECT_SET,
- + BM_ANADIG_USB1_CHRG_DETECT_CHK_CONTACT |
- + BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B);
- +
- + /* Check if plug is connected */
- + for (i = 0; i < 100; i = i + 1) {
- + regmap_read(regmap, HW_ANADIG_USB1_CHRG_DET_STAT, &val);
- + if (val & BM_ANADIG_USB1_CHRG_DET_STAT_PLUG_CONTACT) {
- + if (data_pin_contact_count++ > 5)
- + /* Data pin makes contact */
- + break;
- + } else {
- + msleep(20);
- + }
- + }
- +
- + if (i == 100) {
- + dev_err(charger->dev,
- + "VBUS is coming from a dedicated power supply.\n");
- + disable_current_limiter(regmap);
- + disable_charger_detector(regmap);
- + return -ENXIO;
- + }
- +
- + /*
- + * - Do check whether a charger is connected to the USB port
- + * - Do not Check whether the USB plug has been in contact with
- + * each other
- + */
- + regmap_write(regmap, HW_ANADIG_USB1_CHRG_DETECT_CLR,
- + BM_ANADIG_USB1_CHRG_DETECT_CHK_CONTACT |
- + BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B);
- + msleep(45);
- +
- + /* Check if it is a charger */
- + regmap_read(regmap, HW_ANADIG_USB1_CHRG_DET_STAT, &val);
- + if (!(val & BM_ANADIG_USB1_CHRG_DET_STAT_CHRG_DETECTED)) {
- + dev_dbg(charger->dev, "It is a stardard downstream port\n");
- + charger->psy.type = POWER_SUPPLY_TYPE_USB;
- + charger->max_current = 500;
- + disable_charger_detector(regmap);
- + } else {
- + /* It is a charger */
- + disable_charger_detector(regmap);
- + msleep(45);
- + }
- +
- + disable_current_limiter(regmap);
- +
- + return 0;
- +}
- +
- +/*
- + * imx6_usb_vbus_connect - inform about VBUS connection
- + * @charger: the usb charger
- + *
- + * Inform the charger VBUS is connected, vbus detect supplier should call it.
- + * Besides, the USB device controller is expected to keep the dataline
- + * pullups disabled.
- + */
- +int imx6_usb_vbus_connect(struct usb_charger *charger)
- +{
- + int ret;
- +
- + charger->online = 1;
- +
- + mutex_lock(&charger->lock);
- +
- + /* Start the 1st period charger detection. */
- + ret = imx6_usb_charger_detect(charger);
- + if (ret)
- + dev_err(charger->dev,
- + "Error occurs during detection: %d\n",
- + ret);
- + else
- + charger->present = 1;
- +
- + mutex_unlock(&charger->lock);
- +
- + return ret;
- +}
- +EXPORT_SYMBOL(imx6_usb_vbus_connect);
- +
- +/*
- + * It must be called after dp is pulled up (from USB controller driver),
- + * That is used to differentiate DCP and CDP
- + */
- +int imx6_usb_charger_detect_post(struct usb_charger *charger)
- +{
- + struct regmap *regmap = charger->anatop;
- + int val;
- +
- + mutex_lock(&charger->lock);
- +
- + msleep(40);
- +
- + regmap_read(regmap, HW_ANADIG_USB1_CHRG_DET_STAT, &val);
- + if (val & BM_ANADIG_USB1_CHRG_DET_STAT_DM_STATE) {
- + dev_dbg(charger->dev, "It is a dedicate charging port\n");
- + charger->psy.type = POWER_SUPPLY_TYPE_USB_DCP;
- + charger->max_current = 1500;
- + } else {
- + dev_dbg(charger->dev, "It is a charging downstream port\n");
- + charger->psy.type = POWER_SUPPLY_TYPE_USB_CDP;
- + charger->max_current = 900;
- + }
- +
- + power_supply_changed(&charger->psy);
- +
- + mutex_unlock(&charger->lock);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(imx6_usb_charger_detect_post);
- +
- +/*
- + * imx6_usb_vbus_disconnect - inform about VBUS disconnection
- + * @charger: the usb charger
- + *
- + * Inform the charger that VBUS is disconnected. The charging will be
- + * stopped and the charger properties cleared.
- + */
- +int imx6_usb_vbus_disconnect(struct usb_charger *charger)
- +{
- + charger->online = 0;
- + charger->present = 0;
- + charger->max_current = 0;
- + charger->psy.type = POWER_SUPPLY_TYPE_MAINS;
- +
- + power_supply_changed(&charger->psy);
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(imx6_usb_vbus_disconnect);
- +
- +/*
- + * imx6_usb_create_charger - create a USB charger
- + * @charger: the charger to be initialized
- + * @name: name for the power supply
- +
- + * Registers a power supply for the charger. The USB Controller
- + * driver will call this after filling struct usb_charger.
- + */
- +int imx6_usb_create_charger(struct usb_charger *charger,
- + const char *name)
- +{
- + struct power_supply *psy = &charger->psy;
- +
- + if (!charger->dev)
- + return -EINVAL;
- +
- + if (name)
- + psy->name = name;
- + else
- + psy->name = "imx6_usb_charger";
- +
- + charger->bc = BATTERY_CHARGING_SPEC_1_2;
- + mutex_init(&charger->lock);
- +
- + psy->type = POWER_SUPPLY_TYPE_MAINS;
- + psy->properties = imx6_usb_charger_power_props;
- + psy->num_properties = ARRAY_SIZE(imx6_usb_charger_power_props);
- + psy->get_property = imx6_usb_charger_get_property;
- + psy->supplied_to = imx6_usb_charger_supplied_to;
- + psy->num_supplicants = sizeof(imx6_usb_charger_supplied_to)
- + / sizeof(char *);
- +
- + return power_supply_register(charger->dev, psy);
- +}
- +EXPORT_SYMBOL(imx6_usb_create_charger);
- +
- +/*
- + * imx6_usb_remove_charger - remove a USB charger
- + * @charger: the charger to be removed
- + *
- + * Unregister the chargers power supply.
- + */
- +void imx6_usb_remove_charger(struct usb_charger *charger)
- +{
- + power_supply_unregister(&charger->psy);
- +}
- +EXPORT_SYMBOL(imx6_usb_remove_charger);
- diff -Nur linux-3.14.35.orig/drivers/power/Kconfig linux-3.14.35/drivers/power/Kconfig
- --- linux-3.14.35.orig/drivers/power/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/power/Kconfig 2015-03-08 14:27:37.713684500 -0500
- @@ -389,6 +389,12 @@
- Say Y to enable support for the battery and AC power in the
- Goldfish emulator.
-
- +config IMX6_USB_CHARGER
- + bool "Freescale imx6 USB Charger"
- + depends on SOC_IMX6Q || SOC_IMX6SL
- + help
- + Say Y to enable Freescale imx6 USB Charger Detect.
- +
- source "drivers/power/reset/Kconfig"
-
- endif # POWER_SUPPLY
- diff -Nur linux-3.14.35.orig/drivers/power/Makefile linux-3.14.35/drivers/power/Makefile
- --- linux-3.14.35.orig/drivers/power/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/power/Makefile 2015-03-08 14:27:37.713684500 -0500
- @@ -58,3 +58,4 @@
- obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o
- obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o
- obj-$(CONFIG_POWER_RESET) += reset/
- +obj-$(CONFIG_IMX6_USB_CHARGER) += imx6_usb_charger.o
- diff -Nur linux-3.14.35.orig/drivers/ptp/ptp_chardev.c linux-3.14.35/drivers/ptp/ptp_chardev.c
- --- linux-3.14.35.orig/drivers/ptp/ptp_chardev.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ptp/ptp_chardev.c 2015-03-08 14:27:37.713684500 -0500
- @@ -25,6 +25,96 @@
-
- #include "ptp_private.h"
-
- +static int ptp_disable_pinfunc(struct ptp_clock_info *ops,
- + enum ptp_pin_function func, unsigned int chan)
- +{
- + struct ptp_clock_request rq;
- + int err = 0;
- +
- + memset(&rq, 0, sizeof(rq));
- +
- + switch (func) {
- + case PTP_PF_NONE:
- + break;
- + case PTP_PF_EXTTS:
- + rq.type = PTP_CLK_REQ_EXTTS;
- + rq.extts.index = chan;
- + err = ops->enable(ops, &rq, 0);
- + break;
- + case PTP_PF_PEROUT:
- + rq.type = PTP_CLK_REQ_PEROUT;
- + rq.perout.index = chan;
- + err = ops->enable(ops, &rq, 0);
- + break;
- + case PTP_PF_PHYSYNC:
- + break;
- + default:
- + return -EINVAL;
- + }
- +
- + return err;
- +}
- +
- +int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin,
- + enum ptp_pin_function func, unsigned int chan)
- +{
- + struct ptp_clock_info *info = ptp->info;
- + struct ptp_pin_desc *pin1 = NULL, *pin2 = &info->pin_config[pin];
- + unsigned int i;
- +
- + /* Check to see if any other pin previously had this function. */
- + for (i = 0; i < info->n_pins; i++) {
- + if (info->pin_config[i].func == func &&
- + info->pin_config[i].chan == chan) {
- + pin1 = &info->pin_config[i];
- + break;
- + }
- + }
- + if (pin1 && i == pin)
- + return 0;
- +
- + /* Check the desired function and channel. */
- + switch (func) {
- + case PTP_PF_NONE:
- + break;
- + case PTP_PF_EXTTS:
- + if (chan >= info->n_ext_ts)
- + return -EINVAL;
- + break;
- + case PTP_PF_PEROUT:
- + if (chan >= info->n_per_out)
- + return -EINVAL;
- + break;
- + case PTP_PF_PHYSYNC:
- + pr_err("sorry, cannot reassign the calibration pin\n");
- + return -EINVAL;
- + default:
- + return -EINVAL;
- + }
- +
- + if (pin2->func == PTP_PF_PHYSYNC) {
- + pr_err("sorry, cannot reprogram the calibration pin\n");
- + return -EINVAL;
- + }
- +
- + if (info->verify(info, pin, func, chan)) {
- + pr_err("driver cannot use function %u on pin %u\n", func, chan);
- + return -EOPNOTSUPP;
- + }
- +
- + /* Disable whatever function was previously assigned. */
- + if (pin1) {
- + ptp_disable_pinfunc(info, func, chan);
- + pin1->func = PTP_PF_NONE;
- + pin1->chan = 0;
- + }
- + ptp_disable_pinfunc(info, pin2->func, pin2->chan);
- + pin2->func = func;
- + pin2->chan = chan;
- +
- + return 0;
- +}
- +
- int ptp_open(struct posix_clock *pc, fmode_t fmode)
- {
- return 0;
- @@ -35,12 +125,13 @@
- struct ptp_clock_caps caps;
- struct ptp_clock_request req;
- struct ptp_sys_offset *sysoff = NULL;
- + struct ptp_pin_desc pd;
- struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
- struct ptp_clock_info *ops = ptp->info;
- struct ptp_clock_time *pct;
- struct timespec ts;
- int enable, err = 0;
- - unsigned int i;
- + unsigned int i, pin_index;
-
- switch (cmd) {
-
- @@ -51,6 +142,7 @@
- caps.n_ext_ts = ptp->info->n_ext_ts;
- caps.n_per_out = ptp->info->n_per_out;
- caps.pps = ptp->info->pps;
- + caps.n_pins = ptp->info->n_pins;
- if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
- err = -EFAULT;
- break;
- @@ -126,6 +218,40 @@
- err = -EFAULT;
- break;
-
- + case PTP_PIN_GETFUNC:
- + if (copy_from_user(&pd, (void __user *)arg, sizeof(pd))) {
- + err = -EFAULT;
- + break;
- + }
- + pin_index = pd.index;
- + if (pin_index >= ops->n_pins) {
- + err = -EINVAL;
- + break;
- + }
- + if (mutex_lock_interruptible(&ptp->pincfg_mux))
- + return -ERESTARTSYS;
- + pd = ops->pin_config[pin_index];
- + mutex_unlock(&ptp->pincfg_mux);
- + if (!err && copy_to_user((void __user *)arg, &pd, sizeof(pd)))
- + err = -EFAULT;
- + break;
- +
- + case PTP_PIN_SETFUNC:
- + if (copy_from_user(&pd, (void __user *)arg, sizeof(pd))) {
- + err = -EFAULT;
- + break;
- + }
- + pin_index = pd.index;
- + if (pin_index >= ops->n_pins) {
- + err = -EINVAL;
- + break;
- + }
- + if (mutex_lock_interruptible(&ptp->pincfg_mux))
- + return -ERESTARTSYS;
- + err = ptp_set_pinfunc(ptp, pin_index, pd.func, pd.chan);
- + mutex_unlock(&ptp->pincfg_mux);
- + break;
- +
- default:
- err = -ENOTTY;
- break;
- diff -Nur linux-3.14.35.orig/drivers/ptp/ptp_clock.c linux-3.14.35/drivers/ptp/ptp_clock.c
- --- linux-3.14.35.orig/drivers/ptp/ptp_clock.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ptp/ptp_clock.c 2015-03-08 14:27:37.713684500 -0500
- @@ -169,6 +169,7 @@
- struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
-
- mutex_destroy(&ptp->tsevq_mux);
- + mutex_destroy(&ptp->pincfg_mux);
- ida_simple_remove(&ptp_clocks_map, ptp->index);
- kfree(ptp);
- }
- @@ -203,6 +204,7 @@
- ptp->index = index;
- spin_lock_init(&ptp->tsevq.lock);
- mutex_init(&ptp->tsevq_mux);
- + mutex_init(&ptp->pincfg_mux);
- init_waitqueue_head(&ptp->tsev_wq);
-
- /* Create a new device in our class. */
- @@ -249,6 +251,7 @@
- device_destroy(ptp_class, ptp->devid);
- no_device:
- mutex_destroy(&ptp->tsevq_mux);
- + mutex_destroy(&ptp->pincfg_mux);
- no_slot:
- kfree(ptp);
- no_memory:
- @@ -305,6 +308,26 @@
- }
- EXPORT_SYMBOL(ptp_clock_index);
-
- +int ptp_find_pin(struct ptp_clock *ptp,
- + enum ptp_pin_function func, unsigned int chan)
- +{
- + struct ptp_pin_desc *pin = NULL;
- + int i;
- +
- + mutex_lock(&ptp->pincfg_mux);
- + for (i = 0; i < ptp->info->n_pins; i++) {
- + if (ptp->info->pin_config[i].func == func &&
- + ptp->info->pin_config[i].chan == chan) {
- + pin = &ptp->info->pin_config[i];
- + break;
- + }
- + }
- + mutex_unlock(&ptp->pincfg_mux);
- +
- + return pin ? i : -1;
- +}
- +EXPORT_SYMBOL(ptp_find_pin);
- +
- /* module operations */
-
- static void __exit ptp_exit(void)
- diff -Nur linux-3.14.35.orig/drivers/ptp/ptp_ixp46x.c linux-3.14.35/drivers/ptp/ptp_ixp46x.c
- --- linux-3.14.35.orig/drivers/ptp/ptp_ixp46x.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ptp/ptp_ixp46x.c 2015-03-08 14:27:37.713684500 -0500
- @@ -244,6 +244,7 @@
- .name = "IXP46X timer",
- .max_adj = 66666655,
- .n_ext_ts = N_EXT_TS,
- + .n_pins = 0,
- .pps = 0,
- .adjfreq = ptp_ixp_adjfreq,
- .adjtime = ptp_ixp_adjtime,
- diff -Nur linux-3.14.35.orig/drivers/ptp/ptp_pch.c linux-3.14.35/drivers/ptp/ptp_pch.c
- --- linux-3.14.35.orig/drivers/ptp/ptp_pch.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ptp/ptp_pch.c 2015-03-08 14:27:37.713684500 -0500
- @@ -514,6 +514,7 @@
- .name = "PCH timer",
- .max_adj = 50000000,
- .n_ext_ts = N_EXT_TS,
- + .n_pins = 0,
- .pps = 0,
- .adjfreq = ptp_pch_adjfreq,
- .adjtime = ptp_pch_adjtime,
- diff -Nur linux-3.14.35.orig/drivers/ptp/ptp_private.h linux-3.14.35/drivers/ptp/ptp_private.h
- --- linux-3.14.35.orig/drivers/ptp/ptp_private.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/ptp/ptp_private.h 2015-03-08 14:27:37.713684500 -0500
- @@ -48,6 +48,7 @@
- long dialed_frequency; /* remembers the frequency adjustment */
- struct timestamp_event_queue tsevq; /* simple fifo for time stamps */
- struct mutex tsevq_mux; /* one process at a time reading the fifo */
- + struct mutex pincfg_mux; /* protect concurrent info->pin_config access */
- wait_queue_head_t tsev_wq;
- int defunct; /* tells readers to go away when clock is being removed */
- };
- @@ -69,6 +70,10 @@
- * see ptp_chardev.c
- */
-
- +/* caller must hold pincfg_mux */
- +int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin,
- + enum ptp_pin_function func, unsigned int chan);
- +
- long ptp_ioctl(struct posix_clock *pc,
- unsigned int cmd, unsigned long arg);
-
- diff -Nur linux-3.14.35.orig/drivers/pwm/pwm-imx.c linux-3.14.35/drivers/pwm/pwm-imx.c
- --- linux-3.14.35.orig/drivers/pwm/pwm-imx.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/pwm/pwm-imx.c 2015-03-08 14:27:37.713684500 -0500
- @@ -1,4 +1,5 @@
- /*
- + * Copyright (C) 2013 Freescale Semiconductor, Inc.
- * simple driver for PWM (Pulse Width Modulator) controller
- *
- * This program is free software; you can redistribute it and/or modify
- @@ -293,11 +294,34 @@
- return pwmchip_remove(&imx->chip);
- }
-
- +#ifdef CONFIG_PM
- +static int imx_pwm_suspend(struct device *dev)
- +{
- + pinctrl_pm_select_sleep_state(dev);
- +
- + return 0;
- +}
- +
- +static int imx_pwm_resume(struct device *dev)
- +{
- + pinctrl_pm_select_default_state(dev);
- +
- + return 0;
- +}
- +
- +static const struct dev_pm_ops imx_pwm_pm_ops = {
- + SET_SYSTEM_SLEEP_PM_OPS(imx_pwm_suspend, imx_pwm_resume)
- +};
- +#endif
- +
- static struct platform_driver imx_pwm_driver = {
- .driver = {
- .name = "imx-pwm",
- .owner = THIS_MODULE,
- .of_match_table = imx_pwm_dt_ids,
- +#ifdef CONFIG_PM
- + .pm = &imx_pwm_pm_ops,
- +#endif
- },
- .probe = imx_pwm_probe,
- .remove = imx_pwm_remove,
- diff -Nur linux-3.14.35.orig/drivers/regulator/anatop-regulator.c linux-3.14.35/drivers/regulator/anatop-regulator.c
- --- linux-3.14.35.orig/drivers/regulator/anatop-regulator.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/regulator/anatop-regulator.c 2015-03-08 14:27:37.713684500 -0500
- @@ -1,5 +1,5 @@
- /*
- - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- + * Copyright (C) 2011, 2013 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
- /*
- @@ -34,6 +34,22 @@
- #define LDO_RAMP_UP_UNIT_IN_CYCLES 64 /* 64 cycles per step */
- #define LDO_RAMP_UP_FREQ_IN_MHZ 24 /* cycle based on 24M OSC */
-
- +#define REG_SET 0x4
- +#define REG_CLR 0x8
- +#define SOC_PU_FIELD_OFFSET 0x9
- +
- +/*
- + * for CORE, SOC and PU regulator, the register field
- + * has following definition: 00001 -- Target core voltage
- + * = 0.725V, which means the lowest setting in this
- + * field is 0.725V once the regulator is enabled. So
- + * when these regulators are turned on from off status,
- + * we need to count the voltage step of 0V to 0.7V, it will
- + * need additional delay, so the additional step number is
- + * 700mV / 25mV = 28.
- + */
- +#define CORE_REG_ENABLE_STEP_ADD 28
- +
- struct anatop_regulator {
- const char *name;
- u32 control_reg;
- @@ -97,12 +113,86 @@
- return regulator_get_voltage_sel_regmap(reg);
- }
-
- +/*
- + * currently on anatop regulators, only PU regulator supports
- + * enable/disable function, and its voltage must be equal
- + * to SOC voltage, so we need to get SOC voltage then set
- + * into PU regulator. Other regulators are always on due
- + * to hardware design, so enable/disable/is_enabled/enable_time
- + * functions are only used by PU regulator.
- + */
- +static int anatop_regmap_enable(struct regulator_dev *reg)
- +{
- + struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
- + u32 val;
- +
- + if (!anatop_reg->control_reg)
- + return -ENOTSUPP;
- +
- + regmap_read(anatop_reg->anatop, anatop_reg->control_reg, &val);
- + val &= ((1 << anatop_reg->vol_bit_width) - 1) <<
- + (anatop_reg->vol_bit_shift + SOC_PU_FIELD_OFFSET);
- + regmap_write(anatop_reg->anatop, anatop_reg->control_reg +
- + REG_SET, val >> SOC_PU_FIELD_OFFSET);
- +
- + return 0;
- +}
- +
- +static int anatop_regmap_disable(struct regulator_dev *reg)
- +{
- + struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
- +
- + if (!anatop_reg->control_reg)
- + return -ENOTSUPP;
- +
- + regmap_write(anatop_reg->anatop, anatop_reg->control_reg +
- + REG_CLR, ((1 << anatop_reg->vol_bit_width) - 1) <<
- + anatop_reg->vol_bit_shift);
- +
- + return 0;
- +}
- +
- +static int anatop_regmap_is_enabled(struct regulator_dev *reg)
- +{
- + struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
- + u32 val;
- +
- + if (!anatop_reg->control_reg)
- + return -ENOTSUPP;
- +
- + regmap_read(anatop_reg->anatop, anatop_reg->control_reg, &val);
- +
- + return (val >> anatop_reg->vol_bit_shift) &
- + ((1 << anatop_reg->vol_bit_width) - 1) ? 1 : 0;
- +}
- +
- +static int anatop_regmap_enable_time(struct regulator_dev *reg)
- +{
- + struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
- + u32 val, soc_val;
- +
- + if (!anatop_reg->control_reg)
- + return -ENOTSUPP;
- +
- + regmap_read(anatop_reg->anatop, anatop_reg->control_reg, &val);
- + soc_val = (val >> (anatop_reg->vol_bit_shift +
- + SOC_PU_FIELD_OFFSET)) &
- + ((1 << anatop_reg->vol_bit_width) - 1);
- +
- + return anatop_regmap_set_voltage_time_sel(reg, 0,
- + soc_val + CORE_REG_ENABLE_STEP_ADD);
- +}
- +
- static struct regulator_ops anatop_rops = {
- .set_voltage_sel = anatop_regmap_set_voltage_sel,
- .set_voltage_time_sel = anatop_regmap_set_voltage_time_sel,
- .get_voltage_sel = anatop_regmap_get_voltage_sel,
- + .enable = anatop_regmap_enable,
- + .disable = anatop_regmap_disable,
- + .is_enabled = anatop_regmap_is_enabled,
- .list_voltage = regulator_list_voltage_linear,
- .map_voltage = regulator_map_voltage_linear,
- + .enable_time = anatop_regmap_enable_time,
- };
-
- static int anatop_regulator_probe(struct platform_device *pdev)
- @@ -196,6 +286,7 @@
- config.driver_data = sreg;
- config.of_node = pdev->dev.of_node;
- config.regmap = sreg->anatop;
- + config.ena_gpio = -EINVAL;
-
- /* register regulator */
- rdev = devm_regulator_register(dev, rdesc, &config);
- diff -Nur linux-3.14.35.orig/drivers/regulator/core.c linux-3.14.35/drivers/regulator/core.c
- --- linux-3.14.35.orig/drivers/regulator/core.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/regulator/core.c 2015-03-08 14:27:37.713684500 -0500
- @@ -3,6 +3,7 @@
- *
- * Copyright 2007, 2008 Wolfson Microelectronics PLC.
- * Copyright 2008 SlimLogic Ltd.
- + * Copyright (C) 2013 Freescale Semiconductor, Inc.
- *
- * Author: Liam Girdwood <lrg@slimlogic.co.uk>
- *
- @@ -24,6 +25,7 @@
- #include <linux/suspend.h>
- #include <linux/delay.h>
- #include <linux/gpio.h>
- +#include <linux/gpio/consumer.h>
- #include <linux/of.h>
- #include <linux/regmap.h>
- #include <linux/regulator/of_regulator.h>
- @@ -77,7 +79,7 @@
- */
- struct regulator_enable_gpio {
- struct list_head list;
- - int gpio;
- + struct gpio_desc *gpiod;
- u32 enable_count; /* a number of enabled shared GPIO */
- u32 request_count; /* a number of requested shared GPIO */
- unsigned int ena_gpio_invert:1;
- @@ -1655,10 +1657,13 @@
- const struct regulator_config *config)
- {
- struct regulator_enable_gpio *pin;
- + struct gpio_desc *gpiod;
- int ret;
-
- + gpiod = gpio_to_desc(config->ena_gpio);
- +
- list_for_each_entry(pin, ®ulator_ena_gpio_list, list) {
- - if (pin->gpio == config->ena_gpio) {
- + if (pin->gpiod == gpiod) {
- rdev_dbg(rdev, "GPIO %d is already used\n",
- config->ena_gpio);
- goto update_ena_gpio_to_rdev;
- @@ -1677,7 +1682,7 @@
- return -ENOMEM;
- }
-
- - pin->gpio = config->ena_gpio;
- + pin->gpiod = gpiod;
- pin->ena_gpio_invert = config->ena_gpio_invert;
- list_add(&pin->list, ®ulator_ena_gpio_list);
-
- @@ -1696,10 +1701,10 @@
-
- /* Free the GPIO only in case of no use */
- list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) {
- - if (pin->gpio == rdev->ena_pin->gpio) {
- + if (pin->gpiod == rdev->ena_pin->gpiod) {
- if (pin->request_count <= 1) {
- pin->request_count = 0;
- - gpio_free(pin->gpio);
- + gpiod_put(pin->gpiod);
- list_del(&pin->list);
- kfree(pin);
- } else {
- @@ -1727,8 +1732,8 @@
- if (enable) {
- /* Enable GPIO at initial use */
- if (pin->enable_count == 0)
- - gpio_set_value_cansleep(pin->gpio,
- - !pin->ena_gpio_invert);
- + gpiod_set_value_cansleep(pin->gpiod,
- + !pin->ena_gpio_invert);
-
- pin->enable_count++;
- } else {
- @@ -1739,8 +1744,8 @@
-
- /* Disable GPIO if not used */
- if (pin->enable_count <= 1) {
- - gpio_set_value_cansleep(pin->gpio,
- - pin->ena_gpio_invert);
- + gpiod_set_value_cansleep(pin->gpiod,
- + pin->ena_gpio_invert);
- pin->enable_count = 0;
- }
- }
- @@ -1817,6 +1822,7 @@
- }
-
- trace_regulator_enable_complete(rdev_get_name(rdev));
- + _notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE, NULL);
-
- return 0;
- }
- @@ -1894,6 +1900,7 @@
- {
- int ret;
-
- + _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_DISABLE, NULL);
- trace_regulator_disable(rdev_get_name(rdev));
-
- if (rdev->ena_pin) {
- @@ -2140,7 +2147,7 @@
- * @regulator: regulator source
- *
- * Returns positive if the regulator driver backing the source/client
- - * can change its voltage, false otherwise. Usefull for detecting fixed
- + * can change its voltage, false otherwise. Useful for detecting fixed
- * or dummy regulators and disabling voltage change logic in the client
- * driver.
- */
- @@ -3447,7 +3454,7 @@
-
- dev_set_drvdata(&rdev->dev, rdev);
-
- - if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) {
- + if (gpio_is_valid(config->ena_gpio)) {
- ret = regulator_ena_gpio_request(rdev, config);
- if (ret != 0) {
- rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
- diff -Nur linux-3.14.35.orig/drivers/regulator/dummy.c linux-3.14.35/drivers/regulator/dummy.c
- --- linux-3.14.35.orig/drivers/regulator/dummy.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/regulator/dummy.c 2015-03-08 14:27:37.713684500 -0500
- @@ -44,6 +44,7 @@
-
- config.dev = &pdev->dev;
- config.init_data = &dummy_initdata;
- + config.ena_gpio = -EINVAL;
-
- dummy_regulator_rdev = regulator_register(&dummy_desc, &config);
- if (IS_ERR(dummy_regulator_rdev)) {
- diff -Nur linux-3.14.35.orig/drivers/regulator/fixed.c linux-3.14.35/drivers/regulator/fixed.c
- --- linux-3.14.35.orig/drivers/regulator/fixed.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/regulator/fixed.c 2015-03-08 14:27:37.713684500 -0500
- @@ -163,9 +163,7 @@
- drvdata->desc.n_voltages = 1;
-
- drvdata->desc.fixed_uV = config->microvolts;
- -
- - if (config->gpio >= 0)
- - cfg.ena_gpio = config->gpio;
- + cfg.ena_gpio = config->gpio;
- cfg.ena_gpio_invert = !config->enable_high;
- if (config->enabled_at_boot) {
- if (config->enable_high)
- diff -Nur linux-3.14.35.orig/drivers/reset/gpio-reset.c linux-3.14.35/drivers/reset/gpio-reset.c
- --- linux-3.14.35.orig/drivers/reset/gpio-reset.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/reset/gpio-reset.c 2015-03-08 14:27:37.713684500 -0500
- @@ -0,0 +1,187 @@
- +/*
- + * GPIO Reset Controller driver
- + *
- + * Copyright 2013 Philipp Zabel, Pengutronix
- + *
- + * 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.
- + */
- +#include <linux/delay.h>
- +#include <linux/err.h>
- +#include <linux/gpio.h>
- +#include <linux/module.h>
- +#include <linux/of_gpio.h>
- +#include <linux/platform_device.h>
- +#include <linux/reset-controller.h>
- +
- +struct gpio_reset_data {
- + struct reset_controller_dev rcdev;
- + unsigned int gpio;
- + bool active_low;
- + s32 delay_us;
- +};
- +
- +static void gpio_reset_set(struct reset_controller_dev *rcdev, int asserted)
- +{
- + struct gpio_reset_data *drvdata = container_of(rcdev,
- + struct gpio_reset_data, rcdev);
- + int value = asserted;
- +
- + if (drvdata->active_low)
- + value = !value;
- +
- + if (gpio_cansleep(drvdata->gpio))
- + gpio_set_value_cansleep(drvdata->gpio, value);
- + else
- + gpio_set_value(drvdata->gpio, value);
- +}
- +
- +static int gpio_reset(struct reset_controller_dev *rcdev, unsigned long id)
- +{
- + struct gpio_reset_data *drvdata = container_of(rcdev,
- + struct gpio_reset_data, rcdev);
- +
- + if (drvdata->delay_us < 0)
- + return -ENOSYS;
- +
- + gpio_reset_set(rcdev, 1);
- + udelay(drvdata->delay_us);
- + gpio_reset_set(rcdev, 0);
- +
- + return 0;
- +}
- +
- +static int gpio_reset_assert(struct reset_controller_dev *rcdev,
- + unsigned long id)
- +{
- + gpio_reset_set(rcdev, 1);
- +
- + return 0;
- +}
- +
- +static int gpio_reset_deassert(struct reset_controller_dev *rcdev,
- + unsigned long id)
- +{
- + gpio_reset_set(rcdev, 0);
- +
- + return 0;
- +}
- +
- +static struct reset_control_ops gpio_reset_ops = {
- + .reset = gpio_reset,
- + .assert = gpio_reset_assert,
- + .deassert = gpio_reset_deassert,
- +};
- +
- +static int of_gpio_reset_xlate(struct reset_controller_dev *rcdev,
- + const struct of_phandle_args *reset_spec)
- +{
- + if (WARN_ON(reset_spec->args_count != 0))
- + return -EINVAL;
- +
- + return 0;
- +}
- +
- +static int gpio_reset_probe(struct platform_device *pdev)
- +{
- + struct device_node *np = pdev->dev.of_node;
- + struct gpio_reset_data *drvdata;
- + enum of_gpio_flags flags;
- + unsigned long gpio_flags;
- + bool initially_in_reset;
- + int ret;
- +
- + drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
- + if (drvdata == NULL)
- + return -ENOMEM;
- +
- + if (of_gpio_named_count(np, "reset-gpios") != 1) {
- + dev_err(&pdev->dev,
- + "reset-gpios property missing, or not a single gpio\n");
- + return -EINVAL;
- + }
- +
- + drvdata->gpio = of_get_named_gpio_flags(np, "reset-gpios", 0, &flags);
- + if (drvdata->gpio == -EPROBE_DEFER) {
- + return drvdata->gpio;
- + } else if (!gpio_is_valid(drvdata->gpio)) {
- + dev_err(&pdev->dev, "invalid reset gpio: %d\n", drvdata->gpio);
- + return drvdata->gpio;
- + }
- +
- + drvdata->active_low = flags & OF_GPIO_ACTIVE_LOW;
- +
- + ret = of_property_read_u32(np, "reset-delay-us", &drvdata->delay_us);
- + if (ret < 0)
- + drvdata->delay_us = -1;
- + else if (drvdata->delay_us < 0)
- + dev_warn(&pdev->dev, "reset delay too high\n");
- +
- + initially_in_reset = of_property_read_bool(np, "initially-in-reset");
- + if (drvdata->active_low ^ initially_in_reset)
- + gpio_flags = GPIOF_OUT_INIT_HIGH;
- + else
- + gpio_flags = GPIOF_OUT_INIT_LOW;
- +
- + ret = devm_gpio_request_one(&pdev->dev, drvdata->gpio, gpio_flags, NULL);
- + if (ret < 0) {
- + dev_err(&pdev->dev, "failed to request gpio %d: %d\n",
- + drvdata->gpio, ret);
- + return ret;
- + }
- +
- + platform_set_drvdata(pdev, drvdata);
- +
- + drvdata->rcdev.of_node = np;
- + drvdata->rcdev.owner = THIS_MODULE;
- + drvdata->rcdev.nr_resets = 1;
- + drvdata->rcdev.ops = &gpio_reset_ops;
- + drvdata->rcdev.of_xlate = of_gpio_reset_xlate;
- + reset_controller_register(&drvdata->rcdev);
- +
- + return 0;
- +}
- +
- +static int gpio_reset_remove(struct platform_device *pdev)
- +{
- + struct gpio_reset_data *drvdata = platform_get_drvdata(pdev);
- +
- + reset_controller_unregister(&drvdata->rcdev);
- +
- + return 0;
- +}
- +
- +static struct of_device_id gpio_reset_dt_ids[] = {
- + { .compatible = "gpio-reset" },
- + { }
- +};
- +
- +static struct platform_driver gpio_reset_driver = {
- + .probe = gpio_reset_probe,
- + .remove = gpio_reset_remove,
- + .driver = {
- + .name = "gpio-reset",
- + .owner = THIS_MODULE,
- + .of_match_table = of_match_ptr(gpio_reset_dt_ids),
- + },
- +};
- +
- +static int __init gpio_reset_init(void)
- +{
- + return platform_driver_register(&gpio_reset_driver);
- +}
- +arch_initcall(gpio_reset_init);
- +
- +static void __exit gpio_reset_exit(void)
- +{
- + platform_driver_unregister(&gpio_reset_driver);
- +}
- +module_exit(gpio_reset_exit);
- +
- +MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>");
- +MODULE_DESCRIPTION("gpio reset controller");
- +MODULE_LICENSE("GPL");
- +MODULE_ALIAS("platform:gpio-reset");
- +MODULE_DEVICE_TABLE(of, gpio_reset_dt_ids);
- diff -Nur linux-3.14.35.orig/drivers/reset/Kconfig linux-3.14.35/drivers/reset/Kconfig
- --- linux-3.14.35.orig/drivers/reset/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/reset/Kconfig 2015-03-08 14:27:37.713684500 -0500
- @@ -11,3 +11,15 @@
- via GPIOs or SoC-internal reset controller modules.
-
- If unsure, say no.
- +
- +if RESET_CONTROLLER
- +
- +config RESET_GPIO
- + tristate "GPIO reset controller support"
- + default y
- + depends on GPIOLIB && OF
- + help
- + This driver provides support for reset lines that are controlled
- + directly by GPIOs.
- +
- +endif
- diff -Nur linux-3.14.35.orig/drivers/reset/Makefile linux-3.14.35/drivers/reset/Makefile
- --- linux-3.14.35.orig/drivers/reset/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/reset/Makefile 2015-03-08 14:27:37.713684500 -0500
- @@ -1,2 +1,3 @@
- obj-$(CONFIG_RESET_CONTROLLER) += core.o
- +obj-$(CONFIG_RESET_GPIO) += gpio-reset.o
- obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
- diff -Nur linux-3.14.35.orig/drivers/rtc/rtc-pcf8523.c linux-3.14.35/drivers/rtc/rtc-pcf8523.c
- --- linux-3.14.35.orig/drivers/rtc/rtc-pcf8523.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/rtc/rtc-pcf8523.c 2015-03-08 14:27:37.713684500 -0500
- @@ -7,6 +7,7 @@
- */
-
- #include <linux/bcd.h>
- +#include <linux/delay.h>
- #include <linux/i2c.h>
- #include <linux/module.h>
- #include <linux/rtc.h>
- @@ -82,24 +83,85 @@
- return 0;
- }
-
- -static int pcf8523_select_capacitance(struct i2c_client *client, bool high)
- +static int pcf8523_rtc_check_oscillator(struct i2c_client *client)
- {
- u8 value;
- int err;
-
- - err = pcf8523_read(client, REG_CONTROL1, &value);
- + err = pcf8523_read(client, REG_SECONDS, &value);
- if (err < 0)
- return err;
-
- - if (!high)
- - value &= ~REG_CONTROL1_CAP_SEL;
- - else
- - value |= REG_CONTROL1_CAP_SEL;
- + if (value & REG_SECONDS_OS) {
- + /*
- + * If the oscillator was stopped, try to clear the flag. Upon
- + * power-up the flag is always set, but if we cannot clear it
- + * the oscillator isn't running properly for some reason. The
- + * sensible thing therefore is to return an error, signalling
- + * that the clock cannot be assumed to be correct.
- + */
- +
- + value &= ~REG_SECONDS_OS;
- +
- + err = pcf8523_write(client, REG_SECONDS, value);
- + if (err < 0)
- + return err;
- +
- + err = pcf8523_read(client, REG_SECONDS, &value);
- + if (err < 0)
- + return err;
- +
- + if (value & REG_SECONDS_OS)
- + return -EAGAIN;
- + }
- +
- + return 0;
- +}
- +
- +static int pcf8523_switch_capacitance(struct i2c_client *client)
- +{
- + u8 value;
- + int err;
- +
- + err = pcf8523_read(client, REG_CONTROL1, &value);
- + if (err < 0)
- + goto out;
- +
- + value ^= REG_CONTROL1_CAP_SEL;
-
- err = pcf8523_write(client, REG_CONTROL1, value);
- +
- +out:
- + return err;
- +}
- +
- +static int pcf8523_enable_oscillator(struct i2c_client *client)
- +{
- + int err, loop;
- +
- + loop = 0;
- + while (loop < 200) {
- + err = pcf8523_rtc_check_oscillator(client);
- + if (!err)
- + return 0;
- + loop++;
- + msleep(10);
- + }
- +
- + err = pcf8523_switch_capacitance(client);
- if (err < 0)
- - return err;
- + goto out;
- +
- + loop = 0;
- + while (loop < 200) {
- + err = pcf8523_rtc_check_oscillator(client);
- + if (!err)
- + return 0;
- + loop++;
- + msleep(10);
- + }
-
- +out:
- return err;
- }
-
- @@ -290,6 +352,7 @@
- const struct i2c_device_id *id)
- {
- struct pcf8523 *pcf;
- + u8 value;
- int err;
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
- @@ -299,10 +362,20 @@
- if (!pcf)
- return -ENOMEM;
-
- - err = pcf8523_select_capacitance(client, true);
- + /* Check whether the RTC reports battery low */
- + err = pcf8523_read(client, REG_CONTROL3, &value);
- if (err < 0)
- return err;
-
- + if (value & REG_CONTROL3_BLF)
- + dev_warn(&client->dev, "RTC reports battery is low\n");
- +
- + err = pcf8523_enable_oscillator(client);
- + if (err < 0) {
- + dev_warn(&client->dev, "RTC reports oscillator is not running\n");
- + return err;
- + }
- +
- err = pcf8523_set_pm(client, 0);
- if (err < 0)
- return err;
- diff -Nur linux-3.14.35.orig/drivers/rtc/rtc-snvs.c linux-3.14.35/drivers/rtc/rtc-snvs.c
- --- linux-3.14.35.orig/drivers/rtc/rtc-snvs.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/rtc/rtc-snvs.c 2015-03-08 14:27:37.757684499 -0500
- @@ -1,5 +1,5 @@
- /*
- - * Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- @@ -41,6 +41,8 @@
- spinlock_t lock;
- };
-
- +static void __iomem *snvs_base;
- +
- static u32 rtc_read_lp_counter(void __iomem *ioaddr)
- {
- u64 read1, read2;
- @@ -241,6 +243,15 @@
- return events ? IRQ_HANDLED : IRQ_NONE;
- }
-
- +static void snvs_poweroff(void)
- +{
- + u32 value;
- +
- + value = readl(snvs_base + SNVS_LPCR);
- + /* set TOP and DP_EN bit */
- + writel(value | 0x60, snvs_base + SNVS_LPCR);
- +}
- +
- static int snvs_rtc_probe(struct platform_device *pdev)
- {
- struct snvs_rtc_data *data;
- @@ -270,13 +281,15 @@
- /* Clear interrupt status */
- writel(0xffffffff, data->ioaddr + SNVS_LPSR);
-
- + snvs_base = data->ioaddr;
- /* Enable RTC */
- snvs_rtc_enable(data, true);
-
- device_init_wakeup(&pdev->dev, true);
-
- ret = devm_request_irq(&pdev->dev, data->irq, snvs_rtc_irq_handler,
- - IRQF_SHARED, "rtc alarm", &pdev->dev);
- + IRQF_SHARED | IRQF_NO_SUSPEND,
- + "rtc alarm", &pdev->dev);
- if (ret) {
- dev_err(&pdev->dev, "failed to request irq %d: %d\n",
- data->irq, ret);
- @@ -290,6 +303,12 @@
- dev_err(&pdev->dev, "failed to register rtc: %d\n", ret);
- return ret;
- }
- + /*
- + * if no specific power off function in board file, power off system by
- + * SNVS
- + */
- + if (!pm_power_off)
- + pm_power_off = snvs_poweroff;
-
- return 0;
- }
- diff -Nur linux-3.14.35.orig/drivers/scsi/scsi_transport_iscsi.c linux-3.14.35/drivers/scsi/scsi_transport_iscsi.c
- --- linux-3.14.35.orig/drivers/scsi/scsi_transport_iscsi.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/scsi/scsi_transport_iscsi.c 2015-03-08 14:27:37.761684500 -0500
- @@ -1225,7 +1225,7 @@
- * Adds a sysfs entry for the flashnode session attributes
- *
- * Returns:
- - * pointer to allocated flashnode sess on sucess
- + * pointer to allocated flashnode sess on success
- * %NULL on failure
- */
- struct iscsi_bus_flash_session *
- @@ -1423,7 +1423,7 @@
- }
-
- /**
- - * iscsi_destroy_flashnode_sess - destory flashnode session entry
- + * iscsi_destroy_flashnode_sess - destroy flashnode session entry
- * @fnode_sess: pointer to flashnode session entry to be destroyed
- *
- * Deletes the flashnode session entry and all children flashnode connection
- @@ -1453,7 +1453,7 @@
- }
-
- /**
- - * iscsi_destroy_all_flashnode - destory all flashnode session entries
- + * iscsi_destroy_all_flashnode - destroy all flashnode session entries
- * @shost: pointer to host data
- *
- * Destroys all the flashnode session entries and all corresponding children
- diff -Nur linux-3.14.35.orig/drivers/staging/bcm/Typedefs.h linux-3.14.35/drivers/staging/bcm/Typedefs.h
- --- linux-3.14.35.orig/drivers/staging/bcm/Typedefs.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/staging/bcm/Typedefs.h 2015-03-08 14:27:37.761684500 -0500
- @@ -25,16 +25,16 @@
- typedef unsigned long ULONG;
- typedef unsigned long DWORD;
-
- -typedef char* PCHAR;
- -typedef short* PSHORT;
- -typedef int* PINT;
- -typedef long* PLONG;
- -typedef void* PVOID;
- +typedef char *PCHAR;
- +typedef short *PSHORT;
- +typedef int *PINT;
- +typedef long *PLONG;
- +typedef void *PVOID;
-
- -typedef unsigned char* PUCHAR;
- -typedef unsigned short* PUSHORT;
- -typedef unsigned int* PUINT;
- -typedef unsigned long* PULONG;
- +typedef unsigned char *PUCHAR;
- +typedef unsigned short *PUSHORT;
- +typedef unsigned int *PUINT;
- +typedef unsigned long *PULONG;
- typedef unsigned long long ULONG64;
- typedef unsigned long long LARGE_INTEGER;
- typedef unsigned int UINT32;
- diff -Nur linux-3.14.35.orig/drivers/staging/media/lirc/Kconfig linux-3.14.35/drivers/staging/media/lirc/Kconfig
- --- linux-3.14.35.orig/drivers/staging/media/lirc/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/staging/media/lirc/Kconfig 2015-03-08 14:27:37.761684500 -0500
- @@ -38,6 +38,12 @@
- help
- Driver for Homebrew Parallel Port Receivers
-
- +config LIRC_GPIO
- + tristate "Homebrew GPIO Port Receiver/Transmitter"
- + depends on LIRC
- + help
- + Driver for Homebrew GPIO Port Receiver/Transmitter
- +
- config LIRC_SASEM
- tristate "Sasem USB IR Remote"
- depends on LIRC && USB
- diff -Nur linux-3.14.35.orig/drivers/staging/media/lirc/lirc_gpio.c linux-3.14.35/drivers/staging/media/lirc/lirc_gpio.c
- --- linux-3.14.35.orig/drivers/staging/media/lirc/lirc_gpio.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/staging/media/lirc/lirc_gpio.c 2015-03-08 14:27:37.765684500 -0500
- @@ -0,0 +1,782 @@
- +/*
- + * lirc_gpio.c
- + *
- + * lirc_gpio - Device driver that records pulse- and pause-lengths
- + * (space-lengths) (just like the lirc_serial driver does)
- + * between GPIO interrupt events on GPIO capable devices.
- + * Lots of code has been taken from the lirc_serial and the
- + * lirc_rpi modules so I would like say thanks to the authors.
- + *
- + * Copyright (C) 2014 CurlyMo <curlymoo1@gmail.com>
- + * Aron Robert Szabo <aron@reon.hu>,
- + * Michael Bishop <cleverca22@gmail.com>
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + */
- +
- +/*
- + lirc_gpio {
- + compatible = "lirc_gpio";
- + gpios = <&gpio3 6 1 &gpio3 7 2>;
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_hummingboard_gpio3_6>;
- + pinctrl-1 = <&pinctrl_hummingboard_gpio3_7>;
- + linux,sense = <-1>;
- + linux,softcarrier = <1>;
- + linux,validgpios = <1 73 72 71 70 194 195 67>;
- + };
- + */
- +
- +
- +#include <linux/module.h>
- +#include <linux/errno.h>
- +#include <linux/interrupt.h>
- +#include <linux/sched.h>
- +#include <linux/kernel.h>
- +#include <linux/time.h>
- +#include <linux/string.h>
- +#include <linux/delay.h>
- +#include <linux/platform_device.h>
- +#include <linux/irq.h>
- +#include <linux/spinlock.h>
- +#include <media/lirc.h>
- +#include <media/lirc_dev.h>
- +#include <linux/gpio.h>
- +#include <linux/of.h>
- +#include <linux/of_gpio.h>
- +
- +#define LIRC_DRIVER_NAME "lirc_gpio"
- +#define RBUF_LEN 256
- +#define LIRC_TRANSMITTER_LATENCY 256
- +
- +#ifndef MAX_UDELAY_MS
- +#define MAX_UDELAY_US 5000
- +#else
- +#define MAX_UDELAY_US (MAX_UDELAY_MS*1000)
- +#endif
- +
- +static ssize_t lirc_write(struct file *file, const char *buf, size_t n, loff_t *ppos);
- +static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
- +static int set_use_inc(void *data);
- +static void set_use_dec(void *data);
- +static int lirc_gpio_probe(struct platform_device *pdev);
- +static int lirc_gpio_remove(struct platform_device *pdev);
- +
- +struct lirc_gpio_platform_data {
- + int gpio_rx_nr;
- + int gpio_tx_nr;
- + bool active_rx_low;
- + bool active_tx_low;
- + u64 allowed_rx_protos;
- + u64 allowed_tx_protos;
- + int sense;
- + int softcarrier;
- + int validgpios[255];
- +};
- +
- +struct lirc_gpio_dev {
- + int gpio_rx_nr;
- + int gpio_tx_nr;
- + int sense;
- + int softcarrier;
- + int validgpios[255];
- +};
- +
- +struct lirc_gpio_dev *gpio_dev;
- +
- +static const struct file_operations lirc_fops = {
- + .owner = THIS_MODULE,
- + .write = lirc_write,
- + .unlocked_ioctl = lirc_ioctl,
- + .read = lirc_dev_fop_read,
- + .poll = lirc_dev_fop_poll,
- + .open = lirc_dev_fop_open,
- + .release = lirc_dev_fop_close,
- + .llseek = no_llseek,
- +};
- +
- +struct irq_chip *irqchip;
- +struct irq_data *irqdata;
- +
- +static struct timeval lasttv = { 0, 0 };
- +static struct lirc_buffer rbuf;
- +static spinlock_t lock;
- +
- +/* set the default GPIO input pin */
- +static int gpio_in_pin = -1;
- +/* set the default GPIO output pin */
- +static int gpio_out_pin = -1;
- +/* -1 = auto, 0 = active high, 1 = active low */
- +static int sense = -2;
- +/* use softcarrier by default */
- +static int softcarrier = -1;
- +
- +/* initialized/set in init_timing_params() */
- +static unsigned int freq = 38000;
- +static unsigned int duty_cycle = 50;
- +static unsigned long period;
- +static unsigned long pulse_width;
- +static unsigned long space_width;
- +
- +static struct lirc_driver driver = {
- + .name = LIRC_DRIVER_NAME,
- + .minor = -1,
- + .code_length = 1,
- + .sample_rate = 0,
- + .data = NULL,
- + .add_to_buf = NULL,
- + .rbuf = &rbuf,
- + .set_use_inc = set_use_inc,
- + .set_use_dec = set_use_dec,
- + .fops = &lirc_fops,
- + .dev = NULL,
- + .owner = THIS_MODULE,
- +};
- +
- +static struct of_device_id lirc_gpio_of_match[] = {
- + { .compatible = "lirc_gpio", },
- + {}
- +};
- +
- +static struct platform_driver lirc_gpio_driver = {
- + .probe = lirc_gpio_probe,
- + .remove = lirc_gpio_remove,
- + .driver = {
- + .name = LIRC_DRIVER_NAME,
- + .owner = THIS_MODULE,
- + .of_match_table = lirc_gpio_of_match,
- + },
- +};
- +
- +static void safe_udelay(unsigned long usecs) {
- + while (usecs > MAX_UDELAY_US) {
- + udelay(MAX_UDELAY_US);
- + usecs -= MAX_UDELAY_US;
- + }
- + udelay(usecs);
- +}
- +
- +static int init_timing_params(unsigned int new_duty_cycle, unsigned int new_freq) {
- + /*
- + * period, pulse/space width are kept with 8 binary places -
- + * IE multiplied by 256.
- + */
- + if(256 * 1000000L / new_freq * new_duty_cycle / 100 <=
- + LIRC_TRANSMITTER_LATENCY)
- + return -EINVAL;
- + if(256 * 1000000L / new_freq * (100 - new_duty_cycle) / 100 <=
- + LIRC_TRANSMITTER_LATENCY)
- + return -EINVAL;
- + duty_cycle = new_duty_cycle;
- + freq = new_freq;
- + period = 256 * 1000000L / freq;
- + pulse_width = period * duty_cycle / 100;
- + space_width = period - pulse_width;
- + return 0;
- +}
- +
- +
- +static long send_pulse_softcarrier(unsigned long length) {
- + int flag;
- + unsigned long actual, target, d;
- +
- + if(gpio_dev->gpio_tx_nr >= 0) {
- + length <<= 8;
- +
- + actual = 0; target = 0; flag = 0;
- + while(actual < length) {
- + if(flag) {
- + gpio_set_value(gpio_dev->gpio_tx_nr, 0);
- + target += space_width;
- + } else {
- + gpio_set_value(gpio_dev->gpio_tx_nr, 1);
- + target += pulse_width;
- + }
- + d = (target - actual - LIRC_TRANSMITTER_LATENCY + 128) >> 8;
- + /*
- + * Note - we've checked in ioctl that the pulse/space
- + * widths are big enough so that d is > 0
- + */
- + udelay(d);
- + actual += (d << 8) + LIRC_TRANSMITTER_LATENCY;
- + flag = !flag;
- + }
- + return (actual-length) >> 8;
- + }
- + return 0;
- +}
- +
- +static long send_pulse(unsigned long length) {
- + if(length <= 0)
- + return 0;
- +
- + if(gpio_dev->gpio_tx_nr >= 0) {
- + if(gpio_dev->softcarrier) {
- + return send_pulse_softcarrier(length);
- + } else {
- + gpio_set_value(gpio_dev->gpio_tx_nr, 1);
- + safe_udelay(length);
- + return 0;
- + }
- + }
- + return 0;
- +}
- +
- +static void send_space(long length) {
- + if(gpio_dev->gpio_tx_nr >= 0) {
- + gpio_set_value(gpio_dev->gpio_tx_nr, 0);
- + if(length <= 0)
- + return;
- + safe_udelay(length);
- + }
- +}
- +
- +static void rbwrite(int l) {
- + if (lirc_buffer_full(&rbuf)) {
- + /* no new signals will be accepted */
- + return;
- + }
- + lirc_buffer_write(&rbuf, (void *)&l);
- +}
- +
- +static void frbwrite(int l) {
- + /* simple noise filter */
- + static int pulse, space;
- + static unsigned int ptr;
- +
- + if(ptr > 0 && (l & PULSE_BIT)) {
- + pulse += l & PULSE_MASK;
- + if(pulse > 250) {
- + rbwrite(space);
- + rbwrite(pulse | PULSE_BIT);
- + ptr = 0;
- + pulse = 0;
- + }
- + return;
- + }
- + if(!(l & PULSE_BIT)) {
- + if(ptr == 0) {
- + if (l > 20000) {
- + space = l;
- + ptr++;
- + return;
- + }
- + } else {
- + if(l > 20000) {
- + space += pulse;
- + if (space > PULSE_MASK)
- + space = PULSE_MASK;
- + space += l;
- + if (space > PULSE_MASK)
- + space = PULSE_MASK;
- + pulse = 0;
- + return;
- + }
- + rbwrite(space);
- + rbwrite(pulse | PULSE_BIT);
- + ptr = 0;
- + pulse = 0;
- + }
- + }
- + rbwrite(l);
- +}
- +
- +static irqreturn_t irq_handler(int i, void *blah, struct pt_regs *regs) {
- + struct timeval tv;
- + long deltv;
- + int data;
- + int signal;
- +
- + /* use the GPIO signal level */
- + signal = gpio_get_value(gpio_dev->gpio_rx_nr);
- +
- + /* unmask the irq */
- + irqchip->irq_unmask(irqdata);
- +
- + if(gpio_dev->sense != -1) {
- + /* The HB GPIO input acts like it is an analogue input.
- + Therefor a high signal is 256 and a low signal is 1.
- + For Lirc to properly interpret the spaces and pulses,
- + we need to transform these to ones and zeros. To be
- + on the safe side, every signal higher then 128 will
- + be interpreted as a high and vice versa. */
- + if (signal > 128) {
- + signal = 1;
- + } else {
- + signal = 0;
- + }
- + /* get current time */
- + do_gettimeofday(&tv);
- +
- + /* calc time since last interrupt in microseconds */
- + deltv = tv.tv_sec-lasttv.tv_sec;
- + if(tv.tv_sec < lasttv.tv_sec ||
- + (tv.tv_sec == lasttv.tv_sec &&
- + tv.tv_usec < lasttv.tv_usec)) {
- + printk(KERN_WARNING LIRC_DRIVER_NAME
- + ": AIEEEE: your clock just jumped backwards\n");
- + printk(KERN_WARNING LIRC_DRIVER_NAME
- + ": %d %d %lx %lx %lx %lx\n", signal, gpio_dev->sense,
- + tv.tv_sec, lasttv.tv_sec,
- + tv.tv_usec, lasttv.tv_usec);
- + data = PULSE_MASK;
- + } else if (deltv > 15) {
- + data = PULSE_MASK; /* really long time */
- + if(!(signal^gpio_dev->sense)) {
- + /* sanity check */
- + printk(KERN_WARNING LIRC_DRIVER_NAME
- + ": AIEEEE: %d %d %lx %lx %lx %lx\n",
- + signal, gpio_dev->sense, tv.tv_sec, lasttv.tv_sec,
- + tv.tv_usec, lasttv.tv_usec);
- + /*
- + * detecting pulse while this
- + * MUST be a space!
- + */
- + gpio_dev->sense = gpio_dev->sense ? 0 : 1;
- + }
- + } else {
- + data = (int) (deltv*1000000 +
- + (tv.tv_usec - lasttv.tv_usec));
- + }
- + frbwrite(signal^gpio_dev->sense ? data : (data|PULSE_BIT));
- + lasttv = tv;
- + wake_up_interruptible(&rbuf.wait_poll);
- + }
- +
- + return IRQ_HANDLED;
- +}
- +
- +// called when the character device is opened
- +static int set_use_inc(void *data) {
- + int result;
- + unsigned long flags;
- +
- + /* initialize timestamp */
- + do_gettimeofday(&lasttv);
- +
- + if(gpio_dev->gpio_rx_nr >= 0) {
- + result = request_irq(gpio_to_irq(gpio_dev->gpio_rx_nr),
- + (irq_handler_t) irq_handler, 0,
- + LIRC_DRIVER_NAME, (void*) 0);
- +
- + switch (result) {
- + case -EBUSY:
- + printk(KERN_ERR LIRC_DRIVER_NAME
- + ": IRQ %d is busy\n",
- + gpio_to_irq(gpio_dev->gpio_rx_nr));
- + return -EBUSY;
- + case -EINVAL:
- + printk(KERN_ERR LIRC_DRIVER_NAME
- + ": Bad irq number or handler\n");
- + return -EINVAL;
- + default:
- + break;
- + };
- +
- + /* initialize pulse/space widths */
- + init_timing_params(duty_cycle, freq);
- +
- + spin_lock_irqsave(&lock, flags);
- +
- + /* GPIO Pin Falling/Rising Edge Detect Enable */
- + irqchip->irq_set_type(irqdata,
- + IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING);
- +
- + /* unmask the irq */
- + irqchip->irq_unmask(irqdata);
- +
- + spin_unlock_irqrestore(&lock, flags);
- + }
- +
- + return 0;
- +}
- +
- +static void set_use_dec(void *data) {
- + unsigned long flags;
- + if(gpio_dev->gpio_rx_nr >= 0) {
- + spin_lock_irqsave(&lock, flags);
- +
- + /* GPIO Pin Falling/Rising Edge Detect Disable */
- + irqchip->irq_set_type(irqdata, 0);
- + irqchip->irq_mask(irqdata);
- +
- + spin_unlock_irqrestore(&lock, flags);
- +
- + free_irq(gpio_to_irq(gpio_dev->gpio_rx_nr), (void *) 0);
- + }
- +}
- +
- +static ssize_t lirc_write(struct file *file, const char *buf, size_t n, loff_t *ppos) {
- + int i, count;
- + unsigned long flags;
- + long delta = 0;
- + int *wbuf;
- +
- + if(gpio_dev->gpio_tx_nr >= 0) {
- + count = n / sizeof(int);
- + if(n % sizeof(int) || count % 2 == 0)
- + return -EINVAL;
- + wbuf = memdup_user(buf, n);
- + if(IS_ERR(wbuf))
- + return PTR_ERR(wbuf);
- + spin_lock_irqsave(&lock, flags);
- +
- + for(i = 0; i < count; i++) {
- + if(i%2)
- + send_space(wbuf[i] - delta);
- + else
- + delta = send_pulse(wbuf[i]);
- + }
- + gpio_set_value(gpio_dev->gpio_tx_nr, 0);
- +
- + spin_unlock_irqrestore(&lock, flags);
- + kfree(wbuf);
- + return n;
- + }
- + return 0;
- +}
- +
- +
- +static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) {
- + int result;
- + __u32 value;
- +
- + switch(cmd) {
- + case LIRC_GET_SEND_MODE:
- + return -ENOIOCTLCMD;
- + break;
- +
- + case LIRC_SET_SEND_MODE:
- + result = get_user(value, (__u32 *) arg);
- + if(result)
- + return result;
- + /* only LIRC_MODE_PULSE supported */
- + if(value != LIRC_MODE_PULSE)
- + return -ENOSYS;
- + break;
- +
- + case LIRC_GET_LENGTH:
- + return -ENOSYS;
- + break;
- +
- + case LIRC_SET_SEND_DUTY_CYCLE:
- + result = get_user(value, (__u32 *) arg);
- + if (result)
- + return result;
- + if (value <= 0 || value > 100)
- + return -EINVAL;
- + return init_timing_params(value, freq);
- + break;
- +
- + case LIRC_SET_SEND_CARRIER:
- + result = get_user(value, (__u32 *) arg);
- + if(result)
- + return result;
- + if(value > 500000 || value < 20000)
- + return -EINVAL;
- + return init_timing_params(duty_cycle, value);
- + break;
- +
- + default:
- + return lirc_dev_fop_ioctl(filep, cmd, arg);
- + }
- + return 0;
- +}
- +
- +static int lirc_gpio_get_devtree_pdata(struct device *dev, struct lirc_gpio_platform_data *pdata) {
- + struct device_node *np = dev->of_node;
- + enum of_gpio_flags flags;
- + struct property *prop;
- + const __be32 *cur;
- + int gpio = -1;
- + int ret = 0;
- + int i = 0;
- +
- + if(np) {
- + gpio = of_get_gpio_flags(np, 0, &flags);
- + if(gpio < 0) {
- + if(gpio != -EPROBE_DEFER)
- + dev_err(dev, "RX gpio not defined (%d)\n", gpio);
- +
- + pdata->gpio_rx_nr = -1;
- + pdata->active_rx_low = 0;
- + pdata->allowed_rx_protos = 0;
- + } else {
- + pdata->gpio_rx_nr = gpio;
- + pdata->active_rx_low = (flags & OF_GPIO_ACTIVE_LOW);
- + pdata->allowed_rx_protos = 0;
- + }
- +
- + gpio = of_get_gpio_flags(np, 1, &flags);
- + if(gpio < 0) {
- + if(gpio != -EPROBE_DEFER)
- + dev_err(dev, "TX gpio not defined (%d)\n", gpio);
- +
- + pdata->gpio_tx_nr = -1;
- + pdata->active_tx_low = 0;
- + pdata->allowed_tx_protos = 0;
- + } else {
- + pdata->gpio_tx_nr = gpio;
- + pdata->active_tx_low = (flags & OF_GPIO_ACTIVE_LOW);
- + pdata->allowed_tx_protos = 0;
- + }
- + ret = of_property_read_u32(np, "linux,sense", &pdata->sense);
- + if(ret) {
- + pdata->sense = -1;
- + }
- + ret = of_property_read_u32(np, "linux,softcarrier", &pdata->softcarrier);
- + if(ret) {
- + pdata->softcarrier = 1;
- + }
- + i = 0;
- + printk(KERN_DEBUG LIRC_DRIVER_NAME ": valid gpios");
- + of_property_for_each_u32(np, "linux,validgpios", prop, cur, gpio) {
- + printk(" %d", gpio);
- + pdata->validgpios[i++] = gpio;
- + }
- + printk("\n");
- + pdata->validgpios[i] = -1;
- + }
- +
- + return 0;
- +}
- +
- +static int init_port(void) {
- + int i, nlow, nhigh, ret, irq;
- +
- + if(gpio_dev->gpio_tx_nr >= 0) {
- + if(gpio_request(gpio_dev->gpio_tx_nr, LIRC_DRIVER_NAME " ir/out")) {
- + printk(KERN_ALERT LIRC_DRIVER_NAME ": cant claim gpio pin %d\n", gpio_dev->gpio_tx_nr);
- + ret = -ENODEV;
- + goto exit_init_port;
- + }
- + }
- +
- + if(gpio_dev->gpio_rx_nr >= 0) {
- + if(gpio_request(gpio_dev->gpio_rx_nr, LIRC_DRIVER_NAME " ir/in")) {
- + printk(KERN_ALERT LIRC_DRIVER_NAME ": cant claim gpio pin %d\n", gpio_dev->gpio_rx_nr);
- + ret = -ENODEV;
- + goto exit_gpio_free_out_pin;
- + }
- + }
- +
- + if(gpio_dev->gpio_rx_nr >= 0) {
- + gpio_direction_input(gpio_dev->gpio_rx_nr);
- + }
- + if(gpio_dev->gpio_tx_nr >= 0) {
- + gpio_direction_output(gpio_dev->gpio_tx_nr, 1);
- + gpio_set_value(gpio_dev->gpio_tx_nr, 0);
- + }
- +
- + if(gpio_dev->gpio_rx_nr >= 0) {
- + irq = gpio_to_irq(gpio_dev->gpio_rx_nr);
- + irqdata = irq_get_irq_data(irq);
- +
- + if(irqdata && irqdata->chip) {
- + irqchip = irqdata->chip;
- + } else {
- + ret = -ENODEV;
- + goto exit_gpio_free_in_pin;
- + }
- +
- + /* if pin is high, then this must be an active low receiver. */
- + if(gpio_dev->sense == -1) {
- + /* wait 1/2 sec for the power supply */
- + msleep(500);
- +
- + /*
- + * probe 9 times every 0.04s, collect "votes" for
- + * active high/low
- + */
- + nlow = 0;
- + nhigh = 0;
- + for(i = 0; i < 9; i++) {
- + if(gpio_get_value(gpio_dev->gpio_rx_nr))
- + nlow++;
- + else
- + nhigh++;
- + msleep(40);
- + }
- + gpio_dev->sense = (nlow >= nhigh ? 1 : 0);
- + printk(KERN_INFO LIRC_DRIVER_NAME ": auto-detected active %s receiver on GPIO pin %d\n",
- + gpio_dev->sense ? "low" : "high", gpio_dev->gpio_rx_nr);
- + } else {
- + printk(KERN_INFO LIRC_DRIVER_NAME ": manually using active %s receiver on GPIO pin %d\n",
- + gpio_dev->sense ? "low" : "high", gpio_dev->gpio_rx_nr);
- + }
- + }
- +
- + return 0;
- +
- +exit_gpio_free_in_pin:
- + gpio_free(gpio_dev->gpio_rx_nr);
- +
- +exit_gpio_free_out_pin:
- + gpio_free(gpio_dev->gpio_tx_nr);
- +
- +exit_init_port:
- + return ret;
- +}
- +
- +static void lirc_gpio_exit(void) {
- + if(gpio_dev->gpio_tx_nr >= 0) {
- + gpio_free(gpio_dev->gpio_tx_nr);
- + }
- + if(gpio_dev->gpio_rx_nr >= 0) {
- + gpio_free(gpio_dev->gpio_rx_nr);
- + }
- +
- + lirc_unregister_driver(driver.minor);
- + lirc_buffer_free(&rbuf);
- +}
- +
- +static int lirc_gpio_probe(struct platform_device *pdev) {
- + const struct lirc_gpio_platform_data *pdata =
- + pdev->dev.platform_data;
- + int rc;
- + int result = 0;
- + int match = 0;
- + int i = 0;
- +
- + if(pdev->dev.of_node) {
- + struct lirc_gpio_platform_data *dtpdata = devm_kzalloc(&pdev->dev, sizeof(*dtpdata), GFP_KERNEL);
- + if(!dtpdata)
- + return -ENOMEM;
- + rc = lirc_gpio_get_devtree_pdata(&pdev->dev, dtpdata);
- + if(rc)
- + return rc;
- + pdata = dtpdata;
- + }
- +
- + if(!pdata)
- + return -EINVAL;
- +
- + gpio_dev = kzalloc(sizeof(struct lirc_gpio_dev), GFP_KERNEL);
- + if(!gpio_dev)
- + return -ENOMEM;
- +
- + gpio_dev->gpio_rx_nr = pdata->gpio_rx_nr;
- + gpio_dev->gpio_tx_nr = pdata->gpio_tx_nr;
- + gpio_dev->sense = pdata->sense;
- + gpio_dev->softcarrier = pdata->softcarrier;
- + memcpy(gpio_dev->validgpios, pdata->validgpios, 255);
- +
- + if(gpio_in_pin != gpio_out_pin) {
- + match = 0;
- + for(i = 0; (i < ARRAY_SIZE(gpio_dev->validgpios)) && (!match) && (gpio_dev->validgpios[i] != -1); i++) {
- + if(gpio_in_pin == gpio_dev->validgpios[i]) {
- + match = 1;
- + break;
- + }
- + }
- + if(gpio_in_pin > -1) {
- + if(!match) {
- + printk(KERN_ERR LIRC_DRIVER_NAME
- + ": invalid RX GPIO pin specified!\n");
- + return -EINVAL;
- + } else {
- + gpio_dev->gpio_rx_nr = gpio_in_pin;
- + }
- + }
- + match = 0;
- + for(i = 0; (i < ARRAY_SIZE(gpio_dev->validgpios)) && (!match) && (gpio_dev->validgpios[i] != -1); i++) {
- + if(gpio_out_pin == gpio_dev->validgpios[i]) {
- + match = 1;
- + break;
- + }
- + }
- + if(gpio_out_pin > -1) {
- + if(!match) {
- + printk(KERN_ERR LIRC_DRIVER_NAME
- + ": invalid TX GPIO pin specified!\n");
- + return -EINVAL;
- + } else {
- + gpio_dev->gpio_tx_nr = gpio_out_pin;
- + }
- + }
- + }
- + if(sense > -2) {
- + gpio_dev->sense = sense;
- + }
- + if(softcarrier >= 0) {
- + gpio_dev->softcarrier = softcarrier;
- + }
- +
- + printk(KERN_DEBUG LIRC_DRIVER_NAME ": rx %d, tx %d, sense %d, softcarrier %d\n",
- + gpio_dev->gpio_rx_nr, gpio_dev->gpio_tx_nr, gpio_dev->sense, gpio_dev->softcarrier);
- +
- + platform_set_drvdata(pdev, gpio_dev);
- +
- + result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN);
- + if(result < 0)
- + return -ENOMEM;
- +
- + driver.features = LIRC_CAN_SET_SEND_DUTY_CYCLE |
- + LIRC_CAN_SET_SEND_CARRIER |
- + LIRC_CAN_SEND_PULSE |
- + LIRC_CAN_REC_MODE2;
- +
- + driver.dev = &pdev->dev;
- + driver.minor = lirc_register_driver(&driver);
- +
- + if(driver.minor < 0) {
- + printk(KERN_ERR LIRC_DRIVER_NAME ": device registration failed with %d\n", result);
- + result = -EIO;
- + goto exit_gpio;
- + }
- +
- + result = init_port();
- + if(result < 0)
- + goto exit_gpio;
- +
- + return 0;
- +
- +exit_gpio:
- + lirc_gpio_exit();
- +
- + return result;
- +}
- +
- +static int lirc_gpio_remove(struct platform_device *pdev) {
- + struct lirc_gpio_dev *gpio_dev = platform_get_drvdata(pdev);
- +
- + lirc_gpio_exit();
- +
- + kfree(gpio_dev);
- +
- + return 0;
- +}
- +
- +MODULE_DEVICE_TABLE(of, lirc_gpio_of_match);
- +module_platform_driver(lirc_gpio_driver);
- +
- +MODULE_DESCRIPTION("Infra-red GPIO receiver and blaster driver.");
- +MODULE_AUTHOR("CurlyMo <development@xbian.org>");
- +MODULE_AUTHOR("Aron Robert Szabo <aron@reon.hu>");
- +MODULE_AUTHOR("Michael Bishop <cleverca22@gmail.com>");
- +MODULE_LICENSE("GPL");
- +
- +module_param(gpio_out_pin, int, S_IRUGO);
- +MODULE_PARM_DESC(gpio_out_pin, "GPIO output/transmitter pin number");
- +
- +module_param(gpio_in_pin, int, S_IRUGO);
- +MODULE_PARM_DESC(gpio_in_pin, "GPIO input/receiver pin number.");
- +
- +module_param(sense, int, S_IRUGO);
- +MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit"
- + " (0 = active high, 1 = active low )");
- +
- +module_param(softcarrier, int, S_IRUGO);
- +MODULE_PARM_DESC(softcarrier, "Software carrier (0 = off, 1 = on, default on)");
- +
- diff -Nur linux-3.14.35.orig/drivers/staging/octeon/ethernet-rgmii.c linux-3.14.35/drivers/staging/octeon/ethernet-rgmii.c
- --- linux-3.14.35.orig/drivers/staging/octeon/ethernet-rgmii.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/staging/octeon/ethernet-rgmii.c 2015-03-08 14:27:37.765684500 -0500
- @@ -166,9 +166,8 @@
-
- if (use_global_register_lock)
- spin_unlock_irqrestore(&global_register_lock, flags);
- - else {
- + else
- mutex_unlock(&priv->phydev->bus->mdio_lock);
- - }
-
- if (priv->phydev == NULL) {
- /* Tell core. */
- diff -Nur linux-3.14.35.orig/drivers/staging/rtl8821ae/core.c linux-3.14.35/drivers/staging/rtl8821ae/core.c
- --- linux-3.14.35.orig/drivers/staging/rtl8821ae/core.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/staging/rtl8821ae/core.c 2015-03-08 14:27:37.765684500 -0500
- @@ -1414,23 +1414,15 @@
- * before switch channle or power save, or tx buffer packet
- * maybe send after offchannel or rf sleep, this may cause
- * dis-association by AP */
- -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
- -static void rtl_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
- +static void rtl_op_flush(struct ieee80211_hw *hw,
- + struct ieee80211_vif *vif,
- + u32 queues, bool drop)
- {
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- if (rtlpriv->intf_ops->flush)
- rtlpriv->intf_ops->flush(hw, queues, drop);
- }
- -#else
- -static void rtl_op_flush(struct ieee80211_hw *hw, bool drop)
- -{
- - struct rtl_priv *rtlpriv = rtl_priv(hw);
- -
- - if (rtlpriv->intf_ops->flush)
- - rtlpriv->intf_ops->flush(hw, drop);
- -}
- -#endif
-
- const struct ieee80211_ops rtl_ops = {
- .start = rtl_op_start,
- diff -Nur linux-3.14.35.orig/drivers/thermal/device_cooling.c linux-3.14.35/drivers/thermal/device_cooling.c
- --- linux-3.14.35.orig/drivers/thermal/device_cooling.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/thermal/device_cooling.c 2015-03-08 14:27:37.765684500 -0500
- @@ -0,0 +1,151 @@
- +/*
- + * Copyright (C) 2013 Freescale Semiconductor, Inc.
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + */
- +
- +#include <linux/module.h>
- +#include <linux/thermal.h>
- +#include <linux/err.h>
- +#include <linux/slab.h>
- +
- +struct devfreq_cooling_device {
- + int id;
- + struct thermal_cooling_device *cool_dev;
- + unsigned int devfreq_state;
- +};
- +
- +static DEFINE_IDR(devfreq_idr);
- +static DEFINE_MUTEX(devfreq_cooling_lock);
- +
- +#define MAX_STATE 1
- +
- +static BLOCKING_NOTIFIER_HEAD(devfreq_cooling_chain_head);
- +
- +int register_devfreq_cooling_notifier(struct notifier_block *nb)
- +{
- + return blocking_notifier_chain_register(
- + &devfreq_cooling_chain_head, nb);
- +}
- +EXPORT_SYMBOL_GPL(register_devfreq_cooling_notifier);
- +
- +int unregister_devfreq_cooling_notifier(struct notifier_block *nb)
- +{
- + return blocking_notifier_chain_unregister(
- + &devfreq_cooling_chain_head, nb);
- +}
- +EXPORT_SYMBOL_GPL(unregister_devfreq_cooling_notifier);
- +
- +static int devfreq_cooling_notifier_call_chain(unsigned long val)
- +{
- + return (blocking_notifier_call_chain(
- + &devfreq_cooling_chain_head, val, NULL)
- + == NOTIFY_BAD) ? -EINVAL : 0;
- +}
- +
- +static int devfreq_set_cur_state(struct thermal_cooling_device *cdev,
- + unsigned long state)
- +{
- + struct devfreq_cooling_device *devfreq_device = cdev->devdata;
- + int ret;
- +
- + ret = devfreq_cooling_notifier_call_chain(state);
- + if (ret)
- + return -EINVAL;
- + devfreq_device->devfreq_state = state;
- +
- + return 0;
- +}
- +
- +static int devfreq_get_max_state(struct thermal_cooling_device *cdev,
- + unsigned long *state)
- +{
- + *state = MAX_STATE;
- +
- + return 0;
- +}
- +
- +static int devfreq_get_cur_state(struct thermal_cooling_device *cdev,
- + unsigned long *state)
- +{
- + struct devfreq_cooling_device *devfreq_device = cdev->devdata;
- +
- + *state = devfreq_device->devfreq_state;
- +
- + return 0;
- +}
- +
- +static struct thermal_cooling_device_ops const devfreq_cooling_ops = {
- + .get_max_state = devfreq_get_max_state,
- + .get_cur_state = devfreq_get_cur_state,
- + .set_cur_state = devfreq_set_cur_state,
- +};
- +
- +static int get_idr(struct idr *idr, int *id)
- +{
- + int ret;
- +
- + mutex_lock(&devfreq_cooling_lock);
- + ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL);
- + mutex_unlock(&devfreq_cooling_lock);
- + if (unlikely(ret < 0))
- + return ret;
- + *id = ret;
- +
- + return 0;
- +}
- +
- +static void release_idr(struct idr *idr, int id)
- +{
- + mutex_lock(&devfreq_cooling_lock);
- + idr_remove(idr, id);
- + mutex_unlock(&devfreq_cooling_lock);
- +}
- +
- +struct thermal_cooling_device *devfreq_cooling_register(void)
- +{
- + struct thermal_cooling_device *cool_dev;
- + struct devfreq_cooling_device *devfreq_dev = NULL;
- + char dev_name[THERMAL_NAME_LENGTH];
- + int ret = 0;
- +
- + devfreq_dev = kzalloc(sizeof(struct devfreq_cooling_device),
- + GFP_KERNEL);
- + if (!devfreq_dev)
- + return ERR_PTR(-ENOMEM);
- +
- + ret = get_idr(&devfreq_idr, &devfreq_dev->id);
- + if (ret) {
- + kfree(devfreq_dev);
- + return ERR_PTR(-EINVAL);
- + }
- +
- + snprintf(dev_name, sizeof(dev_name), "thermal-devfreq-%d",
- + devfreq_dev->id);
- +
- + cool_dev = thermal_cooling_device_register(dev_name, devfreq_dev,
- + &devfreq_cooling_ops);
- + if (!cool_dev) {
- + release_idr(&devfreq_idr, devfreq_dev->id);
- + kfree(devfreq_dev);
- + return ERR_PTR(-EINVAL);
- + }
- + devfreq_dev->cool_dev = cool_dev;
- + devfreq_dev->devfreq_state = 0;
- +
- + return cool_dev;
- +}
- +EXPORT_SYMBOL_GPL(devfreq_cooling_register);
- +
- +void devfreq_cooling_unregister(struct thermal_cooling_device *cdev)
- +{
- + struct devfreq_cooling_device *devfreq_dev = cdev->devdata;
- +
- + thermal_cooling_device_unregister(devfreq_dev->cool_dev);
- + release_idr(&devfreq_idr, devfreq_dev->id);
- + kfree(devfreq_dev);
- +}
- +EXPORT_SYMBOL_GPL(devfreq_cooling_unregister);
- diff -Nur linux-3.14.35.orig/drivers/thermal/imx_thermal.c linux-3.14.35/drivers/thermal/imx_thermal.c
- --- linux-3.14.35.orig/drivers/thermal/imx_thermal.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/thermal/imx_thermal.c 2015-03-08 14:27:37.765684500 -0500
- @@ -12,6 +12,7 @@
- #include <linux/cpufreq.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- +#include <linux/device_cooling.h>
- #include <linux/init.h>
- #include <linux/interrupt.h>
- #include <linux/io.h>
- @@ -58,13 +59,14 @@
- * that will trigger cooling action when crossed.
- */
- #define IMX_TEMP_PASSIVE 85000
- +#define IMX_TEMP_PASSIVE_COOL_DELTA 10000
-
- #define IMX_POLLING_DELAY 2000 /* millisecond */
- #define IMX_PASSIVE_DELAY 1000
-
- struct imx_thermal_data {
- struct thermal_zone_device *tz;
- - struct thermal_cooling_device *cdev;
- + struct thermal_cooling_device *cdev[2];
- enum thermal_device_mode mode;
- struct regmap *tempmon;
- int c1, c2; /* See formula in imx_get_sensor_data() */
- @@ -286,6 +288,24 @@
- return 0;
- }
-
- + int imx_get_trend(struct thermal_zone_device *tz,
- + int trip, enum thermal_trend *trend)
- +{
- + int ret;
- + unsigned long trip_temp;
- +
- + ret = imx_get_trip_temp(tz, trip, &trip_temp);
- + if (ret < 0)
- + return ret;
- +
- + if (tz->temperature >= (trip_temp - IMX_TEMP_PASSIVE_COOL_DELTA))
- + *trend = THERMAL_TREND_RAISE_FULL;
- + else
- + *trend = THERMAL_TREND_DROP_FULL;
- +
- + return 0;
- +}
- +
- static struct thermal_zone_device_ops imx_tz_ops = {
- .bind = imx_bind,
- .unbind = imx_unbind,
- @@ -295,6 +315,7 @@
- .get_trip_type = imx_get_trip_type,
- .get_trip_temp = imx_get_trip_temp,
- .get_crit_temp = imx_get_crit_temp,
- + .get_trend = imx_get_trend,
- .set_trip_temp = imx_set_trip_temp,
- };
-
- @@ -437,9 +458,17 @@
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
-
- cpumask_set_cpu(0, &clip_cpus);
- - data->cdev = cpufreq_cooling_register(&clip_cpus);
- - if (IS_ERR(data->cdev)) {
- - ret = PTR_ERR(data->cdev);
- + data->cdev[0] = cpufreq_cooling_register(&clip_cpus);
- + if (IS_ERR(data->cdev[0])) {
- + ret = PTR_ERR(data->cdev[0]);
- + dev_err(&pdev->dev,
- + "failed to register cpufreq cooling device: %d\n", ret);
- + return ret;
- + }
- +
- + data->cdev[1] = cpufreq_cooling_register(&clip_cpus);
- + if (IS_ERR(data->cdev[1])) {
- + ret = PTR_ERR(data->cdev[1]);
- dev_err(&pdev->dev,
- "failed to register cpufreq cooling device: %d\n", ret);
- return ret;
- @@ -455,7 +484,8 @@
- ret = PTR_ERR(data->tz);
- dev_err(&pdev->dev,
- "failed to register thermal zone device %d\n", ret);
- - cpufreq_cooling_unregister(data->cdev);
- + cpufreq_cooling_unregister(data->cdev[0]);
- + devfreq_cooling_unregister(data->cdev[1]);
- return ret;
- }
-
- @@ -500,7 +530,8 @@
- clk_disable_unprepare(data->thermal_clk);
-
- thermal_zone_device_unregister(data->tz);
- - cpufreq_cooling_unregister(data->cdev);
- + cpufreq_cooling_unregister(data->cdev[0]);
- + devfreq_cooling_unregister(data->cdev[1]);
-
- return 0;
- }
- diff -Nur linux-3.14.35.orig/drivers/thermal/Kconfig linux-3.14.35/drivers/thermal/Kconfig
- --- linux-3.14.35.orig/drivers/thermal/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/thermal/Kconfig 2015-03-08 14:27:37.765684500 -0500
- @@ -125,6 +125,13 @@
- cpufreq is used as the cooling device to throttle CPUs when the
- passive trip is crossed.
-
- +config DEVICE_THERMAL
- + tristate "generic device cooling support"
- + help
- + Support for device cooling.
- + It supports notification of crossing passive trip for devices,
- + devices need to do their own actions to cool down the SOC.
- +
- config SPEAR_THERMAL
- bool "SPEAr thermal sensor driver"
- depends on PLAT_SPEAR
- diff -Nur linux-3.14.35.orig/drivers/thermal/Makefile linux-3.14.35/drivers/thermal/Makefile
- --- linux-3.14.35.orig/drivers/thermal/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/thermal/Makefile 2015-03-08 14:27:37.769684499 -0500
- @@ -26,6 +26,7 @@
- obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o
- obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o
- obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
- +obj-$(CONFIG_DEVICE_THERMAL) += device_cooling.o
- obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o
- obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
- obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
- diff -Nur linux-3.14.35.orig/drivers/tty/serial/earlycon.c linux-3.14.35/drivers/tty/serial/earlycon.c
- --- linux-3.14.35.orig/drivers/tty/serial/earlycon.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/tty/serial/earlycon.c 2015-03-08 14:27:37.769684499 -0500
- @@ -0,0 +1,152 @@
- +/*
- + * Copyright (C) 2014 Linaro Ltd.
- + * Author: Rob Herring <robh@kernel.org>
- + *
- + * Based on 8250 earlycon:
- + * (c) Copyright 2004 Hewlett-Packard Development Company, L.P.
- + * Bjorn Helgaas <bjorn.helgaas@hp.com>
- + *
- + * This program is free software: you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#include <linux/console.h>
- +#include <linux/kernel.h>
- +#include <linux/init.h>
- +#include <linux/io.h>
- +#include <linux/serial_core.h>
- +
- +#ifdef CONFIG_FIX_EARLYCON_MEM
- +#include <asm/fixmap.h>
- +#endif
- +
- +#include <asm/serial.h>
- +
- +static struct console early_con = {
- + .name = "earlycon",
- + .flags = CON_PRINTBUFFER | CON_BOOT,
- + .index = -1,
- +};
- +
- +static struct earlycon_device early_console_dev = {
- + .con = &early_con,
- +};
- +
- +static void __iomem * __init earlycon_map(unsigned long paddr, size_t size)
- +{
- + void __iomem *base;
- +#ifdef CONFIG_FIX_EARLYCON_MEM
- + set_fixmap_io(FIX_EARLYCON_MEM_BASE, paddr & PAGE_MASK);
- + base = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
- + base += paddr & ~PAGE_MASK;
- +#else
- + base = ioremap(paddr, size);
- +#endif
- + if (!base)
- + pr_err("%s: Couldn't map 0x%llx\n", __func__,
- + (unsigned long long)paddr);
- +
- + return base;
- +}
- +
- +static int __init parse_options(struct earlycon_device *device,
- + char *options)
- +{
- + struct uart_port *port = &device->port;
- + int mmio, mmio32, length, ret;
- + unsigned long addr;
- +
- + if (!options)
- + return -ENODEV;
- +
- + mmio = !strncmp(options, "mmio,", 5);
- + mmio32 = !strncmp(options, "mmio32,", 7);
- + if (mmio || mmio32) {
- + port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32);
- + options += mmio ? 5 : 7;
- + ret = kstrtoul(options, 0, &addr);
- + if (ret)
- + return ret;
- + port->mapbase = addr;
- + if (mmio32)
- + port->regshift = 2;
- + } else if (!strncmp(options, "io,", 3)) {
- + port->iotype = UPIO_PORT;
- + options += 3;
- + ret = kstrtoul(options, 0, &addr);
- + if (ret)
- + return ret;
- + port->iobase = addr;
- + mmio = 0;
- + } else if (!strncmp(options, "0x", 2)) {
- + port->iotype = UPIO_MEM;
- + ret = kstrtoul(options, 0, &addr);
- + if (ret)
- + return ret;
- + port->mapbase = addr;
- + } else {
- + return -EINVAL;
- + }
- +
- + port->uartclk = BASE_BAUD * 16;
- +
- + options = strchr(options, ',');
- + if (options) {
- + options++;
- + ret = kstrtouint(options, 0, &device->baud);
- + if (ret)
- + return ret;
- + length = min(strcspn(options, " ") + 1,
- + (size_t)(sizeof(device->options)));
- + strlcpy(device->options, options, length);
- + }
- +
- + if (mmio || mmio32)
- + pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n",
- + mmio32 ? "32" : "",
- + (unsigned long long)port->mapbase,
- + device->options);
- + else
- + pr_info("Early serial console at I/O port 0x%lx (options '%s')\n",
- + port->iobase,
- + device->options);
- +
- + return 0;
- +}
- +
- +int __init setup_earlycon(char *buf, const char *match,
- + int (*setup)(struct earlycon_device *, const char *))
- +{
- + int err;
- + size_t len;
- + struct uart_port *port = &early_console_dev.port;
- +
- + if (!buf || !match || !setup)
- + return 0;
- +
- + len = strlen(match);
- + if (strncmp(buf, match, len))
- + return 0;
- + if (buf[len] && (buf[len] != ','))
- + return 0;
- +
- + buf += len + 1;
- +
- + err = parse_options(&early_console_dev, buf);
- + /* On parsing error, pass the options buf to the setup function */
- + if (!err)
- + buf = NULL;
- +
- + if (port->mapbase)
- + port->membase = earlycon_map(port->mapbase, 64);
- +
- + early_console_dev.con->data = &early_console_dev;
- + err = setup(&early_console_dev, buf);
- + if (err < 0)
- + return err;
- + if (!early_console_dev.con->write)
- + return -ENODEV;
- +
- + register_console(early_console_dev.con);
- + return 0;
- +}
- diff -Nur linux-3.14.35.orig/drivers/tty/serial/Kconfig linux-3.14.35/drivers/tty/serial/Kconfig
- --- linux-3.14.35.orig/drivers/tty/serial/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/tty/serial/Kconfig 2015-03-08 14:27:37.769684499 -0500
- @@ -7,6 +7,13 @@
- menu "Serial drivers"
- depends on HAS_IOMEM
-
- +config SERIAL_EARLYCON
- + bool
- + help
- + Support for early consoles with the earlycon parameter. This enables
- + the console before standard serial driver is probed. The console is
- + enabled when early_param is processed.
- +
- source "drivers/tty/serial/8250/Kconfig"
-
- comment "Non-8250 serial port support"
- diff -Nur linux-3.14.35.orig/drivers/tty/serial/Makefile linux-3.14.35/drivers/tty/serial/Makefile
- --- linux-3.14.35.orig/drivers/tty/serial/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/tty/serial/Makefile 2015-03-08 14:27:37.769684499 -0500
- @@ -5,6 +5,8 @@
- obj-$(CONFIG_SERIAL_CORE) += serial_core.o
- obj-$(CONFIG_SERIAL_21285) += 21285.o
-
- +obj-$(CONFIG_SERIAL_EARLYCON) += earlycon.o
- +
- # These Sparc drivers have to appear before others such as 8250
- # which share ttySx minor node space. Otherwise console device
- # names change and other unplesantries.
- diff -Nur linux-3.14.35.orig/drivers/usb/chipidea/ci.h linux-3.14.35/drivers/usb/chipidea/ci.h
- --- linux-3.14.35.orig/drivers/usb/chipidea/ci.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/chipidea/ci.h 2015-03-08 14:27:37.769684499 -0500
- @@ -139,8 +139,8 @@
- * @roles: array of supported roles for this controller
- * @role: current role
- * @is_otg: if the device is otg-capable
- - * @work: work for role changing
- - * @wq: workqueue thread
- + * @otg_task: the thread for handling otg task
- + * @otg_wait: the otg event waitqueue head
- * @qh_pool: allocation pool for queue heads
- * @td_pool: allocation pool for transfer descriptors
- * @gadget: device side representation for peripheral controller
- @@ -165,6 +165,10 @@
- * @b_sess_valid_event: indicates there is a vbus event, and handled
- * at ci_otg_work
- * @imx28_write_fix: Freescale imx28 needs swp instruction for writing
- + * @supports_runtime_pm: if runtime pm is supported
- + * @in_lpm: if the core in low power mode
- + * @wakeup_int: if wakeup interrupt occur
- + * @timer: timer to delay clock closing
- */
- struct ci_hdrc {
- struct device *dev;
- @@ -174,8 +178,8 @@
- struct ci_role_driver *roles[CI_ROLE_END];
- enum ci_role role;
- bool is_otg;
- - struct work_struct work;
- - struct workqueue_struct *wq;
- + struct task_struct *otg_task;
- + wait_queue_head_t otg_wait;
-
- struct dma_pool *qh_pool;
- struct dma_pool *td_pool;
- @@ -204,6 +208,10 @@
- bool id_event;
- bool b_sess_valid_event;
- bool imx28_write_fix;
- + bool supports_runtime_pm;
- + bool in_lpm;
- + bool wakeup_int;
- + struct timer_list timer;
- };
-
- static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci)
- diff -Nur linux-3.14.35.orig/drivers/usb/chipidea/ci_hdrc_imx.c linux-3.14.35/drivers/usb/chipidea/ci_hdrc_imx.c
- --- linux-3.14.35.orig/drivers/usb/chipidea/ci_hdrc_imx.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/chipidea/ci_hdrc_imx.c 2015-03-08 14:27:37.769684499 -0500
- @@ -19,11 +19,14 @@
- #include <linux/dma-mapping.h>
- #include <linux/usb/chipidea.h>
- #include <linux/clk.h>
- +#include <linux/busfreq-imx6.h>
-
- #include "ci.h"
- #include "ci_hdrc_imx.h"
-
- -#define CI_HDRC_IMX_IMX28_WRITE_FIX BIT(0)
- +#define CI_HDRC_IMX_IMX28_WRITE_FIX BIT(0)
- +#define CI_HDRC_IMX_SUPPORT_RUNTIME_PM BIT(1)
- +#define CI_HDRC_IMX_HOST_QUIRK BIT(2)
-
- struct ci_hdrc_imx_platform_flag {
- unsigned int flags;
- @@ -32,12 +35,30 @@
- static const struct ci_hdrc_imx_platform_flag imx27_usb_data = {
- };
-
- +static const struct ci_hdrc_imx_platform_flag imx23_usb_data = {
- + .flags = CI_HDRC_IMX_HOST_QUIRK,
- +};
- +
- static const struct ci_hdrc_imx_platform_flag imx28_usb_data = {
- - .flags = CI_HDRC_IMX_IMX28_WRITE_FIX,
- + .flags = CI_HDRC_IMX_IMX28_WRITE_FIX |
- + CI_HDRC_IMX_HOST_QUIRK,
- +};
- +
- +static const struct ci_hdrc_imx_platform_flag imx6q_usb_data = {
- + .flags = CI_HDRC_IMX_SUPPORT_RUNTIME_PM |
- + CI_HDRC_IMX_HOST_QUIRK,
- +};
- +
- +static const struct ci_hdrc_imx_platform_flag imx6sl_usb_data = {
- + .flags = CI_HDRC_IMX_SUPPORT_RUNTIME_PM |
- + CI_HDRC_IMX_HOST_QUIRK,
- };
-
- static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
- + { .compatible = "fsl,imx6sl-usb", .data = &imx6sl_usb_data},
- + { .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data},
- { .compatible = "fsl,imx28-usb", .data = &imx28_usb_data},
- + { .compatible = "fsl,imx23-usb", .data = &imx23_usb_data},
- { .compatible = "fsl,imx27-usb", .data = &imx27_usb_data},
- { /* sentinel */ }
- };
- @@ -48,6 +69,8 @@
- struct platform_device *ci_pdev;
- struct clk *clk;
- struct imx_usbmisc_data *usbmisc_data;
- + bool supports_runtime_pm;
- + bool in_lpm;
- };
-
- /* Common functions shared by usbmisc drivers */
- @@ -123,8 +146,10 @@
- return PTR_ERR(data->clk);
- }
-
- + request_bus_freq(BUS_FREQ_HIGH);
- ret = clk_prepare_enable(data->clk);
- if (ret) {
- + release_bus_freq(BUS_FREQ_HIGH);
- dev_err(&pdev->dev,
- "Failed to prepare or enable clock, err=%d\n", ret);
- return ret;
- @@ -145,6 +170,14 @@
- if (ret)
- goto err_clk;
-
- + if (imx_platform_flag->flags & CI_HDRC_IMX_SUPPORT_RUNTIME_PM) {
- + pdata.flags |= CI_HDRC_SUPPORTS_RUNTIME_PM;
- + data->supports_runtime_pm = true;
- + }
- +
- + if (imx_platform_flag->flags & CI_HDRC_IMX_HOST_QUIRK)
- + pdata.flags |= CI_HDRC_IMX_EHCI_QUIRK;
- +
- if (data->usbmisc_data) {
- ret = imx_usbmisc_init(data->usbmisc_data);
- if (ret) {
- @@ -165,6 +198,11 @@
- goto err_clk;
- }
-
- + /* usbmisc needs to know dr mode to choose wakeup setting */
- + if (data->usbmisc_data)
- + data->usbmisc_data->available_role =
- + ci_hdrc_query_available_role(data->ci_pdev);
- +
- if (data->usbmisc_data) {
- ret = imx_usbmisc_init_post(data->usbmisc_data);
- if (ret) {
- @@ -174,10 +212,23 @@
- }
- }
-
- + if (data->usbmisc_data) {
- + ret = imx_usbmisc_set_wakeup(data->usbmisc_data, false);
- + if (ret) {
- + dev_err(&pdev->dev, "usbmisc set_wakeup failed, ret=%d\n",
- + ret);
- + goto disable_device;
- + }
- + }
- +
- platform_set_drvdata(pdev, data);
-
- - pm_runtime_no_callbacks(&pdev->dev);
- - pm_runtime_enable(&pdev->dev);
- + device_set_wakeup_capable(&pdev->dev, true);
- +
- + if (data->supports_runtime_pm) {
- + pm_runtime_set_active(&pdev->dev);
- + pm_runtime_enable(&pdev->dev);
- + }
-
- return 0;
-
- @@ -185,6 +236,7 @@
- ci_hdrc_remove_device(data->ci_pdev);
- err_clk:
- clk_disable_unprepare(data->clk);
- + release_bus_freq(BUS_FREQ_HIGH);
- return ret;
- }
-
- @@ -195,10 +247,119 @@
- pm_runtime_disable(&pdev->dev);
- ci_hdrc_remove_device(data->ci_pdev);
- clk_disable_unprepare(data->clk);
- + release_bus_freq(BUS_FREQ_HIGH);
-
- return 0;
- }
-
- +#ifdef CONFIG_PM
- +static int imx_controller_suspend(struct device *dev)
- +{
- + struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
- + int ret;
- +
- + dev_dbg(dev, "at %s\n", __func__);
- +
- + if (data->in_lpm)
- + return 0;
- +
- + if (data->usbmisc_data) {
- + ret = imx_usbmisc_set_wakeup(data->usbmisc_data, true);
- + if (ret) {
- + dev_err(dev,
- + "usbmisc set_wakeup failed, ret=%d\n",
- + ret);
- + return ret;
- + }
- + }
- +
- + clk_disable_unprepare(data->clk);
- + release_bus_freq(BUS_FREQ_HIGH);
- + data->in_lpm = true;
- +
- + return 0;
- +}
- +
- +static int imx_controller_resume(struct device *dev)
- +{
- + struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
- + int ret = 0;
- +
- + dev_dbg(dev, "at %s\n", __func__);
- +
- + if (!data->in_lpm)
- + return 0;
- +
- + request_bus_freq(BUS_FREQ_HIGH);
- + ret = clk_prepare_enable(data->clk);
- + if (ret) {
- + release_bus_freq(BUS_FREQ_HIGH);
- + return ret;
- + }
- +
- + data->in_lpm = false;
- +
- + if (data->usbmisc_data) {
- + ret = imx_usbmisc_set_wakeup(data->usbmisc_data, false);
- + if (ret) {
- + dev_err(dev,
- + "usbmisc set_wakeup failed, ret=%d\n",
- + ret);
- + ret = -EINVAL;
- + goto clk_disable;
- + }
- + }
- +
- + return 0;
- +
- +clk_disable:
- + clk_disable_unprepare(data->clk);
- + release_bus_freq(BUS_FREQ_HIGH);
- +
- + return ret;
- +}
- +
- +#ifdef CONFIG_PM_SLEEP
- +static int ci_hdrc_imx_suspend(struct device *dev)
- +{
- + return imx_controller_suspend(dev);
- +}
- +
- +static int ci_hdrc_imx_resume(struct device *dev)
- +{
- + struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
- + int ret;
- +
- + ret = imx_controller_resume(dev);
- + if (!ret && data->supports_runtime_pm) {
- + pm_runtime_disable(dev);
- + pm_runtime_set_active(dev);
- + pm_runtime_enable(dev);
- + }
- +
- + return ret;
- +}
- +#endif /* CONFIG_PM_SLEEP */
- +
- +#ifdef CONFIG_PM_RUNTIME
- +static int ci_hdrc_imx_runtime_suspend(struct device *dev)
- +{
- + return imx_controller_suspend(dev);
- +}
- +
- +static int ci_hdrc_imx_runtime_resume(struct device *dev)
- +{
- + return imx_controller_resume(dev);
- +}
- +#endif /* CONFIG_PM_RUNTIME */
- +
- +#endif /* CONFIG_PM */
- +static const struct dev_pm_ops ci_hdrc_imx_pm_ops = {
- + SET_SYSTEM_SLEEP_PM_OPS(ci_hdrc_imx_suspend, ci_hdrc_imx_resume)
- + SET_RUNTIME_PM_OPS(ci_hdrc_imx_runtime_suspend,
- + ci_hdrc_imx_runtime_resume, NULL)
- +};
- +
- static struct platform_driver ci_hdrc_imx_driver = {
- .probe = ci_hdrc_imx_probe,
- .remove = ci_hdrc_imx_remove,
- @@ -206,6 +367,7 @@
- .name = "imx_usb",
- .owner = THIS_MODULE,
- .of_match_table = ci_hdrc_imx_dt_ids,
- + .pm = &ci_hdrc_imx_pm_ops,
- },
- };
-
- diff -Nur linux-3.14.35.orig/drivers/usb/chipidea/ci_hdrc_imx.h linux-3.14.35/drivers/usb/chipidea/ci_hdrc_imx.h
- --- linux-3.14.35.orig/drivers/usb/chipidea/ci_hdrc_imx.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/chipidea/ci_hdrc_imx.h 2015-03-08 14:27:37.773684499 -0500
- @@ -1,5 +1,5 @@
- /*
- - * Copyright 2012 Freescale Semiconductor, Inc.
- + * Copyright 2012-2013 Freescale Semiconductor, Inc.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- @@ -12,14 +12,18 @@
- #ifndef __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H
- #define __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H
-
- +#include <linux/usb/otg.h>
- +
- struct imx_usbmisc_data {
- int index;
-
- unsigned int disable_oc:1; /* over current detect disabled */
- unsigned int evdo:1; /* set external vbus divider option */
- + enum usb_dr_mode available_role;
- };
-
- int imx_usbmisc_init(struct imx_usbmisc_data *);
- int imx_usbmisc_init_post(struct imx_usbmisc_data *);
- +int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *, bool);
-
- #endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */
- diff -Nur linux-3.14.35.orig/drivers/usb/chipidea/ci_hdrc_msm.c linux-3.14.35/drivers/usb/chipidea/ci_hdrc_msm.c
- --- linux-3.14.35.orig/drivers/usb/chipidea/ci_hdrc_msm.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/chipidea/ci_hdrc_msm.c 2015-03-08 14:27:37.773684499 -0500
- @@ -17,7 +17,7 @@
-
- #define MSM_USB_BASE (ci->hw_bank.abs)
-
- -static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
- +static int ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
- {
- struct device *dev = ci->gadget.dev.parent;
-
- @@ -40,6 +40,8 @@
- dev_dbg(dev, "unknown ci_hdrc event\n");
- break;
- }
- +
- + return 0;
- }
-
- static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
- diff -Nur linux-3.14.35.orig/drivers/usb/chipidea/core.c linux-3.14.35/drivers/usb/chipidea/core.c
- --- linux-3.14.35.orig/drivers/usb/chipidea/core.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/chipidea/core.c 2015-03-08 14:27:37.773684499 -0500
- @@ -165,25 +165,30 @@
- return hw_read(ci, OP_PORTSC, PORTSC_PTC) >> __ffs(PORTSC_PTC);
- }
-
- +static void hw_wait_phy_stable(void)
- +{
- + /* The controller needs at least 1ms to reflect PHY's status */
- + usleep_range(2000, 2500);
- +}
- +
- +static void delay_runtime_pm_put_timer(unsigned long arg)
- +{
- + struct ci_hdrc *ci = (struct ci_hdrc *)arg;
- +
- + pm_runtime_put(ci->dev);
- +}
- +
- /* The PHY enters/leaves low power mode */
- static void ci_hdrc_enter_lpm(struct ci_hdrc *ci, bool enable)
- {
- enum ci_hw_regs reg = ci->hw_bank.lpm ? OP_DEVLC : OP_PORTSC;
- bool lpm = !!(hw_read(ci, reg, PORTSC_PHCD(ci->hw_bank.lpm)));
-
- - if (enable && !lpm) {
- + if (enable && !lpm)
- hw_write(ci, reg, PORTSC_PHCD(ci->hw_bank.lpm),
- PORTSC_PHCD(ci->hw_bank.lpm));
- - } else if (!enable && lpm) {
- - hw_write(ci, reg, PORTSC_PHCD(ci->hw_bank.lpm),
- - 0);
- - /*
- - * The controller needs at least 1ms to reflect
- - * PHY's status, the PHY also needs some time (less
- - * than 1ms) to leave low power mode.
- - */
- - usleep_range(1500, 2000);
- - }
- + else if (!enable && lpm)
- + hw_write(ci, reg, PORTSC_PHCD(ci->hw_bank.lpm), 0);
- }
-
- static int hw_device_init(struct ci_hdrc *ci, void __iomem *base)
- @@ -351,6 +356,13 @@
- irqreturn_t ret = IRQ_NONE;
- u32 otgsc = 0;
-
- + if (ci->in_lpm) {
- + disable_irq_nosync(irq);
- + ci->wakeup_int = true;
- + pm_runtime_get(ci->dev);
- + return IRQ_HANDLED;
- + }
- +
- if (ci->is_otg)
- otgsc = hw_read(ci, OP_OTGSC, ~0);
-
- @@ -362,7 +374,7 @@
- ci->id_event = true;
- ci_clear_otg_interrupt(ci, OTGSC_IDIS);
- disable_irq_nosync(ci->irq);
- - queue_work(ci->wq, &ci->work);
- + wake_up(&ci->otg_wait);
- return IRQ_HANDLED;
- }
-
- @@ -374,7 +386,7 @@
- ci->b_sess_valid_event = true;
- ci_clear_otg_interrupt(ci, OTGSC_BSVIS);
- disable_irq_nosync(ci->irq);
- - queue_work(ci->wq, &ci->work);
- + wake_up(&ci->otg_wait);
- return IRQ_HANDLED;
- }
-
- @@ -473,6 +485,33 @@
- }
- EXPORT_SYMBOL_GPL(ci_hdrc_remove_device);
-
- +/**
- + * ci_hdrc_query_available_role: get runtime available operation mode
- + *
- + * The glue layer can get current operation mode (host/peripheral/otg)
- + * This function should be called after ci core device has created.
- + *
- + * @pdev: the platform device of ci core.
- + *
- + * Return USB_DR_MODE_XXX.
- + */
- +enum usb_dr_mode ci_hdrc_query_available_role(struct platform_device *pdev)
- +{
- + struct ci_hdrc *ci = platform_get_drvdata(pdev);
- +
- + if (!ci)
- + return USB_DR_MODE_UNKNOWN;
- + if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET])
- + return USB_DR_MODE_OTG;
- + else if (ci->roles[CI_ROLE_HOST])
- + return USB_DR_MODE_HOST;
- + else if (ci->roles[CI_ROLE_GADGET])
- + return USB_DR_MODE_PERIPHERAL;
- + else
- + return USB_DR_MODE_UNKNOWN;
- +}
- +EXPORT_SYMBOL_GPL(ci_hdrc_query_available_role);
- +
- static inline void ci_role_destroy(struct ci_hdrc *ci)
- {
- ci_hdrc_gadget_destroy(ci);
- @@ -498,9 +537,14 @@
-
- static int ci_usb_phy_init(struct ci_hdrc *ci)
- {
- + int ret;
- +
- if (ci->platdata->phy) {
- ci->transceiver = ci->platdata->phy;
- - return usb_phy_init(ci->transceiver);
- + ret = usb_phy_init(ci->transceiver);
- + if (!ret)
- + hw_wait_phy_stable();
- + return ret;
- } else {
- ci->global_phy = true;
- ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
- @@ -559,8 +603,6 @@
- return -ENODEV;
- }
-
- - hw_phymode_configure(ci);
- -
- ret = ci_usb_phy_init(ci);
- if (ret) {
- dev_err(dev, "unable to init phy: %d\n", ret);
- @@ -578,7 +620,13 @@
-
- ci_get_otg_capable(ci);
-
- + hw_phymode_configure(ci);
- +
- dr_mode = ci->platdata->dr_mode;
- +
- + ci->supports_runtime_pm = !!(ci->platdata->flags &
- + CI_HDRC_SUPPORTS_RUNTIME_PM);
- +
- /* initialize role(s) before the interrupt is requested */
- if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) {
- ret = ci_hdrc_host_init(ci);
- @@ -619,11 +667,6 @@
-
- if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) {
- if (ci->is_otg) {
- - /*
- - * ID pin needs 1ms debouce time,
- - * we delay 2ms for safe.
- - */
- - mdelay(2);
- ci->role = ci_otg_role(ci);
- ci_enable_otg_interrupt(ci, OTGSC_IDIE);
- } else {
- @@ -656,6 +699,15 @@
- if (ret)
- goto stop;
-
- + device_set_wakeup_capable(&pdev->dev, true);
- +
- + if (ci->supports_runtime_pm) {
- + pm_runtime_set_active(&pdev->dev);
- + pm_runtime_enable(&pdev->dev);
- + }
- +
- + setup_timer(&ci->timer, delay_runtime_pm_put_timer,
- + (unsigned long)ci);
- ret = dbg_create_files(ci);
- if (!ret)
- return 0;
- @@ -673,6 +725,11 @@
- {
- struct ci_hdrc *ci = platform_get_drvdata(pdev);
-
- + if (ci->supports_runtime_pm) {
- + pm_runtime_get_sync(&pdev->dev);
- + pm_runtime_disable(&pdev->dev);
- + pm_runtime_put_noidle(&pdev->dev);
- + }
- dbg_remove_files(ci);
- free_irq(ci->irq, ci);
- ci_role_destroy(ci);
- @@ -682,11 +739,120 @@
- return 0;
- }
-
- +#ifdef CONFIG_PM
- +static int ci_controller_suspend(struct device *dev)
- +{
- + struct ci_hdrc *ci = dev_get_drvdata(dev);
- +
- + dev_dbg(dev, "at %s\n", __func__);
- +
- + if (ci->in_lpm)
- + return 0;
- +
- + disable_irq(ci->irq);
- +
- + if (ci->transceiver)
- + usb_phy_set_wakeup(ci->transceiver, true);
- +
- + ci_hdrc_enter_lpm(ci, true);
- +
- + if (ci->transceiver)
- + usb_phy_set_suspend(ci->transceiver, 1);
- +
- + ci->in_lpm = true;
- +
- + enable_irq(ci->irq);
- +
- + return 0;
- +}
- +
- +static int ci_controller_resume(struct device *dev)
- +{
- + struct ci_hdrc *ci = dev_get_drvdata(dev);
- +
- + dev_dbg(dev, "at %s\n", __func__);
- +
- + if (!ci->in_lpm)
- + return 0;
- +
- + ci_hdrc_enter_lpm(ci, false);
- +
- + if (ci->transceiver) {
- + usb_phy_set_suspend(ci->transceiver, 0);
- + usb_phy_set_wakeup(ci->transceiver, false);
- + hw_wait_phy_stable();
- + }
- +
- + ci->in_lpm = false;
- +
- + if (ci->wakeup_int) {
- + ci->wakeup_int = false;
- + enable_irq(ci->irq);
- + mod_timer(&ci->timer, jiffies + msecs_to_jiffies(2000));
- + }
- +
- + return 0;
- +}
- +
- +#ifdef CONFIG_PM_SLEEP
- +static int ci_suspend(struct device *dev)
- +{
- + struct ci_hdrc *ci = dev_get_drvdata(dev);
- + int ret;
- +
- + ret = ci_controller_suspend(dev);
- + if (ret)
- + return ret;
- +
- + if (device_may_wakeup(dev))
- + enable_irq_wake(ci->irq);
- +
- + return ret;
- +}
- +
- +static int ci_resume(struct device *dev)
- +{
- + struct ci_hdrc *ci = dev_get_drvdata(dev);
- + int ret;
- +
- + if (device_may_wakeup(dev))
- + disable_irq_wake(ci->irq);
- +
- + ret = ci_controller_resume(dev);
- + if (!ret && ci->supports_runtime_pm) {
- + pm_runtime_disable(dev);
- + pm_runtime_set_active(dev);
- + pm_runtime_enable(dev);
- + }
- +
- + return ret;
- +}
- +#endif /* CONFIG_PM_SLEEP */
- +
- +#ifdef CONFIG_PM_RUNTIME
- +static int ci_runtime_suspend(struct device *dev)
- +{
- + return ci_controller_suspend(dev);
- +}
- +
- +static int ci_runtime_resume(struct device *dev)
- +{
- + return ci_controller_resume(dev);
- +}
- +#endif /* CONFIG_PM_RUNTIME */
- +
- +#endif /* CONFIG_PM */
- +static const struct dev_pm_ops ci_pm_ops = {
- + SET_SYSTEM_SLEEP_PM_OPS(ci_suspend, ci_resume)
- + SET_RUNTIME_PM_OPS(ci_runtime_suspend, ci_runtime_resume, NULL)
- +};
- +
- static struct platform_driver ci_hdrc_driver = {
- .probe = ci_hdrc_probe,
- .remove = ci_hdrc_remove,
- .driver = {
- .name = "ci_hdrc",
- + .pm = &ci_pm_ops,
- },
- };
-
- diff -Nur linux-3.14.35.orig/drivers/usb/chipidea/host.c linux-3.14.35/drivers/usb/chipidea/host.c
- --- linux-3.14.35.orig/drivers/usb/chipidea/host.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/chipidea/host.c 2015-03-08 14:27:37.773684499 -0500
- @@ -33,6 +33,176 @@
- #include "host.h"
-
- static struct hc_driver __read_mostly ci_ehci_hc_driver;
- +static int (*orig_bus_suspend)(struct usb_hcd *hcd);
- +static int (*orig_bus_resume)(struct usb_hcd *hcd);
- +static int (*orig_hub_control)(struct usb_hcd *hcd,
- + u16 typeReq, u16 wValue, u16 wIndex,
- + char *buf, u16 wLength);
- +
- +static int ci_ehci_bus_suspend(struct usb_hcd *hcd)
- +{
- + struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- + int port;
- + u32 tmp;
- +
- + int ret = orig_bus_suspend(hcd);
- +
- + if (ret)
- + return ret;
- +
- + port = HCS_N_PORTS(ehci->hcs_params);
- + while (port--) {
- + u32 __iomem *reg = &ehci->regs->port_status[port];
- + u32 portsc = ehci_readl(ehci, reg);
- +
- + if (portsc & PORT_CONNECT) {
- + /*
- + * For chipidea, the resume signal will be ended
- + * automatically, so for remote wakeup case, the
- + * usbcmd.rs may not be set before the resume has
- + * ended if other resume path consumes too much
- + * time (~23ms-24ms), in that case, the SOF will not
- + * send out within 3ms after resume ends, then the
- + * device will enter suspend again.
- + */
- + if (hcd->self.root_hub->do_remote_wakeup) {
- + ehci_dbg(ehci,
- + "Remote wakeup is enabled, "
- + "and device is on the port\n");
- +
- + tmp = ehci_readl(ehci, &ehci->regs->command);
- + tmp |= CMD_RUN;
- + ehci_writel(ehci, tmp, &ehci->regs->command);
- + /*
- + * It needs a short delay between set RUNSTOP
- + * and set PHCD.
- + */
- + udelay(125);
- + }
- + if (hcd->phy && test_bit(port, &ehci->bus_suspended)
- + && (ehci_port_speed(ehci, portsc) ==
- + USB_PORT_STAT_HIGH_SPEED))
- + /*
- + * notify the USB PHY, it is for global
- + * suspend case.
- + */
- + usb_phy_notify_suspend(hcd->phy,
- + USB_SPEED_HIGH);
- + }
- + }
- +
- + return 0;
- +}
- +
- +static int ci_imx_ehci_bus_resume(struct usb_hcd *hcd)
- +{
- + struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- + int port;
- +
- + int ret = orig_bus_resume(hcd);
- +
- + if (ret)
- + return ret;
- +
- + port = HCS_N_PORTS(ehci->hcs_params);
- + while (port--) {
- + u32 __iomem *reg = &ehci->regs->port_status[port];
- + u32 portsc = ehci_readl(ehci, reg);
- + /*
- + * Notify PHY after resume signal has finished, it is
- + * for global suspend case.
- + */
- + if (hcd->phy
- + && test_bit(port, &ehci->bus_suspended)
- + && (portsc & PORT_CONNECT)
- + && (ehci_port_speed(ehci, portsc) ==
- + USB_PORT_STAT_HIGH_SPEED))
- + /* notify the USB PHY */
- + usb_phy_notify_resume(hcd->phy, USB_SPEED_HIGH);
- + }
- +
- + return 0;
- +}
- +
- +/* The below code is based on tegra ehci driver */
- +static int ci_imx_ehci_hub_control(
- + struct usb_hcd *hcd,
- + u16 typeReq,
- + u16 wValue,
- + u16 wIndex,
- + char *buf,
- + u16 wLength
- +)
- +{
- + struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- + u32 __iomem *status_reg;
- + u32 temp;
- + unsigned long flags;
- + int retval = 0;
- +
- + status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1];
- +
- + spin_lock_irqsave(&ehci->lock, flags);
- +
- + if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) {
- + temp = ehci_readl(ehci, status_reg);
- + if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) {
- + retval = -EPIPE;
- + goto done;
- + }
- +
- + temp &= ~(PORT_RWC_BITS | PORT_WKCONN_E);
- + temp |= PORT_WKDISC_E | PORT_WKOC_E;
- + ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
- +
- + /*
- + * If a transaction is in progress, there may be a delay in
- + * suspending the port. Poll until the port is suspended.
- + */
- + if (ehci_handshake(ehci, status_reg, PORT_SUSPEND,
- + PORT_SUSPEND, 5000))
- + ehci_err(ehci, "timeout waiting for SUSPEND\n");
- +
- + spin_unlock_irqrestore(&ehci->lock, flags);
- + if (ehci_port_speed(ehci, temp) ==
- + USB_PORT_STAT_HIGH_SPEED && hcd->phy) {
- + /* notify the USB PHY */
- + usb_phy_notify_suspend(hcd->phy, USB_SPEED_HIGH);
- + }
- + spin_lock_irqsave(&ehci->lock, flags);
- +
- + set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports);
- + goto done;
- + }
- +
- + /*
- + * After resume has finished, it needs do some post resume
- + * operation for some SoCs.
- + */
- + else if (typeReq == ClearPortFeature &&
- + wValue == USB_PORT_FEAT_C_SUSPEND) {
- +
- + /* Make sure the resume has finished, it should be finished */
- + if (ehci_handshake(ehci, status_reg, PORT_RESUME, 0, 25000))
- + ehci_err(ehci, "timeout waiting for resume\n");
- +
- + temp = ehci_readl(ehci, status_reg);
- +
- + if (ehci_port_speed(ehci, temp) ==
- + USB_PORT_STAT_HIGH_SPEED && hcd->phy) {
- + /* notify the USB PHY */
- + usb_phy_notify_resume(hcd->phy, USB_SPEED_HIGH);
- + }
- + }
- +
- + spin_unlock_irqrestore(&ehci->lock, flags);
- +
- + /* Handle the hub control events here */
- + return orig_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
- +done:
- + spin_unlock_irqrestore(&ehci->lock, flags);
- + return retval;
- +}
-
- static irqreturn_t host_irq(struct ci_hdrc *ci)
- {
- @@ -64,7 +234,6 @@
- ehci = hcd_to_ehci(hcd);
- ehci->caps = ci->hw_bank.cap;
- ehci->has_hostpc = ci->hw_bank.lpm;
- - ehci->has_tdi_phy_lpm = ci->hw_bank.lpm;
- ehci->imx28_write_fix = ci->imx28_write_fix;
-
- if (ci->platdata->reg_vbus) {
- @@ -136,5 +305,15 @@
-
- ehci_init_driver(&ci_ehci_hc_driver, NULL);
-
- + orig_bus_suspend = ci_ehci_hc_driver.bus_suspend;
- + orig_bus_resume = ci_ehci_hc_driver.bus_resume;
- + orig_hub_control = ci_ehci_hc_driver.hub_control;
- +
- + ci_ehci_hc_driver.bus_suspend = ci_ehci_bus_suspend;
- + if (ci->platdata->flags & CI_HDRC_IMX_EHCI_QUIRK) {
- + ci_ehci_hc_driver.bus_resume = ci_imx_ehci_bus_resume;
- + ci_ehci_hc_driver.hub_control = ci_imx_ehci_hub_control;
- + }
- +
- return 0;
- }
- diff -Nur linux-3.14.35.orig/drivers/usb/chipidea/otg.c linux-3.14.35/drivers/usb/chipidea/otg.c
- --- linux-3.14.35.orig/drivers/usb/chipidea/otg.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/chipidea/otg.c 2015-03-08 14:27:37.773684499 -0500
- @@ -18,6 +18,8 @@
- #include <linux/usb/otg.h>
- #include <linux/usb/gadget.h>
- #include <linux/usb/chipidea.h>
- +#include <linux/kthread.h>
- +#include <linux/freezer.h>
-
- #include "ci.h"
- #include "bits.h"
- @@ -68,26 +70,53 @@
- ci_role_start(ci, role);
- }
- }
- +
- +/* If there is pending otg event */
- +static inline bool ci_otg_event_is_pending(struct ci_hdrc *ci)
- +{
- + return ci->id_event || ci->b_sess_valid_event;
- +}
- +
- /**
- - * ci_otg_work - perform otg (vbus/id) event handle
- - * @work: work struct
- + * ci_otg_event - perform otg (vbus/id) event handle
- + * @ci: ci_hdrc struct
- */
- -static void ci_otg_work(struct work_struct *work)
- +static void ci_otg_event(struct ci_hdrc *ci)
- {
- - struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work);
- -
- if (ci->id_event) {
- ci->id_event = false;
- + /* Keep controller active during id switch */
- + pm_runtime_get_sync(ci->dev);
- ci_handle_id_switch(ci);
- + pm_runtime_put_sync(ci->dev);
- } else if (ci->b_sess_valid_event) {
- ci->b_sess_valid_event = false;
- + pm_runtime_get_sync(ci->dev);
- ci_handle_vbus_change(ci);
- + pm_runtime_put_sync(ci->dev);
- } else
- - dev_err(ci->dev, "unexpected event occurs at %s\n", __func__);
- + dev_dbg(ci->dev, "it should be quit event\n");
-
- enable_irq(ci->irq);
- }
-
- +static int ci_otg_thread(void *ptr)
- +{
- + struct ci_hdrc *ci = ptr;
- +
- + set_freezable();
- +
- + do {
- + wait_event_freezable(ci->otg_wait,
- + ci_otg_event_is_pending(ci) ||
- + kthread_should_stop());
- + ci_otg_event(ci);
- + } while (!kthread_should_stop());
- +
- + dev_warn(ci->dev, "ci_otg_thread quits\n");
- +
- + return 0;
- +}
-
- /**
- * ci_hdrc_otg_init - initialize otg struct
- @@ -95,11 +124,11 @@
- */
- int ci_hdrc_otg_init(struct ci_hdrc *ci)
- {
- - INIT_WORK(&ci->work, ci_otg_work);
- - ci->wq = create_singlethread_workqueue("ci_otg");
- - if (!ci->wq) {
- - dev_err(ci->dev, "can't create workqueue\n");
- - return -ENODEV;
- + init_waitqueue_head(&ci->otg_wait);
- + ci->otg_task = kthread_run(ci_otg_thread, ci, "ci otg thread");
- + if (IS_ERR(ci->otg_task)) {
- + dev_err(ci->dev, "error to create otg thread\n");
- + return PTR_ERR(ci->otg_task);
- }
-
- return 0;
- @@ -111,10 +140,7 @@
- */
- void ci_hdrc_otg_destroy(struct ci_hdrc *ci)
- {
- - if (ci->wq) {
- - flush_workqueue(ci->wq);
- - destroy_workqueue(ci->wq);
- - }
- + kthread_stop(ci->otg_task);
- ci_disable_otg_interrupt(ci, OTGSC_INT_EN_BITS);
- ci_clear_otg_interrupt(ci, OTGSC_INT_STATUS_BITS);
- }
- diff -Nur linux-3.14.35.orig/drivers/usb/chipidea/udc.c linux-3.14.35/drivers/usb/chipidea/udc.c
- --- linux-3.14.35.orig/drivers/usb/chipidea/udc.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/chipidea/udc.c 2015-03-08 14:27:37.777684499 -0500
- @@ -681,12 +681,6 @@
- struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget);
- unsigned long flags;
-
- - spin_lock_irqsave(&ci->lock, flags);
- - ci->gadget.speed = USB_SPEED_UNKNOWN;
- - ci->remote_wakeup = 0;
- - ci->suspended = 0;
- - spin_unlock_irqrestore(&ci->lock, flags);
- -
- /* flush all endpoints */
- gadget_for_each_ep(ep, gadget) {
- usb_ep_fifo_flush(ep);
- @@ -704,6 +698,12 @@
- ci->status = NULL;
- }
-
- + spin_lock_irqsave(&ci->lock, flags);
- + ci->gadget.speed = USB_SPEED_UNKNOWN;
- + ci->remote_wakeup = 0;
- + ci->suspended = 0;
- + spin_unlock_irqrestore(&ci->lock, flags);
- +
- return 0;
- }
-
- @@ -1222,6 +1222,10 @@
- return -EBUSY;
-
- spin_lock_irqsave(hwep->lock, flags);
- + if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) {
- + spin_unlock_irqrestore(hwep->lock, flags);
- + return 0;
- + }
-
- /* only internal SW should disable ctrl endpts */
-
- @@ -1311,6 +1315,10 @@
- return -EINVAL;
-
- spin_lock_irqsave(hwep->lock, flags);
- + if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) {
- + spin_unlock_irqrestore(hwep->lock, flags);
- + return 0;
- + }
- retval = _ep_queue(ep, req, gfp_flags);
- spin_unlock_irqrestore(hwep->lock, flags);
- return retval;
- @@ -1334,8 +1342,8 @@
- return -EINVAL;
-
- spin_lock_irqsave(hwep->lock, flags);
- -
- - hw_ep_flush(hwep->ci, hwep->num, hwep->dir);
- + if (hwep->ci->gadget.speed != USB_SPEED_UNKNOWN)
- + hw_ep_flush(hwep->ci, hwep->num, hwep->dir);
-
- list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) {
- dma_pool_free(hwep->td_pool, node->ptr, node->dma);
- @@ -1379,6 +1387,10 @@
-
- spin_lock_irqsave(hwep->lock, flags);
-
- + if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) {
- + spin_unlock_irqrestore(hwep->lock, flags);
- + return 0;
- + }
- #ifndef STALL_IN
- /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
- if (value && hwep->type == USB_ENDPOINT_XFER_BULK && hwep->dir == TX &&
- @@ -1440,6 +1452,10 @@
- }
-
- spin_lock_irqsave(hwep->lock, flags);
- + if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) {
- + spin_unlock_irqrestore(hwep->lock, flags);
- + return;
- + }
-
- hw_ep_flush(hwep->ci, hwep->num, hwep->dir);
-
- @@ -1506,6 +1522,10 @@
- int ret = 0;
-
- spin_lock_irqsave(&ci->lock, flags);
- + if (ci->gadget.speed == USB_SPEED_UNKNOWN) {
- + spin_unlock_irqrestore(&ci->lock, flags);
- + return 0;
- + }
- if (!ci->remote_wakeup) {
- ret = -EOPNOTSUPP;
- goto out;
- diff -Nur linux-3.14.35.orig/drivers/usb/chipidea/usbmisc_imx.c linux-3.14.35/drivers/usb/chipidea/usbmisc_imx.c
- --- linux-3.14.35.orig/drivers/usb/chipidea/usbmisc_imx.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/chipidea/usbmisc_imx.c 2015-03-08 14:27:37.777684499 -0500
- @@ -1,5 +1,5 @@
- /*
- - * Copyright 2012 Freescale Semiconductor, Inc.
- + * Copyright 2012-2013 Freescale Semiconductor, Inc.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- @@ -11,10 +11,10 @@
-
- #include <linux/module.h>
- #include <linux/of_platform.h>
- -#include <linux/clk.h>
- #include <linux/err.h>
- #include <linux/io.h>
- #include <linux/delay.h>
- +#include <linux/regulator/consumer.h>
-
- #include "ci_hdrc_imx.h"
-
- @@ -33,22 +33,28 @@
- #define MX53_BM_OVER_CUR_DIS_UHx BIT(30)
-
- #define MX6_BM_OVER_CUR_DIS BIT(7)
- +#define MX6_BM_WAKEUP_ENABLE BIT(10)
- +#define MX6_BM_ID_WAKEUP BIT(16)
- +#define MX6_BM_VBUS_WAKEUP BIT(17)
- +#define MX6_BM_WAKEUP_INTR BIT(31)
-
- struct usbmisc_ops {
- /* It's called once when probe a usb device */
- int (*init)(struct imx_usbmisc_data *data);
- /* It's called once after adding a usb device */
- int (*post)(struct imx_usbmisc_data *data);
- + /* It's called when we need to enable usb wakeup */
- + int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled);
- };
-
- struct imx_usbmisc {
- void __iomem *base;
- spinlock_t lock;
- - struct clk *clk;
- const struct usbmisc_ops *ops;
- };
-
- static struct imx_usbmisc *usbmisc;
- +static struct regulator *vbus_wakeup_reg;
-
- static int usbmisc_imx25_post(struct imx_usbmisc_data *data)
- {
- @@ -158,6 +164,47 @@
- return 0;
- }
-
- +static u32 imx6q_finalize_wakeup_setting(struct imx_usbmisc_data *data)
- +{
- + if (data->available_role == USB_DR_MODE_PERIPHERAL)
- + return MX6_BM_VBUS_WAKEUP;
- + else if (data->available_role == USB_DR_MODE_OTG)
- + return MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP;
- +
- + return 0;
- +}
- +
- +static int usbmisc_imx6q_set_wakeup
- + (struct imx_usbmisc_data *data, bool enabled)
- +{
- + unsigned long flags;
- + u32 reg, val = MX6_BM_WAKEUP_ENABLE;
- + int ret = 0;
- +
- + if (data->index > 3)
- + return -EINVAL;
- +
- + spin_lock_irqsave(&usbmisc->lock, flags);
- + reg = readl(usbmisc->base + data->index * 4);
- + if (enabled) {
- + val |= imx6q_finalize_wakeup_setting(data);
- + writel(reg | val, usbmisc->base + data->index * 4);
- + if (vbus_wakeup_reg)
- + ret = regulator_enable(vbus_wakeup_reg);
- + } else {
- + if (reg & MX6_BM_WAKEUP_INTR)
- + pr_debug("wakeup int at ci_hdrc.%d\n", data->index);
- + val = MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP
- + | MX6_BM_ID_WAKEUP;
- + writel(reg & ~val, usbmisc->base + data->index * 4);
- + if (vbus_wakeup_reg && regulator_is_enabled(vbus_wakeup_reg))
- + regulator_disable(vbus_wakeup_reg);
- + }
- + spin_unlock_irqrestore(&usbmisc->lock, flags);
- +
- + return ret;
- +}
- +
- static const struct usbmisc_ops imx25_usbmisc_ops = {
- .post = usbmisc_imx25_post,
- };
- @@ -172,6 +219,7 @@
-
- static const struct usbmisc_ops imx6q_usbmisc_ops = {
- .init = usbmisc_imx6q_init,
- + .set_wakeup = usbmisc_imx6q_set_wakeup,
- };
-
- int imx_usbmisc_init(struct imx_usbmisc_data *data)
- @@ -194,6 +242,16 @@
- }
- EXPORT_SYMBOL_GPL(imx_usbmisc_init_post);
-
- +int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled)
- +{
- + if (!usbmisc)
- + return -ENODEV;
- + if (!usbmisc->ops->set_wakeup)
- + return 0;
- + return usbmisc->ops->set_wakeup(data, enabled);
- +}
- +EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup);
- +
- static const struct of_device_id usbmisc_imx_dt_ids[] = {
- {
- .compatible = "fsl,imx25-usbmisc",
- @@ -223,7 +281,6 @@
- {
- struct resource *res;
- struct imx_usbmisc *data;
- - int ret;
- struct of_device_id *tmp_dev;
-
- if (usbmisc)
- @@ -240,31 +297,28 @@
- if (IS_ERR(data->base))
- return PTR_ERR(data->base);
-
- - data->clk = devm_clk_get(&pdev->dev, NULL);
- - if (IS_ERR(data->clk)) {
- - dev_err(&pdev->dev,
- - "failed to get clock, err=%ld\n", PTR_ERR(data->clk));
- - return PTR_ERR(data->clk);
- - }
- -
- - ret = clk_prepare_enable(data->clk);
- - if (ret) {
- - dev_err(&pdev->dev,
- - "clk_prepare_enable failed, err=%d\n", ret);
- - return ret;
- - }
- -
- tmp_dev = (struct of_device_id *)
- of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
- data->ops = (const struct usbmisc_ops *)tmp_dev->data;
- usbmisc = data;
-
- + vbus_wakeup_reg = devm_regulator_get(&pdev->dev, "vbus-wakeup");
- + if (PTR_ERR(vbus_wakeup_reg) == -EPROBE_DEFER)
- + return -EPROBE_DEFER;
- + else if (PTR_ERR(vbus_wakeup_reg) == -ENODEV)
- + /* no vbus regualator is needed */
- + vbus_wakeup_reg = NULL;
- + else if (IS_ERR(vbus_wakeup_reg)) {
- + dev_err(&pdev->dev, "Getting regulator error: %ld\n",
- + PTR_ERR(vbus_wakeup_reg));
- + return PTR_ERR(vbus_wakeup_reg);
- + }
- +
- return 0;
- }
-
- static int usbmisc_imx_remove(struct platform_device *pdev)
- {
- - clk_disable_unprepare(usbmisc->clk);
- usbmisc = NULL;
- return 0;
- }
- diff -Nur linux-3.14.35.orig/drivers/usb/core/hub.c linux-3.14.35/drivers/usb/core/hub.c
- --- linux-3.14.35.orig/drivers/usb/core/hub.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/core/hub.c 2015-03-08 14:27:37.777684499 -0500
- @@ -3916,6 +3916,12 @@
- void usb_enable_ltm(struct usb_device *udev) { }
- EXPORT_SYMBOL_GPL(usb_enable_ltm);
-
- +static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port,
- + u16 portstatus, u16 portchange)
- +{
- + return 0;
- +}
- +
- #endif /* CONFIG_PM */
-
-
- @@ -4512,8 +4518,7 @@
-
- /* Disconnect any existing devices under this port */
- if (udev) {
- - if (hcd->phy && !hdev->parent &&
- - !(portstatus & USB_PORT_STAT_CONNECTION))
- + if (hcd->phy && !hdev->parent)
- usb_phy_notify_disconnect(hcd->phy, udev->speed);
- usb_disconnect(&hub->ports[port1 - 1]->child);
- }
- diff -Nur linux-3.14.35.orig/drivers/usb/core/message.c linux-3.14.35/drivers/usb/core/message.c
- --- linux-3.14.35.orig/drivers/usb/core/message.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/core/message.c 2015-03-08 14:27:37.777684499 -0500
- @@ -178,7 +178,7 @@
- *
- * Return:
- * If successful, 0. Otherwise a negative error number. The number of actual
- - * bytes transferred will be stored in the @actual_length paramater.
- + * bytes transferred will be stored in the @actual_length parameter.
- */
- int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe,
- void *data, int len, int *actual_length, int timeout)
- diff -Nur linux-3.14.35.orig/drivers/usb/core/urb.c linux-3.14.35/drivers/usb/core/urb.c
- --- linux-3.14.35.orig/drivers/usb/core/urb.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/core/urb.c 2015-03-08 14:27:37.777684499 -0500
- @@ -831,7 +831,7 @@
- *
- * this allows all outstanding URBs to be unlinked starting
- * from the back of the queue. This function is asynchronous.
- - * The unlinking is just tiggered. It may happen after this
- + * The unlinking is just triggered. It may happen after this
- * function has returned.
- *
- * This routine should not be called by a driver after its disconnect
- diff -Nur linux-3.14.35.orig/drivers/usb/gadget/f_mass_storage.c linux-3.14.35/drivers/usb/gadget/f_mass_storage.c
- --- linux-3.14.35.orig/drivers/usb/gadget/f_mass_storage.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/gadget/f_mass_storage.c 2015-03-08 14:27:37.777684499 -0500
- @@ -336,8 +336,15 @@
-
- struct usb_ep *bulk_in;
- struct usb_ep *bulk_out;
- +#ifdef CONFIG_FSL_UTP
- + void *utp;
- +#endif
- };
-
- +#ifdef CONFIG_FSL_UTP
- +#include "fsl_updater.h"
- +#endif
- +
- static inline int __fsg_is_set(struct fsg_common *common,
- const char *func, unsigned line)
- {
- @@ -1131,6 +1138,13 @@
- }
- #endif
-
- +#ifdef CONFIG_FSL_UTP
- + if (utp_get_sense(common->fsg) == 0) { /* got the sense from the UTP */
- + sd = UTP_CTX(common->fsg)->sd;
- + sdinfo = UTP_CTX(common->fsg)->sdinfo;
- + valid = 0;
- + } else
- +#endif
- if (!curlun) { /* Unsupported LUNs are okay */
- common->bad_lun_okay = 1;
- sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
- @@ -1152,6 +1166,9 @@
- buf[7] = 18 - 8; /* Additional sense length */
- buf[12] = ASC(sd);
- buf[13] = ASCQ(sd);
- +#ifdef CONFIG_FSL_UTP
- + put_unaligned_be32(UTP_CTX(common->fsg)->sdinfo_h, &buf[8]);
- +#endif
- return 18;
- }
-
- @@ -1645,7 +1662,18 @@
- sd = SS_INVALID_COMMAND;
- } else if (sd != SS_NO_SENSE) {
- DBG(common, "sending command-failure status\n");
- +#ifdef CONFIG_FSL_UTP
- +/*
- + * mfgtool host frequently reset bus during transfer
- + * - the response in csw to request sense will be 1 due to UTP change
- + * some storage information
- + * - host will reset the bus if response to request sense is 1
- + * - change the response to 0 if CONFIG_FSL_UTP is defined
- + */
- + status = US_BULK_STAT_OK;
- +#else
- status = US_BULK_STAT_FAIL;
- +#endif
- VDBG(common, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
- " info x%x\n",
- SK(sd), ASC(sd), ASCQ(sd), sdinfo);
- @@ -1836,6 +1864,13 @@
- common->phase_error = 0;
- common->short_packet_received = 0;
-
- +#ifdef CONFIG_FSL_UTP
- + reply = utp_handle_message(common->fsg, common->cmnd, reply);
- +
- + if (reply != -EINVAL)
- + return reply;
- +#endif
- +
- down_read(&common->filesem); /* We're using the backing file */
- switch (common->cmnd[0]) {
-
- @@ -2502,12 +2537,14 @@
- /* Allow the thread to be frozen */
- set_freezable();
-
- +#ifndef CONFIG_FSL_UTP
- /*
- * Arrange for userspace references to be interpreted as kernel
- * pointers. That way we can pass a kernel pointer to a routine
- * that expects a __user pointer and it will work okay.
- */
- set_fs(get_ds());
- +#endif
-
- /* The main loop */
- while (common->state != FSG_STATE_TERMINATED) {
- @@ -3096,6 +3133,10 @@
-
- /*-------------------------------------------------------------------------*/
-
- +#ifdef CONFIG_FSL_UTP
- +#include "fsl_updater.c"
- +#endif
- +
- static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
- {
- struct fsg_dev *fsg = fsg_from_func(f);
- @@ -3127,6 +3168,10 @@
- fsg_intf_desc.bInterfaceNumber = i;
- fsg->interface_number = i;
-
- +#ifdef CONFIG_FSL_UTP
- + utp_init(fsg);
- +#endif
- +
- /* Find all the endpoints we will use */
- ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc);
- if (!ep)
- @@ -3185,6 +3230,10 @@
- }
-
- usb_free_all_descriptors(&fsg->function);
- +
- +#ifdef CONFIG_FSL_UTP
- + utp_exit(fsg);
- +#endif
- }
-
- static inline struct fsg_lun_opts *to_fsg_lun_opts(struct config_item *item)
- diff -Nur linux-3.14.35.orig/drivers/usb/gadget/fsl_updater.c linux-3.14.35/drivers/usb/gadget/fsl_updater.c
- --- linux-3.14.35.orig/drivers/usb/gadget/fsl_updater.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/usb/gadget/fsl_updater.c 2015-03-08 14:27:37.777684499 -0500
- @@ -0,0 +1,594 @@
- +/*
- + * Freescale UUT driver
- + *
- + * Copyright 2008-2013 Freescale Semiconductor, Inc.
- + * Copyright 2008-2009 Embedded Alley Solutions, Inc All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +static u64 get_be64(u8 *buf)
- +{
- + return ((u64)get_unaligned_be32(buf) << 32) |
- + get_unaligned_be32(buf + 4);
- +}
- +
- +static int utp_init(struct fsg_dev *fsg)
- +{
- + init_waitqueue_head(&utp_context.wq);
- + init_waitqueue_head(&utp_context.list_full_wq);
- +
- + INIT_LIST_HEAD(&utp_context.read);
- + INIT_LIST_HEAD(&utp_context.write);
- + mutex_init(&utp_context.lock);
- +
- + /* the max message is 64KB */
- + utp_context.buffer = vmalloc(0x10000);
- + if (!utp_context.buffer)
- + return -EIO;
- + utp_context.utp_version = 0x1ull;
- + fsg->utp = &utp_context;
- + return misc_register(&utp_dev);
- +}
- +
- +static void utp_exit(struct fsg_dev *fsg)
- +{
- + vfree(utp_context.buffer);
- + misc_deregister(&utp_dev);
- +}
- +
- +static struct utp_user_data *utp_user_data_alloc(size_t size)
- +{
- + struct utp_user_data *uud;
- +
- + uud = vmalloc(size + sizeof(*uud));
- + if (!uud)
- + return uud;
- + memset(uud, 0, size + sizeof(*uud));
- + uud->data.size = size + sizeof(uud->data);
- + INIT_LIST_HEAD(&uud->link);
- + return uud;
- +}
- +
- +static void utp_user_data_free(struct utp_user_data *uud)
- +{
- + mutex_lock(&utp_context.lock);
- + list_del(&uud->link);
- + mutex_unlock(&utp_context.lock);
- + vfree(uud);
- +}
- +
- +/* Get the number of element for list */
- +static u32 count_list(struct list_head *l)
- +{
- + u32 count = 0;
- + struct list_head *tmp;
- +
- + mutex_lock(&utp_context.lock);
- + list_for_each(tmp, l) {
- + count++;
- + }
- + mutex_unlock(&utp_context.lock);
- +
- + return count;
- +}
- +/* The routine will not go on if utp_context.queue is empty */
- +#define WAIT_ACTIVITY(queue) \
- + wait_event_interruptible(utp_context.wq, !list_empty(&utp_context.queue))
- +
- +/* Called by userspace program (uuc) */
- +static ssize_t utp_file_read(struct file *file,
- + char __user *buf,
- + size_t size,
- + loff_t *off)
- +{
- + struct utp_user_data *uud;
- + size_t size_to_put;
- + int free = 0;
- +
- + WAIT_ACTIVITY(read);
- +
- + mutex_lock(&utp_context.lock);
- + uud = list_first_entry(&utp_context.read, struct utp_user_data, link);
- + mutex_unlock(&utp_context.lock);
- + size_to_put = uud->data.size;
- +
- + if (size >= size_to_put)
- + free = !0;
- + if (copy_to_user(buf, &uud->data, size_to_put)) {
- + printk(KERN_INFO "[ %s ] copy error\n", __func__);
- + return -EACCES;
- + }
- + if (free)
- + utp_user_data_free(uud);
- + else {
- + pr_info("sizeof = %d, size = %d\n",
- + sizeof(uud->data),
- + uud->data.size);
- +
- + pr_err("Will not free utp_user_data, because buffer size = %d,"
- + "need to put %d\n", size, size_to_put);
- + }
- +
- + /*
- + * The user program has already finished data process,
- + * go on getting data from the host
- + */
- + wake_up(&utp_context.list_full_wq);
- +
- + return size_to_put;
- +}
- +
- +static ssize_t utp_file_write(struct file *file, const char __user *buf,
- + size_t size, loff_t *off)
- +{
- + struct utp_user_data *uud;
- +
- + if (size < sizeof(uud->data))
- + return -EINVAL;
- + uud = utp_user_data_alloc(size);
- + if (uud == NULL)
- + return -ENOMEM;
- + if (copy_from_user(&uud->data, buf, size)) {
- + printk(KERN_INFO "[ %s ] copy error!\n", __func__);
- + vfree(uud);
- + return -EACCES;
- + }
- + mutex_lock(&utp_context.lock);
- + list_add_tail(&uud->link, &utp_context.write);
- + /* Go on EXEC routine process */
- + wake_up(&utp_context.wq);
- + mutex_unlock(&utp_context.lock);
- + return size;
- +}
- +
- +/*
- + * uuc should change to use soc bus infrastructure to soc information
- + * /sys/devices/soc0/soc_id
- + * this function can be removed.
- + */
- +static long
- +utp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
- +{
- + int cpu_id = 0;
- +
- + switch (cmd) {
- + case UTP_GET_CPU_ID:
- + return put_user(cpu_id, (int __user *)arg);
- + default:
- + return -ENOIOCTLCMD;
- + }
- +}
- +
- +/* Will be called when the host wants to get the sense data */
- +static int utp_get_sense(struct fsg_dev *fsg)
- +{
- + if (UTP_CTX(fsg)->processed == 0)
- + return -1;
- +
- + UTP_CTX(fsg)->processed = 0;
- + return 0;
- +}
- +
- +static int utp_do_read(struct fsg_dev *fsg, void *data, size_t size)
- +{
- + struct fsg_buffhd *bh;
- + int rc;
- + u32 amount_left;
- + unsigned int amount;
- +
- + /* Get the starting Logical Block Address and check that it's
- + * not too big */
- +
- + amount_left = size;
- + if (unlikely(amount_left == 0))
- + return -EIO; /* No default reply*/
- +
- + pr_debug("%s: sending %d\n", __func__, size);
- + for (;;) {
- + /* Figure out how much we need to read:
- + * Try to read the remaining amount.
- + * But don't read more than the buffer size.
- + * And don't try to read past the end of the file.
- + * Finally, if we're not at a page boundary, don't read past
- + * the next page.
- + * If this means reading 0 then we were asked to read past
- + * the end of file. */
- + amount = min((unsigned int) amount_left, FSG_BUFLEN);
- +
- + /* Wait for the next buffer to become available */
- + bh = fsg->common->next_buffhd_to_fill;
- + while (bh->state != BUF_STATE_EMPTY) {
- + rc = sleep_thread(fsg->common);
- + if (rc)
- + return rc;
- + }
- +
- + /* If we were asked to read past the end of file,
- + * end with an empty buffer. */
- + if (amount == 0) {
- + bh->inreq->length = 0;
- + bh->state = BUF_STATE_FULL;
- + break;
- + }
- +
- + /* Perform the read */
- + pr_info("Copied to %p, %d bytes started from %d\n",
- + bh->buf, amount, size - amount_left);
- + /* from upt buffer to file_storeage buffer */
- + memcpy(bh->buf, data + size - amount_left, amount);
- + amount_left -= amount;
- + fsg->common->residue -= amount;
- +
- + bh->inreq->length = amount;
- + bh->state = BUF_STATE_FULL;
- +
- + /* Send this buffer and go read some more */
- + bh->inreq->zero = 0;
- +
- + /* USB Physical transfer: Data from device to host */
- + start_transfer(fsg, fsg->bulk_in, bh->inreq,
- + &bh->inreq_busy, &bh->state);
- +
- + fsg->common->next_buffhd_to_fill = bh->next;
- +
- + if (amount_left <= 0)
- + break;
- + }
- +
- + return size - amount_left;
- +}
- +
- +static int utp_do_write(struct fsg_dev *fsg, void *data, size_t size)
- +{
- + struct fsg_buffhd *bh;
- + int get_some_more;
- + u32 amount_left_to_req, amount_left_to_write;
- + unsigned int amount;
- + int rc;
- + loff_t offset;
- +
- + /* Carry out the file writes */
- + get_some_more = 1;
- + amount_left_to_req = amount_left_to_write = size;
- +
- + if (unlikely(amount_left_to_write == 0))
- + return -EIO;
- +
- + offset = 0;
- + while (amount_left_to_write > 0) {
- +
- + /* Queue a request for more data from the host */
- + bh = fsg->common->next_buffhd_to_fill;
- + if (bh->state == BUF_STATE_EMPTY && get_some_more) {
- +
- + /* Figure out how much we want to get:
- + * Try to get the remaining amount.
- + * But don't get more than the buffer size.
- + * And don't try to go past the end of the file.
- + * If we're not at a page boundary,
- + * don't go past the next page.
- + * If this means getting 0, then we were asked
- + * to write past the end of file.
- + * Finally, round down to a block boundary. */
- + amount = min(amount_left_to_req, FSG_BUFLEN);
- +
- + if (amount == 0) {
- + get_some_more = 0;
- + /* cry now */
- + continue;
- + }
- +
- + /* Get the next buffer */
- + amount_left_to_req -= amount;
- + if (amount_left_to_req == 0)
- + get_some_more = 0;
- +
- + /* amount is always divisible by 512, hence by
- + * the bulk-out maxpacket size */
- + bh->outreq->length = bh->bulk_out_intended_length =
- + amount;
- + bh->outreq->short_not_ok = 1;
- + start_transfer(fsg, fsg->bulk_out, bh->outreq,
- + &bh->outreq_busy, &bh->state);
- + fsg->common->next_buffhd_to_fill = bh->next;
- + continue;
- + }
- +
- + /* Write the received data to the backing file */
- + bh = fsg->common->next_buffhd_to_drain;
- + if (bh->state == BUF_STATE_EMPTY && !get_some_more)
- + break; /* We stopped early */
- + if (bh->state == BUF_STATE_FULL) {
- + smp_rmb();
- + fsg->common->next_buffhd_to_drain = bh->next;
- + bh->state = BUF_STATE_EMPTY;
- +
- + /* Did something go wrong with the transfer? */
- + if (bh->outreq->status != 0)
- + /* cry again, COMMUNICATION_FAILURE */
- + break;
- +
- + amount = bh->outreq->actual;
- +
- + /* Perform the write */
- + memcpy(data + offset, bh->buf, amount);
- +
- + offset += amount;
- + if (signal_pending(current))
- + return -EINTR; /* Interrupted!*/
- + amount_left_to_write -= amount;
- + fsg->common->residue -= amount;
- +
- + /* Did the host decide to stop early? */
- + if (bh->outreq->actual != bh->outreq->length) {
- + fsg->common->short_packet_received = 1;
- + break;
- + }
- + continue;
- + }
- +
- + /* Wait for something to happen */
- + rc = sleep_thread(fsg->common);
- + if (rc)
- + return rc;
- + }
- +
- + return -EIO;
- +}
- +
- +static inline void utp_set_sense(struct fsg_dev *fsg, u16 code, u64 reply)
- +{
- + UTP_CTX(fsg)->processed = true;
- + UTP_CTX(fsg)->sdinfo = reply & 0xFFFFFFFF;
- + UTP_CTX(fsg)->sdinfo_h = (reply >> 32) & 0xFFFFFFFF;
- + UTP_CTX(fsg)->sd = (UTP_SENSE_KEY << 16) | code;
- +}
- +
- +static void utp_poll(struct fsg_dev *fsg)
- +{
- + struct utp_context *ctx = UTP_CTX(fsg);
- + struct utp_user_data *uud = NULL;
- +
- + mutex_lock(&ctx->lock);
- + if (!list_empty(&ctx->write))
- + uud = list_first_entry(&ctx->write, struct utp_user_data, link);
- + mutex_unlock(&ctx->lock);
- +
- + if (uud) {
- + if (uud->data.flags & UTP_FLAG_STATUS) {
- + printk(KERN_WARNING "%s: exit with status %d\n",
- + __func__, uud->data.status);
- + UTP_SS_EXIT(fsg, uud->data.status);
- + } else if (uud->data.flags & UTP_FLAG_REPORT_BUSY) {
- + UTP_SS_BUSY(fsg, --ctx->counter);
- + } else {
- + printk("%s: pass returned.\n", __func__);
- + UTP_SS_PASS(fsg);
- + }
- + utp_user_data_free(uud);
- + } else {
- + if (utp_context.cur_state & UTP_FLAG_DATA) {
- + if (count_list(&ctx->read) < 7) {
- + pr_debug("%s: pass returned in POLL stage. \n", __func__);
- + UTP_SS_PASS(fsg);
- + utp_context.cur_state = 0;
- + return;
- + }
- + }
- + UTP_SS_BUSY(fsg, --ctx->counter);
- + }
- +}
- +
- +static int utp_exec(struct fsg_dev *fsg,
- + char *command,
- + int cmdsize,
- + unsigned long long payload)
- +{
- + struct utp_user_data *uud = NULL, *uud2r;
- + struct utp_context *ctx = UTP_CTX(fsg);
- +
- + ctx->counter = 0xFFFF;
- + uud2r = utp_user_data_alloc(cmdsize + 1);
- + if (!uud2r)
- + return -ENOMEM;
- + uud2r->data.flags = UTP_FLAG_COMMAND;
- + uud2r->data.payload = payload;
- + strncpy(uud2r->data.command, command, cmdsize);
- +
- + mutex_lock(&ctx->lock);
- + list_add_tail(&uud2r->link, &ctx->read);
- + mutex_unlock(&ctx->lock);
- + /* wake up the read routine */
- + wake_up(&ctx->wq);
- +
- + if (command[0] == '!') /* there will be no response */
- + return 0;
- +
- + /*
- + * the user program (uuc) will return utp_message
- + * and add list to write list
- + */
- + WAIT_ACTIVITY(write);
- +
- + mutex_lock(&ctx->lock);
- + if (!list_empty(&ctx->write)) {
- + uud = list_first_entry(&ctx->write, struct utp_user_data, link);
- +#ifdef DEBUG
- + pr_info("UUD:\n\tFlags = %02X\n", uud->data.flags);
- + if (uud->data.flags & UTP_FLAG_DATA) {
- + pr_info("\tbufsize = %d\n", uud->data.bufsize);
- + print_hex_dump(KERN_DEBUG, "\t", DUMP_PREFIX_NONE,
- + 16, 2, uud->data.data, uud->data.bufsize, true);
- + }
- + if (uud->data.flags & UTP_FLAG_REPORT_BUSY)
- + pr_info("\tBUSY\n");
- +#endif
- + }
- + mutex_unlock(&ctx->lock);
- +
- + if (uud->data.flags & UTP_FLAG_DATA) {
- + memcpy(ctx->buffer, uud->data.data, uud->data.bufsize);
- + UTP_SS_SIZE(fsg, uud->data.bufsize);
- + } else if (uud->data.flags & UTP_FLAG_REPORT_BUSY) {
- + UTP_SS_BUSY(fsg, ctx->counter);
- + } else if (uud->data.flags & UTP_FLAG_STATUS) {
- + printk(KERN_WARNING "%s: exit with status %d\n", __func__,
- + uud->data.status);
- + UTP_SS_EXIT(fsg, uud->data.status);
- + } else {
- + pr_debug("%s: pass returned in EXEC stage. \n", __func__);
- + UTP_SS_PASS(fsg);
- + }
- + utp_user_data_free(uud);
- + return 0;
- +}
- +
- +static int utp_send_status(struct fsg_dev *fsg)
- +{
- + struct fsg_buffhd *bh;
- + u8 status = US_BULK_STAT_OK;
- + struct bulk_cs_wrap *csw;
- + int rc;
- +
- + /* Wait for the next buffer to become available */
- + bh = fsg->common->next_buffhd_to_fill;
- + while (bh->state != BUF_STATE_EMPTY) {
- + rc = sleep_thread(fsg->common);
- + if (rc)
- + return rc;
- + }
- +
- + if (fsg->common->phase_error) {
- + DBG(fsg, "sending phase-error status\n");
- + status = US_BULK_STAT_PHASE;
- +
- + } else if ((UTP_CTX(fsg)->sd & 0xFFFF) != UTP_REPLY_PASS) {
- + status = US_BULK_STAT_FAIL;
- + }
- +
- + csw = bh->buf;
- +
- + /* Store and send the Bulk-only CSW */
- + csw->Signature = __constant_cpu_to_le32(US_BULK_CS_SIGN);
- + csw->Tag = fsg->common->tag;
- + csw->Residue = cpu_to_le32(fsg->common->residue);
- + csw->Status = status;
- +
- + bh->inreq->length = US_BULK_CS_WRAP_LEN;
- + bh->inreq->zero = 0;
- + start_transfer(fsg, fsg->bulk_in, bh->inreq,
- + &bh->inreq_busy, &bh->state);
- + fsg->common->next_buffhd_to_fill = bh->next;
- + return 0;
- +}
- +
- +static int utp_handle_message(struct fsg_dev *fsg,
- + char *cdb_data,
- + int default_reply)
- +{
- + struct utp_msg *m = (struct utp_msg *)cdb_data;
- + void *data = NULL;
- + int r;
- + struct utp_user_data *uud2r;
- + unsigned long long param;
- + unsigned long tag;
- +
- + if (m->f0 != 0xF0)
- + return default_reply;
- +
- + tag = get_unaligned_be32((void *)&m->utp_msg_tag);
- + param = get_be64((void *)&m->param);
- + pr_debug("Type 0x%x, tag 0x%08lx, param %llx\n",
- + m->utp_msg_type, tag, param);
- +
- + switch ((enum utp_msg_type)m->utp_msg_type) {
- +
- + case UTP_POLL:
- + if (get_be64((void *)&m->param) == 1) {
- + pr_debug("%s: version request\n", __func__);
- + UTP_SS_EXIT(fsg, UTP_CTX(fsg)->utp_version);
- + break;
- + }
- + utp_poll(fsg);
- + break;
- + case UTP_EXEC:
- + pr_debug("%s: EXEC\n", __func__);
- + data = vmalloc(fsg->common->data_size);
- + memset(data, 0, fsg->common->data_size);
- + /* copy data from usb buffer to utp buffer */
- + utp_do_write(fsg, data, fsg->common->data_size);
- + utp_exec(fsg, data, fsg->common->data_size, param);
- + vfree(data);
- + break;
- + case UTP_GET: /* data from device to host */
- + pr_debug("%s: GET, %d bytes\n", __func__,
- + fsg->common->data_size);
- + r = utp_do_read(fsg, UTP_CTX(fsg)->buffer,
- + fsg->common->data_size);
- + UTP_SS_PASS(fsg);
- + break;
- + case UTP_PUT:
- + utp_context.cur_state = UTP_FLAG_DATA;
- + pr_debug("%s: PUT, Received %d bytes\n", __func__, fsg->common->data_size);/* data from host to device */
- + uud2r = utp_user_data_alloc(fsg->common->data_size);
- + if (!uud2r)
- + return -ENOMEM;
- + uud2r->data.bufsize = fsg->common->data_size;
- + uud2r->data.flags = UTP_FLAG_DATA;
- + utp_do_write(fsg, uud2r->data.data, fsg->common->data_size);
- + /* don't know what will be written */
- + mutex_lock(&UTP_CTX(fsg)->lock);
- + list_add_tail(&uud2r->link, &UTP_CTX(fsg)->read);
- + mutex_unlock(&UTP_CTX(fsg)->lock);
- + wake_up(&UTP_CTX(fsg)->wq);
- + /*
- + * Return PASS or FAIL according to uuc's status
- + * Please open it if need to check uuc's status
- + * and use another version uuc
- + */
- +#if 0
- + struct utp_user_data *uud = NULL;
- + struct utp_context *ctx;
- + WAIT_ACTIVITY(write);
- + ctx = UTP_CTX(fsg);
- + mutex_lock(&ctx->lock);
- +
- + if (!list_empty(&ctx->write))
- + uud = list_first_entry(&ctx->write,
- + struct utp_user_data, link);
- +
- + mutex_unlock(&ctx->lock);
- + if (uud) {
- + if (uud->data.flags & UTP_FLAG_STATUS) {
- + printk(KERN_WARNING "%s: exit with status %d\n",
- + __func__, uud->data.status);
- + UTP_SS_EXIT(fsg, uud->data.status);
- + } else {
- + pr_debug("%s: pass\n", __func__);
- + UTP_SS_PASS(fsg);
- + }
- + utp_user_data_free(uud);
- + } else{
- + UTP_SS_PASS(fsg);
- + }
- +#endif
- + if (count_list(&UTP_CTX(fsg)->read) < 7) {
- + utp_context.cur_state = 0;
- + UTP_SS_PASS(fsg);
- + } else
- + UTP_SS_BUSY(fsg, UTP_CTX(fsg)->counter);
- +
- + break;
- + }
- +
- + utp_send_status(fsg);
- + return -1;
- +}
- diff -Nur linux-3.14.35.orig/drivers/usb/gadget/fsl_updater.h linux-3.14.35/drivers/usb/gadget/fsl_updater.h
- --- linux-3.14.35.orig/drivers/usb/gadget/fsl_updater.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/usb/gadget/fsl_updater.h 2015-03-08 14:27:37.777684499 -0500
- @@ -0,0 +1,150 @@
- +/*
- + * Freescale UUT driver
- + *
- + * Copyright 2008-2013 Freescale Semiconductor, Inc.
- + * Copyright 2008-2009 Embedded Alley Solutions, Inc All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#ifndef __FSL_UPDATER_H
- +#define __FSL_UPDATER_H
- +
- +#include <linux/miscdevice.h>
- +#include <linux/list.h>
- +#include <linux/vmalloc.h>
- +#include <linux/ioctl.h>
- +/* #include <mach/hardware.h> */
- +
- +static int utp_init(struct fsg_dev *fsg);
- +static void utp_exit(struct fsg_dev *fsg);
- +static ssize_t utp_file_read(struct file *file,
- + char __user *buf,
- + size_t size,
- + loff_t *off);
- +
- +static ssize_t utp_file_write(struct file *file,
- + const char __user *buf,
- + size_t size,
- + loff_t *off);
- +
- +static long utp_ioctl(struct file *file,
- + unsigned int cmd, unsigned long arg);
- +static struct utp_user_data *utp_user_data_alloc(size_t size);
- +static void utp_user_data_free(struct utp_user_data *uud);
- +static int utp_get_sense(struct fsg_dev *fsg);
- +static int utp_do_read(struct fsg_dev *fsg, void *data, size_t size);
- +static int utp_do_write(struct fsg_dev *fsg, void *data, size_t size);
- +static inline void utp_set_sense(struct fsg_dev *fsg, u16 code, u64 reply);
- +static int utp_handle_message(struct fsg_dev *fsg,
- + char *cdb_data,
- + int default_reply);
- +
- +#define UTP_REPLY_PASS 0
- +#define UTP_REPLY_EXIT 0x8001
- +#define UTP_REPLY_BUSY 0x8002
- +#define UTP_REPLY_SIZE 0x8003
- +#define UTP_SENSE_KEY 9
- +
- +#define UTP_MINOR 222
- +/* MISC_DYNAMIC_MINOR would be better, but... */
- +
- +#define UTP_COMMAND_SIZE 80
- +
- +#define UTP_SS_EXIT(fsg, r) utp_set_sense(fsg, UTP_REPLY_EXIT, (u64)r)
- +#define UTP_SS_PASS(fsg) utp_set_sense(fsg, UTP_REPLY_PASS, 0)
- +#define UTP_SS_BUSY(fsg, r) utp_set_sense(fsg, UTP_REPLY_BUSY, (u64)r)
- +#define UTP_SS_SIZE(fsg, r) utp_set_sense(fsg, UTP_REPLY_SIZE, (u64)r)
- +
- +#define UTP_IOCTL_BASE 'U'
- +#define UTP_GET_CPU_ID _IOR(UTP_IOCTL_BASE, 0, int)
- +/* the structure of utp message which is mapped to 16-byte SCSI CBW's CDB */
- +#pragma pack(1)
- +struct utp_msg {
- + u8 f0;
- + u8 utp_msg_type;
- + u32 utp_msg_tag;
- + union {
- + struct {
- + u32 param_lsb;
- + u32 param_msb;
- + };
- + u64 param;
- + };
- +};
- +
- +enum utp_msg_type {
- + UTP_POLL = 0,
- + UTP_EXEC,
- + UTP_GET,
- + UTP_PUT,
- +};
- +
- +static struct utp_context {
- + wait_queue_head_t wq;
- + wait_queue_head_t list_full_wq;
- + struct mutex lock;
- + struct list_head read;
- + struct list_head write;
- + u32 sd, sdinfo, sdinfo_h; /* sense data */
- + int processed;
- + u8 *buffer;
- + u32 counter;
- + u64 utp_version;
- + u32 cur_state;
- +} utp_context;
- +
- +static const struct file_operations utp_fops = {
- + .open = nonseekable_open,
- + .read = utp_file_read,
- + .write = utp_file_write,
- + /* .ioctl = utp_ioctl, */
- + .unlocked_ioctl = utp_ioctl,
- +};
- +
- +static struct miscdevice utp_dev = {
- + .minor = UTP_MINOR,
- + .name = "utp",
- + .fops = &utp_fops,
- +};
- +
- +#define UTP_FLAG_COMMAND 0x00000001
- +#define UTP_FLAG_DATA 0x00000002
- +#define UTP_FLAG_STATUS 0x00000004
- +#define UTP_FLAG_REPORT_BUSY 0x10000000
- +struct utp_message {
- + u32 flags;
- + size_t size;
- + union {
- + struct {
- + u64 payload;
- + char command[1];
- + };
- + struct {
- + size_t bufsize;
- + u8 data[1];
- + };
- + u32 status;
- + };
- +};
- +
- +struct utp_user_data {
- + struct list_head link;
- + struct utp_message data;
- +};
- +#pragma pack()
- +
- +static inline struct utp_context *UTP_CTX(struct fsg_dev *fsg)
- +{
- + return (struct utp_context *)fsg->utp;
- +}
- +
- +#endif /* __FSL_UPDATER_H */
- +
- diff -Nur linux-3.14.35.orig/drivers/usb/gadget/Kconfig linux-3.14.35/drivers/usb/gadget/Kconfig
- --- linux-3.14.35.orig/drivers/usb/gadget/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/gadget/Kconfig 2015-03-08 14:27:37.777684499 -0500
- @@ -953,6 +953,12 @@
- Say "y" to link the driver statically, or "m" to build
- a dynamically linked module called "g_mass_storage".
-
- +config FSL_UTP
- + bool "UTP over Storage Gadget"
- + depends on USB_MASS_STORAGE
- + help
- + Freescale's extension to MSC protocol
- +
- config USB_GADGET_TARGET
- tristate "USB Gadget Target Fabric Module"
- depends on TARGET_CORE
- diff -Nur linux-3.14.35.orig/drivers/usb/gadget/mass_storage.c linux-3.14.35/drivers/usb/gadget/mass_storage.c
- --- linux-3.14.35.orig/drivers/usb/gadget/mass_storage.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/gadget/mass_storage.c 2015-03-08 14:27:37.777684499 -0500
- @@ -266,7 +266,7 @@
- {
- return usb_composite_probe(&msg_driver);
- }
- -module_init(msg_init);
- +late_initcall(msg_init);
-
- static void msg_cleanup(void)
- {
- diff -Nur linux-3.14.35.orig/drivers/usb/host/ehci-h20ahb.c linux-3.14.35/drivers/usb/host/ehci-h20ahb.c
- --- linux-3.14.35.orig/drivers/usb/host/ehci-h20ahb.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/usb/host/ehci-h20ahb.c 2015-03-08 14:27:37.777684499 -0500
- @@ -0,0 +1,341 @@
- +/*
- + * Copyright (C) 2007-2013 Texas Instruments, Inc.
- + * Author: Vikram Pandita <vikram.pandita@ti.com>
- + * Author: Anand Gadiyar <gadiyar@ti.com>
- + * Author: Keshava Munegowda <keshava_mgowda@ti.com>
- + * Author: Roger Quadros <rogerq@ti.com>
- + *
- + * Copyright (C) 2009 Nokia Corporation
- + * Contact: Felipe Balbi <felipe.balbi@nokia.com>
- + *
- + * Based on ehci-omap.c - driver for USBHOST on OMAP3/4 processors
- + *
- + * This file is subject to the terms and conditions of the GNU General Public
- + * License. See the file COPYING in the main directory of this archive
- + * for more details.
- + *
- + */
- +
- +#include <linux/kernel.h>
- +#include <linux/module.h>
- +#include <linux/io.h>
- +#include <linux/platform_device.h>
- +#include <linux/slab.h>
- +#include <linux/usb/ulpi.h>
- +#include <linux/pm_runtime.h>
- +#include <linux/gpio.h>
- +#include <linux/clk.h>
- +#include <linux/usb.h>
- +#include <linux/usb/hcd.h>
- +#include <linux/of.h>
- +#include <linux/dma-mapping.h>
- +
- +#include "ehci.h"
- +
- +#define H20AHB_HS_USB_PORTS 1
- +
- +/* EHCI Synopsys-specific Register Set */
- +#define EHCI_INSNREG04 (0xA0)
- +#define EHCI_INSNREG04_DISABLE_UNSUSPEND (1 << 5)
- +#define EHCI_INSNREG05_ULPI (0xA4)
- +#define EHCI_INSNREG05_ULPI_CONTROL_SHIFT 31
- +#define EHCI_INSNREG05_ULPI_PORTSEL_SHIFT 24
- +#define EHCI_INSNREG05_ULPI_OPSEL_SHIFT 22
- +#define EHCI_INSNREG05_ULPI_REGADD_SHIFT 16
- +#define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8
- +#define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0
- +
- +#define DRIVER_DESC "H20AHB-EHCI Host Controller driver"
- +
- +static const char hcd_name[] = "ehci-h20ahb";
- +
- +/*-------------------------------------------------------------------------*/
- +
- +struct h20ahb_hcd {
- + struct usb_phy *phy[H20AHB_HS_USB_PORTS]; /* one PHY for each port */
- + int nports;
- +};
- +
- +static inline void ehci_write(void __iomem *base, u32 reg, u32 val)
- +{
- + __raw_writel(val, base + reg);
- +}
- +
- +static inline u32 ehci_read(void __iomem *base, u32 reg)
- +{
- + return __raw_readl(base + reg);
- +}
- +
- +/* configure so an HC device and id are always provided */
- +/* always called with process context; sleeping is OK */
- +
- +static struct hc_driver __read_mostly ehci_h20ahb_hc_driver;
- +
- +static const struct ehci_driver_overrides ehci_h20ahb_overrides __initdata = {
- + .extra_priv_size = sizeof(struct h20ahb_hcd),
- +};
- +
- +static int ehci_h20ahb_phy_read(struct usb_phy *x, u32 reg)
- +{
- + u32 val = (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |
- + (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |
- + (3 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |
- + (reg << EHCI_INSNREG05_ULPI_REGADD_SHIFT);
- + ehci_write(x->io_priv, 0, val);
- + while ((val = ehci_read(x->io_priv, 0)) &
- + (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT));
- + return val & 0xff;
- +}
- +
- +static int ehci_h20ahb_phy_write(struct usb_phy *x, u32 val, u32 reg)
- +{
- + u32 v = (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |
- + (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |
- + (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |
- + (reg << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |
- + (val & 0xff);
- + ehci_write(x->io_priv, 0, v);
- + while ((v = ehci_read(x->io_priv, 0)) &
- + (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT));
- + return 0;
- +}
- +
- +static struct usb_phy_io_ops ehci_h20ahb_phy_io_ops = {
- + .read = ehci_h20ahb_phy_read,
- + .write = ehci_h20ahb_phy_write,
- +};
- +
- +
- +/**
- + * ehci_hcd_h20ahb_probe - initialize Synopsis-based HCDs
- + *
- + * Allocates basic resources for this USB host controller, and
- + * then invokes the start() method for the HCD associated with it
- + * through the hotplug entry's driver_data.
- + */
- +static int ehci_hcd_h20ahb_probe(struct platform_device *pdev)
- +{
- + struct device *dev = &pdev->dev;
- + struct resource *res;
- + struct usb_hcd *hcd;
- + void __iomem *regs;
- + int ret;
- + int irq;
- + int i;
- + struct h20ahb_hcd *h20ahb;
- +
- + if (usb_disabled())
- + return -ENODEV;
- +
- + /* if (!dev->parent) {
- + dev_err(dev, "Missing parent device\n");
- + return -ENODEV;
- + }*/
- +
- + /* For DT boot, get platform data from parent. i.e. usbhshost */
- + /*if (dev->of_node) {
- + pdata = dev_get_platdata(dev->parent);
- + dev->platform_data = pdata;
- + }
- +
- + if (!pdata) {
- + dev_err(dev, "Missing platform data\n");
- + return -ENODEV;
- + }*/
- +
- + irq = platform_get_irq(pdev, 0);
- + if (irq < 0) {
- + dev_err(dev, "EHCI irq failed\n");
- + return -ENODEV;
- + }
- +
- + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- + regs = devm_ioremap_resource(dev, res);
- + if (IS_ERR(regs))
- + return PTR_ERR(regs);
- +
- + /*
- + * Right now device-tree probed devices don't get dma_mask set.
- + * Since shared usb code relies on it, set it here for now.
- + * Once we have dma capability bindings this can go away.
- + */
- + ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
- + if (ret)
- + return ret;
- +
- + ret = -ENODEV;
- + hcd = usb_create_hcd(&ehci_h20ahb_hc_driver, dev,
- + dev_name(dev));
- + if (!hcd) {
- + dev_err(dev, "Failed to create HCD\n");
- + return -ENOMEM;
- + }
- +
- + hcd->rsrc_start = res->start;
- + hcd->rsrc_len = resource_size(res);
- + hcd->regs = regs;
- + hcd_to_ehci(hcd)->caps = regs;
- +
- + h20ahb = (struct h20ahb_hcd *)hcd_to_ehci(hcd)->priv;
- + h20ahb->nports = 1;
- +
- + platform_set_drvdata(pdev, hcd);
- +
- + /* get the PHY devices if needed */
- + for (i = 0 ; i < h20ahb->nports ; i++) {
- + struct usb_phy *phy;
- +
- + /* get the PHY device */
- +#if 0
- + if (dev->of_node)
- + phy = devm_usb_get_phy_by_phandle(dev, "phys", i);
- + else
- + phy = devm_usb_get_phy_dev(dev, i);
- +#endif
- + phy = otg_ulpi_create(&ehci_h20ahb_phy_io_ops, 0);
- + if (IS_ERR(phy)) {
- + ret = PTR_ERR(phy);
- + dev_err(dev, "Can't get PHY device for port %d: %d\n",
- + i, ret);
- + goto err_phy;
- + }
- + phy->dev = dev;
- + usb_add_phy_dev(phy);
- +
- + h20ahb->phy[i] = phy;
- + phy->io_priv = hcd->regs + EHCI_INSNREG05_ULPI;
- +
- +#if 0
- + usb_phy_init(h20ahb->phy[i]);
- + /* bring PHY out of suspend */
- + usb_phy_set_suspend(h20ahb->phy[i], 0);
- +#endif
- + }
- +
- + /* make the first port's phy the one used by hcd as well */
- + hcd->phy = h20ahb->phy[0];
- +
- + pm_runtime_enable(dev);
- + pm_runtime_get_sync(dev);
- +
- + /*
- + * An undocumented "feature" in the H20AHB EHCI controller,
- + * causes suspended ports to be taken out of suspend when
- + * the USBCMD.Run/Stop bit is cleared (for example when
- + * we do ehci_bus_suspend).
- + * This breaks suspend-resume if the root-hub is allowed
- + * to suspend. Writing 1 to this undocumented register bit
- + * disables this feature and restores normal behavior.
- + */
- + ehci_write(regs, EHCI_INSNREG04,
- + EHCI_INSNREG04_DISABLE_UNSUSPEND);
- +
- + ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
- + if (ret) {
- + dev_err(dev, "failed to add hcd with err %d\n", ret);
- + goto err_pm_runtime;
- + }
- + device_wakeup_enable(hcd->self.controller);
- +
- + /*
- + * Bring PHYs out of reset for non PHY modes.
- + * Even though HSIC mode is a PHY-less mode, the reset
- + * line exists between the chips and can be modelled
- + * as a PHY device for reset control.
- + */
- + for (i = 0; i < h20ahb->nports; i++) {
- + usb_phy_init(h20ahb->phy[i]);
- + /* bring PHY out of suspend */
- + usb_phy_set_suspend(h20ahb->phy[i], 0);
- + }
- +
- + return 0;
- +
- +err_pm_runtime:
- + pm_runtime_put_sync(dev);
- +
- +err_phy:
- + for (i = 0; i < h20ahb->nports; i++) {
- + if (h20ahb->phy[i])
- + usb_phy_shutdown(h20ahb->phy[i]);
- + }
- +
- + usb_put_hcd(hcd);
- +
- + return ret;
- +}
- +
- +
- +/**
- + * ehci_hcd_h20ahb_remove - shutdown processing for EHCI HCDs
- + * @pdev: USB Host Controller being removed
- + *
- + * Reverses the effect of usb_ehci_hcd_h20ahb_probe(), first invoking
- + * the HCD's stop() method. It is always called from a thread
- + * context, normally "rmmod", "apmd", or something similar.
- + */
- +static int ehci_hcd_h20ahb_remove(struct platform_device *pdev)
- +{
- + struct device *dev = &pdev->dev;
- + struct usb_hcd *hcd = dev_get_drvdata(dev);
- + struct h20ahb_hcd *h20ahb = (struct h20ahb_hcd *)hcd_to_ehci(hcd)->priv;
- + int i;
- +
- + usb_remove_hcd(hcd);
- +
- + for (i = 0; i < h20ahb->nports; i++) {
- + if (h20ahb->phy[i])
- + usb_phy_shutdown(h20ahb->phy[i]);
- + }
- +
- + usb_put_hcd(hcd);
- + pm_runtime_put_sync(dev);
- + pm_runtime_disable(dev);
- +
- + return 0;
- +}
- +
- +static const struct of_device_id h20ahb_ehci_dt_ids[] = {
- + { .compatible = "snps,ehci-h20ahb" },
- + { }
- +};
- +
- +MODULE_DEVICE_TABLE(of, h20ahb_ehci_dt_ids);
- +
- +static struct platform_driver ehci_hcd_h20ahb_driver = {
- + .probe = ehci_hcd_h20ahb_probe,
- + .remove = ehci_hcd_h20ahb_remove,
- + .shutdown = usb_hcd_platform_shutdown,
- + /*.suspend = ehci_hcd_h20ahb_suspend, */
- + /*.resume = ehci_hcd_h20ahb_resume, */
- + .driver = {
- + .name = hcd_name,
- + .of_match_table = h20ahb_ehci_dt_ids,
- + }
- +};
- +
- +/*-------------------------------------------------------------------------*/
- +
- +static int __init ehci_h20ahb_init(void)
- +{
- + if (usb_disabled())
- + return -ENODEV;
- +
- + pr_info("%s: " DRIVER_DESC "\n", hcd_name);
- +
- + ehci_init_driver(&ehci_h20ahb_hc_driver, &ehci_h20ahb_overrides);
- + return platform_driver_register(&ehci_hcd_h20ahb_driver);
- +}
- +module_init(ehci_h20ahb_init);
- +
- +static void __exit ehci_h20ahb_cleanup(void)
- +{
- + platform_driver_unregister(&ehci_hcd_h20ahb_driver);
- +}
- +module_exit(ehci_h20ahb_cleanup);
- +
- +MODULE_ALIAS("platform:ehci-h20ahb");
- +MODULE_AUTHOR("Liviu Dudau <Liviu.Dudau@arm.com>");
- +
- +MODULE_DESCRIPTION(DRIVER_DESC);
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/usb/host/ehci-hcd.c linux-3.14.35/drivers/usb/host/ehci-hcd.c
- --- linux-3.14.35.orig/drivers/usb/host/ehci-hcd.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/host/ehci-hcd.c 2015-03-08 14:27:37.781684499 -0500
- @@ -590,11 +590,16 @@
- */
- hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
- if (HCC_64BIT_ADDR(hcc_params)) {
- - ehci_writel(ehci, 0, &ehci->regs->segment);
- -#if 0
- -// this is deeply broken on almost all architectures
- +#ifdef CONFIG_ARM64
- + ehci_writel(ehci, ehci->periodic_dma >> 32, &ehci->regs->segment);
- + /*
- + * this is deeply broken on almost all architectures
- + * but arm64 can use it so enable it
- + */
- if (!dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64)))
- ehci_info(ehci, "enabled 64bit DMA\n");
- +#else
- + ehci_writel(ehci, 0, &ehci->regs->segment);
- #endif
- }
-
- diff -Nur linux-3.14.35.orig/drivers/usb/host/ehci-hub.c linux-3.14.35/drivers/usb/host/ehci-hub.c
- --- linux-3.14.35.orig/drivers/usb/host/ehci-hub.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/host/ehci-hub.c 2015-03-08 14:27:37.781684499 -0500
- @@ -313,6 +313,15 @@
- USB_PORT_STAT_HIGH_SPEED)
- fs_idle_delay = true;
- ehci_writel(ehci, t2, reg);
- + if ((t2 & PORT_WKDISC_E)
- + && (ehci_port_speed(ehci, t2) ==
- + USB_PORT_STAT_HIGH_SPEED))
- + /*
- + * If the high-speed device has not switched
- + * to full-speed idle before WKDISC_E has
- + * effected, there will be a WKDISC event.
- + */
- + mdelay(4);
- changed = 1;
- }
- }
- diff -Nur linux-3.14.35.orig/drivers/usb/host/Kconfig linux-3.14.35/drivers/usb/host/Kconfig
- --- linux-3.14.35.orig/drivers/usb/host/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/host/Kconfig 2015-03-08 14:27:37.781684499 -0500
- @@ -158,6 +158,13 @@
- Enables support for the on-chip EHCI controller on
- ST SPEAr chips.
-
- +config USB_EHCI_HCD_SYNOPSYS
- + tristate "Support for Synopsys Host-AHB USB 2.0 controller"
- + depends on USB_EHCI_HCD && USB_PHY
- + ---help---
- + Enable support for onchip USB controllers based on DesignWare USB 2.0
- + Host-AHB Controller IP from Synopsys.
- +
- config USB_EHCI_HCD_AT91
- tristate "Support for Atmel on-chip EHCI USB controller"
- depends on USB_EHCI_HCD && ARCH_AT91
- diff -Nur linux-3.14.35.orig/drivers/usb/host/Makefile linux-3.14.35/drivers/usb/host/Makefile
- --- linux-3.14.35.orig/drivers/usb/host/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/host/Makefile 2015-03-08 14:27:37.781684499 -0500
- @@ -33,6 +33,8 @@
- obj-$(CONFIG_USB_EHCI_HCD_ORION) += ehci-orion.o
- obj-$(CONFIG_USB_EHCI_HCD_SPEAR) += ehci-spear.o
- obj-$(CONFIG_USB_EHCI_EXYNOS) += ehci-exynos.o
- +obj-$(CONFIG_USB_EHCI_S5P) += ehci-s5p.o
- +obj-$(CONFIG_USB_EHCI_HCD_SYNOPSYS) += ehci-h20ahb.o
- obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
- obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o
- obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o
- diff -Nur linux-3.14.35.orig/drivers/usb/phy/Kconfig linux-3.14.35/drivers/usb/phy/Kconfig
- --- linux-3.14.35.orig/drivers/usb/phy/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/phy/Kconfig 2015-03-08 14:27:37.781684499 -0500
- @@ -253,7 +253,7 @@
-
- config USB_ULPI
- bool "Generic ULPI Transceiver Driver"
- - depends on ARM
- + depends on ARM || ARM64
- help
- Enable this to support ULPI connected USB OTG transceivers which
- are likely found on embedded boards.
- diff -Nur linux-3.14.35.orig/drivers/usb/phy/phy-mxs-usb.c linux-3.14.35/drivers/usb/phy/phy-mxs-usb.c
- --- linux-3.14.35.orig/drivers/usb/phy/phy-mxs-usb.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/phy/phy-mxs-usb.c 2015-03-08 14:27:37.781684499 -0500
- @@ -1,5 +1,5 @@
- /*
- - * Copyright 2012 Freescale Semiconductor, Inc.
- + * Copyright 2012-2013 Freescale Semiconductor, Inc.
- * Copyright (C) 2012 Marek Vasut <marex@denx.de>
- * on behalf of DENX Software Engineering GmbH
- *
- @@ -20,6 +20,9 @@
- #include <linux/delay.h>
- #include <linux/err.h>
- #include <linux/io.h>
- +#include <linux/of_device.h>
- +#include <linux/regmap.h>
- +#include <linux/mfd/syscon.h>
-
- #define DRIVER_NAME "mxs_phy"
-
- @@ -28,18 +31,137 @@
- #define HW_USBPHY_CTRL_SET 0x34
- #define HW_USBPHY_CTRL_CLR 0x38
-
- +#define HW_USBPHY_DEBUG_SET 0x54
- +#define HW_USBPHY_DEBUG_CLR 0x58
- +
- +#define HW_USBPHY_IP 0x90
- +#define HW_USBPHY_IP_SET 0x94
- +#define HW_USBPHY_IP_CLR 0x98
- +
- #define BM_USBPHY_CTRL_SFTRST BIT(31)
- #define BM_USBPHY_CTRL_CLKGATE BIT(30)
- +#define BM_USBPHY_CTRL_ENAUTOSET_USBCLKS BIT(26)
- +#define BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE BIT(25)
- +#define BM_USBPHY_CTRL_ENVBUSCHG_WKUP BIT(23)
- +#define BM_USBPHY_CTRL_ENIDCHG_WKUP BIT(22)
- +#define BM_USBPHY_CTRL_ENDPDMCHG_WKUP BIT(21)
- +#define BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD BIT(20)
- +#define BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE BIT(19)
- +#define BM_USBPHY_CTRL_ENAUTO_PWRON_PLL BIT(18)
- #define BM_USBPHY_CTRL_ENUTMILEVEL3 BIT(15)
- #define BM_USBPHY_CTRL_ENUTMILEVEL2 BIT(14)
- #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT BIT(1)
-
- +#define BM_USBPHY_IP_FIX (BIT(17) | BIT(18))
- +
- +#define BM_USBPHY_DEBUG_CLKGATE BIT(30)
- +
- +/* Anatop Registers */
- +#define ANADIG_ANA_MISC0 0x150
- +#define ANADIG_ANA_MISC0_SET 0x154
- +#define ANADIG_ANA_MISC0_CLR 0x158
- +
- +#define ANADIG_USB1_VBUS_DET_STAT 0x1c0
- +#define ANADIG_USB2_VBUS_DET_STAT 0x220
- +
- +#define ANADIG_USB1_LOOPBACK_SET 0x1e4
- +#define ANADIG_USB1_LOOPBACK_CLR 0x1e8
- +#define ANADIG_USB2_LOOPBACK_SET 0x244
- +#define ANADIG_USB2_LOOPBACK_CLR 0x248
- +
- +#define ANADIG_USB1_MISC 0x1f0
- +#define ANADIG_USB2_MISC 0x250
- +
- +#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG BIT(12)
- +#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG_SL BIT(11)
- +
- +#define BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID BIT(3)
- +#define BM_ANADIG_USB2_VBUS_DET_STAT_VBUS_VALID BIT(3)
- +
- +#define BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST1 BIT(2)
- +#define BM_ANADIG_USB1_LOOPBACK_TSTI_TX_EN BIT(5)
- +#define BM_ANADIG_USB2_LOOPBACK_UTMI_DIG_TST1 BIT(2)
- +#define BM_ANADIG_USB2_LOOPBACK_TSTI_TX_EN BIT(5)
- +
- +#define BM_ANADIG_USB1_MISC_RX_VPIN_FS BIT(29)
- +#define BM_ANADIG_USB1_MISC_RX_VMIN_FS BIT(28)
- +#define BM_ANADIG_USB2_MISC_RX_VPIN_FS BIT(29)
- +#define BM_ANADIG_USB2_MISC_RX_VMIN_FS BIT(28)
- +
- +#define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
- +
- +/* Do disconnection between PHY and controller without vbus */
- +#define MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS BIT(0)
- +
- +/*
- + * The PHY will be in messy if there is an wakeup after putting
- + * bus to suspend (set portsc.suspendM) but before setting PHY to low
- + * power mode (set portsc.phcd).
- + */
- +#define MXS_PHY_ABNORAML_IN_SUSPEND BIT(1)
- +
- +/*
- + * The SOF sends too fast after resuming, it will cause disconnection
- + * between host and high speed device.
- + */
- +#define MXS_PHY_SENDING_SOF_TOO_FAST BIT(2)
- +
- +/* The SoCs who have anatop module */
- +#define MXS_PHY_HAS_ANATOP BIT(3)
- +
- +struct mxs_phy_data {
- + unsigned int flags;
- +};
- +
- +static const struct mxs_phy_data imx23_phy_data = {
- + .flags = MXS_PHY_ABNORAML_IN_SUSPEND | MXS_PHY_SENDING_SOF_TOO_FAST,
- +};
- +
- +static const struct mxs_phy_data imx6q_phy_data = {
- + .flags = MXS_PHY_SENDING_SOF_TOO_FAST |
- + MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
- + MXS_PHY_HAS_ANATOP,
- +};
- +
- +static const struct mxs_phy_data imx6sl_phy_data = {
- + .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
- + MXS_PHY_HAS_ANATOP,
- +};
- +
- +static const struct of_device_id mxs_phy_dt_ids[] = {
- + { .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, },
- + { .compatible = "fsl,imx6q-usbphy", .data = &imx6q_phy_data, },
- + { .compatible = "fsl,imx23-usbphy", .data = &imx23_phy_data, },
- + { /* sentinel */ }
- +};
- +MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids);
- +
- struct mxs_phy {
- struct usb_phy phy;
- struct clk *clk;
- + const struct mxs_phy_data *data;
- + struct regmap *regmap_anatop;
- + int port_id;
- };
-
- -#define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
- +static inline bool is_imx6q_phy(struct mxs_phy *mxs_phy)
- +{
- + return mxs_phy->data == &imx6q_phy_data;
- +}
- +
- +static inline bool is_imx6sl_phy(struct mxs_phy *mxs_phy)
- +{
- + return mxs_phy->data == &imx6sl_phy_data;
- +}
- +
- +/*
- + * PHY needs some 32K cycles to switch from 32K clock to
- + * bus (such as AHB/AXI, etc) clock.
- + */
- +static void mxs_phy_clock_switch(void)
- +{
- + usleep_range(300, 400);
- +}
-
- static int mxs_phy_hw_init(struct mxs_phy *mxs_phy)
- {
- @@ -53,19 +175,122 @@
- /* Power up the PHY */
- writel(0, base + HW_USBPHY_PWD);
-
- - /* enable FS/LS device */
- - writel(BM_USBPHY_CTRL_ENUTMILEVEL2 |
- - BM_USBPHY_CTRL_ENUTMILEVEL3,
- + /*
- + * USB PHY Ctrl Setting
- + * - Auto clock/power on
- + * - Enable full/low speed support
- + */
- + writel(BM_USBPHY_CTRL_ENAUTOSET_USBCLKS |
- + BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE |
- + BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD |
- + BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE |
- + BM_USBPHY_CTRL_ENAUTO_PWRON_PLL |
- + BM_USBPHY_CTRL_ENUTMILEVEL2 |
- + BM_USBPHY_CTRL_ENUTMILEVEL3,
- base + HW_USBPHY_CTRL_SET);
-
- + /* Enable IC solution */
- + if (is_imx6q_phy(mxs_phy) || is_imx6sl_phy(mxs_phy))
- + writel(BM_USBPHY_IP_FIX, base + HW_USBPHY_IP_SET);
- +
- return 0;
- }
-
- +/* Return true if the vbus is there */
- +static bool mxs_phy_get_vbus_status(struct mxs_phy *mxs_phy)
- +{
- + unsigned int vbus_value;
- +
- + if (mxs_phy->port_id == 0)
- + regmap_read(mxs_phy->regmap_anatop,
- + ANADIG_USB1_VBUS_DET_STAT,
- + &vbus_value);
- + else if (mxs_phy->port_id == 1)
- + regmap_read(mxs_phy->regmap_anatop,
- + ANADIG_USB2_VBUS_DET_STAT,
- + &vbus_value);
- +
- + if (vbus_value & BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID)
- + return true;
- + else
- + return false;
- +}
- +
- +static void __mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool disconnect)
- +{
- + void __iomem *base = mxs_phy->phy.io_priv;
- + u32 reg;
- +
- + if (disconnect)
- + writel_relaxed(BM_USBPHY_DEBUG_CLKGATE,
- + base + HW_USBPHY_DEBUG_CLR);
- +
- + if (mxs_phy->port_id == 0) {
- + reg = disconnect ? ANADIG_USB1_LOOPBACK_SET
- + : ANADIG_USB1_LOOPBACK_CLR;
- + regmap_write(mxs_phy->regmap_anatop, reg,
- + BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST1 |
- + BM_ANADIG_USB1_LOOPBACK_TSTI_TX_EN);
- + } else if (mxs_phy->port_id == 1) {
- + reg = disconnect ? ANADIG_USB2_LOOPBACK_SET
- + : ANADIG_USB2_LOOPBACK_CLR;
- + regmap_write(mxs_phy->regmap_anatop, reg,
- + BM_ANADIG_USB2_LOOPBACK_UTMI_DIG_TST1 |
- + BM_ANADIG_USB2_LOOPBACK_TSTI_TX_EN);
- + }
- +
- + if (!disconnect)
- + writel_relaxed(BM_USBPHY_DEBUG_CLKGATE,
- + base + HW_USBPHY_DEBUG_SET);
- +
- + /* Delay some time, and let Linestate be SE0 for controller */
- + if (disconnect)
- + usleep_range(500, 1000);
- +}
- +
- +static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on)
- +{
- + bool vbus_is_on = false;
- +
- + /* If the SoCs don't need to disconnect line without vbus, quit */
- + if (!(mxs_phy->data->flags & MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS))
- + return;
- +
- + /* If the SoCs don't have anatop, quit */
- + if (!mxs_phy->regmap_anatop)
- + return;
- +
- + vbus_is_on = mxs_phy_get_vbus_status(mxs_phy);
- +
- + if (on && !vbus_is_on)
- + __mxs_phy_disconnect_line(mxs_phy, true);
- + else
- + __mxs_phy_disconnect_line(mxs_phy, false);
- +
- +}
- +
- +static void mxs_phy_enable_ldo_in_suspend(struct mxs_phy *mxs_phy, bool on)
- +{
- + unsigned int reg = on ? ANADIG_ANA_MISC0_SET : ANADIG_ANA_MISC0_CLR;
- +
- + /* If the SoCs don't have anatop, quit */
- + if (!mxs_phy->regmap_anatop)
- + return;
- +
- + if (is_imx6q_phy(mxs_phy))
- + regmap_write(mxs_phy->regmap_anatop, reg,
- + BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG);
- + else if (is_imx6sl_phy(mxs_phy))
- + regmap_write(mxs_phy->regmap_anatop,
- + reg, BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG_SL);
- +}
- +
- static int mxs_phy_init(struct usb_phy *phy)
- {
- int ret;
- struct mxs_phy *mxs_phy = to_mxs_phy(phy);
-
- + mxs_phy_clock_switch();
- ret = clk_prepare_enable(mxs_phy->clk);
- if (ret)
- return ret;
- @@ -83,17 +308,62 @@
- clk_disable_unprepare(mxs_phy->clk);
- }
-
- +static bool mxs_phy_is_low_speed_connection(struct mxs_phy *mxs_phy)
- +{
- + unsigned int line_state;
- + /* bit definition is the same for all controllers */
- + unsigned int dp_bit = BM_ANADIG_USB1_MISC_RX_VPIN_FS,
- + dm_bit = BM_ANADIG_USB1_MISC_RX_VMIN_FS;
- + unsigned int reg = ANADIG_USB1_MISC;
- +
- + /* If the SoCs don't have anatop, quit */
- + if (!mxs_phy->regmap_anatop)
- + return false;
- +
- + if (mxs_phy->port_id == 0)
- + reg = ANADIG_USB1_MISC;
- + else if (mxs_phy->port_id == 1)
- + reg = ANADIG_USB2_MISC;
- +
- + regmap_read(mxs_phy->regmap_anatop, reg, &line_state);
- +
- + if ((line_state & (dp_bit | dm_bit)) == dm_bit)
- + return true;
- + else
- + return false;
- +}
- +
- static int mxs_phy_suspend(struct usb_phy *x, int suspend)
- {
- int ret;
- struct mxs_phy *mxs_phy = to_mxs_phy(x);
- + bool low_speed_connection, vbus_is_on;
- +
- + low_speed_connection = mxs_phy_is_low_speed_connection(mxs_phy);
- + vbus_is_on = mxs_phy_get_vbus_status(mxs_phy);
-
- if (suspend) {
- writel(0xffffffff, x->io_priv + HW_USBPHY_PWD);
- + /*
- + * FIXME: Do not power down RXPWD1PT1 bit for low speed
- + * connect. The low speed connection will have problem at
- + * very rare cases during usb suspend and resume process.
- + */
- + if (low_speed_connection & vbus_is_on) {
- + /*
- + * If value to be set as pwd value is not 0xffffffff,
- + * several 32Khz cycles are needed.
- + */
- + mxs_phy_clock_switch();
- + writel(0xffbfffff, x->io_priv + HW_USBPHY_PWD);
- + } else {
- + writel(0xffffffff, x->io_priv + HW_USBPHY_PWD);
- + }
- writel(BM_USBPHY_CTRL_CLKGATE,
- x->io_priv + HW_USBPHY_CTRL_SET);
- clk_disable_unprepare(mxs_phy->clk);
- } else {
- + mxs_phy_clock_switch();
- ret = clk_prepare_enable(mxs_phy->clk);
- if (ret)
- return ret;
- @@ -105,11 +375,28 @@
- return 0;
- }
-
- +static int mxs_phy_set_wakeup(struct usb_phy *x, bool enabled)
- +{
- + struct mxs_phy *mxs_phy = to_mxs_phy(x);
- + u32 value = BM_USBPHY_CTRL_ENVBUSCHG_WKUP |
- + BM_USBPHY_CTRL_ENDPDMCHG_WKUP |
- + BM_USBPHY_CTRL_ENIDCHG_WKUP;
- + if (enabled) {
- + mxs_phy_disconnect_line(mxs_phy, true);
- + writel_relaxed(value, x->io_priv + HW_USBPHY_CTRL_SET);
- + } else {
- + writel_relaxed(value, x->io_priv + HW_USBPHY_CTRL_CLR);
- + mxs_phy_disconnect_line(mxs_phy, false);
- + }
- +
- + return 0;
- +}
- +
- static int mxs_phy_on_connect(struct usb_phy *phy,
- enum usb_device_speed speed)
- {
- - dev_dbg(phy->dev, "%s speed device has connected\n",
- - (speed == USB_SPEED_HIGH) ? "high" : "non-high");
- + dev_dbg(phy->dev, "%s device has connected\n",
- + (speed == USB_SPEED_HIGH) ? "HS" : "FS/LS");
-
- if (speed == USB_SPEED_HIGH)
- writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
- @@ -121,8 +408,8 @@
- static int mxs_phy_on_disconnect(struct usb_phy *phy,
- enum usb_device_speed speed)
- {
- - dev_dbg(phy->dev, "%s speed device has disconnected\n",
- - (speed == USB_SPEED_HIGH) ? "high" : "non-high");
- + dev_dbg(phy->dev, "%s device has disconnected\n",
- + (speed == USB_SPEED_HIGH) ? "HS" : "FS/LS");
-
- if (speed == USB_SPEED_HIGH)
- writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
- @@ -131,6 +418,48 @@
- return 0;
- }
-
- +static int mxs_phy_on_suspend(struct usb_phy *phy,
- + enum usb_device_speed speed)
- +{
- + struct mxs_phy *mxs_phy = to_mxs_phy(phy);
- +
- + dev_dbg(phy->dev, "%s device has suspended\n",
- + (speed == USB_SPEED_HIGH) ? "HS" : "FS/LS");
- +
- + /* delay 4ms to wait bus entering idle */
- + usleep_range(4000, 5000);
- +
- + if (mxs_phy->data->flags & MXS_PHY_ABNORAML_IN_SUSPEND) {
- + writel_relaxed(0xffffffff, phy->io_priv + HW_USBPHY_PWD);
- + writel_relaxed(0, phy->io_priv + HW_USBPHY_PWD);
- + }
- +
- + if (speed == USB_SPEED_HIGH)
- + writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
- + phy->io_priv + HW_USBPHY_CTRL_CLR);
- +
- + return 0;
- +}
- +
- +/*
- + * The resume signal must be finished here.
- + */
- +static int mxs_phy_on_resume(struct usb_phy *phy,
- + enum usb_device_speed speed)
- +{
- + dev_dbg(phy->dev, "%s device has resumed\n",
- + (speed == USB_SPEED_HIGH) ? "HS" : "FS/LS");
- +
- + if (speed == USB_SPEED_HIGH) {
- + /* Make sure the device has switched to High-Speed mode */
- + udelay(500);
- + writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
- + phy->io_priv + HW_USBPHY_CTRL_SET);
- + }
- +
- + return 0;
- +}
- +
- static int mxs_phy_probe(struct platform_device *pdev)
- {
- struct resource *res;
- @@ -138,6 +467,9 @@
- struct clk *clk;
- struct mxs_phy *mxs_phy;
- int ret;
- + const struct of_device_id *of_id =
- + of_match_device(mxs_phy_dt_ids, &pdev->dev);
- + struct device_node *np = pdev->dev.of_node;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(&pdev->dev, res);
- @@ -157,6 +489,13 @@
- return -ENOMEM;
- }
-
- + ret = of_alias_get_id(np, "usbphy");
- + if (ret < 0) {
- + dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
- + return ret;
- + }
- + mxs_phy->port_id = ret;
- +
- mxs_phy->phy.io_priv = base;
- mxs_phy->phy.dev = &pdev->dev;
- mxs_phy->phy.label = DRIVER_NAME;
- @@ -166,11 +505,30 @@
- mxs_phy->phy.notify_connect = mxs_phy_on_connect;
- mxs_phy->phy.notify_disconnect = mxs_phy_on_disconnect;
- mxs_phy->phy.type = USB_PHY_TYPE_USB2;
- + mxs_phy->phy.set_wakeup = mxs_phy_set_wakeup;
-
- mxs_phy->clk = clk;
- + mxs_phy->data = of_id->data;
- +
- + if (mxs_phy->data->flags & MXS_PHY_SENDING_SOF_TOO_FAST) {
- + mxs_phy->phy.notify_suspend = mxs_phy_on_suspend;
- + mxs_phy->phy.notify_resume = mxs_phy_on_resume;
- + }
-
- platform_set_drvdata(pdev, mxs_phy);
-
- + if (mxs_phy->data->flags & MXS_PHY_HAS_ANATOP) {
- + mxs_phy->regmap_anatop = syscon_regmap_lookup_by_phandle
- + (np, "fsl,anatop");
- + if (IS_ERR(mxs_phy->regmap_anatop)) {
- + dev_dbg(&pdev->dev,
- + "failed to find regmap for anatop\n");
- + return PTR_ERR(mxs_phy->regmap_anatop);
- + }
- + }
- +
- + device_set_wakeup_capable(&pdev->dev, true);
- +
- ret = usb_add_phy_dev(&mxs_phy->phy);
- if (ret)
- return ret;
- @@ -187,11 +545,27 @@
- return 0;
- }
-
- -static const struct of_device_id mxs_phy_dt_ids[] = {
- - { .compatible = "fsl,imx23-usbphy", },
- - { /* sentinel */ }
- -};
- -MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids);
- +static int mxs_phy_system_suspend(struct device *dev)
- +{
- + struct mxs_phy *mxs_phy = dev_get_drvdata(dev);
- +
- + if (device_may_wakeup(dev))
- + mxs_phy_enable_ldo_in_suspend(mxs_phy, true);
- +
- + return 0;
- +}
- +
- +static int mxs_phy_system_resume(struct device *dev)
- +{
- + struct mxs_phy *mxs_phy = dev_get_drvdata(dev);
- +
- + if (device_may_wakeup(dev))
- + mxs_phy_enable_ldo_in_suspend(mxs_phy, false);
- +
- + return 0;
- +}
- +
- +SIMPLE_DEV_PM_OPS(mxs_phy_pm, mxs_phy_system_suspend, mxs_phy_system_resume);
-
- static struct platform_driver mxs_phy_driver = {
- .probe = mxs_phy_probe,
- @@ -200,6 +574,7 @@
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
- .of_match_table = mxs_phy_dt_ids,
- + .pm = &mxs_phy_pm,
- },
- };
-
- diff -Nur linux-3.14.35.orig/drivers/usb/phy/phy-ulpi.c linux-3.14.35/drivers/usb/phy/phy-ulpi.c
- --- linux-3.14.35.orig/drivers/usb/phy/phy-ulpi.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/usb/phy/phy-ulpi.c 2015-03-08 14:27:37.781684499 -0500
- @@ -48,6 +48,7 @@
- ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"),
- ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"),
- ULPI_INFO(ULPI_ID(0x0424, 0x0007), "SMSC USB3320"),
- + ULPI_INFO(ULPI_ID(0x0424, 0x0009), "SMSC USB334x"),
- ULPI_INFO(ULPI_ID(0x0451, 0x1507), "TI TUSB1210"),
- };
-
- diff -Nur linux-3.14.35.orig/drivers/video/amba-clcd.c linux-3.14.35/drivers/video/amba-clcd.c
- --- linux-3.14.35.orig/drivers/video/amba-clcd.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/video/amba-clcd.c 2015-03-08 14:27:37.781684499 -0500
- @@ -17,7 +17,10 @@
- #include <linux/string.h>
- #include <linux/slab.h>
- #include <linux/delay.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/memblock.h>
- #include <linux/mm.h>
- +#include <linux/of.h>
- #include <linux/fb.h>
- #include <linux/init.h>
- #include <linux/ioport.h>
- @@ -31,8 +34,20 @@
-
- #define to_clcd(info) container_of(info, struct clcd_fb, fb)
-
- +#ifdef CONFIG_ARM
- +#define clcdfb_dma_alloc dma_alloc_writecombine
- +#define clcdfb_dma_free dma_free_writecombine
- +#define clcdfb_dma_mmap dma_mmap_writecombine
- +#else
- +#define clcdfb_dma_alloc dma_alloc_coherent
- +#define clcdfb_dma_free dma_free_coherent
- +#define clcdfb_dma_mmap dma_mmap_coherent
- +#endif
- +
- /* This is limited to 16 characters when displayed by X startup */
- static const char *clcd_name = "CLCD FB";
- +static char *def_mode;
- +module_param_named(mode, def_mode, charp, 0);
-
- /*
- * Unfortunately, the enable/disable functions may be called either from
- @@ -234,6 +249,17 @@
- bgr = caps & CLCD_CAP_BGR && var->blue.offset == 0;
- rgb = caps & CLCD_CAP_RGB && var->red.offset == 0;
-
- + /*
- + * Seems that for 32-bit mode there is confusion about RGB
- + * ordering somewhere between user-side, kernel and hardware.
- + * The following hack seems get things working, at least on
- + * vexpress hardware and models...
- + */
- + if (var->bits_per_pixel == 32) {
- + bgr = false;
- + rgb = true;
- + }
- +
- if (!bgr && !rgb)
- /*
- * The requested format was not possible, try just
- @@ -393,6 +419,44 @@
- return 0;
- }
-
- +int clcdfb_mmap_dma(struct clcd_fb *fb, struct vm_area_struct *vma)
- +{
- + return clcdfb_dma_mmap(&fb->dev->dev, vma,
- + fb->fb.screen_base,
- + fb->fb.fix.smem_start,
- + fb->fb.fix.smem_len);
- +}
- +
- +int clcdfb_mmap_io(struct clcd_fb *fb, struct vm_area_struct *vma)
- +{
- + unsigned long user_count, count, pfn, off;
- +
- + user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
- + count = PAGE_ALIGN(fb->fb.fix.smem_len) >> PAGE_SHIFT;
- + pfn = fb->fb.fix.smem_start >> PAGE_SHIFT;
- + off = vma->vm_pgoff;
- +
- + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- +
- + if (off < count && user_count <= (count - off))
- + return remap_pfn_range(vma, vma->vm_start, pfn + off,
- + user_count << PAGE_SHIFT,
- + vma->vm_page_prot);
- +
- + return -ENXIO;
- +}
- +
- +void clcdfb_remove_dma(struct clcd_fb *fb)
- +{
- + clcdfb_dma_free(&fb->dev->dev, fb->fb.fix.smem_len,
- + fb->fb.screen_base, fb->fb.fix.smem_start);
- +}
- +
- +void clcdfb_remove_io(struct clcd_fb *fb)
- +{
- + iounmap(fb->fb.screen_base);
- +}
- +
- static int clcdfb_mmap(struct fb_info *info,
- struct vm_area_struct *vma)
- {
- @@ -543,14 +607,247 @@
- return ret;
- }
-
- +struct string_lookup {
- + const char *string;
- + const u32 val;
- +};
- +
- +static struct string_lookup vmode_lookups[] = {
- + { "FB_VMODE_NONINTERLACED", FB_VMODE_NONINTERLACED},
- + { "FB_VMODE_INTERLACED", FB_VMODE_INTERLACED},
- + { "FB_VMODE_DOUBLE", FB_VMODE_DOUBLE},
- + { "FB_VMODE_ODD_FLD_FIRST", FB_VMODE_ODD_FLD_FIRST},
- + { NULL, 0 },
- +};
- +
- +static struct string_lookup tim2_lookups[] = {
- + { "TIM2_CLKSEL", TIM2_CLKSEL},
- + { "TIM2_IVS", TIM2_IVS},
- + { "TIM2_IHS", TIM2_IHS},
- + { "TIM2_IPC", TIM2_IPC},
- + { "TIM2_IOE", TIM2_IOE},
- + { "TIM2_BCD", TIM2_BCD},
- + { NULL, 0},
- +};
- +static struct string_lookup cntl_lookups[] = {
- + {"CNTL_LCDEN", CNTL_LCDEN},
- + {"CNTL_LCDBPP1", CNTL_LCDBPP1},
- + {"CNTL_LCDBPP2", CNTL_LCDBPP2},
- + {"CNTL_LCDBPP4", CNTL_LCDBPP4},
- + {"CNTL_LCDBPP8", CNTL_LCDBPP8},
- + {"CNTL_LCDBPP16", CNTL_LCDBPP16},
- + {"CNTL_LCDBPP16_565", CNTL_LCDBPP16_565},
- + {"CNTL_LCDBPP16_444", CNTL_LCDBPP16_444},
- + {"CNTL_LCDBPP24", CNTL_LCDBPP24},
- + {"CNTL_LCDBW", CNTL_LCDBW},
- + {"CNTL_LCDTFT", CNTL_LCDTFT},
- + {"CNTL_LCDMONO8", CNTL_LCDMONO8},
- + {"CNTL_LCDDUAL", CNTL_LCDDUAL},
- + {"CNTL_BGR", CNTL_BGR},
- + {"CNTL_BEBO", CNTL_BEBO},
- + {"CNTL_BEPO", CNTL_BEPO},
- + {"CNTL_LCDPWR", CNTL_LCDPWR},
- + {"CNTL_LCDVCOMP(1)", CNTL_LCDVCOMP(1)},
- + {"CNTL_LCDVCOMP(2)", CNTL_LCDVCOMP(2)},
- + {"CNTL_LCDVCOMP(3)", CNTL_LCDVCOMP(3)},
- + {"CNTL_LCDVCOMP(4)", CNTL_LCDVCOMP(4)},
- + {"CNTL_LCDVCOMP(5)", CNTL_LCDVCOMP(5)},
- + {"CNTL_LCDVCOMP(6)", CNTL_LCDVCOMP(6)},
- + {"CNTL_LCDVCOMP(7)", CNTL_LCDVCOMP(7)},
- + {"CNTL_LDMAFIFOTIME", CNTL_LDMAFIFOTIME},
- + {"CNTL_WATERMARK", CNTL_WATERMARK},
- + { NULL, 0},
- +};
- +static struct string_lookup caps_lookups[] = {
- + {"CLCD_CAP_RGB444", CLCD_CAP_RGB444},
- + {"CLCD_CAP_RGB5551", CLCD_CAP_RGB5551},
- + {"CLCD_CAP_RGB565", CLCD_CAP_RGB565},
- + {"CLCD_CAP_RGB888", CLCD_CAP_RGB888},
- + {"CLCD_CAP_BGR444", CLCD_CAP_BGR444},
- + {"CLCD_CAP_BGR5551", CLCD_CAP_BGR5551},
- + {"CLCD_CAP_BGR565", CLCD_CAP_BGR565},
- + {"CLCD_CAP_BGR888", CLCD_CAP_BGR888},
- + {"CLCD_CAP_444", CLCD_CAP_444},
- + {"CLCD_CAP_5551", CLCD_CAP_5551},
- + {"CLCD_CAP_565", CLCD_CAP_565},
- + {"CLCD_CAP_888", CLCD_CAP_888},
- + {"CLCD_CAP_RGB", CLCD_CAP_RGB},
- + {"CLCD_CAP_BGR", CLCD_CAP_BGR},
- + {"CLCD_CAP_ALL", CLCD_CAP_ALL},
- + { NULL, 0},
- +};
- +
- +u32 parse_setting(struct string_lookup *lookup, const char *name)
- +{
- + int i = 0;
- + while (lookup[i].string != NULL) {
- + if (strcmp(lookup[i].string, name) == 0)
- + return lookup[i].val;
- + ++i;
- + }
- + return -EINVAL;
- +}
- +
- +u32 get_string_lookup(struct device_node *node, const char *name,
- + struct string_lookup *lookup)
- +{
- + const char *string;
- + int count, i, ret = 0;
- +
- + count = of_property_count_strings(node, name);
- + if (count >= 0)
- + for (i = 0; i < count; i++)
- + if (of_property_read_string_index(node, name, i,
- + &string) == 0)
- + ret |= parse_setting(lookup, string);
- + return ret;
- +}
- +
- +int get_val(struct device_node *node, const char *string)
- +{
- + u32 ret = 0;
- +
- + if (of_property_read_u32(node, string, &ret))
- + ret = -1;
- + return ret;
- +}
- +
- +struct clcd_panel *getPanel(struct device_node *node)
- +{
- + static struct clcd_panel panel;
- +
- + panel.mode.refresh = get_val(node, "refresh");
- + panel.mode.xres = get_val(node, "xres");
- + panel.mode.yres = get_val(node, "yres");
- + panel.mode.pixclock = get_val(node, "pixclock");
- + panel.mode.left_margin = get_val(node, "left_margin");
- + panel.mode.right_margin = get_val(node, "right_margin");
- + panel.mode.upper_margin = get_val(node, "upper_margin");
- + panel.mode.lower_margin = get_val(node, "lower_margin");
- + panel.mode.hsync_len = get_val(node, "hsync_len");
- + panel.mode.vsync_len = get_val(node, "vsync_len");
- + panel.mode.sync = get_val(node, "sync");
- + panel.bpp = get_val(node, "bpp");
- + panel.width = (signed short) get_val(node, "width");
- + panel.height = (signed short) get_val(node, "height");
- +
- + panel.mode.vmode = get_string_lookup(node, "vmode", vmode_lookups);
- + panel.tim2 = get_string_lookup(node, "tim2", tim2_lookups);
- + panel.cntl = get_string_lookup(node, "cntl", cntl_lookups);
- + panel.caps = get_string_lookup(node, "caps", caps_lookups);
- +
- + return &panel;
- +}
- +
- +struct clcd_panel *clcdfb_get_panel(const char *name)
- +{
- + struct device_node *node = NULL;
- + const char *mode;
- + struct clcd_panel *panel = NULL;
- +
- + do {
- + node = of_find_compatible_node(node, NULL, "panel");
- + if (node)
- + if (of_property_read_string(node, "mode", &mode) == 0)
- + if (strcmp(mode, name) == 0) {
- + panel = getPanel(node);
- + panel->mode.name = name;
- + }
- + } while (node != NULL);
- +
- + return panel;
- +}
- +
- +#ifdef CONFIG_OF
- +static int clcdfb_dt_init(struct clcd_fb *fb)
- +{
- + int err = 0;
- + struct device_node *node;
- + const char *mode;
- + dma_addr_t dma;
- + u32 use_dma;
- + const __be32 *prop;
- + int len, na, ns;
- + phys_addr_t fb_base, fb_size;
- +
- + node = fb->dev->dev.of_node;
- + if (!node)
- + return -ENODEV;
- +
- + na = of_n_addr_cells(node);
- + ns = of_n_size_cells(node);
- +
- + if (def_mode && strlen(def_mode) > 0) {
- + fb->panel = clcdfb_get_panel(def_mode);
- + if (!fb->panel)
- + printk(KERN_ERR "CLCD: invalid mode specified on the command line (%s)\n", def_mode);
- + }
- +
- + if (!fb->panel) {
- + if (WARN_ON(of_property_read_string(node, "mode", &mode)))
- + return -ENODEV;
- + fb->panel = clcdfb_get_panel(mode);
- + }
- +
- + if (!fb->panel)
- + return -EINVAL;
- + fb->fb.fix.smem_len = fb->panel->mode.xres * fb->panel->mode.yres * 4;
- +
- + fb->board->name = "Device Tree CLCD PL111";
- + fb->board->caps = CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888;
- + fb->board->check = clcdfb_check;
- + fb->board->decode = clcdfb_decode;
- +
- + if (of_property_read_u32(node, "use_dma", &use_dma))
- + use_dma = 0;
- +
- + if (use_dma) {
- + fb->fb.screen_base = clcdfb_dma_alloc(&fb->dev->dev,
- + fb->fb.fix.smem_len,
- + &dma, GFP_KERNEL);
- + if (!fb->fb.screen_base) {
- + pr_err("CLCD: unable to map framebuffer\n");
- + return -ENOMEM;
- + }
- +
- + fb->fb.fix.smem_start = dma;
- + fb->board->mmap = clcdfb_mmap_dma;
- + fb->board->remove = clcdfb_remove_dma;
- + } else {
- + prop = of_get_property(node, "framebuffer", &len);
- + if (WARN_ON(!prop || len < (na + ns) * sizeof(*prop)))
- + return -EINVAL;
- +
- + fb_base = of_read_number(prop, na);
- + fb_size = of_read_number(prop + na, ns);
- +
- + fb->fb.fix.smem_start = fb_base;
- + fb->fb.screen_base = ioremap_wc(fb_base, fb_size);
- + fb->board->mmap = clcdfb_mmap_io;
- + fb->board->remove = clcdfb_remove_io;
- + }
- +
- + return err;
- +}
- +#endif /* CONFIG_OF */
- +
- static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
- {
- struct clcd_board *board = dev_get_platdata(&dev->dev);
- struct clcd_fb *fb;
- int ret;
-
- - if (!board)
- - return -EINVAL;
- + if (!board) {
- +#ifdef CONFIG_OF
- + if (dev->dev.of_node) {
- + board = kzalloc(sizeof(struct clcd_board), GFP_KERNEL);
- + if (!board)
- + return -ENOMEM;
- + board->setup = clcdfb_dt_init;
- + } else
- +#endif
- + return -EINVAL;
- + }
-
- ret = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
- if (ret)
- diff -Nur linux-3.14.35.orig/drivers/video/arm-hdlcd.c linux-3.14.35/drivers/video/arm-hdlcd.c
- --- linux-3.14.35.orig/drivers/video/arm-hdlcd.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/video/arm-hdlcd.c 2015-03-08 14:27:37.781684499 -0500
- @@ -0,0 +1,844 @@
- +/*
- + * drivers/video/arm-hdlcd.c
- + *
- + * Copyright (C) 2011 ARM Limited
- + *
- + * This file is subject to the terms and conditions of the GNU General Public
- + * License. See the file COPYING in the main directory of this archive
- + * for more details.
- + *
- + * ARM HDLCD Controller
- + */
- +
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/errno.h>
- +#include <linux/string.h>
- +#include <linux/ctype.h>
- +#include <linux/mm.h>
- +#include <linux/delay.h>
- +#include <linux/of.h>
- +#include <linux/fb.h>
- +#include <linux/clk.h>
- +#include <linux/init.h>
- +#include <linux/interrupt.h>
- +#include <linux/ioport.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/platform_device.h>
- +#include <linux/memblock.h>
- +#include <linux/arm-hdlcd.h>
- +#ifdef HDLCD_COUNT_BUFFERUNDERRUNS
- +#include <linux/proc_fs.h>
- +#include <linux/seq_file.h>
- +#endif
- +
- +#include "edid.h"
- +
- +#ifdef CONFIG_SERIAL_AMBA_PCU_UART
- +int get_edid(u8 *msgbuf);
- +#else
- +#endif
- +
- +#define to_hdlcd_device(info) container_of(info, struct hdlcd_device, fb)
- +
- +static struct of_device_id hdlcd_of_matches[] = {
- + { .compatible = "arm,hdlcd" },
- + {},
- +};
- +
- +/* Framebuffer size. */
- +static unsigned long framebuffer_size;
- +
- +#ifdef HDLCD_COUNT_BUFFERUNDERRUNS
- +static unsigned long buffer_underrun_events;
- +static DEFINE_SPINLOCK(hdlcd_underrun_lock);
- +
- +static void hdlcd_underrun_set(unsigned long val)
- +{
- + spin_lock(&hdlcd_underrun_lock);
- + buffer_underrun_events = val;
- + spin_unlock(&hdlcd_underrun_lock);
- +}
- +
- +static unsigned long hdlcd_underrun_get(void)
- +{
- + unsigned long val;
- + spin_lock(&hdlcd_underrun_lock);
- + val = buffer_underrun_events;
- + spin_unlock(&hdlcd_underrun_lock);
- + return val;
- +}
- +
- +#ifdef CONFIG_PROC_FS
- +static int hdlcd_underrun_show(struct seq_file *m, void *v)
- +{
- + unsigned char underrun_string[32];
- + snprintf(underrun_string, 32, "%lu\n", hdlcd_underrun_get());
- + seq_puts(m, underrun_string);
- + return 0;
- +}
- +
- +static int proc_hdlcd_underrun_open(struct inode *inode, struct file *file)
- +{
- + return single_open(file, hdlcd_underrun_show, NULL);
- +}
- +
- +static const struct file_operations proc_hdlcd_underrun_operations = {
- + .open = proc_hdlcd_underrun_open,
- + .read = seq_read,
- + .llseek = seq_lseek,
- + .release = single_release,
- +};
- +
- +static int hdlcd_underrun_init(void)
- +{
- + hdlcd_underrun_set(0);
- + proc_create("hdlcd_underrun", 0, NULL, &proc_hdlcd_underrun_operations);
- + return 0;
- +}
- +static void hdlcd_underrun_close(void)
- +{
- + remove_proc_entry("hdlcd_underrun", NULL);
- +}
- +#else
- +static int hdlcd_underrun_init(void) { return 0; }
- +static void hdlcd_underrun_close(void) { }
- +#endif
- +#endif
- +
- +static char *fb_mode = "1680x1050-32@60\0\0\0\0\0";
- +
- +static struct fb_var_screeninfo cached_var_screeninfo;
- +
- +static struct fb_videomode hdlcd_default_mode = {
- + .refresh = 60,
- + .xres = 1680,
- + .yres = 1050,
- + .pixclock = 8403,
- + .left_margin = 80,
- + .right_margin = 48,
- + .upper_margin = 21,
- + .lower_margin = 3,
- + .hsync_len = 32,
- + .vsync_len = 6,
- + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- + .vmode = FB_VMODE_NONINTERLACED
- +};
- +
- +static inline void hdlcd_enable(struct hdlcd_device *hdlcd)
- +{
- + dev_dbg(hdlcd->dev, "HDLCD: output enabled\n");
- + writel(1, hdlcd->base + HDLCD_REG_COMMAND);
- +}
- +
- +static inline void hdlcd_disable(struct hdlcd_device *hdlcd)
- +{
- + dev_dbg(hdlcd->dev, "HDLCD: output disabled\n");
- + writel(0, hdlcd->base + HDLCD_REG_COMMAND);
- +}
- +
- +static int hdlcd_set_bitfields(struct hdlcd_device *hdlcd,
- + struct fb_var_screeninfo *var)
- +{
- + int ret = 0;
- +
- + memset(&var->transp, 0, sizeof(var->transp));
- + var->red.msb_right = 0;
- + var->green.msb_right = 0;
- + var->blue.msb_right = 0;
- + var->blue.offset = 0;
- +
- + switch (var->bits_per_pixel) {
- + case 8:
- + /* pseudocolor */
- + var->red.length = 8;
- + var->green.length = 8;
- + var->blue.length = 8;
- + break;
- + case 16:
- + /* 565 format */
- + var->red.length = 5;
- + var->green.length = 6;
- + var->blue.length = 5;
- + break;
- + case 32:
- + var->transp.length = 8;
- + case 24:
- + var->red.length = 8;
- + var->green.length = 8;
- + var->blue.length = 8;
- + break;
- + default:
- + ret = -EINVAL;
- + break;
- + }
- +
- + if (!ret) {
- + if(var->bits_per_pixel != 32)
- + {
- + var->green.offset = var->blue.length;
- + var->red.offset = var->green.offset + var->green.length;
- + }
- + else
- + {
- + /* Previously, the byte ordering for 32-bit color was
- + * (msb)<alpha><red><green><blue>(lsb)
- + * but this does not match what android expects and
- + * the colors are odd. Instead, use
- + * <alpha><blue><green><red>
- + * Since we tell fb what we are doing, console
- + * , X and directfb access should work fine.
- + */
- + var->green.offset = var->red.length;
- + var->blue.offset = var->green.offset + var->green.length;
- + var->transp.offset = var->blue.offset + var->blue.length;
- + }
- + }
- +
- + return ret;
- +}
- +
- +static int hdlcd_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
- +{
- + struct hdlcd_device *hdlcd = to_hdlcd_device(info);
- + int bytes_per_pixel = var->bits_per_pixel / 8;
- +
- +#ifdef HDLCD_NO_VIRTUAL_SCREEN
- + var->yres_virtual = var->yres;
- +#else
- + var->yres_virtual = 2 * var->yres;
- +#endif
- +
- + if ((var->xres_virtual * bytes_per_pixel * var->yres_virtual) > hdlcd->fb.fix.smem_len)
- + return -ENOMEM;
- +
- + if (var->xres > HDLCD_MAX_XRES || var->yres > HDLCD_MAX_YRES)
- + return -EINVAL;
- +
- + /* make sure the bitfields are set appropriately */
- + return hdlcd_set_bitfields(hdlcd, var);
- +}
- +
- +/* prototype */
- +static int hdlcd_pan_display(struct fb_var_screeninfo *var,
- + struct fb_info *info);
- +
- +#define WRITE_HDLCD_REG(reg, value) writel((value), hdlcd->base + (reg))
- +#define READ_HDLCD_REG(reg) readl(hdlcd->base + (reg))
- +
- +static int hdlcd_set_par(struct fb_info *info)
- +{
- + struct hdlcd_device *hdlcd = to_hdlcd_device(info);
- + int bytes_per_pixel = hdlcd->fb.var.bits_per_pixel / 8;
- + int polarities;
- + int old_yoffset;
- +
- + /* check for shortcuts */
- + old_yoffset = cached_var_screeninfo.yoffset;
- + cached_var_screeninfo.yoffset = info->var.yoffset;
- + if (!memcmp(&info->var, &cached_var_screeninfo,
- + sizeof(struct fb_var_screeninfo))) {
- + if(old_yoffset != info->var.yoffset) {
- + /* we only changed yoffset, and we already
- + * already recorded it a couple lines up
- + */
- + hdlcd_pan_display(&info->var, info);
- + }
- + /* or no change */
- + return 0;
- + }
- +
- + hdlcd->fb.fix.line_length = hdlcd->fb.var.xres * bytes_per_pixel;
- +
- + if (hdlcd->fb.var.bits_per_pixel >= 16)
- + hdlcd->fb.fix.visual = FB_VISUAL_TRUECOLOR;
- + else
- + hdlcd->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
- +
- + memcpy(&cached_var_screeninfo, &info->var, sizeof(struct fb_var_screeninfo));
- +
- + polarities = HDLCD_POLARITY_DATAEN |
- +#ifndef CONFIG_ARCH_TUSCAN
- + HDLCD_POLARITY_PIXELCLK |
- +#endif
- + HDLCD_POLARITY_DATA;
- + polarities |= (hdlcd->fb.var.sync & FB_SYNC_HOR_HIGH_ACT) ? HDLCD_POLARITY_HSYNC : 0;
- + polarities |= (hdlcd->fb.var.sync & FB_SYNC_VERT_HIGH_ACT) ? HDLCD_POLARITY_VSYNC : 0;
- +
- + hdlcd_disable(hdlcd);
- +
- + WRITE_HDLCD_REG(HDLCD_REG_FB_LINE_LENGTH, hdlcd->fb.var.xres * bytes_per_pixel);
- + WRITE_HDLCD_REG(HDLCD_REG_FB_LINE_PITCH, hdlcd->fb.var.xres * bytes_per_pixel);
- + WRITE_HDLCD_REG(HDLCD_REG_FB_LINE_COUNT, hdlcd->fb.var.yres - 1);
- + WRITE_HDLCD_REG(HDLCD_REG_V_SYNC, hdlcd->fb.var.vsync_len - 1);
- + WRITE_HDLCD_REG(HDLCD_REG_V_BACK_PORCH, hdlcd->fb.var.upper_margin - 1);
- + WRITE_HDLCD_REG(HDLCD_REG_V_DATA, hdlcd->fb.var.yres - 1);
- + WRITE_HDLCD_REG(HDLCD_REG_V_FRONT_PORCH, hdlcd->fb.var.lower_margin - 1);
- + WRITE_HDLCD_REG(HDLCD_REG_H_SYNC, hdlcd->fb.var.hsync_len - 1);
- + WRITE_HDLCD_REG(HDLCD_REG_H_BACK_PORCH, hdlcd->fb.var.left_margin - 1);
- + WRITE_HDLCD_REG(HDLCD_REG_H_DATA, hdlcd->fb.var.xres - 1);
- + WRITE_HDLCD_REG(HDLCD_REG_H_FRONT_PORCH, hdlcd->fb.var.right_margin - 1);
- + WRITE_HDLCD_REG(HDLCD_REG_POLARITIES, polarities);
- + WRITE_HDLCD_REG(HDLCD_REG_PIXEL_FORMAT, (bytes_per_pixel - 1) << 3);
- +#ifdef HDLCD_RED_DEFAULT_COLOUR
- + WRITE_HDLCD_REG(HDLCD_REG_RED_SELECT, (0x00ff0000 | (hdlcd->fb.var.red.length & 0xf) << 8) \
- + | hdlcd->fb.var.red.offset);
- +#else
- + WRITE_HDLCD_REG(HDLCD_REG_RED_SELECT, ((hdlcd->fb.var.red.length & 0xf) << 8) | hdlcd->fb.var.red.offset);
- +#endif
- + WRITE_HDLCD_REG(HDLCD_REG_GREEN_SELECT, ((hdlcd->fb.var.green.length & 0xf) << 8) | hdlcd->fb.var.green.offset);
- + WRITE_HDLCD_REG(HDLCD_REG_BLUE_SELECT, ((hdlcd->fb.var.blue.length & 0xf) << 8) | hdlcd->fb.var.blue.offset);
- +
- + clk_set_rate(hdlcd->clk, (1000000000 / hdlcd->fb.var.pixclock) * 1000);
- + clk_enable(hdlcd->clk);
- +
- + hdlcd_enable(hdlcd);
- +
- + return 0;
- +}
- +
- +static int hdlcd_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
- + unsigned int blue, unsigned int transp, struct fb_info *info)
- +{
- + if (regno < 16) {
- + u32 *pal = info->pseudo_palette;
- +
- + pal[regno] = ((red >> 8) << info->var.red.offset) |
- + ((green >> 8) << info->var.green.offset) |
- + ((blue >> 8) << info->var.blue.offset);
- + }
- +
- + return 0;
- +}
- +
- +static irqreturn_t hdlcd_irq(int irq, void *data)
- +{
- + struct hdlcd_device *hdlcd = data;
- + unsigned long irq_mask, irq_status;
- +
- + irq_mask = READ_HDLCD_REG(HDLCD_REG_INT_MASK);
- + irq_status = READ_HDLCD_REG(HDLCD_REG_INT_STATUS);
- +
- + /* acknowledge interrupt(s) */
- + WRITE_HDLCD_REG(HDLCD_REG_INT_CLEAR, irq_status);
- +#ifdef HDLCD_COUNT_BUFFERUNDERRUNS
- + if (irq_status & HDLCD_INTERRUPT_UNDERRUN) {
- + /* increment the count */
- + hdlcd_underrun_set(hdlcd_underrun_get() + 1);
- + }
- +#endif
- + if (irq_status & HDLCD_INTERRUPT_VSYNC) {
- + /* disable future VSYNC interrupts */
- + WRITE_HDLCD_REG(HDLCD_REG_INT_MASK, irq_mask & ~HDLCD_INTERRUPT_VSYNC);
- +
- + complete(&hdlcd->vsync_completion);
- + }
- +
- + return IRQ_HANDLED;
- +}
- +
- +static int hdlcd_wait_for_vsync(struct fb_info *info)
- +{
- + struct hdlcd_device *hdlcd = to_hdlcd_device(info);
- + unsigned long irq_mask;
- + int err;
- +
- + /* enable VSYNC interrupt */
- + irq_mask = READ_HDLCD_REG(HDLCD_REG_INT_MASK);
- + WRITE_HDLCD_REG(HDLCD_REG_INT_MASK, irq_mask | HDLCD_INTERRUPT_VSYNC);
- +
- + err = wait_for_completion_interruptible_timeout(&hdlcd->vsync_completion,
- + msecs_to_jiffies(100));
- +
- + if (!err)
- + return -ETIMEDOUT;
- +
- + return 0;
- +}
- +
- +static int hdlcd_blank(int blank_mode, struct fb_info *info)
- +{
- + struct hdlcd_device *hdlcd = to_hdlcd_device(info);
- +
- + switch (blank_mode) {
- + case FB_BLANK_POWERDOWN:
- + clk_disable(hdlcd->clk);
- + case FB_BLANK_NORMAL:
- + hdlcd_disable(hdlcd);
- + break;
- + case FB_BLANK_UNBLANK:
- + clk_enable(hdlcd->clk);
- + hdlcd_enable(hdlcd);
- + break;
- + case FB_BLANK_VSYNC_SUSPEND:
- + case FB_BLANK_HSYNC_SUSPEND:
- + default:
- + return 1;
- + }
- +
- + return 0;
- +}
- +
- +static void hdlcd_mmap_open(struct vm_area_struct *vma)
- +{
- +}
- +
- +static void hdlcd_mmap_close(struct vm_area_struct *vma)
- +{
- +}
- +
- +static struct vm_operations_struct hdlcd_mmap_ops = {
- + .open = hdlcd_mmap_open,
- + .close = hdlcd_mmap_close,
- +};
- +
- +static int hdlcd_mmap(struct fb_info *info, struct vm_area_struct *vma)
- +{
- + struct hdlcd_device *hdlcd = to_hdlcd_device(info);
- + unsigned long off;
- + unsigned long start;
- + unsigned long len = hdlcd->fb.fix.smem_len;
- +
- + if (vma->vm_end - vma->vm_start == 0)
- + return 0;
- + if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
- + return -EINVAL;
- +
- + off = vma->vm_pgoff << PAGE_SHIFT;
- + if ((off >= len) || (vma->vm_end - vma->vm_start + off) > len)
- + return -EINVAL;
- +
- + start = hdlcd->fb.fix.smem_start;
- + off += start;
- +
- + vma->vm_pgoff = off >> PAGE_SHIFT;
- + vma->vm_flags |= VM_IO;
- + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- + vma->vm_ops = &hdlcd_mmap_ops;
- + if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
- + vma->vm_end - vma->vm_start,
- + vma->vm_page_prot))
- + return -EAGAIN;
- +
- + return 0;
- +}
- +
- +static int hdlcd_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
- +{
- + struct hdlcd_device *hdlcd = to_hdlcd_device(info);
- +
- + hdlcd->fb.var.yoffset = var->yoffset;
- + WRITE_HDLCD_REG(HDLCD_REG_FB_BASE, hdlcd->fb.fix.smem_start +
- + (var->yoffset * hdlcd->fb.fix.line_length));
- +
- + hdlcd_wait_for_vsync(info);
- +
- + return 0;
- +}
- +
- +static int hdlcd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
- +{
- + int err;
- +
- + switch (cmd) {
- + case FBIO_WAITFORVSYNC:
- + err = hdlcd_wait_for_vsync(info);
- + break;
- + default:
- + err = -ENOIOCTLCMD;
- + break;
- + }
- +
- + return err;
- +}
- +
- +static struct fb_ops hdlcd_ops = {
- + .owner = THIS_MODULE,
- + .fb_check_var = hdlcd_check_var,
- + .fb_set_par = hdlcd_set_par,
- + .fb_setcolreg = hdlcd_setcolreg,
- + .fb_blank = hdlcd_blank,
- + .fb_fillrect = cfb_fillrect,
- + .fb_copyarea = cfb_copyarea,
- + .fb_imageblit = cfb_imageblit,
- + .fb_mmap = hdlcd_mmap,
- + .fb_pan_display = hdlcd_pan_display,
- + .fb_ioctl = hdlcd_ioctl,
- + .fb_compat_ioctl = hdlcd_ioctl
- +};
- +
- +static int hdlcd_setup(struct hdlcd_device *hdlcd)
- +{
- + u32 version;
- + int err = -EFAULT;
- +
- + hdlcd->fb.device = hdlcd->dev;
- +
- + hdlcd->clk = clk_get(hdlcd->dev, NULL);
- + if (IS_ERR(hdlcd->clk)) {
- + dev_err(hdlcd->dev, "HDLCD: unable to find clock data\n");
- + return PTR_ERR(hdlcd->clk);
- + }
- +
- + err = clk_prepare(hdlcd->clk);
- + if (err)
- + goto clk_prepare_err;
- +
- + hdlcd->base = ioremap_nocache(hdlcd->fb.fix.mmio_start, hdlcd->fb.fix.mmio_len);
- + if (!hdlcd->base) {
- + dev_err(hdlcd->dev, "HDLCD: unable to map registers\n");
- + goto remap_err;
- + }
- +
- + hdlcd->fb.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
- + if (!hdlcd->fb.pseudo_palette) {
- + dev_err(hdlcd->dev, "HDLCD: unable to allocate pseudo_palette memory\n");
- + err = -ENOMEM;
- + goto kmalloc_err;
- + }
- +
- + version = readl(hdlcd->base + HDLCD_REG_VERSION);
- + if ((version & HDLCD_PRODUCT_MASK) != HDLCD_PRODUCT_ID) {
- + dev_err(hdlcd->dev, "HDLCD: unknown product id: 0x%x\n", version);
- + err = -EINVAL;
- + goto kmalloc_err;
- + }
- + dev_info(hdlcd->dev, "HDLCD: found ARM HDLCD version r%dp%d\n",
- + (version & HDLCD_VERSION_MAJOR_MASK) >> 8,
- + version & HDLCD_VERSION_MINOR_MASK);
- +
- + strcpy(hdlcd->fb.fix.id, "hdlcd");
- + hdlcd->fb.fbops = &hdlcd_ops;
- + hdlcd->fb.flags = FBINFO_FLAG_DEFAULT/* | FBINFO_VIRTFB*/;
- +
- + hdlcd->fb.fix.type = FB_TYPE_PACKED_PIXELS;
- + hdlcd->fb.fix.type_aux = 0;
- + hdlcd->fb.fix.xpanstep = 0;
- + hdlcd->fb.fix.ypanstep = 1;
- + hdlcd->fb.fix.ywrapstep = 0;
- + hdlcd->fb.fix.accel = FB_ACCEL_NONE;
- +
- + hdlcd->fb.var.nonstd = 0;
- + hdlcd->fb.var.activate = FB_ACTIVATE_NOW;
- + hdlcd->fb.var.height = -1;
- + hdlcd->fb.var.width = -1;
- + hdlcd->fb.var.accel_flags = 0;
- +
- + init_completion(&hdlcd->vsync_completion);
- +
- + if (hdlcd->edid) {
- + /* build modedb from EDID */
- + fb_edid_to_monspecs(hdlcd->edid, &hdlcd->fb.monspecs);
- + fb_videomode_to_modelist(hdlcd->fb.monspecs.modedb,
- + hdlcd->fb.monspecs.modedb_len,
- + &hdlcd->fb.modelist);
- + fb_find_mode(&hdlcd->fb.var, &hdlcd->fb, fb_mode,
- + hdlcd->fb.monspecs.modedb,
- + hdlcd->fb.monspecs.modedb_len,
- + &hdlcd_default_mode, 32);
- + } else {
- + hdlcd->fb.monspecs.hfmin = 0;
- + hdlcd->fb.monspecs.hfmax = 100000;
- + hdlcd->fb.monspecs.vfmin = 0;
- + hdlcd->fb.monspecs.vfmax = 400;
- + hdlcd->fb.monspecs.dclkmin = 1000000;
- + hdlcd->fb.monspecs.dclkmax = 100000000;
- + fb_find_mode(&hdlcd->fb.var, &hdlcd->fb, fb_mode, NULL, 0, &hdlcd_default_mode, 32);
- + }
- +
- + dev_info(hdlcd->dev, "using %dx%d-%d@%d mode\n", hdlcd->fb.var.xres,
- + hdlcd->fb.var.yres, hdlcd->fb.var.bits_per_pixel,
- + hdlcd->fb.mode ? hdlcd->fb.mode->refresh : 60);
- + hdlcd->fb.var.xres_virtual = hdlcd->fb.var.xres;
- +#ifdef HDLCD_NO_VIRTUAL_SCREEN
- + hdlcd->fb.var.yres_virtual = hdlcd->fb.var.yres;
- +#else
- + hdlcd->fb.var.yres_virtual = hdlcd->fb.var.yres * 2;
- +#endif
- +
- + /* initialise and set the palette */
- + if (fb_alloc_cmap(&hdlcd->fb.cmap, NR_PALETTE, 0)) {
- + dev_err(hdlcd->dev, "failed to allocate cmap memory\n");
- + err = -ENOMEM;
- + goto setup_err;
- + }
- + fb_set_cmap(&hdlcd->fb.cmap, &hdlcd->fb);
- +
- + /* Allow max number of outstanding requests with the largest beat burst */
- + WRITE_HDLCD_REG(HDLCD_REG_BUS_OPTIONS, HDLCD_BUS_MAX_OUTSTAND | HDLCD_BUS_BURST_16);
- + /* Set the framebuffer base to start of allocated memory */
- + WRITE_HDLCD_REG(HDLCD_REG_FB_BASE, hdlcd->fb.fix.smem_start);
- +#ifdef HDLCD_COUNT_BUFFERUNDERRUNS
- + /* turn on underrun interrupt for counting */
- + WRITE_HDLCD_REG(HDLCD_REG_INT_MASK, HDLCD_INTERRUPT_UNDERRUN);
- +#else
- + /* Ensure interrupts are disabled */
- + WRITE_HDLCD_REG(HDLCD_REG_INT_MASK, 0);
- +#endif
- + fb_set_var(&hdlcd->fb, &hdlcd->fb.var);
- +
- + if (!register_framebuffer(&hdlcd->fb)) {
- + return 0;
- + }
- +
- + dev_err(hdlcd->dev, "HDLCD: cannot register framebuffer\n");
- +
- + fb_dealloc_cmap(&hdlcd->fb.cmap);
- +setup_err:
- + iounmap(hdlcd->base);
- +kmalloc_err:
- + kfree(hdlcd->fb.pseudo_palette);
- +remap_err:
- + clk_unprepare(hdlcd->clk);
- +clk_prepare_err:
- + clk_put(hdlcd->clk);
- + return err;
- +}
- +
- +static inline unsigned char atohex(u8 data)
- +{
- + if (!isxdigit(data))
- + return 0;
- + /* truncate the upper nibble and add 9 to non-digit values */
- + return (data > 0x39) ? ((data & 0xf) + 9) : (data & 0xf);
- +}
- +
- +/* EDID data is passed from devicetree in a literal string that can contain spaces and
- + the hexadecimal dump of the data */
- +static int parse_edid_data(struct hdlcd_device *hdlcd, const u8 *edid_data, int data_len)
- +{
- + int i, j;
- +
- + if (!edid_data)
- + return -EINVAL;
- +
- + hdlcd->edid = kzalloc(EDID_LENGTH, GFP_KERNEL);
- + if (!hdlcd->edid)
- + return -ENOMEM;
- +
- + for (i = 0, j = 0; i < data_len; i++) {
- + if (isspace(edid_data[i]))
- + continue;
- + hdlcd->edid[j++] = atohex(edid_data[i]);
- + if (j >= EDID_LENGTH)
- + break;
- + }
- +
- + if (j < EDID_LENGTH) {
- + kfree(hdlcd->edid);
- + hdlcd->edid = NULL;
- + return -EINVAL;
- + }
- +
- + return 0;
- +}
- +
- +static int hdlcd_probe(struct platform_device *pdev)
- +{
- + int err = 0, i;
- + struct hdlcd_device *hdlcd;
- + struct resource *mem;
- +#ifdef CONFIG_OF
- + struct device_node *of_node;
- +#endif
- +
- + memset(&cached_var_screeninfo, 0, sizeof(struct fb_var_screeninfo));
- +
- + dev_dbg(&pdev->dev, "HDLCD: probing\n");
- +
- + hdlcd = kzalloc(sizeof(*hdlcd), GFP_KERNEL);
- + if (!hdlcd)
- + return -ENOMEM;
- +
- +#ifdef CONFIG_OF
- + of_node = pdev->dev.of_node;
- + if (of_node) {
- + int len;
- + const u8 *edid;
- + const __be32 *prop = of_get_property(of_node, "mode", &len);
- + if (prop)
- + strncpy(fb_mode, (char *)prop, len);
- + prop = of_get_property(of_node, "framebuffer", &len);
- + if (prop) {
- + hdlcd->fb.fix.smem_start = of_read_ulong(prop,
- + of_n_addr_cells(of_node));
- + prop += of_n_addr_cells(of_node);
- + framebuffer_size = of_read_ulong(prop,
- + of_n_size_cells(of_node));
- + if (framebuffer_size > HDLCD_MAX_FRAMEBUFFER_SIZE)
- + framebuffer_size = HDLCD_MAX_FRAMEBUFFER_SIZE;
- + dev_dbg(&pdev->dev, "HDLCD: phys_addr = 0x%lx, size = 0x%lx\n",
- + hdlcd->fb.fix.smem_start, framebuffer_size);
- + }
- + edid = of_get_property(of_node, "edid", &len);
- + if (edid) {
- + err = parse_edid_data(hdlcd, edid, len);
- +#ifdef CONFIG_SERIAL_AMBA_PCU_UART
- + } else {
- + /* ask the firmware to fetch the EDID */
- + dev_dbg(&pdev->dev, "HDLCD: Requesting EDID data\n");
- + hdlcd->edid = kzalloc(EDID_LENGTH, GFP_KERNEL);
- + if (!hdlcd->edid)
- + return -ENOMEM;
- + err = get_edid(hdlcd->edid);
- +#endif /* CONFIG_SERIAL_AMBA_PCU_UART */
- + }
- + if (err)
- + dev_info(&pdev->dev, "HDLCD: Failed to parse EDID data\n");
- + }
- +#endif /* CONFIG_OF */
- +
- + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- + if (!mem) {
- + dev_err(&pdev->dev, "HDLCD: cannot get platform resources\n");
- + err = -EINVAL;
- + goto resource_err;
- + }
- +
- + i = platform_get_irq(pdev, 0);
- + if (i < 0) {
- + dev_err(&pdev->dev, "HDLCD: no irq defined for vsync\n");
- + err = -ENOENT;
- + goto resource_err;
- + } else {
- + err = request_irq(i, hdlcd_irq, 0, dev_name(&pdev->dev), hdlcd);
- + if (err) {
- + dev_err(&pdev->dev, "HDLCD: unable to request irq\n");
- + goto resource_err;
- + }
- + hdlcd->irq = i;
- + }
- +
- + if (!request_mem_region(mem->start, resource_size(mem), dev_name(&pdev->dev))) {
- + err = -ENXIO;
- + goto request_err;
- + }
- +
- + if (!hdlcd->fb.fix.smem_start) {
- + dev_err(&pdev->dev, "platform did not allocate frame buffer memory\n");
- + err = -ENOMEM;
- + goto memalloc_err;
- + }
- + hdlcd->fb.screen_base = ioremap_wc(hdlcd->fb.fix.smem_start, framebuffer_size);
- + if (!hdlcd->fb.screen_base) {
- + dev_err(&pdev->dev, "unable to ioremap framebuffer\n");
- + err = -ENOMEM;
- + goto probe_err;
- + }
- +
- + hdlcd->fb.screen_size = framebuffer_size;
- + hdlcd->fb.fix.smem_len = framebuffer_size;
- + hdlcd->fb.fix.mmio_start = mem->start;
- + hdlcd->fb.fix.mmio_len = resource_size(mem);
- +
- + /* Clear the framebuffer */
- + memset(hdlcd->fb.screen_base, 0, framebuffer_size);
- +
- + hdlcd->dev = &pdev->dev;
- +
- + dev_dbg(&pdev->dev, "HDLCD: framebuffer virt base %p, phys base 0x%lX\n",
- + hdlcd->fb.screen_base, (unsigned long)hdlcd->fb.fix.smem_start);
- +
- + err = hdlcd_setup(hdlcd);
- +
- + if (err)
- + goto probe_err;
- +
- + platform_set_drvdata(pdev, hdlcd);
- + return 0;
- +
- +probe_err:
- + iounmap(hdlcd->fb.screen_base);
- + memblock_free(hdlcd->fb.fix.smem_start, hdlcd->fb.fix.smem_start);
- +
- +memalloc_err:
- + release_mem_region(mem->start, resource_size(mem));
- +
- +request_err:
- + free_irq(hdlcd->irq, hdlcd);
- +
- +resource_err:
- + kfree(hdlcd);
- +
- + return err;
- +}
- +
- +static int hdlcd_remove(struct platform_device *pdev)
- +{
- + struct hdlcd_device *hdlcd = platform_get_drvdata(pdev);
- +
- + clk_disable(hdlcd->clk);
- + clk_unprepare(hdlcd->clk);
- + clk_put(hdlcd->clk);
- +
- + /* unmap memory */
- + iounmap(hdlcd->fb.screen_base);
- + iounmap(hdlcd->base);
- +
- + /* deallocate fb memory */
- + fb_dealloc_cmap(&hdlcd->fb.cmap);
- + kfree(hdlcd->fb.pseudo_palette);
- + memblock_free(hdlcd->fb.fix.smem_start, hdlcd->fb.fix.smem_start);
- + release_mem_region(hdlcd->fb.fix.mmio_start, hdlcd->fb.fix.mmio_len);
- +
- + free_irq(hdlcd->irq, NULL);
- + kfree(hdlcd);
- +
- + return 0;
- +}
- +
- +#ifdef CONFIG_PM
- +static int hdlcd_suspend(struct platform_device *pdev, pm_message_t state)
- +{
- + /* not implemented yet */
- + return 0;
- +}
- +
- +static int hdlcd_resume(struct platform_device *pdev)
- +{
- + /* not implemented yet */
- + return 0;
- +}
- +#else
- +#define hdlcd_suspend NULL
- +#define hdlcd_resume NULL
- +#endif
- +
- +static struct platform_driver hdlcd_driver = {
- + .probe = hdlcd_probe,
- + .remove = hdlcd_remove,
- + .suspend = hdlcd_suspend,
- + .resume = hdlcd_resume,
- + .driver = {
- + .name = "hdlcd",
- + .owner = THIS_MODULE,
- + .of_match_table = hdlcd_of_matches,
- + },
- +};
- +
- +static int __init hdlcd_init(void)
- +{
- +#ifdef HDLCD_COUNT_BUFFERUNDERRUNS
- + int err = platform_driver_register(&hdlcd_driver);
- + if (!err)
- + hdlcd_underrun_init();
- + return err;
- +#else
- + return platform_driver_register(&hdlcd_driver);
- +#endif
- +}
- +
- +void __exit hdlcd_exit(void)
- +{
- +#ifdef HDLCD_COUNT_BUFFERUNDERRUNS
- + hdlcd_underrun_close();
- +#endif
- + platform_driver_unregister(&hdlcd_driver);
- +}
- +
- +module_init(hdlcd_init);
- +module_exit(hdlcd_exit);
- +
- +MODULE_AUTHOR("Liviu Dudau");
- +MODULE_DESCRIPTION("ARM HDLCD core driver");
- +MODULE_LICENSE("GPL v2");
- diff -Nur linux-3.14.35.orig/drivers/video/backlight/backlight.c linux-3.14.35/drivers/video/backlight/backlight.c
- --- linux-3.14.35.orig/drivers/video/backlight/backlight.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/video/backlight/backlight.c 2015-03-08 14:27:37.781684499 -0500
- @@ -41,6 +41,8 @@
- {
- struct backlight_device *bd;
- struct fb_event *evdata = data;
- + int node = evdata->info->node;
- + int fb_blank = 0;
-
- /* If we aren't interested in this event, skip it immediately ... */
- if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK)
- @@ -51,12 +53,24 @@
- if (bd->ops)
- if (!bd->ops->check_fb ||
- bd->ops->check_fb(bd, evdata->info)) {
- - bd->props.fb_blank = *(int *)evdata->data;
- - if (bd->props.fb_blank == FB_BLANK_UNBLANK)
- - bd->props.state &= ~BL_CORE_FBBLANK;
- - else
- - bd->props.state |= BL_CORE_FBBLANK;
- - backlight_update_status(bd);
- + fb_blank = *(int *)evdata->data;
- + if (fb_blank == FB_BLANK_UNBLANK &&
- + !bd->fb_bl_on[node]) {
- + bd->fb_bl_on[node] = true;
- + if (!bd->use_count++) {
- + bd->props.state &= ~BL_CORE_FBBLANK;
- + bd->props.fb_blank = FB_BLANK_UNBLANK;
- + backlight_update_status(bd);
- + }
- + } else if (fb_blank != FB_BLANK_UNBLANK &&
- + bd->fb_bl_on[node]) {
- + bd->fb_bl_on[node] = false;
- + if (!(--bd->use_count)) {
- + bd->props.state |= BL_CORE_FBBLANK;
- + bd->props.fb_blank = FB_BLANK_POWERDOWN;
- + backlight_update_status(bd);
- + }
- + }
- }
- mutex_unlock(&bd->ops_lock);
- return 0;
- diff -Nur linux-3.14.35.orig/drivers/video/Kconfig linux-3.14.35/drivers/video/Kconfig
- --- linux-3.14.35.orig/drivers/video/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/video/Kconfig 2015-03-08 14:27:37.781684499 -0500
- @@ -39,6 +39,11 @@
- config HDMI
- bool
-
- +config VEXPRESS_DVI_CONTROL
- + bool "Versatile Express DVI control"
- + depends on FB && VEXPRESS_CONFIG
- + default y
- +
- menuconfig FB
- tristate "Support for frame buffer devices"
- ---help---
- @@ -327,6 +332,21 @@
- here and read <file:Documentation/kbuild/modules.txt>. The module
- will be called amba-clcd.
-
- +config FB_ARMHDLCD
- + tristate "ARM High Definition LCD support"
- + depends on FB && ARM
- + select FB_CFB_FILLRECT
- + select FB_CFB_COPYAREA
- + select FB_CFB_IMAGEBLIT
- + help
- + This framebuffer device driver is for the ARM High Definition
- + Colour LCD controller.
- +
- + If you want to compile this as a module (=code which can be
- + inserted into and removed from the running kernel), say M
- + here and read <file:Documentation/kbuild/modules.txt>. The module
- + will be called arm-hdlcd.
- +
- config FB_ACORN
- bool "Acorn VIDC support"
- depends on (FB = y) && ARM && ARCH_ACORN
- @@ -2491,6 +2511,10 @@
- source "drivers/video/mmp/Kconfig"
- source "drivers/video/backlight/Kconfig"
-
- +if ARCH_MXC
- +source "drivers/video/mxc/Kconfig"
- +endif
- +
- if VT
- source "drivers/video/console/Kconfig"
- endif
- diff -Nur linux-3.14.35.orig/drivers/video/Makefile linux-3.14.35/drivers/video/Makefile
- --- linux-3.14.35.orig/drivers/video/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/video/Makefile 2015-03-08 14:27:37.781684499 -0500
- @@ -53,6 +53,7 @@
- obj-$(CONFIG_FB_SAVAGE) += savage/
- obj-$(CONFIG_FB_GEODE) += geode/
- obj-$(CONFIG_FB_MBX) += mbx/
- +obj-$(CONFIG_FB_MXC) += mxc/
- obj-$(CONFIG_FB_NEOMAGIC) += neofb.o
- obj-$(CONFIG_FB_3DFX) += tdfxfb.o
- obj-$(CONFIG_FB_CONTROL) += controlfb.o
- @@ -99,6 +100,7 @@
- obj-$(CONFIG_FB_PVR2) += pvr2fb.o
- obj-$(CONFIG_FB_VOODOO1) += sstfb.o
- obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o
- +obj-$(CONFIG_FB_ARMHDLCD) += arm-hdlcd.o
- obj-$(CONFIG_FB_GOLDFISH) += goldfishfb.o
- obj-$(CONFIG_FB_68328) += 68328fb.o
- obj-$(CONFIG_FB_GBE) += gbefb.o
- @@ -178,3 +180,6 @@
- ifeq ($(CONFIG_OF),y)
- obj-$(CONFIG_VIDEOMODE_HELPERS) += of_display_timing.o of_videomode.o
- endif
- +
- +# platform specific output drivers
- +obj-$(CONFIG_VEXPRESS_DVI_CONTROL) += vexpress-dvi.o
- diff -Nur linux-3.14.35.orig/drivers/video/mxc/Kconfig linux-3.14.35/drivers/video/mxc/Kconfig
- --- linux-3.14.35.orig/drivers/video/mxc/Kconfig 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/video/mxc/Kconfig 2015-03-08 14:27:37.781684499 -0500
- @@ -0,0 +1,48 @@
- +config FB_MXC
- + tristate "MXC Framebuffer support"
- + depends on FB
- + select FB_CFB_FILLRECT
- + select FB_CFB_COPYAREA
- + select FB_CFB_IMAGEBLIT
- + select FB_MODE_HELPERS
- + default y
- + help
- + This is a framebuffer device for the MXC LCD Controller.
- + See <http://www.linux-fbdev.org/> for information on framebuffer
- + devices.
- +
- + If you plan to use the LCD display with your MXC system, say
- + Y here.
- +
- +config FB_MXC_SYNC_PANEL
- + depends on FB_MXC
- + tristate "Synchronous Panel Framebuffer"
- +
- +config FB_MXC_LDB
- + tristate "MXC LDB"
- + depends on FB_MXC_SYNC_PANEL
- + depends on MXC_IPU_V3
- +
- +config FB_MXC_MIPI_DSI
- + tristate "MXC MIPI_DSI"
- + depends on FB_MXC_SYNC_PANEL
- + depends on MXC_IPU_V3
- +
- +config FB_MXC_TRULY_WVGA_SYNC_PANEL
- + tristate "TRULY WVGA Panel"
- + depends on FB_MXC_SYNC_PANEL
- + depends on FB_MXC_MIPI_DSI
- +
- +config FB_MXC_HDMI
- + depends on FB_MXC_SYNC_PANEL
- + depends on MXC_IPU_V3
- + depends on I2C
- + tristate "MXC HDMI driver support"
- + select MFD_MXC_HDMI
- + help
- + Driver for the on-chip MXC HDMI controller.
- +
- +config FB_MXC_EDID
- + depends on FB_MXC && I2C
- + tristate "MXC EDID support"
- + default y
- diff -Nur linux-3.14.35.orig/drivers/video/mxc/ldb.c linux-3.14.35/drivers/video/mxc/ldb.c
- --- linux-3.14.35.orig/drivers/video/mxc/ldb.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/video/mxc/ldb.c 2015-03-08 14:27:37.781684499 -0500
- @@ -0,0 +1,1036 @@
- +/*
- + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +/*!
- + * @file mxc_ldb.c
- + *
- + * @brief This file contains the LDB driver device interface and fops
- + * functions.
- + */
- +#include <linux/types.h>
- +#include <linux/init.h>
- +#include <linux/module.h>
- +#include <linux/platform_device.h>
- +#include <linux/err.h>
- +#include <linux/clk.h>
- +#include <linux/console.h>
- +#include <linux/io.h>
- +#include <linux/ipu.h>
- +#include <linux/mxcfb.h>
- +#include <linux/regulator/consumer.h>
- +#include <linux/spinlock.h>
- +#include <linux/of_device.h>
- +#include <linux/mod_devicetable.h>
- +#include "mxc_dispdrv.h"
- +
- +#define DISPDRV_LDB "ldb"
- +
- +#define LDB_BGREF_RMODE_MASK 0x00008000
- +#define LDB_BGREF_RMODE_INT 0x00008000
- +#define LDB_BGREF_RMODE_EXT 0x0
- +
- +#define LDB_DI1_VS_POL_MASK 0x00000400
- +#define LDB_DI1_VS_POL_ACT_LOW 0x00000400
- +#define LDB_DI1_VS_POL_ACT_HIGH 0x0
- +#define LDB_DI0_VS_POL_MASK 0x00000200
- +#define LDB_DI0_VS_POL_ACT_LOW 0x00000200
- +#define LDB_DI0_VS_POL_ACT_HIGH 0x0
- +
- +#define LDB_BIT_MAP_CH1_MASK 0x00000100
- +#define LDB_BIT_MAP_CH1_JEIDA 0x00000100
- +#define LDB_BIT_MAP_CH1_SPWG 0x0
- +#define LDB_BIT_MAP_CH0_MASK 0x00000040
- +#define LDB_BIT_MAP_CH0_JEIDA 0x00000040
- +#define LDB_BIT_MAP_CH0_SPWG 0x0
- +
- +#define LDB_DATA_WIDTH_CH1_MASK 0x00000080
- +#define LDB_DATA_WIDTH_CH1_24 0x00000080
- +#define LDB_DATA_WIDTH_CH1_18 0x0
- +#define LDB_DATA_WIDTH_CH0_MASK 0x00000020
- +#define LDB_DATA_WIDTH_CH0_24 0x00000020
- +#define LDB_DATA_WIDTH_CH0_18 0x0
- +
- +#define LDB_CH1_MODE_MASK 0x0000000C
- +#define LDB_CH1_MODE_EN_TO_DI1 0x0000000C
- +#define LDB_CH1_MODE_EN_TO_DI0 0x00000004
- +#define LDB_CH1_MODE_DISABLE 0x0
- +#define LDB_CH0_MODE_MASK 0x00000003
- +#define LDB_CH0_MODE_EN_TO_DI1 0x00000003
- +#define LDB_CH0_MODE_EN_TO_DI0 0x00000001
- +#define LDB_CH0_MODE_DISABLE 0x0
- +
- +#define LDB_SPLIT_MODE_EN 0x00000010
- +
- +enum {
- + IMX6_LDB,
- +};
- +
- +enum {
- + LDB_IMX6 = 1,
- +};
- +
- +struct fsl_mxc_ldb_platform_data {
- + int devtype;
- + u32 ext_ref;
- +#define LDB_SPL_DI0 1
- +#define LDB_SPL_DI1 2
- +#define LDB_DUL_DI0 3
- +#define LDB_DUL_DI1 4
- +#define LDB_SIN0 5
- +#define LDB_SIN1 6
- +#define LDB_SEP0 7
- +#define LDB_SEP1 8
- + int mode;
- + int ipu_id;
- + int disp_id;
- +
- + /*only work for separate mode*/
- + int sec_ipu_id;
- + int sec_disp_id;
- +};
- +
- +struct ldb_data {
- + struct platform_device *pdev;
- + struct mxc_dispdrv_handle *disp_ldb;
- + uint32_t *reg;
- + uint32_t *control_reg;
- + uint32_t *gpr3_reg;
- + uint32_t control_reg_data;
- + struct regulator *lvds_bg_reg;
- + int mode;
- + bool inited;
- + struct ldb_setting {
- + struct clk *di_clk;
- + struct clk *ldb_di_clk;
- + struct clk *div_3_5_clk;
- + struct clk *div_7_clk;
- + struct clk *div_sel_clk;
- + bool active;
- + bool clk_en;
- + int ipu;
- + int di;
- + uint32_t ch_mask;
- + uint32_t ch_val;
- + } setting[2];
- + struct notifier_block nb;
- +};
- +
- +static int g_ldb_mode;
- +
- +static struct fb_videomode ldb_modedb[] = {
- + {
- + "LDB-WXGA", 60, 1280, 800, 14065,
- + 40, 40,
- + 10, 3,
- + 80, 10,
- + 0,
- + FB_VMODE_NONINTERLACED,
- + FB_MODE_IS_DETAILED,},
- + {
- + "LDB-XGA", 60, 1024, 768, 15385,
- + 220, 40,
- + 21, 7,
- + 60, 10,
- + 0,
- + FB_VMODE_NONINTERLACED,
- + FB_MODE_IS_DETAILED,},
- + {
- + "LDB-1080P60", 60, 1920, 1080, 7692,
- + 100, 40,
- + 30, 3,
- + 10, 2,
- + 0,
- + FB_VMODE_NONINTERLACED,
- + FB_MODE_IS_DETAILED,},
- +};
- +static int ldb_modedb_sz = ARRAY_SIZE(ldb_modedb);
- +
- +static inline int is_imx6_ldb(struct fsl_mxc_ldb_platform_data *plat_data)
- +{
- + return (plat_data->devtype == LDB_IMX6);
- +}
- +
- +static int bits_per_pixel(int pixel_fmt)
- +{
- + switch (pixel_fmt) {
- + case IPU_PIX_FMT_BGR24:
- + case IPU_PIX_FMT_RGB24:
- + return 24;
- + break;
- + case IPU_PIX_FMT_BGR666:
- + case IPU_PIX_FMT_RGB666:
- + case IPU_PIX_FMT_LVDS666:
- + return 18;
- + break;
- + default:
- + break;
- + }
- + return 0;
- +}
- +
- +static int valid_mode(int pixel_fmt)
- +{
- + return ((pixel_fmt == IPU_PIX_FMT_RGB24) ||
- + (pixel_fmt == IPU_PIX_FMT_BGR24) ||
- + (pixel_fmt == IPU_PIX_FMT_LVDS666) ||
- + (pixel_fmt == IPU_PIX_FMT_RGB666) ||
- + (pixel_fmt == IPU_PIX_FMT_BGR666));
- +}
- +
- +static int parse_ldb_mode(char *mode)
- +{
- + int ldb_mode;
- +
- + if (!strcmp(mode, "spl0"))
- + ldb_mode = LDB_SPL_DI0;
- + else if (!strcmp(mode, "spl1"))
- + ldb_mode = LDB_SPL_DI1;
- + else if (!strcmp(mode, "dul0"))
- + ldb_mode = LDB_DUL_DI0;
- + else if (!strcmp(mode, "dul1"))
- + ldb_mode = LDB_DUL_DI1;
- + else if (!strcmp(mode, "sin0"))
- + ldb_mode = LDB_SIN0;
- + else if (!strcmp(mode, "sin1"))
- + ldb_mode = LDB_SIN1;
- + else if (!strcmp(mode, "sep0"))
- + ldb_mode = LDB_SEP0;
- + else if (!strcmp(mode, "sep1"))
- + ldb_mode = LDB_SEP1;
- + else
- + ldb_mode = -EINVAL;
- +
- + return ldb_mode;
- +}
- +
- +#ifndef MODULE
- +/*
- + * "ldb=spl0/1" -- split mode on DI0/1
- + * "ldb=dul0/1" -- dual mode on DI0/1
- + * "ldb=sin0/1" -- single mode on LVDS0/1
- + * "ldb=sep0/1" -- separate mode begin from LVDS0/1
- + *
- + * there are two LVDS channels(LVDS0 and LVDS1) which can transfer video
- + * datas, there two channels can be used as split/dual/single/separate mode.
- + *
- + * split mode means display data from DI0 or DI1 will send to both channels
- + * LVDS0+LVDS1.
- + * dual mode means display data from DI0 or DI1 will be duplicated on LVDS0
- + * and LVDS1, it said, LVDS0 and LVDS1 has the same content.
- + * single mode means only work for DI0/DI1->LVDS0 or DI0/DI1->LVDS1.
- + * separate mode means you can make DI0/DI1->LVDS0 and DI0/DI1->LVDS1 work
- + * at the same time.
- + */
- +static int __init ldb_setup(char *options)
- +{
- + g_ldb_mode = parse_ldb_mode(options);
- + return (g_ldb_mode < 0) ? 0 : 1;
- +}
- +__setup("ldb=", ldb_setup);
- +#endif
- +
- +static int ldb_get_of_property(struct platform_device *pdev,
- + struct fsl_mxc_ldb_platform_data *plat_data)
- +{
- + struct device_node *np = pdev->dev.of_node;
- + int err;
- + u32 ipu_id, disp_id;
- + u32 sec_ipu_id, sec_disp_id;
- + char *mode;
- + u32 ext_ref;
- +
- + err = of_property_read_string(np, "mode", (const char **)&mode);
- + if (err) {
- + dev_dbg(&pdev->dev, "get of property mode fail\n");
- + return err;
- + }
- + err = of_property_read_u32(np, "ext_ref", &ext_ref);
- + if (err) {
- + dev_dbg(&pdev->dev, "get of property ext_ref fail\n");
- + return err;
- + }
- + err = of_property_read_u32(np, "ipu_id", &ipu_id);
- + if (err) {
- + dev_dbg(&pdev->dev, "get of property ipu_id fail\n");
- + return err;
- + }
- + err = of_property_read_u32(np, "disp_id", &disp_id);
- + if (err) {
- + dev_dbg(&pdev->dev, "get of property disp_id fail\n");
- + return err;
- + }
- + err = of_property_read_u32(np, "sec_ipu_id", &sec_ipu_id);
- + if (err) {
- + dev_dbg(&pdev->dev, "get of property sec_ipu_id fail\n");
- + return err;
- + }
- + err = of_property_read_u32(np, "sec_disp_id", &sec_disp_id);
- + if (err) {
- + dev_dbg(&pdev->dev, "get of property sec_disp_id fail\n");
- + return err;
- + }
- +
- + plat_data->mode = parse_ldb_mode(mode);
- + plat_data->ext_ref = ext_ref;
- + plat_data->ipu_id = ipu_id;
- + plat_data->disp_id = disp_id;
- + plat_data->sec_ipu_id = sec_ipu_id;
- + plat_data->sec_disp_id = sec_disp_id;
- +
- + return err;
- +}
- +
- +static int find_ldb_setting(struct ldb_data *ldb, struct fb_info *fbi)
- +{
- + char *id_di[] = {
- + "DISP3 BG",
- + "DISP3 BG - DI1",
- + };
- + char id[16];
- + int i;
- +
- + for (i = 0; i < 2; i++) {
- + if (ldb->setting[i].active) {
- + memset(id, 0, 16);
- + memcpy(id, id_di[ldb->setting[i].di],
- + strlen(id_di[ldb->setting[i].di]));
- + id[4] += ldb->setting[i].ipu;
- + if (!strcmp(id, fbi->fix.id))
- + return i;
- + }
- + }
- + return -EINVAL;
- +}
- +
- +static int ldb_disp_setup(struct mxc_dispdrv_handle *disp, struct fb_info *fbi)
- +{
- + uint32_t reg, val;
- + uint32_t pixel_clk, rounded_pixel_clk;
- + struct clk *ldb_clk_parent;
- + struct ldb_data *ldb = mxc_dispdrv_getdata(disp);
- + int setting_idx, di;
- + int ret;
- +
- + setting_idx = find_ldb_setting(ldb, fbi);
- + if (setting_idx < 0)
- + return setting_idx;
- +
- + di = ldb->setting[setting_idx].di;
- +
- + /* restore channel mode setting */
- + val = readl(ldb->control_reg);
- + val |= ldb->setting[setting_idx].ch_val;
- + writel(val, ldb->control_reg);
- + dev_dbg(&ldb->pdev->dev, "LDB setup, control reg:0x%x\n",
- + readl(ldb->control_reg));
- +
- + /* vsync setup */
- + reg = readl(ldb->control_reg);
- + if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) {
- + if (di == 0)
- + reg = (reg & ~LDB_DI0_VS_POL_MASK)
- + | LDB_DI0_VS_POL_ACT_HIGH;
- + else
- + reg = (reg & ~LDB_DI1_VS_POL_MASK)
- + | LDB_DI1_VS_POL_ACT_HIGH;
- + } else {
- + if (di == 0)
- + reg = (reg & ~LDB_DI0_VS_POL_MASK)
- + | LDB_DI0_VS_POL_ACT_LOW;
- + else
- + reg = (reg & ~LDB_DI1_VS_POL_MASK)
- + | LDB_DI1_VS_POL_ACT_LOW;
- + }
- + writel(reg, ldb->control_reg);
- +
- + /* clk setup */
- + if (ldb->setting[setting_idx].clk_en)
- + clk_disable_unprepare(ldb->setting[setting_idx].ldb_di_clk);
- + pixel_clk = (PICOS2KHZ(fbi->var.pixclock)) * 1000UL;
- + ldb_clk_parent = clk_get_parent(ldb->setting[setting_idx].ldb_di_clk);
- + if (IS_ERR(ldb_clk_parent)) {
- + dev_err(&ldb->pdev->dev, "get ldb di parent clk fail\n");
- + return PTR_ERR(ldb_clk_parent);
- + }
- + if ((ldb->mode == LDB_SPL_DI0) || (ldb->mode == LDB_SPL_DI1))
- + ret = clk_set_rate(ldb_clk_parent, pixel_clk * 7 / 2);
- + else
- + ret = clk_set_rate(ldb_clk_parent, pixel_clk * 7);
- + if (ret < 0) {
- + dev_err(&ldb->pdev->dev, "set ldb parent clk fail:%d\n", ret);
- + return ret;
- + }
- + rounded_pixel_clk = clk_round_rate(ldb->setting[setting_idx].ldb_di_clk,
- + pixel_clk);
- + dev_dbg(&ldb->pdev->dev, "pixel_clk:%d, rounded_pixel_clk:%d\n",
- + pixel_clk, rounded_pixel_clk);
- + ret = clk_set_rate(ldb->setting[setting_idx].ldb_di_clk,
- + rounded_pixel_clk);
- + if (ret < 0) {
- + dev_err(&ldb->pdev->dev, "set ldb di clk fail:%d\n", ret);
- + return ret;
- + }
- + ret = clk_prepare_enable(ldb->setting[setting_idx].ldb_di_clk);
- + if (ret < 0) {
- + dev_err(&ldb->pdev->dev, "enable ldb di clk fail:%d\n", ret);
- + return ret;
- + }
- +
- + if (!ldb->setting[setting_idx].clk_en)
- + ldb->setting[setting_idx].clk_en = true;
- +
- + return 0;
- +}
- +
- +int ldb_fb_event(struct notifier_block *nb, unsigned long val, void *v)
- +{
- + struct ldb_data *ldb = container_of(nb, struct ldb_data, nb);
- + struct fb_event *event = v;
- + struct fb_info *fbi = event->info;
- + int index;
- + uint32_t data;
- +
- + index = find_ldb_setting(ldb, fbi);
- + if (index < 0)
- + return 0;
- +
- + fbi->mode = (struct fb_videomode *)fb_match_mode(&fbi->var,
- + &fbi->modelist);
- +
- + if (!fbi->mode) {
- + dev_warn(&ldb->pdev->dev,
- + "LDB: can not find mode for xres=%d, yres=%d\n",
- + fbi->var.xres, fbi->var.yres);
- + if (ldb->setting[index].clk_en) {
- + clk_disable(ldb->setting[index].ldb_di_clk);
- + ldb->setting[index].clk_en = false;
- + data = readl(ldb->control_reg);
- + data &= ~ldb->setting[index].ch_mask;
- + writel(data, ldb->control_reg);
- + }
- + return 0;
- + }
- +
- + switch (val) {
- + case FB_EVENT_BLANK:
- + {
- + if (*((int *)event->data) == FB_BLANK_UNBLANK) {
- + if (!ldb->setting[index].clk_en) {
- + clk_enable(ldb->setting[index].ldb_di_clk);
- + ldb->setting[index].clk_en = true;
- + }
- + } else {
- + if (ldb->setting[index].clk_en) {
- + clk_disable(ldb->setting[index].ldb_di_clk);
- + ldb->setting[index].clk_en = false;
- + data = readl(ldb->control_reg);
- + data &= ~ldb->setting[index].ch_mask;
- + writel(data, ldb->control_reg);
- + dev_dbg(&ldb->pdev->dev,
- + "LDB blank, control reg:0x%x\n",
- + readl(ldb->control_reg));
- + }
- + }
- + break;
- + }
- + case FB_EVENT_SUSPEND:
- + if (ldb->setting[index].clk_en) {
- + clk_disable(ldb->setting[index].ldb_di_clk);
- + ldb->setting[index].clk_en = false;
- + }
- + break;
- + default:
- + break;
- + }
- + return 0;
- +}
- +
- +#define LVDS_MUX_CTL_WIDTH 2
- +#define LVDS_MUX_CTL_MASK 3
- +#define LVDS0_MUX_CTL_OFFS 6
- +#define LVDS1_MUX_CTL_OFFS 8
- +#define LVDS0_MUX_CTL_MASK (LVDS_MUX_CTL_MASK << 6)
- +#define LVDS1_MUX_CTL_MASK (LVDS_MUX_CTL_MASK << 8)
- +#define ROUTE_IPU_DI(ipu, di) (((ipu << 1) | di) & LVDS_MUX_CTL_MASK)
- +static int ldb_ipu_ldb_route(int ipu, int di, struct ldb_data *ldb)
- +{
- + uint32_t reg;
- + int channel;
- + int shift;
- + int mode = ldb->mode;
- +
- + reg = readl(ldb->gpr3_reg);
- + if (mode < LDB_SIN0) {
- + reg &= ~(LVDS0_MUX_CTL_MASK | LVDS1_MUX_CTL_MASK);
- + reg |= (ROUTE_IPU_DI(ipu, di) << LVDS0_MUX_CTL_OFFS) |
- + (ROUTE_IPU_DI(ipu, di) << LVDS1_MUX_CTL_OFFS);
- + dev_dbg(&ldb->pdev->dev,
- + "Dual/Split mode both channels route to IPU%d-DI%d\n",
- + ipu, di);
- + } else if ((mode == LDB_SIN0) || (mode == LDB_SIN1)) {
- + reg &= ~(LVDS0_MUX_CTL_MASK | LVDS1_MUX_CTL_MASK);
- + channel = mode - LDB_SIN0;
- + shift = LVDS0_MUX_CTL_OFFS + channel * LVDS_MUX_CTL_WIDTH;
- + reg |= ROUTE_IPU_DI(ipu, di) << shift;
- + dev_dbg(&ldb->pdev->dev,
- + "Single mode channel %d route to IPU%d-DI%d\n",
- + channel, ipu, di);
- + } else {
- + static bool first = true;
- +
- + if (first) {
- + if (mode == LDB_SEP0) {
- + reg &= ~LVDS0_MUX_CTL_MASK;
- + channel = 0;
- + } else {
- + reg &= ~LVDS1_MUX_CTL_MASK;
- + channel = 1;
- + }
- + first = false;
- + } else {
- + if (mode == LDB_SEP0) {
- + reg &= ~LVDS1_MUX_CTL_MASK;
- + channel = 1;
- + } else {
- + reg &= ~LVDS0_MUX_CTL_MASK;
- + channel = 0;
- + }
- + }
- +
- + shift = LVDS0_MUX_CTL_OFFS + channel * LVDS_MUX_CTL_WIDTH;
- + reg |= ROUTE_IPU_DI(ipu, di) << shift;
- +
- + dev_dbg(&ldb->pdev->dev,
- + "Separate mode channel %d route to IPU%d-DI%d\n",
- + channel, ipu, di);
- + }
- + writel(reg, ldb->gpr3_reg);
- +
- + return 0;
- +}
- +
- +static int ldb_disp_init(struct mxc_dispdrv_handle *disp,
- + struct mxc_dispdrv_setting *setting)
- +{
- + int ret = 0, i, lvds_channel = 0;
- + struct ldb_data *ldb = mxc_dispdrv_getdata(disp);
- + struct fsl_mxc_ldb_platform_data *plat_data = ldb->pdev->dev.platform_data;
- + struct resource *res;
- + uint32_t reg, setting_idx;
- + uint32_t ch_mask = 0, ch_val = 0;
- + uint32_t ipu_id, disp_id;
- + char di_clk[] = "ipu1_di0_sel";
- + char ldb_clk[] = "ldb_di0";
- + char div_3_5_clk[] = "di0_div_3_5";
- + char div_7_clk[] = "di0_div_7";
- + char div_sel_clk[] = "di0_div_sel";
- +
- + /* if input format not valid, make RGB666 as default*/
- + if (!valid_mode(setting->if_fmt)) {
- + dev_warn(&ldb->pdev->dev, "Input pixel format not valid"
- + " use default RGB666\n");
- + setting->if_fmt = IPU_PIX_FMT_RGB666;
- + }
- +
- + if (!ldb->inited) {
- + setting_idx = 0;
- + res = platform_get_resource(ldb->pdev, IORESOURCE_MEM, 0);
- + if (!res) {
- + dev_err(&ldb->pdev->dev, "get iomem fail.\n");
- + return -ENOMEM;
- + }
- +
- + ldb->reg = devm_ioremap(&ldb->pdev->dev, res->start,
- + resource_size(res));
- + ldb->control_reg = ldb->reg + 2;
- + ldb->gpr3_reg = ldb->reg + 3;
- +
- + /* ipu selected by platform data setting */
- + setting->dev_id = plat_data->ipu_id;
- +
- + reg = readl(ldb->control_reg);
- +
- + /* refrence resistor select */
- + reg &= ~LDB_BGREF_RMODE_MASK;
- + if (plat_data->ext_ref)
- + reg |= LDB_BGREF_RMODE_EXT;
- + else
- + reg |= LDB_BGREF_RMODE_INT;
- +
- + /* TODO: now only use SPWG data mapping for both channel */
- + reg &= ~(LDB_BIT_MAP_CH0_MASK | LDB_BIT_MAP_CH1_MASK);
- + reg |= LDB_BIT_MAP_CH0_SPWG | LDB_BIT_MAP_CH1_SPWG;
- +
- + /* channel mode setting */
- + reg &= ~(LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK);
- + reg &= ~(LDB_DATA_WIDTH_CH0_MASK | LDB_DATA_WIDTH_CH1_MASK);
- +
- + if (bits_per_pixel(setting->if_fmt) == 24)
- + reg |= LDB_DATA_WIDTH_CH0_24 | LDB_DATA_WIDTH_CH1_24;
- + else
- + reg |= LDB_DATA_WIDTH_CH0_18 | LDB_DATA_WIDTH_CH1_18;
- +
- + if (g_ldb_mode >= LDB_SPL_DI0)
- + ldb->mode = g_ldb_mode;
- + else
- + ldb->mode = plat_data->mode;
- +
- + if ((ldb->mode == LDB_SIN0) || (ldb->mode == LDB_SIN1)) {
- + ret = ldb->mode - LDB_SIN0;
- + if (plat_data->disp_id != ret) {
- + dev_warn(&ldb->pdev->dev,
- + "change IPU DI%d to IPU DI%d for LDB "
- + "channel%d.\n",
- + plat_data->disp_id, ret, ret);
- + plat_data->disp_id = ret;
- + }
- + } else if (((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1))
- + && is_imx6_ldb(plat_data)) {
- + if (plat_data->disp_id == plat_data->sec_disp_id) {
- + dev_err(&ldb->pdev->dev,
- + "For LVDS separate mode,"
- + "two DIs should be different!\n");
- + return -EINVAL;
- + }
- +
- + if (((!plat_data->disp_id) && (ldb->mode == LDB_SEP1))
- + || ((plat_data->disp_id) &&
- + (ldb->mode == LDB_SEP0))) {
- + dev_dbg(&ldb->pdev->dev,
- + "LVDS separate mode:"
- + "swap DI configuration!\n");
- + ipu_id = plat_data->ipu_id;
- + disp_id = plat_data->disp_id;
- + plat_data->ipu_id = plat_data->sec_ipu_id;
- + plat_data->disp_id = plat_data->sec_disp_id;
- + plat_data->sec_ipu_id = ipu_id;
- + plat_data->sec_disp_id = disp_id;
- + }
- + }
- +
- + if (ldb->mode == LDB_SPL_DI0) {
- + reg |= LDB_SPLIT_MODE_EN | LDB_CH0_MODE_EN_TO_DI0
- + | LDB_CH1_MODE_EN_TO_DI0;
- + setting->disp_id = 0;
- + } else if (ldb->mode == LDB_SPL_DI1) {
- + reg |= LDB_SPLIT_MODE_EN | LDB_CH0_MODE_EN_TO_DI1
- + | LDB_CH1_MODE_EN_TO_DI1;
- + setting->disp_id = 1;
- + } else if (ldb->mode == LDB_DUL_DI0) {
- + reg &= ~LDB_SPLIT_MODE_EN;
- + reg |= LDB_CH0_MODE_EN_TO_DI0 | LDB_CH1_MODE_EN_TO_DI0;
- + setting->disp_id = 0;
- + } else if (ldb->mode == LDB_DUL_DI1) {
- + reg &= ~LDB_SPLIT_MODE_EN;
- + reg |= LDB_CH0_MODE_EN_TO_DI1 | LDB_CH1_MODE_EN_TO_DI1;
- + setting->disp_id = 1;
- + } else if (ldb->mode == LDB_SIN0) {
- + reg &= ~LDB_SPLIT_MODE_EN;
- + setting->disp_id = plat_data->disp_id;
- + if (setting->disp_id == 0)
- + reg |= LDB_CH0_MODE_EN_TO_DI0;
- + else
- + reg |= LDB_CH0_MODE_EN_TO_DI1;
- + ch_mask = LDB_CH0_MODE_MASK;
- + ch_val = reg & LDB_CH0_MODE_MASK;
- + } else if (ldb->mode == LDB_SIN1) {
- + reg &= ~LDB_SPLIT_MODE_EN;
- + setting->disp_id = plat_data->disp_id;
- + if (setting->disp_id == 0)
- + reg |= LDB_CH1_MODE_EN_TO_DI0;
- + else
- + reg |= LDB_CH1_MODE_EN_TO_DI1;
- + ch_mask = LDB_CH1_MODE_MASK;
- + ch_val = reg & LDB_CH1_MODE_MASK;
- + } else { /* separate mode*/
- + setting->disp_id = plat_data->disp_id;
- +
- + /* first output is LVDS0 or LVDS1 */
- + if (ldb->mode == LDB_SEP0)
- + lvds_channel = 0;
- + else
- + lvds_channel = 1;
- +
- + reg &= ~LDB_SPLIT_MODE_EN;
- +
- + if ((lvds_channel == 0) && (setting->disp_id == 0))
- + reg |= LDB_CH0_MODE_EN_TO_DI0;
- + else if ((lvds_channel == 0) && (setting->disp_id == 1))
- + reg |= LDB_CH0_MODE_EN_TO_DI1;
- + else if ((lvds_channel == 1) && (setting->disp_id == 0))
- + reg |= LDB_CH1_MODE_EN_TO_DI0;
- + else
- + reg |= LDB_CH1_MODE_EN_TO_DI1;
- + ch_mask = lvds_channel ? LDB_CH1_MODE_MASK :
- + LDB_CH0_MODE_MASK;
- + ch_val = reg & ch_mask;
- +
- + if (bits_per_pixel(setting->if_fmt) == 24) {
- + if (lvds_channel == 0)
- + reg &= ~LDB_DATA_WIDTH_CH1_24;
- + else
- + reg &= ~LDB_DATA_WIDTH_CH0_24;
- + } else {
- + if (lvds_channel == 0)
- + reg &= ~LDB_DATA_WIDTH_CH1_18;
- + else
- + reg &= ~LDB_DATA_WIDTH_CH0_18;
- + }
- + }
- +
- + writel(reg, ldb->control_reg);
- + if (ldb->mode < LDB_SIN0) {
- + ch_mask = LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK;
- + ch_val = reg & (LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK);
- + }
- + } else { /* second time for separate mode */
- + if ((ldb->mode == LDB_SPL_DI0) ||
- + (ldb->mode == LDB_SPL_DI1) ||
- + (ldb->mode == LDB_DUL_DI0) ||
- + (ldb->mode == LDB_DUL_DI1) ||
- + (ldb->mode == LDB_SIN0) ||
- + (ldb->mode == LDB_SIN1)) {
- + dev_err(&ldb->pdev->dev, "for second ldb disp"
- + "ldb mode should in separate mode\n");
- + return -EINVAL;
- + }
- +
- + setting_idx = 1;
- + if (is_imx6_ldb(plat_data)) {
- + setting->dev_id = plat_data->sec_ipu_id;
- + setting->disp_id = plat_data->sec_disp_id;
- + } else {
- + setting->dev_id = plat_data->ipu_id;
- + setting->disp_id = !plat_data->disp_id;
- + }
- + if (setting->disp_id == ldb->setting[0].di) {
- + dev_err(&ldb->pdev->dev, "Err: for second ldb disp in"
- + "separate mode, DI should be different!\n");
- + return -EINVAL;
- + }
- +
- + /* second output is LVDS0 or LVDS1 */
- + if (ldb->mode == LDB_SEP0)
- + lvds_channel = 1;
- + else
- + lvds_channel = 0;
- +
- + reg = readl(ldb->control_reg);
- + if ((lvds_channel == 0) && (setting->disp_id == 0))
- + reg |= LDB_CH0_MODE_EN_TO_DI0;
- + else if ((lvds_channel == 0) && (setting->disp_id == 1))
- + reg |= LDB_CH0_MODE_EN_TO_DI1;
- + else if ((lvds_channel == 1) && (setting->disp_id == 0))
- + reg |= LDB_CH1_MODE_EN_TO_DI0;
- + else
- + reg |= LDB_CH1_MODE_EN_TO_DI1;
- + ch_mask = lvds_channel ? LDB_CH1_MODE_MASK :
- + LDB_CH0_MODE_MASK;
- + ch_val = reg & ch_mask;
- +
- + if (bits_per_pixel(setting->if_fmt) == 24) {
- + if (lvds_channel == 0)
- + reg |= LDB_DATA_WIDTH_CH0_24;
- + else
- + reg |= LDB_DATA_WIDTH_CH1_24;
- + } else {
- + if (lvds_channel == 0)
- + reg |= LDB_DATA_WIDTH_CH0_18;
- + else
- + reg |= LDB_DATA_WIDTH_CH1_18;
- + }
- + writel(reg, ldb->control_reg);
- + }
- +
- + /* get clocks */
- + if (is_imx6_ldb(plat_data) &&
- + ((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1))) {
- + ldb_clk[6] += lvds_channel;
- + div_3_5_clk[2] += lvds_channel;
- + div_7_clk[2] += lvds_channel;
- + div_sel_clk[2] += lvds_channel;
- + } else {
- + ldb_clk[6] += setting->disp_id;
- + div_3_5_clk[2] += setting->disp_id;
- + div_7_clk[2] += setting->disp_id;
- + div_sel_clk[2] += setting->disp_id;
- + }
- + ldb->setting[setting_idx].ldb_di_clk = clk_get(&ldb->pdev->dev,
- + ldb_clk);
- + if (IS_ERR(ldb->setting[setting_idx].ldb_di_clk)) {
- + dev_err(&ldb->pdev->dev, "get ldb clk failed\n");
- + return PTR_ERR(ldb->setting[setting_idx].ldb_di_clk);
- + }
- +
- + ldb->setting[setting_idx].div_3_5_clk = clk_get(&ldb->pdev->dev,
- + div_3_5_clk);
- + if (IS_ERR(ldb->setting[setting_idx].div_3_5_clk)) {
- + dev_err(&ldb->pdev->dev, "get div 3.5 clk failed\n");
- + return PTR_ERR(ldb->setting[setting_idx].div_3_5_clk);
- + }
- + ldb->setting[setting_idx].div_7_clk = clk_get(&ldb->pdev->dev,
- + div_7_clk);
- + if (IS_ERR(ldb->setting[setting_idx].div_7_clk)) {
- + dev_err(&ldb->pdev->dev, "get div 7 clk failed\n");
- + return PTR_ERR(ldb->setting[setting_idx].div_7_clk);
- + }
- +
- + ldb->setting[setting_idx].div_sel_clk = clk_get(&ldb->pdev->dev,
- + div_sel_clk);
- + if (IS_ERR(ldb->setting[setting_idx].div_sel_clk)) {
- + dev_err(&ldb->pdev->dev, "get div sel clk failed\n");
- + return PTR_ERR(ldb->setting[setting_idx].div_sel_clk);
- + }
- +
- + di_clk[3] += setting->dev_id;
- + di_clk[7] += setting->disp_id;
- + ldb->setting[setting_idx].di_clk = clk_get(&ldb->pdev->dev,
- + di_clk);
- + if (IS_ERR(ldb->setting[setting_idx].di_clk)) {
- + dev_err(&ldb->pdev->dev, "get di clk failed\n");
- + return PTR_ERR(ldb->setting[setting_idx].di_clk);
- + }
- +
- + ldb->setting[setting_idx].ch_mask = ch_mask;
- + ldb->setting[setting_idx].ch_val = ch_val;
- +
- + if (is_imx6_ldb(plat_data))
- + ldb_ipu_ldb_route(setting->dev_id, setting->disp_id, ldb);
- +
- + /* must use spec video mode defined by driver */
- + ret = fb_find_mode(&setting->fbi->var, setting->fbi, setting->dft_mode_str,
- + ldb_modedb, ldb_modedb_sz, NULL, setting->default_bpp);
- + if (ret != 1)
- + fb_videomode_to_var(&setting->fbi->var, &ldb_modedb[0]);
- +
- + INIT_LIST_HEAD(&setting->fbi->modelist);
- + for (i = 0; i < ldb_modedb_sz; i++) {
- + struct fb_videomode m;
- + fb_var_to_videomode(&m, &setting->fbi->var);
- + if (fb_mode_is_equal(&m, &ldb_modedb[i])) {
- + fb_add_videomode(&ldb_modedb[i],
- + &setting->fbi->modelist);
- + break;
- + }
- + }
- +
- + ldb->setting[setting_idx].ipu = setting->dev_id;
- + ldb->setting[setting_idx].di = setting->disp_id;
- +
- + return ret;
- +}
- +
- +static int ldb_post_disp_init(struct mxc_dispdrv_handle *disp,
- + int ipu_id, int disp_id)
- +{
- + struct ldb_data *ldb = mxc_dispdrv_getdata(disp);
- + int setting_idx = ldb->inited ? 1 : 0;
- + int ret = 0;
- +
- + if (!ldb->inited) {
- + ldb->nb.notifier_call = ldb_fb_event;
- + fb_register_client(&ldb->nb);
- + }
- +
- + ret = clk_set_parent(ldb->setting[setting_idx].di_clk,
- + ldb->setting[setting_idx].ldb_di_clk);
- + if (ret) {
- + dev_err(&ldb->pdev->dev, "fail to set ldb_di clk as"
- + "the parent of ipu_di clk\n");
- + return ret;
- + }
- +
- + if ((ldb->mode == LDB_SPL_DI0) || (ldb->mode == LDB_SPL_DI1)) {
- + ret = clk_set_parent(ldb->setting[setting_idx].div_sel_clk,
- + ldb->setting[setting_idx].div_3_5_clk);
- + if (ret) {
- + dev_err(&ldb->pdev->dev, "fail to set div 3.5 clk as"
- + "the parent of div sel clk\n");
- + return ret;
- + }
- + } else {
- + ret = clk_set_parent(ldb->setting[setting_idx].div_sel_clk,
- + ldb->setting[setting_idx].div_7_clk);
- + if (ret) {
- + dev_err(&ldb->pdev->dev, "fail to set div 7 clk as"
- + "the parent of div sel clk\n");
- + return ret;
- + }
- + }
- +
- + /* save active ldb setting for fb notifier */
- + ldb->setting[setting_idx].active = true;
- +
- + ldb->inited = true;
- + return ret;
- +}
- +
- +static void ldb_disp_deinit(struct mxc_dispdrv_handle *disp)
- +{
- + struct ldb_data *ldb = mxc_dispdrv_getdata(disp);
- + int i;
- +
- + writel(0, ldb->control_reg);
- +
- + for (i = 0; i < 2; i++) {
- + clk_disable(ldb->setting[i].ldb_di_clk);
- + clk_put(ldb->setting[i].ldb_di_clk);
- + clk_put(ldb->setting[i].div_3_5_clk);
- + clk_put(ldb->setting[i].div_7_clk);
- + clk_put(ldb->setting[i].div_sel_clk);
- + }
- +
- + fb_unregister_client(&ldb->nb);
- +}
- +
- +static struct mxc_dispdrv_driver ldb_drv = {
- + .name = DISPDRV_LDB,
- + .init = ldb_disp_init,
- + .post_init = ldb_post_disp_init,
- + .deinit = ldb_disp_deinit,
- + .setup = ldb_disp_setup,
- +};
- +
- +static int ldb_suspend(struct platform_device *pdev, pm_message_t state)
- +{
- + struct ldb_data *ldb = dev_get_drvdata(&pdev->dev);
- + uint32_t data;
- +
- + if (!ldb->inited)
- + return 0;
- + data = readl(ldb->control_reg);
- + ldb->control_reg_data = data;
- + data &= ~(LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK);
- + writel(data, ldb->control_reg);
- +
- + return 0;
- +}
- +
- +static int ldb_resume(struct platform_device *pdev)
- +{
- + struct ldb_data *ldb = dev_get_drvdata(&pdev->dev);
- +
- + if (!ldb->inited)
- + return 0;
- + writel(ldb->control_reg_data, ldb->control_reg);
- +
- + return 0;
- +}
- +
- +static struct platform_device_id imx_ldb_devtype[] = {
- + {
- + .name = "ldb-imx6",
- + .driver_data = LDB_IMX6,
- + }, {
- + /* sentinel */
- + }
- +};
- +
- +static const struct of_device_id imx_ldb_dt_ids[] = {
- + { .compatible = "fsl,imx6q-ldb", .data = &imx_ldb_devtype[IMX6_LDB],},
- + { /* sentinel */ }
- +};
- +
- +/*!
- + * This function is called by the driver framework to initialize the LDB
- + * device.
- + *
- + * @param dev The device structure for the LDB passed in by the
- + * driver framework.
- + *
- + * @return Returns 0 on success or negative error code on error
- + */
- +static int ldb_probe(struct platform_device *pdev)
- +{
- + int ret = 0;
- + struct ldb_data *ldb;
- + struct fsl_mxc_ldb_platform_data *plat_data;
- + const struct of_device_id *of_id =
- + of_match_device(imx_ldb_dt_ids, &pdev->dev);
- +
- + dev_dbg(&pdev->dev, "%s enter\n", __func__);
- + ldb = devm_kzalloc(&pdev->dev, sizeof(struct ldb_data), GFP_KERNEL);
- + if (!ldb)
- + return -ENOMEM;
- +
- + plat_data = devm_kzalloc(&pdev->dev,
- + sizeof(struct fsl_mxc_ldb_platform_data),
- + GFP_KERNEL);
- + if (!plat_data)
- + return -ENOMEM;
- + pdev->dev.platform_data = plat_data;
- + if (of_id)
- + pdev->id_entry = of_id->data;
- + plat_data->devtype = pdev->id_entry->driver_data;
- +
- + ret = ldb_get_of_property(pdev, plat_data);
- + if (ret < 0) {
- + dev_err(&pdev->dev, "get ldb of property fail\n");
- + return ret;
- + }
- +
- + ldb->pdev = pdev;
- + ldb->disp_ldb = mxc_dispdrv_register(&ldb_drv);
- + mxc_dispdrv_setdata(ldb->disp_ldb, ldb);
- +
- + dev_set_drvdata(&pdev->dev, ldb);
- +
- + dev_dbg(&pdev->dev, "%s exit\n", __func__);
- + return ret;
- +}
- +
- +static int ldb_remove(struct platform_device *pdev)
- +{
- + struct ldb_data *ldb = dev_get_drvdata(&pdev->dev);
- +
- + if (!ldb->inited)
- + return 0;
- + mxc_dispdrv_puthandle(ldb->disp_ldb);
- + mxc_dispdrv_unregister(ldb->disp_ldb);
- + return 0;
- +}
- +
- +static struct platform_driver mxcldb_driver = {
- + .driver = {
- + .name = "mxc_ldb",
- + .of_match_table = imx_ldb_dt_ids,
- + },
- + .probe = ldb_probe,
- + .remove = ldb_remove,
- + .suspend = ldb_suspend,
- + .resume = ldb_resume,
- +};
- +
- +static int __init ldb_init(void)
- +{
- + return platform_driver_register(&mxcldb_driver);
- +}
- +
- +static void __exit ldb_uninit(void)
- +{
- + platform_driver_unregister(&mxcldb_driver);
- +}
- +
- +module_init(ldb_init);
- +module_exit(ldb_uninit);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("MXC LDB driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/video/mxc/Makefile linux-3.14.35/drivers/video/mxc/Makefile
- --- linux-3.14.35.orig/drivers/video/mxc/Makefile 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/video/mxc/Makefile 2015-03-08 14:27:37.781684499 -0500
- @@ -0,0 +1,6 @@
- +obj-$(CONFIG_FB_MXC_LDB) += ldb.o
- +obj-$(CONFIG_FB_MXC_MIPI_DSI) += mipi_dsi.o
- +obj-$(CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL) += mxcfb_hx8369_wvga.o
- +obj-$(CONFIG_FB_MXC_HDMI) += mxc_hdmi.o
- +obj-$(CONFIG_FB_MXC_EDID) += mxc_edid.o
- +obj-$(CONFIG_FB_MXC_SYNC_PANEL) += mxc_dispdrv.o mxc_lcdif.o mxc_ipuv3_fb.o
- diff -Nur linux-3.14.35.orig/drivers/video/mxc/mipi_dsi.c linux-3.14.35/drivers/video/mxc/mipi_dsi.c
- --- linux-3.14.35.orig/drivers/video/mxc/mipi_dsi.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/video/mxc/mipi_dsi.c 2015-03-08 14:27:37.785684499 -0500
- @@ -0,0 +1,953 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#include <linux/types.h>
- +#include <linux/init.h>
- +#include <linux/platform_device.h>
- +#include <linux/err.h>
- +#include <linux/clk.h>
- +#include <linux/console.h>
- +#include <linux/io.h>
- +#include <linux/bitops.h>
- +#include <linux/ipu.h>
- +#include <linux/mfd/syscon.h>
- +#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
- +#include <linux/mipi_dsi.h>
- +#include <linux/module.h>
- +#include <linux/mxcfb.h>
- +#include <linux/backlight.h>
- +#include <linux/of_device.h>
- +#include <linux/regulator/consumer.h>
- +#include <linux/reset.h>
- +#include <linux/spinlock.h>
- +#include <linux/delay.h>
- +#include <video/mipi_display.h>
- +
- +#include "mxc_dispdrv.h"
- +#include "mipi_dsi.h"
- +
- +#define DISPDRV_MIPI "mipi_dsi"
- +#define ROUND_UP(x) ((x)+1)
- +#define NS2PS_RATIO (1000)
- +#define NUMBER_OF_CHUNKS (0x8)
- +#define NULL_PKT_SIZE (0x8)
- +#define PHY_BTA_MAXTIME (0xd00)
- +#define PHY_LP2HS_MAXTIME (0x40)
- +#define PHY_HS2LP_MAXTIME (0x40)
- +#define PHY_STOP_WAIT_TIME (0x20)
- +#define DSI_CLKMGR_CFG_CLK_DIV (0x107)
- +#define DSI_GEN_PLD_DATA_BUF_ENTRY (0x10)
- +#define MIPI_MUX_CTRL(v) (((v) & 0x3) << 4)
- +#define MIPI_LCD_SLEEP_MODE_DELAY (120)
- +#define MIPI_DSI_REG_RW_TIMEOUT (20)
- +#define MIPI_DSI_PHY_TIMEOUT (10)
- +
- +static struct mipi_dsi_match_lcd mipi_dsi_lcd_db[] = {
- +#ifdef CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL
- + {
- + "TRULY-WVGA",
- + {mipid_hx8369_get_lcd_videomode, mipid_hx8369_lcd_setup}
- + },
- +#endif
- + {
- + "", {NULL, NULL}
- + }
- +};
- +
- +struct _mipi_dsi_phy_pll_clk {
- + u32 max_phy_clk;
- + u32 config;
- +};
- +
- +/* configure data for DPHY PLL 27M reference clk out */
- +static const struct _mipi_dsi_phy_pll_clk mipi_dsi_phy_pll_clk_table[] = {
- + {1000, 0x74}, /* 950-1000MHz */
- + {950, 0x54}, /* 900-950Mhz */
- + {900, 0x34}, /* 850-900Mhz */
- + {850, 0x14}, /* 800-850MHz */
- + {800, 0x32}, /* 750-800MHz */
- + {750, 0x12}, /* 700-750Mhz */
- + {700, 0x30}, /* 650-700Mhz */
- + {650, 0x10}, /* 600-650MHz */
- + {600, 0x2e}, /* 550-600MHz */
- + {550, 0x0e}, /* 500-550Mhz */
- + {500, 0x2c}, /* 450-500Mhz */
- + {450, 0x0c}, /* 400-450MHz */
- + {400, 0x4a}, /* 360-400MHz */
- + {360, 0x2a}, /* 330-360Mhz */
- + {330, 0x48}, /* 300-330Mhz */
- + {300, 0x28}, /* 270-300MHz */
- + {270, 0x08}, /* 250-270MHz */
- + {250, 0x46}, /* 240-250Mhz */
- + {240, 0x26}, /* 210-240Mhz */
- + {210, 0x06}, /* 200-210MHz */
- + {200, 0x44}, /* 180-200MHz */
- + {180, 0x24}, /* 160-180MHz */
- + {160, 0x04}, /* 150-160MHz */
- +};
- +
- +static int valid_mode(int pixel_fmt)
- +{
- + return ((pixel_fmt == IPU_PIX_FMT_RGB24) ||
- + (pixel_fmt == IPU_PIX_FMT_BGR24) ||
- + (pixel_fmt == IPU_PIX_FMT_RGB666) ||
- + (pixel_fmt == IPU_PIX_FMT_RGB565) ||
- + (pixel_fmt == IPU_PIX_FMT_BGR666) ||
- + (pixel_fmt == IPU_PIX_FMT_RGB332));
- +}
- +
- +static inline void mipi_dsi_read_register(struct mipi_dsi_info *mipi_dsi,
- + u32 reg, u32 *val)
- +{
- + *val = ioread32(mipi_dsi->mmio_base + reg);
- + dev_dbg(&mipi_dsi->pdev->dev, "read_reg:0x%02x, val:0x%08x.\n",
- + reg, *val);
- +}
- +
- +static inline void mipi_dsi_write_register(struct mipi_dsi_info *mipi_dsi,
- + u32 reg, u32 val)
- +{
- + iowrite32(val, mipi_dsi->mmio_base + reg);
- + dev_dbg(&mipi_dsi->pdev->dev, "\t\twrite_reg:0x%02x, val:0x%08x.\n",
- + reg, val);
- +}
- +
- +int mipi_dsi_pkt_write(struct mipi_dsi_info *mipi_dsi,
- + u8 data_type, const u32 *buf, int len)
- +{
- + u32 val;
- + u32 status = 0;
- + int write_len = len;
- + uint32_t timeout = 0;
- +
- + if (len) {
- + /* generic long write command */
- + while (len / DSI_GEN_PLD_DATA_BUF_SIZE) {
- + mipi_dsi_write_register(mipi_dsi,
- + MIPI_DSI_GEN_PLD_DATA, *buf);
- + buf++;
- + len -= DSI_GEN_PLD_DATA_BUF_SIZE;
- + mipi_dsi_read_register(mipi_dsi,
- + MIPI_DSI_CMD_PKT_STATUS, &status);
- + while ((status & DSI_CMD_PKT_STATUS_GEN_PLD_W_FULL) ==
- + DSI_CMD_PKT_STATUS_GEN_PLD_W_FULL) {
- + msleep(1);
- + timeout++;
- + if (timeout == MIPI_DSI_REG_RW_TIMEOUT)
- + return -EIO;
- + mipi_dsi_read_register(mipi_dsi,
- + MIPI_DSI_CMD_PKT_STATUS, &status);
- + }
- + }
- + /* write the remainder bytes */
- + if (len > 0) {
- + while ((status & DSI_CMD_PKT_STATUS_GEN_PLD_W_FULL) ==
- + DSI_CMD_PKT_STATUS_GEN_PLD_W_FULL) {
- + msleep(1);
- + timeout++;
- + if (timeout == MIPI_DSI_REG_RW_TIMEOUT)
- + return -EIO;
- + mipi_dsi_read_register(mipi_dsi,
- + MIPI_DSI_CMD_PKT_STATUS, &status);
- + }
- + mipi_dsi_write_register(mipi_dsi,
- + MIPI_DSI_GEN_PLD_DATA, *buf);
- + }
- +
- + val = data_type | ((write_len & DSI_GEN_HDR_DATA_MASK)
- + << DSI_GEN_HDR_DATA_SHIFT);
- + } else {
- + /* generic short write command */
- + val = data_type | ((*buf & DSI_GEN_HDR_DATA_MASK)
- + << DSI_GEN_HDR_DATA_SHIFT);
- + }
- +
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS, &status);
- + while ((status & DSI_CMD_PKT_STATUS_GEN_CMD_FULL) ==
- + DSI_CMD_PKT_STATUS_GEN_CMD_FULL) {
- + msleep(1);
- + timeout++;
- + if (timeout == MIPI_DSI_REG_RW_TIMEOUT)
- + return -EIO;
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS,
- + &status);
- + }
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_GEN_HDR, val);
- +
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS, &status);
- + while (!((status & DSI_CMD_PKT_STATUS_GEN_CMD_EMPTY) ==
- + DSI_CMD_PKT_STATUS_GEN_CMD_EMPTY) ||
- + !((status & DSI_CMD_PKT_STATUS_GEN_PLD_W_EMPTY) ==
- + DSI_CMD_PKT_STATUS_GEN_PLD_W_EMPTY)) {
- + msleep(1);
- + timeout++;
- + if (timeout == MIPI_DSI_REG_RW_TIMEOUT)
- + return -EIO;
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS,
- + &status);
- + }
- +
- + return 0;
- +}
- +
- +int mipi_dsi_pkt_read(struct mipi_dsi_info *mipi_dsi,
- + u8 data_type, u32 *buf, int len)
- +{
- + u32 val;
- + int read_len = 0;
- + uint32_t timeout = 0;
- +
- + if (!len) {
- + mipi_dbg("%s, len = 0 invalid error!\n", __func__);
- + return -EINVAL;
- + }
- +
- + val = data_type | ((*buf & DSI_GEN_HDR_DATA_MASK)
- + << DSI_GEN_HDR_DATA_SHIFT);
- + memset(buf, 0, len);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_GEN_HDR, val);
- +
- + /* wait for cmd to sent out */
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS, &val);
- + while ((val & DSI_CMD_PKT_STATUS_GEN_RD_CMD_BUSY) !=
- + DSI_CMD_PKT_STATUS_GEN_RD_CMD_BUSY) {
- + msleep(1);
- + timeout++;
- + if (timeout == MIPI_DSI_REG_RW_TIMEOUT)
- + return -EIO;
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS,
- + &val);
- + }
- + /* wait for entire response stroed in FIFO */
- + while ((val & DSI_CMD_PKT_STATUS_GEN_RD_CMD_BUSY) ==
- + DSI_CMD_PKT_STATUS_GEN_RD_CMD_BUSY) {
- + msleep(1);
- + timeout++;
- + if (timeout == MIPI_DSI_REG_RW_TIMEOUT)
- + return -EIO;
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS,
- + &val);
- + }
- +
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS, &val);
- + while (!(val & DSI_CMD_PKT_STATUS_GEN_PLD_R_EMPTY)) {
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_GEN_PLD_DATA, buf);
- + read_len += DSI_GEN_PLD_DATA_BUF_SIZE;
- + buf++;
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS,
- + &val);
- + if (read_len == (DSI_GEN_PLD_DATA_BUF_ENTRY *
- + DSI_GEN_PLD_DATA_BUF_SIZE))
- + break;
- + }
- +
- + if ((len <= read_len) &&
- + ((len + DSI_GEN_PLD_DATA_BUF_SIZE) >= read_len))
- + return 0;
- + else {
- + dev_err(&mipi_dsi->pdev->dev,
- + "actually read_len:%d != len:%d.\n", read_len, len);
- + return -ERANGE;
- + }
- +}
- +
- +int mipi_dsi_dcs_cmd(struct mipi_dsi_info *mipi_dsi,
- + u8 cmd, const u32 *param, int num)
- +{
- + int err = 0;
- + u32 buf[DSI_CMD_BUF_MAXSIZE];
- +
- + switch (cmd) {
- + case MIPI_DCS_EXIT_SLEEP_MODE:
- + case MIPI_DCS_ENTER_SLEEP_MODE:
- + case MIPI_DCS_SET_DISPLAY_ON:
- + case MIPI_DCS_SET_DISPLAY_OFF:
- + buf[0] = cmd;
- + err = mipi_dsi_pkt_write(mipi_dsi,
- + MIPI_DSI_DCS_SHORT_WRITE, buf, 0);
- + break;
- +
- + default:
- + dev_err(&mipi_dsi->pdev->dev,
- + "MIPI DSI DCS Command:0x%x Not supported!\n", cmd);
- + break;
- + }
- +
- + return err;
- +}
- +
- +static void mipi_dsi_dphy_init(struct mipi_dsi_info *mipi_dsi,
- + u32 cmd, u32 data)
- +{
- + u32 val;
- + u32 timeout = 0;
- +
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_IF_CTRL,
- + DSI_PHY_IF_CTRL_RESET);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PWR_UP, DSI_PWRUP_POWERUP);
- +
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_TST_CTRL0, 0);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_TST_CTRL1,
- + (0x10000 | cmd));
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_TST_CTRL0, 2);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_TST_CTRL0, 0);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_TST_CTRL1, (0 | data));
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_TST_CTRL0, 2);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_TST_CTRL0, 0);
- + val = DSI_PHY_RSTZ_EN_CLK | DSI_PHY_RSTZ_DISABLE_RST |
- + DSI_PHY_RSTZ_DISABLE_SHUTDOWN;
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_RSTZ, val);
- +
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_PHY_STATUS, &val);
- + while ((val & DSI_PHY_STATUS_LOCK) != DSI_PHY_STATUS_LOCK) {
- + msleep(1);
- + timeout++;
- + if (timeout == MIPI_DSI_PHY_TIMEOUT) {
- + dev_err(&mipi_dsi->pdev->dev,
- + "Error: phy lock timeout!\n");
- + break;
- + }
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_PHY_STATUS, &val);
- + }
- + timeout = 0;
- + while ((val & DSI_PHY_STATUS_STOPSTATE_CLK_LANE) !=
- + DSI_PHY_STATUS_STOPSTATE_CLK_LANE) {
- + msleep(1);
- + timeout++;
- + if (timeout == MIPI_DSI_PHY_TIMEOUT) {
- + dev_err(&mipi_dsi->pdev->dev,
- + "Error: phy lock lane timeout!\n");
- + break;
- + }
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_PHY_STATUS, &val);
- + }
- +}
- +
- +static void mipi_dsi_enable_controller(struct mipi_dsi_info *mipi_dsi,
- + bool init)
- +{
- + u32 val;
- + u32 lane_byte_clk_period;
- + struct fb_videomode *mode = mipi_dsi->mode;
- + struct mipi_lcd_config *lcd_config = mipi_dsi->lcd_config;
- +
- + if (init) {
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PWR_UP,
- + DSI_PWRUP_RESET);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_RSTZ,
- + DSI_PHY_RSTZ_RST);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_CLKMGR_CFG,
- + DSI_CLKMGR_CFG_CLK_DIV);
- +
- + if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
- + val = DSI_DPI_CFG_VSYNC_ACT_LOW;
- + if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
- + val |= DSI_DPI_CFG_HSYNC_ACT_LOW;
- + if ((mode->sync & FB_SYNC_OE_LOW_ACT))
- + val |= DSI_DPI_CFG_DATAEN_ACT_LOW;
- + if (MIPI_RGB666_LOOSELY == lcd_config->dpi_fmt)
- + val |= DSI_DPI_CFG_EN18LOOSELY;
- + val |= (lcd_config->dpi_fmt & DSI_DPI_CFG_COLORCODE_MASK)
- + << DSI_DPI_CFG_COLORCODE_SHIFT;
- + val |= (lcd_config->virtual_ch & DSI_DPI_CFG_VID_MASK)
- + << DSI_DPI_CFG_VID_SHIFT;
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_DPI_CFG, val);
- +
- + val = DSI_PCKHDL_CFG_EN_BTA |
- + DSI_PCKHDL_CFG_EN_ECC_RX |
- + DSI_PCKHDL_CFG_EN_CRC_RX;
- +
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PCKHDL_CFG, val);
- +
- + val = (mode->xres & DSI_VID_PKT_CFG_VID_PKT_SZ_MASK)
- + << DSI_VID_PKT_CFG_VID_PKT_SZ_SHIFT;
- + val |= (NUMBER_OF_CHUNKS & DSI_VID_PKT_CFG_NUM_CHUNKS_MASK)
- + << DSI_VID_PKT_CFG_NUM_CHUNKS_SHIFT;
- + val |= (NULL_PKT_SIZE & DSI_VID_PKT_CFG_NULL_PKT_SZ_MASK)
- + << DSI_VID_PKT_CFG_NULL_PKT_SZ_SHIFT;
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_VID_PKT_CFG, val);
- +
- + /* enable LP mode when TX DCS cmd and enable DSI command mode */
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_CMD_MODE_CFG,
- + MIPI_DSI_CMD_MODE_CFG_EN_LOWPOWER);
- +
- + /* mipi lane byte clk period in ns unit */
- + lane_byte_clk_period = NS2PS_RATIO /
- + (lcd_config->max_phy_clk / BITS_PER_BYTE);
- + val = ROUND_UP(mode->hsync_len * mode->pixclock /
- + NS2PS_RATIO / lane_byte_clk_period)
- + << DSI_TME_LINE_CFG_HSA_TIME_SHIFT;
- + val |= ROUND_UP(mode->left_margin * mode->pixclock /
- + NS2PS_RATIO / lane_byte_clk_period)
- + << DSI_TME_LINE_CFG_HBP_TIME_SHIFT;
- + val |= ROUND_UP((mode->left_margin + mode->right_margin +
- + mode->hsync_len + mode->xres) * mode->pixclock
- + / NS2PS_RATIO / lane_byte_clk_period)
- + << DSI_TME_LINE_CFG_HLINE_TIME_SHIFT;
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_TMR_LINE_CFG, val);
- +
- + val = ((mode->vsync_len & DSI_VTIMING_CFG_VSA_LINES_MASK)
- + << DSI_VTIMING_CFG_VSA_LINES_SHIFT);
- + val |= ((mode->upper_margin & DSI_VTIMING_CFG_VBP_LINES_MASK)
- + << DSI_VTIMING_CFG_VBP_LINES_SHIFT);
- + val |= ((mode->lower_margin & DSI_VTIMING_CFG_VFP_LINES_MASK)
- + << DSI_VTIMING_CFG_VFP_LINES_SHIFT);
- + val |= ((mode->yres & DSI_VTIMING_CFG_V_ACT_LINES_MASK)
- + << DSI_VTIMING_CFG_V_ACT_LINES_SHIFT);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_VTIMING_CFG, val);
- +
- + val = ((PHY_BTA_MAXTIME & DSI_PHY_TMR_CFG_BTA_TIME_MASK)
- + << DSI_PHY_TMR_CFG_BTA_TIME_SHIFT);
- + val |= ((PHY_LP2HS_MAXTIME & DSI_PHY_TMR_CFG_LP2HS_TIME_MASK)
- + << DSI_PHY_TMR_CFG_LP2HS_TIME_SHIFT);
- + val |= ((PHY_HS2LP_MAXTIME & DSI_PHY_TMR_CFG_HS2LP_TIME_MASK)
- + << DSI_PHY_TMR_CFG_HS2LP_TIME_SHIFT);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_TMR_CFG, val);
- +
- + val = (((lcd_config->data_lane_num - 1) &
- + DSI_PHY_IF_CFG_N_LANES_MASK)
- + << DSI_PHY_IF_CFG_N_LANES_SHIFT);
- + val |= ((PHY_STOP_WAIT_TIME & DSI_PHY_IF_CFG_WAIT_TIME_MASK)
- + << DSI_PHY_IF_CFG_WAIT_TIME_SHIFT);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_IF_CFG, val);
- +
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_ERROR_ST0, &val);
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_ERROR_ST1, &val);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_ERROR_MSK0, 0);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_ERROR_MSK1, 0);
- +
- + mipi_dsi_dphy_init(mipi_dsi, DSI_PHY_CLK_INIT_COMMAND,
- + mipi_dsi->dphy_pll_config);
- + } else {
- + mipi_dsi_dphy_init(mipi_dsi, DSI_PHY_CLK_INIT_COMMAND,
- + mipi_dsi->dphy_pll_config);
- + }
- +}
- +
- +static void mipi_dsi_disable_controller(struct mipi_dsi_info *mipi_dsi)
- +{
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_IF_CTRL,
- + DSI_PHY_IF_CTRL_RESET);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PWR_UP, DSI_PWRUP_RESET);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_RSTZ, DSI_PHY_RSTZ_RST);
- +}
- +
- +static irqreturn_t mipi_dsi_irq_handler(int irq, void *data)
- +{
- + u32 mask0;
- + u32 mask1;
- + u32 status0;
- + u32 status1;
- + struct mipi_dsi_info *mipi_dsi;
- +
- + mipi_dsi = (struct mipi_dsi_info *)data;
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_ERROR_ST0, &status0);
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_ERROR_ST1, &status1);
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_ERROR_MSK0, &mask0);
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_ERROR_MSK1, &mask1);
- +
- + if ((status0 & (~mask0)) || (status1 & (~mask1))) {
- + dev_err(&mipi_dsi->pdev->dev,
- + "mipi_dsi IRQ status0:0x%x, status1:0x%x!\n",
- + status0, status1);
- + }
- +
- + return IRQ_HANDLED;
- +}
- +
- +static inline void mipi_dsi_set_mode(struct mipi_dsi_info *mipi_dsi,
- + bool cmd_mode)
- +{
- + u32 val;
- +
- + if (cmd_mode) {
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PWR_UP,
- + DSI_PWRUP_RESET);
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_MODE_CFG, &val);
- + val |= MIPI_DSI_CMD_MODE_CFG_EN_CMD_MODE;
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_CMD_MODE_CFG, val);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_VID_MODE_CFG, 0);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PWR_UP,
- + DSI_PWRUP_POWERUP);
- + } else {
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PWR_UP,
- + DSI_PWRUP_RESET);
- + /* Disable Command mode when tranfering video data */
- + mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_MODE_CFG, &val);
- + val &= ~MIPI_DSI_CMD_MODE_CFG_EN_CMD_MODE;
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_CMD_MODE_CFG, val);
- + val = DSI_VID_MODE_CFG_EN | DSI_VID_MODE_CFG_EN_BURSTMODE |
- + DSI_VID_MODE_CFG_EN_LP_MODE;
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_VID_MODE_CFG, val);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PWR_UP,
- + DSI_PWRUP_POWERUP);
- + mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_IF_CTRL,
- + DSI_PHY_IF_CTRL_TX_REQ_CLK_HS);
- + }
- +}
- +
- +static int mipi_dsi_power_on(struct mxc_dispdrv_handle *disp)
- +{
- + int err;
- + struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
- +
- + if (!mipi_dsi->dsi_power_on) {
- + clk_prepare_enable(mipi_dsi->dphy_clk);
- + clk_prepare_enable(mipi_dsi->cfg_clk);
- + mipi_dsi_enable_controller(mipi_dsi, false);
- + mipi_dsi_set_mode(mipi_dsi, false);
- + /* host send pclk/hsync/vsync for two frames before sleep-out */
- + msleep((1000/mipi_dsi->mode->refresh + 1) << 1);
- + mipi_dsi_set_mode(mipi_dsi, true);
- + err = mipi_dsi_dcs_cmd(mipi_dsi, MIPI_DCS_EXIT_SLEEP_MODE,
- + NULL, 0);
- + if (err) {
- + dev_err(&mipi_dsi->pdev->dev,
- + "MIPI DSI DCS Command sleep-in error!\n");
- + }
- + msleep(MIPI_LCD_SLEEP_MODE_DELAY);
- + mipi_dsi_set_mode(mipi_dsi, false);
- + mipi_dsi->dsi_power_on = 1;
- + }
- +
- + return 0;
- +}
- +
- +void mipi_dsi_power_off(struct mxc_dispdrv_handle *disp)
- +{
- + int err;
- + struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
- +
- + if (mipi_dsi->dsi_power_on) {
- + mipi_dsi_set_mode(mipi_dsi, true);
- + err = mipi_dsi_dcs_cmd(mipi_dsi, MIPI_DCS_ENTER_SLEEP_MODE,
- + NULL, 0);
- + if (err) {
- + dev_err(&mipi_dsi->pdev->dev,
- + "MIPI DSI DCS Command display on error!\n");
- + }
- + /* To allow time for the supply voltages
- + * and clock circuits to stabilize.
- + */
- + msleep(5);
- + /* video stream timing on */
- + mipi_dsi_set_mode(mipi_dsi, false);
- + msleep(MIPI_LCD_SLEEP_MODE_DELAY);
- +
- + mipi_dsi_set_mode(mipi_dsi, true);
- + mipi_dsi_disable_controller(mipi_dsi);
- + mipi_dsi->dsi_power_on = 0;
- + clk_disable_unprepare(mipi_dsi->dphy_clk);
- + clk_disable_unprepare(mipi_dsi->cfg_clk);
- + }
- +}
- +
- +static int mipi_dsi_lcd_init(struct mipi_dsi_info *mipi_dsi,
- + struct mxc_dispdrv_setting *setting)
- +{
- + int err;
- + int size;
- + int i;
- + struct fb_videomode *mipi_lcd_modedb;
- + struct fb_videomode mode;
- + struct device *dev = &mipi_dsi->pdev->dev;
- +
- + for (i = 0; i < ARRAY_SIZE(mipi_dsi_lcd_db); i++) {
- + if (!strcmp(mipi_dsi->lcd_panel,
- + mipi_dsi_lcd_db[i].lcd_panel)) {
- + mipi_dsi->lcd_callback =
- + &mipi_dsi_lcd_db[i].lcd_callback;
- + break;
- + }
- + }
- + if (i == ARRAY_SIZE(mipi_dsi_lcd_db)) {
- + dev_err(dev, "failed to find supported lcd panel.\n");
- + return -EINVAL;
- + }
- + /* get the videomode in the order: cmdline->platform data->driver */
- + mipi_dsi->lcd_callback->get_mipi_lcd_videomode(&mipi_lcd_modedb, &size,
- + &mipi_dsi->lcd_config);
- + err = fb_find_mode(&setting->fbi->var, setting->fbi,
- + setting->dft_mode_str,
- + mipi_lcd_modedb, size, NULL,
- + setting->default_bpp);
- + if (err != 1)
- + fb_videomode_to_var(&setting->fbi->var, mipi_lcd_modedb);
- +
- + INIT_LIST_HEAD(&setting->fbi->modelist);
- + for (i = 0; i < size; i++) {
- + fb_var_to_videomode(&mode, &setting->fbi->var);
- + if (fb_mode_is_equal(&mode, mipi_lcd_modedb + i)) {
- + err = fb_add_videomode(mipi_lcd_modedb + i,
- + &setting->fbi->modelist);
- + /* Note: only support fb mode from driver */
- + mipi_dsi->mode = mipi_lcd_modedb + i;
- + break;
- + }
- + }
- + if ((err < 0) || (size == i)) {
- + dev_err(dev, "failed to add videomode.\n");
- + return err;
- + }
- +
- + for (i = 0; i < ARRAY_SIZE(mipi_dsi_phy_pll_clk_table); i++) {
- + if (mipi_dsi_phy_pll_clk_table[i].max_phy_clk <
- + mipi_dsi->lcd_config->max_phy_clk)
- + break;
- + }
- + if ((i == ARRAY_SIZE(mipi_dsi_phy_pll_clk_table)) ||
- + (mipi_dsi->lcd_config->max_phy_clk >
- + mipi_dsi_phy_pll_clk_table[0].max_phy_clk)) {
- + dev_err(dev, "failed to find data in"
- + "mipi_dsi_phy_pll_clk_table.\n");
- + return -EINVAL;
- + }
- + mipi_dsi->dphy_pll_config = mipi_dsi_phy_pll_clk_table[--i].config;
- + dev_dbg(dev, "dphy_pll_config:0x%x.\n", mipi_dsi->dphy_pll_config);
- +
- + return 0;
- +}
- +
- +int mipi_dsi_enable(struct mxc_dispdrv_handle *disp)
- +{
- + int err;
- + struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
- +
- + if (!mipi_dsi->lcd_inited) {
- + err = clk_prepare_enable(mipi_dsi->dphy_clk);
- + err |= clk_prepare_enable(mipi_dsi->cfg_clk);
- + if (err)
- + dev_err(&mipi_dsi->pdev->dev,
- + "clk enable error:%d!\n", err);
- + mipi_dsi_enable_controller(mipi_dsi, true);
- + err = mipi_dsi->lcd_callback->mipi_lcd_setup(
- + mipi_dsi);
- + if (err < 0) {
- + dev_err(&mipi_dsi->pdev->dev,
- + "failed to init mipi lcd.");
- + clk_disable_unprepare(mipi_dsi->dphy_clk);
- + clk_disable_unprepare(mipi_dsi->cfg_clk);
- + return err;
- + }
- + mipi_dsi_set_mode(mipi_dsi, false);
- + mipi_dsi->dsi_power_on = 1;
- + mipi_dsi->lcd_inited = 1;
- + }
- + mipi_dsi_power_on(mipi_dsi->disp_mipi);
- +
- + return 0;
- +}
- +
- +static int mipi_dsi_disp_init(struct mxc_dispdrv_handle *disp,
- + struct mxc_dispdrv_setting *setting)
- +{
- + struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
- + struct device *dev = &mipi_dsi->pdev->dev;
- + int ret = 0;
- +
- + if (!valid_mode(setting->if_fmt)) {
- + dev_warn(dev, "Input pixel format not valid"
- + "use default RGB24\n");
- + setting->if_fmt = IPU_PIX_FMT_RGB24;
- + }
- +
- + setting->dev_id = mipi_dsi->dev_id;
- + setting->disp_id = mipi_dsi->disp_id;
- +
- + ret = mipi_dsi_lcd_init(mipi_dsi, setting);
- + if (ret) {
- + dev_err(dev, "failed to init mipi dsi lcd\n");
- + return ret;
- + }
- +
- + dev_dbg(dev, "MIPI DSI dispdrv inited!\n");
- + return ret;
- +}
- +
- +static void mipi_dsi_disp_deinit(struct mxc_dispdrv_handle *disp)
- +{
- + struct mipi_dsi_info *mipi_dsi;
- +
- + mipi_dsi = mxc_dispdrv_getdata(disp);
- +
- + mipi_dsi_power_off(mipi_dsi->disp_mipi);
- + if (mipi_dsi->bl)
- + backlight_device_unregister(mipi_dsi->bl);
- +}
- +
- +static struct mxc_dispdrv_driver mipi_dsi_drv = {
- + .name = DISPDRV_MIPI,
- + .init = mipi_dsi_disp_init,
- + .deinit = mipi_dsi_disp_deinit,
- + .enable = mipi_dsi_enable,
- + .disable = mipi_dsi_power_off,
- +};
- +
- +static int imx6q_mipi_dsi_get_mux(int dev_id, int disp_id)
- +{
- + if (dev_id > 1 || disp_id > 1)
- + return -EINVAL;
- +
- + return (dev_id << 5) | (disp_id << 4);
- +}
- +
- +static struct mipi_dsi_bus_mux imx6q_mipi_dsi_mux[] = {
- + {
- + .reg = IOMUXC_GPR3,
- + .mask = IMX6Q_GPR3_MIPI_MUX_CTL_MASK,
- + .get_mux = imx6q_mipi_dsi_get_mux,
- + },
- +};
- +
- +static int imx6dl_mipi_dsi_get_mux(int dev_id, int disp_id)
- +{
- + if (dev_id > 1 || disp_id > 1)
- + return -EINVAL;
- +
- + /* MIPI DSI source is LCDIF */
- + if (dev_id)
- + disp_id = 0;
- +
- + return (dev_id << 5) | (disp_id << 4);
- +}
- +
- +static struct mipi_dsi_bus_mux imx6dl_mipi_dsi_mux[] = {
- + {
- + .reg = IOMUXC_GPR3,
- + .mask = IMX6Q_GPR3_MIPI_MUX_CTL_MASK,
- + .get_mux = imx6dl_mipi_dsi_get_mux,
- + },
- +};
- +
- +static const struct of_device_id imx_mipi_dsi_dt_ids[] = {
- + { .compatible = "fsl,imx6q-mipi-dsi", .data = imx6q_mipi_dsi_mux, },
- + { .compatible = "fsl,imx6dl-mipi-dsi", .data = imx6dl_mipi_dsi_mux, },
- + { }
- +};
- +MODULE_DEVICE_TABLE(of, imx_mipi_dsi_dt_ids);
- +
- +/**
- + * This function is called by the driver framework to initialize the MIPI DSI
- + * device.
- + *
- + * @param pdev The device structure for the MIPI DSI passed in by the
- + * driver framework.
- + *
- + * @return Returns 0 on success or negative error code on error
- + */
- +static int mipi_dsi_probe(struct platform_device *pdev)
- +{
- + struct device_node *np = pdev->dev.of_node;
- + const struct of_device_id *of_id =
- + of_match_device(of_match_ptr(imx_mipi_dsi_dt_ids),
- + &pdev->dev);
- + struct mipi_dsi_info *mipi_dsi;
- + struct resource *res;
- + u32 dev_id, disp_id;
- + const char *lcd_panel;
- + unsigned int mux;
- + int ret = 0;
- +
- + mipi_dsi = devm_kzalloc(&pdev->dev, sizeof(*mipi_dsi), GFP_KERNEL);
- + if (!mipi_dsi)
- + return -ENOMEM;
- +
- + ret = of_property_read_string(np, "lcd_panel", &lcd_panel);
- + if (ret) {
- + dev_err(&pdev->dev, "failed to read of property lcd_panel\n");
- + return ret;
- + }
- +
- + ret = of_property_read_u32(np, "dev_id", &dev_id);
- + if (ret) {
- + dev_err(&pdev->dev, "failed to read of property dev_id\n");
- + return ret;
- + }
- + ret = of_property_read_u32(np, "disp_id", &disp_id);
- + if (ret) {
- + dev_err(&pdev->dev, "failed to read of property disp_id\n");
- + return ret;
- + }
- + mipi_dsi->dev_id = dev_id;
- + mipi_dsi->disp_id = disp_id;
- +
- + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- + if (!res) {
- + dev_err(&pdev->dev, "failed to get platform resource 0\n");
- + return -ENODEV;
- + }
- +
- + if (!devm_request_mem_region(&pdev->dev, res->start,
- + resource_size(res), pdev->name))
- + return -EBUSY;
- +
- + mipi_dsi->mmio_base = devm_ioremap(&pdev->dev, res->start,
- + resource_size(res));
- + if (!mipi_dsi->mmio_base)
- + return -EBUSY;
- +
- + mipi_dsi->irq = platform_get_irq(pdev, 0);
- + if (mipi_dsi->irq < 0) {
- + dev_err(&pdev->dev, "failed get device irq\n");
- + return -ENODEV;
- + }
- +
- + ret = devm_request_irq(&pdev->dev, mipi_dsi->irq,
- + mipi_dsi_irq_handler,
- + 0, "mipi_dsi", mipi_dsi);
- + if (ret) {
- + dev_err(&pdev->dev, "failed to request irq\n");
- + return ret;
- + }
- +
- + mipi_dsi->dphy_clk = devm_clk_get(&pdev->dev, "mipi_pllref_clk");
- + if (IS_ERR(mipi_dsi->dphy_clk)) {
- + dev_err(&pdev->dev, "failed to get dphy pll_ref_clk\n");
- + return PTR_ERR(mipi_dsi->dphy_clk);
- + }
- +
- + mipi_dsi->cfg_clk = devm_clk_get(&pdev->dev, "mipi_cfg_clk");
- + if (IS_ERR(mipi_dsi->cfg_clk)) {
- + dev_err(&pdev->dev, "failed to get cfg_clk\n");
- + return PTR_ERR(mipi_dsi->cfg_clk);
- + }
- +
- + mipi_dsi->disp_power_on = devm_regulator_get(&pdev->dev,
- + "disp-power-on");
- + if (!IS_ERR(mipi_dsi->disp_power_on)) {
- + ret = regulator_enable(mipi_dsi->disp_power_on);
- + if (ret) {
- + dev_err(&pdev->dev, "failed to enable display "
- + "power regulator, err=%d\n", ret);
- + return ret;
- + }
- + } else {
- + mipi_dsi->disp_power_on = NULL;
- + }
- +
- + ret = device_reset(&pdev->dev);
- + if (ret) {
- + dev_err(&pdev->dev, "failed to reset: %d\n", ret);
- + goto dev_reset_fail;
- + }
- +
- + if (of_id)
- + mipi_dsi->bus_mux = of_id->data;
- +
- + mipi_dsi->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
- + if (IS_ERR(mipi_dsi->regmap)) {
- + dev_err(&pdev->dev, "failed to get parent regmap\n");
- + ret = PTR_ERR(mipi_dsi->regmap);
- + goto get_parent_regmap_fail;
- + }
- +
- + mux = mipi_dsi->bus_mux->get_mux(dev_id, disp_id);
- + if (mux >= 0)
- + regmap_update_bits(mipi_dsi->regmap, mipi_dsi->bus_mux->reg,
- + mipi_dsi->bus_mux->mask, mux);
- + else
- + dev_warn(&pdev->dev, "invalid dev_id or disp_id muxing\n");
- +
- + mipi_dsi->lcd_panel = kstrdup(lcd_panel, GFP_KERNEL);
- + if (!mipi_dsi->lcd_panel) {
- + dev_err(&pdev->dev, "failed to allocate lcd panel name\n");
- + ret = -ENOMEM;
- + goto kstrdup_fail;
- + }
- +
- + mipi_dsi->pdev = pdev;
- + mipi_dsi->disp_mipi = mxc_dispdrv_register(&mipi_dsi_drv);
- + if (IS_ERR(mipi_dsi->disp_mipi)) {
- + dev_err(&pdev->dev, "mxc_dispdrv_register error\n");
- + ret = PTR_ERR(mipi_dsi->disp_mipi);
- + goto dispdrv_reg_fail;
- + }
- +
- + mxc_dispdrv_setdata(mipi_dsi->disp_mipi, mipi_dsi);
- + dev_set_drvdata(&pdev->dev, mipi_dsi);
- +
- + dev_info(&pdev->dev, "i.MX MIPI DSI driver probed\n");
- + return ret;
- +
- +dispdrv_reg_fail:
- + kfree(mipi_dsi->lcd_panel);
- +kstrdup_fail:
- +get_parent_regmap_fail:
- +dev_reset_fail:
- + if (mipi_dsi->disp_power_on)
- + regulator_disable(mipi_dsi->disp_power_on);
- + return ret;
- +}
- +
- +static void mipi_dsi_shutdown(struct platform_device *pdev)
- +{
- + struct mipi_dsi_info *mipi_dsi = dev_get_drvdata(&pdev->dev);
- +
- + mipi_dsi_power_off(mipi_dsi->disp_mipi);
- +}
- +
- +static int mipi_dsi_remove(struct platform_device *pdev)
- +{
- + struct mipi_dsi_info *mipi_dsi = dev_get_drvdata(&pdev->dev);
- +
- + mxc_dispdrv_puthandle(mipi_dsi->disp_mipi);
- + mxc_dispdrv_unregister(mipi_dsi->disp_mipi);
- +
- + if (mipi_dsi->disp_power_on)
- + regulator_disable(mipi_dsi->disp_power_on);
- +
- + kfree(mipi_dsi->lcd_panel);
- + dev_set_drvdata(&pdev->dev, NULL);
- +
- + return 0;
- +}
- +
- +static struct platform_driver mipi_dsi_driver = {
- + .driver = {
- + .of_match_table = imx_mipi_dsi_dt_ids,
- + .name = "mxc_mipi_dsi",
- + },
- + .probe = mipi_dsi_probe,
- + .remove = mipi_dsi_remove,
- + .shutdown = mipi_dsi_shutdown,
- +};
- +
- +static int __init mipi_dsi_init(void)
- +{
- + int err;
- +
- + err = platform_driver_register(&mipi_dsi_driver);
- + if (err) {
- + pr_err("mipi_dsi_driver register failed\n");
- + return -ENODEV;
- + }
- + pr_info("MIPI DSI driver module loaded\n");
- + return 0;
- +}
- +
- +static void __exit mipi_dsi_cleanup(void)
- +{
- + platform_driver_unregister(&mipi_dsi_driver);
- +}
- +
- +module_init(mipi_dsi_init);
- +module_exit(mipi_dsi_cleanup);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("i.MX MIPI DSI driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/video/mxc/mipi_dsi.h linux-3.14.35/drivers/video/mxc/mipi_dsi.h
- --- linux-3.14.35.orig/drivers/video/mxc/mipi_dsi.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/video/mxc/mipi_dsi.h 2015-03-08 14:27:37.785684499 -0500
- @@ -0,0 +1,112 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#ifndef __MIPI_DSI_H__
- +#define __MIPI_DSI_H__
- +
- +#include <linux/regmap.h>
- +
- +#ifdef DEBUG
- +#define mipi_dbg(fmt, ...) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
- +#else
- +#define mipi_dbg(fmt, ...)
- +#endif
- +
- +#define DSI_CMD_BUF_MAXSIZE (32)
- +
- +/* DPI interface pixel color coding map */
- +enum mipi_dsi_dpi_fmt {
- + MIPI_RGB565_PACKED = 0,
- + MIPI_RGB565_LOOSELY,
- + MIPI_RGB565_CONFIG3,
- + MIPI_RGB666_PACKED,
- + MIPI_RGB666_LOOSELY,
- + MIPI_RGB888,
- +};
- +
- +struct mipi_lcd_config {
- + u32 virtual_ch;
- + u32 data_lane_num;
- + /* device max DPHY clock in MHz unit */
- + u32 max_phy_clk;
- + enum mipi_dsi_dpi_fmt dpi_fmt;
- +};
- +
- +struct mipi_dsi_info;
- +struct mipi_dsi_lcd_callback {
- + /* callback for lcd panel operation */
- + void (*get_mipi_lcd_videomode)(struct fb_videomode **, int *,
- + struct mipi_lcd_config **);
- + int (*mipi_lcd_setup)(struct mipi_dsi_info *);
- +
- +};
- +
- +struct mipi_dsi_match_lcd {
- + char *lcd_panel;
- + struct mipi_dsi_lcd_callback lcd_callback;
- +};
- +
- +struct mipi_dsi_bus_mux {
- + int reg;
- + int mask;
- + int (*get_mux) (int dev_id, int disp_id);
- +};
- +
- +/* driver private data */
- +struct mipi_dsi_info {
- + struct platform_device *pdev;
- + void __iomem *mmio_base;
- + struct regmap *regmap;
- + const struct mipi_dsi_bus_mux *bus_mux;
- + int dsi_power_on;
- + int lcd_inited;
- + u32 dphy_pll_config;
- + int dev_id;
- + int disp_id;
- + char *lcd_panel;
- + int irq;
- + struct clk *dphy_clk;
- + struct clk *cfg_clk;
- + struct mxc_dispdrv_handle *disp_mipi;
- + struct fb_videomode *mode;
- + struct regulator *disp_power_on;
- + struct mipi_lcd_config *lcd_config;
- + /* board related power control */
- + struct backlight_device *bl;
- + /* callback for lcd panel operation */
- + struct mipi_dsi_lcd_callback *lcd_callback;
- +};
- +
- +int mipi_dsi_pkt_write(struct mipi_dsi_info *mipi,
- + u8 data_type, const u32 *buf, int len);
- +int mipi_dsi_pkt_read(struct mipi_dsi_info *mipi,
- + u8 data_type, u32 *buf, int len);
- +int mipi_dsi_dcs_cmd(struct mipi_dsi_info *mipi,
- + u8 cmd, const u32 *param, int num);
- +
- +#ifdef CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL
- +void mipid_hx8369_get_lcd_videomode(struct fb_videomode **mode, int *size,
- + struct mipi_lcd_config **data);
- +int mipid_hx8369_lcd_setup(struct mipi_dsi_info *);
- +#endif
- +
- +#ifndef CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL
- +#error "Please configure MIPI LCD panel, we cannot find one!"
- +#endif
- +
- +#endif
- diff -Nur linux-3.14.35.orig/drivers/video/mxc/mxc_dispdrv.c linux-3.14.35/drivers/video/mxc/mxc_dispdrv.c
- --- linux-3.14.35.orig/drivers/video/mxc/mxc_dispdrv.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/video/mxc/mxc_dispdrv.c 2015-03-08 14:27:37.785684499 -0500
- @@ -0,0 +1,150 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @file mxc_dispdrv.c
- + * @brief mxc display driver framework.
- + *
- + * A display device driver could call mxc_dispdrv_register(drv) in its dev_probe() function.
- + * Move all dev_probe() things into mxc_dispdrv_driver->init(), init() function should init
- + * and feedback setting;
- + * Necessary deferred operations can be done in mxc_dispdrv_driver->post_init(),
- + * after dev_id and disp_id pass usage check;
- + * Move all dev_remove() things into mxc_dispdrv_driver->deinit();
- + * Move all dev_suspend() things into fb_notifier for SUSPEND, if there is;
- + * Move all dev_resume() things into fb_notifier for RESUME, if there is;
- + *
- + * ipuv3 fb driver could call mxc_dispdrv_gethandle(name, setting) before a fb
- + * need be added, with fbi param passing by setting, after
- + * mxc_dispdrv_gethandle() return, FB driver should get the basic setting
- + * about fbi info and ipuv3-hw (ipu_id and disp_id).
- + *
- + * @ingroup Framebuffer
- + */
- +
- +#include <linux/kernel.h>
- +#include <linux/module.h>
- +#include <linux/list.h>
- +#include <linux/mutex.h>
- +#include <linux/slab.h>
- +#include <linux/err.h>
- +#include <linux/string.h>
- +#include "mxc_dispdrv.h"
- +
- +static LIST_HEAD(dispdrv_list);
- +static DEFINE_MUTEX(dispdrv_lock);
- +
- +struct mxc_dispdrv_entry {
- + /* Note: drv always the first element */
- + struct mxc_dispdrv_driver *drv;
- + bool active;
- + void *priv;
- + struct list_head list;
- +};
- +
- +struct mxc_dispdrv_handle *mxc_dispdrv_register(struct mxc_dispdrv_driver *drv)
- +{
- + struct mxc_dispdrv_entry *new;
- +
- + mutex_lock(&dispdrv_lock);
- +
- + new = kzalloc(sizeof(struct mxc_dispdrv_entry), GFP_KERNEL);
- + if (!new) {
- + mutex_unlock(&dispdrv_lock);
- + return ERR_PTR(-ENOMEM);
- + }
- +
- + new->drv = drv;
- + list_add_tail(&new->list, &dispdrv_list);
- +
- + mutex_unlock(&dispdrv_lock);
- +
- + return (struct mxc_dispdrv_handle *)new;
- +}
- +EXPORT_SYMBOL_GPL(mxc_dispdrv_register);
- +
- +int mxc_dispdrv_unregister(struct mxc_dispdrv_handle *handle)
- +{
- + struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle;
- +
- + if (entry) {
- + mutex_lock(&dispdrv_lock);
- + list_del(&entry->list);
- + mutex_unlock(&dispdrv_lock);
- + kfree(entry);
- + return 0;
- + } else
- + return -EINVAL;
- +}
- +EXPORT_SYMBOL_GPL(mxc_dispdrv_unregister);
- +
- +struct mxc_dispdrv_handle *mxc_dispdrv_gethandle(char *name,
- + struct mxc_dispdrv_setting *setting)
- +{
- + int ret, found = 0;
- + struct mxc_dispdrv_entry *entry;
- +
- + mutex_lock(&dispdrv_lock);
- + list_for_each_entry(entry, &dispdrv_list, list) {
- + if (!strcmp(entry->drv->name, name) && (entry->drv->init)) {
- + ret = entry->drv->init((struct mxc_dispdrv_handle *)
- + entry, setting);
- + if (ret >= 0) {
- + entry->active = true;
- + found = 1;
- + break;
- + }
- + }
- + }
- + mutex_unlock(&dispdrv_lock);
- +
- + return found ? (struct mxc_dispdrv_handle *)entry:ERR_PTR(-ENODEV);
- +}
- +EXPORT_SYMBOL_GPL(mxc_dispdrv_gethandle);
- +
- +void mxc_dispdrv_puthandle(struct mxc_dispdrv_handle *handle)
- +{
- + struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle;
- +
- + mutex_lock(&dispdrv_lock);
- + if (entry && entry->active && entry->drv->deinit) {
- + entry->drv->deinit(handle);
- + entry->active = false;
- + }
- + mutex_unlock(&dispdrv_lock);
- +
- +}
- +EXPORT_SYMBOL_GPL(mxc_dispdrv_puthandle);
- +
- +int mxc_dispdrv_setdata(struct mxc_dispdrv_handle *handle, void *data)
- +{
- + struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle;
- +
- + if (entry) {
- + entry->priv = data;
- + return 0;
- + } else
- + return -EINVAL;
- +}
- +EXPORT_SYMBOL_GPL(mxc_dispdrv_setdata);
- +
- +void *mxc_dispdrv_getdata(struct mxc_dispdrv_handle *handle)
- +{
- + struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle;
- +
- + if (entry) {
- + return entry->priv;
- + } else
- + return ERR_PTR(-EINVAL);
- +}
- +EXPORT_SYMBOL_GPL(mxc_dispdrv_getdata);
- diff -Nur linux-3.14.35.orig/drivers/video/mxc/mxc_dispdrv.h linux-3.14.35/drivers/video/mxc/mxc_dispdrv.h
- --- linux-3.14.35.orig/drivers/video/mxc/mxc_dispdrv.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/video/mxc/mxc_dispdrv.h 2015-03-08 14:27:37.785684499 -0500
- @@ -0,0 +1,54 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +#ifndef __MXC_DISPDRV_H__
- +#define __MXC_DISPDRV_H__
- +#include <linux/fb.h>
- +
- +struct mxc_dispdrv_handle {
- + struct mxc_dispdrv_driver *drv;
- +};
- +
- +struct mxc_dispdrv_setting {
- + /*input-feedback parameter*/
- + struct fb_info *fbi;
- + int if_fmt;
- + int default_bpp;
- + char *dft_mode_str;
- +
- + /*feedback parameter*/
- + int dev_id;
- + int disp_id;
- +};
- +
- +struct mxc_dispdrv_driver {
- + const char *name;
- + int (*init) (struct mxc_dispdrv_handle *, struct mxc_dispdrv_setting *);
- + /* deferred operations after dev_id and disp_id pass usage check */
- + int (*post_init) (struct mxc_dispdrv_handle *, int dev_id, int disp_id);
- + void (*deinit) (struct mxc_dispdrv_handle *);
- + /* display driver enable function for extension */
- + int (*enable) (struct mxc_dispdrv_handle *);
- + /* display driver disable function, called at early part of fb_blank */
- + void (*disable) (struct mxc_dispdrv_handle *);
- + /* display driver setup function, called at early part of fb_set_par */
- + int (*setup) (struct mxc_dispdrv_handle *, struct fb_info *fbi);
- +};
- +
- +struct mxc_dispdrv_handle *mxc_dispdrv_register(struct mxc_dispdrv_driver *drv);
- +int mxc_dispdrv_unregister(struct mxc_dispdrv_handle *handle);
- +struct mxc_dispdrv_handle *mxc_dispdrv_gethandle(char *name,
- + struct mxc_dispdrv_setting *setting);
- +void mxc_dispdrv_puthandle(struct mxc_dispdrv_handle *handle);
- +int mxc_dispdrv_setdata(struct mxc_dispdrv_handle *handle, void *data);
- +void *mxc_dispdrv_getdata(struct mxc_dispdrv_handle *handle);
- +#endif
- diff -Nur linux-3.14.35.orig/drivers/video/mxc/mxc_edid.c linux-3.14.35/drivers/video/mxc/mxc_edid.c
- --- linux-3.14.35.orig/drivers/video/mxc/mxc_edid.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/video/mxc/mxc_edid.c 2015-03-08 14:27:37.785684499 -0500
- @@ -0,0 +1,762 @@
- +/*
- + * Copyright 2009-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @defgroup Framebuffer Framebuffer Driver for SDC and ADC.
- + */
- +
- +/*!
- + * @file mxc_edid.c
- + *
- + * @brief MXC EDID driver
- + *
- + * @ingroup Framebuffer
- + */
- +
- +/*!
- + * Include files
- + */
- +#include <linux/i2c.h>
- +#include <linux/fb.h>
- +#include <video/mxc_edid.h>
- +#include "../edid.h"
- +
- +#undef DEBUG /* define this for verbose EDID parsing output */
- +#ifdef DEBUG
- +#define DPRINTK(fmt, args...) printk(fmt, ## args)
- +#else
- +#define DPRINTK(fmt, args...)
- +#endif
- +
- +const struct fb_videomode mxc_cea_mode[64] = {
- + /* #1: 640x480p@59.94/60Hz 4:3 */
- + [1] = {
- + NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
- + },
- + /* #2: 720x480p@59.94/60Hz 4:3 */
- + [2] = {
- + NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
- + },
- + /* #3: 720x480p@59.94/60Hz 16:9 */
- + [3] = {
- + NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
- + },
- + /* #4: 1280x720p@59.94/60Hz 16:9 */
- + [4] = {
- + NULL, 60, 1280, 720, 13468, 220, 110, 20, 5, 40, 5,
- + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0
- + },
- + /* #5: 1920x1080i@59.94/60Hz 16:9 */
- + [5] = {
- + NULL, 60, 1920, 1080, 13763, 148, 88, 15, 2, 44, 5,
- + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- + FB_VMODE_INTERLACED | FB_VMODE_ASPECT_16_9, 0,
- + },
- + /* #6: 720(1440)x480iH@59.94/60Hz 4:3 */
- + [6] = {
- + NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0,
- + FB_VMODE_INTERLACED | FB_VMODE_ASPECT_4_3, 0,
- + },
- + /* #7: 720(1440)x480iH@59.94/60Hz 16:9 */
- + [7] = {
- + NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0,
- + FB_VMODE_INTERLACED | FB_VMODE_ASPECT_16_9, 0,
- + },
- + /* #8: 720(1440)x240pH@59.94/60Hz 4:3 */
- + [8] = {
- + NULL, 60, 1440, 240, 37108, 114, 38, 15, 4, 124, 3, 0,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
- + },
- + /* #9: 720(1440)x240pH@59.94/60Hz 16:9 */
- + [9] = {
- + NULL, 60, 1440, 240, 37108, 114, 38, 15, 4, 124, 3, 0,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
- + },
- + /* #14: 1440x480p@59.94/60Hz 4:3 */
- + [14] = {
- + NULL, 60, 1440, 480, 18500, 120, 32, 30, 9, 124, 6, 0,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
- + },
- + /* #15: 1440x480p@59.94/60Hz 16:9 */
- + [15] = {
- + NULL, 60, 1440, 480, 18500, 120, 32, 30, 9, 124, 6, 0,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
- + },
- + /* #16: 1920x1080p@60Hz 16:9 */
- + [16] = {
- + NULL, 60, 1920, 1080, 6734, 148, 88, 36, 4, 44, 5,
- + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
- + },
- + /* #17: 720x576pH@50Hz 4:3 */
- + [17] = {
- + NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
- + },
- + /* #18: 720x576pH@50Hz 16:9 */
- + [18] = {
- + NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
- + },
- + /* #19: 1280x720p@50Hz */
- + [19] = {
- + NULL, 50, 1280, 720, 13468, 220, 440, 20, 5, 40, 5,
- + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
- + },
- + /* #20: 1920x1080i@50Hz */
- + [20] = {
- + NULL, 50, 1920, 1080, 13480, 148, 528, 15, 5, 528, 5,
- + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- + FB_VMODE_INTERLACED | FB_VMODE_ASPECT_16_9, 0,
- + },
- + /* #23: 720(1440)x288pH@50Hz 4:3 */
- + [23] = {
- + NULL, 50, 1440, 288, 37037, 138, 24, 19, 2, 126, 3, 0,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
- + },
- + /* #24: 720(1440)x288pH@50Hz 16:9 */
- + [24] = {
- + NULL, 50, 1440, 288, 37037, 138, 24, 19, 2, 126, 3, 0,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
- + },
- + /* #29: 720(1440)x576pH@50Hz 4:3 */
- + [29] = {
- + NULL, 50, 1440, 576, 18518, 136, 24, 39, 5, 128, 5, 0,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
- + },
- + /* #30: 720(1440)x576pH@50Hz 16:9 */
- + [30] = {
- + NULL, 50, 1440, 576, 18518, 136, 24, 39, 5, 128, 5, 0,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
- + },
- + /* #31: 1920x1080p@50Hz */
- + [31] = {
- + NULL, 50, 1920, 1080, 6734, 148, 528, 36, 4, 44, 5,
- + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
- + },
- + /* #32: 1920x1080p@23.98/24Hz */
- + [32] = {
- + NULL, 24, 1920, 1080, 13468, 148, 638, 36, 4, 44, 5,
- + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
- + },
- + /* #33: 1920x1080p@25Hz */
- + [33] = {
- + NULL, 25, 1920, 1080, 13468, 148, 528, 36, 4, 44, 5,
- + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
- + },
- + /* #34: 1920x1080p@30Hz */
- + [34] = {
- + NULL, 30, 1920, 1080, 13468, 148, 88, 36, 4, 44, 5,
- + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
- + },
- + /* #41: 1280x720p@100Hz 16:9 */
- + [41] = {
- + NULL, 100, 1280, 720, 6734, 220, 440, 20, 5, 40, 5,
- + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0
- + },
- + /* #47: 1280x720p@119.88/120Hz 16:9 */
- + [47] = {
- + NULL, 120, 1280, 720, 6734, 220, 110, 20, 5, 40, 5,
- + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0
- + },
- +};
- +
- +/*
- + * We have a special version of fb_mode_is_equal that ignores
- + * pixclock, since for many CEA modes, 2 frequencies are supported
- + * e.g. 640x480 @ 60Hz or 59.94Hz
- + */
- +int mxc_edid_fb_mode_is_equal(bool use_aspect,
- + const struct fb_videomode *mode1,
- + const struct fb_videomode *mode2)
- +{
- + u32 mask;
- +
- + if (use_aspect)
- + mask = ~0;
- + else
- + mask = ~FB_VMODE_ASPECT_MASK;
- +
- + return (mode1->xres == mode2->xres &&
- + mode1->yres == mode2->yres &&
- + mode1->hsync_len == mode2->hsync_len &&
- + mode1->vsync_len == mode2->vsync_len &&
- + mode1->left_margin == mode2->left_margin &&
- + mode1->right_margin == mode2->right_margin &&
- + mode1->upper_margin == mode2->upper_margin &&
- + mode1->lower_margin == mode2->lower_margin &&
- + mode1->sync == mode2->sync &&
- + /* refresh check, 59.94Hz and 60Hz have the same parameter
- + * in struct of mxc_cea_mode */
- + abs(mode1->refresh - mode2->refresh) <= 1 &&
- + (mode1->vmode & mask) == (mode2->vmode & mask));
- +}
- +
- +static void get_detailed_timing(unsigned char *block,
- + struct fb_videomode *mode)
- +{
- + mode->xres = H_ACTIVE;
- + mode->yres = V_ACTIVE;
- + mode->pixclock = PIXEL_CLOCK;
- + mode->pixclock /= 1000;
- + mode->pixclock = KHZ2PICOS(mode->pixclock);
- + mode->right_margin = H_SYNC_OFFSET;
- + mode->left_margin = (H_ACTIVE + H_BLANKING) -
- + (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
- + mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
- + V_SYNC_WIDTH;
- + mode->lower_margin = V_SYNC_OFFSET;
- + mode->hsync_len = H_SYNC_WIDTH;
- + mode->vsync_len = V_SYNC_WIDTH;
- + if (HSYNC_POSITIVE)
- + mode->sync |= FB_SYNC_HOR_HIGH_ACT;
- + if (VSYNC_POSITIVE)
- + mode->sync |= FB_SYNC_VERT_HIGH_ACT;
- + mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
- + (V_ACTIVE + V_BLANKING));
- + if (INTERLACED) {
- + mode->yres *= 2;
- + mode->upper_margin *= 2;
- + mode->lower_margin *= 2;
- + mode->vsync_len *= 2;
- + mode->vmode |= FB_VMODE_INTERLACED;
- + }
- + mode->flag = FB_MODE_IS_DETAILED;
- +
- + if ((H_SIZE / 16) == (V_SIZE / 9))
- + mode->vmode |= FB_VMODE_ASPECT_16_9;
- + else if ((H_SIZE / 4) == (V_SIZE / 3))
- + mode->vmode |= FB_VMODE_ASPECT_4_3;
- + else if ((mode->xres / 16) == (mode->yres / 9))
- + mode->vmode |= FB_VMODE_ASPECT_16_9;
- + else if ((mode->xres / 4) == (mode->yres / 3))
- + mode->vmode |= FB_VMODE_ASPECT_4_3;
- +
- + if (mode->vmode & FB_VMODE_ASPECT_16_9)
- + DPRINTK("Aspect ratio: 16:9\n");
- + if (mode->vmode & FB_VMODE_ASPECT_4_3)
- + DPRINTK("Aspect ratio: 4:3\n");
- + DPRINTK(" %d MHz ", PIXEL_CLOCK/1000000);
- + DPRINTK("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
- + H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
- + DPRINTK("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
- + V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
- + DPRINTK("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
- + (VSYNC_POSITIVE) ? "+" : "-");
- +}
- +
- +int mxc_edid_parse_ext_blk(unsigned char *edid,
- + struct mxc_edid_cfg *cfg,
- + struct fb_monspecs *specs)
- +{
- + char detail_timing_desc_offset;
- + struct fb_videomode *mode, *m;
- + unsigned char index = 0x0;
- + unsigned char *block;
- + int i, num = 0, revision;
- +
- + if (edid[index++] != 0x2) /* only support cea ext block now */
- + return -1;
- + revision = edid[index++];
- + DPRINTK("cea extent revision %d\n", revision);
- + mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
- + if (mode == NULL)
- + return -1;
- +
- + detail_timing_desc_offset = edid[index++];
- +
- + if (revision >= 2) {
- + cfg->cea_underscan = (edid[index] >> 7) & 0x1;
- + cfg->cea_basicaudio = (edid[index] >> 6) & 0x1;
- + cfg->cea_ycbcr444 = (edid[index] >> 5) & 0x1;
- + cfg->cea_ycbcr422 = (edid[index] >> 4) & 0x1;
- +
- + DPRINTK("CEA underscan %d\n", cfg->cea_underscan);
- + DPRINTK("CEA basicaudio %d\n", cfg->cea_basicaudio);
- + DPRINTK("CEA ycbcr444 %d\n", cfg->cea_ycbcr444);
- + DPRINTK("CEA ycbcr422 %d\n", cfg->cea_ycbcr422);
- + }
- +
- + if (revision >= 3) {
- + /* short desc */
- + DPRINTK("CEA Short desc timmings\n");
- + index++;
- + while (index < detail_timing_desc_offset) {
- + unsigned char tagcode, blklen;
- +
- + tagcode = (edid[index] >> 5) & 0x7;
- + blklen = (edid[index]) & 0x1f;
- +
- + DPRINTK("Tagcode %x Len %d\n", tagcode, blklen);
- +
- + switch (tagcode) {
- + case 0x2: /*Video data block*/
- + {
- + int cea_idx;
- + i = 0;
- + while (i < blklen) {
- + index++;
- + cea_idx = edid[index] & 0x7f;
- + if (cea_idx < ARRAY_SIZE(mxc_cea_mode) &&
- + (mxc_cea_mode[cea_idx].xres)) {
- + DPRINTK("Support CEA Format #%d\n", cea_idx);
- + mode[num] = mxc_cea_mode[cea_idx];
- + mode[num].flag |= FB_MODE_IS_STANDARD;
- + num++;
- + }
- + i++;
- + }
- + break;
- + }
- + case 0x3: /*Vendor specific data*/
- + {
- + unsigned char IEEE_reg_iden[3];
- + unsigned char deep_color;
- + unsigned char latency_present;
- + unsigned char I_latency_present;
- + unsigned char hdmi_video_present;
- + unsigned char hdmi_3d_present;
- + unsigned char hdmi_3d_multi_present;
- + unsigned char hdmi_vic_len;
- + unsigned char hdmi_3d_len;
- + unsigned char index_inc = 0;
- + unsigned char vsd_end;
- +
- + vsd_end = index + blklen;
- +
- + IEEE_reg_iden[0] = edid[index+1];
- + IEEE_reg_iden[1] = edid[index+2];
- + IEEE_reg_iden[2] = edid[index+3];
- + cfg->physical_address[0] = (edid[index+4] & 0xf0) >> 4;
- + cfg->physical_address[1] = (edid[index+4] & 0x0f);
- + cfg->physical_address[2] = (edid[index+5] & 0xf0) >> 4;
- + cfg->physical_address[3] = (edid[index+5] & 0x0f);
- +
- + if ((IEEE_reg_iden[0] == 0x03) &&
- + (IEEE_reg_iden[1] == 0x0c) &&
- + (IEEE_reg_iden[2] == 0x00))
- + cfg->hdmi_cap = 1;
- +
- + if (blklen > 5) {
- + deep_color = edid[index+6];
- + if (deep_color & 0x80)
- + cfg->vsd_support_ai = true;
- + if (deep_color & 0x40)
- + cfg->vsd_dc_48bit = true;
- + if (deep_color & 0x20)
- + cfg->vsd_dc_36bit = true;
- + if (deep_color & 0x10)
- + cfg->vsd_dc_30bit = true;
- + if (deep_color & 0x08)
- + cfg->vsd_dc_y444 = true;
- + if (deep_color & 0x01)
- + cfg->vsd_dvi_dual = true;
- + }
- +
- + DPRINTK("VSD hdmi capability %d\n", cfg->hdmi_cap);
- + DPRINTK("VSD support ai %d\n", cfg->vsd_support_ai);
- + DPRINTK("VSD support deep color 48bit %d\n", cfg->vsd_dc_48bit);
- + DPRINTK("VSD support deep color 36bit %d\n", cfg->vsd_dc_36bit);
- + DPRINTK("VSD support deep color 30bit %d\n", cfg->vsd_dc_30bit);
- + DPRINTK("VSD support deep color y444 %d\n", cfg->vsd_dc_y444);
- + DPRINTK("VSD support dvi dual %d\n", cfg->vsd_dvi_dual);
- +
- + if (blklen > 6)
- + cfg->vsd_max_tmdsclk_rate = edid[index+7] * 5;
- + DPRINTK("VSD MAX TMDS CLOCK RATE %d\n", cfg->vsd_max_tmdsclk_rate);
- +
- + if (blklen > 7) {
- + latency_present = edid[index+8] >> 7;
- + I_latency_present = (edid[index+8] & 0x40) >> 6;
- + hdmi_video_present = (edid[index+8] & 0x20) >> 5;
- + cfg->vsd_cnc3 = (edid[index+8] & 0x8) >> 3;
- + cfg->vsd_cnc2 = (edid[index+8] & 0x4) >> 2;
- + cfg->vsd_cnc1 = (edid[index+8] & 0x2) >> 1;
- + cfg->vsd_cnc0 = edid[index+8] & 0x1;
- +
- + DPRINTK("VSD cnc0 %d\n", cfg->vsd_cnc0);
- + DPRINTK("VSD cnc1 %d\n", cfg->vsd_cnc1);
- + DPRINTK("VSD cnc2 %d\n", cfg->vsd_cnc2);
- + DPRINTK("VSD cnc3 %d\n", cfg->vsd_cnc3);
- + DPRINTK("latency_present %d\n", latency_present);
- + DPRINTK("I_latency_present %d\n", I_latency_present);
- + DPRINTK("hdmi_video_present %d\n", hdmi_video_present);
- +
- + } else {
- + index += blklen;
- + break;
- + }
- +
- + index += 9;
- +
- + /*latency present */
- + if (latency_present) {
- + cfg->vsd_video_latency = edid[index++];
- + cfg->vsd_audio_latency = edid[index++];
- +
- + if (I_latency_present) {
- + cfg->vsd_I_video_latency = edid[index++];
- + cfg->vsd_I_audio_latency = edid[index++];
- + } else {
- + cfg->vsd_I_video_latency = cfg->vsd_video_latency;
- + cfg->vsd_I_audio_latency = cfg->vsd_audio_latency;
- + }
- +
- + DPRINTK("VSD latency video_latency %d\n", cfg->vsd_video_latency);
- + DPRINTK("VSD latency audio_latency %d\n", cfg->vsd_audio_latency);
- + DPRINTK("VSD latency I_video_latency %d\n", cfg->vsd_I_video_latency);
- + DPRINTK("VSD latency I_audio_latency %d\n", cfg->vsd_I_audio_latency);
- + }
- +
- + if (hdmi_video_present) {
- + hdmi_3d_present = edid[index] >> 7;
- + hdmi_3d_multi_present = (edid[index] & 0x60) >> 5;
- + index++;
- + hdmi_vic_len = (edid[index] & 0xe0) >> 5;
- + hdmi_3d_len = edid[index] & 0x1f;
- + index++;
- +
- + DPRINTK("hdmi_3d_present %d\n", hdmi_3d_present);
- + DPRINTK("hdmi_3d_multi_present %d\n", hdmi_3d_multi_present);
- + DPRINTK("hdmi_vic_len %d\n", hdmi_vic_len);
- + DPRINTK("hdmi_3d_len %d\n", hdmi_3d_len);
- +
- + if (hdmi_vic_len > 0) {
- + for (i = 0; i < hdmi_vic_len; i++) {
- + cfg->hdmi_vic[i] = edid[index++];
- + DPRINTK("HDMI_vic=%d\n", cfg->hdmi_vic[i]);
- + }
- + }
- +
- + if (hdmi_3d_len > 0) {
- + if (hdmi_3d_present) {
- + if (hdmi_3d_multi_present == 0x1) {
- + cfg->hdmi_3d_struct_all = (edid[index] << 8) | edid[index+1];
- + index_inc = 2;
- + } else if (hdmi_3d_multi_present == 0x2) {
- + cfg->hdmi_3d_struct_all = (edid[index] << 8) | edid[index+1];
- + cfg->hdmi_3d_mask_all = (edid[index+2] << 8) | edid[index+3];
- + index_inc = 4;
- + } else
- + index_inc = 0;
- + }
- +
- + DPRINTK("HDMI 3d struct all =0x%x\n", cfg->hdmi_3d_struct_all);
- + DPRINTK("HDMI 3d mask all =0x%x\n", cfg->hdmi_3d_mask_all);
- +
- + /* Read 2D vic 3D_struct */
- + if ((hdmi_3d_len - index_inc) > 0) {
- + DPRINTK("Support 3D video format\n");
- + i = 0;
- + while ((hdmi_3d_len - index_inc) > 0) {
- +
- + cfg->hdmi_3d_format[i].vic_order_2d = edid[index+index_inc] >> 4;
- + cfg->hdmi_3d_format[i].struct_3d = edid[index+index_inc] & 0x0f;
- + index_inc++;
- +
- + if (cfg->hdmi_3d_format[i].struct_3d == 8) {
- + cfg->hdmi_3d_format[i].detail_3d = edid[index+index_inc] >> 4;
- + index_inc++;
- + } else if (cfg->hdmi_3d_format[i].struct_3d > 8) {
- + cfg->hdmi_3d_format[i].detail_3d = 0;
- + index_inc++;
- + }
- +
- + DPRINTK("vic_order_2d=%d, 3d_struct=%d, 3d_detail=0x%x\n",
- + cfg->hdmi_3d_format[i].vic_order_2d,
- + cfg->hdmi_3d_format[i].struct_3d,
- + cfg->hdmi_3d_format[i].detail_3d);
- + i++;
- + }
- + }
- + index += index_inc;
- + }
- + }
- +
- + index = vsd_end;
- +
- + break;
- + }
- + case 0x1: /*Audio data block*/
- + {
- + u8 audio_format, max_ch, byte1, byte2, byte3;
- +
- + i = 0;
- + cfg->max_channels = 0;
- + cfg->sample_rates = 0;
- + cfg->sample_sizes = 0;
- +
- + while (i < blklen) {
- + byte1 = edid[index + 1];
- + byte2 = edid[index + 2];
- + byte3 = edid[index + 3];
- + index += 3;
- + i += 3;
- +
- + audio_format = byte1 >> 3;
- + max_ch = (byte1 & 0x07) + 1;
- +
- + DPRINTK("Audio Format Descriptor : %2d\n", audio_format);
- + DPRINTK("Max Number of Channels : %2d\n", max_ch);
- + DPRINTK("Sample Rates : %02x\n", byte2);
- +
- + /* ALSA can't specify specific compressed
- + * formats, so only care about PCM for now. */
- + if (audio_format == AUDIO_CODING_TYPE_LPCM) {
- + if (max_ch > cfg->max_channels)
- + cfg->max_channels = max_ch;
- +
- + cfg->sample_rates |= byte2;
- + cfg->sample_sizes |= byte3 & 0x7;
- + DPRINTK("Sample Sizes : %02x\n",
- + byte3 & 0x7);
- + }
- + }
- + break;
- + }
- + case 0x4: /*Speaker allocation block*/
- + {
- + i = 0;
- + while (i < blklen) {
- + cfg->speaker_alloc = edid[index + 1];
- + index += 3;
- + i += 3;
- + DPRINTK("Speaker Alloc : %02x\n", cfg->speaker_alloc);
- + }
- + break;
- + }
- + case 0x7: /*User extended block*/
- + default:
- + /* skip */
- + DPRINTK("Not handle block, tagcode = 0x%x\n", tagcode);
- + index += blklen;
- + break;
- + }
- +
- + index++;
- + }
- + }
- +
- + /* long desc */
- + DPRINTK("CEA long desc timmings\n");
- + index = detail_timing_desc_offset;
- + block = edid + index;
- + while (index < (EDID_LENGTH - DETAILED_TIMING_DESCRIPTION_SIZE)) {
- + if (!(block[0] == 0x00 && block[1] == 0x00)) {
- + get_detailed_timing(block, &mode[num]);
- + num++;
- + }
- + block += DETAILED_TIMING_DESCRIPTION_SIZE;
- + index += DETAILED_TIMING_DESCRIPTION_SIZE;
- + }
- +
- + if (!num) {
- + kfree(mode);
- + return 0;
- + }
- +
- + m = kmalloc((num + specs->modedb_len) *
- + sizeof(struct fb_videomode), GFP_KERNEL);
- + if (!m)
- + return 0;
- +
- + if (specs->modedb_len) {
- + memmove(m, specs->modedb,
- + specs->modedb_len * sizeof(struct fb_videomode));
- + kfree(specs->modedb);
- + }
- + memmove(m+specs->modedb_len, mode,
- + num * sizeof(struct fb_videomode));
- + kfree(mode);
- +
- + specs->modedb_len += num;
- + specs->modedb = m;
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(mxc_edid_parse_ext_blk);
- +
- +static int mxc_edid_readblk(struct i2c_adapter *adp,
- + unsigned short addr, unsigned char *edid)
- +{
- + int ret = 0, extblknum = 0;
- + unsigned char regaddr = 0x0;
- + struct i2c_msg msg[2] = {
- + {
- + .addr = addr,
- + .flags = 0,
- + .len = 1,
- + .buf = ®addr,
- + }, {
- + .addr = addr,
- + .flags = I2C_M_RD,
- + .len = EDID_LENGTH,
- + .buf = edid,
- + },
- + };
- +
- + ret = i2c_transfer(adp, msg, ARRAY_SIZE(msg));
- + if (ret != ARRAY_SIZE(msg)) {
- + DPRINTK("unable to read EDID block\n");
- + return -EIO;
- + }
- +
- + if (edid[1] == 0x00)
- + return -ENOENT;
- +
- + extblknum = edid[0x7E];
- +
- + if (extblknum) {
- + regaddr = 128;
- + msg[1].buf = edid + EDID_LENGTH;
- +
- + ret = i2c_transfer(adp, msg, ARRAY_SIZE(msg));
- + if (ret != ARRAY_SIZE(msg)) {
- + DPRINTK("unable to read EDID ext block\n");
- + return -EIO;
- + }
- + }
- +
- + return extblknum;
- +}
- +
- +static int mxc_edid_readsegblk(struct i2c_adapter *adp, unsigned short addr,
- + unsigned char *edid, int seg_num)
- +{
- + int ret = 0;
- + unsigned char segment = 0x1, regaddr = 0;
- + struct i2c_msg msg[3] = {
- + {
- + .addr = 0x30,
- + .flags = 0,
- + .len = 1,
- + .buf = &segment,
- + }, {
- + .addr = addr,
- + .flags = 0,
- + .len = 1,
- + .buf = ®addr,
- + }, {
- + .addr = addr,
- + .flags = I2C_M_RD,
- + .len = EDID_LENGTH,
- + .buf = edid,
- + },
- + };
- +
- + ret = i2c_transfer(adp, msg, ARRAY_SIZE(msg));
- + if (ret != ARRAY_SIZE(msg)) {
- + DPRINTK("unable to read EDID block\n");
- + return -EIO;
- + }
- +
- + if (seg_num == 2) {
- + regaddr = 128;
- + msg[2].buf = edid + EDID_LENGTH;
- +
- + ret = i2c_transfer(adp, msg, ARRAY_SIZE(msg));
- + if (ret != ARRAY_SIZE(msg)) {
- + DPRINTK("unable to read EDID block\n");
- + return -EIO;
- + }
- + }
- +
- + return ret;
- +}
- +
- +int mxc_edid_var_to_vic(struct fb_var_screeninfo *var)
- +{
- + int i;
- + struct fb_videomode m;
- +
- + for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) {
- + fb_var_to_videomode(&m, var);
- + if (mxc_edid_fb_mode_is_equal(false, &m, &mxc_cea_mode[i]))
- + break;
- + }
- +
- + if (i == ARRAY_SIZE(mxc_cea_mode))
- + return 0;
- +
- + return i;
- +}
- +EXPORT_SYMBOL(mxc_edid_var_to_vic);
- +
- +int mxc_edid_mode_to_vic(const struct fb_videomode *mode)
- +{
- + int i;
- + bool use_aspect = (mode->vmode & FB_VMODE_ASPECT_MASK);
- +
- + for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) {
- + if (mxc_edid_fb_mode_is_equal(use_aspect, mode, &mxc_cea_mode[i]))
- + break;
- + }
- +
- + if (i == ARRAY_SIZE(mxc_cea_mode))
- + return 0;
- +
- + return i;
- +}
- +EXPORT_SYMBOL(mxc_edid_mode_to_vic);
- +
- +/* make sure edid has 512 bytes*/
- +int mxc_edid_read(struct i2c_adapter *adp, unsigned short addr,
- + unsigned char *edid, struct mxc_edid_cfg *cfg, struct fb_info *fbi)
- +{
- + int ret = 0, extblknum;
- + if (!adp || !edid || !cfg || !fbi)
- + return -EINVAL;
- +
- + memset(edid, 0, EDID_LENGTH*4);
- + memset(cfg, 0, sizeof(struct mxc_edid_cfg));
- +
- + extblknum = mxc_edid_readblk(adp, addr, edid);
- + if (extblknum < 0)
- + return extblknum;
- +
- + /* edid first block parsing */
- + memset(&fbi->monspecs, 0, sizeof(fbi->monspecs));
- + fb_edid_to_monspecs(edid, &fbi->monspecs);
- +
- + if (extblknum) {
- + int i;
- +
- + /* need read segment block? */
- + if (extblknum > 1) {
- + ret = mxc_edid_readsegblk(adp, addr,
- + edid + EDID_LENGTH*2, extblknum - 1);
- + if (ret < 0)
- + return ret;
- + }
- +
- + for (i = 1; i <= extblknum; i++)
- + /* edid ext block parsing */
- + mxc_edid_parse_ext_blk(edid + i*EDID_LENGTH,
- + cfg, &fbi->monspecs);
- + }
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(mxc_edid_read);
- +
- diff -Nur linux-3.14.35.orig/drivers/video/mxc/mxcfb_hx8369_wvga.c linux-3.14.35/drivers/video/mxc/mxcfb_hx8369_wvga.c
- --- linux-3.14.35.orig/drivers/video/mxc/mxcfb_hx8369_wvga.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/video/mxc/mxcfb_hx8369_wvga.c 2015-03-08 14:27:37.785684499 -0500
- @@ -0,0 +1,449 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#include <linux/types.h>
- +#include <linux/init.h>
- +#include <linux/delay.h>
- +#include <linux/platform_device.h>
- +#include <linux/err.h>
- +#include <linux/clk.h>
- +#include <linux/console.h>
- +#include <linux/io.h>
- +#include <linux/bitops.h>
- +#include <linux/spinlock.h>
- +#include <linux/mipi_dsi.h>
- +#include <linux/mxcfb.h>
- +#include <linux/backlight.h>
- +#include <video/mipi_display.h>
- +
- +#include "mipi_dsi.h"
- +
- +#define MIPI_DSI_MAX_RET_PACK_SIZE (0x4)
- +
- +#define HX8369BL_MAX_BRIGHT (255)
- +#define HX8369BL_DEF_BRIGHT (255)
- +
- +#define HX8369_MAX_DPHY_CLK (800)
- +#define HX8369_ONE_DATA_LANE (0x1)
- +#define HX8369_TWO_DATA_LANE (0x2)
- +
- +#define HX8369_CMD_SETEXTC (0xB9)
- +#define HX8369_CMD_SETEXTC_LEN (0x4)
- +#define HX8369_CMD_SETEXTC_PARAM_1 (0x6983ff)
- +
- +#define HX8369_CMD_GETHXID (0xF4)
- +#define HX8369_CMD_GETHXID_LEN (0x4)
- +#define HX8369_ID (0x69)
- +#define HX8369_ID_MASK (0xFF)
- +
- +#define HX8369_CMD_SETDISP (0xB2)
- +#define HX8369_CMD_SETDISP_LEN (16)
- +#define HX8369_CMD_SETDISP_1_HALT (0x00)
- +#define HX8369_CMD_SETDISP_2_RES_MODE (0x23)
- +#define HX8369_CMD_SETDISP_3_BP (0x03)
- +#define HX8369_CMD_SETDISP_4_FP (0x03)
- +#define HX8369_CMD_SETDISP_5_SAP (0x70)
- +#define HX8369_CMD_SETDISP_6_GENON (0x00)
- +#define HX8369_CMD_SETDISP_7_GENOFF (0xff)
- +#define HX8369_CMD_SETDISP_8_RTN (0x00)
- +#define HX8369_CMD_SETDISP_9_TEI (0x00)
- +#define HX8369_CMD_SETDISP_10_TEP_UP (0x00)
- +#define HX8369_CMD_SETDISP_11_TEP_LOW (0x00)
- +#define HX8369_CMD_SETDISP_12_BP_PE (0x03)
- +#define HX8369_CMD_SETDISP_13_FP_PE (0x03)
- +#define HX8369_CMD_SETDISP_14_RTN_PE (0x00)
- +#define HX8369_CMD_SETDISP_15_GON (0x01)
- +
- +#define HX8369_CMD_SETCYC (0xB4)
- +#define HX8369_CMD_SETCYC_LEN (6)
- +#define HX8369_CMD_SETCYC_PARAM_1 (0x5f1d00)
- +#define HX8369_CMD_SETCYC_PARAM_2 (0x060e)
- +
- +#define HX8369_CMD_SETGIP (0xD5)
- +#define HX8369_CMD_SETGIP_LEN (27)
- +#define HX8369_CMD_SETGIP_PARAM_1 (0x030400)
- +#define HX8369_CMD_SETGIP_PARAM_2 (0x1c050100)
- +#define HX8369_CMD_SETGIP_PARAM_3 (0x00030170)
- +#define HX8369_CMD_SETGIP_PARAM_4 (0x51064000)
- +#define HX8369_CMD_SETGIP_PARAM_5 (0x41000007)
- +#define HX8369_CMD_SETGIP_PARAM_6 (0x07075006)
- +#define HX8369_CMD_SETGIP_PARAM_7 (0x040f)
- +
- +#define HX8369_CMD_SETPOWER (0xB1)
- +#define HX8369_CMD_SETPOWER_LEN (20)
- +#define HX8369_CMD_SETPOWER_PARAM_1 (0x340001)
- +#define HX8369_CMD_SETPOWER_PARAM_2 (0x0f0f0006)
- +#define HX8369_CMD_SETPOWER_PARAM_3 (0x3f3f322a)
- +#define HX8369_CMD_SETPOWER_PARAM_4 (0xe6013a07)
- +#define HX8369_CMD_SETPOWER_PARAM_5 (0xe6e6e6e6)
- +
- +#define HX8369_CMD_SETVCOM (0xB6)
- +#define HX8369_CMD_SETVCOM_LEN (3)
- +#define HX8369_CMD_SETVCOM_PARAM_1 (0x5656)
- +
- +#define HX8369_CMD_SETPANEL (0xCC)
- +#define HX8369_CMD_SETPANEL_PARAM_1 (0x02)
- +
- +#define HX8369_CMD_SETGAMMA (0xE0)
- +#define HX8369_CMD_SETGAMMA_LEN (35)
- +#define HX8369_CMD_SETGAMMA_PARAM_1 (0x221d00)
- +#define HX8369_CMD_SETGAMMA_PARAM_2 (0x2e3f3d38)
- +#define HX8369_CMD_SETGAMMA_PARAM_3 (0x0f0d064a)
- +#define HX8369_CMD_SETGAMMA_PARAM_4 (0x16131513)
- +#define HX8369_CMD_SETGAMMA_PARAM_5 (0x1d001910)
- +#define HX8369_CMD_SETGAMMA_PARAM_6 (0x3f3d3822)
- +#define HX8369_CMD_SETGAMMA_PARAM_7 (0x0d064a2e)
- +#define HX8369_CMD_SETGAMMA_PARAM_8 (0x1315130f)
- +#define HX8369_CMD_SETGAMMA_PARAM_9 (0x191016)
- +
- +#define HX8369_CMD_SETMIPI (0xBA)
- +#define HX8369_CMD_SETMIPI_LEN (14)
- +#define HX8369_CMD_SETMIPI_PARAM_1 (0xc6a000)
- +#define HX8369_CMD_SETMIPI_PARAM_2 (0x10000a00)
- +#define HX8369_CMD_SETMIPI_ONELANE (0x10 << 24)
- +#define HX8369_CMD_SETMIPI_TWOLANE (0x11 << 24)
- +#define HX8369_CMD_SETMIPI_PARAM_3 (0x00026f30)
- +#define HX8369_CMD_SETMIPI_PARAM_4 (0x4018)
- +
- +#define HX8369_CMD_SETPIXEL_FMT (0x3A)
- +#define HX8369_CMD_SETPIXEL_FMT_24BPP (0x77)
- +#define HX8369_CMD_SETPIXEL_FMT_18BPP (0x66)
- +#define HX8369_CMD_SETPIXEL_FMT_16BPP (0x55)
- +
- +#define HX8369_CMD_SETCLUMN_ADDR (0x2A)
- +#define HX8369_CMD_SETCLUMN_ADDR_LEN (5)
- +#define HX8369_CMD_SETCLUMN_ADDR_PARAM_1 (0xdf0000)
- +#define HX8369_CMD_SETCLUMN_ADDR_PARAM_2 (0x01)
- +
- +#define HX8369_CMD_SETPAGE_ADDR (0x2B)
- +#define HX8369_CMD_SETPAGE_ADDR_LEN (5)
- +#define HX8369_CMD_SETPAGE_ADDR_PARAM_1 (0x1f0000)
- +#define HX8369_CMD_SETPAGE_ADDR_PARAM_2 (0x03)
- +
- +#define HX8369_CMD_WRT_DISP_BRIGHT (0x51)
- +#define HX8369_CMD_WRT_DISP_BRIGHT_PARAM_1 (0xFF)
- +
- +#define HX8369_CMD_WRT_CABC_MIN_BRIGHT (0x5E)
- +#define HX8369_CMD_WRT_CABC_MIN_BRIGHT_PARAM_1 (0x20)
- +
- +#define HX8369_CMD_WRT_CABC_CTRL (0x55)
- +#define HX8369_CMD_WRT_CABC_CTRL_PARAM_1 (0x1)
- +
- +#define HX8369_CMD_WRT_CTRL_DISP (0x53)
- +#define HX8369_CMD_WRT_CTRL_DISP_PARAM_1 (0x24)
- +
- +#define CHECK_RETCODE(ret) \
- +do { \
- + if (ret < 0) { \
- + dev_err(&mipi_dsi->pdev->dev, \
- + "%s ERR: ret:%d, line:%d.\n", \
- + __func__, ret, __LINE__); \
- + return ret; \
- + } \
- +} while (0)
- +
- +static int hx8369bl_brightness;
- +static int mipid_init_backlight(struct mipi_dsi_info *mipi_dsi);
- +
- +static struct fb_videomode truly_lcd_modedb[] = {
- + {
- + "TRULY-WVGA", 64, 480, 800, 37880,
- + 8, 8,
- + 6, 6,
- + 8, 6,
- + FB_SYNC_OE_LOW_ACT,
- + FB_VMODE_NONINTERLACED,
- + 0,
- + },
- +};
- +
- +static struct mipi_lcd_config lcd_config = {
- + .virtual_ch = 0x0,
- + .data_lane_num = HX8369_TWO_DATA_LANE,
- + .max_phy_clk = HX8369_MAX_DPHY_CLK,
- + .dpi_fmt = MIPI_RGB888,
- +};
- +void mipid_hx8369_get_lcd_videomode(struct fb_videomode **mode, int *size,
- + struct mipi_lcd_config **data)
- +{
- + *mode = &truly_lcd_modedb[0];
- + *size = ARRAY_SIZE(truly_lcd_modedb);
- + *data = &lcd_config;
- +}
- +
- +int mipid_hx8369_lcd_setup(struct mipi_dsi_info *mipi_dsi)
- +{
- + u32 buf[DSI_CMD_BUF_MAXSIZE];
- + int err;
- +
- + dev_dbg(&mipi_dsi->pdev->dev, "MIPI DSI LCD setup.\n");
- + buf[0] = HX8369_CMD_SETEXTC | (HX8369_CMD_SETEXTC_PARAM_1 << 8);
- + err = mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE,
- + buf, HX8369_CMD_SETEXTC_LEN);
- + CHECK_RETCODE(err);
- + buf[0] = MIPI_DSI_MAX_RET_PACK_SIZE;
- + err = mipi_dsi_pkt_write(mipi_dsi,
- + MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
- + buf, 0);
- + CHECK_RETCODE(err);
- + buf[0] = HX8369_CMD_GETHXID;
- + err = mipi_dsi_pkt_read(mipi_dsi,
- + MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM,
- + buf, HX8369_CMD_GETHXID_LEN);
- + if (!err && ((buf[0] & HX8369_ID_MASK) == HX8369_ID)) {
- + dev_info(&mipi_dsi->pdev->dev,
- + "MIPI DSI LCD ID:0x%x.\n", buf[0]);
- + } else {
- + dev_err(&mipi_dsi->pdev->dev,
- + "mipi_dsi_pkt_read err:%d, data:0x%x.\n",
- + err, buf[0]);
- + dev_info(&mipi_dsi->pdev->dev,
- + "MIPI DSI LCD not detected!\n");
- + return err;
- + }
- +
- + /* set LCD resolution as 480RGBx800, DPI interface,
- + * display operation mode: RGB data bypass GRAM mode.
- + */
- + buf[0] = HX8369_CMD_SETDISP | (HX8369_CMD_SETDISP_1_HALT << 8) |
- + (HX8369_CMD_SETDISP_2_RES_MODE << 16) |
- + (HX8369_CMD_SETDISP_3_BP << 24);
- + buf[1] = HX8369_CMD_SETDISP_4_FP | (HX8369_CMD_SETDISP_5_SAP << 8) |
- + (HX8369_CMD_SETDISP_6_GENON << 16) |
- + (HX8369_CMD_SETDISP_7_GENOFF << 24);
- + buf[2] = HX8369_CMD_SETDISP_8_RTN | (HX8369_CMD_SETDISP_9_TEI << 8) |
- + (HX8369_CMD_SETDISP_10_TEP_UP << 16) |
- + (HX8369_CMD_SETDISP_11_TEP_LOW << 24);
- + buf[3] = HX8369_CMD_SETDISP_12_BP_PE |
- + (HX8369_CMD_SETDISP_13_FP_PE << 8) |
- + (HX8369_CMD_SETDISP_14_RTN_PE << 16) |
- + (HX8369_CMD_SETDISP_15_GON << 24);
- + err = mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE,
- + buf, HX8369_CMD_SETDISP_LEN);
- + CHECK_RETCODE(err);
- +
- + /* Set display waveform cycle */
- + buf[0] = HX8369_CMD_SETCYC | (HX8369_CMD_SETCYC_PARAM_1 << 8);
- + buf[1] = HX8369_CMD_SETCYC_PARAM_2;
- + err = mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE,
- + buf, HX8369_CMD_SETCYC_LEN);
- + CHECK_RETCODE(err);
- +
- + /* Set GIP timing output control */
- + buf[0] = HX8369_CMD_SETGIP | (HX8369_CMD_SETGIP_PARAM_1 << 8);
- + buf[1] = HX8369_CMD_SETGIP_PARAM_2;
- + buf[2] = HX8369_CMD_SETGIP_PARAM_3;
- + buf[3] = HX8369_CMD_SETGIP_PARAM_4;
- + buf[4] = HX8369_CMD_SETGIP_PARAM_5;
- + buf[5] = HX8369_CMD_SETGIP_PARAM_6;
- + buf[6] = HX8369_CMD_SETGIP_PARAM_7;
- + err = mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE, buf,
- + HX8369_CMD_SETGIP_LEN);
- + CHECK_RETCODE(err);
- +
- + /* Set power: standby, DC etc. */
- + buf[0] = HX8369_CMD_SETPOWER | (HX8369_CMD_SETPOWER_PARAM_1 << 8);
- + buf[1] = HX8369_CMD_SETPOWER_PARAM_2;
- + buf[2] = HX8369_CMD_SETPOWER_PARAM_3;
- + buf[3] = HX8369_CMD_SETPOWER_PARAM_4;
- + buf[4] = HX8369_CMD_SETPOWER_PARAM_5;
- + err = mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE, buf,
- + HX8369_CMD_SETPOWER_LEN);
- + CHECK_RETCODE(err);
- +
- + /* Set VCOM voltage. */
- + buf[0] = HX8369_CMD_SETVCOM | (HX8369_CMD_SETVCOM_PARAM_1 << 8);
- + err = mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE, buf,
- + HX8369_CMD_SETVCOM_LEN);
- + CHECK_RETCODE(err);
- +
- + /* Set Panel: BGR/RGB or Inversion. */
- + buf[0] = HX8369_CMD_SETPANEL | (HX8369_CMD_SETPANEL_PARAM_1 << 8);
- + err = mipi_dsi_pkt_write(mipi_dsi,
- + MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM, buf, 0);
- + CHECK_RETCODE(err);
- +
- + /* Set gamma curve related setting */
- + buf[0] = HX8369_CMD_SETGAMMA | (HX8369_CMD_SETGAMMA_PARAM_1 << 8);
- + buf[1] = HX8369_CMD_SETGAMMA_PARAM_2;
- + buf[2] = HX8369_CMD_SETGAMMA_PARAM_3;
- + buf[3] = HX8369_CMD_SETGAMMA_PARAM_4;
- + buf[4] = HX8369_CMD_SETGAMMA_PARAM_5;
- + buf[5] = HX8369_CMD_SETGAMMA_PARAM_6;
- + buf[7] = HX8369_CMD_SETGAMMA_PARAM_7;
- + buf[7] = HX8369_CMD_SETGAMMA_PARAM_8;
- + buf[8] = HX8369_CMD_SETGAMMA_PARAM_9;
- + err = mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE, buf,
- + HX8369_CMD_SETGAMMA_LEN);
- + CHECK_RETCODE(err);
- +
- + /* Set MIPI: DPHYCMD & DSICMD, data lane number */
- + buf[0] = HX8369_CMD_SETMIPI | (HX8369_CMD_SETMIPI_PARAM_1 << 8);
- + buf[1] = HX8369_CMD_SETMIPI_PARAM_2;
- + buf[2] = HX8369_CMD_SETMIPI_PARAM_3;
- + if (lcd_config.data_lane_num == HX8369_ONE_DATA_LANE)
- + buf[2] |= HX8369_CMD_SETMIPI_ONELANE;
- + else
- + buf[2] |= HX8369_CMD_SETMIPI_TWOLANE;
- + buf[3] = HX8369_CMD_SETMIPI_PARAM_4;
- + err = mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE, buf,
- + HX8369_CMD_SETMIPI_LEN);
- + CHECK_RETCODE(err);
- +
- + /* Set pixel format:24bpp */
- + buf[0] = HX8369_CMD_SETPIXEL_FMT;
- + switch (lcd_config.dpi_fmt) {
- + case MIPI_RGB565_PACKED:
- + case MIPI_RGB565_LOOSELY:
- + case MIPI_RGB565_CONFIG3:
- + buf[0] |= (HX8369_CMD_SETPIXEL_FMT_16BPP << 8);
- + break;
- +
- + case MIPI_RGB666_LOOSELY:
- + case MIPI_RGB666_PACKED:
- + buf[0] |= (HX8369_CMD_SETPIXEL_FMT_18BPP << 8);
- + break;
- +
- + case MIPI_RGB888:
- + buf[0] |= (HX8369_CMD_SETPIXEL_FMT_24BPP << 8);
- + break;
- +
- + default:
- + buf[0] |= (HX8369_CMD_SETPIXEL_FMT_24BPP << 8);
- + break;
- + }
- + err = mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM,
- + buf, 0);
- + CHECK_RETCODE(err);
- +
- + /* Set column address: 0~479 */
- + buf[0] = HX8369_CMD_SETCLUMN_ADDR |
- + (HX8369_CMD_SETCLUMN_ADDR_PARAM_1 << 8);
- + buf[1] = HX8369_CMD_SETCLUMN_ADDR_PARAM_2;
- + err = mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE,
- + buf, HX8369_CMD_SETCLUMN_ADDR_LEN);
- + CHECK_RETCODE(err);
- +
- + /* Set page address: 0~799 */
- + buf[0] = HX8369_CMD_SETPAGE_ADDR |
- + (HX8369_CMD_SETPAGE_ADDR_PARAM_1 << 8);
- + buf[1] = HX8369_CMD_SETPAGE_ADDR_PARAM_2;
- + err = mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE,
- + buf, HX8369_CMD_SETPAGE_ADDR_LEN);
- + CHECK_RETCODE(err);
- +
- + /* Set display brightness related */
- + buf[0] = HX8369_CMD_WRT_DISP_BRIGHT |
- + (HX8369_CMD_WRT_DISP_BRIGHT_PARAM_1 << 8);
- + err = mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM,
- + buf, 0);
- + CHECK_RETCODE(err);
- +
- + buf[0] = HX8369_CMD_WRT_CABC_CTRL |
- + (HX8369_CMD_WRT_CABC_CTRL_PARAM_1 << 8);
- + err = mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM,
- + buf, 0);
- + CHECK_RETCODE(err);
- +
- + buf[0] = HX8369_CMD_WRT_CTRL_DISP |
- + (HX8369_CMD_WRT_CTRL_DISP_PARAM_1 << 8);
- + err = mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM,
- + buf, 0);
- + CHECK_RETCODE(err);
- +
- + /* exit sleep mode and set display on */
- + buf[0] = MIPI_DCS_EXIT_SLEEP_MODE;
- + err = mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM,
- + buf, 0);
- + CHECK_RETCODE(err);
- + /* To allow time for the supply voltages
- + * and clock circuits to stabilize.
- + */
- + msleep(5);
- + buf[0] = MIPI_DCS_SET_DISPLAY_ON;
- + err = mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM,
- + buf, 0);
- + CHECK_RETCODE(err);
- +
- + err = mipid_init_backlight(mipi_dsi);
- + return err;
- +}
- +
- +static int mipid_bl_update_status(struct backlight_device *bl)
- +{
- + u32 buf;
- + int brightness = bl->props.brightness;
- + struct mipi_dsi_info *mipi_dsi = bl_get_data(bl);
- +
- + if (bl->props.power != FB_BLANK_UNBLANK ||
- + bl->props.fb_blank != FB_BLANK_UNBLANK)
- + brightness = 0;
- +
- + buf = HX8369_CMD_WRT_DISP_BRIGHT |
- + ((brightness & HX8369BL_MAX_BRIGHT) << 8);
- + mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM,
- + &buf, 0);
- +
- + hx8369bl_brightness = brightness & HX8369BL_MAX_BRIGHT;
- +
- + dev_dbg(&bl->dev, "mipid backlight bringtness:%d.\n", brightness);
- + return 0;
- +}
- +
- +static int mipid_bl_get_brightness(struct backlight_device *bl)
- +{
- + return hx8369bl_brightness;
- +}
- +
- +static int mipi_bl_check_fb(struct backlight_device *bl, struct fb_info *fbi)
- +{
- + return 0;
- +}
- +
- +static const struct backlight_ops mipid_lcd_bl_ops = {
- + .update_status = mipid_bl_update_status,
- + .get_brightness = mipid_bl_get_brightness,
- + .check_fb = mipi_bl_check_fb,
- +};
- +
- +static int mipid_init_backlight(struct mipi_dsi_info *mipi_dsi)
- +{
- + struct backlight_properties props;
- + struct backlight_device *bl;
- +
- + if (mipi_dsi->bl) {
- + pr_debug("mipid backlight already init!\n");
- + return 0;
- + }
- + memset(&props, 0, sizeof(struct backlight_properties));
- + props.max_brightness = HX8369BL_MAX_BRIGHT;
- + props.type = BACKLIGHT_RAW;
- + bl = backlight_device_register("mipid-bl", &mipi_dsi->pdev->dev,
- + mipi_dsi, &mipid_lcd_bl_ops, &props);
- + if (IS_ERR(bl)) {
- + pr_err("error %ld on backlight register\n", PTR_ERR(bl));
- + return PTR_ERR(bl);
- + }
- + mipi_dsi->bl = bl;
- + bl->props.power = FB_BLANK_UNBLANK;
- + bl->props.fb_blank = FB_BLANK_UNBLANK;
- + bl->props.brightness = HX8369BL_DEF_BRIGHT;
- +
- + mipid_bl_update_status(bl);
- + return 0;
- +}
- diff -Nur linux-3.14.35.orig/drivers/video/mxc/mxc_hdmi.c linux-3.14.35/drivers/video/mxc/mxc_hdmi.c
- --- linux-3.14.35.orig/drivers/video/mxc/mxc_hdmi.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/video/mxc/mxc_hdmi.c 2015-03-08 14:27:37.785684499 -0500
- @@ -0,0 +1,3042 @@
- +/*
- + * Copyright (C) 2011-2014 Freescale Semiconductor, 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + */
- +/*
- + * SH-Mobile High-Definition Multimedia Interface (HDMI) driver
- + * for SLISHDMI13T and SLIPHDMIT IP cores
- + *
- + * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/device.h>
- +#include <linux/platform_device.h>
- +#include <linux/input.h>
- +#include <linux/interrupt.h>
- +#include <linux/irq.h>
- +#include <linux/io.h>
- +#include <linux/fb.h>
- +#include <linux/init.h>
- +#include <linux/list.h>
- +#include <linux/delay.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/err.h>
- +#include <linux/clk.h>
- +#include <linux/uaccess.h>
- +#include <linux/cpufreq.h>
- +#include <linux/firmware.h>
- +#include <linux/kthread.h>
- +#include <linux/regulator/driver.h>
- +#include <linux/fsl_devices.h>
- +#include <linux/ipu.h>
- +#include <linux/regmap.h>
- +#include <linux/pinctrl/consumer.h>
- +#include <linux/of_device.h>
- +
- +#include <linux/console.h>
- +#include <linux/types.h>
- +
- +#include "../edid.h"
- +#include <video/mxc_edid.h>
- +#include <video/mxc_hdmi.h>
- +#include "mxc_dispdrv.h"
- +
- +#include <linux/mfd/mxc-hdmi-core.h>
- +
- +#define DISPDRV_HDMI "hdmi"
- +#define HDMI_EDID_LEN 512
- +
- +/* status codes for reading edid */
- +#define HDMI_EDID_SUCCESS 0
- +#define HDMI_EDID_FAIL -1
- +#define HDMI_EDID_SAME -2
- +#define HDMI_EDID_NO_MODES -3
- +
- +#define NUM_CEA_VIDEO_MODES 64
- +#define DEFAULT_VIDEO_MODE 16 /* 1080P */
- +
- +#define RGB 0
- +#define YCBCR444 1
- +#define YCBCR422_16BITS 2
- +#define YCBCR422_8BITS 3
- +#define XVYCC444 4
- +
- +/*
- + * We follow a flowchart which is in the "Synopsys DesignWare Courses
- + * HDMI Transmitter Controller User Guide, 1.30a", section 3.1
- + * (dwc_hdmi_tx_user.pdf)
- + *
- + * Below are notes that say "HDMI Initialization Step X"
- + * These correspond to the flowchart.
- + */
- +
- +/*
- + * We are required to configure VGA mode before reading edid
- + * in HDMI Initialization Step B
- + */
- +static const struct fb_videomode vga_mode = {
- + /* 640x480 @ 60 Hz, 31.5 kHz hsync */
- + NULL, 60, 640, 480, 39721, 48, 16, 33, 10, 96, 2, 0,
- + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, FB_MODE_IS_VESA,
- +};
- +
- +enum hdmi_datamap {
- + RGB444_8B = 0x01,
- + RGB444_10B = 0x03,
- + RGB444_12B = 0x05,
- + RGB444_16B = 0x07,
- + YCbCr444_8B = 0x09,
- + YCbCr444_10B = 0x0B,
- + YCbCr444_12B = 0x0D,
- + YCbCr444_16B = 0x0F,
- + YCbCr422_8B = 0x16,
- + YCbCr422_10B = 0x14,
- + YCbCr422_12B = 0x12,
- +};
- +
- +enum hdmi_colorimetry {
- + eITU601,
- + eITU709,
- +};
- +
- +struct hdmi_vmode {
- + bool mDVI;
- + bool mHSyncPolarity;
- + bool mVSyncPolarity;
- + bool mInterlaced;
- + bool mDataEnablePolarity;
- +
- + unsigned int mPixelClock;
- + unsigned int mPixelRepetitionInput;
- + unsigned int mPixelRepetitionOutput;
- +};
- +
- +struct hdmi_data_info {
- + unsigned int enc_in_format;
- + unsigned int enc_out_format;
- + unsigned int enc_color_depth;
- + unsigned int colorimetry;
- + unsigned int pix_repet_factor;
- + unsigned int hdcp_enable;
- + unsigned int rgb_out_enable;
- + unsigned int rgb_quant_range;
- + struct hdmi_vmode video_mode;
- +};
- +
- +struct hdmi_phy_reg_config {
- + /* HDMI PHY register config for pass HCT */
- + u16 reg_vlev;
- + u16 reg_cksymtx;
- +};
- +
- +struct mxc_hdmi {
- + struct platform_device *pdev;
- + struct platform_device *core_pdev;
- + struct mxc_dispdrv_handle *disp_mxc_hdmi;
- + struct fb_info *fbi;
- + struct clk *hdmi_isfr_clk;
- + struct clk *hdmi_iahb_clk;
- + struct timer_list jitter_timer;
- + struct work_struct hotplug_work;
- + struct delayed_work hdcp_hdp_work;
- +
- + struct notifier_block nb;
- +
- + struct hdmi_data_info hdmi_data;
- + int vic;
- + int edid_status;
- + struct mxc_edid_cfg edid_cfg;
- + u8 edid[HDMI_EDID_LEN];
- + bool fb_reg;
- + bool cable_plugin;
- + u8 blank;
- + bool dft_mode_set;
- + char *dft_mode_str;
- + int default_bpp;
- + u8 latest_intr_stat;
- + u8 plug_event;
- + u8 plug_mask;
- + bool irq_enabled;
- + spinlock_t irq_lock;
- + bool phy_enabled;
- + struct fb_videomode default_mode;
- + struct fb_videomode previous_non_vga_mode;
- + bool requesting_vga_for_initialization;
- +
- + int *gpr_base;
- + int *gpr_hdmi_base;
- + int *gpr_sdma_base;
- + int cpu_type;
- + int cpu_version;
- + struct hdmi_phy_reg_config phy_config;
- +
- + struct pinctrl *pinctrl;
- +};
- +
- +static int hdmi_major;
- +static struct class *hdmi_class;
- +
- +struct i2c_client *hdmi_i2c;
- +struct mxc_hdmi *g_hdmi;
- +
- +static bool hdmi_inited;
- +static bool hdcp_init;
- +
- +extern const struct fb_videomode mxc_cea_mode[64];
- +extern void mxc_hdmi_cec_handle(u16 cec_stat);
- +
- +static void mxc_hdmi_setup(struct mxc_hdmi *hdmi, unsigned long event);
- +static void hdmi_enable_overflow_interrupts(void);
- +static void hdmi_disable_overflow_interrupts(void);
- +
- +static char *rgb_quant_range = "default";
- +module_param(rgb_quant_range, charp, S_IRUGO);
- +MODULE_PARM_DESC(rgb_quant_range, "RGB Quant Range (default, limited, full)");
- +
- +static struct platform_device_id imx_hdmi_devtype[] = {
- + {
- + .name = "hdmi-imx6DL",
- + .driver_data = IMX6DL_HDMI,
- + }, {
- + .name = "hdmi-imx6Q",
- + .driver_data = IMX6Q_HDMI,
- + }, {
- + /* sentinel */
- + }
- +};
- +MODULE_DEVICE_TABLE(platform, imx_hdmi_devtype);
- +
- +static const struct of_device_id imx_hdmi_dt_ids[] = {
- + { .compatible = "fsl,imx6dl-hdmi-video", .data = &imx_hdmi_devtype[IMX6DL_HDMI], },
- + { .compatible = "fsl,imx6q-hdmi-video", .data = &imx_hdmi_devtype[IMX6Q_HDMI], },
- + { /* sentinel */ }
- +};
- +MODULE_DEVICE_TABLE(of, imx_hdmi_dt_ids);
- +
- +static inline int cpu_is_imx6dl(struct mxc_hdmi *hdmi)
- +{
- + return hdmi->cpu_type == IMX6DL_HDMI;
- +}
- +#ifdef DEBUG
- +static void dump_fb_videomode(struct fb_videomode *m)
- +{
- + pr_debug("fb_videomode = %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
- + m->refresh, m->xres, m->yres, m->pixclock, m->left_margin,
- + m->right_margin, m->upper_margin, m->lower_margin,
- + m->hsync_len, m->vsync_len, m->sync, m->vmode, m->flag);
- +}
- +#else
- +static void dump_fb_videomode(struct fb_videomode *m)
- +{}
- +#endif
- +
- +static ssize_t mxc_hdmi_show_name(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + struct mxc_hdmi *hdmi = dev_get_drvdata(dev);
- +
- + strcpy(buf, hdmi->fbi->fix.id);
- + sprintf(buf+strlen(buf), "\n");
- +
- + return strlen(buf);
- +}
- +
- +static DEVICE_ATTR(fb_name, S_IRUGO, mxc_hdmi_show_name, NULL);
- +
- +static ssize_t mxc_hdmi_show_state(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + struct mxc_hdmi *hdmi = dev_get_drvdata(dev);
- +
- + if (hdmi->cable_plugin == false)
- + strcpy(buf, "plugout\n");
- + else
- + strcpy(buf, "plugin\n");
- +
- + return strlen(buf);
- +}
- +
- +static DEVICE_ATTR(cable_state, S_IRUGO, mxc_hdmi_show_state, NULL);
- +
- +static ssize_t mxc_hdmi_show_edid(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + struct mxc_hdmi *hdmi = dev_get_drvdata(dev);
- + int i, j, len = 0;
- +
- + for (j = 0; j < HDMI_EDID_LEN/16; j++) {
- + for (i = 0; i < 16; i++)
- + len += sprintf(buf+len, "0x%02X ",
- + hdmi->edid[j*16 + i]);
- + len += sprintf(buf+len, "\n");
- + }
- +
- + return len;
- +}
- +
- +static DEVICE_ATTR(edid, S_IRUGO, mxc_hdmi_show_edid, NULL);
- +
- +static ssize_t mxc_hdmi_show_rgb_out_enable(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + struct mxc_hdmi *hdmi = dev_get_drvdata(dev);
- +
- + if (hdmi->hdmi_data.rgb_out_enable == true)
- + strcpy(buf, "RGB out\n");
- + else
- + strcpy(buf, "YCbCr out\n");
- +
- + return strlen(buf);
- +}
- +
- +static ssize_t mxc_hdmi_store_rgb_out_enable(struct device *dev,
- + struct device_attribute *attr, const char *buf, size_t count)
- +{
- + struct mxc_hdmi *hdmi = dev_get_drvdata(dev);
- + unsigned long value;
- + int ret;
- +
- + ret = strict_strtoul(buf, 10, &value);
- + if (ret)
- + return ret;
- +
- + hdmi->hdmi_data.rgb_out_enable = value;
- +
- + /* Reconfig HDMI for output color space change */
- + mxc_hdmi_setup(hdmi, 0);
- +
- + return count;
- +}
- +
- +static DEVICE_ATTR(rgb_out_enable, S_IRUGO | S_IWUSR,
- + mxc_hdmi_show_rgb_out_enable,
- + mxc_hdmi_store_rgb_out_enable);
- +
- +static ssize_t mxc_hdmi_show_rgb_quant_range(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + struct mxc_hdmi *hdmi = dev_get_drvdata(dev);
- +
- + switch (hdmi->hdmi_data.rgb_quant_range) {
- + case HDMI_FC_AVICONF2_RGB_QUANT_LIMITED_RANGE:
- + strcpy(buf, "limited\n");
- + break;
- + case HDMI_FC_AVICONF2_RGB_QUANT_FULL_RANGE:
- + strcpy(buf, "full\n");
- + break;
- + case HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT:
- + default:
- + strcpy(buf, "default\n");
- + break;
- + };
- +
- + return strlen(buf);
- +}
- +
- +static ssize_t mxc_hdmi_store_rgb_quant_range(struct device *dev,
- + struct device_attribute *attr, const char *buf, size_t count)
- +{
- + struct mxc_hdmi *hdmi = dev_get_drvdata(dev);
- + int ret = count;
- +
- + if (sysfs_streq("limited", buf)) {
- + hdmi->hdmi_data.rgb_quant_range = HDMI_FC_AVICONF2_RGB_QUANT_LIMITED_RANGE;
- + } else if (sysfs_streq("full", buf)) {
- + hdmi->hdmi_data.rgb_quant_range = HDMI_FC_AVICONF2_RGB_QUANT_FULL_RANGE;
- + } else if (sysfs_streq("default", buf)) {
- + hdmi->hdmi_data.rgb_quant_range = HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT;
- + } else {
- + ret = -EINVAL;
- + goto out;
- + }
- +
- + /* Reconfig HDMI for output RGB Quant Range change if using RGB out */
- + if(hdmi->hdmi_data.rgb_out_enable)
- + mxc_hdmi_setup(hdmi, 0);
- +out:
- + return ret;
- +}
- +
- +static DEVICE_ATTR(rgb_quant_range, S_IRUGO | S_IWUSR,
- + mxc_hdmi_show_rgb_quant_range,
- + mxc_hdmi_store_rgb_quant_range);
- +
- +static ssize_t mxc_hdmi_show_hdcp_enable(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + struct mxc_hdmi *hdmi = dev_get_drvdata(dev);
- +
- + if (hdmi->hdmi_data.hdcp_enable == false)
- + strcpy(buf, "hdcp disable\n");
- + else
- + strcpy(buf, "hdcp enable\n");
- +
- + return strlen(buf);
- +
- +}
- +
- +static ssize_t mxc_hdmi_store_hdcp_enable(struct device *dev,
- + struct device_attribute *attr, const char *buf, size_t count)
- +{
- + struct mxc_hdmi *hdmi = dev_get_drvdata(dev);
- + char event_string[32];
- + char *envp[] = { event_string, NULL };
- + unsigned long value;
- + int ret;
- +
- + ret = strict_strtoul(buf, 10, &value);
- + if (ret)
- + return ret;
- +
- + hdmi->hdmi_data.hdcp_enable = value;
- +
- + /* Reconfig HDMI for HDCP */
- + mxc_hdmi_setup(hdmi, 0);
- +
- + if (hdmi->hdmi_data.hdcp_enable == false) {
- + sprintf(event_string, "EVENT=hdcpdisable");
- + kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
- + } else {
- + sprintf(event_string, "EVENT=hdcpenable");
- + kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
- + }
- +
- + return count;
- +
- +}
- +
- +static DEVICE_ATTR(hdcp_enable, S_IRUGO | S_IWUSR,
- + mxc_hdmi_show_hdcp_enable, mxc_hdmi_store_hdcp_enable);
- +
- +/*!
- + * this submodule is responsible for the video data synchronization.
- + * for example, for RGB 4:4:4 input, the data map is defined as
- + * pin{47~40} <==> R[7:0]
- + * pin{31~24} <==> G[7:0]
- + * pin{15~8} <==> B[7:0]
- + */
- +static void hdmi_video_sample(struct mxc_hdmi *hdmi)
- +{
- + int color_format = 0;
- + u8 val;
- +
- + if (hdmi->hdmi_data.enc_in_format == RGB) {
- + if (hdmi->hdmi_data.enc_color_depth == 8)
- + color_format = 0x01;
- + else if (hdmi->hdmi_data.enc_color_depth == 10)
- + color_format = 0x03;
- + else if (hdmi->hdmi_data.enc_color_depth == 12)
- + color_format = 0x05;
- + else if (hdmi->hdmi_data.enc_color_depth == 16)
- + color_format = 0x07;
- + else
- + return;
- + } else if (hdmi->hdmi_data.enc_in_format == YCBCR444) {
- + if (hdmi->hdmi_data.enc_color_depth == 8)
- + color_format = 0x09;
- + else if (hdmi->hdmi_data.enc_color_depth == 10)
- + color_format = 0x0B;
- + else if (hdmi->hdmi_data.enc_color_depth == 12)
- + color_format = 0x0D;
- + else if (hdmi->hdmi_data.enc_color_depth == 16)
- + color_format = 0x0F;
- + else
- + return;
- + } else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) {
- + if (hdmi->hdmi_data.enc_color_depth == 8)
- + color_format = 0x16;
- + else if (hdmi->hdmi_data.enc_color_depth == 10)
- + color_format = 0x14;
- + else if (hdmi->hdmi_data.enc_color_depth == 12)
- + color_format = 0x12;
- + else
- + return;
- + }
- +
- + val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
- + ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
- + HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
- + hdmi_writeb(val, HDMI_TX_INVID0);
- +
- + /* Enable TX stuffing: When DE is inactive, fix the output data to 0 */
- + val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
- + HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
- + HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
- + hdmi_writeb(val, HDMI_TX_INSTUFFING);
- + hdmi_writeb(0x0, HDMI_TX_GYDATA0);
- + hdmi_writeb(0x0, HDMI_TX_GYDATA1);
- + hdmi_writeb(0x0, HDMI_TX_RCRDATA0);
- + hdmi_writeb(0x0, HDMI_TX_RCRDATA1);
- + hdmi_writeb(0x0, HDMI_TX_BCBDATA0);
- + hdmi_writeb(0x0, HDMI_TX_BCBDATA1);
- +}
- +
- +static int isColorSpaceConversion(struct mxc_hdmi *hdmi)
- +{
- + return (hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format) ||
- + (hdmi->hdmi_data.enc_out_format == RGB &&
- + ((hdmi->hdmi_data.rgb_quant_range == HDMI_FC_AVICONF2_RGB_QUANT_LIMITED_RANGE) ||
- + (hdmi->hdmi_data.rgb_quant_range == HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT && hdmi->vic > 1)));
- +}
- +
- +static int isColorSpaceDecimation(struct mxc_hdmi *hdmi)
- +{
- + return ((hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS) &&
- + (hdmi->hdmi_data.enc_in_format == RGB ||
- + hdmi->hdmi_data.enc_in_format == YCBCR444));
- +}
- +
- +static int isColorSpaceInterpolation(struct mxc_hdmi *hdmi)
- +{
- + return ((hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) &&
- + (hdmi->hdmi_data.enc_out_format == RGB
- + || hdmi->hdmi_data.enc_out_format == YCBCR444));
- +}
- +
- +/*!
- + * update the color space conversion coefficients.
- + */
- +static void update_csc_coeffs(struct mxc_hdmi *hdmi)
- +{
- + unsigned short csc_coeff[3][4];
- + unsigned int csc_scale = 1;
- + u8 val;
- + bool coeff_selected = false;
- +
- + if (isColorSpaceConversion(hdmi)) { /* csc needed */
- + if (hdmi->hdmi_data.enc_out_format == RGB) {
- + if (hdmi->hdmi_data.enc_in_format == RGB) {
- + csc_coeff[0][0] = 0x1b80;
- + csc_coeff[0][1] = 0x0000;
- + csc_coeff[0][2] = 0x0000;
- + csc_coeff[0][3] = 0x0020;
- +
- + csc_coeff[1][0] = 0x0000;
- + csc_coeff[1][1] = 0x1b80;
- + csc_coeff[1][2] = 0x0000;
- + csc_coeff[1][3] = 0x0020;
- +
- + csc_coeff[2][0] = 0x0000;
- + csc_coeff[2][1] = 0x0000;
- + csc_coeff[2][2] = 0x1b80;
- + csc_coeff[2][3] = 0x0020;
- +
- + csc_scale = 1;
- + coeff_selected = true;
- + } else if (hdmi->hdmi_data.colorimetry == eITU601) {
- + csc_coeff[0][0] = 0x2000;
- + csc_coeff[0][1] = 0x6926;
- + csc_coeff[0][2] = 0x74fd;
- + csc_coeff[0][3] = 0x010e;
- +
- + csc_coeff[1][0] = 0x2000;
- + csc_coeff[1][1] = 0x2cdd;
- + csc_coeff[1][2] = 0x0000;
- + csc_coeff[1][3] = 0x7e9a;
- +
- + csc_coeff[2][0] = 0x2000;
- + csc_coeff[2][1] = 0x0000;
- + csc_coeff[2][2] = 0x38b4;
- + csc_coeff[2][3] = 0x7e3b;
- +
- + csc_scale = 1;
- + coeff_selected = true;
- + } else if (hdmi->hdmi_data.colorimetry == eITU709) {
- + csc_coeff[0][0] = 0x2000;
- + csc_coeff[0][1] = 0x7106;
- + csc_coeff[0][2] = 0x7a02;
- + csc_coeff[0][3] = 0x00a7;
- +
- + csc_coeff[1][0] = 0x2000;
- + csc_coeff[1][1] = 0x3264;
- + csc_coeff[1][2] = 0x0000;
- + csc_coeff[1][3] = 0x7e6d;
- +
- + csc_coeff[2][0] = 0x2000;
- + csc_coeff[2][1] = 0x0000;
- + csc_coeff[2][2] = 0x3b61;
- + csc_coeff[2][3] = 0x7e25;
- +
- + csc_scale = 1;
- + coeff_selected = true;
- + }
- + } else if (hdmi->hdmi_data.enc_in_format == RGB) {
- + if (hdmi->hdmi_data.colorimetry == eITU601) {
- + csc_coeff[0][0] = 0x2591;
- + csc_coeff[0][1] = 0x1322;
- + csc_coeff[0][2] = 0x074b;
- + csc_coeff[0][3] = 0x0000;
- +
- + csc_coeff[1][0] = 0x6535;
- + csc_coeff[1][1] = 0x2000;
- + csc_coeff[1][2] = 0x7acc;
- + csc_coeff[1][3] = 0x0200;
- +
- + csc_coeff[2][0] = 0x6acd;
- + csc_coeff[2][1] = 0x7534;
- + csc_coeff[2][2] = 0x2000;
- + csc_coeff[2][3] = 0x0200;
- +
- + csc_scale = 0;
- + coeff_selected = true;
- + } else if (hdmi->hdmi_data.colorimetry == eITU709) {
- + csc_coeff[0][0] = 0x2dc5;
- + csc_coeff[0][1] = 0x0d9b;
- + csc_coeff[0][2] = 0x049e;
- + csc_coeff[0][3] = 0x0000;
- +
- + csc_coeff[1][0] = 0x62f0;
- + csc_coeff[1][1] = 0x2000;
- + csc_coeff[1][2] = 0x7d11;
- + csc_coeff[1][3] = 0x0200;
- +
- + csc_coeff[2][0] = 0x6756;
- + csc_coeff[2][1] = 0x78ab;
- + csc_coeff[2][2] = 0x2000;
- + csc_coeff[2][3] = 0x0200;
- +
- + csc_scale = 0;
- + coeff_selected = true;
- + }
- + }
- + }
- +
- + if (!coeff_selected) {
- + csc_coeff[0][0] = 0x2000;
- + csc_coeff[0][1] = 0x0000;
- + csc_coeff[0][2] = 0x0000;
- + csc_coeff[0][3] = 0x0000;
- +
- + csc_coeff[1][0] = 0x0000;
- + csc_coeff[1][1] = 0x2000;
- + csc_coeff[1][2] = 0x0000;
- + csc_coeff[1][3] = 0x0000;
- +
- + csc_coeff[2][0] = 0x0000;
- + csc_coeff[2][1] = 0x0000;
- + csc_coeff[2][2] = 0x2000;
- + csc_coeff[2][3] = 0x0000;
- +
- + csc_scale = 1;
- + }
- +
- + /* Update CSC parameters in HDMI CSC registers */
- + hdmi_writeb((unsigned char)(csc_coeff[0][0] & 0xFF),
- + HDMI_CSC_COEF_A1_LSB);
- + hdmi_writeb((unsigned char)(csc_coeff[0][0] >> 8),
- + HDMI_CSC_COEF_A1_MSB);
- + hdmi_writeb((unsigned char)(csc_coeff[0][1] & 0xFF),
- + HDMI_CSC_COEF_A2_LSB);
- + hdmi_writeb((unsigned char)(csc_coeff[0][1] >> 8),
- + HDMI_CSC_COEF_A2_MSB);
- + hdmi_writeb((unsigned char)(csc_coeff[0][2] & 0xFF),
- + HDMI_CSC_COEF_A3_LSB);
- + hdmi_writeb((unsigned char)(csc_coeff[0][2] >> 8),
- + HDMI_CSC_COEF_A3_MSB);
- + hdmi_writeb((unsigned char)(csc_coeff[0][3] & 0xFF),
- + HDMI_CSC_COEF_A4_LSB);
- + hdmi_writeb((unsigned char)(csc_coeff[0][3] >> 8),
- + HDMI_CSC_COEF_A4_MSB);
- +
- + hdmi_writeb((unsigned char)(csc_coeff[1][0] & 0xFF),
- + HDMI_CSC_COEF_B1_LSB);
- + hdmi_writeb((unsigned char)(csc_coeff[1][0] >> 8),
- + HDMI_CSC_COEF_B1_MSB);
- + hdmi_writeb((unsigned char)(csc_coeff[1][1] & 0xFF),
- + HDMI_CSC_COEF_B2_LSB);
- + hdmi_writeb((unsigned char)(csc_coeff[1][1] >> 8),
- + HDMI_CSC_COEF_B2_MSB);
- + hdmi_writeb((unsigned char)(csc_coeff[1][2] & 0xFF),
- + HDMI_CSC_COEF_B3_LSB);
- + hdmi_writeb((unsigned char)(csc_coeff[1][2] >> 8),
- + HDMI_CSC_COEF_B3_MSB);
- + hdmi_writeb((unsigned char)(csc_coeff[1][3] & 0xFF),
- + HDMI_CSC_COEF_B4_LSB);
- + hdmi_writeb((unsigned char)(csc_coeff[1][3] >> 8),
- + HDMI_CSC_COEF_B4_MSB);
- +
- + hdmi_writeb((unsigned char)(csc_coeff[2][0] & 0xFF),
- + HDMI_CSC_COEF_C1_LSB);
- + hdmi_writeb((unsigned char)(csc_coeff[2][0] >> 8),
- + HDMI_CSC_COEF_C1_MSB);
- + hdmi_writeb((unsigned char)(csc_coeff[2][1] & 0xFF),
- + HDMI_CSC_COEF_C2_LSB);
- + hdmi_writeb((unsigned char)(csc_coeff[2][1] >> 8),
- + HDMI_CSC_COEF_C2_MSB);
- + hdmi_writeb((unsigned char)(csc_coeff[2][2] & 0xFF),
- + HDMI_CSC_COEF_C3_LSB);
- + hdmi_writeb((unsigned char)(csc_coeff[2][2] >> 8),
- + HDMI_CSC_COEF_C3_MSB);
- + hdmi_writeb((unsigned char)(csc_coeff[2][3] & 0xFF),
- + HDMI_CSC_COEF_C4_LSB);
- + hdmi_writeb((unsigned char)(csc_coeff[2][3] >> 8),
- + HDMI_CSC_COEF_C4_MSB);
- +
- + val = hdmi_readb(HDMI_CSC_SCALE);
- + val &= ~HDMI_CSC_SCALE_CSCSCALE_MASK;
- + val |= csc_scale & HDMI_CSC_SCALE_CSCSCALE_MASK;
- + hdmi_writeb(val, HDMI_CSC_SCALE);
- +}
- +
- +static void hdmi_video_csc(struct mxc_hdmi *hdmi)
- +{
- + int color_depth = 0;
- + int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
- + int decimation = HDMI_CSC_CFG_DECMODE_DISABLE;
- + u8 val;
- +
- + /* YCC422 interpolation to 444 mode */
- + if (isColorSpaceInterpolation(hdmi))
- + interpolation = HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1;
- + else if (isColorSpaceDecimation(hdmi))
- + decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
- +
- + if (hdmi->hdmi_data.enc_color_depth == 8)
- + color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
- + else if (hdmi->hdmi_data.enc_color_depth == 10)
- + color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
- + else if (hdmi->hdmi_data.enc_color_depth == 12)
- + color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
- + else if (hdmi->hdmi_data.enc_color_depth == 16)
- + color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
- + else
- + return;
- +
- + /*configure the CSC registers */
- + hdmi_writeb(interpolation | decimation, HDMI_CSC_CFG);
- + val = hdmi_readb(HDMI_CSC_SCALE);
- + val &= ~HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK;
- + val |= color_depth;
- + hdmi_writeb(val, HDMI_CSC_SCALE);
- +
- + update_csc_coeffs(hdmi);
- +}
- +
- +/*!
- + * HDMI video packetizer is used to packetize the data.
- + * for example, if input is YCC422 mode or repeater is used,
- + * data should be repacked this module can be bypassed.
- + */
- +static void hdmi_video_packetize(struct mxc_hdmi *hdmi)
- +{
- + unsigned int color_depth = 0;
- + unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit;
- + unsigned int output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_PP;
- + struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
- + u8 val;
- +
- + if (hdmi_data->enc_out_format == RGB
- + || hdmi_data->enc_out_format == YCBCR444) {
- + if (hdmi_data->enc_color_depth == 0)
- + output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
- + else if (hdmi_data->enc_color_depth == 8) {
- + color_depth = 4;
- + output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
- + } else if (hdmi_data->enc_color_depth == 10)
- + color_depth = 5;
- + else if (hdmi_data->enc_color_depth == 12)
- + color_depth = 6;
- + else if (hdmi_data->enc_color_depth == 16)
- + color_depth = 7;
- + else
- + return;
- + } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
- + if (hdmi_data->enc_color_depth == 0 ||
- + hdmi_data->enc_color_depth == 8)
- + remap_size = HDMI_VP_REMAP_YCC422_16bit;
- + else if (hdmi_data->enc_color_depth == 10)
- + remap_size = HDMI_VP_REMAP_YCC422_20bit;
- + else if (hdmi_data->enc_color_depth == 12)
- + remap_size = HDMI_VP_REMAP_YCC422_24bit;
- + else
- + return;
- + output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
- + } else
- + return;
- +
- + /* HDMI not support deep color,
- + * because IPU MAX support color depth is 24bit */
- + color_depth = 0;
- +
- + /* set the packetizer registers */
- + val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
- + HDMI_VP_PR_CD_COLOR_DEPTH_MASK) |
- + ((hdmi_data->pix_repet_factor <<
- + HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) &
- + HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
- + hdmi_writeb(val, HDMI_VP_PR_CD);
- +
- + val = hdmi_readb(HDMI_VP_STUFF);
- + val &= ~HDMI_VP_STUFF_PR_STUFFING_MASK;
- + val |= HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE;
- + hdmi_writeb(val, HDMI_VP_STUFF);
- +
- + /* Data from pixel repeater block */
- + if (hdmi_data->pix_repet_factor > 1) {
- + val = hdmi_readb(HDMI_VP_CONF);
- + val &= ~(HDMI_VP_CONF_PR_EN_MASK |
- + HDMI_VP_CONF_BYPASS_SELECT_MASK);
- + val |= HDMI_VP_CONF_PR_EN_ENABLE |
- + HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER;
- + hdmi_writeb(val, HDMI_VP_CONF);
- + } else { /* data from packetizer block */
- + val = hdmi_readb(HDMI_VP_CONF);
- + val &= ~(HDMI_VP_CONF_PR_EN_MASK |
- + HDMI_VP_CONF_BYPASS_SELECT_MASK);
- + val |= HDMI_VP_CONF_PR_EN_DISABLE |
- + HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
- + hdmi_writeb(val, HDMI_VP_CONF);
- + }
- +
- + val = hdmi_readb(HDMI_VP_STUFF);
- + val &= ~HDMI_VP_STUFF_IDEFAULT_PHASE_MASK;
- + val |= 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET;
- + hdmi_writeb(val, HDMI_VP_STUFF);
- +
- + hdmi_writeb(remap_size, HDMI_VP_REMAP);
- +
- + if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) {
- + val = hdmi_readb(HDMI_VP_CONF);
- + val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
- + HDMI_VP_CONF_PP_EN_ENMASK |
- + HDMI_VP_CONF_YCC422_EN_MASK);
- + val |= HDMI_VP_CONF_BYPASS_EN_DISABLE |
- + HDMI_VP_CONF_PP_EN_ENABLE |
- + HDMI_VP_CONF_YCC422_EN_DISABLE;
- + hdmi_writeb(val, HDMI_VP_CONF);
- + } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422) {
- + val = hdmi_readb(HDMI_VP_CONF);
- + val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
- + HDMI_VP_CONF_PP_EN_ENMASK |
- + HDMI_VP_CONF_YCC422_EN_MASK);
- + val |= HDMI_VP_CONF_BYPASS_EN_DISABLE |
- + HDMI_VP_CONF_PP_EN_DISABLE |
- + HDMI_VP_CONF_YCC422_EN_ENABLE;
- + hdmi_writeb(val, HDMI_VP_CONF);
- + } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS) {
- + val = hdmi_readb(HDMI_VP_CONF);
- + val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
- + HDMI_VP_CONF_PP_EN_ENMASK |
- + HDMI_VP_CONF_YCC422_EN_MASK);
- + val |= HDMI_VP_CONF_BYPASS_EN_ENABLE |
- + HDMI_VP_CONF_PP_EN_DISABLE |
- + HDMI_VP_CONF_YCC422_EN_DISABLE;
- + hdmi_writeb(val, HDMI_VP_CONF);
- + } else {
- + return;
- + }
- +
- + val = hdmi_readb(HDMI_VP_STUFF);
- + val &= ~(HDMI_VP_STUFF_PP_STUFFING_MASK |
- + HDMI_VP_STUFF_YCC422_STUFFING_MASK);
- + val |= HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
- + HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE;
- + hdmi_writeb(val, HDMI_VP_STUFF);
- +
- + val = hdmi_readb(HDMI_VP_CONF);
- + val &= ~HDMI_VP_CONF_OUTPUT_SELECTOR_MASK;
- + val |= output_select;
- + hdmi_writeb(val, HDMI_VP_CONF);
- +}
- +
- +#if 0
- +/* Force a fixed color screen */
- +static void hdmi_video_force_output(struct mxc_hdmi *hdmi, unsigned char force)
- +{
- + u8 val;
- +
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + if (force) {
- + hdmi_writeb(0x00, HDMI_FC_DBGTMDS2); /* R */
- + hdmi_writeb(0x00, HDMI_FC_DBGTMDS1); /* G */
- + hdmi_writeb(0xFF, HDMI_FC_DBGTMDS0); /* B */
- + val = hdmi_readb(HDMI_FC_DBGFORCE);
- + val |= HDMI_FC_DBGFORCE_FORCEVIDEO;
- + hdmi_writeb(val, HDMI_FC_DBGFORCE);
- + } else {
- + val = hdmi_readb(HDMI_FC_DBGFORCE);
- + val &= ~HDMI_FC_DBGFORCE_FORCEVIDEO;
- + hdmi_writeb(val, HDMI_FC_DBGFORCE);
- + hdmi_writeb(0x00, HDMI_FC_DBGTMDS2); /* R */
- + hdmi_writeb(0x00, HDMI_FC_DBGTMDS1); /* G */
- + hdmi_writeb(0x00, HDMI_FC_DBGTMDS0); /* B */
- + }
- +}
- +#endif
- +
- +static inline void hdmi_phy_test_clear(struct mxc_hdmi *hdmi,
- + unsigned char bit)
- +{
- + u8 val = hdmi_readb(HDMI_PHY_TST0);
- + val &= ~HDMI_PHY_TST0_TSTCLR_MASK;
- + val |= (bit << HDMI_PHY_TST0_TSTCLR_OFFSET) &
- + HDMI_PHY_TST0_TSTCLR_MASK;
- + hdmi_writeb(val, HDMI_PHY_TST0);
- +}
- +
- +static inline void hdmi_phy_test_enable(struct mxc_hdmi *hdmi,
- + unsigned char bit)
- +{
- + u8 val = hdmi_readb(HDMI_PHY_TST0);
- + val &= ~HDMI_PHY_TST0_TSTEN_MASK;
- + val |= (bit << HDMI_PHY_TST0_TSTEN_OFFSET) &
- + HDMI_PHY_TST0_TSTEN_MASK;
- + hdmi_writeb(val, HDMI_PHY_TST0);
- +}
- +
- +static inline void hdmi_phy_test_clock(struct mxc_hdmi *hdmi,
- + unsigned char bit)
- +{
- + u8 val = hdmi_readb(HDMI_PHY_TST0);
- + val &= ~HDMI_PHY_TST0_TSTCLK_MASK;
- + val |= (bit << HDMI_PHY_TST0_TSTCLK_OFFSET) &
- + HDMI_PHY_TST0_TSTCLK_MASK;
- + hdmi_writeb(val, HDMI_PHY_TST0);
- +}
- +
- +static inline void hdmi_phy_test_din(struct mxc_hdmi *hdmi,
- + unsigned char bit)
- +{
- + hdmi_writeb(bit, HDMI_PHY_TST1);
- +}
- +
- +static inline void hdmi_phy_test_dout(struct mxc_hdmi *hdmi,
- + unsigned char bit)
- +{
- + hdmi_writeb(bit, HDMI_PHY_TST2);
- +}
- +
- +static bool hdmi_phy_wait_i2c_done(struct mxc_hdmi *hdmi, int msec)
- +{
- + unsigned char val = 0;
- + val = hdmi_readb(HDMI_IH_I2CMPHY_STAT0) & 0x3;
- + while (val == 0) {
- + udelay(1000);
- + if (msec-- == 0)
- + return false;
- + val = hdmi_readb(HDMI_IH_I2CMPHY_STAT0) & 0x3;
- + }
- + return true;
- +}
- +
- +static void hdmi_phy_i2c_write(struct mxc_hdmi *hdmi, unsigned short data,
- + unsigned char addr)
- +{
- + hdmi_writeb(0xFF, HDMI_IH_I2CMPHY_STAT0);
- + hdmi_writeb(addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
- + hdmi_writeb((unsigned char)(data >> 8),
- + HDMI_PHY_I2CM_DATAO_1_ADDR);
- + hdmi_writeb((unsigned char)(data >> 0),
- + HDMI_PHY_I2CM_DATAO_0_ADDR);
- + hdmi_writeb(HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
- + HDMI_PHY_I2CM_OPERATION_ADDR);
- + hdmi_phy_wait_i2c_done(hdmi, 1000);
- +}
- +
- +#if 0
- +static unsigned short hdmi_phy_i2c_read(struct mxc_hdmi *hdmi,
- + unsigned char addr)
- +{
- + unsigned short data;
- + unsigned char msb = 0, lsb = 0;
- + hdmi_writeb(0xFF, HDMI_IH_I2CMPHY_STAT0);
- + hdmi_writeb(addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
- + hdmi_writeb(HDMI_PHY_I2CM_OPERATION_ADDR_READ,
- + HDMI_PHY_I2CM_OPERATION_ADDR);
- + hdmi_phy_wait_i2c_done(hdmi, 1000);
- + msb = hdmi_readb(HDMI_PHY_I2CM_DATAI_1_ADDR);
- + lsb = hdmi_readb(HDMI_PHY_I2CM_DATAI_0_ADDR);
- + data = (msb << 8) | lsb;
- + return data;
- +}
- +
- +static int hdmi_phy_i2c_write_verify(struct mxc_hdmi *hdmi, unsigned short data,
- + unsigned char addr)
- +{
- + unsigned short val = 0;
- + hdmi_phy_i2c_write(hdmi, data, addr);
- + val = hdmi_phy_i2c_read(hdmi, addr);
- + return (val == data);
- +}
- +#endif
- +
- +static bool hdmi_edid_wait_i2c_done(struct mxc_hdmi *hdmi, int msec)
- +{
- + unsigned char val = 0;
- + val = hdmi_readb(HDMI_IH_I2CM_STAT0) & 0x2;
- + while (val == 0) {
- +
- + udelay(1000);
- + if (msec-- == 0) {
- + dev_dbg(&hdmi->pdev->dev,
- + "HDMI EDID i2c operation time out!!\n");
- + return false;
- + }
- + val = hdmi_readb(HDMI_IH_I2CM_STAT0) & 0x2;
- + }
- + return true;
- +}
- +
- +static u8 hdmi_edid_i2c_read(struct mxc_hdmi *hdmi,
- + u8 addr, u8 blockno)
- +{
- + u8 spointer = blockno / 2;
- + u8 edidaddress = ((blockno % 2) * 0x80) + addr;
- + u8 data;
- +
- + hdmi_writeb(0xFF, HDMI_IH_I2CM_STAT0);
- + hdmi_writeb(edidaddress, HDMI_I2CM_ADDRESS);
- + hdmi_writeb(spointer, HDMI_I2CM_SEGADDR);
- + if (spointer == 0)
- + hdmi_writeb(HDMI_I2CM_OPERATION_READ,
- + HDMI_I2CM_OPERATION);
- + else
- + hdmi_writeb(HDMI_I2CM_OPERATION_READ_EXT,
- + HDMI_I2CM_OPERATION);
- +
- + hdmi_edid_wait_i2c_done(hdmi, 1000);
- + data = hdmi_readb(HDMI_I2CM_DATAI);
- + hdmi_writeb(0xFF, HDMI_IH_I2CM_STAT0);
- + return data;
- +}
- +
- +
- +/* "Power-down enable (active low)"
- + * That mean that power up == 1! */
- +static void mxc_hdmi_phy_enable_power(u8 enable)
- +{
- + hdmi_mask_writeb(enable, HDMI_PHY_CONF0,
- + HDMI_PHY_CONF0_PDZ_OFFSET,
- + HDMI_PHY_CONF0_PDZ_MASK);
- +}
- +
- +static void mxc_hdmi_phy_enable_tmds(u8 enable)
- +{
- + hdmi_mask_writeb(enable, HDMI_PHY_CONF0,
- + HDMI_PHY_CONF0_ENTMDS_OFFSET,
- + HDMI_PHY_CONF0_ENTMDS_MASK);
- +}
- +
- +static void mxc_hdmi_phy_gen2_pddq(u8 enable)
- +{
- + hdmi_mask_writeb(enable, HDMI_PHY_CONF0,
- + HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET,
- + HDMI_PHY_CONF0_GEN2_PDDQ_MASK);
- +}
- +
- +static void mxc_hdmi_phy_gen2_txpwron(u8 enable)
- +{
- + hdmi_mask_writeb(enable, HDMI_PHY_CONF0,
- + HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET,
- + HDMI_PHY_CONF0_GEN2_TXPWRON_MASK);
- +}
- +
- +#if 0
- +static void mxc_hdmi_phy_gen2_enhpdrxsense(u8 enable)
- +{
- + hdmi_mask_writeb(enable, HDMI_PHY_CONF0,
- + HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_OFFSET,
- + HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_MASK);
- +}
- +#endif
- +
- +static void mxc_hdmi_phy_sel_data_en_pol(u8 enable)
- +{
- + hdmi_mask_writeb(enable, HDMI_PHY_CONF0,
- + HDMI_PHY_CONF0_SELDATAENPOL_OFFSET,
- + HDMI_PHY_CONF0_SELDATAENPOL_MASK);
- +}
- +
- +static void mxc_hdmi_phy_sel_interface_control(u8 enable)
- +{
- + hdmi_mask_writeb(enable, HDMI_PHY_CONF0,
- + HDMI_PHY_CONF0_SELDIPIF_OFFSET,
- + HDMI_PHY_CONF0_SELDIPIF_MASK);
- +}
- +
- +static int hdmi_phy_configure(struct mxc_hdmi *hdmi, unsigned char pRep,
- + unsigned char cRes, int cscOn)
- +{
- + u8 val;
- + u8 msec;
- +
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + /* color resolution 0 is 8 bit colour depth */
- + if (cRes == 0)
- + cRes = 8;
- +
- + if (pRep != 0)
- + return false;
- + else if (cRes != 8 && cRes != 12)
- + return false;
- +
- + /* Enable csc path */
- + if (cscOn)
- + val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH;
- + else
- + val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS;
- +
- + hdmi_writeb(val, HDMI_MC_FLOWCTRL);
- +
- + /* gen2 tx power off */
- + mxc_hdmi_phy_gen2_txpwron(0);
- +
- + /* gen2 pddq */
- + mxc_hdmi_phy_gen2_pddq(1);
- +
- + /* PHY reset */
- + hdmi_writeb(HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
- + hdmi_writeb(HDMI_MC_PHYRSTZ_ASSERT, HDMI_MC_PHYRSTZ);
- +
- + hdmi_writeb(HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST);
- +
- + hdmi_phy_test_clear(hdmi, 1);
- + hdmi_writeb(HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
- + HDMI_PHY_I2CM_SLAVE_ADDR);
- + hdmi_phy_test_clear(hdmi, 0);
- +
- + if (hdmi->hdmi_data.video_mode.mPixelClock < 0) {
- + dev_dbg(&hdmi->pdev->dev, "Pixel clock (%d) must be positive\n",
- + hdmi->hdmi_data.video_mode.mPixelClock);
- + return false;
- + }
- +
- + if (hdmi->hdmi_data.video_mode.mPixelClock <= 45250000) {
- + switch (cRes) {
- + case 8:
- + /* PLL/MPLL Cfg */
- + hdmi_phy_i2c_write(hdmi, 0x01e0, 0x06);
- + hdmi_phy_i2c_write(hdmi, 0x0000, 0x15); /* GMPCTRL */
- + break;
- + case 10:
- + hdmi_phy_i2c_write(hdmi, 0x21e1, 0x06);
- + hdmi_phy_i2c_write(hdmi, 0x0000, 0x15);
- + break;
- + case 12:
- + hdmi_phy_i2c_write(hdmi, 0x41e2, 0x06);
- + hdmi_phy_i2c_write(hdmi, 0x0000, 0x15);
- + break;
- + default:
- + return false;
- + }
- + } else if (hdmi->hdmi_data.video_mode.mPixelClock <= 92500000) {
- + switch (cRes) {
- + case 8:
- + hdmi_phy_i2c_write(hdmi, 0x0140, 0x06);
- + hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
- + break;
- + case 10:
- + hdmi_phy_i2c_write(hdmi, 0x2141, 0x06);
- + hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
- + break;
- + case 12:
- + hdmi_phy_i2c_write(hdmi, 0x4142, 0x06);
- + hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
- + default:
- + return false;
- + }
- + } else if (hdmi->hdmi_data.video_mode.mPixelClock <= 148500000) {
- + switch (cRes) {
- + case 8:
- + hdmi_phy_i2c_write(hdmi, 0x00a0, 0x06);
- + hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
- + break;
- + case 10:
- + hdmi_phy_i2c_write(hdmi, 0x20a1, 0x06);
- + hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
- + break;
- + case 12:
- + hdmi_phy_i2c_write(hdmi, 0x40a2, 0x06);
- + hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
- + default:
- + return false;
- + }
- + } else {
- + switch (cRes) {
- + case 8:
- + hdmi_phy_i2c_write(hdmi, 0x00a0, 0x06);
- + hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
- + break;
- + case 10:
- + hdmi_phy_i2c_write(hdmi, 0x2001, 0x06);
- + hdmi_phy_i2c_write(hdmi, 0x000f, 0x15);
- + break;
- + case 12:
- + hdmi_phy_i2c_write(hdmi, 0x4002, 0x06);
- + hdmi_phy_i2c_write(hdmi, 0x000f, 0x15);
- + default:
- + return false;
- + }
- + }
- +
- + if (hdmi->hdmi_data.video_mode.mPixelClock <= 54000000) {
- + switch (cRes) {
- + case 8:
- + hdmi_phy_i2c_write(hdmi, 0x091c, 0x10); /* CURRCTRL */
- + break;
- + case 10:
- + hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
- + break;
- + case 12:
- + hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
- + break;
- + default:
- + return false;
- + }
- + } else if (hdmi->hdmi_data.video_mode.mPixelClock <= 58400000) {
- + switch (cRes) {
- + case 8:
- + hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
- + break;
- + case 10:
- + hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
- + break;
- + case 12:
- + hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
- + break;
- + default:
- + return false;
- + }
- + } else if (hdmi->hdmi_data.video_mode.mPixelClock <= 72000000) {
- + switch (cRes) {
- + case 8:
- + hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
- + break;
- + case 10:
- + hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
- + break;
- + case 12:
- + hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
- + break;
- + default:
- + return false;
- + }
- + } else if (hdmi->hdmi_data.video_mode.mPixelClock <= 74250000) {
- + switch (cRes) {
- + case 8:
- + hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
- + break;
- + case 10:
- + hdmi_phy_i2c_write(hdmi, 0x0b5c, 0x10);
- + break;
- + case 12:
- + hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
- + break;
- + default:
- + return false;
- + }
- + } else if (hdmi->hdmi_data.video_mode.mPixelClock <= 118800000) {
- + switch (cRes) {
- + case 8:
- + hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
- + break;
- + case 10:
- + hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
- + break;
- + case 12:
- + hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
- + break;
- + default:
- + return false;
- + }
- + } else if (hdmi->hdmi_data.video_mode.mPixelClock <= 216000000) {
- + switch (cRes) {
- + case 8:
- + hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
- + break;
- + case 10:
- + hdmi_phy_i2c_write(hdmi, 0x0b5c, 0x10);
- + break;
- + case 12:
- + hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
- + break;
- + default:
- + return false;
- + }
- + } else {
- + dev_err(&hdmi->pdev->dev,
- + "Pixel clock %d - unsupported by HDMI\n",
- + hdmi->hdmi_data.video_mode.mPixelClock);
- + return false;
- + }
- +
- + hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */
- + hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
- + /* RESISTANCE TERM 133Ohm Cfg */
- + hdmi_phy_i2c_write(hdmi, 0x0005, 0x19); /* TXTERM */
- + /* PREEMP Cgf 0.00 */
- + hdmi_phy_i2c_write(hdmi, 0x800d, 0x09); /* CKSYMTXCTRL */
- + /* TX/CK LVL 10 */
- + hdmi_phy_i2c_write(hdmi, 0x01ad, 0x0E); /* VLEVCTRL */
- +
- + /* Board specific setting for PHY register 0x09, 0x0e to pass HCT */
- + if (hdmi->phy_config.reg_cksymtx != 0)
- + hdmi_phy_i2c_write(hdmi, hdmi->phy_config.reg_cksymtx, 0x09);
- +
- + if (hdmi->phy_config.reg_vlev != 0)
- + hdmi_phy_i2c_write(hdmi, hdmi->phy_config.reg_vlev, 0x0E);
- +
- + /* REMOVE CLK TERM */
- + hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */
- +
- + if (hdmi->hdmi_data.video_mode.mPixelClock > 148500000) {
- + hdmi_phy_i2c_write(hdmi, 0x800b, 0x09);
- + hdmi_phy_i2c_write(hdmi, 0x0129, 0x0E);
- + }
- +
- + mxc_hdmi_phy_enable_power(1);
- +
- + /* toggle TMDS enable */
- + mxc_hdmi_phy_enable_tmds(0);
- + mxc_hdmi_phy_enable_tmds(1);
- +
- + /* gen2 tx power on */
- + mxc_hdmi_phy_gen2_txpwron(1);
- + mxc_hdmi_phy_gen2_pddq(0);
- +
- + /*Wait for PHY PLL lock */
- + msec = 4;
- + val = hdmi_readb(HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
- + while (val == 0) {
- + udelay(1000);
- + if (msec-- == 0) {
- + dev_dbg(&hdmi->pdev->dev, "PHY PLL not locked\n");
- + return false;
- + }
- + val = hdmi_readb(HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
- + }
- +
- + return true;
- +}
- +
- +static void mxc_hdmi_phy_init(struct mxc_hdmi *hdmi)
- +{
- + int i;
- + bool cscon = false;
- +
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + /* Never do phy init if pixel clock is gated.
- + * Otherwise HDMI PHY will get messed up and generate an overflow
- + * interrupt that can't be cleared or detected by accessing the
- + * status register. */
- + if (!hdmi->fb_reg || !hdmi->cable_plugin
- + || (hdmi->blank != FB_BLANK_UNBLANK))
- + return;
- +
- + /*check csc whether needed activated in HDMI mode */
- + cscon = (isColorSpaceConversion(hdmi) &&
- + !hdmi->hdmi_data.video_mode.mDVI);
- +
- + /* HDMI Phy spec says to do the phy initialization sequence twice */
- + for (i = 0 ; i < 2 ; i++) {
- + mxc_hdmi_phy_sel_data_en_pol(1);
- + mxc_hdmi_phy_sel_interface_control(0);
- + mxc_hdmi_phy_enable_tmds(0);
- + mxc_hdmi_phy_enable_power(0);
- +
- + /* Enable CSC */
- + hdmi_phy_configure(hdmi, 0, 8, cscon);
- + }
- +
- + hdmi->phy_enabled = true;
- + if (!hdmi->hdmi_data.video_mode.mDVI)
- + hdmi_enable_overflow_interrupts();
- +}
- +
- +static void hdmi_config_AVI(struct mxc_hdmi *hdmi)
- +{
- + u8 val;
- + u8 pix_fmt;
- + u8 under_scan;
- + u8 act_ratio, coded_ratio, colorimetry, ext_colorimetry;
- + struct fb_videomode mode;
- + const struct fb_videomode *edid_mode;
- + bool aspect_16_9;
- +
- + dev_dbg(&hdmi->pdev->dev, "set up AVI frame\n");
- +
- + fb_var_to_videomode(&mode, &hdmi->fbi->var);
- + /* Use mode from list extracted from EDID to get aspect ratio */
- + if (!list_empty(&hdmi->fbi->modelist)) {
- + edid_mode = fb_find_nearest_mode(&mode, &hdmi->fbi->modelist);
- + if (edid_mode->vmode & FB_VMODE_ASPECT_16_9)
- + aspect_16_9 = true;
- + else
- + aspect_16_9 = false;
- + } else
- + aspect_16_9 = false;
- +
- + /********************************************
- + * AVI Data Byte 1
- + ********************************************/
- + if (hdmi->hdmi_data.enc_out_format == YCBCR444)
- + pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR444;
- + else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS)
- + pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR422;
- + else
- + pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_RGB;
- +
- + if (hdmi->edid_cfg.cea_underscan)
- + under_scan = HDMI_FC_AVICONF0_SCAN_INFO_UNDERSCAN;
- + else
- + under_scan = HDMI_FC_AVICONF0_SCAN_INFO_NODATA;
- +
- + /*
- + * Active format identification data is present in the AVI InfoFrame.
- + * Under scan info, no bar data
- + */
- + val = pix_fmt | under_scan |
- + HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT |
- + HDMI_FC_AVICONF0_BAR_DATA_NO_DATA;
- +
- + hdmi_writeb(val, HDMI_FC_AVICONF0);
- +
- + /********************************************
- + * AVI Data Byte 2
- + ********************************************/
- +
- + /* Set the Aspect Ratio */
- + if (aspect_16_9) {
- + act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9;
- + coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9;
- + } else {
- + act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3;
- + coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3;
- + }
- +
- + /* Set up colorimetry */
- + if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
- + colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO;
- + if (hdmi->hdmi_data.colorimetry == eITU601)
- + ext_colorimetry =
- + HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
- + else /* hdmi->hdmi_data.colorimetry == eITU709 */
- + ext_colorimetry =
- + HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709;
- + } else if (hdmi->hdmi_data.enc_out_format != RGB) {
- + if (hdmi->hdmi_data.colorimetry == eITU601)
- + colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_SMPTE;
- + else /* hdmi->hdmi_data.colorimetry == eITU709 */
- + colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_ITUR;
- + ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
- + } else { /* Carries no data */
- + colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA;
- + ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
- + }
- +
- + val = colorimetry | coded_ratio | act_ratio;
- + hdmi_writeb(val, HDMI_FC_AVICONF1);
- +
- + /********************************************
- + * AVI Data Byte 3
- + ********************************************/
- +
- + val = HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA | ext_colorimetry |
- + hdmi->hdmi_data.rgb_quant_range |
- + HDMI_FC_AVICONF2_SCALING_NONE;
- + hdmi_writeb(val, HDMI_FC_AVICONF2);
- +
- + /********************************************
- + * AVI Data Byte 4
- + ********************************************/
- + hdmi_writeb(hdmi->vic, HDMI_FC_AVIVID);
- +
- + /********************************************
- + * AVI Data Byte 5
- + ********************************************/
- +
- + /* Set up input and output pixel repetition */
- + val = (((hdmi->hdmi_data.video_mode.mPixelRepetitionInput + 1) <<
- + HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET) &
- + HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK) |
- + ((hdmi->hdmi_data.video_mode.mPixelRepetitionOutput <<
- + HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET) &
- + HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK);
- + hdmi_writeb(val, HDMI_FC_PRCONF);
- +
- + /* IT Content and quantization range = don't care */
- + val = HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS |
- + HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED;
- + hdmi_writeb(val, HDMI_FC_AVICONF3);
- +
- + /********************************************
- + * AVI Data Bytes 6-13
- + ********************************************/
- + hdmi_writeb(0, HDMI_FC_AVIETB0);
- + hdmi_writeb(0, HDMI_FC_AVIETB1);
- + hdmi_writeb(0, HDMI_FC_AVISBB0);
- + hdmi_writeb(0, HDMI_FC_AVISBB1);
- + hdmi_writeb(0, HDMI_FC_AVIELB0);
- + hdmi_writeb(0, HDMI_FC_AVIELB1);
- + hdmi_writeb(0, HDMI_FC_AVISRB0);
- + hdmi_writeb(0, HDMI_FC_AVISRB1);
- +}
- +
- +/*!
- + * this submodule is responsible for the video/audio data composition.
- + */
- +static void hdmi_av_composer(struct mxc_hdmi *hdmi)
- +{
- + u8 inv_val;
- + struct fb_info *fbi = hdmi->fbi;
- + struct fb_videomode fb_mode;
- + struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode;
- + int hblank, vblank;
- +
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + fb_var_to_videomode(&fb_mode, &fbi->var);
- +
- + vmode->mHSyncPolarity = ((fb_mode.sync & FB_SYNC_HOR_HIGH_ACT) != 0);
- + vmode->mVSyncPolarity = ((fb_mode.sync & FB_SYNC_VERT_HIGH_ACT) != 0);
- + vmode->mInterlaced = ((fb_mode.vmode & FB_VMODE_INTERLACED) != 0);
- + vmode->mPixelClock = (fb_mode.xres + fb_mode.left_margin +
- + fb_mode.right_margin + fb_mode.hsync_len) * (fb_mode.yres +
- + fb_mode.upper_margin + fb_mode.lower_margin +
- + fb_mode.vsync_len) * fb_mode.refresh;
- +
- + dev_dbg(&hdmi->pdev->dev, "final pixclk = %d\n", vmode->mPixelClock);
- +
- + /* Set up HDMI_FC_INVIDCONF */
- + inv_val = (vmode->mVSyncPolarity ?
- + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
- + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW);
- +
- + inv_val |= (vmode->mHSyncPolarity ?
- + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
- + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW);
- +
- + inv_val |= (vmode->mDataEnablePolarity ?
- + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
- + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
- +
- + if (hdmi->vic == 39)
- + inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH;
- + else
- + inv_val |= (vmode->mInterlaced ?
- + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH :
- + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW);
- +
- + inv_val |= (vmode->mInterlaced ?
- + HDMI_FC_INVIDCONF_IN_I_P_INTERLACED :
- + HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE);
- +
- + inv_val |= (vmode->mDVI ?
- + HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE :
- + HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE);
- +
- + hdmi_writeb(inv_val, HDMI_FC_INVIDCONF);
- +
- + /* Set up horizontal active pixel region width */
- + hdmi_writeb(fb_mode.xres >> 8, HDMI_FC_INHACTV1);
- + hdmi_writeb(fb_mode.xres, HDMI_FC_INHACTV0);
- +
- + /* Set up vertical blanking pixel region width */
- + hdmi_writeb(fb_mode.yres >> 8, HDMI_FC_INVACTV1);
- + hdmi_writeb(fb_mode.yres, HDMI_FC_INVACTV0);
- +
- + /* Set up horizontal blanking pixel region width */
- + hblank = fb_mode.left_margin + fb_mode.right_margin +
- + fb_mode.hsync_len;
- + hdmi_writeb(hblank >> 8, HDMI_FC_INHBLANK1);
- + hdmi_writeb(hblank, HDMI_FC_INHBLANK0);
- +
- + /* Set up vertical blanking pixel region width */
- + vblank = fb_mode.upper_margin + fb_mode.lower_margin +
- + fb_mode.vsync_len;
- + hdmi_writeb(vblank, HDMI_FC_INVBLANK);
- +
- + /* Set up HSYNC active edge delay width (in pixel clks) */
- + hdmi_writeb(fb_mode.right_margin >> 8, HDMI_FC_HSYNCINDELAY1);
- + hdmi_writeb(fb_mode.right_margin, HDMI_FC_HSYNCINDELAY0);
- +
- + /* Set up VSYNC active edge delay (in pixel clks) */
- + hdmi_writeb(fb_mode.lower_margin, HDMI_FC_VSYNCINDELAY);
- +
- + /* Set up HSYNC active pulse width (in pixel clks) */
- + hdmi_writeb(fb_mode.hsync_len >> 8, HDMI_FC_HSYNCINWIDTH1);
- + hdmi_writeb(fb_mode.hsync_len, HDMI_FC_HSYNCINWIDTH0);
- +
- + /* Set up VSYNC active edge delay (in pixel clks) */
- + hdmi_writeb(fb_mode.vsync_len, HDMI_FC_VSYNCINWIDTH);
- +
- + dev_dbg(&hdmi->pdev->dev, "%s exit\n", __func__);
- +}
- +
- +static int mxc_edid_read_internal(struct mxc_hdmi *hdmi, unsigned char *edid,
- + struct mxc_edid_cfg *cfg, struct fb_info *fbi)
- +{
- + int extblknum;
- + int i, j, ret;
- + unsigned char *ediddata = edid;
- + unsigned char tmpedid[EDID_LENGTH];
- +
- + dev_info(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + if (!edid || !cfg || !fbi)
- + return -EINVAL;
- +
- + /* init HDMI I2CM for read edid*/
- + hdmi_writeb(0x0, HDMI_I2CM_DIV);
- + hdmi_writeb(0x00, HDMI_I2CM_SS_SCL_HCNT_1_ADDR);
- + hdmi_writeb(0x79, HDMI_I2CM_SS_SCL_HCNT_0_ADDR);
- + hdmi_writeb(0x00, HDMI_I2CM_SS_SCL_LCNT_1_ADDR);
- + hdmi_writeb(0x91, HDMI_I2CM_SS_SCL_LCNT_0_ADDR);
- +
- + hdmi_writeb(0x00, HDMI_I2CM_FS_SCL_HCNT_1_ADDR);
- + hdmi_writeb(0x0F, HDMI_I2CM_FS_SCL_HCNT_0_ADDR);
- + hdmi_writeb(0x00, HDMI_I2CM_FS_SCL_LCNT_1_ADDR);
- + hdmi_writeb(0x21, HDMI_I2CM_FS_SCL_LCNT_0_ADDR);
- +
- + hdmi_writeb(0x50, HDMI_I2CM_SLAVE);
- + hdmi_writeb(0x30, HDMI_I2CM_SEGADDR);
- +
- + /* Umask edid interrupt */
- + hdmi_writeb(HDMI_I2CM_INT_DONE_POL,
- + HDMI_I2CM_INT);
- +
- + hdmi_writeb(HDMI_I2CM_CTLINT_NAC_POL |
- + HDMI_I2CM_CTLINT_ARBITRATION_POL,
- + HDMI_I2CM_CTLINT);
- +
- + /* reset edid data zero */
- + memset(edid, 0, EDID_LENGTH*4);
- + memset(cfg, 0, sizeof(struct mxc_edid_cfg));
- +
- + /* Check first three byte of EDID head */
- + if (!(hdmi_edid_i2c_read(hdmi, 0, 0) == 0x00) ||
- + !(hdmi_edid_i2c_read(hdmi, 1, 0) == 0xFF) ||
- + !(hdmi_edid_i2c_read(hdmi, 2, 0) == 0xFF)) {
- + dev_info(&hdmi->pdev->dev, "EDID head check failed!");
- + return -ENOENT;
- + }
- +
- + for (i = 0; i < 128; i++) {
- + *ediddata = hdmi_edid_i2c_read(hdmi, i, 0);
- + ediddata++;
- + }
- +
- + extblknum = edid[0x7E];
- + if (extblknum < 0)
- + return extblknum;
- +
- + if (extblknum) {
- + ediddata = edid + EDID_LENGTH;
- + for (i = 0; i < 128; i++) {
- + *ediddata = hdmi_edid_i2c_read(hdmi, i, 1);
- + ediddata++;
- + }
- + }
- +
- + /* edid first block parsing */
- + memset(&fbi->monspecs, 0, sizeof(fbi->monspecs));
- + fb_edid_to_monspecs(edid, &fbi->monspecs);
- +
- + ret = mxc_edid_parse_ext_blk(edid + EDID_LENGTH,
- + cfg, &fbi->monspecs);
- + if (ret < 0) {
- + fb_edid_add_monspecs(edid + EDID_LENGTH, &fbi->monspecs);
- + if (fbi->monspecs.modedb_len > 0)
- + hdmi->edid_cfg.hdmi_cap = false;
- + else
- + return -ENOENT;
- + }
- +
- + /* need read segment block? */
- + if (extblknum > 1) {
- + for (j = 1; j <= extblknum; j++) {
- + for (i = 0; i < 128; i++)
- + *(tmpedid + 1) = hdmi_edid_i2c_read(hdmi, i, j);
- +
- + /* edid ext block parsing */
- + ret = mxc_edid_parse_ext_blk(tmpedid + EDID_LENGTH,
- + cfg, &fbi->monspecs);
- + if (ret < 0)
- + return -ENOENT;
- + }
- + }
- +
- + return 0;
- +}
- +
- +static int mxc_hdmi_read_edid(struct mxc_hdmi *hdmi)
- +{
- + int ret;
- + u8 edid_old[HDMI_EDID_LEN];
- + u8 clkdis;
- +
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + /* save old edid */
- + memcpy(edid_old, hdmi->edid, HDMI_EDID_LEN);
- +
- + /* Read EDID via HDMI DDC when HDCP Enable */
- + if (!hdcp_init)
- + ret = mxc_edid_read(hdmi_i2c->adapter, hdmi_i2c->addr,
- + hdmi->edid, &hdmi->edid_cfg, hdmi->fbi);
- + else {
- +
- + /* Disable HDCP clk */
- + if (hdmi->hdmi_data.hdcp_enable) {
- + clkdis = hdmi_readb(HDMI_MC_CLKDIS);
- + clkdis |= HDMI_MC_CLKDIS_HDCPCLK_DISABLE;
- + hdmi_writeb(clkdis, HDMI_MC_CLKDIS);
- + }
- +
- + ret = mxc_edid_read_internal(hdmi, hdmi->edid,
- + &hdmi->edid_cfg, hdmi->fbi);
- +
- + /* Enable HDCP clk */
- + if (hdmi->hdmi_data.hdcp_enable) {
- + clkdis = hdmi_readb(HDMI_MC_CLKDIS);
- + clkdis &= ~HDMI_MC_CLKDIS_HDCPCLK_DISABLE;
- + hdmi_writeb(clkdis, HDMI_MC_CLKDIS);
- + }
- +
- + }
- +
- + if (ret < 0)
- + return HDMI_EDID_FAIL;
- +
- + dev_info(&hdmi->pdev->dev, "%s HDMI in %s mode\n", __func__, hdmi->edid_cfg.hdmi_cap?"HDMI":"DVI");
- + hdmi->plug_event = hdmi->edid_cfg.hdmi_cap?HDMI_IH_PHY_STAT0_HPD:HDMI_DVI_IH_STAT;
- + hdmi->plug_mask = hdmi->edid_cfg.hdmi_cap?HDMI_PHY_HPD:HDMI_DVI_STAT;
- +
- + if (!memcmp(edid_old, hdmi->edid, HDMI_EDID_LEN)) {
- + dev_info(&hdmi->pdev->dev, "same edid\n");
- + return HDMI_EDID_SAME;
- + }
- +
- + if (hdmi->fbi->monspecs.modedb_len == 0) {
- + dev_info(&hdmi->pdev->dev, "No modes read from edid\n");
- + return HDMI_EDID_NO_MODES;
- + }
- +
- + return HDMI_EDID_SUCCESS;
- +}
- +
- +static void mxc_hdmi_phy_disable(struct mxc_hdmi *hdmi)
- +{
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + if (!hdmi->phy_enabled)
- + return;
- +
- + hdmi_disable_overflow_interrupts();
- +
- + /* Setting PHY to reset status */
- + hdmi_writeb(HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
- +
- + /* Power down PHY */
- + mxc_hdmi_phy_enable_tmds(0);
- + mxc_hdmi_phy_enable_power(0);
- + mxc_hdmi_phy_gen2_txpwron(0);
- + mxc_hdmi_phy_gen2_pddq(1);
- +
- + hdmi->phy_enabled = false;
- + dev_dbg(&hdmi->pdev->dev, "%s - exit\n", __func__);
- +}
- +
- +/* HDMI Initialization Step B.4 */
- +static void mxc_hdmi_enable_video_path(struct mxc_hdmi *hdmi)
- +{
- + u8 clkdis;
- +
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + /* control period minimum duration */
- + hdmi_writeb(12, HDMI_FC_CTRLDUR);
- + hdmi_writeb(32, HDMI_FC_EXCTRLDUR);
- + hdmi_writeb(1, HDMI_FC_EXCTRLSPAC);
- +
- + /* Set to fill TMDS data channels */
- + hdmi_writeb(0x0B, HDMI_FC_CH0PREAM);
- + hdmi_writeb(0x16, HDMI_FC_CH1PREAM);
- + hdmi_writeb(0x21, HDMI_FC_CH2PREAM);
- +
- + /* Save CEC clock */
- + clkdis = hdmi_readb(HDMI_MC_CLKDIS) & HDMI_MC_CLKDIS_CECCLK_DISABLE;
- + clkdis |= ~HDMI_MC_CLKDIS_CECCLK_DISABLE;
- +
- + /* Enable pixel clock and tmds data path */
- + clkdis = 0x7F & clkdis;
- + clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
- + hdmi_writeb(clkdis, HDMI_MC_CLKDIS);
- +
- + clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
- + hdmi_writeb(clkdis, HDMI_MC_CLKDIS);
- +
- + /* Enable csc path */
- + if (isColorSpaceConversion(hdmi) && !hdmi->hdmi_data.video_mode.mDVI) {
- + clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
- + hdmi_writeb(clkdis, HDMI_MC_CLKDIS);
- + }
- +}
- +
- +static void hdmi_enable_audio_clk(struct mxc_hdmi *hdmi)
- +{
- + u8 clkdis;
- +
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + clkdis = hdmi_readb(HDMI_MC_CLKDIS);
- + clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
- + hdmi_writeb(clkdis, HDMI_MC_CLKDIS);
- +}
- +
- +/* Workaround to clear the overflow condition */
- +static void mxc_hdmi_clear_overflow(struct mxc_hdmi *hdmi)
- +{
- + int count;
- + u8 val;
- +
- + /* TMDS software reset */
- + hdmi_writeb((u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
- +
- + val = hdmi_readb(HDMI_FC_INVIDCONF);
- +
- + if (cpu_is_imx6dl(hdmi)) {
- + hdmi_writeb(val, HDMI_FC_INVIDCONF);
- + return;
- + }
- +
- + for (count = 0 ; count < 5 ; count++)
- + hdmi_writeb(val, HDMI_FC_INVIDCONF);
- +}
- +
- +static void hdmi_enable_overflow_interrupts(void)
- +{
- + pr_debug("%s\n", __func__);
- + hdmi_writeb(0, HDMI_FC_MASK2);
- + hdmi_writeb(0, HDMI_IH_MUTE_FC_STAT2);
- +}
- +
- +static void hdmi_disable_overflow_interrupts(void)
- +{
- + pr_debug("%s\n", __func__);
- + hdmi_writeb(HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK,
- + HDMI_IH_MUTE_FC_STAT2);
- + hdmi_writeb(0xff, HDMI_FC_MASK2);
- +}
- +
- +static void mxc_hdmi_notify_fb(struct mxc_hdmi *hdmi)
- +{
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + /* Don't notify if we aren't registered yet */
- + WARN_ON(!hdmi->fb_reg);
- +
- + /* disable the phy before ipu changes mode */
- + mxc_hdmi_phy_disable(hdmi);
- +
- + /*
- + * Note that fb_set_var will block. During this time,
- + * FB_EVENT_MODE_CHANGE callback will happen.
- + * So by the end of this function, mxc_hdmi_setup()
- + * will be done.
- + */
- + hdmi->fbi->var.activate |= FB_ACTIVATE_FORCE;
- + console_lock();
- + hdmi->fbi->flags |= FBINFO_MISC_USEREVENT;
- + fb_set_var(hdmi->fbi, &hdmi->fbi->var);
- + hdmi->fbi->flags &= ~FBINFO_MISC_USEREVENT;
- + console_unlock();
- +
- + dev_dbg(&hdmi->pdev->dev, "%s exit\n", __func__);
- +}
- +
- +static void mxc_hdmi_edid_rebuild_modelist(struct mxc_hdmi *hdmi)
- +{
- + int i;
- + struct fb_videomode *mode;
- +
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + console_lock();
- +
- + fb_destroy_modelist(&hdmi->fbi->modelist);
- + fb_add_videomode(&vga_mode, &hdmi->fbi->modelist);
- +
- + for (i = 0; i < hdmi->fbi->monspecs.modedb_len; i++) {
- + /*
- + * We might check here if mode is supported by HDMI.
- + * We do not currently support interlaced modes.
- + * And add CEA modes in the modelist.
- + */
- + mode = &hdmi->fbi->monspecs.modedb[i];
- +
- + if ((mode->vmode & FB_VMODE_INTERLACED) ||
- + (hdmi->edid_cfg.hdmi_cap &&
- + (mxc_edid_mode_to_vic(mode) == 0)))
- + continue;
- +
- + dev_dbg(&hdmi->pdev->dev, "Added mode %d:", i);
- + dev_dbg(&hdmi->pdev->dev,
- + "xres = %d, yres = %d, freq = %d, vmode = %d, flag = %d\n",
- + hdmi->fbi->monspecs.modedb[i].xres,
- + hdmi->fbi->monspecs.modedb[i].yres,
- + hdmi->fbi->monspecs.modedb[i].refresh,
- + hdmi->fbi->monspecs.modedb[i].vmode,
- + hdmi->fbi->monspecs.modedb[i].flag);
- +
- + fb_add_videomode(mode, &hdmi->fbi->modelist);
- + }
- +
- + console_unlock();
- +}
- +
- +static void mxc_hdmi_default_edid_cfg(struct mxc_hdmi *hdmi)
- +{
- + /* Default setting HDMI working in HDMI mode */
- + hdmi->edid_cfg.hdmi_cap = true;
- +}
- +
- +static void mxc_hdmi_default_modelist(struct mxc_hdmi *hdmi)
- +{
- + u32 i;
- + const struct fb_videomode *mode;
- +
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + /* If not EDID data read, set up default modelist */
- + dev_info(&hdmi->pdev->dev, "No modes read from edid\n");
- + dev_info(&hdmi->pdev->dev, "create default modelist\n");
- +
- + console_lock();
- +
- + fb_destroy_modelist(&hdmi->fbi->modelist);
- +
- + /*Add all no interlaced CEA mode to default modelist */
- + for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) {
- + mode = &mxc_cea_mode[i];
- + if (!(mode->vmode & FB_VMODE_INTERLACED) && (mode->xres != 0))
- + fb_add_videomode(mode, &hdmi->fbi->modelist);
- + }
- +
- + console_unlock();
- +}
- +
- +static void mxc_hdmi_set_mode_to_vga_dvi(struct mxc_hdmi *hdmi)
- +{
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + hdmi_disable_overflow_interrupts();
- +
- + fb_videomode_to_var(&hdmi->fbi->var, &vga_mode);
- +
- + hdmi->requesting_vga_for_initialization = true;
- + mxc_hdmi_notify_fb(hdmi);
- + hdmi->requesting_vga_for_initialization = false;
- +}
- +
- +static void mxc_hdmi_set_mode(struct mxc_hdmi *hdmi)
- +{
- + const struct fb_videomode *mode;
- + struct fb_videomode m;
- + struct fb_var_screeninfo var;
- +
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + /* Set the default mode only once. */
- + if (!hdmi->dft_mode_set) {
- + fb_videomode_to_var(&var, &hdmi->default_mode);
- + hdmi->dft_mode_set = true;
- + } else
- + fb_videomode_to_var(&var, &hdmi->previous_non_vga_mode);
- +
- + fb_var_to_videomode(&m, &var);
- + dump_fb_videomode(&m);
- +
- + mode = fb_find_nearest_mode(&m, &hdmi->fbi->modelist);
- + if (!mode) {
- + pr_err("%s: could not find mode in modelist\n", __func__);
- + return;
- + }
- +
- + /* If video mode same as previous, init HDMI again */
- + if (fb_mode_is_equal(&hdmi->previous_non_vga_mode, mode)) {
- + dev_dbg(&hdmi->pdev->dev,
- + "%s: Video mode same as previous\n", __func__);
- + /* update fbi mode in case modelist is updated */
- + hdmi->fbi->mode = (struct fb_videomode *)mode;
- + /* update hdmi setting in case EDID data updated */
- + mxc_hdmi_setup(hdmi, 0);
- + } else {
- + dev_dbg(&hdmi->pdev->dev, "%s: New video mode\n", __func__);
- + mxc_hdmi_set_mode_to_vga_dvi(hdmi);
- + fb_videomode_to_var(&hdmi->fbi->var, mode);
- + dump_fb_videomode((struct fb_videomode *)mode);
- + mxc_hdmi_notify_fb(hdmi);
- + }
- +
- +}
- +
- +static void mxc_hdmi_cable_connected(struct mxc_hdmi *hdmi)
- +{
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + hdmi->cable_plugin = true;
- +
- + /* HDMI Initialization Step C */
- + hdmi->edid_status = mxc_hdmi_read_edid(hdmi);
- +
- + /* Read EDID again if first EDID read failed */
- + if (hdmi->edid_status == HDMI_EDID_NO_MODES ||
- + hdmi->edid_status == HDMI_EDID_FAIL) {
- + dev_info(&hdmi->pdev->dev, "Read EDID again\n");
- + hdmi->edid_status = mxc_hdmi_read_edid(hdmi);
- + }
- +
- + /* HDMI Initialization Steps D, E, F */
- + switch (hdmi->edid_status) {
- + case HDMI_EDID_SUCCESS:
- + mxc_hdmi_edid_rebuild_modelist(hdmi);
- + break;
- +
- + /* Nothing to do if EDID same */
- + case HDMI_EDID_SAME:
- + break;
- +
- + case HDMI_EDID_FAIL:
- + mxc_hdmi_default_edid_cfg(hdmi);
- + /* No break here */
- + case HDMI_EDID_NO_MODES:
- + default:
- + mxc_hdmi_default_modelist(hdmi);
- + break;
- + }
- +
- + /* Save edid cfg for audio driver */
- + hdmi_set_edid_cfg(hdmi->edid_status, &hdmi->edid_cfg);
- +
- + /* Setting video mode */
- + mxc_hdmi_set_mode(hdmi);
- +
- + dev_dbg(&hdmi->pdev->dev, "%s exit\n", __func__);
- +}
- +
- +static int mxc_hdmi_power_on(struct mxc_dispdrv_handle *disp)
- +{
- + struct mxc_hdmi *hdmi = mxc_dispdrv_getdata(disp);
- + mxc_hdmi_phy_init(hdmi);
- + return 0;
- +}
- +
- +static void mxc_hdmi_power_off(struct mxc_dispdrv_handle *disp)
- +{
- + struct mxc_hdmi *hdmi = mxc_dispdrv_getdata(disp);
- + mxc_hdmi_phy_disable(hdmi);
- +}
- +
- +static void mxc_hdmi_cable_disconnected(struct mxc_hdmi *hdmi)
- +{
- + u8 clkdis;
- +
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + /* Save CEC clock */
- + clkdis = hdmi_readb(HDMI_MC_CLKDIS) & HDMI_MC_CLKDIS_CECCLK_DISABLE;
- + clkdis |= ~HDMI_MC_CLKDIS_CECCLK_DISABLE;
- +
- + /* Disable All HDMI clock */
- + hdmi_writeb(0xff & clkdis, HDMI_MC_CLKDIS);
- +
- + mxc_hdmi_phy_disable(hdmi);
- +
- + hdmi_disable_overflow_interrupts();
- +
- + hdmi->cable_plugin = false;
- +}
- +
- +static void hotplug_worker(struct work_struct *work)
- +{
- + struct mxc_hdmi *hdmi =
- + container_of(work, struct mxc_hdmi, hotplug_work);
- + u32 hdmi_phy_stat0, hdmi_phy_pol0, hdmi_phy_mask0;
- + unsigned long flags;
- + char event_string[32];
- + char *envp[] = { event_string, NULL };
- +
- + hdmi_phy_stat0 = hdmi_readb(HDMI_PHY_STAT0);
- + hdmi_phy_pol0 = hdmi_readb(HDMI_PHY_POL0);
- +
- + if (hdmi->latest_intr_stat & hdmi->plug_event) {
- + /* Make HPD intr active low to capture unplug event or
- + * active high to capture plugin event */
- + hdmi_writeb((hdmi->plug_mask & ~hdmi_phy_pol0), HDMI_PHY_POL0);
- +
- + /* check cable status */
- + if (hdmi_phy_stat0 & hdmi->plug_mask) {
- + /* Plugin event */
- + dev_dbg(&hdmi->pdev->dev, "EVENT=plugin\n");
- + mxc_hdmi_cable_connected(hdmi);
- +
- + sprintf(event_string, "EVENT=plugin");
- + kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
- +#ifdef CONFIG_MXC_HDMI_CEC
- + mxc_hdmi_cec_handle(0x80);
- +#endif
- + hdmi_set_cable_state(1);
- + } else {
- + /* Plugout event */
- + dev_dbg(&hdmi->pdev->dev, "EVENT=plugout\n");
- + hdmi_set_cable_state(0);
- + mxc_hdmi_abort_stream();
- + mxc_hdmi_cable_disconnected(hdmi);
- +
- + sprintf(event_string, "EVENT=plugout");
- + kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
- +#ifdef CONFIG_MXC_HDMI_CEC
- + mxc_hdmi_cec_handle(0x100);
- +#endif
- + }
- + }
- +
- + /* Lock here to ensure full powerdown sequence
- + * completed before next interrupt processed */
- + spin_lock_irqsave(&hdmi->irq_lock, flags);
- +
- + /* Re-enable HPD interrupts */
- + hdmi_phy_mask0 = hdmi_readb(HDMI_PHY_MASK0);
- + hdmi_phy_mask0 &= ~hdmi->plug_mask;
- + hdmi_writeb(hdmi_phy_mask0, HDMI_PHY_MASK0);
- +
- + /* Unmute interrupts */
- + hdmi_writeb(~hdmi->plug_event, HDMI_IH_MUTE_PHY_STAT0);
- +
- + if (hdmi_readb(HDMI_IH_FC_STAT2) & HDMI_IH_FC_STAT2_OVERFLOW_MASK)
- + mxc_hdmi_clear_overflow(hdmi);
- +
- + spin_unlock_irqrestore(&hdmi->irq_lock, flags);
- +}
- +
- +static void hotplug_work_launch(unsigned long data)
- +{
- + struct mxc_hdmi *hdmi = (struct mxc_hdmi *)data;
- + pr_debug("%s\n", __func__);
- + schedule_work(&hdmi->hotplug_work);
- +}
- +
- +static void hdcp_hdp_worker(struct work_struct *work)
- +{
- + struct delayed_work *delay_work = to_delayed_work(work);
- + struct mxc_hdmi *hdmi =
- + container_of(delay_work, struct mxc_hdmi, hdcp_hdp_work);
- + char event_string[32];
- + char *envp[] = { event_string, NULL };
- +
- + /* HDCP interrupt */
- + sprintf(event_string, "EVENT=hdcpint");
- + kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
- +
- + /* Unmute interrupts in HDCP application*/
- +}
- +
- +static irqreturn_t mxc_hdmi_hotplug(int irq, void *data)
- +{
- + struct mxc_hdmi *hdmi = data;
- + u8 val, intr_stat;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&hdmi->irq_lock, flags);
- +
- + /* Check and clean packet overflow interrupt.*/
- + if (hdmi_readb(HDMI_IH_FC_STAT2) &
- + HDMI_IH_FC_STAT2_OVERFLOW_MASK) {
- + mxc_hdmi_clear_overflow(hdmi);
- +
- + dev_dbg(&hdmi->pdev->dev, "Overflow interrupt received\n");
- + /* clear irq status */
- + hdmi_writeb(HDMI_IH_FC_STAT2_OVERFLOW_MASK,
- + HDMI_IH_FC_STAT2);
- + }
- +
- + /*
- + * We could not disable the irq. Probably the audio driver
- + * has enabled it. Masking off the HDMI interrupts using
- + * HDMI registers.
- + */
- + /* Capture status - used in hotplug_worker ISR */
- + intr_stat = hdmi_readb(HDMI_IH_PHY_STAT0);
- + if (intr_stat & hdmi->plug_event) {
- +
- + dev_dbg(&hdmi->pdev->dev, "Hotplug interrupt received\n");
- + dev_dbg(&hdmi->pdev->dev, "intr_stat %u plug_event %u\n", intr_stat, hdmi->plug_event);
- + hdmi->latest_intr_stat = intr_stat;
- +
- + /* Mute interrupts until handled */
- +
- + val = hdmi_readb(HDMI_IH_MUTE_PHY_STAT0);
- + val |= hdmi->plug_event;
- + hdmi_writeb(val, HDMI_IH_MUTE_PHY_STAT0);
- +
- + val = hdmi_readb(HDMI_PHY_MASK0);
- + val |= hdmi->plug_mask;
- + hdmi_writeb(val, HDMI_PHY_MASK0);
- +
- + /* Clear Hotplug interrupts */
- + hdmi_writeb(hdmi->plug_event, HDMI_IH_PHY_STAT0);
- +
- + if(hdmi_inited) {
- + mod_timer(&hdmi->jitter_timer, jiffies + HZ);
- + }
- + }
- +
- + /* Check HDCP interrupt state */
- + if (hdmi->hdmi_data.hdcp_enable) {
- + val = hdmi_readb(HDMI_A_APIINTSTAT);
- + if (val != 0) {
- + /* Mute interrupts until interrupt handled */
- + val = 0xFF;
- + hdmi_writeb(val, HDMI_A_APIINTMSK);
- + schedule_delayed_work(&(hdmi->hdcp_hdp_work), msecs_to_jiffies(50));
- + }
- + }
- +
- + spin_unlock_irqrestore(&hdmi->irq_lock, flags);
- + return IRQ_HANDLED;
- +}
- +
- +static void mxc_hdmi_setup(struct mxc_hdmi *hdmi, unsigned long event)
- +{
- + struct fb_videomode m;
- + const struct fb_videomode *edid_mode;
- +
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + fb_var_to_videomode(&m, &hdmi->fbi->var);
- + dump_fb_videomode(&m);
- +
- + dev_dbg(&hdmi->pdev->dev, "%s - video mode changed\n", __func__);
- +
- + hdmi->vic = 0;
- + if (!hdmi->requesting_vga_for_initialization) {
- + /* Save mode if this isn't the result of requesting
- + * vga default. */
- + memcpy(&hdmi->previous_non_vga_mode, &m,
- + sizeof(struct fb_videomode));
- + if (!list_empty(&hdmi->fbi->modelist)) {
- + edid_mode = fb_find_nearest_mode(&m, &hdmi->fbi->modelist);
- + pr_debug("edid mode ");
- + dump_fb_videomode((struct fb_videomode *)edid_mode);
- + /* update fbi mode */
- + hdmi->fbi->mode = (struct fb_videomode *)edid_mode;
- + hdmi->vic = mxc_edid_mode_to_vic(edid_mode);
- + }
- + }
- +
- + hdmi_disable_overflow_interrupts();
- +
- + dev_dbg(&hdmi->pdev->dev, "CEA mode used vic=%d\n", hdmi->vic);
- + if (hdmi->edid_cfg.hdmi_cap || !hdmi->edid_status) {
- + hdmi_set_dvi_mode(0);
- + hdmi->hdmi_data.video_mode.mDVI = false;
- + } else {
- + hdmi_set_dvi_mode(1);
- + dev_dbg(&hdmi->pdev->dev, "CEA mode vic=%d work in DVI\n", hdmi->vic);
- + hdmi->hdmi_data.video_mode.mDVI = true;
- + }
- +
- + if ((hdmi->vic == 6) || (hdmi->vic == 7) ||
- + (hdmi->vic == 21) || (hdmi->vic == 22) ||
- + (hdmi->vic == 2) || (hdmi->vic == 3) ||
- + (hdmi->vic == 17) || (hdmi->vic == 18))
- + hdmi->hdmi_data.colorimetry = eITU601;
- + else
- + hdmi->hdmi_data.colorimetry = eITU709;
- +
- + if ((hdmi->vic == 10) || (hdmi->vic == 11) ||
- + (hdmi->vic == 12) || (hdmi->vic == 13) ||
- + (hdmi->vic == 14) || (hdmi->vic == 15) ||
- + (hdmi->vic == 25) || (hdmi->vic == 26) ||
- + (hdmi->vic == 27) || (hdmi->vic == 28) ||
- + (hdmi->vic == 29) || (hdmi->vic == 30) ||
- + (hdmi->vic == 35) || (hdmi->vic == 36) ||
- + (hdmi->vic == 37) || (hdmi->vic == 38))
- + hdmi->hdmi_data.video_mode.mPixelRepetitionOutput = 1;
- + else
- + hdmi->hdmi_data.video_mode.mPixelRepetitionOutput = 0;
- +
- + hdmi->hdmi_data.video_mode.mPixelRepetitionInput = 0;
- +
- + /* TODO: Get input format from IPU (via FB driver iface) */
- + hdmi->hdmi_data.enc_in_format = RGB;
- +
- + hdmi->hdmi_data.enc_out_format = RGB;
- +
- + /* YCbCr only enabled in HDMI mode */
- + if (!hdmi->hdmi_data.video_mode.mDVI &&
- + !hdmi->hdmi_data.rgb_out_enable) {
- + if (hdmi->edid_cfg.cea_ycbcr444)
- + hdmi->hdmi_data.enc_out_format = YCBCR444;
- + else if (hdmi->edid_cfg.cea_ycbcr422)
- + hdmi->hdmi_data.enc_out_format = YCBCR422_8BITS;
- + }
- +
- + /* IPU not support depth color output */
- + hdmi->hdmi_data.enc_color_depth = 8;
- + hdmi->hdmi_data.pix_repet_factor = 0;
- + hdmi->hdmi_data.video_mode.mDataEnablePolarity = true;
- +
- + /* HDMI Initialization Step B.1 */
- + hdmi_av_composer(hdmi);
- +
- + /* HDMI Initializateion Step B.2 */
- + mxc_hdmi_phy_init(hdmi);
- +
- + /* HDMI Initialization Step B.3 */
- + mxc_hdmi_enable_video_path(hdmi);
- +
- + /* not for DVI mode */
- + if (hdmi->hdmi_data.video_mode.mDVI)
- + dev_dbg(&hdmi->pdev->dev, "%s DVI mode\n", __func__);
- + else {
- + dev_dbg(&hdmi->pdev->dev, "%s CEA mode\n", __func__);
- +
- + /* HDMI Initialization Step E - Configure audio */
- + hdmi_clk_regenerator_update_pixel_clock(hdmi->fbi->var.pixclock);
- + hdmi_enable_audio_clk(hdmi);
- +
- + /* HDMI Initialization Step F - Configure AVI InfoFrame */
- + hdmi_config_AVI(hdmi);
- + }
- +
- + hdmi_video_packetize(hdmi);
- + hdmi_video_csc(hdmi);
- + hdmi_video_sample(hdmi);
- +
- + mxc_hdmi_clear_overflow(hdmi);
- +
- + dev_dbg(&hdmi->pdev->dev, "%s exit\n\n", __func__);
- +
- +}
- +
- +/* Wait until we are registered to enable interrupts */
- +static void mxc_hdmi_fb_registered(struct mxc_hdmi *hdmi)
- +{
- + unsigned long flags;
- +
- + if (hdmi->fb_reg)
- + return;
- +
- + spin_lock_irqsave(&hdmi->irq_lock, flags);
- +
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + hdmi_writeb(HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
- + HDMI_PHY_I2CM_INT_ADDR);
- +
- + hdmi_writeb(HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
- + HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
- + HDMI_PHY_I2CM_CTLINT_ADDR);
- +
- + /* enable cable hot plug irq */
- + hdmi_writeb(~hdmi->plug_mask, HDMI_PHY_MASK0);
- +
- + /* Clear Hotplug interrupts */
- + hdmi_writeb(hdmi->plug_event, HDMI_IH_PHY_STAT0);
- +
- + /* Unmute interrupts */
- + hdmi_writeb(~hdmi->plug_event, HDMI_IH_MUTE_PHY_STAT0);
- +
- + hdmi->fb_reg = true;
- +
- + spin_unlock_irqrestore(&hdmi->irq_lock, flags);
- +
- +}
- +
- +static int mxc_hdmi_fb_event(struct notifier_block *nb,
- + unsigned long val, void *v)
- +{
- + struct fb_event *event = v;
- + struct mxc_hdmi *hdmi = container_of(nb, struct mxc_hdmi, nb);
- +
- + if (strcmp(event->info->fix.id, hdmi->fbi->fix.id))
- + return 0;
- +
- + switch (val) {
- + case FB_EVENT_FB_REGISTERED:
- + dev_dbg(&hdmi->pdev->dev, "event=FB_EVENT_FB_REGISTERED\n");
- + mxc_hdmi_fb_registered(hdmi);
- + hdmi_set_registered(1);
- + break;
- +
- + case FB_EVENT_FB_UNREGISTERED:
- + dev_dbg(&hdmi->pdev->dev, "event=FB_EVENT_FB_UNREGISTERED\n");
- + hdmi->fb_reg = false;
- + hdmi_set_registered(0);
- + break;
- +
- + case FB_EVENT_MODE_CHANGE:
- + dev_dbg(&hdmi->pdev->dev, "event=FB_EVENT_MODE_CHANGE\n");
- + if (hdmi->fb_reg)
- + mxc_hdmi_setup(hdmi, val);
- + break;
- +
- + case FB_EVENT_BLANK:
- + if ((*((int *)event->data) == FB_BLANK_UNBLANK) &&
- + (*((int *)event->data) != hdmi->blank)) {
- + dev_dbg(&hdmi->pdev->dev,
- + "event=FB_EVENT_BLANK - UNBLANK\n");
- +
- + hdmi->blank = *((int *)event->data);
- +
- + /* Re-enable HPD interrupts */
- + val = hdmi_readb(HDMI_PHY_MASK0);
- + val &= ~hdmi->plug_mask;
- + hdmi_writeb(val, HDMI_PHY_MASK0);
- +
- + /* Unmute interrupts */
- + hdmi_writeb(~hdmi->plug_event, HDMI_IH_MUTE_PHY_STAT0);
- +
- + if (hdmi->fb_reg && hdmi->cable_plugin)
- + mxc_hdmi_setup(hdmi, val);
- + hdmi_set_blank_state(1);
- + } else if (*((int *)event->data) != hdmi->blank) {
- + dev_dbg(&hdmi->pdev->dev,
- + "event=FB_EVENT_BLANK - BLANK\n");
- + hdmi_set_blank_state(0);
- + mxc_hdmi_abort_stream();
- +
- + mxc_hdmi_phy_disable(hdmi);
- +
- + if(hdmi->plug_mask == HDMI_DVI_STAT) {
- + u8 val;
- + pr_info("In DVI Mode disable interrupts\n");
- + val = hdmi_readb(HDMI_IH_MUTE_PHY_STAT0);
- + val |= hdmi->plug_event;
- + hdmi_writeb(val, HDMI_IH_MUTE_PHY_STAT0);
- +
- + val = hdmi_readb(HDMI_PHY_MASK0);
- + val |= hdmi->plug_mask;
- + hdmi_writeb(val, HDMI_PHY_MASK0);
- +
- + hdmi_set_dvi_mode(1);
- + }
- +
- + hdmi->blank = *((int *)event->data);
- + } else
- + dev_dbg(&hdmi->pdev->dev,
- + "FB BLANK state no changed!\n");
- +
- + break;
- +
- + case FB_EVENT_SUSPEND:
- + dev_dbg(&hdmi->pdev->dev,
- + "event=FB_EVENT_SUSPEND\n");
- +
- + if (hdmi->blank == FB_BLANK_UNBLANK) {
- + mxc_hdmi_phy_disable(hdmi);
- + clk_disable(hdmi->hdmi_iahb_clk);
- + clk_disable(hdmi->hdmi_isfr_clk);
- + }
- + break;
- +
- + case FB_EVENT_RESUME:
- + dev_dbg(&hdmi->pdev->dev,
- + "event=FB_EVENT_RESUME\n");
- +
- + if (hdmi->blank == FB_BLANK_UNBLANK) {
- + clk_enable(hdmi->hdmi_iahb_clk);
- + clk_enable(hdmi->hdmi_isfr_clk);
- + mxc_hdmi_phy_init(hdmi);
- + }
- + break;
- +
- + }
- + return 0;
- +}
- +
- +static void hdmi_init_route(struct mxc_hdmi *hdmi)
- +{
- + uint32_t hdmi_mux_setting, reg;
- + int ipu_id, disp_id;
- +
- + ipu_id = mxc_hdmi_ipu_id;
- + disp_id = mxc_hdmi_disp_id;
- +
- + if ((ipu_id > 1) || (ipu_id < 0)) {
- + pr_err("Invalid IPU select for HDMI: %d. Set to 0\n", ipu_id);
- + ipu_id = 0;
- + }
- +
- + if ((disp_id > 1) || (disp_id < 0)) {
- + pr_err("Invalid DI select for HDMI: %d. Set to 0\n", disp_id);
- + disp_id = 0;
- + }
- +
- + reg = readl(hdmi->gpr_hdmi_base);
- +
- + /* Configure the connection between IPU1/2 and HDMI */
- + hdmi_mux_setting = 2*ipu_id + disp_id;
- +
- + /* GPR3, bits 2-3 = HDMI_MUX_CTL */
- + reg &= ~0xd;
- + reg |= hdmi_mux_setting << 2;
- +
- + writel(reg, hdmi->gpr_hdmi_base);
- +
- + /* Set HDMI event as SDMA event2 for HDMI audio */
- + reg = readl(hdmi->gpr_sdma_base);
- + reg |= 0x1;
- + writel(reg, hdmi->gpr_sdma_base);
- +}
- +
- +static void hdmi_hdcp_get_property(struct platform_device *pdev)
- +{
- + struct device_node *np = pdev->dev.of_node;
- +
- + /* Check hdcp enable by dts.*/
- + hdcp_init = of_property_read_bool(np, "fsl,hdcp");
- + if (hdcp_init)
- + dev_dbg(&pdev->dev, "hdcp enable\n");
- + else
- + dev_dbg(&pdev->dev, "hdcp disable\n");
- +}
- +
- +static void hdmi_get_of_property(struct mxc_hdmi *hdmi)
- +{
- + struct platform_device *pdev = hdmi->pdev;
- + struct device_node *np = pdev->dev.of_node;
- + const struct of_device_id *of_id =
- + of_match_device(imx_hdmi_dt_ids, &pdev->dev);
- + int ret;
- + u32 phy_reg_vlev = 0, phy_reg_cksymtx = 0;
- +
- + if (of_id) {
- + pdev->id_entry = of_id->data;
- + hdmi->cpu_type = pdev->id_entry->driver_data;
- + }
- +
- + /* HDMI PHY register vlev and cksymtx preperty is optional.
- + * It is for specific board to pass HCT electrical part.
- + * Default value will been setting in HDMI PHY config function
- + * if it is not define in device tree.
- + */
- + ret = of_property_read_u32(np, "fsl,phy_reg_vlev", &phy_reg_vlev);
- + if (ret)
- + dev_dbg(&pdev->dev, "No board specific HDMI PHY vlev\n");
- +
- + ret = of_property_read_u32(np, "fsl,phy_reg_cksymtx", &phy_reg_cksymtx);
- + if (ret)
- + dev_dbg(&pdev->dev, "No board specific HDMI PHY cksymtx\n");
- +
- + /* Specific phy config */
- + hdmi->phy_config.reg_cksymtx = phy_reg_cksymtx;
- + hdmi->phy_config.reg_vlev = phy_reg_vlev;
- +
- +}
- +
- +/* HDMI Initialization Step A */
- +static int mxc_hdmi_disp_init(struct mxc_dispdrv_handle *disp,
- + struct mxc_dispdrv_setting *setting)
- +{
- + int ret = 0;
- + u32 i;
- + const struct fb_videomode *mode;
- + struct fb_videomode m;
- + struct mxc_hdmi *hdmi = mxc_dispdrv_getdata(disp);
- + int irq = platform_get_irq(hdmi->pdev, 0);
- +
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + /* Check hdmi disp init once */
- + if (hdmi_inited) {
- + dev_err(&hdmi->pdev->dev,
- + "Error only one HDMI output support now!\n");
- + return -1;
- + }
- +
- + hdmi_get_of_property(hdmi);
- +
- + if (irq < 0)
- + return -ENODEV;
- +
- + /* Setting HDMI default to blank state */
- + hdmi->blank = FB_BLANK_POWERDOWN;
- +
- + setting->dev_id = mxc_hdmi_ipu_id;
- + setting->disp_id = mxc_hdmi_disp_id;
- + setting->if_fmt = IPU_PIX_FMT_RGB24;
- +
- + hdmi->dft_mode_str = setting->dft_mode_str;
- + hdmi->default_bpp = setting->default_bpp;
- + dev_dbg(&hdmi->pdev->dev, "%s - default mode %s bpp=%d\n",
- + __func__, hdmi->dft_mode_str, hdmi->default_bpp);
- +
- + hdmi->fbi = setting->fbi;
- +
- + hdmi_init_route(hdmi);
- +
- + hdmi->hdmi_isfr_clk = clk_get(&hdmi->pdev->dev, "hdmi_isfr");
- + if (IS_ERR(hdmi->hdmi_isfr_clk)) {
- + ret = PTR_ERR(hdmi->hdmi_isfr_clk);
- + dev_err(&hdmi->pdev->dev,
- + "Unable to get HDMI clk: %d\n", ret);
- + goto egetclk1;
- + }
- +
- + ret = clk_prepare_enable(hdmi->hdmi_isfr_clk);
- + if (ret < 0) {
- + dev_err(&hdmi->pdev->dev,
- + "Cannot enable HDMI isfr clock: %d\n", ret);
- + goto erate1;
- + }
- +
- + hdmi->hdmi_iahb_clk = clk_get(&hdmi->pdev->dev, "hdmi_iahb");
- + if (IS_ERR(hdmi->hdmi_iahb_clk)) {
- + ret = PTR_ERR(hdmi->hdmi_iahb_clk);
- + dev_err(&hdmi->pdev->dev,
- + "Unable to get HDMI clk: %d\n", ret);
- + goto egetclk2;
- + }
- +
- + ret = clk_prepare_enable(hdmi->hdmi_iahb_clk);
- + if (ret < 0) {
- + dev_err(&hdmi->pdev->dev,
- + "Cannot enable HDMI iahb clock: %d\n", ret);
- + goto erate2;
- + }
- +
- + dev_dbg(&hdmi->pdev->dev, "Enabled HDMI clocks\n");
- +
- + /* Init DDC pins for HDCP */
- + if (hdcp_init) {
- + hdmi->pinctrl = devm_pinctrl_get_select_default(&hdmi->pdev->dev);
- + if (IS_ERR(hdmi->pinctrl)) {
- + dev_err(&hdmi->pdev->dev, "can't get/select DDC pinctrl\n");
- + goto erate2;
- + }
- + }
- +
- + /* Product and revision IDs */
- + dev_info(&hdmi->pdev->dev,
- + "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n",
- + hdmi_readb(HDMI_DESIGN_ID),
- + hdmi_readb(HDMI_REVISION_ID),
- + hdmi_readb(HDMI_PRODUCT_ID0),
- + hdmi_readb(HDMI_PRODUCT_ID1));
- +
- + /* To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator
- + * N and cts values before enabling phy */
- + hdmi_init_clk_regenerator();
- +
- + INIT_LIST_HEAD(&hdmi->fbi->modelist);
- +
- + spin_lock_init(&hdmi->irq_lock);
- +
- + /* Set the default mode and modelist when disp init. */
- + fb_find_mode(&hdmi->fbi->var, hdmi->fbi,
- + hdmi->dft_mode_str, NULL, 0, NULL,
- + hdmi->default_bpp);
- +
- + console_lock();
- +
- + fb_destroy_modelist(&hdmi->fbi->modelist);
- +
- + /*Add all no interlaced CEA mode to default modelist */
- + for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) {
- + mode = &mxc_cea_mode[i];
- + if (!(mode->vmode & FB_VMODE_INTERLACED) && (mode->xres != 0))
- + fb_add_videomode(mode, &hdmi->fbi->modelist);
- + }
- +
- + console_unlock();
- +
- + /* Find a nearest mode in default modelist */
- + fb_var_to_videomode(&m, &hdmi->fbi->var);
- + dump_fb_videomode(&m);
- +
- + hdmi->dft_mode_set = false;
- + /* Save default video mode */
- + memcpy(&hdmi->default_mode, &m, sizeof(struct fb_videomode));
- +
- + mode = fb_find_nearest_mode(&m, &hdmi->fbi->modelist);
- + if (!mode) {
- + pr_err("%s: could not find mode in modelist\n", __func__);
- + return -1;
- + }
- +
- + fb_videomode_to_var(&hdmi->fbi->var, mode);
- +
- + /* update fbi mode */
- + hdmi->fbi->mode = (struct fb_videomode *)mode;
- +
- + /* Default setting HDMI working in HDMI mode*/
- + hdmi->edid_cfg.hdmi_cap = true;
- +
- + hdmi->plug_event = HDMI_DVI_IH_STAT;
- + hdmi->plug_mask = HDMI_DVI_STAT;
- +
- + setup_timer(&hdmi->jitter_timer, hotplug_work_launch, (unsigned long)hdmi);
- + INIT_WORK(&hdmi->hotplug_work, hotplug_worker);
- + INIT_DELAYED_WORK(&hdmi->hdcp_hdp_work, hdcp_hdp_worker);
- +
- + /* Configure registers related to HDMI interrupt
- + * generation before registering IRQ. */
- + hdmi_writeb(hdmi->plug_mask, HDMI_PHY_POL0);
- +
- + /* Clear Hotplug interrupts */
- + hdmi_writeb(hdmi->plug_event, HDMI_IH_PHY_STAT0);
- +
- + hdmi->nb.notifier_call = mxc_hdmi_fb_event;
- + ret = fb_register_client(&hdmi->nb);
- + if (ret < 0)
- + goto efbclient;
- +
- + memset(&hdmi->hdmi_data, 0, sizeof(struct hdmi_data_info));
- +
- + /* Default HDMI working in RGB mode */
- + hdmi->hdmi_data.rgb_out_enable = true;
- +
- + if (!strcasecmp(rgb_quant_range, "limited")) {
- + hdmi->hdmi_data.rgb_quant_range = HDMI_FC_AVICONF2_RGB_QUANT_LIMITED_RANGE;
- + } else if (!strcasecmp(rgb_quant_range, "full")) {
- + hdmi->hdmi_data.rgb_quant_range = HDMI_FC_AVICONF2_RGB_QUANT_FULL_RANGE;
- + } else {
- + hdmi->hdmi_data.rgb_quant_range = HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT;
- + }
- +
- + ret = devm_request_irq(&hdmi->pdev->dev, irq, mxc_hdmi_hotplug, IRQF_SHARED,
- + dev_name(&hdmi->pdev->dev), hdmi);
- + if (ret < 0) {
- + dev_err(&hdmi->pdev->dev,
- + "Unable to request irq: %d\n", ret);
- + goto ereqirq;
- + }
- +
- + ret = device_create_file(&hdmi->pdev->dev, &dev_attr_fb_name);
- + if (ret < 0)
- + dev_warn(&hdmi->pdev->dev,
- + "cound not create sys node for fb name\n");
- + ret = device_create_file(&hdmi->pdev->dev, &dev_attr_cable_state);
- + if (ret < 0)
- + dev_warn(&hdmi->pdev->dev,
- + "cound not create sys node for cable state\n");
- + ret = device_create_file(&hdmi->pdev->dev, &dev_attr_edid);
- + if (ret < 0)
- + dev_warn(&hdmi->pdev->dev,
- + "cound not create sys node for edid\n");
- +
- + ret = device_create_file(&hdmi->pdev->dev, &dev_attr_rgb_out_enable);
- + if (ret < 0)
- + dev_warn(&hdmi->pdev->dev,
- + "cound not create sys node for rgb out enable\n");
- +
- + ret = device_create_file(&hdmi->pdev->dev, &dev_attr_rgb_quant_range);
- + if (ret < 0)
- + dev_warn(&hdmi->pdev->dev,
- + "cound not create sys node for rgb quant range\n");
- +
- + ret = device_create_file(&hdmi->pdev->dev, &dev_attr_hdcp_enable);
- + if (ret < 0)
- + dev_warn(&hdmi->pdev->dev,
- + "cound not create sys node for hdcp enable\n");
- +
- + dev_dbg(&hdmi->pdev->dev, "%s exit\n", __func__);
- +
- + hdmi_inited = true;
- +
- + return ret;
- +
- +efbclient:
- + free_irq(irq, hdmi);
- +ereqirq:
- + clk_disable_unprepare(hdmi->hdmi_iahb_clk);
- +erate2:
- + clk_put(hdmi->hdmi_iahb_clk);
- +egetclk2:
- + clk_disable_unprepare(hdmi->hdmi_isfr_clk);
- +erate1:
- + clk_put(hdmi->hdmi_isfr_clk);
- +egetclk1:
- + dev_dbg(&hdmi->pdev->dev, "%s error exit\n", __func__);
- +
- + return ret;
- +}
- +
- +static void mxc_hdmi_disp_deinit(struct mxc_dispdrv_handle *disp)
- +{
- + struct mxc_hdmi *hdmi = mxc_dispdrv_getdata(disp);
- +
- + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
- +
- + fb_unregister_client(&hdmi->nb);
- +
- + clk_disable_unprepare(hdmi->hdmi_isfr_clk);
- + clk_put(hdmi->hdmi_isfr_clk);
- + clk_disable_unprepare(hdmi->hdmi_iahb_clk);
- + clk_put(hdmi->hdmi_iahb_clk);
- +
- + platform_device_unregister(hdmi->pdev);
- +
- + hdmi_inited = false;
- +}
- +
- +static struct mxc_dispdrv_driver mxc_hdmi_drv = {
- + .name = DISPDRV_HDMI,
- + .init = mxc_hdmi_disp_init,
- + .deinit = mxc_hdmi_disp_deinit,
- + .enable = mxc_hdmi_power_on,
- + .disable = mxc_hdmi_power_off,
- +};
- +
- +
- +static int mxc_hdmi_open(struct inode *inode, struct file *file)
- +{
- + return 0;
- +}
- +
- +static long mxc_hdmi_ioctl(struct file *file,
- + unsigned int cmd, unsigned long arg)
- +{
- + int __user *argp = (void __user *)arg;
- + int ret = 0;
- +
- + switch (cmd) {
- + case HDMI_IOC_GET_RESOURCE:
- + ret = copy_to_user(argp, &g_hdmi->hdmi_data,
- + sizeof(g_hdmi->hdmi_data)) ? -EFAULT : 0;
- + break;
- + case HDMI_IOC_GET_CPU_TYPE:
- + *argp = g_hdmi->cpu_type;
- + break;
- + default:
- + pr_debug("Unsupport cmd %d\n", cmd);
- + break;
- + }
- + return ret;
- +}
- +
- +static int mxc_hdmi_release(struct inode *inode, struct file *file)
- +{
- + return 0;
- +}
- +
- +static const struct file_operations mxc_hdmi_fops = {
- + .owner = THIS_MODULE,
- + .open = mxc_hdmi_open,
- + .release = mxc_hdmi_release,
- + .unlocked_ioctl = mxc_hdmi_ioctl,
- +};
- +
- +
- +static int mxc_hdmi_probe(struct platform_device *pdev)
- +{
- + struct mxc_hdmi *hdmi;
- + struct device *temp_class;
- + struct resource *res;
- + int ret = 0;
- +
- + /* Check I2C driver is loaded and available
- + * check hdcp function is enable by dts */
- + hdmi_hdcp_get_property(pdev);
- + if (!hdmi_i2c && !hdcp_init)
- + return -ENODEV;
- +
- + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- + if (!res)
- + return -ENOENT;
- +
- + hdmi = devm_kzalloc(&pdev->dev,
- + sizeof(struct mxc_hdmi),
- + GFP_KERNEL);
- + if (!hdmi) {
- + dev_err(&pdev->dev, "Cannot allocate device data\n");
- + ret = -ENOMEM;
- + goto ealloc;
- + }
- + g_hdmi = hdmi;
- +
- + hdmi_major = register_chrdev(hdmi_major, "mxc_hdmi", &mxc_hdmi_fops);
- + if (hdmi_major < 0) {
- + printk(KERN_ERR "HDMI: unable to get a major for HDMI\n");
- + ret = -EBUSY;
- + goto ealloc;
- + }
- +
- + hdmi_class = class_create(THIS_MODULE, "mxc_hdmi");
- + if (IS_ERR(hdmi_class)) {
- + ret = PTR_ERR(hdmi_class);
- + goto err_out_chrdev;
- + }
- +
- + temp_class = device_create(hdmi_class, NULL, MKDEV(hdmi_major, 0),
- + NULL, "mxc_hdmi");
- + if (IS_ERR(temp_class)) {
- + ret = PTR_ERR(temp_class);
- + goto err_out_class;
- + }
- +
- + hdmi->pdev = pdev;
- +
- + hdmi->core_pdev = platform_device_alloc("mxc_hdmi_core", -1);
- + if (!hdmi->core_pdev) {
- + pr_err("%s failed platform_device_alloc for hdmi core\n",
- + __func__);
- + ret = -ENOMEM;
- + goto ecore;
- + }
- +
- + hdmi->gpr_base = ioremap(res->start, resource_size(res));
- + if (!hdmi->gpr_base) {
- + dev_err(&pdev->dev, "ioremap failed\n");
- + ret = -ENOMEM;
- + goto eiomap;
- + }
- +
- + hdmi->gpr_hdmi_base = hdmi->gpr_base + 3;
- + hdmi->gpr_sdma_base = hdmi->gpr_base;
- +
- + hdmi_inited = false;
- +
- + hdmi->disp_mxc_hdmi = mxc_dispdrv_register(&mxc_hdmi_drv);
- + if (IS_ERR(hdmi->disp_mxc_hdmi)) {
- + dev_err(&pdev->dev, "Failed to register dispdrv - 0x%x\n",
- + (int)hdmi->disp_mxc_hdmi);
- + ret = (int)hdmi->disp_mxc_hdmi;
- + goto edispdrv;
- + }
- + mxc_dispdrv_setdata(hdmi->disp_mxc_hdmi, hdmi);
- +
- + platform_set_drvdata(pdev, hdmi);
- +
- + return 0;
- +edispdrv:
- + iounmap(hdmi->gpr_base);
- +eiomap:
- + platform_device_put(hdmi->core_pdev);
- +ecore:
- + kfree(hdmi);
- +err_out_class:
- + device_destroy(hdmi_class, MKDEV(hdmi_major, 0));
- + class_destroy(hdmi_class);
- +err_out_chrdev:
- + unregister_chrdev(hdmi_major, "mxc_hdmi");
- +ealloc:
- + return ret;
- +}
- +
- +static int mxc_hdmi_remove(struct platform_device *pdev)
- +{
- + struct mxc_hdmi *hdmi = platform_get_drvdata(pdev);
- + int irq = platform_get_irq(pdev, 0);
- +
- + fb_unregister_client(&hdmi->nb);
- +
- + mxc_dispdrv_puthandle(hdmi->disp_mxc_hdmi);
- + mxc_dispdrv_unregister(hdmi->disp_mxc_hdmi);
- + iounmap(hdmi->gpr_base);
- + /* No new work will be scheduled, wait for running ISR */
- + free_irq(irq, hdmi);
- + kfree(hdmi);
- + g_hdmi = NULL;
- +
- + return 0;
- +}
- +
- +static struct platform_driver mxc_hdmi_driver = {
- + .probe = mxc_hdmi_probe,
- + .remove = mxc_hdmi_remove,
- + .driver = {
- + .name = "mxc_hdmi",
- + .of_match_table = imx_hdmi_dt_ids,
- + .owner = THIS_MODULE,
- + },
- +};
- +
- +static int __init mxc_hdmi_init(void)
- +{
- + return platform_driver_register(&mxc_hdmi_driver);
- +}
- +module_init(mxc_hdmi_init);
- +
- +static void __exit mxc_hdmi_exit(void)
- +{
- + if (hdmi_major > 0) {
- + device_destroy(hdmi_class, MKDEV(hdmi_major, 0));
- + class_destroy(hdmi_class);
- + unregister_chrdev(hdmi_major, "mxc_hdmi");
- + hdmi_major = 0;
- + }
- +
- + platform_driver_unregister(&mxc_hdmi_driver);
- +}
- +module_exit(mxc_hdmi_exit);
- +
- +static int mxc_hdmi_i2c_probe(struct i2c_client *client,
- + const struct i2c_device_id *id)
- +{
- + if (!i2c_check_functionality(client->adapter,
- + I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
- + return -ENODEV;
- +
- + hdmi_i2c = client;
- +
- + return 0;
- +}
- +
- +static int mxc_hdmi_i2c_remove(struct i2c_client *client)
- +{
- + hdmi_i2c = NULL;
- + return 0;
- +}
- +
- +static const struct of_device_id imx_hdmi_i2c_match[] = {
- + { .compatible = "fsl,imx6-hdmi-i2c", },
- + { /* sentinel */ }
- +};
- +
- +static const struct i2c_device_id mxc_hdmi_i2c_id[] = {
- + { "mxc_hdmi_i2c", 0 },
- + {},
- +};
- +MODULE_DEVICE_TABLE(i2c, mxc_hdmi_i2c_id);
- +
- +static struct i2c_driver mxc_hdmi_i2c_driver = {
- + .driver = {
- + .name = "mxc_hdmi_i2c",
- + .of_match_table = imx_hdmi_i2c_match,
- + },
- + .probe = mxc_hdmi_i2c_probe,
- + .remove = mxc_hdmi_i2c_remove,
- + .id_table = mxc_hdmi_i2c_id,
- +};
- +
- +static int __init mxc_hdmi_i2c_init(void)
- +{
- + return i2c_add_driver(&mxc_hdmi_i2c_driver);
- +}
- +
- +static void __exit mxc_hdmi_i2c_exit(void)
- +{
- + i2c_del_driver(&mxc_hdmi_i2c_driver);
- +}
- +
- +module_init(mxc_hdmi_i2c_init);
- +module_exit(mxc_hdmi_i2c_exit);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- diff -Nur linux-3.14.35.orig/drivers/video/mxc/mxc_ipuv3_fb.c linux-3.14.35/drivers/video/mxc/mxc_ipuv3_fb.c
- --- linux-3.14.35.orig/drivers/video/mxc/mxc_ipuv3_fb.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/video/mxc/mxc_ipuv3_fb.c 2015-03-08 14:27:37.789684499 -0500
- @@ -0,0 +1,2578 @@
- +/*
- + * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @defgroup Framebuffer Framebuffer Driver for SDC and ADC.
- + */
- +
- +/*!
- + * @file mxcfb.c
- + *
- + * @brief MXC Frame buffer driver for SDC
- + *
- + * @ingroup Framebuffer
- + */
- +
- +/*!
- + * Include files
- + */
- +#include <linux/clk.h>
- +#include <linux/console.h>
- +#include <linux/delay.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/errno.h>
- +#include <linux/fb.h>
- +#include <linux/fsl_devices.h>
- +#include <linux/init.h>
- +#include <linux/interrupt.h>
- +#include <linux/io.h>
- +#include <linux/ioport.h>
- +#include <linux/ipu.h>
- +#include <linux/ipu-v3.h>
- +#include <linux/kernel.h>
- +#include <linux/module.h>
- +#include <linux/mxcfb.h>
- +#include <linux/of_device.h>
- +#include <linux/platform_device.h>
- +#include <linux/sched.h>
- +#include <linux/slab.h>
- +#include <linux/string.h>
- +#include <linux/uaccess.h>
- +
- +#include "mxc_dispdrv.h"
- +
- +/*
- + * Driver name
- + */
- +#define MXCFB_NAME "mxc_sdc_fb"
- +
- +/* Display port number */
- +#define MXCFB_PORT_NUM 2
- +/*!
- + * Structure containing the MXC specific framebuffer information.
- + */
- +struct mxcfb_info {
- + int default_bpp;
- + int cur_blank;
- + int next_blank;
- + ipu_channel_t ipu_ch;
- + int ipu_id;
- + int ipu_di;
- + u32 ipu_di_pix_fmt;
- + bool ipu_int_clk;
- + bool overlay;
- + bool alpha_chan_en;
- + bool late_init;
- + bool first_set_par;
- + dma_addr_t alpha_phy_addr0;
- + dma_addr_t alpha_phy_addr1;
- + void *alpha_virt_addr0;
- + void *alpha_virt_addr1;
- + uint32_t alpha_mem_len;
- + uint32_t ipu_ch_irq;
- + uint32_t ipu_ch_nf_irq;
- + uint32_t ipu_alp_ch_irq;
- + uint32_t cur_ipu_buf;
- + uint32_t cur_ipu_alpha_buf;
- +
- + u32 pseudo_palette[16];
- +
- + bool mode_found;
- + struct completion flip_complete;
- + struct completion alpha_flip_complete;
- + struct completion vsync_complete;
- +
- + void *ipu;
- + struct fb_info *ovfbi;
- +
- + struct mxc_dispdrv_handle *dispdrv;
- +
- + struct fb_var_screeninfo cur_var;
- +};
- +
- +struct mxcfb_pfmt {
- + u32 fb_pix_fmt;
- + int bpp;
- + struct fb_bitfield red;
- + struct fb_bitfield green;
- + struct fb_bitfield blue;
- + struct fb_bitfield transp;
- +};
- +
- +static const struct mxcfb_pfmt mxcfb_pfmts[] = {
- + /* pixel bpp red green blue transp */
- + {IPU_PIX_FMT_RGB565, 16, {11, 5, 0}, { 5, 6, 0}, { 0, 5, 0}, { 0, 0, 0} },
- + {IPU_PIX_FMT_RGB24, 24, { 0, 8, 0}, { 8, 8, 0}, {16, 8, 0}, { 0, 0, 0} },
- + {IPU_PIX_FMT_BGR24, 24, {16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 0, 0, 0} },
- + {IPU_PIX_FMT_RGB32, 32, { 0, 8, 0}, { 8, 8, 0}, {16, 8, 0}, {24, 8, 0} },
- + {IPU_PIX_FMT_BGR32, 32, {16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, {24, 8, 0} },
- + {IPU_PIX_FMT_ABGR32, 32, {24, 8, 0}, {16, 8, 0}, { 8, 8, 0}, { 0, 8, 0} },
- +};
- +
- +struct mxcfb_alloc_list {
- + struct list_head list;
- + dma_addr_t phy_addr;
- + void *cpu_addr;
- + u32 size;
- +};
- +
- +enum {
- + BOTH_ON,
- + SRC_ON,
- + TGT_ON,
- + BOTH_OFF
- +};
- +
- +static bool g_dp_in_use[2];
- +LIST_HEAD(fb_alloc_list);
- +
- +/* Return default standard(RGB) pixel format */
- +static uint32_t bpp_to_pixfmt(int bpp)
- +{
- + uint32_t pixfmt = 0;
- +
- + switch (bpp) {
- + case 24:
- + pixfmt = IPU_PIX_FMT_BGR24;
- + break;
- + case 32:
- + pixfmt = IPU_PIX_FMT_BGR32;
- + break;
- + case 16:
- + pixfmt = IPU_PIX_FMT_RGB565;
- + break;
- + }
- + return pixfmt;
- +}
- +
- +static inline int bitfield_is_equal(struct fb_bitfield f1,
- + struct fb_bitfield f2)
- +{
- + return !memcmp(&f1, &f2, sizeof(f1));
- +}
- +
- +static int pixfmt_to_var(uint32_t pixfmt, struct fb_var_screeninfo *var)
- +{
- + int i, ret = -1;
- +
- + for (i = 0; i < ARRAY_SIZE(mxcfb_pfmts); i++) {
- + if (pixfmt == mxcfb_pfmts[i].fb_pix_fmt) {
- + var->red = mxcfb_pfmts[i].red;
- + var->green = mxcfb_pfmts[i].green;
- + var->blue = mxcfb_pfmts[i].blue;
- + var->transp = mxcfb_pfmts[i].transp;
- + var->bits_per_pixel = mxcfb_pfmts[i].bpp;
- + ret = 0;
- + break;
- + }
- + }
- + return ret;
- +}
- +
- +static int bpp_to_var(int bpp, struct fb_var_screeninfo *var)
- +{
- + uint32_t pixfmt = 0;
- +
- + pixfmt = bpp_to_pixfmt(bpp);
- + if (pixfmt)
- + return pixfmt_to_var(pixfmt, var);
- + else
- + return -1;
- +}
- +
- +static int check_var_pixfmt(struct fb_var_screeninfo *var)
- +{
- + int i, ret = -1;
- +
- + for (i = 0; i < ARRAY_SIZE(mxcfb_pfmts); i++) {
- + if (bitfield_is_equal(var->red, mxcfb_pfmts[i].red) &&
- + bitfield_is_equal(var->green, mxcfb_pfmts[i].green) &&
- + bitfield_is_equal(var->blue, mxcfb_pfmts[i].blue) &&
- + bitfield_is_equal(var->transp, mxcfb_pfmts[i].transp) &&
- + var->bits_per_pixel == mxcfb_pfmts[i].bpp) {
- + ret = 0;
- + break;
- + }
- + }
- + return ret;
- +}
- +
- +static uint32_t fbi_to_pixfmt(struct fb_info *fbi)
- +{
- + int i;
- + uint32_t pixfmt = 0;
- +
- + if (fbi->var.nonstd)
- + return fbi->var.nonstd;
- +
- + for (i = 0; i < ARRAY_SIZE(mxcfb_pfmts); i++) {
- + if (bitfield_is_equal(fbi->var.red, mxcfb_pfmts[i].red) &&
- + bitfield_is_equal(fbi->var.green, mxcfb_pfmts[i].green) &&
- + bitfield_is_equal(fbi->var.blue, mxcfb_pfmts[i].blue) &&
- + bitfield_is_equal(fbi->var.transp, mxcfb_pfmts[i].transp)) {
- + pixfmt = mxcfb_pfmts[i].fb_pix_fmt;
- + break;
- + }
- + }
- +
- + if (pixfmt == 0)
- + dev_err(fbi->device, "cannot get pixel format\n");
- +
- + return pixfmt;
- +}
- +
- +static struct fb_info *found_registered_fb(ipu_channel_t ipu_ch, int ipu_id)
- +{
- + int i;
- + struct mxcfb_info *mxc_fbi;
- + struct fb_info *fbi = NULL;
- +
- + for (i = 0; i < num_registered_fb; i++) {
- + mxc_fbi =
- + ((struct mxcfb_info *)(registered_fb[i]->par));
- +
- + if ((mxc_fbi->ipu_ch == ipu_ch) &&
- + (mxc_fbi->ipu_id == ipu_id)) {
- + fbi = registered_fb[i];
- + break;
- + }
- + }
- + return fbi;
- +}
- +
- +static irqreturn_t mxcfb_irq_handler(int irq, void *dev_id);
- +static irqreturn_t mxcfb_nf_irq_handler(int irq, void *dev_id);
- +static int mxcfb_blank(int blank, struct fb_info *info);
- +static int mxcfb_map_video_memory(struct fb_info *fbi);
- +static int mxcfb_unmap_video_memory(struct fb_info *fbi);
- +
- +/*
- + * Set fixed framebuffer parameters based on variable settings.
- + *
- + * @param info framebuffer information pointer
- + */
- +static int mxcfb_set_fix(struct fb_info *info)
- +{
- + struct fb_fix_screeninfo *fix = &info->fix;
- + struct fb_var_screeninfo *var = &info->var;
- +
- + fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
- +
- + fix->type = FB_TYPE_PACKED_PIXELS;
- + fix->accel = FB_ACCEL_NONE;
- + fix->visual = FB_VISUAL_TRUECOLOR;
- + fix->xpanstep = 1;
- + fix->ywrapstep = 1;
- + fix->ypanstep = 1;
- +
- + return 0;
- +}
- +
- +static int _setup_disp_channel1(struct fb_info *fbi)
- +{
- + ipu_channel_params_t params;
- + struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
- +
- + memset(¶ms, 0, sizeof(params));
- +
- + if (mxc_fbi->ipu_ch == MEM_DC_SYNC) {
- + params.mem_dc_sync.di = mxc_fbi->ipu_di;
- + if (fbi->var.vmode & FB_VMODE_INTERLACED)
- + params.mem_dc_sync.interlaced = true;
- + params.mem_dc_sync.out_pixel_fmt = mxc_fbi->ipu_di_pix_fmt;
- + params.mem_dc_sync.in_pixel_fmt = fbi_to_pixfmt(fbi);
- + } else {
- + params.mem_dp_bg_sync.di = mxc_fbi->ipu_di;
- + if (fbi->var.vmode & FB_VMODE_INTERLACED)
- + params.mem_dp_bg_sync.interlaced = true;
- + params.mem_dp_bg_sync.out_pixel_fmt = mxc_fbi->ipu_di_pix_fmt;
- + params.mem_dp_bg_sync.in_pixel_fmt = fbi_to_pixfmt(fbi);
- + if (mxc_fbi->alpha_chan_en)
- + params.mem_dp_bg_sync.alpha_chan_en = true;
- + }
- + ipu_init_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch, ¶ms);
- +
- + return 0;
- +}
- +
- +static int _setup_disp_channel2(struct fb_info *fbi)
- +{
- + int retval = 0;
- + struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
- + int fb_stride;
- + unsigned long base;
- + unsigned int fr_xoff, fr_yoff, fr_w, fr_h;
- +
- + switch (fbi_to_pixfmt(fbi)) {
- + case IPU_PIX_FMT_YUV420P2:
- + case IPU_PIX_FMT_YVU420P:
- + case IPU_PIX_FMT_NV12:
- + case IPU_PIX_FMT_YUV422P:
- + case IPU_PIX_FMT_YVU422P:
- + case IPU_PIX_FMT_YUV420P:
- + case IPU_PIX_FMT_YUV444P:
- + fb_stride = fbi->var.xres_virtual;
- + break;
- + default:
- + fb_stride = fbi->fix.line_length;
- + }
- +
- + base = fbi->fix.smem_start;
- + fr_xoff = fbi->var.xoffset;
- + fr_w = fbi->var.xres_virtual;
- + if (!(fbi->var.vmode & FB_VMODE_YWRAP)) {
- + dev_dbg(fbi->device, "Y wrap disabled\n");
- + fr_yoff = fbi->var.yoffset % fbi->var.yres;
- + fr_h = fbi->var.yres;
- + base += fbi->fix.line_length * fbi->var.yres *
- + (fbi->var.yoffset / fbi->var.yres);
- + } else {
- + dev_dbg(fbi->device, "Y wrap enabled\n");
- + fr_yoff = fbi->var.yoffset;
- + fr_h = fbi->var.yres_virtual;
- + }
- + base += fr_yoff * fb_stride + fr_xoff;
- +
- + mxc_fbi->cur_ipu_buf = 2;
- + init_completion(&mxc_fbi->flip_complete);
- + /*
- + * We don't need to wait for vsync at the first time
- + * we do pan display after fb is initialized, as IPU will
- + * switch to the newly selected buffer automatically,
- + * so we call complete() for both mxc_fbi->flip_complete
- + * and mxc_fbi->alpha_flip_complete.
- + */
- + complete(&mxc_fbi->flip_complete);
- + if (mxc_fbi->alpha_chan_en) {
- + mxc_fbi->cur_ipu_alpha_buf = 1;
- + init_completion(&mxc_fbi->alpha_flip_complete);
- + complete(&mxc_fbi->alpha_flip_complete);
- + }
- +
- + retval = ipu_init_channel_buffer(mxc_fbi->ipu,
- + mxc_fbi->ipu_ch, IPU_INPUT_BUFFER,
- + fbi_to_pixfmt(fbi),
- + fbi->var.xres, fbi->var.yres,
- + fb_stride,
- + fbi->var.rotate,
- + base,
- + base,
- + fbi->var.accel_flags &
- + FB_ACCEL_DOUBLE_FLAG ? 0 : base,
- + 0, 0);
- + if (retval) {
- + dev_err(fbi->device,
- + "ipu_init_channel_buffer error %d\n", retval);
- + return retval;
- + }
- +
- + /* update u/v offset */
- + ipu_update_channel_offset(mxc_fbi->ipu, mxc_fbi->ipu_ch,
- + IPU_INPUT_BUFFER,
- + fbi_to_pixfmt(fbi),
- + fr_w,
- + fr_h,
- + fr_w,
- + 0, 0,
- + fr_yoff,
- + fr_xoff);
- +
- + if (mxc_fbi->alpha_chan_en) {
- + retval = ipu_init_channel_buffer(mxc_fbi->ipu,
- + mxc_fbi->ipu_ch,
- + IPU_ALPHA_IN_BUFFER,
- + IPU_PIX_FMT_GENERIC,
- + fbi->var.xres, fbi->var.yres,
- + fbi->var.xres,
- + fbi->var.rotate,
- + mxc_fbi->alpha_phy_addr1,
- + mxc_fbi->alpha_phy_addr0,
- + 0,
- + 0, 0);
- + if (retval) {
- + dev_err(fbi->device,
- + "ipu_init_channel_buffer error %d\n", retval);
- + return retval;
- + }
- + }
- +
- + return retval;
- +}
- +
- +static bool mxcfb_need_to_set_par(struct fb_info *fbi)
- +{
- + struct mxcfb_info *mxc_fbi = fbi->par;
- +
- + if ((fbi->var.activate & FB_ACTIVATE_FORCE) &&
- + (fbi->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
- + return true;
- +
- + /*
- + * Ignore xoffset and yoffset update,
- + * because pan display handles this case.
- + */
- + mxc_fbi->cur_var.xoffset = fbi->var.xoffset;
- + mxc_fbi->cur_var.yoffset = fbi->var.yoffset;
- +
- + return !!memcmp(&mxc_fbi->cur_var, &fbi->var,
- + sizeof(struct fb_var_screeninfo));
- +}
- +
- +/*
- + * Set framebuffer parameters and change the operating mode.
- + *
- + * @param info framebuffer information pointer
- + */
- +static int mxcfb_set_par(struct fb_info *fbi)
- +{
- + int retval = 0;
- + u32 mem_len, alpha_mem_len;
- + ipu_di_signal_cfg_t sig_cfg;
- + struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
- +
- + int16_t ov_pos_x = 0, ov_pos_y = 0;
- + int ov_pos_ret = 0;
- + struct mxcfb_info *mxc_fbi_fg = NULL;
- + bool ovfbi_enable = false;
- +
- + if (ipu_ch_param_bad_alpha_pos(fbi_to_pixfmt(fbi)) &&
- + mxc_fbi->alpha_chan_en) {
- + dev_err(fbi->device, "Bad pixel format for "
- + "graphics plane fb\n");
- + return -EINVAL;
- + }
- +
- + if (mxc_fbi->ovfbi)
- + mxc_fbi_fg = (struct mxcfb_info *)mxc_fbi->ovfbi->par;
- +
- + if (mxc_fbi->ovfbi && mxc_fbi_fg)
- + if (mxc_fbi_fg->next_blank == FB_BLANK_UNBLANK)
- + ovfbi_enable = true;
- +
- + if (!mxcfb_need_to_set_par(fbi))
- + return 0;
- +
- + dev_dbg(fbi->device, "Reconfiguring framebuffer\n");
- +
- + if (fbi->var.xres == 0 || fbi->var.yres == 0)
- + return 0;
- +
- + if (ovfbi_enable) {
- + ov_pos_ret = ipu_disp_get_window_pos(
- + mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch,
- + &ov_pos_x, &ov_pos_y);
- + if (ov_pos_ret < 0)
- + dev_err(fbi->device, "Get overlay pos failed, dispdrv:%s.\n",
- + mxc_fbi->dispdrv->drv->name);
- +
- + ipu_clear_irq(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch_irq);
- + ipu_disable_irq(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch_irq);
- + ipu_clear_irq(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch_nf_irq);
- + ipu_disable_irq(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch_nf_irq);
- + ipu_disable_channel(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch, true);
- + ipu_uninit_channel(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch);
- + }
- +
- + ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
- + ipu_disable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
- + ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_nf_irq);
- + ipu_disable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_nf_irq);
- + ipu_disable_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch, true);
- + ipu_uninit_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch);
- +
- + /*
- + * Disable IPU hsp clock if it is enabled for an
- + * additional time in ipu common driver.
- + */
- + if (mxc_fbi->first_set_par && mxc_fbi->late_init)
- + ipu_disable_hsp_clk(mxc_fbi->ipu);
- +
- + mxcfb_set_fix(fbi);
- +
- + mem_len = fbi->var.yres_virtual * fbi->fix.line_length;
- + if (!fbi->fix.smem_start || (mem_len > fbi->fix.smem_len)) {
- + if (fbi->fix.smem_start)
- + mxcfb_unmap_video_memory(fbi);
- +
- + if (mxcfb_map_video_memory(fbi) < 0)
- + return -ENOMEM;
- + }
- +
- + if (mxc_fbi->first_set_par) {
- + /*
- + * Clear the screen in case uboot fb pixel format is not
- + * the same to kernel fb pixel format.
- + */
- + if (mxc_fbi->late_init)
- + memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
- +
- + mxc_fbi->first_set_par = false;
- + }
- +
- + if (mxc_fbi->alpha_chan_en) {
- + alpha_mem_len = fbi->var.xres * fbi->var.yres;
- + if ((!mxc_fbi->alpha_phy_addr0 && !mxc_fbi->alpha_phy_addr1) ||
- + (alpha_mem_len > mxc_fbi->alpha_mem_len)) {
- + if (mxc_fbi->alpha_phy_addr0)
- + dma_free_coherent(fbi->device,
- + mxc_fbi->alpha_mem_len,
- + mxc_fbi->alpha_virt_addr0,
- + mxc_fbi->alpha_phy_addr0);
- + if (mxc_fbi->alpha_phy_addr1)
- + dma_free_coherent(fbi->device,
- + mxc_fbi->alpha_mem_len,
- + mxc_fbi->alpha_virt_addr1,
- + mxc_fbi->alpha_phy_addr1);
- +
- + mxc_fbi->alpha_virt_addr0 =
- + dma_alloc_coherent(fbi->device,
- + alpha_mem_len,
- + &mxc_fbi->alpha_phy_addr0,
- + GFP_DMA | GFP_KERNEL);
- +
- + mxc_fbi->alpha_virt_addr1 =
- + dma_alloc_coherent(fbi->device,
- + alpha_mem_len,
- + &mxc_fbi->alpha_phy_addr1,
- + GFP_DMA | GFP_KERNEL);
- + if (mxc_fbi->alpha_virt_addr0 == NULL ||
- + mxc_fbi->alpha_virt_addr1 == NULL) {
- + dev_err(fbi->device, "mxcfb: dma alloc for"
- + " alpha buffer failed.\n");
- + if (mxc_fbi->alpha_virt_addr0)
- + dma_free_coherent(fbi->device,
- + mxc_fbi->alpha_mem_len,
- + mxc_fbi->alpha_virt_addr0,
- + mxc_fbi->alpha_phy_addr0);
- + if (mxc_fbi->alpha_virt_addr1)
- + dma_free_coherent(fbi->device,
- + mxc_fbi->alpha_mem_len,
- + mxc_fbi->alpha_virt_addr1,
- + mxc_fbi->alpha_phy_addr1);
- + return -ENOMEM;
- + }
- + mxc_fbi->alpha_mem_len = alpha_mem_len;
- + }
- + }
- +
- + if (mxc_fbi->next_blank != FB_BLANK_UNBLANK)
- + return retval;
- +
- + if (mxc_fbi->dispdrv && mxc_fbi->dispdrv->drv->setup) {
- + retval = mxc_fbi->dispdrv->drv->setup(mxc_fbi->dispdrv, fbi);
- + if (retval < 0) {
- + dev_err(fbi->device, "setup error, dispdrv:%s.\n",
- + mxc_fbi->dispdrv->drv->name);
- + return -EINVAL;
- + }
- + }
- +
- + _setup_disp_channel1(fbi);
- + if (ovfbi_enable)
- + _setup_disp_channel1(mxc_fbi->ovfbi);
- +
- + if (!mxc_fbi->overlay) {
- + uint32_t out_pixel_fmt;
- +
- + memset(&sig_cfg, 0, sizeof(sig_cfg));
- + if (fbi->var.vmode & FB_VMODE_INTERLACED)
- + sig_cfg.interlaced = true;
- + out_pixel_fmt = mxc_fbi->ipu_di_pix_fmt;
- + if (fbi->var.vmode & FB_VMODE_ODD_FLD_FIRST) /* PAL */
- + sig_cfg.odd_field_first = true;
- + if (mxc_fbi->ipu_int_clk)
- + sig_cfg.int_clk = true;
- + if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT)
- + sig_cfg.Hsync_pol = true;
- + if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)
- + sig_cfg.Vsync_pol = true;
- + if (!(fbi->var.sync & FB_SYNC_CLK_LAT_FALL))
- + sig_cfg.clk_pol = true;
- + if (fbi->var.sync & FB_SYNC_DATA_INVERT)
- + sig_cfg.data_pol = true;
- + if (!(fbi->var.sync & FB_SYNC_OE_LOW_ACT))
- + sig_cfg.enable_pol = true;
- + if (fbi->var.sync & FB_SYNC_CLK_IDLE_EN)
- + sig_cfg.clkidle_en = true;
- +
- + dev_dbg(fbi->device, "pixclock = %ul Hz\n",
- + (u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL));
- +
- + if (ipu_init_sync_panel(mxc_fbi->ipu, mxc_fbi->ipu_di,
- + (PICOS2KHZ(fbi->var.pixclock)) * 1000UL,
- + fbi->var.xres, fbi->var.yres,
- + out_pixel_fmt,
- + fbi->var.left_margin,
- + fbi->var.hsync_len,
- + fbi->var.right_margin,
- + fbi->var.upper_margin,
- + fbi->var.vsync_len,
- + fbi->var.lower_margin,
- + 0, sig_cfg) != 0) {
- + dev_err(fbi->device,
- + "mxcfb: Error initializing panel.\n");
- + return -EINVAL;
- + }
- +
- + fbi->mode =
- + (struct fb_videomode *)fb_match_mode(&fbi->var,
- + &fbi->modelist);
- +
- + ipu_disp_set_window_pos(mxc_fbi->ipu, mxc_fbi->ipu_ch, 0, 0);
- + }
- +
- + retval = _setup_disp_channel2(fbi);
- + if (retval) {
- + ipu_uninit_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch);
- + return retval;
- + }
- +
- + if (ovfbi_enable) {
- + if (ov_pos_ret >= 0)
- + ipu_disp_set_window_pos(
- + mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch,
- + ov_pos_x, ov_pos_y);
- + retval = _setup_disp_channel2(mxc_fbi->ovfbi);
- + if (retval) {
- + ipu_uninit_channel(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch);
- + ipu_uninit_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch);
- + return retval;
- + }
- + }
- +
- + ipu_enable_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch);
- + if (ovfbi_enable)
- + ipu_enable_channel(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch);
- +
- + if (mxc_fbi->dispdrv && mxc_fbi->dispdrv->drv->enable) {
- + retval = mxc_fbi->dispdrv->drv->enable(mxc_fbi->dispdrv);
- + if (retval < 0) {
- + dev_err(fbi->device, "enable error, dispdrv:%s.\n",
- + mxc_fbi->dispdrv->drv->name);
- + return -EINVAL;
- + }
- + }
- +
- + mxc_fbi->cur_var = fbi->var;
- +
- + return retval;
- +}
- +
- +static int _swap_channels(struct fb_info *fbi_from,
- + struct fb_info *fbi_to, bool both_on)
- +{
- + int retval, tmp;
- + ipu_channel_t old_ch;
- + struct fb_info *ovfbi;
- + struct mxcfb_info *mxc_fbi_from = (struct mxcfb_info *)fbi_from->par;
- + struct mxcfb_info *mxc_fbi_to = (struct mxcfb_info *)fbi_to->par;
- +
- + if (both_on) {
- + ipu_disable_channel(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch, true);
- + ipu_uninit_channel(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch);
- + }
- +
- + /* switch the mxc fbi parameters */
- + old_ch = mxc_fbi_from->ipu_ch;
- + mxc_fbi_from->ipu_ch = mxc_fbi_to->ipu_ch;
- + mxc_fbi_to->ipu_ch = old_ch;
- + tmp = mxc_fbi_from->ipu_ch_irq;
- + mxc_fbi_from->ipu_ch_irq = mxc_fbi_to->ipu_ch_irq;
- + mxc_fbi_to->ipu_ch_irq = tmp;
- + tmp = mxc_fbi_from->ipu_ch_nf_irq;
- + mxc_fbi_from->ipu_ch_nf_irq = mxc_fbi_to->ipu_ch_nf_irq;
- + mxc_fbi_to->ipu_ch_nf_irq = tmp;
- + ovfbi = mxc_fbi_from->ovfbi;
- + mxc_fbi_from->ovfbi = mxc_fbi_to->ovfbi;
- + mxc_fbi_to->ovfbi = ovfbi;
- +
- + _setup_disp_channel1(fbi_from);
- + retval = _setup_disp_channel2(fbi_from);
- + if (retval)
- + return retval;
- +
- + /* switch between dp and dc, disable old idmac, enable new idmac */
- + retval = ipu_swap_channel(mxc_fbi_from->ipu, old_ch, mxc_fbi_from->ipu_ch);
- + ipu_uninit_channel(mxc_fbi_from->ipu, old_ch);
- +
- + if (both_on) {
- + _setup_disp_channel1(fbi_to);
- + retval = _setup_disp_channel2(fbi_to);
- + if (retval)
- + return retval;
- + ipu_enable_channel(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch);
- + }
- +
- + return retval;
- +}
- +
- +static int swap_channels(struct fb_info *fbi_from)
- +{
- + int i;
- + int swap_mode;
- + ipu_channel_t ch_to;
- + struct mxcfb_info *mxc_fbi_from = (struct mxcfb_info *)fbi_from->par;
- + struct fb_info *fbi_to = NULL;
- + struct mxcfb_info *mxc_fbi_to;
- +
- + /* what's the target channel? */
- + if (mxc_fbi_from->ipu_ch == MEM_BG_SYNC)
- + ch_to = MEM_DC_SYNC;
- + else
- + ch_to = MEM_BG_SYNC;
- +
- + fbi_to = found_registered_fb(ch_to, mxc_fbi_from->ipu_id);
- + if (!fbi_to)
- + return -1;
- + mxc_fbi_to = (struct mxcfb_info *)fbi_to->par;
- +
- + ipu_clear_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_irq);
- + ipu_clear_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_irq);
- + ipu_free_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_irq, fbi_from);
- + ipu_free_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_irq, fbi_to);
- + ipu_clear_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_nf_irq);
- + ipu_clear_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_nf_irq);
- + ipu_free_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_nf_irq, fbi_from);
- + ipu_free_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_nf_irq, fbi_to);
- +
- + if (mxc_fbi_from->cur_blank == FB_BLANK_UNBLANK) {
- + if (mxc_fbi_to->cur_blank == FB_BLANK_UNBLANK)
- + swap_mode = BOTH_ON;
- + else
- + swap_mode = SRC_ON;
- + } else {
- + if (mxc_fbi_to->cur_blank == FB_BLANK_UNBLANK)
- + swap_mode = TGT_ON;
- + else
- + swap_mode = BOTH_OFF;
- + }
- +
- + switch (swap_mode) {
- + case BOTH_ON:
- + /* disable target->switch src->enable target */
- + _swap_channels(fbi_from, fbi_to, true);
- + break;
- + case SRC_ON:
- + /* just switch src */
- + _swap_channels(fbi_from, fbi_to, false);
- + break;
- + case TGT_ON:
- + /* just switch target */
- + _swap_channels(fbi_to, fbi_from, false);
- + break;
- + case BOTH_OFF:
- + /* switch directly, no more need to do */
- + mxc_fbi_to->ipu_ch = mxc_fbi_from->ipu_ch;
- + mxc_fbi_from->ipu_ch = ch_to;
- + i = mxc_fbi_from->ipu_ch_irq;
- + mxc_fbi_from->ipu_ch_irq = mxc_fbi_to->ipu_ch_irq;
- + mxc_fbi_to->ipu_ch_irq = i;
- + i = mxc_fbi_from->ipu_ch_nf_irq;
- + mxc_fbi_from->ipu_ch_nf_irq = mxc_fbi_to->ipu_ch_nf_irq;
- + mxc_fbi_to->ipu_ch_nf_irq = i;
- + break;
- + default:
- + break;
- + }
- +
- + if (ipu_request_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_irq,
- + mxcfb_irq_handler, IPU_IRQF_ONESHOT,
- + MXCFB_NAME, fbi_from) != 0) {
- + dev_err(fbi_from->device, "Error registering irq %d\n",
- + mxc_fbi_from->ipu_ch_irq);
- + return -EBUSY;
- + }
- + ipu_disable_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_irq);
- + if (ipu_request_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_irq,
- + mxcfb_irq_handler, IPU_IRQF_ONESHOT,
- + MXCFB_NAME, fbi_to) != 0) {
- + dev_err(fbi_to->device, "Error registering irq %d\n",
- + mxc_fbi_to->ipu_ch_irq);
- + return -EBUSY;
- + }
- + ipu_disable_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_irq);
- + if (ipu_request_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_nf_irq,
- + mxcfb_nf_irq_handler, IPU_IRQF_ONESHOT,
- + MXCFB_NAME, fbi_from) != 0) {
- + dev_err(fbi_from->device, "Error registering irq %d\n",
- + mxc_fbi_from->ipu_ch_nf_irq);
- + return -EBUSY;
- + }
- + ipu_disable_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_nf_irq);
- + if (ipu_request_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_nf_irq,
- + mxcfb_nf_irq_handler, IPU_IRQF_ONESHOT,
- + MXCFB_NAME, fbi_to) != 0) {
- + dev_err(fbi_to->device, "Error registering irq %d\n",
- + mxc_fbi_to->ipu_ch_nf_irq);
- + return -EBUSY;
- + }
- + ipu_disable_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_nf_irq);
- +
- + return 0;
- +}
- +
- +/*
- + * Check framebuffer variable parameters and adjust to valid values.
- + *
- + * @param var framebuffer variable parameters
- + *
- + * @param info framebuffer information pointer
- + */
- +static int mxcfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
- +{
- + u32 vtotal;
- + u32 htotal;
- + struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)info->par;
- +
- +
- + if (var->xres == 0 || var->yres == 0)
- + return 0;
- +
- + /* fg should not bigger than bg */
- + if (mxc_fbi->ipu_ch == MEM_FG_SYNC) {
- + struct fb_info *fbi_tmp;
- + int bg_xres = 0, bg_yres = 0;
- + int16_t pos_x, pos_y;
- +
- + bg_xres = var->xres;
- + bg_yres = var->yres;
- +
- + fbi_tmp = found_registered_fb(MEM_BG_SYNC, mxc_fbi->ipu_id);
- + if (fbi_tmp) {
- + bg_xres = fbi_tmp->var.xres;
- + bg_yres = fbi_tmp->var.yres;
- + }
- +
- + ipu_disp_get_window_pos(mxc_fbi->ipu, mxc_fbi->ipu_ch, &pos_x, &pos_y);
- +
- + if ((var->xres + pos_x) > bg_xres)
- + var->xres = bg_xres - pos_x;
- + if ((var->yres + pos_y) > bg_yres)
- + var->yres = bg_yres - pos_y;
- + }
- +
- + if (var->rotate > IPU_ROTATE_VERT_FLIP)
- + var->rotate = IPU_ROTATE_NONE;
- +
- + if (var->xres_virtual < var->xres)
- + var->xres_virtual = var->xres;
- +
- + if (var->yres_virtual < var->yres)
- + var->yres_virtual = var->yres * 3;
- +
- + if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) &&
- + (var->bits_per_pixel != 16) && (var->bits_per_pixel != 12) &&
- + (var->bits_per_pixel != 8))
- + var->bits_per_pixel = 16;
- +
- + if (check_var_pixfmt(var))
- + /* Fall back to default */
- + bpp_to_var(var->bits_per_pixel, var);
- +
- + if (var->pixclock < 1000) {
- + htotal = var->xres + var->right_margin + var->hsync_len +
- + var->left_margin;
- + vtotal = var->yres + var->lower_margin + var->vsync_len +
- + var->upper_margin;
- + var->pixclock = (vtotal * htotal * 6UL) / 100UL;
- + var->pixclock = KHZ2PICOS(var->pixclock);
- + dev_dbg(info->device,
- + "pixclock set for 60Hz refresh = %u ps\n",
- + var->pixclock);
- + }
- +
- + var->height = -1;
- + var->width = -1;
- + var->grayscale = 0;
- +
- + return 0;
- +}
- +
- +static inline u_int _chan_to_field(u_int chan, struct fb_bitfield *bf)
- +{
- + chan &= 0xffff;
- + chan >>= 16 - bf->length;
- + return chan << bf->offset;
- +}
- +
- +static int mxcfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- + u_int trans, struct fb_info *fbi)
- +{
- + unsigned int val;
- + int ret = 1;
- +
- + /*
- + * If greyscale is true, then we convert the RGB value
- + * to greyscale no matter what visual we are using.
- + */
- + if (fbi->var.grayscale)
- + red = green = blue = (19595 * red + 38470 * green +
- + 7471 * blue) >> 16;
- + switch (fbi->fix.visual) {
- + case FB_VISUAL_TRUECOLOR:
- + /*
- + * 16-bit True Colour. We encode the RGB value
- + * according to the RGB bitfield information.
- + */
- + if (regno < 16) {
- + u32 *pal = fbi->pseudo_palette;
- +
- + val = _chan_to_field(red, &fbi->var.red);
- + val |= _chan_to_field(green, &fbi->var.green);
- + val |= _chan_to_field(blue, &fbi->var.blue);
- +
- + pal[regno] = val;
- + ret = 0;
- + }
- + break;
- +
- + case FB_VISUAL_STATIC_PSEUDOCOLOR:
- + case FB_VISUAL_PSEUDOCOLOR:
- + break;
- + }
- +
- + return ret;
- +}
- +
- +/*
- + * Function to handle custom ioctls for MXC framebuffer.
- + *
- + * @param inode inode struct
- + *
- + * @param file file struct
- + *
- + * @param cmd Ioctl command to handle
- + *
- + * @param arg User pointer to command arguments
- + *
- + * @param fbi framebuffer information pointer
- + */
- +static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
- +{
- + int retval = 0;
- + int __user *argp = (void __user *)arg;
- + struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
- +
- + switch (cmd) {
- + case MXCFB_SET_GBL_ALPHA:
- + {
- + struct mxcfb_gbl_alpha ga;
- +
- + if (copy_from_user(&ga, (void *)arg, sizeof(ga))) {
- + retval = -EFAULT;
- + break;
- + }
- +
- + if (ipu_disp_set_global_alpha(mxc_fbi->ipu,
- + mxc_fbi->ipu_ch,
- + (bool)ga.enable,
- + ga.alpha)) {
- + retval = -EINVAL;
- + break;
- + }
- +
- + if (ga.enable)
- + mxc_fbi->alpha_chan_en = false;
- +
- + if (ga.enable)
- + dev_dbg(fbi->device,
- + "Set global alpha of %s to %d\n",
- + fbi->fix.id, ga.alpha);
- + break;
- + }
- + case MXCFB_SET_LOC_ALPHA:
- + {
- + struct mxcfb_loc_alpha la;
- + bool bad_pixfmt =
- + ipu_ch_param_bad_alpha_pos(fbi_to_pixfmt(fbi));
- +
- + if (copy_from_user(&la, (void *)arg, sizeof(la))) {
- + retval = -EFAULT;
- + break;
- + }
- +
- + if (la.enable && !la.alpha_in_pixel) {
- + struct fb_info *fbi_tmp;
- + ipu_channel_t ipu_ch;
- +
- + if (bad_pixfmt) {
- + dev_err(fbi->device, "Bad pixel format "
- + "for graphics plane fb\n");
- + retval = -EINVAL;
- + break;
- + }
- +
- + mxc_fbi->alpha_chan_en = true;
- +
- + if (mxc_fbi->ipu_ch == MEM_FG_SYNC)
- + ipu_ch = MEM_BG_SYNC;
- + else if (mxc_fbi->ipu_ch == MEM_BG_SYNC)
- + ipu_ch = MEM_FG_SYNC;
- + else {
- + retval = -EINVAL;
- + break;
- + }
- +
- + fbi_tmp = found_registered_fb(ipu_ch, mxc_fbi->ipu_id);
- + if (fbi_tmp)
- + ((struct mxcfb_info *)(fbi_tmp->par))->alpha_chan_en = false;
- + } else
- + mxc_fbi->alpha_chan_en = false;
- +
- + if (ipu_disp_set_global_alpha(mxc_fbi->ipu,
- + mxc_fbi->ipu_ch,
- + !(bool)la.enable, 0)) {
- + retval = -EINVAL;
- + break;
- + }
- +
- + fbi->var.activate = (fbi->var.activate & ~FB_ACTIVATE_MASK) |
- + FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
- + mxcfb_set_par(fbi);
- +
- + la.alpha_phy_addr0 = mxc_fbi->alpha_phy_addr0;
- + la.alpha_phy_addr1 = mxc_fbi->alpha_phy_addr1;
- + if (copy_to_user((void *)arg, &la, sizeof(la))) {
- + retval = -EFAULT;
- + break;
- + }
- +
- + if (la.enable)
- + dev_dbg(fbi->device,
- + "Enable DP local alpha for %s\n",
- + fbi->fix.id);
- + break;
- + }
- + case MXCFB_SET_LOC_ALP_BUF:
- + {
- + unsigned long base;
- + uint32_t ipu_alp_ch_irq;
- +
- + if (!(((mxc_fbi->ipu_ch == MEM_FG_SYNC) ||
- + (mxc_fbi->ipu_ch == MEM_BG_SYNC)) &&
- + (mxc_fbi->alpha_chan_en))) {
- + dev_err(fbi->device,
- + "Should use background or overlay "
- + "framebuffer to set the alpha buffer "
- + "number\n");
- + return -EINVAL;
- + }
- +
- + if (get_user(base, argp))
- + return -EFAULT;
- +
- + if (base != mxc_fbi->alpha_phy_addr0 &&
- + base != mxc_fbi->alpha_phy_addr1) {
- + dev_err(fbi->device,
- + "Wrong alpha buffer physical address "
- + "%lu\n", base);
- + return -EINVAL;
- + }
- +
- + if (mxc_fbi->ipu_ch == MEM_FG_SYNC)
- + ipu_alp_ch_irq = IPU_IRQ_FG_ALPHA_SYNC_EOF;
- + else
- + ipu_alp_ch_irq = IPU_IRQ_BG_ALPHA_SYNC_EOF;
- +
- + retval = wait_for_completion_timeout(
- + &mxc_fbi->alpha_flip_complete, HZ/2);
- + if (retval == 0) {
- + dev_err(fbi->device, "timeout when waiting for alpha flip irq\n");
- + retval = -ETIMEDOUT;
- + break;
- + }
- +
- + mxc_fbi->cur_ipu_alpha_buf =
- + !mxc_fbi->cur_ipu_alpha_buf;
- + if (ipu_update_channel_buffer(mxc_fbi->ipu, mxc_fbi->ipu_ch,
- + IPU_ALPHA_IN_BUFFER,
- + mxc_fbi->
- + cur_ipu_alpha_buf,
- + base) == 0) {
- + ipu_select_buffer(mxc_fbi->ipu, mxc_fbi->ipu_ch,
- + IPU_ALPHA_IN_BUFFER,
- + mxc_fbi->cur_ipu_alpha_buf);
- + ipu_clear_irq(mxc_fbi->ipu, ipu_alp_ch_irq);
- + ipu_enable_irq(mxc_fbi->ipu, ipu_alp_ch_irq);
- + } else {
- + dev_err(fbi->device,
- + "Error updating %s SDC alpha buf %d "
- + "to address=0x%08lX\n",
- + fbi->fix.id,
- + mxc_fbi->cur_ipu_alpha_buf, base);
- + }
- + break;
- + }
- + case MXCFB_SET_CLR_KEY:
- + {
- + struct mxcfb_color_key key;
- + if (copy_from_user(&key, (void *)arg, sizeof(key))) {
- + retval = -EFAULT;
- + break;
- + }
- + retval = ipu_disp_set_color_key(mxc_fbi->ipu, mxc_fbi->ipu_ch,
- + key.enable,
- + key.color_key);
- + dev_dbg(fbi->device, "Set color key to 0x%08X\n",
- + key.color_key);
- + break;
- + }
- + case MXCFB_SET_GAMMA:
- + {
- + struct mxcfb_gamma gamma;
- + if (copy_from_user(&gamma, (void *)arg, sizeof(gamma))) {
- + retval = -EFAULT;
- + break;
- + }
- + retval = ipu_disp_set_gamma_correction(mxc_fbi->ipu,
- + mxc_fbi->ipu_ch,
- + gamma.enable,
- + gamma.constk,
- + gamma.slopek);
- + break;
- + }
- + case MXCFB_WAIT_FOR_VSYNC:
- + {
- + if (mxc_fbi->ipu_ch == MEM_FG_SYNC) {
- + /* BG should poweron */
- + struct mxcfb_info *bg_mxcfbi = NULL;
- + struct fb_info *fbi_tmp;
- +
- + fbi_tmp = found_registered_fb(MEM_BG_SYNC, mxc_fbi->ipu_id);
- + if (fbi_tmp)
- + bg_mxcfbi = ((struct mxcfb_info *)(fbi_tmp->par));
- +
- + if (!bg_mxcfbi) {
- + retval = -EINVAL;
- + break;
- + }
- + if (bg_mxcfbi->cur_blank != FB_BLANK_UNBLANK) {
- + retval = -EINVAL;
- + break;
- + }
- + }
- + if (mxc_fbi->cur_blank != FB_BLANK_UNBLANK) {
- + retval = -EINVAL;
- + break;
- + }
- +
- + init_completion(&mxc_fbi->vsync_complete);
- + ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_nf_irq);
- + ipu_enable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_nf_irq);
- + retval = wait_for_completion_interruptible_timeout(
- + &mxc_fbi->vsync_complete, 1 * HZ);
- + if (retval == 0) {
- + dev_err(fbi->device,
- + "MXCFB_WAIT_FOR_VSYNC: timeout %d\n",
- + retval);
- + retval = -ETIME;
- + } else if (retval > 0) {
- + retval = 0;
- + }
- + break;
- + }
- + case FBIO_ALLOC:
- + {
- + int size;
- + struct mxcfb_alloc_list *mem;
- +
- + mem = kzalloc(sizeof(*mem), GFP_KERNEL);
- + if (mem == NULL)
- + return -ENOMEM;
- +
- + if (get_user(size, argp))
- + return -EFAULT;
- +
- + mem->size = PAGE_ALIGN(size);
- +
- + mem->cpu_addr = dma_alloc_coherent(fbi->device, size,
- + &mem->phy_addr,
- + GFP_KERNEL);
- + if (mem->cpu_addr == NULL) {
- + kfree(mem);
- + return -ENOMEM;
- + }
- +
- + list_add(&mem->list, &fb_alloc_list);
- +
- + dev_dbg(fbi->device, "allocated %d bytes @ 0x%08X\n",
- + mem->size, mem->phy_addr);
- +
- + if (put_user(mem->phy_addr, argp))
- + return -EFAULT;
- +
- + break;
- + }
- + case FBIO_FREE:
- + {
- + unsigned long offset;
- + struct mxcfb_alloc_list *mem;
- +
- + if (get_user(offset, argp))
- + return -EFAULT;
- +
- + retval = -EINVAL;
- + list_for_each_entry(mem, &fb_alloc_list, list) {
- + if (mem->phy_addr == offset) {
- + list_del(&mem->list);
- + dma_free_coherent(fbi->device,
- + mem->size,
- + mem->cpu_addr,
- + mem->phy_addr);
- + kfree(mem);
- + retval = 0;
- + break;
- + }
- + }
- +
- + break;
- + }
- + case MXCFB_SET_OVERLAY_POS:
- + {
- + struct mxcfb_pos pos;
- + struct fb_info *bg_fbi = NULL;
- + struct mxcfb_info *bg_mxcfbi = NULL;
- +
- + if (mxc_fbi->ipu_ch != MEM_FG_SYNC) {
- + dev_err(fbi->device, "Should use the overlay "
- + "framebuffer to set the position of "
- + "the overlay window\n");
- + retval = -EINVAL;
- + break;
- + }
- +
- + if (copy_from_user(&pos, (void *)arg, sizeof(pos))) {
- + retval = -EFAULT;
- + break;
- + }
- +
- + bg_fbi = found_registered_fb(MEM_BG_SYNC, mxc_fbi->ipu_id);
- + if (bg_fbi)
- + bg_mxcfbi = ((struct mxcfb_info *)(bg_fbi->par));
- +
- + if (bg_fbi == NULL) {
- + dev_err(fbi->device, "Cannot find the "
- + "background framebuffer\n");
- + retval = -ENOENT;
- + break;
- + }
- +
- + /* if fb is unblank, check if the pos fit the display */
- + if (mxc_fbi->cur_blank == FB_BLANK_UNBLANK) {
- + if (fbi->var.xres + pos.x > bg_fbi->var.xres) {
- + if (bg_fbi->var.xres < fbi->var.xres)
- + pos.x = 0;
- + else
- + pos.x = bg_fbi->var.xres - fbi->var.xres;
- + }
- + if (fbi->var.yres + pos.y > bg_fbi->var.yres) {
- + if (bg_fbi->var.yres < fbi->var.yres)
- + pos.y = 0;
- + else
- + pos.y = bg_fbi->var.yres - fbi->var.yres;
- + }
- + }
- +
- + retval = ipu_disp_set_window_pos(mxc_fbi->ipu, mxc_fbi->ipu_ch,
- + pos.x, pos.y);
- +
- + if (copy_to_user((void *)arg, &pos, sizeof(pos))) {
- + retval = -EFAULT;
- + break;
- + }
- + break;
- + }
- + case MXCFB_GET_FB_IPU_CHAN:
- + {
- + struct mxcfb_info *mxc_fbi =
- + (struct mxcfb_info *)fbi->par;
- +
- + if (put_user(mxc_fbi->ipu_ch, argp))
- + return -EFAULT;
- + break;
- + }
- + case MXCFB_GET_DIFMT:
- + {
- + struct mxcfb_info *mxc_fbi =
- + (struct mxcfb_info *)fbi->par;
- +
- + if (put_user(mxc_fbi->ipu_di_pix_fmt, argp))
- + return -EFAULT;
- + break;
- + }
- + case MXCFB_GET_FB_IPU_DI:
- + {
- + struct mxcfb_info *mxc_fbi =
- + (struct mxcfb_info *)fbi->par;
- +
- + if (put_user(mxc_fbi->ipu_di, argp))
- + return -EFAULT;
- + break;
- + }
- + case MXCFB_GET_FB_BLANK:
- + {
- + struct mxcfb_info *mxc_fbi =
- + (struct mxcfb_info *)fbi->par;
- +
- + if (put_user(mxc_fbi->cur_blank, argp))
- + return -EFAULT;
- + break;
- + }
- + case MXCFB_SET_DIFMT:
- + {
- + struct mxcfb_info *mxc_fbi =
- + (struct mxcfb_info *)fbi->par;
- +
- + if (get_user(mxc_fbi->ipu_di_pix_fmt, argp))
- + return -EFAULT;
- +
- + break;
- + }
- + case MXCFB_CSC_UPDATE:
- + {
- + struct mxcfb_csc_matrix csc;
- +
- + if (copy_from_user(&csc, (void *) arg, sizeof(csc)))
- + return -EFAULT;
- +
- + if ((mxc_fbi->ipu_ch != MEM_FG_SYNC) &&
- + (mxc_fbi->ipu_ch != MEM_BG_SYNC) &&
- + (mxc_fbi->ipu_ch != MEM_BG_ASYNC0))
- + return -EFAULT;
- + ipu_set_csc_coefficients(mxc_fbi->ipu, mxc_fbi->ipu_ch,
- + csc.param);
- + }
- + default:
- + retval = -EINVAL;
- + }
- + return retval;
- +}
- +
- +/*
- + * mxcfb_blank():
- + * Blank the display.
- + */
- +static int mxcfb_blank(int blank, struct fb_info *info)
- +{
- + struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)info->par;
- + int ret = 0;
- +
- + dev_dbg(info->device, "blank = %d\n", blank);
- +
- + if (mxc_fbi->cur_blank == blank)
- + return 0;
- +
- + mxc_fbi->next_blank = blank;
- +
- + switch (blank) {
- + case FB_BLANK_POWERDOWN:
- + case FB_BLANK_VSYNC_SUSPEND:
- + case FB_BLANK_HSYNC_SUSPEND:
- + case FB_BLANK_NORMAL:
- + if (mxc_fbi->dispdrv && mxc_fbi->dispdrv->drv->disable)
- + mxc_fbi->dispdrv->drv->disable(mxc_fbi->dispdrv);
- + ipu_disable_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch, true);
- + if (mxc_fbi->ipu_di >= 0)
- + ipu_uninit_sync_panel(mxc_fbi->ipu, mxc_fbi->ipu_di);
- + ipu_uninit_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch);
- + break;
- + case FB_BLANK_UNBLANK:
- + info->var.activate = (info->var.activate & ~FB_ACTIVATE_MASK) |
- + FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
- + ret = mxcfb_set_par(info);
- + break;
- + }
- + if (!ret)
- + mxc_fbi->cur_blank = blank;
- + return ret;
- +}
- +
- +/*
- + * Pan or Wrap the Display
- + *
- + * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
- + *
- + * @param var Variable screen buffer information
- + * @param info Framebuffer information pointer
- + */
- +static int
- +mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
- +{
- + struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)info->par,
- + *mxc_graphic_fbi = NULL;
- + u_int y_bottom;
- + unsigned int fr_xoff, fr_yoff, fr_w, fr_h;
- + unsigned long base, active_alpha_phy_addr = 0;
- + bool loc_alpha_en = false;
- + int fb_stride;
- + int i;
- + int ret;
- +
- + /* no pan display during fb blank */
- + if (mxc_fbi->ipu_ch == MEM_FG_SYNC) {
- + struct mxcfb_info *bg_mxcfbi = NULL;
- + struct fb_info *fbi_tmp;
- +
- + fbi_tmp = found_registered_fb(MEM_BG_SYNC, mxc_fbi->ipu_id);
- + if (fbi_tmp)
- + bg_mxcfbi = ((struct mxcfb_info *)(fbi_tmp->par));
- + if (!bg_mxcfbi)
- + return -EINVAL;
- + if (bg_mxcfbi->cur_blank != FB_BLANK_UNBLANK)
- + return -EINVAL;
- + }
- + if (mxc_fbi->cur_blank != FB_BLANK_UNBLANK)
- + return -EINVAL;
- +
- + y_bottom = var->yoffset;
- +
- + if (y_bottom > info->var.yres_virtual)
- + return -EINVAL;
- +
- + switch (fbi_to_pixfmt(info)) {
- + case IPU_PIX_FMT_YUV420P2:
- + case IPU_PIX_FMT_YVU420P:
- + case IPU_PIX_FMT_NV12:
- + case IPU_PIX_FMT_YUV422P:
- + case IPU_PIX_FMT_YVU422P:
- + case IPU_PIX_FMT_YUV420P:
- + case IPU_PIX_FMT_YUV444P:
- + fb_stride = info->var.xres_virtual;
- + break;
- + default:
- + fb_stride = info->fix.line_length;
- + }
- +
- + base = info->fix.smem_start;
- + fr_xoff = var->xoffset;
- + fr_w = info->var.xres_virtual;
- + if (!(var->vmode & FB_VMODE_YWRAP)) {
- + dev_dbg(info->device, "Y wrap disabled\n");
- + fr_yoff = var->yoffset % info->var.yres;
- + fr_h = info->var.yres;
- + base += info->fix.line_length * info->var.yres *
- + (var->yoffset / info->var.yres);
- + } else {
- + dev_dbg(info->device, "Y wrap enabled\n");
- + fr_yoff = var->yoffset;
- + fr_h = info->var.yres_virtual;
- + }
- + base += fr_yoff * fb_stride + fr_xoff;
- +
- + /* Check if DP local alpha is enabled and find the graphic fb */
- + if (mxc_fbi->ipu_ch == MEM_BG_SYNC || mxc_fbi->ipu_ch == MEM_FG_SYNC) {
- + for (i = 0; i < num_registered_fb; i++) {
- + char bg_id[] = "DISP3 BG";
- + char fg_id[] = "DISP3 FG";
- + char *idstr = registered_fb[i]->fix.id;
- + bg_id[4] += mxc_fbi->ipu_id;
- + fg_id[4] += mxc_fbi->ipu_id;
- + if ((strcmp(idstr, bg_id) == 0 ||
- + strcmp(idstr, fg_id) == 0) &&
- + ((struct mxcfb_info *)
- + (registered_fb[i]->par))->alpha_chan_en) {
- + loc_alpha_en = true;
- + mxc_graphic_fbi = (struct mxcfb_info *)
- + (registered_fb[i]->par);
- + active_alpha_phy_addr =
- + mxc_fbi->cur_ipu_alpha_buf ?
- + mxc_graphic_fbi->alpha_phy_addr1 :
- + mxc_graphic_fbi->alpha_phy_addr0;
- + dev_dbg(info->device, "Updating SDC alpha "
- + "buf %d address=0x%08lX\n",
- + !mxc_fbi->cur_ipu_alpha_buf,
- + active_alpha_phy_addr);
- + break;
- + }
- + }
- + }
- +
- + ret = wait_for_completion_timeout(&mxc_fbi->flip_complete, HZ/2);
- + if (ret == 0) {
- + dev_err(info->device, "timeout when waiting for flip irq\n");
- + return -ETIMEDOUT;
- + }
- +
- + ++mxc_fbi->cur_ipu_buf;
- + mxc_fbi->cur_ipu_buf %= 3;
- + mxc_fbi->cur_ipu_alpha_buf = !mxc_fbi->cur_ipu_alpha_buf;
- +
- + dev_dbg(info->device, "Updating SDC %s buf %d address=0x%08lX\n",
- + info->fix.id, mxc_fbi->cur_ipu_buf, base);
- +
- + if (ipu_update_channel_buffer(mxc_fbi->ipu, mxc_fbi->ipu_ch, IPU_INPUT_BUFFER,
- + mxc_fbi->cur_ipu_buf, base) == 0) {
- + /* Update the DP local alpha buffer only for graphic plane */
- + if (loc_alpha_en && mxc_graphic_fbi == mxc_fbi &&
- + ipu_update_channel_buffer(mxc_graphic_fbi->ipu, mxc_graphic_fbi->ipu_ch,
- + IPU_ALPHA_IN_BUFFER,
- + mxc_fbi->cur_ipu_alpha_buf,
- + active_alpha_phy_addr) == 0) {
- + ipu_select_buffer(mxc_graphic_fbi->ipu, mxc_graphic_fbi->ipu_ch,
- + IPU_ALPHA_IN_BUFFER,
- + mxc_fbi->cur_ipu_alpha_buf);
- + }
- +
- + /* update u/v offset */
- + ipu_update_channel_offset(mxc_fbi->ipu, mxc_fbi->ipu_ch,
- + IPU_INPUT_BUFFER,
- + fbi_to_pixfmt(info),
- + fr_w,
- + fr_h,
- + fr_w,
- + 0, 0,
- + fr_yoff,
- + fr_xoff);
- +
- + ipu_select_buffer(mxc_fbi->ipu, mxc_fbi->ipu_ch, IPU_INPUT_BUFFER,
- + mxc_fbi->cur_ipu_buf);
- + ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
- + ipu_enable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
- + } else {
- + dev_err(info->device,
- + "Error updating SDC buf %d to address=0x%08lX, "
- + "current buf %d, buf0 ready %d, buf1 ready %d, "
- + "buf2 ready %d\n", mxc_fbi->cur_ipu_buf, base,
- + ipu_get_cur_buffer_idx(mxc_fbi->ipu, mxc_fbi->ipu_ch,
- + IPU_INPUT_BUFFER),
- + ipu_check_buffer_ready(mxc_fbi->ipu, mxc_fbi->ipu_ch,
- + IPU_INPUT_BUFFER, 0),
- + ipu_check_buffer_ready(mxc_fbi->ipu, mxc_fbi->ipu_ch,
- + IPU_INPUT_BUFFER, 1),
- + ipu_check_buffer_ready(mxc_fbi->ipu, mxc_fbi->ipu_ch,
- + IPU_INPUT_BUFFER, 2));
- + ++mxc_fbi->cur_ipu_buf;
- + mxc_fbi->cur_ipu_buf %= 3;
- + ++mxc_fbi->cur_ipu_buf;
- + mxc_fbi->cur_ipu_buf %= 3;
- + mxc_fbi->cur_ipu_alpha_buf = !mxc_fbi->cur_ipu_alpha_buf;
- + ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
- + ipu_enable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
- + return -EBUSY;
- + }
- +
- + dev_dbg(info->device, "Update complete\n");
- +
- + info->var.yoffset = var->yoffset;
- +
- + return 0;
- +}
- +
- +/*
- + * Function to handle custom mmap for MXC framebuffer.
- + *
- + * @param fbi framebuffer information pointer
- + *
- + * @param vma Pointer to vm_area_struct
- + */
- +static int mxcfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
- +{
- + bool found = false;
- + u32 len;
- + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
- + struct mxcfb_alloc_list *mem;
- + struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
- +
- + if (offset < fbi->fix.smem_len) {
- + /* mapping framebuffer memory */
- + len = fbi->fix.smem_len - offset;
- + vma->vm_pgoff = (fbi->fix.smem_start + offset) >> PAGE_SHIFT;
- + } else if ((vma->vm_pgoff ==
- + (mxc_fbi->alpha_phy_addr0 >> PAGE_SHIFT)) ||
- + (vma->vm_pgoff ==
- + (mxc_fbi->alpha_phy_addr1 >> PAGE_SHIFT))) {
- + len = mxc_fbi->alpha_mem_len;
- + } else {
- + list_for_each_entry(mem, &fb_alloc_list, list) {
- + if (offset == mem->phy_addr) {
- + found = true;
- + len = mem->size;
- + break;
- + }
- + }
- + if (!found)
- + return -EINVAL;
- + }
- +
- + len = PAGE_ALIGN(len);
- + if (vma->vm_end - vma->vm_start > len)
- + return -EINVAL;
- +
- + /* make buffers bufferable */
- + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- +
- + vma->vm_flags |= VM_IO;
- +
- + if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- + vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
- + dev_dbg(fbi->device, "mmap remap_pfn_range failed\n");
- + return -ENOBUFS;
- + }
- +
- + return 0;
- +}
- +
- +/*!
- + * This structure contains the pointers to the control functions that are
- + * invoked by the core framebuffer driver to perform operations like
- + * blitting, rectangle filling, copy regions and cursor definition.
- + */
- +static struct fb_ops mxcfb_ops = {
- + .owner = THIS_MODULE,
- + .fb_set_par = mxcfb_set_par,
- + .fb_check_var = mxcfb_check_var,
- + .fb_setcolreg = mxcfb_setcolreg,
- + .fb_pan_display = mxcfb_pan_display,
- + .fb_ioctl = mxcfb_ioctl,
- + .fb_mmap = mxcfb_mmap,
- + .fb_fillrect = cfb_fillrect,
- + .fb_copyarea = cfb_copyarea,
- + .fb_imageblit = cfb_imageblit,
- + .fb_blank = mxcfb_blank,
- +};
- +
- +static irqreturn_t mxcfb_irq_handler(int irq, void *dev_id)
- +{
- + struct fb_info *fbi = dev_id;
- + struct mxcfb_info *mxc_fbi = fbi->par;
- +
- + complete(&mxc_fbi->flip_complete);
- + return IRQ_HANDLED;
- +}
- +
- +static irqreturn_t mxcfb_nf_irq_handler(int irq, void *dev_id)
- +{
- + struct fb_info *fbi = dev_id;
- + struct mxcfb_info *mxc_fbi = fbi->par;
- +
- + complete(&mxc_fbi->vsync_complete);
- + return IRQ_HANDLED;
- +}
- +
- +static irqreturn_t mxcfb_alpha_irq_handler(int irq, void *dev_id)
- +{
- + struct fb_info *fbi = dev_id;
- + struct mxcfb_info *mxc_fbi = fbi->par;
- +
- + complete(&mxc_fbi->alpha_flip_complete);
- + return IRQ_HANDLED;
- +}
- +
- +/*
- + * Suspends the framebuffer and blanks the screen. Power management support
- + */
- +static int mxcfb_suspend(struct platform_device *pdev, pm_message_t state)
- +{
- + struct fb_info *fbi = platform_get_drvdata(pdev);
- + struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
- + int saved_blank;
- +#ifdef CONFIG_FB_MXC_LOW_PWR_DISPLAY
- + void *fbmem;
- +#endif
- +
- + if (mxc_fbi->ovfbi) {
- + struct mxcfb_info *mxc_fbi_fg =
- + (struct mxcfb_info *)mxc_fbi->ovfbi->par;
- +
- + console_lock();
- + fb_set_suspend(mxc_fbi->ovfbi, 1);
- + saved_blank = mxc_fbi_fg->cur_blank;
- + mxcfb_blank(FB_BLANK_POWERDOWN, mxc_fbi->ovfbi);
- + mxc_fbi_fg->next_blank = saved_blank;
- + console_unlock();
- + }
- +
- + console_lock();
- + fb_set_suspend(fbi, 1);
- + saved_blank = mxc_fbi->cur_blank;
- + mxcfb_blank(FB_BLANK_POWERDOWN, fbi);
- + mxc_fbi->next_blank = saved_blank;
- + console_unlock();
- +
- + return 0;
- +}
- +
- +/*
- + * Resumes the framebuffer and unblanks the screen. Power management support
- + */
- +static int mxcfb_resume(struct platform_device *pdev)
- +{
- + struct fb_info *fbi = platform_get_drvdata(pdev);
- + struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
- +
- + console_lock();
- + mxcfb_blank(mxc_fbi->next_blank, fbi);
- + fb_set_suspend(fbi, 0);
- + console_unlock();
- +
- + if (mxc_fbi->ovfbi) {
- + struct mxcfb_info *mxc_fbi_fg =
- + (struct mxcfb_info *)mxc_fbi->ovfbi->par;
- + console_lock();
- + mxcfb_blank(mxc_fbi_fg->next_blank, mxc_fbi->ovfbi);
- + fb_set_suspend(mxc_fbi->ovfbi, 0);
- + console_unlock();
- + }
- +
- + return 0;
- +}
- +
- +/*
- + * Main framebuffer functions
- + */
- +
- +/*!
- + * Allocates the DRAM memory for the frame buffer. This buffer is remapped
- + * into a non-cached, non-buffered, memory region to allow palette and pixel
- + * writes to occur without flushing the cache. Once this area is remapped,
- + * all virtual memory access to the video memory should occur at the new region.
- + *
- + * @param fbi framebuffer information pointer
- + *
- + * @return Error code indicating success or failure
- + */
- +static int mxcfb_map_video_memory(struct fb_info *fbi)
- +{
- + if (fbi->fix.smem_len < fbi->var.yres_virtual * fbi->fix.line_length)
- + fbi->fix.smem_len = fbi->var.yres_virtual *
- + fbi->fix.line_length;
- +
- + fbi->screen_base = dma_alloc_writecombine(fbi->device,
- + fbi->fix.smem_len,
- + (dma_addr_t *)&fbi->fix.smem_start,
- + GFP_DMA | GFP_KERNEL);
- + if (fbi->screen_base == 0) {
- + dev_err(fbi->device, "Unable to allocate framebuffer memory\n");
- + fbi->fix.smem_len = 0;
- + fbi->fix.smem_start = 0;
- + return -EBUSY;
- + }
- +
- + dev_dbg(fbi->device, "allocated fb @ paddr=0x%08X, size=%d.\n",
- + (uint32_t) fbi->fix.smem_start, fbi->fix.smem_len);
- +
- + fbi->screen_size = fbi->fix.smem_len;
- +
- + /* Clear the screen */
- + memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
- +
- + return 0;
- +}
- +
- +/*!
- + * De-allocates the DRAM memory for the frame buffer.
- + *
- + * @param fbi framebuffer information pointer
- + *
- + * @return Error code indicating success or failure
- + */
- +static int mxcfb_unmap_video_memory(struct fb_info *fbi)
- +{
- + dma_free_writecombine(fbi->device, fbi->fix.smem_len,
- + fbi->screen_base, fbi->fix.smem_start);
- + fbi->screen_base = 0;
- + fbi->fix.smem_start = 0;
- + fbi->fix.smem_len = 0;
- + return 0;
- +}
- +
- +/*!
- + * Initializes the framebuffer information pointer. After allocating
- + * sufficient memory for the framebuffer structure, the fields are
- + * filled with custom information passed in from the configurable
- + * structures. This includes information such as bits per pixel,
- + * color maps, screen width/height and RGBA offsets.
- + *
- + * @return Framebuffer structure initialized with our information
- + */
- +static struct fb_info *mxcfb_init_fbinfo(struct device *dev, struct fb_ops *ops)
- +{
- + struct fb_info *fbi;
- + struct mxcfb_info *mxcfbi;
- +
- + /*
- + * Allocate sufficient memory for the fb structure
- + */
- + fbi = framebuffer_alloc(sizeof(struct mxcfb_info), dev);
- + if (!fbi)
- + return NULL;
- +
- + mxcfbi = (struct mxcfb_info *)fbi->par;
- +
- + fbi->var.activate = FB_ACTIVATE_NOW;
- +
- + fbi->fbops = ops;
- + fbi->flags = FBINFO_FLAG_DEFAULT;
- + fbi->pseudo_palette = mxcfbi->pseudo_palette;
- +
- + /*
- + * Allocate colormap
- + */
- + fb_alloc_cmap(&fbi->cmap, 16, 0);
- +
- + return fbi;
- +}
- +
- +static ssize_t show_disp_chan(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + struct fb_info *info = dev_get_drvdata(dev);
- + struct mxcfb_info *mxcfbi = (struct mxcfb_info *)info->par;
- +
- + if (mxcfbi->ipu_ch == MEM_BG_SYNC)
- + return sprintf(buf, "2-layer-fb-bg\n");
- + else if (mxcfbi->ipu_ch == MEM_FG_SYNC)
- + return sprintf(buf, "2-layer-fb-fg\n");
- + else if (mxcfbi->ipu_ch == MEM_DC_SYNC)
- + return sprintf(buf, "1-layer-fb\n");
- + else
- + return sprintf(buf, "err: no display chan\n");
- +}
- +
- +static ssize_t swap_disp_chan(struct device *dev,
- + struct device_attribute *attr,
- + const char *buf, size_t count)
- +{
- + struct fb_info *info = dev_get_drvdata(dev);
- + struct mxcfb_info *mxcfbi = (struct mxcfb_info *)info->par;
- + struct mxcfb_info *fg_mxcfbi = NULL;
- +
- + console_lock();
- + /* swap only happen between DP-BG and DC, while DP-FG disable */
- + if (((mxcfbi->ipu_ch == MEM_BG_SYNC) &&
- + (strstr(buf, "1-layer-fb") != NULL)) ||
- + ((mxcfbi->ipu_ch == MEM_DC_SYNC) &&
- + (strstr(buf, "2-layer-fb-bg") != NULL))) {
- + struct fb_info *fbi_fg;
- +
- + fbi_fg = found_registered_fb(MEM_FG_SYNC, mxcfbi->ipu_id);
- + if (fbi_fg)
- + fg_mxcfbi = (struct mxcfb_info *)fbi_fg->par;
- +
- + if (!fg_mxcfbi ||
- + fg_mxcfbi->cur_blank == FB_BLANK_UNBLANK) {
- + dev_err(dev,
- + "Can not switch while fb2(fb-fg) is on.\n");
- + console_unlock();
- + return count;
- + }
- +
- + if (swap_channels(info) < 0)
- + dev_err(dev, "Swap display channel failed.\n");
- + }
- +
- + console_unlock();
- + return count;
- +}
- +static DEVICE_ATTR(fsl_disp_property, S_IWUSR | S_IRUGO,
- + show_disp_chan, swap_disp_chan);
- +
- +static ssize_t show_disp_dev(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + struct fb_info *info = dev_get_drvdata(dev);
- + struct mxcfb_info *mxcfbi = (struct mxcfb_info *)info->par;
- +
- + if (mxcfbi->ipu_ch == MEM_FG_SYNC)
- + return sprintf(buf, "overlay\n");
- + else
- + return sprintf(buf, "%s\n", mxcfbi->dispdrv->drv->name);
- +}
- +static DEVICE_ATTR(fsl_disp_dev_property, S_IRUGO, show_disp_dev, NULL);
- +
- +static int mxcfb_dispdrv_init(struct platform_device *pdev,
- + struct fb_info *fbi)
- +{
- + struct ipuv3_fb_platform_data *plat_data = pdev->dev.platform_data;
- + struct mxcfb_info *mxcfbi = (struct mxcfb_info *)fbi->par;
- + struct mxc_dispdrv_setting setting;
- + char disp_dev[32], *default_dev = "lcd";
- + int ret = 0;
- +
- + setting.if_fmt = plat_data->interface_pix_fmt;
- + setting.dft_mode_str = plat_data->mode_str;
- + setting.default_bpp = plat_data->default_bpp;
- + if (!setting.default_bpp)
- + setting.default_bpp = 16;
- + setting.fbi = fbi;
- + if (!strlen(plat_data->disp_dev)) {
- + memcpy(disp_dev, default_dev, strlen(default_dev));
- + disp_dev[strlen(default_dev)] = '\0';
- + } else {
- + memcpy(disp_dev, plat_data->disp_dev,
- + strlen(plat_data->disp_dev));
- + disp_dev[strlen(plat_data->disp_dev)] = '\0';
- + }
- +
- + dev_info(&pdev->dev, "register mxc display driver %s\n", disp_dev);
- +
- + mxcfbi->dispdrv = mxc_dispdrv_gethandle(disp_dev, &setting);
- + if (IS_ERR(mxcfbi->dispdrv)) {
- + ret = PTR_ERR(mxcfbi->dispdrv);
- + dev_err(&pdev->dev, "NO mxc display driver found!\n");
- + return ret;
- + } else {
- + /* fix-up */
- + mxcfbi->ipu_di_pix_fmt = setting.if_fmt;
- + mxcfbi->default_bpp = setting.default_bpp;
- +
- + /* setting */
- + mxcfbi->ipu_id = setting.dev_id;
- + mxcfbi->ipu_di = setting.disp_id;
- + dev_dbg(&pdev->dev, "di_pixfmt:0x%x, bpp:0x%x, di:%d, ipu:%d\n",
- + setting.if_fmt, setting.default_bpp,
- + setting.disp_id, setting.dev_id);
- + }
- +
- + return ret;
- +}
- +
- +/*
- + * Parse user specified options (`video=trident:')
- + * example:
- + * video=mxcfb0:dev=lcd,800x480M-16@55,if=RGB565,bpp=16,noaccel
- + * video=mxcfb0:dev=lcd,800x480M-16@55,if=RGB565,fbpix=RGB565
- + */
- +static int mxcfb_option_setup(struct platform_device *pdev, struct fb_info *fbi)
- +{
- + struct ipuv3_fb_platform_data *pdata = pdev->dev.platform_data;
- + char *options, *opt, *fb_mode_str = NULL;
- + char name[] = "mxcfb0";
- + uint32_t fb_pix_fmt = 0;
- +
- + name[5] += pdev->id;
- + if (fb_get_options(name, &options)) {
- + dev_err(&pdev->dev, "Can't get fb option for %s!\n", name);
- + return -ENODEV;
- + }
- +
- + if (!options || !*options)
- + return 0;
- +
- + while ((opt = strsep(&options, ",")) != NULL) {
- + if (!*opt)
- + continue;
- +
- + if (!strncmp(opt, "dev=", 4)) {
- + memcpy(pdata->disp_dev, opt + 4, strlen(opt) - 4);
- + pdata->disp_dev[strlen(opt) - 4] = '\0';
- + } else if (!strncmp(opt, "if=", 3)) {
- + if (!strncmp(opt+3, "RGB24", 5))
- + pdata->interface_pix_fmt = IPU_PIX_FMT_RGB24;
- + else if (!strncmp(opt+3, "BGR24", 5))
- + pdata->interface_pix_fmt = IPU_PIX_FMT_BGR24;
- + else if (!strncmp(opt+3, "GBR24", 5))
- + pdata->interface_pix_fmt = IPU_PIX_FMT_GBR24;
- + else if (!strncmp(opt+3, "RGB565", 6))
- + pdata->interface_pix_fmt = IPU_PIX_FMT_RGB565;
- + else if (!strncmp(opt+3, "RGB666", 6))
- + pdata->interface_pix_fmt = IPU_PIX_FMT_RGB666;
- + else if (!strncmp(opt+3, "YUV444", 6))
- + pdata->interface_pix_fmt = IPU_PIX_FMT_YUV444;
- + else if (!strncmp(opt+3, "LVDS666", 7))
- + pdata->interface_pix_fmt = IPU_PIX_FMT_LVDS666;
- + else if (!strncmp(opt+3, "YUYV16", 6))
- + pdata->interface_pix_fmt = IPU_PIX_FMT_YUYV;
- + else if (!strncmp(opt+3, "UYVY16", 6))
- + pdata->interface_pix_fmt = IPU_PIX_FMT_UYVY;
- + else if (!strncmp(opt+3, "YVYU16", 6))
- + pdata->interface_pix_fmt = IPU_PIX_FMT_YVYU;
- + else if (!strncmp(opt+3, "VYUY16", 6))
- + pdata->interface_pix_fmt = IPU_PIX_FMT_VYUY;
- + } else if (!strncmp(opt, "fbpix=", 6)) {
- + if (!strncmp(opt+6, "RGB24", 5))
- + fb_pix_fmt = IPU_PIX_FMT_RGB24;
- + else if (!strncmp(opt+6, "BGR24", 5))
- + fb_pix_fmt = IPU_PIX_FMT_BGR24;
- + else if (!strncmp(opt+6, "RGB32", 5))
- + fb_pix_fmt = IPU_PIX_FMT_RGB32;
- + else if (!strncmp(opt+6, "BGR32", 5))
- + fb_pix_fmt = IPU_PIX_FMT_BGR32;
- + else if (!strncmp(opt+6, "ABGR32", 6))
- + fb_pix_fmt = IPU_PIX_FMT_ABGR32;
- + else if (!strncmp(opt+6, "RGB565", 6))
- + fb_pix_fmt = IPU_PIX_FMT_RGB565;
- +
- + if (fb_pix_fmt) {
- + pixfmt_to_var(fb_pix_fmt, &fbi->var);
- + pdata->default_bpp =
- + fbi->var.bits_per_pixel;
- + }
- + } else if (!strncmp(opt, "int_clk", 7)) {
- + pdata->int_clk = true;
- + continue;
- + } else if (!strncmp(opt, "bpp=", 4)) {
- + /* bpp setting cannot overwirte fbpix setting */
- + if (fb_pix_fmt)
- + continue;
- +
- + pdata->default_bpp =
- + simple_strtoul(opt + 4, NULL, 0);
- +
- + fb_pix_fmt = bpp_to_pixfmt(pdata->default_bpp);
- + if (fb_pix_fmt)
- + pixfmt_to_var(fb_pix_fmt, &fbi->var);
- + } else
- + fb_mode_str = opt;
- + }
- +
- + if (fb_mode_str)
- + pdata->mode_str = fb_mode_str;
- +
- + return 0;
- +}
- +
- +static int mxcfb_register(struct fb_info *fbi)
- +{
- + struct mxcfb_info *mxcfbi = (struct mxcfb_info *)fbi->par;
- + struct fb_videomode m;
- + int ret = 0;
- + char bg0_id[] = "DISP3 BG";
- + char bg1_id[] = "DISP3 BG - DI1";
- + char fg_id[] = "DISP3 FG";
- +
- + if (mxcfbi->ipu_di == 0) {
- + bg0_id[4] += mxcfbi->ipu_id;
- + strcpy(fbi->fix.id, bg0_id);
- + } else if (mxcfbi->ipu_di == 1) {
- + bg1_id[4] += mxcfbi->ipu_id;
- + strcpy(fbi->fix.id, bg1_id);
- + } else { /* Overlay */
- + fg_id[4] += mxcfbi->ipu_id;
- + strcpy(fbi->fix.id, fg_id);
- + }
- +
- + mxcfb_check_var(&fbi->var, fbi);
- +
- + mxcfb_set_fix(fbi);
- +
- + /* Added first mode to fbi modelist. */
- + if (!fbi->modelist.next || !fbi->modelist.prev)
- + INIT_LIST_HEAD(&fbi->modelist);
- + fb_var_to_videomode(&m, &fbi->var);
- + fb_add_videomode(&m, &fbi->modelist);
- +
- + if (ipu_request_irq(mxcfbi->ipu, mxcfbi->ipu_ch_irq,
- + mxcfb_irq_handler, IPU_IRQF_ONESHOT, MXCFB_NAME, fbi) != 0) {
- + dev_err(fbi->device, "Error registering EOF irq handler.\n");
- + ret = -EBUSY;
- + goto err0;
- + }
- + ipu_disable_irq(mxcfbi->ipu, mxcfbi->ipu_ch_irq);
- + if (ipu_request_irq(mxcfbi->ipu, mxcfbi->ipu_ch_nf_irq,
- + mxcfb_nf_irq_handler, IPU_IRQF_ONESHOT, MXCFB_NAME, fbi) != 0) {
- + dev_err(fbi->device, "Error registering NFACK irq handler.\n");
- + ret = -EBUSY;
- + goto err1;
- + }
- + ipu_disable_irq(mxcfbi->ipu, mxcfbi->ipu_ch_nf_irq);
- +
- + if (mxcfbi->ipu_alp_ch_irq != -1)
- + if (ipu_request_irq(mxcfbi->ipu, mxcfbi->ipu_alp_ch_irq,
- + mxcfb_alpha_irq_handler, IPU_IRQF_ONESHOT,
- + MXCFB_NAME, fbi) != 0) {
- + dev_err(fbi->device, "Error registering alpha irq "
- + "handler.\n");
- + ret = -EBUSY;
- + goto err2;
- + }
- +
- + if (!mxcfbi->late_init) {
- + fbi->var.activate |= FB_ACTIVATE_FORCE;
- + console_lock();
- + fbi->flags |= FBINFO_MISC_USEREVENT;
- + ret = fb_set_var(fbi, &fbi->var);
- + fbi->flags &= ~FBINFO_MISC_USEREVENT;
- + console_unlock();
- + if (ret < 0) {
- + dev_err(fbi->device, "Error fb_set_var ret:%d\n", ret);
- + goto err3;
- + }
- +
- + if (mxcfbi->next_blank == FB_BLANK_UNBLANK) {
- + console_lock();
- + ret = fb_blank(fbi, FB_BLANK_UNBLANK);
- + console_unlock();
- + if (ret < 0) {
- + dev_err(fbi->device,
- + "Error fb_blank ret:%d\n", ret);
- + goto err4;
- + }
- + }
- + } else {
- + /*
- + * Setup the channel again though bootloader
- + * has done this, then set_par() can stop the
- + * channel neatly and re-initialize it .
- + */
- + if (mxcfbi->next_blank == FB_BLANK_UNBLANK) {
- + console_lock();
- + _setup_disp_channel1(fbi);
- + ipu_enable_channel(mxcfbi->ipu, mxcfbi->ipu_ch);
- + console_unlock();
- + }
- + }
- +
- +
- + ret = register_framebuffer(fbi);
- + if (ret < 0)
- + goto err5;
- +
- + return ret;
- +err5:
- + if (mxcfbi->next_blank == FB_BLANK_UNBLANK) {
- + console_lock();
- + if (!mxcfbi->late_init)
- + fb_blank(fbi, FB_BLANK_POWERDOWN);
- + else {
- + ipu_disable_channel(mxcfbi->ipu, mxcfbi->ipu_ch,
- + true);
- + ipu_uninit_channel(mxcfbi->ipu, mxcfbi->ipu_ch);
- + }
- + console_unlock();
- + }
- +err4:
- +err3:
- + if (mxcfbi->ipu_alp_ch_irq != -1)
- + ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_alp_ch_irq, fbi);
- +err2:
- + ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_ch_nf_irq, fbi);
- +err1:
- + ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_ch_irq, fbi);
- +err0:
- + return ret;
- +}
- +
- +static void mxcfb_unregister(struct fb_info *fbi)
- +{
- + struct mxcfb_info *mxcfbi = (struct mxcfb_info *)fbi->par;
- +
- + if (mxcfbi->ipu_alp_ch_irq != -1)
- + ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_alp_ch_irq, fbi);
- + if (mxcfbi->ipu_ch_irq)
- + ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_ch_irq, fbi);
- + if (mxcfbi->ipu_ch_nf_irq)
- + ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_ch_nf_irq, fbi);
- +
- + unregister_framebuffer(fbi);
- +}
- +
- +static int mxcfb_setup_overlay(struct platform_device *pdev,
- + struct fb_info *fbi_bg, struct resource *res)
- +{
- + struct fb_info *ovfbi;
- + struct mxcfb_info *mxcfbi_bg = (struct mxcfb_info *)fbi_bg->par;
- + struct mxcfb_info *mxcfbi_fg;
- + int ret = 0;
- +
- + ovfbi = mxcfb_init_fbinfo(&pdev->dev, &mxcfb_ops);
- + if (!ovfbi) {
- + ret = -ENOMEM;
- + goto init_ovfbinfo_failed;
- + }
- + mxcfbi_fg = (struct mxcfb_info *)ovfbi->par;
- +
- + mxcfbi_fg->ipu = ipu_get_soc(mxcfbi_bg->ipu_id);
- + if (IS_ERR(mxcfbi_fg->ipu)) {
- + ret = -ENODEV;
- + goto get_ipu_failed;
- + }
- + mxcfbi_fg->ipu_id = mxcfbi_bg->ipu_id;
- + mxcfbi_fg->ipu_ch_irq = IPU_IRQ_FG_SYNC_EOF;
- + mxcfbi_fg->ipu_ch_nf_irq = IPU_IRQ_FG_SYNC_NFACK;
- + mxcfbi_fg->ipu_alp_ch_irq = IPU_IRQ_FG_ALPHA_SYNC_EOF;
- + mxcfbi_fg->ipu_ch = MEM_FG_SYNC;
- + mxcfbi_fg->ipu_di = -1;
- + mxcfbi_fg->ipu_di_pix_fmt = mxcfbi_bg->ipu_di_pix_fmt;
- + mxcfbi_fg->overlay = true;
- + mxcfbi_fg->cur_blank = mxcfbi_fg->next_blank = FB_BLANK_POWERDOWN;
- +
- + /* Need dummy values until real panel is configured */
- + ovfbi->var.xres = 240;
- + ovfbi->var.yres = 320;
- +
- + if (res && res->start && res->end) {
- + ovfbi->fix.smem_len = res->end - res->start + 1;
- + ovfbi->fix.smem_start = res->start;
- + ovfbi->screen_base = ioremap(
- + ovfbi->fix.smem_start,
- + ovfbi->fix.smem_len);
- + }
- +
- + ret = mxcfb_register(ovfbi);
- + if (ret < 0)
- + goto register_ov_failed;
- +
- + mxcfbi_bg->ovfbi = ovfbi;
- +
- + return ret;
- +
- +register_ov_failed:
- +get_ipu_failed:
- + fb_dealloc_cmap(&ovfbi->cmap);
- + framebuffer_release(ovfbi);
- +init_ovfbinfo_failed:
- + return ret;
- +}
- +
- +static void mxcfb_unsetup_overlay(struct fb_info *fbi_bg)
- +{
- + struct mxcfb_info *mxcfbi_bg = (struct mxcfb_info *)fbi_bg->par;
- + struct fb_info *ovfbi = mxcfbi_bg->ovfbi;
- +
- + mxcfb_unregister(ovfbi);
- +
- + if (&ovfbi->cmap)
- + fb_dealloc_cmap(&ovfbi->cmap);
- + framebuffer_release(ovfbi);
- +}
- +
- +static bool ipu_usage[2][2];
- +static int ipu_test_set_usage(int ipu, int di)
- +{
- + if (ipu_usage[ipu][di])
- + return -EBUSY;
- + else
- + ipu_usage[ipu][di] = true;
- + return 0;
- +}
- +
- +static void ipu_clear_usage(int ipu, int di)
- +{
- + ipu_usage[ipu][di] = false;
- +}
- +
- +static int mxcfb_get_of_property(struct platform_device *pdev,
- + struct ipuv3_fb_platform_data *plat_data)
- +{
- + struct device_node *np = pdev->dev.of_node;
- + const char *disp_dev;
- + const char *mode_str;
- + const char *pixfmt;
- + int err;
- + int len;
- + u32 bpp, int_clk;
- + u32 late_init;
- +
- + err = of_property_read_string(np, "disp_dev", &disp_dev);
- + if (err < 0) {
- + dev_dbg(&pdev->dev, "get of property disp_dev fail\n");
- + return err;
- + }
- + err = of_property_read_string(np, "mode_str", &mode_str);
- + if (err < 0) {
- + dev_dbg(&pdev->dev, "get of property mode_str fail\n");
- + return err;
- + }
- + err = of_property_read_string(np, "interface_pix_fmt", &pixfmt);
- + if (err) {
- + dev_dbg(&pdev->dev, "get of property pix fmt fail\n");
- + return err;
- + }
- + err = of_property_read_u32(np, "default_bpp", &bpp);
- + if (err) {
- + dev_dbg(&pdev->dev, "get of property bpp fail\n");
- + return err;
- + }
- + err = of_property_read_u32(np, "int_clk", &int_clk);
- + if (err) {
- + dev_dbg(&pdev->dev, "get of property int_clk fail\n");
- + return err;
- + }
- + err = of_property_read_u32(np, "late_init", &late_init);
- + if (err) {
- + dev_dbg(&pdev->dev, "get of property late_init fail\n");
- + return err;
- + }
- +
- + if (!strncmp(pixfmt, "RGB24", 5))
- + plat_data->interface_pix_fmt = IPU_PIX_FMT_RGB24;
- + else if (!strncmp(pixfmt, "BGR24", 5))
- + plat_data->interface_pix_fmt = IPU_PIX_FMT_BGR24;
- + else if (!strncmp(pixfmt, "GBR24", 5))
- + plat_data->interface_pix_fmt = IPU_PIX_FMT_GBR24;
- + else if (!strncmp(pixfmt, "RGB565", 6))
- + plat_data->interface_pix_fmt = IPU_PIX_FMT_RGB565;
- + else if (!strncmp(pixfmt, "RGB666", 6))
- + plat_data->interface_pix_fmt = IPU_PIX_FMT_RGB666;
- + else if (!strncmp(pixfmt, "YUV444", 6))
- + plat_data->interface_pix_fmt = IPU_PIX_FMT_YUV444;
- + else if (!strncmp(pixfmt, "LVDS666", 7))
- + plat_data->interface_pix_fmt = IPU_PIX_FMT_LVDS666;
- + else if (!strncmp(pixfmt, "YUYV16", 6))
- + plat_data->interface_pix_fmt = IPU_PIX_FMT_YUYV;
- + else if (!strncmp(pixfmt, "UYVY16", 6))
- + plat_data->interface_pix_fmt = IPU_PIX_FMT_UYVY;
- + else if (!strncmp(pixfmt, "YVYU16", 6))
- + plat_data->interface_pix_fmt = IPU_PIX_FMT_YVYU;
- + else if (!strncmp(pixfmt, "VYUY16", 6))
- + plat_data->interface_pix_fmt = IPU_PIX_FMT_VYUY;
- + else {
- + dev_err(&pdev->dev, "err interface_pix_fmt!\n");
- + return -ENOENT;
- + }
- +
- + len = min(sizeof(plat_data->disp_dev) - 1, strlen(disp_dev));
- + memcpy(plat_data->disp_dev, disp_dev, len);
- + plat_data->disp_dev[len] = '\0';
- + plat_data->mode_str = (char *)mode_str;
- + plat_data->default_bpp = bpp;
- + plat_data->int_clk = (bool)int_clk;
- + plat_data->late_init = (bool)late_init;
- + return err;
- +}
- +
- +/*!
- + * Probe routine for the framebuffer driver. It is called during the
- + * driver binding process. The following functions are performed in
- + * this routine: Framebuffer initialization, Memory allocation and
- + * mapping, Framebuffer registration, IPU initialization.
- + *
- + * @return Appropriate error code to the kernel common code
- + */
- +static int mxcfb_probe(struct platform_device *pdev)
- +{
- + struct ipuv3_fb_platform_data *plat_data;
- + struct fb_info *fbi;
- + struct mxcfb_info *mxcfbi;
- + struct resource *res;
- + int ret = 0;
- +
- + dev_dbg(&pdev->dev, "%s enter\n", __func__);
- + pdev->id = of_alias_get_id(pdev->dev.of_node, "mxcfb");
- + if (pdev->id < 0) {
- + dev_err(&pdev->dev, "can not get alias id\n");
- + return pdev->id;
- + }
- +
- + plat_data = devm_kzalloc(&pdev->dev, sizeof(struct
- + ipuv3_fb_platform_data), GFP_KERNEL);
- + if (!plat_data)
- + return -ENOMEM;
- + pdev->dev.platform_data = plat_data;
- +
- + ret = mxcfb_get_of_property(pdev, plat_data);
- + if (ret < 0) {
- + dev_err(&pdev->dev, "get mxcfb of property fail\n");
- + return ret;
- + }
- +
- + /* Initialize FB structures */
- + fbi = mxcfb_init_fbinfo(&pdev->dev, &mxcfb_ops);
- + if (!fbi) {
- + ret = -ENOMEM;
- + goto init_fbinfo_failed;
- + }
- +
- + ret = mxcfb_option_setup(pdev, fbi);
- + if (ret)
- + goto get_fb_option_failed;
- +
- + mxcfbi = (struct mxcfb_info *)fbi->par;
- + mxcfbi->ipu_int_clk = plat_data->int_clk;
- + mxcfbi->late_init = plat_data->late_init;
- + mxcfbi->first_set_par = true;
- + ret = mxcfb_dispdrv_init(pdev, fbi);
- + if (ret < 0)
- + goto init_dispdrv_failed;
- +
- + ret = ipu_test_set_usage(mxcfbi->ipu_id, mxcfbi->ipu_di);
- + if (ret < 0) {
- + dev_err(&pdev->dev, "ipu%d-di%d already in use\n",
- + mxcfbi->ipu_id, mxcfbi->ipu_di);
- + goto ipu_in_busy;
- + }
- +
- + if (mxcfbi->dispdrv->drv->post_init) {
- + ret = mxcfbi->dispdrv->drv->post_init(mxcfbi->dispdrv,
- + mxcfbi->ipu_id,
- + mxcfbi->ipu_di);
- + if (ret < 0) {
- + dev_err(&pdev->dev, "post init failed\n");
- + goto post_init_failed;
- + }
- + }
- +
- + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- + if (res && res->start && res->end) {
- + fbi->fix.smem_len = res->end - res->start + 1;
- + fbi->fix.smem_start = res->start;
- + fbi->screen_base = ioremap(fbi->fix.smem_start, fbi->fix.smem_len);
- + /* Do not clear the fb content drawn in bootloader. */
- + if (!mxcfbi->late_init)
- + memset(fbi->screen_base, 0, fbi->fix.smem_len);
- + }
- +
- + mxcfbi->ipu = ipu_get_soc(mxcfbi->ipu_id);
- + if (IS_ERR(mxcfbi->ipu)) {
- + ret = -ENODEV;
- + goto get_ipu_failed;
- + }
- +
- + /* first user uses DP with alpha feature */
- + if (!g_dp_in_use[mxcfbi->ipu_id]) {
- + mxcfbi->ipu_ch_irq = IPU_IRQ_BG_SYNC_EOF;
- + mxcfbi->ipu_ch_nf_irq = IPU_IRQ_BG_SYNC_NFACK;
- + mxcfbi->ipu_alp_ch_irq = IPU_IRQ_BG_ALPHA_SYNC_EOF;
- + mxcfbi->ipu_ch = MEM_BG_SYNC;
- + /* Unblank the primary fb only by default */
- + if (pdev->id == 0)
- + mxcfbi->cur_blank = mxcfbi->next_blank = FB_BLANK_UNBLANK;
- + else
- + mxcfbi->cur_blank = mxcfbi->next_blank = FB_BLANK_POWERDOWN;
- +
- + ret = mxcfb_register(fbi);
- + if (ret < 0)
- + goto mxcfb_register_failed;
- +
- + ipu_disp_set_global_alpha(mxcfbi->ipu, mxcfbi->ipu_ch,
- + true, 0x80);
- + ipu_disp_set_color_key(mxcfbi->ipu, mxcfbi->ipu_ch, false, 0);
- +
- + res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- + ret = mxcfb_setup_overlay(pdev, fbi, res);
- +
- + if (ret < 0) {
- + mxcfb_unregister(fbi);
- + goto mxcfb_setupoverlay_failed;
- + }
- +
- + g_dp_in_use[mxcfbi->ipu_id] = true;
- +
- + ret = device_create_file(mxcfbi->ovfbi->dev,
- + &dev_attr_fsl_disp_property);
- + if (ret)
- + dev_err(mxcfbi->ovfbi->dev, "Error %d on creating "
- + "file for disp property\n",
- + ret);
- +
- + ret = device_create_file(mxcfbi->ovfbi->dev,
- + &dev_attr_fsl_disp_dev_property);
- + if (ret)
- + dev_err(mxcfbi->ovfbi->dev, "Error %d on creating "
- + "file for disp device "
- + "propety\n", ret);
- + } else {
- + mxcfbi->ipu_ch_irq = IPU_IRQ_DC_SYNC_EOF;
- + mxcfbi->ipu_ch_nf_irq = IPU_IRQ_DC_SYNC_NFACK;
- + mxcfbi->ipu_alp_ch_irq = -1;
- + mxcfbi->ipu_ch = MEM_DC_SYNC;
- + mxcfbi->cur_blank = mxcfbi->next_blank = FB_BLANK_POWERDOWN;
- +
- + ret = mxcfb_register(fbi);
- + if (ret < 0)
- + goto mxcfb_register_failed;
- + }
- +
- + platform_set_drvdata(pdev, fbi);
- +
- + ret = device_create_file(fbi->dev, &dev_attr_fsl_disp_property);
- + if (ret)
- + dev_err(&pdev->dev, "Error %d on creating file for disp "
- + "property\n", ret);
- +
- + ret = device_create_file(fbi->dev, &dev_attr_fsl_disp_dev_property);
- + if (ret)
- + dev_err(&pdev->dev, "Error %d on creating file for disp "
- + " device propety\n", ret);
- +
- + return 0;
- +
- +mxcfb_setupoverlay_failed:
- +mxcfb_register_failed:
- +get_ipu_failed:
- +post_init_failed:
- + ipu_clear_usage(mxcfbi->ipu_id, mxcfbi->ipu_di);
- +ipu_in_busy:
- +init_dispdrv_failed:
- + fb_dealloc_cmap(&fbi->cmap);
- + framebuffer_release(fbi);
- +get_fb_option_failed:
- +init_fbinfo_failed:
- + return ret;
- +}
- +
- +static int mxcfb_remove(struct platform_device *pdev)
- +{
- + struct fb_info *fbi = platform_get_drvdata(pdev);
- + struct mxcfb_info *mxc_fbi = fbi->par;
- +
- + if (!fbi)
- + return 0;
- +
- + device_remove_file(fbi->dev, &dev_attr_fsl_disp_dev_property);
- + device_remove_file(fbi->dev, &dev_attr_fsl_disp_property);
- + mxcfb_blank(FB_BLANK_POWERDOWN, fbi);
- + mxcfb_unregister(fbi);
- + mxcfb_unmap_video_memory(fbi);
- +
- + if (mxc_fbi->ovfbi) {
- + device_remove_file(mxc_fbi->ovfbi->dev,
- + &dev_attr_fsl_disp_dev_property);
- + device_remove_file(mxc_fbi->ovfbi->dev,
- + &dev_attr_fsl_disp_property);
- + mxcfb_blank(FB_BLANK_POWERDOWN, mxc_fbi->ovfbi);
- + mxcfb_unsetup_overlay(fbi);
- + mxcfb_unmap_video_memory(mxc_fbi->ovfbi);
- + }
- +
- + ipu_clear_usage(mxc_fbi->ipu_id, mxc_fbi->ipu_di);
- + if (&fbi->cmap)
- + fb_dealloc_cmap(&fbi->cmap);
- + framebuffer_release(fbi);
- + return 0;
- +}
- +
- +static const struct of_device_id imx_mxcfb_dt_ids[] = {
- + { .compatible = "fsl,mxc_sdc_fb"},
- + { /* sentinel */ }
- +};
- +
- +/*!
- + * This structure contains pointers to the power management callback functions.
- + */
- +static struct platform_driver mxcfb_driver = {
- + .driver = {
- + .name = MXCFB_NAME,
- + .of_match_table = imx_mxcfb_dt_ids,
- + },
- + .probe = mxcfb_probe,
- + .remove = mxcfb_remove,
- + .suspend = mxcfb_suspend,
- + .resume = mxcfb_resume,
- +};
- +
- +/*!
- + * Main entry function for the framebuffer. The function registers the power
- + * management callback functions with the kernel and also registers the MXCFB
- + * callback functions with the core Linux framebuffer driver \b fbmem.c
- + *
- + * @return Error code indicating success or failure
- + */
- +int __init mxcfb_init(void)
- +{
- + return platform_driver_register(&mxcfb_driver);
- +}
- +
- +void mxcfb_exit(void)
- +{
- + platform_driver_unregister(&mxcfb_driver);
- +}
- +
- +module_init(mxcfb_init);
- +module_exit(mxcfb_exit);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("MXC framebuffer driver");
- +MODULE_LICENSE("GPL");
- +MODULE_SUPPORTED_DEVICE("fb");
- diff -Nur linux-3.14.35.orig/drivers/video/mxc/mxc_lcdif.c linux-3.14.35/drivers/video/mxc/mxc_lcdif.c
- --- linux-3.14.35.orig/drivers/video/mxc/mxc_lcdif.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/video/mxc/mxc_lcdif.c 2015-03-08 14:27:37.789684499 -0500
- @@ -0,0 +1,235 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#include <linux/init.h>
- +#include <linux/ipu.h>
- +#include <linux/kernel.h>
- +#include <linux/module.h>
- +#include <linux/mxcfb.h>
- +#include <linux/of_device.h>
- +#include <linux/pinctrl/consumer.h>
- +#include <linux/platform_device.h>
- +
- +#include "mxc_dispdrv.h"
- +
- +struct mxc_lcd_platform_data {
- + u32 default_ifmt;
- + u32 ipu_id;
- + u32 disp_id;
- +};
- +
- +struct mxc_lcdif_data {
- + struct platform_device *pdev;
- + struct mxc_dispdrv_handle *disp_lcdif;
- +};
- +
- +#define DISPDRV_LCD "lcd"
- +
- +static struct fb_videomode lcdif_modedb[] = {
- + {
- + /* 800x480 @ 57 Hz , pixel clk @ 27MHz */
- + "CLAA-WVGA", 57, 800, 480, 37037, 40, 60, 10, 10, 20, 10,
- + FB_SYNC_CLK_LAT_FALL,
- + FB_VMODE_NONINTERLACED,
- + 0,},
- + {
- + /* 800x480 @ 60 Hz , pixel clk @ 32MHz */
- + "SEIKO-WVGA", 60, 800, 480, 29850, 89, 164, 23, 10, 10, 10,
- + FB_SYNC_CLK_LAT_FALL,
- + FB_VMODE_NONINTERLACED,
- + 0,},
- +};
- +static int lcdif_modedb_sz = ARRAY_SIZE(lcdif_modedb);
- +
- +static int lcdif_init(struct mxc_dispdrv_handle *disp,
- + struct mxc_dispdrv_setting *setting)
- +{
- + int ret, i;
- + struct mxc_lcdif_data *lcdif = mxc_dispdrv_getdata(disp);
- + struct mxc_lcd_platform_data *plat_data
- + = lcdif->pdev->dev.platform_data;
- + struct fb_videomode *modedb = lcdif_modedb;
- + int modedb_sz = lcdif_modedb_sz;
- +
- + /* use platform defined ipu/di */
- + setting->dev_id = plat_data->ipu_id;
- + setting->disp_id = plat_data->disp_id;
- +
- + ret = fb_find_mode(&setting->fbi->var, setting->fbi, setting->dft_mode_str,
- + modedb, modedb_sz, NULL, setting->default_bpp);
- + if (!ret) {
- + fb_videomode_to_var(&setting->fbi->var, &modedb[0]);
- + setting->if_fmt = plat_data->default_ifmt;
- + }
- +
- + INIT_LIST_HEAD(&setting->fbi->modelist);
- + for (i = 0; i < modedb_sz; i++) {
- + struct fb_videomode m;
- + fb_var_to_videomode(&m, &setting->fbi->var);
- + if (fb_mode_is_equal(&m, &modedb[i])) {
- + fb_add_videomode(&modedb[i],
- + &setting->fbi->modelist);
- + break;
- + }
- + }
- +
- + return ret;
- +}
- +
- +void lcdif_deinit(struct mxc_dispdrv_handle *disp)
- +{
- + /*TODO*/
- +}
- +
- +static struct mxc_dispdrv_driver lcdif_drv = {
- + .name = DISPDRV_LCD,
- + .init = lcdif_init,
- + .deinit = lcdif_deinit,
- +};
- +
- +static int lcd_get_of_property(struct platform_device *pdev,
- + struct mxc_lcd_platform_data *plat_data)
- +{
- + struct device_node *np = pdev->dev.of_node;
- + int err;
- + u32 ipu_id, disp_id;
- + const char *default_ifmt;
- +
- + err = of_property_read_string(np, "default_ifmt", &default_ifmt);
- + if (err) {
- + dev_dbg(&pdev->dev, "get of property default_ifmt fail\n");
- + return err;
- + }
- + err = of_property_read_u32(np, "ipu_id", &ipu_id);
- + if (err) {
- + dev_dbg(&pdev->dev, "get of property ipu_id fail\n");
- + return err;
- + }
- + err = of_property_read_u32(np, "disp_id", &disp_id);
- + if (err) {
- + dev_dbg(&pdev->dev, "get of property disp_id fail\n");
- + return err;
- + }
- +
- + plat_data->ipu_id = ipu_id;
- + plat_data->disp_id = disp_id;
- + if (!strncmp(default_ifmt, "RGB24", 5))
- + plat_data->default_ifmt = IPU_PIX_FMT_RGB24;
- + else if (!strncmp(default_ifmt, "BGR24", 5))
- + plat_data->default_ifmt = IPU_PIX_FMT_BGR24;
- + else if (!strncmp(default_ifmt, "GBR24", 5))
- + plat_data->default_ifmt = IPU_PIX_FMT_GBR24;
- + else if (!strncmp(default_ifmt, "RGB565", 6))
- + plat_data->default_ifmt = IPU_PIX_FMT_RGB565;
- + else if (!strncmp(default_ifmt, "RGB666", 6))
- + plat_data->default_ifmt = IPU_PIX_FMT_RGB666;
- + else if (!strncmp(default_ifmt, "YUV444", 6))
- + plat_data->default_ifmt = IPU_PIX_FMT_YUV444;
- + else if (!strncmp(default_ifmt, "LVDS666", 7))
- + plat_data->default_ifmt = IPU_PIX_FMT_LVDS666;
- + else if (!strncmp(default_ifmt, "YUYV16", 6))
- + plat_data->default_ifmt = IPU_PIX_FMT_YUYV;
- + else if (!strncmp(default_ifmt, "UYVY16", 6))
- + plat_data->default_ifmt = IPU_PIX_FMT_UYVY;
- + else if (!strncmp(default_ifmt, "YVYU16", 6))
- + plat_data->default_ifmt = IPU_PIX_FMT_YVYU;
- + else if (!strncmp(default_ifmt, "VYUY16", 6))
- + plat_data->default_ifmt = IPU_PIX_FMT_VYUY;
- + else {
- + dev_err(&pdev->dev, "err default_ifmt!\n");
- + return -ENOENT;
- + }
- +
- + return err;
- +}
- +
- +static int mxc_lcdif_probe(struct platform_device *pdev)
- +{
- + int ret;
- + struct pinctrl *pinctrl;
- + struct mxc_lcdif_data *lcdif;
- + struct mxc_lcd_platform_data *plat_data;
- +
- + dev_dbg(&pdev->dev, "%s enter\n", __func__);
- + lcdif = devm_kzalloc(&pdev->dev, sizeof(struct mxc_lcdif_data),
- + GFP_KERNEL);
- + if (!lcdif)
- + return -ENOMEM;
- + plat_data = devm_kzalloc(&pdev->dev,
- + sizeof(struct mxc_lcd_platform_data),
- + GFP_KERNEL);
- + if (!plat_data)
- + return -ENOMEM;
- + pdev->dev.platform_data = plat_data;
- +
- + ret = lcd_get_of_property(pdev, plat_data);
- + if (ret < 0) {
- + dev_err(&pdev->dev, "get lcd of property fail\n");
- + return ret;
- + }
- +
- + pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
- + if (IS_ERR(pinctrl)) {
- + dev_err(&pdev->dev, "can't get/select pinctrl\n");
- + return PTR_ERR(pinctrl);
- + }
- +
- + lcdif->pdev = pdev;
- + lcdif->disp_lcdif = mxc_dispdrv_register(&lcdif_drv);
- + mxc_dispdrv_setdata(lcdif->disp_lcdif, lcdif);
- +
- + dev_set_drvdata(&pdev->dev, lcdif);
- + dev_dbg(&pdev->dev, "%s exit\n", __func__);
- +
- + return ret;
- +}
- +
- +static int mxc_lcdif_remove(struct platform_device *pdev)
- +{
- + struct mxc_lcdif_data *lcdif = dev_get_drvdata(&pdev->dev);
- +
- + mxc_dispdrv_puthandle(lcdif->disp_lcdif);
- + mxc_dispdrv_unregister(lcdif->disp_lcdif);
- + kfree(lcdif);
- + return 0;
- +}
- +
- +static const struct of_device_id imx_lcd_dt_ids[] = {
- + { .compatible = "fsl,lcd"},
- + { /* sentinel */ }
- +};
- +static struct platform_driver mxc_lcdif_driver = {
- + .driver = {
- + .name = "mxc_lcdif",
- + .of_match_table = imx_lcd_dt_ids,
- + },
- + .probe = mxc_lcdif_probe,
- + .remove = mxc_lcdif_remove,
- +};
- +
- +static int __init mxc_lcdif_init(void)
- +{
- + return platform_driver_register(&mxc_lcdif_driver);
- +}
- +
- +static void __exit mxc_lcdif_exit(void)
- +{
- + platform_driver_unregister(&mxc_lcdif_driver);
- +}
- +
- +module_init(mxc_lcdif_init);
- +module_exit(mxc_lcdif_exit);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("i.MX ipuv3 LCD extern port driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/drivers/video/mxsfb.c linux-3.14.35/drivers/video/mxsfb.c
- --- linux-3.14.35.orig/drivers/video/mxsfb.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/drivers/video/mxsfb.c 2015-03-08 14:27:37.789684499 -0500
- @@ -96,9 +96,10 @@
- #define CTRL_DF24 (1 << 1)
- #define CTRL_RUN (1 << 0)
-
- -#define CTRL1_FIFO_CLEAR (1 << 21)
- -#define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
- -#define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
- +#define CTRL1_RECOVERY_ON_UNDERFLOW (1 << 24)
- +#define CTRL1_FIFO_CLEAR (1 << 21)
- +#define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
- +#define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
-
- #define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16)
- #define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff)
- @@ -149,8 +150,8 @@
- #define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */
- #define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */
-
- -#define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT (1 << 6)
- -#define MXSFB_SYNC_DOTCLK_FALLING_ACT (1 << 7) /* negtive edge sampling */
- +#define FB_SYNC_OE_LOW_ACT 0x80000000
- +#define FB_SYNC_CLK_LAT_FALL 0x40000000
-
- enum mxsfb_devtype {
- MXSFB_V3,
- @@ -178,7 +179,6 @@
- unsigned ld_intf_width;
- unsigned dotclk_delay;
- const struct mxsfb_devdata *devdata;
- - u32 sync;
- struct regulator *reg_lcd;
- };
-
- @@ -275,9 +275,15 @@
- if (var->yres < MIN_YRES)
- var->yres = MIN_YRES;
-
- - var->xres_virtual = var->xres;
- + if (var->xres_virtual > var->xres) {
- + dev_dbg(fb_info->device, "stride not supported\n");
- + return -EINVAL;
- + }
-
- - var->yres_virtual = var->yres;
- + if (var->xres_virtual < var->xres)
- + var->xres_virtual = var->xres;
- + if (var->yres_virtual < var->yres)
- + var->yres_virtual = var->yres;
-
- switch (var->bits_per_pixel) {
- case 16:
- @@ -344,6 +350,9 @@
-
- writel(CTRL_RUN, host->base + LCDC_CTRL + REG_SET);
-
- + /* Recovery on underflow */
- + writel(CTRL1_RECOVERY_ON_UNDERFLOW, host->base + LCDC_CTRL1 + REG_SET);
- +
- host->enabled = 1;
- }
-
- @@ -392,14 +401,6 @@
- int line_size, fb_size;
- int reenable = 0;
-
- - line_size = fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3);
- - fb_size = fb_info->var.yres_virtual * line_size;
- -
- - if (fb_size > fb_info->fix.smem_len)
- - return -ENOMEM;
- -
- - fb_info->fix.line_length = line_size;
- -
- /*
- * It seems, you can't re-program the controller if it is still running.
- * This may lead into shifted pictures (FIFO issue?).
- @@ -413,6 +414,19 @@
- /* clear the FIFOs */
- writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET);
-
- + line_size = fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3);
- + fb_info->fix.line_length = line_size;
- + fb_size = fb_info->var.yres_virtual * line_size;
- +
- + /* Reallocate memory */
- + if (!fb_info->fix.smem_start || (fb_size > fb_info->fix.smem_len)) {
- + if (fb_info->fix.smem_start)
- + mxsfb_unmap_videomem(fb_info);
- +
- + if (mxsfb_map_videomem(fb_info) < 0)
- + return -ENOMEM;
- + }
- +
- ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER |
- CTRL_SET_BUS_WIDTH(host->ld_intf_width);
-
- @@ -459,9 +473,9 @@
- vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
- if (fb_info->var.sync & FB_SYNC_VERT_HIGH_ACT)
- vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
- - if (host->sync & MXSFB_SYNC_DATA_ENABLE_HIGH_ACT)
- + if (!(fb_info->var.sync & FB_SYNC_OE_LOW_ACT))
- vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
- - if (host->sync & MXSFB_SYNC_DOTCLK_FALLING_ACT)
- + if (fb_info->var.sync & FB_SYNC_CLK_LAT_FALL)
- vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
-
- writel(vdctrl0, host->base + LCDC_VDCTRL0);
- @@ -578,6 +592,34 @@
- return 0;
- }
-
- +static int mxsfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
- +{
- + u32 len;
- + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
- +
- + if (offset < info->fix.smem_len) {
- + /* mapping framebuffer memory */
- + len = info->fix.smem_len - offset;
- + vma->vm_pgoff = (info->fix.smem_start + offset) >> PAGE_SHIFT;
- + } else
- + return -EINVAL;
- +
- + len = PAGE_ALIGN(len);
- + if (vma->vm_end - vma->vm_start > len)
- + return -EINVAL;
- +
- + /* make buffers bufferable */
- + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- +
- + if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- + vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
- + dev_dbg(info->device, "mmap remap_pfn_range failed\n");
- + return -ENOBUFS;
- + }
- +
- + return 0;
- +}
- +
- static struct fb_ops mxsfb_ops = {
- .owner = THIS_MODULE,
- .fb_check_var = mxsfb_check_var,
- @@ -585,6 +627,7 @@
- .fb_setcolreg = mxsfb_setcolreg,
- .fb_blank = mxsfb_blank,
- .fb_pan_display = mxsfb_pan_display,
- + .fb_mmap = mxsfb_mmap,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
- @@ -800,7 +843,62 @@
- {
- struct fb_info *fb_info = &host->fb_info;
-
- - free_pages_exact(fb_info->screen_base, fb_info->fix.smem_len);
- + mxsfb_unmap_videomem(fb_info);
- +}
- +
- +/*!
- + * Allocates the DRAM memory for the frame buffer. This buffer is remapped
- + * into a non-cached, non-buffered, memory region to allow palette and pixel
- + * writes to occur without flushing the cache. Once this area is remapped,
- + * all virtual memory access to the video memory should occur at the new region.
- + *
- + * @param fbi framebuffer information pointer
- + *
- + * @return Error code indicating success or failure
- + */
- +static int mxsfb_map_videomem(struct fb_info *fbi)
- +{
- + if (fbi->fix.smem_len < fbi->var.yres_virtual * fbi->fix.line_length)
- + fbi->fix.smem_len = fbi->var.yres_virtual *
- + fbi->fix.line_length;
- +
- + fbi->screen_base = dma_alloc_writecombine(fbi->device,
- + fbi->fix.smem_len,
- + (dma_addr_t *)&fbi->fix.smem_start,
- + GFP_DMA | GFP_KERNEL);
- + if (fbi->screen_base == 0) {
- + dev_err(fbi->device, "Unable to allocate framebuffer memory\n");
- + fbi->fix.smem_len = 0;
- + fbi->fix.smem_start = 0;
- + return -EBUSY;
- + }
- +
- + dev_dbg(fbi->device, "allocated fb @ paddr=0x%08X, size=%d.\n",
- + (uint32_t) fbi->fix.smem_start, fbi->fix.smem_len);
- +
- + fbi->screen_size = fbi->fix.smem_len;
- +
- + /* Clear the screen */
- + memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
- +
- + return 0;
- +}
- +
- +/*!
- + * De-allocates the DRAM memory for the frame buffer.
- + *
- + * @param fbi framebuffer information pointer
- + *
- + * @return Error code indicating success or failure
- + */
- +static int mxsfb_unmap_videomem(struct fb_info *fbi)
- +{
- + dma_free_writecombine(fbi->device, fbi->fix.smem_len,
- + fbi->screen_base, fbi->fix.smem_start);
- + fbi->screen_base = 0;
- + fbi->fix.smem_start = 0;
- + fbi->fix.smem_len = 0;
- + return 0;
- }
-
- static struct platform_device_id mxsfb_devtype[] = {
- diff -Nur linux-3.14.35.orig/drivers/video/vexpress-dvi.c linux-3.14.35/drivers/video/vexpress-dvi.c
- --- linux-3.14.35.orig/drivers/video/vexpress-dvi.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/drivers/video/vexpress-dvi.c 2015-03-08 14:27:37.789684499 -0500
- @@ -0,0 +1,220 @@
- +/*
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * Copyright (C) 2012 ARM Limited
- + */
- +
- +#define pr_fmt(fmt) "vexpress-dvi: " fmt
- +
- +#include <linux/fb.h>
- +#include <linux/of.h>
- +#include <linux/of_device.h>
- +#include <linux/vexpress.h>
- +
- +
- +static struct vexpress_config_func *vexpress_dvimode_func;
- +
- +static struct {
- + u32 xres, yres, mode;
- +} vexpress_dvi_dvimodes[] = {
- + { 640, 480, 0 }, /* VGA */
- + { 800, 600, 1 }, /* SVGA */
- + { 1024, 768, 2 }, /* XGA */
- + { 1280, 1024, 3 }, /* SXGA */
- + { 1600, 1200, 4 }, /* UXGA */
- + { 1920, 1080, 5 }, /* HD1080 */
- +};
- +
- +static void vexpress_dvi_mode_set(struct fb_info *info, u32 xres, u32 yres)
- +{
- + int err = -ENOENT;
- + int i;
- +
- + if (!vexpress_dvimode_func)
- + return;
- +
- + for (i = 0; i < ARRAY_SIZE(vexpress_dvi_dvimodes); i++) {
- + if (vexpress_dvi_dvimodes[i].xres == xres &&
- + vexpress_dvi_dvimodes[i].yres == yres) {
- + pr_debug("mode: %ux%u = %d\n", xres, yres,
- + vexpress_dvi_dvimodes[i].mode);
- + err = vexpress_config_write(vexpress_dvimode_func, 0,
- + vexpress_dvi_dvimodes[i].mode);
- + break;
- + }
- + }
- +
- + if (err)
- + pr_warn("Failed to set %ux%u mode! (%d)\n", xres, yres, err);
- +}
- +
- +
- +static struct vexpress_config_func *vexpress_muxfpga_func;
- +static int vexpress_dvi_fb = -1;
- +
- +static int vexpress_dvi_mux_set(struct fb_info *info)
- +{
- + int err;
- + u32 site = vexpress_get_site_by_dev(info->device);
- +
- + if (!vexpress_muxfpga_func)
- + return -ENXIO;
- +
- + err = vexpress_config_write(vexpress_muxfpga_func, 0, site);
- + if (!err) {
- + pr_debug("Selected MUXFPGA input %d (fb%d)\n", site,
- + info->node);
- + vexpress_dvi_fb = info->node;
- + vexpress_dvi_mode_set(info, info->var.xres,
- + info->var.yres);
- + } else {
- + pr_warn("Failed to select MUXFPGA input %d (fb%d)! (%d)\n",
- + site, info->node, err);
- + }
- +
- + return err;
- +}
- +
- +static int vexpress_dvi_fb_select(int fb)
- +{
- + int err;
- + struct fb_info *info;
- +
- + /* fb0 is the default */
- + if (fb < 0)
- + fb = 0;
- +
- + info = registered_fb[fb];
- + if (!info || !lock_fb_info(info))
- + return -ENODEV;
- +
- + err = vexpress_dvi_mux_set(info);
- +
- + unlock_fb_info(info);
- +
- + return err;
- +}
- +
- +static ssize_t vexpress_dvi_fb_show(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + return sprintf(buf, "%d\n", vexpress_dvi_fb);
- +}
- +
- +static ssize_t vexpress_dvi_fb_store(struct device *dev,
- + struct device_attribute *attr, const char *buf, size_t count)
- +{
- + long value;
- + int err = kstrtol(buf, 0, &value);
- +
- + if (!err)
- + err = vexpress_dvi_fb_select(value);
- +
- + return err ? err : count;
- +}
- +
- +DEVICE_ATTR(fb, S_IRUGO | S_IWUSR, vexpress_dvi_fb_show,
- + vexpress_dvi_fb_store);
- +
- +
- +static int vexpress_dvi_fb_event_notify(struct notifier_block *self,
- + unsigned long action, void *data)
- +{
- + struct fb_event *event = data;
- + struct fb_info *info = event->info;
- + struct fb_videomode *mode = event->data;
- +
- + switch (action) {
- + case FB_EVENT_FB_REGISTERED:
- + if (vexpress_dvi_fb < 0)
- + vexpress_dvi_mux_set(info);
- + break;
- + case FB_EVENT_MODE_CHANGE:
- + case FB_EVENT_MODE_CHANGE_ALL:
- + if (info->node == vexpress_dvi_fb)
- + vexpress_dvi_mode_set(info, mode->xres, mode->yres);
- + break;
- + }
- +
- + return NOTIFY_OK;
- +}
- +
- +static struct notifier_block vexpress_dvi_fb_notifier = {
- + .notifier_call = vexpress_dvi_fb_event_notify,
- +};
- +static bool vexpress_dvi_fb_notifier_registered;
- +
- +
- +enum vexpress_dvi_func { FUNC_MUXFPGA, FUNC_DVIMODE };
- +
- +static struct of_device_id vexpress_dvi_of_match[] = {
- + {
- + .compatible = "arm,vexpress-muxfpga",
- + .data = (void *)FUNC_MUXFPGA,
- + }, {
- + .compatible = "arm,vexpress-dvimode",
- + .data = (void *)FUNC_DVIMODE,
- + },
- + {}
- +};
- +
- +static int vexpress_dvi_probe(struct platform_device *pdev)
- +{
- + enum vexpress_dvi_func func;
- + const struct of_device_id *match =
- + of_match_device(vexpress_dvi_of_match, &pdev->dev);
- +
- + if (match)
- + func = (enum vexpress_dvi_func)match->data;
- + else
- + func = pdev->id_entry->driver_data;
- +
- + switch (func) {
- + case FUNC_MUXFPGA:
- + vexpress_muxfpga_func =
- + vexpress_config_func_get_by_dev(&pdev->dev);
- + device_create_file(&pdev->dev, &dev_attr_fb);
- + break;
- + case FUNC_DVIMODE:
- + vexpress_dvimode_func =
- + vexpress_config_func_get_by_dev(&pdev->dev);
- + break;
- + }
- +
- + if (!vexpress_dvi_fb_notifier_registered) {
- + fb_register_client(&vexpress_dvi_fb_notifier);
- + vexpress_dvi_fb_notifier_registered = true;
- + }
- +
- + vexpress_dvi_fb_select(vexpress_dvi_fb);
- +
- + return 0;
- +}
- +
- +static const struct platform_device_id vexpress_dvi_id_table[] = {
- + { .name = "vexpress-muxfpga", .driver_data = FUNC_MUXFPGA, },
- + { .name = "vexpress-dvimode", .driver_data = FUNC_DVIMODE, },
- + {}
- +};
- +
- +static struct platform_driver vexpress_dvi_driver = {
- + .probe = vexpress_dvi_probe,
- + .driver = {
- + .name = "vexpress-dvi",
- + .of_match_table = vexpress_dvi_of_match,
- + },
- + .id_table = vexpress_dvi_id_table,
- +};
- +
- +static int __init vexpress_dvi_init(void)
- +{
- + return platform_driver_register(&vexpress_dvi_driver);
- +}
- +device_initcall(vexpress_dvi_init);
- diff -Nur linux-3.14.35.orig/firmware/imx/sdma/sdma-imx6q.bin.ihex linux-3.14.35/firmware/imx/sdma/sdma-imx6q.bin.ihex
- --- linux-3.14.35.orig/firmware/imx/sdma/sdma-imx6q.bin.ihex 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/firmware/imx/sdma/sdma-imx6q.bin.ihex 2015-03-08 14:27:37.789684499 -0500
- @@ -0,0 +1,116 @@
- +:1000000053444D4101000000010000001C000000AD
- +:1000100026000000B40000007A0600008202000002
- +:10002000FFFFFFFF00000000FFFFFFFFFFFFFFFFDC
- +:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0
- +:10004000FFFFFFFFFFFFFFFF6A1A0000FFFFFFFF38
- +:10005000EB020000BB180000FFFFFFFF08040000D8
- +:10006000FFFFFFFFC0030000FFFFFFFFFFFFFFFFD9
- +:10007000FFFFFFFFAB020000FFFFFFFF7B0300005D
- +:10008000FFFFFFFFFFFFFFFF4C0400006E040000B6
- +:10009000FFFFFFFF00180000FFFFFFFFFFFFFFFF54
- +:1000A000000000000018000062180000161A00008E
- +:1000B000061B0000E3C1DB57E35FE357F352016A1D
- +:1000C0008F00D500017D8D00A005EB5D7804037DD8
- +:1000D00079042C7D367C79041F7CEE56000F600677
- +:1000E000057D0965437E0A62417E20980A623E7E54
- +:1000F00009653C7E12051205AD026007037DFB55C4
- +:10010000D36D2B98FB55041DD36DC86A2F7F011F3B
- +:1001100003200048E47C5398FB55D76D1500057803
- +:100120000962C86A0962C86AD76D5298FB55D76DD3
- +:100130001500150005780A62C86A0A62C86AD76D98
- +:100140005298FB55D76D15001500150005780B6208
- +:10015000C86A0B62C86AD76D097CDF6D077F000033
- +:10016000EB55004D077DFAC1E35706980700CC68B0
- +:100170000C6813C20AC20398D9C1E3C1DB57E35F1D
- +:10018000E357F352216A8F00D500017D8D00A00551
- +:10019000EB5DFB567804037D79042A7D317C79047C
- +:1001A000207C700B1103EB53000F6003057D096584
- +:1001B000377E0A62357E86980A62327E0965307E15
- +:1001C00012051205AD026007027C065A8E98265A67
- +:1001D000277F011F03200048E87C700B1103135395
- +:1001E000AF98150004780962065A0962265AAE983B
- +:1001F0001500150004780A62065A0A62265AAE985B
- +:1002000015001500150004780B62065A0B62265A79
- +:10021000077C0000EB55004D067DFAC1E357699855
- +:1002200007000C6813C20AC26698700B11031353BF
- +:100230006C07017CD9C1FB5E8A066B07017CD9C1C2
- +:10024000F35EDB59D3588F0110010F398B003CC18D
- +:100250002B7DC05AC85B4EC1277C88038906E35CAE
- +:10026000FF0D1105FF1DBC053E07004D187D7008F0
- +:1002700011007E07097D7D07027D2852E698F8521D
- +:10028000DB54BC02CC02097C7C07027D2852EF982B
- +:10029000F852D354BC02CC02097D0004DD988B00D7
- +:1002A000C052C85359C1D67D0002CD98FF08BF0087
- +:1002B0007F07157D8804D500017D8D00A005EB5DCD
- +:1002C0008F0212021202FF3ADA05027C3E071899E9
- +:1002D000A402DD02027D3E0718995E071899EB55CE
- +:1002E0009805EB5DF352FB546A07267D6C07017D90
- +:1002F00055996B07577C6907047D6807027D010EDD
- +:100300002F999358D600017D8E009355A005935DDB
- +:10031000A00602780255045D1D7C004E087C69072A
- +:10032000037D0255177E3C99045D147F8906935026
- +:100330000048017D2799A099150006780255045DB3
- +:100340004F070255245D2F07017CA09917006F0706
- +:10035000017C012093559D000700A7D9F598D36C27
- +:100360006907047D6807027D010E64999358D600E1
- +:10037000017D8E009355A005935DA006027802557D
- +:10038000C86D0F7C004E087C6907037D0255097E0D
- +:100390007199C86D067F890693500048017D5C996C
- +:1003A000A0999A99C36A6907047D6807027D010EC6
- +:1003B00087999358D600017D8E009355A005935DD3
- +:1003C000A0060278C865045D0F7C004E087C6907B2
- +:1003D000037DC865097E9499045D067F8906935064
- +:1003E0000048017D7F99A09993559D000700FF6CFF
- +:1003F000A7D9F5980000E354EB55004D017CF59822
- +:10040000DD98E354EB55FF0A1102FF1A7F07027CC7
- +:10041000A005B4999D008C05BA05A0051002BA0488
- +:10042000AD0454040600E3C1DB57FB52C36AF35228
- +:10043000056A8F00D500017D8D00A005EB5D780475
- +:10044000037D79042B7D1E7C7904337CEE56000FEE
- +:10045000FB556007027DC36DD599041DC36DC8624D
- +:100460003B7E6006027D10021202096A357F12028D
- +:10047000096A327F1202096A2F7F011F0320004898
- +:10048000E77C099AFB55C76D150015001500057826
- +:10049000C8620B6AC8620B6AC76D089AFB55C76DC4
- +:1004A000150015000578C8620A6AC8620A6AC76D35
- +:1004B000089AFB55C76D15000578C862096AC862BD
- +:1004C000096AC76D097C286A077F0000EB55004D5B
- +:1004D000057DFAC1DB57BF9977C254040AC2BA99A5
- +:1004E000D9C1E3C1DB57F352056A8F00D500017D06
- +:1004F0008D00A005FB567804037D7904297D1F7CBF
- +:1005000079042E7CE35D700D1105ED55000F600739
- +:10051000027D0652329A2652337E6005027D100219
- +:100520001202096A2D7F1202096A2A7F1202096AE1
- +:10053000277F011F03200048EA7CE3555D9A1500E0
- +:1005400015001500047806520B6A26520B6A5C9A55
- +:1005500015001500047806520A6A26520A6A5C9A47
- +:10056000150004780652096A2652096A097C286A2D
- +:10057000077F0000DB57004D057DFAC1DB571B9A52
- +:1005800077C254040AC2189AE3C1DB57F352056AD2
- +:10059000FB568E02941AC36AC8626902247D941EB7
- +:1005A000C36ED36EC8624802C86A9426981EC36E92
- +:1005B000D36EC8624C02C86A9826C36E981EC36E7A
- +:1005C000C8629826C36E6002097CC8626E02247DF0
- +:1005D000096A1E7F0125004D257D849A286A187FAF
- +:1005E00004627AC2B89AE36E8F00D805017D8D004F
- +:1005F000A005C8626E02107D096A0A7F0120F97C9D
- +:10060000286A067F0000004D0D7DFAC1DB576E9A07
- +:10061000070004620C6AB59A286AFA7F04627AC2FB
- +:1006200058045404286AF47F0AC26B9AD9C1E3C102
- +:10063000DB57F352056AFB568E02941A0252690286
- +:100640001D7D941E06524802065A9426981E065294
- +:100650004C02065A9826981E065260020A7C98267A
- +:1006600006526E02237D096A1D7F0125004D247DFF
- +:10067000D19A286A177F04627AC2029B8F00D8053C
- +:10068000017D8D00A00506526E02107D096A0A7F69
- +:100690000120F97C286A067F0000004D0D7DFAC11B
- +:1006A000DB57C19A070004620C6AFF9A286AFA7F36
- +:1006B00004627AC258045404286AF47F0AC2BE9ABB
- +:1006C000016E0B612F7E0B622D7E0B632B7E0C0D5A
- +:1006D0001704170417049D04081DCC05017C0C0D9C
- +:1006E000D16A000F4207C86FDD6F1C7F8E009D002E
- +:1006F00001680B67177ED56B04080278C86F120774
- +:10070000117C0B670F7E04080278C86F12070A7C01
- +:10071000DD6F087FD169010FC86FDD6F037F0101B5
- +:0E0720000004129B0700FF680C680002129B89
- +:00000001FF
- diff -Nur linux-3.14.35.orig/firmware/Makefile linux-3.14.35/firmware/Makefile
- --- linux-3.14.35.orig/firmware/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/firmware/Makefile 2015-03-08 14:27:37.789684499 -0500
- @@ -61,6 +61,7 @@
- radeon/RV770_pfp.bin radeon/RV770_me.bin \
- radeon/RV730_pfp.bin radeon/RV730_me.bin \
- radeon/RV710_pfp.bin radeon/RV710_me.bin
- +fw-shipped-$(CONFIG_IMX_SDMA) += imx/sdma/sdma-imx6q.bin
- fw-shipped-$(CONFIG_DVB_AV7110) += av7110/bootcode.bin
- fw-shipped-$(CONFIG_DVB_TTUSB_BUDGET) += ttusb-budget/dspbootcode.bin
- fw-shipped-$(CONFIG_E100) += e100/d101m_ucode.bin e100/d101s_ucode.bin \
- @@ -210,6 +211,8 @@
- $(obj)/%: $(obj)/%.ihex | $(objtree)/$(obj)/$$(dir %)
- $(call cmd,ihex)
-
- +.NOTPARALLEL: $(obj)/%
- +
- # Don't depend on ihex2fw if we're installing and it already exists.
- # Putting it after | in the dependencies doesn't seem sufficient when
- # we're installing after a cross-compile, because ihex2fw has dependencies
- diff -Nur linux-3.14.35.orig/fs/btrfs/Kconfig linux-3.14.35/fs/btrfs/Kconfig
- --- linux-3.14.35.orig/fs/btrfs/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/fs/btrfs/Kconfig 2015-03-08 14:27:37.789684499 -0500
- @@ -1,5 +1,6 @@
- config BTRFS_FS
- tristate "Btrfs filesystem support"
- + select LIBCRC32C
- select CRYPTO
- select CRYPTO_CRC32C
- select ZLIB_INFLATE
- diff -Nur linux-3.14.35.orig/fs/buffer.c linux-3.14.35/fs/buffer.c
- --- linux-3.14.35.orig/fs/buffer.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/fs/buffer.c 2015-03-08 14:27:37.817684499 -0500
- @@ -3110,7 +3110,7 @@
- * until the buffer gets unlocked).
- *
- * ll_rw_block sets b_end_io to simple completion handler that marks
- - * the buffer up-to-date (if approriate), unlocks the buffer and wakes
- + * the buffer up-to-date (if appropriate), unlocks the buffer and wakes
- * any waiters.
- *
- * All of the buffers must be for the same device, and must also be a
- diff -Nur linux-3.14.35.orig/fs/compat_binfmt_elf.c linux-3.14.35/fs/compat_binfmt_elf.c
- --- linux-3.14.35.orig/fs/compat_binfmt_elf.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/fs/compat_binfmt_elf.c 2015-03-08 14:27:37.817684499 -0500
- @@ -88,6 +88,11 @@
- #define ELF_HWCAP COMPAT_ELF_HWCAP
- #endif
-
- +#ifdef COMPAT_ELF_HWCAP2
- +#undef ELF_HWCAP2
- +#define ELF_HWCAP2 COMPAT_ELF_HWCAP2
- +#endif
- +
- #ifdef COMPAT_ARCH_DLINFO
- #undef ARCH_DLINFO
- #define ARCH_DLINFO COMPAT_ARCH_DLINFO
- diff -Nur linux-3.14.35.orig/fs/debugfs/inode.c linux-3.14.35/fs/debugfs/inode.c
- --- linux-3.14.35.orig/fs/debugfs/inode.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/fs/debugfs/inode.c 2015-03-08 14:27:37.817684499 -0500
- @@ -358,7 +358,7 @@
- * @name: a pointer to a string containing the name of the file to create.
- * @mode: the permission that the file should have.
- * @parent: a pointer to the parent dentry for this file. This should be a
- - * directory dentry if set. If this paramater is NULL, then the
- + * directory dentry if set. If this parameter is NULL, then the
- * file will be created in the root of the debugfs filesystem.
- * @data: a pointer to something that the caller will want to get to later
- * on. The inode.i_private pointer will point to this value on
- @@ -400,7 +400,7 @@
- * @name: a pointer to a string containing the name of the directory to
- * create.
- * @parent: a pointer to the parent dentry for this file. This should be a
- - * directory dentry if set. If this paramater is NULL, then the
- + * directory dentry if set. If this parameter is NULL, then the
- * directory will be created in the root of the debugfs filesystem.
- *
- * This function creates a directory in debugfs with the given name.
- @@ -425,7 +425,7 @@
- * @name: a pointer to a string containing the name of the symbolic link to
- * create.
- * @parent: a pointer to the parent dentry for this symbolic link. This
- - * should be a directory dentry if set. If this paramater is NULL,
- + * should be a directory dentry if set. If this parameter is NULL,
- * then the symbolic link will be created in the root of the debugfs
- * filesystem.
- * @target: a pointer to a string containing the path to the target of the
- diff -Nur linux-3.14.35.orig/include/asm-generic/word-at-a-time.h linux-3.14.35/include/asm-generic/word-at-a-time.h
- --- linux-3.14.35.orig/include/asm-generic/word-at-a-time.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/asm-generic/word-at-a-time.h 2015-03-08 14:27:37.821684499 -0500
- @@ -50,7 +50,7 @@
- }
-
- #ifndef zero_bytemask
- -#define zero_bytemask(mask) (~0ul << __fls(mask) << 1)
- +#define zero_bytemask(mask) (~1ul << __fls(mask))
- #endif
-
- #endif /* _ASM_WORD_AT_A_TIME_H */
- diff -Nur linux-3.14.35.orig/include/crypto/algapi.h linux-3.14.35/include/crypto/algapi.h
- --- linux-3.14.35.orig/include/crypto/algapi.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/crypto/algapi.h 2015-03-08 14:27:37.837684499 -0500
- @@ -100,9 +100,12 @@
- void *page;
- u8 *buffer;
- u8 *iv;
- + unsigned int ivsize;
-
- int flags;
- - unsigned int blocksize;
- + unsigned int walk_blocksize;
- + unsigned int cipher_blocksize;
- + unsigned int alignmask;
- };
-
- struct ablkcipher_walk {
- @@ -192,6 +195,10 @@
- int blkcipher_walk_virt_block(struct blkcipher_desc *desc,
- struct blkcipher_walk *walk,
- unsigned int blocksize);
- +int blkcipher_aead_walk_virt_block(struct blkcipher_desc *desc,
- + struct blkcipher_walk *walk,
- + struct crypto_aead *tfm,
- + unsigned int blocksize);
-
- int ablkcipher_walk_done(struct ablkcipher_request *req,
- struct ablkcipher_walk *walk, int err);
- diff -Nur linux-3.14.35.orig/include/drm/drm_fb_helper.h linux-3.14.35/include/drm/drm_fb_helper.h
- --- linux-3.14.35.orig/include/drm/drm_fb_helper.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/drm/drm_fb_helper.h 2015-03-08 14:27:37.837684499 -0500
- @@ -55,7 +55,7 @@
- * save the current lut when force-restoring the fbdev for e.g.
- * kdbg.
- * @fb_probe: Driver callback to allocate and initialize the fbdev info
- - * structure. Futhermore it also needs to allocate the drm
- + * structure. Furthermore it also needs to allocate the drm
- * framebuffer used to back the fbdev.
- * @initial_config: Setup an initial fbdev display configuration
- *
- diff -Nur linux-3.14.35.orig/include/dt-bindings/clock/imx6sl-clock.h linux-3.14.35/include/dt-bindings/clock/imx6sl-clock.h
- --- linux-3.14.35.orig/include/dt-bindings/clock/imx6sl-clock.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/dt-bindings/clock/imx6sl-clock.h 2015-03-08 14:27:37.837684499 -0500
- @@ -1,5 +1,5 @@
- /*
- - * Copyright 2013 Freescale Semiconductor, Inc.
- + * Copyright (C) 2013 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- @@ -71,8 +71,8 @@
- #define IMX6SL_CLK_PERIPH 58
- #define IMX6SL_CLK_PERIPH2 59
- #define IMX6SL_CLK_OCRAM_PODF 60
- -#define IMX6SL_CLK_PERIPH_CLK2_PODF 61
- -#define IMX6SL_CLK_PERIPH2_CLK2_PODF 62
- +#define IMX6SL_CLK_PERIPH_CLK2 61
- +#define IMX6SL_CLK_PERIPH2_CLK2 62
- #define IMX6SL_CLK_IPG 63
- #define IMX6SL_CLK_CSI_PODF 64
- #define IMX6SL_CLK_LCDIF_AXI_PODF 65
- @@ -145,6 +145,7 @@
- #define IMX6SL_CLK_USDHC4 132
- #define IMX6SL_CLK_PLL4_AUDIO_DIV 133
- #define IMX6SL_CLK_SPBA 134
- -#define IMX6SL_CLK_END 135
- +#define IMX6SL_CLK_UART_OSC_4M 135
- +#define IMX6SL_CLK_END 136
-
- #endif /* __DT_BINDINGS_CLOCK_IMX6SL_H */
- diff -Nur linux-3.14.35.orig/include/linux/ahci_platform.h linux-3.14.35/include/linux/ahci_platform.h
- --- linux-3.14.35.orig/include/linux/ahci_platform.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/ahci_platform.h 2015-03-08 14:27:37.841684499 -0500
- @@ -19,15 +19,38 @@
-
- struct device;
- struct ata_port_info;
- +struct ahci_host_priv;
- +struct platform_device;
-
- +/*
- + * Note ahci_platform_data is deprecated, it is only kept around for use
- + * by the old da850 and spear13xx ahci code.
- + * New drivers should instead declare their own platform_driver struct, and
- + * use ahci_platform* functions in their own probe, suspend and resume methods.
- + */
- struct ahci_platform_data {
- int (*init)(struct device *dev, void __iomem *addr);
- void (*exit)(struct device *dev);
- int (*suspend)(struct device *dev);
- int (*resume)(struct device *dev);
- - const struct ata_port_info *ata_port_info;
- - unsigned int force_port_map;
- - unsigned int mask_port_map;
- };
-
- +int ahci_platform_enable_clks(struct ahci_host_priv *hpriv);
- +void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
- +int ahci_platform_enable_resources(struct ahci_host_priv *hpriv);
- +void ahci_platform_disable_resources(struct ahci_host_priv *hpriv);
- +struct ahci_host_priv *ahci_platform_get_resources(
- + struct platform_device *pdev);
- +int ahci_platform_init_host(struct platform_device *pdev,
- + struct ahci_host_priv *hpriv,
- + const struct ata_port_info *pi_template,
- + unsigned long host_flags,
- + unsigned int force_port_map,
- + unsigned int mask_port_map);
- +
- +int ahci_platform_suspend_host(struct device *dev);
- +int ahci_platform_resume_host(struct device *dev);
- +int ahci_platform_suspend(struct device *dev);
- +int ahci_platform_resume(struct device *dev);
- +
- #endif /* _AHCI_PLATFORM_H */
- diff -Nur linux-3.14.35.orig/include/linux/amba/clcd.h linux-3.14.35/include/linux/amba/clcd.h
- --- linux-3.14.35.orig/include/linux/amba/clcd.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/amba/clcd.h 2015-03-08 14:27:37.841684499 -0500
- @@ -243,6 +243,9 @@
- val |= CNTL_BGR;
- }
-
- + /* Reset the current colour depth */
- + val &= ~CNTL_LCDBPP16_444;
- +
- switch (var->bits_per_pixel) {
- case 1:
- val |= CNTL_LCDBPP1;
- @@ -264,14 +267,15 @@
- */
- if (amba_part(fb->dev) == 0x110 ||
- var->green.length == 5)
- - val |= CNTL_LCDBPP16;
- + val |= CNTL_LCDBPP16 | CNTL_BGR;
- else if (var->green.length == 6)
- - val |= CNTL_LCDBPP16_565;
- + val |= CNTL_LCDBPP16_565 | CNTL_BGR;
- else
- - val |= CNTL_LCDBPP16_444;
- + val |= CNTL_LCDBPP16_444 | CNTL_BGR;
- break;
- case 32:
- val |= CNTL_LCDBPP24;
- + val &= ~CNTL_BGR;
- break;
- }
-
- diff -Nur linux-3.14.35.orig/include/linux/arm-hdlcd.h linux-3.14.35/include/linux/arm-hdlcd.h
- --- linux-3.14.35.orig/include/linux/arm-hdlcd.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/arm-hdlcd.h 2015-03-08 14:27:37.841684499 -0500
- @@ -0,0 +1,122 @@
- +/*
- + * include/linux/arm-hdlcd.h
- + *
- + * Copyright (C) 2011 ARM Limited
- + *
- + * This file is subject to the terms and conditions of the GNU General Public
- + * License. See the file COPYING in the main directory of this archive
- + * for more details.
- + *
- + * ARM HDLCD Controller register definition
- + */
- +
- +#include <linux/fb.h>
- +#include <linux/completion.h>
- +
- +/* register offsets */
- +#define HDLCD_REG_VERSION 0x0000 /* ro */
- +#define HDLCD_REG_INT_RAWSTAT 0x0010 /* rw */
- +#define HDLCD_REG_INT_CLEAR 0x0014 /* wo */
- +#define HDLCD_REG_INT_MASK 0x0018 /* rw */
- +#define HDLCD_REG_INT_STATUS 0x001c /* ro */
- +#define HDLCD_REG_USER_OUT 0x0020 /* rw */
- +#define HDLCD_REG_FB_BASE 0x0100 /* rw */
- +#define HDLCD_REG_FB_LINE_LENGTH 0x0104 /* rw */
- +#define HDLCD_REG_FB_LINE_COUNT 0x0108 /* rw */
- +#define HDLCD_REG_FB_LINE_PITCH 0x010c /* rw */
- +#define HDLCD_REG_BUS_OPTIONS 0x0110 /* rw */
- +#define HDLCD_REG_V_SYNC 0x0200 /* rw */
- +#define HDLCD_REG_V_BACK_PORCH 0x0204 /* rw */
- +#define HDLCD_REG_V_DATA 0x0208 /* rw */
- +#define HDLCD_REG_V_FRONT_PORCH 0x020c /* rw */
- +#define HDLCD_REG_H_SYNC 0x0210 /* rw */
- +#define HDLCD_REG_H_BACK_PORCH 0x0214 /* rw */
- +#define HDLCD_REG_H_DATA 0x0218 /* rw */
- +#define HDLCD_REG_H_FRONT_PORCH 0x021c /* rw */
- +#define HDLCD_REG_POLARITIES 0x0220 /* rw */
- +#define HDLCD_REG_COMMAND 0x0230 /* rw */
- +#define HDLCD_REG_PIXEL_FORMAT 0x0240 /* rw */
- +#define HDLCD_REG_BLUE_SELECT 0x0244 /* rw */
- +#define HDLCD_REG_GREEN_SELECT 0x0248 /* rw */
- +#define HDLCD_REG_RED_SELECT 0x024c /* rw */
- +
- +/* version */
- +#define HDLCD_PRODUCT_ID 0x1CDC0000
- +#define HDLCD_PRODUCT_MASK 0xFFFF0000
- +#define HDLCD_VERSION_MAJOR_MASK 0x0000FF00
- +#define HDLCD_VERSION_MINOR_MASK 0x000000FF
- +
- +/* interrupts */
- +#define HDLCD_INTERRUPT_DMA_END (1 << 0)
- +#define HDLCD_INTERRUPT_BUS_ERROR (1 << 1)
- +#define HDLCD_INTERRUPT_VSYNC (1 << 2)
- +#define HDLCD_INTERRUPT_UNDERRUN (1 << 3)
- +
- +/* polarity */
- +#define HDLCD_POLARITY_VSYNC (1 << 0)
- +#define HDLCD_POLARITY_HSYNC (1 << 1)
- +#define HDLCD_POLARITY_DATAEN (1 << 2)
- +#define HDLCD_POLARITY_DATA (1 << 3)
- +#define HDLCD_POLARITY_PIXELCLK (1 << 4)
- +
- +/* commands */
- +#define HDLCD_COMMAND_DISABLE (0 << 0)
- +#define HDLCD_COMMAND_ENABLE (1 << 0)
- +
- +/* pixel format */
- +#define HDLCD_PIXEL_FMT_LITTLE_ENDIAN (0 << 31)
- +#define HDLCD_PIXEL_FMT_BIG_ENDIAN (1 << 31)
- +#define HDLCD_BYTES_PER_PIXEL_MASK (3 << 3)
- +
- +/* bus options */
- +#define HDLCD_BUS_BURST_MASK 0x01f
- +#define HDLCD_BUS_MAX_OUTSTAND 0xf00
- +#define HDLCD_BUS_BURST_NONE (0 << 0)
- +#define HDLCD_BUS_BURST_1 (1 << 0)
- +#define HDLCD_BUS_BURST_2 (1 << 1)
- +#define HDLCD_BUS_BURST_4 (1 << 2)
- +#define HDLCD_BUS_BURST_8 (1 << 3)
- +#define HDLCD_BUS_BURST_16 (1 << 4)
- +
- +/* Max resolution supported is 4096x4096, 8 bit per color component,
- + 8 bit alpha, but we are going to choose the usual hardware default
- + (2048x2048, 32 bpp) and enable double buffering */
- +#define HDLCD_MAX_XRES 2048
- +#define HDLCD_MAX_YRES 2048
- +#define HDLCD_MAX_FRAMEBUFFER_SIZE (HDLCD_MAX_XRES * HDLCD_MAX_YRES << 2)
- +
- +#define HDLCD_MEM_BASE (CONFIG_PAGE_OFFSET - 0x1000000)
- +
- +#define NR_PALETTE 256
- +
- +/* OEMs using HDLCD may wish to enable these settings if
- + * display disruption is apparent and you suspect HDLCD
- + * access to RAM may be starved.
- + */
- +/* Turn HDLCD default color red instead of black so
- + * that it's easy to see pixel clock data underruns
- + * (compared to other visual disruption)
- + */
- +//#define HDLCD_RED_DEFAULT_COLOUR
- +/* Add a counter in the IRQ handler to count buffer underruns
- + * and /proc/hdlcd_underrun to read the counter
- + */
- +//#define HDLCD_COUNT_BUFFERUNDERRUNS
- +/* Restrict height to 1x screen size
- + *
- + */
- +//#define HDLCD_NO_VIRTUAL_SCREEN
- +
- +#ifdef CONFIG_ANDROID
- +#define HDLCD_NO_VIRTUAL_SCREEN
- +#endif
- +
- +struct hdlcd_device {
- + struct fb_info fb;
- + struct device *dev;
- + struct clk *clk;
- + void __iomem *base;
- + int irq;
- + struct completion vsync_completion;
- + unsigned char *edid;
- +};
- diff -Nur linux-3.14.35.orig/include/linux/backlight.h linux-3.14.35/include/linux/backlight.h
- --- linux-3.14.35.orig/include/linux/backlight.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/backlight.h 2015-03-08 14:27:37.841684499 -0500
- @@ -9,6 +9,7 @@
- #define _LINUX_BACKLIGHT_H
-
- #include <linux/device.h>
- +#include <linux/fb.h>
- #include <linux/mutex.h>
- #include <linux/notifier.h>
-
- @@ -104,6 +105,11 @@
- struct list_head entry;
-
- struct device dev;
- +
- + /* Multiple framebuffers may share one backlight device */
- + bool fb_bl_on[FB_MAX];
- +
- + int use_count;
- };
-
- static inline void backlight_update_status(struct backlight_device *bd)
- diff -Nur linux-3.14.35.orig/include/linux/busfreq-imx6.h linux-3.14.35/include/linux/busfreq-imx6.h
- --- linux-3.14.35.orig/include/linux/busfreq-imx6.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/busfreq-imx6.h 2015-03-08 14:27:37.841684499 -0500
- @@ -0,0 +1,23 @@
- +/*
- + * Copyright 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#ifndef __ASM_ARCH_MXC_BUSFREQ_H__
- +#define __ASM_ARCH_MXC_BUSFREQ_H__
- +
- +/*
- + * This enumerates busfreq mode.
- + */
- +enum bus_freq_mode {
- + BUS_FREQ_HIGH,
- + BUS_FREQ_MED,
- + BUS_FREQ_AUDIO,
- + BUS_FREQ_LOW,
- +};
- +void request_bus_freq(enum bus_freq_mode mode);
- +void release_bus_freq(enum bus_freq_mode mode);
- +#endif
- diff -Nur linux-3.14.35.orig/include/linux/cgroup_subsys.h linux-3.14.35/include/linux/cgroup_subsys.h
- --- linux-3.14.35.orig/include/linux/cgroup_subsys.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/cgroup_subsys.h 2015-03-08 14:27:37.841684499 -0500
- @@ -39,6 +39,10 @@
- SUBSYS(blkio)
- #endif
-
- +#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_BFQIO)
- +SUBSYS(bfqio)
- +#endif
- +
- #if IS_SUBSYS_ENABLED(CONFIG_CGROUP_PERF)
- SUBSYS(perf)
- #endif
- diff -Nur linux-3.14.35.orig/include/linux/clk-provider.h linux-3.14.35/include/linux/clk-provider.h
- --- linux-3.14.35.orig/include/linux/clk-provider.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/clk-provider.h 2015-03-08 14:27:37.841684499 -0500
- @@ -30,6 +30,13 @@
- #define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */
- #define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */
- #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */
- +/*
- + * Basic mux clk, can't switch parent while there is another basic mux clk
- + * being its child. Otherwise, a glitch might be propagated to downstream
- + * clocks through this child mux.
- + */
- +#define CLK_IS_BASIC_MUX BIT(9)
- +
-
- struct clk_hw;
-
- diff -Nur linux-3.14.35.orig/include/linux/cma.h linux-3.14.35/include/linux/cma.h
- --- linux-3.14.35.orig/include/linux/cma.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/cma.h 2015-03-08 14:27:37.841684499 -0500
- @@ -0,0 +1,27 @@
- +#ifndef __CMA_H__
- +#define __CMA_H__
- +
- +/*
- + * There is always at least global CMA area and a few optional
- + * areas configured in kernel .config.
- + */
- +#ifdef CONFIG_CMA_AREAS
- +#define MAX_CMA_AREAS (1 + CONFIG_CMA_AREAS)
- +
- +#else
- +#define MAX_CMA_AREAS (0)
- +
- +#endif
- +
- +struct cma;
- +
- +extern phys_addr_t cma_get_base(struct cma *cma);
- +extern unsigned long cma_get_size(struct cma *cma);
- +
- +extern int __init cma_declare_contiguous(phys_addr_t size,
- + phys_addr_t base, phys_addr_t limit,
- + phys_addr_t alignment, unsigned int order_per_bit,
- + bool fixed, struct cma **res_cma);
- +extern struct page *cma_alloc(struct cma *cma, int count, unsigned int align);
- +extern bool cma_release(struct cma *cma, struct page *pages, int count);
- +#endif
- diff -Nur linux-3.14.35.orig/include/linux/cpufeature.h linux-3.14.35/include/linux/cpufeature.h
- --- linux-3.14.35.orig/include/linux/cpufeature.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/cpufeature.h 2015-03-08 14:27:37.845684499 -0500
- @@ -0,0 +1,60 @@
- +/*
- + * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#ifndef __LINUX_CPUFEATURE_H
- +#define __LINUX_CPUFEATURE_H
- +
- +#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
- +
- +#include <linux/mod_devicetable.h>
- +#include <asm/cpufeature.h>
- +
- +/*
- + * Macros imported from <asm/cpufeature.h>:
- + * - cpu_feature(x) ordinal value of feature called 'x'
- + * - cpu_have_feature(u32 n) whether feature #n is available
- + * - MAX_CPU_FEATURES upper bound for feature ordinal values
- + * Optional:
- + * - CPU_FEATURE_TYPEFMT format string fragment for printing the cpu type
- + * - CPU_FEATURE_TYPEVAL set of values matching the format string above
- + */
- +
- +#ifndef CPU_FEATURE_TYPEFMT
- +#define CPU_FEATURE_TYPEFMT "%s"
- +#endif
- +
- +#ifndef CPU_FEATURE_TYPEVAL
- +#define CPU_FEATURE_TYPEVAL ELF_PLATFORM
- +#endif
- +
- +/*
- + * Use module_cpu_feature_match(feature, module_init_function) to
- + * declare that
- + * a) the module shall be probed upon discovery of CPU feature 'feature'
- + * (typically at boot time using udev)
- + * b) the module must not be loaded if CPU feature 'feature' is not present
- + * (not even by manual insmod).
- + *
- + * For a list of legal values for 'feature', please consult the file
- + * 'asm/cpufeature.h' of your favorite architecture.
- + */
- +#define module_cpu_feature_match(x, __init) \
- +static struct cpu_feature const cpu_feature_match_ ## x[] = \
- + { { .feature = cpu_feature(x) }, { } }; \
- +MODULE_DEVICE_TABLE(cpu, cpu_feature_match_ ## x); \
- + \
- +static int cpu_feature_match_ ## x ## _init(void) \
- +{ \
- + if (!cpu_have_feature(cpu_feature(x))) \
- + return -ENODEV; \
- + return __init(); \
- +} \
- +module_init(cpu_feature_match_ ## x ## _init)
- +
- +#endif
- +#endif
- diff -Nur linux-3.14.35.orig/include/linux/cpufreq.h linux-3.14.35/include/linux/cpufreq.h
- --- linux-3.14.35.orig/include/linux/cpufreq.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/cpufreq.h 2015-03-08 14:27:37.845684499 -0500
- @@ -429,6 +429,9 @@
- #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND)
- extern struct cpufreq_governor cpufreq_gov_ondemand;
- #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_ondemand)
- +#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE)
- +extern struct cpufreq_governor cpufreq_gov_interactive;
- +#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_interactive)
- #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE)
- extern struct cpufreq_governor cpufreq_gov_conservative;
- #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_conservative)
- diff -Nur linux-3.14.35.orig/include/linux/cpu.h linux-3.14.35/include/linux/cpu.h
- --- linux-3.14.35.orig/include/linux/cpu.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/cpu.h 2015-03-08 14:27:37.845684499 -0500
- @@ -226,4 +226,11 @@
- void arch_cpu_idle_exit(void);
- void arch_cpu_idle_dead(void);
-
- +#define IDLE_START 1
- +#define IDLE_END 2
- +
- +void idle_notifier_register(struct notifier_block *n);
- +void idle_notifier_unregister(struct notifier_block *n);
- +void idle_notifier_call_chain(unsigned long val);
- +
- #endif /* _LINUX_CPU_H_ */
- diff -Nur linux-3.14.35.orig/include/linux/device_cooling.h linux-3.14.35/include/linux/device_cooling.h
- --- linux-3.14.35.orig/include/linux/device_cooling.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/device_cooling.h 2015-03-08 14:27:37.845684499 -0500
- @@ -0,0 +1,45 @@
- +/*
- + * Copyright (C) 2013 Freescale Semiconductor, Inc.
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + */
- +
- +#ifndef __DEVICE_THERMAL_H__
- +#define __DEVICE_THERMAL_H__
- +
- +#include <linux/thermal.h>
- +
- +#ifdef CONFIG_DEVICE_THERMAL
- +int register_devfreq_cooling_notifier(struct notifier_block *nb);
- +int unregister_devfreq_cooling_notifier(struct notifier_block *nb);
- +struct thermal_cooling_device *devfreq_cooling_register(void);
- +void devfreq_cooling_unregister(struct thermal_cooling_device *cdev);
- +#else
- +static inline
- +int register_devfreq_cooling_notifier(struct notifier_block *nb)
- +{
- + return 0;
- +}
- +
- +static inline
- +int unregister_devfreq_cooling_notifier(struct notifier_block *nb)
- +{
- + return 0;
- +}
- +
- +static inline
- +struct thermal_cooling_device *devfreq_cooling_register(void)
- +{
- + return NULL;
- +}
- +
- +static inline
- +void devfreq_cooling_unregister(struct thermal_cooling_device *cdev)
- +{
- + return;
- +}
- +#endif
- +#endif /* __DEVICE_THERMAL_H__ */
- diff -Nur linux-3.14.35.orig/include/linux/dma-contiguous.h linux-3.14.35/include/linux/dma-contiguous.h
- --- linux-3.14.35.orig/include/linux/dma-contiguous.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/dma-contiguous.h 2015-03-08 14:27:37.845684499 -0500
- @@ -53,18 +53,13 @@
-
- #ifdef __KERNEL__
-
- +#include <linux/device.h>
- +
- struct cma;
- struct page;
- -struct device;
-
- #ifdef CONFIG_DMA_CMA
-
- -/*
- - * There is always at least global CMA area and a few optional device
- - * private areas configured in kernel .config.
- - */
- -#define MAX_CMA_AREAS (1 + CONFIG_CMA_AREAS)
- -
- extern struct cma *dma_contiguous_default_area;
-
- static inline struct cma *dev_get_cma_area(struct device *dev)
- @@ -88,7 +83,8 @@
- void dma_contiguous_reserve(phys_addr_t addr_limit);
-
- int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
- - phys_addr_t limit, struct cma **res_cma);
- + phys_addr_t limit, struct cma **res_cma,
- + bool fixed);
-
- /**
- * dma_declare_contiguous() - reserve area for contiguous memory handling
- @@ -108,7 +104,7 @@
- {
- struct cma *cma;
- int ret;
- - ret = dma_contiguous_reserve_area(size, base, limit, &cma);
- + ret = dma_contiguous_reserve_area(size, base, limit, &cma, true);
- if (ret == 0)
- dev_set_cma_area(dev, cma);
-
- @@ -122,8 +118,6 @@
-
- #else
-
- -#define MAX_CMA_AREAS (0)
- -
- static inline struct cma *dev_get_cma_area(struct device *dev)
- {
- return NULL;
- @@ -136,7 +130,9 @@
- static inline void dma_contiguous_reserve(phys_addr_t limit) { }
-
- static inline int dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
- - phys_addr_t limit, struct cma **res_cma) {
- + phys_addr_t limit, struct cma **res_cma,
- + bool fixed)
- +{
- return -ENOSYS;
- }
-
- diff -Nur linux-3.14.35.orig/include/linux/dmaengine.h linux-3.14.35/include/linux/dmaengine.h
- --- linux-3.14.35.orig/include/linux/dmaengine.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/dmaengine.h 2015-03-08 14:27:37.849684498 -0500
- @@ -333,6 +333,8 @@
- * @slave_id: Slave requester id. Only valid for slave channels. The dma
- * slave peripheral will have unique id as dma requester which need to be
- * pass as slave config.
- + * @dma_request0: this is the first dma request of this dma channel.
- + * @dma_request1: this is the second dma request of this dma channel.
- *
- * This struct is passed in as configuration data to a DMA engine
- * in order to set up a certain channel for DMA transport at runtime.
- @@ -361,6 +363,8 @@
- u32 dst_maxburst;
- bool device_fc;
- unsigned int slave_id;
- + int dma_request0;
- + int dma_request1;
- };
-
- /**
- diff -Nur linux-3.14.35.orig/include/linux/ftrace.h linux-3.14.35/include/linux/ftrace.h
- --- linux-3.14.35.orig/include/linux/ftrace.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/ftrace.h 2015-03-08 14:27:37.849684498 -0500
- @@ -605,25 +605,27 @@
- #endif
- }
-
- -#ifndef HAVE_ARCH_CALLER_ADDR
- +/* All archs should have this, but we define it for consistency */
- +#ifndef ftrace_return_address0
- +# define ftrace_return_address0 __builtin_return_address(0)
- +#endif
- +
- +/* Archs may use other ways for ADDR1 and beyond */
- +#ifndef ftrace_return_address
- # ifdef CONFIG_FRAME_POINTER
- -# define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
- -# define CALLER_ADDR1 ((unsigned long)__builtin_return_address(1))
- -# define CALLER_ADDR2 ((unsigned long)__builtin_return_address(2))
- -# define CALLER_ADDR3 ((unsigned long)__builtin_return_address(3))
- -# define CALLER_ADDR4 ((unsigned long)__builtin_return_address(4))
- -# define CALLER_ADDR5 ((unsigned long)__builtin_return_address(5))
- -# define CALLER_ADDR6 ((unsigned long)__builtin_return_address(6))
- +# define ftrace_return_address(n) __builtin_return_address(n)
- # else
- -# define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
- -# define CALLER_ADDR1 0UL
- -# define CALLER_ADDR2 0UL
- -# define CALLER_ADDR3 0UL
- -# define CALLER_ADDR4 0UL
- -# define CALLER_ADDR5 0UL
- -# define CALLER_ADDR6 0UL
- +# define ftrace_return_address(n) 0UL
- # endif
- -#endif /* ifndef HAVE_ARCH_CALLER_ADDR */
- +#endif
- +
- +#define CALLER_ADDR0 ((unsigned long)ftrace_return_address0)
- +#define CALLER_ADDR1 ((unsigned long)ftrace_return_address(1))
- +#define CALLER_ADDR2 ((unsigned long)ftrace_return_address(2))
- +#define CALLER_ADDR3 ((unsigned long)ftrace_return_address(3))
- +#define CALLER_ADDR4 ((unsigned long)ftrace_return_address(4))
- +#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
- +#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
-
- #ifdef CONFIG_IRQSOFF_TRACER
- extern void time_hardirqs_on(unsigned long a0, unsigned long a1);
- diff -Nur linux-3.14.35.orig/include/linux/hardirq.h linux-3.14.35/include/linux/hardirq.h
- --- linux-3.14.35.orig/include/linux/hardirq.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/hardirq.h 2015-03-08 14:27:37.849684498 -0500
- @@ -9,6 +9,7 @@
-
-
- extern void synchronize_irq(unsigned int irq);
- +extern void synchronize_hardirq(unsigned int irq);
-
- #if defined(CONFIG_TINY_RCU)
-
- diff -Nur linux-3.14.35.orig/include/linux/hsi/hsi.h linux-3.14.35/include/linux/hsi/hsi.h
- --- linux-3.14.35.orig/include/linux/hsi/hsi.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/hsi/hsi.h 2015-03-08 14:27:37.849684498 -0500
- @@ -178,7 +178,7 @@
- * @complete: Transfer completion callback
- * @destructor: Destructor to free resources when flushing
- * @status: Status of the transfer when completed
- - * @actual_len: Actual length of data transfered on completion
- + * @actual_len: Actual length of data transferred on completion
- * @channel: Channel were to TX/RX the message
- * @ttype: Transfer type (TX if set, RX otherwise)
- * @break_frame: if true HSI will send/receive a break frame. Data buffers are
- diff -Nur linux-3.14.35.orig/include/linux/ipu.h linux-3.14.35/include/linux/ipu.h
- --- linux-3.14.35.orig/include/linux/ipu.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/ipu.h 2015-03-08 14:27:37.849684498 -0500
- @@ -0,0 +1,38 @@
- +/*
- + * Copyright 2005-2013 Freescale Semiconductor, Inc.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU Lesser General
- + * Public License. You may obtain a copy of the GNU Lesser General
- + * Public License Version 2.1 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/lgpl-license.html
- + * http://www.gnu.org/copyleft/lgpl.html
- + */
- +
- +/*!
- + * @defgroup IPU MXC Image Processing Unit (IPU) Driver
- + */
- +/*!
- + * @file linux/ipu.h
- + *
- + * @brief This file contains the IPU driver API declarations.
- + *
- + * @ingroup IPU
- + */
- +
- +#ifndef __LINUX_IPU_H__
- +#define __LINUX_IPU_H__
- +
- +#include <linux/interrupt.h>
- +#include <uapi/linux/ipu.h>
- +
- +unsigned int fmt_to_bpp(unsigned int pixelformat);
- +cs_t colorspaceofpixel(int fmt);
- +int need_csc(int ifmt, int ofmt);
- +
- +int ipu_queue_task(struct ipu_task *task);
- +int ipu_check_task(struct ipu_task *task);
- +
- +#endif
- diff -Nur linux-3.14.35.orig/include/linux/ipu-v3.h linux-3.14.35/include/linux/ipu-v3.h
- --- linux-3.14.35.orig/include/linux/ipu-v3.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/ipu-v3.h 2015-03-08 14:27:37.853684498 -0500
- @@ -0,0 +1,752 @@
- +/*
- + * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
- + * Copyright (C) 2011-2013 Freescale Semiconductor, 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 program is distributed in the hope that it will be useful, but
- + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + */
- +
- +#ifndef __LINUX_IPU_V3_H_
- +#define __LINUX_IPU_V3_H_
- +
- +#include <linux/ipu.h>
- +
- +/* IPU Driver channels definitions. */
- +/* Note these are different from IDMA channels */
- +#define IPU_MAX_CH 32
- +#define _MAKE_CHAN(num, v_in, g_in, a_in, out) \
- + ((num << 24) | (v_in << 18) | (g_in << 12) | (a_in << 6) | out)
- +#define _MAKE_ALT_CHAN(ch) (ch | (IPU_MAX_CH << 24))
- +#define IPU_CHAN_ID(ch) (ch >> 24)
- +#define IPU_CHAN_ALT(ch) (ch & 0x02000000)
- +#define IPU_CHAN_ALPHA_IN_DMA(ch) ((uint32_t) (ch >> 6) & 0x3F)
- +#define IPU_CHAN_GRAPH_IN_DMA(ch) ((uint32_t) (ch >> 12) & 0x3F)
- +#define IPU_CHAN_VIDEO_IN_DMA(ch) ((uint32_t) (ch >> 18) & 0x3F)
- +#define IPU_CHAN_OUT_DMA(ch) ((uint32_t) (ch & 0x3F))
- +#define NO_DMA 0x3F
- +#define ALT 1
- +/*!
- + * Enumeration of IPU logical channels. An IPU logical channel is defined as a
- + * combination of an input (memory to IPU), output (IPU to memory), and/or
- + * secondary input IDMA channels and in some cases an Image Converter task.
- + * Some channels consist of only an input or output.
- + */
- +typedef enum {
- + CHAN_NONE = -1,
- + MEM_ROT_ENC_MEM = _MAKE_CHAN(1, 45, NO_DMA, NO_DMA, 48),
- + MEM_ROT_VF_MEM = _MAKE_CHAN(2, 46, NO_DMA, NO_DMA, 49),
- + MEM_ROT_PP_MEM = _MAKE_CHAN(3, 47, NO_DMA, NO_DMA, 50),
- +
- + MEM_PRP_ENC_MEM = _MAKE_CHAN(4, 12, 14, 17, 20),
- + MEM_PRP_VF_MEM = _MAKE_CHAN(5, 12, 14, 17, 21),
- + MEM_PP_MEM = _MAKE_CHAN(6, 11, 15, 18, 22),
- +
- + MEM_DC_SYNC = _MAKE_CHAN(7, 28, NO_DMA, NO_DMA, NO_DMA),
- + MEM_DC_ASYNC = _MAKE_CHAN(8, 41, NO_DMA, NO_DMA, NO_DMA),
- + MEM_BG_SYNC = _MAKE_CHAN(9, 23, NO_DMA, 51, NO_DMA),
- + MEM_FG_SYNC = _MAKE_CHAN(10, 27, NO_DMA, 31, NO_DMA),
- +
- + MEM_BG_ASYNC0 = _MAKE_CHAN(11, 24, NO_DMA, 52, NO_DMA),
- + MEM_FG_ASYNC0 = _MAKE_CHAN(12, 29, NO_DMA, 33, NO_DMA),
- + MEM_BG_ASYNC1 = _MAKE_ALT_CHAN(MEM_BG_ASYNC0),
- + MEM_FG_ASYNC1 = _MAKE_ALT_CHAN(MEM_FG_ASYNC0),
- +
- + DIRECT_ASYNC0 = _MAKE_CHAN(13, NO_DMA, NO_DMA, NO_DMA, NO_DMA),
- + DIRECT_ASYNC1 = _MAKE_CHAN(14, NO_DMA, NO_DMA, NO_DMA, NO_DMA),
- +
- + CSI_MEM0 = _MAKE_CHAN(15, NO_DMA, NO_DMA, NO_DMA, 0),
- + CSI_MEM1 = _MAKE_CHAN(16, NO_DMA, NO_DMA, NO_DMA, 1),
- + CSI_MEM2 = _MAKE_CHAN(17, NO_DMA, NO_DMA, NO_DMA, 2),
- + CSI_MEM3 = _MAKE_CHAN(18, NO_DMA, NO_DMA, NO_DMA, 3),
- +
- + CSI_MEM = CSI_MEM0,
- +
- + CSI_PRP_ENC_MEM = _MAKE_CHAN(19, NO_DMA, NO_DMA, NO_DMA, 20),
- + CSI_PRP_VF_MEM = _MAKE_CHAN(20, NO_DMA, NO_DMA, NO_DMA, 21),
- +
- + /* for vdi mem->vdi->ic->mem , add graphics plane and alpha*/
- + MEM_VDI_PRP_VF_MEM_P = _MAKE_CHAN(21, 8, 14, 17, 21),
- + MEM_VDI_PRP_VF_MEM = _MAKE_CHAN(22, 9, 14, 17, 21),
- + MEM_VDI_PRP_VF_MEM_N = _MAKE_CHAN(23, 10, 14, 17, 21),
- +
- + /* for vdi mem->vdi->mem */
- + MEM_VDI_MEM_P = _MAKE_CHAN(24, 8, NO_DMA, NO_DMA, 5),
- + MEM_VDI_MEM = _MAKE_CHAN(25, 9, NO_DMA, NO_DMA, 5),
- + MEM_VDI_MEM_N = _MAKE_CHAN(26, 10, NO_DMA, NO_DMA, 5),
- +
- + /* fake channel for vdoa to link with IPU */
- + MEM_VDOA_MEM = _MAKE_CHAN(27, NO_DMA, NO_DMA, NO_DMA, NO_DMA),
- +
- + MEM_PP_ADC = CHAN_NONE,
- + ADC_SYS2 = CHAN_NONE,
- +
- +} ipu_channel_t;
- +
- +/*!
- + * Enumeration of types of buffers for a logical channel.
- + */
- +typedef enum {
- + IPU_OUTPUT_BUFFER = 0, /*!< Buffer for output from IPU */
- + IPU_ALPHA_IN_BUFFER = 1, /*!< Buffer for input to IPU */
- + IPU_GRAPH_IN_BUFFER = 2, /*!< Buffer for input to IPU */
- + IPU_VIDEO_IN_BUFFER = 3, /*!< Buffer for input to IPU */
- + IPU_INPUT_BUFFER = IPU_VIDEO_IN_BUFFER,
- + IPU_SEC_INPUT_BUFFER = IPU_GRAPH_IN_BUFFER,
- +} ipu_buffer_t;
- +
- +#define IPU_PANEL_SERIAL 1
- +#define IPU_PANEL_PARALLEL 2
- +
- +/*!
- + * Enumeration of ADC channel operation mode.
- + */
- +typedef enum {
- + Disable,
- + WriteTemplateNonSeq,
- + ReadTemplateNonSeq,
- + WriteTemplateUnCon,
- + ReadTemplateUnCon,
- + WriteDataWithRS,
- + WriteDataWoRS,
- + WriteCmd
- +} mcu_mode_t;
- +
- +/*!
- + * Enumeration of ADC channel addressing mode.
- + */
- +typedef enum {
- + FullWoBE,
- + FullWithBE,
- + XY
- +} display_addressing_t;
- +
- +/*!
- + * Union of initialization parameters for a logical channel.
- + */
- +typedef union {
- + struct {
- + uint32_t csi;
- + uint32_t mipi_id;
- + uint32_t mipi_vc;
- + bool mipi_en;
- + bool interlaced;
- + } csi_mem;
- + struct {
- + uint32_t in_width;
- + uint32_t in_height;
- + uint32_t in_pixel_fmt;
- + uint32_t out_width;
- + uint32_t out_height;
- + uint32_t out_pixel_fmt;
- + uint32_t outh_resize_ratio;
- + uint32_t outv_resize_ratio;
- + uint32_t csi;
- + uint32_t mipi_id;
- + uint32_t mipi_vc;
- + bool mipi_en;
- + } csi_prp_enc_mem;
- + struct {
- + uint32_t in_width;
- + uint32_t in_height;
- + uint32_t in_pixel_fmt;
- + uint32_t out_width;
- + uint32_t out_height;
- + uint32_t out_pixel_fmt;
- + uint32_t outh_resize_ratio;
- + uint32_t outv_resize_ratio;
- + } mem_prp_enc_mem;
- + struct {
- + uint32_t in_width;
- + uint32_t in_height;
- + uint32_t in_pixel_fmt;
- + uint32_t out_width;
- + uint32_t out_height;
- + uint32_t out_pixel_fmt;
- + } mem_rot_enc_mem;
- + struct {
- + uint32_t in_width;
- + uint32_t in_height;
- + uint32_t in_pixel_fmt;
- + uint32_t out_width;
- + uint32_t out_height;
- + uint32_t out_pixel_fmt;
- + uint32_t outh_resize_ratio;
- + uint32_t outv_resize_ratio;
- + bool graphics_combine_en;
- + bool global_alpha_en;
- + bool key_color_en;
- + uint32_t in_g_pixel_fmt;
- + uint8_t alpha;
- + uint32_t key_color;
- + bool alpha_chan_en;
- + ipu_motion_sel motion_sel;
- + enum v4l2_field field_fmt;
- + uint32_t csi;
- + uint32_t mipi_id;
- + uint32_t mipi_vc;
- + bool mipi_en;
- + } csi_prp_vf_mem;
- + struct {
- + uint32_t in_width;
- + uint32_t in_height;
- + uint32_t in_pixel_fmt;
- + uint32_t out_width;
- + uint32_t out_height;
- + uint32_t out_pixel_fmt;
- + bool graphics_combine_en;
- + bool global_alpha_en;
- + bool key_color_en;
- + display_port_t disp;
- + uint32_t out_left;
- + uint32_t out_top;
- + } csi_prp_vf_adc;
- + struct {
- + uint32_t in_width;
- + uint32_t in_height;
- + uint32_t in_pixel_fmt;
- + uint32_t out_width;
- + uint32_t out_height;
- + uint32_t out_pixel_fmt;
- + uint32_t outh_resize_ratio;
- + uint32_t outv_resize_ratio;
- + bool graphics_combine_en;
- + bool global_alpha_en;
- + bool key_color_en;
- + uint32_t in_g_pixel_fmt;
- + uint8_t alpha;
- + uint32_t key_color;
- + bool alpha_chan_en;
- + ipu_motion_sel motion_sel;
- + enum v4l2_field field_fmt;
- + } mem_prp_vf_mem;
- + struct {
- + uint32_t temp;
- + } mem_prp_vf_adc;
- + struct {
- + uint32_t temp;
- + } mem_rot_vf_mem;
- + struct {
- + uint32_t in_width;
- + uint32_t in_height;
- + uint32_t in_pixel_fmt;
- + uint32_t out_width;
- + uint32_t out_height;
- + uint32_t out_pixel_fmt;
- + uint32_t outh_resize_ratio;
- + uint32_t outv_resize_ratio;
- + bool graphics_combine_en;
- + bool global_alpha_en;
- + bool key_color_en;
- + uint32_t in_g_pixel_fmt;
- + uint8_t alpha;
- + uint32_t key_color;
- + bool alpha_chan_en;
- + } mem_pp_mem;
- + struct {
- + uint32_t temp;
- + } mem_rot_mem;
- + struct {
- + uint32_t in_width;
- + uint32_t in_height;
- + uint32_t in_pixel_fmt;
- + uint32_t out_width;
- + uint32_t out_height;
- + uint32_t out_pixel_fmt;
- + bool graphics_combine_en;
- + bool global_alpha_en;
- + bool key_color_en;
- + display_port_t disp;
- + uint32_t out_left;
- + uint32_t out_top;
- + } mem_pp_adc;
- + struct {
- + uint32_t di;
- + bool interlaced;
- + uint32_t in_pixel_fmt;
- + uint32_t out_pixel_fmt;
- + } mem_dc_sync;
- + struct {
- + uint32_t temp;
- + } mem_sdc_fg;
- + struct {
- + uint32_t di;
- + bool interlaced;
- + uint32_t in_pixel_fmt;
- + uint32_t out_pixel_fmt;
- + bool alpha_chan_en;
- + } mem_dp_bg_sync;
- + struct {
- + uint32_t temp;
- + } mem_sdc_bg;
- + struct {
- + uint32_t di;
- + bool interlaced;
- + uint32_t in_pixel_fmt;
- + uint32_t out_pixel_fmt;
- + bool alpha_chan_en;
- + } mem_dp_fg_sync;
- + struct {
- + uint32_t di;
- + } direct_async;
- + struct {
- + display_port_t disp;
- + mcu_mode_t ch_mode;
- + uint32_t out_left;
- + uint32_t out_top;
- + } adc_sys1;
- + struct {
- + display_port_t disp;
- + mcu_mode_t ch_mode;
- + uint32_t out_left;
- + uint32_t out_top;
- + } adc_sys2;
- +} ipu_channel_params_t;
- +
- +/*
- + * IPU_IRQF_ONESHOT - Interrupt is not reenabled after the irq handler finished.
- + */
- +#define IPU_IRQF_NONE 0x00000000
- +#define IPU_IRQF_ONESHOT 0x00000001
- +
- +/*!
- + * Enumeration of IPU interrupt sources.
- + */
- +enum ipu_irq_line {
- + IPU_IRQ_CSI0_OUT_EOF = 0,
- + IPU_IRQ_CSI1_OUT_EOF = 1,
- + IPU_IRQ_CSI2_OUT_EOF = 2,
- + IPU_IRQ_CSI3_OUT_EOF = 3,
- + IPU_IRQ_VDIC_OUT_EOF = 5,
- + IPU_IRQ_VDI_P_IN_EOF = 8,
- + IPU_IRQ_VDI_C_IN_EOF = 9,
- + IPU_IRQ_VDI_N_IN_EOF = 10,
- + IPU_IRQ_PP_IN_EOF = 11,
- + IPU_IRQ_PRP_IN_EOF = 12,
- + IPU_IRQ_PRP_GRAPH_IN_EOF = 14,
- + IPU_IRQ_PP_GRAPH_IN_EOF = 15,
- + IPU_IRQ_PRP_ALPHA_IN_EOF = 17,
- + IPU_IRQ_PP_ALPHA_IN_EOF = 18,
- + IPU_IRQ_PRP_ENC_OUT_EOF = 20,
- + IPU_IRQ_PRP_VF_OUT_EOF = 21,
- + IPU_IRQ_PP_OUT_EOF = 22,
- + IPU_IRQ_BG_SYNC_EOF = 23,
- + IPU_IRQ_BG_ASYNC_EOF = 24,
- + IPU_IRQ_FG_SYNC_EOF = 27,
- + IPU_IRQ_DC_SYNC_EOF = 28,
- + IPU_IRQ_FG_ASYNC_EOF = 29,
- + IPU_IRQ_FG_ALPHA_SYNC_EOF = 31,
- +
- + IPU_IRQ_FG_ALPHA_ASYNC_EOF = 33,
- + IPU_IRQ_DC_READ_EOF = 40,
- + IPU_IRQ_DC_ASYNC_EOF = 41,
- + IPU_IRQ_DC_CMD1_EOF = 42,
- + IPU_IRQ_DC_CMD2_EOF = 43,
- + IPU_IRQ_DC_MASK_EOF = 44,
- + IPU_IRQ_PRP_ENC_ROT_IN_EOF = 45,
- + IPU_IRQ_PRP_VF_ROT_IN_EOF = 46,
- + IPU_IRQ_PP_ROT_IN_EOF = 47,
- + IPU_IRQ_PRP_ENC_ROT_OUT_EOF = 48,
- + IPU_IRQ_PRP_VF_ROT_OUT_EOF = 49,
- + IPU_IRQ_PP_ROT_OUT_EOF = 50,
- + IPU_IRQ_BG_ALPHA_SYNC_EOF = 51,
- + IPU_IRQ_BG_ALPHA_ASYNC_EOF = 52,
- +
- + IPU_IRQ_BG_SYNC_NFACK = 64 + 23,
- + IPU_IRQ_FG_SYNC_NFACK = 64 + 27,
- + IPU_IRQ_DC_SYNC_NFACK = 64 + 28,
- +
- + IPU_IRQ_DP_SF_START = 448 + 2,
- + IPU_IRQ_DP_SF_END = 448 + 3,
- + IPU_IRQ_BG_SF_END = IPU_IRQ_DP_SF_END,
- + IPU_IRQ_DC_FC_0 = 448 + 8,
- + IPU_IRQ_DC_FC_1 = 448 + 9,
- + IPU_IRQ_DC_FC_2 = 448 + 10,
- + IPU_IRQ_DC_FC_3 = 448 + 11,
- + IPU_IRQ_DC_FC_4 = 448 + 12,
- + IPU_IRQ_DC_FC_6 = 448 + 13,
- + IPU_IRQ_VSYNC_PRE_0 = 448 + 14,
- + IPU_IRQ_VSYNC_PRE_1 = 448 + 15,
- +
- + IPU_IRQ_COUNT
- +};
- +
- +/*!
- + * Bitfield of Display Interface signal polarities.
- + */
- +typedef struct {
- + unsigned datamask_en:1;
- + unsigned int_clk:1;
- + unsigned interlaced:1;
- + unsigned odd_field_first:1;
- + unsigned clksel_en:1;
- + unsigned clkidle_en:1;
- + unsigned data_pol:1; /* true = inverted */
- + unsigned clk_pol:1; /* true = rising edge */
- + unsigned enable_pol:1;
- + unsigned Hsync_pol:1; /* true = active high */
- + unsigned Vsync_pol:1;
- +} ipu_di_signal_cfg_t;
- +
- +/*!
- + * Bitfield of CSI signal polarities and modes.
- + */
- +
- +typedef struct {
- + unsigned data_width:4;
- + unsigned clk_mode:3;
- + unsigned ext_vsync:1;
- + unsigned Vsync_pol:1;
- + unsigned Hsync_pol:1;
- + unsigned pixclk_pol:1;
- + unsigned data_pol:1;
- + unsigned sens_clksrc:1;
- + unsigned pack_tight:1;
- + unsigned force_eof:1;
- + unsigned data_en_pol:1;
- + unsigned data_fmt;
- + unsigned csi;
- + unsigned mclk;
- +} ipu_csi_signal_cfg_t;
- +
- +/*!
- + * Enumeration of CSI data bus widths.
- + */
- +enum {
- + IPU_CSI_DATA_WIDTH_4 = 0,
- + IPU_CSI_DATA_WIDTH_8 = 1,
- + IPU_CSI_DATA_WIDTH_10 = 3,
- + IPU_CSI_DATA_WIDTH_16 = 9,
- +};
- +
- +/*!
- + * Enumeration of CSI clock modes.
- + */
- +enum {
- + IPU_CSI_CLK_MODE_GATED_CLK,
- + IPU_CSI_CLK_MODE_NONGATED_CLK,
- + IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE,
- + IPU_CSI_CLK_MODE_CCIR656_INTERLACED,
- + IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR,
- + IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR,
- + IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR,
- + IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR,
- +};
- +
- +enum {
- + IPU_CSI_MIPI_DI0,
- + IPU_CSI_MIPI_DI1,
- + IPU_CSI_MIPI_DI2,
- + IPU_CSI_MIPI_DI3,
- +};
- +
- +typedef enum {
- + RGB,
- + YCbCr,
- + YUV
- +} ipu_color_space_t;
- +
- +/*!
- + * Enumeration of ADC vertical sync mode.
- + */
- +typedef enum {
- + VsyncNone,
- + VsyncInternal,
- + VsyncCSI,
- + VsyncExternal
- +} vsync_t;
- +
- +typedef enum {
- + DAT,
- + CMD
- +} cmddata_t;
- +
- +/*!
- + * Enumeration of ADC display update mode.
- + */
- +typedef enum {
- + IPU_ADC_REFRESH_NONE,
- + IPU_ADC_AUTO_REFRESH,
- + IPU_ADC_AUTO_REFRESH_SNOOP,
- + IPU_ADC_SNOOPING,
- +} ipu_adc_update_mode_t;
- +
- +/*!
- + * Enumeration of ADC display interface types (serial or parallel).
- + */
- +enum {
- + IPU_ADC_IFC_MODE_SYS80_TYPE1,
- + IPU_ADC_IFC_MODE_SYS80_TYPE2,
- + IPU_ADC_IFC_MODE_SYS68K_TYPE1,
- + IPU_ADC_IFC_MODE_SYS68K_TYPE2,
- + IPU_ADC_IFC_MODE_3WIRE_SERIAL,
- + IPU_ADC_IFC_MODE_4WIRE_SERIAL,
- + IPU_ADC_IFC_MODE_5WIRE_SERIAL_CLK,
- + IPU_ADC_IFC_MODE_5WIRE_SERIAL_CS,
- +};
- +
- +enum {
- + IPU_ADC_IFC_WIDTH_8,
- + IPU_ADC_IFC_WIDTH_16,
- +};
- +
- +/*!
- + * Enumeration of ADC display interface burst mode.
- + */
- +enum {
- + IPU_ADC_BURST_WCS,
- + IPU_ADC_BURST_WBLCK,
- + IPU_ADC_BURST_NONE,
- + IPU_ADC_BURST_SERIAL,
- +};
- +
- +/*!
- + * Enumeration of ADC display interface RW signal timing modes.
- + */
- +enum {
- + IPU_ADC_SER_NO_RW,
- + IPU_ADC_SER_RW_BEFORE_RS,
- + IPU_ADC_SER_RW_AFTER_RS,
- +};
- +
- +/*!
- + * Bitfield of ADC signal polarities and modes.
- + */
- +typedef struct {
- + unsigned data_pol:1;
- + unsigned clk_pol:1;
- + unsigned cs_pol:1;
- + unsigned rs_pol:1;
- + unsigned addr_pol:1;
- + unsigned read_pol:1;
- + unsigned write_pol:1;
- + unsigned Vsync_pol:1;
- + unsigned burst_pol:1;
- + unsigned burst_mode:2;
- + unsigned ifc_mode:3;
- + unsigned ifc_width:5;
- + unsigned ser_preamble_len:4;
- + unsigned ser_preamble:8;
- + unsigned ser_rw_mode:2;
- +} ipu_adc_sig_cfg_t;
- +
- +/*!
- + * Enumeration of ADC template commands.
- + */
- +enum {
- + RD_DATA,
- + RD_ACK,
- + RD_WAIT,
- + WR_XADDR,
- + WR_YADDR,
- + WR_ADDR,
- + WR_CMND,
- + WR_DATA,
- +};
- +
- +/*!
- + * Enumeration of ADC template command flow control.
- + */
- +enum {
- + SINGLE_STEP,
- + PAUSE,
- + STOP,
- +};
- +
- +
- +/*Define template constants*/
- +#define ATM_ADDR_RANGE 0x20 /*offset address of DISP */
- +#define TEMPLATE_BUF_SIZE 0x20 /*size of template */
- +
- +/*!
- + * Define to create ADC template command entry.
- + */
- +#define ipu_adc_template_gen(oc, rs, fc, dat) (((rs) << 29) | ((fc) << 27) | \
- + ((oc) << 24) | (dat))
- +
- +typedef struct {
- + u32 reg;
- + u32 value;
- +} ipu_lpmc_reg_t;
- +
- +#define IPU_LPMC_REG_READ 0x80000000L
- +
- +#define CSI_MCLK_VF 1
- +#define CSI_MCLK_ENC 2
- +#define CSI_MCLK_RAW 4
- +#define CSI_MCLK_I2C 8
- +
- +struct ipu_soc;
- +/* Common IPU API */
- +struct ipu_soc *ipu_get_soc(int id);
- +int32_t ipu_init_channel(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel_params_t *params);
- +void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel);
- +void ipu_disable_hsp_clk(struct ipu_soc *ipu);
- +
- +static inline bool ipu_can_rotate_in_place(ipu_rotate_mode_t rot)
- +{
- +#ifdef CONFIG_MXC_IPU_V3D
- + return (rot < IPU_ROTATE_HORIZ_FLIP);
- +#else
- + return (rot < IPU_ROTATE_90_RIGHT);
- +#endif
- +}
- +
- +int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
- + uint32_t pixel_fmt,
- + uint16_t width, uint16_t height,
- + uint32_t stride,
- + ipu_rotate_mode_t rot_mode,
- + dma_addr_t phyaddr_0, dma_addr_t phyaddr_1,
- + dma_addr_t phyaddr_2,
- + uint32_t u_offset, uint32_t v_offset);
- +
- +int32_t ipu_update_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
- + uint32_t bufNum, dma_addr_t phyaddr);
- +
- +int32_t ipu_update_channel_offset(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
- + uint32_t pixel_fmt,
- + uint16_t width, uint16_t height,
- + uint32_t stride,
- + uint32_t u, uint32_t v,
- + uint32_t vertical_offset, uint32_t horizontal_offset);
- +
- +int32_t ipu_select_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
- + ipu_buffer_t type, uint32_t bufNum);
- +int32_t ipu_select_multi_vdi_buffer(struct ipu_soc *ipu, uint32_t bufNum);
- +
- +int32_t ipu_link_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch);
- +int32_t ipu_unlink_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch);
- +
- +int32_t ipu_is_channel_busy(struct ipu_soc *ipu, ipu_channel_t channel);
- +int32_t ipu_check_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
- + uint32_t bufNum);
- +void ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
- + uint32_t bufNum);
- +uint32_t ipu_get_cur_buffer_idx(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type);
- +int32_t ipu_enable_channel(struct ipu_soc *ipu, ipu_channel_t channel);
- +int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wait_for_stop);
- +int32_t ipu_swap_channel(struct ipu_soc *ipu, ipu_channel_t from_ch, ipu_channel_t to_ch);
- +uint32_t ipu_channel_status(struct ipu_soc *ipu, ipu_channel_t channel);
- +
- +int32_t ipu_enable_csi(struct ipu_soc *ipu, uint32_t csi);
- +int32_t ipu_disable_csi(struct ipu_soc *ipu, uint32_t csi);
- +
- +int ipu_lowpwr_display_enable(void);
- +int ipu_lowpwr_display_disable(void);
- +
- +int ipu_enable_irq(struct ipu_soc *ipu, uint32_t irq);
- +void ipu_disable_irq(struct ipu_soc *ipu, uint32_t irq);
- +void ipu_clear_irq(struct ipu_soc *ipu, uint32_t irq);
- +int ipu_request_irq(struct ipu_soc *ipu, uint32_t irq,
- + irqreturn_t(*handler) (int, void *),
- + uint32_t irq_flags, const char *devname, void *dev_id);
- +void ipu_free_irq(struct ipu_soc *ipu, uint32_t irq, void *dev_id);
- +bool ipu_get_irq_status(struct ipu_soc *ipu, uint32_t irq);
- +void ipu_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3]);
- +int32_t ipu_set_channel_bandmode(struct ipu_soc *ipu, ipu_channel_t channel,
- + ipu_buffer_t type, uint32_t band_height);
- +
- +/* two stripe calculations */
- +struct stripe_param{
- + unsigned int input_width; /* width of the input stripe */
- + unsigned int output_width; /* width of the output stripe */
- + unsigned int input_column; /* the first column on the input stripe */
- + unsigned int output_column; /* the first column on the output stripe */
- + unsigned int idr;
- + /* inverse downisizing ratio parameter; expressed as a power of 2 */
- + unsigned int irr;
- + /* inverse resizing ratio parameter; expressed as a multiple of 2^-13 */
- +};
- +int ipu_calc_stripes_sizes(const unsigned int input_frame_width,
- + unsigned int output_frame_width,
- + const unsigned int maximal_stripe_width,
- + const unsigned long long cirr,
- + const unsigned int equal_stripes,
- + u32 input_pixelformat,
- + u32 output_pixelformat,
- + struct stripe_param *left,
- + struct stripe_param *right);
- +
- +/* SDC API */
- +int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp,
- + uint32_t pixel_clk,
- + uint16_t width, uint16_t height,
- + uint32_t pixel_fmt,
- + uint16_t h_start_width, uint16_t h_sync_width,
- + uint16_t h_end_width, uint16_t v_start_width,
- + uint16_t v_sync_width, uint16_t v_end_width,
- + uint32_t v_to_h_sync, ipu_di_signal_cfg_t sig);
- +
- +void ipu_uninit_sync_panel(struct ipu_soc *ipu, int disp);
- +
- +int32_t ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel, int16_t x_pos,
- + int16_t y_pos);
- +int32_t ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel, int16_t *x_pos,
- + int16_t *y_pos);
- +int32_t ipu_disp_set_global_alpha(struct ipu_soc *ipu, ipu_channel_t channel, bool enable,
- + uint8_t alpha);
- +int32_t ipu_disp_set_color_key(struct ipu_soc *ipu, ipu_channel_t channel, bool enable,
- + uint32_t colorKey);
- +int32_t ipu_disp_set_gamma_correction(struct ipu_soc *ipu, ipu_channel_t channel, bool enable,
- + int constk[], int slopek[]);
- +
- +int ipu_init_async_panel(struct ipu_soc *ipu, int disp, int type, uint32_t cycle_time,
- + uint32_t pixel_fmt, ipu_adc_sig_cfg_t sig);
- +void ipu_disp_direct_write(struct ipu_soc *ipu, ipu_channel_t channel, u32 value, u32 offset);
- +void ipu_reset_disp_panel(struct ipu_soc *ipu);
- +
- +/* CMOS Sensor Interface API */
- +int32_t ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
- + uint32_t pixel_fmt, ipu_csi_signal_cfg_t sig);
- +
- +int32_t ipu_csi_get_sensor_protocol(struct ipu_soc *ipu, uint32_t csi);
- +
- +int32_t ipu_csi_enable_mclk(struct ipu_soc *ipu, int src, bool flag, bool wait);
- +
- +static inline int32_t ipu_csi_enable_mclk_if(struct ipu_soc *ipu, int src, uint32_t csi,
- + bool flag, bool wait)
- +{
- + return ipu_csi_enable_mclk(ipu, csi, flag, wait);
- +}
- +
- +int ipu_csi_read_mclk_flag(void);
- +
- +void ipu_csi_flash_strobe(bool flag);
- +
- +void ipu_csi_get_window_size(struct ipu_soc *ipu, uint32_t *width, uint32_t *height, uint32_t csi);
- +
- +void ipu_csi_set_window_size(struct ipu_soc *ipu, uint32_t width, uint32_t height, uint32_t csi);
- +
- +void ipu_csi_set_window_pos(struct ipu_soc *ipu, uint32_t left, uint32_t top, uint32_t csi);
- +
- +uint32_t bytes_per_pixel(uint32_t fmt);
- +
- +bool ipu_ch_param_bad_alpha_pos(uint32_t fmt);
- +
- +struct ipuv3_fb_platform_data {
- + char disp_dev[32];
- + u32 interface_pix_fmt;
- + char *mode_str;
- + int default_bpp;
- + bool int_clk;
- +
- + /* reserved mem */
- + resource_size_t res_base[2];
- + resource_size_t res_size[2];
- +
- + /*
- + * Late init to avoid display channel being
- + * re-initialized as we've probably setup the
- + * channel in bootloader.
- + */
- + bool late_init;
- +};
- +
- +#endif /* __LINUX_IPU_V3_H_ */
- diff -Nur linux-3.14.35.orig/include/linux/isl29023.h linux-3.14.35/include/linux/isl29023.h
- --- linux-3.14.35.orig/include/linux/isl29023.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/isl29023.h 2015-03-08 14:27:37.853684498 -0500
- @@ -0,0 +1,47 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#ifndef __ISL29023_H__
- +#define __ISL29023_H__
- +
- +#include <linux/types.h>
- +
- +#define ISL29023_PD_MODE 0x0
- +#define ISL29023_ALS_ONCE_MODE 0x1
- +#define ISL29023_IR_ONCE_MODE 0x2
- +#define ISL29023_ALS_CONT_MODE 0x5
- +#define ISL29023_IR_CONT_MODE 0x6
- +
- +#define ISL29023_INT_PERSISTS_1 0x0
- +#define ISL29023_INT_PERSISTS_4 0x1
- +#define ISL29023_INT_PERSISTS_8 0x2
- +#define ISL29023_INT_PERSISTS_16 0x3
- +
- +#define ISL29023_RES_16 0x0
- +#define ISL29023_RES_12 0x1
- +#define ISL29023_RES_8 0x2
- +#define ISL29023_RES_4 0x3
- +
- +#define ISL29023_RANGE_1K 0x0
- +#define ISL29023_RANGE_4K 0x1
- +#define ISL29023_RANGE_16K 0x2
- +#define ISL29023_RANGE_64K 0x3
- +
- +#endif
- diff -Nur linux-3.14.35.orig/include/linux/kfifo.h linux-3.14.35/include/linux/kfifo.h
- --- linux-3.14.35.orig/include/linux/kfifo.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/kfifo.h 2015-03-08 14:27:37.853684498 -0500
- @@ -722,7 +722,7 @@
- /**
- * kfifo_dma_out_finish - finish a DMA OUT operation
- * @fifo: address of the fifo to be used
- - * @len: number of bytes transferd
- + * @len: number of bytes transferrd
- *
- * This macro finish a DMA OUT operation. The out counter will be updated by
- * the len parameter. No error checking will be done.
- diff -Nur linux-3.14.35.orig/include/linux/mailbox_client.h linux-3.14.35/include/linux/mailbox_client.h
- --- linux-3.14.35.orig/include/linux/mailbox_client.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/mailbox_client.h 2015-03-08 14:27:37.853684498 -0500
- @@ -0,0 +1,46 @@
- +/*
- + * Copyright (C) 2014 Linaro Ltd.
- + * Author: Jassi Brar <jassisinghbrar@gmail.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#ifndef __MAILBOX_CLIENT_H
- +#define __MAILBOX_CLIENT_H
- +
- +#include <linux/of.h>
- +
- +struct mbox_chan;
- +
- +/**
- + * struct mbox_client - User of a mailbox
- + * @dev: The client device
- + * @chan_name: The "controller:channel" this client wants
- + * @rx_callback: Atomic callback to provide client the data received
- + * @tx_done: Atomic callback to tell client of data transmission
- + * @tx_block: If the mbox_send_message should block until data is
- + * transmitted.
- + * @tx_tout: Max block period in ms before TX is assumed failure
- + * @knows_txdone: if the client could run the TX state machine. Usually
- + * if the client receives some ACK packet for transmission.
- + * Unused if the controller already has TX_Done/RTR IRQ.
- + */
- +struct mbox_client {
- + struct device *dev;
- + const char *chan_name;
- + void (*rx_callback)(struct mbox_client *cl, void *mssg);
- + void (*tx_done)(struct mbox_client *cl, void *mssg, int r);
- + bool tx_block;
- + unsigned long tx_tout;
- + bool knows_txdone;
- +};
- +
- +struct mbox_chan *mbox_request_channel(struct mbox_client *cl);
- +int mbox_send_message(struct mbox_chan *chan, void *mssg);
- +void mbox_client_txdone(struct mbox_chan *chan, int r);
- +bool mbox_client_peek_data(struct mbox_chan *chan);
- +void mbox_free_channel(struct mbox_chan *chan);
- +
- +#endif /* __MAILBOX_CLIENT_H */
- diff -Nur linux-3.14.35.orig/include/linux/mailbox_controller.h linux-3.14.35/include/linux/mailbox_controller.h
- --- linux-3.14.35.orig/include/linux/mailbox_controller.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/mailbox_controller.h 2015-03-08 14:27:37.853684498 -0500
- @@ -0,0 +1,121 @@
- +/*
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#ifndef __MAILBOX_CONTROLLER_H
- +#define __MAILBOX_CONTROLLER_H
- +
- +#include <linux/of.h>
- +
- +struct mbox_chan;
- +
- +/**
- + * struct mbox_chan_ops - s/w representation of a communication chan
- + * @send_data: The API asks the MBOX controller driver, in atomic
- + * context try to transmit a message on the bus. Returns 0 if
- + * data is accepted for transmission, -EBUSY while rejecting
- + * if the remote hasn't yet read the last data sent. Actual
- + * transmission of data is reported by the controller via
- + * mbox_chan_txdone (if it has some TX ACK irq). It must not
- + * block.
- + * @startup: Called when a client requests the chan. The controller
- + * could ask clients for additional parameters of communication
- + * to be provided via client's chan_data. This call may
- + * block. After this call the Controller must forward any
- + * data received on the chan by calling mbox_chan_received_data.
- + * @shutdown: Called when a client relinquishes control of a chan.
- + * This call may block too. The controller must not forwared
- + * any received data anymore.
- + * @last_tx_done: If the controller sets 'txdone_poll', the API calls
- + * this to poll status of last TX. The controller must
- + * give priority to IRQ method over polling and never
- + * set both txdone_poll and txdone_irq. Only in polling
- + * mode 'send_data' is expected to return -EBUSY.
- + * Used only if txdone_poll:=true && txdone_irq:=false
- + * @peek_data: Atomic check for any received data. Return true if controller
- + * has some data to push to the client. False otherwise.
- + */
- +struct mbox_chan_ops {
- + int (*send_data)(struct mbox_chan *chan, void *data);
- + int (*startup)(struct mbox_chan *chan);
- + void (*shutdown)(struct mbox_chan *chan);
- + bool (*last_tx_done)(struct mbox_chan *chan);
- + bool (*peek_data)(struct mbox_chan *chan);
- +};
- +
- +/**
- + * struct mbox_controller - Controller of a class of communication chans
- + * @dev: Device backing this controller
- + * @controller_name: Literal name of the controller.
- + * @ops: Operators that work on each communication chan
- + * @chans: Null terminated array of chans.
- + * @txdone_irq: Indicates if the controller can report to API when
- + * the last transmitted data was read by the remote.
- + * Eg, if it has some TX ACK irq.
- + * @txdone_poll: If the controller can read but not report the TX
- + * done. Ex, some register shows the TX status but
- + * no interrupt rises. Ignored if 'txdone_irq' is set.
- + * @txpoll_period: If 'txdone_poll' is in effect, the API polls for
- + * last TX's status after these many millisecs
- + */
- +struct mbox_controller {
- + struct device *dev;
- + struct mbox_chan_ops *ops;
- + struct mbox_chan *chans;
- + int num_chans;
- + bool txdone_irq;
- + bool txdone_poll;
- + unsigned txpoll_period;
- + struct mbox_chan *(*of_xlate)(struct mbox_controller *mbox,
- + const struct of_phandle_args *sp);
- + /*
- + * If the controller supports only TXDONE_BY_POLL,
- + * this timer polls all the links for txdone.
- + */
- + struct timer_list poll;
- + unsigned period;
- + /* Hook to add to the global controller list */
- + struct list_head node;
- +};
- +
- +/*
- + * The length of circular buffer for queuing messages from a client.
- + * 'msg_count' tracks the number of buffered messages while 'msg_free'
- + * is the index where the next message would be buffered.
- + * We shouldn't need it too big because every transferr is interrupt
- + * triggered and if we have lots of data to transfer, the interrupt
- + * latencies are going to be the bottleneck, not the buffer length.
- + * Besides, mbox_send_message could be called from atomic context and
- + * the client could also queue another message from the notifier 'tx_done'
- + * of the last transfer done.
- + * REVIST: If too many platforms see the "Try increasing MBOX_TX_QUEUE_LEN"
- + * print, it needs to be taken from config option or somesuch.
- + */
- +#define MBOX_TX_QUEUE_LEN 20
- +
- +struct mbox_chan {
- + struct mbox_controller *mbox; /* Parent Controller */
- + unsigned txdone_method;
- +
- + /* client */
- + struct mbox_client *cl;
- + struct completion tx_complete;
- +
- + void *active_req;
- + unsigned msg_count, msg_free;
- + void *msg_data[MBOX_TX_QUEUE_LEN];
- + /* Access to the channel */
- + spinlock_t lock;
- +
- + /* Private data for controller */
- + void *con_priv;
- +};
- +
- +int mbox_controller_register(struct mbox_controller *mbox);
- +void mbox_chan_received_data(struct mbox_chan *chan, void *data);
- +void mbox_chan_txdone(struct mbox_chan *chan, int r);
- +void mbox_controller_unregister(struct mbox_controller *mbox);
- +
- +#endif /* __MAILBOX_CONTROLLER_H */
- diff -Nur linux-3.14.35.orig/include/linux/mailbox.h linux-3.14.35/include/linux/mailbox.h
- --- linux-3.14.35.orig/include/linux/mailbox.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/mailbox.h 1969-12-31 18:00:00.000000000 -0600
- @@ -1,17 +0,0 @@
- -/*
- - * This program is free software; you can redistribute it and/or modify it
- - * under the terms and conditions of the GNU General Public License,
- - * version 2, as published by the Free Software Foundation.
- - *
- - * This program is distributed in the hope it will be useful, but WITHOUT
- - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- - * more details.
- - *
- - * You should have received a copy of the GNU General Public License along with
- - * this program. If not, see <http://www.gnu.org/licenses/>.
- - */
- -
- -int pl320_ipc_transmit(u32 *data);
- -int pl320_ipc_register_notifier(struct notifier_block *nb);
- -int pl320_ipc_unregister_notifier(struct notifier_block *nb);
- diff -Nur linux-3.14.35.orig/include/linux/memblock.h linux-3.14.35/include/linux/memblock.h
- --- linux-3.14.35.orig/include/linux/memblock.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/memblock.h 2015-03-08 14:27:37.861684499 -0500
- @@ -221,6 +221,8 @@
- #define MEMBLOCK_ALLOC_ANYWHERE (~(phys_addr_t)0)
- #define MEMBLOCK_ALLOC_ACCESSIBLE 0
-
- +phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align,
- + phys_addr_t start, phys_addr_t end);
- phys_addr_t memblock_alloc_base(phys_addr_t size, phys_addr_t align,
- phys_addr_t max_addr);
- phys_addr_t __memblock_alloc_base(phys_addr_t size, phys_addr_t align,
- diff -Nur linux-3.14.35.orig/include/linux/mfd/abx500/ab8500.h linux-3.14.35/include/linux/mfd/abx500/ab8500.h
- --- linux-3.14.35.orig/include/linux/mfd/abx500/ab8500.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/mfd/abx500/ab8500.h 2015-03-08 14:27:37.865684498 -0500
- @@ -347,7 +347,6 @@
- struct mutex lock;
- struct mutex irq_lock;
- atomic_t transfer_ongoing;
- - int irq_base;
- int irq;
- struct irq_domain *domain;
- enum ab8500_version version;
- @@ -378,7 +377,6 @@
- * @regulator: machine-specific constraints for regulators
- */
- struct ab8500_platform_data {
- - int irq_base;
- void (*init) (struct ab8500 *);
- struct ab8500_regulator_platform_data *regulator;
- struct ab8500_codec_platform_data *codec;
- diff -Nur linux-3.14.35.orig/include/linux/mfd/dbx500-prcmu.h linux-3.14.35/include/linux/mfd/dbx500-prcmu.h
- --- linux-3.14.35.orig/include/linux/mfd/dbx500-prcmu.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/mfd/dbx500-prcmu.h 2015-03-08 14:27:37.865684498 -0500
- @@ -183,8 +183,6 @@
- bool enable_set_ddr_opp;
- bool enable_ape_opp_100_voltage;
- struct ab8500_platform_data *ab_platdata;
- - int ab_irq;
- - int irq_base;
- u32 version_offset;
- u32 legacy_offset;
- u32 adt_offset;
- diff -Nur linux-3.14.35.orig/include/linux/mfd/mxc-hdmi-core.h linux-3.14.35/include/linux/mfd/mxc-hdmi-core.h
- --- linux-3.14.35.orig/include/linux/mfd/mxc-hdmi-core.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/mfd/mxc-hdmi-core.h 2015-03-08 14:27:37.865684498 -0500
- @@ -0,0 +1,68 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + */
- +#ifndef __LINUX_MXC_HDMI_CORE_H_
- +#define __LINUX_MXC_HDMI_CORE_H_
- +
- +#include <video/mxc_edid.h>
- +
- +#include <sound/core.h>
- +#include <sound/pcm.h>
- +#include <sound/pcm_params.h>
- +#include <sound/soc.h>
- +
- +#define IRQ_DISABLE_SUCCEED 0
- +#define IRQ_DISABLE_FAIL 1
- +
- +bool hdmi_check_overflow(void);
- +
- +u8 hdmi_readb(unsigned int reg);
- +void hdmi_writeb(u8 value, unsigned int reg);
- +void hdmi_mask_writeb(u8 data, unsigned int addr, u8 shift, u8 mask);
- +unsigned int hdmi_read4(unsigned int reg);
- +void hdmi_write4(unsigned int value, unsigned int reg);
- +
- +void hdmi_irq_init(void);
- +void hdmi_irq_enable(int irq);
- +unsigned int hdmi_irq_disable(int irq);
- +
- +void hdmi_set_sample_rate(unsigned int rate);
- +void hdmi_set_dma_mode(unsigned int dma_running);
- +void hdmi_init_clk_regenerator(void);
- +void hdmi_clk_regenerator_update_pixel_clock(u32 pixclock);
- +
- +void hdmi_set_edid_cfg(int edid_status, struct mxc_edid_cfg *cfg);
- +int hdmi_get_edid_cfg(struct mxc_edid_cfg *cfg);
- +
- +extern int mxc_hdmi_ipu_id;
- +extern int mxc_hdmi_disp_id;
- +
- +void hdmi_set_registered(int registered);
- +int hdmi_get_registered(void);
- +int mxc_hdmi_abort_stream(void);
- +int mxc_hdmi_register_audio(struct snd_pcm_substream *substream);
- +void mxc_hdmi_unregister_audio(struct snd_pcm_substream *substream);
- +void hdmi_set_dvi_mode(unsigned int state);
- +unsigned int hdmi_set_cable_state(unsigned int state);
- +unsigned int hdmi_set_blank_state(unsigned int state);
- +int check_hdmi_state(void);
- +
- +void hdmi_cec_start_device(void);
- +void hdmi_cec_stop_device(void);
- +
- +#endif
- diff -Nur linux-3.14.35.orig/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h linux-3.14.35/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
- --- linux-3.14.35.orig/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h 2015-03-08 14:27:37.865684498 -0500
- @@ -1,5 +1,5 @@
- /*
- - * Copyright (C) 2012 Freescale Semiconductor, Inc.
- + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- @@ -122,7 +122,9 @@
- #define IMX6Q_GPR1_USB_OTG_ID_SEL_MASK BIT(13)
- #define IMX6Q_GPR1_USB_OTG_ID_SEL_ENET_RX_ER 0x0
- #define IMX6Q_GPR1_USB_OTG_ID_SEL_GPIO_1 BIT(13)
- -#define IMX6Q_GPR1_GINT BIT(12)
- +#define IMX6Q_GPR1_GINT_MASK BIT(12)
- +#define IMX6Q_GPR1_GINT_CLEAR 0x0
- +#define IMX6Q_GPR1_GINT_ASSERT BIT(12)
- #define IMX6Q_GPR1_ADDRS3_MASK (0x3 << 10)
- #define IMX6Q_GPR1_ADDRS3_32MB (0x0 << 10)
- #define IMX6Q_GPR1_ADDRS3_64MB (0x1 << 10)
- diff -Nur linux-3.14.35.orig/include/linux/mipi_csi2.h linux-3.14.35/include/linux/mipi_csi2.h
- --- linux-3.14.35.orig/include/linux/mipi_csi2.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/mipi_csi2.h 2015-03-08 14:27:37.865684498 -0500
- @@ -0,0 +1,93 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#ifndef __INCLUDE_MIPI_CSI2_H
- +#define __INCLUDE_MIPI_CSI2_H
- +
- +/* MIPI CSI2 registers */
- +#define MIPI_CSI2_REG(offset) (offset)
- +
- +#define MIPI_CSI2_VERSION MIPI_CSI2_REG(0x000)
- +#define MIPI_CSI2_N_LANES MIPI_CSI2_REG(0x004)
- +#define MIPI_CSI2_PHY_SHUTDOWNZ MIPI_CSI2_REG(0x008)
- +#define MIPI_CSI2_DPHY_RSTZ MIPI_CSI2_REG(0x00c)
- +#define MIPI_CSI2_CSI2_RESETN MIPI_CSI2_REG(0x010)
- +#define MIPI_CSI2_PHY_STATE MIPI_CSI2_REG(0x014)
- +#define MIPI_CSI2_DATA_IDS_1 MIPI_CSI2_REG(0x018)
- +#define MIPI_CSI2_DATA_IDS_2 MIPI_CSI2_REG(0x01c)
- +#define MIPI_CSI2_ERR1 MIPI_CSI2_REG(0x020)
- +#define MIPI_CSI2_ERR2 MIPI_CSI2_REG(0x024)
- +#define MIPI_CSI2_MASK1 MIPI_CSI2_REG(0x028)
- +#define MIPI_CSI2_MASK2 MIPI_CSI2_REG(0x02c)
- +#define MIPI_CSI2_PHY_TST_CTRL0 MIPI_CSI2_REG(0x030)
- +#define MIPI_CSI2_PHY_TST_CTRL1 MIPI_CSI2_REG(0x034)
- +#define MIPI_CSI2_SFT_RESET MIPI_CSI2_REG(0xf00)
- +
- +/* mipi data type */
- +#define MIPI_DT_YUV420 0x18 /* YYY.../UYVY.... */
- +#define MIPI_DT_YUV420_LEGACY 0x1a /* UYY.../VYY... */
- +#define MIPI_DT_YUV422 0x1e /* UYVY... */
- +#define MIPI_DT_RGB444 0x20
- +#define MIPI_DT_RGB555 0x21
- +#define MIPI_DT_RGB565 0x22
- +#define MIPI_DT_RGB666 0x23
- +#define MIPI_DT_RGB888 0x24
- +#define MIPI_DT_RAW6 0x28
- +#define MIPI_DT_RAW7 0x29
- +#define MIPI_DT_RAW8 0x2a
- +#define MIPI_DT_RAW10 0x2b
- +#define MIPI_DT_RAW12 0x2c
- +#define MIPI_DT_RAW14 0x2d
- +
- +
- +struct mipi_csi2_info;
- +/* mipi csi2 API */
- +struct mipi_csi2_info *mipi_csi2_get_info(void);
- +
- +bool mipi_csi2_enable(struct mipi_csi2_info *info);
- +
- +bool mipi_csi2_disable(struct mipi_csi2_info *info);
- +
- +bool mipi_csi2_get_status(struct mipi_csi2_info *info);
- +
- +int mipi_csi2_get_bind_ipu(struct mipi_csi2_info *info);
- +
- +unsigned int mipi_csi2_get_bind_csi(struct mipi_csi2_info *info);
- +
- +unsigned int mipi_csi2_get_virtual_channel(struct mipi_csi2_info *info);
- +
- +unsigned int mipi_csi2_set_lanes(struct mipi_csi2_info *info);
- +
- +unsigned int mipi_csi2_set_datatype(struct mipi_csi2_info *info,
- + unsigned int datatype);
- +
- +unsigned int mipi_csi2_get_datatype(struct mipi_csi2_info *info);
- +
- +unsigned int mipi_csi2_dphy_status(struct mipi_csi2_info *info);
- +
- +unsigned int mipi_csi2_get_error1(struct mipi_csi2_info *info);
- +
- +unsigned int mipi_csi2_get_error2(struct mipi_csi2_info *info);
- +
- +int mipi_csi2_pixelclk_enable(struct mipi_csi2_info *info);
- +
- +void mipi_csi2_pixelclk_disable(struct mipi_csi2_info *info);
- +
- +int mipi_csi2_reset(struct mipi_csi2_info *info);
- +
- +#endif
- diff -Nur linux-3.14.35.orig/include/linux/mipi_dsi.h linux-3.14.35/include/linux/mipi_dsi.h
- --- linux-3.14.35.orig/include/linux/mipi_dsi.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/mipi_dsi.h 2015-03-08 14:27:37.865684498 -0500
- @@ -0,0 +1,171 @@
- +/*
- + * Copyright (C) 2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#ifndef __INCLUDE_MIPI_DSI_H
- +#define __INCLUDE_MIPI_DSI_H
- +
- +#define MIPI_DSI_VERSION (0x000)
- +#define MIPI_DSI_PWR_UP (0x004)
- +#define MIPI_DSI_CLKMGR_CFG (0x008)
- +#define MIPI_DSI_DPI_CFG (0x00c)
- +#define MIPI_DSI_DBI_CFG (0x010)
- +#define MIPI_DSI_DBIS_CMDSIZE (0x014)
- +#define MIPI_DSI_PCKHDL_CFG (0x018)
- +#define MIPI_DSI_VID_MODE_CFG (0x01c)
- +#define MIPI_DSI_VID_PKT_CFG (0x020)
- +#define MIPI_DSI_CMD_MODE_CFG (0x024)
- +#define MIPI_DSI_TMR_LINE_CFG (0x028)
- +#define MIPI_DSI_VTIMING_CFG (0x02c)
- +#define MIPI_DSI_PHY_TMR_CFG (0x030)
- +#define MIPI_DSI_GEN_HDR (0x034)
- +#define MIPI_DSI_GEN_PLD_DATA (0x038)
- +#define MIPI_DSI_CMD_PKT_STATUS (0x03c)
- +#define MIPI_DSI_TO_CNT_CFG (0x040)
- +#define MIPI_DSI_ERROR_ST0 (0x044)
- +#define MIPI_DSI_ERROR_ST1 (0x048)
- +#define MIPI_DSI_ERROR_MSK0 (0x04c)
- +#define MIPI_DSI_ERROR_MSK1 (0x050)
- +#define MIPI_DSI_PHY_RSTZ (0x054)
- +#define MIPI_DSI_PHY_IF_CFG (0x058)
- +#define MIPI_DSI_PHY_IF_CTRL (0x05c)
- +#define MIPI_DSI_PHY_STATUS (0x060)
- +#define MIPI_DSI_PHY_TST_CTRL0 (0x064)
- +#define MIPI_DSI_PHY_TST_CTRL1 (0x068)
- +
- +#define DSI_PWRUP_RESET (0x0 << 0)
- +#define DSI_PWRUP_POWERUP (0x1 << 0)
- +
- +#define DSI_DPI_CFG_VID_SHIFT (0)
- +#define DSI_DPI_CFG_VID_MASK (0x3)
- +#define DSI_DPI_CFG_COLORCODE_SHIFT (2)
- +#define DSI_DPI_CFG_COLORCODE_MASK (0x7)
- +#define DSI_DPI_CFG_DATAEN_ACT_LOW (0x1 << 5)
- +#define DSI_DPI_CFG_DATAEN_ACT_HIGH (0x0 << 5)
- +#define DSI_DPI_CFG_VSYNC_ACT_LOW (0x1 << 6)
- +#define DSI_DPI_CFG_VSYNC_ACT_HIGH (0x0 << 6)
- +#define DSI_DPI_CFG_HSYNC_ACT_LOW (0x1 << 7)
- +#define DSI_DPI_CFG_HSYNC_ACT_HIGH (0x0 << 7)
- +#define DSI_DPI_CFG_SHUTD_ACT_LOW (0x1 << 8)
- +#define DSI_DPI_CFG_SHUTD_ACT_HIGH (0x0 << 8)
- +#define DSI_DPI_CFG_COLORMODE_ACT_LOW (0x1 << 9)
- +#define DSI_DPI_CFG_COLORMODE_ACT_HIGH (0x0 << 9)
- +#define DSI_DPI_CFG_EN18LOOSELY (0x1 << 10)
- +
- +#define DSI_PCKHDL_CFG_EN_EOTP_TX (0x1 << 0)
- +#define DSI_PCKHDL_CFG_EN_EOTP_RX (0x1 << 1)
- +#define DSI_PCKHDL_CFG_EN_BTA (0x1 << 2)
- +#define DSI_PCKHDL_CFG_EN_ECC_RX (0x1 << 3)
- +#define DSI_PCKHDL_CFG_EN_CRC_RX (0x1 << 4)
- +#define DSI_PCKHDL_CFG_GEN_VID_RX_MASK (0x3)
- +#define DSI_PCKHDL_CFG_GEN_VID_RX_SHIFT (5)
- +
- +#define DSI_VID_MODE_CFG_EN (0x1 << 0)
- +#define DSI_VID_MODE_CFG_EN_BURSTMODE (0x3 << 1)
- +#define DSI_VID_MODE_CFG_TYPE_MASK (0x3)
- +#define DSI_VID_MODE_CFG_TYPE_SHIFT (1)
- +#define DSI_VID_MODE_CFG_EN_LP_VSA (0x1 << 3)
- +#define DSI_VID_MODE_CFG_EN_LP_VBP (0x1 << 4)
- +#define DSI_VID_MODE_CFG_EN_LP_VFP (0x1 << 5)
- +#define DSI_VID_MODE_CFG_EN_LP_VACT (0x1 << 6)
- +#define DSI_VID_MODE_CFG_EN_LP_HBP (0x1 << 7)
- +#define DSI_VID_MODE_CFG_EN_LP_HFP (0x1 << 8)
- +#define DSI_VID_MODE_CFG_EN_MULTI_PKT (0x1 << 9)
- +#define DSI_VID_MODE_CFG_EN_NULL_PKT (0x1 << 10)
- +#define DSI_VID_MODE_CFG_EN_FRAME_ACK (0x1 << 11)
- +#define DSI_VID_MODE_CFG_EN_LP_MODE (DSI_VID_MODE_CFG_EN_LP_VSA | \
- + DSI_VID_MODE_CFG_EN_LP_VBP | \
- + DSI_VID_MODE_CFG_EN_LP_VFP | \
- + DSI_VID_MODE_CFG_EN_LP_HFP | \
- + DSI_VID_MODE_CFG_EN_LP_HBP | \
- + DSI_VID_MODE_CFG_EN_LP_VACT)
- +
- +
- +
- +#define DSI_VID_PKT_CFG_VID_PKT_SZ_MASK (0x7ff)
- +#define DSI_VID_PKT_CFG_VID_PKT_SZ_SHIFT (0)
- +#define DSI_VID_PKT_CFG_NUM_CHUNKS_MASK (0x3ff)
- +#define DSI_VID_PKT_CFG_NUM_CHUNKS_SHIFT (11)
- +#define DSI_VID_PKT_CFG_NULL_PKT_SZ_MASK (0x3ff)
- +#define DSI_VID_PKT_CFG_NULL_PKT_SZ_SHIFT (21)
- +
- +#define MIPI_DSI_CMD_MODE_CFG_EN_LOWPOWER (0x1FFF)
- +#define MIPI_DSI_CMD_MODE_CFG_EN_CMD_MODE (0x1 << 0)
- +
- +#define DSI_TME_LINE_CFG_HSA_TIME_MASK (0x1ff)
- +#define DSI_TME_LINE_CFG_HSA_TIME_SHIFT (0)
- +#define DSI_TME_LINE_CFG_HBP_TIME_MASK (0x1ff)
- +#define DSI_TME_LINE_CFG_HBP_TIME_SHIFT (9)
- +#define DSI_TME_LINE_CFG_HLINE_TIME_MASK (0x3fff)
- +#define DSI_TME_LINE_CFG_HLINE_TIME_SHIFT (18)
- +
- +#define DSI_VTIMING_CFG_VSA_LINES_MASK (0xf)
- +#define DSI_VTIMING_CFG_VSA_LINES_SHIFT (0)
- +#define DSI_VTIMING_CFG_VBP_LINES_MASK (0x3f)
- +#define DSI_VTIMING_CFG_VBP_LINES_SHIFT (4)
- +#define DSI_VTIMING_CFG_VFP_LINES_MASK (0x3f)
- +#define DSI_VTIMING_CFG_VFP_LINES_SHIFT (10)
- +#define DSI_VTIMING_CFG_V_ACT_LINES_MASK (0x7ff)
- +#define DSI_VTIMING_CFG_V_ACT_LINES_SHIFT (16)
- +
- +#define DSI_PHY_TMR_CFG_BTA_TIME_MASK (0xfff)
- +#define DSI_PHY_TMR_CFG_BTA_TIME_SHIFT (0)
- +#define DSI_PHY_TMR_CFG_LP2HS_TIME_MASK (0xff)
- +#define DSI_PHY_TMR_CFG_LP2HS_TIME_SHIFT (12)
- +#define DSI_PHY_TMR_CFG_HS2LP_TIME_MASK (0xff)
- +#define DSI_PHY_TMR_CFG_HS2LP_TIME_SHIFT (20)
- +
- +#define DSI_PHY_IF_CFG_N_LANES_MASK (0x3)
- +#define DSI_PHY_IF_CFG_N_LANES_SHIFT (0)
- +#define DSI_PHY_IF_CFG_WAIT_TIME_MASK (0xff)
- +#define DSI_PHY_IF_CFG_WAIT_TIME_SHIFT (2)
- +
- +#define DSI_PHY_RSTZ_EN_CLK (0x1 << 2)
- +#define DSI_PHY_RSTZ_DISABLE_RST (0x1 << 1)
- +#define DSI_PHY_RSTZ_DISABLE_SHUTDOWN (0x1 << 0)
- +#define DSI_PHY_RSTZ_RST (0x0)
- +
- +#define DSI_PHY_STATUS_LOCK (0x1 << 0)
- +#define DSI_PHY_STATUS_STOPSTATE_CLK_LANE (0x1 << 2)
- +
- +#define DSI_GEN_HDR_TYPE_MASK (0xff)
- +#define DSI_GEN_HDR_TYPE_SHIFT (0)
- +#define DSI_GEN_HDR_DATA_MASK (0xffff)
- +#define DSI_GEN_HDR_DATA_SHIFT (8)
- +
- +#define DSI_CMD_PKT_STATUS_GEN_CMD_EMPTY (0x1 << 0)
- +#define DSI_CMD_PKT_STATUS_GEN_CMD_FULL (0x1 << 1)
- +#define DSI_CMD_PKT_STATUS_GEN_PLD_W_EMPTY (0x1 << 2)
- +#define DSI_CMD_PKT_STATUS_GEN_PLD_W_FULL (0x1 << 3)
- +#define DSI_CMD_PKT_STATUS_GEN_PLD_R_EMPTY (0x1 << 4)
- +#define DSI_CMD_PKT_STATUS_GEN_RD_CMD_BUSY (0x1 << 6)
- +
- +#define DSI_ERROR_MSK0_ALL_MASK (0x1fffff)
- +#define DSI_ERROR_MSK1_ALL_MASK (0x3ffff)
- +
- +#define DSI_PHY_IF_CTRL_RESET (0x0)
- +#define DSI_PHY_IF_CTRL_TX_REQ_CLK_HS (0x1 << 0)
- +#define DSI_PHY_IF_CTRL_TX_REQ_CLK_ULPS (0x1 << 1)
- +#define DSI_PHY_IF_CTRL_TX_EXIT_CLK_ULPS (0x1 << 2)
- +#define DSI_PHY_IF_CTRL_TX_REQ_DATA_ULPS (0x1 << 3)
- +#define DSI_PHY_IF_CTRL_TX_EXIT_DATA_ULPS (0x1 << 4)
- +#define DSI_PHY_IF_CTRL_TX_TRIG_MASK (0xF)
- +#define DSI_PHY_IF_CTRL_TX_TRIG_SHIFT (5)
- +
- +#define DSI_PHY_CLK_INIT_COMMAND (0x44)
- +#define DSI_GEN_PLD_DATA_BUF_SIZE (0x4)
- +#endif
- diff -Nur linux-3.14.35.orig/include/linux/mmc/card.h linux-3.14.35/include/linux/mmc/card.h
- --- linux-3.14.35.orig/include/linux/mmc/card.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/mmc/card.h 2015-03-08 14:27:37.869684498 -0500
- @@ -86,10 +86,13 @@
- unsigned int data_sector_size; /* 512 bytes or 4KB */
- unsigned int data_tag_unit_size; /* DATA TAG UNIT size */
- unsigned int boot_ro_lock; /* ro lock support */
- + unsigned int boot_size;
- bool boot_ro_lockable;
- u8 raw_exception_status; /* 54 */
- u8 raw_partition_support; /* 160 */
- u8 raw_rpmb_size_mult; /* 168 */
- + u8 boot_bus_width; /* 177 */
- + u8 boot_config; /* 179 */
- u8 raw_erased_mem_count; /* 181 */
- u8 raw_ext_csd_structure; /* 194 */
- u8 raw_card_type; /* 196 */
- @@ -102,6 +105,7 @@
- u8 raw_hc_erase_gap_size; /* 221 */
- u8 raw_erase_timeout_mult; /* 223 */
- u8 raw_hc_erase_grp_size; /* 224 */
- + u8 boot_info; /* 228 */
- u8 raw_sec_trim_mult; /* 229 */
- u8 raw_sec_erase_mult; /* 230 */
- u8 raw_sec_feature_support;/* 231 */
- diff -Nur linux-3.14.35.orig/include/linux/mmc/host.h linux-3.14.35/include/linux/mmc/host.h
- --- linux-3.14.35.orig/include/linux/mmc/host.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/mmc/host.h 2015-03-08 14:27:37.869684498 -0500
- @@ -282,6 +282,7 @@
- MMC_CAP2_PACKED_WR)
- #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */
- #define MMC_CAP2_SANITIZE (1 << 15) /* Support Sanitize */
- +#define MMC_CAP2_SDIO_NOTHREAD (1 << 16)
-
- mmc_pm_flag_t pm_caps; /* supported pm features */
-
- @@ -297,6 +298,11 @@
- unsigned long clkgate_delay;
- #endif
-
- + /* card specific properties to deal with power and reset */
- + struct regulator *card_regulator; /* External VCC needed by the card */
- + struct gpio_desc *card_reset_gpios[2]; /* External resets, active low */
- + struct clk *card_clk; /* External clock needed by the card */
- +
- /* host specific block data */
- unsigned int max_seg_size; /* see blk_queue_max_segment_size */
- unsigned short max_segs; /* see blk_queue_max_segments */
- @@ -397,6 +403,8 @@
- wake_up_process(host->sdio_irq_thread);
- }
-
- +void sdio_run_irqs(struct mmc_host *host);
- +
- #ifdef CONFIG_REGULATOR
- int mmc_regulator_get_ocrmask(struct regulator *supply);
- int mmc_regulator_set_ocr(struct mmc_host *mmc,
- diff -Nur linux-3.14.35.orig/include/linux/mmc/mmc.h linux-3.14.35/include/linux/mmc/mmc.h
- --- linux-3.14.35.orig/include/linux/mmc/mmc.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/mmc/mmc.h 2015-03-08 14:27:37.869684498 -0500
- @@ -292,6 +292,7 @@
- #define EXT_CSD_RPMB_MULT 168 /* RO */
- #define EXT_CSD_BOOT_WP 173 /* R/W */
- #define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */
- +#define EXT_CSD_BOOT_BUS_WIDTH 177 /* R/W */
- #define EXT_CSD_PART_CONFIG 179 /* R/W */
- #define EXT_CSD_ERASED_MEM_CONT 181 /* RO */
- #define EXT_CSD_BUS_WIDTH 183 /* R/W */
- @@ -313,6 +314,7 @@
- #define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */
- #define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */
- #define EXT_CSD_BOOT_MULT 226 /* RO */
- +#define EXT_CSD_BOOT_INFO 228 /* RO, 1 bytes */
- #define EXT_CSD_SEC_TRIM_MULT 229 /* RO */
- #define EXT_CSD_SEC_ERASE_MULT 230 /* RO */
- #define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */
- @@ -378,6 +380,29 @@
- #define EXT_CSD_SEC_GB_CL_EN BIT(4)
- #define EXT_CSD_SEC_SANITIZE BIT(6) /* v4.5 only */
-
- +#define EXT_CSD_BOOT_BUS_WIDTH_MASK (0x1F)
- +#define EXT_CSD_BOOT_BUS_WIDTH_MODE_MASK (0x3 << 3)
- +#define EXT_CSD_BOOT_BUS_WIDTH_MODE_SDR_NORMAL (0x0)
- +#define EXT_CSD_BOOT_BUS_WIDTH_MODE_SDR_HIGH (0x1)
- +#define EXT_CSD_BOOT_BUS_WIDTH_MODE_DDR (0x2)
- +#define EXT_CSD_BOOT_BUS_WIDTH_RST_WIDTH (1 << 2)
- +#define EXT_CSD_BOOT_BUS_WIDTH_WIDTH_MASK (0x3)
- +#define EXT_CSD_BOOT_BUS_WIDTH_1_SDR_4_DDR (0x0)
- +#define EXT_CSD_BOOT_BUS_WIDTH_4_SDR_4_DDR (0x1)
- +#define EXT_CSD_BOOT_BUS_WIDTH_8_SDR_8_DDR (0x2)
- +
- +#define EXT_CSD_BOOT_ACK_ENABLE (0x1 << 6)
- +#define EXT_CSD_BOOT_PARTITION_ENABLE_MASK (0x7 << 3)
- +#define EXT_CSD_BOOT_PARTITION_DISABLE (0x0)
- +#define EXT_CSD_BOOT_PARTITION_PART1 (0x1 << 3)
- +#define EXT_CSD_BOOT_PARTITION_PART2 (0x2 << 3)
- +#define EXT_CSD_BOOT_PARTITION_USER (0x7 << 3)
- +
- +#define EXT_CSD_BOOT_PARTITION_ACCESS_MASK (0x7)
- +#define EXT_CSD_BOOT_PARTITION_ACCESS_DISABLE (0x0)
- +#define EXT_CSD_BOOT_PARTITION_ACCESS_PART1 (0x1)
- +#define EXT_CSD_BOOT_PARTITION_ACCESS_PART2 (0x2)
- +
- #define EXT_CSD_RST_N_EN_MASK 0x3
- #define EXT_CSD_RST_N_ENABLED 1 /* RST_n is enabled on card */
-
- diff -Nur linux-3.14.35.orig/include/linux/mmc/sdhci.h linux-3.14.35/include/linux/mmc/sdhci.h
- --- linux-3.14.35.orig/include/linux/mmc/sdhci.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/mmc/sdhci.h 2015-03-08 14:27:37.869684498 -0500
- @@ -57,12 +57,8 @@
- #define SDHCI_QUIRK_BROKEN_CARD_DETECTION (1<<15)
- /* Controller reports inverted write-protect state */
- #define SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1<<16)
- -/* Controller has nonstandard clock management */
- -#define SDHCI_QUIRK_NONSTANDARD_CLOCK (1<<17)
- /* Controller does not like fast PIO transfers */
- #define SDHCI_QUIRK_PIO_NEEDS_DELAY (1<<18)
- -/* Controller losing signal/interrupt enable states after reset */
- -#define SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET (1<<19)
- /* Controller has to be forced to use block size of 2048 bytes */
- #define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1<<20)
- /* Controller cannot do multi-block transfers */
- @@ -100,6 +96,7 @@
- #define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1<<5)
- /* Controller does not support HS200 */
- #define SDHCI_QUIRK2_BROKEN_HS200 (1<<6)
- +#define SDHCI_QUIRK2_NOSTD_TIMEOUT_COUNTER (1<<7)
-
- int irq; /* Device IRQ */
- void __iomem *ioaddr; /* Mapped address */
- @@ -145,6 +142,7 @@
-
- bool runtime_suspended; /* Host is runtime suspended */
- bool bus_on; /* Bus power prevents runtime suspend */
- + bool preset_enabled; /* Preset is enabled */
-
- struct mmc_request *mrq; /* Current request */
- struct mmc_command *cmd; /* Current command */
- @@ -162,8 +160,7 @@
- dma_addr_t adma_addr; /* Mapped ADMA descr. table */
- dma_addr_t align_addr; /* Mapped bounce buffer */
-
- - struct tasklet_struct card_tasklet; /* Tasklet structures */
- - struct tasklet_struct finish_tasklet;
- + struct tasklet_struct finish_tasklet; /* Tasklet structures */
-
- struct timer_list timer; /* Timer for timeouts */
-
- @@ -175,6 +172,13 @@
- unsigned int ocr_avail_mmc;
- u32 ocr_mask; /* available voltages */
-
- + unsigned timing; /* Current timing */
- +
- + u32 thread_isr;
- +
- + /* cached registers */
- + u32 ier;
- +
- wait_queue_head_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */
- unsigned int tuning_done; /* Condition flag set when CMD19 succeeds */
-
- diff -Nur linux-3.14.35.orig/include/linux/mmc/sdio_ids.h linux-3.14.35/include/linux/mmc/sdio_ids.h
- --- linux-3.14.35.orig/include/linux/mmc/sdio_ids.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/mmc/sdio_ids.h 2015-03-08 14:27:37.869684498 -0500
- @@ -31,6 +31,7 @@
- #define SDIO_DEVICE_ID_BROADCOM_4334 0x4334
- #define SDIO_DEVICE_ID_BROADCOM_4335_4339 0x4335
- #define SDIO_DEVICE_ID_BROADCOM_43362 43362
- +#define SDIO_DEVICE_ID_BROADCOM_4354 0x4354
-
- #define SDIO_VENDOR_ID_INTEL 0x0089
- #define SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX 0x1402
- diff -Nur linux-3.14.35.orig/include/linux/mod_devicetable.h linux-3.14.35/include/linux/mod_devicetable.h
- --- linux-3.14.35.orig/include/linux/mod_devicetable.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/mod_devicetable.h 2015-03-08 14:27:37.869684498 -0500
- @@ -564,6 +564,15 @@
- #define X86_MODEL_ANY 0
- #define X86_FEATURE_ANY 0 /* Same as FPU, you can't test for that */
-
- +/*
- + * Generic table type for matching CPU features.
- + * @feature: the bit number of the feature (0 - 65535)
- + */
- +
- +struct cpu_feature {
- + __u16 feature;
- +};
- +
- #define IPACK_ANY_FORMAT 0xff
- #define IPACK_ANY_ID (~0)
- struct ipack_device_id {
- diff -Nur linux-3.14.35.orig/include/linux/mtd/map.h linux-3.14.35/include/linux/mtd/map.h
- --- linux-3.14.35.orig/include/linux/mtd/map.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/mtd/map.h 2015-03-08 14:27:37.873684498 -0500
- @@ -438,7 +438,7 @@
- if (map->cached)
- memcpy(to, (char *)map->cached + from, len);
- else
- - memcpy_fromio(to, map->virt + from, len);
- + memcpy(to, map->virt + from, len);
- }
-
- static inline void inline_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
- diff -Nur linux-3.14.35.orig/include/linux/mxc_asrc.h linux-3.14.35/include/linux/mxc_asrc.h
- --- linux-3.14.35.orig/include/linux/mxc_asrc.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/mxc_asrc.h 2015-03-08 14:27:37.873684498 -0500
- @@ -0,0 +1,386 @@
- +/*
- + * Copyright 2008-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + *
- + * @file mxc_asrc.h
- + *
- + * @brief i.MX Asynchronous Sample Rate Converter
- + *
- + * @ingroup Audio
- + */
- +
- +#ifndef __MXC_ASRC_H__
- +#define __MXC_ASRC_H__
- +
- +#include <uapi/linux/mxc_asrc.h>
- +#include <linux/scatterlist.h>
- +
- +#define ASRC_DMA_BUFFER_NUM 2
- +#define ASRC_INPUTFIFO_THRESHOLD 32
- +#define ASRC_OUTPUTFIFO_THRESHOLD 32
- +#define ASRC_FIFO_THRESHOLD_MIN 0
- +#define ASRC_FIFO_THRESHOLD_MAX 63
- +#define ASRC_DMA_BUFFER_SIZE (1024 * 48 * 4)
- +#define ASRC_MAX_BUFFER_SIZE (1024 * 48)
- +#define ASRC_OUTPUT_LAST_SAMPLE_DEFAULT 8
- +
- +
- +/* Ideal Ratio mode doesn't care the outclk frequency, so be fixed */
- +#define ASRC_PRESCALER_IDEAL_RATIO 5
- +/* SPDIF rxclk pulse rate is 128 * samplerate, so 2 ^ 7 */
- +#define ASRC_PRESCALER_SPDIF_RX 7
- +/* SPDIF txclk pulse rate is 64 * samplerate, so 2 ^ 6 */
- +#define ASRC_PRESCALER_SPDIF_TX 6
- +/* I2S bclk is 16 * 2 = 32, so 2 ^ 5 */
- +#define ASRC_PRESCALER_I2S_16BIT 5
- +/* I2S bclk is 24 * 2 = 48 -> 64, so 2 ^ 6 */
- +#define ASRC_PRESCALER_I2S_24BIT 6
- +
- +
- +#define REG_ASRCTR 0x00
- +#define REG_ASRIER 0x04
- +#define REG_ASRCNCR 0x0C
- +#define REG_ASRCFG 0x10
- +#define REG_ASRCSR 0x14
- +
- +#define REG_ASRCDR1 0x18
- +#define REG_ASRCDR2 0x1C
- +#define REG_ASRCDR(x) ((x < 2) ? REG_ASRCDR1 : REG_ASRCDR2)
- +
- +#define REG_ASRSTR 0x20
- +#define REG_ASRRA 0x24
- +#define REG_ASRRB 0x28
- +#define REG_ASRRC 0x2C
- +#define REG_ASRPM1 0x40
- +#define REG_ASRPM2 0x44
- +#define REG_ASRPM3 0x48
- +#define REG_ASRPM4 0x4C
- +#define REG_ASRPM5 0x50
- +#define REG_ASRTFR1 0x54
- +#define REG_ASRCCR 0x5C
- +
- +#define REG_ASRDIA 0x60
- +#define REG_ASRDOA 0x64
- +#define REG_ASRDIB 0x68
- +#define REG_ASRDOB 0x6C
- +#define REG_ASRDIC 0x70
- +#define REG_ASRDOC 0x74
- +#define REG_ASRDI(x) (REG_ASRDIA + (x << 3))
- +#define REG_ASRDO(x) (REG_ASRDOA + (x << 3))
- +
- +#define REG_ASRIDRHA 0x80
- +#define REG_ASRIDRLA 0x84
- +#define REG_ASRIDRHB 0x88
- +#define REG_ASRIDRLB 0x8C
- +#define REG_ASRIDRHC 0x90
- +#define REG_ASRIDRLC 0x94
- +#define REG_ASRIDRH(x) (REG_ASRIDRHA + (x << 3))
- +#define REG_ASRIDRL(x) (REG_ASRIDRLA + (x << 3))
- +
- +#define REG_ASR76K 0x98
- +#define REG_ASR56K 0x9C
- +
- +#define REG_ASRMCRA 0xA0
- +#define REG_ASRFSTA 0xA4
- +#define REG_ASRMCRB 0xA8
- +#define REG_ASRFSTB 0xAC
- +#define REG_ASRMCRC 0xB0
- +#define REG_ASRFSTC 0xB4
- +#define REG_ASRMCR(x) (REG_ASRMCRA + (x << 3))
- +#define REG_ASRFST(x) (REG_ASRFSTA + (x << 3))
- +
- +#define REG_ASRMCR1A 0xC0
- +#define REG_ASRMCR1B 0xC4
- +#define REG_ASRMCR1C 0xC8
- +#define REG_ASRMCR1(x) (REG_ASRMCR1A + (x << 2))
- +
- +
- +/* REG0 0x00 REG_ASRCTR */
- +#define ASRCTR_ATSx_SHIFT(x) (20 + x)
- +#define ASRCTR_ATSx_MASK(x) (1 << ASRCTR_ATSx_SHIFT(x))
- +#define ASRCTR_ATS(x) (1 << ASRCTR_ATSx_SHIFT(x))
- +#define ASRCTR_USRx_SHIFT(x) (14 + (x << 1))
- +#define ASRCTR_USRx_MASK(x) (1 << ASRCTR_USRx_SHIFT(x))
- +#define ASRCTR_USR(x) (1 << ASRCTR_USRx_SHIFT(x))
- +#define ASRCTR_IDRx_SHIFT(x) (13 + (x << 1))
- +#define ASRCTR_IDRx_MASK(x) (1 << ASRCTR_IDRx_SHIFT(x))
- +#define ASRCTR_IDR(x) (1 << ASRCTR_IDRx_SHIFT(x))
- +#define ASRCTR_SRST_SHIFT 4
- +#define ASRCTR_SRST_MASK (1 << ASRCTR_SRST_SHIFT)
- +#define ASRCTR_SRST (1 << ASRCTR_SRST_SHIFT)
- +#define ASRCTR_ASRCEx_SHIFT(x) (1 + x)
- +#define ASRCTR_ASRCEx_MASK(x) (1 << ASRCTR_ASRCEx_SHIFT(x))
- +#define ASRCTR_ASRCE(x) (1 << ASRCTR_ASRCEx_SHIFT(x))
- +#define ASRCTR_ASRCEN_SHIFT 0
- +#define ASRCTR_ASRCEN_MASK (1 << ASRCTR_ASRCEN_SHIFT)
- +#define ASRCTR_ASRCEN (1 << ASRCTR_ASRCEN_SHIFT)
- +
- +/* REG1 0x04 REG_ASRIER */
- +#define ASRIER_AFPWE_SHIFT 7
- +#define ASRIER_AFPWE_MASK (1 << ASRIER_AFPWE_SHIFT)
- +#define ASRIER_AFPWE (1 << ASRIER_AFPWE_SHIFT)
- +#define ASRIER_AOLIE_SHIFT 6
- +#define ASRIER_AOLIE_MASK (1 << ASRIER_AOLIE_SHIFT)
- +#define ASRIER_AOLIE (1 << ASRIER_AOLIE_SHIFT)
- +#define ASRIER_ADOEx_SHIFT(x) (3 + x)
- +#define ASRIER_ADOEx_MASK(x) (1 << ASRIER_ADOEx_SHIFT(x))
- +#define ASRIER_ADOE(x) (1 << ASRIER_ADOEx_SHIFT(x))
- +#define ASRIER_ADIEx_SHIFT(x) (0 + x)
- +#define ASRIER_ADIEx_MASK(x) (1 << ASRIER_ADIEx_SHIFT(x))
- +#define ASRIER_ADIE(x) (1 << ASRIER_ADIEx_SHIFT(x))
- +
- +/* REG2 0x0C REG_ASRCNCR */
- +#define ASRCNCR_ANCx_SHIFT(x, b) (b * x)
- +#define ASRCNCR_ANCx_MASK(x, b) (((1 << b) - 1) << ASRCNCR_ANCx_SHIFT(x, b))
- +#define ASRCNCR_ANCx_get(x, v, b) ((v & ASRCNCR_ANCx_MASK(x, b)) >> ASRCNCR_ANCx_SHIFT(x, b))
- +#define ASRCNCR_ANCx_set(x, v, b) ((v << ASRCNCR_ANCx_SHIFT(x, b)) & ASRCNCR_ANCx_MASK(x, b))
- +
- +/* REG3 0x10 REG_ASRCFG */
- +#define ASRCFG_INIRQx_SHIFT(x) (21 + x)
- +#define ASRCFG_INIRQx_MASK(x) (1 << ASRCFG_INIRQx_SHIFT(x))
- +#define ASRCFG_INIRQx (1 << ASRCFG_INIRQx_SHIFT(x))
- +#define ASRCFG_NDPRx_SHIFT(x) (18 + x)
- +#define ASRCFG_NDPRx_MASK(x) (1 << ASRCFG_NDPRx_SHIFT(x))
- +#define ASRCFG_NDPRx (1 << ASRCFG_NDPRx_SHIFT(x))
- +#define ASRCFG_POSTMODx_SHIFT(x) (8 + (x << 2))
- +#define ASRCFG_POSTMODx_WIDTH 2
- +#define ASRCFG_POSTMODx_MASK(x) (((1 << ASRCFG_POSTMODx_WIDTH) - 1) << ASRCFG_POSTMODx_SHIFT(x))
- +#define ASRCFG_POSTMOD(x, v) ((v) << ASRCFG_POSTMODx_SHIFT(x))
- +#define ASRCFG_POSTMODx_UP(x) (0 << ASRCFG_POSTMODx_SHIFT(x))
- +#define ASRCFG_POSTMODx_DCON(x) (1 << ASRCFG_POSTMODx_SHIFT(x))
- +#define ASRCFG_POSTMODx_DOWN(x) (2 << ASRCFG_POSTMODx_SHIFT(x))
- +#define ASRCFG_PREMODx_SHIFT(x) (6 + (x << 2))
- +#define ASRCFG_PREMODx_WIDTH 2
- +#define ASRCFG_PREMODx_MASK(x) (((1 << ASRCFG_PREMODx_WIDTH) - 1) << ASRCFG_PREMODx_SHIFT(x))
- +#define ASRCFG_PREMOD(x, v) ((v) << ASRCFG_PREMODx_SHIFT(x))
- +#define ASRCFG_PREMODx_UP(x) (0 << ASRCFG_PREMODx_SHIFT(x))
- +#define ASRCFG_PREMODx_DCON(x) (1 << ASRCFG_PREMODx_SHIFT(x))
- +#define ASRCFG_PREMODx_DOWN(x) (2 << ASRCFG_PREMODx_SHIFT(x))
- +#define ASRCFG_PREMODx_BYPASS(x) (3 << ASRCFG_PREMODx_SHIFT(x))
- +
- +/* REG4 0x14 REG_ASRCSR */
- +#define ASRCSR_AxCSx_WIDTH 4
- +#define ASRCSR_AxCSx_MASK ((1 << ASRCSR_AxCSx_WIDTH) - 1)
- +#define ASRCSR_AOCSx_SHIFT(x) (12 + (x << 2))
- +#define ASRCSR_AOCSx_MASK(x) (((1 << ASRCSR_AxCSx_WIDTH) - 1) << ASRCSR_AOCSx_SHIFT(x))
- +#define ASRCSR_AOCS(x, v) ((v) << ASRCSR_AOCSx_SHIFT(x))
- +#define ASRCSR_AICSx_SHIFT(x) (x << 2)
- +#define ASRCSR_AICSx_MASK(x) (((1 << ASRCSR_AxCSx_WIDTH) - 1) << ASRCSR_AICSx_SHIFT(x))
- +#define ASRCSR_AICS(x, v) ((v) << ASRCSR_AICSx_SHIFT(x))
- +
- +/* REG5&6 0x18 & 0x1C REG_ASRCDR1 & ASRCDR2 */
- +#define ASRCDRx_AxCPx_WIDTH 3
- +#define ASRCDRx_AICPx_SHIFT(x) (0 + (x % 2) * 6)
- +#define ASRCDRx_AICPx_MASK(x) (((1 << ASRCDRx_AxCPx_WIDTH) - 1) << ASRCDRx_AICPx_SHIFT(x))
- +#define ASRCDRx_AICP(x, v) ((v) << ASRCDRx_AICPx_SHIFT(x))
- +#define ASRCDRx_AICDx_SHIFT(x) (3 + (x % 2) * 6)
- +#define ASRCDRx_AICDx_MASK(x) (((1 << ASRCDRx_AxCPx_WIDTH) - 1) << ASRCDRx_AICDx_SHIFT(x))
- +#define ASRCDRx_AICD(x, v) ((v) << ASRCDRx_AICDx_SHIFT(x))
- +#define ASRCDRx_AOCPx_SHIFT(x) ((x < 2) ? 12 + x * 6 : 6)
- +#define ASRCDRx_AOCPx_MASK(x) (((1 << ASRCDRx_AxCPx_WIDTH) - 1) << ASRCDRx_AOCPx_SHIFT(x))
- +#define ASRCDRx_AOCP(x, v) ((v) << ASRCDRx_AOCPx_SHIFT(x))
- +#define ASRCDRx_AOCDx_SHIFT(x) ((x < 2) ? 15 + x * 6 : 9)
- +#define ASRCDRx_AOCDx_MASK(x) (((1 << ASRCDRx_AxCPx_WIDTH) - 1) << ASRCDRx_AOCDx_SHIFT(x))
- +#define ASRCDRx_AOCD(x, v) ((v) << ASRCDRx_AOCDx_SHIFT(x))
- +
- +/* REG7 0x20 REG_ASRSTR */
- +#define ASRSTR_DSLCNT_SHIFT 21
- +#define ASRSTR_DSLCNT_MASK (1 << ASRSTR_DSLCNT_SHIFT)
- +#define ASRSTR_DSLCNT (1 << ASRSTR_DSLCNT_SHIFT)
- +#define ASRSTR_ATQOL_SHIFT 20
- +#define ASRSTR_ATQOL_MASK (1 << ASRSTR_ATQOL_SHIFT)
- +#define ASRSTR_ATQOL (1 << ASRSTR_ATQOL_SHIFT)
- +#define ASRSTR_AOOLx_SHIFT(x) (17 + x)
- +#define ASRSTR_AOOLx_MASK(x) (1 << ASRSTR_AOOLx_SHIFT(x))
- +#define ASRSTR_AOOL(x) (1 << ASRSTR_AOOLx_SHIFT(x))
- +#define ASRSTR_AIOLx_SHIFT(x) (14 + x)
- +#define ASRSTR_AIOLx_MASK(x) (1 << ASRSTR_AIOLx_SHIFT(x))
- +#define ASRSTR_AIOL(x) (1 << ASRSTR_AIOLx_SHIFT(x))
- +#define ASRSTR_AODOx_SHIFT(x) (11 + x)
- +#define ASRSTR_AODOx_MASK(x) (1 << ASRSTR_AODOx_SHIFT(x))
- +#define ASRSTR_AODO(x) (1 << ASRSTR_AODOx_SHIFT(x))
- +#define ASRSTR_AIDUx_SHIFT(x) (8 + x)
- +#define ASRSTR_AIDUx_MASK(x) (1 << ASRSTR_AIDUx_SHIFT(x))
- +#define ASRSTR_AIDU(x) (1 << ASRSTR_AIDUx_SHIFT(x))
- +#define ASRSTR_FPWT_SHIFT 7
- +#define ASRSTR_FPWT_MASK (1 << ASRSTR_FPWT_SHIFT)
- +#define ASRSTR_FPWT (1 << ASRSTR_FPWT_SHIFT)
- +#define ASRSTR_AOLE_SHIFT 6
- +#define ASRSTR_AOLE_MASK (1 << ASRSTR_AOLE_SHIFT)
- +#define ASRSTR_AOLE (1 << ASRSTR_AOLE_SHIFT)
- +#define ASRSTR_AODEx_SHIFT(x) (3 + x)
- +#define ASRSTR_AODFx_MASK(x) (1 << ASRSTR_AODEx_SHIFT(x))
- +#define ASRSTR_AODF(x) (1 << ASRSTR_AODEx_SHIFT(x))
- +#define ASRSTR_AIDEx_SHIFT(x) (0 + x)
- +#define ASRSTR_AIDEx_MASK(x) (1 << ASRSTR_AIDEx_SHIFT(x))
- +#define ASRSTR_AIDE(x) (1 << ASRSTR_AIDEx_SHIFT(x))
- +
- +/* REG10 0x54 REG_ASRTFR1 */
- +#define ASRTFR1_TF_BASE_WIDTH 7
- +#define ASRTFR1_TF_BASE_SHIFT 6
- +#define ASRTFR1_TF_BASE_MASK (((1 << ASRTFR1_TF_BASE_WIDTH) - 1) << ASRTFR1_TF_BASE_SHIFT)
- +#define ASRTFR1_TF_BASE(x) ((x) << ASRTFR1_TF_BASE_SHIFT)
- +
- +/*
- + * REG22 0xA0 REG_ASRMCRA
- + * REG24 0xA8 REG_ASRMCRB
- + * REG26 0xB0 REG_ASRMCRC
- + */
- +#define ASRMCRx_ZEROBUFx_SHIFT 23
- +#define ASRMCRx_ZEROBUFxCLR_MASK (1 << ASRMCRx_ZEROBUFx_SHIFT)
- +#define ASRMCRx_ZEROBUFxCLR (1 << ASRMCRx_ZEROBUFx_SHIFT)
- +#define ASRMCRx_EXTTHRSHx_SHIFT 22
- +#define ASRMCRx_EXTTHRSHx_MASK (1 << ASRMCRx_EXTTHRSHx_SHIFT)
- +#define ASRMCRx_EXTTHRSHx (1 << ASRMCRx_EXTTHRSHx_SHIFT)
- +#define ASRMCRx_BUFSTALLx_SHIFT 21
- +#define ASRMCRx_BUFSTALLx_MASK (1 << ASRMCRx_BUFSTALLx_SHIFT)
- +#define ASRMCRx_BUFSTALLx (1 << ASRMCRx_BUFSTALLx_SHIFT)
- +#define ASRMCRx_BYPASSPOLYx_SHIFT 20
- +#define ASRMCRx_BYPASSPOLYx_MASK (1 << ASRMCRx_BYPASSPOLYx_SHIFT)
- +#define ASRMCRx_BYPASSPOLYx (1 << ASRMCRx_BYPASSPOLYx_SHIFT)
- +#define ASRMCRx_OUTFIFO_THRESHOLD_WIDTH 6
- +#define ASRMCRx_OUTFIFO_THRESHOLD_SHIFT 12
- +#define ASRMCRx_OUTFIFO_THRESHOLD_MASK (((1 << ASRMCRx_OUTFIFO_THRESHOLD_WIDTH) - 1) << ASRMCRx_OUTFIFO_THRESHOLD_SHIFT)
- +#define ASRMCRx_OUTFIFO_THRESHOLD(v) (((v) << ASRMCRx_OUTFIFO_THRESHOLD_SHIFT) & ASRMCRx_OUTFIFO_THRESHOLD_MASK)
- +#define ASRMCRx_RSYNIFx_SHIFT 11
- +#define ASRMCRx_RSYNIFx_MASK (1 << ASRMCRx_RSYNIFx_SHIFT)
- +#define ASRMCRx_RSYNIFx (1 << ASRMCRx_RSYNIFx_SHIFT)
- +#define ASRMCRx_RSYNOFx_SHIFT 10
- +#define ASRMCRx_RSYNOFx_MASK (1 << ASRMCRx_RSYNOFx_SHIFT)
- +#define ASRMCRx_RSYNOFx (1 << ASRMCRx_RSYNOFx_SHIFT)
- +#define ASRMCRx_INFIFO_THRESHOLD_WIDTH 6
- +#define ASRMCRx_INFIFO_THRESHOLD_SHIFT 0
- +#define ASRMCRx_INFIFO_THRESHOLD_MASK (((1 << ASRMCRx_INFIFO_THRESHOLD_WIDTH) - 1) << ASRMCRx_INFIFO_THRESHOLD_SHIFT)
- +#define ASRMCRx_INFIFO_THRESHOLD(v) (((v) << ASRMCRx_INFIFO_THRESHOLD_SHIFT) & ASRMCRx_INFIFO_THRESHOLD_MASK)
- +
- +/*
- + * REG23 0xA4 REG_ASRFSTA
- + * REG25 0xAC REG_ASRFSTB
- + * REG27 0xB4 REG_ASRFSTC
- + */
- +#define ASRFSTx_OAFx_SHIFT 23
- +#define ASRFSTx_OAFx_MASK (1 << ASRFSTx_OAFx_SHIFT)
- +#define ASRFSTx_OAFx (1 << ASRFSTx_OAFx_SHIFT)
- +#define ASRFSTx_OUTPUT_FIFO_WIDTH 7
- +#define ASRFSTx_OUTPUT_FIFO_SHIFT 12
- +#define ASRFSTx_OUTPUT_FIFO_MASK (((1 << ASRFSTx_OUTPUT_FIFO_WIDTH) - 1) << ASRFSTx_OUTPUT_FIFO_SHIFT)
- +#define ASRFSTx_IAEx_SHIFT 11
- +#define ASRFSTx_IAEx_MASK (1 << ASRFSTx_OAFx_SHIFT)
- +#define ASRFSTx_IAEx (1 << ASRFSTx_OAFx_SHIFT)
- +#define ASRFSTx_INPUT_FIFO_WIDTH 7
- +#define ASRFSTx_INPUT_FIFO_SHIFT 0
- +#define ASRFSTx_INPUT_FIFO_MASK ((1 << ASRFSTx_INPUT_FIFO_WIDTH) - 1)
- +
- +/* REG28 0xC0 & 0xC4 & 0xC8 REG_ASRMCR1x */
- +#define ASRMCR1x_IWD_WIDTH 3
- +#define ASRMCR1x_IWD_SHIFT 9
- +#define ASRMCR1x_IWD_MASK (((1 << ASRMCR1x_IWD_WIDTH) - 1) << ASRMCR1x_IWD_SHIFT)
- +#define ASRMCR1x_IWD(v) ((v) << ASRMCR1x_IWD_SHIFT)
- +#define ASRMCR1x_IMSB_SHIFT 8
- +#define ASRMCR1x_IMSB_MASK (1 << ASRMCR1x_IMSB_SHIFT)
- +#define ASRMCR1x_IMSB_MSB (1 << ASRMCR1x_IMSB_SHIFT)
- +#define ASRMCR1x_IMSB_LSB (0 << ASRMCR1x_IMSB_SHIFT)
- +#define ASRMCR1x_OMSB_SHIFT 2
- +#define ASRMCR1x_OMSB_MASK (1 << ASRMCR1x_OMSB_SHIFT)
- +#define ASRMCR1x_OMSB_MSB (1 << ASRMCR1x_OMSB_SHIFT)
- +#define ASRMCR1x_OMSB_LSB (0 << ASRMCR1x_OMSB_SHIFT)
- +#define ASRMCR1x_OSGN_SHIFT 1
- +#define ASRMCR1x_OSGN_MASK (1 << ASRMCR1x_OSGN_SHIFT)
- +#define ASRMCR1x_OSGN (1 << ASRMCR1x_OSGN_SHIFT)
- +#define ASRMCR1x_OW16_SHIFT 0
- +#define ASRMCR1x_OW16_MASK (1 << ASRMCR1x_OW16_SHIFT)
- +#define ASRMCR1x_OW16(v) ((v) << ASRMCR1x_OW16_SHIFT)
- +
- +
- +struct dma_block {
- + unsigned int index;
- + unsigned int length;
- + void *dma_vaddr;
- + dma_addr_t dma_paddr;
- + struct list_head queue;
- +};
- +
- +struct asrc_p2p_params {
- + u32 p2p_rate; /* ASRC output rate for p2p */
- + enum asrc_word_width p2p_width; /* ASRC output wordwidth for p2p */
- +};
- +
- +struct asrc_pair_params {
- + enum asrc_pair_index index;
- + struct completion input_complete;
- + struct completion output_complete;
- + struct completion lastperiod_complete;
- + struct dma_chan *input_dma_channel;
- + struct dma_chan *output_dma_channel;
- + unsigned int input_buffer_size;
- + unsigned int output_buffer_size;
- + unsigned int buffer_num;
- + unsigned int pair_hold;
- + unsigned int asrc_active;
- + unsigned int channel_nums;
- + struct dma_block input_dma_total;
- + struct dma_block input_dma[ASRC_DMA_BUFFER_NUM];
- + struct dma_block output_dma_total;
- + struct dma_block output_dma[ASRC_DMA_BUFFER_NUM];
- + struct dma_block output_last_period;
- + struct dma_async_tx_descriptor *desc_in;
- + struct dma_async_tx_descriptor *desc_out;
- + struct work_struct task_output_work;
- + unsigned int input_sg_nodes;
- + unsigned int output_sg_nodes;
- + struct scatterlist input_sg[4], output_sg[4];
- + enum asrc_word_width input_word_width;
- + enum asrc_word_width output_word_width;
- + u32 input_sample_rate;
- + u32 output_sample_rate;
- + u32 input_wm;
- + u32 output_wm;
- + unsigned int last_period_sample;
- +};
- +
- +struct asrc_data {
- + struct asrc_pair asrc_pair[ASRC_PAIR_MAX_NUM];
- + struct proc_dir_entry *proc_asrc;
- + struct class *asrc_class;
- + struct regmap *regmap;
- + struct clk *asrc_clk;
- + struct clk *dma_clk;
- + unsigned long paddr;
- + unsigned int channel_bits;
- + int asrc_major;
- + int irq;
- + struct device *dev;
- +};
- +
- +struct asrc_p2p_ops {
- + void (*asrc_p2p_start_conv)(enum asrc_pair_index);
- + void (*asrc_p2p_stop_conv)(enum asrc_pair_index);
- + int (*asrc_p2p_get_dma_request)(enum asrc_pair_index, bool);
- + u32 (*asrc_p2p_per_addr)(enum asrc_pair_index, bool);
- + int (*asrc_p2p_req_pair)(int, enum asrc_pair_index *index);
- + int (*asrc_p2p_config_pair)(struct asrc_config *config);
- + void (*asrc_p2p_release_pair)(enum asrc_pair_index);
- + void (*asrc_p2p_finish_conv)(enum asrc_pair_index);
- +};
- +
- +extern void asrc_p2p_hook(struct asrc_p2p_ops *asrc_p2p_ct);
- +
- +extern int asrc_req_pair(int chn_num, enum asrc_pair_index *index);
- +extern void asrc_release_pair(enum asrc_pair_index index);
- +extern int asrc_config_pair(struct asrc_config *config);
- +extern void asrc_get_status(struct asrc_status_flags *flags);
- +extern void asrc_start_conv(enum asrc_pair_index index);
- +extern void asrc_stop_conv(enum asrc_pair_index index);
- +extern u32 asrc_get_per_addr(enum asrc_pair_index index, bool i);
- +extern int asrc_get_dma_request(enum asrc_pair_index index, bool i);
- +extern void asrc_finish_conv(enum asrc_pair_index index);
- +extern int asrc_set_watermark(enum asrc_pair_index index,
- + u32 in_wm, u32 out_wm);
- +
- +#endif/* __MXC_ASRC_H__ */
- diff -Nur linux-3.14.35.orig/include/linux/mxcfb.h linux-3.14.35/include/linux/mxcfb.h
- --- linux-3.14.35.orig/include/linux/mxcfb.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/mxcfb.h 2015-03-08 14:27:37.873684498 -0500
- @@ -0,0 +1,46 @@
- +/*
- + * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU Lesser General
- + * Public License. You may obtain a copy of the GNU Lesser General
- + * Public License Version 2.1 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/lgpl-license.html
- + * http://www.gnu.org/copyleft/lgpl.html
- + */
- +
- +/*
- + * @file linux/mxcfb.h
- + *
- + * @brief Global header file for the MXC Frame buffer
- + *
- + * @ingroup Framebuffer
- + */
- +#ifndef __LINUX_MXCFB_H__
- +#define __LINUX_MXCFB_H__
- +
- +#include <uapi/linux/mxcfb.h>
- +
- +extern struct fb_videomode mxcfb_modedb[];
- +extern int mxcfb_modedb_sz;
- +
- +enum {
- + MXC_DISP_SPEC_DEV = 0,
- + MXC_DISP_DDC_DEV = 1,
- +};
- +
- +enum {
- + MXCFB_REFRESH_OFF,
- + MXCFB_REFRESH_AUTO,
- + MXCFB_REFRESH_PARTIAL,
- +};
- +
- +int mxcfb_set_refresh_mode(struct fb_info *fbi, int mode,
- + struct mxcfb_rect *update_region);
- +int mxc_elcdif_frame_addr_setup(dma_addr_t phys);
- +void mxcfb_elcdif_register_mode(const struct fb_videomode *modedb,
- + int num_modes, int dev_mode);
- +
- +#endif
- diff -Nur linux-3.14.35.orig/include/linux/mxc_mlb.h linux-3.14.35/include/linux/mxc_mlb.h
- --- linux-3.14.35.orig/include/linux/mxc_mlb.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/mxc_mlb.h 2015-03-08 14:27:37.873684498 -0500
- @@ -0,0 +1,55 @@
- +/*
- + * mxc_mlb.h
- + *
- + * Copyright 2008-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#ifndef _MXC_MLB_H
- +#define _MXC_MLB_H
- +
- +/* define IOCTL command */
- +#define MLB_DBG_RUNTIME _IO('S', 0x09)
- +#define MLB_SET_FPS _IOW('S', 0x10, unsigned int)
- +#define MLB_GET_VER _IOR('S', 0x11, unsigned long)
- +#define MLB_SET_DEVADDR _IOR('S', 0x12, unsigned char)
- +
- +/*!
- + * set channel address for each logical channel
- + * the MSB 16bits is for tx channel, the left LSB is for rx channel
- + */
- +#define MLB_CHAN_SETADDR _IOW('S', 0x13, unsigned int)
- +#define MLB_CHAN_STARTUP _IO('S', 0x14)
- +#define MLB_CHAN_SHUTDOWN _IO('S', 0x15)
- +#define MLB_CHAN_GETEVENT _IOR('S', 0x16, unsigned long)
- +
- +#define MLB_SET_ISOC_BLKSIZE_188 _IO('S', 0x17)
- +#define MLB_SET_ISOC_BLKSIZE_196 _IO('S', 0x18)
- +#define MLB_SET_SYNC_QUAD _IOW('S', 0x19, unsigned int)
- +#define MLB_IRQ_ENABLE _IO('S', 0x20)
- +#define MLB_IRQ_DISABLE _IO('S', 0x21)
- +
- +/*!
- + * MLB event define
- + */
- +enum {
- + MLB_EVT_TX_PROTO_ERR_CUR = 1 << 0,
- + MLB_EVT_TX_BRK_DETECT_CUR = 1 << 1,
- + MLB_EVT_TX_PROTO_ERR_PREV = 1 << 8,
- + MLB_EVT_TX_BRK_DETECT_PREV = 1 << 9,
- + MLB_EVT_RX_PROTO_ERR_CUR = 1 << 16,
- + MLB_EVT_RX_BRK_DETECT_CUR = 1 << 17,
- + MLB_EVT_RX_PROTO_ERR_PREV = 1 << 24,
- + MLB_EVT_RX_BRK_DETECT_PREV = 1 << 25,
- +};
- +
- +
- +#endif /* _MXC_MLB_H */
- diff -Nur linux-3.14.35.orig/include/linux/mxc_v4l2.h linux-3.14.35/include/linux/mxc_v4l2.h
- --- linux-3.14.35.orig/include/linux/mxc_v4l2.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/mxc_v4l2.h 2015-03-08 14:27:37.873684498 -0500
- @@ -0,0 +1,27 @@
- +/*
- + * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU Lesser General
- + * Public License. You may obtain a copy of the GNU Lesser General
- + * Public License Version 2.1 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/lgpl-license.html
- + * http://www.gnu.org/copyleft/lgpl.html
- + */
- +
- +/*!
- + * @file linux/mxc_v4l2.h
- + *
- + * @brief MXC V4L2 private header file
- + *
- + * @ingroup MXC V4L2
- + */
- +
- +#ifndef __LINUX_MXC_V4L2_H__
- +#define __LINUX_MXC_V4L2_H__
- +
- +#include <uapi/linux/mxc_v4l2.h>
- +
- +#endif
- diff -Nur linux-3.14.35.orig/include/linux/mxc_vpu.h linux-3.14.35/include/linux/mxc_vpu.h
- --- linux-3.14.35.orig/include/linux/mxc_vpu.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/mxc_vpu.h 2015-03-08 14:27:37.873684498 -0500
- @@ -0,0 +1,118 @@
- +/*
- + * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU Lesser General
- + * Public License. You may obtain a copy of the GNU Lesser General
- + * Public License Version 2.1 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/lgpl-license.html
- + * http://www.gnu.org/copyleft/lgpl.html
- + */
- +
- +/*!
- + * @defgroup VPU Video Processor Unit Driver
- + */
- +
- +/*!
- + * @file linux/mxc_vpu.h
- + *
- + * @brief VPU system initialization and file operation definition
- + *
- + * @ingroup VPU
- + */
- +
- +#ifndef __LINUX_MXC_VPU_H__
- +#define __LINUX_MXC_VPU_H__
- +
- +#include <linux/fs.h>
- +
- +struct mxc_vpu_platform_data {
- + bool iram_enable;
- + int iram_size;
- + void (*reset) (void);
- + void (*pg) (int);
- +};
- +
- +struct vpu_mem_desc {
- + u32 size;
- + dma_addr_t phy_addr;
- + u32 cpu_addr; /* cpu address to free the dma mem */
- + u32 virt_uaddr; /* virtual user space address */
- +};
- +
- +#define VPU_IOC_MAGIC 'V'
- +
- +#define VPU_IOC_PHYMEM_ALLOC _IO(VPU_IOC_MAGIC, 0)
- +#define VPU_IOC_PHYMEM_FREE _IO(VPU_IOC_MAGIC, 1)
- +#define VPU_IOC_WAIT4INT _IO(VPU_IOC_MAGIC, 2)
- +#define VPU_IOC_PHYMEM_DUMP _IO(VPU_IOC_MAGIC, 3)
- +#define VPU_IOC_REG_DUMP _IO(VPU_IOC_MAGIC, 4)
- +#define VPU_IOC_IRAM_SETTING _IO(VPU_IOC_MAGIC, 6)
- +#define VPU_IOC_CLKGATE_SETTING _IO(VPU_IOC_MAGIC, 7)
- +#define VPU_IOC_GET_WORK_ADDR _IO(VPU_IOC_MAGIC, 8)
- +#define VPU_IOC_REQ_VSHARE_MEM _IO(VPU_IOC_MAGIC, 9)
- +#define VPU_IOC_SYS_SW_RESET _IO(VPU_IOC_MAGIC, 11)
- +#define VPU_IOC_GET_SHARE_MEM _IO(VPU_IOC_MAGIC, 12)
- +#define VPU_IOC_QUERY_BITWORK_MEM _IO(VPU_IOC_MAGIC, 13)
- +#define VPU_IOC_SET_BITWORK_MEM _IO(VPU_IOC_MAGIC, 14)
- +#define VPU_IOC_PHYMEM_CHECK _IO(VPU_IOC_MAGIC, 15)
- +#define VPU_IOC_LOCK_DEV _IO(VPU_IOC_MAGIC, 16)
- +
- +#define BIT_CODE_RUN 0x000
- +#define BIT_CODE_DOWN 0x004
- +#define BIT_INT_CLEAR 0x00C
- +#define BIT_INT_STATUS 0x010
- +#define BIT_CUR_PC 0x018
- +#define BIT_INT_REASON 0x174
- +
- +#define MJPEG_PIC_STATUS_REG 0x3004
- +#define MBC_SET_SUBBLK_EN 0x4A0
- +
- +#define BIT_WORK_CTRL_BUF_BASE 0x100
- +#define BIT_WORK_CTRL_BUF_REG(i) (BIT_WORK_CTRL_BUF_BASE + i * 4)
- +#define BIT_CODE_BUF_ADDR BIT_WORK_CTRL_BUF_REG(0)
- +#define BIT_WORK_BUF_ADDR BIT_WORK_CTRL_BUF_REG(1)
- +#define BIT_PARA_BUF_ADDR BIT_WORK_CTRL_BUF_REG(2)
- +#define BIT_BIT_STREAM_CTRL BIT_WORK_CTRL_BUF_REG(3)
- +#define BIT_FRAME_MEM_CTRL BIT_WORK_CTRL_BUF_REG(4)
- +#define BIT_BIT_STREAM_PARAM BIT_WORK_CTRL_BUF_REG(5)
- +
- +#ifndef CONFIG_SOC_IMX6Q
- +#define BIT_RESET_CTRL 0x11C
- +#else
- +#define BIT_RESET_CTRL 0x128
- +#endif
- +
- +/* i could be 0, 1, 2, 3 */
- +#define BIT_RD_PTR_BASE 0x120
- +#define BIT_RD_PTR_REG(i) (BIT_RD_PTR_BASE + i * 8)
- +#define BIT_WR_PTR_REG(i) (BIT_RD_PTR_BASE + i * 8 + 4)
- +
- +/* i could be 0, 1, 2, 3 */
- +#define BIT_FRM_DIS_FLG_BASE (cpu_is_mx51() ? 0x150 : 0x140)
- +#define BIT_FRM_DIS_FLG_REG(i) (BIT_FRM_DIS_FLG_BASE + i * 4)
- +
- +#define BIT_BUSY_FLAG 0x160
- +#define BIT_RUN_COMMAND 0x164
- +#define BIT_INT_ENABLE 0x170
- +
- +#define BITVAL_PIC_RUN 8
- +
- +#define VPU_SLEEP_REG_VALUE 10
- +#define VPU_WAKE_REG_VALUE 11
- +
- +int vl2cc_init(u32 vl2cc_hw_base);
- +void vl2cc_enable(void);
- +void vl2cc_flush(void);
- +void vl2cc_disable(void);
- +void vl2cc_cleanup(void);
- +
- +int vl2cc_init(u32 vl2cc_hw_base);
- +void vl2cc_enable(void);
- +void vl2cc_flush(void);
- +void vl2cc_disable(void);
- +void vl2cc_cleanup(void);
- +
- +#endif
- diff -Nur linux-3.14.35.orig/include/linux/phy.h linux-3.14.35/include/linux/phy.h
- --- linux-3.14.35.orig/include/linux/phy.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/phy.h 2015-03-08 14:27:37.873684498 -0500
- @@ -609,6 +609,7 @@
- return phydev->drv->read_status(phydev);
- }
-
- +int genphy_config_init(struct phy_device *phydev);
- int genphy_setup_forced(struct phy_device *phydev);
- int genphy_restart_aneg(struct phy_device *phydev);
- int genphy_config_aneg(struct phy_device *phydev);
- diff -Nur linux-3.14.35.orig/include/linux/pipe_fs_i.h linux-3.14.35/include/linux/pipe_fs_i.h
- --- linux-3.14.35.orig/include/linux/pipe_fs_i.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/pipe_fs_i.h 2015-03-08 14:27:37.873684498 -0500
- @@ -35,7 +35,7 @@
- * @tmp_page: cached released page
- * @readers: number of current readers of this pipe
- * @writers: number of current writers of this pipe
- - * @files: number of struct file refering this pipe (protected by ->i_lock)
- + * @files: number of struct file referring this pipe (protected by ->i_lock)
- * @waiting_writers: number of writers blocked waiting for room
- * @r_counter: reader counter
- * @w_counter: writer counter
- diff -Nur linux-3.14.35.orig/include/linux/pl320-ipc.h linux-3.14.35/include/linux/pl320-ipc.h
- --- linux-3.14.35.orig/include/linux/pl320-ipc.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/pl320-ipc.h 2015-03-08 14:27:37.873684498 -0500
- @@ -0,0 +1,17 @@
- +/*
- + * This program is free software; you can redistribute it and/or modify it
- + * under the terms and conditions of the GNU General Public License,
- + * version 2, as published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- + * more details.
- + *
- + * You should have received a copy of the GNU General Public License along with
- + * this program. If not, see <http://www.gnu.org/licenses/>.
- + */
- +
- +int pl320_ipc_transmit(u32 *data);
- +int pl320_ipc_register_notifier(struct notifier_block *nb);
- +int pl320_ipc_unregister_notifier(struct notifier_block *nb);
- diff -Nur linux-3.14.35.orig/include/linux/platform_data/dma-imx.h linux-3.14.35/include/linux/platform_data/dma-imx.h
- --- linux-3.14.35.orig/include/linux/platform_data/dma-imx.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/platform_data/dma-imx.h 2015-03-08 14:27:37.873684498 -0500
- @@ -1,5 +1,5 @@
- /*
- - * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
- + * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- @@ -40,6 +40,7 @@
- IMX_DMATYPE_ASRC, /* ASRC */
- IMX_DMATYPE_ESAI, /* ESAI */
- IMX_DMATYPE_SSI_DUAL, /* SSI Dual FIFO */
- + IMX_DMATYPE_HDMI, /* HDMI Audio */
- };
-
- enum imx_dma_prio {
- @@ -49,9 +50,11 @@
- };
-
- struct imx_dma_data {
- - int dma_request; /* DMA request line */
- + int dma_request0; /* DMA request line */
- + int dma_request1;
- enum sdma_peripheral_type peripheral_type;
- int priority;
- + void *data_addr1, *data_addr2;
- };
-
- static inline int imx_dma_is_ipu(struct dma_chan *chan)
- @@ -59,6 +62,11 @@
- return !strcmp(dev_name(chan->device->dev), "ipu-core");
- }
-
- +static inline int imx_dma_is_pxp(struct dma_chan *chan)
- +{
- + return strstr(dev_name(chan->device->dev), "pxp") != NULL;
- +}
- +
- static inline int imx_dma_is_general_purpose(struct dma_chan *chan)
- {
- return !strcmp(chan->device->dev->driver->name, "imx-sdma") ||
- diff -Nur linux-3.14.35.orig/include/linux/power/imx6_usb_charger.h linux-3.14.35/include/linux/power/imx6_usb_charger.h
- --- linux-3.14.35.orig/include/linux/power/imx6_usb_charger.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/power/imx6_usb_charger.h 2015-03-08 14:27:37.873684498 -0500
- @@ -0,0 +1,80 @@
- +/*
- + * Copyright (C) 2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#ifndef __IMXUSB6_CHARGER_H
- +#define __IMXUSB6_CHARGER_H
- +
- +#include <linux/power_supply.h>
- +enum battery_charging_spec {
- + BATTERY_CHARGING_SPEC_NONE = 0,
- + BATTERY_CHARGING_SPEC_UNKNOWN,
- + BATTERY_CHARGING_SPEC_1_0,
- + BATTERY_CHARGING_SPEC_1_1,
- + BATTERY_CHARGING_SPEC_1_2,
- +};
- +
- +struct usb_charger {
- + /* The anatop regmap */
- + struct regmap *anatop;
- + /* USB controller */
- + struct device *dev;
- + struct power_supply psy;
- + struct mutex lock;
- +
- + /* Compliant with Battery Charging Specification version (if any) */
- + enum battery_charging_spec bc;
- +
- + /* properties */
- + unsigned present:1;
- + unsigned online:1;
- + unsigned max_current;
- + int (*connect)(struct usb_charger *charger);
- + int (*disconnect)(struct usb_charger *charger);
- + int (*set_power)(struct usb_charger *charger, unsigned mA);
- +
- + int (*detect)(struct usb_charger *charger);
- +};
- +
- +#ifdef CONFIG_IMX6_USB_CHARGER
- +extern void imx6_usb_remove_charger(struct usb_charger *charger);
- +extern int imx6_usb_create_charger(struct usb_charger *charger,
- + const char *name);
- +extern int imx6_usb_vbus_disconnect(struct usb_charger *charger);
- +extern int imx6_usb_vbus_connect(struct usb_charger *charger);
- +extern int imx6_usb_charger_detect_post(struct usb_charger *charger);
- +#else
- +void imx6_usb_remove_charger(struct usb_charger *charger)
- +{
- +
- +}
- +
- +int imx6_usb_create_charger(struct usb_charger *charger,
- + const char *name)
- +{
- + return -ENODEV;
- +}
- +
- +int imx6_usb_vbus_disconnect(struct usb_charger *charger)
- +{
- + return -ENODEV;
- +}
- +
- +int imx6_usb_vbus_connect(struct usb_charger *charger)
- +{
- + return -ENODEV;
- +}
- +int imx6_usb_charger_detect_post(struct usb_charger *charger)
- +{
- + return -ENODEV;
- +}
- +#endif
- +
- +#endif /* __IMXUSB6_CHARGER_H */
- diff -Nur linux-3.14.35.orig/include/linux/ptp_clock_kernel.h linux-3.14.35/include/linux/ptp_clock_kernel.h
- --- linux-3.14.35.orig/include/linux/ptp_clock_kernel.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/ptp_clock_kernel.h 2015-03-08 14:27:37.877684498 -0500
- @@ -49,7 +49,11 @@
- * @n_alarm: The number of programmable alarms.
- * @n_ext_ts: The number of external time stamp channels.
- * @n_per_out: The number of programmable periodic signals.
- + * @n_pins: The number of programmable pins.
- * @pps: Indicates whether the clock supports a PPS callback.
- + * @pin_config: Array of length 'n_pins'. If the number of
- + * programmable pins is nonzero, then drivers must
- + * allocate and initialize this array.
- *
- * clock operations
- *
- @@ -70,6 +74,18 @@
- * parameter request: Desired resource to enable or disable.
- * parameter on: Caller passes one to enable or zero to disable.
- *
- + * @verify: Confirm that a pin can perform a given function. The PTP
- + * Hardware Clock subsystem maintains the 'pin_config'
- + * array on behalf of the drivers, but the PHC subsystem
- + * assumes that every pin can perform every function. This
- + * hook gives drivers a way of telling the core about
- + * limitations on specific pins. This function must return
- + * zero if the function can be assigned to this pin, and
- + * nonzero otherwise.
- + * parameter pin: index of the pin in question.
- + * parameter func: the desired function to use.
- + * parameter chan: the function channel index to use.
- + *
- * Drivers should embed their ptp_clock_info within a private
- * structure, obtaining a reference to it using container_of().
- *
- @@ -83,13 +99,17 @@
- int n_alarm;
- int n_ext_ts;
- int n_per_out;
- + int n_pins;
- int pps;
- + struct ptp_pin_desc *pin_config;
- int (*adjfreq)(struct ptp_clock_info *ptp, s32 delta);
- int (*adjtime)(struct ptp_clock_info *ptp, s64 delta);
- int (*gettime)(struct ptp_clock_info *ptp, struct timespec *ts);
- int (*settime)(struct ptp_clock_info *ptp, const struct timespec *ts);
- int (*enable)(struct ptp_clock_info *ptp,
- struct ptp_clock_request *request, int on);
- + int (*verify)(struct ptp_clock_info *ptp, unsigned int pin,
- + enum ptp_pin_function func, unsigned int chan);
- };
-
- struct ptp_clock;
- @@ -156,4 +176,17 @@
-
- extern int ptp_clock_index(struct ptp_clock *ptp);
-
- +/**
- + * ptp_find_pin() - obtain the pin index of a given auxiliary function
- + *
- + * @ptp: The clock obtained from ptp_clock_register().
- + * @func: One of the ptp_pin_function enumerated values.
- + * @chan: The particular functional channel to find.
- + * Return: Pin index in the range of zero to ptp_clock_caps.n_pins - 1,
- + * or -1 if the auxiliary function cannot be found.
- + */
- +
- +int ptp_find_pin(struct ptp_clock *ptp,
- + enum ptp_pin_function func, unsigned int chan);
- +
- #endif
- diff -Nur linux-3.14.35.orig/include/linux/pxp_device.h linux-3.14.35/include/linux/pxp_device.h
- --- linux-3.14.35.orig/include/linux/pxp_device.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/pxp_device.h 2015-03-08 14:27:37.877684498 -0500
- @@ -0,0 +1,68 @@
- +/*
- + * Copyright (C) 2013-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + */
- +#ifndef _PXP_DEVICE
- +#define _PXP_DEVICE
- +
- +#include <linux/idr.h>
- +#include <linux/hash.h>
- +#include <uapi/linux/pxp_device.h>
- +
- +struct pxp_irq_info {
- + wait_queue_head_t waitq;
- + atomic_t irq_pending;
- + int hist_status;
- +};
- +
- +struct pxp_buffer_hash {
- + struct hlist_head *hash_table;
- + u32 order;
- + spinlock_t hash_lock;
- +};
- +
- +struct pxp_buf_obj {
- + uint32_t handle;
- +
- + uint32_t size;
- + uint32_t mem_type;
- +
- + unsigned long offset;
- + void *virtual;
- +
- + struct hlist_node item;
- +};
- +
- +struct pxp_chan_obj {
- + uint32_t handle;
- + struct dma_chan *chan;
- +};
- +
- +/* File private data */
- +struct pxp_file {
- + struct file *filp;
- +
- + /* record allocated dma buffer */
- + struct idr buffer_idr;
- + spinlock_t buffer_lock;
- +
- + /* record allocated dma channel */
- + struct idr channel_idr;
- + spinlock_t channel_lock;
- +};
- +
- +#endif
- diff -Nur linux-3.14.35.orig/include/linux/pxp_dma.h linux-3.14.35/include/linux/pxp_dma.h
- --- linux-3.14.35.orig/include/linux/pxp_dma.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/linux/pxp_dma.h 2015-03-08 14:27:37.877684498 -0500
- @@ -0,0 +1,72 @@
- +/*
- + * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + */
- +#ifndef _PXP_DMA
- +#define _PXP_DMA
- +
- +#include <uapi/linux/pxp_dma.h>
- +
- +struct pxp_tx_desc {
- + struct dma_async_tx_descriptor txd;
- + struct list_head tx_list;
- + struct list_head list;
- + int len;
- + union {
- + struct pxp_layer_param s0_param;
- + struct pxp_layer_param out_param;
- + struct pxp_layer_param ol_param;
- + } layer_param;
- + struct pxp_proc_data proc_data;
- +
- + u32 hist_status; /* Histogram output status */
- +
- + struct pxp_tx_desc *next;
- +};
- +
- +struct pxp_channel {
- + struct dma_chan dma_chan;
- + dma_cookie_t completed; /* last completed cookie */
- + enum pxp_channel_status status;
- + void *client; /* Only one client per channel */
- + unsigned int n_tx_desc;
- + struct pxp_tx_desc *desc; /* allocated tx-descriptors */
- + struct list_head queue; /* queued tx-descriptors */
- + struct list_head list; /* track queued channel number */
- + spinlock_t lock; /* protects sg[0,1], queue,
- + * status, cookie, free_list
- + */
- + int active_buffer;
- + unsigned int eof_irq;
- + char eof_name[16]; /* EOF IRQ name for request_irq() */
- +};
- +
- +#define to_tx_desc(tx) container_of(tx, struct pxp_tx_desc, txd)
- +#define to_pxp_channel(d) container_of(d, struct pxp_channel, dma_chan)
- +
- +void pxp_txd_ack(struct dma_async_tx_descriptor *txd,
- + struct pxp_channel *pxp_chan);
- +
- +#ifdef CONFIG_MXC_PXP_CLIENT_DEVICE
- +int register_pxp_device(void);
- +void unregister_pxp_device(void);
- +#else
- +int register_pxp_device(void) { return 0; }
- +void unregister_pxp_device(void) {}
- +#endif
- +
- +#endif
- diff -Nur linux-3.14.35.orig/include/linux/regulator/consumer.h linux-3.14.35/include/linux/regulator/consumer.h
- --- linux-3.14.35.orig/include/linux/regulator/consumer.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/regulator/consumer.h 2015-03-08 14:27:37.877684498 -0500
- @@ -2,6 +2,7 @@
- * consumer.h -- SoC Regulator consumer support.
- *
- * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC.
- + * Copyright (C) 2013 Freescale Semiconductor, Inc.
- *
- * Author: Liam Girdwood <lrg@slimlogic.co.uk>
- *
- @@ -105,6 +106,8 @@
- #define REGULATOR_EVENT_FORCE_DISABLE 0x20
- #define REGULATOR_EVENT_VOLTAGE_CHANGE 0x40
- #define REGULATOR_EVENT_DISABLE 0x80
- +#define REGULATOR_EVENT_PRE_DISABLE 0x100
- +#define REGULATOR_EVENT_ENABLE 0x200
-
- struct regulator;
-
- diff -Nur linux-3.14.35.orig/include/linux/reset.h linux-3.14.35/include/linux/reset.h
- --- linux-3.14.35.orig/include/linux/reset.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/reset.h 2015-03-08 14:27:37.877684498 -0500
- @@ -12,6 +12,13 @@
- void reset_control_put(struct reset_control *rstc);
- struct reset_control *devm_reset_control_get(struct device *dev, const char *id);
-
- +#ifdef CONFIG_RESET_CONTROLLER
- int device_reset(struct device *dev);
- +#else
- +static inline int device_reset(struct device *dev)
- +{
- + return 0;
- +}
- +#endif /* CONFIG_RESET_CONTROLLER */
-
- #endif
- diff -Nur linux-3.14.35.orig/include/linux/serial_core.h linux-3.14.35/include/linux/serial_core.h
- --- linux-3.14.35.orig/include/linux/serial_core.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/serial_core.h 2015-03-08 14:27:37.877684498 -0500
- @@ -285,6 +285,22 @@
- /*
- * Console helpers.
- */
- +struct earlycon_device {
- + struct console *con;
- + struct uart_port port;
- + char options[16]; /* e.g., 115200n8 */
- + unsigned int baud;
- +};
- +int setup_earlycon(char *buf, const char *match,
- + int (*setup)(struct earlycon_device *, const char *));
- +
- +#define EARLYCON_DECLARE(name, func) \
- +static int __init name ## _setup_earlycon(char *buf) \
- +{ \
- + return setup_earlycon(buf, __stringify(name), func); \
- +} \
- +early_param("earlycon", name ## _setup_earlycon);
- +
- struct uart_port *uart_get_console(struct uart_port *ports, int nr,
- struct console *c);
- void uart_parse_options(char *options, int *baud, int *parity, int *bits,
- diff -Nur linux-3.14.35.orig/include/linux/skbuff.h linux-3.14.35/include/linux/skbuff.h
- --- linux-3.14.35.orig/include/linux/skbuff.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/skbuff.h 2015-03-08 14:27:37.877684498 -0500
- @@ -2038,7 +2038,7 @@
- }
-
- /**
- - * skb_frag_page - retrieve the page refered to by a paged fragment
- + * skb_frag_page - retrieve the page referred to by a paged fragment
- * @frag: the paged fragment
- *
- * Returns the &struct page associated with @frag.
- diff -Nur linux-3.14.35.orig/include/linux/spi/spi.h linux-3.14.35/include/linux/spi/spi.h
- --- linux-3.14.35.orig/include/linux/spi/spi.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/spi/spi.h 2015-03-08 14:27:37.877684498 -0500
- @@ -234,7 +234,7 @@
- * @mode_bits: flags understood by this controller driver
- * @bits_per_word_mask: A mask indicating which values of bits_per_word are
- * supported by the driver. Bit n indicates that a bits_per_word n+1 is
- - * suported. If set, the SPI core will reject any transfer with an
- + * supported. If set, the SPI core will reject any transfer with an
- * unsupported bits_per_word. If not set, this value is simply ignored,
- * and it's up to the individual driver to perform any validation.
- * @min_speed_hz: Lowest supported transfer speed
- @@ -259,7 +259,7 @@
- * @cur_msg: the currently in-flight message
- * @cur_msg_prepared: spi_prepare_message was called for the currently
- * in-flight message
- - * @xfer_completion: used by core tranfer_one_message()
- + * @xfer_completion: used by core transfer_one_message()
- * @busy: message pump is busy
- * @running: message pump is running
- * @rt: whether this queue is set to run as a realtime task
- @@ -498,7 +498,7 @@
- * @rx_buf: data to be read (dma-safe memory), or NULL
- * @tx_dma: DMA address of tx_buf, if @spi_message.is_dma_mapped
- * @rx_dma: DMA address of rx_buf, if @spi_message.is_dma_mapped
- - * @tx_nbits: number of bits used for writting. If 0 the default
- + * @tx_nbits: number of bits used for writing. If 0 the default
- * (SPI_NBITS_SINGLE) is used.
- * @rx_nbits: number of bits used for reading. If 0 the default
- * (SPI_NBITS_SINGLE) is used.
- @@ -556,7 +556,7 @@
- * by the results of previous messages and where the whole transaction
- * ends when the chipselect goes intactive.
- *
- - * When SPI can transfer in 1x,2x or 4x. It can get this tranfer information
- + * When SPI can transfer in 1x,2x or 4x. It can get this transfer information
- * from device through @tx_nbits and @rx_nbits. In Bi-direction, these
- * two should both be set. User can set transfer mode with SPI_NBITS_SINGLE(1x)
- * SPI_NBITS_DUAL(2x) and SPI_NBITS_QUAD(4x) to support these three transfer.
- diff -Nur linux-3.14.35.orig/include/linux/syscalls.h linux-3.14.35/include/linux/syscalls.h
- --- linux-3.14.35.orig/include/linux/syscalls.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/syscalls.h 2015-03-08 14:27:37.877684498 -0500
- @@ -744,6 +744,9 @@
- int newdfd, const char __user *newname, int flags);
- asmlinkage long sys_renameat(int olddfd, const char __user * oldname,
- int newdfd, const char __user * newname);
- +asmlinkage long sys_renameat2(int olddfd, const char __user *oldname,
- + int newdfd, const char __user *newname,
- + unsigned int flags);
- asmlinkage long sys_futimesat(int dfd, const char __user *filename,
- struct timeval __user *utimes);
- asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode);
- diff -Nur linux-3.14.35.orig/include/linux/usb/chipidea.h linux-3.14.35/include/linux/usb/chipidea.h
- --- linux-3.14.35.orig/include/linux/usb/chipidea.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/usb/chipidea.h 2015-03-08 14:27:37.877684498 -0500
- @@ -18,6 +18,7 @@
- unsigned long flags;
- #define CI_HDRC_REGS_SHARED BIT(0)
- #define CI_HDRC_REQUIRE_TRANSCEIVER BIT(1)
- +#define CI_HDRC_SUPPORTS_RUNTIME_PM BIT(2)
- #define CI_HDRC_DISABLE_STREAMING BIT(3)
- /*
- * Only set it when DCCPARAMS.DC==1 and DCCPARAMS.HC==1,
- @@ -25,6 +26,7 @@
- */
- #define CI_HDRC_DUAL_ROLE_NOT_OTG BIT(4)
- #define CI_HDRC_IMX28_WRITE_FIX BIT(5)
- +#define CI_HDRC_IMX_EHCI_QUIRK BIT(6)
- enum usb_dr_mode dr_mode;
- #define CI_HDRC_CONTROLLER_RESET_EVENT 0
- #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1
- @@ -42,4 +44,6 @@
- /* Remove ci hdrc device */
- void ci_hdrc_remove_device(struct platform_device *pdev);
-
- +/* Get current available role */
- +enum usb_dr_mode ci_hdrc_query_available_role(struct platform_device *pdev);
- #endif
- diff -Nur linux-3.14.35.orig/include/linux/usb/composite.h linux-3.14.35/include/linux/usb/composite.h
- --- linux-3.14.35.orig/include/linux/usb/composite.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/usb/composite.h 2015-03-08 14:27:37.877684498 -0500
- @@ -92,7 +92,7 @@
- * @suspend: Notifies functions when the host stops sending USB traffic.
- * @resume: Notifies functions when the host restarts USB traffic.
- * @get_status: Returns function status as a reply to
- - * GetStatus() request when the recepient is Interface.
- + * GetStatus() request when the recipient is Interface.
- * @func_suspend: callback to be called when
- * SetFeature(FUNCTION_SUSPEND) is reseived
- *
- diff -Nur linux-3.14.35.orig/include/linux/usb/phy.h linux-3.14.35/include/linux/usb/phy.h
- --- linux-3.14.35.orig/include/linux/usb/phy.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/linux/usb/phy.h 2015-03-08 14:27:37.877684498 -0500
- @@ -111,11 +111,23 @@
- int (*set_suspend)(struct usb_phy *x,
- int suspend);
-
- + /*
- + * Set wakeup enable for PHY, in that case, the PHY can be
- + * waken up from suspend status due to external events,
- + * like vbus change, dp/dm change and id.
- + */
- + int (*set_wakeup)(struct usb_phy *x, bool enabled);
- +
- /* notify phy connect status change */
- int (*notify_connect)(struct usb_phy *x,
- enum usb_device_speed speed);
- int (*notify_disconnect)(struct usb_phy *x,
- enum usb_device_speed speed);
- + int (*notify_suspend)(struct usb_phy *x,
- + enum usb_device_speed speed);
- + int (*notify_resume)(struct usb_phy *x,
- + enum usb_device_speed speed);
- +
- };
-
- /**
- @@ -265,6 +277,15 @@
- }
-
- static inline int
- +usb_phy_set_wakeup(struct usb_phy *x, bool enabled)
- +{
- + if (x && x->set_wakeup)
- + return x->set_wakeup(x, enabled);
- + else
- + return 0;
- +}
- +
- +static inline int
- usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed)
- {
- if (x && x->notify_connect)
- @@ -281,6 +302,24 @@
- else
- return 0;
- }
- +
- +static inline int usb_phy_notify_suspend
- + (struct usb_phy *x, enum usb_device_speed speed)
- +{
- + if (x && x->notify_suspend)
- + return x->notify_suspend(x, speed);
- + else
- + return 0;
- +}
- +
- +static inline int usb_phy_notify_resume
- + (struct usb_phy *x, enum usb_device_speed speed)
- +{
- + if (x && x->notify_resume)
- + return x->notify_resume(x, speed);
- + else
- + return 0;
- +}
-
- /* notifiers */
- static inline int
- diff -Nur linux-3.14.35.orig/include/net/cfg80211.h linux-3.14.35/include/net/cfg80211.h
- --- linux-3.14.35.orig/include/net/cfg80211.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/net/cfg80211.h 2015-03-08 14:27:37.881684498 -0500
- @@ -1729,7 +1729,7 @@
- u8 *ssid;
- size_t ssid_len;
- enum nl80211_auth_type auth_type;
- - u8 *ie;
- + const u8 *ie;
- size_t ie_len;
- bool privacy;
- enum nl80211_mfp mfp;
- @@ -3888,6 +3888,7 @@
- *
- * @dev: network device
- * @bssid: the BSSID of the IBSS joined
- + * @channel: the channel of the IBSS joined
- * @gfp: allocation flags
- *
- * This function notifies cfg80211 that the device joined an IBSS or
- @@ -3897,7 +3898,8 @@
- * with the locally generated beacon -- this guarantees that there is
- * always a scan result for this IBSS. cfg80211 will handle the rest.
- */
- -void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);
- +void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
- + struct ieee80211_channel *channel, gfp_t gfp);
-
- /**
- * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate
- diff -Nur linux-3.14.35.orig/include/net/mac80211.h linux-3.14.35/include/net/mac80211.h
- --- linux-3.14.35.orig/include/net/mac80211.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/net/mac80211.h 2015-03-08 14:27:37.881684498 -0500
- @@ -1895,7 +1895,7 @@
- *
- * Driver informs U-APSD client support by enabling
- * %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the
- - * uapsd paramater in conf_tx() operation. Hardware needs to send the QoS
- + * uapsd parameter in conf_tx() operation. Hardware needs to send the QoS
- * Nullfunc frames and stay awake until the service period has ended. To
- * utilize U-APSD, dynamic powersave is disabled for voip AC and all frames
- * from that AC are transmitted with powersave enabled.
- @@ -2101,7 +2101,7 @@
- * with the number of frames to be released and which TIDs they are
- * to come from. In this case, the driver is responsible for setting
- * the EOSP (for uAPSD) and MORE_DATA bits in the released frames,
- - * to help the @more_data paramter is passed to tell the driver if
- + * to help the @more_data parameter is passed to tell the driver if
- * there is more data on other TIDs -- the TIDs to release frames
- * from are ignored since mac80211 doesn't know how many frames the
- * buffers for those TIDs contain.
- @@ -2616,6 +2616,7 @@
- * of queues to flush, which is useful if different virtual interfaces
- * use different hardware queues; it may also indicate all queues.
- * If the parameter @drop is set to %true, pending frames may be dropped.
- + * Note that vif can be NULL.
- * The callback can sleep.
- *
- * @channel_switch: Drivers that need (or want) to offload the channel
- @@ -2662,7 +2663,7 @@
- * parameters. In the case where the driver buffers some frames for
- * sleeping stations mac80211 will use this callback to tell the driver
- * to release some frames, either for PS-poll or uAPSD.
- - * Note that if the @more_data paramter is %false the driver must check
- + * Note that if the @more_data parameter is %false the driver must check
- * if there are more frames on the given TIDs, and if there are more than
- * the frames being released then it must still set the more-data bit in
- * the frame. If the @more_data parameter is %true, then of course the
- @@ -2878,7 +2879,8 @@
- struct netlink_callback *cb,
- void *data, int len);
- #endif
- - void (*flush)(struct ieee80211_hw *hw, u32 queues, bool drop);
- + void (*flush)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- + u32 queues, bool drop);
- void (*channel_switch)(struct ieee80211_hw *hw,
- struct ieee80211_channel_switch *ch_switch);
- int (*napi_poll)(struct ieee80211_hw *hw, int budget);
- diff -Nur linux-3.14.35.orig/include/net/rtnetlink.h linux-3.14.35/include/net/rtnetlink.h
- --- linux-3.14.35.orig/include/net/rtnetlink.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/net/rtnetlink.h 2015-03-08 14:27:37.881684498 -0500
- @@ -140,7 +140,7 @@
- struct nlattr *tb[]);
- int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm);
-
- -extern const struct nla_policy ifla_policy[IFLA_MAX+1];
- +int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len);
-
- #define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)
-
- diff -Nur linux-3.14.35.orig/include/net/tso.h linux-3.14.35/include/net/tso.h
- --- linux-3.14.35.orig/include/net/tso.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/net/tso.h 2015-03-08 14:27:37.881684498 -0500
- @@ -0,0 +1,20 @@
- +#ifndef _TSO_H
- +#define _TSO_H
- +
- +#include <net/ip.h>
- +
- +struct tso_t {
- + int next_frag_idx;
- + void *data;
- + size_t size;
- + u16 ip_id;
- + u32 tcp_seq;
- +};
- +
- +int tso_count_descs(struct sk_buff *skb);
- +void tso_build_hdr(struct sk_buff *skb, char *hdr, struct tso_t *tso,
- + int size, bool is_last);
- +void tso_build_data(struct sk_buff *skb, struct tso_t *tso, int size);
- +void tso_start(struct sk_buff *skb, struct tso_t *tso);
- +
- +#endif /* _TSO_H */
- diff -Nur linux-3.14.35.orig/include/sound/wm8962.h linux-3.14.35/include/sound/wm8962.h
- --- linux-3.14.35.orig/include/sound/wm8962.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/sound/wm8962.h 2015-03-08 14:27:37.881684498 -0500
- @@ -55,6 +55,9 @@
- * in a DC measurement configuration.
- */
- bool in4_dc_measure;
- +
- + /* MCLK for wm8962 */
- + struct clk *codec_mclk;
- };
-
- #endif
- diff -Nur linux-3.14.35.orig/include/trace/events/cpufreq_interactive.h linux-3.14.35/include/trace/events/cpufreq_interactive.h
- --- linux-3.14.35.orig/include/trace/events/cpufreq_interactive.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/trace/events/cpufreq_interactive.h 2015-03-08 14:27:37.885684498 -0500
- @@ -0,0 +1,112 @@
- +#undef TRACE_SYSTEM
- +#define TRACE_SYSTEM cpufreq_interactive
- +
- +#if !defined(_TRACE_CPUFREQ_INTERACTIVE_H) || defined(TRACE_HEADER_MULTI_READ)
- +#define _TRACE_CPUFREQ_INTERACTIVE_H
- +
- +#include <linux/tracepoint.h>
- +
- +DECLARE_EVENT_CLASS(set,
- + TP_PROTO(u32 cpu_id, unsigned long targfreq,
- + unsigned long actualfreq),
- + TP_ARGS(cpu_id, targfreq, actualfreq),
- +
- + TP_STRUCT__entry(
- + __field( u32, cpu_id )
- + __field(unsigned long, targfreq )
- + __field(unsigned long, actualfreq )
- + ),
- +
- + TP_fast_assign(
- + __entry->cpu_id = (u32) cpu_id;
- + __entry->targfreq = targfreq;
- + __entry->actualfreq = actualfreq;
- + ),
- +
- + TP_printk("cpu=%u targ=%lu actual=%lu",
- + __entry->cpu_id, __entry->targfreq,
- + __entry->actualfreq)
- +);
- +
- +DEFINE_EVENT(set, cpufreq_interactive_setspeed,
- + TP_PROTO(u32 cpu_id, unsigned long targfreq,
- + unsigned long actualfreq),
- + TP_ARGS(cpu_id, targfreq, actualfreq)
- +);
- +
- +DECLARE_EVENT_CLASS(loadeval,
- + TP_PROTO(unsigned long cpu_id, unsigned long load,
- + unsigned long curtarg, unsigned long curactual,
- + unsigned long newtarg),
- + TP_ARGS(cpu_id, load, curtarg, curactual, newtarg),
- +
- + TP_STRUCT__entry(
- + __field(unsigned long, cpu_id )
- + __field(unsigned long, load )
- + __field(unsigned long, curtarg )
- + __field(unsigned long, curactual )
- + __field(unsigned long, newtarg )
- + ),
- +
- + TP_fast_assign(
- + __entry->cpu_id = cpu_id;
- + __entry->load = load;
- + __entry->curtarg = curtarg;
- + __entry->curactual = curactual;
- + __entry->newtarg = newtarg;
- + ),
- +
- + TP_printk("cpu=%lu load=%lu cur=%lu actual=%lu targ=%lu",
- + __entry->cpu_id, __entry->load, __entry->curtarg,
- + __entry->curactual, __entry->newtarg)
- +);
- +
- +DEFINE_EVENT(loadeval, cpufreq_interactive_target,
- + TP_PROTO(unsigned long cpu_id, unsigned long load,
- + unsigned long curtarg, unsigned long curactual,
- + unsigned long newtarg),
- + TP_ARGS(cpu_id, load, curtarg, curactual, newtarg)
- +);
- +
- +DEFINE_EVENT(loadeval, cpufreq_interactive_already,
- + TP_PROTO(unsigned long cpu_id, unsigned long load,
- + unsigned long curtarg, unsigned long curactual,
- + unsigned long newtarg),
- + TP_ARGS(cpu_id, load, curtarg, curactual, newtarg)
- +);
- +
- +DEFINE_EVENT(loadeval, cpufreq_interactive_notyet,
- + TP_PROTO(unsigned long cpu_id, unsigned long load,
- + unsigned long curtarg, unsigned long curactual,
- + unsigned long newtarg),
- + TP_ARGS(cpu_id, load, curtarg, curactual, newtarg)
- +);
- +
- +TRACE_EVENT(cpufreq_interactive_boost,
- + TP_PROTO(const char *s),
- + TP_ARGS(s),
- + TP_STRUCT__entry(
- + __string(s, s)
- + ),
- + TP_fast_assign(
- + __assign_str(s, s);
- + ),
- + TP_printk("%s", __get_str(s))
- +);
- +
- +TRACE_EVENT(cpufreq_interactive_unboost,
- + TP_PROTO(const char *s),
- + TP_ARGS(s),
- + TP_STRUCT__entry(
- + __string(s, s)
- + ),
- + TP_fast_assign(
- + __assign_str(s, s);
- + ),
- + TP_printk("%s", __get_str(s))
- +);
- +
- +#endif /* _TRACE_CPUFREQ_INTERACTIVE_H */
- +
- +/* This part must be outside protection */
- +#include <trace/define_trace.h>
- diff -Nur linux-3.14.35.orig/include/uapi/linux/ipu.h linux-3.14.35/include/uapi/linux/ipu.h
- --- linux-3.14.35.orig/include/uapi/linux/ipu.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/uapi/linux/ipu.h 2015-03-08 14:27:37.885684498 -0500
- @@ -0,0 +1,282 @@
- +/*
- + * Copyright (C) 2013 Freescale Semiconductor, Inc. All Rights Reserved
- + */
- +
- +/*
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +/*!
- + * @defgroup IPU MXC Image Processing Unit (IPU) Driver
- + */
- +/*!
- + * @file uapi/linux/ipu.h
- + *
- + * @brief This file contains the IPU driver API declarations.
- + *
- + * @ingroup IPU
- + */
- +
- +#ifndef __ASM_ARCH_IPU_H__
- +#define __ASM_ARCH_IPU_H__
- +
- +#include <linux/types.h>
- +#include <linux/videodev2.h>
- +
- +#ifndef __KERNEL__
- +#ifndef __cplusplus
- +typedef unsigned char bool;
- +#endif
- +#define irqreturn_t int
- +#define dma_addr_t int
- +#define uint32_t unsigned int
- +#define uint16_t unsigned short
- +#define uint8_t unsigned char
- +#define u32 unsigned int
- +#define u8 unsigned char
- +#define __u32 u32
- +#endif
- +
- +/*!
- + * Enumeration of IPU rotation modes
- + */
- +typedef enum {
- + /* Note the enum values correspond to BAM value */
- + IPU_ROTATE_NONE = 0,
- + IPU_ROTATE_VERT_FLIP = 1,
- + IPU_ROTATE_HORIZ_FLIP = 2,
- + IPU_ROTATE_180 = 3,
- + IPU_ROTATE_90_RIGHT = 4,
- + IPU_ROTATE_90_RIGHT_VFLIP = 5,
- + IPU_ROTATE_90_RIGHT_HFLIP = 6,
- + IPU_ROTATE_90_LEFT = 7,
- +} ipu_rotate_mode_t;
- +
- +/*!
- + * Enumeration of VDI MOTION select
- + */
- +typedef enum {
- + MED_MOTION = 0,
- + LOW_MOTION = 1,
- + HIGH_MOTION = 2,
- +} ipu_motion_sel;
- +
- +/*!
- + * Enumeration of DI ports for ADC.
- + */
- +typedef enum {
- + DISP0,
- + DISP1,
- + DISP2,
- + DISP3
- +} display_port_t;
- +
- +/* IPU Pixel format definitions */
- +/* Four-character-code (FOURCC) */
- +#define fourcc(a, b, c, d)\
- + (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24))
- +
- +/*!
- + * @name IPU Pixel Formats
- + *
- + * Pixel formats are defined with ASCII FOURCC code. The pixel format codes are
- + * the same used by V4L2 API.
- + */
- +
- +/*! @{ */
- +/*! @name Generic or Raw Data Formats */
- +/*! @{ */
- +#define IPU_PIX_FMT_GENERIC fourcc('I', 'P', 'U', '0') /*!< IPU Generic Data */
- +#define IPU_PIX_FMT_GENERIC_32 fourcc('I', 'P', 'U', '1') /*!< IPU Generic Data */
- +#define IPU_PIX_FMT_GENERIC_16 fourcc('I', 'P', 'U', '2') /*!< IPU Generic Data */
- +#define IPU_PIX_FMT_LVDS666 fourcc('L', 'V', 'D', '6') /*!< IPU Generic Data */
- +#define IPU_PIX_FMT_LVDS888 fourcc('L', 'V', 'D', '8') /*!< IPU Generic Data */
- +/*! @} */
- +/*! @name RGB Formats */
- +/*! @{ */
- +#define IPU_PIX_FMT_RGB332 fourcc('R', 'G', 'B', '1') /*!< 8 RGB-3-3-2 */
- +#define IPU_PIX_FMT_RGB555 fourcc('R', 'G', 'B', 'O') /*!< 16 RGB-5-5-5 */
- +#define IPU_PIX_FMT_RGB565 fourcc('R', 'G', 'B', 'P') /*!< 1 6 RGB-5-6-5 */
- +#define IPU_PIX_FMT_RGB666 fourcc('R', 'G', 'B', '6') /*!< 18 RGB-6-6-6 */
- +#define IPU_PIX_FMT_BGR666 fourcc('B', 'G', 'R', '6') /*!< 18 BGR-6-6-6 */
- +#define IPU_PIX_FMT_BGR24 fourcc('B', 'G', 'R', '3') /*!< 24 BGR-8-8-8 */
- +#define IPU_PIX_FMT_RGB24 fourcc('R', 'G', 'B', '3') /*!< 24 RGB-8-8-8 */
- +#define IPU_PIX_FMT_GBR24 fourcc('G', 'B', 'R', '3') /*!< 24 GBR-8-8-8 */
- +#define IPU_PIX_FMT_BGR32 fourcc('B', 'G', 'R', '4') /*!< 32 BGR-8-8-8-8 */
- +#define IPU_PIX_FMT_BGRA32 fourcc('B', 'G', 'R', 'A') /*!< 32 BGR-8-8-8-8 */
- +#define IPU_PIX_FMT_RGB32 fourcc('R', 'G', 'B', '4') /*!< 32 RGB-8-8-8-8 */
- +#define IPU_PIX_FMT_RGBA32 fourcc('R', 'G', 'B', 'A') /*!< 32 RGB-8-8-8-8 */
- +#define IPU_PIX_FMT_ABGR32 fourcc('A', 'B', 'G', 'R') /*!< 32 ABGR-8-8-8-8 */
- +/*! @} */
- +/*! @name YUV Interleaved Formats */
- +/*! @{ */
- +#define IPU_PIX_FMT_YUYV fourcc('Y', 'U', 'Y', 'V') /*!< 16 YUV 4:2:2 */
- +#define IPU_PIX_FMT_UYVY fourcc('U', 'Y', 'V', 'Y') /*!< 16 YUV 4:2:2 */
- +#define IPU_PIX_FMT_YVYU fourcc('Y', 'V', 'Y', 'U') /*!< 16 YVYU 4:2:2 */
- +#define IPU_PIX_FMT_VYUY fourcc('V', 'Y', 'U', 'Y') /*!< 16 VYYU 4:2:2 */
- +#define IPU_PIX_FMT_Y41P fourcc('Y', '4', '1', 'P') /*!< 12 YUV 4:1:1 */
- +#define IPU_PIX_FMT_YUV444 fourcc('Y', '4', '4', '4') /*!< 24 YUV 4:4:4 */
- +#define IPU_PIX_FMT_VYU444 fourcc('V', '4', '4', '4') /*!< 24 VYU 4:4:4 */
- +/* two planes -- one Y, one Cb + Cr interleaved */
- +#define IPU_PIX_FMT_NV12 fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */
- +/* two planes -- 12 tiled Y/CbCr 4:2:0 */
- +#define IPU_PIX_FMT_TILED_NV12 fourcc('T', 'N', 'V', 'P')
- +#define IPU_PIX_FMT_TILED_NV12F fourcc('T', 'N', 'V', 'F')
- +
- +/*! @} */
- +/*! @name YUV Planar Formats */
- +/*! @{ */
- +#define IPU_PIX_FMT_GREY fourcc('G', 'R', 'E', 'Y') /*!< 8 Greyscale */
- +#define IPU_PIX_FMT_YVU410P fourcc('Y', 'V', 'U', '9') /*!< 9 YVU 4:1:0 */
- +#define IPU_PIX_FMT_YUV410P fourcc('Y', 'U', 'V', '9') /*!< 9 YUV 4:1:0 */
- +#define IPU_PIX_FMT_YVU420P fourcc('Y', 'V', '1', '2') /*!< 12 YVU 4:2:0 */
- +#define IPU_PIX_FMT_YUV420P fourcc('I', '4', '2', '0') /*!< 12 YUV 4:2:0 */
- +#define IPU_PIX_FMT_YUV420P2 fourcc('Y', 'U', '1', '2') /*!< 12 YUV 4:2:0 */
- +#define IPU_PIX_FMT_YVU422P fourcc('Y', 'V', '1', '6') /*!< 16 YVU 4:2:2 */
- +#define IPU_PIX_FMT_YUV422P fourcc('4', '2', '2', 'P') /*!< 16 YUV 4:2:2 */
- +/* non-interleaved 4:4:4 */
- +#define IPU_PIX_FMT_YUV444P fourcc('4', '4', '4', 'P') /*!< 24 YUV 4:4:4 */
- +/*! @} */
- +#define IPU_PIX_FMT_TILED_NV12_MBALIGN (16)
- +#define TILED_NV12_FRAME_SIZE(w, h) \
- + (ALIGN((w) * (h), SZ_4K) + ALIGN((w) * (h) / 2, SZ_4K))
- +/* IPU device */
- +typedef enum {
- + RGB_CS,
- + YUV_CS,
- + NULL_CS
- +} cs_t;
- +
- +struct ipu_pos {
- + u32 x;
- + u32 y;
- +};
- +
- +struct ipu_crop {
- + struct ipu_pos pos;
- + u32 w;
- + u32 h;
- +};
- +
- +struct ipu_deinterlace {
- + bool enable;
- + u8 motion; /*see ipu_motion_sel*/
- +#define IPU_DEINTERLACE_FIELD_TOP 0
- +#define IPU_DEINTERLACE_FIELD_BOTTOM 1
- +#define IPU_DEINTERLACE_FIELD_MASK \
- + (IPU_DEINTERLACE_FIELD_TOP | IPU_DEINTERLACE_FIELD_BOTTOM)
- + /* deinterlace frame rate double flags */
- +#define IPU_DEINTERLACE_RATE_EN 0x80
- +#define IPU_DEINTERLACE_RATE_FRAME1 0x40
- +#define IPU_DEINTERLACE_RATE_MASK \
- + (IPU_DEINTERLACE_RATE_EN | IPU_DEINTERLACE_RATE_FRAME1)
- +#define IPU_DEINTERLACE_MAX_FRAME 2
- + u8 field_fmt;
- +};
- +
- +struct ipu_input {
- + u32 width;
- + u32 height;
- + u32 format;
- + struct ipu_crop crop;
- + dma_addr_t paddr;
- +
- + struct ipu_deinterlace deinterlace;
- + dma_addr_t paddr_n; /*valid when deinterlace enable*/
- +};
- +
- +struct ipu_alpha {
- +#define IPU_ALPHA_MODE_GLOBAL 0
- +#define IPU_ALPHA_MODE_LOCAL 1
- + u8 mode;
- + u8 gvalue; /* 0~255 */
- + dma_addr_t loc_alp_paddr;
- +};
- +
- +struct ipu_colorkey {
- + bool enable;
- + u32 value; /* RGB 24bit */
- +};
- +
- +struct ipu_overlay {
- + u32 width;
- + u32 height;
- + u32 format;
- + struct ipu_crop crop;
- + struct ipu_alpha alpha;
- + struct ipu_colorkey colorkey;
- + dma_addr_t paddr;
- +};
- +
- +struct ipu_output {
- + u32 width;
- + u32 height;
- + u32 format;
- + u8 rotate;
- + struct ipu_crop crop;
- + dma_addr_t paddr;
- +};
- +
- +struct ipu_task {
- + struct ipu_input input;
- + struct ipu_output output;
- +
- + bool overlay_en;
- + struct ipu_overlay overlay;
- +
- +#define IPU_TASK_PRIORITY_NORMAL 0
- +#define IPU_TASK_PRIORITY_HIGH 1
- + u8 priority;
- +
- +#define IPU_TASK_ID_ANY 0
- +#define IPU_TASK_ID_VF 1
- +#define IPU_TASK_ID_PP 2
- +#define IPU_TASK_ID_MAX 3
- + u8 task_id;
- +
- + int timeout;
- +};
- +
- +enum {
- + IPU_CHECK_OK = 0,
- + IPU_CHECK_WARN_INPUT_OFFS_NOT8ALIGN = 0x1,
- + IPU_CHECK_WARN_OUTPUT_OFFS_NOT8ALIGN = 0x2,
- + IPU_CHECK_WARN_OVERLAY_OFFS_NOT8ALIGN = 0x4,
- + IPU_CHECK_ERR_MIN,
- + IPU_CHECK_ERR_INPUT_CROP,
- + IPU_CHECK_ERR_OUTPUT_CROP,
- + IPU_CHECK_ERR_OVERLAY_CROP,
- + IPU_CHECK_ERR_INPUT_OVER_LIMIT,
- + IPU_CHECK_ERR_OV_OUT_NO_FIT,
- + IPU_CHECK_ERR_OVERLAY_WITH_VDI,
- + IPU_CHECK_ERR_PROC_NO_NEED,
- + IPU_CHECK_ERR_SPLIT_INPUTW_OVER,
- + IPU_CHECK_ERR_SPLIT_INPUTH_OVER,
- + IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER,
- + IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER,
- + IPU_CHECK_ERR_SPLIT_WITH_ROT,
- + IPU_CHECK_ERR_NOT_SUPPORT,
- + IPU_CHECK_ERR_NOT16ALIGN,
- + IPU_CHECK_ERR_W_DOWNSIZE_OVER,
- + IPU_CHECK_ERR_H_DOWNSIZE_OVER,
- +};
- +
- +/* IOCTL commands */
- +#define IPU_CHECK_TASK _IOWR('I', 0x1, struct ipu_task)
- +#define IPU_QUEUE_TASK _IOW('I', 0x2, struct ipu_task)
- +#define IPU_ALLOC _IOWR('I', 0x3, int)
- +#define IPU_FREE _IOW('I', 0x4, int)
- +
- +#endif
- diff -Nur linux-3.14.35.orig/include/uapi/linux/isl29023.h linux-3.14.35/include/uapi/linux/isl29023.h
- --- linux-3.14.35.orig/include/uapi/linux/isl29023.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/uapi/linux/isl29023.h 2015-03-08 14:27:37.885684498 -0500
- @@ -0,0 +1,47 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- +
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#ifndef __UAPI_LINUX_ISL29023_H__
- +#define __UAPI_LINUX_ISL29023_H__
- +
- +#include <linux/types.h>
- +
- +#define ISL29023_PD_MODE 0x0
- +#define ISL29023_ALS_ONCE_MODE 0x1
- +#define ISL29023_IR_ONCE_MODE 0x2
- +#define ISL29023_ALS_CONT_MODE 0x5
- +#define ISL29023_IR_CONT_MODE 0x6
- +
- +#define ISL29023_INT_PERSISTS_1 0x0
- +#define ISL29023_INT_PERSISTS_4 0x1
- +#define ISL29023_INT_PERSISTS_8 0x2
- +#define ISL29023_INT_PERSISTS_16 0x3
- +
- +#define ISL29023_RES_16 0x0
- +#define ISL29023_RES_12 0x1
- +#define ISL29023_RES_8 0x2
- +#define ISL29023_RES_4 0x3
- +
- +#define ISL29023_RANGE_1K 0x0
- +#define ISL29023_RANGE_4K 0x1
- +#define ISL29023_RANGE_16K 0x2
- +#define ISL29023_RANGE_64K 0x3
- +
- +#endif
- diff -Nur linux-3.14.35.orig/include/uapi/linux/Kbuild linux-3.14.35/include/uapi/linux/Kbuild
- --- linux-3.14.35.orig/include/uapi/linux/Kbuild 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/uapi/linux/Kbuild 2015-03-08 14:27:37.885684498 -0500
- @@ -226,6 +226,7 @@
- header-y += kvm_para.h
- endif
-
- +header-y += ipu.h
- header-y += l2tp.h
- header-y += libc-compat.h
- header-y += limits.h
- @@ -253,6 +254,9 @@
- header-y += msdos_fs.h
- header-y += msg.h
- header-y += mtio.h
- +header-y += mxcfb.h
- +header-y += mxc_asrc.h
- +header-y += mxc_v4l2.h
- header-y += n_r3964.h
- header-y += nbd.h
- header-y += ncp.h
- @@ -318,6 +322,8 @@
- header-y += prctl.h
- header-y += ptp_clock.h
- header-y += ptrace.h
- +header-y += pxp_dma.h
- +header-y += pxp_device.h
- header-y += qnx4_fs.h
- header-y += qnxtypes.h
- header-y += quota.h
- diff -Nur linux-3.14.35.orig/include/uapi/linux/mxc_asrc.h linux-3.14.35/include/uapi/linux/mxc_asrc.h
- --- linux-3.14.35.orig/include/uapi/linux/mxc_asrc.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/uapi/linux/mxc_asrc.h 2015-03-08 14:27:37.885684498 -0500
- @@ -0,0 +1,143 @@
- +/*
- + * Copyright 2008-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + *
- + * @file mxc_asrc.h
- + *
- + * @brief i.MX Asynchronous Sample Rate Converter
- + *
- + * @ingroup Audio
- + */
- +
- +#ifndef __MXC_ASRC_UAPI_H__
- +#define __MXC_ASRC_UAPI_H__
- +
- +#define ASRC_IOC_MAGIC 'C'
- +
- +#define ASRC_REQ_PAIR _IOWR(ASRC_IOC_MAGIC, 0, struct asrc_req)
- +#define ASRC_CONFIG_PAIR _IOWR(ASRC_IOC_MAGIC, 1, struct asrc_config)
- +#define ASRC_RELEASE_PAIR _IOW(ASRC_IOC_MAGIC, 2, enum asrc_pair_index)
- +#define ASRC_CONVERT _IOW(ASRC_IOC_MAGIC, 3, struct asrc_convert_buffer)
- +#define ASRC_START_CONV _IOW(ASRC_IOC_MAGIC, 4, enum asrc_pair_index)
- +#define ASRC_STOP_CONV _IOW(ASRC_IOC_MAGIC, 5, enum asrc_pair_index)
- +#define ASRC_STATUS _IOW(ASRC_IOC_MAGIC, 6, struct asrc_status_flags)
- +#define ASRC_FLUSH _IOW(ASRC_IOC_MAGIC, 7, enum asrc_pair_index)
- +
- +enum asrc_pair_index {
- + ASRC_UNVALID_PAIR = -1,
- + ASRC_PAIR_A = 0,
- + ASRC_PAIR_B = 1,
- + ASRC_PAIR_C = 2,
- +};
- +
- +#define ASRC_PAIR_MAX_NUM (ASRC_PAIR_C + 1)
- +
- +enum asrc_inclk {
- + INCLK_NONE = 0x03,
- + INCLK_ESAI_RX = 0x00,
- + INCLK_SSI1_RX = 0x01,
- + INCLK_SSI2_RX = 0x02,
- + INCLK_SSI3_RX = 0x07,
- + INCLK_SPDIF_RX = 0x04,
- + INCLK_MLB_CLK = 0x05,
- + INCLK_PAD = 0x06,
- + INCLK_ESAI_TX = 0x08,
- + INCLK_SSI1_TX = 0x09,
- + INCLK_SSI2_TX = 0x0a,
- + INCLK_SSI3_TX = 0x0b,
- + INCLK_SPDIF_TX = 0x0c,
- + INCLK_ASRCK1_CLK = 0x0f,
- +};
- +
- +enum asrc_outclk {
- + OUTCLK_NONE = 0x03,
- + OUTCLK_ESAI_TX = 0x00,
- + OUTCLK_SSI1_TX = 0x01,
- + OUTCLK_SSI2_TX = 0x02,
- + OUTCLK_SSI3_TX = 0x07,
- + OUTCLK_SPDIF_TX = 0x04,
- + OUTCLK_MLB_CLK = 0x05,
- + OUTCLK_PAD = 0x06,
- + OUTCLK_ESAI_RX = 0x08,
- + OUTCLK_SSI1_RX = 0x09,
- + OUTCLK_SSI2_RX = 0x0a,
- + OUTCLK_SSI3_RX = 0x0b,
- + OUTCLK_SPDIF_RX = 0x0c,
- + OUTCLK_ASRCK1_CLK = 0x0f,
- +};
- +
- +enum asrc_word_width {
- + ASRC_WIDTH_24_BIT = 0,
- + ASRC_WIDTH_16_BIT = 1,
- + ASRC_WIDTH_8_BIT = 2,
- +};
- +
- +struct asrc_config {
- + enum asrc_pair_index pair;
- + unsigned int channel_num;
- + unsigned int buffer_num;
- + unsigned int dma_buffer_size;
- + unsigned int input_sample_rate;
- + unsigned int output_sample_rate;
- + enum asrc_word_width input_word_width;
- + enum asrc_word_width output_word_width;
- + enum asrc_inclk inclk;
- + enum asrc_outclk outclk;
- +};
- +
- +struct asrc_pair {
- + unsigned int start_channel;
- + unsigned int chn_num;
- + unsigned int chn_max;
- + unsigned int active;
- + unsigned int overload_error;
- +};
- +
- +struct asrc_req {
- + unsigned int chn_num;
- + enum asrc_pair_index index;
- +};
- +
- +struct asrc_querybuf {
- + unsigned int buffer_index;
- + unsigned int input_length;
- + unsigned int output_length;
- + unsigned long input_offset;
- + unsigned long output_offset;
- +};
- +
- +struct asrc_convert_buffer {
- + void *input_buffer_vaddr;
- + void *output_buffer_vaddr;
- + unsigned int input_buffer_length;
- + unsigned int output_buffer_length;
- +};
- +
- +struct asrc_buffer {
- + unsigned int index;
- + unsigned int length;
- + unsigned int output_last_length;
- + int buf_valid;
- +};
- +
- +struct asrc_status_flags {
- + enum asrc_pair_index index;
- + unsigned int overload_error;
- +};
- +
- +#define ASRC_BUF_NA -35 /* ASRC DQ's buffer is NOT available */
- +#define ASRC_BUF_AV 35 /* ASRC DQ's buffer is available */
- +enum asrc_error_status {
- + ASRC_TASK_Q_OVERLOAD = 0x01,
- + ASRC_OUTPUT_TASK_OVERLOAD = 0x02,
- + ASRC_INPUT_TASK_OVERLOAD = 0x04,
- + ASRC_OUTPUT_BUFFER_OVERFLOW = 0x08,
- + ASRC_INPUT_BUFFER_UNDERRUN = 0x10,
- +};
- +#endif/* __MXC_ASRC_UAPI_H__ */
- diff -Nur linux-3.14.35.orig/include/uapi/linux/mxcfb.h linux-3.14.35/include/uapi/linux/mxcfb.h
- --- linux-3.14.35.orig/include/uapi/linux/mxcfb.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/uapi/linux/mxcfb.h 2015-03-08 14:27:37.885684498 -0500
- @@ -0,0 +1,174 @@
- +/*
- + * Copyright (C) 2013 Freescale Semiconductor, Inc. All Rights Reserved
- + */
- +
- +/*
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +/*
- + * @file uapi/linux/mxcfb.h
- + *
- + * @brief Global header file for the MXC frame buffer
- + *
- + * @ingroup Framebuffer
- + */
- +#ifndef __ASM_ARCH_MXCFB_H__
- +#define __ASM_ARCH_MXCFB_H__
- +
- +#include <linux/fb.h>
- +
- +#define FB_SYNC_OE_LOW_ACT 0x80000000
- +#define FB_SYNC_CLK_LAT_FALL 0x40000000
- +#define FB_SYNC_DATA_INVERT 0x20000000
- +#define FB_SYNC_CLK_IDLE_EN 0x10000000
- +#define FB_SYNC_SHARP_MODE 0x08000000
- +#define FB_SYNC_SWAP_RGB 0x04000000
- +#define FB_ACCEL_TRIPLE_FLAG 0x00000000
- +#define FB_ACCEL_DOUBLE_FLAG 0x00000001
- +
- +struct mxcfb_gbl_alpha {
- + int enable;
- + int alpha;
- +};
- +
- +struct mxcfb_loc_alpha {
- + int enable;
- + int alpha_in_pixel;
- + unsigned long alpha_phy_addr0;
- + unsigned long alpha_phy_addr1;
- +};
- +
- +struct mxcfb_color_key {
- + int enable;
- + __u32 color_key;
- +};
- +
- +struct mxcfb_pos {
- + __u16 x;
- + __u16 y;
- +};
- +
- +struct mxcfb_gamma {
- + int enable;
- + int constk[16];
- + int slopek[16];
- +};
- +
- +struct mxcfb_rect {
- + __u32 top;
- + __u32 left;
- + __u32 width;
- + __u32 height;
- +};
- +
- +#define GRAYSCALE_8BIT 0x1
- +#define GRAYSCALE_8BIT_INVERTED 0x2
- +#define GRAYSCALE_4BIT 0x3
- +#define GRAYSCALE_4BIT_INVERTED 0x4
- +
- +#define AUTO_UPDATE_MODE_REGION_MODE 0
- +#define AUTO_UPDATE_MODE_AUTOMATIC_MODE 1
- +
- +#define UPDATE_SCHEME_SNAPSHOT 0
- +#define UPDATE_SCHEME_QUEUE 1
- +#define UPDATE_SCHEME_QUEUE_AND_MERGE 2
- +
- +#define UPDATE_MODE_PARTIAL 0x0
- +#define UPDATE_MODE_FULL 0x1
- +
- +#define WAVEFORM_MODE_AUTO 257
- +
- +#define TEMP_USE_AMBIENT 0x1000
- +
- +#define EPDC_FLAG_ENABLE_INVERSION 0x01
- +#define EPDC_FLAG_FORCE_MONOCHROME 0x02
- +#define EPDC_FLAG_USE_CMAP 0x04
- +#define EPDC_FLAG_USE_ALT_BUFFER 0x100
- +#define EPDC_FLAG_TEST_COLLISION 0x200
- +#define EPDC_FLAG_GROUP_UPDATE 0x400
- +#define EPDC_FLAG_USE_DITHERING_Y1 0x2000
- +#define EPDC_FLAG_USE_DITHERING_Y4 0x4000
- +
- +#define FB_POWERDOWN_DISABLE -1
- +
- +struct mxcfb_alt_buffer_data {
- + __u32 phys_addr;
- + __u32 width; /* width of entire buffer */
- + __u32 height; /* height of entire buffer */
- + struct mxcfb_rect alt_update_region; /* region within buffer to update */
- +};
- +
- +struct mxcfb_update_data {
- + struct mxcfb_rect update_region;
- + __u32 waveform_mode;
- + __u32 update_mode;
- + __u32 update_marker;
- + int temp;
- + unsigned int flags;
- + struct mxcfb_alt_buffer_data alt_buffer_data;
- +};
- +
- +struct mxcfb_update_marker_data {
- + __u32 update_marker;
- + __u32 collision_test;
- +};
- +
- +/*
- + * Structure used to define waveform modes for driver
- + * Needed for driver to perform auto-waveform selection
- + */
- +struct mxcfb_waveform_modes {
- + int mode_init;
- + int mode_du;
- + int mode_gc4;
- + int mode_gc8;
- + int mode_gc16;
- + int mode_gc32;
- +};
- +
- +/*
- + * Structure used to define a 5*3 matrix of parameters for
- + * setting IPU DP CSC module related to this framebuffer.
- + */
- +struct mxcfb_csc_matrix {
- + int param[5][3];
- +};
- +
- +#define MXCFB_WAIT_FOR_VSYNC _IOW('F', 0x20, u_int32_t)
- +#define MXCFB_SET_GBL_ALPHA _IOW('F', 0x21, struct mxcfb_gbl_alpha)
- +#define MXCFB_SET_CLR_KEY _IOW('F', 0x22, struct mxcfb_color_key)
- +#define MXCFB_SET_OVERLAY_POS _IOWR('F', 0x24, struct mxcfb_pos)
- +#define MXCFB_GET_FB_IPU_CHAN _IOR('F', 0x25, u_int32_t)
- +#define MXCFB_SET_LOC_ALPHA _IOWR('F', 0x26, struct mxcfb_loc_alpha)
- +#define MXCFB_SET_LOC_ALP_BUF _IOW('F', 0x27, unsigned long)
- +#define MXCFB_SET_GAMMA _IOW('F', 0x28, struct mxcfb_gamma)
- +#define MXCFB_GET_FB_IPU_DI _IOR('F', 0x29, u_int32_t)
- +#define MXCFB_GET_DIFMT _IOR('F', 0x2A, u_int32_t)
- +#define MXCFB_GET_FB_BLANK _IOR('F', 0x2B, u_int32_t)
- +#define MXCFB_SET_DIFMT _IOW('F', 0x2C, u_int32_t)
- +#define MXCFB_CSC_UPDATE _IOW('F', 0x2D, struct mxcfb_csc_matrix)
- +
- +/* IOCTLs for E-ink panel updates */
- +#define MXCFB_SET_WAVEFORM_MODES _IOW('F', 0x2B, struct mxcfb_waveform_modes)
- +#define MXCFB_SET_TEMPERATURE _IOW('F', 0x2C, int32_t)
- +#define MXCFB_SET_AUTO_UPDATE_MODE _IOW('F', 0x2D, __u32)
- +#define MXCFB_SEND_UPDATE _IOW('F', 0x2E, struct mxcfb_update_data)
- +#define MXCFB_WAIT_FOR_UPDATE_COMPLETE _IOWR('F', 0x2F, struct mxcfb_update_marker_data)
- +#define MXCFB_SET_PWRDOWN_DELAY _IOW('F', 0x30, int32_t)
- +#define MXCFB_GET_PWRDOWN_DELAY _IOR('F', 0x31, int32_t)
- +#define MXCFB_SET_UPDATE_SCHEME _IOW('F', 0x32, __u32)
- +#define MXCFB_GET_WORK_BUFFER _IOWR('F', 0x34, unsigned long)
- +#endif
- diff -Nur linux-3.14.35.orig/include/uapi/linux/mxc_mlb.h linux-3.14.35/include/uapi/linux/mxc_mlb.h
- --- linux-3.14.35.orig/include/uapi/linux/mxc_mlb.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/uapi/linux/mxc_mlb.h 2015-03-08 14:27:37.885684498 -0500
- @@ -0,0 +1,55 @@
- +/*
- + * mxc_mlb.h
- + *
- + * Copyright 2008-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#ifndef _MXC_MLB_UAPI_H
- +#define _MXC_MLB_UAPI_H
- +
- +/* define IOCTL command */
- +#define MLB_DBG_RUNTIME _IO('S', 0x09)
- +#define MLB_SET_FPS _IOW('S', 0x10, unsigned int)
- +#define MLB_GET_VER _IOR('S', 0x11, unsigned long)
- +#define MLB_SET_DEVADDR _IOR('S', 0x12, unsigned char)
- +
- +/*!
- + * set channel address for each logical channel
- + * the MSB 16bits is for tx channel, the left LSB is for rx channel
- + */
- +#define MLB_CHAN_SETADDR _IOW('S', 0x13, unsigned int)
- +#define MLB_CHAN_STARTUP _IO('S', 0x14)
- +#define MLB_CHAN_SHUTDOWN _IO('S', 0x15)
- +#define MLB_CHAN_GETEVENT _IOR('S', 0x16, unsigned long)
- +
- +#define MLB_SET_ISOC_BLKSIZE_188 _IO('S', 0x17)
- +#define MLB_SET_ISOC_BLKSIZE_196 _IO('S', 0x18)
- +#define MLB_SET_SYNC_QUAD _IOW('S', 0x19, unsigned int)
- +#define MLB_IRQ_ENABLE _IO('S', 0x20)
- +#define MLB_IRQ_DISABLE _IO('S', 0x21)
- +
- +/*!
- + * MLB event define
- + */
- +enum {
- + MLB_EVT_TX_PROTO_ERR_CUR = 1 << 0,
- + MLB_EVT_TX_BRK_DETECT_CUR = 1 << 1,
- + MLB_EVT_TX_PROTO_ERR_PREV = 1 << 8,
- + MLB_EVT_TX_BRK_DETECT_PREV = 1 << 9,
- + MLB_EVT_RX_PROTO_ERR_CUR = 1 << 16,
- + MLB_EVT_RX_BRK_DETECT_CUR = 1 << 17,
- + MLB_EVT_RX_PROTO_ERR_PREV = 1 << 24,
- + MLB_EVT_RX_BRK_DETECT_PREV = 1 << 25,
- +};
- +
- +
- +#endif /* _MXC_MLB_H */
- diff -Nur linux-3.14.35.orig/include/uapi/linux/mxc_v4l2.h linux-3.14.35/include/uapi/linux/mxc_v4l2.h
- --- linux-3.14.35.orig/include/uapi/linux/mxc_v4l2.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/uapi/linux/mxc_v4l2.h 2015-03-08 14:27:37.885684498 -0500
- @@ -0,0 +1,56 @@
- +/*
- + * Copyright (C) 2013 Freescale Semiconductor, Inc. All Rights Reserved
- + */
- +
- +/*
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +/*!
- + * @file uapi/linux/mxc_v4l2.h
- + *
- + * @brief MXC V4L2 private header file
- + *
- + * @ingroup MXC V4L2
- + */
- +
- +#ifndef __ASM_ARCH_MXC_V4L2_H__
- +#define __ASM_ARCH_MXC_V4L2_H__
- +
- +/*
- + * For IPUv1 and IPUv3, V4L2_CID_MXC_ROT means encoder ioctl ID.
- + * And V4L2_CID_MXC_VF_ROT is viewfinder ioctl ID only for IPUv1 and IPUv3.
- + */
- +#define V4L2_CID_MXC_ROT (V4L2_CID_PRIVATE_BASE + 0)
- +#define V4L2_CID_MXC_FLASH (V4L2_CID_PRIVATE_BASE + 1)
- +#define V4L2_CID_MXC_VF_ROT (V4L2_CID_PRIVATE_BASE + 2)
- +#define V4L2_CID_MXC_MOTION (V4L2_CID_PRIVATE_BASE + 3)
- +#define V4L2_CID_MXC_SWITCH_CAM (V4L2_CID_PRIVATE_BASE + 6)
- +
- +#define V4L2_MXC_ROTATE_NONE 0
- +#define V4L2_MXC_ROTATE_VERT_FLIP 1
- +#define V4L2_MXC_ROTATE_HORIZ_FLIP 2
- +#define V4L2_MXC_ROTATE_180 3
- +#define V4L2_MXC_ROTATE_90_RIGHT 4
- +#define V4L2_MXC_ROTATE_90_RIGHT_VFLIP 5
- +#define V4L2_MXC_ROTATE_90_RIGHT_HFLIP 6
- +#define V4L2_MXC_ROTATE_90_LEFT 7
- +
- +struct v4l2_mxc_offset {
- + uint32_t u_offset;
- + uint32_t v_offset;
- +};
- +
- +#endif
- diff -Nur linux-3.14.35.orig/include/uapi/linux/ptp_clock.h linux-3.14.35/include/uapi/linux/ptp_clock.h
- --- linux-3.14.35.orig/include/uapi/linux/ptp_clock.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/include/uapi/linux/ptp_clock.h 2015-03-08 14:27:37.885684498 -0500
- @@ -50,7 +50,8 @@
- int n_ext_ts; /* Number of external time stamp channels. */
- int n_per_out; /* Number of programmable periodic signals. */
- int pps; /* Whether the clock supports a PPS callback. */
- - int rsv[15]; /* Reserved for future use. */
- + int n_pins; /* Number of input/output pins. */
- + int rsv[14]; /* Reserved for future use. */
- };
-
- struct ptp_extts_request {
- @@ -80,6 +81,40 @@
- struct ptp_clock_time ts[2 * PTP_MAX_SAMPLES + 1];
- };
-
- +enum ptp_pin_function {
- + PTP_PF_NONE,
- + PTP_PF_EXTTS,
- + PTP_PF_PEROUT,
- + PTP_PF_PHYSYNC,
- +};
- +
- +struct ptp_pin_desc {
- + /*
- + * Hardware specific human readable pin name. This field is
- + * set by the kernel during the PTP_PIN_GETFUNC ioctl and is
- + * ignored for the PTP_PIN_SETFUNC ioctl.
- + */
- + char name[64];
- + /*
- + * Pin index in the range of zero to ptp_clock_caps.n_pins - 1.
- + */
- + unsigned int index;
- + /*
- + * Which of the PTP_PF_xxx functions to use on this pin.
- + */
- + unsigned int func;
- + /*
- + * The specific channel to use for this function.
- + * This corresponds to the 'index' field of the
- + * PTP_EXTTS_REQUEST and PTP_PEROUT_REQUEST ioctls.
- + */
- + unsigned int chan;
- + /*
- + * Reserved for future use.
- + */
- + unsigned int rsv[5];
- +};
- +
- #define PTP_CLK_MAGIC '='
-
- #define PTP_CLOCK_GETCAPS _IOR(PTP_CLK_MAGIC, 1, struct ptp_clock_caps)
- @@ -87,6 +122,8 @@
- #define PTP_PEROUT_REQUEST _IOW(PTP_CLK_MAGIC, 3, struct ptp_perout_request)
- #define PTP_ENABLE_PPS _IOW(PTP_CLK_MAGIC, 4, int)
- #define PTP_SYS_OFFSET _IOW(PTP_CLK_MAGIC, 5, struct ptp_sys_offset)
- +#define PTP_PIN_GETFUNC _IOWR(PTP_CLK_MAGIC, 6, struct ptp_pin_desc)
- +#define PTP_PIN_SETFUNC _IOW(PTP_CLK_MAGIC, 7, struct ptp_pin_desc)
-
- struct ptp_extts_event {
- struct ptp_clock_time t; /* Time event occured. */
- diff -Nur linux-3.14.35.orig/include/uapi/linux/pxp_device.h linux-3.14.35/include/uapi/linux/pxp_device.h
- --- linux-3.14.35.orig/include/uapi/linux/pxp_device.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/uapi/linux/pxp_device.h 2015-03-08 14:27:37.889684498 -0500
- @@ -0,0 +1,63 @@
- +/*
- + * Copyright (C) 2013-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + */
- +#ifndef _UAPI_PXP_DEVICE
- +#define _UAPI_PXP_DEVICE
- +
- +#include <linux/pxp_dma.h>
- +
- +struct pxp_chan_handle {
- + unsigned int handle;
- + int hist_status;
- +};
- +
- +struct pxp_mem_desc {
- + unsigned int handle;
- + unsigned int size;
- + dma_addr_t phys_addr;
- + unsigned int virt_uaddr; /* virtual user space address */
- + unsigned int mtype;
- +};
- +
- +struct pxp_mem_flush {
- + unsigned int handle;
- + unsigned int type;
- +};
- +
- +#define PXP_IOC_MAGIC 'P'
- +
- +#define PXP_IOC_GET_CHAN _IOR(PXP_IOC_MAGIC, 0, struct pxp_mem_desc)
- +#define PXP_IOC_PUT_CHAN _IOW(PXP_IOC_MAGIC, 1, struct pxp_mem_desc)
- +#define PXP_IOC_CONFIG_CHAN _IOW(PXP_IOC_MAGIC, 2, struct pxp_mem_desc)
- +#define PXP_IOC_START_CHAN _IOW(PXP_IOC_MAGIC, 3, struct pxp_mem_desc)
- +#define PXP_IOC_GET_PHYMEM _IOWR(PXP_IOC_MAGIC, 4, struct pxp_mem_desc)
- +#define PXP_IOC_PUT_PHYMEM _IOW(PXP_IOC_MAGIC, 5, struct pxp_mem_desc)
- +#define PXP_IOC_WAIT4CMPLT _IOWR(PXP_IOC_MAGIC, 6, struct pxp_mem_desc)
- +#define PXP_IOC_FLUSH_PHYMEM _IOR(PXP_IOC_MAGIC, 7, struct pxp_mem_flush)
- +
- +/* Memory types supported*/
- +#define MEMORY_TYPE_UNCACHED 0x0
- +#define MEMORY_TYPE_WC 0x1
- +#define MEMORY_TYPE_CACHED 0x2
- +
- +/* Cache flush operations */
- +#define CACHE_CLEAN 0x1
- +#define CACHE_INVALIDATE 0x2
- +#define CACHE_FLUSH 0x4
- +
- +#endif
- diff -Nur linux-3.14.35.orig/include/uapi/linux/pxp_dma.h linux-3.14.35/include/uapi/linux/pxp_dma.h
- --- linux-3.14.35.orig/include/uapi/linux/pxp_dma.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/uapi/linux/pxp_dma.h 2015-03-08 14:27:37.893684498 -0500
- @@ -0,0 +1,173 @@
- +/*
- + * Copyright (C) 2013-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + */
- +#ifndef _UAPI_PXP_DMA
- +#define _UAPI_PXP_DMA
- +
- +#include <linux/posix_types.h>
- +#include <linux/types.h>
- +
- +#ifndef __KERNEL__
- +typedef unsigned long dma_addr_t;
- +typedef unsigned char bool;
- +#endif
- +
- +/* PXP Pixel format definitions */
- +/* Four-character-code (FOURCC) */
- +#define fourcc(a, b, c, d)\
- + (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24))
- +
- +/*!
- + * @name PXP Pixel Formats
- + *
- + * Pixel formats are defined with ASCII FOURCC code. The pixel format codes are
- + * the same used by V4L2 API.
- + */
- +
- +/*! @} */
- +/*! @name RGB Formats */
- +/*! @{ */
- +#define PXP_PIX_FMT_RGB332 fourcc('R', 'G', 'B', '1') /*!< 8 RGB-3-3-2 */
- +#define PXP_PIX_FMT_RGB555 fourcc('R', 'G', 'B', 'O') /*!< 16 RGB-5-5-5 */
- +#define PXP_PIX_FMT_RGB565 fourcc('R', 'G', 'B', 'P') /*!< 1 6 RGB-5-6-5 */
- +#define PXP_PIX_FMT_RGB666 fourcc('R', 'G', 'B', '6') /*!< 18 RGB-6-6-6 */
- +#define PXP_PIX_FMT_BGR666 fourcc('B', 'G', 'R', '6') /*!< 18 BGR-6-6-6 */
- +#define PXP_PIX_FMT_BGR24 fourcc('B', 'G', 'R', '3') /*!< 24 BGR-8-8-8 */
- +#define PXP_PIX_FMT_RGB24 fourcc('R', 'G', 'B', '3') /*!< 24 RGB-8-8-8 */
- +#define PXP_PIX_FMT_BGR32 fourcc('B', 'G', 'R', '4') /*!< 32 BGR-8-8-8-8 */
- +#define PXP_PIX_FMT_BGRA32 fourcc('B', 'G', 'R', 'A') /*!< 32 BGR-8-8-8-8 */
- +#define PXP_PIX_FMT_RGB32 fourcc('R', 'G', 'B', '4') /*!< 32 RGB-8-8-8-8 */
- +#define PXP_PIX_FMT_RGBA32 fourcc('R', 'G', 'B', 'A') /*!< 32 RGB-8-8-8-8 */
- +#define PXP_PIX_FMT_ABGR32 fourcc('A', 'B', 'G', 'R') /*!< 32 ABGR-8-8-8-8 */
- +/*! @} */
- +/*! @name YUV Interleaved Formats */
- +/*! @{ */
- +#define PXP_PIX_FMT_YUYV fourcc('Y', 'U', 'Y', 'V') /*!< 16 YUV 4:2:2 */
- +#define PXP_PIX_FMT_UYVY fourcc('U', 'Y', 'V', 'Y') /*!< 16 YUV 4:2:2 */
- +#define PXP_PIX_FMT_VYUY fourcc('V', 'Y', 'U', 'Y') /*!< 16 YVU 4:2:2 */
- +#define PXP_PIX_FMT_YVYU fourcc('Y', 'V', 'Y', 'U') /*!< 16 YVU 4:2:2 */
- +#define PXP_PIX_FMT_Y41P fourcc('Y', '4', '1', 'P') /*!< 12 YUV 4:1:1 */
- +#define PXP_PIX_FMT_YUV444 fourcc('Y', '4', '4', '4') /*!< 24 YUV 4:4:4 */
- +/* two planes -- one Y, one Cb + Cr interleaved */
- +#define PXP_PIX_FMT_NV12 fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */
- +#define PXP_PIX_FMT_NV21 fourcc('N', 'V', '2', '1') /* 12 Y/CbCr 4:2:0 */
- +#define PXP_PIX_FMT_NV16 fourcc('N', 'V', '1', '6') /* 12 Y/CbCr 4:2:2 */
- +#define PXP_PIX_FMT_NV61 fourcc('N', 'V', '6', '1') /* 12 Y/CbCr 4:2:2 */
- +/*! @} */
- +/*! @name YUV Planar Formats */
- +/*! @{ */
- +#define PXP_PIX_FMT_GREY fourcc('G', 'R', 'E', 'Y') /*!< 8 Greyscale */
- +#define PXP_PIX_FMT_GY04 fourcc('G', 'Y', '0', '4') /*!< 4 Greyscale */
- +#define PXP_PIX_FMT_YVU410P fourcc('Y', 'V', 'U', '9') /*!< 9 YVU 4:1:0 */
- +#define PXP_PIX_FMT_YUV410P fourcc('Y', 'U', 'V', '9') /*!< 9 YUV 4:1:0 */
- +#define PXP_PIX_FMT_YVU420P fourcc('Y', 'V', '1', '2') /*!< 12 YVU 4:2:0 */
- +#define PXP_PIX_FMT_YUV420P fourcc('I', '4', '2', '0') /*!< 12 YUV 4:2:0 */
- +#define PXP_PIX_FMT_YUV420P2 fourcc('Y', 'U', '1', '2') /*!< 12 YUV 4:2:0 */
- +#define PXP_PIX_FMT_YVU422P fourcc('Y', 'V', '1', '6') /*!< 16 YVU 4:2:2 */
- +#define PXP_PIX_FMT_YUV422P fourcc('4', '2', '2', 'P') /*!< 16 YUV 4:2:2 */
- +/*! @} */
- +
- +#define PXP_LUT_NONE 0x0
- +#define PXP_LUT_INVERT 0x1
- +#define PXP_LUT_BLACK_WHITE 0x2
- +#define PXP_LUT_USE_CMAP 0x4
- +
- +#define NR_PXP_VIRT_CHANNEL 16
- +
- +/* Order significant! */
- +enum pxp_channel_status {
- + PXP_CHANNEL_FREE,
- + PXP_CHANNEL_INITIALIZED,
- + PXP_CHANNEL_READY,
- +};
- +
- +struct rect {
- + int top; /* Upper left coordinate of rectangle */
- + int left;
- + int width;
- + int height;
- +};
- +
- +struct pxp_layer_param {
- + unsigned short width;
- + unsigned short height;
- + unsigned short stride; /* aka pitch */
- + unsigned int pixel_fmt;
- +
- + /* layers combining parameters
- + * (these are ignored for S0 and output
- + * layers, and only apply for OL layer)
- + */
- + bool combine_enable;
- + unsigned int color_key_enable;
- + unsigned int color_key;
- + bool global_alpha_enable;
- + /* global alpha is either override or multiply */
- + bool global_override;
- + unsigned char global_alpha;
- + bool alpha_invert;
- + bool local_alpha_enable;
- +
- + dma_addr_t paddr;
- +};
- +
- +struct pxp_proc_data {
- + /* S0 Transformation Info */
- + int scaling;
- + int hflip;
- + int vflip;
- + int rotate;
- + int rot_pos;
- + int yuv;
- +
- + /* Source rectangle (srect) defines the sub-rectangle
- + * within S0 to undergo processing.
- + */
- + struct rect srect;
- + /* Dest rect (drect) defines how to position the processed
- + * source rectangle (after resizing) within the output frame,
- + * whose dimensions are defined in pxp->pxp_conf_state.out_param
- + */
- + struct rect drect;
- +
- + /* Current S0 configuration */
- + unsigned int bgcolor;
- +
- + /* Output overlay support */
- + int overlay_state;
- +
- + /* LUT transformation on Y data */
- + int lut_transform;
- + unsigned char *lut_map; /* 256 entries */
- + bool lut_map_updated; /* Map recently changed */
- + bool combine_enable;
- +};
- +
- +struct pxp_config_data {
- + struct pxp_layer_param s0_param;
- + struct pxp_layer_param ol_param[8];
- + struct pxp_layer_param out_param;
- + struct pxp_proc_data proc_data;
- + int layer_nr;
- +
- + /* Users don't touch */
- + int handle;
- +};
- +
- +
- +#endif
- diff -Nur linux-3.14.35.orig/include/video/mxc_edid.h linux-3.14.35/include/video/mxc_edid.h
- --- linux-3.14.35.orig/include/video/mxc_edid.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/video/mxc_edid.h 2015-03-08 14:27:37.893684498 -0500
- @@ -0,0 +1,105 @@
- +/*
- + * Copyright 2009-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +/*!
- + * @defgroup Framebuffer Framebuffer Driver for SDC and ADC.
- + */
- +
- +/*!
- + * @file mxc_edid.h
- + *
- + * @brief MXC EDID tools
- + *
- + * @ingroup Framebuffer
- + */
- +
- +#ifndef MXC_EDID_H
- +#define MXC_EDID_H
- +
- +#include <linux/fb.h>
- +
- +#define FB_VMODE_ASPECT_4_3 0x10
- +#define FB_VMODE_ASPECT_16_9 0x20
- +#define FB_VMODE_ASPECT_MASK (FB_VMODE_ASPECT_4_3 | FB_VMODE_ASPECT_16_9)
- +
- +enum cea_audio_coding_types {
- + AUDIO_CODING_TYPE_REF_STREAM_HEADER = 0,
- + AUDIO_CODING_TYPE_LPCM = 1,
- + AUDIO_CODING_TYPE_AC3 = 2,
- + AUDIO_CODING_TYPE_MPEG1 = 3,
- + AUDIO_CODING_TYPE_MP3 = 4,
- + AUDIO_CODING_TYPE_MPEG2 = 5,
- + AUDIO_CODING_TYPE_AACLC = 6,
- + AUDIO_CODING_TYPE_DTS = 7,
- + AUDIO_CODING_TYPE_ATRAC = 8,
- + AUDIO_CODING_TYPE_SACD = 9,
- + AUDIO_CODING_TYPE_EAC3 = 10,
- + AUDIO_CODING_TYPE_DTS_HD = 11,
- + AUDIO_CODING_TYPE_MLP = 12,
- + AUDIO_CODING_TYPE_DST = 13,
- + AUDIO_CODING_TYPE_WMAPRO = 14,
- + AUDIO_CODING_TYPE_RESERVED = 15,
- +};
- +
- +struct mxc_hdmi_3d_format {
- + unsigned char vic_order_2d;
- + unsigned char struct_3d;
- + unsigned char detail_3d;
- + unsigned char reserved;
- +};
- +
- +struct mxc_edid_cfg {
- + bool cea_underscan;
- + bool cea_basicaudio;
- + bool cea_ycbcr444;
- + bool cea_ycbcr422;
- + bool hdmi_cap;
- +
- + /*VSD*/
- + bool vsd_support_ai;
- + bool vsd_dc_48bit;
- + bool vsd_dc_36bit;
- + bool vsd_dc_30bit;
- + bool vsd_dc_y444;
- + bool vsd_dvi_dual;
- +
- + bool vsd_cnc0;
- + bool vsd_cnc1;
- + bool vsd_cnc2;
- + bool vsd_cnc3;
- +
- + u8 vsd_video_latency;
- + u8 vsd_audio_latency;
- + u8 vsd_I_video_latency;
- + u8 vsd_I_audio_latency;
- +
- + u8 physical_address[4];
- + u8 hdmi_vic[64];
- + struct mxc_hdmi_3d_format hdmi_3d_format[64];
- + u16 hdmi_3d_mask_all;
- + u16 hdmi_3d_struct_all;
- + u32 vsd_max_tmdsclk_rate;
- +
- + u8 max_channels;
- + u8 sample_sizes;
- + u8 sample_rates;
- + u8 speaker_alloc;
- +};
- +
- +int mxc_edid_var_to_vic(struct fb_var_screeninfo *var);
- +int mxc_edid_mode_to_vic(const struct fb_videomode *mode);
- +int mxc_edid_read(struct i2c_adapter *adp, unsigned short addr,
- + unsigned char *edid, struct mxc_edid_cfg *cfg, struct fb_info *fbi);
- +int mxc_edid_parse_ext_blk(unsigned char *edid, struct mxc_edid_cfg *cfg,
- + struct fb_monspecs *specs);
- +#endif
- diff -Nur linux-3.14.35.orig/include/video/mxc_hdmi.h linux-3.14.35/include/video/mxc_hdmi.h
- --- linux-3.14.35.orig/include/video/mxc_hdmi.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/include/video/mxc_hdmi.h 2015-03-08 14:27:37.893684498 -0500
- @@ -0,0 +1,1027 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#ifndef __MXC_HDMI_H__
- +#define __MXC_HDMI_H__
- +
- +/*
- + * Hdmi controller registers
- + */
- +
- +/* Identification Registers */
- +#define HDMI_DESIGN_ID 0x0000
- +#define HDMI_REVISION_ID 0x0001
- +#define HDMI_PRODUCT_ID0 0x0002
- +#define HDMI_PRODUCT_ID1 0x0003
- +#define HDMI_CONFIG0_ID 0x0004
- +#define HDMI_CONFIG1_ID 0x0005
- +#define HDMI_CONFIG2_ID 0x0006
- +#define HDMI_CONFIG3_ID 0x0007
- +
- +/* Interrupt Registers */
- +#define HDMI_IH_FC_STAT0 0x0100
- +#define HDMI_IH_FC_STAT1 0x0101
- +#define HDMI_IH_FC_STAT2 0x0102
- +#define HDMI_IH_AS_STAT0 0x0103
- +#define HDMI_IH_PHY_STAT0 0x0104
- +#define HDMI_IH_I2CM_STAT0 0x0105
- +#define HDMI_IH_CEC_STAT0 0x0106
- +#define HDMI_IH_VP_STAT0 0x0107
- +#define HDMI_IH_I2CMPHY_STAT0 0x0108
- +#define HDMI_IH_AHBDMAAUD_STAT0 0x0109
- +
- +#define HDMI_IH_MUTE_FC_STAT0 0x0180
- +#define HDMI_IH_MUTE_FC_STAT1 0x0181
- +#define HDMI_IH_MUTE_FC_STAT2 0x0182
- +#define HDMI_IH_MUTE_AS_STAT0 0x0183
- +#define HDMI_IH_MUTE_PHY_STAT0 0x0184
- +#define HDMI_IH_MUTE_I2CM_STAT0 0x0185
- +#define HDMI_IH_MUTE_CEC_STAT0 0x0186
- +#define HDMI_IH_MUTE_VP_STAT0 0x0187
- +#define HDMI_IH_MUTE_I2CMPHY_STAT0 0x0188
- +#define HDMI_IH_MUTE_AHBDMAAUD_STAT0 0x0189
- +#define HDMI_IH_MUTE 0x01FF
- +
- +/* Video Sample Registers */
- +#define HDMI_TX_INVID0 0x0200
- +#define HDMI_TX_INSTUFFING 0x0201
- +#define HDMI_TX_GYDATA0 0x0202
- +#define HDMI_TX_GYDATA1 0x0203
- +#define HDMI_TX_RCRDATA0 0x0204
- +#define HDMI_TX_RCRDATA1 0x0205
- +#define HDMI_TX_BCBDATA0 0x0206
- +#define HDMI_TX_BCBDATA1 0x0207
- +
- +/* Video Packetizer Registers */
- +#define HDMI_VP_STATUS 0x0800
- +#define HDMI_VP_PR_CD 0x0801
- +#define HDMI_VP_STUFF 0x0802
- +#define HDMI_VP_REMAP 0x0803
- +#define HDMI_VP_CONF 0x0804
- +#define HDMI_VP_STAT 0x0805
- +#define HDMI_VP_INT 0x0806
- +#define HDMI_VP_MASK 0x0807
- +#define HDMI_VP_POL 0x0808
- +
- +/* Frame Composer Registers */
- +#define HDMI_FC_INVIDCONF 0x1000
- +#define HDMI_FC_INHACTV0 0x1001
- +#define HDMI_FC_INHACTV1 0x1002
- +#define HDMI_FC_INHBLANK0 0x1003
- +#define HDMI_FC_INHBLANK1 0x1004
- +#define HDMI_FC_INVACTV0 0x1005
- +#define HDMI_FC_INVACTV1 0x1006
- +#define HDMI_FC_INVBLANK 0x1007
- +#define HDMI_FC_HSYNCINDELAY0 0x1008
- +#define HDMI_FC_HSYNCINDELAY1 0x1009
- +#define HDMI_FC_HSYNCINWIDTH0 0x100A
- +#define HDMI_FC_HSYNCINWIDTH1 0x100B
- +#define HDMI_FC_VSYNCINDELAY 0x100C
- +#define HDMI_FC_VSYNCINWIDTH 0x100D
- +#define HDMI_FC_INFREQ0 0x100E
- +#define HDMI_FC_INFREQ1 0x100F
- +#define HDMI_FC_INFREQ2 0x1010
- +#define HDMI_FC_CTRLDUR 0x1011
- +#define HDMI_FC_EXCTRLDUR 0x1012
- +#define HDMI_FC_EXCTRLSPAC 0x1013
- +#define HDMI_FC_CH0PREAM 0x1014
- +#define HDMI_FC_CH1PREAM 0x1015
- +#define HDMI_FC_CH2PREAM 0x1016
- +#define HDMI_FC_AVICONF3 0x1017
- +#define HDMI_FC_GCP 0x1018
- +#define HDMI_FC_AVICONF0 0x1019
- +#define HDMI_FC_AVICONF1 0x101A
- +#define HDMI_FC_AVICONF2 0x101B
- +#define HDMI_FC_AVIVID 0x101C
- +#define HDMI_FC_AVIETB0 0x101D
- +#define HDMI_FC_AVIETB1 0x101E
- +#define HDMI_FC_AVISBB0 0x101F
- +#define HDMI_FC_AVISBB1 0x1020
- +#define HDMI_FC_AVIELB0 0x1021
- +#define HDMI_FC_AVIELB1 0x1022
- +#define HDMI_FC_AVISRB0 0x1023
- +#define HDMI_FC_AVISRB1 0x1024
- +#define HDMI_FC_AUDICONF0 0x1025
- +#define HDMI_FC_AUDICONF1 0x1026
- +#define HDMI_FC_AUDICONF2 0x1027
- +#define HDMI_FC_AUDICONF3 0x1028
- +#define HDMI_FC_VSDIEEEID0 0x1029
- +#define HDMI_FC_VSDSIZE 0x102A
- +#define HDMI_FC_VSDIEEEID1 0x1030
- +#define HDMI_FC_VSDIEEEID2 0x1031
- +#define HDMI_FC_VSDPAYLOAD0 0x1032
- +#define HDMI_FC_VSDPAYLOAD1 0x1033
- +#define HDMI_FC_VSDPAYLOAD2 0x1034
- +#define HDMI_FC_VSDPAYLOAD3 0x1035
- +#define HDMI_FC_VSDPAYLOAD4 0x1036
- +#define HDMI_FC_VSDPAYLOAD5 0x1037
- +#define HDMI_FC_VSDPAYLOAD6 0x1038
- +#define HDMI_FC_VSDPAYLOAD7 0x1039
- +#define HDMI_FC_VSDPAYLOAD8 0x103A
- +#define HDMI_FC_VSDPAYLOAD9 0x103B
- +#define HDMI_FC_VSDPAYLOAD10 0x103C
- +#define HDMI_FC_VSDPAYLOAD11 0x103D
- +#define HDMI_FC_VSDPAYLOAD12 0x103E
- +#define HDMI_FC_VSDPAYLOAD13 0x103F
- +#define HDMI_FC_VSDPAYLOAD14 0x1040
- +#define HDMI_FC_VSDPAYLOAD15 0x1041
- +#define HDMI_FC_VSDPAYLOAD16 0x1042
- +#define HDMI_FC_VSDPAYLOAD17 0x1043
- +#define HDMI_FC_VSDPAYLOAD18 0x1044
- +#define HDMI_FC_VSDPAYLOAD19 0x1045
- +#define HDMI_FC_VSDPAYLOAD20 0x1046
- +#define HDMI_FC_VSDPAYLOAD21 0x1047
- +#define HDMI_FC_VSDPAYLOAD22 0x1048
- +#define HDMI_FC_VSDPAYLOAD23 0x1049
- +#define HDMI_FC_SPDVENDORNAME0 0x104A
- +#define HDMI_FC_SPDVENDORNAME1 0x104B
- +#define HDMI_FC_SPDVENDORNAME2 0x104C
- +#define HDMI_FC_SPDVENDORNAME3 0x104D
- +#define HDMI_FC_SPDVENDORNAME4 0x104E
- +#define HDMI_FC_SPDVENDORNAME5 0x104F
- +#define HDMI_FC_SPDVENDORNAME6 0x1050
- +#define HDMI_FC_SPDVENDORNAME7 0x1051
- +#define HDMI_FC_SDPPRODUCTNAME0 0x1052
- +#define HDMI_FC_SDPPRODUCTNAME1 0x1053
- +#define HDMI_FC_SDPPRODUCTNAME2 0x1054
- +#define HDMI_FC_SDPPRODUCTNAME3 0x1055
- +#define HDMI_FC_SDPPRODUCTNAME4 0x1056
- +#define HDMI_FC_SDPPRODUCTNAME5 0x1057
- +#define HDMI_FC_SDPPRODUCTNAME6 0x1058
- +#define HDMI_FC_SDPPRODUCTNAME7 0x1059
- +#define HDMI_FC_SDPPRODUCTNAME8 0x105A
- +#define HDMI_FC_SDPPRODUCTNAME9 0x105B
- +#define HDMI_FC_SDPPRODUCTNAME10 0x105C
- +#define HDMI_FC_SDPPRODUCTNAME11 0x105D
- +#define HDMI_FC_SDPPRODUCTNAME12 0x105E
- +#define HDMI_FC_SDPPRODUCTNAME13 0x105F
- +#define HDMI_FC_SDPPRODUCTNAME14 0x1060
- +#define HDMI_FC_SPDPRODUCTNAME15 0x1061
- +#define HDMI_FC_SPDDEVICEINF 0x1062
- +#define HDMI_FC_AUDSCONF 0x1063
- +#define HDMI_FC_AUDSSTAT 0x1064
- +#define HDMI_FC_DATACH0FILL 0x1070
- +#define HDMI_FC_DATACH1FILL 0x1071
- +#define HDMI_FC_DATACH2FILL 0x1072
- +#define HDMI_FC_CTRLQHIGH 0x1073
- +#define HDMI_FC_CTRLQLOW 0x1074
- +#define HDMI_FC_ACP0 0x1075
- +#define HDMI_FC_ACP28 0x1076
- +#define HDMI_FC_ACP27 0x1077
- +#define HDMI_FC_ACP26 0x1078
- +#define HDMI_FC_ACP25 0x1079
- +#define HDMI_FC_ACP24 0x107A
- +#define HDMI_FC_ACP23 0x107B
- +#define HDMI_FC_ACP22 0x107C
- +#define HDMI_FC_ACP21 0x107D
- +#define HDMI_FC_ACP20 0x107E
- +#define HDMI_FC_ACP19 0x107F
- +#define HDMI_FC_ACP18 0x1080
- +#define HDMI_FC_ACP17 0x1081
- +#define HDMI_FC_ACP16 0x1082
- +#define HDMI_FC_ACP15 0x1083
- +#define HDMI_FC_ACP14 0x1084
- +#define HDMI_FC_ACP13 0x1085
- +#define HDMI_FC_ACP12 0x1086
- +#define HDMI_FC_ACP11 0x1087
- +#define HDMI_FC_ACP10 0x1088
- +#define HDMI_FC_ACP9 0x1089
- +#define HDMI_FC_ACP8 0x108A
- +#define HDMI_FC_ACP7 0x108B
- +#define HDMI_FC_ACP6 0x108C
- +#define HDMI_FC_ACP5 0x108D
- +#define HDMI_FC_ACP4 0x108E
- +#define HDMI_FC_ACP3 0x108F
- +#define HDMI_FC_ACP2 0x1090
- +#define HDMI_FC_ACP1 0x1091
- +#define HDMI_FC_ISCR1_0 0x1092
- +#define HDMI_FC_ISCR1_16 0x1093
- +#define HDMI_FC_ISCR1_15 0x1094
- +#define HDMI_FC_ISCR1_14 0x1095
- +#define HDMI_FC_ISCR1_13 0x1096
- +#define HDMI_FC_ISCR1_12 0x1097
- +#define HDMI_FC_ISCR1_11 0x1098
- +#define HDMI_FC_ISCR1_10 0x1099
- +#define HDMI_FC_ISCR1_9 0x109A
- +#define HDMI_FC_ISCR1_8 0x109B
- +#define HDMI_FC_ISCR1_7 0x109C
- +#define HDMI_FC_ISCR1_6 0x109D
- +#define HDMI_FC_ISCR1_5 0x109E
- +#define HDMI_FC_ISCR1_4 0x109F
- +#define HDMI_FC_ISCR1_3 0x10A0
- +#define HDMI_FC_ISCR1_2 0x10A1
- +#define HDMI_FC_ISCR1_1 0x10A2
- +#define HDMI_FC_ISCR2_15 0x10A3
- +#define HDMI_FC_ISCR2_14 0x10A4
- +#define HDMI_FC_ISCR2_13 0x10A5
- +#define HDMI_FC_ISCR2_12 0x10A6
- +#define HDMI_FC_ISCR2_11 0x10A7
- +#define HDMI_FC_ISCR2_10 0x10A8
- +#define HDMI_FC_ISCR2_9 0x10A9
- +#define HDMI_FC_ISCR2_8 0x10AA
- +#define HDMI_FC_ISCR2_7 0x10AB
- +#define HDMI_FC_ISCR2_6 0x10AC
- +#define HDMI_FC_ISCR2_5 0x10AD
- +#define HDMI_FC_ISCR2_4 0x10AE
- +#define HDMI_FC_ISCR2_3 0x10AF
- +#define HDMI_FC_ISCR2_2 0x10B0
- +#define HDMI_FC_ISCR2_1 0x10B1
- +#define HDMI_FC_ISCR2_0 0x10B2
- +#define HDMI_FC_DATAUTO0 0x10B3
- +#define HDMI_FC_DATAUTO1 0x10B4
- +#define HDMI_FC_DATAUTO2 0x10B5
- +#define HDMI_FC_DATMAN 0x10B6
- +#define HDMI_FC_DATAUTO3 0x10B7
- +#define HDMI_FC_RDRB0 0x10B8
- +#define HDMI_FC_RDRB1 0x10B9
- +#define HDMI_FC_RDRB2 0x10BA
- +#define HDMI_FC_RDRB3 0x10BB
- +#define HDMI_FC_RDRB4 0x10BC
- +#define HDMI_FC_RDRB5 0x10BD
- +#define HDMI_FC_RDRB6 0x10BE
- +#define HDMI_FC_RDRB7 0x10BF
- +#define HDMI_FC_STAT0 0x10D0
- +#define HDMI_FC_INT0 0x10D1
- +#define HDMI_FC_MASK0 0x10D2
- +#define HDMI_FC_POL0 0x10D3
- +#define HDMI_FC_STAT1 0x10D4
- +#define HDMI_FC_INT1 0x10D5
- +#define HDMI_FC_MASK1 0x10D6
- +#define HDMI_FC_POL1 0x10D7
- +#define HDMI_FC_STAT2 0x10D8
- +#define HDMI_FC_INT2 0x10D9
- +#define HDMI_FC_MASK2 0x10DA
- +#define HDMI_FC_POL2 0x10DB
- +#define HDMI_FC_PRCONF 0x10E0
- +
- +#define HDMI_FC_GMD_STAT 0x1100
- +#define HDMI_FC_GMD_EN 0x1101
- +#define HDMI_FC_GMD_UP 0x1102
- +#define HDMI_FC_GMD_CONF 0x1103
- +#define HDMI_FC_GMD_HB 0x1104
- +#define HDMI_FC_GMD_PB0 0x1105
- +#define HDMI_FC_GMD_PB1 0x1106
- +#define HDMI_FC_GMD_PB2 0x1107
- +#define HDMI_FC_GMD_PB3 0x1108
- +#define HDMI_FC_GMD_PB4 0x1109
- +#define HDMI_FC_GMD_PB5 0x110A
- +#define HDMI_FC_GMD_PB6 0x110B
- +#define HDMI_FC_GMD_PB7 0x110C
- +#define HDMI_FC_GMD_PB8 0x110D
- +#define HDMI_FC_GMD_PB9 0x110E
- +#define HDMI_FC_GMD_PB10 0x110F
- +#define HDMI_FC_GMD_PB11 0x1110
- +#define HDMI_FC_GMD_PB12 0x1111
- +#define HDMI_FC_GMD_PB13 0x1112
- +#define HDMI_FC_GMD_PB14 0x1113
- +#define HDMI_FC_GMD_PB15 0x1114
- +#define HDMI_FC_GMD_PB16 0x1115
- +#define HDMI_FC_GMD_PB17 0x1116
- +#define HDMI_FC_GMD_PB18 0x1117
- +#define HDMI_FC_GMD_PB19 0x1118
- +#define HDMI_FC_GMD_PB20 0x1119
- +#define HDMI_FC_GMD_PB21 0x111A
- +#define HDMI_FC_GMD_PB22 0x111B
- +#define HDMI_FC_GMD_PB23 0x111C
- +#define HDMI_FC_GMD_PB24 0x111D
- +#define HDMI_FC_GMD_PB25 0x111E
- +#define HDMI_FC_GMD_PB26 0x111F
- +#define HDMI_FC_GMD_PB27 0x1120
- +
- +#define HDMI_FC_DBGFORCE 0x1200
- +#define HDMI_FC_DBGAUD0CH0 0x1201
- +#define HDMI_FC_DBGAUD1CH0 0x1202
- +#define HDMI_FC_DBGAUD2CH0 0x1203
- +#define HDMI_FC_DBGAUD0CH1 0x1204
- +#define HDMI_FC_DBGAUD1CH1 0x1205
- +#define HDMI_FC_DBGAUD2CH1 0x1206
- +#define HDMI_FC_DBGAUD0CH2 0x1207
- +#define HDMI_FC_DBGAUD1CH2 0x1208
- +#define HDMI_FC_DBGAUD2CH2 0x1209
- +#define HDMI_FC_DBGAUD0CH3 0x120A
- +#define HDMI_FC_DBGAUD1CH3 0x120B
- +#define HDMI_FC_DBGAUD2CH3 0x120C
- +#define HDMI_FC_DBGAUD0CH4 0x120D
- +#define HDMI_FC_DBGAUD1CH4 0x120E
- +#define HDMI_FC_DBGAUD2CH4 0x120F
- +#define HDMI_FC_DBGAUD0CH5 0x1210
- +#define HDMI_FC_DBGAUD1CH5 0x1211
- +#define HDMI_FC_DBGAUD2CH5 0x1212
- +#define HDMI_FC_DBGAUD0CH6 0x1213
- +#define HDMI_FC_DBGAUD1CH6 0x1214
- +#define HDMI_FC_DBGAUD2CH6 0x1215
- +#define HDMI_FC_DBGAUD0CH7 0x1216
- +#define HDMI_FC_DBGAUD1CH7 0x1217
- +#define HDMI_FC_DBGAUD2CH7 0x1218
- +#define HDMI_FC_DBGTMDS0 0x1219
- +#define HDMI_FC_DBGTMDS1 0x121A
- +#define HDMI_FC_DBGTMDS2 0x121B
- +
- +/* HDMI Source PHY Registers */
- +#define HDMI_PHY_CONF0 0x3000
- +#define HDMI_PHY_TST0 0x3001
- +#define HDMI_PHY_TST1 0x3002
- +#define HDMI_PHY_TST2 0x3003
- +#define HDMI_PHY_STAT0 0x3004
- +#define HDMI_PHY_INT0 0x3005
- +#define HDMI_PHY_MASK0 0x3006
- +#define HDMI_PHY_POL0 0x3007
- +
- +/* HDMI Master PHY Registers */
- +#define HDMI_PHY_I2CM_SLAVE_ADDR 0x3020
- +#define HDMI_PHY_I2CM_ADDRESS_ADDR 0x3021
- +#define HDMI_PHY_I2CM_DATAO_1_ADDR 0x3022
- +#define HDMI_PHY_I2CM_DATAO_0_ADDR 0x3023
- +#define HDMI_PHY_I2CM_DATAI_1_ADDR 0x3024
- +#define HDMI_PHY_I2CM_DATAI_0_ADDR 0x3025
- +#define HDMI_PHY_I2CM_OPERATION_ADDR 0x3026
- +#define HDMI_PHY_I2CM_INT_ADDR 0x3027
- +#define HDMI_PHY_I2CM_CTLINT_ADDR 0x3028
- +#define HDMI_PHY_I2CM_DIV_ADDR 0x3029
- +#define HDMI_PHY_I2CM_SOFTRSTZ_ADDR 0x302a
- +#define HDMI_PHY_I2CM_SS_SCL_HCNT_1_ADDR 0x302b
- +#define HDMI_PHY_I2CM_SS_SCL_HCNT_0_ADDR 0x302c
- +#define HDMI_PHY_I2CM_SS_SCL_LCNT_1_ADDR 0x302d
- +#define HDMI_PHY_I2CM_SS_SCL_LCNT_0_ADDR 0x302e
- +#define HDMI_PHY_I2CM_FS_SCL_HCNT_1_ADDR 0x302f
- +#define HDMI_PHY_I2CM_FS_SCL_HCNT_0_ADDR 0x3030
- +#define HDMI_PHY_I2CM_FS_SCL_LCNT_1_ADDR 0x3031
- +#define HDMI_PHY_I2CM_FS_SCL_LCNT_0_ADDR 0x3032
- +
- +/* Audio Sampler Registers */
- +#define HDMI_AUD_CONF0 0x3100
- +#define HDMI_AUD_CONF1 0x3101
- +#define HDMI_AUD_INT 0x3102
- +#define HDMI_AUD_CONF2 0x3103
- +#define HDMI_AUD_N1 0x3200
- +#define HDMI_AUD_N2 0x3201
- +#define HDMI_AUD_N3 0x3202
- +#define HDMI_AUD_CTS1 0x3203
- +#define HDMI_AUD_CTS2 0x3204
- +#define HDMI_AUD_CTS3 0x3205
- +#define HDMI_AUD_INPUTCLKFS 0x3206
- +#define HDMI_AUD_SPDIFINT 0x3302
- +#define HDMI_AUD_CONF0_HBR 0x3400
- +#define HDMI_AUD_HBR_STATUS 0x3401
- +#define HDMI_AUD_HBR_INT 0x3402
- +#define HDMI_AUD_HBR_POL 0x3403
- +#define HDMI_AUD_HBR_MASK 0x3404
- +
- +/* Generic Parallel Audio Interface Registers */
- +/* Not used as GPAUD interface is not enabled in hw */
- +#define HDMI_GP_CONF0 0x3500
- +#define HDMI_GP_CONF1 0x3501
- +#define HDMI_GP_CONF2 0x3502
- +#define HDMI_GP_STAT 0x3503
- +#define HDMI_GP_INT 0x3504
- +#define HDMI_GP_MASK 0x3505
- +#define HDMI_GP_POL 0x3506
- +
- +/* Audio DMA Registers */
- +#define HDMI_AHB_DMA_CONF0 0x3600
- +#define HDMI_AHB_DMA_START 0x3601
- +#define HDMI_AHB_DMA_STOP 0x3602
- +#define HDMI_AHB_DMA_THRSLD 0x3603
- +#define HDMI_AHB_DMA_STRADDR0 0x3604
- +#define HDMI_AHB_DMA_STRADDR1 0x3605
- +#define HDMI_AHB_DMA_STRADDR2 0x3606
- +#define HDMI_AHB_DMA_STRADDR3 0x3607
- +#define HDMI_AHB_DMA_STPADDR0 0x3608
- +#define HDMI_AHB_DMA_STPADDR1 0x3609
- +#define HDMI_AHB_DMA_STPADDR2 0x360a
- +#define HDMI_AHB_DMA_STPADDR3 0x360b
- +#define HDMI_AHB_DMA_BSTADDR0 0x360c
- +#define HDMI_AHB_DMA_BSTADDR1 0x360d
- +#define HDMI_AHB_DMA_BSTADDR2 0x360e
- +#define HDMI_AHB_DMA_BSTADDR3 0x360f
- +#define HDMI_AHB_DMA_MBLENGTH0 0x3610
- +#define HDMI_AHB_DMA_MBLENGTH1 0x3611
- +#define HDMI_AHB_DMA_STAT 0x3612
- +#define HDMI_AHB_DMA_INT 0x3613
- +#define HDMI_AHB_DMA_MASK 0x3614
- +#define HDMI_AHB_DMA_POL 0x3615
- +#define HDMI_AHB_DMA_CONF1 0x3616
- +#define HDMI_AHB_DMA_BUFFSTAT 0x3617
- +#define HDMI_AHB_DMA_BUFFINT 0x3618
- +#define HDMI_AHB_DMA_BUFFMASK 0x3619
- +#define HDMI_AHB_DMA_BUFFPOL 0x361a
- +
- +/* Main Controller Registers */
- +#define HDMI_MC_SFRDIV 0x4000
- +#define HDMI_MC_CLKDIS 0x4001
- +#define HDMI_MC_SWRSTZ 0x4002
- +#define HDMI_MC_OPCTRL 0x4003
- +#define HDMI_MC_FLOWCTRL 0x4004
- +#define HDMI_MC_PHYRSTZ 0x4005
- +#define HDMI_MC_LOCKONCLOCK 0x4006
- +#define HDMI_MC_HEACPHY_RST 0x4007
- +
- +/* Color Space Converter Registers */
- +#define HDMI_CSC_CFG 0x4100
- +#define HDMI_CSC_SCALE 0x4101
- +#define HDMI_CSC_COEF_A1_MSB 0x4102
- +#define HDMI_CSC_COEF_A1_LSB 0x4103
- +#define HDMI_CSC_COEF_A2_MSB 0x4104
- +#define HDMI_CSC_COEF_A2_LSB 0x4105
- +#define HDMI_CSC_COEF_A3_MSB 0x4106
- +#define HDMI_CSC_COEF_A3_LSB 0x4107
- +#define HDMI_CSC_COEF_A4_MSB 0x4108
- +#define HDMI_CSC_COEF_A4_LSB 0x4109
- +#define HDMI_CSC_COEF_B1_MSB 0x410A
- +#define HDMI_CSC_COEF_B1_LSB 0x410B
- +#define HDMI_CSC_COEF_B2_MSB 0x410C
- +#define HDMI_CSC_COEF_B2_LSB 0x410D
- +#define HDMI_CSC_COEF_B3_MSB 0x410E
- +#define HDMI_CSC_COEF_B3_LSB 0x410F
- +#define HDMI_CSC_COEF_B4_MSB 0x4110
- +#define HDMI_CSC_COEF_B4_LSB 0x4111
- +#define HDMI_CSC_COEF_C1_MSB 0x4112
- +#define HDMI_CSC_COEF_C1_LSB 0x4113
- +#define HDMI_CSC_COEF_C2_MSB 0x4114
- +#define HDMI_CSC_COEF_C2_LSB 0x4115
- +#define HDMI_CSC_COEF_C3_MSB 0x4116
- +#define HDMI_CSC_COEF_C3_LSB 0x4117
- +#define HDMI_CSC_COEF_C4_MSB 0x4118
- +#define HDMI_CSC_COEF_C4_LSB 0x4119
- +
- +/* HDCP Interrupt Registers */
- +#define HDMI_A_APIINTCLR 0x5006
- +#define HDMI_A_APIINTSTAT 0x5007
- +#define HDMI_A_APIINTMSK 0x5008
- +
- +/* CEC Engine Registers */
- +#define HDMI_CEC_CTRL 0x7D00
- +#define HDMI_CEC_STAT 0x7D01
- +#define HDMI_CEC_MASK 0x7D02
- +#define HDMI_CEC_POLARITY 0x7D03
- +#define HDMI_CEC_INT 0x7D04
- +#define HDMI_CEC_ADDR_L 0x7D05
- +#define HDMI_CEC_ADDR_H 0x7D06
- +#define HDMI_CEC_TX_CNT 0x7D07
- +#define HDMI_CEC_RX_CNT 0x7D08
- +#define HDMI_CEC_TX_DATA0 0x7D10
- +#define HDMI_CEC_TX_DATA1 0x7D11
- +#define HDMI_CEC_TX_DATA2 0x7D12
- +#define HDMI_CEC_TX_DATA3 0x7D13
- +#define HDMI_CEC_TX_DATA4 0x7D14
- +#define HDMI_CEC_TX_DATA5 0x7D15
- +#define HDMI_CEC_TX_DATA6 0x7D16
- +#define HDMI_CEC_TX_DATA7 0x7D17
- +#define HDMI_CEC_TX_DATA8 0x7D18
- +#define HDMI_CEC_TX_DATA9 0x7D19
- +#define HDMI_CEC_TX_DATA10 0x7D1a
- +#define HDMI_CEC_TX_DATA11 0x7D1b
- +#define HDMI_CEC_TX_DATA12 0x7D1c
- +#define HDMI_CEC_TX_DATA13 0x7D1d
- +#define HDMI_CEC_TX_DATA14 0x7D1e
- +#define HDMI_CEC_TX_DATA15 0x7D1f
- +#define HDMI_CEC_RX_DATA0 0x7D20
- +#define HDMI_CEC_RX_DATA1 0x7D21
- +#define HDMI_CEC_RX_DATA2 0x7D22
- +#define HDMI_CEC_RX_DATA3 0x7D23
- +#define HDMI_CEC_RX_DATA4 0x7D24
- +#define HDMI_CEC_RX_DATA5 0x7D25
- +#define HDMI_CEC_RX_DATA6 0x7D26
- +#define HDMI_CEC_RX_DATA7 0x7D27
- +#define HDMI_CEC_RX_DATA8 0x7D28
- +#define HDMI_CEC_RX_DATA9 0x7D29
- +#define HDMI_CEC_RX_DATA10 0x7D2a
- +#define HDMI_CEC_RX_DATA11 0x7D2b
- +#define HDMI_CEC_RX_DATA12 0x7D2c
- +#define HDMI_CEC_RX_DATA13 0x7D2d
- +#define HDMI_CEC_RX_DATA14 0x7D2e
- +#define HDMI_CEC_RX_DATA15 0x7D2f
- +#define HDMI_CEC_LOCK 0x7D30
- +#define HDMI_CEC_WKUPCTRL 0x7D31
- +
- +/* I2C Master Registers (E-DDC) */
- +#define HDMI_I2CM_SLAVE 0x7E00
- +#define HDMI_I2CM_ADDRESS 0x7E01
- +#define HDMI_I2CM_DATAO 0x7E02
- +#define HDMI_I2CM_DATAI 0x7E03
- +#define HDMI_I2CM_OPERATION 0x7E04
- +#define HDMI_I2CM_INT 0x7E05
- +#define HDMI_I2CM_CTLINT 0x7E06
- +#define HDMI_I2CM_DIV 0x7E07
- +#define HDMI_I2CM_SEGADDR 0x7E08
- +#define HDMI_I2CM_SOFTRSTZ 0x7E09
- +#define HDMI_I2CM_SEGPTR 0x7E0A
- +#define HDMI_I2CM_SS_SCL_HCNT_1_ADDR 0x7E0B
- +#define HDMI_I2CM_SS_SCL_HCNT_0_ADDR 0x7E0C
- +#define HDMI_I2CM_SS_SCL_LCNT_1_ADDR 0x7E0D
- +#define HDMI_I2CM_SS_SCL_LCNT_0_ADDR 0x7E0E
- +#define HDMI_I2CM_FS_SCL_HCNT_1_ADDR 0x7E0F
- +#define HDMI_I2CM_FS_SCL_HCNT_0_ADDR 0x7E10
- +#define HDMI_I2CM_FS_SCL_LCNT_1_ADDR 0x7E11
- +#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR 0x7E12
- +
- +/* Random Number Generator Registers (RNG) */
- +#define HDMI_RNG_BASE 0x8000
- +
- +
- +/*
- + * Register field definitions
- + */
- +enum {
- +/* IH_FC_INT2 field values */
- + HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03,
- + HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
- + HDMI_IH_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01,
- +
- +/* IH_FC_STAT2 field values */
- + HDMI_IH_FC_STAT2_OVERFLOW_MASK = 0x03,
- + HDMI_IH_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
- + HDMI_IH_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
- +
- +/* IH_PHY_STAT0 field values */
- + HDMI_IH_PHY_STAT0_RX_SENSE3 = 0x20,
- + HDMI_IH_PHY_STAT0_RX_SENSE2 = 0x10,
- + HDMI_IH_PHY_STAT0_RX_SENSE1 = 0x8,
- + HDMI_IH_PHY_STAT0_RX_SENSE0 = 0x4,
- + HDMI_IH_PHY_STAT0_TX_PHY_LOCK = 0x2,
- + HDMI_IH_PHY_STAT0_HPD = 0x1,
- +
- +/* IH_CEC_STAT0 field values */
- + HDMI_IH_CEC_STAT0_WAKEUP = 0x40,
- + HDMI_IH_CEC_STAT0_ERROR_FOLL = 0x20,
- + HDMI_IH_CEC_STAT0_ERROR_INIT = 0x10,
- + HDMI_IH_CEC_STAT0_ARB_LOST = 0x8,
- + HDMI_IH_CEC_STAT0_NACK = 0x4,
- + HDMI_IH_CEC_STAT0_EOM = 0x2,
- + HDMI_IH_CEC_STAT0_DONE = 0x1,
- +
- +
- +/* IH_MUTE_I2CMPHY_STAT0 field values */
- + HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYDONE = 0x2,
- + HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYERROR = 0x1,
- +
- +/* IH_PHY_STAT0 field values */
- + HDMI_IH_MUTE_PHY_STAT0_RX_SENSE3 = 0x20,
- + HDMI_IH_MUTE_PHY_STAT0_RX_SENSE2 = 0x10,
- + HDMI_IH_MUTE_PHY_STAT0_RX_SENSE1 = 0x8,
- + HDMI_IH_MUTE_PHY_STAT0_RX_SENSE0 = 0x4,
- + HDMI_IH_MUTE_PHY_STAT0_TX_PHY_LOCK = 0x2,
- + HDMI_IH_MUTE_PHY_STAT0_HPD = 0x1,
- +
- +/* IH and IH_MUTE convenience macro RX_SENSE | HPD*/
- + HDMI_DVI_IH_STAT = 0x3D,
- +
- +
- +/* IH_AHBDMAAUD_STAT0 field values */
- + HDMI_IH_AHBDMAAUD_STAT0_ERROR = 0x20,
- + HDMI_IH_AHBDMAAUD_STAT0_LOST = 0x10,
- + HDMI_IH_AHBDMAAUD_STAT0_RETRY = 0x08,
- + HDMI_IH_AHBDMAAUD_STAT0_DONE = 0x04,
- + HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = 0x02,
- + HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01,
- +
- +/* IH_MUTE_FC_STAT2 field values */
- + HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK = 0x03,
- + HDMI_IH_MUTE_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
- + HDMI_IH_MUTE_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
- +
- +/* IH_MUTE_AHBDMAAUD_STAT0 field values */
- + HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = 0x20,
- + HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = 0x10,
- + HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = 0x08,
- + HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = 0x04,
- + HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = 0x02,
- + HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01,
- +
- +/* IH_MUTE field values */
- + HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT = 0x2,
- + HDMI_IH_MUTE_MUTE_ALL_INTERRUPT = 0x1,
- +
- +/* TX_INVID0 field values */
- + HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_MASK = 0x80,
- + HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_ENABLE = 0x80,
- + HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE = 0x00,
- + HDMI_TX_INVID0_VIDEO_MAPPING_MASK = 0x1F,
- + HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET = 0,
- +
- +/* TX_INSTUFFING field values */
- + HDMI_TX_INSTUFFING_BDBDATA_STUFFING_MASK = 0x4,
- + HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE = 0x4,
- + HDMI_TX_INSTUFFING_BDBDATA_STUFFING_DISABLE = 0x0,
- + HDMI_TX_INSTUFFING_RCRDATA_STUFFING_MASK = 0x2,
- + HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE = 0x2,
- + HDMI_TX_INSTUFFING_RCRDATA_STUFFING_DISABLE = 0x0,
- + HDMI_TX_INSTUFFING_GYDATA_STUFFING_MASK = 0x1,
- + HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE = 0x1,
- + HDMI_TX_INSTUFFING_GYDATA_STUFFING_DISABLE = 0x0,
- +
- +/* VP_PR_CD field values */
- + HDMI_VP_PR_CD_COLOR_DEPTH_MASK = 0xF0,
- + HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET = 4,
- + HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK = 0x0F,
- + HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET = 0,
- +
- +/* VP_STUFF field values */
- + HDMI_VP_STUFF_IDEFAULT_PHASE_MASK = 0x20,
- + HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET = 5,
- + HDMI_VP_STUFF_IFIX_PP_TO_LAST_MASK = 0x10,
- + HDMI_VP_STUFF_IFIX_PP_TO_LAST_OFFSET = 4,
- + HDMI_VP_STUFF_ICX_GOTO_P0_ST_MASK = 0x8,
- + HDMI_VP_STUFF_ICX_GOTO_P0_ST_OFFSET = 3,
- + HDMI_VP_STUFF_YCC422_STUFFING_MASK = 0x4,
- + HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE = 0x4,
- + HDMI_VP_STUFF_YCC422_STUFFING_DIRECT_MODE = 0x0,
- + HDMI_VP_STUFF_PP_STUFFING_MASK = 0x2,
- + HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE = 0x2,
- + HDMI_VP_STUFF_PP_STUFFING_DIRECT_MODE = 0x0,
- + HDMI_VP_STUFF_PR_STUFFING_MASK = 0x1,
- + HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE = 0x1,
- + HDMI_VP_STUFF_PR_STUFFING_DIRECT_MODE = 0x0,
- +
- +/* VP_CONF field values */
- + HDMI_VP_CONF_BYPASS_EN_MASK = 0x40,
- + HDMI_VP_CONF_BYPASS_EN_ENABLE = 0x40,
- + HDMI_VP_CONF_BYPASS_EN_DISABLE = 0x00,
- + HDMI_VP_CONF_PP_EN_ENMASK = 0x20,
- + HDMI_VP_CONF_PP_EN_ENABLE = 0x20,
- + HDMI_VP_CONF_PP_EN_DISABLE = 0x00,
- + HDMI_VP_CONF_PR_EN_MASK = 0x10,
- + HDMI_VP_CONF_PR_EN_ENABLE = 0x10,
- + HDMI_VP_CONF_PR_EN_DISABLE = 0x00,
- + HDMI_VP_CONF_YCC422_EN_MASK = 0x8,
- + HDMI_VP_CONF_YCC422_EN_ENABLE = 0x8,
- + HDMI_VP_CONF_YCC422_EN_DISABLE = 0x0,
- + HDMI_VP_CONF_BYPASS_SELECT_MASK = 0x4,
- + HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER = 0x4,
- + HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER = 0x0,
- + HDMI_VP_CONF_OUTPUT_SELECTOR_MASK = 0x3,
- + HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS = 0x3,
- + HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422 = 0x1,
- + HDMI_VP_CONF_OUTPUT_SELECTOR_PP = 0x0,
- +
- +/* VP_REMAP field values */
- + HDMI_VP_REMAP_MASK = 0x3,
- + HDMI_VP_REMAP_YCC422_24bit = 0x2,
- + HDMI_VP_REMAP_YCC422_20bit = 0x1,
- + HDMI_VP_REMAP_YCC422_16bit = 0x0,
- +
- +/* FC_INVIDCONF field values */
- + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_MASK = 0x40,
- + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH = 0x40,
- + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW = 0x00,
- + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_MASK = 0x20,
- + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH = 0x20,
- + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW = 0x00,
- + HDMI_FC_INVIDCONF_DE_IN_POLARITY_MASK = 0x10,
- + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH = 0x10,
- + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW = 0x00,
- + HDMI_FC_INVIDCONF_DVI_MODEZ_MASK = 0x8,
- + HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE = 0x8,
- + HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE = 0x0,
- + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_MASK = 0x2,
- + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH = 0x2,
- + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW = 0x0,
- + HDMI_FC_INVIDCONF_IN_I_P_MASK = 0x1,
- + HDMI_FC_INVIDCONF_IN_I_P_INTERLACED = 0x1,
- + HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE = 0x0,
- +
- +/* FC_AUDICONF0 field values */
- + HDMI_FC_AUDICONF0_CC_OFFSET = 4,
- + HDMI_FC_AUDICONF0_CC_MASK = 0x70,
- + HDMI_FC_AUDICONF0_CT_OFFSET = 0,
- + HDMI_FC_AUDICONF0_CT_MASK = 0xF,
- +
- +/* FC_AUDICONF1 field values */
- + HDMI_FC_AUDICONF1_SS_OFFSET = 3,
- + HDMI_FC_AUDICONF1_SS_MASK = 0x18,
- + HDMI_FC_AUDICONF1_SF_OFFSET = 0,
- + HDMI_FC_AUDICONF1_SF_MASK = 0x7,
- +
- +/* FC_AUDICONF3 field values */
- + HDMI_FC_AUDICONF3_LFEPBL_OFFSET = 5,
- + HDMI_FC_AUDICONF3_LFEPBL_MASK = 0x60,
- + HDMI_FC_AUDICONF3_DM_INH_OFFSET = 4,
- + HDMI_FC_AUDICONF3_DM_INH_MASK = 0x10,
- + HDMI_FC_AUDICONF3_LSV_OFFSET = 0,
- + HDMI_FC_AUDICONF3_LSV_MASK = 0xF,
- +
- +/* FC_AUDSCHNLS0 field values */
- + HDMI_FC_AUDSCHNLS0_CGMSA_OFFSET = 4,
- + HDMI_FC_AUDSCHNLS0_CGMSA_MASK = 0x30,
- + HDMI_FC_AUDSCHNLS0_COPYRIGHT_OFFSET = 0,
- + HDMI_FC_AUDSCHNLS0_COPYRIGHT_MASK = 0x01,
- +
- +/* FC_AUDSCHNLS3-6 field values */
- + HDMI_FC_AUDSCHNLS3_OIEC_CH0_OFFSET = 0,
- + HDMI_FC_AUDSCHNLS3_OIEC_CH0_MASK = 0x0f,
- + HDMI_FC_AUDSCHNLS3_OIEC_CH1_OFFSET = 4,
- + HDMI_FC_AUDSCHNLS3_OIEC_CH1_MASK = 0xf0,
- + HDMI_FC_AUDSCHNLS4_OIEC_CH2_OFFSET = 0,
- + HDMI_FC_AUDSCHNLS4_OIEC_CH2_MASK = 0x0f,
- + HDMI_FC_AUDSCHNLS4_OIEC_CH3_OFFSET = 4,
- + HDMI_FC_AUDSCHNLS4_OIEC_CH3_MASK = 0xf0,
- +
- + HDMI_FC_AUDSCHNLS5_OIEC_CH0_OFFSET = 0,
- + HDMI_FC_AUDSCHNLS5_OIEC_CH0_MASK = 0x0f,
- + HDMI_FC_AUDSCHNLS5_OIEC_CH1_OFFSET = 4,
- + HDMI_FC_AUDSCHNLS5_OIEC_CH1_MASK = 0xf0,
- + HDMI_FC_AUDSCHNLS6_OIEC_CH2_OFFSET = 0,
- + HDMI_FC_AUDSCHNLS6_OIEC_CH2_MASK = 0x0f,
- + HDMI_FC_AUDSCHNLS6_OIEC_CH3_OFFSET = 4,
- + HDMI_FC_AUDSCHNLS6_OIEC_CH3_MASK = 0xf0,
- +
- +/* HDMI_FC_AUDSCHNLS7 field values */
- + HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
- + HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
- +
- +/* HDMI_FC_AUDSCHNLS8 field values */
- + HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
- + HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET = 4,
- + HDMI_FC_AUDSCHNLS8_WORDLEGNTH_MASK = 0x0f,
- + HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET = 0,
- +
- +/* FC_AUDSCONF field values */
- + HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_MASK = 0xF0,
- + HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_OFFSET = 4,
- + HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_MASK = 0x1,
- + HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_OFFSET = 0,
- + HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT1 = 0x1,
- + HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT0 = 0x0,
- +
- +/* FC_STAT2 field values */
- + HDMI_FC_STAT2_OVERFLOW_MASK = 0x03,
- + HDMI_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
- + HDMI_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
- +
- +/* FC_INT2 field values */
- + HDMI_FC_INT2_OVERFLOW_MASK = 0x03,
- + HDMI_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
- + HDMI_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01,
- +
- +/* FC_MASK2 field values */
- + HDMI_FC_MASK2_OVERFLOW_MASK = 0x03,
- + HDMI_FC_MASK2_LOW_PRIORITY_OVERFLOW = 0x02,
- + HDMI_FC_MASK2_HIGH_PRIORITY_OVERFLOW = 0x01,
- +
- +/* FC_PRCONF field values */
- + HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK = 0xF0,
- + HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET = 4,
- + HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK = 0x0F,
- + HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET = 0,
- +
- +/* FC_AVICONF0-FC_AVICONF3 field values */
- + HDMI_FC_AVICONF0_PIX_FMT_MASK = 0x03,
- + HDMI_FC_AVICONF0_PIX_FMT_RGB = 0x00,
- + HDMI_FC_AVICONF0_PIX_FMT_YCBCR422 = 0x01,
- + HDMI_FC_AVICONF0_PIX_FMT_YCBCR444 = 0x02,
- + HDMI_FC_AVICONF0_ACTIVE_FMT_MASK = 0x40,
- + HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT = 0x40,
- + HDMI_FC_AVICONF0_ACTIVE_FMT_NO_INFO = 0x00,
- + HDMI_FC_AVICONF0_BAR_DATA_MASK = 0x0C,
- + HDMI_FC_AVICONF0_BAR_DATA_NO_DATA = 0x00,
- + HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR = 0x04,
- + HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR = 0x08,
- + HDMI_FC_AVICONF0_BAR_DATA_VERT_HORIZ_BAR = 0x0C,
- + HDMI_FC_AVICONF0_SCAN_INFO_MASK = 0x30,
- + HDMI_FC_AVICONF0_SCAN_INFO_OVERSCAN = 0x10,
- + HDMI_FC_AVICONF0_SCAN_INFO_UNDERSCAN = 0x20,
- + HDMI_FC_AVICONF0_SCAN_INFO_NODATA = 0x00,
- +
- + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_MASK = 0x0F,
- + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_USE_CODED = 0x08,
- + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3 = 0x09,
- + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9 = 0x0A,
- + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_14_9 = 0x0B,
- + HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_MASK = 0x30,
- + HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_NO_DATA = 0x00,
- + HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3 = 0x10,
- + HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9 = 0x20,
- + HDMI_FC_AVICONF1_COLORIMETRY_MASK = 0xC0,
- + HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA = 0x00,
- + HDMI_FC_AVICONF1_COLORIMETRY_SMPTE = 0x40,
- + HDMI_FC_AVICONF1_COLORIMETRY_ITUR = 0x80,
- + HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO = 0xC0,
- +
- + HDMI_FC_AVICONF2_SCALING_MASK = 0x03,
- + HDMI_FC_AVICONF2_SCALING_NONE = 0x00,
- + HDMI_FC_AVICONF2_SCALING_HORIZ = 0x01,
- + HDMI_FC_AVICONF2_SCALING_VERT = 0x02,
- + HDMI_FC_AVICONF2_SCALING_HORIZ_VERT = 0x03,
- + HDMI_FC_AVICONF2_RGB_QUANT_MASK = 0x0C,
- + HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT = 0x00,
- + HDMI_FC_AVICONF2_RGB_QUANT_LIMITED_RANGE = 0x04,
- + HDMI_FC_AVICONF2_RGB_QUANT_FULL_RANGE = 0x08,
- + HDMI_FC_AVICONF2_EXT_COLORIMETRY_MASK = 0x70,
- + HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601 = 0x00,
- + HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709 = 0x10,
- + HDMI_FC_AVICONF2_EXT_COLORIMETRY_SYCC601 = 0x20,
- + HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_YCC601 = 0x30,
- + HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_RGB = 0x40,
- + HDMI_FC_AVICONF2_IT_CONTENT_MASK = 0x80,
- + HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA = 0x00,
- + HDMI_FC_AVICONF2_IT_CONTENT_VALID = 0x80,
- +
- + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_MASK = 0x03,
- + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS = 0x00,
- + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_PHOTO = 0x01,
- + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_CINEMA = 0x02,
- + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GAME = 0x03,
- + HDMI_FC_AVICONF3_QUANT_RANGE_MASK = 0x0C,
- + HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00,
- + HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04,
- +
- +/* FC_DBGFORCE field values */
- + HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10,
- + HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1,
- +
- +/* PHY_CONF0 field values */
- + HDMI_PHY_CONF0_PDZ_MASK = 0x80,
- + HDMI_PHY_CONF0_PDZ_OFFSET = 7,
- + HDMI_PHY_CONF0_ENTMDS_MASK = 0x40,
- + HDMI_PHY_CONF0_ENTMDS_OFFSET = 6,
- + HDMI_PHY_CONF0_SPARECTRL = 0x20,
- + HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10,
- + HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4,
- + HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8,
- + HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET = 3,
- + HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_MASK = 0x4,
- + HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_OFFSET = 2,
- + HDMI_PHY_CONF0_SELDATAENPOL_MASK = 0x2,
- + HDMI_PHY_CONF0_SELDATAENPOL_OFFSET = 1,
- + HDMI_PHY_CONF0_SELDIPIF_MASK = 0x1,
- + HDMI_PHY_CONF0_SELDIPIF_OFFSET = 0,
- +
- +/* PHY_TST0 field values */
- + HDMI_PHY_TST0_TSTCLR_MASK = 0x20,
- + HDMI_PHY_TST0_TSTCLR_OFFSET = 5,
- + HDMI_PHY_TST0_TSTEN_MASK = 0x10,
- + HDMI_PHY_TST0_TSTEN_OFFSET = 4,
- + HDMI_PHY_TST0_TSTCLK_MASK = 0x1,
- + HDMI_PHY_TST0_TSTCLK_OFFSET = 0,
- +
- +/* PHY_STAT0 field values */
- + HDMI_PHY_RX_SENSE3 = 0x80,
- + HDMI_PHY_RX_SENSE2 = 0x40,
- + HDMI_PHY_RX_SENSE1 = 0x20,
- + HDMI_PHY_RX_SENSE0 = 0x10,
- + HDMI_PHY_HPD = 0x02,
- + HDMI_PHY_TX_PHY_LOCK = 0x01,
- +
- +/* HDMI STAT convenience RX_SENSE | HPD */
- + HDMI_DVI_STAT = 0xF2,
- +
- +/* PHY_I2CM_SLAVE_ADDR field values */
- + HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2 = 0x69,
- + HDMI_PHY_I2CM_SLAVE_ADDR_HEAC_PHY = 0x49,
- +
- +/* PHY_I2CM_OPERATION_ADDR field values */
- + HDMI_PHY_I2CM_OPERATION_ADDR_WRITE = 0x10,
- + HDMI_PHY_I2CM_OPERATION_ADDR_READ = 0x1,
- +
- +/* HDMI_PHY_I2CM_INT_ADDR */
- + HDMI_PHY_I2CM_INT_ADDR_DONE_POL = 0x08,
- + HDMI_PHY_I2CM_INT_ADDR_DONE_MASK = 0x04,
- +
- +/* HDMI_PHY_I2CM_CTLINT_ADDR */
- + HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL = 0x80,
- + HDMI_PHY_I2CM_CTLINT_ADDR_NAC_MASK = 0x40,
- + HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL = 0x08,
- + HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_MASK = 0x04,
- +
- +/* AUD_CTS3 field values */
- + HDMI_AUD_CTS3_N_SHIFT_OFFSET = 5,
- + HDMI_AUD_CTS3_N_SHIFT_MASK = 0xe0,
- + HDMI_AUD_CTS3_N_SHIFT_1 = 0,
- + HDMI_AUD_CTS3_N_SHIFT_16 = 0x20,
- + HDMI_AUD_CTS3_N_SHIFT_32 = 0x40,
- + HDMI_AUD_CTS3_N_SHIFT_64 = 0x60,
- + HDMI_AUD_CTS3_N_SHIFT_128 = 0x80,
- + HDMI_AUD_CTS3_N_SHIFT_256 = 0xa0,
- + /* note that the CTS3 MANUAL bit has been removed
- + from our part. Can't set it, will read as 0. */
- + HDMI_AUD_CTS3_CTS_MANUAL = 0x10,
- + HDMI_AUD_CTS3_AUDCTS19_16_MASK = 0x0f,
- +
- +/* AHB_DMA_CONF0 field values */
- + HDMI_AHB_DMA_CONF0_SW_FIFO_RST_OFFSET = 7,
- + HDMI_AHB_DMA_CONF0_SW_FIFO_RST_MASK = 0x80,
- + HDMI_AHB_DMA_CONF0_HBR_OFFSET = 4,
- + HDMI_AHB_DMA_CONF0_HBR_MASK = 0x10,
- + HDMI_AHB_DMA_CONF0_EN_HLOCK_OFFSET = 3,
- + HDMI_AHB_DMA_CONF0_EN_HLOCK_MASK = 0x08,
- + HDMI_AHB_DMA_CONF0_INCR_TYPE_OFFSET = 1,
- + HDMI_AHB_DMA_CONF0_INCR_TYPE_MASK = 0x06,
- + HDMI_AHB_DMA_CONF0_INCR4 = 0x0,
- + HDMI_AHB_DMA_CONF0_INCR8 = 0x2,
- + HDMI_AHB_DMA_CONF0_INCR16 = 0x4,
- + HDMI_AHB_DMA_CONF0_BURST_MODE = 0x1,
- +
- +/* HDMI_AHB_DMA_START field values */
- + HDMI_AHB_DMA_START_START_OFFSET = 0,
- + HDMI_AHB_DMA_START_START_MASK = 0x01,
- +
- +/* HDMI_AHB_DMA_STOP field values */
- + HDMI_AHB_DMA_STOP_STOP_OFFSET = 0,
- + HDMI_AHB_DMA_STOP_STOP_MASK = 0x01,
- +
- +/* AHB_DMA_STAT, AHB_DMA_INT, AHB_DMA_MASK, AHB_DMA_POL field values */
- + HDMI_AHB_DMA_DONE = 0x80,
- + HDMI_AHB_DMA_RETRY_SPLIT = 0x40,
- + HDMI_AHB_DMA_LOSTOWNERSHIP = 0x20,
- + HDMI_AHB_DMA_ERROR = 0x10,
- + HDMI_AHB_DMA_FIFO_THREMPTY = 0x04,
- + HDMI_AHB_DMA_FIFO_FULL = 0x02,
- + HDMI_AHB_DMA_FIFO_EMPTY = 0x01,
- +
- +/* AHB_DMA_BUFFSTAT, AHB_DMA_BUFFINT, AHB_DMA_BUFFMASK, AHB_DMA_BUFFPOL field values */
- + HDMI_AHB_DMA_BUFFSTAT_FULL = 0x02,
- + HDMI_AHB_DMA_BUFFSTAT_EMPTY = 0x01,
- +
- +/* MC_CLKDIS field values */
- + HDMI_MC_CLKDIS_HDCPCLK_DISABLE = 0x40,
- + HDMI_MC_CLKDIS_CECCLK_DISABLE = 0x20,
- + HDMI_MC_CLKDIS_CSCCLK_DISABLE = 0x10,
- + HDMI_MC_CLKDIS_AUDCLK_DISABLE = 0x8,
- + HDMI_MC_CLKDIS_PREPCLK_DISABLE = 0x4,
- + HDMI_MC_CLKDIS_TMDSCLK_DISABLE = 0x2,
- + HDMI_MC_CLKDIS_PIXELCLK_DISABLE = 0x1,
- +
- +/* MC_SWRSTZ field values */
- + HDMI_MC_SWRSTZ_TMDSSWRST_REQ = 0x02,
- +
- +/* MC_FLOWCTRL field values */
- + HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_MASK = 0x1,
- + HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH = 0x1,
- + HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS = 0x0,
- +
- +/* MC_PHYRSTZ field values */
- + HDMI_MC_PHYRSTZ_ASSERT = 0x0,
- + HDMI_MC_PHYRSTZ_DEASSERT = 0x1,
- +
- +/* MC_HEACPHY_RST field values */
- + HDMI_MC_HEACPHY_RST_ASSERT = 0x1,
- + HDMI_MC_HEACPHY_RST_DEASSERT = 0x0,
- +
- +/* CSC_CFG field values */
- + HDMI_CSC_CFG_INTMODE_MASK = 0x30,
- + HDMI_CSC_CFG_INTMODE_OFFSET = 4,
- + HDMI_CSC_CFG_INTMODE_DISABLE = 0x00,
- + HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1 = 0x10,
- + HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA2 = 0x20,
- + HDMI_CSC_CFG_DECMODE_MASK = 0x3,
- + HDMI_CSC_CFG_DECMODE_OFFSET = 0,
- + HDMI_CSC_CFG_DECMODE_DISABLE = 0x0,
- + HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA1 = 0x1,
- + HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA2 = 0x2,
- + HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3 = 0x3,
- +
- +/* CSC_SCALE field values */
- + HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK = 0xF0,
- + HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP = 0x00,
- + HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP = 0x50,
- + HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP = 0x60,
- + HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP = 0x70,
- + HDMI_CSC_SCALE_CSCSCALE_MASK = 0x03,
- +
- +/* I2CM_OPERATION field values */
- + HDMI_I2CM_OPERATION_WRITE = 0x10,
- + HDMI_I2CM_OPERATION_READ_EXT = 0x2,
- + HDMI_I2CM_OPERATION_READ = 0x1,
- +
- +/* HDMI_I2CM_INT */
- + HDMI_I2CM_INT_DONE_POL = 0x08,
- + HDMI_I2CM_INT_DONE_MASK = 0x04,
- +
- +/* HDMI_I2CM_CTLINT */
- + HDMI_I2CM_CTLINT_NAC_POL = 0x80,
- + HDMI_I2CM_CTLINT_NAC_MASK = 0x40,
- + HDMI_I2CM_CTLINT_ARBITRATION_POL = 0x08,
- + HDMI_I2CM_CTLINT_ARBITRATION_MASK = 0x04,
- +
- +};
- +
- +enum imx_hdmi_type {
- + IMX6DL_HDMI,
- + IMX6Q_HDMI,
- +};
- +
- +/* IOCTL commands */
- +#define HDMI_IOC_MAGIC 'H'
- +
- +#define HDMI_IOC_GET_RESOURCE _IO(HDMI_IOC_MAGIC, 0)
- +#define HDMI_IOC_GET_CPU_TYPE _IO(HDMI_IOC_MAGIC, 1)
- +
- +
- +#endif /* __MXC_HDMI_H__ */
- diff -Nur linux-3.14.35.orig/kernel/cpu.c linux-3.14.35/kernel/cpu.c
- --- linux-3.14.35.orig/kernel/cpu.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/kernel/cpu.c 2015-03-08 14:27:37.893684498 -0500
- @@ -722,3 +722,22 @@
- {
- cpumask_copy(to_cpumask(cpu_online_bits), src);
- }
- +
- +static ATOMIC_NOTIFIER_HEAD(idle_notifier);
- +void idle_notifier_register(struct notifier_block *n)
- +{
- + atomic_notifier_chain_register(&idle_notifier, n);
- +}
- +EXPORT_SYMBOL_GPL(idle_notifier_register);
- +
- +void idle_notifier_unregister(struct notifier_block *n)
- +{
- + atomic_notifier_chain_unregister(&idle_notifier, n);
- +}
- +EXPORT_SYMBOL_GPL(idle_notifier_unregister);
- +
- +void idle_notifier_call_chain(unsigned long val)
- +{
- + atomic_notifier_call_chain(&idle_notifier, val, NULL);
- +}
- +EXPORT_SYMBOL_GPL(idle_notifier_call_chain);
- diff -Nur linux-3.14.35.orig/kernel/irq/manage.c linux-3.14.35/kernel/irq/manage.c
- --- linux-3.14.35.orig/kernel/irq/manage.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/kernel/irq/manage.c 2015-03-08 14:27:37.893684498 -0500
- @@ -32,24 +32,10 @@
- early_param("threadirqs", setup_forced_irqthreads);
- #endif
-
- -/**
- - * synchronize_irq - wait for pending IRQ handlers (on other CPUs)
- - * @irq: interrupt number to wait for
- - *
- - * This function waits for any pending IRQ handlers for this interrupt
- - * to complete before returning. If you use this function while
- - * holding a resource the IRQ handler may need you will deadlock.
- - *
- - * This function may be called - with care - from IRQ context.
- - */
- -void synchronize_irq(unsigned int irq)
- +static void __synchronize_hardirq(struct irq_desc *desc)
- {
- - struct irq_desc *desc = irq_to_desc(irq);
- bool inprogress;
-
- - if (!desc)
- - return;
- -
- do {
- unsigned long flags;
-
- @@ -67,12 +53,56 @@
-
- /* Oops, that failed? */
- } while (inprogress);
- +}
- +
- +/**
- + * synchronize_hardirq - wait for pending hard IRQ handlers (on other CPUs)
- + * @irq: interrupt number to wait for
- + *
- + * This function waits for any pending hard IRQ handlers for this
- + * interrupt to complete before returning. If you use this
- + * function while holding a resource the IRQ handler may need you
- + * will deadlock. It does not take associated threaded handlers
- + * into account.
- + *
- + * Do not use this for shutdown scenarios where you must be sure
- + * that all parts (hardirq and threaded handler) have completed.
- + *
- + * This function may be called - with care - from IRQ context.
- + */
- +void synchronize_hardirq(unsigned int irq)
- +{
- + struct irq_desc *desc = irq_to_desc(irq);
-
- - /*
- - * We made sure that no hardirq handler is running. Now verify
- - * that no threaded handlers are active.
- - */
- - wait_event(desc->wait_for_threads, !atomic_read(&desc->threads_active));
- + if (desc)
- + __synchronize_hardirq(desc);
- +}
- +EXPORT_SYMBOL(synchronize_hardirq);
- +
- +/**
- + * synchronize_irq - wait for pending IRQ handlers (on other CPUs)
- + * @irq: interrupt number to wait for
- + *
- + * This function waits for any pending IRQ handlers for this interrupt
- + * to complete before returning. If you use this function while
- + * holding a resource the IRQ handler may need you will deadlock.
- + *
- + * This function may be called - with care - from IRQ context.
- + */
- +void synchronize_irq(unsigned int irq)
- +{
- + struct irq_desc *desc = irq_to_desc(irq);
- +
- + if (desc) {
- + __synchronize_hardirq(desc);
- + /*
- + * We made sure that no hardirq handler is
- + * running. Now verify that no threaded handlers are
- + * active.
- + */
- + wait_event(desc->wait_for_threads,
- + !atomic_read(&desc->threads_active));
- + }
- }
- EXPORT_SYMBOL(synchronize_irq);
-
- diff -Nur linux-3.14.35.orig/kernel/relay.c linux-3.14.35/kernel/relay.c
- --- linux-3.14.35.orig/kernel/relay.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/kernel/relay.c 2015-03-08 14:27:37.893684498 -0500
- @@ -227,7 +227,7 @@
- * relay_remove_buf - remove a channel buffer
- * @kref: target kernel reference that contains the relay buffer
- *
- - * Removes the file from the fileystem, which also frees the
- + * Removes the file from the filesystem, which also frees the
- * rchan_buf_struct and the channel buffer. Should only be called from
- * kref_put().
- */
- diff -Nur linux-3.14.35.orig/kernel/signal.c linux-3.14.35/kernel/signal.c
- --- linux-3.14.35.orig/kernel/signal.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/kernel/signal.c 2015-03-08 14:27:37.897684498 -0500
- @@ -2382,7 +2382,7 @@
- * @regs: user register state
- * @stepping: nonzero if debugger single-step or block-step in use
- *
- - * This function should be called when a signal has succesfully been
- + * This function should be called when a signal has successfully been
- * delivered. It updates the blocked signals accordingly (@ka->sa.sa_mask
- * is always blocked, and the signal itself is blocked unless %SA_NODEFER
- * is set in @ka->sa.sa_flags. Tracing is notified.
- diff -Nur linux-3.14.35.orig/linaro/configs/android.conf linux-3.14.35/linaro/configs/android.conf
- --- linux-3.14.35.orig/linaro/configs/android.conf 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/linaro/configs/android.conf 2015-03-08 14:27:37.897684498 -0500
- @@ -0,0 +1,42 @@
- +CONFIG_IPV6=y
- +# CONFIG_IPV6_SIT is not set
- +CONFIG_PANIC_TIMEOUT=0
- +CONFIG_HAS_WAKELOCK=y
- +CONFIG_WAKELOCK=y
- +CONFIG_BLK_DEV_LOOP=y
- +CONFIG_DM_CRYPT=y
- +CONFIG_POWER_SUPPLY=y
- +CONFIG_ANDROID_PARANOID_NETWORK=y
- +CONFIG_NET_ACTIVITY_STATS=y
- +CONFIG_INPUT_MISC=y
- +CONFIG_INPUT_UINPUT=y
- +CONFIG_INPUT_GPIO=y
- +CONFIG_USB_G_ANDROID=y
- +CONFIG_SWITCH=y
- +CONFIG_STAGING=y
- +CONFIG_ANDROID=y
- +CONFIG_ANDROID_BINDER_IPC=y
- +CONFIG_ASHMEM=y
- +CONFIG_ANDROID_LOGGER=y
- +CONFIG_ANDROID_TIMED_OUTPUT=y
- +CONFIG_ANDROID_TIMED_GPIO=y
- +CONFIG_ANDROID_LOW_MEMORY_KILLER=y
- +CONFIG_ANDROID_INTF_ALARM_DEV=y
- +CONFIG_CRYPTO_TWOFISH=y
- +CONFIG_BLK_DEV_RAM=y
- +CONFIG_BLK_DEV_RAM_COUNT=16
- +CONFIG_BLK_DEV_RAM_SIZE=16384
- +CONFIG_FUSE_FS=y
- +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
- +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y
- +CONFIG_ION=y
- +CONFIG_SYNC=y
- +CONFIG_SW_SYNC=y
- +CONFIG_SW_SYNC_USER=y
- +CONFIG_ION_TEST=y
- +CONFIG_ION_DUMMY=y
- +CONFIG_ADF=y
- +CONFIG_ADF_FBDEV=y
- +CONFIG_ADF_MEMBLOCK=y
- +CONFIG_DMA_SHARED_BUFFER=y
- +CONFIG_TUN=y
- diff -Nur linux-3.14.35.orig/linaro/configs/arndale.conf linux-3.14.35/linaro/configs/arndale.conf
- --- linux-3.14.35.orig/linaro/configs/arndale.conf 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/linaro/configs/arndale.conf 2015-03-08 14:27:37.897684498 -0500
- @@ -0,0 +1,66 @@
- +CONFIG_KALLSYMS_ALL=y
- +CONFIG_PARTITION_ADVANCED=y
- +CONFIG_BSD_DISKLABEL=y
- +CONFIG_SOLARIS_X86_PARTITION=y
- +CONFIG_ARCH_EXYNOS=y
- +CONFIG_S3C_LOWLEVEL_UART_PORT=2
- +CONFIG_ARCH_EXYNOS5=y
- +# CONFIG_EXYNOS_ATAGS is not set
- +CONFIG_MACH_EXYNOS4_DT=y
- +CONFIG_VMSPLIT_2G=y
- +CONFIG_NR_CPUS=2
- +CONFIG_HIGHMEM=y
- +# CONFIG_COMPACTION is not set
- +CONFIG_ARM_APPENDED_DTB=y
- +CONFIG_ARM_ATAG_DTB_COMPAT=y
- +CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init= mem=256M"
- +CONFIG_CPU_FREQ_GOV_USERSPACE=y
- +CONFIG_VFP=y
- +CONFIG_NEON=y
- +CONFIG_PM_RUNTIME=y
- +CONFIG_BLK_DEV_LOOP=y
- +CONFIG_BLK_DEV_SD=y
- +CONFIG_CHR_DEV_SG=y
- +CONFIG_ATA=y
- +CONFIG_SATA_AHCI_PLATFORM=y
- +CONFIG_SATA_EXYNOS=y
- +CONFIG_AX88796=y
- +CONFIG_AX88796_93CX6=y
- +CONFIG_INPUT_EVDEV=y
- +CONFIG_KEYBOARD_GPIO=y
- +CONFIG_INPUT_TOUCHSCREEN=y
- +CONFIG_SERIAL_8250=y
- +CONFIG_SERIAL_SAMSUNG=y
- +CONFIG_SERIAL_SAMSUNG_CONSOLE=y
- +CONFIG_HW_RANDOM=y
- +CONFIG_I2C=y
- +CONFIG_I2C_S3C2410=y
- +CONFIG_THERMAL=y
- +CONFIG_CPU_THERMAL=y
- +CONFIG_EXYNOS_THERMAL=y
- +CONFIG_MFD_SEC_CORE=y
- +CONFIG_REGULATOR=y
- +CONFIG_REGULATOR_FIXED_VOLTAGE=y
- +CONFIG_REGULATOR_S5M8767=y
- +CONFIG_DRM=y
- +CONFIG_DRM_LOAD_EDID_FIRMWARE=y
- +CONFIG_DRM_EXYNOS=y
- +CONFIG_DRM_EXYNOS_DMABUF=y
- +CONFIG_DRM_EXYNOS_HDMI=y
- +CONFIG_FRAMEBUFFER_CONSOLE=y
- +CONFIG_LOGO=y
- +CONFIG_MMC=y
- +CONFIG_MMC_UNSAFE_RESUME=y
- +CONFIG_MMC_DW=y
- +CONFIG_MMC_DW_IDMAC=y
- +CONFIG_MMC_DW_EXYNOS=y
- +CONFIG_RTC_CLASS=y
- +CONFIG_RTC_DRV_S3C=y
- +CONFIG_DEBUG_KERNEL=y
- +CONFIG_DETECT_HUNG_TASK=y
- +CONFIG_DEBUG_RT_MUTEXES=y
- +CONFIG_DEBUG_SPINLOCK=y
- +CONFIG_DEBUG_INFO=y
- +CONFIG_RCU_CPU_STALL_TIMEOUT=60
- +CONFIG_DEBUG_USER=y
- +CONFIG_TUN=y
- diff -Nur linux-3.14.35.orig/linaro/configs/bigendian.conf linux-3.14.35/linaro/configs/bigendian.conf
- --- linux-3.14.35.orig/linaro/configs/bigendian.conf 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/linaro/configs/bigendian.conf 2015-03-08 14:27:37.897684498 -0500
- @@ -0,0 +1,4 @@
- +CONFIG_CPU_BIG_ENDIAN=y
- +CONFIG_CPU_ENDIAN_BE8=y
- +# CONFIG_VIRTUALIZATION is not set
- +# CONFIG_MMC_DW_IDMAC is not set
- diff -Nur linux-3.14.35.orig/linaro/configs/big-LITTLE-IKS.conf linux-3.14.35/linaro/configs/big-LITTLE-IKS.conf
- --- linux-3.14.35.orig/linaro/configs/big-LITTLE-IKS.conf 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/linaro/configs/big-LITTLE-IKS.conf 2015-03-08 14:27:37.897684498 -0500
- @@ -0,0 +1,5 @@
- +CONFIG_BIG_LITTLE=y
- +CONFIG_BL_SWITCHER=y
- +CONFIG_ARM_DT_BL_CPUFREQ=y
- +CONFIG_ARM_VEXPRESS_BL_CPUFREQ=y
- +CONFIG_CPU_FREQ_GOV_USERSPACE=y
- diff -Nur linux-3.14.35.orig/linaro/configs/debug.conf linux-3.14.35/linaro/configs/debug.conf
- --- linux-3.14.35.orig/linaro/configs/debug.conf 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/linaro/configs/debug.conf 2015-03-08 14:27:37.897684498 -0500
- @@ -0,0 +1 @@
- +CONFIG_PROVE_LOCKING=y
- diff -Nur linux-3.14.35.orig/linaro/configs/distribution.conf linux-3.14.35/linaro/configs/distribution.conf
- --- linux-3.14.35.orig/linaro/configs/distribution.conf 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/linaro/configs/distribution.conf 2015-03-08 14:27:37.897684498 -0500
- @@ -0,0 +1,49 @@
- +# CONFIG_LOCALVERSION_AUTO is not set
- +CONFIG_CGROUPS=y
- +# CONFIG_COMPAT_BRK is not set
- +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
- +CONFIG_SECCOMP=y
- +CONFIG_CC_STACKPROTECTOR=y
- +CONFIG_SYN_COOKIES=y
- +CONFIG_IPV6=y
- +CONFIG_NETLABEL=y
- +CONFIG_BRIDGE_NETFILTER=y
- +CONFIG_NF_CONNTRACK=m
- +CONFIG_NETFILTER_XT_CONNMARK=m
- +CONFIG_NETFILTER_XT_MARK=m
- +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
- +CONFIG_NF_CONNTRACK_IPV4=m
- +CONFIG_NF_NAT_IPV4=m
- +CONFIG_IP_NF_IPTABLES=m
- +CONFIG_IP_NF_FILTER=m
- +CONFIG_IP_NF_MANGLE=m
- +CONFIG_NF_CONNTRACK_IPV6=m
- +CONFIG_NF_NAT_IPV6=m
- +CONFIG_IP6_NF_IPTABLES=m
- +CONFIG_IP6_NF_FILTER=m
- +CONFIG_IP6_NF_MANGLE=m
- +CONFIG_BRIDGE_NF_EBTABLES=m
- +CONFIG_BRIDGE_EBT_MARK_T=m
- +CONFIG_BRIDGE=m
- +CONFIG_TUN=y
- +CONFIG_DEVTMPFS=y
- +CONFIG_DEVTMPFS_MOUNT=y
- +CONFIG_BLK_DEV_RAM=y
- +CONFIG_BLK_DEV_RAM_SIZE=65536
- +CONFIG_INPUT_MISC=y
- +CONFIG_INPUT_UINPUT=y
- +# CONFIG_DEVKMEM is not set
- +CONFIG_FRAMEBUFFER_CONSOLE=y
- +CONFIG_AUTOFS4_FS=y
- +CONFIG_TMPFS_POSIX_ACL=y
- +CONFIG_STRICT_DEVMEM=y
- +CONFIG_SECURITY=y
- +CONFIG_LSM_MMAP_MIN_ADDR=0
- +CONFIG_SECURITY_SELINUX=y
- +CONFIG_SECURITY_SMACK=y
- +CONFIG_SECURITY_APPARMOR=y
- +CONFIG_DEFAULT_SECURITY_APPARMOR=y
- +CONFIG_HUGETLBFS=y
- +CONFIG_HUGETLB_PAGE=y
- +CONFIG_TRANSPARENT_HUGEPAGE=y
- +CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
- diff -Nur linux-3.14.35.orig/linaro/configs/highbank.conf linux-3.14.35/linaro/configs/highbank.conf
- --- linux-3.14.35.orig/linaro/configs/highbank.conf 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/linaro/configs/highbank.conf 2015-03-08 14:27:37.897684498 -0500
- @@ -0,0 +1,40 @@
- +CONFIG_EXPERIMENTAL=y
- +CONFIG_NO_HZ=y
- +CONFIG_HIGH_RES_TIMERS=y
- +CONFIG_ARCH_HIGHBANK=y
- +CONFIG_ARM_ERRATA_754322=y
- +CONFIG_SMP=y
- +CONFIG_SCHED_MC=y
- +CONFIG_AEABI=y
- +CONFIG_CMDLINE="console=ttyAMA0"
- +CONFIG_CPU_IDLE=y
- +CONFIG_VFP=y
- +CONFIG_NEON=y
- +CONFIG_NET=y
- +CONFIG_SCSI=y
- +CONFIG_BLK_DEV_SD=y
- +CONFIG_ATA=y
- +CONFIG_SATA_AHCI_PLATFORM=y
- +CONFIG_SATA_HIGHBANK=y
- +CONFIG_NETDEVICES=y
- +CONFIG_NET_CALXEDA_XGMAC=y
- +CONFIG_SERIAL_AMBA_PL011=y
- +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
- +CONFIG_IPMI_HANDLER=y
- +CONFIG_IPMI_SI=y
- +CONFIG_I2C=y
- +CONFIG_I2C_DESIGNWARE_PLATFORM=y
- +CONFIG_SPI=y
- +CONFIG_SPI_PL022=y
- +CONFIG_GPIO_PL061=y
- +CONFIG_MMC=y
- +CONFIG_MMC_SDHCI=y
- +CONFIG_MMC_SDHCI_PLTFM=y
- +CONFIG_EDAC=y
- +CONFIG_EDAC_MM_EDAC=y
- +CONFIG_EDAC_HIGHBANK_MC=y
- +CONFIG_EDAC_HIGHBANK_L2=y
- +CONFIG_RTC_CLASS=y
- +CONFIG_RTC_DRV_PL031=y
- +CONFIG_DMADEVICES=y
- +CONFIG_PL330_DMA=y
- diff -Nur linux-3.14.35.orig/linaro/configs/kvm-guest.conf linux-3.14.35/linaro/configs/kvm-guest.conf
- --- linux-3.14.35.orig/linaro/configs/kvm-guest.conf 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/linaro/configs/kvm-guest.conf 2015-03-08 14:27:37.897684498 -0500
- @@ -0,0 +1,11 @@
- +CONFIG_BALLOON_COMPACTION=y
- +CONFIG_VIRTIO_BLK=y
- +CONFIG_VIRTIO_NET=y
- +CONFIG_HVC_DRIVER=y
- +CONFIG_VIRTIO_CONSOLE=y
- +CONFIG_VIRTIO=y
- +CONFIG_VIRTIO_BALLOON=y
- +CONFIG_VIRTIO_MMIO=y
- +CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
- +CONFIG_VIRTUALIZATION=y
- +# CONFIG_THUMB2_KERNEL is not set
- diff -Nur linux-3.14.35.orig/linaro/configs/kvm-host.conf linux-3.14.35/linaro/configs/kvm-host.conf
- --- linux-3.14.35.orig/linaro/configs/kvm-host.conf 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/linaro/configs/kvm-host.conf 2015-03-08 14:27:37.897684498 -0500
- @@ -0,0 +1,11 @@
- +CONFIG_VIRTUALIZATION=y
- +CONFIG_ARM_LPAE=y
- +CONFIG_ARM_VIRT_EXT=y
- +CONFIG_HAVE_KVM_IRQCHIP=y
- +CONFIG_KVM_ARM_HOST=y
- +CONFIG_KVM_ARM_MAX_VCPUS=4
- +CONFIG_KVM_ARM_TIMER=y
- +CONFIG_KVM_ARM_VGIC=y
- +CONFIG_KVM_MMIO=y
- +CONFIG_KVM=y
- +CONFIG_BLK_DEV_NBD=m
- diff -Nur linux-3.14.35.orig/linaro/configs/linaro-base.conf linux-3.14.35/linaro/configs/linaro-base.conf
- --- linux-3.14.35.orig/linaro/configs/linaro-base.conf 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/linaro/configs/linaro-base.conf 2015-03-08 14:27:37.897684498 -0500
- @@ -0,0 +1,115 @@
- +CONFIG_SYSVIPC=y
- +CONFIG_POSIX_MQUEUE=y
- +CONFIG_BSD_PROCESS_ACCT=y
- +CONFIG_IKCONFIG=y
- +CONFIG_IKCONFIG_PROC=y
- +CONFIG_LOG_BUF_SHIFT=16
- +CONFIG_BLK_DEV_INITRD=y
- +CONFIG_EMBEDDED=y
- +CONFIG_HOTPLUG=y
- +CONFIG_PERF_EVENTS=y
- +CONFIG_SLAB=y
- +CONFIG_PROFILING=y
- +CONFIG_OPROFILE=y
- +CONFIG_MODULES=y
- +CONFIG_MODULE_UNLOAD=y
- +CONFIG_NO_HZ=y
- +CONFIG_HIGH_RES_TIMERS=y
- +CONFIG_SMP=y
- +CONFIG_SCHED_MC=y
- +CONFIG_SCHED_SMT=y
- +CONFIG_THUMB2_KERNEL=y
- +CONFIG_AEABI=y
- +# CONFIG_OABI_COMPAT is not set
- +CONFIG_CPU_FREQ=y
- +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
- +CONFIG_CPU_IDLE=y
- +CONFIG_BINFMT_MISC=y
- +CONFIG_MD=y
- +CONFIG_BLK_DEV_DM=y
- +CONFIG_NET=y
- +CONFIG_PACKET=y
- +CONFIG_UNIX=y
- +CONFIG_XFRM_USER=y
- +CONFIG_NET_KEY=y
- +CONFIG_NET_KEY_MIGRATE=y
- +CONFIG_INET=y
- +CONFIG_IP_MULTICAST=y
- +CONFIG_IP_PNP=y
- +CONFIG_IP_PNP_DHCP=y
- +CONFIG_IP_PNP_BOOTP=y
- +CONFIG_IP_PNP_RARP=y
- +# CONFIG_INET_LRO is not set
- +CONFIG_NETFILTER=y
- +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
- +CONFIG_CONNECTOR=y
- +CONFIG_MTD=y
- +CONFIG_MTD_CMDLINE_PARTS=y
- +CONFIG_MTD_BLOCK=y
- +CONFIG_MTD_OOPS=y
- +CONFIG_MTD_CFI=y
- +CONFIG_MTD_CFI_INTELEXT=y
- +CONFIG_MTD_NAND=y
- +CONFIG_NETDEVICES=y
- +CONFIG_EXT2_FS=y
- +CONFIG_EXT3_FS=y
- +CONFIG_EXT4_FS=y
- +CONFIG_BTRFS_FS=y
- +CONFIG_QUOTA=y
- +CONFIG_QFMT_V2=y
- +CONFIG_MSDOS_FS=y
- +CONFIG_VFAT_FS=y
- +CONFIG_TMPFS=y
- +CONFIG_ECRYPT_FS=y
- +CONFIG_JFFS2_FS=y
- +CONFIG_JFFS2_SUMMARY=y
- +CONFIG_JFFS2_FS_XATTR=y
- +CONFIG_JFFS2_COMPRESSION_OPTIONS=y
- +CONFIG_JFFS2_LZO=y
- +CONFIG_JFFS2_RUBIN=y
- +CONFIG_CRAMFS=y
- +CONFIG_NETWORK_FILESYSTEMS=y
- +CONFIG_NFS_FS=y
- +# CONFIG_NFS_V2 is not set
- +CONFIG_NFS_V3=y
- +CONFIG_NFS_V3_ACL=y
- +CONFIG_NFS_V4=y
- +CONFIG_ROOT_NFS=y
- +CONFIG_NLS_CODEPAGE_437=y
- +CONFIG_NLS_ISO8859_1=y
- +CONFIG_PRINTK_TIME=y
- +CONFIG_MAGIC_SYSRQ=y
- +CONFIG_DEBUG_FS=y
- +CONFIG_SCHEDSTATS=y
- +CONFIG_TIMER_STATS=y
- +CONFIG_KEYS=y
- +CONFIG_CRYPTO_MICHAEL_MIC=y
- +CONFIG_CRC_CCITT=y
- +CONFIG_CRC_T10DIF=y
- +CONFIG_CRC_ITU_T=y
- +CONFIG_CRC7=y
- +CONFIG_HW_PERF_EVENTS=y
- +CONFIG_FUNCTION_TRACER=y
- +CONFIG_ENABLE_DEFAULT_TRACERS=y
- +CONFIG_PROC_DEVICETREE=y
- +CONFIG_JUMP_LABEL=y
- +CONFIG_STRICT_DEVMEM=y
- +CONFIG_KGDB=y
- +CONFIG_KGDB_TESTS=y
- +CONFIG_OF_IDLE_STATES=y
- +CONFIG_FTRACE=y
- +CONFIG_FUNCTION_TRACER=y
- +CONFIG_FTRACE_SYSCALLS=y
- +CONFIG_STACK_TRACER=y
- +CONFIG_FUNCTION_PROFILER=y
- +CONFIG_MAILBOX=y
- +CONFIG_AUDIT=y
- +CONFIG_NF_CONNTRACK_SECMARK=y
- +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
- +CONFIG_NETFILTER_XT_TARGET_SECMARK=y
- +CONFIG_IP_NF_SECURITY=y
- +CONFIG_SECURITY=y
- +CONFIG_SECURITY_NETWORK=y
- +CONFIG_LSM_MMAP_MIN_ADDR=4096
- +CONFIG_SECURITY_SELINUX=y
- +CONFIG_EXT4_FS_SECURITY=y
- diff -Nur linux-3.14.35.orig/linaro/configs/omap4.conf linux-3.14.35/linaro/configs/omap4.conf
- --- linux-3.14.35.orig/linaro/configs/omap4.conf 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/linaro/configs/omap4.conf 2015-03-08 14:27:37.897684498 -0500
- @@ -0,0 +1,196 @@
- +CONFIG_EXPERT=y
- +CONFIG_KPROBES=y
- +CONFIG_MODULE_FORCE_LOAD=y
- +CONFIG_MODULE_FORCE_UNLOAD=y
- +CONFIG_MODVERSIONS=y
- +CONFIG_MODULE_SRCVERSION_ALL=y
- +# CONFIG_BLK_DEV_BSG is not set
- +CONFIG_PARTITION_ADVANCED=y
- +CONFIG_GPIO_PCA953X=y
- +CONFIG_OMAP_RESET_CLOCKS=y
- +CONFIG_OMAP_MUX_DEBUG=y
- +CONFIG_ARCH_OMAP3=y
- +CONFIG_ARCH_OMAP4=y
- +CONFIG_ARCH_OMAP2PLUS=y
- +CONFIG_SOC_OMAP5=y
- +# CONFIG_ARCH_OMAP2 is not set
- +CONFIG_ARCH_VEXPRESS_CA9X4=y
- +CONFIG_ARM_THUMBEE=y
- +CONFIG_ARM_ERRATA_411920=y
- +CONFIG_NR_CPUS=2
- +CONFIG_ZBOOT_ROM_TEXT=0x0
- +CONFIG_ZBOOT_ROM_BSS=0x0
- +CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200"
- +CONFIG_KEXEC=y
- +CONFIG_PM_DEBUG=y
- +CONFIG_CAN=m
- +CONFIG_CAN_C_CAN=m
- +CONFIG_CAN_C_CAN_PLATFORM=m
- +CONFIG_BT=m
- +CONFIG_BT_HCIUART=m
- +CONFIG_BT_HCIUART_H4=y
- +CONFIG_BT_HCIUART_BCSP=y
- +CONFIG_BT_HCIUART_LL=y
- +CONFIG_BT_HCIBCM203X=m
- +CONFIG_BT_HCIBPA10X=m
- +CONFIG_CFG80211=m
- +CONFIG_MAC80211=m
- +CONFIG_MAC80211_RC_PID=y
- +CONFIG_MAC80211_RC_DEFAULT_PID=y
- +CONFIG_CMA=y
- +CONFIG_MTD_NAND_OMAP2=y
- +CONFIG_MTD_ONENAND=y
- +CONFIG_MTD_ONENAND_VERIFY_WRITE=y
- +CONFIG_MTD_ONENAND_OMAP2=y
- +CONFIG_MTD_UBI=y
- +CONFIG_BLK_DEV_LOOP=y
- +CONFIG_BLK_DEV_RAM_SIZE=16384
- +CONFIG_SENSORS_TSL2550=m
- +CONFIG_SENSORS_LIS3_I2C=m
- +CONFIG_SCSI=y
- +CONFIG_BLK_DEV_SD=y
- +CONFIG_SCSI_MULTI_LUN=y
- +CONFIG_SCSI_SCAN_ASYNC=y
- +CONFIG_KS8851=y
- +CONFIG_KS8851_MLL=y
- +CONFIG_SMC91X=y
- +CONFIG_SMSC911X=y
- +CONFIG_TI_CPSW=y
- +CONFIG_SMSC_PHY=y
- +CONFIG_USB_USBNET=y
- +CONFIG_USB_NET_SMSC95XX=y
- +CONFIG_USB_ALI_M5632=y
- +CONFIG_USB_AN2720=y
- +CONFIG_USB_EPSON2888=y
- +CONFIG_USB_KC2190=y
- +CONFIG_LIBERTAS=m
- +CONFIG_LIBERTAS_USB=m
- +CONFIG_LIBERTAS_SDIO=m
- +CONFIG_LIBERTAS_DEBUG=y
- +CONFIG_INPUT_JOYDEV=y
- +CONFIG_INPUT_EVDEV=y
- +CONFIG_KEYBOARD_GPIO=y
- +CONFIG_KEYBOARD_MATRIX=m
- +CONFIG_KEYBOARD_TWL4030=y
- +CONFIG_INPUT_TOUCHSCREEN=y
- +CONFIG_TOUCHSCREEN_ADS7846=y
- +CONFIG_INPUT_TWL4030_PWRBUTTON=y
- +CONFIG_VT_HW_CONSOLE_BINDING=y
- +# CONFIG_LEGACY_PTYS is not set
- +CONFIG_SERIAL_8250=y
- +CONFIG_SERIAL_8250_CONSOLE=y
- +CONFIG_SERIAL_8250_NR_UARTS=32
- +CONFIG_SERIAL_8250_EXTENDED=y
- +CONFIG_SERIAL_8250_MANY_PORTS=y
- +CONFIG_SERIAL_8250_SHARE_IRQ=y
- +CONFIG_SERIAL_8250_DETECT_IRQ=y
- +CONFIG_SERIAL_8250_RSA=y
- +CONFIG_SERIAL_AMBA_PL011=y
- +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
- +CONFIG_SERIAL_OMAP=y
- +CONFIG_SERIAL_OMAP_CONSOLE=y
- +CONFIG_HW_RANDOM=y
- +CONFIG_I2C_CHARDEV=y
- +CONFIG_SPI=y
- +CONFIG_SPI_OMAP24XX=y
- +CONFIG_PINCTRL_SINGLE=y
- +CONFIG_DEBUG_GPIO=y
- +CONFIG_GPIO_SYSFS=y
- +CONFIG_GPIO_TWL4030=y
- +CONFIG_W1=y
- +CONFIG_SENSORS_LM75=m
- +CONFIG_WATCHDOG=y
- +CONFIG_OMAP_WATCHDOG=y
- +CONFIG_TWL4030_WATCHDOG=y
- +CONFIG_MFD_TPS65217=y
- +CONFIG_MFD_TPS65910=y
- +CONFIG_TWL6040_CORE=y
- +CONFIG_REGULATOR_TPS65023=y
- +CONFIG_REGULATOR_TPS6507X=y
- +CONFIG_REGULATOR_TPS65217=y
- +CONFIG_REGULATOR_TPS65910=y
- +CONFIG_REGULATOR_TWL4030=y
- +CONFIG_FB=y
- +CONFIG_FIRMWARE_EDID=y
- +CONFIG_FB_MODE_HELPERS=y
- +CONFIG_FB_TILEBLITTING=y
- +CONFIG_OMAP2_DSS=m
- +CONFIG_OMAP2_DSS_RFBI=y
- +CONFIG_OMAP2_DSS_SDI=y
- +CONFIG_OMAP2_DSS_DSI=y
- +CONFIG_FB_OMAP2=m
- +CONFIG_PANEL_GENERIC_DPI=m
- +CONFIG_PANEL_TFP410=m
- +CONFIG_PANEL_SHARP_LS037V7DW01=m
- +CONFIG_PANEL_NEC_NL8048HL11_01B=m
- +CONFIG_PANEL_TAAL=m
- +CONFIG_PANEL_TPO_TD043MTEA1=m
- +CONFIG_PANEL_ACX565AKM=m
- +CONFIG_BACKLIGHT_LCD_SUPPORT=y
- +CONFIG_LCD_CLASS_DEVICE=y
- +CONFIG_LCD_PLATFORM=y
- +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
- +CONFIG_FONTS=y
- +CONFIG_FONT_8x8=y
- +CONFIG_FONT_8x16=y
- +CONFIG_LOGO=y
- +CONFIG_SOUND=m
- +CONFIG_SND=m
- +CONFIG_SND_VERBOSE_PRINTK=y
- +CONFIG_SND_DEBUG=y
- +CONFIG_SND_USB_AUDIO=m
- +CONFIG_SND_SOC=m
- +CONFIG_SND_OMAP_SOC=m
- +CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m
- +CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m
- +CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m
- +CONFIG_USB=y
- +CONFIG_USB_DEBUG=y
- +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
- +CONFIG_USB_MON=y
- +CONFIG_USB_EHCI_HCD=y
- +CONFIG_USB_OHCI_HCD=y
- +CONFIG_USB_WDM=y
- +CONFIG_USB_STORAGE=y
- +CONFIG_USB_TEST=y
- +CONFIG_USB_PHY=y
- +CONFIG_NOP_USB_XCEIV=y
- +CONFIG_USB_GADGET=y
- +CONFIG_USB_GADGET_DEBUG=y
- +CONFIG_USB_GADGET_DEBUG_FILES=y
- +CONFIG_USB_GADGET_DEBUG_FS=y
- +CONFIG_USB_ZERO=m
- +CONFIG_MMC=y
- +CONFIG_MMC_UNSAFE_RESUME=y
- +CONFIG_SDIO_UART=y
- +CONFIG_MMC_ARMMMCI=y
- +CONFIG_MMC_OMAP=y
- +CONFIG_MMC_OMAP_HS=y
- +CONFIG_NEW_LEDS=y
- +CONFIG_LEDS_CLASS=y
- +CONFIG_LEDS_GPIO=y
- +CONFIG_LEDS_TRIGGERS=y
- +CONFIG_LEDS_TRIGGER_TIMER=y
- +CONFIG_LEDS_TRIGGER_ONESHOT=y
- +CONFIG_LEDS_TRIGGER_HEARTBEAT=y
- +CONFIG_LEDS_TRIGGER_BACKLIGHT=y
- +CONFIG_LEDS_TRIGGER_CPU=y
- +CONFIG_LEDS_TRIGGER_GPIO=y
- +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
- +CONFIG_RTC_CLASS=y
- +CONFIG_RTC_DRV_TWL92330=y
- +CONFIG_RTC_DRV_TWL4030=y
- +CONFIG_RTC_DRV_OMAP=y
- +CONFIG_DMADEVICES=y
- +CONFIG_DMA_OMAP=y
- +# CONFIG_EXT3_FS_XATTR is not set
- +CONFIG_UBIFS_FS=y
- +CONFIG_NFS_FS=y
- +CONFIG_NFS_V3_ACL=y
- +CONFIG_NFS_V4=y
- +CONFIG_ROOT_NFS=y
- +# CONFIG_DEBUG_BUGVERBOSE is not set
- +CONFIG_DEBUG_INFO=y
- +# CONFIG_CRYPTO_ANSI_CPRNG is not set
- +CONFIG_LIBCRC32C=y
- +# CONFIG_CPU_FREQ is not set
- diff -Nur linux-3.14.35.orig/linaro/configs/preempt-rt.conf linux-3.14.35/linaro/configs/preempt-rt.conf
- --- linux-3.14.35.orig/linaro/configs/preempt-rt.conf 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/linaro/configs/preempt-rt.conf 2015-03-08 14:27:37.897684498 -0500
- @@ -0,0 +1,4 @@
- +CONFIG_PREEMPT=y
- +CONFIG_PREEMPT_RT_FULL=y
- +CONFIG_SLUB=y
- +# CONFIG_CPU_FREQ is not set
- diff -Nur linux-3.14.35.orig/linaro/configs/vexpress64.conf linux-3.14.35/linaro/configs/vexpress64.conf
- --- linux-3.14.35.orig/linaro/configs/vexpress64.conf 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/linaro/configs/vexpress64.conf 2015-03-08 14:27:37.897684498 -0500
- @@ -0,0 +1,56 @@
- +CONFIG_ARCH_VEXPRESS=y
- +CONFIG_SMP=y
- +CONFIG_NR_CPUS=8
- +CONFIG_CMDLINE="console=ttyAMA0"
- +CONFIG_COMPAT=y
- +CONFIG_SMC91X=y
- +CONFIG_INPUT_EVDEV=y
- +CONFIG_SERIO_AMBAKMI=y
- +CONFIG_SERIAL_AMBA_PL011=y
- +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
- +# CONFIG_SERIO_I8042 is not set
- +CONFIG_FB=y
- +CONFIG_FB_ARMCLCD=y
- +CONFIG_FRAMEBUFFER_CONSOLE=y
- +# CONFIG_VGA_CONSOLE is not set
- +CONFIG_LOGO=y
- +# CONFIG_LOGO_LINUX_MONO is not set
- +# CONFIG_LOGO_LINUX_VGA16 is not set
- +CONFIG_MMC=y
- +CONFIG_MMC_ARMMMCI=y
- +CONFIG_RTC_CLASS=y
- +CONFIG_RTC_DRV_PL031=y
- +CONFIG_NFS_FS=y
- +CONFIG_NFS_V3=y
- +CONFIG_NFS_V3_ACL=y
- +CONFIG_NFS_V4=y
- +CONFIG_ROOT_NFS=y
- +CONFIG_VIRTIO=y
- +CONFIG_VIRTIO_BLK=y
- +CONFIG_VIRTIO_MMIO=y
- +CONFIG_REGULATOR=y
- +CONFIG_REGULATOR_FIXED_VOLTAGE=y
- +CONFIG_CMA=y
- +CONFIG_DMA_CMA=y
- +CONFIG_COMMON_CLK_SCPI=y
- +CONFIG_SMSC911X=y
- +CONFIG_I2C=y
- +CONFIG_ARM_MHU_MBOX=y
- +CONFIG_ARM_SCPI_PROTOCOL=y
- +CONFIG_USB_HIDDEV=y
- +CONFIG_SCSI=y
- +CONFIG_BLK_DEV_SD=y
- +CONFIG_USB_STORAGE=y
- +CONFIG_USB=y
- +CONFIG_USB_ULPI=y
- +CONFIG_USB_EHCI_HCD=y
- +CONFIG_USB_EHCI_HCD_SYNOPSYS=y
- +CONFIG_USB_OHCI_HCD=y
- +CONFIG_USB_PHY=y
- +CONFIG_USB_ISP1301=y
- +CONFIG_PM_OPP=y
- +CONFIG_GENERIC_CPUFREQ_CPU0=y
- +CONFIG_ARM_BIG_LITTLE_CPUFREQ=y
- +CONFIG_ARM_DT_BL_CPUFREQ=y
- +CONFIG_ARM64_CPUIDLE=y
- +CONFIG_ARM64_CRYPTO=y
- diff -Nur linux-3.14.35.orig/linaro/configs/vexpress.conf linux-3.14.35/linaro/configs/vexpress.conf
- --- linux-3.14.35.orig/linaro/configs/vexpress.conf 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/linaro/configs/vexpress.conf 2015-03-08 14:27:37.897684498 -0500
- @@ -0,0 +1,64 @@
- +CONFIG_ARCH_VEXPRESS=y
- +CONFIG_ARCH_VEXPRESS_CA9X4=y
- +CONFIG_HAVE_ARM_ARCH_TIMER=y
- +CONFIG_NR_CPUS=8
- +CONFIG_HIGHMEM=y
- +CONFIG_HIGHPTE=y
- +CONFIG_ARM_PSCI=y
- +CONFIG_MCPM=y
- +CONFIG_ARCH_VEXPRESS_DCSCB=y
- +CONFIG_ARCH_VEXPRESS_TC2_PM=y
- +CONFIG_ARM_BIG_LITTLE_CPUIDLE=y
- +CONFIG_BIG_LITTLE=y
- +CONFIG_ARM_VEXPRESS_SPC_CPUFREQ=y
- +CONFIG_PM_OPP=y
- +CONFIG_CPU_FREQ=y
- +CONFIG_CPU_FREQ_GOV_ONDEMAND=y
- +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
- +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
- +CONFIG_CMDLINE="console=ttyAMA0,38400n8 root=/dev/mmcblk0p2 rootwait mmci.fmax=4000000"
- +CONFIG_VFP=y
- +CONFIG_NEON=y
- +CONFIG_SCSI=y
- +CONFIG_BLK_DEV_SD=y
- +CONFIG_SMSC911X=y
- +CONFIG_SMC91X=y
- +CONFIG_INPUT_EVDEV=y
- +CONFIG_SERIO_AMBAKMI=y
- +CONFIG_SERIAL_AMBA_PL011=y
- +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
- +CONFIG_FB=y
- +CONFIG_FB_ARMCLCD=y
- +CONFIG_FB_ARMHDLCD=y
- +CONFIG_LOGO=y
- +# CONFIG_LOGO_LINUX_MONO is not set
- +# CONFIG_LOGO_LINUX_VGA16 is not set
- +CONFIG_SOUND=y
- +CONFIG_SND=y
- +CONFIG_SND_ARMAACI=y
- +CONFIG_USB=y
- +CONFIG_USB_ISP1760_HCD=y
- +CONFIG_USB_STORAGE=y
- +CONFIG_MMC=y
- +CONFIG_MMC_ARMMMCI=y
- +CONFIG_RTC_CLASS=y
- +CONFIG_RTC_DRV_PL031=y
- +CONFIG_NFS_FS=y
- +CONFIG_NFS_V3=y
- +CONFIG_NFS_V3_ACL=y
- +CONFIG_NFS_V4=y
- +CONFIG_ROOT_NFS=y
- +CONFIG_VEXPRESS_CONFIG=y
- +CONFIG_SENSORS_VEXPRESS=y
- +CONFIG_REGULATOR=y
- +CONFIG_REGULATOR_VEXPRESS=y
- +CONFIG_NEW_LEDS=y
- +CONFIG_LEDS_CLASS=y
- +CONFIG_LEDS_GPIO=y
- +CONFIG_LEDS_TRIGGERS=y
- +CONFIG_LEDS_TRIGGER_HEARTBEAT=y
- +CONFIG_LEDS_TRIGGER_CPU=y
- +CONFIG_VIRTIO=y
- +CONFIG_VIRTIO_BLK=y
- +CONFIG_VIRTIO_MMIO=y
- +CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
- diff -Nur linux-3.14.35.orig/linaro/configs/vexpress-tuning.conf linux-3.14.35/linaro/configs/vexpress-tuning.conf
- --- linux-3.14.35.orig/linaro/configs/vexpress-tuning.conf 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/linaro/configs/vexpress-tuning.conf 2015-03-08 14:27:37.897684498 -0500
- @@ -0,0 +1 @@
- +# CONFIG_PROVE_LOCKING is not set
- diff -Nur linux-3.14.35.orig/linaro/configs/xen.conf linux-3.14.35/linaro/configs/xen.conf
- --- linux-3.14.35.orig/linaro/configs/xen.conf 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/linaro/configs/xen.conf 2015-03-08 14:27:37.897684498 -0500
- @@ -0,0 +1,7 @@
- +CONFIG_XEN=y
- +CONFIG_XEN_NETDEV_FRONTEND=y
- +CONFIG_XEN_NETDEV_BACKEND=y
- +CONFIG_XEN_BLKDEV_FRONTEND=y
- +CONFIG_XEN_BLKDEV_BACKEND=y
- +CONFIG_XENFS=y
- +CONFIG_XEN_COMPAT_XENFS=y
- diff -Nur linux-3.14.35.orig/MAINTAINERS linux-3.14.35/MAINTAINERS
- --- linux-3.14.35.orig/MAINTAINERS 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/MAINTAINERS 2015-03-08 14:27:37.901684498 -0500
- @@ -5511,6 +5511,14 @@
- F: drivers/net/macvlan.c
- F: include/linux/if_macvlan.h
-
- +MAILBOX API
- +M: Jassi Brar <jassisinghbrar@gmail.com>
- +L: linux-kernel@vger.kernel.org
- +S: Maintained
- +F: drivers/mailbox/
- +F: include/linux/mailbox_client.h
- +F: include/linux/mailbox_controller.h
- +
- MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
- M: Michael Kerrisk <mtk.manpages@gmail.com>
- W: http://www.kernel.org/doc/man-pages
- diff -Nur linux-3.14.35.orig/mm/cma.c linux-3.14.35/mm/cma.c
- --- linux-3.14.35.orig/mm/cma.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/mm/cma.c 2015-03-08 14:27:37.901684498 -0500
- @@ -0,0 +1,356 @@
- +/*
- + * Contiguous Memory Allocator
- + *
- + * Copyright (c) 2010-2011 by Samsung Electronics.
- + * Copyright IBM Corporation, 2013
- + * Copyright LG Electronics Inc., 2014
- + * Written by:
- + * Marek Szyprowski <m.szyprowski@samsung.com>
- + * Michal Nazarewicz <mina86@mina86.com>
- + * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
- + * Joonsoo Kim <iamjoonsoo.kim@lge.com>
- + *
- + * 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 optional) any later version of the license.
- + */
- +
- +#define pr_fmt(fmt) "cma: " fmt
- +
- +#ifdef CONFIG_CMA_DEBUG
- +#ifndef DEBUG
- +# define DEBUG
- +#endif
- +#endif
- +
- +#include <linux/memblock.h>
- +#include <linux/err.h>
- +#include <linux/mm.h>
- +#include <linux/mutex.h>
- +#include <linux/sizes.h>
- +#include <linux/slab.h>
- +#include <linux/log2.h>
- +#include <linux/cma.h>
- +#include <linux/highmem.h>
- +
- +struct cma {
- + unsigned long base_pfn;
- + unsigned long count;
- + unsigned long *bitmap;
- + unsigned int order_per_bit; /* Order of pages represented by one bit */
- + struct mutex lock;
- +};
- +
- +static struct cma cma_areas[MAX_CMA_AREAS];
- +static unsigned cma_area_count;
- +static DEFINE_MUTEX(cma_mutex);
- +
- +phys_addr_t cma_get_base(struct cma *cma)
- +{
- + return PFN_PHYS(cma->base_pfn);
- +}
- +
- +unsigned long cma_get_size(struct cma *cma)
- +{
- + return cma->count << PAGE_SHIFT;
- +}
- +
- +static unsigned long cma_bitmap_aligned_mask(struct cma *cma, int align_order)
- +{
- + return (1UL << (align_order >> cma->order_per_bit)) - 1;
- +}
- +
- +static unsigned long cma_bitmap_maxno(struct cma *cma)
- +{
- + return cma->count >> cma->order_per_bit;
- +}
- +
- +static unsigned long cma_bitmap_pages_to_bits(struct cma *cma,
- + unsigned long pages)
- +{
- + return ALIGN(pages, 1UL << cma->order_per_bit) >> cma->order_per_bit;
- +}
- +
- +static void cma_clear_bitmap(struct cma *cma, unsigned long pfn, int count)
- +{
- + unsigned long bitmap_no, bitmap_count;
- +
- + bitmap_no = (pfn - cma->base_pfn) >> cma->order_per_bit;
- + bitmap_count = cma_bitmap_pages_to_bits(cma, count);
- +
- + mutex_lock(&cma->lock);
- + bitmap_clear(cma->bitmap, bitmap_no, bitmap_count);
- + mutex_unlock(&cma->lock);
- +}
- +
- +static int __init cma_activate_area(struct cma *cma)
- +{
- + int bitmap_size = BITS_TO_LONGS(cma_bitmap_maxno(cma)) * sizeof(long);
- + unsigned long base_pfn = cma->base_pfn, pfn = base_pfn;
- + unsigned i = cma->count >> pageblock_order;
- + struct zone *zone;
- +
- + cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
- +
- + if (!cma->bitmap)
- + return -ENOMEM;
- +
- + WARN_ON_ONCE(!pfn_valid(pfn));
- + zone = page_zone(pfn_to_page(pfn));
- +
- + do {
- + unsigned j;
- +
- + base_pfn = pfn;
- + for (j = pageblock_nr_pages; j; --j, pfn++) {
- + WARN_ON_ONCE(!pfn_valid(pfn));
- + /*
- + * alloc_contig_range requires the pfn range
- + * specified to be in the same zone. Make this
- + * simple by forcing the entire CMA resv range
- + * to be in the same zone.
- + */
- + if (page_zone(pfn_to_page(pfn)) != zone)
- + goto err;
- + }
- + init_cma_reserved_pageblock(pfn_to_page(base_pfn));
- + } while (--i);
- +
- + mutex_init(&cma->lock);
- + return 0;
- +
- +err:
- + kfree(cma->bitmap);
- + return -EINVAL;
- +}
- +
- +static int __init cma_init_reserved_areas(void)
- +{
- + int i;
- +
- + for (i = 0; i < cma_area_count; i++) {
- + int ret = cma_activate_area(&cma_areas[i]);
- +
- + if (ret)
- + return ret;
- + }
- +
- + return 0;
- +}
- +core_initcall(cma_init_reserved_areas);
- +
- +/**
- + * cma_declare_contiguous() - reserve custom contiguous area
- + * @base: Base address of the reserved area optional, use 0 for any
- + * @size: Size of the reserved area (in bytes),
- + * @limit: End address of the reserved memory (optional, 0 for any).
- + * @alignment: Alignment for the CMA area, should be power of 2 or zero
- + * @order_per_bit: Order of pages represented by one bit on bitmap.
- + * @fixed: hint about where to place the reserved area
- + * @res_cma: Pointer to store the created cma region.
- + *
- + * This function reserves memory from early allocator. It should be
- + * called by arch specific code once the early allocator (memblock or bootmem)
- + * has been activated and all other subsystems have already allocated/reserved
- + * memory. This function allows to create custom reserved areas.
- + *
- + * If @fixed is true, reserve contiguous area at exactly @base. If false,
- + * reserve in range from @base to @limit.
- + */
- +int __init cma_declare_contiguous(phys_addr_t base,
- + phys_addr_t size, phys_addr_t limit,
- + phys_addr_t alignment, unsigned int order_per_bit,
- + bool fixed, struct cma **res_cma)
- +{
- + struct cma *cma;
- + phys_addr_t memblock_end = memblock_end_of_DRAM();
- + phys_addr_t highmem_start = __pa(high_memory);
- + int ret = 0;
- +
- + pr_debug("%s(size %lx, base %08lx, limit %08lx alignment %08lx)\n",
- + __func__, (unsigned long)size, (unsigned long)base,
- + (unsigned long)limit, (unsigned long)alignment);
- +
- + if (cma_area_count == ARRAY_SIZE(cma_areas)) {
- + pr_err("Not enough slots for CMA reserved regions!\n");
- + return -ENOSPC;
- + }
- +
- + if (!size)
- + return -EINVAL;
- +
- + if (alignment && !is_power_of_2(alignment))
- + return -EINVAL;
- +
- + /*
- + * Sanitise input arguments.
- + * Pages both ends in CMA area could be merged into adjacent unmovable
- + * migratetype page by page allocator's buddy algorithm. In the case,
- + * you couldn't get a contiguous memory, which is not what we want.
- + */
- + alignment = max(alignment,
- + (phys_addr_t)PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order));
- + base = ALIGN(base, alignment);
- + size = ALIGN(size, alignment);
- + limit &= ~(alignment - 1);
- +
- + /* size should be aligned with order_per_bit */
- + if (!IS_ALIGNED(size >> PAGE_SHIFT, 1 << order_per_bit))
- + return -EINVAL;
- +
- + /*
- + * adjust limit to avoid crossing low/high memory boundary for
- + * automatically allocated regions
- + */
- + if (((limit == 0 || limit > memblock_end) &&
- + (memblock_end - size < highmem_start &&
- + memblock_end > highmem_start)) ||
- + (!fixed && limit > highmem_start && limit - size < highmem_start)) {
- + limit = highmem_start;
- + }
- +
- + if (fixed && base < highmem_start && base+size > highmem_start) {
- + ret = -EINVAL;
- + pr_err("Region at %08lx defined on low/high memory boundary (%08lx)\n",
- + (unsigned long)base, (unsigned long)highmem_start);
- + goto err;
- + }
- +
- + /* Reserve memory */
- + if (base && fixed) {
- + if (memblock_is_region_reserved(base, size) ||
- + memblock_reserve(base, size) < 0) {
- + ret = -EBUSY;
- + goto err;
- + }
- + } else {
- + phys_addr_t addr = memblock_alloc_range(size, alignment, base,
- + limit);
- + if (!addr) {
- + ret = -ENOMEM;
- + goto err;
- + } else {
- + base = addr;
- + }
- + }
- +
- + /*
- + * Each reserved area must be initialised later, when more kernel
- + * subsystems (like slab allocator) are available.
- + */
- + cma = &cma_areas[cma_area_count];
- + cma->base_pfn = PFN_DOWN(base);
- + cma->count = size >> PAGE_SHIFT;
- + cma->order_per_bit = order_per_bit;
- + *res_cma = cma;
- + cma_area_count++;
- +
- + pr_info("CMA: reserved %ld MiB at %08lx\n", (unsigned long)size / SZ_1M,
- + (unsigned long)base);
- + return 0;
- +
- +err:
- + pr_err("CMA: failed to reserve %ld MiB\n", (unsigned long)size / SZ_1M);
- + return ret;
- +}
- +
- +/**
- + * cma_alloc() - allocate pages from contiguous area
- + * @cma: Contiguous memory region for which the allocation is performed.
- + * @count: Requested number of pages.
- + * @align: Requested alignment of pages (in PAGE_SIZE order).
- + *
- + * This function allocates part of contiguous memory on specific
- + * contiguous memory area.
- + */
- +struct page *cma_alloc(struct cma *cma, int count, unsigned int align)
- +{
- + unsigned long mask, pfn, start = 0;
- + unsigned long bitmap_maxno, bitmap_no, bitmap_count;
- + struct page *page = NULL;
- + int ret;
- +
- + if (!cma || !cma->count)
- + return NULL;
- +
- + pr_debug("%s(cma %p, count %d, align %d)\n", __func__, (void *)cma,
- + count, align);
- +
- + if (!count)
- + return NULL;
- +
- + mask = cma_bitmap_aligned_mask(cma, align);
- + bitmap_maxno = cma_bitmap_maxno(cma);
- + bitmap_count = cma_bitmap_pages_to_bits(cma, count);
- +
- + for (;;) {
- + mutex_lock(&cma->lock);
- + bitmap_no = bitmap_find_next_zero_area(cma->bitmap,
- + bitmap_maxno, start, bitmap_count, mask);
- + if (bitmap_no >= bitmap_maxno) {
- + mutex_unlock(&cma->lock);
- + break;
- + }
- + bitmap_set(cma->bitmap, bitmap_no, bitmap_count);
- + /*
- + * It's safe to drop the lock here. We've marked this region for
- + * our exclusive use. If the migration fails we will take the
- + * lock again and unmark it.
- + */
- + mutex_unlock(&cma->lock);
- +
- + pfn = cma->base_pfn + (bitmap_no << cma->order_per_bit);
- + mutex_lock(&cma_mutex);
- + ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA);
- + mutex_unlock(&cma_mutex);
- + if (ret == 0) {
- + page = pfn_to_page(pfn);
- + break;
- + }
- +
- + cma_clear_bitmap(cma, pfn, count);
- + if (ret != -EBUSY)
- + break;
- +
- + pr_debug("%s(): memory range at %p is busy, retrying\n",
- + __func__, pfn_to_page(pfn));
- + /* try again with a bit different memory target */
- + start = bitmap_no + mask + 1;
- + }
- +
- + pr_debug("%s(): returned %p\n", __func__, page);
- + return page;
- +}
- +
- +/**
- + * cma_release() - release allocated pages
- + * @cma: Contiguous memory region for which the allocation is performed.
- + * @pages: Allocated pages.
- + * @count: Number of allocated pages.
- + *
- + * This function releases memory allocated by alloc_cma().
- + * It returns false when provided pages do not belong to contiguous area and
- + * true otherwise.
- + */
- +bool cma_release(struct cma *cma, struct page *pages, int count)
- +{
- + unsigned long pfn;
- +
- + if (!cma || !pages)
- + return false;
- +
- + pr_debug("%s(page %p)\n", __func__, (void *)pages);
- +
- + pfn = page_to_pfn(pages);
- +
- + if (pfn < cma->base_pfn || pfn >= cma->base_pfn + cma->count)
- + return false;
- +
- + VM_BUG_ON(pfn + count > cma->base_pfn + cma->count);
- +
- + free_contig_range(pfn, count);
- + cma_clear_bitmap(cma, pfn, count);
- +
- + return true;
- +}
- diff -Nur linux-3.14.35.orig/mm/Kconfig linux-3.14.35/mm/Kconfig
- --- linux-3.14.35.orig/mm/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/mm/Kconfig 2015-03-08 14:27:37.901684498 -0500
- @@ -514,6 +514,17 @@
- processing calls such as dma_alloc_from_contiguous().
- This option does not affect warning and error messages.
-
- +config CMA_AREAS
- + int "Maximum count of the CMA areas"
- + depends on CMA
- + default 7
- + help
- + CMA allows to create CMA areas for particular purpose, mainly,
- + used as device private area. This parameter sets the maximum
- + number of CMA area in the system.
- +
- + If unsure, leave the default value "7".
- +
- config ZBUD
- tristate
- default n
- diff -Nur linux-3.14.35.orig/mm/Makefile linux-3.14.35/mm/Makefile
- --- linux-3.14.35.orig/mm/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/mm/Makefile 2015-03-08 14:27:37.901684498 -0500
- @@ -61,3 +61,4 @@
- obj-$(CONFIG_MEMORY_ISOLATION) += page_isolation.o
- obj-$(CONFIG_ZBUD) += zbud.o
- obj-$(CONFIG_ZSMALLOC) += zsmalloc.o
- +obj-$(CONFIG_CMA) += cma.o
- diff -Nur linux-3.14.35.orig/mm/memblock.c linux-3.14.35/mm/memblock.c
- --- linux-3.14.35.orig/mm/memblock.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/mm/memblock.c 2015-03-08 14:27:37.901684498 -0500
- @@ -974,22 +974,35 @@
- }
- #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
-
- -static phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,
- - phys_addr_t align, phys_addr_t max_addr,
- - int nid)
- +static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,
- + phys_addr_t align, phys_addr_t start,
- + phys_addr_t end, int nid)
- {
- phys_addr_t found;
-
- if (!align)
- align = SMP_CACHE_BYTES;
-
- - found = memblock_find_in_range_node(size, align, 0, max_addr, nid);
- + found = memblock_find_in_range_node(size, align, start, end, nid);
- if (found && !memblock_reserve(found, size))
- return found;
-
- return 0;
- }
-
- +phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align,
- + phys_addr_t start, phys_addr_t end)
- +{
- + return memblock_alloc_range_nid(size, align, start, end, NUMA_NO_NODE);
- +}
- +
- +static phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,
- + phys_addr_t align, phys_addr_t max_addr,
- + int nid)
- +{
- + return memblock_alloc_range_nid(size, align, 0, max_addr, nid);
- +}
- +
- phys_addr_t __init memblock_alloc_nid(phys_addr_t size, phys_addr_t align, int nid)
- {
- return memblock_alloc_base_nid(size, align, MEMBLOCK_ALLOC_ACCESSIBLE, nid);
- diff -Nur linux-3.14.35.orig/net/atm/svc.c linux-3.14.35/net/atm/svc.c
- --- linux-3.14.35.orig/net/atm/svc.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/net/atm/svc.c 2015-03-08 14:27:37.901684498 -0500
- @@ -263,17 +263,11 @@
- goto out;
- }
- }
- -/*
- - * Not supported yet
- - *
- - * #ifndef CONFIG_SINGLE_SIGITF
- - */
- +
- vcc->qos.txtp.max_pcr = SELECT_TOP_PCR(vcc->qos.txtp);
- vcc->qos.txtp.pcr = 0;
- vcc->qos.txtp.min_pcr = 0;
- -/*
- - * #endif
- - */
- +
- error = vcc_connect(sock, vcc->itf, vcc->vpi, vcc->vci);
- if (!error)
- sock->state = SS_CONNECTED;
- diff -Nur linux-3.14.35.orig/net/core/dev.c linux-3.14.35/net/core/dev.c
- --- linux-3.14.35.orig/net/core/dev.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/net/core/dev.c 2015-03-08 14:27:37.905684498 -0500
- @@ -3457,7 +3457,7 @@
- * @rx_handler: receive handler to register
- * @rx_handler_data: data pointer that is used by rx handler
- *
- - * Register a receive hander for a device. This handler will then be
- + * Register a receive handler for a device. This handler will then be
- * called from __netif_receive_skb. A negative errno code is returned
- * on a failure.
- *
- diff -Nur linux-3.14.35.orig/net/core/Makefile linux-3.14.35/net/core/Makefile
- --- linux-3.14.35.orig/net/core/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/net/core/Makefile 2015-03-08 14:27:37.905684498 -0500
- @@ -9,7 +9,7 @@
-
- obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \
- neighbour.o rtnetlink.o utils.o link_watch.o filter.o \
- - sock_diag.o dev_ioctl.o
- + sock_diag.o dev_ioctl.o tso.o
-
- obj-$(CONFIG_XFRM) += flow.o
- obj-y += net-sysfs.o
- diff -Nur linux-3.14.35.orig/net/core/rtnetlink.c linux-3.14.35/net/core/rtnetlink.c
- --- linux-3.14.35.orig/net/core/rtnetlink.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/net/core/rtnetlink.c 2015-03-08 14:27:37.905684498 -0500
- @@ -1157,73 +1157,7 @@
- return -EMSGSIZE;
- }
-
- -static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
- -{
- - struct net *net = sock_net(skb->sk);
- - int h, s_h;
- - int idx = 0, s_idx;
- - struct net_device *dev;
- - struct hlist_head *head;
- - struct nlattr *tb[IFLA_MAX+1];
- - u32 ext_filter_mask = 0;
- - int err;
- - int hdrlen;
- -
- - s_h = cb->args[0];
- - s_idx = cb->args[1];
- -
- - rcu_read_lock();
- - cb->seq = net->dev_base_seq;
- -
- - /* A hack to preserve kernel<->userspace interface.
- - * The correct header is ifinfomsg. It is consistent with rtnl_getlink.
- - * However, before Linux v3.9 the code here assumed rtgenmsg and that's
- - * what iproute2 < v3.9.0 used.
- - * We can detect the old iproute2. Even including the IFLA_EXT_MASK
- - * attribute, its netlink message is shorter than struct ifinfomsg.
- - */
- - hdrlen = nlmsg_len(cb->nlh) < sizeof(struct ifinfomsg) ?
- - sizeof(struct rtgenmsg) : sizeof(struct ifinfomsg);
- -
- - if (nlmsg_parse(cb->nlh, hdrlen, tb, IFLA_MAX, ifla_policy) >= 0) {
- -
- - if (tb[IFLA_EXT_MASK])
- - ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
- - }
- -
- - for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
- - idx = 0;
- - head = &net->dev_index_head[h];
- - hlist_for_each_entry_rcu(dev, head, index_hlist) {
- - if (idx < s_idx)
- - goto cont;
- - err = rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
- - NETLINK_CB(cb->skb).portid,
- - cb->nlh->nlmsg_seq, 0,
- - NLM_F_MULTI,
- - ext_filter_mask);
- - /* If we ran out of room on the first message,
- - * we're in trouble
- - */
- - WARN_ON((err == -EMSGSIZE) && (skb->len == 0));
- -
- - if (err <= 0)
- - goto out;
- -
- - nl_dump_check_consistent(cb, nlmsg_hdr(skb));
- -cont:
- - idx++;
- - }
- - }
- -out:
- - rcu_read_unlock();
- - cb->args[1] = idx;
- - cb->args[0] = h;
- -
- - return skb->len;
- -}
- -
- -const struct nla_policy ifla_policy[IFLA_MAX+1] = {
- +static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
- [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 },
- [IFLA_ADDRESS] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
- [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
- @@ -1250,7 +1184,6 @@
- [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 },
- [IFLA_PHYS_PORT_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_PORT_ID_LEN },
- };
- -EXPORT_SYMBOL(ifla_policy);
-
- static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
- [IFLA_INFO_KIND] = { .type = NLA_STRING },
- @@ -1288,6 +1221,61 @@
- [IFLA_PORT_RESPONSE] = { .type = NLA_U16, },
- };
-
- +static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
- +{
- + struct net *net = sock_net(skb->sk);
- + int h, s_h;
- + int idx = 0, s_idx;
- + struct net_device *dev;
- + struct hlist_head *head;
- + struct nlattr *tb[IFLA_MAX+1];
- + u32 ext_filter_mask = 0;
- +
- + s_h = cb->args[0];
- + s_idx = cb->args[1];
- +
- + rcu_read_lock();
- + cb->seq = net->dev_base_seq;
- +
- + if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
- + ifla_policy) >= 0) {
- +
- + if (tb[IFLA_EXT_MASK])
- + ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
- + }
- +
- + for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
- + idx = 0;
- + head = &net->dev_index_head[h];
- + hlist_for_each_entry_rcu(dev, head, index_hlist) {
- + if (idx < s_idx)
- + goto cont;
- + if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
- + NETLINK_CB(cb->skb).portid,
- + cb->nlh->nlmsg_seq, 0,
- + NLM_F_MULTI,
- + ext_filter_mask) <= 0)
- + goto out;
- +
- + nl_dump_check_consistent(cb, nlmsg_hdr(skb));
- +cont:
- + idx++;
- + }
- + }
- +out:
- + rcu_read_unlock();
- + cb->args[1] = idx;
- + cb->args[0] = h;
- +
- + return skb->len;
- +}
- +
- +int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len)
- +{
- + return nla_parse(tb, IFLA_MAX, head, len, ifla_policy);
- +}
- +EXPORT_SYMBOL(rtnl_nla_parse_ifla);
- +
- struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
- {
- struct net *net;
- diff -Nur linux-3.14.35.orig/net/core/tso.c linux-3.14.35/net/core/tso.c
- --- linux-3.14.35.orig/net/core/tso.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/net/core/tso.c 2015-03-08 14:27:37.905684498 -0500
- @@ -0,0 +1,72 @@
- +#include <net/ip.h>
- +#include <net/tso.h>
- +
- +/* Calculate expected number of TX descriptors */
- +int tso_count_descs(struct sk_buff *skb)
- +{
- + /* The Marvell Way */
- + return skb_shinfo(skb)->gso_segs * 2 + skb_shinfo(skb)->nr_frags;
- +}
- +
- +void tso_build_hdr(struct sk_buff *skb, char *hdr, struct tso_t *tso,
- + int size, bool is_last)
- +{
- + struct iphdr *iph;
- + struct tcphdr *tcph;
- + int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
- + int mac_hdr_len = skb_network_offset(skb);
- +
- + memcpy(hdr, skb->data, hdr_len);
- + iph = (struct iphdr *)(hdr + mac_hdr_len);
- + iph->id = htons(tso->ip_id);
- + iph->tot_len = htons(size + hdr_len - mac_hdr_len);
- + tcph = (struct tcphdr *)(hdr + skb_transport_offset(skb));
- + tcph->seq = htonl(tso->tcp_seq);
- + tso->ip_id++;
- +
- + if (!is_last) {
- + /* Clear all special flags for not last packet */
- + tcph->psh = 0;
- + tcph->fin = 0;
- + tcph->rst = 0;
- + }
- +}
- +
- +void tso_build_data(struct sk_buff *skb, struct tso_t *tso, int size)
- +{
- + tso->tcp_seq += size;
- + tso->size -= size;
- + tso->data += size;
- +
- + if ((tso->size == 0) &&
- + (tso->next_frag_idx < skb_shinfo(skb)->nr_frags)) {
- + skb_frag_t *frag = &skb_shinfo(skb)->frags[tso->next_frag_idx];
- +
- + /* Move to next segment */
- + tso->size = frag->size;
- + tso->data = page_address(frag->page.p) + frag->page_offset;
- + tso->next_frag_idx++;
- + }
- +}
- +
- +void tso_start(struct sk_buff *skb, struct tso_t *tso)
- +{
- + int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
- +
- + tso->ip_id = ntohs(ip_hdr(skb)->id);
- + tso->tcp_seq = ntohl(tcp_hdr(skb)->seq);
- + tso->next_frag_idx = 0;
- +
- + /* Build first data */
- + tso->size = skb_headlen(skb) - hdr_len;
- + tso->data = skb->data + hdr_len;
- + if ((tso->size == 0) &&
- + (tso->next_frag_idx < skb_shinfo(skb)->nr_frags)) {
- + skb_frag_t *frag = &skb_shinfo(skb)->frags[tso->next_frag_idx];
- +
- + /* Move to next segment */
- + tso->size = frag->size;
- + tso->data = page_address(frag->page.p) + frag->page_offset;
- + tso->next_frag_idx++;
- + }
- +}
- diff -Nur linux-3.14.35.orig/net/ieee802154/Kconfig linux-3.14.35/net/ieee802154/Kconfig
- --- linux-3.14.35.orig/net/ieee802154/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/net/ieee802154/Kconfig 2015-03-08 14:27:37.905684498 -0500
- @@ -15,7 +15,7 @@
- depends on IEEE802154 && IPV6
- select 6LOWPAN_IPHC
- ---help---
- - IPv6 compression over IEEE 802.15.4.
- + IPv6 compression over IEEE 802.15.4.
-
- config 6LOWPAN_IPHC
- tristate
- diff -Nur linux-3.14.35.orig/net/mac80211/driver-ops.h linux-3.14.35/net/mac80211/driver-ops.h
- --- linux-3.14.35.orig/net/mac80211/driver-ops.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/net/mac80211/driver-ops.h 2015-03-08 14:27:37.905684498 -0500
- @@ -722,13 +722,19 @@
- }
-
- static inline void drv_flush(struct ieee80211_local *local,
- + struct ieee80211_sub_if_data *sdata,
- u32 queues, bool drop)
- {
- + struct ieee80211_vif *vif = sdata ? &sdata->vif : NULL;
- +
- might_sleep();
-
- + if (sdata)
- + check_sdata_in_driver(sdata);
- +
- trace_drv_flush(local, queues, drop);
- if (local->ops->flush)
- - local->ops->flush(&local->hw, queues, drop);
- + local->ops->flush(&local->hw, vif, queues, drop);
- trace_drv_return_void(local);
- }
-
- diff -Nur linux-3.14.35.orig/net/mac80211/ibss.c linux-3.14.35/net/mac80211/ibss.c
- --- linux-3.14.35.orig/net/mac80211/ibss.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/net/mac80211/ibss.c 2015-03-08 14:27:37.905684498 -0500
- @@ -386,7 +386,7 @@
- presp->head_len, 0, GFP_KERNEL);
- cfg80211_put_bss(local->hw.wiphy, bss);
- netif_carrier_on(sdata->dev);
- - cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
- + cfg80211_ibss_joined(sdata->dev, ifibss->bssid, chan, GFP_KERNEL);
- }
-
- static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
- diff -Nur linux-3.14.35.orig/net/mac80211/util.c linux-3.14.35/net/mac80211/util.c
- --- linux-3.14.35.orig/net/mac80211/util.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/net/mac80211/util.c 2015-03-08 14:27:37.905684498 -0500
- @@ -554,7 +554,7 @@
- ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
- IEEE80211_QUEUE_STOP_REASON_FLUSH);
-
- - drv_flush(local, queues, false);
- + drv_flush(local, sdata, queues, false);
-
- ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
- IEEE80211_QUEUE_STOP_REASON_FLUSH);
- diff -Nur linux-3.14.35.orig/net/wireless/core.h linux-3.14.35/net/wireless/core.h
- --- linux-3.14.35.orig/net/wireless/core.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/net/wireless/core.h 2015-03-08 14:27:37.909684498 -0500
- @@ -211,6 +211,7 @@
- } dc;
- struct {
- u8 bssid[ETH_ALEN];
- + struct ieee80211_channel *channel;
- } ij;
- };
- };
- @@ -258,7 +259,8 @@
- struct net_device *dev, bool nowext);
- int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
- struct net_device *dev, bool nowext);
- -void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid);
- +void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
- + struct ieee80211_channel *channel);
- int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev);
-
- diff -Nur linux-3.14.35.orig/net/wireless/ibss.c linux-3.14.35/net/wireless/ibss.c
- --- linux-3.14.35.orig/net/wireless/ibss.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/net/wireless/ibss.c 2015-03-08 14:27:37.909684498 -0500
- @@ -14,7 +14,8 @@
- #include "rdev-ops.h"
-
-
- -void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
- +void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
- + struct ieee80211_channel *channel)
- {
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct cfg80211_bss *bss;
- @@ -28,8 +29,7 @@
- if (!wdev->ssid_len)
- return;
-
- - bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
- - wdev->ssid, wdev->ssid_len,
- + bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0,
- WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
-
- if (WARN_ON(!bss))
- @@ -54,21 +54,26 @@
- #endif
- }
-
- -void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
- +void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
- + struct ieee80211_channel *channel, gfp_t gfp)
- {
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
- struct cfg80211_event *ev;
- unsigned long flags;
-
- - trace_cfg80211_ibss_joined(dev, bssid);
- + trace_cfg80211_ibss_joined(dev, bssid, channel);
- +
- + if (WARN_ON(!channel))
- + return;
-
- ev = kzalloc(sizeof(*ev), gfp);
- if (!ev)
- return;
-
- ev->type = EVENT_IBSS_JOINED;
- - memcpy(ev->cr.bssid, bssid, ETH_ALEN);
- + memcpy(ev->ij.bssid, bssid, ETH_ALEN);
- + ev->ij.channel = channel;
-
- spin_lock_irqsave(&wdev->event_lock, flags);
- list_add_tail(&ev->list, &wdev->event_list);
- diff -Nur linux-3.14.35.orig/net/wireless/trace.h linux-3.14.35/net/wireless/trace.h
- --- linux-3.14.35.orig/net/wireless/trace.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/net/wireless/trace.h 2015-03-08 14:27:37.909684498 -0500
- @@ -2279,11 +2279,6 @@
- TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr))
- );
-
- -DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined,
- - TP_PROTO(struct net_device *netdev, const u8 *addr),
- - TP_ARGS(netdev, addr)
- -);
- -
- DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame,
- TP_PROTO(struct net_device *netdev, const u8 *addr),
- TP_ARGS(netdev, addr)
- @@ -2294,6 +2289,24 @@
- TP_ARGS(netdev, addr)
- );
-
- +TRACE_EVENT(cfg80211_ibss_joined,
- + TP_PROTO(struct net_device *netdev, const u8 *bssid,
- + struct ieee80211_channel *channel),
- + TP_ARGS(netdev, bssid, channel),
- + TP_STRUCT__entry(
- + NETDEV_ENTRY
- + MAC_ENTRY(bssid)
- + CHAN_ENTRY
- + ),
- + TP_fast_assign(
- + NETDEV_ASSIGN;
- + MAC_ASSIGN(bssid, bssid);
- + CHAN_ASSIGN(channel);
- + ),
- + TP_printk(NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", " CHAN_PR_FMT,
- + NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG)
- +);
- +
- TRACE_EVENT(cfg80211_probe_status,
- TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie,
- bool acked),
- diff -Nur linux-3.14.35.orig/net/wireless/util.c linux-3.14.35/net/wireless/util.c
- --- linux-3.14.35.orig/net/wireless/util.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/net/wireless/util.c 2015-03-08 14:27:37.909684498 -0500
- @@ -820,7 +820,8 @@
- ev->dc.reason, true);
- break;
- case EVENT_IBSS_JOINED:
- - __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid);
- + __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid,
- + ev->ij.channel);
- break;
- }
- wdev_unlock(wdev);
- diff -Nur linux-3.14.35.orig/scripts/Makefile.lib linux-3.14.35/scripts/Makefile.lib
- --- linux-3.14.35.orig/scripts/Makefile.lib 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/scripts/Makefile.lib 2015-03-08 14:27:37.909684498 -0500
- @@ -153,6 +153,7 @@
- -I$(srctree)/arch/$(SRCARCH)/boot/dts \
- -I$(srctree)/arch/$(SRCARCH)/boot/dts/include \
- -I$(srctree)/drivers/of/testcase-data \
- + -I$(srctree)/include \
- -undef -D__DTS__
-
- # Finds the multi-part object the current object will be linked into
- diff -Nur linux-3.14.35.orig/scripts/mod/devicetable-offsets.c linux-3.14.35/scripts/mod/devicetable-offsets.c
- --- linux-3.14.35.orig/scripts/mod/devicetable-offsets.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/scripts/mod/devicetable-offsets.c 2015-03-08 14:27:37.909684498 -0500
- @@ -174,6 +174,9 @@
- DEVID_FIELD(x86_cpu_id, model);
- DEVID_FIELD(x86_cpu_id, vendor);
-
- + DEVID(cpu_feature);
- + DEVID_FIELD(cpu_feature, feature);
- +
- DEVID(mei_cl_device_id);
- DEVID_FIELD(mei_cl_device_id, name);
-
- diff -Nur linux-3.14.35.orig/scripts/mod/file2alias.c linux-3.14.35/scripts/mod/file2alias.c
- --- linux-3.14.35.orig/scripts/mod/file2alias.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/scripts/mod/file2alias.c 2015-03-08 14:27:37.909684498 -0500
- @@ -1135,6 +1135,16 @@
- }
- ADD_TO_DEVTABLE("x86cpu", x86_cpu_id, do_x86cpu_entry);
-
- +/* LOOKS like cpu:type:*:feature:*FEAT* */
- +static int do_cpu_entry(const char *filename, void *symval, char *alias)
- +{
- + DEF_FIELD(symval, cpu_feature, feature);
- +
- + sprintf(alias, "cpu:type:*:feature:*%04X*", feature);
- + return 1;
- +}
- +ADD_TO_DEVTABLE("cpu", cpu_feature, do_cpu_entry);
- +
- /* Looks like: mei:S */
- static int do_mei_entry(const char *filename, void *symval,
- char *alias)
- diff -Nur linux-3.14.35.orig/scripts/recordmcount.c linux-3.14.35/scripts/recordmcount.c
- --- linux-3.14.35.orig/scripts/recordmcount.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/scripts/recordmcount.c 2015-03-08 14:27:37.909684498 -0500
- @@ -40,6 +40,11 @@
- #define R_METAG_NONE 3
- #endif
-
- +#ifndef EM_AARCH64
- +#define EM_AARCH64 183
- +#define R_AARCH64_ABS64 257
- +#endif
- +
- static int fd_map; /* File descriptor for file being modified. */
- static int mmap_failed; /* Boolean flag. */
- static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */
- @@ -347,6 +352,8 @@
- case EM_ARM: reltype = R_ARM_ABS32;
- altmcount = "__gnu_mcount_nc";
- break;
- + case EM_AARCH64:
- + reltype = R_AARCH64_ABS64; gpfx = '_'; break;
- case EM_IA_64: reltype = R_IA64_IMM64; gpfx = '_'; break;
- case EM_METAG: reltype = R_METAG_ADDR32;
- altmcount = "_mcount_wrapper";
- diff -Nur linux-3.14.35.orig/scripts/recordmcount.pl linux-3.14.35/scripts/recordmcount.pl
- --- linux-3.14.35.orig/scripts/recordmcount.pl 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/scripts/recordmcount.pl 2015-03-08 14:27:37.909684498 -0500
- @@ -278,6 +278,11 @@
- $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
- "\\s+(__gnu_mcount_nc|mcount)\$";
-
- +} elsif ($arch eq "arm64") {
- + $alignment = 3;
- + $section_type = '%progbits';
- + $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
- + $type = ".quad";
- } elsif ($arch eq "ia64") {
- $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
- $type = "data8";
- diff -Nur linux-3.14.35.orig/sound/soc/codecs/cs42888.c linux-3.14.35/sound/soc/codecs/cs42888.c
- --- linux-3.14.35.orig/sound/soc/codecs/cs42888.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/sound/soc/codecs/cs42888.c 2015-03-08 14:27:37.909684498 -0500
- @@ -0,0 +1,934 @@
- +/*
- + * cs42888.c -- CS42888 ALSA SoC Audio Driver
- + * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#include <linux/module.h>
- +#include <linux/moduleparam.h>
- +#include <linux/kernel.h>
- +#include <linux/init.h>
- +#include <linux/clk.h>
- +#include <linux/delay.h>
- +#include <linux/pm.h>
- +#include <linux/i2c.h>
- +#include <linux/spi/spi.h>
- +#include <linux/platform_device.h>
- +#include <linux/regulator/consumer.h>
- +
- +#include <sound/core.h>
- +#include <sound/pcm.h>
- +#include <sound/pcm_params.h>
- +#include <sound/soc.h>
- +#include <sound/soc-dapm.h>
- +#include <sound/tlv.h>
- +#include <sound/initval.h>
- +#include <asm/div64.h>
- +#include "cs42888.h"
- +
- +#define CS42888_NUM_SUPPLIES 4
- +static const char *cs42888_supply_names[CS42888_NUM_SUPPLIES] = {
- + "VA",
- + "VD",
- + "VLS",
- + "VLC",
- +};
- +
- +#define CS42888_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
- + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
- +
- +/* Private data for the CS42888 */
- +struct cs42888_private {
- + struct clk *clk;
- + struct snd_soc_codec *codec;
- + u8 reg_cache[CS42888_NUMREGS + 1];
- + unsigned int mclk; /* Input frequency of the MCLK pin */
- + unsigned int slave_mode;
- + struct regulator_bulk_data supplies[CS42888_NUM_SUPPLIES];
- +};
- +
- +/**
- + * cs42888_fill_cache - pre-fill the CS42888 register cache.
- + * @codec: the codec for this CS42888
- + *
- + * This function fills in the CS42888 register cache by reading the register
- + * values from the hardware.
- + *
- + * This CS42888 registers are cached to avoid excessive I2C I/O operations.
- + * After the initial read to pre-fill the cache, the CS42888 never updates
- + * the register values, so we won't have a cache coherency problem.
- + *
- + * We use the auto-increment feature of the CS42888 to read all registers in
- + * one shot.
- + */
- +static int cs42888_fill_cache(struct snd_soc_codec *codec)
- +{
- + u8 *cache = codec->reg_cache;
- + struct i2c_client *i2c_client = to_i2c_client(codec->dev);
- + s32 length;
- +
- + length = i2c_smbus_read_i2c_block_data(i2c_client,
- + CS42888_FIRSTREG | CS42888_I2C_INCR, CS42888_NUMREGS, \
- + cache + 1);
- +
- + if (length != CS42888_NUMREGS) {
- + dev_err(codec->dev, "i2c read failure, addr=0x%x\n",
- + i2c_client->addr);
- + return -EIO;
- + }
- + return 0;
- +}
- +
- +#ifdef DEBUG
- +static void dump_reg(struct snd_soc_codec *codec)
- +{
- + int i, reg;
- + int ret;
- + u8 *cache = codec->reg_cache + 1;
- +
- + dev_dbg(codec->dev, "dump begin\n");
- + dev_dbg(codec->dev, "reg value in cache\n");
- + for (i = 0; i < CS42888_NUMREGS; i++)
- + dev_dbg(codec->dev, "reg[%d] = 0x%x\n", i, cache[i]);
- +
- + dev_dbg(codec->dev, "real reg value\n");
- + ret = cs42888_fill_cache(codec);
- + if (ret < 0) {
- + dev_err(codec->dev, "failed to fill register cache\n");
- + return ret;
- + }
- + for (i = 0; i < CS42888_NUMREGS; i++)
- + dev_dbg(codec->dev, "reg[%d] = 0x%x\n", i, cache[i]);
- +
- + dev_dbg(codec->dev, "dump end\n");
- +}
- +#else
- +static void dump_reg(struct snd_soc_codec *codec)
- +{
- +}
- +#endif
- +
- +/* -127.5dB to 0dB with step of 0.5dB */
- +static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
- +/* -64dB to 24dB with step of 0.5dB */
- +static const DECLARE_TLV_DB_SCALE(adc_tlv, -6400, 50, 1);
- +
- +static int cs42888_out_vu(struct snd_kcontrol *kcontrol,
- + struct snd_ctl_elem_value *ucontrol)
- +{
- + return snd_soc_put_volsw_2r(kcontrol, ucontrol);
- +}
- +
- +static int cs42888_info_volsw_s8(struct snd_kcontrol *kcontrol,
- + struct snd_ctl_elem_info *uinfo)
- +{
- + struct soc_mixer_control *mc =
- + (struct soc_mixer_control *)kcontrol->private_value;
- +
- + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- + uinfo->count = 2;
- + uinfo->value.integer.min = 0;
- + uinfo->value.integer.max = mc->max - mc->min;
- + return 0;
- +}
- +
- +static int cs42888_get_volsw_s8(struct snd_kcontrol *kcontrol,
- + struct snd_ctl_elem_value *ucontrol)
- +{
- + struct soc_mixer_control *mc =
- + (struct soc_mixer_control *)kcontrol->private_value;
- + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- + s8 val = snd_soc_read(codec, mc->reg);
- + ucontrol->value.integer.value[0] = val - mc->min;
- +
- + val = snd_soc_read(codec, mc->rreg);
- + ucontrol->value.integer.value[1] = val - mc->min;
- + return 0;
- +}
- +
- +int cs42888_put_volsw_s8(struct snd_kcontrol *kcontrol,
- + struct snd_ctl_elem_value *ucontrol)
- +{
- + struct soc_mixer_control *mc =
- + (struct soc_mixer_control *)kcontrol->private_value;
- + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- + unsigned short val;
- + int ret;
- +
- + val = ucontrol->value.integer.value[0] + mc->min;
- + ret = snd_soc_write(codec, mc->reg, val);
- + if (ret < 0) {
- + dev_err(codec->dev, "i2c write failed\n");
- + return ret;
- + }
- +
- + val = ucontrol->value.integer.value[1] + mc->min;
- + ret = snd_soc_write(codec, mc->rreg, val);
- + if (ret < 0) {
- + dev_err(codec->dev, "i2c write failed\n");
- + return ret;
- + }
- + return 0;
- +}
- +
- +#define SOC_CS42888_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \
- + xinvert, tlv_array) \
- +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- + .name = (xname), \
- + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
- + SNDRV_CTL_ELEM_ACCESS_READWRITE, \
- + .tlv.p = (tlv_array), \
- + .info = snd_soc_info_volsw, \
- + .get = snd_soc_get_volsw, \
- + .put = cs42888_out_vu, \
- + .private_value = (unsigned long)&(struct soc_mixer_control) \
- + {.reg = reg_left, \
- + .rreg = reg_right, \
- + .shift = xshift, \
- + .max = xmax, \
- + .invert = xinvert} \
- +}
- +
- +#define SOC_CS42888_DOUBLE_R_S8_TLV(xname, reg_left, reg_right, xmin, xmax, \
- + tlv_array) \
- +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
- + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
- + SNDRV_CTL_ELEM_ACCESS_READWRITE, \
- + .tlv.p = (tlv_array), \
- + .info = cs42888_info_volsw_s8, \
- + .get = cs42888_get_volsw_s8, \
- + .put = cs42888_put_volsw_s8, \
- + .private_value = (unsigned long)&(struct soc_mixer_control) \
- + {.reg = reg_left, \
- + .rreg = reg_right, \
- + .min = xmin, \
- + .max = xmax} \
- +}
- +
- +static const char *cs42888_adcfilter[] = { "None", "High Pass" };
- +static const char *cs42888_dacinvert[] = { "Disabled", "Enabled" };
- +static const char *cs42888_adcinvert[] = { "Disabled", "Enabled" };
- +static const char *cs42888_dacamute[] = { "Disabled", "AutoMute" };
- +static const char *cs42888_dac_sngvol[] = { "Disabled", "Enabled" };
- +static const char *cs42888_dac_szc[] = { "Immediate Change", "Zero Cross",
- + "Soft Ramp", "Soft Ramp on Zero Cross" };
- +static const char *cs42888_mute_adc[] = { "UnMute", "Mute" };
- +static const char *cs42888_adc_sngvol[] = { "Disabled", "Enabled" };
- +static const char *cs42888_adc_szc[] = { "Immediate Change", "Zero Cross",
- + "Soft Ramp", "Soft Ramp on Zero Cross" };
- +static const char *cs42888_dac_dem[] = { "No-De-Emphasis", "De-Emphasis" };
- +static const char *cs42888_adc_single[] = { "Differential", "Single-Ended" };
- +
- +static const struct soc_enum cs42888_enum[] = {
- + SOC_ENUM_SINGLE(CS42888_ADCCTL, 7, 2, cs42888_adcfilter),
- + SOC_ENUM_DOUBLE(CS42888_DACINV, 0, 1, 2, cs42888_dacinvert),
- + SOC_ENUM_DOUBLE(CS42888_DACINV, 2, 3, 2, cs42888_dacinvert),
- + SOC_ENUM_DOUBLE(CS42888_DACINV, 4, 5, 2, cs42888_dacinvert),
- + SOC_ENUM_DOUBLE(CS42888_DACINV, 6, 7, 2, cs42888_dacinvert),
- + SOC_ENUM_DOUBLE(CS42888_ADCINV, 0, 1, 2, cs42888_adcinvert),
- + SOC_ENUM_DOUBLE(CS42888_ADCINV, 2, 3, 2, cs42888_adcinvert),
- + SOC_ENUM_SINGLE(CS42888_TRANS, 4, 2, cs42888_dacamute),
- + SOC_ENUM_SINGLE(CS42888_TRANS, 7, 2, cs42888_dac_sngvol),
- + SOC_ENUM_SINGLE(CS42888_TRANS, 5, 4, cs42888_dac_szc),
- + SOC_ENUM_SINGLE(CS42888_TRANS, 3, 2, cs42888_mute_adc),
- + SOC_ENUM_SINGLE(CS42888_TRANS, 2, 2, cs42888_adc_sngvol),
- + SOC_ENUM_SINGLE(CS42888_TRANS, 0, 4, cs42888_adc_szc),
- + SOC_ENUM_SINGLE(CS42888_ADCCTL, 5, 2, cs42888_dac_dem),
- + SOC_ENUM_SINGLE(CS42888_ADCCTL, 4, 2, cs42888_adc_single),
- + SOC_ENUM_SINGLE(CS42888_ADCCTL, 3, 2, cs42888_adc_single),
- +};
- +
- +static const struct snd_kcontrol_new cs42888_snd_controls[] = {
- + SOC_CS42888_DOUBLE_R_TLV("DAC1 Playback Volume", CS42888_VOLAOUT1,
- + CS42888_VOLAOUT2, 0, 0xff, 1, dac_tlv),
- + SOC_CS42888_DOUBLE_R_TLV("DAC2 Playback Volume", CS42888_VOLAOUT3,
- + CS42888_VOLAOUT4, 0, 0xff, 1, dac_tlv),
- + SOC_CS42888_DOUBLE_R_TLV("DAC3 Playback Volume", CS42888_VOLAOUT5,
- + CS42888_VOLAOUT6, 0, 0xff, 1, dac_tlv),
- + SOC_CS42888_DOUBLE_R_TLV("DAC4 Playback Volume", CS42888_VOLAOUT7,
- + CS42888_VOLAOUT8, 0, 0xff, 1, dac_tlv),
- + SOC_CS42888_DOUBLE_R_S8_TLV("ADC1 Capture Volume", CS42888_VOLAIN1,
- + CS42888_VOLAIN2, -128, 48, adc_tlv),
- + SOC_CS42888_DOUBLE_R_S8_TLV("ADC2 Capture Volume", CS42888_VOLAIN3,
- + CS42888_VOLAIN4, -128, 48, adc_tlv),
- + SOC_ENUM("ADC High-Pass Filter Switch", cs42888_enum[0]),
- + SOC_ENUM("DAC1 Invert Switch", cs42888_enum[1]),
- + SOC_ENUM("DAC2 Invert Switch", cs42888_enum[2]),
- + SOC_ENUM("DAC3 Invert Switch", cs42888_enum[3]),
- + SOC_ENUM("DAC4 Invert Switch", cs42888_enum[4]),
- + SOC_ENUM("ADC1 Invert Switch", cs42888_enum[5]),
- + SOC_ENUM("ADC2 Invert Switch", cs42888_enum[6]),
- + SOC_ENUM("DAC Auto Mute Switch", cs42888_enum[7]),
- + SOC_ENUM("DAC Single Volume Control Switch", cs42888_enum[8]),
- + SOC_ENUM("DAC Soft Ramp and Zero Cross Control Switch", cs42888_enum[9]),
- + SOC_ENUM("Mute ADC Serial Port Switch", cs42888_enum[10]),
- + SOC_ENUM("ADC Single Volume Control Switch", cs42888_enum[11]),
- + SOC_ENUM("ADC Soft Ramp and Zero Cross Control Switch", cs42888_enum[12]),
- + SOC_ENUM("DAC Deemphasis Switch", cs42888_enum[13]),
- + SOC_ENUM("ADC1 Single Ended Mode Switch", cs42888_enum[14]),
- + SOC_ENUM("ADC2 Single Ended Mode Switch", cs42888_enum[15]),
- +};
- +
- +
- +static const struct snd_soc_dapm_widget cs42888_dapm_widgets[] = {
- + SND_SOC_DAPM_DAC("DAC1", "codec-Playback", CS42888_PWRCTL, 1, 1),
- + SND_SOC_DAPM_DAC("DAC2", "codec-Playback", CS42888_PWRCTL, 2, 1),
- + SND_SOC_DAPM_DAC("DAC3", "codec-Playback", CS42888_PWRCTL, 3, 1),
- + SND_SOC_DAPM_DAC("DAC4", "codec-Playback", CS42888_PWRCTL, 4, 1),
- +
- + SND_SOC_DAPM_OUTPUT("AOUT1L"),
- + SND_SOC_DAPM_OUTPUT("AOUT1R"),
- + SND_SOC_DAPM_OUTPUT("AOUT2L"),
- + SND_SOC_DAPM_OUTPUT("AOUT2R"),
- + SND_SOC_DAPM_OUTPUT("AOUT3L"),
- + SND_SOC_DAPM_OUTPUT("AOUT3R"),
- + SND_SOC_DAPM_OUTPUT("AOUT4L"),
- + SND_SOC_DAPM_OUTPUT("AOUT4R"),
- +
- + SND_SOC_DAPM_ADC("ADC1", "codec-Capture", CS42888_PWRCTL, 5, 1),
- + SND_SOC_DAPM_ADC("ADC2", "codec-Capture", CS42888_PWRCTL, 6, 1),
- +
- + SND_SOC_DAPM_INPUT("AIN1L"),
- + SND_SOC_DAPM_INPUT("AIN1R"),
- + SND_SOC_DAPM_INPUT("AIN2L"),
- + SND_SOC_DAPM_INPUT("AIN2R"),
- +
- + SND_SOC_DAPM_PGA_E("PWR", CS42888_PWRCTL, 0, 1, NULL, 0,
- + NULL, 0),
- +};
- +
- +static const struct snd_soc_dapm_route audio_map[] = {
- + /* Playback */
- + { "PWR", NULL, "DAC1" },
- + { "PWR", NULL, "DAC1" },
- +
- + { "PWR", NULL, "DAC2" },
- + { "PWR", NULL, "DAC2" },
- +
- + { "PWR", NULL, "DAC3" },
- + { "PWR", NULL, "DAC3" },
- +
- + { "PWR", NULL, "DAC4" },
- + { "PWR", NULL, "DAC4" },
- +
- + { "AOUT1L", NULL, "PWR" },
- + { "AOUT1R", NULL, "PWR" },
- +
- + { "AOUT2L", NULL, "PWR" },
- + { "AOUT2R", NULL, "PWR" },
- +
- + { "AOUT3L", NULL, "PWR" },
- + { "AOUT3R", NULL, "PWR" },
- +
- + { "AOUT4L", NULL, "PWR" },
- + { "AOUT4R", NULL, "PWR" },
- +
- + /* Capture */
- + { "PWR", NULL, "AIN1L" },
- + { "PWR", NULL, "AIN1R" },
- +
- + { "PWR", NULL, "AIN2L" },
- + { "PWR", NULL, "AIN2R" },
- +
- + { "ADC1", NULL, "PWR" },
- + { "ADC1", NULL, "PWR" },
- +
- + { "ADC2", NULL, "PWR" },
- + { "ADC2", NULL, "PWR" },
- +};
- +
- +
- +static int cs42888_add_widgets(struct snd_soc_codec *codec)
- +{
- + snd_soc_dapm_new_controls(&codec->dapm, cs42888_dapm_widgets,
- + ARRAY_SIZE(cs42888_dapm_widgets));
- +
- + snd_soc_dapm_add_routes(&codec->dapm, audio_map, ARRAY_SIZE(audio_map));
- +
- + snd_soc_dapm_new_widgets(&codec->dapm);
- + return 0;
- +}
- +
- +/**
- + * struct cs42888_mode_ratios - clock ratio tables
- + * @ratio: the ratio of MCLK to the sample rate
- + * @speed_mode: the Speed Mode bits to set in the Mode Control register for
- + * this ratio
- + * @mclk: the Ratio Select bits to set in the Mode Control register for this
- + * ratio
- + *
- + * The data for this chart is taken from Table 10 of the CS42888 reference
- + * manual.
- + *
- + * This table is used to determine how to program the Functional Mode register.
- + * It is also used by cs42888_set_dai_sysclk() to tell ALSA which sampling
- + * rates the CS42888 currently supports.
- + *
- + * @speed_mode is the corresponding bit pattern to be written to the
- + * MODE bits of the Mode Control Register
- + *
- + * @mclk is the corresponding bit pattern to be wirten to the MCLK bits of
- + * the Mode Control Register.
- + *
- + */
- +struct cs42888_mode_ratios {
- + unsigned int ratio;
- + u8 speed_mode;
- + u8 mclk;
- +};
- +
- +static struct cs42888_mode_ratios cs42888_mode_ratios[] = {
- + {64, CS42888_MODE_4X, CS42888_MODE_DIV1},
- + {96, CS42888_MODE_4X, CS42888_MODE_DIV2},
- + {128, CS42888_MODE_2X, CS42888_MODE_DIV1},
- + {192, CS42888_MODE_2X, CS42888_MODE_DIV2},
- + {256, CS42888_MODE_1X, CS42888_MODE_DIV1},
- + {384, CS42888_MODE_2X, CS42888_MODE_DIV4},
- + {512, CS42888_MODE_1X, CS42888_MODE_DIV3},
- + {768, CS42888_MODE_1X, CS42888_MODE_DIV4},
- + {1024, CS42888_MODE_1X, CS42888_MODE_DIV5}
- +};
- +
- +/* The number of MCLK/LRCK ratios supported by the CS42888 */
- +#define NUM_MCLK_RATIOS ARRAY_SIZE(cs42888_mode_ratios)
- +
- +/**
- + * cs42888_set_dai_sysclk - determine the CS42888 samples rates.
- + * @codec_dai: the codec DAI
- + * @clk_id: the clock ID (ignored)
- + * @freq: the MCLK input frequency
- + * @dir: the clock direction (ignored)
- + *
- + * This function is used to tell the codec driver what the input MCLK
- + * frequency is.
- + *
- + */
- +static int cs42888_set_dai_sysclk(struct snd_soc_dai *codec_dai,
- + int clk_id, unsigned int freq, int dir)
- +{
- + struct snd_soc_codec *codec = codec_dai->codec;
- + struct cs42888_private *cs42888 = snd_soc_codec_get_drvdata(codec);
- +
- + cs42888->mclk = freq;
- + return 0;
- +}
- +
- +/**
- + * cs42888_set_dai_fmt - configure the codec for the selected audio format
- + * @codec_dai: the codec DAI
- + * @format: a SND_SOC_DAIFMT_x value indicating the data format
- + *
- + * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the
- + * codec accordingly.
- + *
- + * Currently, this function only supports SND_SOC_DAIFMT_I2S and
- + * SND_SOC_DAIFMT_LEFT_J. The CS42888 codec also supports right-justified
- + * data for playback only, but ASoC currently does not support different
- + * formats for playback vs. record.
- + */
- +static int cs42888_set_dai_fmt(struct snd_soc_dai *codec_dai,
- + unsigned int format)
- +{
- + struct snd_soc_codec *codec = codec_dai->codec;
- + struct cs42888_private *cs42888 = snd_soc_codec_get_drvdata(codec);
- + int ret = 0;
- + u8 val;
- +
- + val = snd_soc_read(codec, CS42888_FORMAT);
- + val &= ~CS42888_FORMAT_DAC_DIF_MASK;
- + val &= ~CS42888_FORMAT_ADC_DIF_MASK;
- + /* set DAI format */
- + switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
- + case SND_SOC_DAIFMT_LEFT_J:
- + val |= DIF_LEFT_J << CS42888_FORMAT_DAC_DIF_OFFSET;
- + val |= DIF_LEFT_J << CS42888_FORMAT_ADC_DIF_OFFSET;
- + break;
- + case SND_SOC_DAIFMT_I2S:
- + val |= DIF_I2S << CS42888_FORMAT_DAC_DIF_OFFSET;
- + val |= DIF_I2S << CS42888_FORMAT_ADC_DIF_OFFSET;
- + break;
- + case SND_SOC_DAIFMT_RIGHT_J:
- + val |= DIF_RIGHT_J << CS42888_FORMAT_DAC_DIF_OFFSET;
- + val |= DIF_RIGHT_J << CS42888_FORMAT_ADC_DIF_OFFSET;
- + break;
- + default:
- + dev_err(codec->dev, "invalid dai format\n");
- + return -EINVAL;
- + }
- +
- + ret = snd_soc_write(codec, CS42888_FORMAT, val);
- + if (ret < 0) {
- + dev_err(codec->dev, "i2c write failed\n");
- + return ret;
- + }
- +
- + val = snd_soc_read(codec, CS42888_MODE);
- + /* set master/slave audio interface */
- + switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
- + case SND_SOC_DAIFMT_CBS_CFS:
- + cs42888->slave_mode = 1;
- + val &= ~CS42888_MODE_SPEED_MASK;
- + val |= CS42888_MODE_SLAVE;
- + break;
- + case SND_SOC_DAIFMT_CBM_CFM:
- + cs42888->slave_mode = 0;
- + break;
- + default:
- + /* all other modes are unsupported by the hardware */
- + return -EINVAL;
- + }
- +
- + ret = snd_soc_write(codec, CS42888_MODE, val);
- + if (ret < 0) {
- + dev_err(codec->dev, "i2c write failed\n");
- + return ret;
- + }
- +
- + dump_reg(codec);
- + return ret;
- +}
- +
- +/**
- + * cs42888_hw_params - program the CS42888 with the given hardware parameters.
- + * @substream: the audio stream
- + * @params: the hardware parameters to set
- +
- + * @dai: the SOC DAI (ignored)
- + *
- + * This function programs the hardware with the values provided.
- + * Specifically, the sample rate and the data format.
- + *
- + * The .ops functions are used to provide board-specific data, like input
- + * frequencies, to this driver. This function takes that information,
- + * combines it with the hardware parameters provided, and programs the
- + * hardware accordingly.
- + */
- +static int cs42888_hw_params(struct snd_pcm_substream *substream,
- + struct snd_pcm_hw_params *params,
- + struct snd_soc_dai *dai)
- +{
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct snd_soc_codec *codec = rtd->codec;
- + struct cs42888_private *cs42888 = snd_soc_codec_get_drvdata(codec);
- + int ret;
- + u32 i, rate, ratio, val;
- +
- + rate = params_rate(params); /* Sampling rate, in Hz */
- + ratio = cs42888->mclk / rate; /* MCLK/LRCK ratio */
- + for (i = 0; i < NUM_MCLK_RATIOS; i++) {
- + if (cs42888_mode_ratios[i].ratio == ratio)
- + break;
- + }
- +
- + if (i == NUM_MCLK_RATIOS) {
- + /* We did not find a matching ratio */
- + dev_err(codec->dev, "could not find matching ratio\n");
- + return -EINVAL;
- + }
- +
- + if (!cs42888->slave_mode) {
- + val = snd_soc_read(codec, CS42888_MODE);
- + val &= ~CS42888_MODE_SPEED_MASK;
- + val |= cs42888_mode_ratios[i].speed_mode;
- + val &= ~CS42888_MODE_DIV_MASK;
- + val |= cs42888_mode_ratios[i].mclk;
- + } else {
- + val = snd_soc_read(codec, CS42888_MODE);
- + val &= ~CS42888_MODE_SPEED_MASK;
- + val |= CS42888_MODE_SLAVE;
- + val &= ~CS42888_MODE_DIV_MASK;
- + val |= cs42888_mode_ratios[i].mclk;
- + }
- + ret = snd_soc_write(codec, CS42888_MODE, val);
- + if (ret < 0) {
- + dev_err(codec->dev, "i2c write failed\n");
- + return ret;
- + }
- +
- + /* Unmute all the channels */
- + val = snd_soc_read(codec, CS42888_MUTE);
- + val &= ~CS42888_MUTE_ALL;
- + ret = snd_soc_write(codec, CS42888_MUTE, val);
- + if (ret < 0) {
- + dev_err(codec->dev, "i2c write failed\n");
- + return ret;
- + }
- +
- + ret = cs42888_fill_cache(codec);
- + if (ret < 0) {
- + dev_err(codec->dev, "failed to fill register cache\n");
- + return ret;
- + }
- +
- + dump_reg(codec);
- + return ret;
- +}
- +
- +/**
- + * cs42888_shutdown - cs42888 enters into low power mode again.
- + * @substream: the audio stream
- + * @dai: the SOC DAI (ignored)
- + *
- + * The .ops functions are used to provide board-specific data, like input
- + * frequencies, to this driver. This function takes that information,
- + * combines it with the hardware parameters provided, and programs the
- + * hardware accordingly.
- + */
- +static void cs42888_shutdown(struct snd_pcm_substream *substream,
- + struct snd_soc_dai *dai)
- +{
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct snd_soc_codec *codec = rtd->codec;
- + int ret;
- + u8 val;
- +
- + /* Mute all the channels */
- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- + val = snd_soc_read(codec, CS42888_MUTE);
- + val |= CS42888_MUTE_ALL;
- + ret = snd_soc_write(codec, CS42888_MUTE, val);
- + if (ret < 0)
- + dev_err(codec->dev, "i2c write failed\n");
- + }
- +}
- +
- +static int cs42888_prepare(struct snd_pcm_substream *substream,
- + struct snd_soc_dai *dai)
- +{
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct snd_soc_card *card = rtd->card;
- + struct snd_soc_dai *tmp_codec_dai;
- + struct snd_soc_pcm_runtime *tmp_rtd;
- + u32 i;
- +
- + for (i = 0; i < card->num_rtd; i++) {
- + tmp_codec_dai = card->rtd[i].codec_dai;
- + tmp_rtd = (struct snd_soc_pcm_runtime *)(card->rtd + i);
- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- + cancel_delayed_work(&tmp_rtd->delayed_work);
- + }
- + return 0;
- +}
- +
- +static struct snd_soc_dai_ops cs42888_dai_ops = {
- + .set_fmt = cs42888_set_dai_fmt,
- + .set_sysclk = cs42888_set_dai_sysclk,
- + .hw_params = cs42888_hw_params,
- + .shutdown = cs42888_shutdown,
- + .prepare = cs42888_prepare,
- +};
- +
- +
- +static struct snd_soc_dai_driver cs42888_dai = {
- + .name = "CS42888",
- + .playback = {
- + .stream_name = "codec-Playback",
- + .channels_min = 2,
- + .channels_max = 8,
- + .rates = SNDRV_PCM_RATE_8000_192000,
- + .formats = CS42888_FORMATS,
- + },
- + .capture = {
- + .stream_name = "codec-Capture",
- + .channels_min = 2,
- + .channels_max = 4,
- + .rates = SNDRV_PCM_RATE_8000_192000,
- + .formats = CS42888_FORMATS,
- + },
- + .ops = &cs42888_dai_ops,
- +};
- +
- +/**
- + * cs42888_probe - ASoC probe function
- + * @pdev: platform device
- + *
- + * This function is called when ASoC has all the pieces it needs to
- + * instantiate a sound driver.
- + */
- +static int cs42888_probe(struct snd_soc_codec *codec)
- +{
- + struct cs42888_private *cs42888 = snd_soc_codec_get_drvdata(codec);
- + int ret, i, val;
- +
- + cs42888->codec = codec;
- + /* setup i2c data ops */
- + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
- + if (ret < 0) {
- + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- + return ret;
- + }
- +
- + for (i = 0; i < ARRAY_SIZE(cs42888->supplies); i++)
- + cs42888->supplies[i].supply = cs42888_supply_names[i];
- +
- + ret = devm_regulator_bulk_get(codec->dev,
- + ARRAY_SIZE(cs42888->supplies), cs42888->supplies);
- + if (ret) {
- + dev_err(codec->dev, "Failed to request supplies: %d\n",
- + ret);
- + return ret;
- + }
- +
- + ret = regulator_bulk_enable(ARRAY_SIZE(cs42888->supplies),
- + cs42888->supplies);
- + if (ret) {
- + dev_err(codec->dev, "Failed to enable supplies: %d\n",
- + ret);
- + goto err;
- + }
- + msleep(1);
- +
- + /* The I2C interface is set up, so pre-fill our register cache */
- + ret = cs42888_fill_cache(codec);
- + if (ret < 0) {
- + dev_err(codec->dev, "failed to fill register cache\n");
- + goto err;
- + }
- +
- + /* Enter low power state */
- + val = snd_soc_read(codec, CS42888_PWRCTL);
- + val |= CS42888_PWRCTL_PDN_MASK;
- + ret = snd_soc_write(codec, CS42888_PWRCTL, val);
- + if (ret < 0) {
- + dev_err(codec->dev, "i2c write failed\n");
- + goto err;
- + }
- +
- + /* Disable auto-mute */
- + val = snd_soc_read(codec, CS42888_TRANS);
- + val &= ~CS42888_TRANS_AMUTE_MASK;
- + val &= ~CS42888_TRANS_DAC_SZC_MASK;
- + val |= CS42888_TRANS_DAC_SZC_SR;
- + ret = snd_soc_write(codec, CS42888_TRANS, val);
- + if (ret < 0) {
- + dev_err(codec->dev, "i2c write failed\n");
- + goto err;
- + }
- + /* Add the non-DAPM controls */
- + snd_soc_add_codec_controls(codec, cs42888_snd_controls,
- + ARRAY_SIZE(cs42888_snd_controls));
- +
- + /* Add DAPM controls */
- + cs42888_add_widgets(codec);
- + return 0;
- +err:
- + regulator_bulk_disable(ARRAY_SIZE(cs42888->supplies),
- + cs42888->supplies);
- + return ret;
- +}
- +
- +/**
- + * cs42888_remove - ASoC remove function
- + * @pdev: platform device
- + *
- + * This function is the counterpart to cs42888_probe().
- + */
- +static int cs42888_remove(struct snd_soc_codec *codec)
- +{
- + struct cs42888_private *cs42888 = snd_soc_codec_get_drvdata(codec);
- +
- + regulator_bulk_disable(ARRAY_SIZE(cs42888->supplies),
- + cs42888->supplies);
- +
- + return 0;
- +};
- +
- +/*
- + * ASoC codec device structure
- + *
- + * Assign this variable to the codec_dev field of the machine driver's
- + * snd_soc_device structure.
- + */
- +static struct snd_soc_codec_driver cs42888_driver = {
- + .probe = cs42888_probe,
- + .remove = cs42888_remove,
- + .reg_cache_size = CS42888_NUMREGS + 1,
- + .reg_word_size = sizeof(u8),
- + .reg_cache_step = 1,
- +};
- +
- +/**
- + * cs42888_i2c_probe - initialize the I2C interface of the CS42888
- + * @i2c_client: the I2C client object
- + * @id: the I2C device ID (ignored)
- + *
- + * This function is called whenever the I2C subsystem finds a device that
- + * matches the device ID given via a prior call to i2c_add_driver().
- + */
- +static int cs42888_i2c_probe(struct i2c_client *i2c_client,
- + const struct i2c_device_id *id)
- +{
- + struct cs42888_private *cs42888;
- + int ret, val;
- +
- + /* Verify that we have a CS42888 */
- + val = i2c_smbus_read_byte_data(i2c_client, CS42888_CHIPID);
- + if (val < 0) {
- + dev_err(&i2c_client->dev, "Device with ID register %x is not a CS42888", val);
- + return -ENODEV;
- + }
- + /* The top four bits of the chip ID should be 0000. */
- + if ((val & CS42888_CHIPID_ID_MASK) != 0x00) {
- + dev_err(&i2c_client->dev, "device is not a CS42888\n");
- + return -ENODEV;
- + }
- +
- + dev_info(&i2c_client->dev, "found device at i2c address %X\n",
- + i2c_client->addr);
- + dev_info(&i2c_client->dev, "hardware revision %X\n", val & 0xF);
- +
- + /* Allocate enough space for the snd_soc_codec structure
- + and our private data together. */
- + cs42888 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42888_private), GFP_KERNEL);
- + if (!cs42888) {
- + dev_err(&i2c_client->dev, "could not allocate codec\n");
- + return -ENOMEM;
- + }
- +
- + i2c_set_clientdata(i2c_client, cs42888);
- +
- + cs42888->clk = devm_clk_get(&i2c_client->dev, NULL);
- + if (IS_ERR(cs42888->clk)) {
- + ret = PTR_ERR(cs42888->clk);
- + dev_err(&i2c_client->dev, "Cannot get the clock: %d\n", ret);
- + return ret;
- + }
- +
- + cs42888->mclk = clk_get_rate(cs42888->clk);
- + switch (cs42888->mclk) {
- + case 24576000:
- + cs42888_dai.playback.rates = SNDRV_PCM_RATE_48000 |
- + SNDRV_PCM_RATE_96000 |
- + SNDRV_PCM_RATE_192000;
- + cs42888_dai.capture.rates = SNDRV_PCM_RATE_48000 |
- + SNDRV_PCM_RATE_96000 |
- + SNDRV_PCM_RATE_192000;
- + break;
- + case 16934400:
- + cs42888_dai.playback.rates = SNDRV_PCM_RATE_44100 |
- + SNDRV_PCM_RATE_88200 |
- + SNDRV_PCM_RATE_176400;
- + cs42888_dai.capture.rates = SNDRV_PCM_RATE_44100 |
- + SNDRV_PCM_RATE_88200 |
- + SNDRV_PCM_RATE_176400;
- + break;
- + default:
- + dev_err(&i2c_client->dev, "codec mclk is not supported %d\n", cs42888->mclk);
- + break;
- + }
- +
- + ret = snd_soc_register_codec(&i2c_client->dev,
- + &cs42888_driver, &cs42888_dai, 1);
- + if (ret) {
- + dev_err(&i2c_client->dev, "Failed to register codec:%d\n", ret);
- + return ret;
- + }
- + return 0;
- +}
- +
- +/**
- + * cs42888_i2c_remove - remove an I2C device
- + * @i2c_client: the I2C client object
- + *
- + * This function is the counterpart to cs42888_i2c_probe().
- + */
- +static int cs42888_i2c_remove(struct i2c_client *i2c_client)
- +{
- + snd_soc_unregister_codec(&i2c_client->dev);
- + return 0;
- +}
- +
- +/*
- + * cs42888_i2c_id - I2C device IDs supported by this driver
- + */
- +static struct i2c_device_id cs42888_i2c_id[] = {
- + {"cs42888", 0},
- + {}
- +};
- +MODULE_DEVICE_TABLE(i2c, cs42888_i2c_id);
- +
- +#ifdef CONFIG_PM
- +/* This suspend/resume implementation can handle both - a simple standby
- + * where the codec remains powered, and a full suspend, where the voltage
- + * domain the codec is connected to is teared down and/or any other hardware
- + * reset condition is asserted.
- + *
- + * The codec's own power saving features are enabled in the suspend callback,
- + * and all registers are written back to the hardware when resuming.
- + */
- +
- +static int cs42888_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
- +{
- + struct cs42888_private *cs42888 = i2c_get_clientdata(client);
- + struct snd_soc_codec *codec = cs42888->codec;
- + int reg = snd_soc_read(codec, CS42888_PWRCTL) | CS42888_PWRCTL_PDN_MASK;
- + return snd_soc_write(codec, CS42888_PWRCTL, reg);
- +}
- +
- +static int cs42888_i2c_resume(struct i2c_client *client)
- +{
- + struct cs42888_private *cs42888 = i2c_get_clientdata(client);
- + struct snd_soc_codec *codec = cs42888->codec;
- + int reg;
- +
- + /* In case the device was put to hard reset during sleep, we need to
- + * wait 500ns here before any I2C communication. */
- + ndelay(500);
- +
- + /* first restore the entire register cache ... */
- + for (reg = CS42888_FIRSTREG; reg <= CS42888_LASTREG; reg++) {
- + u8 val = snd_soc_read(codec, reg);
- +
- + if (i2c_smbus_write_byte_data(client, reg, val)) {
- + dev_err(codec->dev, "i2c write failed\n");
- + return -EIO;
- + }
- + }
- +
- + /* ... then disable the power-down bits */
- + reg = snd_soc_read(codec, CS42888_PWRCTL);
- + reg &= ~CS42888_PWRCTL_PDN_MASK;
- + return snd_soc_write(codec, CS42888_PWRCTL, reg);
- +}
- +#else
- +#define cs42888_i2c_suspend NULL
- +#define cs42888_i2c_resume NULL
- +#endif /* CONFIG_PM */
- +
- +/*
- + * cs42888_i2c_driver - I2C device identification
- + *
- + * This structure tells the I2C subsystem how to identify and support a
- + * given I2C device type.
- + */
- +
- +static const struct of_device_id cs42888_dt_ids[] = {
- + { .compatible = "cirrus,cs42888", },
- + { /* sentinel */ }
- +};
- +
- +static struct i2c_driver cs42888_i2c_driver = {
- + .driver = {
- + .name = "cs42888",
- + .owner = THIS_MODULE,
- + .of_match_table = cs42888_dt_ids,
- + },
- + .probe = cs42888_i2c_probe,
- + .remove = cs42888_i2c_remove,
- + .suspend = cs42888_i2c_suspend,
- + .resume = cs42888_i2c_resume,
- + .id_table = cs42888_i2c_id,
- +};
- +
- +module_i2c_driver(cs42888_i2c_driver);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("Cirrus Logic CS42888 ALSA SoC Codec Driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/sound/soc/codecs/cs42888.h linux-3.14.35/sound/soc/codecs/cs42888.h
- --- linux-3.14.35.orig/sound/soc/codecs/cs42888.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/sound/soc/codecs/cs42888.h 2015-03-08 14:27:37.909684498 -0500
- @@ -0,0 +1,123 @@
- +/*
- + * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#ifndef _CS42888_H
- +#define _CS42888_H
- +
- +/* CS42888 registers addresses */
- +#define CS42888_CHIPID 0x01 /* Chip ID */
- +#define CS42888_PWRCTL 0x02 /* Power Control */
- +#define CS42888_MODE 0x03 /* Functional Mode */
- +#define CS42888_FORMAT 0x04 /* Interface Formats */
- +#define CS42888_ADCCTL 0x05 /* ADC Control */
- +#define CS42888_TRANS 0x06 /* Transition Control */
- +#define CS42888_MUTE 0x07 /* Mute Control */
- +#define CS42888_VOLAOUT1 0x08 /* Volume Control AOUT1*/
- +#define CS42888_VOLAOUT2 0x09 /* Volume Control AOUT2*/
- +#define CS42888_VOLAOUT3 0x0A /* Volume Control AOUT3*/
- +#define CS42888_VOLAOUT4 0x0B /* Volume Control AOUT4*/
- +#define CS42888_VOLAOUT5 0x0C /* Volume Control AOUT5*/
- +#define CS42888_VOLAOUT6 0x0D /* Volume Control AOUT6*/
- +#define CS42888_VOLAOUT7 0x0E /* Volume Control AOUT7*/
- +#define CS42888_VOLAOUT8 0x0F /* Volume Control AOUT8*/
- +#define CS42888_DACINV 0x10 /* DAC Channel Invert */
- +#define CS42888_VOLAIN1 0x11 /* Volume Control AIN1 */
- +#define CS42888_VOLAIN2 0x12 /* Volume Control AIN2 */
- +#define CS42888_VOLAIN3 0x13 /* Volume Control AIN3 */
- +#define CS42888_VOLAIN4 0x14 /* Volume Control AIN4 */
- +#define CS42888_ADCINV 0x17 /* ADC Channel Invert */
- +#define CS42888_STATUSCTL 0x18 /* Status Control */
- +#define CS42888_STATUS 0x19 /* Status */
- +#define CS42888_STATUSMASK 0x1A /* Status Mask */
- +
- +#define CS42888_FIRSTREG 0x01
- +#define CS42888_LASTREG 0x1A
- +#define CS42888_NUMREGS (CS42888_LASTREG - CS42888_FIRSTREG + 1)
- +#define CS42888_I2C_INCR 0x80
- +
- +/* Bit masks for the CS42888 registers */
- +#define CS42888_CHIPID_ID_MASK 0xF0
- +#define CS42888_CHIPID_REV 0x0F
- +#define CS42888_PWRCTL_PDN_ADC2_OFFSET 6
- +#define CS42888_PWRCTL_PDN_ADC1_OFFSET 5
- +#define CS42888_PWRCTL_PDN_DAC4_OFFSET 4
- +#define CS42888_PWRCTL_PDN_DAC3_OFFSET 3
- +#define CS42888_PWRCTL_PDN_DAC2_OFFSET 2
- +#define CS42888_PWRCTL_PDN_DAC1_OFFSET 1
- +#define CS42888_PWRCTL_PDN_OFFSET 0
- +#define CS42888_PWRCTL_PDN_ADC2_MASK (1 << CS42888_PWRCTL_PDN_ADC2_OFFSET)
- +#define CS42888_PWRCTL_PDN_ADC1_MASK (1 << CS42888_PWRCTL_PDN_ADC1_OFFSET)
- +#define CS42888_PWRCTL_PDN_DAC4_MASK (1 << CS42888_PWRCTL_PDN_DAC4_OFFSET)
- +#define CS42888_PWRCTL_PDN_DAC3_MASK (1 << CS42888_PWRCTL_PDN_DAC3_OFFSET)
- +#define CS42888_PWRCTL_PDN_DAC2_MASK (1 << CS42888_PWRCTL_PDN_DAC2_OFFSET)
- +#define CS42888_PWRCTL_PDN_DAC1_MASK (1 << CS42888_PWRCTL_PDN_DAC1_OFFSET)
- +#define CS42888_PWRCTL_PDN_MASK (1 << CS42888_PWRCTL_PDN_OFFSET)
- +
- +#define CS42888_MODE_SPEED_MASK 0xF0
- +#define CS42888_MODE_1X 0x00
- +#define CS42888_MODE_2X 0x50
- +#define CS42888_MODE_4X 0xA0
- +#define CS42888_MODE_SLAVE 0xF0
- +#define CS42888_MODE_DIV_MASK 0x0E
- +#define CS42888_MODE_DIV1 0x00
- +#define CS42888_MODE_DIV2 0x02
- +#define CS42888_MODE_DIV3 0x04
- +#define CS42888_MODE_DIV4 0x06
- +#define CS42888_MODE_DIV5 0x08
- +
- +#define CS42888_FORMAT_FREEZE_OFFSET 7
- +#define CS42888_FORMAT_AUX_DIF_OFFSET 6
- +#define CS42888_FORMAT_DAC_DIF_OFFSET 3
- +#define CS42888_FORMAT_ADC_DIF_OFFSET 0
- +#define CS42888_FORMAT_FREEZE_MASK (1 << CS42888_FORMAT_FREEZE_OFFSET)
- +#define CS42888_FORMAT_AUX_DIF_MASK (1 << CS42888_FORMAT_AUX_DIF_OFFSET)
- +#define CS42888_FORMAT_DAC_DIF_MASK (7 << CS42888_FORMAT_DAC_DIF_OFFSET)
- +#define CS42888_FORMAT_ADC_DIF_MASK (7 << CS42888_FORMAT_ADC_DIF_OFFSET)
- +
- +#define CS42888_TRANS_DAC_SNGVOL_OFFSET 7
- +#define CS42888_TRANS_DAC_SZC_OFFSET 5
- +#define CS42888_TRANS_AMUTE_OFFSET 4
- +#define CS42888_TRANS_MUTE_ADC_SP_OFFSET 3
- +#define CS42888_TRANS_ADC_SNGVOL_OFFSET 2
- +#define CS42888_TRANS_ADC_SZC_OFFSET 0
- +#define CS42888_TRANS_DAC_SNGVOL_MASK (1 << CS42888_TRANS_DAC_SNGVOL_OFFSET)
- +#define CS42888_TRANS_DAC_SZC_MASK (3 << CS42888_TRANS_DAC_SZC_OFFSET)
- +#define CS42888_TRANS_AMUTE_MASK (1 << CS42888_TRANS_AMUTE_OFFSET)
- +#define CS42888_TRANS_MUTE_ADC_SP_MASK (1 << CS42888_TRANS_MUTE_ADC_SP_OFFSET)
- +#define CS42888_TRANS_ADC_SNGVOL_MASK (1 << CS42888_TRANS_ADC_SNGVOL_OFFSET)
- +#define CS42888_TRANS_ADC_SZC_MASK (3 << CS42888_TRANS_ADC_SZC_OFFSET)
- +#define CS42888_TRANS_DAC_SZC_IC (0 << CS42888_TRANS_DAC_SZC_OFFSET)
- +#define CS42888_TRANS_DAC_SZC_ZC (1 << CS42888_TRANS_DAC_SZC_OFFSET)
- +#define CS42888_TRANS_DAC_SZC_SR (2 << CS42888_TRANS_DAC_SZC_OFFSET)
- +#define CS42888_TRANS_DAC_SZC_SRZC (3 << CS42888_TRANS_DAC_SZC_OFFSET)
- +
- +#define CS42888_MUTE_AOUT8 (0x1 << 7)
- +#define CS42888_MUTE_AOUT7 (0x1 << 6)
- +#define CS42888_MUTE_AOUT6 (0x1 << 5)
- +#define CS42888_MUTE_AOUT5 (0x1 << 4)
- +#define CS42888_MUTE_AOUT4 (0x1 << 3)
- +#define CS42888_MUTE_AOUT3 (0x1 << 2)
- +#define CS42888_MUTE_AOUT2 (0x1 << 1)
- +#define CS42888_MUTE_AOUT1 (0x1 << 0)
- +#define CS42888_MUTE_ALL (CS42888_MUTE_AOUT1 | CS42888_MUTE_AOUT2 | \
- + CS42888_MUTE_AOUT3 | CS42888_MUTE_AOUT4 | \
- + CS42888_MUTE_AOUT5 | CS42888_MUTE_AOUT6 | \
- + CS42888_MUTE_AOUT7 | CS42888_MUTE_AOUT8)
- +
- +#define DIF_LEFT_J 0
- +#define DIF_I2S 1
- +#define DIF_RIGHT_J 2
- +#define DIF_TDM 6
- +
- +
- +#endif
- diff -Nur linux-3.14.35.orig/sound/soc/codecs/Kconfig linux-3.14.35/sound/soc/codecs/Kconfig
- --- linux-3.14.35.orig/sound/soc/codecs/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/sound/soc/codecs/Kconfig 2015-03-08 14:27:37.909684498 -0500
- @@ -37,6 +37,7 @@
- select SND_SOC_CS42L73 if I2C
- select SND_SOC_CS4270 if I2C
- select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
- + select SND_SOC_CS42888 if I2C
- select SND_SOC_CX20442 if TTY
- select SND_SOC_DA7210 if I2C
- select SND_SOC_DA7213 if I2C
- @@ -254,6 +255,9 @@
- config SND_SOC_CS4271
- tristate
-
- +config SND_SOC_CS42888
- + tristate
- +
- config SND_SOC_CX20442
- tristate
- depends on TTY
- diff -Nur linux-3.14.35.orig/sound/soc/codecs/Makefile linux-3.14.35/sound/soc/codecs/Makefile
- --- linux-3.14.35.orig/sound/soc/codecs/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/sound/soc/codecs/Makefile 2015-03-08 14:27:37.909684498 -0500
- @@ -23,6 +23,7 @@
- snd-soc-cs42l73-objs := cs42l73.o
- snd-soc-cs4270-objs := cs4270.o
- snd-soc-cs4271-objs := cs4271.o
- +snd-soc-cs42888-objs := cs42888.o
- snd-soc-cx20442-objs := cx20442.o
- snd-soc-da7210-objs := da7210.o
- snd-soc-da7213-objs := da7213.o
- @@ -156,6 +157,7 @@
- obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o
- obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
- obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o
- +obj-$(CONFIG_SND_SOC_CS42888) += snd-soc-cs42888.o
- obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
- obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
- obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o
- diff -Nur linux-3.14.35.orig/sound/soc/codecs/sgtl5000.c linux-3.14.35/sound/soc/codecs/sgtl5000.c
- --- linux-3.14.35.orig/sound/soc/codecs/sgtl5000.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/sound/soc/codecs/sgtl5000.c 2015-03-08 14:27:37.909684498 -0500
- @@ -756,7 +756,7 @@
- struct ldo_regulator *ldo = rdev_get_drvdata(dev);
- struct snd_soc_codec *codec = (struct snd_soc_codec *)ldo->codec_data;
- int reg;
- -
- +dev_info(codec->dev, "%s(): enabled %u\n", __func__, ldo->enabled);
- if (ldo_regulator_is_enabled(dev))
- return 0;
-
- @@ -788,10 +788,16 @@
- {
- struct ldo_regulator *ldo = rdev_get_drvdata(dev);
- struct snd_soc_codec *codec = (struct snd_soc_codec *)ldo->codec_data;
- +dev_info(codec->dev, "%s(): enabled %u\n", __func__, ldo->enabled);
- +
- + snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
- + SGTL5000_LINREG_SIMPLE_POWERUP,
- + SGTL5000_LINREG_SIMPLE_POWERUP);
-
- snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
- SGTL5000_LINEREG_D_POWERUP,
- 0);
- +dev_info(codec->dev, "%s: ANA_POWER = 0x%04x\n", __func__, snd_soc_read(codec, SGTL5000_CHIP_ANA_POWER));
-
- /* clear voltage info */
- snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
- @@ -849,6 +855,7 @@
- config.dev = codec->dev;
- config.driver_data = ldo;
- config.init_data = init_data;
- + config.ena_gpio = -EINVAL;
-
- ldo->dev = regulator_register(&ldo->desc, &config);
- if (IS_ERR(ldo->dev)) {
- @@ -1202,8 +1209,11 @@
- * if vddio and vddd > 3.1v,
- * charge pump should be clean before set ana_pwr
- */
- - snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
- - SGTL5000_VDDC_CHRGPMP_POWERUP, 0);
- +// FIXME: this is total crap - we have read this register above into
- +// ana_pwr, which we then modify (above), and then write back to the
- +// register below. This modification just gets completely overwritten.
- +// snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
- +// SGTL5000_VDDC_CHRGPMP_POWERUP, 0);
-
- /* VDDC use VDDIO rail */
- lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD;
- @@ -1320,7 +1330,7 @@
- return ret;
- }
-
- - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies),
- + ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies),
- sgtl5000->supplies);
- if (ret)
- goto err_ldo_remove;
- @@ -1328,16 +1338,13 @@
- ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies),
- sgtl5000->supplies);
- if (ret)
- - goto err_regulator_free;
- + goto err_ldo_remove;
-
- /* wait for all power rails bring up */
- udelay(10);
-
- return 0;
-
- -err_regulator_free:
- - regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
- - sgtl5000->supplies);
- err_ldo_remove:
- if (!external_vddd)
- ldo_regulator_remove(codec);
- @@ -1358,6 +1365,9 @@
- return ret;
- }
-
- + if (!devres_open_group(codec->dev, NULL, GFP_KERNEL))
- + return -ENOMEM;
- +
- ret = sgtl5000_enable_regulators(codec);
- if (ret)
- return ret;
- @@ -1414,8 +1424,9 @@
- err:
- regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
- sgtl5000->supplies);
- - regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
- - sgtl5000->supplies);
- +
- + devres_release_group(codec->dev, NULL);
- +
- ldo_regulator_remove(codec);
-
- return ret;
- @@ -1429,8 +1440,9 @@
-
- regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
- sgtl5000->supplies);
- - regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
- - sgtl5000->supplies);
- +
- + devres_release_group(codec->dev, NULL);
- +
- ldo_regulator_remove(codec);
-
- return 0;
- diff -Nur linux-3.14.35.orig/sound/soc/codecs/spdif_transmitter.c linux-3.14.35/sound/soc/codecs/spdif_transmitter.c
- --- linux-3.14.35.orig/sound/soc/codecs/spdif_transmitter.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/sound/soc/codecs/spdif_transmitter.c 2015-03-08 14:27:37.913684498 -0500
- @@ -24,7 +24,7 @@
-
- #define DRV_NAME "spdif-dit"
-
- -#define STUB_RATES SNDRV_PCM_RATE_8000_96000
- +#define STUB_RATES SNDRV_PCM_RATE_8000_192000
- #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
- SNDRV_PCM_FMTBIT_S20_3LE | \
- SNDRV_PCM_FMTBIT_S24_LE)
- diff -Nur linux-3.14.35.orig/sound/soc/codecs/wm8962.c linux-3.14.35/sound/soc/codecs/wm8962.c
- --- linux-3.14.35.orig/sound/soc/codecs/wm8962.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/sound/soc/codecs/wm8962.c 2015-03-08 14:27:37.913684498 -0500
- @@ -16,6 +16,7 @@
- #include <linux/init.h>
- #include <linux/delay.h>
- #include <linux/pm.h>
- +#include <linux/clk.h>
- #include <linux/gcd.h>
- #include <linux/gpio.h>
- #include <linux/i2c.h>
- @@ -2942,7 +2943,8 @@
- WM8962_DAC_MUTE, val);
- }
-
- -#define WM8962_RATES SNDRV_PCM_RATE_8000_96000
- +#define WM8962_RATES (SNDRV_PCM_RATE_8000_48000 |\
- + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
-
- #define WM8962_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
- SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
- @@ -3536,6 +3538,15 @@
- pdata->gpio_init[i] = 0x0;
- }
-
- + pdata->codec_mclk = devm_clk_get(&i2c->dev, NULL);
- +
- + /*
- + * If clk_get() failed, we assume that clock's enabled by default.
- + * Otherwise, we let driver prepare and control the clock source.
- + */
- + if (IS_ERR(pdata->codec_mclk))
- + pdata->codec_mclk = NULL;
- +
- return 0;
- }
-
- @@ -3567,6 +3578,9 @@
- return ret;
- }
-
- + if (wm8962->pdata.codec_mclk)
- + clk_prepare(wm8962->pdata.codec_mclk);
- +
- for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
- wm8962->supplies[i].supply = wm8962_supply_names[i];
-
- @@ -3669,6 +3683,27 @@
- WM8962_MICBIAS_LVL,
- wm8962->pdata.mic_cfg);
-
- + /* set the default volume for playback and record*/
- + snd_soc_update_bits(codec, WM8962_HPOUTL_VOLUME,
- + WM8962_HPOUTL_VOL_MASK, 0x5d);
- + snd_soc_update_bits(codec, WM8962_HPOUTR_VOLUME,
- + WM8962_HPOUTR_VOL_MASK, 0x5d);
- + snd_soc_update_bits(codec, WM8962_SPKOUTL_VOLUME,
- + WM8962_SPKOUTL_VOL_MASK, 0x72);
- + snd_soc_update_bits(codec, WM8962_SPKOUTR_VOLUME,
- + WM8962_SPKOUTR_VOL_MASK, 0x72);
- +
- + snd_soc_update_bits(codec, WM8962_LEFT_INPUT_VOLUME,
- + WM8962_INL_VOL_MASK, 0x3f);
- + snd_soc_update_bits(codec, WM8962_RIGHT_INPUT_VOLUME,
- + WM8962_INR_VOL_MASK, 0x3f);
- + snd_soc_update_bits(codec, WM8962_LEFT_ADC_VOLUME,
- + WM8962_ADCL_VOL_MASK, 0xd8);
- + snd_soc_update_bits(codec, WM8962_RIGHT_ADC_VOLUME,
- + WM8962_ADCR_VOL_MASK, 0xd8);
- + snd_soc_update_bits(codec, WM8962_RIGHT_INPUT_MIXER_VOLUME,
- + WM8962_IN3R_MIXINR_VOL_MASK, 0x7);
- +
- /* Latch volume update bits */
- regmap_update_bits(wm8962->regmap, WM8962_LEFT_INPUT_VOLUME,
- WM8962_IN_VU, WM8962_IN_VU);
- @@ -3752,6 +3787,9 @@
-
- regcache_cache_only(wm8962->regmap, true);
-
- + /* The cache-only should be turned on before we power down the codec */
- + regcache_cache_only(wm8962->regmap, true);
- +
- /* The drivers should power up as needed */
- regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
-
- @@ -3760,11 +3798,19 @@
- err_enable:
- regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
- err:
- + if (wm8962->pdata.codec_mclk)
- + clk_unprepare(wm8962->pdata.codec_mclk);
- +
- return ret;
- }
-
- static int wm8962_i2c_remove(struct i2c_client *client)
- {
- + struct wm8962_priv *wm8962 = dev_get_drvdata(&client->dev);
- +
- + if (wm8962->pdata.codec_mclk)
- + clk_unprepare(wm8962->pdata.codec_mclk);
- +
- snd_soc_unregister_codec(&client->dev);
- return 0;
- }
- @@ -3775,6 +3821,9 @@
- struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
- int ret;
-
- + if (wm8962->pdata.codec_mclk)
- + clk_enable(wm8962->pdata.codec_mclk);
- +
- ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
- wm8962->supplies);
- if (ret != 0) {
- @@ -3834,6 +3883,10 @@
- regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies),
- wm8962->supplies);
-
- + if (wm8962->pdata.codec_mclk)
- + clk_disable(wm8962->pdata.codec_mclk);
- +
- +
- return 0;
- }
- #endif
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/fsl_asrc.c linux-3.14.35/sound/soc/fsl/fsl_asrc.c
- --- linux-3.14.35.orig/sound/soc/fsl/fsl_asrc.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/fsl_asrc.c 2015-03-08 14:27:37.913684498 -0500
- @@ -0,0 +1,498 @@
- +/*
- + * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#include <linux/module.h>
- +#include <linux/of.h>
- +#include <linux/of_platform.h>
- +#include <linux/slab.h>
- +#include <linux/device.h>
- +#include <linux/i2c.h>
- +#include <linux/clk.h>
- +#include <linux/delay.h>
- +#include <linux/mxc_asrc.h>
- +#include <sound/core.h>
- +#include <sound/pcm.h>
- +#include <sound/pcm_params.h>
- +#include <sound/soc.h>
- +#include <sound/initval.h>
- +#include <sound/dmaengine_pcm.h>
- +
- +#include "fsl_asrc.h"
- +#include "imx-pcm.h"
- +
- +static bool filter(struct dma_chan *chan, void *param)
- +{
- + if (!imx_dma_is_general_purpose(chan))
- + return false;
- +
- + chan->private = param;
- +
- + return true;
- +}
- +
- +static int asrc_p2p_request_channel(struct snd_pcm_substream *substream)
- +{
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- + struct fsl_asrc_p2p *asrc_p2p = snd_soc_dai_get_drvdata(cpu_dai);
- + enum dma_slave_buswidth buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
- + struct snd_dmaengine_dai_dma_data *dma_params_be = NULL;
- + struct snd_dmaengine_dai_dma_data *dma_params_fe = NULL;
- + struct imx_dma_data *fe_filter_data = NULL;
- + struct imx_dma_data *be_filter_data = NULL;
- +
- + struct dma_slave_config slave_config;
- + dma_cap_mask_t mask;
- + struct dma_chan *chan;
- + int ret;
- + struct snd_soc_dpcm *dpcm;
- +
- + /* find the be for this fe stream */
- + list_for_each_entry(dpcm, &rtd->dpcm[substream->stream].be_clients, list_be) {
- + if (dpcm->fe == rtd) {
- + struct snd_soc_pcm_runtime *be = dpcm->be;
- + struct snd_soc_dai *dai = be->cpu_dai;
- + struct snd_pcm_substream *be_substream;
- + be_substream = snd_soc_dpcm_get_substream(be, substream->stream);
- + dma_params_be = snd_soc_dai_get_dma_data(dai, be_substream);
- + break;
- + }
- + }
- +
- + if (!dma_params_be) {
- + dev_err(rtd->card->dev, "can not get be substream\n");
- + return -EINVAL;
- + }
- +
- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- + dma_params_fe = &asrc_p2p->dma_params_tx;
- + else
- + dma_params_fe = &asrc_p2p->dma_params_rx;
- +
- + fe_filter_data = dma_params_fe->filter_data;
- + be_filter_data = dma_params_be->filter_data;
- +
- + if (asrc_p2p->output_width == 16)
- + buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
- + else
- + buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
- +
- + /* reconfig memory to FIFO dma request */
- + dma_params_fe->addr = asrc_p2p->asrc_ops.asrc_p2p_per_addr(
- + asrc_p2p->asrc_index, 1);
- + fe_filter_data->dma_request0 = asrc_p2p->dmarx[asrc_p2p->asrc_index];
- + dma_params_fe->maxburst = dma_params_be->maxburst;
- +
- + dma_cap_zero(mask);
- + dma_cap_set(DMA_SLAVE, mask);
- + dma_cap_set(DMA_CYCLIC, mask);
- +
- + /* config p2p dma channel */
- + asrc_p2p->asrc_p2p_dma_data.peripheral_type = IMX_DMATYPE_ASRC;
- + asrc_p2p->asrc_p2p_dma_data.priority = DMA_PRIO_HIGH;
- + asrc_p2p->asrc_p2p_dma_data.dma_request1 = asrc_p2p->dmatx[asrc_p2p->asrc_index];
- + /* need to get target device's dma dma_addr, burstsize */
- + asrc_p2p->asrc_p2p_dma_data.dma_request0 = be_filter_data->dma_request0;
- +
- + /* Request channel */
- + asrc_p2p->asrc_p2p_dma_chan =
- + dma_request_channel(mask, filter, &asrc_p2p->asrc_p2p_dma_data);
- +
- + if (!asrc_p2p->asrc_p2p_dma_chan) {
- + dev_err(rtd->card->dev, "can not request dma channel\n");
- + goto error;
- + }
- + chan = asrc_p2p->asrc_p2p_dma_chan;
- +
- + /*
- + * Buswidth is not used in the sdma for p2p. Here we set the maxburst fix to
- + * twice of dma_params's burstsize.
- + */
- + slave_config.direction = DMA_DEV_TO_DEV;
- + slave_config.src_addr = asrc_p2p->asrc_ops.asrc_p2p_per_addr(asrc_p2p->asrc_index, 0);
- + slave_config.src_addr_width = buswidth;
- + slave_config.src_maxburst = dma_params_be->maxburst * 2;
- + slave_config.dst_addr = dma_params_be->addr;
- + slave_config.dst_addr_width = buswidth;
- + slave_config.dst_maxburst = dma_params_be->maxburst * 2;
- + slave_config.dma_request0 = be_filter_data->dma_request0;
- + slave_config.dma_request1 = asrc_p2p->dmatx[asrc_p2p->asrc_index];
- +
- + ret = dmaengine_slave_config(asrc_p2p->asrc_p2p_dma_chan,
- + &slave_config);
- + if (ret) {
- + dev_err(rtd->card->dev, "can not config dma channel\n");
- + goto error;
- + }
- +
- + return 0;
- +error:
- + if (asrc_p2p->asrc_p2p_dma_chan) {
- + dma_release_channel(asrc_p2p->asrc_p2p_dma_chan);
- + asrc_p2p->asrc_p2p_dma_chan = NULL;
- + }
- +
- + return -EINVAL;
- +}
- +
- +static int config_asrc(struct snd_pcm_substream *substream,
- + struct snd_pcm_hw_params *params)
- +{
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- + struct fsl_asrc_p2p *asrc_p2p = snd_soc_dai_get_drvdata(cpu_dai);
- + unsigned int rate = params_rate(params);
- + unsigned int channel = params_channels(params);
- + struct asrc_config config = {0};
- + int output_word_width = 0;
- + int input_word_width = 0;
- + int ret = 0;
- + if ((channel != 2) && (channel != 4) && (channel != 6)) {
- + dev_err(cpu_dai->dev, "param channel is not correct\n");
- + return -EINVAL;
- + }
- +
- + ret = asrc_p2p->asrc_ops.asrc_p2p_req_pair(channel, &asrc_p2p->asrc_index);
- + if (ret < 0) {
- + dev_err(cpu_dai->dev, "Fail to request asrc pair\n");
- + return -EINVAL;
- + }
- +
- + if (asrc_p2p->output_width == 16)
- + output_word_width = ASRC_WIDTH_16_BIT;
- + else
- + output_word_width = ASRC_WIDTH_24_BIT;
- +
- + switch (params_format(params)) {
- + case SNDRV_PCM_FORMAT_U16:
- + case SNDRV_PCM_FORMAT_S16_LE:
- + case SNDRV_PCM_FORMAT_S16_BE:
- + input_word_width = ASRC_WIDTH_16_BIT;
- + break;
- + case SNDRV_PCM_FORMAT_S20_3LE:
- + case SNDRV_PCM_FORMAT_S20_3BE:
- + case SNDRV_PCM_FORMAT_S24_3LE:
- + case SNDRV_PCM_FORMAT_S24_3BE:
- + case SNDRV_PCM_FORMAT_S24_BE:
- + case SNDRV_PCM_FORMAT_S24_LE:
- + case SNDRV_PCM_FORMAT_U24_BE:
- + case SNDRV_PCM_FORMAT_U24_LE:
- + case SNDRV_PCM_FORMAT_U24_3BE:
- + case SNDRV_PCM_FORMAT_U24_3LE:
- + input_word_width = ASRC_WIDTH_24_BIT;
- + break;
- + case SNDRV_PCM_FORMAT_S8:
- + case SNDRV_PCM_FORMAT_U8:
- + case SNDRV_PCM_FORMAT_S32:
- + case SNDRV_PCM_FORMAT_U32:
- + default:
- + dev_err(cpu_dai->dev, "Format is not support!\n");
- + return -EINVAL;
- + }
- +
- + config.input_word_width = input_word_width;
- + config.output_word_width = output_word_width;
- + config.pair = asrc_p2p->asrc_index;
- + config.channel_num = channel;
- + config.input_sample_rate = rate;
- + config.output_sample_rate = asrc_p2p->output_rate;
- + config.inclk = INCLK_NONE;
- +
- + switch (asrc_p2p->per_dev) {
- + case SSI1:
- + config.outclk = OUTCLK_SSI1_TX;
- + break;
- + case SSI2:
- + config.outclk = OUTCLK_SSI2_TX;
- + break;
- + case SSI3:
- + config.outclk = OUTCLK_SSI3_TX;
- + break;
- + case ESAI:
- + config.outclk = OUTCLK_ESAI_TX;
- + break;
- + default:
- + dev_err(cpu_dai->dev, "peripheral device is not correct\n");
- + return -EINVAL;
- + }
- +
- + ret = asrc_p2p->asrc_ops.asrc_p2p_config_pair(&config);
- + if (ret < 0) {
- + dev_err(cpu_dai->dev, "Fail to config asrc\n");
- + return ret;
- + }
- +
- + return 0;
- +}
- +
- +static int fsl_asrc_p2p_hw_params(struct snd_pcm_substream *substream,
- + struct snd_pcm_hw_params *params,
- + struct snd_soc_dai *cpu_dai)
- +{
- + int ret = 0;
- +
- + ret = config_asrc(substream, params);
- + if (ret < 0)
- + return ret;
- +
- + return asrc_p2p_request_channel(substream);
- +}
- +
- +static int fsl_asrc_p2p_hw_free(struct snd_pcm_substream *substream,
- + struct snd_soc_dai *cpu_dai)
- +{
- + struct fsl_asrc_p2p *asrc_p2p = snd_soc_dai_get_drvdata(cpu_dai);
- +
- + if (asrc_p2p->asrc_p2p_dma_chan) {
- + /* Release p2p dma resource */
- + dma_release_channel(asrc_p2p->asrc_p2p_dma_chan);
- + asrc_p2p->asrc_p2p_dma_chan = NULL;
- + }
- +
- + if (asrc_p2p->asrc_index != -1) {
- + asrc_p2p->asrc_ops.asrc_p2p_release_pair(asrc_p2p->asrc_index);
- + asrc_p2p->asrc_ops.asrc_p2p_finish_conv(asrc_p2p->asrc_index);
- + }
- + asrc_p2p->asrc_index = -1;
- +
- + return 0;
- +}
- +
- +static int fsl_asrc_dma_prepare_and_submit(struct snd_pcm_substream *substream,
- + struct fsl_asrc_p2p *asrc_p2p)
- +{
- + struct dma_async_tx_descriptor *desc = asrc_p2p->asrc_p2p_desc;
- + struct dma_chan *chan = asrc_p2p->asrc_p2p_dma_chan;
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct device *dev = rtd->platform->dev;
- +
- + desc = dmaengine_prep_dma_cyclic(chan, 0xffff, 64, 64, DMA_DEV_TO_DEV, 0);
- + if (!desc) {
- + dev_err(dev, "failed to prepare slave dma\n");
- + return -EINVAL;
- + }
- +
- + dmaengine_submit(desc);
- +
- + return 0;
- +}
- +
- +static int fsl_asrc_p2p_trigger(struct snd_pcm_substream *substream, int cmd,
- + struct snd_soc_dai *cpu_dai)
- +{
- + struct fsl_asrc_p2p *asrc_p2p = snd_soc_dai_get_drvdata(cpu_dai);
- + int ret;
- +
- + switch (cmd) {
- + case SNDRV_PCM_TRIGGER_START:
- + case SNDRV_PCM_TRIGGER_RESUME:
- + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- + ret = fsl_asrc_dma_prepare_and_submit(substream, asrc_p2p);
- + if (ret)
- + return ret;
- + dma_async_issue_pending(asrc_p2p->asrc_p2p_dma_chan);
- + asrc_p2p->asrc_ops.asrc_p2p_start_conv(asrc_p2p->asrc_index);
- + break;
- + case SNDRV_PCM_TRIGGER_SUSPEND:
- + case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- + case SNDRV_PCM_TRIGGER_STOP:
- + dmaengine_terminate_all(asrc_p2p->asrc_p2p_dma_chan);
- + asrc_p2p->asrc_ops.asrc_p2p_stop_conv(asrc_p2p->asrc_index);
- + break;
- + default:
- + return -EINVAL;
- + }
- +
- + return 0;
- +}
- +
- +#define IMX_ASRC_RATES SNDRV_PCM_RATE_8000_192000
- +
- +#define IMX_ASRC_FORMATS \
- + (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE | \
- + SNDRV_PCM_FORMAT_S20_3LE)
- +
- +static struct snd_soc_dai_ops fsl_asrc_p2p_dai_ops = {
- + .trigger = fsl_asrc_p2p_trigger,
- + .hw_params = fsl_asrc_p2p_hw_params,
- + .hw_free = fsl_asrc_p2p_hw_free,
- +};
- +
- +static int fsl_asrc_p2p_dai_probe(struct snd_soc_dai *dai)
- +{
- + struct fsl_asrc_p2p *asrc_p2p = snd_soc_dai_get_drvdata(dai);
- +
- + dai->playback_dma_data = &asrc_p2p->dma_params_tx;
- + dai->capture_dma_data = &asrc_p2p->dma_params_rx;
- +
- + return 0;
- +}
- +
- +static struct snd_soc_dai_driver fsl_asrc_p2p_dai = {
- + .probe = fsl_asrc_p2p_dai_probe,
- + .playback = {
- + .stream_name = "asrc-Playback",
- + .channels_min = 1,
- + .channels_max = 10,
- + .rates = IMX_ASRC_RATES,
- + .formats = IMX_ASRC_FORMATS,
- + },
- + .capture = {
- + .stream_name = "asrc-Capture",
- + .channels_min = 1,
- + .channels_max = 4,
- + .rates = IMX_ASRC_RATES,
- + .formats = IMX_ASRC_FORMATS,
- + },
- + .ops = &fsl_asrc_p2p_dai_ops,
- +};
- +
- +static const struct snd_soc_component_driver fsl_asrc_p2p_component = {
- + .name = "fsl-asrc-p2p",
- +};
- +
- +/*
- + * This function will register the snd_soc_pcm_link drivers.
- + */
- +static int fsl_asrc_p2p_probe(struct platform_device *pdev)
- +{
- + struct fsl_asrc_p2p *asrc_p2p;
- + struct device_node *np = pdev->dev.of_node;
- + const char *p;
- + const uint32_t *iprop_rate, *iprop_width;
- + int ret = 0;
- +
- + if (!of_device_is_available(np)) {
- + dev_err(&pdev->dev, "There is no device node\n");
- + return -ENODEV;
- + }
- +
- + asrc_p2p = devm_kzalloc(&pdev->dev, sizeof(struct fsl_asrc_p2p), GFP_KERNEL);
- + if (!asrc_p2p) {
- + dev_err(&pdev->dev, "can not alloc memory\n");
- + return -ENOMEM;
- + }
- + asrc_p2p->asrc_ops.asrc_p2p_start_conv = asrc_start_conv;
- + asrc_p2p->asrc_ops.asrc_p2p_stop_conv = asrc_stop_conv;
- + asrc_p2p->asrc_ops.asrc_p2p_per_addr = asrc_get_per_addr;
- + asrc_p2p->asrc_ops.asrc_p2p_req_pair = asrc_req_pair;
- + asrc_p2p->asrc_ops.asrc_p2p_config_pair = asrc_config_pair;
- + asrc_p2p->asrc_ops.asrc_p2p_release_pair = asrc_release_pair;
- + asrc_p2p->asrc_ops.asrc_p2p_finish_conv = asrc_finish_conv;
- +
- + asrc_p2p->asrc_index = -1;
- +
- + iprop_rate = of_get_property(np, "fsl,output-rate", NULL);
- + if (iprop_rate)
- + asrc_p2p->output_rate = be32_to_cpup(iprop_rate);
- + else {
- + dev_err(&pdev->dev, "There is no output-rate in dts\n");
- + return -EINVAL;
- + }
- + iprop_width = of_get_property(np, "fsl,output-width", NULL);
- + if (iprop_width)
- + asrc_p2p->output_width = be32_to_cpup(iprop_width);
- +
- + if (asrc_p2p->output_width != 16 && asrc_p2p->output_width != 24) {
- + dev_err(&pdev->dev, "output_width is not acceptable\n");
- + return -EINVAL;
- + }
- +
- + ret = of_property_read_u32_array(np,
- + "fsl,asrc-dma-tx-events", asrc_p2p->dmatx, 3);
- + if (ret) {
- + dev_err(&pdev->dev, "Failed to get fsl,asrc-dma-tx-events.\n");
- + return -EINVAL;
- + }
- +
- + ret = of_property_read_u32_array(np,
- + "fsl,asrc-dma-rx-events", asrc_p2p->dmarx, 3);
- + if (ret) {
- + dev_err(&pdev->dev, "Failed to get fsl,asrc-dma-rx-events.\n");
- + return -EINVAL;
- + }
- +
- + asrc_p2p->filter_data_tx.peripheral_type = IMX_DMATYPE_ASRC;
- + asrc_p2p->filter_data_rx.peripheral_type = IMX_DMATYPE_ASRC;
- +
- + asrc_p2p->dma_params_tx.filter_data = &asrc_p2p->filter_data_tx;
- + asrc_p2p->dma_params_rx.filter_data = &asrc_p2p->filter_data_rx;
- +
- + platform_set_drvdata(pdev, asrc_p2p);
- +
- + p = strrchr(np->full_name, '/') + 1;
- + strcpy(asrc_p2p->name, p);
- + fsl_asrc_p2p_dai.name = asrc_p2p->name;
- +
- + ret = snd_soc_register_component(&pdev->dev, &fsl_asrc_p2p_component,
- + &fsl_asrc_p2p_dai, 1);
- + if (ret) {
- + dev_err(&pdev->dev, "register DAI failed\n");
- + goto failed_register;
- + }
- +
- + asrc_p2p->soc_platform_pdev = platform_device_register_simple(
- + "imx-pcm-asrc", -1, NULL, 0);
- + if (IS_ERR(asrc_p2p->soc_platform_pdev)) {
- + ret = PTR_ERR(asrc_p2p->soc_platform_pdev);
- + goto failed_pdev_alloc;
- + }
- +
- + ret = imx_pcm_dma_init(asrc_p2p->soc_platform_pdev, SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
- + SND_DMAENGINE_PCM_FLAG_NO_DT |
- + SND_DMAENGINE_PCM_FLAG_COMPAT,
- + IMX_ASRC_DMABUF_SIZE);
- + if (ret) {
- + dev_err(&pdev->dev, "init pcm dma failed\n");
- + goto failed_pcm_init;
- + }
- +
- + return 0;
- +
- +failed_pcm_init:
- + platform_device_unregister(asrc_p2p->soc_platform_pdev);
- +failed_pdev_alloc:
- + snd_soc_unregister_component(&pdev->dev);
- +failed_register:
- +
- + return ret;
- +}
- +
- +static int fsl_asrc_p2p_remove(struct platform_device *pdev)
- +{
- + struct fsl_asrc_p2p *asrc_p2p = platform_get_drvdata(pdev);
- +
- + platform_device_unregister(asrc_p2p->soc_platform_pdev);
- + snd_soc_unregister_component(&pdev->dev);
- +
- + return 0;
- +}
- +
- +static const struct of_device_id fsl_asrc_p2p_dt_ids[] = {
- + { .compatible = "fsl,imx6q-asrc-p2p", },
- + { /* sentinel */ }
- +};
- +
- +static struct platform_driver fsl_asrc_p2p_driver = {
- + .probe = fsl_asrc_p2p_probe,
- + .remove = fsl_asrc_p2p_remove,
- + .driver = {
- + .name = "fsl-asrc-p2p",
- + .owner = THIS_MODULE,
- + .of_match_table = fsl_asrc_p2p_dt_ids,
- + },
- +};
- +module_platform_driver(fsl_asrc_p2p_driver);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("i.MX ASoC ASRC P2P driver");
- +MODULE_ALIAS("platform:fsl-asrc-p2p");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/fsl_asrc.h linux-3.14.35/sound/soc/fsl/fsl_asrc.h
- --- linux-3.14.35.orig/sound/soc/fsl/fsl_asrc.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/fsl_asrc.h 2015-03-08 14:27:37.913684498 -0500
- @@ -0,0 +1,48 @@
- +/*
- + * fsl_asrc.h - ALSA ASRC interface
- + *
- + * Copyright (C) 2013 Freescale Semiconductor, Inc. This file is licensed
- + * under the terms of the GNU General Public License version 2. This
- + * program is licensed "as is" without any warranty of any kind, whether
- + * express or implied.
- + */
- +
- +#ifndef _FSL_ASRC_P2P_H
- +#define _FSL_ASRC_P2P_H
- +
- +#include <linux/mxc_asrc.h>
- +#include <sound/dmaengine_pcm.h>
- +#include <linux/platform_data/dma-imx.h>
- +
- +enum peripheral_device_type {
- + UNKNOWN,
- + SSI1,
- + SSI2,
- + SSI3,
- + ESAI,
- +};
- +
- +struct fsl_asrc_p2p {
- + int output_rate;
- + int output_width;
- + enum asrc_pair_index asrc_index;
- + enum peripheral_device_type per_dev;
- + struct asrc_p2p_ops asrc_ops;
- +
- + struct snd_dmaengine_dai_dma_data dma_params_rx;
- + struct snd_dmaengine_dai_dma_data dma_params_tx;
- + struct imx_dma_data filter_data_tx;
- + struct imx_dma_data filter_data_rx;
- +
- + struct dma_async_tx_descriptor *asrc_p2p_desc;
- + struct dma_chan *asrc_p2p_dma_chan;
- + struct imx_dma_data asrc_p2p_dma_data;
- + struct platform_device *soc_platform_pdev;
- +
- + int dmarx[3];
- + int dmatx[3];
- +
- + char name[32];
- +};
- +
- +#endif
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/fsl_asrc_pcm.c linux-3.14.35/sound/soc/fsl/fsl_asrc_pcm.c
- --- linux-3.14.35.orig/sound/soc/fsl/fsl_asrc_pcm.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/fsl_asrc_pcm.c 2015-03-08 14:27:37.913684498 -0500
- @@ -0,0 +1,41 @@
- +/*
- + * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#include <linux/module.h>
- +#include <linux/platform_device.h>
- +
- +
- +/*
- + * Here add one platform module "imx-pcm-asrc" as pcm platform module.
- + * If we use the asrc_p2p node as the pcm platform, there will be one issue.
- + * snd_soc_dapm_new_dai_widgets will be called twice, one in probe link_dais,
- + * one in probe platform. so there will be two dai_widgets added to widget list.
- + * but only the seconed one will be recorded in dai->playback_widget.
- + * Machine driver will add the audio route, but when it go through the
- + * widget list, it will found the cpu_dai widget is the first one in the list.
- + * add use the first one to link the audio route.
- + * when use the fe/be architecture for asrc p2p, it need to go through from
- + * the fe->cpu_dai->playback_widget. but this is the second widget, so the
- + * result is that it can't find a availble audio route for p2p case. So here
- + * use another pcm platform to avoid this issue.
- + */
- +static struct platform_driver imx_pcm_driver = {
- + .driver = {
- + .name = "imx-pcm-asrc",
- + .owner = THIS_MODULE,
- + },
- +};
- +
- +module_platform_driver(imx_pcm_driver);
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("i.MX ASoC PCM driver");
- +MODULE_ALIAS("platform:imx-pcm-asrc");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/fsl_esai.c linux-3.14.35/sound/soc/fsl/fsl_esai.c
- --- linux-3.14.35.orig/sound/soc/fsl/fsl_esai.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/fsl_esai.c 2015-03-08 14:27:37.913684498 -0500
- @@ -785,7 +785,7 @@
- return ret;
- }
-
- - ret = imx_pcm_dma_init(pdev);
- + ret = imx_pcm_dma_init(pdev, NULL, IMX_ESAI_DMABUF_SIZE);
- if (ret)
- dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret);
-
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/fsl_hdmi.c linux-3.14.35/sound/soc/fsl/fsl_hdmi.c
- --- linux-3.14.35.orig/sound/soc/fsl/fsl_hdmi.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/fsl_hdmi.c 2015-03-08 14:27:37.913684498 -0500
- @@ -0,0 +1,614 @@
- +/*
- + * ALSA SoC HDMI Audio Layer for Freescale i.MX
- + *
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
- + *
- + * Some code from patch_hdmi.c
- + * Copyright (c) 2008-2010 Intel Corporation. All rights reserved.
- + * Copyright (c) 2006 ATI Technologies Inc.
- + * Copyright (c) 2008 NVIDIA Corp. All rights reserved.
- + * Copyright (c) 2008 Wei Ni <wni@nvidia.com>
- + *
- + * 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#include <linux/init.h>
- +#include <linux/module.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/slab.h>
- +#include <linux/clk.h>
- +#include <linux/delay.h>
- +#include <linux/mfd/mxc-hdmi-core.h>
- +#include <sound/pcm.h>
- +#include <sound/soc.h>
- +#include <sound/asoundef.h>
- +
- +#include <video/mxc_hdmi.h>
- +
- +#include "imx-hdmi.h"
- +
- +
- +static struct mxc_edid_cfg edid_cfg;
- +
- +static u32 playback_rates[HDMI_MAX_RATES];
- +static u32 playback_sample_size[HDMI_MAX_SAMPLE_SIZE];
- +static u32 playback_channels[HDMI_MAX_CHANNEL_CONSTRAINTS];
- +
- +static struct snd_pcm_hw_constraint_list playback_constraint_rates;
- +static struct snd_pcm_hw_constraint_list playback_constraint_bits;
- +static struct snd_pcm_hw_constraint_list playback_constraint_channels;
- +
- +#ifdef DEBUG
- +static void dumpregs(struct snd_soc_dai *dai)
- +{
- + u32 n, cts;
- +
- + cts = (hdmi_readb(HDMI_AUD_CTS3) << 16) |
- + (hdmi_readb(HDMI_AUD_CTS2) << 8) |
- + hdmi_readb(HDMI_AUD_CTS1);
- +
- + n = (hdmi_readb(HDMI_AUD_N3) << 16) |
- + (hdmi_readb(HDMI_AUD_N2) << 8) |
- + hdmi_readb(HDMI_AUD_N1);
- +
- + dev_dbg(dai->dev, "HDMI_PHY_CONF0 0x%02x\n",
- + hdmi_readb(HDMI_PHY_CONF0));
- + dev_dbg(dai->dev, "HDMI_MC_CLKDIS 0x%02x\n",
- + hdmi_readb(HDMI_MC_CLKDIS));
- + dev_dbg(dai->dev, "HDMI_AUD_N[1-3] 0x%06x (%d)\n",
- + n, n);
- + dev_dbg(dai->dev, "HDMI_AUD_CTS[1-3] 0x%06x (%d)\n",
- + cts, cts);
- + dev_dbg(dai->dev, "HDMI_FC_AUDSCONF 0x%02x\n",
- + hdmi_readb(HDMI_FC_AUDSCONF));
- +}
- +#else
- +static void dumpregs(struct snd_soc_dai *dai) {}
- +#endif
- +
- +enum cea_speaker_placement {
- + FL = (1 << 0), /* Front Left */
- + FC = (1 << 1), /* Front Center */
- + FR = (1 << 2), /* Front Right */
- + FLC = (1 << 3), /* Front Left Center */
- + FRC = (1 << 4), /* Front Right Center */
- + RL = (1 << 5), /* Rear Left */
- + RC = (1 << 6), /* Rear Center */
- + RR = (1 << 7), /* Rear Right */
- + RLC = (1 << 8), /* Rear Left Center */
- + RRC = (1 << 9), /* Rear Right Center */
- + LFE = (1 << 10), /* Low Frequency Effect */
- + FLW = (1 << 11), /* Front Left Wide */
- + FRW = (1 << 12), /* Front Right Wide */
- + FLH = (1 << 13), /* Front Left High */
- + FCH = (1 << 14), /* Front Center High */
- + FRH = (1 << 15), /* Front Right High */
- + TC = (1 << 16), /* Top Center */
- +};
- +
- +/*
- + * EDID SA bits in the CEA Speaker Allocation data block
- + */
- +static int edid_speaker_allocation_bits[] = {
- + [0] = FL | FR,
- + [1] = LFE,
- + [2] = FC,
- + [3] = RL | RR,
- + [4] = RC,
- + [5] = FLC | FRC,
- + [6] = RLC | RRC,
- + [7] = FLW | FRW,
- + [8] = FLH | FRH,
- + [9] = TC,
- + [10] = FCH,
- +};
- +
- +struct cea_channel_speaker_allocation {
- + int ca_index;
- + int speakers[8];
- +
- + /* Derived values, just for convenience */
- + int channels;
- + int spk_mask;
- +};
- +
- +/*
- + * This is an ordered list!
- + *
- + * The preceding ones have better chances to be selected by
- + * hdmi_channel_allocation().
- + */
- +static struct cea_channel_speaker_allocation channel_allocations[] = {
- + /* channel: 7 6 5 4 3 2 1 0 */
- + { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL },},
- + /* 2.1 */
- + { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL },},
- + /* Dolby Surround */
- + { .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL },}, /* Prefer FL/FR/RL/RR over FL/FR/LFE/FC */
- + { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL },},
- + { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL },},
- + { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL },},
- + { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL },},
- + { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL },},
- + { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL },},
- + { .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL },},
- + { .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL },},
- + /* surround51 */
- + { .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL },},
- + { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL },},
- + { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL },},
- + { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL },},
- + /* 6.1 */
- + { .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL },},
- + { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL },},
- + { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL },},
- + { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL },},
- + /* surround71 */
- + { .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL },},
- + { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL },},
- + { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL },},
- + { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL },},
- + { .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL },},
- + { .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL },},
- + { .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL },},
- + { .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL },},
- + { .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL },},
- + { .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL },},
- + { .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL },},
- + { .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL },},
- + { .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL },},
- + { .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL },},
- + { .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL },},
- + { .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL },},
- + { .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL },},
- + { .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL },},
- + { .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL },},
- + { .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL },},
- + { .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL },},
- + { .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL },},
- + { .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL },},
- + { .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL },},
- + { .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL },},
- + { .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL },},
- + { .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL },},
- + { .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL },},
- + { .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL },},
- + { .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL },},
- + { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL },},
- +};
- +
- +/* Compute derived values in channel_allocations[] */
- +static void init_channel_allocations(void)
- +{
- + struct cea_channel_speaker_allocation *p;
- + int i, j;
- +
- + for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
- + p = channel_allocations + i;
- + p->channels = 0;
- + p->spk_mask = 0;
- + for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
- + if (p->speakers[j]) {
- + p->channels++;
- + p->spk_mask |= p->speakers[j];
- + }
- + }
- +}
- +
- +/*
- + * The transformation takes two steps:
- + *
- + * speaker_alloc => (edid_speaker_allocation_bits[]) => spk_mask
- + * spk_mask => (channel_allocations[]) => CA
- + *
- + * TODO: it could select the wrong CA from multiple candidates.
- +*/
- +static int hdmi_channel_allocation(int channels)
- +{
- + int spk_mask = 0, ca = 0, i, tmpchn, tmpspk;
- +
- + /* CA defaults to 0 for basic stereo audio */
- + if (channels <= 2)
- + return 0;
- +
- + /*
- + * Expand EDID's speaker allocation mask
- + *
- + * EDID tells the speaker mask in a compact(paired) form,
- + * expand EDID's notions to match the ones used by Audio InfoFrame.
- + */
- + for (i = 0; i < ARRAY_SIZE(edid_speaker_allocation_bits); i++) {
- + if (edid_cfg.speaker_alloc & (1 << i))
- + spk_mask |= edid_speaker_allocation_bits[i];
- + }
- +
- + /* Search for the first working match in the CA table */
- + for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
- + tmpchn = channel_allocations[i].channels;
- + tmpspk = channel_allocations[i].spk_mask;
- +
- + if (channels == tmpchn && (spk_mask & tmpspk) == tmpspk) {
- + ca = channel_allocations[i].ca_index;
- + break;
- + }
- + }
- +
- + return ca;
- +}
- +
- +static void hdmi_set_audio_infoframe(unsigned int channels)
- +{
- + u8 audiconf0, audiconf2;
- +
- + /*
- + * From CEA-861-D spec:
- + * HDMI requires the CT, SS and SF fields to be set to 0 ("Refer
- + * to Stream Header") as these items are carried in the audio stream.
- + *
- + * So we only set the CC and CA fields.
- + */
- + audiconf0 = ((channels - 1) << HDMI_FC_AUDICONF0_CC_OFFSET) &
- + HDMI_FC_AUDICONF0_CC_MASK;
- +
- + audiconf2 = hdmi_channel_allocation(channels);
- +
- + hdmi_writeb(audiconf0, HDMI_FC_AUDICONF0);
- + hdmi_writeb(0, HDMI_FC_AUDICONF1);
- + hdmi_writeb(audiconf2, HDMI_FC_AUDICONF2);
- + hdmi_writeb(0, HDMI_FC_AUDICONF3);
- +}
- +
- +static int cea_audio_rates[HDMI_MAX_RATES] = {
- + 32000, 44100, 48000, 88200, 96000, 176400, 192000,
- +};
- +
- +static void fsl_hdmi_get_playback_rates(void)
- +{
- + int i, count = 0;
- + u8 rates;
- +
- + /* Always assume basic audio support */
- + rates = edid_cfg.sample_rates | 0x7;
- +
- + for (i = 0 ; i < HDMI_MAX_RATES ; i++)
- + if ((rates & (1 << i)) != 0)
- + playback_rates[count++] = cea_audio_rates[i];
- +
- + playback_constraint_rates.list = playback_rates;
- + playback_constraint_rates.count = count;
- +
- + for (i = 0 ; i < playback_constraint_rates.count ; i++)
- + pr_debug("%s: constraint = %d Hz\n", __func__, playback_rates[i]);
- +}
- +
- +static void fsl_hdmi_get_playback_sample_size(void)
- +{
- + int i = 0;
- +
- + /* Always assume basic audio support */
- + playback_sample_size[i++] = 16;
- +
- + if (edid_cfg.sample_sizes & 0x4)
- + playback_sample_size[i++] = 32;
- +
- + playback_constraint_bits.list = playback_sample_size;
- + playback_constraint_bits.count = i;
- +
- + for (i = 0 ; i < playback_constraint_bits.count ; i++)
- + pr_debug("%s: constraint = %d bits\n", __func__, playback_sample_size[i]);
- +}
- +
- +static void fsl_hdmi_get_playback_channels(void)
- +{
- + int channels = 2, i = 0;
- +
- + /* Always assume basic audio support */
- + playback_channels[i++] = channels;
- + channels += 2;
- +
- + while ((i < HDMI_MAX_CHANNEL_CONSTRAINTS) &&
- + (channels <= edid_cfg.max_channels)) {
- + playback_channels[i++] = channels;
- + channels += 2;
- + }
- +
- + playback_constraint_channels.list = playback_channels;
- + playback_constraint_channels.count = i;
- +
- + for (i = 0 ; i < playback_constraint_channels.count ; i++)
- + pr_debug("%s: constraint = %d channels\n", __func__, playback_channels[i]);
- +}
- +
- +static int fsl_hdmi_update_constraints(struct snd_pcm_substream *substream)
- +{
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + int edid_status, ret;
- +
- + edid_status = hdmi_get_edid_cfg(&edid_cfg);
- +
- + if (edid_status && !edid_cfg.hdmi_cap)
- + return -1;
- +
- + fsl_hdmi_get_playback_rates();
- + ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
- + &playback_constraint_rates);
- + if (ret)
- + return ret;
- +
- + fsl_hdmi_get_playback_sample_size();
- + ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
- + &playback_constraint_bits);
- + if (ret)
- + return ret;
- +
- + fsl_hdmi_get_playback_channels();
- + ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
- + &playback_constraint_channels);
- + if (ret)
- + return ret;
- +
- + ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
- + if (ret)
- + return ret;
- +
- + return 0;
- +}
- +
- +static int fsl_hdmi_soc_startup(struct snd_pcm_substream *substream,
- + struct snd_soc_dai *dai)
- +{
- + struct imx_hdmi *hdmi_data = snd_soc_dai_get_drvdata(dai);
- + int ret;
- +
- + ret = fsl_hdmi_update_constraints(substream);
- + if (ret < 0)
- + return ret;
- +
- + clk_prepare_enable(hdmi_data->isfr_clk);
- + clk_prepare_enable(hdmi_data->iahb_clk);
- +
- + dev_dbg(dai->dev, "%s hdmi clks: isfr:%d iahb:%d\n", __func__,
- + (int)clk_get_rate(hdmi_data->isfr_clk),
- + (int)clk_get_rate(hdmi_data->iahb_clk));
- +
- + /* Indicates the subpacket represents a flatline sample */
- + hdmi_audio_writeb(FC_AUDSCONF, AUD_PACKET_SAMPFIT, 0x0);
- +
- + return 0;
- +}
- +
- +static void fsl_hdmi_soc_shutdown(struct snd_pcm_substream *substream,
- + struct snd_soc_dai *dai)
- +{
- + struct imx_hdmi *hdmi_data = snd_soc_dai_get_drvdata(dai);
- +
- + clk_disable_unprepare(hdmi_data->iahb_clk);
- + clk_disable_unprepare(hdmi_data->isfr_clk);
- +}
- +
- +static int fsl_hdmi_soc_prepare(struct snd_pcm_substream *substream,
- + struct snd_soc_dai *dai)
- +{
- + struct snd_pcm_runtime *runtime = substream->runtime;
- +
- + hdmi_set_audio_infoframe(runtime->channels);
- + hdmi_audio_writeb(FC_AUDSCONF, AUD_PACKET_LAYOUT,
- + (runtime->channels > 2) ? 0x1 : 0x0);
- + hdmi_set_sample_rate(runtime->rate);
- + dumpregs(dai);
- +
- + return 0;
- +}
- +
- +static struct snd_soc_dai_ops fsl_hdmi_soc_dai_ops = {
- + .startup = fsl_hdmi_soc_startup,
- + .shutdown = fsl_hdmi_soc_shutdown,
- + .prepare = fsl_hdmi_soc_prepare,
- +};
- +
- +/* IEC60958 status functions */
- +static int fsl_hdmi_iec_info(struct snd_kcontrol *kcontrol,
- + struct snd_ctl_elem_info *uinfo)
- +{
- + uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
- + uinfo->count = 1;
- +
- + return 0;
- +}
- +
- +
- +static int fsl_hdmi_iec_get(struct snd_kcontrol *kcontrol,
- + struct snd_ctl_elem_value *uvalue)
- +{
- + int i;
- +
- + for (i = 0 ; i < 6 ; i++)
- + uvalue->value.iec958.status[i] = iec_header.status[i];
- +
- + return 0;
- +}
- +
- +static int fsl_hdmi_iec_put(struct snd_kcontrol *kcontrol,
- + struct snd_ctl_elem_value *uvalue)
- +{
- + int i;
- +
- + /* Do not allow professional mode */
- + if (uvalue->value.iec958.status[0] & IEC958_AES0_PROFESSIONAL)
- + return -EPERM;
- +
- + for (i = 0 ; i < 6 ; i++) {
- + iec_header.status[i] = uvalue->value.iec958.status[i];
- + pr_debug("%s status[%d]=0x%02x\n", __func__, i, iec_header.status[i]);
- + }
- +
- + return 0;
- +}
- +
- +static struct snd_kcontrol_new fsl_hdmi_ctrls[] = {
- + /* Status cchanel controller */
- + {
- + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
- + .access = SNDRV_CTL_ELEM_ACCESS_READ |
- + SNDRV_CTL_ELEM_ACCESS_WRITE |
- + SNDRV_CTL_ELEM_ACCESS_VOLATILE,
- + .info = fsl_hdmi_iec_info,
- + .get = fsl_hdmi_iec_get,
- + .put = fsl_hdmi_iec_put,
- + },
- +};
- +
- +static int fsl_hdmi_soc_dai_probe(struct snd_soc_dai *dai)
- +{
- + int ret;
- +
- + init_channel_allocations();
- +
- + ret = snd_soc_add_dai_controls(dai, fsl_hdmi_ctrls,
- + ARRAY_SIZE(fsl_hdmi_ctrls));
- + if (ret)
- + dev_warn(dai->dev, "failed to add dai controls\n");
- +
- + return 0;
- +}
- +
- +static struct snd_soc_dai_driver fsl_hdmi_dai = {
- + .probe = &fsl_hdmi_soc_dai_probe,
- + .playback = {
- + .channels_min = 2,
- + .channels_max = 8,
- + .rates = MXC_HDMI_RATES_PLAYBACK,
- + .formats = MXC_HDMI_FORMATS_PLAYBACK,
- + },
- + .ops = &fsl_hdmi_soc_dai_ops,
- +};
- +
- +static const struct snd_soc_component_driver fsl_hdmi_component = {
- + .name = "fsl-hdmi",
- +};
- +
- +static int fsl_hdmi_dai_probe(struct platform_device *pdev)
- +{
- + struct device_node *np = pdev->dev.of_node;
- + struct imx_hdmi *hdmi_data;
- + int ret = 0;
- +
- + if (!np)
- + return -ENODEV;
- +
- + if (!hdmi_get_registered()) {
- + dev_err(&pdev->dev, "failed to probe. Load HDMI-video first.\n");
- + return -ENOMEM;
- + }
- +
- + hdmi_data = devm_kzalloc(&pdev->dev, sizeof(*hdmi_data), GFP_KERNEL);
- + if (!hdmi_data) {
- + dev_err(&pdev->dev, "failed to alloc hdmi_data\n");
- + return -ENOMEM;
- + }
- +
- + hdmi_data->pdev = pdev;
- +
- + memcpy(&hdmi_data->cpu_dai_drv, &fsl_hdmi_dai, sizeof(fsl_hdmi_dai));
- + hdmi_data->cpu_dai_drv.name = np->name;
- +
- + hdmi_data->isfr_clk = devm_clk_get(&pdev->dev, "hdmi_isfr");
- + if (IS_ERR(hdmi_data->isfr_clk)) {
- + ret = PTR_ERR(hdmi_data->isfr_clk);
- + dev_err(&pdev->dev, "failed to get HDMI isfr clk: %d\n", ret);
- + return -EINVAL;
- + }
- +
- + hdmi_data->iahb_clk = devm_clk_get(&pdev->dev, "hdmi_iahb");
- + if (IS_ERR(hdmi_data->iahb_clk)) {
- + ret = PTR_ERR(hdmi_data->iahb_clk);
- + dev_err(&pdev->dev, "failed to get HDMI ahb clk: %d\n", ret);
- + return -EINVAL;
- + }
- +
- + dev_set_drvdata(&pdev->dev, hdmi_data);
- + ret = snd_soc_register_component(&pdev->dev, &fsl_hdmi_component,
- + &hdmi_data->cpu_dai_drv, 1);
- + if (ret) {
- + dev_err(&pdev->dev, "register DAI failed\n");
- + return ret;
- + }
- +
- + hdmi_data->codec_dev = platform_device_register_simple(
- + "hdmi-audio-codec", -1, NULL, 0);
- + if (IS_ERR(hdmi_data->codec_dev)) {
- + dev_err(&pdev->dev, "failed to register HDMI audio codec\n");
- + ret = PTR_ERR(hdmi_data->codec_dev);
- + goto fail;
- + }
- +
- + hdmi_data->dma_dev = platform_device_alloc("imx-hdmi-audio", -1);
- + if (IS_ERR(hdmi_data->dma_dev)) {
- + ret = PTR_ERR(hdmi_data->dma_dev);
- + goto fail_dma;
- + }
- +
- + platform_set_drvdata(hdmi_data->dma_dev, hdmi_data);
- +
- + ret = platform_device_add(hdmi_data->dma_dev);
- + if (ret) {
- + platform_device_put(hdmi_data->dma_dev);
- + goto fail_dma;
- + }
- +
- + return 0;
- +
- +fail_dma:
- + platform_device_unregister(hdmi_data->codec_dev);
- +fail:
- + snd_soc_unregister_component(&pdev->dev);
- +
- + return ret;
- +}
- +
- +static int fsl_hdmi_dai_remove(struct platform_device *pdev)
- +{
- + struct imx_hdmi *hdmi_data = platform_get_drvdata(pdev);
- +
- + platform_device_unregister(hdmi_data->dma_dev);
- + platform_device_unregister(hdmi_data->codec_dev);
- + snd_soc_unregister_component(&pdev->dev);
- +
- + return 0;
- +}
- +
- +static const struct of_device_id fsl_hdmi_dai_dt_ids[] = {
- + { .compatible = "fsl,imx6dl-hdmi-audio", },
- + { .compatible = "fsl,imx6q-hdmi-audio", },
- + { /* sentinel */ }
- +};
- +MODULE_DEVICE_TABLE(of, fsl_hdmi_dai_dt_ids);
- +
- +static struct platform_driver fsl_hdmi_driver = {
- + .probe = fsl_hdmi_dai_probe,
- + .remove = fsl_hdmi_dai_remove,
- + .driver = {
- + .name = "fsl-hdmi-dai",
- + .owner = THIS_MODULE,
- + .of_match_table = fsl_hdmi_dai_dt_ids,
- + },
- +};
- +module_platform_driver(fsl_hdmi_driver);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("IMX HDMI TX DAI");
- +MODULE_LICENSE("GPL");
- +MODULE_ALIAS("platform:fsl-hdmi-dai");
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/fsl_spdif.c linux-3.14.35/sound/soc/fsl/fsl_spdif.c
- --- linux-3.14.35.orig/sound/soc/fsl/fsl_spdif.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/fsl_spdif.c 2015-03-08 14:27:37.913684498 -0500
- @@ -21,6 +21,8 @@
- #include <linux/of_address.h>
- #include <linux/of_device.h>
- #include <linux/of_irq.h>
- +#include <linux/pm_runtime.h>
- +#include <linux/busfreq-imx6.h>
-
- #include <sound/asoundef.h>
- #include <sound/soc.h>
- @@ -53,7 +55,7 @@
- spinlock_t ctl_lock;
-
- /* IEC958 channel tx status bit */
- - unsigned char ch_status[4];
- + unsigned char ch_status[6];
-
- /* User bits */
- unsigned char subcode[2 * SPDIF_UBITS_SIZE];
- @@ -80,6 +82,7 @@
- u8 rxclk_src;
- struct clk *txclk[SPDIF_TXRATE_MAX];
- struct clk *rxclk;
- + struct clk *sysclk;
- struct snd_dmaengine_dai_dma_data dma_params_tx;
- struct snd_dmaengine_dai_dma_data dma_params_rx;
-
- @@ -295,11 +298,11 @@
- return -EBUSY;
- }
-
- -static void spdif_set_cstatus(struct spdif_mixer_control *ctrl,
- - u8 mask, u8 cstatus)
- +static inline void spdif_set_cstatus(struct spdif_mixer_control *ctrl,
- + u8 byteno, u8 mask, u8 cstatus)
- {
- - ctrl->ch_status[3] &= ~mask;
- - ctrl->ch_status[3] |= cstatus & mask;
- + ctrl->ch_status[byteno] &= ~mask;
- + ctrl->ch_status[byteno] |= cstatus & mask;
- }
-
- static void spdif_write_channel_status(struct fsl_spdif_priv *spdif_priv)
- @@ -316,10 +319,16 @@
-
- dev_dbg(&pdev->dev, "STCSCH: 0x%06x\n", ch_status);
-
- - ch_status = bitrev8(ctrl->ch_status[3]) << 16;
- + ch_status = bitrev8(ctrl->ch_status[3]) << 16 |
- + (bitrev8(ctrl->ch_status[4]) << 8) |
- + bitrev8(ctrl->ch_status[5]);
- regmap_write(regmap, REG_SPDIF_STCSCL, ch_status);
-
- dev_dbg(&pdev->dev, "STCSCL: 0x%06x\n", ch_status);
- +
- + /* Set outgoing validity (0: pcm, 1: non-audio) */
- + regmap_update_bits(regmap, REG_SPDIF_SCR, SCR_VAL_MASK,
- + (ctrl->ch_status[0] & IEC958_AES0_NONAUDIO) ? 0 : SCR_VAL_CLEAR);
- }
-
- /* Set SPDIF PhaseConfig register for rx clock */
- @@ -347,23 +356,45 @@
- struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
- struct regmap *regmap = spdif_priv->regmap;
- struct platform_device *pdev = spdif_priv->pdev;
- - unsigned long csfs = 0;
- u32 stc, mask, rate;
- - u8 clk, div;
- + u8 clk, div, csfs, csofs;
- int ret;
-
- switch (sample_rate) {
- case 32000:
- rate = SPDIF_TXRATE_32000;
- csfs = IEC958_AES3_CON_FS_32000;
- + csofs = IEC958_AES4_CON_ORIGFS_32000;
- break;
- case 44100:
- rate = SPDIF_TXRATE_44100;
- csfs = IEC958_AES3_CON_FS_44100;
- + csofs = IEC958_AES4_CON_ORIGFS_44100;
- break;
- case 48000:
- rate = SPDIF_TXRATE_48000;
- csfs = IEC958_AES3_CON_FS_48000;
- + csofs = IEC958_AES4_CON_ORIGFS_48000;
- + break;
- + case 88200:
- + rate = SPDIF_TXRATE_88200;
- + csfs = IEC958_AES3_CON_FS_88200;
- + csofs = IEC958_AES4_CON_ORIGFS_88200;
- + break;
- + case 96000:
- + rate = SPDIF_TXRATE_96000;
- + csfs = IEC958_AES3_CON_FS_96000;
- + csofs = IEC958_AES4_CON_ORIGFS_96000;
- + break;
- + case 176400:
- + rate = SPDIF_TXRATE_176400;
- + csfs = IEC958_AES3_CON_FS_176400;
- + csofs = IEC958_AES4_CON_ORIGFS_176400;
- + break;
- + case 192000:
- + rate = SPDIF_TXRATE_192000;
- + csfs = IEC958_AES3_CON_FS_192000;
- + csofs = IEC958_AES4_CON_ORIGFS_192000;
- break;
- default:
- dev_err(&pdev->dev, "unsupported sample rate %d\n", sample_rate);
- @@ -399,7 +430,8 @@
- clk_get_rate(spdif_priv->txclk[rate]));
-
- /* set fs field in consumer channel status */
- - spdif_set_cstatus(ctrl, IEC958_AES3_CON_FS, csfs);
- + spdif_set_cstatus(ctrl, 3, IEC958_AES3_CON_FS, csfs);
- + spdif_set_cstatus(ctrl, 4, IEC958_AES4_CON_ORIGFS, csofs);
-
- /* select clock source and divisor */
- stc = STC_TXCLK_ALL_EN | STC_TXCLK_SRC_SET(clk) | STC_TXCLK_DIV(div);
- @@ -421,6 +453,8 @@
- u32 scr, mask, i;
- int ret;
-
- + pm_runtime_get_sync(cpu_dai->dev);
- +
- /* Reset module and interrupts only for first initialization */
- if (!cpu_dai->active) {
- ret = spdif_softreset(spdif_priv);
- @@ -485,6 +519,8 @@
- regmap_update_bits(regmap, REG_SPDIF_SCR,
- SCR_LOW_POWER, SCR_LOW_POWER);
- }
- +
- + pm_runtime_put_sync(cpu_dai->dev);
- }
-
- static int fsl_spdif_hw_params(struct snd_pcm_substream *substream,
- @@ -505,8 +541,8 @@
- __func__, sample_rate);
- return ret;
- }
- - spdif_set_cstatus(ctrl, IEC958_AES3_CON_CLOCK,
- - IEC958_AES3_CON_CLOCK_1000PPM);
- + spdif_set_cstatus(ctrl, 3, IEC958_AES3_CON_CLOCK,
- + IEC958_AES3_CON_CLOCK_1000PPM);
- spdif_write_channel_status(spdif_priv);
- } else {
- /* Setup rx clock source */
- @@ -576,14 +612,13 @@
- static int fsl_spdif_pb_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *uvalue)
- {
- + int i;
- struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
- struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
- struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
-
- - uvalue->value.iec958.status[0] = ctrl->ch_status[0];
- - uvalue->value.iec958.status[1] = ctrl->ch_status[1];
- - uvalue->value.iec958.status[2] = ctrl->ch_status[2];
- - uvalue->value.iec958.status[3] = ctrl->ch_status[3];
- + for (i = 0; i < ARRAY_SIZE(ctrl->ch_status); i++)
- + uvalue->value.iec958.status[i] = ctrl->ch_status[i];
-
- return 0;
- }
- @@ -591,14 +626,13 @@
- static int fsl_spdif_pb_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *uvalue)
- {
- + int i;
- struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
- struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
- struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
-
- - ctrl->ch_status[0] = uvalue->value.iec958.status[0];
- - ctrl->ch_status[1] = uvalue->value.iec958.status[1];
- - ctrl->ch_status[2] = uvalue->value.iec958.status[2];
- - ctrl->ch_status[3] = uvalue->value.iec958.status[3];
- + for (i = 0; i < ARRAY_SIZE(ctrl->ch_status); i++)
- + ctrl->ch_status[i] = uvalue->value.iec958.status[i];
-
- spdif_write_channel_status(spdif_priv);
-
- @@ -754,7 +788,7 @@
- clksrc = (phaseconf >> SRPC_CLKSRC_SEL_OFFSET) & 0xf;
- if (srpc_dpll_locked[clksrc] && (phaseconf & SRPC_DPLL_LOCKED)) {
- /* Get bus clock from system */
- - busclk_freq = clk_get_rate(spdif_priv->rxclk);
- + busclk_freq = clk_get_rate(spdif_priv->sysclk);
- }
-
- /* FreqMeas_CLK = (BUS_CLK * FreqMeas) / 2 ^ 10 / GAINSEL / 128 */
- @@ -999,7 +1033,7 @@
- struct clk *clk, u64 savesub,
- enum spdif_txrate index)
- {
- - const u32 rate[] = { 32000, 44100, 48000 };
- + const u32 rate[] = { 32000, 44100, 48000, 88200, 96000, 176400, 192000 };
- u64 rate_ideal, rate_actual, sub;
- u32 div, arate;
-
- @@ -1017,7 +1051,7 @@
- break;
- } else if (arate / rate[index] == 1) {
- /* A little bigger than expect */
- - sub = (arate - rate[index]) * 100000;
- + sub = (u64)(arate - rate[index]) * 100000;
- do_div(sub, rate[index]);
- if (sub < savesub) {
- savesub = sub;
- @@ -1025,7 +1059,7 @@
- }
- } else if (rate[index] / arate == 1) {
- /* A little smaller than expect */
- - sub = (rate[index] - arate) * 100000;
- + sub = (u64)(rate[index] - arate) * 100000;
- do_div(sub, rate[index]);
- if (sub < savesub) {
- savesub = sub;
- @@ -1040,7 +1074,7 @@
- static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv,
- enum spdif_txrate index)
- {
- - const u32 rate[] = { 32000, 44100, 48000 };
- + const u32 rate[] = { 32000, 44100, 48000, 88200, 96000, 176400, 192000 };
- struct platform_device *pdev = spdif_priv->pdev;
- struct device *dev = &pdev->dev;
- u64 savesub = 100000, ret;
- @@ -1058,6 +1092,13 @@
- if (!clk_get_rate(clk))
- continue;
-
- + /* TODO: We here ignore sysclk source due to imperfect clock
- + * selecting mechanism: sysclk is a bit different which we can
- + * not change its clock rate but use another inner divider to
- + * derive a proper clock rate. */
- + if (i == SPDIF_CLK_SRC_SYSCLK)
- + continue;
- +
- ret = fsl_spdif_txclk_caldiv(spdif_priv, clk, savesub, index);
- if (savesub == ret)
- continue;
- @@ -1131,6 +1172,13 @@
- return ret;
- }
-
- + /* Get system clock for rx clock rate calculation */
- + spdif_priv->sysclk = devm_clk_get(&pdev->dev, "rxtx5");
- + if (IS_ERR(spdif_priv->sysclk)) {
- + dev_err(&pdev->dev, "no system clock(rxtx5) in devicetree\n");
- + return PTR_ERR(spdif_priv->sysclk);
- + }
- +
- /* Select clock source for rx/tx clock */
- spdif_priv->rxclk = devm_clk_get(&pdev->dev, "rxtx1");
- if (IS_ERR(spdif_priv->rxclk)) {
- @@ -1150,12 +1198,13 @@
- spin_lock_init(&ctrl->ctl_lock);
-
- /* Init tx channel status default value */
- - ctrl->ch_status[0] =
- - IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_5015;
- + ctrl->ch_status[0] = IEC958_AES0_CON_NOT_COPYRIGHT;
- ctrl->ch_status[1] = IEC958_AES1_CON_DIGDIGCONV_ID;
- ctrl->ch_status[2] = 0x00;
- ctrl->ch_status[3] =
- IEC958_AES3_CON_FS_44100 | IEC958_AES3_CON_CLOCK_1000PPM;
- + ctrl->ch_status[4] = IEC958_AES4_CON_ORIGFS_44100;
- + ctrl->ch_status[5] = IEC958_AES5_CON_CGMSA_COPYFREELY;
-
- spdif_priv->dpll_locked = false;
-
- @@ -1164,6 +1213,8 @@
- spdif_priv->dma_params_tx.addr = res->start + REG_SPDIF_STL;
- spdif_priv->dma_params_rx.addr = res->start + REG_SPDIF_SRL;
-
- + pm_runtime_enable(&pdev->dev);
- +
- /* Register with ASoC */
- dev_set_drvdata(&pdev->dev, spdif_priv);
-
- @@ -1174,13 +1225,34 @@
- return ret;
- }
-
- - ret = imx_pcm_dma_init(pdev);
- + ret = imx_pcm_dma_init(pdev, SND_DMAENGINE_PCM_FLAG_COMPAT,
- + IMX_SPDIF_DMABUF_SIZE);
- if (ret)
- dev_err(&pdev->dev, "imx_pcm_dma_init failed: %d\n", ret);
-
- return ret;
- }
-
- +#ifdef CONFIG_PM_RUNTIME
- +static int fsl_spdif_runtime_resume(struct device *dev)
- +{
- + request_bus_freq(BUS_FREQ_HIGH);
- + return 0;
- +}
- +
- +static int fsl_spdif_runtime_suspend(struct device *dev)
- +{
- + release_bus_freq(BUS_FREQ_HIGH);
- + return 0;
- +}
- +#endif
- +
- +static const struct dev_pm_ops fsl_spdif_pm = {
- + SET_RUNTIME_PM_OPS(fsl_spdif_runtime_suspend,
- + fsl_spdif_runtime_resume,
- + NULL)
- +};
- +
- static const struct of_device_id fsl_spdif_dt_ids[] = {
- { .compatible = "fsl,imx35-spdif", },
- {}
- @@ -1192,6 +1264,7 @@
- .name = "fsl-spdif-dai",
- .owner = THIS_MODULE,
- .of_match_table = fsl_spdif_dt_ids,
- + .pm = &fsl_spdif_pm,
- },
- .probe = fsl_spdif_probe,
- };
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/fsl_spdif.h linux-3.14.35/sound/soc/fsl/fsl_spdif.h
- --- linux-3.14.35.orig/sound/soc/fsl/fsl_spdif.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/fsl_spdif.h 2015-03-08 14:27:37.913684498 -0500
- @@ -157,13 +157,19 @@
- #define STC_TXCLK_DIV(x) ((((x) - 1) << STC_TXCLK_DIV_OFFSET) & STC_TXCLK_DIV_MASK)
- #define STC_TXCLK_SRC_MAX 8
-
- +#define SPDIF_CLK_SRC_SYSCLK 5
- +
- /* SPDIF tx rate */
- enum spdif_txrate {
- SPDIF_TXRATE_32000 = 0,
- SPDIF_TXRATE_44100,
- SPDIF_TXRATE_48000,
- + SPDIF_TXRATE_88200,
- + SPDIF_TXRATE_96000,
- + SPDIF_TXRATE_176400,
- + SPDIF_TXRATE_192000,
- };
- -#define SPDIF_TXRATE_MAX (SPDIF_TXRATE_48000 + 1)
- +#define SPDIF_TXRATE_MAX (SPDIF_TXRATE_192000 + 1)
-
-
- #define SPDIF_CSTATUS_BYTE 6
- @@ -173,7 +179,11 @@
-
- #define FSL_SPDIF_RATES_PLAYBACK (SNDRV_PCM_RATE_32000 | \
- SNDRV_PCM_RATE_44100 | \
- - SNDRV_PCM_RATE_48000)
- + SNDRV_PCM_RATE_48000 | \
- + SNDRV_PCM_RATE_88200 | \
- + SNDRV_PCM_RATE_96000 | \
- + SNDRV_PCM_RATE_176400| \
- + SNDRV_PCM_RATE_192000)
-
- #define FSL_SPDIF_RATES_CAPTURE (SNDRV_PCM_RATE_16000 | \
- SNDRV_PCM_RATE_32000 | \
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/fsl_ssi.c linux-3.14.35/sound/soc/fsl/fsl_ssi.c
- --- linux-3.14.35.orig/sound/soc/fsl/fsl_ssi.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/fsl_ssi.c 2015-03-08 14:27:37.913684498 -0500
- @@ -3,7 +3,7 @@
- *
- * Author: Timur Tabi <timur@freescale.com>
- *
- - * Copyright 2007-2010 Freescale Semiconductor, Inc.
- + * Copyright (C) 2007-2013 Freescale Semiconductor, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- @@ -30,6 +30,7 @@
- * around this by not polling these bits but only wait a fixed delay.
- */
-
- +#include <linux/busfreq-imx6.h>
- #include <linux/init.h>
- #include <linux/io.h>
- #include <linux/module.h>
- @@ -43,6 +44,7 @@
- #include <linux/of_address.h>
- #include <linux/of_irq.h>
- #include <linux/of_platform.h>
- +#include <linux/pm_runtime.h>
-
- #include <sound/core.h>
- #include <sound/pcm.h>
- @@ -73,6 +75,24 @@
- }
- #endif
-
- +#ifdef DEBUG
- +#define NUM_OF_SSI_REG (sizeof(struct ccsr_ssi) / sizeof(__be32))
- +
- +void dump_reg(struct ccsr_ssi __iomem *ssi)
- +{
- + u32 val, i;
- +
- + for (i = 0; i < NUM_OF_SSI_REG; i++) {
- + if (&ssi->stx0 + i == NULL)
- + continue;
- + val = read_ssi(&ssi->stx0 + i);
- + pr_debug("REG %x = %x\n", (u32)(&ssi->stx0 + i) & 0xff, val);
- + }
- +}
- +#else
- +void dump_reg(struct ccsr_ssi __iomem *ssi) {}
- +#endif
- +
- /**
- * FSLSSI_I2S_RATES: sample rates supported by the I2S
- *
- @@ -171,8 +191,6 @@
- struct clk *clk;
- struct snd_dmaengine_dai_dma_data dma_params_tx;
- struct snd_dmaengine_dai_dma_data dma_params_rx;
- - struct imx_dma_data filter_data_tx;
- - struct imx_dma_data filter_data_rx;
- struct imx_pcm_fiq_params fiq_params;
- /* Register values for rx/tx configuration */
- struct fsl_ssi_rxtx_reg_val rxtx_reg_val;
- @@ -206,6 +224,26 @@
- char name[1];
- };
-
- +#ifdef CONFIG_PM_RUNTIME
- +static int fsl_ssi_runtime_resume(struct device *dev)
- +{
- + request_bus_freq(BUS_FREQ_AUDIO);
- + return 0;
- +}
- +
- +static int fsl_ssi_runtime_suspend(struct device *dev)
- +{
- + release_bus_freq(BUS_FREQ_AUDIO);
- + return 0;
- +}
- +#endif
- +
- +static const struct dev_pm_ops fsl_ssi_pm = {
- + SET_RUNTIME_PM_OPS(fsl_ssi_runtime_suspend,
- + fsl_ssi_runtime_resume,
- + NULL)
- +};
- +
- static const struct of_device_id fsl_ssi_ids[] = {
- { .compatible = "fsl,mpc8610-ssi", .data = (void *) FSL_SSI_MCP8610},
- { .compatible = "fsl,imx51-ssi", .data = (void *) FSL_SSI_MX51},
- @@ -489,6 +527,23 @@
- }
- }
-
- +static void fsl_ssi_clk_ctrl(struct fsl_ssi_private *ssi_private, bool enable)
- +{
- + if (enable) {
- + if (ssi_private->ssi_on_imx) {
- + if (!IS_ERR(ssi_private->baudclk))
- + clk_enable(ssi_private->baudclk);
- + clk_enable(ssi_private->clk);
- + }
- + } else {
- + if (ssi_private->ssi_on_imx) {
- + if (!IS_ERR(ssi_private->baudclk))
- + clk_disable(ssi_private->baudclk);
- + clk_disable(ssi_private->clk);
- + }
- + }
- +}
- +
- /*
- * Enable/Disable a ssi configuration. You have to pass either
- * ssi_private->rxtx_reg_val.rx or tx as vals parameter.
- @@ -509,6 +564,8 @@
- else
- avals = &ssi_private->rxtx_reg_val.rx;
-
- + fsl_ssi_clk_ctrl(ssi_private, enable);
- +
- /* If vals should be disabled, start with disabling the unit */
- if (!enable) {
- u32 scr = vals->scr & (vals->scr ^ avals->scr);
- @@ -748,6 +805,8 @@
- snd_soc_dai_get_drvdata(rtd->cpu_dai);
- unsigned long flags;
-
- + pm_runtime_get_sync(dai->dev);
- +
- /* First, we only do fsl_ssi_setup() when SSI is going to be active.
- * Second, fsl_ssi_setup was already called by ac97_init earlier if
- * the driver is in ac97 mode.
- @@ -1083,14 +1142,17 @@
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- + case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- fsl_ssi_tx_config(ssi_private, true);
- else
- fsl_ssi_rx_config(ssi_private, true);
- + dump_reg(ssi);
- break;
-
- case SNDRV_PCM_TRIGGER_STOP:
- + case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- fsl_ssi_tx_config(ssi_private, false);
- @@ -1119,6 +1181,12 @@
- return 0;
- }
-
- +static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
- + struct snd_soc_dai *dai)
- +{
- + pm_runtime_put_sync(dai->dev);
- +}
- +
- static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
- {
- struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai);
- @@ -1138,6 +1206,7 @@
- .set_sysclk = fsl_ssi_set_dai_sysclk,
- .set_tdm_slot = fsl_ssi_set_dai_tdm_slot,
- .trigger = fsl_ssi_trigger,
- + .shutdown = fsl_ssi_shutdown,
- };
-
- /* Template for the CPU dai driver structure */
- @@ -1257,13 +1326,13 @@
- int ret = 0;
- struct device_attribute *dev_attr = NULL;
- struct device_node *np = pdev->dev.of_node;
- + u32 dmas[4];
- const struct of_device_id *of_id;
- enum fsl_ssi_type hw_type;
- const char *p, *sprop;
- const uint32_t *iprop;
- struct resource res;
- char name[64];
- - bool shared;
- bool ac97 = false;
-
- /* SSIs that are not connected on the board should have a
- @@ -1381,7 +1450,6 @@
-
- if (hw_type == FSL_SSI_MX21 || hw_type == FSL_SSI_MX51 ||
- hw_type == FSL_SSI_MX35) {
- - u32 dma_events[2], dmas[4];
- ssi_private->ssi_on_imx = true;
-
- ssi_private->clk = devm_clk_get(&pdev->dev, NULL);
- @@ -1390,9 +1458,9 @@
- dev_err(&pdev->dev, "could not get clock: %d\n", ret);
- goto error_irqmap;
- }
- - ret = clk_prepare_enable(ssi_private->clk);
- + ret = clk_prepare(ssi_private->clk);
- if (ret) {
- - dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n",
- + dev_err(&pdev->dev, "clk_prepare failed: %d\n",
- ret);
- goto error_irqmap;
- }
- @@ -1405,41 +1473,21 @@
- dev_dbg(&pdev->dev, "could not get baud clock: %ld\n",
- PTR_ERR(ssi_private->baudclk));
- else
- - clk_prepare_enable(ssi_private->baudclk);
- + clk_prepare(ssi_private->baudclk);
-
- /*
- * We have burstsize be "fifo_depth - 2" to match the SSI
- * watermark setting in fsl_ssi_startup().
- */
- - ssi_private->dma_params_tx.maxburst =
- - ssi_private->fifo_depth - 2;
- - ssi_private->dma_params_rx.maxburst =
- - ssi_private->fifo_depth - 2;
- + ssi_private->dma_params_tx.maxburst = ssi_private->fifo_depth - 2;
- + ssi_private->dma_params_rx.maxburst = ssi_private->fifo_depth - 2;
- ssi_private->dma_params_tx.addr =
- ssi_private->ssi_phys + offsetof(struct ccsr_ssi, stx0);
- ssi_private->dma_params_rx.addr =
- ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0);
- - ssi_private->dma_params_tx.filter_data =
- - &ssi_private->filter_data_tx;
- - ssi_private->dma_params_rx.filter_data =
- - &ssi_private->filter_data_rx;
- - if (!of_property_read_bool(pdev->dev.of_node, "dmas") &&
- - ssi_private->use_dma) {
- - /*
- - * FIXME: This is a temporary solution until all
- - * necessary dma drivers support the generic dma
- - * bindings.
- - */
- - ret = of_property_read_u32_array(pdev->dev.of_node,
- - "fsl,ssi-dma-events", dma_events, 2);
- - if (ret && ssi_private->use_dma) {
- - dev_err(&pdev->dev, "could not get dma events but fsl-ssi is configured to use DMA\n");
- - goto error_clk;
- - }
- - }
- - /* Should this be merge with the above? */
- - if (!of_property_read_u32_array(pdev->dev.of_node, "dmas", dmas, 4)
- - && dmas[2] == IMX_DMATYPE_SSI_DUAL) {
- +
- + ret = !of_property_read_u32_array(np, "dmas", dmas, 4);
- + if (ssi_private->use_dma && !ret && dmas[2] == IMX_DMATYPE_SSI_DUAL) {
- ssi_private->use_dual_fifo = true;
- /* When using dual fifo mode, we need to keep watermark
- * as even numbers due to dma script limitation.
- @@ -1447,14 +1495,6 @@
- ssi_private->dma_params_tx.maxburst &= ~0x1;
- ssi_private->dma_params_rx.maxburst &= ~0x1;
- }
- -
- - shared = of_device_is_compatible(of_get_parent(np),
- - "fsl,spba-bus");
- -
- - imx_pcm_dma_params_init_data(&ssi_private->filter_data_tx,
- - dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
- - imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx,
- - dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
- }
-
- /*
- @@ -1474,6 +1514,8 @@
- }
- }
-
- + pm_runtime_enable(&pdev->dev);
- +
- /* Register with ASoC */
- dev_set_drvdata(&pdev->dev, ssi_private);
-
- @@ -1509,7 +1551,8 @@
- if (ret)
- goto error_pcm;
- } else {
- - ret = imx_pcm_dma_init(pdev);
- + ret = imx_pcm_dma_init(pdev, NULL,
- + IMX_SSI_DMABUF_SIZE);
- if (ret)
- goto error_pcm;
- }
- @@ -1565,12 +1608,16 @@
- error_dev:
- device_remove_file(&pdev->dev, dev_attr);
-
- -error_clk:
- if (ssi_private->ssi_on_imx) {
- if (!IS_ERR(ssi_private->baudclk))
- - clk_disable_unprepare(ssi_private->baudclk);
- - clk_disable_unprepare(ssi_private->clk);
- + clk_unprepare(ssi_private->baudclk);
- + clk_unprepare(ssi_private->clk);
- }
- +error_clk:
- + if (!IS_ERR(ssi_private->baudclk))
- + clk_unprepare(ssi_private->baudclk);
- + if (!IS_ERR(ssi_private->clk))
- + clk_unprepare(ssi_private->clk);
-
- error_irqmap:
- if (ssi_private->irq_stats)
- @@ -1590,8 +1637,8 @@
- snd_soc_unregister_component(&pdev->dev);
- if (ssi_private->ssi_on_imx) {
- if (!IS_ERR(ssi_private->baudclk))
- - clk_disable_unprepare(ssi_private->baudclk);
- - clk_disable_unprepare(ssi_private->clk);
- + clk_unprepare(ssi_private->baudclk);
- + clk_unprepare(ssi_private->clk);
- }
- if (ssi_private->irq_stats)
- irq_dispose_mapping(ssi_private->irq);
- @@ -1604,6 +1651,7 @@
- .name = "fsl-ssi-dai",
- .owner = THIS_MODULE,
- .of_match_table = fsl_ssi_ids,
- + .pm = &fsl_ssi_pm,
- },
- .probe = fsl_ssi_probe,
- .remove = fsl_ssi_remove,
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/imx-cs42888.c linux-3.14.35/sound/soc/fsl/imx-cs42888.c
- --- linux-3.14.35.orig/sound/soc/fsl/imx-cs42888.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/imx-cs42888.c 2015-03-08 14:27:37.913684498 -0500
- @@ -0,0 +1,369 @@
- +/*
- + * Copyright (C) 2010-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +/*
- + * The code contained herein is licensed under the GNU General Public
- + * License. You may obtain a copy of the GNU General Public License
- + * Version 2 or later at the following locations:
- + *
- + * http://www.opensource.org/licenses/gpl-license.html
- + * http://www.gnu.org/copyleft/gpl.html
- + */
- +
- +#include <linux/module.h>
- +#include <linux/of.h>
- +#include <linux/of_platform.h>
- +#include <linux/slab.h>
- +#include <linux/device.h>
- +#include <linux/i2c.h>
- +#include <linux/clk.h>
- +#include <linux/delay.h>
- +#include <sound/core.h>
- +#include <sound/pcm.h>
- +#include <sound/soc.h>
- +#include <sound/initval.h>
- +#include <sound/pcm_params.h>
- +
- +#include "fsl_esai.h"
- +#include "fsl_asrc.h"
- +
- +#define CODEC_CLK_EXTER_OSC 1
- +#define CODEC_CLK_ESAI_HCKT 2
- +
- +struct imx_priv {
- + int hw;
- + int fe_output_rate;
- + int fe_output_width;
- + unsigned int mclk_freq;
- + unsigned int codec_mclk;
- + struct platform_device *pdev;
- +};
- +
- +static struct imx_priv card_priv;
- +
- +static int imx_cs42888_startup(struct snd_pcm_substream *substream)
- +{
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- + struct imx_priv *priv = &card_priv;
- +
- + if (!cpu_dai->active)
- + priv->hw = 0;
- + return 0;
- +}
- +
- +static void imx_cs42888_shutdown(struct snd_pcm_substream *substream)
- +{
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- + struct imx_priv *priv = &card_priv;
- +
- + if (!cpu_dai->active)
- + priv->hw = 0;
- +}
- +
- +static const struct {
- + int rate;
- + int ratio1;
- + int ratio2;
- +} sr_vals[] = {
- + { 32000, 5, 3 },
- + { 48000, 5, 3 },
- + { 64000, 2, 1 },
- + { 96000, 2, 1 },
- + { 128000, 2, 1 },
- + { 44100, 5, 3 },
- + { 88200, 2, 1 },
- + { 176400, 0, 0 },
- + { 192000, 0, 0 },
- +};
- +
- +static int imx_cs42888_surround_hw_params(struct snd_pcm_substream *substream,
- + struct snd_pcm_hw_params *params)
- +{
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- + struct snd_soc_dai *codec_dai = rtd->codec_dai;
- + struct imx_priv *priv = &card_priv;
- + unsigned int rate = params_rate(params);
- + unsigned int lrclk_ratio = 0, i;
- + u32 dai_format = 0;
- +
- + if (priv->hw)
- + return 0;
- +
- + priv->hw = 1;
- +
- + if (priv->codec_mclk & CODEC_CLK_ESAI_HCKT) {
- + for (i = 0; i < ARRAY_SIZE(sr_vals); i++) {
- + if (sr_vals[i].rate == rate) {
- + lrclk_ratio = sr_vals[i].ratio1;
- + break;
- + }
- + }
- + if (i == ARRAY_SIZE(sr_vals)) {
- + dev_err(&priv->pdev->dev, "Unsupported rate %dHz\n", rate);
- + return -EINVAL;
- + }
- +
- + dai_format = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF |
- + SND_SOC_DAIFMT_CBS_CFS;
- +
- + /* set the ESAI system clock as output */
- + snd_soc_dai_set_sysclk(cpu_dai, ESAI_CLK_EXTAL_DIV,
- + priv->mclk_freq, SND_SOC_CLOCK_OUT);
- + snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PM, 2);
- + snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PM, 2);
- + /* set codec Master clock */
- + snd_soc_dai_set_sysclk(codec_dai, 0, priv->mclk_freq,\
- + SND_SOC_CLOCK_IN);
- + } else if (priv->codec_mclk & CODEC_CLK_EXTER_OSC) {
- + for (i = 0; i < ARRAY_SIZE(sr_vals); i++) {
- + if (sr_vals[i].rate == rate) {
- + lrclk_ratio = sr_vals[i].ratio2;
- + break;
- + }
- + }
- + if (i == ARRAY_SIZE(sr_vals)) {
- + dev_err(&priv->pdev->dev, "Unsupported rate %dHz\n", rate);
- + return -EINVAL;
- + }
- +
- + dai_format = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF |
- + SND_SOC_DAIFMT_CBS_CFS;
- +
- + snd_soc_dai_set_sysclk(cpu_dai, ESAI_CLK_EXTAL,
- + priv->mclk_freq, SND_SOC_CLOCK_OUT);
- + snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PM, 0);
- + snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PM, 0);
- + snd_soc_dai_set_sysclk(codec_dai, 0, priv->mclk_freq,\
- + SND_SOC_CLOCK_IN);
- + }
- +
- + /* set cpu DAI configuration */
- + snd_soc_dai_set_fmt(cpu_dai, dai_format);
- + /* set i.MX active slot mask */
- + snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32);
- + /* set the ratio */
- + snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PSR, 1);
- + snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_FP, lrclk_ratio);
- + snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PSR, 1);
- + snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_FP, lrclk_ratio);
- +
- + /* set codec DAI configuration */
- + snd_soc_dai_set_fmt(codec_dai, dai_format);
- + return 0;
- +}
- +
- +static struct snd_soc_ops imx_cs42888_surround_ops = {
- + .startup = imx_cs42888_startup,
- + .shutdown = imx_cs42888_shutdown,
- + .hw_params = imx_cs42888_surround_hw_params,
- +};
- +
- +static const struct snd_soc_dapm_widget imx_cs42888_dapm_widgets[] = {
- + SND_SOC_DAPM_LINE("Line Out Jack", NULL),
- + SND_SOC_DAPM_LINE("Line In Jack", NULL),
- +};
- +
- +static const struct snd_soc_dapm_route audio_map[] = {
- + /* Line out jack */
- + {"Line Out Jack", NULL, "AOUT1L"},
- + {"Line Out Jack", NULL, "AOUT1R"},
- + {"Line Out Jack", NULL, "AOUT2L"},
- + {"Line Out Jack", NULL, "AOUT2R"},
- + {"Line Out Jack", NULL, "AOUT3L"},
- + {"Line Out Jack", NULL, "AOUT3R"},
- + {"Line Out Jack", NULL, "AOUT4L"},
- + {"Line Out Jack", NULL, "AOUT4R"},
- + {"AIN1L", NULL, "Line In Jack"},
- + {"AIN1R", NULL, "Line In Jack"},
- + {"AIN2L", NULL, "Line In Jack"},
- + {"AIN2R", NULL, "Line In Jack"},
- + {"esai-Playback", NULL, "asrc-Playback"},
- + {"codec-Playback", NULL, "esai-Playback"},/*Playback is the codec dai*/
- +};
- +
- +static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
- + struct snd_pcm_hw_params *params) {
- +
- + struct imx_priv *priv = &card_priv;
- +
- + hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min = priv->fe_output_rate;
- + hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max = priv->fe_output_rate;
- + snd_mask_none(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT));
- + if (priv->fe_output_width == 16)
- + snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
- + SNDRV_PCM_FORMAT_S16_LE);
- + else
- + snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
- + SNDRV_PCM_FORMAT_S24_LE);
- + return 0;
- +}
- +
- +static struct snd_soc_dai_link imx_cs42888_dai[] = {
- + {
- + .name = "HiFi",
- + .stream_name = "HiFi",
- + .codec_dai_name = "CS42888",
- + .ops = &imx_cs42888_surround_ops,
- + },
- + {
- + .name = "HiFi-ASRC-FE",
- + .stream_name = "HiFi-ASRC-FE",
- + .codec_name = "snd-soc-dummy",
- + .codec_dai_name = "snd-soc-dummy-dai",
- + .dynamic = 1,
- + },
- + {
- + .name = "HiFi-ASRC-BE",
- + .stream_name = "HiFi-ASRC-BE",
- + .codec_dai_name = "CS42888",
- + .platform_name = "snd-soc-dummy",
- + .no_pcm = 1,
- + .ops = &imx_cs42888_surround_ops,
- + .be_hw_params_fixup = be_hw_params_fixup,
- + },
- +};
- +
- +static struct snd_soc_card snd_soc_card_imx_cs42888 = {
- + .name = "cs42888-audio",
- + .dai_link = imx_cs42888_dai,
- + .dapm_widgets = imx_cs42888_dapm_widgets,
- + .num_dapm_widgets = ARRAY_SIZE(imx_cs42888_dapm_widgets),
- + .dapm_routes = audio_map,
- + .num_dapm_routes = ARRAY_SIZE(audio_map),
- +};
- +
- +/*
- + * This function will register the snd_soc_pcm_link drivers.
- + */
- +static int imx_cs42888_probe(struct platform_device *pdev)
- +{
- + struct device_node *esai_np, *codec_np;
- + struct device_node *asrc_np;
- + struct platform_device *esai_pdev;
- + struct platform_device *asrc_pdev = NULL;
- + struct i2c_client *codec_dev;
- + struct imx_priv *priv = &card_priv;
- + struct clk *codec_clk = NULL;
- + const char *mclk_name;
- + int ret;
- +
- + priv->pdev = pdev;
- +
- + esai_np = of_parse_phandle(pdev->dev.of_node, "esai-controller", 0);
- + codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
- + if (!esai_np || !codec_np) {
- + dev_err(&pdev->dev, "phandle missing or invalid\n");
- + ret = -EINVAL;
- + goto fail;
- + }
- +
- + asrc_np = of_parse_phandle(pdev->dev.of_node, "asrc-controller", 0);
- + if (asrc_np) {
- + asrc_pdev = of_find_device_by_node(asrc_np);
- + if (asrc_pdev) {
- + struct fsl_asrc_p2p *asrc_p2p;
- + asrc_p2p = platform_get_drvdata(asrc_pdev);
- + asrc_p2p->per_dev = ESAI;
- + priv->fe_output_rate = asrc_p2p->output_rate;
- + priv->fe_output_width = asrc_p2p->output_width;
- + }
- + }
- +
- + esai_pdev = of_find_device_by_node(esai_np);
- + if (!esai_pdev) {
- + dev_err(&pdev->dev, "failed to find ESAI platform device\n");
- + ret = -EINVAL;
- + goto fail;
- + }
- + codec_dev = of_find_i2c_device_by_node(codec_np);
- + if (!codec_dev) {
- + dev_err(&pdev->dev, "failed to find codec platform device\n");
- + ret = -EINVAL;
- + goto fail;
- + }
- +
- + /*if there is no asrc controller, we only enable one device*/
- + if (!asrc_pdev) {
- + imx_cs42888_dai[0].codec_of_node = codec_np;
- + imx_cs42888_dai[0].cpu_dai_name = dev_name(&esai_pdev->dev);
- + imx_cs42888_dai[0].platform_of_node = esai_np;
- + snd_soc_card_imx_cs42888.num_links = 1;
- + } else {
- + imx_cs42888_dai[0].codec_of_node = codec_np;
- + imx_cs42888_dai[0].cpu_dai_name = dev_name(&esai_pdev->dev);
- + imx_cs42888_dai[0].platform_of_node = esai_np;
- + imx_cs42888_dai[1].cpu_dai_name = dev_name(&asrc_pdev->dev);
- + imx_cs42888_dai[1].platform_name = "imx-pcm-asrc";
- + imx_cs42888_dai[2].codec_of_node = codec_np;
- + imx_cs42888_dai[2].cpu_dai_name = dev_name(&esai_pdev->dev);
- + snd_soc_card_imx_cs42888.num_links = 3;
- + }
- +
- + codec_clk = devm_clk_get(&codec_dev->dev, NULL);
- + if (IS_ERR(codec_clk)) {
- + ret = PTR_ERR(codec_clk);
- + dev_err(&codec_dev->dev, "failed to get codec clk: %d\n", ret);
- + goto fail;
- + }
- + priv->mclk_freq = clk_get_rate(codec_clk);
- +
- + ret = of_property_read_string(codec_np, "clock-names", &mclk_name);
- + if (ret) {
- + dev_err(&pdev->dev, "%s: failed to get mclk source\n", __func__);
- + goto fail;
- + }
- + if (!strcmp(mclk_name, "codec_osc"))
- + priv->codec_mclk = CODEC_CLK_EXTER_OSC;
- + else if (!strcmp(mclk_name, "esai"))
- + priv->codec_mclk = CODEC_CLK_ESAI_HCKT;
- + else {
- + dev_err(&pdev->dev, "mclk source is not correct %s\n", mclk_name);
- + goto fail;
- + }
- +
- + snd_soc_card_imx_cs42888.dev = &pdev->dev;
- +
- + platform_set_drvdata(pdev, &snd_soc_card_imx_cs42888);
- +
- + ret = snd_soc_register_card(&snd_soc_card_imx_cs42888);
- + if (ret)
- + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
- +fail:
- + if (esai_np)
- + of_node_put(esai_np);
- + if (codec_np)
- + of_node_put(codec_np);
- + return ret;
- +}
- +
- +static int imx_cs42888_remove(struct platform_device *pdev)
- +{
- + snd_soc_unregister_card(&snd_soc_card_imx_cs42888);
- + return 0;
- +}
- +
- +static const struct of_device_id imx_cs42888_dt_ids[] = {
- + { .compatible = "fsl,imx-audio-cs42888", },
- + { /* sentinel */ }
- +};
- +
- +static struct platform_driver imx_cs42888_driver = {
- + .probe = imx_cs42888_probe,
- + .remove = imx_cs42888_remove,
- + .driver = {
- + .name = "imx-cs42888",
- + .owner = THIS_MODULE,
- + .pm = &snd_soc_pm_ops,
- + .of_match_table = imx_cs42888_dt_ids,
- + },
- +};
- +module_platform_driver(imx_cs42888_driver);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("ALSA SoC cs42888 Machine Layer Driver");
- +MODULE_ALIAS("platform:imx-cs42888");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/imx-hdmi.c linux-3.14.35/sound/soc/fsl/imx-hdmi.c
- --- linux-3.14.35.orig/sound/soc/fsl/imx-hdmi.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/imx-hdmi.c 2015-03-08 14:27:37.913684498 -0500
- @@ -0,0 +1,113 @@
- +/*
- + * ASoC HDMI Transmitter driver for IMX development boards
- + *
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
- + *
- + * based on stmp3780_devb_hdmi.c
- + *
- + * Vladimir Barinov <vbarinov@embeddedalley.com>
- + *
- + * Copyright 2008 SigmaTel, Inc
- + * Copyright 2008 Embedded Alley Solutions, Inc
- + *
- + * This file is licensed under the terms of the GNU General Public License
- + * version 2. This program is licensed "as is" without any warranty of any
- + * kind, whether express or implied.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/of_platform.h>
- +#include <linux/mfd/mxc-hdmi-core.h>
- +#include <sound/soc.h>
- +
- +#include "imx-hdmi.h"
- +
- +/* imx digital audio interface glue - connects codec <--> CPU */
- +static struct snd_soc_dai_link imx_hdmi_dai_link = {
- + .name = "i.MX HDMI Audio Tx",
- + .stream_name = "i.MX HDMI Audio Tx",
- + .codec_dai_name = "hdmi-hifi",
- + .codec_name = "hdmi-audio-codec",
- + .platform_name = "imx-hdmi-audio",
- +};
- +
- +static struct snd_soc_card snd_soc_card_imx_hdmi = {
- + .name = "imx-hdmi-soc",
- + .dai_link = &imx_hdmi_dai_link,
- + .num_links = 1,
- +};
- +
- +static int imx_hdmi_audio_probe(struct platform_device *pdev)
- +{
- + struct device_node *hdmi_np, *np = pdev->dev.of_node;
- + struct snd_soc_card *card = &snd_soc_card_imx_hdmi;
- + struct platform_device *hdmi_pdev;
- + int ret = 0;
- +
- + if (!hdmi_get_registered()) {
- + dev_err(&pdev->dev, "initialize HDMI-audio failed. load HDMI-video first!\n");
- + return -ENODEV;
- + }
- +
- + hdmi_np = of_parse_phandle(np, "hdmi-controller", 0);
- + if (!hdmi_np) {
- + dev_err(&pdev->dev, "failed to find hdmi-audio cpudai\n");
- + ret = -EINVAL;
- + goto end;
- + }
- +
- + hdmi_pdev = of_find_device_by_node(hdmi_np);
- + if (!hdmi_pdev) {
- + dev_err(&pdev->dev, "failed to find SSI platform device\n");
- + ret = -EINVAL;
- + goto end;
- + }
- +
- + card->dev = &pdev->dev;
- + card->dai_link->cpu_dai_name = dev_name(&hdmi_pdev->dev);
- +
- + platform_set_drvdata(pdev, card);
- +
- + ret = snd_soc_register_card(card);
- + if (ret)
- + dev_err(&pdev->dev, "failed to register card: %d\n", ret);
- +
- +end:
- + if (hdmi_np)
- + of_node_put(hdmi_np);
- +
- + return ret;
- +}
- +
- +static int imx_hdmi_audio_remove(struct platform_device *pdev)
- +{
- + struct snd_soc_card *card = platform_get_drvdata(pdev);
- +
- + snd_soc_unregister_card(card);
- +
- + return 0;
- +}
- +
- +static const struct of_device_id imx_hdmi_dt_ids[] = {
- + { .compatible = "fsl,imx-audio-hdmi", },
- + { /* sentinel */ }
- +};
- +MODULE_DEVICE_TABLE(of, imx_hdmi_dt_ids);
- +
- +static struct platform_driver imx_hdmi_audio_driver = {
- + .probe = imx_hdmi_audio_probe,
- + .remove = imx_hdmi_audio_remove,
- + .driver = {
- + .of_match_table = imx_hdmi_dt_ids,
- + .name = "imx-audio-hdmi",
- + .owner = THIS_MODULE,
- + .pm = &snd_soc_pm_ops,
- + },
- +};
- +
- +module_platform_driver(imx_hdmi_audio_driver);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("IMX HDMI TX ASoC driver");
- +MODULE_LICENSE("GPL");
- +MODULE_ALIAS("platform:imx-audio-hdmi");
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/imx-hdmi-dma.c linux-3.14.35/sound/soc/fsl/imx-hdmi-dma.c
- --- linux-3.14.35.orig/sound/soc/fsl/imx-hdmi-dma.c 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/imx-hdmi-dma.c 2015-03-08 14:27:37.917684498 -0500
- @@ -0,0 +1,1240 @@
- +/*
- + * imx-hdmi-dma.c -- HDMI DMA driver for ALSA Soc Audio Layer
- + *
- + * Copyright (C) 2011-2014 Freescale Semiconductor, Inc.
- + *
- + * based on imx-pcm-dma-mx2.c
- + * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
- + *
- + * This code is based on code copyrighted by Freescale,
- + * Liam Girdwood, Javier Martin and probably others.
- + *
- + * 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.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/delay.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/mfd/mxc-hdmi-core.h>
- +#include <linux/platform_data/dma-imx.h>
- +
- +#include <video/mxc_hdmi.h>
- +
- +#include "imx-hdmi.h"
- +
- +#define HDMI_DMA_BURST_UNSPECIFIED_LEGNTH 0
- +#define HDMI_DMA_BURST_INCR4 1
- +#define HDMI_DMA_BURST_INCR8 2
- +#define HDMI_DMA_BURST_INCR16 3
- +
- +#define HDMI_BASE_ADDR 0x00120000
- +
- +struct hdmi_sdma_script {
- + int control_reg_addr;
- + int status_reg_addr;
- + int dma_start_addr;
- + u32 buffer[20];
- +};
- +
- +struct hdmi_dma_priv {
- + struct snd_pcm_substream *substream;
- + struct platform_device *pdev;
- +
- + struct snd_dma_buffer hw_buffer;
- + unsigned long buffer_bytes;
- + unsigned long appl_bytes;
- +
- + int periods;
- + int period_time;
- + int period_bytes;
- + int dma_period_bytes;
- + int buffer_ratio;
- +
- + unsigned long offset;
- +
- + snd_pcm_format_t format;
- + int sample_align;
- + int sample_bits;
- + int channels;
- + int rate;
- +
- + int frame_idx;
- +
- + bool tx_active;
- + spinlock_t irq_lock;
- +
- + /* SDMA part */
- + dma_addr_t phy_hdmi_sdma_t;
- + struct hdmi_sdma_script *hdmi_sdma_t;
- + struct dma_chan *dma_channel;
- + struct imx_dma_data dma_data;
- + struct dma_async_tx_descriptor *desc;
- + struct imx_hdmi_sdma_params sdma_params;
- +};
- +
- +/* bit 0:0:0:b:p(0):c:(u)0:(v)0 */
- +/* max 8 channels supported; channels are interleaved */
- +static u8 g_packet_head_table[48 * 8];
- +
- +/* channel remapping for hdmi_dma_copy_xxxx() */
- +static u8 g_channel_remap_table[24];
- +
- +/* default mapping tables */
- +static const u8 channel_maps_alsa_cea[5][8] = {
- + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* 0CH: no remapping */
- + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* 2CH: no remapping */
- + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* 4CH: no remapping */
- + { 0, 1, 4, 5, 3, 2, 6, 7 }, /* 6CH: ALSA5.1 to CEA */
- + { 0, 1, 6, 7, 3, 2, 4, 5 } /* 8CH: ALSA7.1 to CEA */
- +};
- +
- +static const u8 channel_maps_cea_alsa[5][8] = {
- + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* 0CH: no remapping */
- + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* 2CH: no remapping */
- + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* 4CH: no remapping */
- + { 0, 1, 5, 4, 2, 3, 6, 7 }, /* 6CH: CEA to ALSA5.1 */
- + { 0, 1, 5, 4, 6, 7, 2, 3 } /* 8CH: CEA to ALSA7.1 */
- +};
- +
- +union hdmi_audio_header_t iec_header;
- +EXPORT_SYMBOL(iec_header);
- +
- +/*
- + * Note that the period size for DMA != period size for ALSA because the
- + * driver adds iec frame info to the audio samples (in hdmi_dma_copy).
- + *
- + * Each 4 byte subframe = 1 byte of iec data + 3 byte audio sample.
- + *
- + * A 16 bit audio sample becomes 32 bits including the frame info. Ratio=2
- + * A 24 bit audio sample becomes 32 bits including the frame info. Ratio=3:4
- + * If the 24 bit raw audio is in 32 bit words, the
- + *
- + * Original Packed into subframe Ratio of size Format
- + * sample how many size of DMA buffer
- + * (bits) bits to ALSA buffer
- + * -------- ----------- -------- -------------- ------------------------
- + * 16 16 32 2 SNDRV_PCM_FORMAT_S16_LE
- + * 24 24 32 1.33 SNDRV_PCM_FORMAT_S24_3LE*
- + * 24 32 32 1 SNDRV_PCM_FORMAT_S24_LE
- + *
- + * *so SNDRV_PCM_FORMAT_S24_3LE is not supported.
- + */
- +
- +/*
- + * The minimum dma period is one IEC audio frame (192 * 4 * channels).
- + * The maximum dma period for the HDMI DMA is 8K.
- + *
- + * channels minimum maximum
- + * dma period dma period
- + * -------- ------------------ ----------
- + * 2 192 * 4 * 2 = 1536 * 4 = 6144
- + * 4 192 * 4 * 4 = 3072 * 2 = 6144
- + * 6 192 * 4 * 6 = 4608 * 1 = 4608
- + * 8 192 * 4 * 8 = 6144 * 1 = 6144
- + *
- + * Bottom line:
- + * 1. Must keep the ratio of DMA buffer to ALSA buffer consistent.
- + * 2. frame_idx is saved in the private data, so even if a frame cannot be
- + * transmitted in a period, it can be continued in the next period. This
- + * is necessary for 6 ch.
- + */
- +#define HDMI_DMA_PERIOD_BYTES (12288)
- +#define HDMI_DMA_BUF_SIZE (1280 * 1024)
- +#define HDMI_PCM_BUF_SIZE (1280 * 1024)
- +
- +#define hdmi_audio_debug(dev, reg) \
- + dev_dbg(dev, #reg ": 0x%02x\n", hdmi_readb(reg))
- +
- +#ifdef DEBUG
- +static void dumpregs(struct device *dev)
- +{
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_CONF0);
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_START);
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_STOP);
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_THRSLD);
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_STRADDR0);
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_STPADDR0);
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_BSTADDR0);
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_MBLENGTH0);
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_MBLENGTH1);
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_STAT);
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_INT);
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_MASK);
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_POL);
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_CONF1);
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_BUFFSTAT);
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_BUFFINT);
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_BUFFMASK);
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_BUFFPOL);
- + hdmi_audio_debug(dev, HDMI_IH_MUTE_AHBDMAAUD_STAT0);
- + hdmi_audio_debug(dev, HDMI_IH_AHBDMAAUD_STAT0);
- + hdmi_audio_debug(dev, HDMI_IH_MUTE);
- +}
- +
- +static void dumppriv(struct device *dev, struct hdmi_dma_priv *priv)
- +{
- + dev_dbg(dev, "channels = %d\n", priv->channels);
- + dev_dbg(dev, "periods = %d\n", priv->periods);
- + dev_dbg(dev, "period_bytes = %d\n", priv->period_bytes);
- + dev_dbg(dev, "dma period_bytes = %d\n", priv->dma_period_bytes);
- + dev_dbg(dev, "buffer_ratio = %d\n", priv->buffer_ratio);
- + dev_dbg(dev, "hw dma buffer = 0x%08x\n", (int)priv->hw_buffer.addr);
- + dev_dbg(dev, "dma buf size = %d\n", (int)priv->buffer_bytes);
- + dev_dbg(dev, "sample_rate = %d\n", (int)priv->rate);
- +}
- +#else
- +static void dumpregs(struct device *dev) {}
- +static void dumppriv(struct device *dev, struct hdmi_dma_priv *priv) {}
- +#endif
- +
- +/*
- + * Conditions for DMA to work:
- + * ((final_addr - initial_addr)>>2)+1) < 2k. So max period is 8k.
- + * (inital_addr & 0x3) == 0
- + * (final_addr & 0x3) == 0x3
- + *
- + * The DMA Period should be an integer multiple of the IEC 60958 audio
- + * frame size, which is 768 bytes (192 * 4).
- + */
- +static void hdmi_dma_set_addr(int start_addr, int dma_period_bytes)
- +{
- + int final_addr = start_addr + dma_period_bytes - 1;
- +
- + hdmi_write4(start_addr, HDMI_AHB_DMA_STRADDR0);
- + hdmi_write4(final_addr, HDMI_AHB_DMA_STPADDR0);
- +}
- +
- +static void hdmi_dma_irq_set(bool set)
- +{
- + u8 val = hdmi_readb(HDMI_AHB_DMA_MASK);
- +
- + if (set)
- + val |= HDMI_AHB_DMA_DONE;
- + else
- + val &= (u8)~HDMI_AHB_DMA_DONE;
- +
- + hdmi_writeb(val, HDMI_AHB_DMA_MASK);
- +}
- +
- +static void hdmi_mask(int mask)
- +{
- + u8 regval = hdmi_readb(HDMI_AHB_DMA_MASK);
- +
- + if (mask)
- + regval |= HDMI_AHB_DMA_ERROR | HDMI_AHB_DMA_FIFO_EMPTY;
- + else
- + regval &= (u8)~(HDMI_AHB_DMA_ERROR | HDMI_AHB_DMA_FIFO_EMPTY);
- +
- + hdmi_writeb(regval, HDMI_AHB_DMA_MASK);
- +}
- +
- +static inline int odd_ones(unsigned a)
- +{
- + a ^= a >> 16;
- + a ^= a >> 8;
- + a ^= a >> 4;
- + a ^= a >> 2;
- + a ^= a >> 1;
- +
- + return a & 1;
- +}
- +
- +/* Add frame information for one pcm subframe */
- +static u32 hdmi_dma_add_frame_info(struct hdmi_dma_priv *priv,
- + u32 pcm_data, int subframe_idx)
- +{
- + union hdmi_audio_dma_data_t subframe;
- + union hdmi_audio_header_t tmp_header;
- +
- + subframe.U = 0;
- +
- + if (priv->frame_idx < 42) {
- + tmp_header = iec_header;
- +
- + /* fill v (validity) */
- + subframe.B.v = tmp_header.B.linear_pcm;
- +
- + /* fill c (channel status) */
- + if (tmp_header.B.linear_pcm == 0)
- + tmp_header.B.channel = subframe_idx + 1;
- + subframe.B.c = tmp_header.U >> priv->frame_idx;
- + } else {
- + /* fill v (validity), c is always zero */
- + subframe.B.v = iec_header.B.linear_pcm;
- + }
- +
- + /* fill data */
- + if (priv->sample_bits == 16)
- + pcm_data <<= 8;
- + subframe.B.data = pcm_data;
- +
- + /* fill p (parity) Note: Do not include b ! */
- + subframe.B.p = odd_ones(subframe.U);
- +
- + /* fill b (start-of-block) */
- + if (priv->frame_idx == 0)
- + subframe.B.b = 1;
- +
- + return subframe.U;
- +}
- +
- +static void init_table(int channels)
- +{
- + int i, map_sel, ch;
- + unsigned char *p = g_packet_head_table;
- + union hdmi_audio_header_t tmp_header = iec_header;
- +
- + for (i = 0; i < 48; i++) {
- + int b = 0;
- + if (i == 0)
- + b = 1;
- +
- + for (ch = 0; ch < channels; ch++) {
- + int c = 0;
- + if (i < 42) {
- + tmp_header.B.channel = ch + 1;
- + c = (tmp_header.U >> i) & 0x1;
- + }
- + /* preset bit p as c */
- + *p++ = (b << 4) | (c << 2) | (c << 3);
- + }
- + }
- +
- + map_sel = channels / 2;
- + for (i = 0; i < 24; i++) {
- + g_channel_remap_table[i] = (i / channels) * channels +
- + channel_maps_cea_alsa[map_sel][i % channels];
- + }
- +}
- +
- +/* Optimization for IEC head */
- +static void hdmi_dma_copy_16_c_lut(u16 *src, u32 *dst, int samples,
- + u8 *lookup_table)
- +{
- + u32 sample, head;
- + int i = 0;
- +
- + while (samples--) {
- + /* get source sample */
- + sample = src[g_channel_remap_table[i]];
- +
- + /* get packet header and p-bit */
- + head = *lookup_table++ ^ (odd_ones(sample) << 3);
- +
- + /* store sample and header */
- + *dst++ = (head << 24) | (sample << 8);
- +
- + if (++i == 24) {
- + src += 24;
- + i = 0;
- + }
- + }
- +}
- +
- +static void hdmi_dma_copy_16_c_fast(u16 *src, u32 *dst, int samples)
- +{
- + u32 sample;
- + int i = 0;
- +
- + while (samples--) {
- + /* get source sample */
- + sample = src[g_channel_remap_table[i]];
- +
- + /* store sample and p-bit */
- + *dst++ = (odd_ones(sample) << (3+24)) | (sample << 8);
- +
- + if (++i == 24) {
- + src += 24;
- + i = 0;
- + }
- + }
- +}
- +
- +static void hdmi_dma_copy_24_c_lut(u32 *src, u32 *dst, int samples,
- + u8 *lookup_table)
- +{
- + u32 sample, head;
- + int i = 0;
- +
- + while (samples--) {
- + /* get source sample */
- + sample = src[g_channel_remap_table[i]] & 0x00ffffff;
- +
- + /* get packet header and p-bit */
- + head = *lookup_table++ ^ (odd_ones(sample) << 3);
- +
- + /* store sample and header */
- + *dst++ = (head << 24) | sample;
- +
- + if (++i == 24) {
- + src += 24;
- + i = 0;
- + }
- + }
- +}
- +
- +static void hdmi_dma_copy_24_c_fast(u32 *src, u32 *dst, int samples)
- +{
- + u32 sample;
- + int i = 0;
- +
- + while (samples--) {
- + /* get source sample */
- + sample = src[g_channel_remap_table[i]] & 0x00ffffff;
- +
- + /* store sample and p-bit */
- + *dst++ = (odd_ones(sample) << (3+24)) | sample;
- +
- + if (++i == 24) {
- + src += 24;
- + i = 0;
- + }
- + }
- +}
- +
- +static void hdmi_mmap_copy(u8 *src, int samplesize, u32 *dst, int framecnt, int channelcnt)
- +{
- + /* split input frames into 192-frame each */
- + int count_in_192 = (framecnt + 191) / 192;
- + int i;
- +
- + typedef void (*fn_copy_lut)(u8 *src, u32 *dst, int samples, u8 *lookup_table);
- + typedef void (*fn_copy_fast)(u8 *src, u32 *dst, int samples);
- + fn_copy_lut copy_lut;
- + fn_copy_fast copy_fast;
- +
- + if (samplesize == 4) {
- + copy_lut = (fn_copy_lut)hdmi_dma_copy_24_c_lut;
- + copy_fast = (fn_copy_fast)hdmi_dma_copy_24_c_fast;
- + } else {
- + copy_lut = (fn_copy_lut)hdmi_dma_copy_16_c_lut;
- + copy_fast = (fn_copy_fast)hdmi_dma_copy_16_c_fast;
- + }
- +
- + for (i = 0; i < count_in_192; i++) {
- + int count, samples;
- +
- + /* handles frame index [0, 48) */
- + count = (framecnt < 48) ? framecnt : 48;
- + samples = count * channelcnt;
- + copy_lut(src, dst, samples, g_packet_head_table);
- + framecnt -= count;
- + if (framecnt == 0)
- + break;
- +
- + src += samples * samplesize;
- + dst += samples;
- +
- + /* handles frame index [48, 192) */
- + count = (framecnt < 192 - 48) ? framecnt : 192 - 48;
- + samples = count * channelcnt;
- + copy_fast(src, dst, samples);
- + framecnt -= count;
- + src += samples * samplesize;
- + dst += samples;
- + }
- +}
- +
- +static void hdmi_dma_mmap_copy(struct snd_pcm_substream *substream,
- + int offset, int count)
- +{
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + struct hdmi_dma_priv *priv = runtime->private_data;
- + struct device *dev = rtd->platform->dev;
- + u32 framecount, *dst;
- +
- + framecount = count / (priv->sample_align * priv->channels);
- +
- + /* hw_buffer is the destination for pcm data plus frame info. */
- + dst = (u32 *)(priv->hw_buffer.area + (offset * priv->buffer_ratio));
- +
- + switch (priv->format) {
- + case SNDRV_PCM_FORMAT_S16_LE:
- + case SNDRV_PCM_FORMAT_S24_LE:
- + /* dma_buffer is the mmapped buffer we are copying pcm from. */
- + hdmi_mmap_copy(runtime->dma_area + offset,
- + priv->sample_align, dst, framecount, priv->channels);
- + break;
- + default:
- + dev_err(dev, "unsupported sample format %s\n",
- + snd_pcm_format_name(priv->format));
- + return;
- + }
- +}
- +
- +static void hdmi_dma_data_copy(struct snd_pcm_substream *substream,
- + struct hdmi_dma_priv *priv, char type)
- +{
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + unsigned long offset, count, appl_bytes, space_to_end;
- +
- + if (runtime->access != SNDRV_PCM_ACCESS_MMAP_INTERLEAVED)
- + return;
- +
- + appl_bytes = frames_to_bytes(runtime, runtime->status->hw_ptr);
- +
- + switch (type) {
- + case 'p':
- + offset = (appl_bytes + 2 * priv->period_bytes) % priv->buffer_bytes;
- + count = priv->period_bytes;
- + space_to_end = priv->period_bytes;
- + break;
- + case 'b':
- + offset = appl_bytes % priv->buffer_bytes;
- + count = priv->buffer_bytes;
- + space_to_end = priv->buffer_bytes - offset;
- + break;
- + default:
- + return;
- + }
- +
- + if (count <= space_to_end) {
- + hdmi_dma_mmap_copy(substream, offset, count);
- + } else {
- + hdmi_dma_mmap_copy(substream, offset, space_to_end);
- + hdmi_dma_mmap_copy(substream, 0, count - space_to_end);
- + }
- +}
- +
- +static void hdmi_sdma_callback(void *data)
- +{
- + struct hdmi_dma_priv *priv = (struct hdmi_dma_priv *)data;
- + struct snd_pcm_substream *substream = priv->substream;
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&priv->irq_lock, flags);
- +
- + if (runtime && runtime->dma_area && priv->tx_active) {
- + priv->offset += priv->period_bytes;
- + priv->offset %= priv->period_bytes * priv->periods;
- +
- + /* Copy data by period_bytes */
- + hdmi_dma_data_copy(substream, priv, 'p');
- +
- + snd_pcm_period_elapsed(substream);
- + }
- +
- + spin_unlock_irqrestore(&priv->irq_lock, flags);
- +
- + return;
- +}
- +
- +static int hdmi_dma_set_thrsld_incrtype(struct device *dev, int channels)
- +{
- + u8 mask = HDMI_AHB_DMA_CONF0_BURST_MODE | HDMI_AHB_DMA_CONF0_INCR_TYPE_MASK;
- + u8 val = hdmi_readb(HDMI_AHB_DMA_CONF0) & ~mask;
- + int incr_type, threshold;
- +
- + switch (hdmi_readb(HDMI_REVISION_ID)) {
- + case 0x0a:
- + incr_type = HDMI_DMA_BURST_INCR4;
- + if (channels == 2)
- + threshold = 126;
- + else
- + threshold = 124;
- + break;
- + case 0x1a:
- + incr_type = HDMI_DMA_BURST_INCR8;
- + threshold = 128;
- + break;
- + default:
- + dev_err(dev, "unknown hdmi controller!\n");
- + return -ENODEV;
- + }
- +
- + hdmi_writeb(threshold, HDMI_AHB_DMA_THRSLD);
- +
- + switch (incr_type) {
- + case HDMI_DMA_BURST_UNSPECIFIED_LEGNTH:
- + break;
- + case HDMI_DMA_BURST_INCR4:
- + val |= HDMI_AHB_DMA_CONF0_BURST_MODE;
- + break;
- + case HDMI_DMA_BURST_INCR8:
- + val |= HDMI_AHB_DMA_CONF0_BURST_MODE |
- + HDMI_AHB_DMA_CONF0_INCR8;
- + break;
- + case HDMI_DMA_BURST_INCR16:
- + val |= HDMI_AHB_DMA_CONF0_BURST_MODE |
- + HDMI_AHB_DMA_CONF0_INCR16;
- + break;
- + default:
- + dev_err(dev, "invalid increment type: %d!", incr_type);
- + return -EINVAL;
- + }
- +
- + hdmi_writeb(val, HDMI_AHB_DMA_CONF0);
- +
- + hdmi_audio_debug(dev, HDMI_AHB_DMA_THRSLD);
- +
- + return 0;
- +}
- +
- +static int hdmi_dma_configure_dma(struct device *dev, int channels)
- +{
- + int ret;
- + static u8 chan_enable[] = { 0x00, 0x03, 0x33, 0x3f, 0xff };
- +
- + if (channels <= 0 || channels > 8 || channels % 2 != 0) {
- + dev_err(dev, "unsupported channel number: %d\n", channels);
- + return -EINVAL;
- + }
- +
- + hdmi_audio_writeb(AHB_DMA_CONF0, EN_HLOCK, 0x1);
- +
- + ret = hdmi_dma_set_thrsld_incrtype(dev, channels);
- + if (ret)
- + return ret;
- +
- + hdmi_writeb(chan_enable[channels / 2], HDMI_AHB_DMA_CONF1);
- +
- + return 0;
- +}
- +
- +static void hdmi_dma_init_iec_header(void)
- +{
- + iec_header.U = 0;
- +
- + iec_header.B.consumer = 0; /* Consumer use */
- + iec_header.B.linear_pcm = 0; /* linear pcm audio */
- + iec_header.B.copyright = 1; /* no copyright */
- + iec_header.B.pre_emphasis = 0; /* 2 channels without pre-emphasis */
- + iec_header.B.mode = 0; /* Mode 0 */
- +
- + iec_header.B.category_code = 0;
- +
- + iec_header.B.source = 2; /* stereo */
- + iec_header.B.channel = 0;
- +
- + iec_header.B.sample_freq = 0x02; /* 48 KHz */
- + iec_header.B.clock_acc = 0; /* Level II */
- +
- + iec_header.B.word_length = 0x02; /* 16 bits */
- + iec_header.B.org_sample_freq = 0x0D; /* 48 KHz */
- +
- + iec_header.B.cgms_a = 0; /* Copying is permitted without restriction */
- +}
- +
- +static int hdmi_dma_update_iec_header(struct snd_pcm_substream *substream)
- +{
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + struct hdmi_dma_priv *priv = runtime->private_data;
- + struct device *dev = rtd->platform->dev;
- +
- + iec_header.B.source = priv->channels;
- +
- + switch (priv->rate) {
- + case 32000:
- + iec_header.B.sample_freq = 0x03;
- + iec_header.B.org_sample_freq = 0x0C;
- + break;
- + case 44100:
- + iec_header.B.sample_freq = 0x00;
- + iec_header.B.org_sample_freq = 0x0F;
- + break;
- + case 48000:
- + iec_header.B.sample_freq = 0x02;
- + iec_header.B.org_sample_freq = 0x0D;
- + break;
- + case 88200:
- + iec_header.B.sample_freq = 0x08;
- + iec_header.B.org_sample_freq = 0x07;
- + break;
- + case 96000:
- + iec_header.B.sample_freq = 0x0A;
- + iec_header.B.org_sample_freq = 0x05;
- + break;
- + case 176400:
- + iec_header.B.sample_freq = 0x0C;
- + iec_header.B.org_sample_freq = 0x03;
- + break;
- + case 192000:
- + iec_header.B.sample_freq = 0x0E;
- + iec_header.B.org_sample_freq = 0x01;
- + break;
- + default:
- + dev_err(dev, "unsupported sample rate\n");
- + return -EFAULT;
- + }
- +
- + switch (priv->format) {
- + case SNDRV_PCM_FORMAT_S16_LE:
- + iec_header.B.word_length = 0x02;
- + break;
- + case SNDRV_PCM_FORMAT_S24_LE:
- + iec_header.B.word_length = 0x0b;
- + break;
- + default:
- + return -EFAULT;
- + }
- +
- + return 0;
- +}
- +
- +/*
- + * The HDMI block transmits the audio data without adding any of the audio
- + * frame bits. So we have to copy the raw dma data from the ALSA buffer
- + * to the DMA buffer, adding the frame information.
- + */
- +static int hdmi_dma_copy(struct snd_pcm_substream *substream, int channel,
- + snd_pcm_uframes_t pos, void __user *buf,
- + snd_pcm_uframes_t frames)
- +{
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + struct hdmi_dma_priv *priv = runtime->private_data;
- + unsigned int count = frames_to_bytes(runtime, frames);
- + unsigned int pos_bytes = frames_to_bytes(runtime, pos);
- + int channel_no, pcm_idx, subframe_idx, bits_left, sample_bits, map_sel;
- + u32 pcm_data[8], pcm_temp, *hw_buf, sample_block, inc_mask;
- +
- + /* Adding frame info to pcm data from userspace and copy to hw_buffer */
- + hw_buf = (u32 *)(priv->hw_buffer.area + (pos_bytes * priv->buffer_ratio));
- +
- + sample_bits = priv->sample_align * 8;
- + sample_block = priv->sample_align * priv->channels;
- +
- + if (iec_header.B.linear_pcm == 0) {
- + map_sel = priv->channels / 2;
- + inc_mask = 1 << (priv->channels - 1);
- + } else {
- + map_sel = 0;
- + inc_mask = 0xaa;
- + }
- +
- + while (count > 0) {
- + if (copy_from_user(pcm_data, buf, sample_block))
- + return -EFAULT;
- +
- + buf += sample_block;
- + count -= sample_block;
- +
- + channel_no = pcm_idx = 0;
- + do {
- + pcm_temp = pcm_data[pcm_idx++];
- + bits_left = 32;
- + for (;;) {
- + /* re-map channels */
- + subframe_idx = channel_maps_alsa_cea[map_sel][channel_no];
- +
- + /* Save the header info to the audio dma buffer */
- + hw_buf[subframe_idx] = hdmi_dma_add_frame_info(
- + priv, pcm_temp, subframe_idx);
- +
- + if (inc_mask & (1 << channel_no)) {
- + if (++priv->frame_idx == 192)
- + priv->frame_idx = 0;
- + }
- +
- + channel_no++;
- +
- + if (bits_left <= sample_bits)
- + break;
- +
- + bits_left -= sample_bits;
- + pcm_temp >>= sample_bits;
- + }
- + } while (channel_no < priv->channels);
- +
- + hw_buf += priv->channels;
- + }
- +
- + return 0;
- +}
- +
- +static int hdmi_sdma_initbuf(struct device *dev, struct hdmi_dma_priv *priv)
- +{
- + struct hdmi_sdma_script *hdmi_sdma_t = priv->hdmi_sdma_t;
- + u32 *head, *tail, i;
- +
- + if (!hdmi_sdma_t) {
- + dev_err(dev, "hdmi private addr invalid!!!\n");
- + return -EINVAL;
- + }
- +
- + hdmi_sdma_t->control_reg_addr = HDMI_BASE_ADDR + HDMI_AHB_DMA_START;
- + hdmi_sdma_t->status_reg_addr = HDMI_BASE_ADDR + HDMI_IH_AHBDMAAUD_STAT0;
- + hdmi_sdma_t->dma_start_addr = HDMI_BASE_ADDR + HDMI_AHB_DMA_STRADDR0;
- +
- + head = &hdmi_sdma_t->buffer[0];
- + tail = &hdmi_sdma_t->buffer[1];
- +
- + for (i = 0; i < priv->sdma_params.buffer_num; i++) {
- + *head = priv->hw_buffer.addr + i * priv->period_bytes * priv->buffer_ratio;
- + *tail = *head + priv->dma_period_bytes - 1;
- + head += 2;
- + tail += 2;
- + }
- +
- + return 0;
- +}
- +
- +static int hdmi_sdma_config(struct snd_pcm_substream *substream,
- + struct hdmi_dma_priv *priv)
- +{
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct device *dai_dev = &priv->pdev->dev;
- + struct device *dev = rtd->platform->dev;
- + struct dma_slave_config slave_config;
- + int ret;
- +
- + priv->dma_channel = dma_request_slave_channel(dai_dev, "tx");
- + if (priv->dma_channel == NULL) {
- + dev_err(dev, "failed to alloc dma channel\n");
- + return -EBUSY;
- + }
- +
- + priv->dma_data.data_addr1 = &priv->sdma_params.buffer_num;
- + priv->dma_data.data_addr2 = &priv->sdma_params.phyaddr;
- + priv->dma_channel->private = &priv->dma_data;
- +
- + slave_config.direction = DMA_TRANS_NONE;
- + slave_config.dma_request0 = 0;
- + slave_config.dma_request1 = 0;
- +
- + ret = dmaengine_slave_config(priv->dma_channel, &slave_config);
- + if (ret) {
- + dev_err(dev, "failed to config slave dma\n");
- + return -EINVAL;
- + }
- +
- + return 0;
- +}
- +
- +static int hdmi_dma_hw_free(struct snd_pcm_substream *substream)
- +{
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + struct hdmi_dma_priv *priv = runtime->private_data;
- +
- + if (priv->dma_channel) {
- + dma_release_channel(priv->dma_channel);
- + priv->dma_channel = NULL;
- + }
- +
- + return 0;
- +}
- +
- +static int hdmi_dma_hw_params(struct snd_pcm_substream *substream,
- + struct snd_pcm_hw_params *params)
- +{
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + struct hdmi_dma_priv *priv = runtime->private_data;
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct device *dev = rtd->platform->dev;
- + int ret;
- +
- + priv->buffer_bytes = params_buffer_bytes(params);
- + priv->periods = params_periods(params);
- + priv->period_bytes = params_period_bytes(params);
- + priv->channels = params_channels(params);
- + priv->format = params_format(params);
- + priv->rate = params_rate(params);
- +
- + priv->offset = 0;
- + priv->period_time = HZ / (priv->rate / params_period_size(params));
- +
- + switch (priv->format) {
- + case SNDRV_PCM_FORMAT_S16_LE:
- + priv->buffer_ratio = 2;
- + priv->sample_align = 2;
- + priv->sample_bits = 16;
- + break;
- + case SNDRV_PCM_FORMAT_S24_LE:
- + /* 24 bit audio in 32 bit word */
- + priv->buffer_ratio = 1;
- + priv->sample_align = 4;
- + priv->sample_bits = 24;
- + break;
- + default:
- + dev_err(dev, "unsupported sample format: %d\n", priv->format);
- + return -EINVAL;
- + }
- +
- + priv->dma_period_bytes = priv->period_bytes * priv->buffer_ratio;
- + priv->sdma_params.buffer_num = priv->periods;
- + priv->sdma_params.phyaddr = priv->phy_hdmi_sdma_t;
- +
- + ret = hdmi_sdma_initbuf(dev, priv);
- + if (ret)
- + return ret;
- +
- + ret = hdmi_sdma_config(substream, priv);
- + if (ret)
- + return ret;
- +
- + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- +
- + ret = hdmi_dma_configure_dma(dev, priv->channels);
- + if (ret)
- + return ret;
- +
- + hdmi_dma_set_addr(priv->hw_buffer.addr, priv->dma_period_bytes);
- +
- + dumppriv(dev, priv);
- +
- + hdmi_dma_update_iec_header(substream);
- +
- + /* Init par for mmap optimizate */
- + init_table(priv->channels);
- +
- + priv->appl_bytes = 0;
- + priv->frame_idx = 0;
- +
- + return 0;
- +}
- +
- +static void hdmi_dma_trigger_init(struct snd_pcm_substream *substream,
- + struct hdmi_dma_priv *priv)
- +{
- + unsigned long status;
- + bool hbr;
- +
- + /*
- + * Set HBR mode (>192kHz IEC-61937 HD audio bitstreaming).
- + * This is done this late because userspace may alter the AESx
- + * parameters until the stream is finally prepared.
- + */
- + hbr = (iec_header.B.linear_pcm != 0 && priv->channels == 8);
- + hdmi_audio_writeb(AHB_DMA_CONF0, HBR, !!hbr);
- +
- + /*
- + * Override AES3 - parameter: This is a temporary hack for
- + * callers that provide incorrect information when opening
- + * the device. 0x09 (i.e. 768K) is the only acceptable value.
- + */
- + if (hbr) {
- + iec_header.B.sample_freq = 0x09;
- + iec_header.B.org_sample_freq = 0x00;
- + }
- +
- + priv->offset = 0;
- +
- + /* Copy data by buffer_bytes */
- + hdmi_dma_data_copy(substream, priv, 'b');
- +
- + hdmi_audio_writeb(AHB_DMA_CONF0, SW_FIFO_RST, 0x1);
- +
- + /* Delay after reset */
- + udelay(1);
- +
- + status = hdmi_readb(HDMI_IH_AHBDMAAUD_STAT0);
- + hdmi_writeb(status, HDMI_IH_AHBDMAAUD_STAT0);
- +}
- +
- +static int hdmi_dma_prepare_and_submit(struct snd_pcm_substream *substream,
- + struct hdmi_dma_priv *priv)
- +{
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct device *dev = rtd->platform->dev;
- +
- + priv->desc = dmaengine_prep_dma_cyclic(priv->dma_channel, 0, 0, 0,
- + DMA_TRANS_NONE, 0);
- + if (!priv->desc) {
- + dev_err(dev, "failed to prepare slave dma\n");
- + return -EINVAL;
- + }
- +
- + priv->desc->callback = hdmi_sdma_callback;
- + priv->desc->callback_param = (void *)priv;
- + dmaengine_submit(priv->desc);
- +
- + return 0;
- +}
- +
- +static int hdmi_dma_trigger(struct snd_pcm_substream *substream, int cmd)
- +{
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct hdmi_dma_priv *priv = runtime->private_data;
- + struct device *dev = rtd->platform->dev;
- + int ret;
- +
- + switch (cmd) {
- + case SNDRV_PCM_TRIGGER_START:
- + case SNDRV_PCM_TRIGGER_RESUME:
- + if (!check_hdmi_state())
- + return 0;
- + hdmi_dma_trigger_init(substream, priv);
- +
- + dumpregs(dev);
- +
- + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- + priv->tx_active = true;
- + hdmi_audio_writeb(AHB_DMA_START, START, 0x1);
- + hdmi_dma_irq_set(false);
- + hdmi_set_dma_mode(1);
- + ret = hdmi_dma_prepare_and_submit(substream, priv);
- + if (ret)
- + return ret;
- + dma_async_issue_pending(priv->desc->chan);
- + break;
- + case SNDRV_PCM_TRIGGER_STOP:
- + case SNDRV_PCM_TRIGGER_SUSPEND:
- + case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- + dmaengine_terminate_all(priv->dma_channel);
- + hdmi_set_dma_mode(0);
- + hdmi_dma_irq_set(true);
- + hdmi_audio_writeb(AHB_DMA_STOP, STOP, 0x1);
- + priv->tx_active = false;
- + break;
- + default:
- + return -EINVAL;
- + }
- +
- + return 0;
- +}
- +
- +static snd_pcm_uframes_t hdmi_dma_pointer(struct snd_pcm_substream *substream)
- +{
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + struct hdmi_dma_priv *priv = runtime->private_data;
- +
- + return bytes_to_frames(runtime, priv->offset);
- +}
- +
- +static struct snd_pcm_hardware snd_imx_hardware = {
- + .info = SNDRV_PCM_INFO_INTERLEAVED |
- + SNDRV_PCM_INFO_BLOCK_TRANSFER |
- + SNDRV_PCM_INFO_MMAP |
- + SNDRV_PCM_INFO_MMAP_VALID |
- + SNDRV_PCM_INFO_PAUSE |
- + SNDRV_PCM_INFO_RESUME,
- + .formats = MXC_HDMI_FORMATS_PLAYBACK,
- + .rate_min = 32000,
- + .channels_min = 2,
- + .channels_max = 8,
- + .buffer_bytes_max = HDMI_PCM_BUF_SIZE,
- + .period_bytes_min = HDMI_DMA_PERIOD_BYTES / 2,
- + .period_bytes_max = HDMI_DMA_PERIOD_BYTES / 2,
- + .periods_min = 8,
- + .periods_max = HDMI_DMA_BUF_SIZE / HDMI_DMA_PERIOD_BYTES,
- + .fifo_size = 0,
- +};
- +
- +static void hdmi_dma_irq_enable(struct hdmi_dma_priv *priv)
- +{
- + unsigned long flags;
- +
- + hdmi_writeb(0xff, HDMI_AHB_DMA_POL);
- + hdmi_writeb(0xff, HDMI_AHB_DMA_BUFFPOL);
- +
- + spin_lock_irqsave(&priv->irq_lock, flags);
- +
- + hdmi_writeb(0xff, HDMI_IH_AHBDMAAUD_STAT0);
- + hdmi_writeb(0xff, HDMI_IH_MUTE_AHBDMAAUD_STAT0);
- + hdmi_dma_irq_set(false);
- + hdmi_mask(0);
- +
- + spin_unlock_irqrestore(&priv->irq_lock, flags);
- +}
- +
- +static void hdmi_dma_irq_disable(struct hdmi_dma_priv *priv)
- +{
- + unsigned long flags;
- +
- + spin_lock_irqsave(&priv->irq_lock, flags);
- +
- + hdmi_dma_irq_set(true);
- + hdmi_writeb(0x0, HDMI_IH_MUTE_AHBDMAAUD_STAT0);
- + hdmi_writeb(0xff, HDMI_IH_AHBDMAAUD_STAT0);
- + hdmi_mask(1);
- +
- + spin_unlock_irqrestore(&priv->irq_lock, flags);
- +}
- +
- +static int hdmi_dma_open(struct snd_pcm_substream *substream)
- +{
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct device *dev = rtd->platform->dev;
- + struct hdmi_dma_priv *priv = dev_get_drvdata(dev);
- + int ret;
- +
- + runtime->private_data = priv;
- +
- + ret = mxc_hdmi_register_audio(substream);
- + if (ret < 0) {
- + dev_err(dev, "HDMI Video is not ready!\n");
- + return ret;
- + }
- +
- + hdmi_audio_writeb(AHB_DMA_CONF0, SW_FIFO_RST, 0x1);
- +
- + ret = snd_pcm_hw_constraint_integer(substream->runtime,
- + SNDRV_PCM_HW_PARAM_PERIODS);
- + if (ret < 0)
- + return ret;
- +
- + snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
- +
- + hdmi_dma_irq_enable(priv);
- +
- + return 0;
- +}
- +
- +static int hdmi_dma_close(struct snd_pcm_substream *substream)
- +{
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + struct hdmi_dma_priv *priv = runtime->private_data;
- +
- + hdmi_dma_irq_disable(priv);
- + mxc_hdmi_unregister_audio(substream);
- +
- + return 0;
- +}
- +
- +static struct snd_pcm_ops imx_hdmi_dma_pcm_ops = {
- + .open = hdmi_dma_open,
- + .close = hdmi_dma_close,
- + .ioctl = snd_pcm_lib_ioctl,
- + .hw_params = hdmi_dma_hw_params,
- + .hw_free = hdmi_dma_hw_free,
- + .trigger = hdmi_dma_trigger,
- + .pointer = hdmi_dma_pointer,
- + .copy = hdmi_dma_copy,
- +};
- +
- +static int imx_hdmi_dma_pcm_new(struct snd_soc_pcm_runtime *rtd)
- +{
- + struct hdmi_dma_priv *priv = dev_get_drvdata(rtd->platform->dev);
- + struct snd_card *card = rtd->card->snd_card;
- + struct snd_pcm_substream *substream;
- + struct snd_pcm *pcm = rtd->pcm;
- + u64 dma_mask = DMA_BIT_MASK(32);
- + int ret = 0;
- +
- + if (!card->dev->dma_mask)
- + card->dev->dma_mask = &dma_mask;
- + if (!card->dev->coherent_dma_mask)
- + card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- +
- + substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
- +
- + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
- + HDMI_PCM_BUF_SIZE, &substream->dma_buffer);
- + if (ret) {
- + dev_err(card->dev, "failed to alloc playback dma buffer\n");
- + return ret;
- + }
- +
- + priv->substream = substream;
- +
- + /* Alloc the hw_buffer */
- + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
- + HDMI_DMA_BUF_SIZE, &priv->hw_buffer);
- + if (ret) {
- + dev_err(card->dev, "failed to alloc hw dma buffer\n");
- + return ret;
- + }
- +
- + return ret;
- +}
- +
- +static void imx_hdmi_dma_pcm_free(struct snd_pcm *pcm)
- +{
- + int stream = SNDRV_PCM_STREAM_PLAYBACK;
- + struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- + struct snd_soc_pcm_runtime *rtd = pcm->private_data;
- + struct hdmi_dma_priv *priv = dev_get_drvdata(rtd->platform->dev);
- +
- + if (substream) {
- + snd_dma_free_pages(&substream->dma_buffer);
- + substream->dma_buffer.area = NULL;
- + substream->dma_buffer.addr = 0;
- + }
- +
- + /* Free the hw_buffer */
- + snd_dma_free_pages(&priv->hw_buffer);
- + priv->hw_buffer.area = NULL;
- + priv->hw_buffer.addr = 0;
- +}
- +
- +static struct snd_soc_platform_driver imx_hdmi_platform = {
- + .ops = &imx_hdmi_dma_pcm_ops,
- + .pcm_new = imx_hdmi_dma_pcm_new,
- + .pcm_free = imx_hdmi_dma_pcm_free,
- +};
- +
- +static int imx_soc_platform_probe(struct platform_device *pdev)
- +{
- + struct imx_hdmi *hdmi_drvdata = platform_get_drvdata(pdev);
- + struct hdmi_dma_priv *priv;
- + int ret = 0;
- +
- + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- + if (!priv) {
- + dev_err(&pdev->dev, "Failed to alloc hdmi_dma\n");
- + return -ENOMEM;
- + }
- +
- + priv->hdmi_sdma_t = dma_alloc_coherent(NULL,
- + sizeof(struct hdmi_sdma_script),
- + &priv->phy_hdmi_sdma_t, GFP_KERNEL);
- + if (!priv->hdmi_sdma_t) {
- + dev_err(&pdev->dev, "Failed to alloc hdmi_sdma_t\n");
- + return -ENOMEM;
- + }
- +
- + priv->tx_active = false;
- + spin_lock_init(&priv->irq_lock);
- +
- + priv->pdev = hdmi_drvdata->pdev;
- +
- + hdmi_dma_init_iec_header();
- +
- + dev_set_drvdata(&pdev->dev, priv);
- +
- + switch (hdmi_readb(HDMI_REVISION_ID)) {
- + case 0x0a:
- + snd_imx_hardware.period_bytes_max = HDMI_DMA_PERIOD_BYTES / 4;
- + snd_imx_hardware.period_bytes_min = HDMI_DMA_PERIOD_BYTES / 4;
- + snd_imx_hardware.periods_max = HDMI_DMA_BUF_SIZE / (HDMI_DMA_PERIOD_BYTES / 2);
- + break;
- + default:
- + break;
- + }
- +
- + ret = snd_soc_register_platform(&pdev->dev, &imx_hdmi_platform);
- + if (ret)
- + goto err_plat;
- +
- + return 0;
- +
- +err_plat:
- + dma_free_coherent(NULL, sizeof(struct hdmi_sdma_script),
- + priv->hdmi_sdma_t, priv->phy_hdmi_sdma_t);
- +
- + return ret;
- +}
- +
- +static int imx_soc_platform_remove(struct platform_device *pdev)
- +{
- + struct hdmi_dma_priv *priv = dev_get_drvdata(&pdev->dev);
- +
- + dma_free_coherent(NULL, sizeof(struct hdmi_sdma_script),
- + priv->hdmi_sdma_t, priv->phy_hdmi_sdma_t);
- +
- + snd_soc_unregister_platform(&pdev->dev);
- +
- + return 0;
- +}
- +
- +static struct platform_driver imx_hdmi_dma_driver = {
- + .driver = {
- + .name = "imx-hdmi-audio",
- + .owner = THIS_MODULE,
- + },
- + .probe = imx_soc_platform_probe,
- + .remove = imx_soc_platform_remove,
- +};
- +
- +module_platform_driver(imx_hdmi_dma_driver);
- +
- +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
- +MODULE_DESCRIPTION("i.MX HDMI audio DMA");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/imx-hdmi.h linux-3.14.35/sound/soc/fsl/imx-hdmi.h
- --- linux-3.14.35.orig/sound/soc/fsl/imx-hdmi.h 1969-12-31 18:00:00.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/imx-hdmi.h 2015-03-08 14:27:37.917684498 -0500
- @@ -0,0 +1,105 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, 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 program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * 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.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + */
- +
- +#ifndef __IMX_HDMI_H
- +#define __IMX_HDMI_H
- +
- +struct imx_hdmi_sdma_params {
- + dma_addr_t phyaddr;
- + u32 buffer_num;
- + int dma;
- +};
- +
- +struct imx_hdmi {
- + struct snd_soc_dai_driver cpu_dai_drv;
- + struct platform_device *codec_dev;
- + struct platform_device *dma_dev;
- + struct platform_device *pdev;
- + struct clk *isfr_clk;
- + struct clk *iahb_clk;
- +};
- +
- +#define HDMI_MAX_RATES 7
- +#define HDMI_MAX_SAMPLE_SIZE 3
- +#define HDMI_MAX_CHANNEL_CONSTRAINTS 4
- +
- +#define MXC_HDMI_RATES_PLAYBACK \
- + (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
- + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
- + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
- +
- +#define MXC_HDMI_FORMATS_PLAYBACK \
- + (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
- +
- +union hdmi_audio_header_t {
- + uint64_t U;
- + struct {
- + unsigned consumer:1;
- + unsigned linear_pcm:1;
- + unsigned copyright:1;
- + unsigned pre_emphasis:3;
- + unsigned mode:2;
- +
- + unsigned category_code:8;
- +
- + unsigned source:4;
- + unsigned channel:4;
- +
- + unsigned sample_freq:4;
- + unsigned clock_acc:2;
- + unsigned reserved0:2;
- +
- + unsigned word_length:4;
- + unsigned org_sample_freq:4;
- +
- + unsigned cgms_a:2;
- + unsigned reserved1:6;
- +
- + unsigned reserved2:8;
- +
- + unsigned reserved3:8;
- + } B;
- + unsigned char status[8];
- +};
- +
- +union hdmi_audio_dma_data_t {
- + uint32_t U;
- + struct {
- + unsigned data:24;
- + unsigned v:1;
- + unsigned u:1;
- + unsigned c:1;
- + unsigned p:1;
- + unsigned b:1;
- + unsigned reserved:3;
- + } B;
- +};
- +
- +extern union hdmi_audio_header_t iec_header;
- +
- +#define hdmi_audio_writeb(reg, bit, val) \
- + do { \
- + hdmi_mask_writeb(val, HDMI_ ## reg, \
- + HDMI_ ## reg ## _ ## bit ## _OFFSET, \
- + HDMI_ ## reg ## _ ## bit ## _MASK); \
- + pr_debug("Set reg: HDMI_" #reg " (0x%x) "\
- + "bit: HDMI_" #reg "_" #bit " (%d) to val: %x\n", \
- + HDMI_ ## reg, HDMI_ ## reg ## _ ## bit ## _OFFSET, val); \
- + } while (0)
- +
- +#endif /* __IMX_HDMI_H */
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/imx-pcm-dma.c linux-3.14.35/sound/soc/fsl/imx-pcm-dma.c
- --- linux-3.14.35.orig/sound/soc/fsl/imx-pcm-dma.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/imx-pcm-dma.c 2015-03-08 14:27:37.917684498 -0500
- @@ -11,6 +11,10 @@
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
- +#include <linux/init.h>
- +#include <linux/kernel.h>
- +#include <linux/module.h>
- +#include <linux/device.h>
- #include <linux/platform_device.h>
- #include <linux/dmaengine.h>
- #include <linux/types.h>
- @@ -20,6 +24,7 @@
- #include <sound/pcm.h>
- #include <sound/soc.h>
- #include <sound/dmaengine_pcm.h>
- +#include <linux/platform_data/dma-imx.h>
-
- #include "imx-pcm.h"
-
- @@ -40,28 +45,97 @@
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_RESUME,
- - .formats = SNDRV_PCM_FMTBIT_S16_LE,
- - .buffer_bytes_max = IMX_SSI_DMABUF_SIZE,
- + .formats = SNDRV_PCM_FMTBIT_S16_LE |
- + SNDRV_PCM_FMTBIT_S24_LE |
- + SNDRV_PCM_FMTBIT_S20_3LE,
- + .buffer_bytes_max = IMX_DEFAULT_DMABUF_SIZE,
- .period_bytes_min = 128,
- .period_bytes_max = 65535, /* Limited by SDMA engine */
- - .periods_min = 2,
- + .periods_min = 4,
- .periods_max = 255,
- .fifo_size = 0,
- };
-
- +static void imx_pcm_dma_set_config_from_dai_data(
- + const struct snd_pcm_substream *substream,
- + const struct snd_dmaengine_dai_dma_data *dma_data,
- + struct dma_slave_config *slave_config)
- +{
- + struct imx_dma_data *filter_data = dma_data->filter_data;
- +
- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- + slave_config->dst_addr = dma_data->addr;
- + slave_config->dst_maxburst = dma_data->maxburst;
- + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED)
- + slave_config->dst_addr_width = dma_data->addr_width;
- + } else {
- + slave_config->src_addr = dma_data->addr;
- + slave_config->src_maxburst = dma_data->maxburst;
- + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED)
- + slave_config->src_addr_width = dma_data->addr_width;
- + }
- +
- + slave_config->slave_id = dma_data->slave_id;
- +
- + /*
- + * In dma binding mode, there is no filter_data, so dma_request need to be
- + * set to zero.
- + */
- + if (filter_data) {
- + slave_config->dma_request0 = filter_data->dma_request0;
- + slave_config->dma_request1 = filter_data->dma_request1;
- + } else {
- + slave_config->dma_request0 = 0;
- + slave_config->dma_request1 = 0;
- + }
- +}
- +
- +static int imx_pcm_dma_prepare_slave_config(struct snd_pcm_substream *substream,
- + struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config)
- +{
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct snd_dmaengine_dai_dma_data *dma_data;
- + int ret;
- +
- + dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
- +
- + ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config);
- + if (ret)
- + return ret;
- +
- + imx_pcm_dma_set_config_from_dai_data(substream, dma_data,
- + slave_config);
- +
- + return 0;
- +}
- +
- static const struct snd_dmaengine_pcm_config imx_dmaengine_pcm_config = {
- .pcm_hardware = &imx_pcm_hardware,
- - .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
- + .prepare_slave_config = imx_pcm_dma_prepare_slave_config,
- .compat_filter_fn = filter,
- - .prealloc_buffer_size = IMX_SSI_DMABUF_SIZE,
- + .prealloc_buffer_size = IMX_DEFAULT_DMABUF_SIZE,
- };
-
- -int imx_pcm_dma_init(struct platform_device *pdev)
- +int imx_pcm_dma_init(struct platform_device *pdev, unsigned int flags, size_t size)
- {
- - return devm_snd_dmaengine_pcm_register(&pdev->dev,
- - &imx_dmaengine_pcm_config,
- - SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
- - SND_DMAENGINE_PCM_FLAG_COMPAT);
- + struct snd_dmaengine_pcm_config *config;
- + struct snd_pcm_hardware *pcm_hardware;
- +
- + config = devm_kzalloc(&pdev->dev,
- + sizeof(struct snd_dmaengine_pcm_config), GFP_KERNEL);
- + *config = imx_dmaengine_pcm_config;
- + if (size)
- + config->prealloc_buffer_size = size;
- +
- + pcm_hardware = devm_kzalloc(&pdev->dev,
- + sizeof(struct snd_pcm_hardware), GFP_KERNEL);
- + *pcm_hardware = imx_pcm_hardware;
- + if (size)
- + pcm_hardware->buffer_bytes_max = size;
- +
- + config->pcm_hardware = pcm_hardware;
- +
- + return devm_snd_dmaengine_pcm_register(&pdev->dev, config, flags);
- }
- EXPORT_SYMBOL_GPL(imx_pcm_dma_init);
-
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/imx-pcm.h linux-3.14.35/sound/soc/fsl/imx-pcm.h
- --- linux-3.14.35.orig/sound/soc/fsl/imx-pcm.h 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/imx-pcm.h 2015-03-08 14:27:37.917684498 -0500
- @@ -18,13 +18,17 @@
- /*
- * Do not change this as the FIQ handler depends on this size
- */
- +#define IMX_DEFAULT_DMABUF_SIZE (256 * 1024)
- #define IMX_SSI_DMABUF_SIZE (64 * 1024)
- +#define IMX_SPDIF_DMABUF_SIZE (64 * 1024)
- +#define IMX_ESAI_DMABUF_SIZE (256 * 1024)
- +#define IMX_ASRC_DMABUF_SIZE (256 * 1024)
-
- static inline void
- imx_pcm_dma_params_init_data(struct imx_dma_data *dma_data,
- int dma, enum sdma_peripheral_type peripheral_type)
- {
- - dma_data->dma_request = dma;
- + dma_data->dma_request0 = dma;
- dma_data->priority = DMA_PRIO_HIGH;
- dma_data->peripheral_type = peripheral_type;
- }
- @@ -39,9 +43,10 @@
- };
-
- #if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_DMA)
- -int imx_pcm_dma_init(struct platform_device *pdev);
- +int imx_pcm_dma_init(struct platform_device *pdev, unsigned int flags, size_t size);
- #else
- -static inline int imx_pcm_dma_init(struct platform_device *pdev)
- +static inline int imx_pcm_dma_init(struct platform_device *pdev,
- + unsigned int flags, size_t size)
- {
- return -ENODEV;
- }
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/imx-spdif.c linux-3.14.35/sound/soc/fsl/imx-spdif.c
- --- linux-3.14.35.orig/sound/soc/fsl/imx-spdif.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/imx-spdif.c 2015-03-08 14:27:37.917684498 -0500
- @@ -65,14 +65,15 @@
- if (ret)
- goto end;
-
- + platform_set_drvdata(pdev, &data->card);
- + snd_soc_card_set_drvdata(&data->card, data);
- +
- ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
- if (ret) {
- dev_err(&pdev->dev, "snd_soc_register_card failed: %d\n", ret);
- goto end;
- }
-
- - platform_set_drvdata(pdev, data);
- -
- end:
- if (spdif_np)
- of_node_put(spdif_np);
- @@ -90,6 +91,7 @@
- .driver = {
- .name = "imx-spdif",
- .owner = THIS_MODULE,
- + .pm = &snd_soc_pm_ops,
- .of_match_table = imx_spdif_dt_ids,
- },
- .probe = imx_spdif_audio_probe,
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/imx-ssi.c linux-3.14.35/sound/soc/fsl/imx-ssi.c
- --- linux-3.14.35.orig/sound/soc/fsl/imx-ssi.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/imx-ssi.c 2015-03-08 14:27:37.917684498 -0500
- @@ -602,7 +602,8 @@
- ssi->fiq_params.dma_params_tx = &ssi->dma_params_tx;
-
- ssi->fiq_init = imx_pcm_fiq_init(pdev, &ssi->fiq_params);
- - ssi->dma_init = imx_pcm_dma_init(pdev);
- + ssi->dma_init = imx_pcm_dma_init(pdev, SND_DMAENGINE_PCM_FLAG_NO_RESIDUE,
- + IMX_SSI_DMABUF_SIZE);
-
- if (ssi->fiq_init && ssi->dma_init) {
- ret = ssi->fiq_init;
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/imx-wm8962.c linux-3.14.35/sound/soc/fsl/imx-wm8962.c
- --- linux-3.14.35.orig/sound/soc/fsl/imx-wm8962.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/imx-wm8962.c 2015-03-08 14:27:37.917684498 -0500
- @@ -1,9 +1,9 @@
- /*
- - * Copyright 2013 Freescale Semiconductor, Inc.
- + * Copyright (C) 2013 Freescale Semiconductor, Inc.
- *
- * Based on imx-sgtl5000.c
- - * Copyright 2012 Freescale Semiconductor, Inc.
- - * Copyright 2012 Linaro Ltd.
- + * Copyright (C) 2012 Freescale Semiconductor, Inc.
- + * Copyright (C) 2012 Linaro Ltd.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- @@ -16,9 +16,12 @@
- #include <linux/module.h>
- #include <linux/of_platform.h>
- #include <linux/i2c.h>
- +#include <linux/of_gpio.h>
- #include <linux/slab.h>
- +#include <linux/gpio.h>
- #include <linux/clk.h>
- #include <sound/soc.h>
- +#include <sound/jack.h>
- #include <sound/pcm_params.h>
- #include <sound/soc-dapm.h>
- #include <linux/pinctrl/consumer.h>
- @@ -33,15 +36,134 @@
- struct snd_soc_card card;
- char codec_dai_name[DAI_NAME_SIZE];
- char platform_name[DAI_NAME_SIZE];
- - struct clk *codec_clk;
- unsigned int clk_frequency;
- };
-
- struct imx_priv {
- + int hp_gpio;
- + int hp_active_low;
- + int mic_gpio;
- + int mic_active_low;
- + bool amic_mono;
- + bool dmic_mono;
- + struct snd_soc_codec *codec;
- struct platform_device *pdev;
- + struct snd_pcm_substream *first_stream;
- + struct snd_pcm_substream *second_stream;
- };
- static struct imx_priv card_priv;
-
- +static struct snd_soc_jack imx_hp_jack;
- +static struct snd_soc_jack_pin imx_hp_jack_pins[] = {
- + {
- + .pin = "Headphone Jack",
- + .mask = SND_JACK_HEADPHONE,
- + },
- +};
- +static struct snd_soc_jack_gpio imx_hp_jack_gpio = {
- + .name = "headphone detect",
- + .report = SND_JACK_HEADPHONE,
- + .debounce_time = 250,
- + .invert = 0,
- +};
- +
- +static struct snd_soc_jack imx_mic_jack;
- +static struct snd_soc_jack_pin imx_mic_jack_pins[] = {
- + {
- + .pin = "AMIC",
- + .mask = SND_JACK_MICROPHONE,
- + },
- +};
- +static struct snd_soc_jack_gpio imx_mic_jack_gpio = {
- + .name = "microphone detect",
- + .report = SND_JACK_MICROPHONE,
- + .debounce_time = 250,
- + .invert = 0,
- +};
- +
- +static int hpjack_status_check(void)
- +{
- + struct imx_priv *priv = &card_priv;
- + struct platform_device *pdev = priv->pdev;
- + char *envp[3], *buf;
- + int hp_status, ret;
- +
- + if (!gpio_is_valid(priv->hp_gpio))
- + return 0;
- +
- + hp_status = gpio_get_value(priv->hp_gpio) ? 1 : 0;
- +
- + buf = kmalloc(32, GFP_ATOMIC);
- + if (!buf) {
- + dev_err(&pdev->dev, "%s kmalloc failed\n", __func__);
- + return -ENOMEM;
- + }
- +
- + if (hp_status != priv->hp_active_low) {
- + snprintf(buf, 32, "STATE=%d", 2);
- + snd_soc_dapm_disable_pin(&priv->codec->dapm, "Ext Spk");
- + ret = imx_hp_jack_gpio.report;
- + } else {
- + snprintf(buf, 32, "STATE=%d", 0);
- + snd_soc_dapm_enable_pin(&priv->codec->dapm, "Ext Spk");
- + ret = 0;
- + }
- +
- + envp[0] = "NAME=headphone";
- + envp[1] = buf;
- + envp[2] = NULL;
- + kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, envp);
- + kfree(buf);
- +
- + return ret;
- +}
- +
- +static int micjack_status_check(void)
- +{
- + struct imx_priv *priv = &card_priv;
- + struct platform_device *pdev = priv->pdev;
- + char *envp[3], *buf;
- + int mic_status, ret;
- +
- + if (!gpio_is_valid(priv->mic_gpio))
- + return 0;
- +
- + mic_status = gpio_get_value(priv->mic_gpio) ? 1 : 0;
- +
- + if ((mic_status != priv->mic_active_low && priv->amic_mono)
- + || (mic_status == priv->mic_active_low && priv->dmic_mono))
- + snd_soc_update_bits(priv->codec, WM8962_THREED1,
- + WM8962_ADC_MONOMIX_MASK, WM8962_ADC_MONOMIX);
- + else
- + snd_soc_update_bits(priv->codec, WM8962_THREED1,
- + WM8962_ADC_MONOMIX_MASK, 0);
- +
- + buf = kmalloc(32, GFP_ATOMIC);
- + if (!buf) {
- + dev_err(&pdev->dev, "%s kmalloc failed\n", __func__);
- + return -ENOMEM;
- + }
- +
- + if (mic_status != priv->mic_active_low) {
- + snprintf(buf, 32, "STATE=%d", 2);
- + snd_soc_dapm_disable_pin(&priv->codec->dapm, "DMIC");
- + ret = imx_mic_jack_gpio.report;
- + } else {
- + snprintf(buf, 32, "STATE=%d", 0);
- + snd_soc_dapm_enable_pin(&priv->codec->dapm, "DMIC");
- + ret = 0;
- + }
- +
- + envp[0] = "NAME=microphone";
- + envp[1] = buf;
- + envp[2] = NULL;
- + kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, envp);
- + kfree(buf);
- +
- + return ret;
- +}
- +
- +
- static const struct snd_soc_dapm_widget imx_wm8962_dapm_widgets[] = {
- SND_SOC_DAPM_HP("Headphone Jack", NULL),
- SND_SOC_DAPM_SPK("Ext Spk", NULL),
- @@ -49,14 +171,57 @@
- SND_SOC_DAPM_MIC("DMIC", NULL),
- };
-
- -static int sample_rate = 44100;
- -static snd_pcm_format_t sample_format = SNDRV_PCM_FORMAT_S16_LE;
- -
- static int imx_hifi_hw_params(struct snd_pcm_substream *substream,
- - struct snd_pcm_hw_params *params)
- + struct snd_pcm_hw_params *params)
- {
- - sample_rate = params_rate(params);
- - sample_format = params_format(params);
- + struct snd_soc_pcm_runtime *rtd = substream->private_data;
- + struct snd_soc_dai *codec_dai = rtd->codec_dai;
- + struct imx_priv *priv = &card_priv;
- + struct device *dev = &priv->pdev->dev;
- + struct snd_soc_card *card = codec_dai->codec->card;
- + struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
- + unsigned int sample_rate = params_rate(params);
- + snd_pcm_format_t sample_format = params_format(params);
- + u32 dai_format, pll_out;
- + int ret = 0;
- +
- + if (!priv->first_stream) {
- + priv->first_stream = substream;
- + } else {
- + priv->second_stream = substream;
- +
- + /* We suppose the two substream are using same params */
- + return 0;
- + }
- +
- + dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
- + SND_SOC_DAIFMT_CBM_CFM;
- +
- + /* set codec DAI configuration */
- + ret = snd_soc_dai_set_fmt(codec_dai, dai_format);
- + if (ret) {
- + dev_err(dev, "failed to set codec dai fmt: %d\n", ret);
- + return ret;
- + }
- +
- + if (sample_format == SNDRV_PCM_FORMAT_S24_LE)
- + pll_out = sample_rate * 384;
- + else
- + pll_out = sample_rate * 256;
- +
- + ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL, WM8962_FLL_MCLK,
- + data->clk_frequency, pll_out);
- + if (ret) {
- + dev_err(dev, "failed to start FLL: %d\n", ret);
- + return ret;
- + }
- +
- + ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_FLL,
- + pll_out, SND_SOC_CLOCK_IN);
- + if (ret) {
- + dev_err(dev, "failed to set SYSCLK: %d\n", ret);
- + return ret;
- + }
-
- return 0;
- }
- @@ -133,6 +298,89 @@
- return 0;
- }
-
- +static int imx_wm8962_gpio_init(struct snd_soc_pcm_runtime *rtd)
- +{
- + struct snd_soc_codec *codec = rtd->codec;
- + struct imx_priv *priv = &card_priv;
- +
- + priv->codec = codec;
- +
- + if (gpio_is_valid(priv->hp_gpio)) {
- + imx_hp_jack_gpio.gpio = priv->hp_gpio;
- + imx_hp_jack_gpio.jack_status_check = hpjack_status_check;
- +
- + snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, &imx_hp_jack);
- + snd_soc_jack_add_pins(&imx_hp_jack,
- + ARRAY_SIZE(imx_hp_jack_pins), imx_hp_jack_pins);
- + snd_soc_jack_add_gpios(&imx_hp_jack, 1, &imx_hp_jack_gpio);
- + }
- +
- + if (gpio_is_valid(priv->mic_gpio)) {
- + imx_mic_jack_gpio.gpio = priv->mic_gpio;
- + imx_mic_jack_gpio.jack_status_check = micjack_status_check;
- +
- + snd_soc_jack_new(codec, "AMIC", SND_JACK_MICROPHONE, &imx_mic_jack);
- + snd_soc_jack_add_pins(&imx_mic_jack,
- + ARRAY_SIZE(imx_mic_jack_pins), imx_mic_jack_pins);
- + snd_soc_jack_add_gpios(&imx_mic_jack, 1, &imx_mic_jack_gpio);
- + } else if (priv->amic_mono || priv->dmic_mono) {
- + /*
- + * Permanent set monomix bit if only one microphone
- + * is present on the board while it needs monomix.
- + */
- + snd_soc_update_bits(priv->codec, WM8962_THREED1,
- + WM8962_ADC_MONOMIX_MASK, WM8962_ADC_MONOMIX);
- + }
- +
- + return 0;
- +}
- +
- +static ssize_t show_headphone(struct device_driver *dev, char *buf)
- +{
- + struct imx_priv *priv = &card_priv;
- + int hp_status;
- +
- + if (!gpio_is_valid(priv->hp_gpio)) {
- + strcpy(buf, "no detect gpio connected\n");
- + return strlen(buf);
- + }
- +
- + /* Check if headphone is plugged in */
- + hp_status = gpio_get_value(priv->hp_gpio) ? 1 : 0;
- +
- + if (hp_status != priv->hp_active_low)
- + strcpy(buf, "headphone\n");
- + else
- + strcpy(buf, "speaker\n");
- +
- + return strlen(buf);
- +}
- +
- +static DRIVER_ATTR(headphone, S_IRUGO | S_IWUSR, show_headphone, NULL);
- +
- +static ssize_t show_mic(struct device_driver *dev, char *buf)
- +{
- + struct imx_priv *priv = &card_priv;
- + int mic_status;
- +
- + if (!gpio_is_valid(priv->mic_gpio)) {
- + strcpy(buf, "no detect gpio connected\n");
- + return strlen(buf);
- + }
- +
- + /* Check if analog microphone is plugged in */
- + mic_status = gpio_get_value(priv->mic_gpio) ? 1 : 0;
- +
- + if (mic_status != priv->mic_active_low)
- + strcpy(buf, "amic\n");
- + else
- + strcpy(buf, "dmic\n");
- +
- + return strlen(buf);
- +}
- +
- +static DRIVER_ATTR(microphone, S_IRUGO | S_IWUSR, show_mic, NULL);
- +
- static int imx_wm8962_late_probe(struct snd_soc_card *card)
- {
- struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
- @@ -157,6 +405,7 @@
- struct imx_priv *priv = &card_priv;
- struct i2c_client *codec_dev;
- struct imx_wm8962_data *data;
- + struct clk *codec_clk = NULL;
- int int_port, ext_port;
- int ret;
-
- @@ -219,25 +468,31 @@
- goto fail;
- }
-
- + priv->first_stream = NULL;
- + priv->second_stream = NULL;
- +
- data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
- if (!data) {
- ret = -ENOMEM;
- goto fail;
- }
-
- - data->codec_clk = devm_clk_get(&codec_dev->dev, NULL);
- - if (IS_ERR(data->codec_clk)) {
- - ret = PTR_ERR(data->codec_clk);
- + codec_clk = devm_clk_get(&codec_dev->dev, NULL);
- + if (IS_ERR(codec_clk)) {
- + ret = PTR_ERR(codec_clk);
- dev_err(&codec_dev->dev, "failed to get codec clk: %d\n", ret);
- goto fail;
- }
-
- - data->clk_frequency = clk_get_rate(data->codec_clk);
- - ret = clk_prepare_enable(data->codec_clk);
- - if (ret) {
- - dev_err(&codec_dev->dev, "failed to enable codec clk: %d\n", ret);
- - goto fail;
- - }
- + data->clk_frequency = clk_get_rate(codec_clk);
- +
- + priv->amic_mono = of_property_read_bool(codec_np, "amic-mono");
- + priv->dmic_mono = of_property_read_bool(codec_np, "dmic-mono");
- +
- + priv->hp_gpio = of_get_named_gpio_flags(np, "hp-det-gpios", 0,
- + (enum of_gpio_flags *)&priv->hp_active_low);
- + priv->mic_gpio = of_get_named_gpio_flags(np, "mic-det-gpios", 0,
- + (enum of_gpio_flags *)&priv->mic_active_low);
-
- data->dai.name = "HiFi";
- data->dai.stream_name = "HiFi";
- @@ -246,23 +501,23 @@
- data->dai.cpu_dai_name = dev_name(&ssi_pdev->dev);
- data->dai.platform_of_node = ssi_np;
- data->dai.ops = &imx_hifi_ops;
- + data->dai.init = &imx_wm8962_gpio_init;
- data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM;
-
- data->card.dev = &pdev->dev;
- ret = snd_soc_of_parse_card_name(&data->card, "model");
- if (ret)
- - goto clk_fail;
- + goto fail;
- ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing");
- if (ret)
- - goto clk_fail;
- + goto fail;
- data->card.num_links = 1;
- data->card.dai_link = &data->dai;
- data->card.dapm_widgets = imx_wm8962_dapm_widgets;
- data->card.num_dapm_widgets = ARRAY_SIZE(imx_wm8962_dapm_widgets);
-
- data->card.late_probe = imx_wm8962_late_probe;
- - data->card.set_bias_level = imx_wm8962_set_bias_level;
-
- platform_set_drvdata(pdev, &data->card);
- snd_soc_card_set_drvdata(&data->card, data);
- @@ -270,16 +525,31 @@
- ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
- if (ret) {
- dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
- - goto clk_fail;
- + goto fail;
- }
-
- - of_node_put(ssi_np);
- - of_node_put(codec_np);
- + if (gpio_is_valid(priv->hp_gpio)) {
- + ret = driver_create_file(pdev->dev.driver, &driver_attr_headphone);
- + if (ret) {
- + dev_err(&pdev->dev, "create hp attr failed (%d)\n", ret);
- + goto fail_hp;
- + }
- + }
-
- - return 0;
- + if (gpio_is_valid(priv->mic_gpio)) {
- + ret = driver_create_file(pdev->dev.driver, &driver_attr_microphone);
- + if (ret) {
- + dev_err(&pdev->dev, "create mic attr failed (%d)\n", ret);
- + goto fail_mic;
- + }
- + }
- +
- + goto fail;
-
- -clk_fail:
- - clk_disable_unprepare(data->codec_clk);
- +fail_mic:
- + driver_remove_file(pdev->dev.driver, &driver_attr_headphone);
- +fail_hp:
- + snd_soc_unregister_card(&data->card);
- fail:
- if (ssi_np)
- of_node_put(ssi_np);
- @@ -291,11 +561,8 @@
-
- static int imx_wm8962_remove(struct platform_device *pdev)
- {
- - struct snd_soc_card *card = platform_get_drvdata(pdev);
- - struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
- -
- - if (!IS_ERR(data->codec_clk))
- - clk_disable_unprepare(data->codec_clk);
- + driver_remove_file(pdev->dev.driver, &driver_attr_microphone);
- + driver_remove_file(pdev->dev.driver, &driver_attr_headphone);
-
- return 0;
- }
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/Kconfig linux-3.14.35/sound/soc/fsl/Kconfig
- --- linux-3.14.35.orig/sound/soc/fsl/Kconfig 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/Kconfig 2015-03-08 14:27:37.917684498 -0500
- @@ -11,6 +11,12 @@
- config SND_SOC_FSL_ESAI
- tristate
-
- +config SND_SOC_FSL_ASRC
- + tristate
- +
- +config SND_SOC_FSL_HDMI
- + tristate
- +
- config SND_SOC_FSL_UTILS
- tristate
-
- @@ -126,6 +132,11 @@
- tristate
- select SND_SOC_GENERIC_DMAENGINE_PCM
-
- +config SND_SOC_IMX_HDMI_DMA
- + bool
- + select SND_SOC_GENERIC_DMAENGINE_PCM
- + select SND_SOC_IMX_PCM_DMA
- +
- config SND_SOC_IMX_AUDMUX
- tristate
-
- @@ -178,6 +189,18 @@
- Enable I2S based access to the TLV320AIC23B codec attached
- to the SSI interface
-
- +config SND_SOC_IMX_CS42888
- + tristate "SoC Audio support for i.MX boards with cs42888"
- + depends on OF && I2C
- + select SND_SOC_CS42888
- + select SND_SOC_IMX_PCM_DMA
- + select SND_SOC_FSL_ESAI
- + select SND_SOC_FSL_UTILS
- + help
- + SoC Audio support for i.MX boards with cs42888
- + Say Y if you want to add support for SoC audio on an i.MX board with
- + a cs42888 codec.
- +
- config SND_SOC_IMX_WM8962
- tristate "SoC Audio support for i.MX boards with wm8962"
- depends on OF && I2C
- @@ -210,6 +233,17 @@
- Say Y if you want to add support for SoC audio on an i.MX board with
- a S/DPDIF.
-
- +config SND_SOC_IMX_HDMI
- + tristate "SoC Audio support for i.MX boards with HDMI port"
- + depends on MFD_MXC_HDMI
- + select SND_SOC_IMX_HDMI_DMA
- + select SND_SOC_FSL_HDMI
- + select SND_SOC_HDMI_CODEC
- + help
- + SoC Audio support for i.MX boards with HDMI audio
- + Say Y if you want to add support for SoC audio on an i.MX board with
- + IMX HDMI.
- +
- config SND_SOC_IMX_MC13783
- tristate "SoC Audio support for I.MX boards with mc13783"
- depends on MFD_MC13XXX && ARM
- diff -Nur linux-3.14.35.orig/sound/soc/fsl/Makefile linux-3.14.35/sound/soc/fsl/Makefile
- --- linux-3.14.35.orig/sound/soc/fsl/Makefile 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/sound/soc/fsl/Makefile 2015-03-08 14:27:37.917684498 -0500
- @@ -14,13 +14,19 @@
- snd-soc-fsl-sai-objs := fsl_sai.o
- snd-soc-fsl-ssi-objs := fsl_ssi.o
- snd-soc-fsl-spdif-objs := fsl_spdif.o
- +snd-soc-fsl-hdmi-objs := fsl_hdmi.o
- snd-soc-fsl-esai-objs := fsl_esai.o
- +snd-soc-fsl-asrc-pcm-objs := fsl_asrc_pcm.o
- +snd-soc-fsl-asrc-objs := fsl_asrc.o
- snd-soc-fsl-utils-objs := fsl_utils.o
- snd-soc-fsl-dma-objs := fsl_dma.o
- obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o
- obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o
- obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o
- +obj-$(CONFIG_SND_SOC_FSL_HDMI) += snd-soc-fsl-hdmi.o
- obj-$(CONFIG_SND_SOC_FSL_ESAI) += snd-soc-fsl-esai.o
- +obj-$(CONFIG_SND_SOC_FSL_ASRC) += snd-soc-fsl-asrc-pcm.o
- +obj-$(CONFIG_SND_SOC_FSL_ASRC) += snd-soc-fsl-asrc.o
- obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o
- obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
-
- @@ -41,22 +47,27 @@
-
- obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
- obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
- +obj-$(CONFIG_SND_SOC_IMX_HDMI_DMA) += imx-hdmi-dma.o
-
- # i.MX Machine Support
- snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
- snd-soc-phycore-ac97-objs := phycore-ac97.o
- snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o
- snd-soc-wm1133-ev1-objs := wm1133-ev1.o
- +snd-soc-imx-cs42888-objs := imx-cs42888.o
- snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
- snd-soc-imx-wm8962-objs := imx-wm8962.o
- snd-soc-imx-spdif-objs := imx-spdif.o
- +snd-soc-imx-hdmi-objs := imx-hdmi.o
- snd-soc-imx-mc13783-objs := imx-mc13783.o
-
- obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
- obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o
- obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o
- obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
- +obj-$(CONFIG_SND_SOC_IMX_CS42888) += snd-soc-imx-cs42888.o
- obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o
- obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o
- obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o
- +obj-$(CONFIG_SND_SOC_IMX_HDMI) += snd-soc-imx-hdmi.o
- obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o
- diff -Nur linux-3.14.35.orig/sound/soc/soc-pcm.c linux-3.14.35/sound/soc/soc-pcm.c
- --- linux-3.14.35.orig/sound/soc/soc-pcm.c 2015-03-06 16:44:34.000000000 -0600
- +++ linux-3.14.35/sound/soc/soc-pcm.c 2015-03-08 14:27:37.917684498 -0500
- @@ -945,7 +945,7 @@
- }
- }
-
- - dev_err(card->dev, "ASoC: can't get %s BE for %s\n",
- + dev_dbg(card->dev, "ASoC: can't get %s BE for %s\n",
- stream ? "capture" : "playback", widget->name);
- return NULL;
- }
- @@ -1062,7 +1062,7 @@
- /* is there a valid BE rtd for this widget */
- be = dpcm_get_be(card, list->widgets[i], stream);
- if (!be) {
- - dev_err(fe->dev, "ASoC: no BE found for %s\n",
- + dev_dbg(fe->dev, "ASoC: no BE found for %s\n",
- list->widgets[i]->name);
- continue;
- }
|